PolyLineT.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: 7053 $                                                       *
00038  *   $Author: bommes $                                                      *
00039  *   $Date: 2009-09-11 11:52:15 +0200 (Fr, 11. Sep 2009) $                   *
00040  *                                                                           *
00041 \*===========================================================================*/
00042 
00043 
00044 
00045 //=============================================================================
00046 //
00047 //  CLASS PolyLineT - IMPLEMENTATION
00048 //
00049 //=============================================================================
00050 
00051 #define ACG_POLYLINET_C
00052 
00053 //== INCLUDES =================================================================
00054 
00055 #include <OpenMesh/Core/Geometry/VectorT.hh>
00056 
00057 #include <iostream>
00058 #include <fstream>
00059 #include <map>
00060 
00061 #include "PolyLineT.hh"
00062 #include "MeshEdgeSamplerT.hh"
00063 
00064 #include <float.h>
00065 #include <ACG/Geometry/Algorithms.hh>
00066 
00067 #ifdef USE_PHYSIM
00068 #include <PhySim/Meshes/ConstrainedDelaunayT.hh>
00069 #endif
00070 
00071 #ifndef WIN32
00072 #include <stdlib.h>
00073 #endif
00074 
00075 #ifdef USE_OPENMP
00076 #include <omp.h>
00077 #endif
00078 
00079 //== NAMESPACES ===============================================================
00080 
00081 namespace ACG {
00082 
00083 //== IMPLEMENTATION ==========================================================
00084 
00085 
00086 // comparison class for polyline_mesh_integration
00087 template <class MT>
00088 class Ecmp
00089 {
00090 public:
00091   Ecmp( MT& _mesh, typename MT::Point _v) : mesh_(_mesh), v_(_v) {}
00092   
00093   bool operator()(const int& _vidx0, const int& _vidx1)
00094   {
00095     typename MT::Scalar d0 = (mesh_.point( mesh_.vertex_handle(_vidx0)) | v_);
00096     typename MT::Scalar d1 = (mesh_.point( mesh_.vertex_handle(_vidx1)) | v_);
00097     
00098     return d0 < d1;
00099   }
00100   
00101   
00102   MT&                 mesh_;
00103   typename MT::Point  v_;
00104 };
00105 
00106 
00107 //-----------------------------------------------------------------------------
00108 
00109 
00111 template <class PointT>
00112 PolyLineT<PointT>::
00113   PolyLineT( bool _closed )
00114     : closed_(_closed),
00115       ref_count_vnormals_(0),
00116       ref_count_vcolors_(0),
00117       ref_count_vscalars_(0),
00118       ref_count_vselections_(0),
00119       ref_count_vvhandles_(0),
00120       ref_count_vehandles_(0),
00121       ref_count_vfhandles_(0),
00122       ref_count_enormals_(0),
00123       ref_count_ecolors_(0),
00124       ref_count_escalars_(0),
00125       ref_count_eselections_(0)
00126 {
00127 }
00128 
00129 //-----------------------------------------------------------------------------
00130 
00132 template <class PointT>
00133 PolyLineT<PointT>::
00134   PolyLineT( const PolyLineT& _line )
00135 {
00136   closed_ = _line.closed_;
00137 
00138   //copy points
00139   points_ = _line.points_;
00140 
00141   //copy vertex properties
00142   vnormals_    = _line.vnormals_;
00143   vcolors_     = _line.vcolors_;
00144   vscalars_    = _line.vscalars_;
00145   vselections_ = _line.vselections_;
00146   vvhandles_   = _line.vvhandles_;
00147   vehandles_   = _line.vehandles_;
00148   vfhandles_   = _line.vfhandles_;
00149 
00150   //copy edge properties
00151   enormals_    = _line.enormals_;
00152   ecolors_     = _line.ecolors_;
00153   escalars_    = _line.escalars_;
00154   eselections_ = _line.eselections_;
00155 
00156   // property reference counter
00157   ref_count_vnormals_    = _line.ref_count_vnormals_;
00158   ref_count_vcolors_     = _line.ref_count_vcolors_;
00159   ref_count_vscalars_    = _line.ref_count_vscalars_;
00160   ref_count_vselections_ = _line.ref_count_vselections_;
00161   ref_count_vvhandles_   = _line.ref_count_vvhandles_;
00162   ref_count_vehandles_   = _line.ref_count_vehandles_;
00163   ref_count_vfhandles_   = _line.ref_count_vfhandles_;
00164 
00165   ref_count_enormals_    = _line.ref_count_enormals_;
00166   ref_count_ecolors_     = _line.ref_count_ecolors_;
00167   ref_count_escalars_    = _line.ref_count_escalars_;
00168   ref_count_eselections_ = _line.ref_count_eselections_;
00169 }
00170 
00171 //-----------------------------------------------------------------------------
00172 
00173 
00174 template <class PointT>
00175 void
00176 PolyLineT<PointT>::
00177 clear()
00178 {
00179   points_.clear();
00180 
00181   // clear propertiy vectors
00182   vnormals_.clear();
00183   vcolors_.clear();
00184   vscalars_.clear();
00185   vselections_.clear();
00186   vvhandles_.clear();
00187   vehandles_.clear();
00188   vfhandles_.clear();
00189 
00190   enormals_.clear();
00191   ecolors_.clear();
00192   escalars_.clear();
00193   eselections_.clear();
00194 }
00195 
00196 
00197 //-----------------------------------------------------------------------------
00198 
00199 
00200 template <class PointT>
00201 void
00202 PolyLineT<PointT>::
00203 resize( unsigned int _n)
00204 {
00205   if( _n < n_vertices())
00206   {
00207 
00208     points_.resize( _n);
00209 
00210     // clear propertiy vectors
00211     if( vertex_normals_available() )
00212       vnormals_.resize( _n);
00213     if( vertex_colors_available())
00214       vcolors_.resize( _n);
00215     if( vertex_scalars_available())
00216       vscalars_.resize( _n);
00217     if( vertex_selections_available())
00218       vselections_.resize( _n);
00219     if( vertex_vhandles_available())
00220       vvhandles_.resize( _n);
00221     if( vertex_ehandles_available())
00222       vehandles_.resize( _n);
00223     if( vertex_fhandles_available())
00224       vfhandles_.resize( _n);
00225 
00226     if( edge_normals_available())
00227       enormals_.resize( _n);
00228     if( edge_colors_available())
00229       ecolors_.resize( _n);
00230     if( edge_scalars_available())
00231       escalars_.resize( _n);
00232     if( edge_selections_available())
00233       eselections_.resize( _n);
00234   }
00235   else
00236   {
00237     while( n_vertices() < _n)
00238       add_point( Point());
00239   }
00240 }
00241 
00242 
00243 //-----------------------------------------------------------------------------
00244 
00245 
00246 template <class PointT>
00247 void
00248 PolyLineT<PointT>::
00249 add_point(const Point& _p)
00250 {
00251   // add new point
00252   points_.push_back( _p );
00253 
00254   // add available properties
00255   if( vertex_normals_available() )
00256     vnormals_.push_back( Point(0,0,0));
00257 
00258   if( vertex_colors_available())
00259     vcolors_.push_back( Point(1,0,1));
00260 
00261   if( vertex_scalars_available())
00262     vscalars_.push_back( 0.0 );
00263 
00264   if( vertex_selections_available())
00265     vselections_.push_back( false);
00266 
00267   if( vertex_vhandles_available())
00268     vvhandles_.push_back(-1);
00269 
00270   if( vertex_ehandles_available())
00271     vehandles_.push_back(-1);
00272 
00273   if( vertex_fhandles_available())
00274     vfhandles_.push_back(-1);
00275 
00276   if( edge_normals_available())
00277     enormals_.push_back( Point(0,0,0));
00278 
00279   if( edge_colors_available())
00280     ecolors_.push_back( Point(1,0,1));
00281 
00282   if( edge_scalars_available())
00283     escalars_.push_back( 0.0);
00284 
00285   if( edge_selections_available())
00286     eselections_.push_back(false);
00287 }
00288 
00289 //-----------------------------------------------------------------------------
00290 
00291 template <class PointT>
00292 void
00293 PolyLineT<PointT>::
00294 insert_point(int _idx, const Point& _p)
00295 {
00296   assert(_idx < (int)n_vertices() );
00297   
00298   // insert new point
00299   points_.insert(points_.begin()+_idx, _p);
00300 
00301   // insert available properties
00302   if( vertex_normals_available() )
00303     vnormals_.insert(vnormals_.begin()+_idx, Point(0,0,0));
00304 
00305   if( vertex_colors_available())
00306     vcolors_.insert(vcolors_.begin()+_idx, Point(1,0,1));
00307 
00308   if( vertex_scalars_available())
00309     vscalars_.insert(vscalars_.begin()+_idx, 0.0 );
00310 
00311   if( vertex_selections_available())
00312     vselections_.insert(vselections_.begin()+_idx, false);
00313 
00314   if( vertex_vhandles_available())
00315     vvhandles_.insert(vvhandles_.begin()+_idx, -1);
00316 
00317   if( vertex_ehandles_available())
00318     vehandles_.insert(vehandles_.begin()+_idx, -1);
00319 
00320   if( vertex_fhandles_available())
00321     vfhandles_.insert(vfhandles_.begin()+_idx, -1);
00322 
00323   if( edge_normals_available())
00324     enormals_.insert(enormals_.begin()+_idx, Point(0,0,0));
00325 
00326   if( edge_colors_available())
00327     ecolors_.insert(ecolors_.begin()+_idx, Point(1,0,1));
00328 
00329   if( edge_scalars_available())
00330     escalars_.insert(escalars_.begin()+_idx, 0.0);
00331 
00332   if( edge_selections_available())
00333     eselections_.insert(eselections_.begin()+_idx, false);
00334 }
00335 
00336 
00337 //-----------------------------------------------------------------------------
00338   
00339 
00340 template <class PointT>
00341 void
00342 PolyLineT<PointT>::
00343 delete_point(int _idx)
00344 {
00345   assert(_idx < (int)n_vertices() );
00346 
00347   // delete point at given index
00348   points_.erase(points_.begin()+_idx);
00349 
00350 
00351   // delete available properties
00352   if( vertex_normals_available() )
00353     vnormals_.erase(vnormals_.begin()+_idx);
00354 
00355   if( vertex_colors_available())
00356     vcolors_.erase(vcolors_.begin()+_idx);
00357 
00358   if( vertex_scalars_available())
00359     vscalars_.erase(vscalars_.begin()+_idx);
00360 
00361   if( vertex_selections_available())
00362     vselections_.erase(vselections_.begin()+_idx);
00363 
00364   if( vertex_vhandles_available())
00365     vvhandles_.erase(vvhandles_.begin()+_idx);
00366 
00367   if( vertex_ehandles_available())
00368     vehandles_.erase(vehandles_.begin()+_idx);
00369 
00370   if( vertex_fhandles_available())
00371     vfhandles_.erase(vfhandles_.begin()+_idx);
00372 
00373   if( edge_normals_available())
00374     enormals_.erase(enormals_.begin()+_idx);
00375 
00376   if( edge_colors_available())
00377     ecolors_.erase(ecolors_.begin()+_idx);
00378 
00379   if( edge_scalars_available())
00380     escalars_.erase(escalars_.begin()+_idx);
00381 
00382   if( edge_selections_available())
00383     eselections_.erase(eselections_.begin()+_idx);
00384 }
00385 
00386 
00387 //-----------------------------------------------------------------------------
00388 
00389 
00390 template <class PointT>
00391 typename PolyLineT<PointT>::Scalar
00392 PolyLineT<PointT>::
00393 length() const
00394 {
00395   Scalar l = 0;
00396 
00397   unsigned int n = points_.size();
00398 
00399   if( !closed_) --n;
00400 
00401   for(unsigned int i=0; i<n; ++i)
00402   {
00403     l += (points_[(i+1)%n]-points_[i]).norm();
00404   }
00405 
00406   return l;
00407 }
00408 
00409 //-----------------------------------------------------------------------------
00410 
00411 
00412 template <class PointT>
00413 void
00414 PolyLineT<PointT>::
00415 subdivide_old(Scalar _largest)
00416 {
00417   // check validity
00418   if(!points_.size()) return;
00419 
00420   unsigned int n_subdivisions = 1;
00421 
00422   while( n_subdivisions != 0)
00423   {
00424 
00425     n_subdivisions = 0;
00426 
00427     std::vector<Point> new_points;
00428 
00429     new_points.push_back( points_[0]);
00430 
00431     // squared maximal length
00432     Scalar l2 = _largest*_largest;
00433 
00434     for(unsigned int i=1; i<points_.size(); ++i)
00435     {
00436       if( (new_points.back() - points_[i]).sqrnorm() > l2)
00437       {
00438         Point mid_point = (new_points.back() + points_[i])*0.5;
00439 
00440         new_points.push_back( mid_point );
00441         ++n_subdivisions;
00442       }
00443 
00444       new_points.push_back( points_[i]);
00445     }
00446 
00447     // last interval for closed polyline
00448     if( closed_)
00449     {
00450       if( (new_points.back() - points_[0]).sqrnorm() > l2)
00451       {
00452         Point mid_point = (new_points.back() + points_[0])*0.5;
00453         new_points.push_back( mid_point );
00454         ++n_subdivisions;
00455       }
00456     }
00457 
00458     // update points
00459     resize( new_points.size() );
00460     points_ = new_points;
00461   }
00462 }
00463 
00464 
00465 //-----------------------------------------------------------------------------
00466 
00467 
00468 template <class PointT>
00469 void
00470 PolyLineT<PointT>::
00471 subdivide(Scalar _largest)
00472 {
00473   // check validity
00474   if(!n_vertices()) return;
00475 
00476   unsigned int n_subdivisions = 1;
00477 
00478   while( n_subdivisions != 0)
00479   {
00480 
00481     n_subdivisions = 0;
00482 
00483     // add new polyline and add first point
00484     PolyLineT<PointT> new_pl = *this;
00485     new_pl.resize(1);
00486     new_pl.copy_vertex_complete(*this, 0, 0);
00487 
00488     // squared maximal length
00489     Scalar l2 = _largest*_largest;
00490 
00491     for(unsigned int i=1; i<points_.size(); ++i)
00492     {
00493       if( (new_pl.point(new_pl.n_vertices()-1) - points_[i]).sqrnorm() > l2)
00494       {
00495         Point mid_point = (new_pl.point(new_pl.n_vertices()-1) + points_[i])*0.5;
00496 
00497         new_pl.add_point( mid_point );
00498         ++n_subdivisions;
00499       }
00500 
00501       // copy vertex
00502       new_pl.resize( new_pl.n_vertices()+1);
00503       new_pl.copy_vertex_complete( *this, i, new_pl.n_vertices()-1);
00504     }
00505 
00506     // last interval for closed polyline
00507     if( closed_)
00508     {
00509       if( (new_pl.point(new_pl.n_vertices()-1) - points_[0]).sqrnorm() > l2)
00510       {
00511         Point mid_point = (new_pl.point(new_pl.n_vertices()-1) + points_[0])*0.5;
00512         new_pl.add_point( mid_point );
00513         ++n_subdivisions;
00514       }
00515     }
00516 
00517     // update points
00518     *this = new_pl;
00519   }
00520 }
00521 
00522 //-----------------------------------------------------------------------------
00523 
00524 
00525 template <class PointT>
00526 void
00527 PolyLineT<PointT>::
00528 collapse(Scalar _smallest)
00529 {
00530   // check validity
00531   if(!n_vertices()) return;
00532 
00533   unsigned int n_collapses = 1;
00534 
00535   unsigned int n_iter = 0;
00536 
00537   while( n_collapses != 0 && n_iter < 5)
00538   {
00539     ++n_iter;
00540     n_collapses = 0;
00541 
00542     // create new PolyLine (with all properties) and insert first point
00543     PolyLineT<PointT> new_pl = *this;
00544     new_pl.resize(1);
00545     new_pl.copy_vertex_complete( *this, 0, 0);
00546 
00547     // squared maximal length
00548     Scalar l2 = _smallest*_smallest;
00549 
00550     for(unsigned int i=1; i<points_.size(); ++i)
00551     {
00552       // check whether vertex is selected
00553       bool vertex_selected = false;
00554       if( vertex_selections_available() && vertex_selection(i))
00555         vertex_selected = true;
00556 
00557       if( (new_pl.point(new_pl.n_vertices()-1) - points_[i]).sqrnorm() >= l2 ||
00558           vertex_selected ||
00559           (!closed_ && i==points_.size()-1) )
00560       {
00561         // copy next point
00562         new_pl.resize( new_pl.n_vertices()+1);
00563         new_pl.copy_vertex_complete( *this, i, new_pl.n_vertices()-1);
00564       }
00565       else ++n_collapses;
00566     }
00567 
00568     // last interval for closed polyline
00569     if( closed_)
00570     {
00571       // check whether vertex is selected
00572       bool vertex_selected = false;
00573       if( vertex_selections_available() && vertex_selection(points_.size()-1))
00574         vertex_selected = true;
00575 
00576       if( (new_pl.point(new_pl.n_vertices()-1) - points_[0]).sqrnorm() < l2 && !vertex_selected)
00577       {
00578         new_pl.resize( new_pl.n_vertices()-1);
00579       }
00580       else ++n_collapses;
00581     }
00582 
00583     // update points
00584     *this = new_pl;
00585   }
00586 }
00587 
00588 
00589 //-----------------------------------------------------------------------------
00590 
00591 
00592 template <class PointT>
00593 void
00594 PolyLineT<PointT>::
00595 collapse_old(Scalar _smallest)
00596 {
00597   // check validity
00598   if(!points_.size()) return;
00599 
00600   unsigned int n_collapses = 1;
00601 
00602   unsigned int n_iter = 0;
00603 
00604   while( n_collapses != 0 && n_iter < 5)
00605   {
00606     ++n_iter;
00607     n_collapses = 0;
00608 
00609     std::vector<Point> new_points;
00610 
00611     new_points.push_back( points_[0]);
00612 
00613     // squared maximal length
00614     Scalar l2 = _smallest*_smallest;
00615 
00616     for(unsigned int i=1; i<points_.size(); ++i)
00617     {
00618       if( (new_points.back() - points_[i]).sqrnorm() >= l2)
00619       {
00620         new_points.push_back( points_[i]);
00621       }
00622       else ++n_collapses;
00623     }
00624 
00625     // last interval for closed polyline
00626     if( closed_)
00627     {
00628       if( (new_points.back() - points_[0]).sqrnorm() >= l2)
00629       {
00630         new_points.resize( new_points.size()-1);
00631       }
00632       else ++n_collapses;
00633     }
00634     else
00635     {
00636       // always add endpoint for open polylines
00637       if( points_.back() != new_points.back())
00638         new_points.back() = points_.back();
00639     }
00640 
00641     // update points
00642     resize( new_points.size() );
00643     points_ = new_points;
00644   }
00645 }
00646 
00647 
00648 //-----------------------------------------------------------------------------
00649 
00650 
00651 template <class PointT>
00652 void
00653 PolyLineT<PointT>::
00654 smooth_uniform_laplace()
00655 {
00656   // copy point positions
00657   std::vector<Point> points_old( points_ );
00658 
00659   int n = points_.size();
00660 
00661   int is = 0;
00662   int ie = n;
00663 
00664   if( !closed_ )
00665   {
00666     ++is;
00667     --ie;
00668   }
00669 
00670   if( vertex_selections_available())
00671   {
00672     #ifdef USE_OPENMP
00673     #pragma omp parallel for
00674     #endif
00675     for( int i=is; i<ie; ++i)
00676     {
00677       // only smooth not selected vertices
00678       if( !vertex_selection(i))
00679       // laplace stencil 1,-2,1
00680              points_[i] = (points_old[ (i-1+n)%n ] +
00681                                 points_old[ (i+n  )%n ]*2.0 +
00682                                 points_old[ (i+1  )%n ]      )*0.25;
00683 
00684     }
00685   }
00686   else
00687   {
00688     #ifdef USE_OPENMP
00689     #pragma omp parallel for
00690     #endif
00691     for( int i=is; i<ie; ++i)
00692     {
00693       // laplace stencil 1,-2,1
00694       points_[i] = (points_old[ (i-1+n)%n ]       +
00695                               points_old[ (i+n  )%n ] * 2.0 +
00696                               points_old[ (i+1  )%n ]         )*0.25;
00697     }
00698   }
00699 }
00700 
00701 
00702 //-----------------------------------------------------------------------------
00703 
00704 
00705 template <class PointT>
00706 void
00707 PolyLineT<PointT>::
00708 smooth_uniform_laplace2()
00709 {
00710   // copy point positions
00711   std::vector<Point> points_old( points_ );
00712 
00713   int n = points_.size();
00714 
00715   int is = 0;
00716   int ie = n;
00717 
00718   if( !closed_ )
00719   {
00720     is+=2;
00721     ie-=2;
00722   }
00723 
00724   if( vertex_selections_available())
00725   {
00726     #ifdef USE_OPENMP
00727     #pragma omp parallel for
00728     #endif
00729     for(int i=is; i<ie; ++i)
00730     {
00731       // only smooth not selected vertices
00732       if( !vertex_selection(i))
00733         // laplace^2 stencil 1,-4,6,-4,1
00734         points_[i] -= (points_old[ (i-2+2*n)%n ]      +
00735                        points_old[ (i-1+2*n)%n ]*-4.0 +
00736                        points_old[ (i      )%n ]* 6.0 +
00737                        points_old[ (i+1    )%n ]*-4.0 +
00738                        points_old[ (i+2    )%n ]      )/(16.0*2.0);
00739     }
00740   }
00741   else
00742   {
00743     #ifdef USE_OPENMP
00744     #pragma omp parallel for
00745     #endif
00746     for(int i=is; i<ie; ++i)
00747     {
00748       // laplace^2 stencil 1,-4,6,-4,1
00749       points_[i] -= (points_old[ (i-2+2*n)%n ]      +
00750                                points_old[ (i-1+2*n)%n ]*-4.0 +
00751                      points_old[ (i      )%n ]* 6.0 +
00752                      points_old[ (i+1    )%n ]*-4.0 +
00753                      points_old[ (i+2    )%n ]      )/(16.0*2.0);
00754     }
00755   }
00756 }
00757 
00758 
00759 //-----------------------------------------------------------------------------
00760 
00761 
00762 template <class PointT>
00763 void
00764 PolyLineT<PointT>::
00765 smooth_uniform_laplace3()
00766 {
00767   // copy point positions
00768   std::vector<Point> points_old( points_ );
00769 
00770   int n = points_.size();
00771 
00772   int is = 0;
00773   int ie = n;
00774 
00775   if( !closed_ )
00776   {
00777     is+=3;
00778     ie-=3;
00779   }
00780 
00781   if( vertex_selections_available())
00782   {
00783     #ifdef USE_OPENMP
00784     #pragma omp parallel for
00785     #endif
00786     for( int i=is; i<ie; ++i)
00787     {
00788       // only smooth not selected vertices
00789       if( !vertex_selection(i))
00790              // laplace^3 stencil 1,-6,15,-20,15,-6,1
00791              points_[i] = (points_old[ (i-3+3*n)%n ]        +
00792                       points_old[ (i-2+3*n)%n ]*(-6.0) +
00793                       points_old[ (i-1+3*n)%n ]*15.0   +
00794                       points_old[ (i      )   ]*(44.0) +
00795                       points_old[ (i+1    )%n ]*15.0   +
00796                       points_old[ (i+2    )%n ]*(-6.0) +
00797                       points_old[ (i+3    )%n ]        )/64.0;
00798 
00799     }
00800   }
00801   else
00802   {
00803     #ifdef USE_OPENMP
00804     #pragma omp parallel for
00805     #endif
00806     for( int i=is; i<ie; ++i)
00807     {
00808            // laplace^3 stencil 1,-6,15,-20,15,-6,1
00809            points_[i] = (points_old[ (i-3+3*n)%n ]        +
00810                     points_old[ (i-2+3*n)%n ]*(-6.0) +
00811                     points_old[ (i-1+3*n)%n ]*15.0   +
00812                     points_old[ (i      )   ]*(44.0) +
00813                     points_old[ (i+1    )%n ]*15.0   +
00814                     points_old[ (i+2    )%n ]*(-6.0) +
00815                     points_old[ (i+3    )%n ]        )/64.0;
00816     }
00817   }
00818 }
00819 
00820 
00821 //-----------------------------------------------------------------------------
00822 
00823 
00824 template <class PointT>
00825 template <class MeshT, class SpatialSearchT>
00826 void
00827 PolyLineT<PointT>::
00828 project_to_mesh( const MeshT& _mesh, SpatialSearchT * _ssearch)
00829 {
00830   typename MeshT::FaceHandle fh;
00831 
00832   #ifdef USE_OPENMP
00833   #pragma omp parallel for
00834   #endif
00835   for(unsigned int i=0; i<points_.size(); ++i)
00836   {
00837     points_[i] = find_nearest_point( _mesh, points_[i], fh, _ssearch);
00838   }
00839 }
00840 
00841 
00842 //-----------------------------------------------------------------------------
00843 
00844 
00845 template <class PointT>
00846 template <class MeshT, class SpatialSearchT>
00847 void
00848 PolyLineT<PointT>::
00849 project_to_mesh( const std::vector<MeshT*>     _mesh,
00850                            std::vector<SpatialSearchT*>* _ssearch)
00851 {
00852   typename MeshT::FaceHandle fh;
00853 
00854   #ifdef USE_OPENMP
00855   #pragma omp parallel for
00856   #endif
00857   for(int i=0; i< (int)points_.size(); ++i)
00858   {
00859     // init d_best
00860     typename MeshT::Scalar d_best = -1;
00861 
00862     // best point
00863     Point p_best(0,0,0);
00864 
00865     // iterate over all possible meshes
00866     for(unsigned int j=0; j<_mesh.size(); ++j)
00867     {
00868       double d_new(-1);
00869 
00870       Point p_new;
00871       if(_ssearch != 0)
00872              p_new = find_nearest_point( *(_mesh[j]), points_[i], fh, ((*_ssearch)[j]), &d_new);
00873       else
00874              p_new = find_nearest_point( *(_mesh[j]), points_[i], fh, (SpatialSearchT*)0, &d_new);
00875 
00876       // store best result
00877       if( d_new < d_best || d_best == -1)
00878       {
00879              p_best = p_new;
00880              d_best = d_new;
00881       }
00882     }
00883 
00884     if( d_best != -1)
00885       points_[i] = p_best;
00886   }
00887 }
00888 
00889 
00890 //-----------------------------------------------------------------------------
00891 
00892 
00893 template <class PointT>
00894 template <class MeshT, class SpatialSearchT>
00895 typename PolyLineT<PointT>::Point
00896 PolyLineT<PointT>::
00897 find_nearest_point( const MeshT&                _mesh,
00898                     const Point&                _point,
00899                     typename MeshT::FaceHandle& _fh,
00900                     SpatialSearchT *            _ssearch,
00901                     double*                     _dbest)
00902 {
00903   typename MeshT::Point p0 = (typename MeshT::Point) _point;
00904 
00905   typename MeshT::Point  p_best = _mesh.point(_mesh.vertex_handle(0));
00906   typename MeshT::Scalar d_best = (p0-p_best).sqrnorm();
00907 
00908   typename MeshT::FaceHandle fh_best;
00909 
00910   if( _ssearch == 0 )
00911   {
00912     // exhaustive search
00913     typename MeshT::ConstFaceIter cf_it  = _mesh.faces_begin();
00914     typename MeshT::ConstFaceIter cf_end = _mesh.faces_end();
00915 
00916     for(; cf_it != cf_end; ++cf_it)
00917     {
00918       typename MeshT::ConstFaceVertexIter cfv_it = _mesh.cfv_iter(cf_it);
00919 
00920       const typename MeshT::Point& pt0 = _mesh.point(   cfv_it);
00921       const typename MeshT::Point& pt1 = _mesh.point( ++cfv_it);
00922       const typename MeshT::Point& pt2 = _mesh.point( ++cfv_it);
00923 
00924       typename MeshT::Point ptn;
00925 
00926       typename MeshT::Scalar d = Geometry::distPointTriangleSquared( p0,
00927                                                                      pt0,
00928                                                                      pt1,
00929                                                                      pt2,
00930                                                                      ptn );
00931 
00932       if( d < d_best)
00933       {
00934         d_best = d;
00935         p_best = ptn;
00936 
00937         fh_best = cf_it.handle();
00938       }
00939     }
00940 
00941     // return facehandle
00942     _fh = fh_best;
00943 
00944     // return distance
00945     if(_dbest)
00946       *_dbest = sqrt(d_best);
00947 
00948 
00949     return (Point) p_best;
00950   }
00951   else
00952   {
00953     typename MeshT::FaceHandle     fh = _ssearch->nearest(p0).handle;
00954     typename MeshT::CFVIter        fv_it = _mesh.cfv_iter(fh);
00955 
00956     const typename MeshT::Point&   pt0 = _mesh.point(  fv_it);
00957     const typename MeshT::Point&   pt1 = _mesh.point(++fv_it);
00958     const typename MeshT::Point&   pt2 = _mesh.point(++fv_it);
00959 
00960     // project
00961     d_best = Geometry::distPointTriangleSquared(p0, pt0, pt1, pt2, p_best);
00962 
00963     // return facehandle
00964     _fh = fh;
00965 
00966     // return distance
00967     if(_dbest)
00968       *_dbest = sqrt(d_best);
00969 
00970     return (Point) p_best;
00971   }
00972 }
00973 
00974 //-----------------------------------------------------------------------------
00975 
00976 
00977 template <class PointT>
00978 template <class MeshT, class SpatialSearchT>
00979 void
00980 PolyLineT<PointT>::
00981 resample_on_mesh_edges( MeshT& _mesh, SpatialSearchT * _ssearch)
00982 {
00983   // init new empty polyline
00984   PolyLineT<PointT> new_pl = *this;
00985 
00986   // vectors for new segment data
00987   std::vector<Point> new_points;
00988   std::vector<typename MeshT::EdgeHandle> new_ehandles;
00989 
00990   // current segment data
00991   Point p_start, p_end;
00992   typename MeshT::FaceHandle fh_start, fh_end;
00993 
00994   // init first endpoint
00995   p_end = find_nearest_point( _mesh, point(0), fh_end, _ssearch);
00996 
00997   // add start point
00998   new_pl.resize(1);
00999   new_pl.copy_vertex_complete(*this, 0, 0);
01000   new_pl.point(0) = p_end;
01001   // update properties
01002   if( new_pl.vertex_fhandles_available())
01003     new_pl.vertex_fhandle(0) = fh_end.idx();
01004   if( new_pl.vertex_ehandles_available())
01005     new_pl.vertex_ehandle(0) = -1;
01006 
01007   MeshEdgeSamplerT<MeshT, Point> mesampler( _mesh );
01008 
01009   for(unsigned int i=1; i<n_vertices(); ++i)
01010   {
01011     // first segment point is last one from previous step!
01012     p_start  = p_end;
01013     fh_start = fh_end;
01014     // get next segment point
01015     p_end   = find_nearest_point( _mesh, point(i), fh_end  , _ssearch);
01016 
01017     // get points for first segment
01018     mesampler.edge_points_in_segment( p_start,
01019                                       p_end,
01020                                       fh_start,
01021                                       fh_end,
01022                                       new_points,
01023                                       new_ehandles );
01024 
01025 //     // get points for first segment
01026 //     edge_points_in_segment( _mesh,
01027 //                          p_start,
01028 //                          p_end,
01029 //                          fh_start,
01030 //                          fh_end,
01031 //                          new_points,
01032 //                          new_ehandles );
01033 
01034     // add new edge points
01035     for( unsigned int j=0; j< new_points.size(); ++j)
01036     {
01037       new_pl.add_point( new_points[j]);
01038       // update properties
01039       if( new_pl.vertex_ehandles_available())
01040         new_pl.vertex_ehandle( new_pl.n_vertices()-1) = new_ehandles[j].idx();
01041       if( new_pl.vertex_fhandles_available())
01042         new_pl.vertex_fhandle( new_pl.n_vertices()-1) = -1;
01043     }
01044 
01045     // add new intermediate point
01046     new_pl.resize( new_pl.n_vertices() + 1);
01047     new_pl.copy_vertex_complete(*this, i, new_pl.n_vertices()-1);
01048     new_pl.point(new_pl.n_vertices()-1) = p_end;
01049     // update properties
01050     if( new_pl.vertex_fhandles_available())
01051       new_pl.vertex_fhandle( new_pl.n_vertices()-1) = fh_end.idx();
01052     if( new_pl.vertex_ehandles_available())
01053       new_pl.vertex_ehandle( new_pl.n_vertices()-1) = -1;
01054   }
01055 
01056   // add points in last segment
01057   if(is_closed())
01058   {
01059     // first segment point is last one from previous step!
01060     p_start  = p_end;
01061     fh_start = fh_end;
01062     // get next segment point
01063     p_end   = find_nearest_point( _mesh, point(0), fh_end  , _ssearch);
01064 
01065     // get points for first segment
01066     mesampler.edge_points_in_segment( p_start,
01067                                       p_end,
01068                                       fh_start,
01069                                       fh_end,
01070                                       new_points,
01071                                       new_ehandles );
01072 
01073 //     // get points for first segment
01074 //     edge_points_in_segment( _mesh,
01075 //                          p_start,
01076 //                          p_end,
01077 //                          fh_start,
01078 //                          fh_end,
01079 //                          new_points,
01080 //                          new_ehandles );
01081 
01082     // add new edge points
01083     for( unsigned int j=0; j< new_points.size(); ++j)
01084     {
01085       new_pl.add_point( new_points[j]);
01086       // update properties
01087       if( new_pl.vertex_ehandles_available())
01088         new_pl.vertex_ehandle( new_pl.n_vertices()-1) = new_ehandles[j].idx();
01089       if( new_pl.vertex_fhandles_available())
01090         new_pl.vertex_fhandle( new_pl.n_vertices()-1) = -1;
01091     }
01092   }
01093 
01094   // overwrite polyline with result
01095   *this = new_pl;
01096 }
01097 
01098 
01099 //-----------------------------------------------------------------------------
01100 
01101 #ifdef USE_PHYSIM
01102 
01103 template <class PointT>
01104 template <class MeshT, class SpatialSearchT>
01105 void
01106 PolyLineT<PointT>::
01107 integrate_into_mesh( MeshT& _mesh, SpatialSearchT * _ssearch)
01108 {
01109   if( is_closed() && points_.size() < 2)
01110   {
01111     std::cerr << "Warning: closed polyline with only one vertex!!!\n";
01112     return;
01113   }
01114 
01115   // resample on mesh edges
01116   resample_on_mesh_edges( _mesh, _ssearch);
01117 
01118   //ToDo: Cleanup
01119 
01120   if( !vertex_ehandles_available() ||
01121       !vertex_fhandles_available()    )
01122   {
01123     std::cerr << "ERROR: PolyLine::integrate_into_mesh needs ehandles and fhandles!!!\n";
01124     return;
01125   }
01126 
01127   //Add points, if polyline starts or ends near boundary
01128   add_boundary_points(_mesh);
01129 
01130   // build constrained delaunay problems
01131   typedef std::pair<int,int>                                     FSegment;
01132   typedef std::pair< std::vector< FSegment >, std::vector<int> > FData;
01133   typedef std::map< int, FData >                                 FSPMap;
01134   // for each face we need a list of segments(=constraints) and
01135   // a list of interior vertices
01136   FSPMap face_map;
01137 
01138   typedef std::vector<int>       EData;
01139   typedef std::map< int, EData > EVMap;
01140   // for each edge we need a list of vertices lying on this edge
01141   // this data has to be sorted !!!
01142   EVMap edge_map;
01143 
01144   // add vertices to mesh
01145   std::vector<int> plvhs;
01146   int last_eidx = -1;
01147   int last_fidx = -1;
01148   int last_vidx = -1;
01149   int boundary_closed = is_closed();
01150 
01151   for(unsigned int i=0; i<points_.size()+boundary_closed; ++i)
01152   {
01153     int vidx = 0;
01154     int eidx = vertex_ehandle(i%points_.size());
01155     int fidx = vertex_fhandle(i%points_.size());
01156 
01157     // not last segment?
01158     if( i < points_.size())
01159     {
01160       plvhs.push_back( _mesh.add_vertex( (typename MeshT::Point) points_[i]).idx());
01161 
01162       vidx = plvhs.back();
01163 
01164       // error checking
01165       if( eidx != -1 && fidx != -1)
01166         std::cerr << "ERROR: eidx and fidx are valid simultaneously, this shouldn't happen!!!!\n";
01167 
01168       // add edge vertex reference
01169       if( eidx != -1)
01170         edge_map[eidx].push_back(vidx);
01171       
01172       // add inner face vertex reference
01173       if( fidx != -1)
01174         face_map[fidx].second.push_back( vidx );
01175     }
01176     else vidx = plvhs[0]; // take first vertex
01177 
01178     // add segments as delaunay constraints
01179     if( i>0 )
01180     {
01181       // inner vertex case
01182       if( ( fidx != -1 && last_eidx != -1) ||
01183           ( eidx != -1 && last_fidx != -1) ||
01184           ( fidx != -1 && last_fidx != -1 && fidx == last_fidx) )
01185       {
01186         int valid_fidx = std::max(fidx, last_fidx);
01187 
01188         face_map[valid_fidx].first.push_back( FSegment(vidx, last_vidx) );
01189       }
01190       else
01191         if( eidx != -1 && last_eidx != -1)
01192         {
01193           typename MeshT::EdgeHandle eh      = _mesh.edge_handle(      eidx );
01194           typename MeshT::HalfedgeHandle heh0= _mesh.halfedge_handle( eh, 0);
01195           typename MeshT::HalfedgeHandle heh1= _mesh.halfedge_handle( eh, 1);
01196 
01197           typename MeshT::FaceHandle fh0, fh1;
01198           // edge might be at boundary !
01199           if( !_mesh.is_boundary( heh0)) fh0 = _mesh.face_handle(heh0);
01200           else                           fh0 = _mesh.face_handle(heh1);
01201           if( !_mesh.is_boundary( heh1)) fh1 = _mesh.face_handle(heh1);
01202           else                           fh1 = _mesh.face_handle(heh0);
01203 
01204           std::pair<int,int> fhs( fh0.idx(), fh1.idx());
01205 
01206           typename MeshT::EdgeHandle     last_eh  = _mesh.edge_handle( last_eidx );
01207           typename MeshT::HalfedgeHandle last_heh0= _mesh.halfedge_handle( last_eh, 0);
01208           typename MeshT::HalfedgeHandle last_heh1= _mesh.halfedge_handle( last_eh, 1);
01209 
01210           typename MeshT::FaceHandle last_fh0, last_fh1;
01211           // edge might be at boundary !
01212           if( !_mesh.is_boundary( last_heh0)) last_fh0 = _mesh.face_handle(last_heh0);
01213           else                                last_fh0 = _mesh.face_handle(last_heh1);
01214           if( !_mesh.is_boundary( last_heh1)) last_fh1 = _mesh.face_handle(last_heh1);
01215           else                                last_fh1 = _mesh.face_handle(last_heh0);
01216 
01217           std::pair<int,int> last_fhs( last_fh0.idx(), last_fh1.idx());
01218 
01219           int common_fh = -1;
01220 
01221           if( fhs.first == last_fhs.first ||
01222               fhs.first == last_fhs.second   )
01223             common_fh = fhs.first;
01224           else
01225             if( fhs.second == last_fhs.first ||
01226                 fhs.second == last_fhs.second   )
01227               common_fh = fhs.second;
01228             else
01229             {
01230               std::cerr << "ERROR: Polyline::integrate_into_mesh no common facehandle!!!\n";
01231             }
01232 
01233           face_map[common_fh].first.push_back( FSegment(vidx, last_vidx));
01234         }
01235         else
01236         {
01237           std::cerr << "ERROR: unhandled segment case!!!\n";
01238           std::cerr << "vidx: " << vidx << " / last " << last_vidx << std::endl;
01239           std::cerr << "fidx: " << fidx << " / last " << last_fidx << std::endl;
01240           std::cerr << "eidx: " << eidx << " / last " << last_eidx << std::endl;
01241 
01242         }
01243     }
01244 
01245     // store data for next segment
01246     last_eidx = eidx;
01247     last_fidx = fidx;
01248     last_vidx = vidx;
01249   }
01250 
01251   // sort edge vertices for halfedge_handle0
01252   EVMap::iterator ev_it  = edge_map.begin();
01253   for(; ev_it != edge_map.end(); ++ev_it)
01254   {
01255     typename MeshT::EdgeHandle eh = _mesh.edge_handle( ev_it->first );
01256     typename MeshT::Point      p0 = _mesh.point( _mesh.to_vertex_handle( _mesh.halfedge_handle(eh,0)));
01257     typename MeshT::Point      p1 = _mesh.point( _mesh.to_vertex_handle( _mesh.halfedge_handle(eh,1)));
01258 
01259     std::sort( ev_it->second.begin(), ev_it->second.end(), Ecmp<MeshT>(_mesh, p0-p1 ));
01260   }
01261   
01262   // setup edge constraints for faces
01263   FSPMap::iterator fsp_it  = face_map.begin();
01264   for(; fsp_it != face_map.end(); ++fsp_it)
01265   {
01266     typename MeshT::FaceHandle fh = _mesh.face_handle( fsp_it->first );
01267     typename MeshT::FHIter  fh_it = _mesh.fh_iter(fh);
01268     for(; fh_it; ++fh_it)
01269     {
01270       // get endpoints
01271       typename MeshT::VertexHandle vh_start = _mesh.from_vertex_handle(fh_it.handle());
01272       typename MeshT::VertexHandle vh_end   = _mesh.to_vertex_handle  (fh_it.handle());
01273 
01274       typename MeshT::EdgeHandle eh = _mesh.edge_handle( fh_it.handle());
01275 
01276       // add start vertex to face
01277       fsp_it->second.second.push_back( vh_start.idx() );
01278 
01279       // correct ordering? (for first halfedge)
01280       std::vector<int> edge_ordered ( edge_map[ eh.idx()]);
01281       if( fh_it.handle() != _mesh.halfedge_handle(eh, 0) )
01282         std::reverse(edge_ordered.begin(), edge_ordered.end());
01283       
01284       int prev_idx = vh_start.idx();
01285 
01286       std::vector<int>::iterator ev_it  = edge_ordered.begin();
01287       std::vector<int>::iterator ev_end = edge_ordered.end();
01288 
01289       for(; ev_it != ev_end; ++ev_it)
01290       {
01291         // add segment
01292         fsp_it->second.first.push_back( FSegment(prev_idx, *ev_it) );
01293 
01294         // add edge vertex to face
01295         fsp_it->second.second.push_back( *ev_it );
01296 
01297         prev_idx = *ev_it;
01298       }
01299       // add last segment
01300       fsp_it->second.first.push_back( FSegment(prev_idx, vh_end.idx()) );
01301     }
01302   }
01303 
01304   // update edge map for triangle consistency check
01305   ev_it  = edge_map.begin();
01306   for(; ev_it != edge_map.end(); ++ev_it)
01307   {
01308     typename MeshT::EdgeHandle     eh   = _mesh.edge_handle( ev_it->first );
01309     typename MeshT::HalfedgeHandle heh0 = _mesh.halfedge_handle( eh, 0 );
01310     typename MeshT::HalfedgeHandle heh1 = _mesh.halfedge_handle( eh, 1 );
01311 
01312     edge_map[eh.idx()].push_back( _mesh.to_vertex_handle(heh0).idx());
01313     edge_map[eh.idx()].push_back( _mesh.to_vertex_handle(heh1).idx());
01314   }
01315 
01316 
01317   // remove faces, solve cdelaunay, and insert new faces
01318   ACG::ConstrainedDelaunayT<double> cdelaunay;
01319   std::vector<int>                  orig_idx;
01320   std::map<int,int>                 new_idx;
01321   fsp_it  = face_map.begin();
01322   for(; fsp_it != face_map.end(); ++fsp_it)
01323   {
01324     typename MeshT::FaceHandle fh = _mesh.face_handle( fsp_it->first );
01325     int fidx = fh.idx();
01326 
01327     // get edge handles for later consistency check
01328     std::vector<int> ehs;
01329     typename MeshT::FEIter fe_it = _mesh.fe_iter( fh );
01330     for(; fe_it; ++fe_it)
01331       ehs.push_back( fe_it.handle().idx());
01332     
01333     // set normal for delaunay problem
01334     cdelaunay.clear();
01335     cdelaunay.set_normal( _mesh.normal(fh) );
01336 
01337     // add vertices of triangle cdelaunay problem
01338     orig_idx.clear();
01339     new_idx.clear();
01340     std::vector<int>::iterator fv_it  = fsp_it->second.second.begin();
01341     std::vector<int>::iterator fv_end = fsp_it->second.second.end();
01342     for(; fv_it != fv_end; ++fv_it)
01343     {
01344       new_idx[*fv_it] = orig_idx.size();
01345       orig_idx.push_back( *fv_it );
01346       bool valid = cdelaunay.add_point((ACG::ConstrainedDelaunayT<double>::Vec3r) _mesh.point(_mesh.vertex_handle(*fv_it)));
01347 
01348       if( !valid )
01349       {
01350         std::cerr << "ERROR: CGAL could not add point, aborting polyline integration...\n";
01351         // remove valence 0 vertices
01352         typename MeshT::VertexIter v_it  = _mesh.vertices_begin();
01353         for(; v_it != _mesh.vertices_end(); ++v_it)
01354         {
01355           if( !_mesh.valence(v_it.handle()))
01356             _mesh.delete_vertex(v_it.handle());
01357         }
01358         _mesh.garbage_collection();
01359         _mesh.update_normals();
01360 
01361         return;
01362       }
01363     }
01364 
01365     // add constraints
01366     std::vector<FSegment>::iterator fc_it  = fsp_it->second.first.begin();
01367     std::vector<FSegment>::iterator fc_end = fsp_it->second.first.end();
01368     for(; fc_it != fc_end; ++fc_it)
01369     {
01370       cdelaunay.add_constraint( new_idx[fc_it->first], new_idx[fc_it->second] );
01371     }
01372 
01373     // get new triangles and add them to _mesh
01374     std::vector< std::vector< int> > tri_list;
01375     cdelaunay.get_triangles( tri_list);
01376 
01377     // delete old face
01378     _mesh.delete_face(fh, false);
01379 
01380     //    if( fsp_it == face_map.begin())
01381     for(unsigned int i=0; i<tri_list.size(); ++i)
01382     {
01383       std::vector<typename MeshT::VertexHandle > tvhs;
01384       for(unsigned int j=0; j<tri_list[i].size(); ++j)
01385         tvhs.push_back( _mesh.vertex_handle( orig_idx[tri_list[i][j]]) );
01386 
01387       // check if face has is valid = not all vertices on the same input triangle edge
01388       bool face_valid = true;
01389       for(unsigned int j=0; j<ehs.size(); ++j)
01390       {
01391         if( tvhs.size() == 3)
01392         {
01393           // ede_map iterators
01394           std::vector<int>::iterator em_begin = edge_map[ehs[j]].begin();
01395           std::vector<int>::iterator em_end   = edge_map[ehs[j]].end();
01396 
01397           // all three vertices on same edge?
01398           if( std::find( em_begin, em_end, tvhs[0].idx()) != em_end &&
01399               std::find( em_begin, em_end, tvhs[1].idx()) != em_end &&
01400               std::find( em_begin, em_end, tvhs[2].idx()) != em_end   )
01401           {
01402             face_valid = false;
01403           }
01404         }
01405         else std::cerr << "ERROR: integrate polyline found triangle which has not 3 vertices...\n";
01406       }
01407 
01408 
01409       if( face_valid)
01410         _mesh.add_face( tvhs );
01411 
01412     }
01413   }
01414 
01415   //select polyline edges
01416   for(unsigned int i=1; i<points_.size()+boundary_closed; ++i)
01417   {
01418     // get vertex handles of segment
01419     typename MeshT::VertexHandle vh0 = _mesh.vertex_handle( plvhs[i-1] );
01420     typename MeshT::VertexHandle vh1 = _mesh.vertex_handle( plvhs[i%points_.size()] );
01421 
01422     // find connecting edge
01423     bool found_edge = false;
01424     typename MeshT::VOHIter voh_it = _mesh.voh_iter(vh0);
01425     for(; voh_it; ++voh_it)
01426       if( _mesh.to_vertex_handle(voh_it.handle()) == vh1)
01427       {
01428         _mesh.status( _mesh.edge_handle( voh_it.handle())).set_selected(true);
01429         found_edge = true;
01430       }
01431 
01432     if( !found_edge )
01433       std::cerr << "Warning: could not find polyline edge: " 
01434                 << i-1 << " to " << i%points_.size() 
01435                 << std::endl;
01436   }
01437 
01438   // clean up mesh
01439   _mesh.garbage_collection();
01440   _mesh.update_normals();
01441 }
01442 
01443 #endif
01444 
01445 //-----------------------------------------------------------------------------
01446 
01447 
01448 template <class PointT>
01449 template <class MeshT>
01450 void
01451 PolyLineT<PointT>::
01452 add_boundary_points(MeshT& _mesh)
01453 {
01454   // face handles should be available
01455   if( ! vertex_fhandles_available() ) return;
01456 
01457   // polyline should have at least one point
01458   if( points_.empty()) return;
01459 
01460   if( !is_closed() )
01461   {
01462     // check first vertex
01463     int fidx = vertex_fhandle(0);
01464     if( fidx != -1)
01465     {
01466       typename MeshT::Point p = (typename MeshT::Point) (points_[0]);
01467       
01468       double                closest_dist = FLT_MAX;
01469       typename MeshT::Point closest_boundary(0,0,0), pb(0,0,0);
01470       int                   closest_eidx = -1;
01471       typename MeshT::FHIter fh_it = _mesh.fh_iter( _mesh.face_handle(fidx));
01472 
01473       for(; fh_it; ++fh_it)
01474       {
01475         if( _mesh.is_boundary( _mesh.opposite_halfedge_handle(fh_it.handle())))
01476         {
01477           typename MeshT::Point v0 = _mesh.point(_mesh.to_vertex_handle  (fh_it.handle()));
01478           typename MeshT::Point v1 = _mesh.point(_mesh.from_vertex_handle(fh_it.handle()));
01479 
01480           double d = ACG::Geometry::distPointLineSquared(p, v0, v1, &pb);
01481 
01482           if( d < closest_dist)
01483           {
01484             closest_dist     = d;
01485             closest_boundary = pb;
01486             closest_eidx     = _mesh.edge_handle( fh_it.handle()).idx();
01487           }
01488         }
01489       }
01490       
01491       // if boundary point found, add it
01492       if( closest_eidx != -1 )
01493       {
01494         insert_point( 0, closest_boundary);
01495         vertex_ehandle(0) = closest_eidx;
01496       }
01497       
01498     }
01499 
01500     // check last vertex
01501     int pvidx = points_.size()-1;
01502     fidx  = vertex_fhandle(pvidx);
01503     if( fidx != -1)
01504     {
01505       typename MeshT::Point p = (typename MeshT::Point) (points_[pvidx]);
01506       
01507       double                closest_dist = FLT_MAX;
01508       typename MeshT::Point closest_boundary(0,0,0), pb(0,0,0);
01509       int                   closest_eidx = -1;
01510       typename MeshT::FHIter fh_it = _mesh.fh_iter( _mesh.face_handle(fidx));
01511 
01512       for(; fh_it; ++fh_it)
01513       {
01514         if( _mesh.is_boundary( _mesh.opposite_halfedge_handle(fh_it.handle())))
01515         {
01516           typename MeshT::Point v0 = _mesh.point(_mesh.to_vertex_handle  (fh_it.handle()));
01517           typename MeshT::Point v1 = _mesh.point(_mesh.from_vertex_handle(fh_it.handle()));
01518 
01519           double d = ACG::Geometry::distPointLineSquared(p, v0, v1, &pb);
01520 
01521           if( d < closest_dist)
01522           {
01523             closest_dist     = d;
01524             closest_boundary = pb;
01525             closest_eidx     = _mesh.edge_handle( fh_it.handle()).idx();
01526           }
01527         }
01528       }
01529       
01530       // if boundary point found, add it
01531       if( closest_eidx != -1 )
01532       {
01533         add_point( closest_boundary);
01534         vertex_ehandle( points_.size()-1 ) = closest_eidx;
01535       }
01536     }
01537   }
01538 }
01539 
01540 
01541 //-----------------------------------------------------------------------------
01542 
01543 
01544 template <class PointT>
01545 template <class LineNodeT>
01546 LineNodeT*
01547 PolyLineT<PointT>::
01548 get_line_node(LineNodeT*& _line_node, int _mode)
01549 {
01550   typedef typename LineNodeT::value_type Vec3fL;
01551 
01552   if( _mode == 0)
01553   {
01554     // LineSegmentsMode
01555 
01556     // create LineNode
01557     _line_node = new LineNodeT(LineNodeT::LineSegmentsMode, 0, "PolyLine");
01558     _line_node->set_line_width(5.0);
01559     //   _line_node->set_base_color(Vec4f(0,1,0,0));
01560     _line_node->set_base_color(OpenMesh::Vec4f(0.2 + double(rand())/double(RAND_MAX)*0.8,
01561                                                0.2 + double(rand())/double(RAND_MAX)*0.8,
01562                                                0.2 + double(rand())/double(RAND_MAX)*0.8,
01563                                                1.0));
01564 
01565     _line_node->show();
01566 
01567     // add line node
01568     for( unsigned int i=0; i<this->points().size()-1; ++i)
01569     {
01570       _line_node->add_line( (Vec3fL) this->points()[i  ],
01571                             (Vec3fL) this->points()[i+1] );
01572     }
01573 
01574     // close loop
01575     if(closed_)
01576       if( !this->points().empty() )
01577       {
01578         _line_node->add_point( (Vec3fL) this->points()[0]);
01579       }
01580 
01581     return _line_node;
01582   }
01583   else
01584   {
01585     // create LineNode
01586     _line_node = new LineNodeT(LineNodeT::PolygonMode, 0, "PolyLine");
01587     _line_node->set_line_width(5.0);
01588     //   _line_node->set_base_color(Vec4f(0,1,0,0));
01589     _line_node->set_base_color(OpenMesh::Vec4f(0.2 + double(rand())/double(RAND_MAX)*0.8,
01590                                                0.2 + double(rand())/double(RAND_MAX)*0.8,
01591                                                0.2 + double(rand())/double(RAND_MAX)*0.8,
01592                                                1.0));
01593 
01594     _line_node->show();
01595 
01596     // add line node
01597     for( unsigned int i=0; i<this->points().size(); ++i)
01598     {
01599       _line_node->add_point( (Vec3fL) this->points()[i]);
01600     }
01601 
01602     // close loop
01603     if(closed_)
01604       if( !this->points().empty() )
01605       {
01606         _line_node->add_point( (Vec3fL) this->points()[0]);
01607       }
01608 
01609     return _line_node;
01610   }
01611 }
01612 
01613 
01614 //-----------------------------------------------------------------------------
01615 
01616 
01617 template <class PointT>
01618 template <class LineNodeT>
01619 void
01620 PolyLineT<PointT>::
01621 set_line_node(LineNodeT*& _line_node, int _mode)
01622 {
01623   //  typedef typename LineNodeT::value_type Vec3fL;
01624 
01625   // clear old values
01626   clear();
01627 
01628   if( _mode == 0)
01629   {
01630     // assume LineSegmentsMode
01631 
01632     const typename LineNodeT::PointVector& ln_points = _line_node->points();
01633 
01634     for(unsigned int i=0; i<ln_points.size();)
01635     {
01636       if( i != ln_points.size()-1)
01637         add_point( (Point) ln_points[i] );
01638       else
01639       {
01640         // last point
01641         if( (ln_points[ln_points.size()-1]-ln_points[0]).sqrnorm() == 0)
01642         {
01643           closed_ = true;
01644         }
01645         else
01646         {
01647           closed_ = false;
01648           add_point( (Point) ln_points[i] );
01649         }
01650       }
01651 
01652 
01653       // increase counter
01654       if( i == 0) i+=1;
01655       else        i+=2;
01656     }
01657   }
01658   else
01659   {
01660     // assume PolygonMode
01661     closed_ = true;
01662 
01663     const typename LineNodeT::PointVector& ln_points( _line_node->points());
01664 
01665     for(unsigned int i=0; i<ln_points.size(); ++i)
01666     {
01667       add_point( (Point) ln_points[i] );
01668     }
01669   }
01670 }
01671 
01672 
01673 //-----------------------------------------------------------------------------
01674 
01675 
01676 template <class PointT>
01677 void
01678 PolyLineT<PointT>::
01679 print() const
01680 {
01681   std::cerr << "****** PolyInfo ******\n";
01682   std::cerr << "closed : " << closed_ << std::endl;
01683   std::cerr << "#points: " << points_.size() << std::endl;
01684   for(unsigned int i=0; i<points_.size(); ++i)
01685     std::cerr << points_[i] << std::endl;
01686 }
01687 
01688 
01689 //-----------------------------------------------------------------------------
01690 
01691 
01692 template <class PointT>
01693 void
01694 PolyLineT<PointT>::
01695 load(const char* _filename)
01696 {
01697   // clear old polyline
01698   clear();
01699 
01700   std::ifstream fin(_filename, std::ios::in);
01701 
01702   // closed ?
01703   fin >> closed_;
01704 
01705   // number of points
01706   int num_points;
01707   fin >> num_points;
01708 
01709 //   std::cerr << "read " << _filename << std::endl;
01710 //   std::cerr << "#points: " << num_points << std::endl;
01711 
01712   // read points
01713   for(int i=0; i<num_points; ++i)
01714   {
01715     Scalar x,y,z;
01716     fin >> x;
01717     fin >> y;
01718     fin >> z;
01719     Point p(x,y,z);
01720     add_point(p);
01721   }
01722 
01723   // ###########################
01724   // READ properties
01725 
01726   std::string token;
01727 
01728   fin >> token;
01729 
01730   if(vertex_vhandles_available())
01731   {
01732     if( token == "VVHANDLES")
01733     {
01734 //       std::cerr << "read VVHANDLES...\n";
01735       for( unsigned int i=0; i<n_vertices(); ++i)
01736         fin >> vertex_vhandle(i);
01737 
01738       fin >> token;
01739     }
01740   }
01741 
01742   if(vertex_ehandles_available())
01743   {
01744     if( token == "VEHANDLES")
01745     {
01746 //       std::cerr << "read VEHANDLES...\n";
01747       for( unsigned int i=0; i<n_vertices(); ++i)
01748       {
01749         fin >> vertex_ehandle(i);
01750       }
01751 
01752       fin >> token;
01753     }
01754   }
01755 
01756   if(vertex_fhandles_available())
01757   {
01758     if( token == "VFHANDLES")
01759     {
01760 //       std::cerr << "read VFHANDLES...\n";
01761 
01762       for( unsigned int i=0; i<n_vertices(); ++i)
01763         fin >> vertex_fhandle(i);
01764 
01765       fin >> token;
01766     }
01767   }
01768 
01769   fin.close();
01770 }
01771 
01772 
01773 //-----------------------------------------------------------------------------
01774 
01775 
01776 template <class PointT>
01777 void
01778 PolyLineT<PointT>::
01779 save(const char* _filename) const
01780 {
01781   std::ofstream fout(_filename, std::ios::out);
01782 
01783   //  is polyline closed?
01784   fout << closed_ << std::endl;
01785 
01786   // number of points
01787   fout << points_.size() << std::endl;
01788 
01789   std::cerr << "write " << _filename << std::endl;
01790   std::cerr << "#points: " << points_.size() << std::endl;
01791 
01792 
01793   // write each point
01794   for(unsigned int i=0; i<points_.size(); ++i)
01795   {
01796 
01797     fout << points_[i][0] << " ";
01798     fout << points_[i][1] << " ";
01799     fout << points_[i][2] << std::endl;
01800   }
01801 
01802   // ###########################
01803   // Write properties
01804 
01805   if(vertex_vhandles_available())
01806   {
01807     fout << "VVHANDLES" << std::endl;
01808     for( unsigned int i=0; i<n_vertices(); ++i)
01809       fout << vertex_vhandle(i) << std::endl;
01810   }
01811 
01812   if(vertex_ehandles_available())
01813   {
01814     fout << "VEHANDLES" << std::endl;
01815     for( unsigned int i=0; i<n_vertices(); ++i)
01816     {
01817       fout << vertex_ehandle(i) << std::endl;
01818     }
01819   }
01820 
01821   if(vertex_fhandles_available())
01822   {
01823     fout << "VFHANDLES" << std::endl;
01824     for( unsigned int i=0; i<n_vertices(); ++i)
01825       fout << vertex_fhandle(i) << std::endl;
01826   }
01827 
01828   fout.close();
01829 }
01830 
01831 
01832 //-----------------------------------------------------------------------------
01833 
01834 
01835 template <class PointT>
01836 template <class PropT>
01837 void
01838 PolyLineT<PointT>::
01839 request_prop( unsigned int& _ref_count, PropT& _prop)
01840 {
01841   if(_ref_count == 0)
01842   {
01843     _ref_count = 1;
01844     // always use vertex size!!!
01845     _prop.resize(n_vertices());
01846   }
01847   else ++_ref_count;
01848 }
01849 
01850 
01851 //-----------------------------------------------------------------------------
01852 
01853 
01854 template <class PointT>
01855 template <class PropT>
01856 void
01857 PolyLineT<PointT>::
01858 release_prop( unsigned int& _ref_count, PropT& _prop)
01859 {
01860   if( _ref_count <= 1)
01861   {
01862     _ref_count = 0;
01863     _prop.clear();
01864   }
01865   else --_ref_count;
01866 }
01867 
01868 
01869 //-----------------------------------------------------------------------------
01870 
01871 
01872 template <class PointT>
01873 void
01874 PolyLineT<PointT>::
01875 copy_vertex_complete(const PolyLineT<PointT>& _pl, unsigned int _i, unsigned int _j)
01876 {
01877   // check range
01878   if( n_vertices() <= _j || _pl.n_vertices() <= _i)
01879   {
01880     std::cerr << "Warning: invalid range in PolyLine::copy_vertex_complete ( "
01881               << _i << " " << _j << " ) " << std::endl;
01882     return;
01883   }
01884 
01885   // copy point position
01886   point(_j) = _pl.point(_i);
01887 
01888   // copy properties if available
01889 
01890   // vertex normal
01891   if( _pl.vertex_normals_available())
01892     if(   vertex_normals_available())
01893       vertex_normal(_j) = _pl.vertex_normal(_i);
01894 
01895   // vertex colors
01896   if( _pl.vertex_colors_available())
01897     if(   vertex_colors_available())
01898       vertex_color(_j) = _pl.vertex_color(_i);
01899 
01900   // vertex scalar
01901   if( _pl.vertex_scalars_available())
01902     if(   vertex_scalars_available())
01903       vertex_scalar(_j) = _pl.vertex_scalar(_i);
01904 
01905   // vertex selection
01906   if( _pl.vertex_selections_available())
01907     if(   vertex_selections_available())
01908       vertex_selection(_j) = _pl.vertex_selection(_i);
01909 
01910   // vertex vhandle
01911   if( _pl.vertex_vhandles_available())
01912     if(   vertex_vhandles_available())
01913       vertex_vhandle(_j) = _pl.vertex_vhandle(_i);
01914 
01915   // vertex ehandle
01916   if( _pl.vertex_ehandles_available())
01917     if(   vertex_ehandles_available())
01918       vertex_ehandle(_j) = _pl.vertex_ehandle(_i);
01919 
01920   // vertex vhandle
01921   if( _pl.vertex_ehandles_available())
01922     if(   vertex_ehandles_available())
01923       vertex_ehandle(_j) = _pl.vertex_ehandle(_i);
01924 }
01925 
01926 
01927 //-----------------------------------------------------------------------------
01928 
01929 
01930 template <class PointT>
01931 void
01932 PolyLineT<PointT>::
01933 copy_edge_complete(const PolyLineT<PointT>& _pl, unsigned int _i, unsigned int _j)
01934 {
01935   // check range
01936   if( n_edges() <= _j || _pl.n_edges() <= _i)
01937   {
01938     std::cerr << "Warning: invalid range in PolyLine::copy_edge_complete ( "
01939               << _i << " " << _j << " ) " << std::endl;
01940     return;
01941   }
01942 
01943   // edge normal
01944   if( _pl.edge_selections_available())
01945     if(   edge_selections_available())
01946       edge_selection(_j) = _pl.edge_selection(_i);
01947 
01948 
01949   // edge normal
01950   if( _pl.edge_normals_available())
01951     if(   edge_normals_available())
01952       edge_normal(_j) = _pl.edge_normal(_i);
01953 
01954   // edge color
01955   if( _pl.edge_colors_available())
01956     if(   edge_colors_available())
01957       edge_color(_j) = _pl.edge_color(_i);
01958 
01959   // edge scalar
01960   if( _pl.edge_scalars_available())
01961     if(   edge_scalars_available())
01962       edge_scalar(_j) = _pl.edge_scalar(_i);
01963 
01964   // edge normal
01965   if( _pl.edge_selections_available())
01966     if(   edge_selections_available())
01967       edge_selection(_j) = _pl.edge_selection(_i);
01968 
01969   // edge selection
01970   if( _pl.edge_selections_available())
01971     if(   edge_selections_available())
01972       edge_selection(_j) = _pl.edge_selection(_i);
01973 }
01974 
01975 
01976 //-----------------------------------------------------------------------------
01977 
01978 
01979 template <class PointT>
01980 void
01981 PolyLineT<PointT>::
01982 invert()
01983 {
01984   // inversion is only supported for open polylines
01985   if(is_closed())
01986   {
01987     std::cerr << "Warning: inversion for closed polylines is not supported!!!\n";
01988     return;
01989   }
01990 
01991   PolyLineT<PointT> pl_temp = *this;
01992 
01993   // copy vertices in reverse order
01994   for(unsigned int i=0; i<n_vertices(); ++i)
01995     pl_temp.copy_vertex_complete( *this, n_vertices()-1-i, i);
01996 
01997   // copy edges in reverse order
01998   for(unsigned int i=0; i<n_edges(); ++i)
01999     pl_temp.copy_edge_complete( *this, n_edges()-1-i, i);
02000 
02001   // save inverted polyline
02002   *this = pl_temp;
02003 }
02004 
02005 
02006 //-----------------------------------------------------------------------------
02007 
02008 
02009 template <class PointT>
02010 void
02011 PolyLineT<PointT>::
02012 append(const PolyLineT<PointT>& _pl)
02013 {
02014   // operation not supported for closed polylines
02015   if( is_closed() || _pl.is_closed())
02016   {
02017     std::cerr << is_closed() << " " << _pl.is_closed() << std::endl;
02018     std::cerr << "Warning: appending not supported for closed polylines!!!\n";
02019     return;
02020   }
02021 
02022   unsigned int old_nv = n_vertices();
02023   unsigned int old_ne = n_edges();
02024 
02025   resize( n_vertices() + _pl.n_vertices());
02026 
02027   for( unsigned int i=0; i<_pl.n_vertices(); ++i)
02028     copy_vertex_complete( _pl, i, i+old_nv);
02029 
02030   for( unsigned int i=0; i<_pl.n_edges(); ++i)
02031     copy_edge_complete( _pl, i, i+old_ne+1);
02032 }
02033 
02034 
02035 //-----------------------------------------------------------------------------
02036 
02037 
02038 template <class PointT>
02039 void
02040 PolyLineT<PointT>::
02041 prepend(const PolyLineT<PointT>& _pl)
02042 {
02043   PolyLineT<PointT> pl_temp = _pl;
02044 
02045   pl_temp.append(*this);
02046   *this = pl_temp;
02047 }
02048 
02049 
02050 //-----------------------------------------------------------------------------
02051 
02052 
02053 template <class PointT>
02054 void
02055 PolyLineT<PointT>::
02056 split_closed( unsigned int _split_idx)
02057 {
02058   if(!is_closed())
02059   {
02060     std::cerr << "Warning: split_closed was called for open polyline!\n";
02061     return;
02062   }
02063 
02064   // prepare new polyline
02065   PolyLineT<PointT> pl_temp = *this;
02066   pl_temp.resize(n_vertices()+1);
02067   pl_temp.set_closed( false);
02068 
02069 
02070   // splitted polyline has n+1 vertices
02071   for(unsigned int i=0; i<n_vertices()+1; ++i)
02072     pl_temp.copy_vertex_complete( *this, (i+_split_idx)%n_vertices(),i);
02073 
02074   for(unsigned int i=0; i<n_edges(); ++i)
02075     pl_temp.copy_edge_complete( *this, (i+_split_idx)%n_edges(),i);
02076 
02077   // copy updated polyline
02078   *this = pl_temp;
02079 }
02080 
02081 
02082 //-----------------------------------------------------------------------------
02083 
02084 
02085 template <class PointT>
02086 void
02087 PolyLineT<PointT>::
02088 split( unsigned int _split_idx, PolyLineT<PointT>& _new_pl)
02089 {
02090   if( is_closed() ) split_closed( _split_idx);
02091   else
02092   {
02093     // copy properties
02094     _new_pl = *this;
02095 
02096     _new_pl.resize( n_vertices() - _split_idx);
02097 
02098     // copy vertex data
02099     for(unsigned int i=_split_idx; i<n_vertices(); ++i)
02100       _new_pl.copy_vertex_complete(*this, i, i-_split_idx);
02101     // copy edge data
02102     for(unsigned int i=_split_idx; i<n_edges(); ++i)
02103       _new_pl.copy_edge_complete(*this, i, i-_split_idx);
02104 
02105     // cut copied part
02106     resize(_split_idx+1);
02107   }
02108 }
02109 
02110 
02111 //-----------------------------------------------------------------------------
02112 
02113 
02114 template <class PointT>
02115 template <class IPoint>
02116 bool
02117 PolyLineT<PointT>::
02118 plane_line_intersection( const IPoint& _p_plane,
02119                          const IPoint& _n_plane,
02120                          const IPoint& _p0,
02121                          const IPoint& _p1,
02122                          IPoint& _p_int)
02123 {
02124   double a = (_n_plane | (_p_plane-_p0));
02125   double b = (_n_plane | (_p1-_p0));
02126 
02127   if( fabs(b) > 1e-9)
02128   {
02129     double s = a/b;
02130 
02131     if( s >= 0.0 && s<= 1.0)
02132     {
02133       _p_int = _p0 + (_p1-_p0)*s;
02134 
02135       // TEST Intersection Point
02136       if( fabs((_n_plane| (_p_int-_p_plane)) ) > 1e-9)
02137         std::cerr << "WARNING: wrong intersection point!!!\n";
02138 
02139       return true;
02140     }
02141     else
02142       return false;
02143   }
02144   else return false;
02145 }
02146 
02147 
02148 //-----------------------------------------------------------------------------
02149 
02150 
02151 template <class PointT>
02152 template<class MeshT>
02153 void
02154 PolyLineT<PointT>::
02155 edge_points_in_segment( const MeshT& _mesh,
02156                         const Point& _p0,
02157                         const Point& _p1,
02158                         const typename MeshT::FaceHandle _fh0,
02159                         const typename MeshT::FaceHandle _fh1,
02160                         std::vector<Point> &                     _points,
02161                         std::vector<typename MeshT::EdgeHandle>& _ehandles )
02162 {
02163   // initialize
02164   _points.clear();
02165   _ehandles.clear();
02166 
02167   Point p_start = _p0;
02168   Point p_end   = _p1;
02169 
02170   typename MeshT::FaceHandle fh_start = _fh0;
02171   typename MeshT::FaceHandle fh_end   = _fh1;
02172 
02173   if( fh_start == fh_end)
02174     return;
02175 
02176   // vectors for new points
02177   std::vector<Point> new_points0, new_points1;
02178 
02179   // vector for new edgehandle
02180   std::vector<typename MeshT::EdgeHandle> new_eh0, new_eh1;
02181 
02182 //   // insert first point
02183 //   new_points0.push_back( p_start);
02184 //   new_points1.push_back( p_start);
02185 
02186   // construct cut plane
02187   // get first normal
02188   typename MeshT::HalfedgeHandle heh = _mesh.halfedge_handle(fh_start);
02189   Point p0      = (Point)_mesh.point(_mesh.to_vertex_handle( heh ));
02190   Point p1      = (Point)_mesh.point(_mesh.to_vertex_handle( heh = _mesh.next_halfedge_handle(heh) ));
02191   Point p2      = (Point)_mesh.point(_mesh.to_vertex_handle( heh = _mesh.next_halfedge_handle(heh) ));
02192   Point n_start = ((p1-p0)%(p2-p0)).normalize();
02193 
02194   // get second normal
02195   heh   = _mesh.halfedge_handle(fh_end);
02196   p0    = _mesh.point(_mesh.to_vertex_handle( heh ));
02197   p1    = _mesh.point(_mesh.to_vertex_handle( heh = _mesh.next_halfedge_handle(heh) ));
02198   p2    = _mesh.point(_mesh.to_vertex_handle( heh = _mesh.next_halfedge_handle(heh) ));
02199   Point n_end = ((p1-p0)%(p2-p0)).normalize();
02200 
02201   // get average normal
02202   Point n_avg = n_start + n_end;
02203   if( n_avg.sqrnorm() < 1e-7) n_avg = n_start - n_end;
02204   n_avg.normalize();
02205 
02206   // get plane data
02207   Point n_plane = n_avg % (p_start-p_end).normalize();
02208   if( n_plane.sqrnorm() > 1e-9) n_plane.normalize();
02209   else std::cerr << "WARNING: Edge Resampling -> not possible to construct stable cut plane!!!\n";
02210   Point p_plane = (p_start + p_end)*0.5;
02211 
02212   // get intersection halfedges of start triangle
02213   std::vector<typename MeshT::HalfedgeHandle > start_hehs;
02214   std::vector<Point>                          start_ps;
02215   heh = _mesh.halfedge_handle(fh_start);
02216   Point p_int;
02217   for(unsigned int i=0; i<3; ++i)
02218   {
02219     // edge endpoints
02220     p0 = (Point) _mesh.point(_mesh.from_vertex_handle(heh));
02221     p1 = (Point) _mesh.point(_mesh.to_vertex_handle  (heh));
02222 
02223     // intersection ?
02224     if( plane_line_intersection( p_plane, n_plane, p0, p1, p_int))
02225     {
02226       start_hehs.push_back( heh );
02227       start_ps.push_back(p_int);
02228     }
02229     // move to next halfedge handle
02230     heh = _mesh.next_halfedge_handle(heh);
02231   }
02232 
02233   // DEBUG
02234   // get intersection halfedges of end triangle
02235   std::vector<typename MeshT::HalfedgeHandle > end_hehs;
02236   std::vector<Point>                          end_ps;
02237   heh = _mesh.halfedge_handle(fh_end);
02238   for(unsigned int i=0; i<3; ++i)
02239   {
02240     // edge endpoints
02241     p0 = (Point) _mesh.point(_mesh.from_vertex_handle(heh));
02242     p1 = (Point) _mesh.point(_mesh.to_vertex_handle  (heh));
02243 
02244     // intersection ?
02245     if( plane_line_intersection( p_plane, n_plane, p0, p1, p_int))
02246     {
02247       end_hehs.push_back( heh );
02248       end_ps.push_back(p_int);
02249     }
02250     // move to next halfedge handle
02251     heh = _mesh.next_halfedge_handle(heh);
02252   }
02253   // END DEBUG
02254 
02255   // hack: debug hints
02256   if( start_hehs.size() != 2 || end_hehs.size() != 2)
02257   {
02258     std::cerr << "PolyLineResampling ERROR: wrong number of intersections... ";
02259     std::cerr << start_hehs.size() << " ";
02260     std::cerr << end_hehs.size()   << std::endl;
02261   }
02262   //  else std::cerr << "SUPI!!!\n";
02263   // end hack
02264 
02265 
02266   if( start_hehs.size() == 2 && end_hehs.size() == 2)
02267   {
02268     // initialize start points
02269     typename MeshT::HalfedgeHandle cur_heh0 = start_hehs[0];
02270     typename MeshT::HalfedgeHandle cur_heh1 = start_hehs[1];
02271 
02272     // store points and edge handles
02273     new_points0.push_back( start_ps[0]);
02274     new_eh0.push_back( _mesh.edge_handle( cur_heh0));
02275 
02276     new_points1.push_back( start_ps[1]);
02277     new_eh1.push_back( _mesh.edge_handle( cur_heh1));
02278 
02279     unsigned int count = 0;
02280 
02281     while( _mesh.face_handle(_mesh.opposite_halfedge_handle(cur_heh0)) != fh_end &&
02282            _mesh.face_handle(_mesh.opposite_halfedge_handle(cur_heh1)) != fh_end &&
02283            count < 1000 )
02284     {
02285       ++count;
02286 
02287       // move into first direction
02288       cur_heh0 = _mesh.opposite_halfedge_handle( cur_heh0);
02289 
02290       // test for boundary
02291       if( _mesh.is_boundary(cur_heh0))
02292       {
02293         std::cerr << "ERROR: found boundary in traversal!!!\n";
02294         cur_heh0 = _mesh.opposite_halfedge_handle( cur_heh0);
02295       } else {
02296 
02297         unsigned int old_size = new_points0.size();
02298 
02299         for(unsigned int i=0; i<2; ++i)
02300         {
02301           // move to next halfedge handle
02302           cur_heh0 = _mesh.next_halfedge_handle(cur_heh0);
02303 
02304           // edge endpoints
02305           p0 = (Point) _mesh.point(_mesh.from_vertex_handle(cur_heh0));
02306           p1 = (Point) _mesh.point(_mesh.to_vertex_handle  (cur_heh0));
02307 
02308           // intersection ?
02309           if( plane_line_intersection( p_plane, n_plane, p0, p1, p_int))
02310           {
02311             new_points0.push_back(p_int);
02312             new_eh0.push_back( _mesh.edge_handle( cur_heh0));
02313             break;
02314           }
02315         }
02316 
02317         // debug helper
02318         if( new_points0.size() != old_size + 1)
02319           std::cerr << "WARNING: could not find new point!!!\n";
02320       }
02321 
02322       // move into second direction
02323       cur_heh1 = _mesh.opposite_halfedge_handle( cur_heh1);
02324 
02325       // test for boundary
02326       if( _mesh.is_boundary(cur_heh1))
02327       {
02328         std::cerr << "ERROR: found boundary in traversal!!!\n";
02329         cur_heh1 = _mesh.opposite_halfedge_handle( cur_heh1);
02330       } else {
02331 
02332         unsigned int old_size = new_points1.size();
02333 
02334         for(unsigned int i=0; i<2; ++i)
02335         {
02336           // move to next halfedge handle
02337           cur_heh1 = _mesh.next_halfedge_handle(cur_heh1);
02338 
02339           // edge endpoints
02340           p0 = (Point) _mesh.point(_mesh.from_vertex_handle(cur_heh1));
02341           p1 = (Point) _mesh.point(_mesh.to_vertex_handle  (cur_heh1));
02342 
02343           // intersection ?
02344           if( plane_line_intersection( p_plane, n_plane, p0, p1, p_int))
02345           {
02346             new_points1.push_back(p_int);
02347             new_eh1.push_back( _mesh.edge_handle( cur_heh1));
02348             break;
02349           }
02350         }
02351 
02352         // debug helper
02353         if( new_points1.size() != old_size + 1)
02354           std::cerr << "WARNING: could not find new point!!!\n";
02355       }
02356 
02357     }
02358 
02359 //     // add end points
02360 //     new_points0.push_back( p_end );
02361 //     new_points1.push_back( p_start );
02362 
02363     // set new points, test which direction converged first
02364     if(_mesh.face_handle(_mesh.opposite_halfedge_handle(cur_heh0)) == fh_end )
02365     {
02366       // return values
02367       _points   = new_points0;
02368       _ehandles = new_eh0;
02369     }
02370     else
02371       if (_mesh.face_handle(_mesh.opposite_halfedge_handle(cur_heh1)) == fh_end)
02372       {
02373         // return values
02374         _points   = new_points1;
02375         _ehandles = new_eh1;
02376       }
02377   }
02378 }
02379 
02380 
02381 //=============================================================================
02382 } // namespace ACG
02383 //=============================================================================

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