Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
VertexCoordRemapper.h
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
23 /* A VertexCoordRemapper uses the reamapping transformations to create a set of
24  * quadrilatrials that approximate the remapping. Each quad represents a small
25  * axis-aligned rectangle of the input image.
26  * This is created by an adaptive subdivision method:
27  * - Each corner is mapped to the correct position, to give a quadrilatial.
28  * - Each edge is tested against some function
29  * - The edges that fail the test are split into two edges, the middle
30  * of the original edge is mapped to the correct position, the new lines
31  * meet at this point, and use the end points of the original line.
32  * - The new edges are tested and optionally split, etc.
33  *
34  * The testing function:
35  * - fails for any edge under minimum depth
36  * - passes for any edge at maximum depth
37  * - passes for any edge not affected by the above conditions and is {shorter
38  * than minimum length | makes an angle of less than a minimum angle}
39  * ? passes for any edge that is not affected by the above conditions, and is
40  * deemed to cross a discontinuity, and has each end point closer than
41  * minimum length to the panorama's edge
42  *
43  * Edges are deemed to span across a discontinuity if they are longer than the
44  * two edges they are created from, and make a sharp turn at each end. This is
45  * not entierly accurate. Since remappings are mostly quite smooth, we let the
46  * minimum depth test avoid most mistakes that can be caused by this assumption.
47  *
48  * The meshes can then be caclulated from these edges. Starting with the initial
49  * quadrilatrial, we can check if the edges have been subdivided in each
50  * direction. Where a subdivided edge and a non subdivided edge are oposite
51  * each other in a quad, the non subdivided edge gets subdivided linearly, so
52  * it lines up with the quad on the other side (this subdivide only
53  * applies to one side of the edge, and adds no more actual geometric detail).
54  */
55 
56 #ifndef __VERTEXCOORDREMAPPER_H
57 #define __VERTEXCOORDREMAPPER_H
58 
59 #include "MeshRemapper.h"
60 #include <panodata/Panorama.h>
63 
65 {
66 public:
69  virtual void UpdateAndResetIndex();
70  // get the texture and vertex coordinates for the next face. The coordinates
71  // are ordered [left / right][top / bottom][x coord / y coord].
72  virtual bool GetNextFaceCoordinates(Coords *result);
73 private:
74  // texture coordinates for passing back in GetNextFaceCoordinates.
75  double tex_coords[2][2][2],
76  // spare vertex coordinates space used for copies we will change.
77  s_vertex_coords[2][2][2],
78  // the size of the output panorama.
80  // extents in +/- 180 degree boundary crossing checking.
83  // values used to flip vertices across the 180 boundary
85 
86  // when we cross the 180 degree split there are two faces to give for every
87  // face on the tree. Set this false when we should give the second in a pair
88  bool done_node;
89  unsigned int tree_node_id;
90  // this stores what vertices need flipping.
91  unsigned short int discontinuity_flags;
92 
93  // The output projection format we are using
95 
96  // set the coordinates of node node_id, decided which directions to
97  // subdivide in and then call recursively on any new faces.
98  // the 'stretch' arguments are needed if the parents of this node have
99  // subdivided in only one direction.
100  void RecursiveUpdate(unsigned int node_id, unsigned int stretch_x,
101  unsigned int stretch_y);
102  // decides when to subdivide. Stores the result in the node.
103  void TestSubdivide(unsigned int node_id);
104 
105  // Where a face crosses a discontinuity the vertices end up on different
106  // sides. Flip a vertex to the other side of the 180 degree seam.
107  void DiscontinuityFlip(double vertex_c[2]);
108 
109  /* We make a quad tree of faces.
110  * Each face has a copy of all the vertices at its corners, and knows if it
111  * has been subdivided in each direction. If it has been subdivided, it is
112  * not actually used for drawing, but the corners can be useful for children
113  */
114  class TreeNode
115  {
116  public:
117  // the edges of the faces: [left/right][top/bottom][x coord / y coord]
118  double verts[2][2][2];
119  unsigned short int flags;
120  // angle of the gradients of the left and top edge.
121  float angle_x, angle_y;
122  // the lengths of the left and top edge.
124  };
125  /* the actual tree stores each tree in constant space, however the space is
126  * quite large. This is so we allocate memory only on creation and have
127  * very cheep lookup operations.
128  */
129  class Tree
130  {
131  public:
132  void GetChildrenIds(const unsigned int node_num,
133  unsigned int children[4],
134  unsigned int &num_children);
135  // The leaf nodes are the ones we want to be drawn
136  // Select the first leaf node
137  void ResetIndex();
138  // return the node for the selected leaf and move on to the next.
139  // returns 0 after they have all been used. (node 0 always subdivides
140  // so cannot be a leaf node).
141  unsigned int GetNext();
142  // get the face that was subdivided to get the requested one.
143  unsigned int GetParentId(const unsigned int nodenum);
144  unsigned int GetParentId(unsigned int x, unsigned int y,
145  unsigned int row_size, unsigned depth);
146  unsigned int GetDepth(const unsigned int nodenum);
147  // find the position of a node given its index
148  void GetPosition(const unsigned int nodenum, unsigned int &x,
149  unsigned int &y, unsigned int &row_size,
150  unsigned int &depth);
151  // find the index of a node, given information about its position.
152  unsigned int GetIndex(const unsigned int x, const unsigned int y,
153  const unsigned int row_size,
154  unsigned int depth);
155  // the scale and offset reduce the texture mapped region to the
156  // rectangle the user has cropped the source image to.
158  void GetInputCoordinates(unsigned int node_num, double coords[2][2][2]);
159 
160  // tries to find a transformed coordinate in the tree that would have
161  // been written before stop. If there are none, return 0, otherwise
162  // set dest_x and dest_y and return the number of the node it used to
163  // work that out. This takes into account where the subdivision has
164  // stopped and performs linear interpolation in that case.
165  unsigned int GetTransform(unsigned int src_x, unsigned int src_y,
166  unsigned int depth,
167  unsigned int stop_x, unsigned int stop_y,
168  double &dest_x, double &dest_y);
169  // Array of as many nodes necessary to store a full tree with subdivions
170  // up to max_depth (defined in VertexCoordRemapper.cpp) times.
171  TreeNode nodes[1+4+16+64+256+1024+4096];
172  private:
173  unsigned int cur_tree_node;
174  };
176  void SetLengthAndAngle(TreeNode *node);
177 };
178 
179 #endif
180 
VertexCoordRemapper(HuginBase::Panorama *m_pano, HuginBase::SrcPanoImage *image, VisualizationState *visualization_state)
unsigned int GetDepth(const unsigned int nodenum)
An abstract base class for objects that calculate an approximate remap specified by quadrilatrials...
Definition: MeshRemapper.h:43
double s_vertex_coords[2][2][2]
unsigned int GetIndex(const unsigned int x, const unsigned int y, const unsigned int row_size, unsigned int depth)
double tex_coords[2][2][2]
void SetLengthAndAngle(TreeNode *node)
A class for exchanging pointers to coordinates.
Definition: MeshRemapper.h:60
HuginBase::SrcPanoImage * image
Definition: MeshRemapper.h:85
void DiscontinuityFlip(double vertex_c[2])
void RecursiveUpdate(unsigned int node_id, unsigned int stretch_x, unsigned int stretch_y)
HuginBase::PanoramaOptions::ProjectionFormat output_projection
VisualizationState * visualization_state
Definition: MeshRemapper.h:83
Model for a panorama.
Definition: Panorama.h:152
TreeNode nodes[1+4+16+64+256+1024+4096]
void GetChildrenIds(const unsigned int node_num, unsigned int children[4], unsigned int &num_children)
unsigned int GetParentId(const unsigned int nodenum)
void GetInputCoordinates(unsigned int node_num, double coords[2][2][2])
void GetPosition(const unsigned int nodenum, unsigned int &x, unsigned int &y, unsigned int &row_size, unsigned int &depth)
unsigned int GetTransform(unsigned int src_x, unsigned int src_y, unsigned int depth, unsigned int stop_x, unsigned int stop_y, double &dest_x, double &dest_y)
virtual bool GetNextFaceCoordinates(Coords *result)
Get the texture and vertex coordinates for the next face.
virtual void UpdateAndResetIndex()
unsigned short int discontinuity_flags
ProjectionFormat
Projection of final panorama.
All variables of a source image.
Definition: SrcPanoImage.h:194
void TestSubdivide(unsigned int node_id)
HuginBase::Panorama * m_pano
Definition: MeshRemapper.h:84