MeshEdgeSamplerT.cc

00001 /*===========================================================================*\
00002  *                                                                           *
00003  *                              OpenFlipper                                  *
00004  *      Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen      *
00005  *                           www.openflipper.org                             *
00006  *                                                                           *
00007  *---------------------------------------------------------------------------*
00008  *  This file is part of OpenFlipper.                                        *
00009  *                                                                           *
00010  *  OpenFlipper is free software: you can redistribute it and/or modify      *
00011  *  it under the terms of the GNU Lesser General Public License as           *
00012  *  published by the Free Software Foundation, either version 3 of           *
00013  *  the License, or (at your option) any later version with the              *
00014  *  following exceptions:                                                    *
00015  *                                                                           *
00016  *  If other files instantiate templates or use macros                       *
00017  *  or inline functions from this file, or you compile this file and         *
00018  *  link it with other files to produce an executable, this file does        *
00019  *  not by itself cause the resulting executable to be covered by the        *
00020  *  GNU Lesser General Public License. This exception does not however       *
00021  *  invalidate any other reasons why the executable file might be            *
00022  *  covered by the GNU Lesser General Public License.                        *
00023  *                                                                           *
00024  *  OpenFlipper is distributed in the hope that it will be useful,           *
00025  *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
00026  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
00027  *  GNU Lesser General Public License for more details.                      *
00028  *                                                                           *
00029  *  You should have received a copy of the GNU LesserGeneral Public          *
00030  *  License along with OpenFlipper. If not,                                  *
00031  *  see <http://www.gnu.org/licenses/>.                                      *
00032  *                                                                           *
00033 \*===========================================================================*/
00034 
00035 /*===========================================================================*\
00036  *                                                                           *
00037  *   $Revision: 6743 $                                                       *
00038  *   $Author: moebius $                                                      *
00039  *   $Date: 2009-08-05 11:03:10 +0200 (Mi, 05. Aug 2009) $                   *
00040  *                                                                           *
00041 \*===========================================================================*/
00042 
00043 
00044 //=============================================================================
00045 //
00046 //  CLASS MeshEdgeSamplerT - IMPLEMENTATION
00047 //
00048 //=============================================================================
00049 
00050 #define ACG_MESHEDGESAMPLERT_C
00051 
00052 //== INCLUDES =================================================================
00053 
00054 #include "MeshEdgeSamplerT.hh"
00055 #include <math.h>
00056 #include <float.h>
00057 #include <map>
00058 #include "../Algorithms.hh"
00059 
00060 // #define MES_DEBUG_HELPER
00061 // #define MES_DEBUG_HELPER_MOVE_ON_EDGE
00062 // #define MES_DEBUG_TEST
00063 
00064 //== NAMESPACES ===============================================================
00065 
00066 namespace ACG {
00067 
00068 //== IMPLEMENTATION ==========================================================
00069 
00070 
00071 template <class MeshT, class PointT>
00072 void
00073 MeshEdgeSamplerT<MeshT, PointT>::
00074 edge_points_in_segment( const PointT&        _p_start,
00075                         const PointT&        _p_end,
00076                         const FH             _fh_start,
00077                         const FH             _fh_end,
00078                         std::vector<PointT>& _points,
00079                         std::vector<EH>&     _ehandles )
00080 {
00081   // clear vectors for new data
00082   _points.clear();
00083   _ehandles.clear();
00084 
00085 #ifdef MES_DEBUG_HELPER
00086   // ############ DEBUG HELPER ###########################
00087   // debug helper: mark start and end triangles
00088   mesh_.status(_fh_start).set_selected(true);
00089   mesh_.status(_fh_end).set_selected(true);
00090   // ############ DEBUG HELPER ###########################
00091 #endif
00092 
00093   // solve trivial case
00094   if(_fh_start == _fh_end)
00095     return;
00096 
00097   // possible end facehandles
00098   std::vector<FH> endfhs;
00099   get_end_fhs_set( _p_end, _fh_end, endfhs);
00100 
00101   // vector for new points and edgehandles
00102   std::vector<Point> new_points0;
00103   std::vector<Point> new_points1;
00104   std::vector<EH>    new_ehs0;
00105   std::vector<EH>    new_ehs1;
00106 
00107   // current values
00108   HEH cur_heh0, cur_heh1;
00109   FH  cur_fh0, cur_fh1;
00110 
00111   // special case _fh_start is in endfhs but not equal to _fh_end
00112   if( std::find(endfhs.begin(), endfhs.end(), _fh_start) != endfhs.end())
00113   {
00114     // find best candidate
00115     Point  p_best;
00116     double d_best = FLT_MAX;
00117 
00118     // find opposite face which is also in endfhs
00119     typename Mesh::FHIter fh_it = mesh_.fh_iter(_fh_start);
00120     for(; fh_it; ++fh_it)
00121     {
00122       FH cur_fh = mesh_.opposite_face_handle(fh_it.handle());
00123       if( std::find(endfhs.begin(), endfhs.end(), cur_fh) != endfhs.end())
00124       {
00125         Point  p_new;
00126         double d_new = line_line_dist(_p_start, _p_end, fh_it.handle(), p_new);
00127         if( d_new < d_best)
00128         {
00129           d_best = d_new;
00130           p_best = p_new;
00131           cur_heh0 = fh_it.handle();
00132           cur_heh1 = fh_it.handle();
00133           cur_fh0  = mesh_.opposite_face_handle( cur_heh0);
00134           cur_fh1  = mesh_.opposite_face_handle( cur_heh1);
00135         }
00136       }
00137     }
00138 
00139     // add new points and edge handles
00140     new_points0.push_back(p_best);
00141     new_points1.push_back(p_best);
00142     new_ehs0.push_back( mesh_.edge_handle( cur_heh0));
00143     new_ehs1.push_back( mesh_.edge_handle( cur_heh1));
00144   }
00145   else // regular case
00146   {
00147     // get current plane
00148     compute_plane( _p_start, _p_end, _fh_start, _fh_end);
00149 
00150     // get two start HalfedgeHandles
00151     get_start_hehs( _p_start, _fh_start, cur_heh0, cur_heh1);
00152 
00153     // hack only one direction
00154     //   cur_heh0 = cur_heh1;
00155 
00156     // add first intersection points
00157     Point p_int;
00158     // first direction
00159     plane_line_intersection( cur_heh0, p_int);
00160     new_points0.push_back( p_int);
00161     new_ehs0.push_back( mesh_.edge_handle( cur_heh0));
00162     // second direction
00163     plane_line_intersection( cur_heh1, p_int);
00164     new_points1.push_back( p_int);
00165     new_ehs1.push_back( mesh_.edge_handle( cur_heh1));
00166 
00167     // current face_handle
00168     cur_fh0 = mesh_.face_handle( mesh_.opposite_halfedge_handle(cur_heh0));
00169     cur_fh1 = mesh_.face_handle( mesh_.opposite_halfedge_handle(cur_heh1));
00170 
00171     // walk until end-facehandle found
00172     int steps = 0;
00173     while( std::find(endfhs.begin(), endfhs.end(), cur_fh0) == endfhs.end() &&
00174            std::find(endfhs.begin(), endfhs.end(), cur_fh1) == endfhs.end() &&
00175            steps < 2000 )
00176     {
00177       // increase steps
00178       ++steps;
00179 
00180       // get next intersection
00181       cur_heh0 = get_next_edge_intersection( cur_heh0, new_points0.back(), p_int);
00182       new_points0.push_back( p_int);
00183       new_ehs0.push_back( mesh_.edge_handle( cur_heh0));
00184 
00185       // get next intersection
00186       cur_heh1 = get_next_edge_intersection( cur_heh1, new_points1.back(), p_int);
00187       new_points1.push_back( p_int);
00188       new_ehs1.push_back( mesh_.edge_handle( cur_heh1));
00189 
00190       // update current face handles
00191       cur_fh0 = mesh_.face_handle(mesh_.opposite_halfedge_handle(cur_heh0));
00192       cur_fh1 = mesh_.face_handle(mesh_.opposite_halfedge_handle(cur_heh1));
00193 
00194       // error handling
00195       if(!cur_fh0.is_valid() || !cur_heh1.is_valid())
00196       {
00197         std::cerr << "ERROR (MeshEdgeSamplerT): face handle not valid (possibly hit boundary)\n";
00198         break;
00199       }
00200     }
00201   }
00202 
00203   // finalize and select
00204   // which case finished ?
00205   if( std::find(endfhs.begin(), endfhs.end(), cur_fh0) != endfhs.end())
00206   {
00207     finish_list( new_points0, new_ehs0, cur_heh0, _fh_end, _p_end, endfhs.size());
00208 
00209     _points = new_points0;
00210     _ehandles = new_ehs0;
00211   }
00212   else if( std::find(endfhs.begin(), endfhs.end(), cur_fh1) != endfhs.end())
00213   {
00214     finish_list( new_points1, new_ehs1, cur_heh1, _fh_end, _p_end, endfhs.size());
00215 
00216     _points = new_points1;
00217     _ehandles = new_ehs1;
00218   }
00219   else
00220   {
00221     std::cerr << "WARNING (MeshEdgeSamplerT): Did not find FH_END\n";
00222 
00223     // return nothing
00224     _points.clear();
00225     _ehandles.clear();
00226   }
00227 
00228 
00229 #ifdef MES_DEBUG_HELPER
00230   // ############ DEBUG HELPER ###########################
00231   // debug helper (select edges
00232   for(unsigned int i=0; i<_ehandles.size(); ++i)
00233   {
00234     mesh_.status( _ehandles[i]).set_selected(true);
00235 
00236 #ifdef MES_DEBUG_HELPER_MOVE_ON_EDGE
00237     HEH heh0 = mesh_.halfedge_handle( _ehandles[i], 0);
00238     HEH heh1 = mesh_.halfedge_handle( _ehandles[i], 1);
00239 
00240     Point p0 = mesh_.point( mesh_.to_vertex_handle(heh0));
00241     Point p1 = mesh_.point( mesh_.to_vertex_handle(heh1));
00242 
00243     if( (_points[i]-p0).norm() < (_points[i]-p1).norm())
00244       _points[i] += (p1-p0)*0.25;
00245     else
00246       _points[i] -= (p1-p0)*0.25;
00247 #endif
00248   }
00249   // ############ DEBUG HELPER ###########################
00250 #endif
00251 }
00252 
00253 
00254 //-----------------------------------------------------------------------------
00255 
00256 
00257 template <class MeshT, class PointT>
00258 void
00259 MeshEdgeSamplerT<MeshT, PointT>::
00260 compute_plane(const PointT&        _p_start,
00261               const PointT&        _p_end,
00262               const FH             _fh_start,
00263               const FH             _fh_end   )
00264 {
00265   // construct cut plane
00266   // get first normal
00267   HEH heh = mesh_.halfedge_handle(_fh_start);
00268   Point p0      = (Point)mesh_.point(mesh_.to_vertex_handle( heh ));
00269   Point p1      = (Point)mesh_.point(mesh_.to_vertex_handle( heh = mesh_.next_halfedge_handle(heh) ));
00270   Point p2      = (Point)mesh_.point(mesh_.to_vertex_handle( heh = mesh_.next_halfedge_handle(heh) ));
00271   Point n_start = ((p1-p0)%(p2-p0)).normalize();
00272 
00273   // get second normal
00274   heh   = mesh_.halfedge_handle(_fh_end);
00275   p0    = mesh_.point(mesh_.to_vertex_handle( heh ));
00276   p1    = mesh_.point(mesh_.to_vertex_handle( heh = mesh_.next_halfedge_handle(heh) ));
00277   p2    = mesh_.point(mesh_.to_vertex_handle( heh = mesh_.next_halfedge_handle(heh) ));
00278   Point n_end = ((p1-p0)%(p2-p0)).normalize();
00279 
00280   // get average normal
00281   Point n_avg = n_start + n_end;
00282   if( n_avg.sqrnorm() < 1e-7) n_avg = n_start - n_end;
00283   n_avg.normalize();
00284 
00285   // get plane data
00286   n_plane_ = n_avg % (_p_start-_p_end).normalize();
00287   if( n_plane_.sqrnorm() > 1e-8) n_plane_.normalize();
00288   else std::cerr << "WARNING: Edge Resampling -> not possible to construct stable cut plane!!!\n";
00289   p_plane_ = (_p_start + _p_end)*0.5;
00290 }
00291 
00292 
00293 //-----------------------------------------------------------------------------
00294 
00295 
00296 template <class MeshT, class PointT>
00297 void
00298 MeshEdgeSamplerT<MeshT, PointT>::
00299 get_start_hehs( const Point& /*_p_start*/ ,
00300                 const FH    _fh_start,
00301                       HEH&  _sheh0,
00302                       HEH&  _sheh1 )
00303 {
00304   // get triangle halfedgehandle
00305   HEH heh0 = mesh_.halfedge_handle( _fh_start);
00306   HEH heh1 = mesh_.next_halfedge_handle( heh0);
00307   HEH heh2 = mesh_.next_halfedge_handle( heh1);
00308 
00309   Point p0 = (Point) mesh_.point(mesh_.to_vertex_handle(heh0));
00310   Point p1 = (Point) mesh_.point(mesh_.to_vertex_handle(heh1));
00311   Point p2 = (Point) mesh_.point(mesh_.to_vertex_handle(heh2));
00312 
00313   double eps = 1e-5*((p1-p0).norm() + (p2-p1).norm() + (p2-p0).norm());
00314 
00315   // degenerate case?
00316   if( line_in_plane( p0, p1, eps))
00317   {
00318 //     std::cerr << "start_hehs degenerate case 0\n";
00319     _sheh0 = heh2;
00320     _sheh1 = heh0;
00321   }
00322   else if( line_in_plane( p1, p2, eps))
00323   {
00324 //     std::cerr << "start_hehs degenerate case 1\n";
00325     _sheh0 = heh0;
00326     _sheh1 = heh1;
00327   }
00328   else if( line_in_plane( p2, p0, eps))
00329   {
00330 //     std::cerr << "start_hehs degenerate case 2\n";
00331     _sheh0 = heh1;
00332     _sheh1 = heh2;
00333   }
00334   // regular case
00335   else
00336   {
00337     // get intersection points
00338     Point ip0, ip1, ip2;
00339     double d0 = plane_line_intersection(p0,p2, ip0);
00340     double d1 = plane_line_intersection(p1,p0, ip1);
00341     double d2 = plane_line_intersection(p2,p1, ip2);
00342 
00343     // sort with increasing distance
00344     sort_intersections( heh0, d0, ip0,
00345                         heh1, d1, ip1,
00346                         heh2, d2, ip2 );
00347 
00348     //no valid case!
00349     if( d1 >= eps && d2 >= eps)
00350     {
00351       std::cerr << "ERROR (MeshEdgeSamplerT): Two intersections larger than epsilon...\n";
00352       _sheh0 = heh0;
00353       _sheh1 = heh1;
00354     }
00355     else if( d0 < eps && d1 < eps && d2 >= eps)
00356     {
00357       // regular case
00358       _sheh0 = heh0;
00359       _sheh1 = heh1;
00360     }
00361     else if( d0 < eps && d1 < eps && d2 < eps)
00362     {
00363       // intersection through vertex (which hehs should be merged?)
00364       if( (ip0-ip1).norm() < (ip0-ip2).norm())
00365       {
00366         _sheh0 = heh0;
00367         _sheh1 = heh2;
00368       }
00369       else
00370       {
00371         _sheh0 = heh0;
00372         _sheh1 = heh1;
00373       }
00374     }
00375     else
00376     {
00377       std::cerr << "ERROR (MeshEdgeSamplerT): this state cannot be reached, what went wrong?\n";
00378       std::cerr << d0 << " " << d1 << " " << d2 << std::endl;
00379       _sheh0 = heh0;
00380       _sheh1 = heh1;
00381     }
00382   }
00383 }
00384 
00385 
00386 //-----------------------------------------------------------------------------
00387 
00388 
00389 template <class MeshT, class PointT>
00390 void
00391 MeshEdgeSamplerT<MeshT, PointT>::
00392 get_end_fhs_set( const Point&     _p_end,
00393                  const FH         _fh_end,
00394                  std::vector<FH>& _endfhs)
00395 {
00396   _endfhs.clear();
00397   _endfhs.push_back( _fh_end );
00398 
00399   std::map<int, bool> stored_fh;
00400   stored_fh[ _fh_end.idx()] = true;
00401 
00402   double eps = epsilon( _fh_end);
00403 
00404   typename Mesh::ConstFaceVertexIter fv_it = mesh_.cfv_iter(_fh_end);
00405   // for each triangle vertex
00406   for(; fv_it; ++fv_it)
00407   {
00408     typename Mesh::ConstVertexFaceIter vf_iter = mesh_.cvf_iter(fv_it.handle());
00409     for(; vf_iter; ++vf_iter)
00410     {
00411       FH cur_fh = vf_iter.handle();
00412 
00413       //not already stored?
00414       if( stored_fh.find(cur_fh.idx()) != stored_fh.end())
00415         continue;
00416 
00417       // get point of triangle
00418       HEH heh0 = mesh_.halfedge_handle( cur_fh);
00419       HEH heh1 = mesh_.next_halfedge_handle( heh0);
00420       HEH heh2 = mesh_.next_halfedge_handle( heh1);
00421 
00422       Point p0 = (Point)mesh_.point( mesh_.to_vertex_handle( heh0));
00423       Point p1 = (Point)mesh_.point( mesh_.to_vertex_handle( heh1));
00424       Point p2 = (Point)mesh_.point( mesh_.to_vertex_handle( heh2));
00425 
00426       Point pc;
00427       double d = ACG::Geometry::distPointTriangle( _p_end,
00428                                                    p0,
00429                                                    p1,
00430                                                    p2,
00431                                                    pc);
00432       // distance small enough?
00433       if( d < eps )
00434       {
00435         _endfhs.push_back( cur_fh);
00436         // tag as stored
00437         stored_fh[cur_fh.idx()] = true;
00438       }
00439     }
00440   }
00441 }
00442 
00443 
00444 //-----------------------------------------------------------------------------
00445 
00446 
00447 template <class MeshT, class PointT>
00448 double
00449 MeshEdgeSamplerT<MeshT, PointT>::
00450 plane_line_intersection( const Point& _p0,
00451                          const Point& _p1,
00452                          Point& _p_int)
00453 {
00454   double a = (n_plane_ | (p_plane_-_p0));
00455   double b = (n_plane_ | (_p1-_p0));
00456 
00457   if( fabs(b) > 1e-8)
00458   {
00459     double s = a/b;
00460 
00461     _p_int = _p0 + (_p1-_p0)*s;
00462 
00463     // TEST Intersection Point
00464     if( fabs((n_plane_| (_p_int-p_plane_)) ) > 1e-8)
00465       std::cerr << "WARNING (MeshEdgeSamplerT): wrong intersection point!!!\n";
00466 
00467 
00468     // in range ?
00469     if( s >= 0.0 && s<= 1.0)
00470       return 0.0;
00471     else
00472       return std::min( (_p_int-_p1).norm(), (_p_int-_p0).norm());
00473   }
00474   else
00475   {
00476     std::cerr << "WARNING (MeshEdgeSamplerT): Line and Plane parallel!!!\n";
00477     return fabs((n_plane_| (_p0-p_plane_)));
00478   }
00479 }
00480 
00481 //-----------------------------------------------------------------------------
00482 
00483 
00484 template <class MeshT, class PointT>
00485 double
00486 MeshEdgeSamplerT<MeshT, PointT>::
00487 plane_line_intersection( const HEH _heh,
00488                          Point& _p_int)
00489 {
00490   Point p0 = mesh_.point(mesh_.from_vertex_handle(_heh));
00491   Point p1 = mesh_.point(mesh_.  to_vertex_handle(_heh));
00492 
00493   return plane_line_intersection( p0, p1, _p_int);
00494 }
00495 
00496 
00497 //-----------------------------------------------------------------------------
00498 
00499 
00500 template <class MeshT, class PointT>
00501 bool
00502 MeshEdgeSamplerT<MeshT, PointT>::
00503 line_in_plane( const Point& _p0,
00504                const Point& _p1,
00505                double       _eps)
00506 {
00507   if( plane_dist( (_p0+_p1)*0.5) < _eps &&
00508       ((_p1-_p0).normalize() | n_plane_) < _eps )
00509     return true;
00510   else
00511     return false;
00512 }
00513 
00514 
00515 //-----------------------------------------------------------------------------
00516 
00517 
00518 template <class MeshT, class PointT>
00519 bool
00520 MeshEdgeSamplerT<MeshT, PointT>::
00521 line_in_plane( const HEH& _heh )
00522 {
00523   Point p0 = mesh_.point(mesh_.from_vertex_handle(_heh));
00524   Point p1 = mesh_.point(mesh_.  to_vertex_handle(_heh));
00525 
00526   double eps = (p1-p0).norm()*3e-5;
00527 
00528   return line_in_plane( p0, p1, eps);
00529 }
00530 
00531 
00532 //-----------------------------------------------------------------------------
00533 
00534 
00535 template <class MeshT, class PointT>
00536 double
00537 MeshEdgeSamplerT<MeshT, PointT>::
00538 plane_dist( const Point& _p0 )
00539 
00540 {
00541   return fabs((n_plane_| (_p0-p_plane_)));
00542 }
00543 
00544 
00545 //-----------------------------------------------------------------------------
00546 
00547 template <class MeshT, class PointT>
00548 double
00549 MeshEdgeSamplerT<MeshT, PointT>::
00550 line_line_dist(const Point& _p_start,
00551                const Point& _p_end,
00552                const HEH&   _heh,
00553                      Point& _p_best)
00554 {
00555   Point phe0 = mesh_.point(mesh_.to_vertex_handle(_heh));
00556   Point phe1 = mesh_.point(mesh_.to_vertex_handle(mesh_.opposite_halfedge_handle(_heh)));
00557   Point pb0;
00558 
00559   return ACG::Geometry::distLineLine(_p_start,
00560                                      _p_end,
00561                                      phe0,
00562                                      phe1,
00563                                      &pb0,
00564                                      &_p_best);
00565 }
00566 
00567 //-----------------------------------------------------------------------------
00568 
00569 
00570 template <class MeshT, class PointT>
00571 typename MeshEdgeSamplerT<MeshT, PointT>::HEH
00572 MeshEdgeSamplerT<MeshT, PointT>::
00573 get_next_edge_intersection( const HEH& _heh, const Point& _pold, Point& _pint)
00574 {
00575   HEH opp_heh = mesh_.opposite_halfedge_handle( _heh);
00576 
00577   if( mesh_.is_boundary( _heh ))
00578   {
00579     std::cerr << "ERROR (MeshEdgeSamplerT): next edge was boundary!!!\n";
00580     return _heh;
00581   }
00582 
00583   // candidate halfedges
00584   HEH cheh0 = mesh_.next_halfedge_handle( opp_heh);
00585   HEH cheh1 = mesh_.next_halfedge_handle( cheh0 );
00586 
00587   // degenerate case?
00588   if( line_in_plane( cheh0))
00589   {
00590     plane_line_intersection( cheh1, _pint);
00591     return cheh1;
00592   }
00593   else if( line_in_plane( cheh1))
00594   {
00595     plane_line_intersection( cheh0, _pint);
00596     return cheh0;
00597   }
00598   else // regular case
00599   {
00600     Point p_int0, p_int1;
00601     double d0 = plane_line_intersection( cheh0, p_int0);
00602     double d1 = plane_line_intersection( cheh1, p_int1);
00603 
00604     double eps = epsilon(_heh);
00605 
00606     // two intersections?
00607     if( d0 < eps && d1 < eps)
00608     {
00609       // take farther intesection
00610       if( (_pold-p_int0).norm() > (_pold-p_int1).norm())
00611       {
00612         _pint = p_int0;
00613         return cheh0;
00614       }
00615       else
00616       {
00617         _pint = p_int1;
00618         return cheh1;
00619       }
00620     }
00621     else
00622     {
00623       if( d0 <= d1 )  // take better candidate
00624       {
00625         _pint = p_int0;
00626         return cheh0;
00627       }
00628       else
00629       {
00630         _pint = p_int1;
00631         return cheh1;
00632       }
00633     }
00634   }
00635 }
00636 
00637 
00638 //-----------------------------------------------------------------------------
00639 
00640 
00641 template <class MeshT, class PointT>
00642 void
00643 MeshEdgeSamplerT<MeshT, PointT>::
00644 sort_intersections( HEH& _heh0, double& _d0, Point& _ip0,
00645                     HEH& _heh1, double& _d1, Point& _ip1,
00646                     HEH& _heh2, double& _d2, Point& _ip2 )
00647 {
00648   if( _d0 > _d1)
00649   {
00650     std::swap( _heh0, _heh1);
00651     std::swap( _d0, _d1);
00652     std::swap( _ip0, _ip1);
00653   }
00654 
00655   if( _d1 > _d2)
00656   {
00657     std::swap( _heh1, _heh2);
00658     std::swap( _d1, _d2);
00659     std::swap( _ip1, _ip2);
00660   }
00661 
00662   if( _d0 > _d1)
00663   {
00664     std::swap( _heh0, _heh1);
00665     std::swap( _d0, _d1);
00666     std::swap( _ip0, _ip1);
00667   }
00668 }
00669 
00670 
00671 //-----------------------------------------------------------------------------
00672 
00673 
00674 template <class MeshT, class PointT>
00675 double
00676 MeshEdgeSamplerT<MeshT, PointT>::
00677 epsilon( const FH& _fh)
00678 {
00679   // get point of triangle
00680   HEH heh0 = mesh_.halfedge_handle( _fh);
00681   HEH heh1 = mesh_.next_halfedge_handle( heh0);
00682   HEH heh2 = mesh_.next_halfedge_handle( heh1);
00683 
00684   Point p0 = (Point)mesh_.point( mesh_.to_vertex_handle( heh0));
00685   Point p1 = (Point)mesh_.point( mesh_.to_vertex_handle( heh1));
00686   Point p2 = (Point)mesh_.point( mesh_.to_vertex_handle( heh2));
00687 
00688   return 1e-5*((p1-p0).norm() + (p2-p1).norm() + (p0-p2).norm());
00689 }
00690 
00691 //-----------------------------------------------------------------------------
00692 
00693 
00694 template <class MeshT, class PointT>
00695 double
00696 MeshEdgeSamplerT<MeshT, PointT>::
00697 epsilon( const HEH& _heh)
00698 {
00699   // get point of edge
00700   Point p0 = (Point)mesh_.point( mesh_.to_vertex_handle  ( _heh));
00701   Point p1 = (Point)mesh_.point( mesh_.from_vertex_handle( _heh));
00702 
00703   return 3e-5*((p1-p0).norm());
00704 }
00705 
00706 
00707 //-----------------------------------------------------------------------------
00708 
00709 
00710 template <class MeshT, class PointT>
00711 void
00712 MeshEdgeSamplerT<MeshT, PointT>::
00713 finish_list( std::vector<Point>& _points,
00714              std::vector<EH>&    _ehs,
00715              const HEH           _cur_heh,
00716              const FH            _fh_end,
00717              const Point&        _p_end,
00718              const int           _type)
00719 
00720 {
00721   // get heh in face and current face handle
00722   HEH cur_opp_heh = mesh_.opposite_halfedge_handle(_cur_heh);
00723   FH  cur_fh = mesh_.face_handle( cur_opp_heh);
00724 
00725   // get two other hehs of triangle
00726   HEH heh0 = mesh_.next_halfedge_handle( cur_opp_heh );
00727   HEH heh1 = mesh_.next_halfedge_handle( heh0);
00728 
00729   // already finished? (only one endfh)
00730   if( cur_fh == _fh_end) return;
00731   else if( _type == 2) // endpoint near edge -> opposite face handle
00732   {
00733     FH fhc0 = mesh_.face_handle(mesh_.opposite_halfedge_handle(heh0));
00734     FH fhc1 = mesh_.face_handle(mesh_.opposite_halfedge_handle(heh1));
00735     FH fhc2 = mesh_.face_handle(_cur_heh);
00736 
00737     // add endpoint
00738     _points.push_back(_p_end);
00739 
00740     if( fhc0 == _fh_end)
00741       _ehs.push_back( mesh_.edge_handle(heh0));
00742     else
00743       if( fhc1 == _fh_end)
00744         _ehs.push_back( mesh_.edge_handle(heh1));
00745       else
00746       {
00747         _ehs.push_back(mesh_.edge_handle(heh0));
00748         std::cerr << "ERROR: could not find end fh...\n";
00749         std::cerr << (fhc2.idx() == _fh_end.idx()) << std::endl;
00750 
00751 //      static bool first_error=true;
00752 //      if(first_error)
00753 //      {
00754 //        first_error = false;
00755 //        std::cerr << "size : " << _ehs.size() << std::endl;
00756 //        std::cerr << "prev : " << fhc2.idx() << std::endl;
00757 //        std::cerr << "cur : " << cur_fh.idx() << std::endl;
00758 //        std::cerr << "next0: " << fhc0.idx() << std::endl;
00759 //        std::cerr << "next1: " << fhc1.idx() << std::endl;
00760 //        std::cerr << "end : " << _fh_end.idx() << std::endl;
00761 
00762 //        mesh_.status(_fh_end).set_selected(true);
00763 //        mesh_.status(fhc2).set_selected(true);
00764 //        mesh_.status(cur_fh).set_selected(true);
00765 //      }
00766 
00767       }
00768 
00769 //     // get triangle points
00770 //     Point p0 = mesh_.point( mesh_.to_vertex_handle(heh0));
00771 //     Point p1 = mesh_.point( mesh_.to_vertex_handle(heh1));
00772 //     Point p2 = mesh_.point( mesh_.to_vertex_handle(cur_opp_heh));
00773 
00774 //     // find corresponding edge
00775 //     double ed0 = ACG::Geometry::distPointLine( _p_end, p2, p0);
00776 //     double ed1 = ACG::Geometry::distPointLine( _p_end, p0, p1);
00777 
00778 //     // add endpoint
00779 //     _points.push_back(_p_end);
00780 
00781 //     if( ed0 < ed1)
00782 //     {
00783 //       _ehs.push_back( mesh_.edge_handle( heh0));
00784 //       // verify result
00785 //       if( mesh_.face_handle( mesh_.opposite_halfedge_handle( heh0)) != _fh_end)
00786 //       {
00787 //      std::cerr << "ERROR (MeshEdgeSamplerT): opposite edge handle is not correct (0) !!!\n";
00788 // #ifdef MES_DEBUG_TEST
00789 //      // ############ DEBUG HELPER ###########################
00790 //      // debug helper (select edge)
00791 //      mesh_.status( mesh_.edge_handle( heh0)).set_selected(true);
00792 //      // ############ DEBUG HELPER ###########################
00793 // #endif
00794 //       }
00795 //     }
00796 //     else
00797 //     {
00798 //       _ehs.push_back( mesh_.edge_handle( heh1));
00799 //       // verify result
00800 //       if( mesh_.face_handle( mesh_.opposite_halfedge_handle( heh1)) != _fh_end)
00801 //       {
00802 //      std::cerr << "ERROR (MeshEdgeSamplerT): opposite edge handle is not correct (1) !!!\n";
00803 // #ifdef MES_DEBUG_TEST
00804 //      // ############ DEBUG HELPER ###########################
00805 //      // debug helper (select edge)
00806 //      mesh_.status( mesh_.edge_handle( heh1)).set_selected(true);
00807 //      // ############ DEBUG HELPER ###########################
00808 // #endif
00809 //       }
00810 //     }
00811   }
00812   else if( _type > 2) // endpoint near triangle point -> circulate
00813   {
00814     std::vector<EH> cw_ehs;
00815     circulate_CW( heh1, _fh_end, cw_ehs);
00816 
00817     std::vector<EH> ccw_ehs;
00818     circulate_CCW(heh0, _fh_end, ccw_ehs);
00819 
00820     // select shorter path to _fh_end
00821     if( cw_ehs.size() < ccw_ehs.size())
00822     {
00823       for(unsigned int i=0; i<cw_ehs.size(); ++i)
00824       {
00825         _ehs.push_back( cw_ehs[i]);
00826         _points.push_back( _p_end);
00827       }
00828     }
00829     else
00830     {
00831       for(unsigned int i=0; i<ccw_ehs.size(); ++i)
00832       {
00833         _ehs.push_back( ccw_ehs[i]);
00834         _points.push_back( _p_end);
00835       }
00836     }
00837 
00838     if( cw_ehs.size() == 0 && ccw_ehs.size() == 0)
00839     {
00840       std::cerr << "circulation failed vidx: " << mesh_.to_vertex_handle( heh0).idx() << std::endl;
00841       mesh_.status( mesh_.to_vertex_handle( heh0)).set_selected(true);
00842     }
00843   }
00844 }
00845 
00846 
00847 //-----------------------------------------------------------------------------
00848 
00849 
00850 template <class MeshT, class PointT>
00851 void
00852 MeshEdgeSamplerT<MeshT, PointT>::
00853 finish_list_old( std::vector<Point>& _points,
00854              std::vector<EH>&    _ehs,
00855              const HEH           _cur_heh,
00856              const FH            _fh_end,
00857              const Point&        _p_end,
00858              const int           _t)
00859 {
00860   // get heh in face and current face handle
00861   HEH cur_opp_heh = mesh_.opposite_halfedge_handle(_cur_heh);
00862   FH  cur_fh = mesh_.face_handle( cur_opp_heh);
00863 
00864   // get two other hehs of triangle
00865   HEH heh0 = mesh_.next_halfedge_handle( cur_opp_heh );
00866   HEH heh1 = mesh_.next_halfedge_handle( heh0);
00867 
00868   // get epsilon
00869   double eps = epsilon( cur_fh );
00870 
00871   VH circulate_vh(-1);
00872 
00873   // already finished?
00874   if( cur_fh == _fh_end) return;
00875   else
00876   {
00877     // get triangle points
00878     Point p0 = mesh_.point( mesh_.to_vertex_handle(heh0));
00879     Point p1 = mesh_.point( mesh_.to_vertex_handle(heh1));
00880     Point p2 = mesh_.point( mesh_.to_vertex_handle(cur_opp_heh));
00881 
00882     double d0 = (_p_end - p0).norm();
00883     double d1 = (_p_end - p1).norm();
00884     double d2 = (_p_end - p2).norm();
00885 
00886     std::cerr << "d0 d1 d2 " << d0 << " " << d1 << " " << d2 << std::endl;
00887     std::cerr << mesh_.to_vertex_handle(heh0).idx() << " "
00888               << mesh_.to_vertex_handle(heh1).idx() << " "
00889               << mesh_.to_vertex_handle(cur_opp_heh).idx() << std::endl;
00890 
00891     // find corresponding circulation vertex
00892     if( d0 < eps)      circulate_vh = mesh_.to_vertex_handle( heh0);
00893     else if( d1 < eps) circulate_vh = mesh_.to_vertex_handle( heh1);
00894     else if( d2 < eps) circulate_vh = mesh_.to_vertex_handle( cur_opp_heh);
00895     else
00896     {
00897       // else find corresponding edge
00898       double ed0 = ACG::Geometry::distPointLine( _p_end, p2, p0);
00899       double ed1 = ACG::Geometry::distPointLine( _p_end, p0, p1);
00900 
00901       // add endpoint
00902       _points.push_back(_p_end);
00903 
00904       if( ed0 < eps)
00905       {
00906         _ehs.push_back( mesh_.edge_handle( heh0));
00907         // verify result
00908         if( mesh_.face_handle( mesh_.opposite_halfedge_handle( heh0)) != _fh_end)
00909           std::cerr << "ERROR (MeshEdgeSamplerT): opposite edge handle is not correct (0) !!!\n";
00910       }
00911       else if( ed1 < eps)
00912       {
00913         _ehs.push_back( mesh_.edge_handle( heh1));
00914         // verify result
00915         if( mesh_.face_handle( mesh_.opposite_halfedge_handle( heh1)) != _fh_end)
00916           std::cerr << "ERROR (MeshEdgeSamplerT): opposite edge handle is not correct (1) !!!\n";
00917       }
00918       else
00919       {
00920         std::cerr << "ERROR (MeshEdgeSamplerT): endpoint should be near edge...\n";
00921         _ehs.push_back( mesh_.edge_handle( heh0));
00922       }
00923     }
00924   }
00925 
00926   if( circulate_vh == mesh_.to_vertex_handle(heh0))
00927   {
00928     std::vector<EH> cw_ehs;
00929     circulate_CW( heh1, _fh_end, cw_ehs);
00930 
00931     std::vector<EH> ccw_ehs;
00932     circulate_CCW(heh0, _fh_end, ccw_ehs);
00933 
00934     // select shorter path to _fh_end
00935     if( cw_ehs.size() < ccw_ehs.size())
00936     {
00937       for(unsigned int i=0; i<cw_ehs.size(); ++i)
00938       {
00939         _ehs.push_back( cw_ehs[i]);
00940         _points.push_back( _p_end);
00941       }
00942     }
00943     else
00944     {
00945       for(unsigned int i=0; i<ccw_ehs.size(); ++i)
00946       {
00947         _ehs.push_back( ccw_ehs[i]);
00948         _points.push_back( _p_end);
00949       }
00950     }
00951   }
00952   else if( circulate_vh == mesh_.to_vertex_handle(heh1))
00953   {
00954     std::vector<EH> ccw_ehs;
00955     circulate_CCW(heh1, _fh_end, ccw_ehs);
00956 
00957     for(unsigned int i=0; i<ccw_ehs.size(); ++i)
00958     {
00959       _ehs.push_back( ccw_ehs[i]);
00960       _points.push_back( _p_end);
00961     }
00962   }
00963   else if( circulate_vh == mesh_.to_vertex_handle(cur_opp_heh))
00964   {
00965     std::vector<EH> cw_ehs;
00966     circulate_CW(heh0, _fh_end, cw_ehs);
00967 
00968     for(unsigned int i=0; i<cw_ehs.size(); ++i)
00969     {
00970       _ehs.push_back( cw_ehs[i]);
00971       _points.push_back( _p_end);
00972     }
00973   }
00974 }
00975 
00976 
00977 //-----------------------------------------------------------------------------
00978 
00979 
00980 template <class MeshT, class PointT>
00981 void
00982 MeshEdgeSamplerT<MeshT, PointT>::
00983 circulate_CW(HEH _heh, FH _fh_end, std::vector<EH>& _cw_ehs)
00984 {
00985   _cw_ehs.clear();
00986 
00987   // insert first heh
00988   HEH cur_heh = _heh;
00989   _cw_ehs.push_back( mesh_.edge_handle(cur_heh) );
00990 
00991   while( mesh_.face_handle(mesh_.opposite_halfedge_handle( cur_heh)) != _fh_end )
00992   {
00993     cur_heh = mesh_.opposite_halfedge_handle( cur_heh);
00994     cur_heh = mesh_.next_halfedge_handle(cur_heh);
00995 
00996     _cw_ehs.push_back( mesh_.edge_handle( cur_heh));
00997 
00998     // error check
00999     if( cur_heh == _heh)
01000     {
01001       std::cerr << "ERROR (MeshEdgeSamplerT): circulate_CW could not find _fh_end... "
01002                 << _cw_ehs.size() << std::endl;
01003       _cw_ehs.clear();
01004       break;
01005     }
01006   }
01007 }
01008 
01009 
01010 //-----------------------------------------------------------------------------
01011 
01012 
01013 template <class MeshT, class PointT>
01014 void
01015 MeshEdgeSamplerT<MeshT, PointT>::
01016 circulate_CCW(HEH _heh, FH _fh_end, std::vector<EH>& _ccw_ehs)
01017 {
01018   _ccw_ehs.clear();
01019 
01020   // insert first heh
01021   HEH cur_heh = _heh;
01022   _ccw_ehs.push_back( mesh_.edge_handle(cur_heh) );
01023 
01024   while( mesh_.face_handle(mesh_.opposite_halfedge_handle( cur_heh)) != _fh_end )
01025   {
01026     cur_heh = mesh_.opposite_halfedge_handle( cur_heh);
01027     cur_heh = mesh_.next_halfedge_handle(cur_heh);
01028     cur_heh = mesh_.next_halfedge_handle(cur_heh);
01029 
01030     _ccw_ehs.push_back( mesh_.edge_handle( cur_heh));
01031 
01032     // error check
01033     if( cur_heh == _heh)
01034     {
01035       std::cerr << "ERROR (MeshEdgeSamplerT): circulate_CCW could not find _fh_end... "
01036                 << _ccw_ehs.size() << std::endl;
01037       _ccw_ehs.clear();
01038       break;
01039     }
01040   }
01041 }
01042 
01043 //=============================================================================
01044 } // namespace ACG
01045 //=============================================================================

acg pic Project OpenFlipper, ©  Computer Graphics Group, RWTH Aachen. Documentation generated using doxygen .