dust3d/thirdparty/cgal/CGAL-4.13/include/CGAL/range_search_delaunay_2.h

452 lines
13 KiB
C
Raw Normal View History

// Copyright (c) 1999
// Max-Planck-Institute Saarbruecken (Germany). 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) : Matthias Baesken
#ifndef CGAL_RANGE_SEARCH_DELAUNAY_2_H
#define CGAL_RANGE_SEARCH_DELAUNAY_2_H
#include <CGAL/license/Point_set_2.h>
#include <CGAL/basic.h>
#include <CGAL/Unique_hash_map.h>
#include <CGAL/Delaunay_triangulation_2.h>
#include <CGAL/nearest_neighbor_delaunay_2.h>
#include <list>
#include <queue>
#include <map>
#include <stack>
#include <cmath>
namespace CGAL {
// was
// std::map<typename Dt::Vertex *,int, std::less<typename Dt::Vertex *> >
template<class Dt,class Circle,class OutputIterator,class MAP_TYPE>
void dfs(const Dt& delau,
MAP_TYPE& mark,
typename Dt::Vertex_handle v,
const Circle& C,
OutputIterator res,
bool first_vertex)
{
typedef typename Dt::Geom_traits Gt;
typedef typename Dt::Vertex_circulator Vertex_circulator;
typedef typename Dt::Vertex_handle Vertex_handle;
typedef typename Gt::Bounded_side_2 Bounded_side_2;
Bounded_side_2 test;
if (! first_vertex) *res = v;
//mark_vertex v
mark[v] = true;
// get incident vertices of v ...
Vertex_circulator vc = delau.incident_vertices(v);
Vertex_circulator start =vc;
Vertex_handle act;
// go through the vertices ...
do {
act = vc;
if (! delau.is_infinite(act)) {
// test, if act is marked ...
bool is_marked = mark[act];
if ((! is_marked) && !( test(C,act->point()) == ON_UNBOUNDED_SIDE) )
dfs(delau, mark, act, C, res, false);
}
vc++;
} while (vc != start);
}
// second dfs uses test - predicate function object ...
template<class Dt,class Circle,class OutputIterator,class MAP_TYPE,class Pred>
bool dfs(const Dt& delau,
MAP_TYPE& mark,
typename Dt::Vertex_handle v,
const Circle& C,
OutputIterator res,
bool first_vertex,
bool return_if_predicate_succeded,
Pred& pred)
{
typedef typename Dt::Geom_traits Gt;
typedef typename Dt::Vertex_circulator Vertex_circulator;
typedef typename Dt::Vertex_handle Vertex_handle;
typedef typename Gt::Bounded_side_2 Bounded_side_2;
Bounded_side_2 test;
if (! first_vertex) {
if (pred(v->point())) {
*res = v;
if (return_if_predicate_succeded) return true;
}
}
//mark_vertex v
mark[v] = true;
// get incident vertices of v ...
Vertex_circulator vc = delau.incident_vertices(v);
Vertex_circulator start =vc;
Vertex_handle act;
// go through the vertices ...
do {
act = vc;
if (! delau.is_infinite(act)) {
// test, if act is marked ...
bool is_marked = mark[act];
if ((! is_marked) && !( test(C,act->point()) == ON_UNBOUNDED_SIDE) )
if (dfs(delau, mark, act, C, res, false, return_if_predicate_succeded, pred)) return true;
}
vc++;
} while (vc != start);
return false;
}
template<class Dt,class Circle,class OutputIterator,class MAP_TYPE,class Pred>
void dfs_using_predicate(const Dt& delau,
MAP_TYPE& mark,
typename Dt::Vertex_handle v,
const Circle& C,
OutputIterator res,
bool first_vertex,
bool return_if_predicate_succeded,
Pred& pred)
{
bool val = dfs(delau, mark, v, C, res, first_vertex, return_if_predicate_succeded, pred);
pred.set_result(val);
}
// circular range search ...
template<class Dt, class Circle, class OutputIterator>
OutputIterator range_search(Dt& delau,
const Circle& C,
OutputIterator res)
{
typedef typename Dt::Geom_traits Gt;
typedef typename Dt::Point Point;
typedef typename Dt::Vertex_handle Vertex_handle;
typedef typename Dt::Vertex_iterator Vertex_iterator;
typedef typename Gt::Bounded_side_2 Bounded_side_2;
typedef typename Gt::Construct_center_2 Construct_center_2;
Bounded_side_2 test;
if (delau.number_of_vertices() == 0) return res;
if (delau.number_of_vertices() == 1)
{
// get the one vertex ...
Vertex_iterator vit = delau.finite_vertices_begin();
Point p = vit->point();
if (! (test(C, p) == ON_UNBOUNDED_SIDE)){
*res= vit; res++;
}
return res;
}
// normal case ...
Point p = Construct_center_2()(C);
Vertex_handle v = lookup(delau, p);
bool new_v = false;
// we have to insert the center ...
if ( v == NULL )
{
new_v = true;
v = delau.insert(p);
}
//std::map<Vertex*,int, std::less<Vertex*> > mark;
Unique_hash_map<Vertex_handle, bool> mark;
dfs(delau,mark,v,C,res,new_v);
if (new_v)
{
delau.remove(v);
}
return res;
}
// triangular range search ...
// Note that the function only works correctly with exact constructions
// because it computes the circumcenter of the points a, b, and c
// and then performs a range query with this circle.
// When vertices of the trinagulation are on the circle the outcome
// is not deterministic.
// A solution would be to not constuct a circle, but to use the
// function CGAL::side_of_bounded_circle
template<class Dt, class OutputIterator>
OutputIterator range_search(Dt& delau,
const typename Dt::Point& a,
const typename Dt::Point& b,
const typename Dt::Point& c,
OutputIterator res)
{
typedef typename Dt::Geom_traits Gt;
typedef typename Dt::Point Point;
typedef typename Gt::Circle_2 Circle;
typedef typename Dt::Vertex_handle Vertex_handle;
typedef typename Gt::Orientation_2 Orientation_2;
typedef typename Gt::Construct_circle_2 Construct_circle_2;
Orientation_2 test_ori;
int orient = (int)(test_ori(a,b,c));
Circle C = Construct_circle_2()(a,b,c);
std::list<Vertex_handle> L;
range_search(delau, C, std::back_inserter(L));
typename std::list<Vertex_handle>::const_iterator it = L.begin();
for(;it != L.end();it++)
{ Point p = (*it)->point();
if ( ((int)(test_ori(a,b,p))) == - orient ||
((int)(test_ori(b,c,p))) == - orient ||
((int)(test_ori(c,a,p))) == - orient ) { }
else { *res = *it; res++; }
}
return res;
}
// rectangular range search ....
template<class Dt,class OutputIterator>
OutputIterator range_search(Dt& delau,
const typename Dt::Point& a1,
const typename Dt::Point& b1,
const typename Dt::Point& c1,
const typename Dt::Point& d1,
OutputIterator res)
// a1 upper left, b1 lower left , c1 lower right
{
typedef typename Dt::Geom_traits Gt;
typedef typename Dt::Point Point;
typedef typename Gt::Circle_2 Circle;
typedef typename Dt::Vertex_handle Vertex_handle;
typedef typename Gt::Orientation_2 Orientation_2;
typedef typename Gt::Construct_circle_2 Construct_circle_2;
Point a=a1,b=b1,c=c1,d=d1;
if (Orientation_2()(a,b,c) == RIGHT_TURN)
{ Point tmp = b;
b = d;
d = tmp;
}
Circle C = Construct_circle_2()(a,b,c);
std::list<Vertex_handle> L;
range_search(delau, C, std::back_inserter(L));
typename std::list<Vertex_handle>::const_iterator it = L.begin();
for(;it != L.end();it++)
{ Point p = (*it)->point();
if ( Orientation_2()(a,b,p) == RIGHT_TURN || Orientation_2()(b,c,p) == RIGHT_TURN ||
Orientation_2()(c,d,p) == RIGHT_TURN || Orientation_2()(d,a,p) == RIGHT_TURN ) { }
else { *res = *it; res++; }
}
return res;
}
// ------------------------------------------------------------------------------------------------
// new range search variants using test function object ...
// circular range search ...
template<class Dt, class Circle, class OutputIterator,class Pred>
OutputIterator range_search(Dt& delau,
const Circle& C,
OutputIterator res,
Pred& pred,
bool return_if_succeded)
{
typedef typename Dt::Geom_traits Gt;
typedef typename Dt::Point Point;
typedef typename Dt::Vertex_handle Vertex_handle;
typedef typename Dt::Vertex_iterator Vertex_iterator;
typedef typename Gt::Bounded_side_2 Bounded_side_2;
typedef typename Gt::Construct_center_2 Construct_center_2;
Bounded_side_2 test;
if (delau.number_of_vertices() == 0) return res;
if (delau.number_of_vertices() == 1)
{
// get the one vertex ...
Vertex_iterator vit = delau.finite_vertices_begin();
Point p = vit->point();
if (! (test(C, p) == ON_UNBOUNDED_SIDE)){
*res= vit; res++;
}
bool val = pred(p);
pred.set_result(val);
return res;
}
// normal case ...
Point p = Construct_center_2()(C);
Vertex_handle v = lookup(delau, p);
bool new_v = false;
// we have to insert the center ...
if ( v == NULL )
{
new_v = true;
v = delau.insert(p);
}
//std::map<Vertex*,int, std::less<Vertex*> > mark;
Unique_hash_map<Vertex_handle, bool> mark;
dfs_using_predicate(delau,mark,v,C,res,new_v, return_if_succeded, pred);
if (new_v)
{
delau.remove(v);
}
return res;
}
// triangular range search ...
template<class Dt, class OutputIterator,class Pred>
OutputIterator range_search(Dt& delau,
const typename Dt::Point& a,
const typename Dt::Point& b,
const typename Dt::Point& c,
OutputIterator res,
Pred& pred,
bool return_if_succeded)
{
typedef typename Dt::Geom_traits Gt;
typedef typename Dt::Point Point;
typedef typename Gt::Circle_2 Circle;
typedef typename Dt::Vertex_handle Vertex_handle;
typedef typename Gt::Orientation_2 Orientation_2;
typedef typename Gt::Construct_circle_2 Construct_circle_2;
Orientation_2 test_ori;
int orient = (int)(test_ori(a,b,c));
Circle C = Construct_circle_2()(a,b,c);
std::list<Vertex_handle> L;
range_search(delau, C, std::back_inserter(L), pred, return_if_succeded);
if (return_if_succeded) return res;
typename std::list<Vertex_handle>::const_iterator it = L.begin();
for(;it != L.end();it++)
{ Point p = (*it)->point();
if ( ((int)(test_ori(a,b,p))) == - orient ||
((int)(test_ori(b,c,p))) == - orient ||
((int)(test_ori(c,a,p))) == - orient ) { }
else { *res = *it; res++; }
}
return res;
}
// rectangular range search ....
template<class Dt,class OutputIterator,class Pred>
OutputIterator range_search(Dt& delau,
const typename Dt::Point& a1,
const typename Dt::Point& b1,
const typename Dt::Point& c1,
const typename Dt::Point& d1,
OutputIterator res,
Pred& pred,
bool return_if_succeded)
// a1 upper left, b1 lower left , c1 lower right
{
typedef typename Dt::Geom_traits Gt;
typedef typename Dt::Point Point;
typedef typename Gt::Circle_2 Circle;
typedef typename Dt::Vertex_handle Vertex_handle;
typedef typename Gt::Orientation_2 Orientation_2;
typedef typename Gt::Construct_circle_2 Construct_circle_2;
Point a=a1,b=b1,c=c1,d=d1;
if (Orientation_2()(a,b,c) == RIGHT_TURN)
{ Point tmp = b;
b = d;
d = tmp;
}
Circle C = Construct_circle_2()(a,b,c);
std::list<Vertex_handle> L;
range_search(delau, C, std::back_inserter(L), pred, return_if_succeded);
if (return_if_succeded) return res;
typename std::list<Vertex_handle>::const_iterator it = L.begin();
for(;it != L.end();it++)
{ Point p = (*it)->point();
if ( Orientation_2()(a,b,p) == RIGHT_TURN || Orientation_2()(b,c,p) == RIGHT_TURN ||
Orientation_2()(c,d,p) == RIGHT_TURN || Orientation_2()(d,a,p) == RIGHT_TURN ) { }
else { *res = *it; res++; }
}
return res;
}
} //namespace CGAL
#endif