// Copyright (c) 2005-2008 Fernando Luis Cacciola Carballal. All rights reserved. // // This file is part of CGAL (www.cgal.org). // You can redistribute it and/or modify it under the terms of the GNU // General Public License as published by the Free Software Foundation, // either version 3 of the License, or (at your option) any later version. // // 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$ // SPDX-License-Identifier: GPL-3.0+ // // Author(s) : Fernando Cacciola <fernando_cacciola@ciudad.com.ar> #ifndef CGAL_STRAIGHT_SKELETON_2_H #define CGAL_STRAIGHT_SKELETON_2_H 1 #include <CGAL/license/Straight_skeleton_2.h> #include <CGAL/disable_warnings.h> #include <CGAL/Straight_skeleton_2/Straight_skeleton_aux.h> #include <CGAL/Straight_skeleton_items_2.h> #include <CGAL/HalfedgeDS_default.h> namespace CGAL { template< class Traits_ , class Items_ = Straight_skeleton_items_2 , class Alloc_ = CGAL_ALLOCATOR(int) > class Straight_skeleton_2 : public CGAL_HALFEDGEDS_DEFAULT <Traits_,Items_,Alloc_> { public : typedef Traits_ Traits ; typedef Straight_skeleton_2<Traits_,Items_,Alloc_> Self ; typedef CGAL_HALFEDGEDS_DEFAULT <Traits_,Items_,Alloc_> Base ; typedef typename Base::Vertex_base Vertex ; typedef typename Base::Halfedge_base Halfedge ; typedef typename Base::Face_base Face ; typedef typename Base::Vertex_handle Vertex_handle ; typedef typename Base::Halfedge_handle Halfedge_handle ; typedef typename Base::Face_handle Face_handle ; typedef typename Base::Vertex_const_handle Vertex_const_handle ; typedef typename Base::Halfedge_const_handle Halfedge_const_handle ; typedef typename Base::Face_const_handle Face_const_handle ; typedef typename Base::Vertex_iterator Vertex_iterator ; typedef typename Base::Halfedge_iterator Halfedge_iterator ; typedef typename Base::Face_iterator Face_iterator ; typedef typename Base::Vertex_const_iterator Vertex_const_iterator ; typedef typename Base::Halfedge_const_iterator Halfedge_const_iterator ; typedef typename Base::Face_const_iterator Face_const_iterator ; typedef typename Base::size_type size_type ; Straight_skeleton_2() {} private : Vertex_handle vertices_push_back( const Vertex& v) { return Base::vertices_push_back(v); } Halfedge_handle edges_push_back( const Halfedge& h, const Halfedge& g) { return Base::edges_push_back(h,g); } Halfedge_handle edges_push_back( const Halfedge& h) { return Base::edges_push_back(h); } Face_handle faces_push_back( const Face& f) { return Base::faces_push_back(f); } void vertices_pop_front() { Base::vertifces_pop_front(); } void vertices_pop_back() { Base::vertifces_pop_back(); } void vertices_erase( Vertex_handle v) { Base::vertices_erase(v); } void vertices_erase( Vertex_iterator first, Vertex_iterator last) { Base::vertices_erase(first,last); } void edges_erase( Halfedge_handle h) { Base::edges_erase(h) ; } void edges_pop_front() { Base::edges_pop_front(); } void edges_pop_back() { Base::edges_pop_back(); } void edges_erase( Halfedge_iterator first, Halfedge_iterator last) { Base::edges_erase(first,last); } void faces_pop_front() { Base::faces_pop_front(); } void faces_pop_back() { Base::faces_pop_back(); } void faces_erase( Face_handle f) { Base::faces_erase(f); } void faces_erase( Face_iterator first, Face_iterator last) { Base::faces_erase(first,last); } void vertices_clear() { Base::vertices_clear(); } void edges_clear() { Base::edeges_clear(); } void faces_clear() { Base::faces_clear(); } void clear() { Base::clear();} void vertices_splice( Vertex_iterator target, Self &source, Vertex_iterator begin, Vertex_iterator end) { Base::vertices_splice(target,source,begin,end); } void halfedges_splice( Halfedge_iterator target, Self &source, Halfedge_iterator begin, Halfedge_iterator end) { Base::halfedges_splice(target,source,begin,end); } void faces_splice( Face_iterator target, Self &source, Face_iterator begin, Face_iterator end) { Base::faces_splice(target,source,begin,end); } void normalize_border() { Base::normalize_border(); } public : static int id ( Vertex_const_handle h ) { Vertex_const_handle null ; return h != null ? h->id() : -1 ; } static int id ( Halfedge_const_handle h ) { Halfedge_const_handle null ; return h != null ? h->id() : -1 ; } static int id ( Face_const_handle h ) { Face_const_handle null ; return h != null ? 0 : -1 ; } bool is_valid() const { // // This is a copy of the validity code in Halfedge_const_decorator with a different reporting mechanism // CGAL_STSKEL_VALIDITY_TRACE("begin Straight_skeleton::is_valid()" ); bool valid = ( 1 != (this->size_of_halfedges() & 1)); CGAL_STSKEL_VALIDITY_TRACE_IF(!valid,"number of halfedges: " << this->size_of_halfedges() << " is odd." ) ; // All halfedges. Halfedge_const_iterator begin = this->halfedges_begin(); Halfedge_const_iterator end = this->halfedges_end(); size_type n = 0; size_type nb = 0; for( ; valid && (begin != end); begin++) { CGAL_STSKEL_VALIDITY_TRACE("he["<< id(begin) << "]" << ( begin->is_border() ? " [border]" : "" ) ); // Pointer integrity. valid = valid && ( begin->next() != Halfedge_const_handle()); if ( ! valid) { CGAL_STSKEL_VALIDITY_TRACE("ERROR: he["<<id(begin)<<"]->next() == NULL!"); break; } valid = valid && ( begin->opposite() != Halfedge_const_handle()); if ( ! valid) { CGAL_STSKEL_VALIDITY_TRACE("ERROR: he["<<id(begin)<<"]->opposite() == NULL!"); break; } // opposite integrity. valid = valid && ( begin->opposite() != begin); if ( ! valid) { CGAL_STSKEL_VALIDITY_TRACE("ERROR: he["<<id(begin)<<"]->opposite() == he!"); break; } valid = valid && ( begin->opposite()->opposite() == begin); if ( ! valid) { CGAL_STSKEL_VALIDITY_TRACE("ERROR: he["<<id(begin)<<"]->opposite()["<< id(begin->opposite()) <<"]->opposite()["<< id(begin->opposite()->opposite()) <<"] != he!" ); break; } // previous integrity. valid = valid && begin->next()->prev() == begin; if ( ! valid) { CGAL_STSKEL_VALIDITY_TRACE("ERROR: he["<< id(begin) <<"]->next()["<< id(begin->next()) <<"]->prev()["<< id(begin->next()->prev()) <<"] != he." ); break; } // vertex integrity. valid = valid && begin->vertex() != Vertex_const_handle(); if ( ! valid) { CGAL_STSKEL_VALIDITY_TRACE("ERROR: he["<<id(begin)<<"]->vertex() == NULL!"); break; } if ( ! begin->vertex()->has_infinite_time() ) { valid = valid && ( begin->vertex() == begin->next()->opposite()->vertex()); if ( ! valid) { CGAL_STSKEL_VALIDITY_TRACE("ERROR: he["<< id(begin) <<"]->vertex()["<< id(begin->vertex()) <<"] != he->next()["<< id(begin->next()) <<"]->opposite()["<< id(begin->next()->opposite()) <<"]->vertex()["<< id(begin->next()->opposite()->vertex())<<"]" ); break; } } // face integrity. valid = valid && ( begin->is_border() || begin->face() != Face_const_handle() ); if ( ! valid) { CGAL_STSKEL_VALIDITY_TRACE("ERROR: he["<<id(begin)<<"]->face() == NULL."); break; } valid = valid && ( begin->face() == begin->next()->face()); if ( ! valid) { CGAL_STSKEL_VALIDITY_TRACE("ERROR: he["<< id(begin) <<"]->face()["<< id(begin->face()) <<"] != he->next()["<< id(begin->next()) <<"]->face()["<< id(begin->next()->face())<<"]." ); break; } ++n; if ( begin->is_border()) ++nb; } CGAL_STSKEL_VALIDITY_TRACE("summe border halfedges (2*nb) = " << 2 * nb ); bool nvalid = ( n == this->size_of_halfedges()); CGAL_STSKEL_VALIDITY_TRACE_IF(valid && !nvalid ,"ERROR: counted number of halfedges:" << n << " mismatch with this->size_of_halfedges():" << this->size_of_halfedges() ); valid = valid && nvalid ; // All vertices. Vertex_const_iterator vbegin = this->vertices_begin(); Vertex_const_iterator vend = this->vertices_end(); size_type v = 0; n = 0; bool is_partial_skeleton = false ; for( ; valid && (vbegin != vend); ++vbegin) { // Pointer integrity. valid = valid && vbegin->halfedge() != Halfedge_const_handle() ; if ( ! valid) { CGAL_STSKEL_VALIDITY_TRACE("ERROR: v["<< id(vbegin) <<"]->halfedge() == NULL."); break; } // cycle-around-vertex test. if ( !vbegin->has_infinite_time() ) { valid = valid && vbegin->halfedge()->vertex() == vbegin; if ( ! valid) { CGAL_STSKEL_VALIDITY_TRACE("ERROR: v["<< id(vbegin) <<"]->halfedge()["<< id(vbegin->halfedge()) <<"]->vertex()["<< id(vbegin->halfedge()->vertex()) <<"] != v." ); break; } CGAL_STSKEL_VALIDITY_TRACE("Circulating halfedges around v["<<id(vbegin)<<"]"); Halfedge_const_handle h = vbegin->halfedge(); if ( h != Halfedge_const_handle()) { Halfedge_const_handle g = h; do { CGAL_STSKEL_VALIDITY_TRACE(" v->halfedge(): " << id(h) << ", ->next(): " << id(h->next()) << ", ->next()->opposite(): " << id(h->next()->opposite()) ); ++n; h = h->next()->opposite(); valid = valid && ( n <= this->size_of_halfedges() && n!=0); CGAL_STSKEL_VALIDITY_TRACE_IF(!valid,"ERROR: more than " << this->size_of_halfedges() << " halfedges around v["<< id(vbegin)<<"]" ); } while ( valid && (h != g)); } } else is_partial_skeleton = true ; ++v; } if ( ! is_partial_skeleton ) { bool vvalid = (v == this->size_of_vertices()); CGAL_STSKEL_VALIDITY_TRACE_IF(valid && !vvalid ,"ERROR: counted number of vertices:" << v << " mismatch with this->size_of_vertices():" << this->size_of_vertices() ); bool vnvalid = n == this->size_of_halfedges() ; CGAL_STSKEL_VALIDITY_TRACE_IF(valid && !vnvalid ,"ERROR: counted number of halfedges via vertices:" << n << " mismatch with this->size_of_halfedges():" << this->size_of_halfedges() ); valid = valid && vvalid && vnvalid ; } // All faces. Face_const_iterator fbegin = this->faces_begin(); Face_const_iterator fend = this->faces_end(); size_type f = 0; n = 0; for( ; valid && (fbegin != fend); ++fbegin) { valid = valid && ( begin->is_border() || fbegin->halfedge() != Halfedge_const_handle() ); if ( ! valid) { CGAL_STSKEL_VALIDITY_TRACE("ERROR: f["<<id(fbegin)<<"]->halfedge() == NULL." ); break; } valid = valid && fbegin->halfedge()->face() == fbegin ; if ( ! valid) { CGAL_STSKEL_VALIDITY_TRACE("ERROR: f["<<id(fbegin)<<"]->halfedge()["<< id(fbegin->halfedge()) <<"]->face()["<< id(fbegin->halfedge()->face()) <<"] != f." ); break; } // cycle-around-face test. CGAL_STSKEL_VALIDITY_TRACE("Circulating halfedges around f["<<id(fbegin)<<"]" ); Halfedge_const_handle h = fbegin->halfedge(); if ( h != Halfedge_const_handle()) { Halfedge_const_handle g = h; do { CGAL_STSKEL_VALIDITY_TRACE(" f->halfedge():" << id(h) << ", ->next(): " << id(h->next())); ++n; h = h->next(); valid = valid && ( n <= this->size_of_halfedges() && n!=0); CGAL_STSKEL_VALIDITY_TRACE_IF(!valid,"ERROR: more than " << this->size_of_halfedges() << " halfedges around f["<< id(fbegin)<<"]" ); } while ( valid && (h != g)); } ++f; } bool fvalid = ( f == this->size_of_faces()); CGAL_STSKEL_VALIDITY_TRACE_IF(valid && !fvalid ,"ERROR: counted number of faces:" << f << " mismatch with this->size_of_faces():" << this->size_of_faces() ); bool fnvalid = ( n + nb == this->size_of_halfedges() ); CGAL_STSKEL_VALIDITY_TRACE_IF(valid && !fnvalid ,"ERROR: counted number of halfedges via faces:" << n << " plus counted number of border halfedges: " << nb << " mismatch with this->size_of_halfedges():" << this->size_of_halfedges() ); valid = valid && fvalid && fnvalid ; CGAL_STSKEL_VALIDITY_TRACE ("end of Straight_skeleton_2>::is_valid(): " << ( valid ? "valid." : "NOT VALID.") ); return valid; } }; } // end namespace CGAL #include <CGAL/enable_warnings.h> #endif // CGAL_STRAIGHT_SKELETON_2_H // // EOF //