Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages
hugin1/hugin/VertexCoordRemapper.h
Go to the documentation of this file.00001 // -*- c-basic-offset: 4 -*- 00002 00023 /* A VertexCoordRemapper uses the reamapping transformations to create a set of 00024 * quadrilatrials that approximate the remapping. Each quad represents a small 00025 * axis-aligned rectangle of the input image. 00026 * This is created by an adaptive subdivision method: 00027 * - Each corner is mapped to the correct position, to give a quadrilatial. 00028 * - Each edge is tested against some function 00029 * - The edges that fail the test are split into two edges, the middle 00030 * of the original edge is mapped to the correct position, the new lines 00031 * meet at this point, and use the end points of the original line. 00032 * - The new edges are tested and optionally split, etc. 00033 * 00034 * The testing function: 00035 * - fails for any edge under minimum depth 00036 * - passes for any edge at maximum depth 00037 * - passes for any edge not affected by the above conditions and is {shorter 00038 * than minimum length | makes an angle of less than a minimum angle} 00039 * ? passes for any edge that is not affected by the above conditions, and is 00040 * deemed to cross a discontinuity, and has each end point closer than 00041 * minimum length to the panorma's edge 00042 * 00043 * Edges are deemed to span across a discontinuity if they are longer than the 00044 * two edges they are created from, and make a sharp turn at each end. This is 00045 * not entierly accurate. Since remappings are mostly quite smooth, we let the 00046 * minimum depth test avoid most mistakes that can be caused by this assumption. 00047 * 00048 * The meshes can then be caclulated from these edges. Starting with the initial 00049 * quadrilatrial, we can check if the edges have been subdivided in each 00050 * direction. Where a subdivided edge and a non subdivided edge are oposite 00051 * each other in a quad, the non subdivided edge gets subdivided linearly, so 00052 * it lines up with the quad on the other side (this subdivide only 00053 * applies to one side of the edge, and adds no more actual geometric detail). 00054 */ 00055 00056 #ifndef __VERTEXCOORDREMAPPER_H 00057 #define __VERTEXCOORDREMAPPER_H 00058 00059 #include "MeshRemapper.h" 00060 #include <panodata/Panorama.h> 00061 #include <panodata/PanoramaOptions.h> 00062 #include <panotools/PanoToolsInterface.h> 00063 00064 class VertexCoordRemapper : public MeshRemapper 00065 { 00066 public: 00067 VertexCoordRemapper(HuginBase::Panorama *m_pano, unsigned int image_number, 00068 ViewState *view_state); 00069 virtual void UpdateAndResetIndex(); 00070 // get the texture and vertex coordinates for the next face. The coordinates 00071 // are ordered [left / right][top / bottom][x coord / y coord]. 00072 virtual bool GetNextFaceCoordinates(Coords *result); 00073 private: 00074 // texture coordinates for passing back in GetNextFaceCoordinates. 00075 double tex_coords[2][2][2], 00076 // spare vertex coordinates space used for copies we will change. 00077 s_vertex_coords[2][2][2], 00078 // the size of the output panorama. 00079 o_width, o_height, 00080 // extents in +/- 180 degree boundary crossing checking. 00081 radius, lower_bound, upper_bound, lower_bound_h, upper_bound_h, 00082 x_midpoint, y_midpoint, 00083 // values used to flip vertices across the 180 boundary 00084 x_add_360, y_add_360; 00085 00086 // when we cross the 180 degree split there are two faces to give for every 00087 // face on the tree. Set this false when we should give the second in a pair 00088 bool done_node; 00089 unsigned int tree_node_id; 00090 // this stores what vertices need flipping. 00091 unsigned short int discontinuity_flags; 00092 00093 // The output projection format we are using 00094 HuginBase::PanoramaOptions::ProjectionFormat output_projection; 00095 00096 // set the coordinates of node node_id, decided which directions to 00097 // subdivide in and then call recursively on any new faces. 00098 // the 'stretch' arguments are needed if the parents of this node have 00099 // subdivided in only one direction. 00100 void RecursiveUpdate(unsigned int node_id, unsigned int stretch_x, 00101 unsigned int stretch_y); 00102 // decides when to subdivide. Stores the result in the node. 00103 void TestSubdivide(unsigned int node_id); 00104 00105 // Where a face crosses a discontinuity the vertices end up on different 00106 // sides. Flip a vertex to the other side of the 180 degree seam. 00107 void DiscontinuityFlip(double vertex_c[2]); 00108 00109 /* We make a quad tree of faces. 00110 * Each face has a copy of all the vertices at its corners, and knows if it 00111 * has been subdivided in each direction. If it has been subdivided, it is 00112 * not actually used for drawing, but the corners can be useful for children 00113 */ 00114 class TreeNode 00115 { 00116 public: 00117 // the edges of the faces: [left/right][top/bottom][x coord / y coord] 00118 double verts[2][2][2]; 00119 unsigned short int flags; 00120 // angle of the gradients of the left and top edge. 00121 float angle_x, angle_y; 00122 // the lengths of the left and top edge. 00123 float length_x, length_y; 00124 }; 00125 /* the actual tree stores each tree in constant space, however the space is 00126 * quite large. This is so we allocate memory only on creation and have 00127 * very cheep lookup operations. 00128 */ 00129 class Tree 00130 { 00131 public: 00132 void GetChildrenIds(const unsigned int node_num, 00133 unsigned int children[4], 00134 unsigned int &num_children); 00135 // The leaf nodes are the ones we want to be drawn 00136 // Select the first leaf node 00137 void ResetIndex(); 00138 // return the node for the selected leaf and move on to the next. 00139 // returns 0 after they have all been used. (node 0 always subdivides 00140 // so cannot be a leaf node). 00141 unsigned int GetNext(); 00142 // get the face that was subdivided to get the requested one. 00143 unsigned int GetParentId(const unsigned int nodenum); 00144 unsigned int GetParentId(unsigned int x, unsigned int y, 00145 unsigned int row_size, unsigned depth); 00146 unsigned int GetDepth(const unsigned int nodenum); 00147 // find the position of a node given its index 00148 void GetPosition(const unsigned int nodenum, unsigned int &x, 00149 unsigned int &y, unsigned int &row_size, 00150 unsigned int &depth); 00151 // find the index of a node, given information about its position. 00152 unsigned int GetIndex(const unsigned int x, const unsigned int y, 00153 const unsigned int row_size, 00154 unsigned int depth); 00155 // the scale and offset reduce the texture mapped region to the 00156 // rectangle the user has cropped the source image to. 00157 double x_crop_scale, y_crop_scale, x_crop_offs, y_crop_offs; 00158 void GetInputCoordinates(unsigned int node_num, double coords[2][2][2]); 00159 00160 // tries to find a transformed coordinate in the tree that would have 00161 // been written before stop. If there are none, return 0, otherwise 00162 // set dest_x and dest_y and return the number of the node it used to 00163 // work that out. This takes into account where the subdivision has 00164 // stopped and performs linear interpolation in that case. 00165 unsigned int GetTransform(unsigned int src_x, unsigned int src_y, 00166 unsigned int depth, 00167 unsigned int stop_x, unsigned int stop_y, 00168 double &dest_x, double &dest_y); 00169 // Array of as many nodes necessary to store a full tree with subdivions 00170 // up to max_depth (defined in VertexCoordRemapper.cpp) times. 00171 TreeNode nodes[1+4+16+64+256+1024+4096]; 00172 private: 00173 unsigned int cur_tree_node; 00174 }; 00175 Tree tree; 00176 void SetLengthAndAngle(TreeNode *node); 00177 }; 00178 00179 #endif 00180
1.3.9.1