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

2169 lines
72 KiB
C++
Executable File

// Copyright (c) 1997-2002,2005 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) : Michael Seel <seel@mpi-sb.mpg.de>
// Miguel Granados <granados@mpi-sb.mpg.de>
// Susan Hert <hert@mpi-sb.mpg.de>
// Lutz Kettner <kettner@mpi-sb.mpg.de>
// Ralf Osbild <osbild@mpi-sb.mpg.de>
// Peter Hachenberger <hachenberger@mpi-sb.mpg.de>
#ifndef CGAL_NEF_POLYHEDRON_3_H
#define CGAL_NEF_POLYHEDRON_3_H
#include <CGAL/license/Nef_3.h>
#include <CGAL/disable_warnings.h>
#include <CGAL/basic.h>
#include <CGAL/Handle_for.h>
#include <CGAL/Nef_3/Default_items.h>
#include <CGAL/Nef_3/SNC_structure.h>
#include <CGAL/Nef_3/SNC_decorator.h>
#include <CGAL/Nef_3/SNC_const_decorator.h>
#include <CGAL/Nef_3/SNC_constructor.h>
#include <CGAL/Nef_3/SNC_external_structure.h>
#include <CGAL/Nef_3/Combine_with_halfspace.h>
#ifdef CGAL_NEF_VISUAL_HULL
#include <CGAL/Nef_3/Binary_operation_vs.h>
#else
#include <CGAL/Nef_3/Binary_operation.h>
#endif
#include <CGAL/Nef_S2/SM_decorator.h>
#include <CGAL/Nef_S2/SM_const_decorator.h>
#include <CGAL/Nef_3/SNC_SM_overlayer.h>
#include <CGAL/Nef_S2/SM_point_locator.h>
#include <CGAL/Nef_3/SNC_SM_explorer.h>
#include <CGAL/Nef_polyhedron_S2.h>
#include <CGAL/Modifier_base.h>
#include <CGAL/Nef_3/Mark_bounded_volumes.h>
#include <CGAL/IO/Verbose_ostream.h>
#include <CGAL/Nef_3/polygon_mesh_to_nef_3.h>
#include <CGAL/Nef_3/shell_to_nef_3.h>
#include <CGAL/Polyhedron_incremental_builder_3.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
#include <CGAL/boost/graph/properties_Polyhedron_3.h>
#include <CGAL/Nef_3/SNC_point_locator.h>
#include <CGAL/assertions.h>
#include <CGAL/Constrained_triangulation_2.h>
#include <CGAL/Triangulation_data_structure_2.h>
#include <CGAL/Projection_traits_xy_3.h>
#include <CGAL/Projection_traits_yz_3.h>
#include <CGAL/Projection_traits_xz_3.h>
#include <CGAL/Constrained_triangulation_face_base_2.h>
#include <list>
#include <boost/type_traits/is_same.hpp>
#include <boost/utility/enable_if.hpp>
// RO: includes for "vertex cycle to Nef" constructor
#include <CGAL/Nef_3/vertex_cycle_to_nef_3.h>
#include <CGAL/Vector_3.h>
#include <CGAL/normal_vector_newell_3.h>
#ifdef CGAL_NEF_VISUAL_HULL
#include <CGAL/Nef_3/Modifying_binary_operation_vs.h>
#endif
#undef CGAL_NEF_DEBUG
#define CGAL_NEF_DEBUG 11
#include <CGAL/Nef_2/debug.h>
namespace CGAL {
template <typename K, typename I, typename M> class Nef_polyhedron_3;
template <typename K, typename I, typename M> class Nef_polyhedron_3_rep;
template <typename K, typename I, typename M>
std::ostream& operator<<(std::ostream& os, Nef_polyhedron_3<K,I,M>& NP);
template <typename K, typename I, typename M>
std::istream& operator>>(std::istream& os, Nef_polyhedron_3<K,I,M>& NP);
template <typename K, typename I, typename M>
class Nef_polyhedron_3_rep
{
typedef Nef_polyhedron_3_rep<K,I,M> Self;
friend class Nef_polyhedron_3<K,I,M>;
public:
typedef CGAL::SNC_structure<K,I,M> SNC_structure;
typedef CGAL::SNC_decorator<SNC_structure> SNC_decorator;
typedef CGAL::SNC_const_decorator<SNC_structure> SNC_const_decorator;
typedef CGAL::Binary_operation<SNC_structure> Binary_operation;
typedef CGAL::SNC_constructor<I, SNC_structure> SNC_constructor;
typedef CGAL::SNC_external_structure<I, SNC_structure> SNC_external_structure;
typedef CGAL::SNC_point_locator<SNC_decorator> SNC_point_locator;
typedef CGAL::SNC_simplify<I, SNC_structure> SNC_simplify;
typedef CGAL::SNC_point_locator_by_spatial_subdivision<SNC_decorator> SNC_point_locator_default;
typedef typename SNC_structure::Sphere_map Sphere_map;
typedef CGAL::SM_decorator<Sphere_map> SM_decorator;
typedef CGAL::SM_const_decorator<Sphere_map> SM_const_decorator;
typedef CGAL::SNC_SM_overlayer<I, SM_decorator> SM_overlayer;
typedef CGAL::SM_point_locator<SNC_structure> SM_point_locator;
private:
SNC_structure snc_;
SNC_point_locator* pl_;
public:
Nef_polyhedron_3_rep() : snc_(), pl_() {}
~Nef_polyhedron_3_rep() {
CGAL_NEF_TRACEN( "Nef_polyhedron_3_rep: destroying SNC structure "<<&snc_<<
", point locator "<<pl_);
snc_.clear();
delete pl_;
}
};
/*{\Manpage {Nef_polyhedron_3} {T} {Nef Polyhedra in Space}{N}}*/
/*{\Mdefinition
An instance of data type |\Mname| is a subset of 3-space which is the
result of forming complements and intersections starting from a set |H| of
halfspaces. |\Mtype| is closed under all binary set opertions |intersection|,
|union|, |difference|, |complement| and under the topological operations
|boundary|, |closure|, and |interior|.}*/
template <typename Kernel_, typename Items_ = typename CGAL::Default_items<Kernel_>::Items, typename Mark_ = bool>
class Nef_polyhedron_3 : public CGAL::Handle_for< Nef_polyhedron_3_rep<Kernel_, Items_, Mark_> >,
public SNC_const_decorator<SNC_structure<Kernel_,Items_,Mark_> >
{
public:
/*{\Mtypes 7}*/
typedef Kernel_ Kernel;
typedef Kernel_ Traits;
typedef Items_ Items;
typedef Mark_ Mark;
typedef Nef_polyhedron_3<Kernel, Items, Mark> Self;
typedef Nef_polyhedron_3<Kernel, Items, Mark> Nef_polyhedron;
typedef Handle_for< Nef_polyhedron_3_rep<Kernel, Items, Mark> > Base;
typedef typename Kernel::Point_3 Point_3;
typedef typename Kernel::Plane_3 Plane_3;
typedef typename Kernel::Vector_3 Vector_3;
typedef typename Kernel::Segment_3 Segment_3;
typedef typename Kernel::Aff_transformation_3 Aff_transformation_3;
#if (! defined _MSC_VER) || (_MSC_VER >= 1900)
// VC++ < 2017 has a problem to digest the following typedef,
// and does not need the using statements -- AF
// The left and right part of these typedefs have the same name. It is
// very important to qualify the left part with the CGAL:: namespace, no
// to confuse g++. -- Laurent Rineau, 2010/09/13
typedef CGAL::SNC_structure<Kernel,Items,Mark> SNC_structure;
typedef CGAL::SNC_const_decorator<SNC_structure> SNC_const_decorator;
using SNC_const_decorator::set_snc;
using SNC_const_decorator::is_standard;
using SNC_const_decorator::is_bounded;
#endif
struct Polylines_tag {};
struct Points_tag {};
enum Boundary { EXCLUDED=0, INCLUDED=1 };
/*{\Menum construction selection.}*/
typedef enum { EMPTY=0, COMPLETE=1 } Content;
/*{\Menum construction selection}*/
typedef enum { DEFAULT, NAIVE, WALKING, SPATIAL_SUBDIVISION } Location_mode;
/*{\Menum selection flag for the point location mode.}*/
protected:
struct AND {
Mark operator()(const Mark& b1, const Mark& b2, bool /* inverted */ =false)const
{ return b1&&b2; }
};
struct OR {
Mark operator()(const Mark& b1, const Mark& b2, bool /* inverted */ =false) const
{ return b1||b2; }
};
struct DIFF {
Mark operator()(const Mark& b1, const Mark& b2, bool inverted=false) const
{ return (inverted) ? !b1&&b2 : b1&&!b2 ; }
};
struct XOR {
Mark operator()(const Mark& b1, const Mark& b2, bool /* inverted */ =false) const
{ return (b1&&!b2)||(!b1&&b2); }
};
public:
typedef Nef_polyhedron_3_rep<Kernel,Items, Mark> Nef_rep;
typedef typename Nef_rep::SM_decorator SM_decorator;
typedef typename Nef_rep::SM_const_decorator SM_const_decorator;
protected:
typedef typename Nef_rep::SNC_decorator SNC_decorator;
typedef typename Nef_rep::SNC_constructor SNC_constructor;
typedef typename Nef_rep::SNC_external_structure SNC_external_structure;
typedef typename Nef_rep::Binary_operation Binary_operation;
typedef typename Nef_rep::SNC_point_locator SNC_point_locator;
typedef typename Nef_rep::SNC_point_locator_default
SNC_point_locator_default;
typedef CGAL::Combine_with_halfspace<SNC_structure, SNC_point_locator>
Combine_with_halfspace;
public:
enum Intersection_mode {
CLOSED_HALFSPACE = Combine_with_halfspace::CLOSED_HALFSPACE,
OPEN_HALFSPACE = Combine_with_halfspace::OPEN_HALFSPACE,
PLANE_ONLY = Combine_with_halfspace::PLANE_ONLY};
protected:
typedef typename Nef_rep::SM_overlayer SM_overlayer;
typedef typename Nef_rep::SM_point_locator SM_point_locator;
typedef typename Nef_rep::SNC_simplify SNC_simplify;
typedef typename Nef_rep::Sphere_map Sphere_map;
public:
typedef CGAL::Nef_polyhedron_S2<Kernel,Items,Mark,Sphere_map> Nef_polyhedron_S2;
protected:
SNC_structure& snc() { return this->ptr()->snc_; }
const SNC_structure& snc() const { return this->ptr()->snc_; }
SNC_point_locator*& pl() { return this->ptr()->pl_; }
const SNC_point_locator* pl() const { return this->ptr()->pl_; }
friend std::ostream& operator<< <>
(std::ostream& os, Nef_polyhedron_3<Kernel,Items, Mark>& NP);
friend std::istream& operator>> <>
(std::istream& is, Nef_polyhedron_3<Kernel,Items, Mark>& NP);
typedef typename SNC_decorator::Vertex_handle Vertex_handle;
typedef typename SNC_decorator::Halfedge_handle Halfedge_handle;
typedef typename SNC_decorator::Halffacet_handle
Halffacet_handle;
typedef typename SNC_decorator::Volume_handle Volume_handle;
public:
typedef typename SNC_structure::Sphere_point Sphere_point;
typedef typename SNC_structure::Sphere_segment Sphere_segment;
typedef typename SNC_structure::Sphere_circle Sphere_circle;
typedef typename SNC_structure::Vertex_base Vertex;
typedef typename SNC_structure::Halfedge_base Halfedge;
typedef typename SNC_structure::Halffacet_base Halffacet;
typedef typename SNC_structure::Volume_base Volume;
typedef typename SNC_structure::Vertex_const_handle Vertex_const_handle;
typedef typename SNC_structure::Halfedge_const_handle Halfedge_const_handle;
typedef typename SNC_structure::Halffacet_const_handle Halffacet_const_handle;
typedef typename SNC_structure::Volume_const_handle Volume_const_handle;
typedef typename SNC_structure::SHalfedge_around_svertex_circulator
SHalfedge_around_svertex_circulator;
typedef typename SNC_structure::SHalfedge_around_svertex_const_circulator
SHalfedge_around_svertex_const_circulator;
typedef typename SNC_structure::SHalfedge_around_facet_circulator
SHalfedge_around_facet_circulator;
typedef typename SNC_structure::SHalfedge_around_facet_const_circulator
SHalfedge_around_facet_const_circulator;
typedef typename SNC_structure::SHalfedge_around_sface_const_circulator
SHalfedge_around_sface_const_circulator;
typedef typename SNC_structure::Halffacet_cycle_const_iterator
Halffacet_cycle_const_iterator;
typedef typename SNC_structure::Halffacet_cycle_iterator
Halffacet_cycle_iterator;
typedef typename SNC_structure::Infi_box Infi_box;
typedef typename SNC_structure::Size_type Size_type;
typedef Size_type size_type;
typedef typename Kernel::RT RT;
public:
typedef typename SM_decorator::SVertex_handle SVertex_handle;
typedef typename SM_decorator::SHalfedge_handle SHalfedge_handle;
typedef typename SM_decorator::SFace_handle SFace_handle;
typedef typename SM_decorator::SVertex_const_handle
SVertex_const_handle;
typedef typename SM_decorator::SHalfedge_const_handle
SHalfedge_const_handle;
typedef typename SM_decorator::SHalfloop_const_handle
SHalfloop_const_handle;
typedef typename SM_decorator::SFace_const_handle
SFace_const_handle;
typedef typename SNC_decorator::Vertex_iterator Vertex_iterator;
typedef typename SNC_decorator::Halfedge_iterator
Halfedge_iterator;
typedef typename SNC_decorator::Halffacet_iterator
Halffacet_iterator;
typedef typename SNC_structure::Shell_entry_iterator
Shell_entry_iterator;
typedef typename SNC_decorator::Volume_iterator Volume_iterator;
typedef typename SNC_structure::Vertex_const_iterator
Vertex_const_iterator;
typedef typename SNC_structure::Halfedge_const_iterator
Halfedge_const_iterator;
typedef typename SNC_structure::Halffacet_const_iterator
Halffacet_const_iterator;
typedef typename SNC_structure::Volume_const_iterator
Volume_const_iterator;
typedef typename SNC_structure::Shell_entry_const_iterator
Shell_entry_const_iterator;
typedef typename SM_decorator::SVertex_iterator SVertex_iterator;
typedef typename SM_decorator::SHalfedge_iterator
SHalfedge_iterator;
typedef typename SM_decorator::SHalfloop_iterator
SHalfloop_iterator;
typedef typename SM_decorator::SFace_iterator SFace_iterator;
typedef typename SM_decorator::SVertex_const_iterator
SVertex_const_iterator;
typedef typename SM_decorator::SHalfedge_const_iterator
SHalfedge_const_iterator;
typedef typename SM_decorator::SHalfloop_const_iterator
SHalfloop_const_iterator;
typedef typename SM_decorator::SFace_const_iterator
SFace_const_iterator;
typedef typename SNC_decorator::SFace_cycle_const_iterator
SFace_cycle_const_iterator;
typedef typename SNC_decorator::Association Association;
protected:
void initialize_infibox_vertices(Content space) {
SNC_constructor C(snc());
Infi_box::initialize_infibox_vertices(C, space == COMPLETE);
}
void check_h_for_intersection_of_12_cube_edges_and_add_vertices
(const Plane_3& p);
void create_intersection_vertex_of_h_and_e();
void init_cube_vertices_depending_on_h(const Plane_3& p);
void add_h_to_local_view_of_v();
public:
void build_external_structure() {
SNC_external_structure es(snc(), pl());
es.build_external_structure();
}
public:
/*{\Mcreation 3}*/
Nef_polyhedron_3( Content space = EMPTY);
/*{\Mcreate creates an instance |\Mvar| of type |\Mname|
and initializes it to the empty set if |space == EMPTY|
and to the whole space if |space == COMPLETE|.}*/
explicit Nef_polyhedron_3(const Plane_3& p, Boundary b = INCLUDED);
/*{\Mcreate creates a Nef polyhedron |\Mvar| containing the
halfspace on the negative side of |p| including |p| if |b==INCLUDED|,
excluding |p| if |b==EXCLUDED|.}*/
Nef_polyhedron_3(const Nef_polyhedron_3<Kernel,Items, Mark>& N1)
: Base(N1) , SNC_const_decorator() {
set_snc(snc());
}
Nef_polyhedron_3& operator=(const Nef_polyhedron_3<Kernel,Items, Mark>& N1) {
Base::operator=(N1);
set_snc(snc());
return (*this);
}
~Nef_polyhedron_3() {
CGAL_NEF_TRACEN("~Nef_polyhedron_3: destructor called for snc "<<&snc()<<
", pl "<<pl());
}
// RO: "vertex cycle to Nef" constructor (main part)
// II input iterator; KN kernel of normal (may differ from Nef kernel)
template <class II, class KN>
Nef_polyhedron_3 (II v_first, II v_last,
const CGAL::Vector_3<KN> &normal, bool verb = false)
{ CGAL_NEF_TRACEN("construction from vertex cycle (main part)");
// project and triangulate vertices,
// convert result to Nef_polyhedron
CGAL_precondition (!CGAL::is_empty_range (v_first, v_last));
bool is_nef = vertex_cycle_to_nef_3<Nef_polyhedron> (snc(),
v_first, v_last, normal, verb);
if (is_nef)
{
// TO DO:
// Wie kann der eigene point_locator pl() eingebunden werden?
// Wie kann der Konstruktor umgangen werden?
typedef CGAL::SNC_point_locator_by_spatial_subdivision
<CGAL::SNC_decorator<SNC_structure> > Point_locator;
Point_locator Pl;
SNC_external_structure es(snc(), &Pl);
es.build_external_structure();
*this = Nef_polyhedron(snc(), &Pl);
}
else
{ *this = Nef_polyhedron();
}
set_snc (snc());
CGAL_expensive_postcondition (is_valid());
}
// RO: "vertex cycle to Nef" constructor (normal computation)
template <class II>
Nef_polyhedron_3 (II v_first, II v_last, bool verb = false)
{ CGAL_NEF_TRACEN("construction from vertex cycle (normal computation)");
// compute normal vector
CGAL_precondition (!CGAL::is_empty_range (v_first, v_last));
CGAL::Vector_3<typename II::value_type::R> normal;
normal_vector_newell_3 (v_first, v_last, normal);
// call "main" constructor
*this = Nef_polyhedron_3 (v_first, v_last, normal, verb);
set_snc (snc());
}
template<typename Items, typename SNC_structure>
class Sphere_map_creator {
typedef typename SNC_structure::SM_decorator SM_decorator;
typedef typename SNC_structure::Vertex_handle Vertex_handle;
typedef typename SNC_structure::SVertex_handle SVertex_handle;
typedef typename SNC_structure::SFace_handle SFace_handle;
typedef typename SNC_structure::Sphere_point Sphere_point;
public:
Sphere_map_creator() {}
template<typename point_iterator>
void create_end_sphere_map(SNC_structure& snc,
point_iterator cur,
point_iterator prev) {
Vertex_handle v(snc.new_vertex(*cur, true));
SM_decorator SM(&*v);
SVertex_handle sv(v->new_svertex(Sphere_point(ORIGIN+(*prev-*cur)),
true));
SFace_handle sf(v->new_sface());
SM.link_as_isolated_vertex(sv,sf);
}
template<typename point_iterator>
void create_sphere_map(SNC_structure& snc,
point_iterator cur,
point_iterator prev,
point_iterator next) {
Vertex_handle v(snc.new_vertex(*cur, true));
SM_decorator SM(&*v);
SVertex_handle sv1(v->new_svertex(Sphere_point(ORIGIN+(*prev-*cur)),
true));
SVertex_handle sv2(v->new_svertex(Sphere_point(ORIGIN+(*next-*cur)),
true));
SFace_handle sf(v->new_sface());
SM.link_as_isolated_vertex(sv1,sf);
SM.link_as_isolated_vertex(sv2,sf);
}
};
template<typename SNC_structure>
class Sphere_map_creator<CGAL::SNC_indexed_items, SNC_structure> {
typedef typename SNC_structure::SM_decorator SM_decorator;
typedef typename SNC_structure::Vertex_handle Vertex_handle;
typedef typename SNC_structure::SVertex_handle SVertex_handle;
typedef typename SNC_structure::SFace_handle SFace_handle;
typedef typename SNC_structure::Sphere_point Sphere_point;
bool first;
int index;
public:
Sphere_map_creator() : first(true), index(0) {}
template<typename point_iterator>
void create_end_sphere_map(SNC_structure& snc,
point_iterator cur,
point_iterator prev) {
Vertex_handle v(snc.new_vertex(*cur, true));
SM_decorator SM(&*v);
SVertex_handle sv(v->new_svertex(Sphere_point(ORIGIN+(*prev-*cur)),
true));
SFace_handle sf(v->new_sface());
SM.link_as_isolated_vertex(sv,sf);
if(first) {
sv->set_index();
index = sv->get_index();
first = false;
} else
sv->set_index(index);
}
template<typename point_iterator>
void create_sphere_map(SNC_structure& snc,
point_iterator cur,
point_iterator prev,
point_iterator next) {
Vertex_handle v(snc.new_vertex(*cur, true));
SM_decorator SM(&*v);
SVertex_handle sv1(v->new_svertex(Sphere_point(ORIGIN+(*prev-*cur)),
true));
SVertex_handle sv2(v->new_svertex(Sphere_point(ORIGIN+(*next-*cur)),
true));
SFace_handle sf(v->new_sface());
SM.link_as_isolated_vertex(sv1,sf);
SM.link_as_isolated_vertex(sv2,sf);
sv1->set_index(index);
sv2->set_index();
index = sv2->get_index();
}
};
template <typename InputIterator>
Nef_polyhedron_3(InputIterator begin, InputIterator end, Polylines_tag) {
typedef typename std::iterator_traits<InputIterator>::value_type
point_iterator_pair;
typedef typename point_iterator_pair::first_type
point_iterator;
empty_rep();
set_snc(snc());
initialize_infibox_vertices(EMPTY);
point_iterator pbegin, pend, pnext, pprev;
Sphere_map_creator<Items, SNC_structure> smc;
for(;begin != end; ++begin) {
pend = begin->second;
pprev = pnext = pbegin = begin->first;
++pnext;
CGAL_assertion(pnext != pend);
smc.create_end_sphere_map(snc(),pbegin,pnext);
for(++pbegin,++pnext; pnext!=pend; ++pbegin,++pprev,++pnext)
smc.create_sphere_map(snc(),pbegin,pprev,pnext);
smc.create_end_sphere_map(snc(),pbegin,pprev);
}
build_external_structure();
simplify();
}
explicit
Nef_polyhedron_3(const Segment_3& s) {
empty_rep();
set_snc(snc());
initialize_infibox_vertices(EMPTY);
Sphere_map_creator<Items, SNC_structure> smc;
std::vector<Point_3> endpoints(2);
endpoints[0]=s.source();
endpoints[1]=s.target();
smc.create_end_sphere_map(snc(),&endpoints[0],&endpoints[1]);
smc.create_end_sphere_map(snc(),&endpoints[1],&endpoints[0]);
build_external_structure();
simplify();
}
template <typename InputIterator>
Nef_polyhedron_3(InputIterator begin, InputIterator end, Points_tag) {
empty_rep();
set_snc(snc());
initialize_infibox_vertices(EMPTY);
for(InputIterator it=begin; it!=end;++it)
{
Vertex_handle v(snc().new_vertex(*it, true));
SM_decorator SM(&*v);
v->new_sface();
}
build_external_structure();
simplify();
}
explicit
Nef_polyhedron_3(const Point_3& p) {
empty_rep();
set_snc(snc());
initialize_infibox_vertices(EMPTY);
Vertex_handle v(snc().new_vertex(p, true));
SM_decorator SM(&*v);
v->new_sface();
build_external_structure();
simplify();
}
template <class T1, class T2,
template <class T31, class T32, class T33>
class T3, class T4 >
Nef_polyhedron_3( CGAL::Polyhedron_3<T1,T2,T3,T4>& P) {
CGAL_NEF_TRACEN("construction from Polyhedron_3");
SNC_structure rsnc;
*this = Nef_polyhedron_3(rsnc, new SNC_point_locator_default, false);
initialize_infibox_vertices(EMPTY);
polyhedron_3_to_nef_3
<CGAL::Polyhedron_3<T1,T2,T3,T4>, SNC_structure>( P, snc());
build_external_structure();
simplify();
CGAL::Mark_bounded_volumes<Nef_polyhedron_3> mbv(true);
delegate(mbv);
set_snc(snc());
}
template <class PolygonMesh>
explicit Nef_polyhedron_3(const PolygonMesh& pm) {
CGAL_NEF_TRACEN("construction from PolygonMesh with internal index maps");
SNC_structure rsnc;
*this = Nef_polyhedron_3(rsnc, new SNC_point_locator_default, false);
initialize_infibox_vertices(EMPTY);
polygon_mesh_to_nef_3<PolygonMesh, SNC_structure>(const_cast<PolygonMesh&>(pm), snc());
build_external_structure();
simplify();
CGAL::Mark_bounded_volumes<Nef_polyhedron_3> mbv(true);
delegate(mbv);
set_snc(snc());
}
template <class PolygonMesh, class HalfedgeIndexMap, class FaceIndexMap>
explicit Nef_polyhedron_3(const PolygonMesh& pm,
const HalfedgeIndexMap& him,
const FaceIndexMap& fim,
typename boost::disable_if <
boost::is_same<FaceIndexMap, bool>
>::type* = NULL // disambiguate with another constructor
)
{
CGAL_NEF_TRACEN("construction from PolygonMesh");
SNC_structure rsnc;
*this = Nef_polyhedron_3(rsnc, new SNC_point_locator_default, false);
initialize_infibox_vertices(EMPTY);
polygon_mesh_to_nef_3<PolygonMesh, SNC_structure>(const_cast<PolygonMesh&>(pm), snc(), fim, him);
build_external_structure();
simplify();
CGAL::Mark_bounded_volumes<Nef_polyhedron_3> mbv(true);
delegate(mbv);
set_snc(snc());
}
Nef_polyhedron_3(const Nef_polyhedron& N,
SFace_const_iterator sf)
{
SNC_structure rsnc;
*this = Nef_polyhedron_3(rsnc, new SNC_point_locator_default, false);
initialize_infibox_vertices(EMPTY);
shell_to_nef_3(N, sf, snc());
build_external_structure();
simplify();
CGAL::Mark_bounded_volumes<Nef_polyhedron_3> mbv(true);
delegate(mbv);
set_snc(snc());
}
protected:
template<typename Kernel>
class Triangulation_handler2 {
typedef typename CGAL::Triangulation_vertex_base_2<Kernel> Vb;
typedef typename CGAL::Constrained_triangulation_face_base_2<Kernel> Fb;
typedef typename CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
typedef typename CGAL::Constrained_triangulation_2<Kernel,TDS> CT;
typedef typename CT::Face_handle Face_handle;
typedef typename CT::Vertex_handle CTVertex_handle;
typedef typename CT::Finite_faces_iterator Finite_face_iterator;
typedef typename CT::Edge Edge;
CT ct;
CGAL::Unique_hash_map<Face_handle, bool> visited;
CGAL::Unique_hash_map<CTVertex_handle, Vertex_const_handle> ctv2v;
Finite_face_iterator fi;
Plane_3 supporting_plane;
public:
Triangulation_handler2(Halffacet_const_handle f) :
visited(false), supporting_plane(f->plane()) {
Halffacet_cycle_const_iterator fci;
for(fci=f->facet_cycles_begin(); fci!=f->facet_cycles_end(); ++fci) {
if(fci.is_shalfedge()) {
SHalfedge_around_facet_const_circulator sfc(fci), send(sfc);
CGAL_For_all(sfc,send) {
CGAL_NEF_TRACEN(" insert point" << sfc->source()->source()->point());
CTVertex_handle ctv = ct.insert(sfc->source()->source()->point());
ctv2v[ctv] = sfc->source()->source();
}
}
}
for(fci=f->facet_cycles_begin(); fci!=f->facet_cycles_end(); ++fci) {
if(fci.is_shalfedge()) {
SHalfedge_around_facet_const_circulator sfc(fci), send(sfc);
CGAL_For_all(sfc,send) {
CGAL_NEF_TRACEN(" insert constraint" << sfc->source()->source()->point()
<< "->" << sfc->source()->twin()->source()->point());
ct.insert_constraint(sfc->source()->source()->point(),
sfc->source()->twin()->source()->point());
}
}
}
CGAL_assertion(ct.is_valid());
CGAL_NEF_TRACEN("number of finite triangles " << ct.number_of_faces());
typename CT::Face_handle infinite = ct.infinite_face();
typename CT::Vertex_handle ctv = infinite->vertex(1);
if(ct.is_infinite(ctv)) ctv = infinite->vertex(2);
CGAL_assertion(!ct.is_infinite(ctv));
typename CT::Face_handle opposite;
typename CT::Face_circulator vc(ctv,infinite);
do { opposite = vc++;
} while(!ct.is_constrained(typename CT::Edge(vc,vc->index(opposite))));
typename CT::Face_handle first = vc;
CGAL_assertion(!ct.is_infinite(first));
traverse_triangulation(first, first->index(opposite));
fi = ct.finite_faces_begin();
}
void traverse_triangulation(Face_handle f, int parent) {
visited[f] = true;
if(!ct.is_constrained(Edge(f,ct.cw(parent))) && !visited[f->neighbor(ct.cw(parent))]) {
Face_handle child(f->neighbor(ct.cw(parent)));
traverse_triangulation(child, child->index(f));
}
if(!ct.is_constrained(Edge(f,ct.ccw(parent))) && !visited[f->neighbor(ct.ccw(parent))]) {
Face_handle child(f->neighbor(ct.ccw(parent)));
traverse_triangulation(child, child->index(f));
}
}
template<typename Triangle_3>
bool get_next_triangle(Triangle_3& tr) {
while(fi != ct.finite_faces_end() && visited[fi] == false) ++fi;
if(fi == ct.finite_faces_end()) return false;
tr = Triangle_3(fi->vertex(0)->point(), fi->vertex(1)->point(), fi->vertex(2)->point());
++fi;
return true;
}
bool same_orientation(Plane_3 p1) const {
if(p1.a() != 0)
return CGAL::sign(p1.a()) == CGAL::sign(supporting_plane.a());
if(p1.b() != 0)
return CGAL::sign(p1.b()) == CGAL::sign(supporting_plane.b());
return CGAL::sign(p1.c()) == CGAL::sign(supporting_plane.c());
}
template<typename PIB, typename Index>
void handle_triangles(PIB& pib, Index& VI) {
while(fi != ct.finite_faces_end() && visited[fi] == false) ++fi;
while(fi != ct.finite_faces_end()) {
Plane_3 plane(fi->vertex(0)->point(),
fi->vertex(1)->point(),
fi->vertex(2)->point());
pib.begin_facet();
if(same_orientation(plane)) {
pib.add_vertex_to_facet(VI[ctv2v[fi->vertex(0)]]);
pib.add_vertex_to_facet(VI[ctv2v[fi->vertex(1)]]);
pib.add_vertex_to_facet(VI[ctv2v[fi->vertex(2)]]);
} else {
pib.add_vertex_to_facet(VI[ctv2v[fi->vertex(0)]]);
pib.add_vertex_to_facet(VI[ctv2v[fi->vertex(2)]]);
pib.add_vertex_to_facet(VI[ctv2v[fi->vertex(1)]]);
}
pib.end_facet();
do {
++fi;
} while(fi != ct.finite_faces_end() && visited[fi] == false);
}
}
};
template <class HDS>
class Build_polyhedron : public CGAL::Modifier_base<HDS> {
class Visitor {
typedef typename CGAL::Projection_traits_xy_3<Kernel> XY;
typedef typename CGAL::Projection_traits_yz_3<Kernel> YZ;
typedef typename CGAL::Projection_traits_xz_3<Kernel> XZ;
const Object_index<Vertex_const_iterator>& VI;
Polyhedron_incremental_builder_3<HDS>& B;
const SNC_const_decorator& D;
public:
Visitor(Polyhedron_incremental_builder_3<HDS>& BB,
const SNC_const_decorator& sd,
Object_index<Vertex_const_iterator>& vi) : VI(vi), B(BB), D(sd){}
void visit(Halffacet_const_handle opposite_facet) {
CGAL_NEF_TRACEN("Build_polyhedron: visit facet " << opposite_facet->plane());
CGAL_assertion(Infi_box::is_standard(opposite_facet->plane()));
SHalfedge_const_handle se;
Halffacet_cycle_const_iterator fc;
Halffacet_const_handle f = opposite_facet->twin();
SHalfedge_around_facet_const_circulator
sfc1(f->facet_cycles_begin()), sfc2(sfc1);
if(++f->facet_cycles_begin() != f->facet_cycles_end() ||
++(++(++sfc1)) != sfc2) {
Vector_3 orth = f->plane().orthogonal_vector();
int c = CGAL::abs(orth[0]) > CGAL::abs(orth[1]) ? 0 : 1;
c = CGAL::abs(orth[2]) > CGAL::abs(orth[c]) ? 2 : c;
if(c == 0) {
Triangulation_handler2<YZ> th(f);
th.handle_triangles(B, VI);
} else if(c == 1) {
Triangulation_handler2<XZ> th(f);
th.handle_triangles(B, VI);
} else if(c == 2) {
Triangulation_handler2<XY> th(f);
th.handle_triangles(B, VI);
} else
CGAL_error_msg( "wrong value");
} else {
B.begin_facet();
fc = f->facet_cycles_begin();
se = SHalfedge_const_handle(fc);
CGAL_assertion(se!=0);
SHalfedge_around_facet_const_circulator hc_start(se);
SHalfedge_around_facet_const_circulator hc_end(hc_start);
CGAL_For_all(hc_start,hc_end) {
CGAL_NEF_TRACEN(" add vertex " << hc_start->source()->center_vertex()->point());
B.add_vertex_to_facet(VI[hc_start->source()->center_vertex()]);
}
B.end_facet();
}
}
void visit(SFace_const_handle) {}
void visit(Halfedge_const_handle) {}
void visit(Vertex_const_handle) {}
void visit(SHalfedge_const_handle) {}
void visit(SHalfloop_const_handle) {}
};
public:
const SNC_const_decorator& scd;
Object_index<Vertex_const_iterator> VI;
Build_polyhedron(const SNC_const_decorator& s) :
scd(s), VI(s.vertices_begin(),s.vertices_end(),'V') {}
void operator()( HDS& hds) {
Polyhedron_incremental_builder_3<HDS> B(hds, true);
int skip_volumes;
if(Infi_box::extended_kernel()) {
B.begin_surface(scd.number_of_vertices()-8,
scd.number_of_facets()-6,
scd.number_of_edges()-12);
skip_volumes = 2;
}
else {
B.begin_surface(scd.number_of_vertices(),
2*scd.number_of_vertices()-4,
3*scd.number_of_vertices()-6);
skip_volumes = 1;
}
int vertex_index = 0;
Vertex_const_iterator v;
CGAL_forall_vertices(v,scd) {
if(Infi_box::is_standard(v->point())) {
VI[v]=vertex_index++;
B.add_vertex(v->point());
}
}
Visitor V(B,scd,VI);
Volume_const_handle c;
CGAL_forall_volumes(c,scd)
if(skip_volumes-- <= 0)
scd.visit_shell_objects(SFace_const_handle(c->shells_begin()),V);
B.end_surface();
if ( B.error() ) B.rollback();
}
};
template <class HDS>
class Build_polyhedron2 : public CGAL::Modifier_base<HDS> {
class Find_holes {
Unique_hash_map<Vertex_const_handle, bool>& omit_vertex;
int nov, nof;
public:
Find_holes(Unique_hash_map<Vertex_const_handle, bool>& omit_vertex_)
: omit_vertex(omit_vertex_), nov(0), nof(0) {}
void visit(Halffacet_const_handle f) {
++nof;
Halffacet_cycle_const_iterator fc = f->facet_cycles_begin();
for(++fc; fc != f->facet_cycles_end(); ++fc) {
if(fc.is_shalfedge()) {
--nof;
SHalfedge_around_facet_const_circulator
sfc(fc), send(sfc);
CGAL_For_all(sfc, send) {
omit_vertex[sfc->source()->source()] = true;
--nov;
}
} else if(fc.is_shalfloop()) {
SHalfloop_const_handle sl(fc);
omit_vertex[sl->incident_sface()->center_vertex()];
--nov;
} else
CGAL_error_msg( "wrong handle type");
}
}
void visit(Vertex_const_handle) { ++nov; }
void visit(SFace_const_handle) {}
void visit(Halfedge_const_handle) {}
void visit(SHalfedge_const_handle) {}
void visit(SHalfloop_const_handle) {}
int number_of_vertices() const {
return nov;
}
int number_of_facets() const {
return nof;
}
};
class Add_vertices {
Polyhedron_incremental_builder_3<HDS>& B;
Unique_hash_map<Vertex_const_handle, bool>& omit_vertex;
Object_index<Vertex_const_iterator>& VI;
int vertex_index;
public:
Add_vertices(Polyhedron_incremental_builder_3<HDS>& B_,
Unique_hash_map<Vertex_const_handle, bool>& omit_vertex_,
Object_index<Vertex_const_iterator>& VI_)
: B(B_), omit_vertex(omit_vertex_), VI(VI_), vertex_index(0) {}
void visit(Vertex_const_handle v) {
if(omit_vertex[v]) return;
VI[v]=vertex_index++;
B.add_vertex(v->point());
}
void visit(Halffacet_const_handle) {}
void visit(SFace_const_handle) {}
void visit(Halfedge_const_handle) {}
void visit(SHalfedge_const_handle) {}
void visit(SHalfloop_const_handle) {}
};
class Visitor {
const Object_index<Vertex_const_iterator>& VI;
Polyhedron_incremental_builder_3<HDS>& B;
const Unique_hash_map<Vertex_const_handle, bool>& omit_vertex;
SNC_const_decorator& D;
public:
Visitor(Polyhedron_incremental_builder_3<HDS>& BB,
const Unique_hash_map<Vertex_const_handle, bool>& omit_vertex_,
SNC_const_decorator& sd,
Object_index<Vertex_const_iterator>& vi)
: VI(vi), B(BB), omit_vertex(omit_vertex_), D(sd){}
void visit(Halffacet_const_handle opposite_facet) {
CGAL_NEF_TRACEN("Build_polyhedron: visit facet " << opposite_facet->plane());
CGAL_assertion(Infi_box::is_standard(opposite_facet->plane()));
SHalfedge_const_handle se;
Halffacet_cycle_const_iterator fc;
Halffacet_const_handle f = opposite_facet->twin();
fc = f->facet_cycles_begin();
se = SHalfedge_const_handle(fc);
CGAL_assertion(se!=0);
if(omit_vertex[se->source()->source()]) return;
B.begin_facet();
SHalfedge_around_facet_const_circulator hc_start(se);
SHalfedge_around_facet_const_circulator hc_end(hc_start);
CGAL_For_all(hc_start,hc_end) {
CGAL_NEF_TRACEN(" add vertex " << hc_start->source()->center_vertex()->point());
B.add_vertex_to_facet(VI[hc_start->source()->center_vertex()]);
}
B.end_facet();
}
void visit(SFace_const_handle) {}
void visit(Halfedge_const_handle) {}
void visit(Vertex_const_handle) {}
void visit(SHalfedge_const_handle) {}
void visit(SHalfloop_const_handle) {}
};
public:
SFace_const_handle sf;
SNC_const_decorator& scd;
Object_index<Vertex_const_iterator> VI;
Unique_hash_map<Vertex_const_handle, bool> omit_vertex;
Build_polyhedron2(SFace_const_handle sf_, SNC_const_decorator& s) :
sf(sf_), scd(s), VI(s.vertices_begin(),s.vertices_end(),'V'),
omit_vertex(false) {}
void operator()(HDS& hds) {
Polyhedron_incremental_builder_3<HDS> B(hds, true);
Find_holes F(omit_vertex);
scd.visit_shell_objects(sf, F);
B.begin_surface(F.number_of_vertices(),
F.number_of_facets(),
F.number_of_vertices()+F.number_of_facets()-2);
Add_vertices A(B,omit_vertex, VI);
scd.visit_shell_objects(sf, A);
Visitor V(B,omit_vertex, scd,VI);
scd.visit_shell_objects(sf, V);
B.end_surface();
if ( B.error() ) B.rollback();
}
};
public:
void delegate( Modifier_base<SNC_structure>& modifier,
bool compute_external = false,
bool do_simplify = true) {
// calls the `operator()' of the `modifier'. Precondition: The
// `modifier' returns a consistent representation.
if( this->is_shared()) clone_rep();
modifier(snc());
if(compute_external) {
SNC_external_structure es(snc());
es.clear_external_structure();
build_external_structure();
}
if(do_simplify)
simplify();
CGAL_expensive_postcondition( is_valid());
}
struct SNC_and_PL {
SNC_structure* sncp;
SNC_point_locator* pl;
SNC_and_PL(SNC_structure* s, SNC_point_locator* p) : sncp(s), pl(p) {}
};
void delegate( Modifier_base<SNC_and_PL>& modifier,
bool compute_external = false,
bool do_simplify = false) {
// calls the `operator()' of the `modifier'. Precondition: The
// `modifier' returns a consistent representation.
if( this->is_shared()) clone_rep();
SNC_and_PL sncpl(&snc(),pl());
modifier(sncpl);
pl() = sncpl.pl;
if(compute_external) {
SNC_external_structure es(snc());
es.clear_external_structure();
build_external_structure();
}
if(do_simplify)
simplify();
CGAL_expensive_postcondition( is_valid());
}
public:
template<typename Polyhedron>
void convert_to_Polyhedron(Polyhedron& P) const {
convert_to_polyhedron(P);
}
template<typename Polyhedron>
void convert_to_polyhedron(Polyhedron& P) const {
typedef typename Polyhedron::HalfedgeDS HalfedgeDS;
CGAL_precondition(is_simple());
P.clear();
Build_polyhedron<HalfedgeDS> bp(*this);
P.delegate(bp);
}
template<typename Polyhedron>
void convert_inner_shell_to_polyhedron(SFace_const_iterator sf, Polyhedron& P) {
typedef typename Polyhedron::HalfedgeDS HalfedgeDS;
P.clear();
Build_polyhedron2<HalfedgeDS> bp(sf, *this);
P.delegate(bp);
}
bool is_valid( bool verb = false, int level = 0) {
// checks the combinatorial consistency.
Verbose_ostream verr(verb);
verr << "begin CGAL::Nef_polyhedron_3<...>::is_valid( verb=true, "
"level = " << level << "):" << std::endl;
SNC_decorator D(snc());
bool valid = D.is_valid(verb, level);
verr << "end of CGAL::Nef_polyhedron_3<...>::is_valid(): structure is "
<< ( valid ? "valid." : "NOT VALID.") << std::endl;
return valid;
}
bool is_simple() const {
Halfedge_const_iterator e;
CGAL_forall_edges(e,snc())
if(!is_edge_2manifold(e))
return false;
CGAL_NEF_TRACEN("there is no edge with non-manifold situation");
Vertex_const_iterator v;
CGAL_forall_vertices(v,snc())
if(!is_vertex_2manifold(v))
return false;
CGAL_NEF_TRACEN("there is no vertex with non-manifold situation");
/*
Halffacet_iterator f;
CGAL_forall_halffacets(f,snc())
if(!is_facet_simple(f))
return false;
CGAL_NEF_TRACEN("there are no holes");
*/
return true;
}
bool is_convex() const {
Vertex_const_iterator v;
CGAL_forall_vertices(v, *this) {
SM_const_decorator SD(&*v);
if(std::distance(SD.sfaces_begin(),SD.sfaces_end())!=2)
return false;
if(!Infi_box::is_standard(v->point())) continue;
SFace_const_iterator sf;
CGAL_forall_sfaces(sf,SD) {
if(sf->volume() == Infi_box::getNirvana(snc())) continue;
if(std::distance(sf->sface_cycles_begin(),sf->sface_cycles_end())!=1)
return false;
SFace_cycle_const_iterator sfi(sf->sface_cycles_begin());
if(!sfi.is_shalfedge())
return false;
SHalfedge_const_handle se(sf->sface_cycles_begin());
SHalfedge_around_sface_const_circulator sec(se),send(sec);
CGAL_For_all(sec,send)
if(spherical_orientation(sec->source()->point(),
sec->snext()->source()->point(),
sec->snext()->snext()->source()->point())<0) {
std::cerr << "vertex at " << v->point() << " is not convex" << std::endl;
return false;
}
}
}
return true;
}
private:
bool is_edge_2manifold(const Halfedge_const_handle& e) const {
SM_decorator SD;
SHalfedge_around_svertex_const_circulator c(SD.first_out_edge(e)), c2(c);
if(c == 0) {
CGAL_assertion(circulator_size(c) !=2);
return false;
}
if(++c == c2){
CGAL_assertion(circulator_size(c) !=2);
return false;
}
if(++c != c2) {
CGAL_assertion(circulator_size(c) !=2);
return false;
}
CGAL_assertion(circulator_size(c) == 2);
return true;
}
bool is_vertex_2manifold(const Vertex_const_handle& v) const {
SFace_const_iterator sfi(v->sfaces_begin());
if (++sfi != v->sfaces_last())
return false;
return true;
}
bool is_facet_simple(const Halffacet_const_handle& f) const {
bool found_first = false;
Halffacet_cycle_const_iterator it;
CGAL_forall_facet_cycles_of(it,f)
if (found_first || !it.is_shalfedge())
return false;
else
found_first = true;
return true;
}
public:
void clear(Content space = EMPTY)
{ *this = Nef_polyhedron_3(space); }
/*{\Mop makes |\Mvar| the empty set if |space == EMPTY| and the
full space if |space == COMPLETE|.}*/
bool is_empty() const {
/*{\Mop returns true if |\Mvar| is empty, false otherwise.}*/
if(Infi_box::extended_kernel())
return this->number_of_vertices() == 8 &&
this->number_of_edges() == 12 &&
this->number_of_facets() == 6 &&
this->number_of_volumes() == 2 &&
(++this->volumes_begin())->mark() == false;
else
return this->number_of_vertices() == 0 &&
this->number_of_edges() == 0 &&
this->number_of_facets() == 0 &&
this->number_of_volumes() == 1 &&
(this->volumes_begin())->mark() == false;
}
bool is_space() const {
/*{\Mop returns true if |\Mvar| is the whole space, false otherwise.}*/
if(Infi_box::extended_kernel())
return this->number_of_vertices() == 8 &&
this->number_of_edges() == 12 &&
this->number_of_facets() == 6 &&
this->number_of_volumes() == 2 &&
(++this->volumes_begin())->mark() == true;
else
return this->number_of_vertices() == 0 &&
this->number_of_edges() == 0 &&
this->number_of_facets() == 0 &&
this->number_of_volumes() == 1 &&
(this->volumes_begin())->mark() == true;
}
/*{\Xtext \headerline{Destructive Operations}}*/
protected:
void clone_rep() { *this = Nef_polyhedron_3<Kernel,Items, Mark>(snc(), pl()); }
void empty_rep() {
SNC_structure rsnc;
delete pl();
*this = Nef_polyhedron_3<Kernel,Items, Mark>(rsnc, new SNC_point_locator_default,false);
}
public:
Nef_polyhedron_3( const SNC_structure& W,
SNC_point_locator* _pl = new SNC_point_locator_default,
bool clone_pl = true,
bool clone_snc = true);
/*{\Xcreate makes |\Mvar| a new object. If |cloneit==true| then the
underlying structure of |W| is copied into |\Mvar|.}*/
// TODO: granados: define behavior when clone=false
/*{\Moperations 4 3 }*/
void simplify() {
SNC_simplify simp(snc());
bool simplified = simp.simplify();
CGAL_NEF_TRACEN( "simplify(): structure simplified? "<<simplified);
if( simplified) {
#ifdef CGAL_NEF3_UPDATE_K3TREE_AFTER_SIMPLIFICATION
/*debug*/ snc().print_statistics();
Unique_hash_map<Vertex_handle, bool>
V(false, snc().number_of_vertices());
Unique_hash_map<Halfedge_handle, bool>
E(false, snc().number_of_halfedges());
Unique_hash_map<Halffacet_handle, bool>
F(false, snc().number_of_halffacets());
Vertex_iterator v;
Halfedge_iterator e;
Halffacet_iterator f;
CGAL_forall_vertices( v, snc()) V[Vertex_handle(v)] = true;
CGAL_forall_halfedges( e, snc()) E[Halfedge_handle(e)] = true;
CGAL_forall_halffacets( f, snc()) F[Halffacet_handle(f)] = true;
bool updated = pl()->update( V, E, F);
CGAL_NEF_TRACEN("simplify(): point locator structure updated? " << updated);
#else
SNC_point_locator* old_pl = pl();
pl() = pl()->clone();
pl()->initialize(&snc());
delete old_pl;
#endif
}
}
public:
Nef_polyhedron_S2 get_sphere_map(Vertex_const_handle v) const {
return Nef_polyhedron_S2(*v);
}
void extract_complement();
/*{\Xop converts |\Mvar| to its complement. }*/
void extract_interior();
/*{\Xop converts |\Mvar| to its interior. }*/
void extract_boundary();
/*{\Xop converts |\Mvar| to its boundary. }*/
void extract_closure()
/*{\Xop converts |\Mvar| to its closure. }*/
{ CGAL_NEF_TRACEN("extract closure");
if( this->is_shared()) clone_rep();
extract_complement();
extract_interior();
extract_complement();
}
void extract_regularization()
/*{\Xop converts |\Mvar| to its regularization. }*/
{ CGAL_NEF_TRACEN("extract regularization");
if( this->is_shared()) clone_rep();
extract_interior();
extract_closure();
}
/*{\Mtext \headerline{Constructive Operations}}*/
Nef_polyhedron_3<Kernel,Items, Mark> complement() const
/*{\Mop returns the complement of |\Mvar| in the plane. }*/
{ Nef_polyhedron_3<Kernel,Items, Mark> res = *this;
res.extract_complement();
return res;
}
Nef_polyhedron_3<Kernel,Items, Mark> interior() const
/*{\Mop returns the interior of |\Mvar|. }*/
{ Nef_polyhedron_3<Kernel,Items, Mark> res = *this;
res.extract_interior();
return res;
}
Nef_polyhedron_3<Kernel,Items, Mark> closure() const
/*{\Mop returns the closure of |\Mvar|. }*/
{ Nef_polyhedron_3<Kernel,Items, Mark> res = *this;
res.extract_closure();
return res;
}
Nef_polyhedron_3<Kernel,Items, Mark> boundary() const
/*{\Mop returns the boundary of |\Mvar|. }*/
{ Nef_polyhedron_3<Kernel,Items, Mark> res = *this;
res.extract_boundary();
return res;
}
Nef_polyhedron_3<Kernel,Items, Mark> regularization() const
/*{\Mop returns the regularized polyhedron (closure of
the interior).}*/
{ Nef_polyhedron_3<Kernel,Items, Mark> res = *this;
res.extract_regularization();
return res;
}
Nef_polyhedron_3<Kernel,Items, Mark>
intersection(const Nef_polyhedron_3<Kernel,Items, Mark>& N1) const
/*{\Mop returns |\Mvar| $\cap$ |N1|. }*/ {
CGAL_NEF_TRACEN(" intersection between nef3 "<<&*this<<" and "<<&N1);
if (is_empty()) return *this;
if (N1.is_empty()) return N1;
if (is_space()) return N1;
if (N1.is_space()) return *this;
AND _and;
SNC_structure rsnc;
Nef_polyhedron_3<Kernel,Items, Mark> res(rsnc, new SNC_point_locator_default, false);
Binary_operation bo( res.snc());
bo(res.pl(), snc(), pl(), N1.snc(), N1.pl(), _and);
return res;
}
Nef_polyhedron_3<Kernel,Items, Mark>
intersection(const Plane_3& plane,
Intersection_mode im) const {
AND _and;
SNC_structure rsnc;
Nef_polyhedron_3<Kernel,Items, Mark> res(rsnc, new SNC_point_locator_default, false);
Combine_with_halfspace cwh(res.snc(), res.pl());
cwh.combine_with_halfspace(snc(), plane, _and,
static_cast<typename Combine_with_halfspace::Intersection_mode>(im));
return res;
}
Nef_polyhedron_3<Kernel,Items, Mark>
join(const Nef_polyhedron_3<Kernel,Items, Mark>& N1) const
/*{\Mop returns |\Mvar| $\cup$ |N1|. }*/ {
CGAL_NEF_TRACEN(" join between nef3 "<<&*this<<" and "<<&N1);
if (is_empty()) return N1;
if (N1.is_empty()) return *this;
if (is_space()) return *this;
if (N1.is_space()) return N1;
OR _or;
//CGAL::binop_intersection_tests_allpairs<SNC_decorator, OR> tests_impl;
SNC_structure rsnc;
Nef_polyhedron_3<Kernel,Items, Mark> res(rsnc, new SNC_point_locator_default, false);
Binary_operation bo(res.snc());
bo(res.pl(), snc(), pl(), N1.snc(), N1.pl(), _or);
return res;
}
Nef_polyhedron_3<Kernel,Items, Mark>
difference(const Nef_polyhedron_3<Kernel,Items, Mark>& N1) const
/*{\Mop returns |\Mvar| $-$ |N1|. }*/ {
CGAL_NEF_TRACEN(" difference between nef3 "<<&*this<<" and "<<&N1);
if (is_empty()) return *this;
if (N1.is_empty()) return *this;
if (is_space()) return N1.complement();
if (N1.is_space()) return Nef_polyhedron_3(EMPTY);
DIFF _diff;
//CGAL::binop_intersection_tests_allpairs<SNC_decorator, DIFF> tests_impl;
SNC_structure rsnc;
Nef_polyhedron_3<Kernel,Items, Mark> res(rsnc, new SNC_point_locator_default, false);
Binary_operation bo(res.snc());
bo(res.pl(), snc(), pl(), N1.snc(), N1.pl(), _diff);
return res;
}
Nef_polyhedron_3<Kernel,Items, Mark>
symmetric_difference(const Nef_polyhedron_3<Kernel,Items, Mark>& N1) const
/*{\Mop returns the symmectric difference |\Mvar - T| $\cup$
|T - \Mvar|. }*/ {
CGAL_NEF_TRACEN(" symmetic difference between nef3 "<<&*this<<" and "<<&N1);
if (is_empty()) return N1;
if (N1.is_empty()) return *this;
if (is_space()) return Nef_polyhedron_3(EMPTY);
if (N1.is_space()) return Nef_polyhedron_3(EMPTY);
XOR _xor;
//CGAL::binop_intersection_tests_allpairs<SNC_decorator, XOR> tests_impl;
SNC_structure rsnc;
Nef_polyhedron_3<Kernel,Items, Mark> res(rsnc, new SNC_point_locator_default, false);
Binary_operation bo(res.snc());
bo(res.pl(), snc(), pl(), N1.snc(), N1.pl(), _xor);
return res;
}
/*{\Mtext Additionally there are operators |*,+,-,^,!| which
implement the binary operations \emph{intersection}, \emph{union},
\emph{difference}, \emph{symmetric difference}, and the unary
operation \emph{complement}. There are also the corresponding
modification operations |*=,+=,-=,^=|.}*/
Nef_polyhedron_3<Kernel,Items, Mark> operator*(const Nef_polyhedron_3<Kernel,Items, Mark>& N1) const
{ return intersection(N1); }
Nef_polyhedron_3<Kernel,Items, Mark> operator+(const Nef_polyhedron_3<Kernel,Items, Mark>& N1) const
{ return join(N1); }
Nef_polyhedron_3<Kernel,Items, Mark> operator-(const Nef_polyhedron_3<Kernel,Items, Mark>& N1) const
{ return difference(N1); }
Nef_polyhedron_3<Kernel,Items, Mark> operator^(const Nef_polyhedron_3<Kernel,Items, Mark>& N1) const
{ return symmetric_difference(N1); }
Nef_polyhedron_3<Kernel,Items, Mark> operator!() const
{ return complement(); }
Nef_polyhedron_3<Kernel,Items, Mark>& operator*=(const Nef_polyhedron_3<Kernel,Items, Mark>& N1)
{
#ifdef CGAL_NEF_VISUAL_HULL
CGAL_NEF_SETDTHREAD(19*43*71);
std::cerr << "visual hull code " << std::endl;
std::cerr << *this << std::endl;
std::cerr << const_cast<Nef_polyhedron&>(N1) << std::endl;
AND _and;
typename CGAL::Modifying_binary_operation<SNC_structure>
mbo(this->snc());
mbo(const_cast<SNC_structure&>(N1.snc()), N1.pl(), pl(), _and);
return *this;
#else
*this = intersection(N1); return *this;
#endif
}
Nef_polyhedron_3<Kernel,Items, Mark>& operator+=(const Nef_polyhedron_3<Kernel,Items, Mark>& N1)
{ *this = join(N1); return *this; }
Nef_polyhedron_3<Kernel,Items, Mark>& operator-=(const Nef_polyhedron_3<Kernel,Items, Mark>& N1)
{ *this = difference(N1); return *this; }
Nef_polyhedron_3<Kernel,Items, Mark>& operator^=(const Nef_polyhedron_3<Kernel,Items, Mark>& N1)
{ *this = symmetric_difference(N1); return *this; }
/*{\Mtext There are also comparison operations like |<,<=,>,>=,==,!=|
which implement the relations subset, subset or equal, superset, superset
or equal, equality, inequality.}*/
bool operator==(const Nef_polyhedron_3<Kernel,Items, Mark>& N1) const
{ CGAL_NEF_TRACEN(" equality comparision between nef3 "<<&*this<<" and "<<&N1);
return symmetric_difference(N1).is_empty(); }
bool operator!=(const Nef_polyhedron_3<Kernel,Items, Mark>& N1) const
{ CGAL_NEF_TRACEN(" inequality comparision between nef3 "<<&*this<<" and "<<&N1);
return !operator==(N1); }
bool operator<(const Nef_polyhedron_3<Kernel,Items, Mark>& N1) const
{ return !N1.difference(*this).is_empty() && difference(N1).is_empty(); }
bool operator>(const Nef_polyhedron_3<Kernel,Items, Mark>& N1) const
{ return difference(*this).is_empty() && !difference(N1).is_empty(); }
bool operator<=(const Nef_polyhedron_3<Kernel,Items, Mark>& N1) const
{ return difference(N1).is_empty(); }
bool operator>=(const Nef_polyhedron_3<Kernel,Items, Mark>& N1) const
{ return N1.difference(*this).is_empty(); }
bool is_90degree_rotation(const Aff_transformation_3& aff) const {
if(aff.hm(0,3) != 0) return false;
if(aff.hm(1,3) != 0) return false;
if(aff.hm(2,3) != 0) return false;
if(CGAL_NTS abs(aff.hm(0,0)) +
CGAL_NTS abs(aff.hm(0,1)) +
CGAL_NTS abs(aff.hm(0,2)) != aff.hm(3,3)) return false;
if(CGAL_NTS abs(aff.hm(1,0)) +
CGAL_NTS abs(aff.hm(1,1)) +
CGAL_NTS abs(aff.hm(1,2)) != aff.hm(3,3)) return false;
if(CGAL_NTS abs(aff.hm(2,0)) +
CGAL_NTS abs(aff.hm(2,1)) +
CGAL_NTS abs(aff.hm(2,2)) != aff.hm(3,3)) return false;
if(CGAL_NTS abs(aff.hm(0,0)) +
CGAL_NTS abs(aff.hm(1,0)) +
CGAL_NTS abs(aff.hm(2,0)) != aff.hm(3,3)) return false;
if(CGAL_NTS abs(aff.hm(0,1)) +
CGAL_NTS abs(aff.hm(1,1)) +
CGAL_NTS abs(aff.hm(2,1)) != aff.hm(3,3)) return false;
if(CGAL_NTS abs(aff.hm(0,2)) +
CGAL_NTS abs(aff.hm(1,2)) +
CGAL_NTS abs(aff.hm(2,2)) != aff.hm(3,3)) return false;
return true;
}
bool is_scaling(const Aff_transformation_3& aff) const {
if(aff.hm(0,3) != 0) return false;
if(aff.hm(1,3) != 0) return false;
if(aff.hm(2,3) != 0) return false;
if(aff.hm(0,1) != 0) return false;
if(aff.hm(0,2) != 0) return false;
if(aff.hm(1,0) != 0) return false;
if(aff.hm(1,2) != 0) return false;
if(aff.hm(2,0) != 0) return false;
if(aff.hm(2,1) != 0) return false;
if(aff.hm(0,0) != aff.hm(1,1)) return false;
if(aff.hm(0,0) != aff.hm(2,2)) return false;
return true;
}
void change_orientation(bool full = false) {
Halffacet_handle ftemp;
Volume_handle vtemp;
SVertex_handle svtemp;
SHalfedge_handle setemp;
SFace_handle sftemp;
SVertex_iterator sv;
CGAL_forall_svertices(sv, snc()) {
if (!sv->is_isolated())
sv->out_sedge() = sv->out_sedge()->twin();
}
SHalfedge_iterator se;
CGAL_forall_shalfedges(se, snc()) {
if(se->is_twin()) {
svtemp = se->source();
se->source() = se->twin()->source();
se->twin()->source() = svtemp;
if(full) {
ftemp = se->facet();
se->facet() = se->twin()->facet();
se->twin()->facet() = ftemp;
}
// sftemp = se->incident_sface();
// se->incident_sface() = se->twin()->incident_sface();
// se->twin()->incident_sface() = sftemp;
}
setemp = se->sprev();
se->sprev() = se->snext();
se->snext() = setemp;
se->circle() = se->circle().opposite();
if(full) {
setemp = se->prev();
se->prev() = se->next();
se->next() = setemp;
}
}
if(full) {
Halffacet_iterator f;
CGAL_forall_facets(f, snc()) {
vtemp = f->incident_volume();
f->incident_volume() = f->twin()->incident_volume();
f->twin()->incident_volume() = vtemp;
Halffacet_cycle_iterator fc(f->facet_cycles_begin()),
fct(f->twin()->facet_cycles_begin());
while(fc!=f->facet_cycles_end()) {
CGAL_assertion(fct!=f->twin()->facet_cycles_end());
if(fc.is_shalfedge()) {
CGAL_assertion(fct.is_shalfedge());
setemp = fc;
*fc = *fct;
*fct = make_object(setemp);
}
++fc;
++fct;
}
}
CGAL_forall_halffacets(f, snc()) {
Halffacet_cycle_iterator fc(f->facet_cycles_begin());
for(;fc!=f->facet_cycles_end();++fc) {
if(fc.is_shalfedge()) {
setemp = fc;
SHalfedge_around_facet_circulator hfc(setemp),hend(hfc);
++hfc;
CGAL_For_all(hfc,hend) {
if ( CGAL::lexicographically_xyz_smaller(hfc->source()->source()->point(),
setemp->source()->source()->point()))
setemp = hfc;
}
*fc = make_object(setemp);
}
}
}
}
}
void transform( const Aff_transformation_3& aff) {
if( this->is_shared())
clone_rep();
// only linear transform for the origin-centered sphere maps
Aff_transformation_3 linear( aff.hm(0,0), aff.hm(0,1), aff.hm(0,2),
aff.hm(1,0), aff.hm(1,1), aff.hm(1,2),
aff.hm(2,0), aff.hm(2,1), aff.hm(2,2),
aff.hm(3,3));
SNC_constructor cstr(snc());
std::list<Vertex_handle> vertex_list;
std::list<Vertex_handle> corner_list;
std::list<Vertex_handle> delete_list;
typename std::list<Vertex_handle>::iterator li;
typename std::list<Vertex_handle>::iterator li2;
bool ninety = is_90degree_rotation(aff);
bool scale = is_scaling(aff);
Vertex_iterator vi;
CGAL_forall_vertices( vi, snc()) {
CGAL_NEF_TRACEN("transform vertex ");
if(scale) {
if(is_standard(vi))
vi->point() = vi->point().transform( aff);
else if(!Infi_box::is_infibox_corner(vi->point())) {
vi->point() = normalized(Infi_box::normalize_transformed_vertex(vi->point().transform(aff)));
}
} else if (!is_standard(vi) && !ninety) {
if(Infi_box::is_infibox_corner(vi->point()))
corner_list.push_back(vi);
vertex_list.push_back(vi);
} else {
vi->point() = vi->point().transform( aff);
SM_decorator sdeco(&*vi);
sdeco.transform( linear);
}
}
if(!this->is_bounded() && !ninety && !scale) {
Halffacet_iterator fi;
CGAL_forall_facets(fi, snc()) {
if(!is_standard(fi) || is_bounded(fi)) continue;
Plane_3 pt = fi->plane();
pt = pt.transform(aff);
std::list<Point_3> points(Infi_box::find_points_of_box_with_plane(cstr,pt));
std::list<Vertex_handle> newVertices;
newVertices = Infi_box::create_vertices_on_infibox(cstr,
pt, points, fi->mark(),
fi->twin()->incident_volume()->mark(),
fi->incident_volume()->mark());
for(li = newVertices.begin(); li != newVertices.end(); ++li) {
if(Infi_box::is_infibox_corner((*li)->point())) {
li2 = corner_list.begin();
while(li2 != corner_list.end() && (*li2)->point() != (*li)->point()) ++li2;
CGAL_assertion(li2 != corner_list.end());
delete_list.push_back(*li2);
*li2 = *li;
}
}
}
for(li = vertex_list.begin(); li != vertex_list.end();++li) {
SM_decorator SD(&**li);
if(Infi_box::is_complex_facet_infibox_intersection(**li)) {
Halffacet_handle hf[2];
int i=0;
SHalfedge_iterator sei;
CGAL_forall_sedges(sei,SD) {
if(!Infi_box::is_sedge_on_infibox(sei)) {
hf[i] = sei->facet();
if(hf[i]->is_twin()) hf[i] = hf[i]->twin();
++i;
}
if(i>1)
break;
}
}
}
Association A;
SNC_external_structure es(snc());
es.clear_external_structure();
for(li = vertex_list.begin(); li != vertex_list.end();++li){
if(Infi_box::is_complex_facet_infibox_intersection(**li)) {
Vertex_handle v2;
Vertex_handle v1 = cstr.create_for_infibox_overlay(*li);
v1->point() = normalized(Infi_box::normalize_transformed_vertex((*li)->point().transform(aff)));
SM_decorator sdeco(&*v1);
sdeco.transform(linear);
switch(Infi_box::type_of_infibox_point(v1->point())) {
case 1:
v2 = cstr.create_from_point_on_infibox_facet(v1->point());
break;
case 2:
v2 = cstr.create_from_point_on_infibox_edge(v1->point());
break;
case 3:
v2 = cstr.create_from_point_on_infibox_vertex(v1->point());
li2 = corner_list.begin();
while(li2 != corner_list.end() && (*li2)->point() != v2->point()) ++li2;
if(li2 != corner_list.end())
delete_list.push_back(*li2);
break;
default: CGAL_error_msg( "wrong value");
}
Vertex_handle v = snc().new_vertex(v1->point(), (*li)->mark());
SM_overlayer O(&*v);
O.subdivide(&*v1, &*v2, A);
AND _and;
O.select(_and);
O.simplify(A);
snc().delete_vertex(v1);
snc().delete_vertex(v2);
}
if(Infi_box::is_infibox_corner((*li)->point())) {
SM_decorator SD(&**li);
if(SD.number_of_svertices() < 4)
continue;
li2 = corner_list.begin();
while(li2 != corner_list.end() && (*li2)->point() != (*li)->point()) ++li2;
CGAL_assertion(li2 != corner_list.end());
if(*li == *li2) {
delete_list.push_back(*li2);
*li2 = cstr.create_from_point_on_infibox_vertex((*li)->point());
}
} else
snc().delete_vertex(*li);
}
for(li = delete_list.begin(); li != delete_list.end(); ++li)
snc().delete_vertex(*li);
if(!aff.is_even())
change_orientation();
while(cstr.erase_redundant_vertices()) ;
cstr.correct_infibox_sedge_marks();
build_external_structure();
cstr.correct_infibox_sface_marks();
// are the upcoming lines necessary?
SNC_point_locator* old_pl = pl();
pl() = pl()->clone();
pl()->initialize(&snc());
delete old_pl;
} else {
Halffacet_iterator fi;
CGAL_forall_halffacets(fi,snc()) {
if(is_standard(fi) || ninety) {
fi->plane() = fi->plane().transform( aff);
#ifdef CGAL_NEF3_FACET_WITH_BOX
typedef typename Halffacet::Box Box;
bool first = true;
Halffacet_cycle_iterator cycle_it = fi->facet_cycles_begin();
if( cycle_it.is_shalfedge() ) {
SHalfedge_iterator edge_it(cycle_it);
SHalfedge_around_facet_circulator
start( edge_it ), end( edge_it );
CGAL_For_all( start, end ) {
const Point_3& p = start->source()->source()->point();
typename Kernel::FT q[3];
q[0] = p.x();
q[1] = p.y();
q[2] = p.z();
if(first) {
fi->b = Box(q,q);
first = false;
} else
fi->b.extend(q);
}
} else
CGAL_error_msg( "is facet first cycle a SHalfloop?");
#endif
}
}
if(!aff.is_even())
change_orientation(true);
if(aff.homogeneous(0,1) != 0 ||
aff.homogeneous(0,2) != 0 ||
aff.homogeneous(1,0) != 0 ||
aff.homogeneous(1,2) != 0 ||
aff.homogeneous(2,0) != 0 ||
aff.homogeneous(2,1) != 0 ||
aff.homogeneous(0,0) != aff.homogeneous(1,1) ||
aff.homogeneous(0,0) != aff.homogeneous(2,2) ||
!this->is_bounded()) {
SNC_point_locator* old_pl = pl();
pl() = pl()->clone();
pl()->initialize(&snc());
delete old_pl;
}
else pl()->transform(aff);
}
SNC_constructor C(snc());
C.assign_indices();
}
/*{\Mtext \headerline{Exploration}
As Nef polyhedra are the result of forming complements
and intersections starting from a set |H| of halfspaces which are
defined by oriented planes in three space. The corresponding
structure is represented by an extended wuerzburg structure
$W = (V,E,F,C)$. For topological queries within |W| the following
types and operations allow exploration access to this structure.}*/
/*{\Mtypes 3}*/
typedef CGAL::SNC_SM_explorer<SM_const_decorator> SM_explorer;
SM_explorer SMexplorer(Vertex_const_handle v) const {
SM_const_decorator SMCD(&*v);
return SM_explorer(SMCD);
}
typedef typename SNC_structure::Object_list Object_list;
typedef typename SNC_structure::Object_handle Object_handle;
/*{\Mtypemember a generic handle to an object of the underlying
plane map. The kind of object |(vertex, halfedge, face)| can
be determined and the object can be assigned to a corresponding
handle by the three functions:\\
|bool assign(Vertex_const_handle& h, Object_handle)|\\
|bool assign(Edge_const_handle& h, Object_handle)|\\
|bool assign(Facet_const_handle& h, Object_handle)|\\
|bool assign(Volume_const_handle& h, Object_handle)|\\
where each function returns |true| iff the assignment to
|h| was done.}*/
/*{\Moperations 3 1 }*/
bool contains(Object_handle /*h*/) const
/*{\Mop returns true iff the object |h| is contained in the set
represented by |\Mvar|.}*/
// { SNC_point_locator PL(snc()); return PL.mark(h);}
{ CGAL_error_msg( "not implemented."); return false;}
bool contained_in_boundary(Object_handle h) const
/*{\Mop returns true iff the object |h| is contained in the $2$-skeleton
of |\Mvar|.}*/
{ Vertex_const_handle v;
Halfedge_const_handle e;
Halffacet_const_handle f;
return ( assign(v,h) || assign(e,h) || assign(f,h) );
}
Object_handle locate(const Point_3& p) const
/*{\Mop returns a generic handle |h| to an object (vertex, edge, facet,
volume) of the underlying SNC which contains the point |p| in its relative
interior. The point |p| is contained in the set represented by |\Mvar| if
|\Mvar.contains(h)| is true.}*/ {
CGAL_NEF_TRACEN( "locating point...");
CGAL_assertion( pl() != NULL);
Object_handle o = pl()->locate(p);
Vertex_handle v;
Halfedge_handle e;
Halffacet_handle f;
Volume_handle c;
if(assign(v,o)) return make_object(Vertex_const_handle(v));
if(assign(e,o)) return make_object(Halfedge_const_handle(e));
if(assign(f,o)) return make_object(Halffacet_const_handle(f));
if(assign(c,o)) return make_object(Volume_const_handle(c));
return Object_handle();
}
/*{\Mimplementation Nef polyhedra are implemented on top of an
extended Wuerzburg structure data structure (EWS) and use linear
space in the number of vertices, edges and facets. Operations like
empty take constant time. The operations clear, complement, interior,
closure, boundary, regularization, input and output take linear
time. All binary set operations and comparison operations take time
$O(N^2)$ where $N$ is the size of the output plus the size of the
input.
The point location operations run in linear query time without any
preprocessing.}*/
/*{\Mexample Nef polyhedra are parameterized by a so called extended
geometric kernel. There's currently only one such kernel based on a
homogeneous representation of extended points called
|Extended_homogeneous<NT>|. The kernel is parameterized by a
multiprecision integer type. The member types of |Nef_polyhedron_3<
Extended_homogeneous_3<NT> >| map to corresponding types of the CGAL
geometry kernel (e.g. |Nef_polyhedron::Plane_3| equals
|CGAL::Homogeneous<leda_integer>::Plane_3| in the example below).
\begin{Mverb}
#include <CGAL/basic.h>
#include <CGAL/leda_integer.h>
#include <CGAL/Extended_homogeneous.h>
#include <CGAL/Nef_polyhedron_3.h>
using namespace CGAL;
typedef Extended_homogeneous<leda_integer> Extended_kernel;
typedef Nef_polyhedron_3<Extended_kernel> Nef_polyhedron;
typedef Nef_polyhedron::Plane_3 Plane_3;
int main()
{
Nef_polyhedron N1(Plane_3(1,0,0,0));
Nef_polyhedron N2(Plane_3(0,1,0,0), Nef_polyhedron::EXCLUDED);
Nef_polyhedron N3 = N1 * N2; // line (*)
return 0;
}
\end{Mverb}
After line (*) |N3| is the intersection of |N1| and |N2|.}*/
std::size_t bytes() {
// bytes used for the Nef_polyhedron_3.
return sizeof(Self) + (snc().bytes() - sizeof(SNC_structure));
}
std::size_t bytes_reduced() {
// bytes used for the Nef_polyhedron_3.
std::cout << sizeof(Self) + (snc().bytes_reduced2() - sizeof(SNC_structure)) << std::endl;
return sizeof(Self) + (snc().bytes_reduced() - sizeof(SNC_structure));
}
}; // end of Nef_polyhedron_3
template <typename Kernel, typename Items, typename Mark>
Nef_polyhedron_3<Kernel,Items, Mark>::
Nef_polyhedron_3( Content space) {
CGAL_NEF_TRACEN("construction from empty or space.");
empty_rep();
set_snc(snc());
if(Infi_box::extended_kernel()) {
initialize_infibox_vertices(space);
build_external_structure();
} else {
build_external_structure();
snc().volumes_begin()->mark() = (space == COMPLETE) ? 1 : 0;
}
}
template <typename Kernel, typename Items, typename Mark>
Nef_polyhedron_3<Kernel,Items, Mark>::
Nef_polyhedron_3(const Plane_3& h, Boundary b) {
CGAL_NEF_TRACEN("construction from plane "<<h);
empty_rep();
set_snc(snc());
SNC_constructor C(snc());
Infi_box::create_vertices_of_box_with_plane(C,h,(b==INCLUDED));
build_external_structure();
/*
if(Infi_box::extended_kernel()) {
SNC_structure snc1, snc2;
SNC_point_locator* pl1 = new SNC_point_locator_default;
SNC_point_locator* pl2 = new SNC_point_locator_default;
SNC_constructor c1(snc1);
Infi_box::initialize_infibox_vertices(c1, true);
SNC_external_structure es1(snc1, pl1);
es1.build_external_structure();
SNC_constructor c2(snc2);
c2.create_vertices_for_halfspace(h, b);
SNC_external_structure es2(snc2, pl2);
es2.pair_up_halfedges();
es2.link_shalfedges_to_facet_cycles();
c2.create_facets_and_volumes_of_halfspace(h);
pl2->initialize(&snc2);
AND _and;
Binary_operation bo(snc());
bo(pl(), snc1, pl1, snc2, pl2, _and);
delete pl1;
delete pl2;
} else
CGAL_error_msg
("Constructor is only available with extended kernels");
*/
}
template <typename Kernel, typename Items, typename Mark>
Nef_polyhedron_3<Kernel,Items, Mark>::
Nef_polyhedron_3( const SNC_structure& W, SNC_point_locator* _pl,
bool clone_pl,
bool clone_snc) {
CGAL_assertion( clone_snc == true || clone_pl == false);
// TODO: granados: define behavior when clone=false
// CGAL_NEF_TRACEN("construction from an existing SNC structure (clone="<<clone<<")");
this->copy_on_write();
if(clone_snc) {
snc() = W;
set_snc(snc());
}
if(clone_pl) {
pl() = _pl->clone();
pl()->initialize(&snc());
}
else
pl() = _pl;
}
template <typename Kernel, typename Items, typename Mark>
void
Nef_polyhedron_3<Kernel,Items, Mark>::
extract_complement() {
CGAL_NEF_TRACEN("extract complement");
if( this->is_shared()) clone_rep();
SNC_decorator D(snc());
Vertex_iterator v;
CGAL_forall_vertices(v,D){
v->mark() = !v->mark();
SM_decorator SM(&*v);
SM.extract_complement();
}
Halffacet_iterator f;
CGAL_forall_halffacets(f,D) f->mark() = !f->mark();
Volume_iterator c;
CGAL_forall_volumes(c,D)
// if(!(Infi_box::extended_kernel && c==D.volumes_begin()))
c->mark() = !c->mark();
}
template <typename Kernel, typename Items, typename Mark>
void
Nef_polyhedron_3<Kernel,Items, Mark>::
extract_interior() {
CGAL_NEF_TRACEN("extract interior");
if (this->is_shared()) clone_rep();
SNC_decorator D(snc());
Vertex_iterator v;
CGAL_forall_vertices(v,D){
v->mark() = false;
SM_decorator SM(&*v);
SM.extract_interior();
}
Halffacet_iterator f;
CGAL_forall_halffacets(f,D) f->mark() = false;
simplify();
}
template <typename Kernel, typename Items, typename Mark>
void
Nef_polyhedron_3<Kernel,Items, Mark>::
extract_boundary() {
CGAL_NEF_TRACEN("extract boundary");
if (this->is_shared()) clone_rep();
SNC_decorator D(snc());
Vertex_iterator v;
CGAL_forall_vertices(v,D) {
v->mark() = true;
SM_decorator SM(&*v);
SM.extract_boundary();
}
Halffacet_iterator f;
CGAL_forall_halffacets(f,D) f->mark() = true;
Volume_iterator c;
CGAL_forall_volumes(c,D) c->mark() = false;
simplify();
}
} //namespace CGAL
#include <CGAL/enable_warnings.h>
#endif //CGAL_NEF_POLYHEDRON_3_H