// Copyright (c) 2005, 2006 Fernando Luis Cacciola Carballal. All rights reserved. // // This file is part of CGAL (www.cgal.org); you may redistribute it under // the terms of the Q Public License version 1.0. // See the file LICENSE.QPL distributed with CGAL. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // // Author(s) : Fernando Cacciola // #ifndef CGAL_POLYGON_OFFSET_BUILDER_2_C #define CGAL_POLYGON_OFFSET_BUILDER_2_C 1 CGAL_BEGIN_NAMESPACE template Polygon_offset_builder_2::Polygon_offset_builder_2( Sls const& aSls, Traits const& aTraits ) : mTraits(aTraits) { int lMaxID = -1 ; for ( Halfedge_const_handle lHE = aSls.halfedges_begin() ; lHE != aSls.halfedges_end() ; ++ lHE ) { if ( lHE->id() > lMaxID ) lMaxID = lHE->id() ; if ( !lHE->is_bisector() && handle_assigned(lHE->face()) ) { CGAL_POLYOFFSET_SHOW (1, DrawBorder(lHE) ) ; mBorders.push_back(lHE); } } CGAL_POLYOFFSET_TRACE(3, "Border count: " << mBorders.size() ) ; CGAL_POLYOFFSET_TRACE(3, "Highest Bisector ID: " << lMaxID ) ; mVisitedBisectors.resize(lMaxID+1); ResetVisitedBisectorsMap(); } template typename Polygon_offset_builder_2::Halfedge_const_handle Polygon_offset_builder_2::LocateHook( FT aTime, Halfedge_const_handle aBisector ) { CGAL_POLYOFFSET_TRACE(2,"Searching for hook at " << aTime ) ; Halfedge_const_handle rHook ; while ( aBisector->is_bisector() ) { CGAL_POLYOFFSET_TRACE(3,"Testing hook on B" << aBisector->id() ) ; Halfedge_const_handle lPrev = aBisector->prev(); Halfedge_const_handle lNext = aBisector->next(); if ( !IsVisited(aBisector) ) { Comparison_result lCNext = lNext->is_bisector() ? Compare_offset_against_event_time(aTime,aBisector,lNext) : SMALLER ; Comparison_result lCPrev = lPrev->is_bisector() ? Compare_offset_against_event_time(aTime,lPrev,aBisector) : SMALLER ; CGAL_POLYOFFSET_TRACE(3,"CPrev: " << lCPrev << " CNext: " << lCNext ) ; if ( lCNext != lCPrev ) { CGAL_POLYOFFSET_TRACE(2, "Hook found on B" << aBisector->id() ) ; rHook = aBisector ; break ; } } aBisector = lNext ; } return rHook; } template typename Polygon_offset_builder_2::Halfedge_const_handle Polygon_offset_builder_2::LocateSeed( FT aTime ) { Halfedge_const_handle rSeed ; for ( typename Halfedge_vector::const_iterator f = mBorders.begin() ; f != mBorders.end() && !handle_assigned(rSeed) ; ++ f ) { CGAL_POLYOFFSET_TRACE(3,"Locating hook for face E" << (*f)->id() ) ; rSeed = LocateHook(aTime,(*f)->next()); } CGAL_POLYOFFSET_TRACE(3,"Seed found on B" << ( handle_assigned(rSeed) ? rSeed->id() : -1 ) ) ; return rSeed; } template void Polygon_offset_builder_2::AddOffsetVertex( FT aTime, Halfedge_const_handle aHook, ContainerPtr aPoly ) { Visit(aHook); Point_2 lP = Construct_offset_point(aTime,aHook); CGAL_POLYOFFSET_SHOW (1, DrawBisector(aHook) ) ; CGAL_POLYOFFSET_SHOW (1, DrawOffset(aPoly,lP) ) ; CGAL_POLYOFFSET_TRACE(3,"Constructing offset point along B" << aHook->id() ) ; aPoly->push_back(lP); } template template OutputIterator Polygon_offset_builder_2::TraceOffsetPolygon( FT aTime, Halfedge_const_handle aSeed, OutputIterator aOut ) { CGAL_POLYOFFSET_TRACE(1,"Tracing new offset polygon" ) ; ContainerPtr lPoly( new Container() ) ; Halfedge_const_handle lHook = aSeed ; AddOffsetVertex(aTime,lHook,lPoly); while ( true ) { lHook = LocateHook(aTime,lHook->next()) ; if ( handle_assigned(lHook) ) { AddOffsetVertex(aTime,lHook,lPoly); Halfedge_const_handle lNextBisector = lHook->opposite(); if ( lNextBisector != aSeed && !IsVisited(lNextBisector) ) { lHook = lNextBisector; continue; } } break ; } CGAL_POLYOFFSET_SHOW (1, DrawOffset(lPoly,(*lPoly)[0]) ) ; if ( lPoly->size() >= 3 ) { CGAL_POLYOFFSET_TRACE(1,"Offset polygon of " << lPoly->size() << " vertices traced." ) ; *aOut++ = lPoly ; } // ResetVisitedBisectorsMap(); return aOut ; } template void Polygon_offset_builder_2::ResetVisitedBisectorsMap() { std::fill(mVisitedBisectors.begin(),mVisitedBisectors.end(),0); } template template OutputIterator Polygon_offset_builder_2::construct_offset_polygons( FT aTime, OutputIterator aOut ) { CGAL_precondition( aTime > static_cast(0.0) ) ; ResetVisitedBisectorsMap(); CGAL_POLYOFFSET_TRACE(1,"Constructing offset polygons for offset: " << aTime ) ; for ( Halfedge_const_handle lSeed = LocateSeed(aTime); handle_assigned(lSeed); lSeed = LocateSeed(aTime) ) aOut = TraceOffsetPolygon(aTime,lSeed,aOut); return aOut ; } CGAL_END_NAMESPACE #endif // CGAL_POLYGON_OFFSET_BUILDER_2_C // // EOF //