dust3d/thirdparty/cgal/CGAL-5.1/include/CGAL/Point_set_2.h

452 lines
12 KiB
C++

// Copyright (c) 1999
// Max-Planck-Institute Saarbruecken (Germany). All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL: https://github.com/CGAL/cgal/blob/v5.1/Point_set_2/include/CGAL/Point_set_2.h $
// $Id: Point_set_2.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Matthias Baesken
#ifndef CGAL_POINT_SET_2_H
#define CGAL_POINT_SET_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/squared_distance_2_1.h>
#include <CGAL/compare_vertices.h>
#include <list>
#include <queue>
#include <map>
#include <stack>
#include <cmath>
#include <climits>
namespace CGAL {
template<class Gt, class Tds = Triangulation_data_structure_2 <Triangulation_vertex_base_2<Gt> > >
class Point_set_2 : public Delaunay_triangulation_2<Gt,Tds>
{
public:
typedef Gt Geom_traits;
typedef typename Geom_traits::Point_2 Point;
typedef typename Geom_traits::Segment_2 Segment;
typedef typename Geom_traits::Circle_2 Circle;
typedef typename Geom_traits::Orientation_2 Orientation_2;
typedef typename Geom_traits::Side_of_oriented_circle_2 Side_of_oriented_circle_2;
typedef typename Geom_traits::Construct_circle_2 Construct_circle_2;
typedef typename Geom_traits::Compute_squared_distance_2 Compute_squared_distance_2;
typedef typename Geom_traits::FT Numb_type; // field number type ...
typedef Delaunay_triangulation_2<Gt,Tds> Triangulation;
typedef typename Triangulation::size_type size_type;
typedef typename Triangulation::Locate_type Locate_type;
typedef typename Triangulation::Face_handle Face_handle;
typedef typename Triangulation::Vertex_handle Vertex_handle;
typedef typename Triangulation::Edge Edge;
typedef typename Triangulation::Vertex Vertex;
typedef typename Triangulation::Face Face;
typedef typename Triangulation::Edge_circulator Edge_circulator;
typedef typename Triangulation::Finite_edges_iterator Finite_edges_iterator;
typedef typename Triangulation::Vertex_iterator Vertex_iterator;
typedef typename Triangulation::Vertex_circulator Vertex_circulator;
typedef typename Triangulation::Edge_iterator Edge_iterator;
typedef typename Geom_traits::Bounded_side_2 Circleptori;
typedef typename Geom_traits::Compare_distance_2 Comparedist;
typedef typename Geom_traits::Construct_center_2 Circlecenter;
typedef Unique_hash_map<Vertex_handle, Numb_type> MAP_TYPE;
typedef Delaunay_triangulation_2<Gt,Tds> Base;
using Base::finite_vertices_begin;
using Base::finite_vertices_end;
using Base::number_of_vertices;
using Base::VERTEX;
using Base::insert;
using Base::remove;
using Base::locate;
using Base::is_infinite;
using Base::nearest_vertex;
using Base::incident_vertices;
Comparedist tr_comparedist;
Orientation_2 tr_orientation;
Side_of_oriented_circle_2 tr_so_circle;
Compute_squared_distance_2 tr_sqrdist;
Circleptori tr_circleptori;
Circlecenter tr_circlecenter;
//constructions...
Construct_circle_2 tr_createcircle_3p;
Point_set_2()
{
init_vertex_marks();
}
template<class InputIterator>
Point_set_2(InputIterator first, InputIterator last)
{
init_vertex_marks();
insert(first,last);
}
~Point_set_2() {}
template<class OutputIterator>
OutputIterator vertices(OutputIterator res)
// return vertex handles ...
{
Vertex_iterator vit = finite_vertices_begin();
for (; vit != finite_vertices_end(); vit++) { *res= vit; res++; }
return res;
}
Vertex_handle lookup(Point p) const
{
if (number_of_vertices() == 0) return nullptr;
// locate ...
Locate_type lt;
int li;
Face_handle fh = locate(p,lt,li);
if (lt == VERTEX){
Face f = *fh;
return f.vertex(li);
}
else return nullptr;
}
Vertex_handle nearest_neighbor(Point p)
{
if (number_of_vertices() == 0) return nullptr;
return nearest_vertex(p);
}
Vertex_handle nearest_neighbor(Vertex_handle v) const
{
if (number_of_vertices() <= 1) return nullptr;
Point p = v->point();
Vertex_circulator vc = incident_vertices(v);
Vertex_circulator start =vc;
Vertex_handle min_v = vc;
if (is_infinite(min_v)){
vc++;
min_v = vc;
}
Vertex_handle act;
// go through the vertices ...
do {
act = vc;
if (! is_infinite(act)) {
if ( tr_comparedist(p,act->point(), min_v->point()) == SMALLER ) {
min_v = act;
}
}
vc++;
} while (vc != start);
return min_v;
}
template<class OutputIterator>
OutputIterator nearest_neighbors(Point p, size_type k, OutputIterator res)
{
size_type n = number_of_vertices();
if ( k <= 0 ) return res;
if ( n <= k ) { // return all finite vertices ...
return vertices(res);
}
// insert p, if nesessary
Vertex_handle vh = lookup(p);
bool old_node = true;
// we have to add a new vertex ...
if (vh == nullptr){
vh = insert(p);
old_node = false;
k++;
}
std::list<Vertex_handle> res_list;
nearest_neighbors_list(vh, k, res_list);
if ( !old_node )
{
res_list.pop_front();
remove(vh);
}
typename std::list<Vertex_handle>::iterator it = res_list.begin();
for (; it != res_list.end(); it++) { *res= *it; res++; }
return res;
}
template<class OutputIterator>
OutputIterator nearest_neighbors(Vertex_handle v, size_type k,OutputIterator res)
{
size_type n = number_of_vertices();
if ( k <= 0 ) return res;
if ( n <= k ) { // return all (finite) vertices ...
return vertices(res);
}
std::list<Vertex_handle> res_list;
nearest_neighbors_list(v, k, res_list);
typename std::list<Vertex_handle>::iterator it = res_list.begin();
for (; it != res_list.end(); it++) { *res= *it; res++; }
return res;
}
void nearest_neighbors_list(Vertex_handle v,
size_type k,
std::list<Vertex_handle>& res)
{
size_type n = number_of_vertices();
if ( k <= 0 ) return;
if ( n <= k ) { vertices(std::back_inserter(res)); return; }
Point p = v->point();
// "unmark" the vertices ...
init_search();
MAP_TYPE priority_number; // here we save the priorities ...
internal::compare_vertices<Vertex_handle,Numb_type,MAP_TYPE>
comp(& priority_number); // comparison object ...
std::priority_queue<Vertex_handle, std::vector<Vertex_handle>, internal::compare_vertices<Vertex_handle,Numb_type,MAP_TYPE> > PQ(comp);
priority_number[v] = 0;
PQ.push(v);
mark_vertex(v);
while ( k > 0 )
{
// find minimum from PQ ...
Vertex_handle w = PQ.top();
PQ.pop();
res.push_back(w);
k--;
// get the incident vertices of w ...
Vertex_circulator vc = incident_vertices(w);
Vertex_circulator start =vc;
Vertex_handle act;
do {
act = vc;
if ( (!is_marked(act)) && (! is_infinite(act)) )
{
priority_number[act] = tr_sqrdist(p,act->point());
PQ.push(act);
mark_vertex(act);
}
vc++;
} while (vc != start);
}
}
// for marking nodes in search procedures
size_type cur_mark;
Unique_hash_map<Vertex_handle, size_type> mark;
void init_vertex_marks()
{
cur_mark = 0;
mark.clear();
}
void init_search()
{
cur_mark++;
if (cur_mark == (std::numeric_limits<size_type>::max)()) init_vertex_marks();
}
void mark_vertex(Vertex_handle vh)
// mark vh as visited ...
{
mark[vh] = cur_mark;
}
bool is_marked(Vertex_handle vh)
{
if (! mark.is_defined(vh)) return false;
return (mark[vh] == cur_mark);
}
void search(Vertex_handle v,const Circle& C, std::list<Vertex_handle>& L)
{
std::stack<Vertex_handle> todo;
todo.push(v);
while (!todo.empty())
{
Vertex_handle current = todo.top();
todo.pop();
if (is_marked(current))
continue;
L.push_back(current);
mark_vertex(current);
// get incident vertices of v ...
Vertex_circulator vc = incident_vertices(current);
Vertex_circulator start =vc;
Vertex_handle act;
// go through the vertices ...
do {
act = vc;
if (! is_infinite(act)) {
if (!is_marked(act) && ! (tr_circleptori(C,act->point())==ON_UNBOUNDED_SIDE) )
todo.push(act);
}
vc++;
} while (vc != start);
}
}
template<class OutputIterator>
OutputIterator range_search(const Circle& C, OutputIterator res)
{
if (number_of_vertices() == 0) return res;
if (number_of_vertices() == 1)
{
// get the one vertex ...
Vertex_iterator vit = finite_vertices_begin();
Point p = vit->point();
if (! (tr_circleptori(C, p) == ON_UNBOUNDED_SIDE)){
*res= vit; res++;
}
return res;
}
// normal case ...
Point p = tr_circlecenter(C);
Vertex_handle v = lookup(p);
bool new_v = false;
if ( v == nullptr )
{
new_v = true;
v = insert(p);
}
init_search();
std::list<Vertex_handle> L;
search(v,C,L);
if (new_v)
{ L.pop_front(); //first one was inserted in range_search ...
remove(v);
}
typename std::list<Vertex_handle>::const_iterator iter = L.begin();
for(;iter != L.end() ;iter++){ *res= *iter; res++; }
return res;
}
template<class OutputIterator>
OutputIterator range_search(const Point& a, const Point& b, const Point& c,OutputIterator res)
{ int orient = (int)(tr_orientation(a,b,c));
Circle C = tr_createcircle_3p(a,b,c);
std::list<Vertex_handle> L;
range_search(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)(tr_orientation(a,b,p))) == - orient ||
((int)(tr_orientation(b,c,p))) == - orient ||
((int)(tr_orientation(c,a,p))) == - orient ) { }
else { *res = *it; res++; }
}
return res;
}
template<class OutputIterator>
OutputIterator range_search(const Point& a1, const Point& b1, const Point& c1,const Point&
d1,OutputIterator res)
// a1 upper left, b1 lower left , c1 lower right
{
//Point b(c.xcoord(),a.ycoord());
//Point d(a.xcoord(),c.ycoord());
Point a=a1,b=b1,c=c1,d=d1;
if (tr_orientation(a,b,c) == RIGHT_TURN)
{ Point tmp = b;
b = d;
d = tmp;
}
Circle C = tr_createcircle_3p(a,b,c);
std::list<Vertex_handle> L;
range_search(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 ( tr_orientation(a,b,p) == RIGHT_TURN || tr_orientation(b,c,p) == RIGHT_TURN ||
tr_orientation(c,d,p) == RIGHT_TURN || tr_orientation(d,a,p) == RIGHT_TURN ) { }
else { *res = *it; res++; }
}
return res;
}
};
} //namespace CGAL
#endif