contrib/brl/bbas/imesh/algo/imesh_generate_mesh.cxx
Go to the documentation of this file.
00001 // This is brl/bbas/imesh/algo/imesh_generate_mesh.cxx
00002 #include "imesh_generate_mesh.h"
00003 //:
00004 // \file
00005 extern "C" {
00006 #include <triangle.h>
00007 }
00008 #include <vcl_cassert.h>
00009 #include <vgl/vgl_point_2d.h>
00010 #include <vgl/vgl_line_segment_2d.h>
00011 #include <vgl/vgl_box_2d.h>
00012 #include <vcl_iostream.h>
00013 #include <vil/vil_image_view.h>
00014 #define GRID_SIZE 1000 // defined by the tolerance for equal vertices
00015 
00016 // a grid index to find coincident vertices
00017 class point_index
00018 {
00019  public:
00020   point_index(vgl_box_2d<double> const&  bb)
00021   : vi_(0), x_min_(bb.min_x()), y_min_(bb.min_y()),
00022     x_size_(bb.width()), y_size_(bb.height())
00023   {
00024     img_.set_size(GRID_SIZE, GRID_SIZE);
00025     img_.fill(-1);//no vert at location
00026   }
00027 
00028   void pt_to_img(vgl_point_2d<double> const& pt, unsigned& i, unsigned& j)
00029   {
00030     double xi = pt.x()-x_min_, yi = pt.y()-y_min_;
00031     i = static_cast<unsigned>((xi*GRID_SIZE)/x_size_);
00032     j = static_cast<unsigned>((yi*GRID_SIZE)/y_size_);
00033     if (i>=GRID_SIZE) i=GRID_SIZE-1;
00034     if (j>=GRID_SIZE) j=GRID_SIZE-1;
00035   }
00036 
00037   void insert_point(vgl_point_2d<double> const& pt)
00038   {
00039     unsigned i=0, j=0;
00040     pt_to_img(pt, i, j);
00041     if (img_(i,j)>=0)
00042       return;//point already exists
00043     //insert vertex index
00044     img_(i,j) = vi_++;
00045   }
00046 
00047   int vert_index(vgl_point_2d<double> const& pt)
00048   {
00049     unsigned i=0, j=0;
00050     pt_to_img(pt, i, j);
00051     int index = img_(i,j);
00052     assert(index>=0);
00053     return index;
00054   }
00055 
00056   unsigned size() const {return vi_;}
00057 
00058  private:
00059   unsigned vi_;
00060   double x_min_;
00061   double y_min_;
00062   double x_size_;
00063   double y_size_;
00064   vil_image_view<int> img_;
00065 };
00066 
00067 void
00068 imesh_generate_mesh_2d(vcl_vector<vgl_point_2d<double> > const& convex_hull,
00069                        vcl_vector<vgl_line_segment_2d<double> > const& segs,
00070                        imesh_mesh& mesh)
00071 {
00072   // form a grid to store vertex indices in order to detect
00073   // shared vertices
00074   unsigned nch = convex_hull.size();
00075   vgl_box_2d<double> bb;
00076   for (unsigned i = 0; i<nch; ++i)
00077     bb.add(convex_hull[i]);
00078   //insert all points into a grid index
00079   point_index pindx(bb);
00080   for (unsigned i =0; i<nch; ++i)
00081     pindx.insert_point(convex_hull[i]);
00082   unsigned nsegs = segs.size();
00083   for (unsigned i = 0; i<nsegs; ++i) {
00084     pindx.insert_point(segs[i].point1());
00085     pindx.insert_point(segs[i].point2());
00086   }
00087   // pindx now contains a single vertex pointer for each pair
00088   // of coincident line segment endpoints as well as for each
00089   // isolated endpoint
00090   unsigned npts = pindx.size();
00091   //set up the Delunay constrained triangulation input parameters
00092   struct triangulateio in, out, vorout;
00093   in.numberofholes = 0;
00094   in.numberofregions = 0;
00095   in.numberofpointattributes = 0;
00096   in.numberofpoints = npts;
00097   in.pointlist = (REAL *) malloc(in.numberofpoints * 2 * sizeof(REAL));
00098   for (unsigned i = 0; i<nch; ++i) {
00099     unsigned pi = pindx.vert_index(convex_hull[i]);
00100     in.pointlist[2*pi]=convex_hull[i].x();
00101     in.pointlist[2*pi+1]=convex_hull[i].y();
00102   }
00103   // line segments to be inserted into the triangulation
00104   in.numberofsegments = nsegs;
00105   in.segmentlist = (int *) malloc(in.numberofsegments * 2 * sizeof(int));
00106   unsigned m = 0;
00107   for (unsigned i = 0; i<nsegs; ++i) {
00108     unsigned pi1 = pindx.vert_index(segs[i].point1());
00109     unsigned pi2 = pindx.vert_index(segs[i].point2());
00110     in.pointlist[2*pi1]   = segs[i].point1().x();
00111     in.pointlist[2*pi1+1] = segs[i].point1().y();
00112     in.pointlist[2*pi2]   = segs[i].point2().x();
00113     in.pointlist[2*pi2+1] = segs[i].point2().y();
00114     in.segmentlist[m]=pi1;     in.segmentlist[m+1]=pi2;
00115   }
00116   //attributes and markers are not used in this algorithm
00117   in.pointattributelist = NULL;
00118   in.pointmarkerlist = (int*)malloc(in.numberofpoints * sizeof(int));
00119   for (int i = 0; i<in.numberofpoints; ++i)
00120     in.pointmarkerlist[i]=0;
00121   in.segmentmarkerlist = (int *) malloc(in.numberofsegments * sizeof(int));;
00122   for (int i = 0; i<in.numberofsegments; ++i)
00123     in.segmentmarkerlist[i]=0;
00124 
00125   out.pointlist = (REAL *) NULL;            // Not needed if -N switch used.
00126   // Not needed if -N switch used or number of point attributes is zero:
00127   out.pointattributelist = (REAL *) NULL;
00128   out.pointmarkerlist = (int *) NULL; // Not needed if -N or -B switch used.
00129   out.trianglelist = (int *) NULL;          // Not needed if -E switch used.
00130   out.neighborlist = (int *) NULL;         // Needed only if -n switch used.
00131   // Needed only if segments are output (-p or -c) and -P not used:
00132   out.segmentlist = (int *) (REAL *) malloc(in.numberofsegments * 2 * sizeof(REAL)); // Suspicious. Why the double cast? and why sizeof(REAL) if it's really int*?
00133   // Needed only if segments are output (-p or -c) and -P and -B not used:
00134   out.segmentmarkerlist = (int *) NULL;
00135   out.edgelist = (int *) NULL;             // Needed only if -e switch used.
00136   out.edgemarkerlist = (int *) NULL;   // Needed if -e used and -B not used.
00137 
00138   //A string of switch characters must be provided
00139   // Triangulate the points.  Switches are chosen to read and write a
00140   //   PSLG (p), preserve the convex hull (c), number everything from
00141   //   zero (z), produce an edge list (e), and a triangle neighbor list (n)
00142 
00143   triangulate("Qpczen", &in, &out, &vorout);
00144 
00145   // construct the imesh data structure
00146   //construct vertices
00147   imesh_vertex_array<2>* verts = new imesh_vertex_array<2>();
00148   unsigned k = 0;
00149   for (unsigned i = 0; i<npts; ++i, k+=2)
00150     verts->push_back(imesh_vertex<2>(out.pointlist[k], out.pointlist[k+1]));
00151   vcl_auto_ptr<imesh_vertex_array_base> v(verts);
00152   mesh.set_vertices(v);
00153   //construct triangular faces
00154   unsigned ntri = static_cast<unsigned>(out.numberoftriangles);
00155   imesh_regular_face_array<3>* faces = new imesh_regular_face_array<3>();
00156   for (unsigned t = 0; t<ntri; ++t)
00157   {
00158     imesh_tri tri(out.trianglelist[t*3],
00159                   out.trianglelist[t*3+1],
00160                   out.trianglelist[t*3+2]);
00161     faces->push_back(tri);
00162   }
00163   //set the faces on the mesh
00164   vcl_auto_ptr<imesh_face_array_base> f(faces);
00165   mesh.set_faces(f);
00166 }
00167 
00168 
00169 void
00170 imesh_generate_mesh_2d_2(vcl_vector<vgl_point_2d<double> > const& convex_hull,
00171                          vcl_vector<vgl_line_segment_2d<double> > const& segs,
00172                          vcl_vector<vgl_point_2d<double> > const & points,
00173                          imesh_mesh& mesh)
00174 {
00175   // form a grid to store vertex indices in order to detect
00176   // shared vertices
00177   unsigned nch = convex_hull.size();
00178   vgl_box_2d<double> bb;
00179   for (unsigned i = 0; i<nch; ++i)
00180     bb.add(convex_hull[i]);
00181   //insert all points into a grid index
00182   point_index pindx(bb);
00183   for (unsigned i =0; i<nch; ++i)
00184     pindx.insert_point(convex_hull[i]);
00185   unsigned nsegs = segs.size();
00186   for (unsigned i = 0; i<nsegs; ++i) {
00187     pindx.insert_point(segs[i].point1());
00188     pindx.insert_point(segs[i].point2());
00189   }
00190 
00191   for (unsigned i = 0; i<points.size(); ++i) {
00192       pindx.insert_point(points[i]);
00193   }
00194   // pindx now contains a single vertex pointer for each pair
00195   // of coincident line segment endpoints as well as for each
00196   // isolated endpoint
00197   unsigned npts = pindx.size();
00198   //set up the Delunay constrained triangulation input parameters
00199   struct triangulateio in, out, vorout;
00200   in.numberofholes = 0;
00201   in.numberofregions = 0;
00202   in.numberofpointattributes = 0;
00203   in.numberofpoints = npts;
00204   in.pointlist = (REAL *) malloc(in.numberofpoints * 2 * sizeof(REAL));
00205   for (unsigned i = 0; i<nch; ++i) {
00206     unsigned pi = pindx.vert_index(convex_hull[i]);
00207     in.pointlist[2*pi]=convex_hull[i].x();
00208     in.pointlist[2*pi+1]=convex_hull[i].y();
00209   }
00210   for (unsigned i = 0; i<points.size(); ++i) {
00211     unsigned pi = pindx.vert_index(points[i]);
00212     in.pointlist[2*pi]=points[i].x();
00213     in.pointlist[2*pi+1]=points[i].y();
00214   }
00215 
00216   // line segments to be inserted into the triangulation
00217   in.numberofsegments = nsegs;
00218   in.segmentlist = (int *) malloc(in.numberofsegments * 2 * sizeof(int));
00219   unsigned m = 0;
00220   for (unsigned i = 0; i<nsegs; ++i) {
00221     unsigned pi1 = pindx.vert_index(segs[i].point1());
00222     unsigned pi2 = pindx.vert_index(segs[i].point2());
00223     in.pointlist[2*pi1]   = segs[i].point1().x();
00224     in.pointlist[2*pi1+1] = segs[i].point1().y();
00225     in.pointlist[2*pi2]   = segs[i].point2().x();
00226     in.pointlist[2*pi2+1] = segs[i].point2().y();
00227     in.segmentlist[m]=pi1;     in.segmentlist[m+1]=pi2;
00228   }
00229   //attributes and markers are not used in this algorithm
00230   in.pointattributelist = NULL;
00231   in.pointmarkerlist = (int*)malloc(in.numberofpoints * sizeof(int));
00232   for (int i = 0; i<in.numberofpoints; ++i)
00233     in.pointmarkerlist[i]=0;
00234   in.segmentmarkerlist = (int *) malloc(in.numberofsegments * sizeof(int));;
00235   for (int i = 0; i<in.numberofsegments; ++i)
00236     in.segmentmarkerlist[i]=0;
00237 
00238   out.pointlist = (REAL *) NULL;            // Not needed if -N switch used.
00239   // Not needed if -N switch used or number of point attributes is zero:
00240   out.pointattributelist = (REAL *) NULL;
00241   out.pointmarkerlist = (int *) NULL; // Not needed if -N or -B switch used.
00242   out.trianglelist = (int *) NULL;          // Not needed if -E switch used.
00243   out.neighborlist = (int *) NULL;         // Needed only if -n switch used.
00244   // Needed only if segments are output (-p or -c) and -P not used:
00245   out.segmentlist = (int *) (REAL *) malloc(in.numberofsegments * 2 * sizeof(REAL)); // Suspicious. Why the double cast? and why sizeof(REAL) if it's really int*?
00246   // Needed only if segments are output (-p or -c) and -P and -B not used:
00247   out.segmentmarkerlist = (int *) NULL;
00248   out.edgelist = (int *) NULL;             // Needed only if -e switch used.
00249   out.edgemarkerlist = (int *) NULL;   // Needed if -e used and -B not used.
00250 
00251   //A string of switch characters must be provided
00252   // Triangulate the points.  Switches are chosen to read and write a
00253   //   PSLG (p), preserve the convex hull (c), number everything from
00254   //   zero (z), produce an edge list (e), and a triangle neighbor list (n)
00255 
00256   triangulate("Qpczen", &in, &out, &vorout);
00257 
00258   // construct the imesh data structure
00259   //construct vertices
00260   imesh_vertex_array<2>* verts = new imesh_vertex_array<2>();
00261   unsigned k = 0;
00262   for (unsigned i = 0; i<npts; ++i, k+=2)
00263     verts->push_back(imesh_vertex<2>(out.pointlist[k], out.pointlist[k+1]));
00264   vcl_auto_ptr<imesh_vertex_array_base> v(verts);
00265   mesh.set_vertices(v);
00266   //construct triangular faces
00267   unsigned ntri = static_cast<unsigned>(out.numberoftriangles);
00268   imesh_regular_face_array<3>* faces = new imesh_regular_face_array<3>();
00269   for (unsigned t = 0; t<ntri; ++t)
00270   {
00271     imesh_tri tri(out.trianglelist[t*3],
00272                   out.trianglelist[t*3+1],
00273                   out.trianglelist[t*3+2]);
00274     faces->push_back(tri);
00275   }
00276   //set the faces on the mesh
00277   vcl_auto_ptr<imesh_face_array_base> f(faces);
00278   mesh.set_faces(f);
00279 }