[an error occurred while processing this directive]
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 

Generated on Mon Sep 20 01:01:26 2010 for Hugintrunk by doxygen 1.3.9.1