// Copyright (c) 2002-2004 INRIA Sophia-Antipolis (France). // 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 Lesser 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: LGPL-3.0+ // // // Author(s) : Radu Ursu #ifndef CGAL_apply_to_range_h #define CGAL_apply_to_range_h #include #include #include namespace CGAL{ template void apply_to_range(const Tr &t, const Point_2 &p1, const Point_2 &p2, Fct& fct) { if (t.dimension()<2) return; typedef typename Tr::Point POINT; typedef typename Tr::Face_handle hFACE; typedef typename Tr::Vertex_handle hVERTEX; typedef typename Tr::Line_face_circulator LFC; typedef typename Tr::Finite_vertices_iterator FVI; typedef typename Tr::Finite_faces_iterator FFI; typedef typename Kernel_traits::Kernel K; typedef typename K::FT FT; LFC l1, l2, l3, l4; //the faces that intersect the pixmap RECTANGLE hFACE hface1, hface2, hface3, hface4; //the faces where we start to search FT xr_left, yr_top, xr_right, yr_bottom;//the coordinates of the screen boundaries CGAL::Unique_hash_map visited(false);//used for DFS std::stack face_stack; //used for DFS xr_left = p1.x(); xr_right = p2.x(); yr_top = p1.y(); yr_bottom = p2.y(); hface1 = t.locate(POINT(xr_left, yr_top)); hface2 = t.locate(POINT(xr_right, yr_top)); hface3 = t.locate(POINT(xr_right, yr_bottom)); hface4 = t.locate(POINT(xr_left, yr_bottom)); l1 = t.line_walk(POINT(xr_left, yr_top), POINT(xr_right, yr_top), hface1); l2 = t.line_walk(POINT(xr_right, yr_top), POINT(xr_right, yr_bottom), hface2); l3 = t.line_walk(POINT(xr_right, yr_bottom), POINT(xr_left, yr_bottom), hface3); l4 = t.line_walk(POINT(xr_left, yr_bottom), POINT(xr_left, yr_top), hface4); //test if everything is inside or outside if( (l1 == (Nullptr_t) NULL) && (l2 == (Nullptr_t) NULL) && (l3 == (Nullptr_t) NULL) && (l4 == (Nullptr_t) NULL)) { FVI v = t.finite_vertices_begin(); if((*v).point().x() < xr_left || (*v).point().x() > xr_right || (*v).point().y() < yr_bottom || (*v).point().y() > yr_top) //true if everything is outside return; else{ //everything is inside FFI it = t.finite_faces_begin(); while(it != t.finite_faces_end()) { fct(it); it++; } } return; } //if we are here, then a part of the triangulation is inside, the other is outside //put all the faces on the boundaries in the stack and the map if(l1 != (Nullptr_t) NULL) //found at least one face that intersect the TOP segment { while (t.is_infinite(l1)) l1++; //we should start with a finite face do{ //put all of them in the stack; face_stack.push(l1); visited[l1] = true; l1++; }while(!t.is_infinite(l1) && t.triangle(l1).has_on_unbounded_side(POINT(xr_right, yr_top))); } if(l2 != (Nullptr_t) NULL) //found at least one face that intersect the RIGHT segment { while (t.is_infinite(l2)) l2++; //we should start with a finite face do{ //put all of them in the stack; if(!visited[l2]){ face_stack.push(l2); visited[l2] = true; } l2++; }while(!t.is_infinite(l2) && t.triangle(l2).has_on_unbounded_side(POINT(xr_right, yr_bottom))); } if(l3 != (Nullptr_t) NULL) //found at least one face that intersect the BOTTOM segment { while (t.is_infinite(l3)) l3++; //we should start with a finite face do{ //put all of them in the stack; if(!visited[l3]){ face_stack.push(l3); visited[l3] = true; } l3++; }while(!t.is_infinite(l3) && t.triangle(l3).has_on_unbounded_side(POINT(xr_left, yr_bottom))); } if(l4 != (Nullptr_t) NULL) //found at least one face that intersect the LEFT segment { while (t.is_infinite(l4)) l4++; //we should start with a finite face do{ //put all of them in the stack; if(!visited[l4]){ face_stack.push(l4); visited[l4] = true; } l4++; }while(!t.is_infinite(l4) && t.triangle(l4).has_on_unbounded_side(POINT(xr_left, yr_top))); } //HERE we begin to walk through the faces DFS hFACE hf; typename CGAL::Unique_hash_map::Data& data_ref_start(visited[hf]); data_ref_start = true; while(!face_stack.empty()){ hf = face_stack.top(); face_stack.pop(); //done with this face for (int i=0; i<3; i++){ //visit all the neighbors if(!visited[(*hf).neighbor(i)] ) if(!t.is_infinite((*hf).neighbor(i))){ //true if it is not an infinite face hVERTEX hv = (*(*hf).neighbor(i)).vertex((*(*hf).neighbor(i)).index(hf)); if(!((*hv).point().x() < xr_left || (*hv).point().x() > xr_right || (*hv).point().y() < yr_bottom || (*hv).point().y() > yr_top)) //true if the vertex is outside face_stack.push((*hf).neighbor(i)); typename CGAL::Unique_hash_map::Data& data_ref(visited[(*hf).neighbor(i)]); data_ref = true; } } fct(hf); } } }//end namespace #endif