mirror of https://github.com/CGAL/cgal
resolve merge conflicts
This commit is contained in:
commit
766673bd8c
|
|
@ -0,0 +1,180 @@
|
|||
|
||||
namespace CGAL {
|
||||
/*!
|
||||
|
||||
\mainpage User Manual
|
||||
\anchor Chapter_Advancing_Front_Surface_Reconstruction
|
||||
\anchor I1ChapterAdvancingFrontSurfaceReconstruction
|
||||
\cgalAutoToc
|
||||
\author Tran Kai Frank Da and David Cohen-Steiner
|
||||
|
||||
|
||||
Surface reconstruction from an unstructured point set is to find
|
||||
a surface that approximates these points. Several techniques have
|
||||
been applied to this problem. Among them are variational
|
||||
methods \cgalCite{s-lsm-96}\cgalCite{zomk-insru-00}, tensor voting \cgalCite{cgal:ml-cfsg-00}, implicit surface \cgalCite{hddhjmss-pssr-94}\cgalCite{bc-ssrnn-00},
|
||||
and Delaunay triangulations.
|
||||
|
||||
For Delaunay based algorithms the output surface
|
||||
usually is the union of some triangles selected in the Delaunay
|
||||
triangulation of the input points. Such algorithms can be volume oriented
|
||||
which output the boundary of selected tetrahedra \cgalCite{abe-cbscc-97}\cgalCite{ack-pcubm-01}, or surface
|
||||
oriented, that is they explicitely select triangles.
|
||||
|
||||
In most surface oriented Delaunay-based algorithms triangles are
|
||||
selected independently, that is in parallel \cgalCite{agj-lcsr-00}\cgalCite{ab-srvf-98}.
|
||||
|
||||
The surface oriented Delaunay-based surface reconstruction algorithm
|
||||
presented in this chapter selects triangles sequentially, that is by
|
||||
using previous selected triangles to select a new one. It adds the
|
||||
most *plausible* triangle first, and only adds triangles in a way
|
||||
that the surface remains an orientable manifold.
|
||||
|
||||
Two other examples of this greedy approach are the ball pivoting
|
||||
algorithm and Boyer and Petitjean's algorithm \cgalCite{bmrst-bpasr-99}\cgalCite{pb-rnrps-01}. In both
|
||||
algorithms a triangulated surface is incrementally grown starting from
|
||||
a seed triangle. Ball pivoting is fast, but the quality of the
|
||||
reconstruction depends on user defined parameters corresponding to the
|
||||
sampling density. The Boyer Petitjean approach can handle non-uniform
|
||||
sampling, but fails when near cocircular points are encountered, and
|
||||
it does not provide any guarantee on the topology of the surface.
|
||||
|
||||
In the next sections we describe the algorithm, and give
|
||||
examples.
|
||||
|
||||
|
||||
\section AFSR_Definitions Definitions and the Algorithm
|
||||
|
||||
A detailed description of the algorithm and the underlying theory can be found
|
||||
in \cgalCite{cgal:csd-gdbsra-04}.
|
||||
|
||||
|
||||
|
||||
The first step of the algorithm is the construction of a 3D Delaunay
|
||||
triangulation of the point set.
|
||||
The Delaunay triangle with the smallest radius is the starting point
|
||||
for the greedy algorithm. It is the initial surface and it has three
|
||||
boundary edges.
|
||||
|
||||
The algorithm maintains a priority queue of
|
||||
candidate triangles, that is of triangles incident to the boundary
|
||||
edges of the current surface. The priority is the \em plausibility.
|
||||
While this priority queue
|
||||
is not empty, the algorithm selects the most plausible candidate triangle and adds into the
|
||||
surface, and inserts new candidate triangles into the priority queue in case
|
||||
there are new boundary edges. As the algorithm creates a two-manifold surface
|
||||
some candidate triangles can not be selected due to <em>topological constraints</em> which are explained next.
|
||||
|
||||
|
||||
\subsection AFSR_Topology Topological Constraints
|
||||
|
||||
Any triangle \f$t\f$ considered as next potential candidate has to share an
|
||||
edge \f$e\f$ with the boundary of the current reconstruction. Let \f$b\f$
|
||||
be the vertex of \f$t\f$ opposite to \f$e\f$. There are four
|
||||
possible situations where \f$t\f$ may be added to the surface.
|
||||
- extension, if \f$b\f$ is not yet on the surface.
|
||||
- hole filling, if \f$b\f$ is on the boundary and both neighbors of \f$b\f$ on the boundary are on edge \f$e\f$.
|
||||
- ear filling, if \f$b\f$ is on the boundary and one neighbor of \f$b\f$ on the boundary is on edge \f$e\f$.
|
||||
- glueing, if \f$b\f$ is on the boundary and no neighbor of \f$b\f$ on the boundary is on edge \f$e\f$.
|
||||
|
||||
\cgalFigureBegin{figAFSRvalid,valid.png}
|
||||
Valid candidates.
|
||||
\cgalFigureEnd
|
||||
|
||||
While the first three operations would never induce a non-manifold edge or vertex,
|
||||
we only can perform glueing, if triangle \f$t\f$ has a *twin* facet, that is a
|
||||
triangle with an edge on the boundary and incident to \f$b\f$, and the
|
||||
third vertex on edge \f$e\f$.
|
||||
|
||||
We call a triangle on which the above operations can be applied *valid*.
|
||||
|
||||
\subsection AFSR_Selection Plausibility of a Candidate Triangle
|
||||
|
||||
Valid triangles for an edge on the boundary are compared through what
|
||||
we call their *radius*. The radius of a triangle \f$t\f$ is the radius of
|
||||
the smallest sphere passing through the vertices of \f$t\f$ and enclosing no
|
||||
sample point. In other words, the radius \f$r_t\f$ is the distance
|
||||
from any vertex of \f$t\f$ to the Voronoi edge dual to \f$t\f$.
|
||||
|
||||
While the radius is a good criterion in the case of 2D smooth curve
|
||||
reconstruction \cgalCite{b-cccda-94}, we need another criterion for 3D surface
|
||||
reconstruction, namely the dihedral angle between triangles on the
|
||||
surface, that is the angle between the normals of the triangles.
|
||||
|
||||
We denote by \f$ \beta_t\f$ the angle between the normal of a triangle
|
||||
\f$ t\f$ incident on a boundary edge \f$ e \f$ and the normal of the
|
||||
triangle on the surface incident to \f$ e \f$.
|
||||
|
||||
The *candidate* triangle of an edge \f$ e \f$ is the triangle
|
||||
with the smallest radius, that is valid for \f$ e \f$
|
||||
and that has \f$ \beta_t < \alpha_\mathrm{sliver} \f$.
|
||||
There may be no such triangle. In the implementation
|
||||
of the algorithm \f$ \alpha_\mathrm{sliver} = 5\pi/6 \f$.
|
||||
|
||||
|
||||
We define the *plausibility* grade \f$ p(t) \f$ as \f$ 1/r_t \f$, if
|
||||
\f$ \beta_t < \beta \f$, and \f$ -\beta_t \f$ else. The parameter \f$
|
||||
\beta \f$ can be chosen by the user and is by default \f$ \pi/6\f$.
|
||||
|
||||
|
||||
\subsection AFSR_Boundaries Dealing with Multiple Components, Boundaries and Sharp Edges
|
||||
|
||||
By construction the output of the algorithm is a connected orientable
|
||||
manifold with or without boundary. To cope with multiple components we
|
||||
merely look for a new seed facet among facets disjoint from the
|
||||
surface. In case of noisy data or outliers, the user has to filter out
|
||||
small surface components.
|
||||
|
||||
It is impossible to handle all kinds of boundaries and non uniform sampling
|
||||
at the same time. A void can either be an undersampled zone of the surface,
|
||||
or a hole.
|
||||
|
||||
As we do not want the algorithm to rely on a uniformity condition on
|
||||
the sampling it will fill holes cut off from "flat" regions of the
|
||||
surface. However, in many cases a boundary component cannot be closed
|
||||
by adding a spanning disk such that the resulting disk is well
|
||||
sampled. Typically, closing a boundary component due to a transversal
|
||||
clipping of the operation, would yield large dihedral angles at
|
||||
boundary edges. Moreover, if the boundary is sufficiently well
|
||||
sampled, the radii of the two triangles incident on a boundary edge
|
||||
would be very different. These heuristic facts can be used for
|
||||
boundary detection.
|
||||
|
||||
We discard any candidate triangle \f$ t \f$, for an edge \f$ e \f$
|
||||
such that \f$ p(t) < 0\f$, and \f$ r_t > k r_{t'}\f$ where \f$ t'\f$ is
|
||||
the triangle on the surface incident on \f$ e \f$. The parameter \f$ k \f$
|
||||
can be chosen by the user and is by default 5.
|
||||
|
||||
|
||||
Note that this heuristic implies that
|
||||
where the sampling is too sparse with respect to curvature, it must
|
||||
be sufficiently uniform for our algorithm to work.
|
||||
|
||||
|
||||
\section AFSR_Examples Examples
|
||||
|
||||
\subsection AFSR_Example_function Example for Global Function
|
||||
|
||||
The global function `advancing_front_surface_reconstruction()`
|
||||
takes an iterator range of points as input and writes for each face of the
|
||||
reconstructed surface a triple of point indices into an output iterator.
|
||||
In the example we write the surface in the OFF format to `std::cout`.
|
||||
|
||||
\cgalExample{Advancing_front_surface_reconstruction/reconstruction_fct.cpp}
|
||||
|
||||
|
||||
\subsection AFSR_Example_class Example for the Reconstruction Class
|
||||
|
||||
When using the class `Advancing_front_surface_reconstruction`
|
||||
you can access a 2D triangulation data structure describing the surface.
|
||||
You can explore the surface by going from faces to neighboring faces,
|
||||
and you can also go to the underlying 3D Delaunay triangulation.
|
||||
|
||||
In the example we write the surface in the STL (Stereo Lithography) format
|
||||
to `std::cout`.
|
||||
|
||||
\cgalExample{Advancing_front_surface_reconstruction/reconstruction_class.cpp}
|
||||
|
||||
*/
|
||||
} /* namespace CGAL */
|
||||
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup PkgAdvancingFrontSurfaceReconstruction
|
||||
|
||||
The class `Advancing_front_surface_reconstruction`
|
||||
|
||||
\tparam Dt must be a `Delaunay_triangulation_3` with
|
||||
`Advancing_front_surface_reconstruction_vertex_base_3` and `Advancing_front_surface_reconstruction_cell_base_3` blended into the vertex and cell type, and the geometric traits class must be the `Exact_predicates_inexact_constructions_kernel`.
|
||||
|
||||
*/
|
||||
|
||||
template< typename Dt>
|
||||
class Advancing_front_surface_reconstruction {
|
||||
public:
|
||||
|
||||
/// \name Types
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
The type of the 2D triangulation data structure describing the reconstructed surface.
|
||||
The type `TDS_2::Vertex` is model of the concept `TriangulationDataStructure_2::Vertex` and has additionally the
|
||||
method `vertex_3()` that returns a `Vertex_handle` to the associated 3D vertex
|
||||
The type `TDS_2::Face` is model of the concept `TriangulationDataStructure_2::Face` and has additionally the
|
||||
method `facet()` that returns the associated `Facet`, and a method `bool is_on_surface()`
|
||||
for testing if a face is part of the reconstructed surface or a face incident to a boundary edge.
|
||||
In case the surface has boundaries, the 2D surface has one vertex which is associated to the infinite
|
||||
vertex of the 3D triangulation.
|
||||
*/
|
||||
typedef unspecified_type TDS_2;
|
||||
|
||||
/*!
|
||||
The type of the 3D triangulation.
|
||||
|
||||
*/
|
||||
typedef Dt Triangulation_3;
|
||||
|
||||
/*!
|
||||
The vertex handle type of the 3D triangulation.
|
||||
|
||||
*/
|
||||
typedef typename Triangulation_3::Vertex_handle Vertex_handle;
|
||||
|
||||
/*!
|
||||
The cell handle type of the 3D triangulation.
|
||||
|
||||
*/
|
||||
typedef typename Triangulation_3::Cell_handle Cell_handle;
|
||||
|
||||
/*!
|
||||
The facet type of the 3D triangulation.
|
||||
|
||||
*/
|
||||
typedef typename Triangulation_3::Facet Facet;
|
||||
|
||||
|
||||
/*!
|
||||
A bidirectional iterator which allows to enumerate all points that were removed
|
||||
from the 3D Delaunay triangulation during the surface reconstruction. The value type
|
||||
of the iterator is `Triangulation_3::Point_3`.
|
||||
*/
|
||||
typedef unspecified_type Outlier_iterator;
|
||||
|
||||
/*!
|
||||
A forward iterator which allows to visit all boundaries. It
|
||||
visits the entry point of each boundary twice. This allows to
|
||||
detect that the traversal of a boundary is finished. One more increment
|
||||
brings us to the vertex on the next boundary.
|
||||
The value type of the iterator is `Triangulation_3::Vertex_handle`.
|
||||
*/
|
||||
typedef unspecified_type Boundary_iterator;
|
||||
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Creation
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
Initializes from a 3D Delaunay triangulation of a point set.
|
||||
*/
|
||||
Advancing_front_surface_reconstruction(Dt& dt);
|
||||
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Operations
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
calls the surface reconstruction function with the default parameters.
|
||||
|
||||
\param k described in Section \ref AFSR_Boundaries
|
||||
\param beta described in Section \ref AFSR_Selection
|
||||
|
||||
*/
|
||||
void operator()(double k=5, double beta= 0.18);
|
||||
|
||||
/*!
|
||||
returns the reconstructed surface.
|
||||
*/
|
||||
const TDS_2&
|
||||
tds_2();
|
||||
|
||||
/*!
|
||||
returns the underlying 3D Delaunay triangulation.
|
||||
*/
|
||||
const Triangulation_3&
|
||||
triangulation_3();
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
An iterator over the outliers.
|
||||
*/
|
||||
Outlier_iterator outliers_begin();
|
||||
|
||||
/*!
|
||||
Past-the-end iterator.
|
||||
*/
|
||||
Outlier_iterator outliers_end();
|
||||
|
||||
/*!
|
||||
An iterator over the boundary vertices.
|
||||
*/
|
||||
Boundary_iterator boundaries_begin();
|
||||
|
||||
/*!
|
||||
Past-the-end iterator.
|
||||
*/
|
||||
Boundary_iterator boundaries_end();
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Predicates
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
returns `true` if the reconstructed surface has boundaries.
|
||||
*/
|
||||
bool
|
||||
has_boundaries() const;
|
||||
|
||||
|
||||
/*!
|
||||
returns `true` if the facet is on the surface.
|
||||
*/
|
||||
bool
|
||||
has_on_surface(Facet f) const;
|
||||
|
||||
/*!
|
||||
returns `true` if the facet f is on the surface.
|
||||
*/
|
||||
bool
|
||||
has_on_surface(TDS_2::Face_handle f2) const;
|
||||
|
||||
/*!
|
||||
returns `true` if the facet f is on the surface.
|
||||
*/
|
||||
bool
|
||||
has_on_surface(TDS_2::Vertex_handle v2) const;
|
||||
/// @}
|
||||
|
||||
|
||||
|
||||
|
||||
}; /* end Advancing_front_surface_reconstruction */
|
||||
|
||||
|
||||
/*!
|
||||
\ingroup PkgAdvancingFrontSurfaceReconstruction
|
||||
|
||||
For a sequence of points computes a sequence of index triples
|
||||
describing the faces of the reconstructed surface.
|
||||
|
||||
\tparam PointInputIterator must be an input iterator with 3D points from the `Exact_predicates_inexact_constructions_kernel` as value type.
|
||||
\tparam IndicesOutputIterator must be an output iterator to which
|
||||
`CGAL::cpp11::tuple<std::size_t,std::size_t,std::size_t>` can be assigned.
|
||||
|
||||
\param begin iterator on the first point of the sequence
|
||||
\param end past the end iterator the point sequence
|
||||
\param out output iterator
|
||||
\param K described in Section \ref AFSR_Boundaries
|
||||
\param beta described in Section \ref AFSR_Selection
|
||||
|
||||
*/
|
||||
template <class PointInputIterator, IndicesOutputIterator>
|
||||
IndicesOutputIterator advancing_front_surface_reconstruction(PointInputIterator b, PointInputIterator e, IndicesOutputIterator out, double k=5, double beta= 0.18 );
|
||||
|
||||
|
||||
} /* end namespace CGAL */
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup PkgAdvancingFrontSurfaceReconstruction
|
||||
|
||||
The class `Advancing_front_surface_reconstruction_cell_base_3` is the default
|
||||
cell type for the class `Advancing_front_surface_reconstruction`.
|
||||
|
||||
\tparam Traits has to be a model of `DelaunayTriangulationTraits_3`.
|
||||
|
||||
\tparam Cb has to be a model of `TriangulationCellBase_3`.
|
||||
|
||||
*/
|
||||
template< typename Traits, typename Cb = Triangulation_cell_base_3<Traits> >
|
||||
class Advancing_front_surface_reconstruction_cell_base_3 : public Cb {
|
||||
public:
|
||||
|
||||
/// @}
|
||||
|
||||
}; /* end Advancing_front_surface_reconstruction_cell_base_3 */
|
||||
} /* end namespace CGAL */
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup PkgAdvancingFrontSurfaceReconstruction
|
||||
|
||||
The class `Advancing_front_surface_reconstruction_vertex_base_3` is the default
|
||||
vertex type for the class `Advancing_front_surface_reconstruction`.
|
||||
|
||||
\tparam Traits has to be a model of `DelaunayTriangulationTraits_3`.
|
||||
|
||||
\tparam Vb has to be a model of `TriangulationVertexBase_3`.
|
||||
|
||||
|
||||
*/
|
||||
template< typename Traits, typename Vb = Triangulation_vertex_base_3<Traits> >
|
||||
class Advancing_front_surface_reconstruction_vertex_base_3 : public Vb {
|
||||
public:
|
||||
|
||||
/// @}
|
||||
|
||||
}; /* end Advancing_front_surface_reconstruction_vertex_base_3 */
|
||||
} /* end namespace CGAL */
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
@INCLUDE = ${CGAL_DOC_PACKAGE_DEFAULTS}
|
||||
|
||||
PROJECT_NAME = "CGAL ${CGAL_CREATED_VERSION_NUM} - Advancing Front Surface Reconstruction"
|
||||
|
||||
|
||||
INPUT = ${CMAKE_SOURCE_DIR}/Advancing_front_surface_reconstruction/doc/Advancing_front_surface_reconstruction/
|
||||
|
||||
|
||||
|
||||
MULTILINE_CPP_IS_BRIEF = YES
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/// \defgroup PkgAdvancingFrontSurfaceReconstruction Advancing Front Surface Reconstruction Reference
|
||||
|
||||
/*!
|
||||
\addtogroup PkgAdvancingFrontSurfaceReconstruction
|
||||
|
||||
\cgalPkgDescriptionBegin{Advancing Front Surface Reconstruction,PkgAdvancingFrontSurfaceReconstructionSummary}
|
||||
\cgalPkgPicture{afsr-detail.png}
|
||||
\cgalPkgSummaryBegin
|
||||
\cgalPkgAuthors{Tran Kai Frank Da, David Cohen-Steiner}
|
||||
\cgalPkgDesc{This package provides a greedy algorithm for surface reconstruction from an
|
||||
unorganized point set. Starting from a seed facet, a piecewise linear
|
||||
surface is grown by adding Delaunay triangles one by one. The most
|
||||
plausible triangles are added first, in a way that avoids the appearance
|
||||
of topological singularities. }
|
||||
\cgalPkgManuals{Chapter_Advancing_Front_Surface_Reconstruction,PkgAdvancingFrontSurfaceReconstruction}
|
||||
\cgalPkgSummaryEnd
|
||||
\cgalPkgShortInfoBegin
|
||||
\cgalPkgSince{4.4}
|
||||
\cgalPkgDependsOn{\ref PkgTriangulation3Summary}
|
||||
\cgalPkgBib{cgal:dc-afsr}
|
||||
\cgalPkgLicense{\ref licensesGPL "GPL"}
|
||||
\cgalPkgShortInfoEnd
|
||||
\cgalPkgDescriptionEnd
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
Manual
|
||||
Kernel_23
|
||||
STL_Extension
|
||||
Algebraic_foundations
|
||||
Circulator
|
||||
Stream_support
|
||||
Triangulation_2
|
||||
Triangulation_3
|
||||
Number_types
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
/*!
|
||||
\example Advancing_front_surface_reconstruction/reconstruction_fct.cpp
|
||||
\example Advancing_front_surface_reconstruction/reconstruction_class.cpp
|
||||
*/
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 82 KiB |
|
|
@ -0,0 +1,36 @@
|
|||
# Created by the script cgal_create_cmake_script
|
||||
# This is the CMake script for compiling a CGAL application.
|
||||
|
||||
|
||||
project( Advancing_front_surface_reconstruction_example )
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.4.5)
|
||||
|
||||
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
|
||||
|
||||
if ( COMMAND cmake_policy )
|
||||
cmake_policy( SET CMP0003 NEW )
|
||||
endif()
|
||||
|
||||
find_package(CGAL QUIET COMPONENTS Core )
|
||||
|
||||
if ( CGAL_FOUND )
|
||||
|
||||
include( ${CGAL_USE_FILE} )
|
||||
|
||||
include( CGAL_CreateSingleSourceCGALProgram )
|
||||
|
||||
include_directories (BEFORE ../../include)
|
||||
# include_directories (BEFORE ../../../../../trunk/Triangulation_2/include)
|
||||
|
||||
create_single_source_cgal_program( "extract.cpp" )
|
||||
create_single_source_cgal_program( "reconstruction_fct.cpp" )
|
||||
create_single_source_cgal_program( "reconstruction_class.cpp" )
|
||||
create_single_source_cgal_program( "reconstruction_polyhedron.cpp" )
|
||||
|
||||
else()
|
||||
|
||||
message(STATUS "This program requires the CGAL library, and will not be compiled.")
|
||||
|
||||
endif()
|
||||
|
||||
|
|
@ -0,0 +1,464 @@
|
|||
#define NOLAZY
|
||||
#define BLIND
|
||||
|
||||
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
|
||||
// Kernel
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Triangulation_data_structure_3.h>
|
||||
#include <CGAL/Delaunay_triangulation_3.h>
|
||||
|
||||
#include <CGAL/Advancing_front_surface_reconstruction.h>
|
||||
#include <CGAL/AFSR_options.h>
|
||||
#include <CGAL/AFSR/write_triple_indices.h>
|
||||
#include <CGAL/IO/Advancing_front_surface_reconstruction.h>
|
||||
|
||||
#include <CGAL/Timer.h>
|
||||
|
||||
|
||||
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
|
||||
typedef Kernel::Point_3 Point;
|
||||
|
||||
typedef CGAL::Advancing_front_surface_reconstruction_vertex_base_3<Kernel> LVb;
|
||||
typedef CGAL::Advancing_front_surface_reconstruction_cell_base_3<Kernel> LCb;
|
||||
|
||||
typedef CGAL::Triangulation_data_structure_3<LVb,LCb> Tds;
|
||||
typedef CGAL::Delaunay_triangulation_3<Kernel,Tds> Triangulation_3;
|
||||
|
||||
typedef Triangulation_3::Vertex_handle Vertex_handle;
|
||||
|
||||
typedef CGAL::Advancing_front_surface_reconstruction<Kernel,Triangulation_3> Surface;
|
||||
typedef CGAL::AFSR_options Options;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
struct Auto_count : public std::unary_function<const Point&,std::pair<Point,int> >{
|
||||
mutable int i;
|
||||
Auto_count() : i(0){}
|
||||
std::pair<Point,int> operator()(const Point& p) const {
|
||||
return std::make_pair(p,i++);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
bool
|
||||
file_input(const Options& opt, std::vector<Point>& points)
|
||||
{
|
||||
const char* finput = opt.finname;
|
||||
bool xyz = opt.xyz;
|
||||
|
||||
std::ios::openmode mode = (opt.binary) ? std::ios::binary : std::ios::in;
|
||||
std::ifstream is(finput, mode);
|
||||
|
||||
if(opt.binary){
|
||||
CGAL::set_binary_mode(is);
|
||||
}
|
||||
if(is.fail())
|
||||
{
|
||||
std::cerr << "+++unable to open file for input" << std::endl;
|
||||
exit(0);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
std::cerr << "Input from file : " << finput << std::endl;
|
||||
|
||||
std::size_t n;
|
||||
if(! xyz){
|
||||
is >> n;
|
||||
std::cerr << " reading " << n << " points" << std::endl;
|
||||
points.reserve(n);
|
||||
CGAL::cpp11::copy_n(std::istream_iterator<Point>(is), n, std::back_inserter(points));
|
||||
} else {
|
||||
// we do not know beforehand how many points we will read
|
||||
std::istream_iterator<Point> it(is), eof;
|
||||
char ignore[256];
|
||||
while(it!= eof){
|
||||
points.push_back(*it);
|
||||
is.getline(ignore,256); // ignore what comes after 3 doubles in a line
|
||||
it++;
|
||||
}
|
||||
n = points.size();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void usage(char* program)
|
||||
{
|
||||
std::cerr << std::endl << "NAME " << std::endl
|
||||
<< program << " - surface extension -" << std::endl << std::endl;
|
||||
|
||||
std::cerr << std::endl << "OPTIONS" << std::endl
|
||||
<< " -xyz : input data in xyz format" << std::endl
|
||||
<< " -no_border -nb : " << std::endl
|
||||
<< " -in fname : reads points from file fname" << std::endl
|
||||
<< " -out fname : writes points to file fname" << std::endl
|
||||
<< " -out_format -of : choose file format for output (iv, wrl, off, medit," << std::endl
|
||||
<< " ply, stl, all, none)" << std::endl
|
||||
<< " -rgb r g b : color of the surface" << std::endl
|
||||
<< " -no_header : The Vrml header and footer are not written" << std::endl
|
||||
<< " -area a : No faces larger than area * average_area" << std::endl
|
||||
<< " -perimeter p : No faces larger than perimeter * average_perimeter" << std::endl
|
||||
<< " -abs_area a : No faces larger than abs_area" << std::endl
|
||||
<< " -abs_perimeter p : No faces with perimeter longer than abs_perimeter" << std::endl
|
||||
<< "\n Options for internal use" << std::endl
|
||||
|
||||
<< " -binary : binary I/O" << std::endl
|
||||
<< " -delta x : set the delta constant" << std::endl
|
||||
<< " -ki x y : set the K interval (default : [1.1 5])" << std::endl
|
||||
<< " -ks x : set the K step (default : .1)" << std::endl
|
||||
<< " -k x : set the K constant (only one pass)" << std::endl
|
||||
<< " -Delaunay : display the underlying Delaunay triangulation" << std::endl
|
||||
<< " -max_of_connected_components x : set the max of connected components" << std::endl
|
||||
<< " (default : non-active)" << std::endl
|
||||
<< " -post x : set a number for the post process" << std::endl
|
||||
<< " -contours : display contours" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
parse(int argc, char* argv[], Options &opt)
|
||||
{
|
||||
std::strcpy(opt.program, argv[0]);
|
||||
--argc;
|
||||
argv++;
|
||||
if(argc == 0)
|
||||
std::cerr << "nothing ???" << std::endl;
|
||||
|
||||
while ((argc > 0) && (argv[0][0] == '-')){
|
||||
if ((!std::strcmp(argv[0], "-D")) || (!std::strcmp(argv[0], "-Delaunay"))) {
|
||||
opt.Delaunay = true;
|
||||
argv++;
|
||||
argc--;
|
||||
std::cerr << "-D ";
|
||||
}
|
||||
else if ((!std::strcmp(argv[0], "-c")) || (!std::strcmp(argv[0], "-contours"))) {
|
||||
opt.contour = true;
|
||||
argv++;
|
||||
argc--;
|
||||
std::cerr << "-c ";
|
||||
}
|
||||
else if ((!std::strcmp(argv[0], "-b")) || (!std::strcmp(argv[0], "-binary"))) {
|
||||
opt.binary = true;
|
||||
argv++;
|
||||
argc--;
|
||||
std::cerr << "-b ";
|
||||
}
|
||||
else if ((!std::strcmp(argv[0], "-x")) || (!std::strcmp(argv[0], "-xyz"))) {
|
||||
opt.xyz = true;
|
||||
argv++;
|
||||
argc--;
|
||||
std::cerr << "-x ";
|
||||
}
|
||||
else if ((!std::strcmp(argv[0], "-nb")) || (!std::strcmp(argv[0], "-no_border"))) {
|
||||
opt.K = HUGE_VAL;
|
||||
opt.K_init = opt.K;
|
||||
argv++;
|
||||
argc--;
|
||||
std::cerr << "-nb ";
|
||||
}
|
||||
else if ((!std::strcmp(argv[0], "-nh")) || (!std::strcmp(argv[0], "-no_header"))) {
|
||||
opt.no_header = true;
|
||||
argv++;
|
||||
argc--;
|
||||
std::cerr << "-nh ";
|
||||
}
|
||||
else if ((!std::strcmp(argv[0], "-d")) || (!std::strcmp(argv[0], "-delta"))){
|
||||
if (sscanf(argv[1], "%lf", &opt.delta) != 1) {
|
||||
std::cerr << "Argument for delta must be a number"
|
||||
<< std::endl;
|
||||
}
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
std::cerr << "-d " << opt.delta << " ";
|
||||
}
|
||||
else if ((!std::strcmp(argv[0], "-a")) || (!std::strcmp(argv[0], "-area"))){
|
||||
if (sscanf(argv[1], "%lf", &opt.area) != 1) {
|
||||
std::cerr << "Argument for area must be a number"
|
||||
<< std::endl;
|
||||
}
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
std::cerr << "-a " << opt.area << " ";
|
||||
}
|
||||
else if ((!std::strcmp(argv[0], "-pe")) || (!std::strcmp(argv[0], "-perimeter"))){
|
||||
if (sscanf(argv[1], "%lf", &opt.perimeter) != 1) {
|
||||
std::cerr << "Argument for perimeter must be a number"
|
||||
<< std::endl;
|
||||
}
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
std::cerr << "-perimeter " << opt.perimeter << " ";
|
||||
}
|
||||
else if ((!std::strcmp(argv[0], "-aa")) || (!std::strcmp(argv[0], "-abs_area"))){
|
||||
if (sscanf(argv[1], "%lf", &opt.abs_area) != 1) {
|
||||
std::cerr << "Argument for abs_area must be a number"
|
||||
<< std::endl;
|
||||
}
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
std::cerr << "-abs_area " << opt.abs_area << " ";
|
||||
}
|
||||
else if ((!std::strcmp(argv[0], "-ae")) || (!std::strcmp(argv[0], "-abs_perimeter"))){
|
||||
if (sscanf(argv[1], "%lf", &opt.abs_perimeter) != 1) {
|
||||
std::cerr << "Argument for abs_perimeter must be a number"
|
||||
<< std::endl;
|
||||
}
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
std::cerr << "-abs_perimeter " << opt.abs_perimeter << " ";
|
||||
}
|
||||
else if ((!std::strcmp(argv[0], "-ki"))){
|
||||
if ((sscanf(argv[1], "%lf", &opt.K_init) != 1)||
|
||||
(sscanf(argv[2], "%lf", &opt.K) != 1)){
|
||||
std::cerr << "Argument for K must be a number"
|
||||
<< std::endl;
|
||||
}
|
||||
argv += 3;
|
||||
argc -= 3;
|
||||
std::cerr << "-ki " << opt.K_init << " " << opt.K << " ";
|
||||
}
|
||||
else if ((!std::strcmp(argv[0], "-rgb"))){
|
||||
if ((sscanf(argv[1], "%lf", &opt.red) != 1)||
|
||||
(sscanf(argv[2], "%lf", &opt.green) != 1) ||
|
||||
(sscanf(argv[3], "%lf", &opt.blue) != 1)){
|
||||
std::cerr << "Argument for rgb must be three numbers"
|
||||
<< std::endl;
|
||||
}
|
||||
argv += 4;
|
||||
argc -= 4;
|
||||
std::cerr << "-rgb " << opt.red << " " << opt.green << " " << opt.blue << " " ;
|
||||
}
|
||||
else if ((!std::strcmp(argv[0], "-ks"))){
|
||||
if (sscanf(argv[1], "%lf", &opt.K_step) != 1) {
|
||||
std::cerr << "Argument for K must be a number"
|
||||
<< std::endl;
|
||||
}
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
std::cerr << "-ks " << opt.K_step << " ";
|
||||
}
|
||||
else if ((!std::strcmp(argv[0], "-k"))){
|
||||
if (sscanf(argv[1], "%lf", &opt.K) != 1) {
|
||||
std::cerr << "Argument for K must be a number"
|
||||
<< std::endl;
|
||||
}
|
||||
opt.K_init = opt.K;
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
std::cerr << "-k " << opt.K_init << " ";
|
||||
}
|
||||
else if ((!std::strcmp(argv[0], "-m")) || (!std::strcmp(argv[0], "-max_of_connected_components"))){
|
||||
if (sscanf(argv[1], "%d", &opt.max_connected_comp) != 1) {
|
||||
std::cerr << "Argument for the number of connected components must be a number"
|
||||
<< std::endl;
|
||||
}
|
||||
/*
|
||||
if(opt.max_connected_comp < 1) {
|
||||
std::cerr << "Argument for the number of connected components must be a positive number"
|
||||
<< "It is set to 1" << std::endl;
|
||||
opt.max_connected_comp = 1;
|
||||
}
|
||||
*/
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
std::cerr << "-m " << opt.max_connected_comp << " ";
|
||||
}
|
||||
else if ((!std::strcmp(argv[0], "-p")) || (!std::strcmp(argv[0], "-post"))){
|
||||
if (sscanf(argv[1], "%d", &opt.NB_BORDER_MAX) != 1) {
|
||||
std::cerr << "Argument for post process must be a number"
|
||||
<< std::endl;
|
||||
}
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
std::cerr << "-p " << opt.NB_BORDER_MAX << " ";
|
||||
}
|
||||
else if ((!std::strcmp(argv[0], "-i")) || (!std::strcmp(argv[0], "-in"))) {
|
||||
std::strcpy(opt.finname, argv[1]);
|
||||
opt.file_input = true;
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
std::cerr << "-i " << opt.finname << " ";
|
||||
}
|
||||
else if ((!std::strcmp(argv[0], "-s")) || (!std::strcmp(argv[0], "-sect_in"))) {
|
||||
std::strcpy(opt.finname, argv[1]);
|
||||
opt.Section_file = true;
|
||||
opt.file_input = true;
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
std::cerr << "-s " << opt.finname << " ";
|
||||
}
|
||||
else if ((!std::strcmp(argv[0], "-o")) || (!std::strcmp(argv[0], "-out"))) {
|
||||
std::strcpy(opt.foutname, argv[1]);
|
||||
opt.file_output = true;
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
std::cerr << "-o " << opt.foutname << " ";
|
||||
}
|
||||
else if ((!std::strcmp(argv[0], "-of")) || (!std::strcmp(argv[0], "-out_format"))) {
|
||||
if (!std::strcmp(argv[1], "wrl"))
|
||||
opt.out_format = 0;
|
||||
else if (!std::strcmp(argv[1], "off"))
|
||||
opt.out_format = 1;
|
||||
else if (!std::strcmp(argv[1], "medit"))
|
||||
opt.out_format = 2;
|
||||
else if (!std::strcmp(argv[1], "ply"))
|
||||
opt.out_format = 3;
|
||||
else if(!std::strcmp(argv[1], "iv"))
|
||||
opt.out_format = 4;
|
||||
else if(!std::strcmp(argv[1], "stl"))
|
||||
opt.out_format = 5;
|
||||
else if (!std::strcmp(argv[1], "all"))
|
||||
opt.out_format = -1;
|
||||
else if (!std::strcmp(argv[1], "none"))
|
||||
opt.out_format = -2;
|
||||
else
|
||||
std::cerr << "unrecognized file format." << std::endl;
|
||||
opt.file_output = true;
|
||||
std::cerr << "-of " << argv[1] << " ";
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
}
|
||||
else if ((!std::strcmp(argv[0], "-?")) ||
|
||||
(!std::strcmp(argv[0], "-h")) ||
|
||||
(!std::strcmp(argv[0], "-help"))) {
|
||||
usage(opt.program);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
std::cerr << "unrecognized option " << argv[0] << std::endl;
|
||||
usage(opt.program);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(argc > 0){
|
||||
std::cerr << "unrecognized option " << argv[0] << std::endl;
|
||||
usage(opt.program);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class PointIterator, class TripleOutputIterator>
|
||||
void reconstruction_test(PointIterator point_begin, PointIterator
|
||||
point_end, TripleOutputIterator out, bool filter_input_points=false,
|
||||
double perimeter=0)
|
||||
{
|
||||
Options opt;
|
||||
opt.abs_perimeter = perimeter;
|
||||
std::cerr << "Compute Delaunay Tetrahedrization " << std::endl;
|
||||
CGAL::Timer t1;
|
||||
t1.start();
|
||||
|
||||
Triangulation_3 dt( boost::make_transform_iterator(point_begin, Auto_count()),
|
||||
boost::make_transform_iterator(point_end, Auto_count() ) );
|
||||
t1.stop();
|
||||
std::cerr << " Inserted " << dt.number_of_vertices() << " points, "
|
||||
<< dt.number_of_cells() << " cells computed in "
|
||||
<< t1.time() << " sec." << std::endl;
|
||||
|
||||
t1.reset();
|
||||
t1.start();
|
||||
Surface S(dt, opt);
|
||||
t1.stop();
|
||||
std::cerr << "Reconstruction takes " << t1.time() << " sec.\n";
|
||||
std::cerr << " " << S.number_of_outliers() << " outliers.\n";
|
||||
std::cerr << " Reconstructed surface: " << S.number_of_facets() <<
|
||||
" facets, " << S.number_of_vertices() << " vertices.\n";
|
||||
std::cerr << " " << S.number_of_border_edges() <<
|
||||
" border edges.\n";
|
||||
std::cerr << " number of connected components <= "
|
||||
<< (std::max)(1, S.number_of_connected_components()-1)
|
||||
<< std::endl;
|
||||
write_triple_indices(out, S);
|
||||
}
|
||||
|
||||
|
||||
//___________________________________________
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
CGAL::Timer timer, total;
|
||||
total.start();
|
||||
timer.start();
|
||||
//parse command line
|
||||
Options opt;
|
||||
std::cerr << "Option line for this execution is :" << std::endl;
|
||||
if (!parse(argc, argv, opt))
|
||||
exit(0);
|
||||
std::cerr << std::endl << std::endl;
|
||||
|
||||
std::vector<Point> points;
|
||||
|
||||
file_input(opt, points);
|
||||
|
||||
#if 0
|
||||
std::cerr << "Time for reading " << timer.time() << " sec." << std::endl;
|
||||
std::vector<CGAL::cpp11::tuple<std::size_t,std::size_t,std::size_t> > triples;
|
||||
reconstruction_test(points.begin(), points.end(), std::back_inserter(triples));
|
||||
|
||||
|
||||
std::cout << triples.size() << std::endl;
|
||||
for(int i = 0; i < triples.size(); ++i){
|
||||
std::cout << "3 " << get<0>(triples[i]) << " " << get<1>(triples[i]) << " " << get<2>(triples[i]) << " " << std::endl;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
std::cerr << "Compute Delaunay Tetrahedrization " << std::endl;
|
||||
CGAL::Timer t1;
|
||||
t1.start();
|
||||
|
||||
Triangulation_3 dt( boost::make_transform_iterator(points.begin(),Auto_count()),
|
||||
boost::make_transform_iterator(points.end(), Auto_count() ) );
|
||||
t1.stop();
|
||||
std::cerr << " Inserted " << dt.number_of_vertices() << " points, "
|
||||
<< dt.number_of_cells() << " cells computed in "
|
||||
<< t1.time() << " sec." << std::endl;
|
||||
|
||||
if (dt.dimension() < 3) {
|
||||
std::cerr << "-- 2D sample of points ???" << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
points.clear();
|
||||
|
||||
|
||||
Surface S(dt, opt);
|
||||
S();
|
||||
|
||||
std::cerr << "Total time: " << timer.time() << " sec." << std::endl;
|
||||
// write_to_file_vrml2(opt.foutname, S, opt.contour, opt.red, opt.green, opt.blue, opt.no_header);
|
||||
write_to_file(opt.foutname, S, opt.contour, opt.out_format, opt.red, opt.green, opt.blue, opt.no_header);
|
||||
|
||||
std::cerr << " " << S.number_of_outliers()
|
||||
<< " outliers." << std::endl;
|
||||
std::cerr << " Reconstructed surface: " << S.number_of_facets() <<
|
||||
" facets, " << S.number_of_vertices() << " vertices." << std::endl;
|
||||
std::cerr << " " << S.number_of_border_edges() <<
|
||||
" border edges." << std::endl;
|
||||
std::cerr << " number of connected components <= "
|
||||
<< (std::max)(1, S.number_of_connected_components()-1)
|
||||
<< std::endl << std::endl;
|
||||
|
||||
#endif
|
||||
total.stop();
|
||||
std::cerr << "Total = " << total.time() << " sec." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
#include <CGAL/basic.h>
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Filtered_kernel.h>
|
||||
#include <CGAL/algorithm.h>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
typedef double NT;
|
||||
|
||||
struct K : public CGAL::Filtered_kernel<CGAL::Simple_cartesian<NT> > {};
|
||||
typedef K::Point_3 Point;
|
||||
typedef K::Vector_3 Vector;
|
||||
typedef K::Segment_3 Segment;
|
||||
typedef K::Triangle_3 Triangle;
|
||||
|
||||
NT
|
||||
weight(const Point& p, const Point& q, const Point& r){
|
||||
NT area = std::sqrt(Triangle(p,q,r).squared_area());
|
||||
NT l1 = std::sqrt((p-q) * (p-q));
|
||||
NT l2 = std::sqrt((p-r) * (p-r));
|
||||
NT l3 = std::sqrt((q-r) * (q-r));
|
||||
if(l1>l2) std::swap(l1,l2);
|
||||
if(l2>l3) std::swap(l2,l3);
|
||||
if(l1>l2) std::swap(l1,l2);
|
||||
if(l2>l3) std::swap(l2,l3);
|
||||
|
||||
// Taken from Piecewise-Linear Interpolation between Polygonal Slices
|
||||
// from Gill Barequet and Micha Sharir
|
||||
return 0.85 * area + 0.05 * (l1 +l2 + l3) + 0.1 * l3/l1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
insert(std::set<CGAL::Triple<int,int,int> >& triangles, int i, int j, int k){
|
||||
std::cout << i << ", " << j << ", " << k << std::endl;
|
||||
if(i>j) std::swap(i,j);
|
||||
if(j>k) std::swap(j,k);
|
||||
if(i>j) std::swap(i,j);
|
||||
if(j>k) std::swap(j,k);
|
||||
std::cout << i << ", " << j << ", " << k << std::endl;
|
||||
triangles.insert(CGAL::make_triple(i,j,k));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
collect(int i, int k, int n, const std::vector<NT>& O, std::set<CGAL::Triple<int,int,int> >& triangles){
|
||||
|
||||
std::cout << "collect(" << i << ", " << k << ")" << std::endl;
|
||||
if((i+2) == k){
|
||||
insert(triangles, i, i+1, k);
|
||||
}else {
|
||||
int o = O[i*n+k];
|
||||
|
||||
if(o != (i+1)){
|
||||
collect(i, o, n, O, triangles);
|
||||
}
|
||||
insert(triangles, i, o, k);
|
||||
if(o != (k-1)){
|
||||
collect(o, k, n, O, triangles);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
main(){
|
||||
|
||||
int n;
|
||||
std::cin >> n;
|
||||
|
||||
std::vector<Point> points(n);
|
||||
CGAL::copy_n(std::istream_iterator<Point>(std::cin), n, points.begin());
|
||||
|
||||
|
||||
std::set<CGAL::Triple<int,int,int> > triangles;
|
||||
|
||||
std::vector<NT> W(n*n);
|
||||
std::vector<NT> O(n*n);
|
||||
|
||||
for(int i = 0; i <= n-2; i++){
|
||||
W[i*n + i + 1] = 0;
|
||||
}
|
||||
for(int i = 0; i <= n-3; i++){
|
||||
W[i*n + i + 2] = weight(points[i], points[i+1], points[i+3]);
|
||||
}
|
||||
|
||||
for(int j = 3; j <= n-1; j++){
|
||||
for(int i=0; i <= n - j - 1; i++){
|
||||
int k = i + j;
|
||||
double lmin = -1;
|
||||
int lmin_index;
|
||||
for(int m = i+1; m < k; m++){
|
||||
double d = W[i*n + m] + W[m*n + k] + weight(points[i], points[m], points[k]);
|
||||
if( (lmin == -1) || (d < lmin )){
|
||||
lmin = d;
|
||||
lmin_index = m;
|
||||
}
|
||||
}
|
||||
W[i*n + k] = lmin;
|
||||
O[i*n + k] = lmin_index;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
collect(0, n-1, n, O, triangles);
|
||||
|
||||
std::cout << "Shape {\n"
|
||||
"appearance Appearance {\n"
|
||||
"material Material { diffuseColor .9 .5 .1}}\n"
|
||||
"geometry\n"
|
||||
"IndexedFaceSet {\n"
|
||||
"coord DEF def_coords Coordinate {\n"
|
||||
"point [ \n" ;
|
||||
|
||||
for (int i = 0; i < n; i++){
|
||||
std::cout << points[i].x() << " " << points[i].y() << " " << points[i].z() << ",\n ";
|
||||
}
|
||||
std::cout << "]\n"
|
||||
"}\n"
|
||||
"solid FALSE\n"
|
||||
"coordIndex [ \n";
|
||||
|
||||
for(std::set<CGAL::Triple<int,int,int> >::iterator it = triangles.begin();
|
||||
it != triangles.end();
|
||||
it++){
|
||||
std::cout << it->first << ", " << it->second << ", " << it->third << ", -1,\n ";
|
||||
}
|
||||
std::cout << "]\n"
|
||||
"}# IndexedFaceSet\n"
|
||||
"}# Shape\n";
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Advancing_front_surface_reconstruction.h>
|
||||
#include <CGAL/tuple.h>
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||
typedef CGAL::Advancing_front_surface_reconstruction<K> Reconstruction;
|
||||
typedef Reconstruction::Triangulation_3 Triangulation_3;
|
||||
typedef Reconstruction::TDS_2 TDS_2;
|
||||
typedef K::Point_3 Point_3;
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
std::istream_iterator<Point_3> begin(std::cin);
|
||||
std::istream_iterator<Point_3> end;
|
||||
|
||||
Triangulation_3 dt(begin,end);
|
||||
|
||||
Reconstruction reconstruction(dt);
|
||||
|
||||
reconstruction();
|
||||
|
||||
const TDS_2& tds = reconstruction.tds_2();
|
||||
|
||||
if(! reconstruction.has_boundaries()){
|
||||
for(TDS_2::Face_iterator fit = tds.faces_begin();
|
||||
fit != tds.faces_end();
|
||||
++fit){
|
||||
Triangulation_3::Facet f = fit->facet();
|
||||
Triangulation_3::Cell_handle ch = f.first;
|
||||
int ci = f.second;
|
||||
for(int i = 0; i < 4; i++){
|
||||
if(ci != i){
|
||||
std:: cout << ch->vertex(i)->point() << " ";
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Advancing_front_surface_reconstruction.h>
|
||||
#include <CGAL/tuple.h>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
typedef Kernel::Point_3 Point_3;
|
||||
|
||||
typedef CGAL::cpp11::tuple<std::size_t,std::size_t,std::size_t> Facet;
|
||||
|
||||
namespace std {
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const Facet& f)
|
||||
{
|
||||
os << "3 " << get<0>(f) << " " << get<1>(f) << " " << get<2>(f);
|
||||
return os;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::vector<Point_3> points;
|
||||
std::vector<Facet> facets;
|
||||
|
||||
std::copy(std::istream_iterator<Point_3>(std::cin),
|
||||
std::istream_iterator<Point_3>(),
|
||||
std::back_inserter(points));
|
||||
|
||||
CGAL::advancing_front_surface_reconstruction(points.begin(),
|
||||
points.end(),
|
||||
std::back_inserter(facets));
|
||||
|
||||
std::cout << "OFF\n" << points.size() << " " << facets.size() << " 0\n";
|
||||
std::copy(points.begin(),
|
||||
points.end(),
|
||||
std::ostream_iterator<Point_3>(std::cout, "\n"));
|
||||
std::copy(facets.begin(),
|
||||
facets.end(),
|
||||
std::ostream_iterator<Facet>(std::cout, "\n"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Advancing_front_surface_reconstruction.h>
|
||||
#include <CGAL/Polyhedron_3.h>
|
||||
#include <CGAL/IO/Polyhedron_iostream.h>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
typedef Kernel::Point_3 Point_3;
|
||||
|
||||
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
std::vector<Point_3> points;
|
||||
Polyhedron P;
|
||||
|
||||
std::copy(std::istream_iterator<Point_3>(std::cin),
|
||||
std::istream_iterator<Point_3>(),
|
||||
std::back_inserter(points));
|
||||
|
||||
CGAL::advancing_front_surface_reconstruction(points.begin(),
|
||||
points.end(),
|
||||
P);
|
||||
|
||||
std::cout << P << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
#ifndef CGAL_AFSR_SURFACE_FACE_BASE_2_H
|
||||
#define CGAL_AFSR_SURFACE_FACE_BASE_2_H
|
||||
|
||||
// This face class stores a facet in the tetrahedrization
|
||||
// When it gets reoriented by the TDS, it also changes the facet
|
||||
|
||||
namespace CGAL {
|
||||
namespace AFSR {
|
||||
|
||||
template < typename GT,
|
||||
typename F3,
|
||||
typename Fb = CGAL::Triangulation_ds_face_base_2<> >
|
||||
class Surface_face_base_2
|
||||
: public Fb
|
||||
{
|
||||
typedef typename Fb::Triangulation_data_structure Tds;
|
||||
|
||||
public:
|
||||
typedef typename Tds::Face_handle Face_handle;
|
||||
typedef typename Tds::Vertex_handle Vertex_handle;
|
||||
|
||||
template < typename TDS2 >
|
||||
struct Rebind_TDS {
|
||||
typedef typename Fb::template Rebind_TDS<TDS2>::Other Fb2;
|
||||
typedef Surface_face_base_2<GT, F3, Fb2> Other;
|
||||
};
|
||||
|
||||
private:
|
||||
F3 _facet;
|
||||
bool _is_on_surface;
|
||||
|
||||
public:
|
||||
Surface_face_base_2()
|
||||
: Fb(), _is_on_surface(true)
|
||||
{}
|
||||
|
||||
Surface_face_base_2(Vertex_handle v0,
|
||||
Vertex_handle v1,
|
||||
Vertex_handle v2)
|
||||
: Fb(v0, v1, v2), _is_on_surface(true)
|
||||
{}
|
||||
|
||||
Surface_face_base_2(Vertex_handle v0,
|
||||
Vertex_handle v1,
|
||||
Vertex_handle v2,
|
||||
Face_handle n0,
|
||||
Face_handle n1,
|
||||
Face_handle n2)
|
||||
: Fb(v0, v1, v2, n0, n1, n2), _is_on_surface(true)
|
||||
{}
|
||||
|
||||
void set_facet(const F3& facet)
|
||||
{
|
||||
_facet = facet;
|
||||
}
|
||||
|
||||
const F3& facet() const
|
||||
{
|
||||
return _facet;
|
||||
}
|
||||
|
||||
void set_is_on_surface(bool is_on_surface)
|
||||
{
|
||||
_is_on_surface = is_on_surface;
|
||||
}
|
||||
|
||||
bool is_on_surface() const
|
||||
{
|
||||
return _is_on_surface;
|
||||
}
|
||||
|
||||
|
||||
void reorient()
|
||||
{
|
||||
Fb::reorient();
|
||||
if( is_on_surface()){
|
||||
_facet = std::make_pair(_facet.first->neighbor(_facet.second),
|
||||
_facet.first->neighbor(_facet.second)->index(_facet.first));
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace AFSR
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_AFSR_SURFACE_FACE_BASE_2_H
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright (c) 2005 GeometryFactory Sarl
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org); you may redistribute it under
|
||||
// the terms of the Q Public License version 1.0.
|
||||
// See the file LICENSE.QPL distributed with CGAL.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Author(s) : Andreas Fabri
|
||||
|
||||
|
||||
#ifndef CGAL_AFSR_SURFACE_VERTEX_BASE_2_H
|
||||
#define CGAL_AFSR_SURFACE_VERTEX_BASE_2_H
|
||||
|
||||
#include <CGAL/basic.h>
|
||||
#include <CGAL/Triangulation_ds_vertex_base_2.h>
|
||||
|
||||
namespace CGAL {
|
||||
namespace AFSR {
|
||||
|
||||
template < typename GT,
|
||||
typename V3,
|
||||
typename Vb = CGAL::Triangulation_ds_vertex_base_2<> >
|
||||
class Surface_vertex_base_2
|
||||
: public Vb
|
||||
|
||||
{
|
||||
typedef typename Vb::Triangulation_data_structure Tds;
|
||||
public:
|
||||
typedef GT Geom_traits;
|
||||
typedef typename GT::Point_3 Point;
|
||||
typedef Tds Triangulation_data_structure;
|
||||
typedef typename Tds::Face_handle Face_handle;
|
||||
typedef typename Tds::Vertex_handle Vertex_handle;
|
||||
|
||||
template < typename TDS2 >
|
||||
struct Rebind_TDS {
|
||||
typedef typename Vb::template Rebind_TDS<TDS2>::Other Vb2;
|
||||
typedef Surface_vertex_base_2<GT,V3, Vb2> Other;
|
||||
};
|
||||
|
||||
private:
|
||||
V3 _vertex;
|
||||
public:
|
||||
Surface_vertex_base_2() : Vb() {}
|
||||
Surface_vertex_base_2(Face_handle f) : Vb(f) {}
|
||||
|
||||
void set_vertex(const V3& v)
|
||||
{
|
||||
_vertex = v;
|
||||
}
|
||||
|
||||
V3 vertex_3() const
|
||||
{
|
||||
return _vertex;
|
||||
}
|
||||
|
||||
const Point& point() const { return _vertex->point(); }
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace AFSR
|
||||
} // namespace CGAL
|
||||
|
||||
#endif //CGAL::AFSR_SURFACE_VERTEX_BASE_2_H
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
#ifndef CGAL_AFSR_CONSTRUCT_POLYHEDRON_2
|
||||
#define CGAL_AFSR_CONSTRUCT_POLYHEDRON_2
|
||||
|
||||
#include <CGAL/Polyhedron_incremental_builder_3.h>
|
||||
#include <CGAL/Polyhedron_3.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <class Kernel, class Triangulation>
|
||||
class Advancing_front_polyhedron_reconstruction;
|
||||
|
||||
namespace AFSR {
|
||||
|
||||
template <class HDS, class Surface>
|
||||
class Construct_polyhedron: public CGAL::Modifier_base<HDS> {
|
||||
|
||||
const Surface& s;
|
||||
|
||||
public:
|
||||
Construct_polyhedron(Surface& s)
|
||||
: s(s)
|
||||
{}
|
||||
|
||||
void operator()( HDS& hds)
|
||||
{
|
||||
CGAL::Polyhedron_incremental_builder_3<HDS> B( hds, true);
|
||||
B.begin_surface( s.number_of_vertices(), s.number_of_facets(), 6* s.number_of_facets());
|
||||
typedef typename HDS::Vertex Vertex;
|
||||
typedef typename Vertex::Point Point;
|
||||
|
||||
typedef typename Surface::TDS_2 TDS_2;
|
||||
typedef typename TDS_2::Face_iterator Face_iterator;
|
||||
typedef typename TDS_2::Vertex_iterator Vertex_iterator;
|
||||
typedef typename Surface::Cell_handle Cell_handle;
|
||||
|
||||
const TDS_2& tds = s.tds_2();
|
||||
|
||||
int index = 0;
|
||||
Vertex_iterator end = tds.vertices_end();
|
||||
|
||||
for(Vertex_iterator vit = tds.vertices_begin(); vit != end; ++vit){
|
||||
if(vit->vertex_3() != s.triangulation().infinite_vertex()){
|
||||
B.add_vertex(vit->point());
|
||||
vit->vertex_3()->id() = index++;
|
||||
}
|
||||
}
|
||||
|
||||
for(Face_iterator fit = tds.faces_begin(); fit != tds.faces_end(); ++fit){
|
||||
|
||||
if(fit->is_on_surface()){
|
||||
B.begin_facet();
|
||||
for(int i=0; i < 3; i++){
|
||||
B.add_vertex_to_facet(fit->vertex(i)->vertex_3()->id());
|
||||
}
|
||||
B.end_facet();
|
||||
}
|
||||
}
|
||||
B.end_surface();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <class Polyhedron, class Surface>
|
||||
void
|
||||
construct_polyhedron(Polyhedron& P, Surface& surface)
|
||||
{
|
||||
typedef typename Polyhedron::HalfedgeDS HalfedgeDS;
|
||||
Construct_polyhedron<HalfedgeDS, Surface> builder(surface);
|
||||
P.delegate(builder);
|
||||
}
|
||||
|
||||
} // namespace AFSR
|
||||
} // namespace CGAL
|
||||
#endif // CGAL_AFSR_CONSTRUCT_POLYHEDRON_2
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
#ifndef CGAL_AFSR_CONSTRUCT_SURFACE_2
|
||||
#define CGAL_AFSR_CONSTRUCT_SURFACE_2
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <class Kernel, class Triangulation>
|
||||
class Advancing_front_surface_reconstruction;
|
||||
|
||||
namespace AFSR {
|
||||
|
||||
|
||||
template <class Kernel, class Triangulation, class TDS>
|
||||
typename TDS::Vertex_handle
|
||||
construct_surface(TDS& tds, const CGAL::Advancing_front_surface_reconstruction<Kernel,Triangulation>& surface)
|
||||
{
|
||||
|
||||
typedef typename TDS::Vertex_handle Vertex_handle;
|
||||
typedef std::pair<Vertex_handle,Vertex_handle> Vh_pair;
|
||||
typedef typename TDS::Face_handle Face_handle;
|
||||
typedef typename TDS::Edge Edge;
|
||||
|
||||
|
||||
Triangulation& T = surface.triangulation();
|
||||
// create an infinite-vertex and infinite faces with the
|
||||
// boundary edges if any.
|
||||
// return the infinite vertex if created
|
||||
Vertex_handle vinf;
|
||||
|
||||
std::vector<Vertex_handle > vvh;
|
||||
if(tds.number_of_vertices() != 0){
|
||||
tds.clear();
|
||||
}
|
||||
int dim = 2;
|
||||
tds.set_dimension(dim);
|
||||
|
||||
CGAL::Unique_hash_map<typename Triangulation::Vertex_handle, int> vertex_index_map(-1, T.number_of_vertices());
|
||||
|
||||
int i=0;
|
||||
for (typename Triangulation::Finite_vertices_iterator v_it = T.finite_vertices_begin();
|
||||
v_it != T.finite_vertices_end();
|
||||
v_it++){
|
||||
typename CGAL::Unique_hash_map<typename Triangulation::Vertex_handle, int>::Data& d = vertex_index_map[v_it];
|
||||
if ((!v_it->is_exterior()) && d == -1){
|
||||
d = i;
|
||||
Vertex_handle vh = tds.create_vertex();
|
||||
vvh.push_back(vh);
|
||||
vh->set_vertex(typename Triangulation::Vertex_handle(v_it));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
std::map<Vh_pair, Edge> edge_map;
|
||||
|
||||
for(typename Triangulation::Finite_facets_iterator f_it = T.finite_facets_begin();
|
||||
f_it != T.finite_facets_end();
|
||||
f_it++)
|
||||
{
|
||||
typename Triangulation::Cell_handle n, c = (*f_it).first;
|
||||
int ni, ci = (*f_it).second;
|
||||
n = c->neighbor(ci);
|
||||
ni = n->index(c);
|
||||
int i1, i2 ,i3;
|
||||
|
||||
if (c->is_selected_facet(ci))
|
||||
{
|
||||
i1 = (ci+1) & 3;
|
||||
i2 = (ci+2) & 3;
|
||||
i3 = (ci+3) & 3;
|
||||
|
||||
Face_handle fh = tds.create_face(vvh[vertex_index_map[c->vertex(i1)]],
|
||||
vvh[vertex_index_map[c->vertex(i2)]],
|
||||
vvh[vertex_index_map[c->vertex(i3)]]);
|
||||
fh->set_facet(*f_it);
|
||||
vvh[vertex_index_map[c->vertex(i1)]]->set_face(fh);
|
||||
vvh[vertex_index_map[c->vertex(i2)]]->set_face(fh);
|
||||
vvh[vertex_index_map[c->vertex(i3)]]->set_face(fh);
|
||||
for (int ih = 0; ih < 3; ++ih) {
|
||||
tds.set_adjacency(fh, ih, edge_map);
|
||||
}
|
||||
}
|
||||
|
||||
if (n->is_selected_facet(ni))
|
||||
{
|
||||
i1 = (ni+1) & 3;
|
||||
i2 = (ni+2) & 3;
|
||||
i3 = (ni+3) & 3;
|
||||
Face_handle fh = tds.create_face(vvh[vertex_index_map[n->vertex(i1)]],
|
||||
vvh[vertex_index_map[n->vertex(i2)]],
|
||||
vvh[vertex_index_map[n->vertex(i3)]]);
|
||||
fh->set_facet(std::make_pair(n, ni));
|
||||
vvh[vertex_index_map[n->vertex(i1)]]->set_face(fh);
|
||||
vvh[vertex_index_map[n->vertex(i2)]]->set_face(fh);
|
||||
vvh[vertex_index_map[n->vertex(i3)]]->set_face(fh);
|
||||
for (int ih = 0; ih < 3; ++ih) {
|
||||
tds.set_adjacency(fh, ih, edge_map);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( !edge_map.empty()) {
|
||||
vinf = tds.create_vertex();
|
||||
vinf->set_vertex(T.infinite_vertex());
|
||||
std::map<Vh_pair, Edge> inf_edge_map;
|
||||
while (!edge_map.empty()) {
|
||||
Face_handle fh = edge_map.begin()->second.first;
|
||||
int ih = edge_map.begin()->second.second;
|
||||
Face_handle fn = tds.create_face( vinf,
|
||||
fh->vertex(TDS::cw(ih)),
|
||||
fh->vertex(TDS::ccw(ih)));
|
||||
fn->set_facet(std::make_pair( typename Triangulation::Cell_handle(),0));
|
||||
fn->set_is_on_surface(false);
|
||||
vinf->set_face(fn);
|
||||
tds.set_adjacency(fn, 0, fh, ih);
|
||||
tds.set_adjacency(fn, 1, inf_edge_map);
|
||||
tds.set_adjacency(fn, 2, inf_edge_map);
|
||||
edge_map.erase(edge_map.begin());
|
||||
}
|
||||
CGAL_triangulation_assertion(inf_edge_map.empty());
|
||||
}
|
||||
tds.reorient_faces();
|
||||
return vinf;
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace AFSR
|
||||
} // namespace CGAL
|
||||
#endif // CGAL_AFSR_CONSTRUCT_SURFACE_2
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
#ifndef CGAL_AFSR_ORIENT
|
||||
|
||||
namespace CGAL {
|
||||
namespace AFSR {
|
||||
|
||||
|
||||
template <class Kernel, class Triangulation, class TDS>
|
||||
typename TDS::Vertex_handle
|
||||
orient(TDS& tds, const Advancing_front_surface_reconstruction<Kernel,Triangulation>& surface)
|
||||
{
|
||||
|
||||
typedef typename TDS::Vertex_handle Vertex_handle;
|
||||
typedef std::pair<Vertex_handle,Vertex_handle> Vh_pair;
|
||||
typedef typename TDS::Face_handle Face_handle;
|
||||
typedef typename TDS::Edge Edge;
|
||||
|
||||
Triangulation& T = surface.triangulation();
|
||||
// create an infinite-vertex and infinite faces with the
|
||||
// boundary edges if any.
|
||||
// return the infinite vertex if created
|
||||
Vertex_handle vinf;
|
||||
|
||||
std::vector<Vertex_handle > vvh;
|
||||
if(tds.number_of_vertices() != 0) tds.clear();
|
||||
int dim = 2;
|
||||
tds.set_dimension(dim);
|
||||
|
||||
CGAL::Unique_hash_map<typename Triangulation::Vertex_handle, int> vertex_index_map(-1, T.number_of_vertices());
|
||||
|
||||
int i=0;
|
||||
for (typename Triangulation::Finite_vertices_iterator v_it = T.finite_vertices_begin();
|
||||
v_it != T.finite_vertices_end();
|
||||
v_it++){
|
||||
typename CGAL::Unique_hash_map<typename Triangulation::Vertex_handle, int>::Data& d = vertex_index_map[v_it];
|
||||
if ((!v_it->is_exterior()) && d == -1){
|
||||
d = i;
|
||||
Vertex_handle vh = tds.create_vertex();
|
||||
vvh.push_back(vh);
|
||||
vh->set_point(v_it->point());
|
||||
i++;
|
||||
}
|
||||
}
|
||||
std::map<Vh_pair, Edge> edge_map;
|
||||
|
||||
|
||||
for(typename Triangulation::Finite_facets_iterator f_it = T.finite_facets_begin();
|
||||
f_it != T.finite_facets_end();
|
||||
f_it++)
|
||||
{
|
||||
typename Triangulation::Cell_handle n, c = (*f_it).first;
|
||||
int ni, ci = (*f_it).second;
|
||||
n = c->neighbor(ci);
|
||||
ni = n->index(c);
|
||||
int i1, i2 ,i3;
|
||||
|
||||
if (c->is_selected_facet(ci))
|
||||
{
|
||||
i1 = (ci+1) & 3;
|
||||
i2 = (ci+2) & 3;
|
||||
i3 = (ci+3) & 3;
|
||||
|
||||
Face_handle fh = tds.create_face(vvh[vertex_index_map[c->vertex(i1)]],
|
||||
vvh[vertex_index_map[c->vertex(i2)]],
|
||||
vvh[vertex_index_map[c->vertex(i3)]]);
|
||||
vvh[vertex_index_map[c->vertex(i1)]]->set_face(fh);
|
||||
vvh[vertex_index_map[c->vertex(i2)]]->set_face(fh);
|
||||
vvh[vertex_index_map[c->vertex(i3)]]->set_face(fh);
|
||||
for (int ih = 0; ih < 3; ++ih) {
|
||||
tds.set_adjacency(fh, ih, edge_map);
|
||||
}
|
||||
}
|
||||
|
||||
if (n->is_selected_facet(ni))
|
||||
{
|
||||
i1 = (ni+1) & 3;
|
||||
i2 = (ni+2) & 3;
|
||||
i3 = (ni+3) & 3;
|
||||
Face_handle fh = tds.create_face(vvh[vertex_index_map[n->vertex(i1)]],
|
||||
vvh[vertex_index_map[n->vertex(i2)]],
|
||||
vvh[vertex_index_map[n->vertex(i3)]]);
|
||||
vvh[vertex_index_map[n->vertex(i1)]]->set_face(fh);
|
||||
vvh[vertex_index_map[n->vertex(i2)]]->set_face(fh);
|
||||
vvh[vertex_index_map[n->vertex(i3)]]->set_face(fh);
|
||||
for (int ih = 0; ih < 3; ++ih) {
|
||||
tds.set_adjacency(fh, ih, edge_map);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( !edge_map.empty()) {
|
||||
vinf = tds.create_vertex();
|
||||
std::map<Vh_pair, Edge> inf_edge_map;
|
||||
while (!edge_map.empty()) {
|
||||
Face_handle fh = edge_map.begin()->second.first;
|
||||
int ih = edge_map.begin()->second.second;
|
||||
Face_handle fn = tds.create_face( vinf,
|
||||
fh->vertex(TDS::cw(ih)),
|
||||
fh->vertex(TDS::ccw(ih)));
|
||||
vinf->set_face(fn);
|
||||
tds.set_adjacency(fn, 0, fh, ih);
|
||||
tds.set_adjacency(fn, 1, inf_edge_map);
|
||||
tds.set_adjacency(fn, 2, inf_edge_map);
|
||||
edge_map.erase(edge_map.begin());
|
||||
}
|
||||
CGAL_triangulation_assertion(inf_edge_map.empty());
|
||||
}
|
||||
|
||||
|
||||
tds.reorient_faces();
|
||||
return vinf;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace AFSR
|
||||
} // namespace CGAL
|
||||
|
||||
#endif //CGAL_AFSR_ORIENT
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
#ifndef CGAL_AFSR_WRITE_TRIPLE_INDICES_H
|
||||
#define CGAL_AFSR_WRITE_TRIPLE_INDICES_H
|
||||
|
||||
#include <CGAL/tuple.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <class Kernel, class Triangulation>
|
||||
class Advancing_front_surface_reconstruction;
|
||||
|
||||
|
||||
|
||||
template <class OutputIterator, class Kernel, class Triangulation>
|
||||
OutputIterator
|
||||
write_triple_indices(OutputIterator out, const Advancing_front_surface_reconstruction<Kernel,Triangulation>& S)
|
||||
{
|
||||
typedef Advancing_front_surface_reconstruction<Kernel,Triangulation> Surface;
|
||||
typedef typename Surface::TDS_2 TDS_2;
|
||||
typedef typename TDS_2::Face_iterator Face_iterator;
|
||||
typedef typename Surface::Cell_handle Cell_handle;
|
||||
|
||||
const TDS_2& tds = S.tds_2();
|
||||
|
||||
for(Face_iterator fit = tds.faces_begin(); fit != tds.faces_end(); ++fit){
|
||||
|
||||
if(fit->is_on_surface()){
|
||||
*out++ = CGAL::cpp11::tuple<std::size_t,std::size_t,std::size_t>(fit->vertex(0)->vertex_3()->id(),
|
||||
fit->vertex(1)->vertex_3()->id(),
|
||||
fit->vertex(2)->vertex_3()->id());
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
#ifndef CGAL_AFSR_OPTIONS_H
|
||||
#define CGAL_AFSR_OPTIONS_H
|
||||
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
class AFSR_options {
|
||||
public:
|
||||
AFSR_options()
|
||||
: file_input(true), file_output(false),
|
||||
Delaunay(false), contour(false), binary(false), xyz(false),
|
||||
Section_file(false), max_connected_comp(-1),
|
||||
delta(.86), K_init(1.1), K_step(.1), K(5), out_format(0),
|
||||
NB_BORDER_MAX(15), red(0), green(0), blue(0), no_header(false), area(0), perimeter(0),
|
||||
abs_area(0), abs_perimeter(0)
|
||||
{
|
||||
std::strcpy(finname,"finput");
|
||||
std::strcpy(foutname,"foutput");
|
||||
}
|
||||
|
||||
char program[100];
|
||||
char finname[100];
|
||||
char foutname[100];
|
||||
bool file_input;
|
||||
bool file_output;
|
||||
bool Delaunay;
|
||||
bool contour;
|
||||
bool binary;
|
||||
bool xyz;
|
||||
bool Section_file;
|
||||
int max_connected_comp;
|
||||
double delta;
|
||||
double K_init;
|
||||
double K_step;
|
||||
double K;
|
||||
int out_format;
|
||||
int NB_BORDER_MAX;
|
||||
double red, green, blue;
|
||||
bool no_header;
|
||||
double area, perimeter, abs_area, abs_perimeter;
|
||||
};
|
||||
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_AFSR_OPTIONS_H
|
||||
|
|
@ -0,0 +1,473 @@
|
|||
#ifndef CGAL_AFSR_VERTEX_BASE_3_H
|
||||
#define CGAL_AFSR_VERTEX_BASE_3_H
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include <CGAL/Triangulation_vertex_base_3.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <class K, class VertexBase = Triangulation_vertex_base_3<K> >
|
||||
class AFSR_vertex_base_3 : public VertexBase
|
||||
{
|
||||
public:
|
||||
|
||||
template < typename TDS2 >
|
||||
struct Rebind_TDS {
|
||||
typedef typename VertexBase::template Rebind_TDS<TDS2>::Other Vb2;
|
||||
typedef AFSR_vertex_base_3<K,Vb2> Other;
|
||||
};
|
||||
|
||||
|
||||
typedef VertexBase Base;
|
||||
typedef typename Base::Vertex_handle Vertex_handle;
|
||||
typedef typename Base::Cell_handle Cell_handle;
|
||||
typedef typename VertexBase::Point Point;
|
||||
typedef double coord_type;
|
||||
|
||||
typedef Triple< Cell_handle, int, int > Edge;
|
||||
typedef std::pair< Edge, int > Edge_incident_facet;
|
||||
typedef std::pair< Edge_incident_facet, Edge_incident_facet > IO_edge_type;
|
||||
|
||||
typedef coord_type criteria;
|
||||
|
||||
typedef std::pair< criteria, IO_edge_type > Radius_edge_type;
|
||||
typedef std::pair< Radius_edge_type, int > Border_elt;
|
||||
typedef std::pair< Vertex_handle, Border_elt > Next_border_elt;
|
||||
|
||||
private:
|
||||
|
||||
//par convention je remplis d'abord first et si necessaire second...
|
||||
typedef std::pair< Next_border_elt*, Next_border_elt*> Intern_successors_type;
|
||||
|
||||
public:
|
||||
|
||||
typedef std::pair< criteria, IO_edge_type* > Radius_ptr_type;
|
||||
typedef std::pair< Vertex_handle, Vertex_handle > Edge_like;
|
||||
typedef std::pair< criteria, Edge_like > Incidence_request_elt;
|
||||
typedef std::list< Incidence_request_elt > Incidence_request_type;
|
||||
typedef typename Incidence_request_type::iterator Incidence_request_iterator;
|
||||
|
||||
// typedef std::set< void* > Interior_edge_set_type;
|
||||
|
||||
//-------------------- DATA MEMBERS ---------------------------------
|
||||
|
||||
private:
|
||||
|
||||
int _mark;
|
||||
int _post_mark;
|
||||
Intern_successors_type* _incident_border;
|
||||
|
||||
// Instead of having a set per vertex, there is a global list.
|
||||
static std::list<Vertex_handle> interior_edges;
|
||||
// and two iterators per vertex in this list
|
||||
// Note that ie_last is not past the end
|
||||
// ie_first == ie_last == interior_edge.end() iff the set is empty
|
||||
typename std::list<Vertex_handle>::iterator ie_first, ie_last;
|
||||
|
||||
|
||||
// We do the same for the incidence requests
|
||||
static std::list< Incidence_request_elt > incidence_requests;
|
||||
typename std::list< Incidence_request_elt >::iterator ir_first, ir_last;
|
||||
//-------------------- CONSTRUCTORS ---------------------------------
|
||||
|
||||
public:
|
||||
|
||||
AFSR_vertex_base_3()
|
||||
: VertexBase(), _mark(-1),
|
||||
_post_mark(-1),
|
||||
ie_first(interior_edges.end()), ie_last(interior_edges.end()),
|
||||
ir_first(incidence_requests.end()), ir_last(incidence_requests.end())
|
||||
{
|
||||
_incident_border = new Intern_successors_type(new Next_border_elt(),
|
||||
new Next_border_elt());
|
||||
_incident_border->first->first = NULL;
|
||||
_incident_border->second->first = NULL;
|
||||
}
|
||||
|
||||
AFSR_vertex_base_3(const Point & p)
|
||||
: VertexBase(p), _mark(-1),
|
||||
_post_mark(-1),
|
||||
ie_first(interior_edges.end()), ie_last(interior_edges.end()),
|
||||
ir_first(incidence_requests.end()), ir_last(incidence_requests.end())
|
||||
{
|
||||
_incident_border = new Intern_successors_type(new Next_border_elt(),
|
||||
new Next_border_elt());
|
||||
_incident_border->first->first = NULL;
|
||||
_incident_border->second->first = NULL;
|
||||
}
|
||||
|
||||
AFSR_vertex_base_3(const Point & p, Cell_handle f)
|
||||
: VertexBase(p, f), _mark(-1),
|
||||
_post_mark(-1),
|
||||
ie_first(interior_edges.end()), ie_last(interior_edges.end()),
|
||||
ir_first(incidence_requests.end()), ir_last(incidence_requests.end())
|
||||
{
|
||||
_incident_border = new Intern_successors_type(new Next_border_elt(),
|
||||
new Next_border_elt());
|
||||
_incident_border->first->first = NULL;
|
||||
_incident_border->second->first = NULL;
|
||||
}
|
||||
|
||||
AFSR_vertex_base_3(Cell_handle f)
|
||||
: VertexBase(f), _mark(-1),
|
||||
_post_mark(-1),
|
||||
ie_first(interior_edges.end()), ie_last(interior_edges.end()),
|
||||
ir_first(incidence_requests.end()), ir_last(incidence_requests.end())
|
||||
{
|
||||
_incident_border = new Intern_successors_type(new Next_border_elt(),
|
||||
new Next_border_elt());
|
||||
_incident_border->first->first = NULL;
|
||||
_incident_border->second->first = NULL;
|
||||
}
|
||||
|
||||
AFSR_vertex_base_3(const AFSR_vertex_base_3& other)
|
||||
: VertexBase(), _mark(-1),
|
||||
_post_mark(-1),
|
||||
ie_first(interior_edges.end()), ie_last(interior_edges.end()),
|
||||
ir_first(incidence_requests.end()), ir_last(incidence_requests.end())
|
||||
{
|
||||
_incident_border = new Intern_successors_type(new Next_border_elt(),
|
||||
new Next_border_elt());
|
||||
_incident_border->first->first = NULL;
|
||||
_incident_border->second->first = NULL;
|
||||
}
|
||||
//-------------------- DESTRUCTOR -----------------------------------
|
||||
|
||||
~AFSR_vertex_base_3()
|
||||
{
|
||||
if (_incident_border != NULL)
|
||||
{
|
||||
delete _incident_border->first;
|
||||
delete _incident_border->second;
|
||||
delete _incident_border;
|
||||
}
|
||||
if(ir_first != incidence_requests.end()){
|
||||
assert(ir_last != incidence_requests.end());
|
||||
typename std::list< Incidence_request_elt >::iterator b(ir_first), e(ir_last);
|
||||
e++;
|
||||
incidence_requests.erase(b, e);
|
||||
}
|
||||
|
||||
if(ie_first != interior_edges.end()){
|
||||
assert(ie_last != interior_edges.end());
|
||||
typename std::list<Vertex_handle>::iterator b(ie_first), e(ie_last);
|
||||
e++;
|
||||
interior_edges.erase(b, e);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------- MEMBER FUNCTIONS -----------------------------
|
||||
|
||||
inline void re_init()
|
||||
{
|
||||
if (_incident_border != NULL)
|
||||
{
|
||||
delete _incident_border->first;
|
||||
delete _incident_border->second;
|
||||
delete _incident_border;
|
||||
}
|
||||
|
||||
if(ir_first != incidence_requests.end()){
|
||||
assert(ir_last != incidence_requests.end());
|
||||
typename std::list< Incidence_request_elt >::iterator b(ir_first), e(ir_last);
|
||||
e++;
|
||||
incidence_requests.erase(b, e);
|
||||
ir_first = incidence_requests.end();
|
||||
ir_last = incidence_requests.end();
|
||||
}
|
||||
|
||||
_incident_border = new Intern_successors_type(new Next_border_elt(),
|
||||
new Next_border_elt());
|
||||
_incident_border->first->first = NULL;
|
||||
_incident_border->second->first = NULL;
|
||||
_mark = -1;
|
||||
_post_mark = -1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
inline bool is_on_border(const int& i) const
|
||||
{
|
||||
if (_incident_border == NULL) return false; //vh is interior
|
||||
if (_incident_border->first->first != NULL)
|
||||
{
|
||||
if (_incident_border->second->first != NULL)
|
||||
return ((_incident_border->first->second.second == i)||
|
||||
(_incident_border->second->second.second == i));
|
||||
return (_incident_border->first->second.second == i);
|
||||
}
|
||||
return false; //vh is still exterior
|
||||
}
|
||||
|
||||
inline Next_border_elt* get_next_on_border(const int& i) const
|
||||
{
|
||||
if (_incident_border == NULL) return NULL; //vh is interior
|
||||
if (_incident_border->first->first != NULL)
|
||||
if (_incident_border->first->second.second == i)
|
||||
return _incident_border->first;
|
||||
if (_incident_border->second->first != NULL)
|
||||
if (_incident_border->second->second.second == i)
|
||||
return _incident_border->second;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
inline void remove_border_edge(Vertex_handle v)
|
||||
{
|
||||
if (_incident_border != NULL)
|
||||
{
|
||||
if (_incident_border->second->first == v)
|
||||
{
|
||||
_incident_border->second->first = NULL;
|
||||
set_interior_edge(v);
|
||||
return;
|
||||
}
|
||||
if (_incident_border->first->first == v)
|
||||
{
|
||||
if (_incident_border->second->first != NULL)
|
||||
{
|
||||
Next_border_elt* tmp = _incident_border->first;
|
||||
_incident_border->first = _incident_border->second;
|
||||
_incident_border->second = tmp;
|
||||
_incident_border->second->first = NULL;
|
||||
set_interior_edge(v);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
_incident_border->first->first = NULL;
|
||||
set_interior_edge(v);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline bool is_border_edge(Vertex_handle v) const
|
||||
{
|
||||
if (_incident_border == NULL) return false;
|
||||
return ((_incident_border->first->first == v)||
|
||||
(_incident_border->second->first == v));
|
||||
}
|
||||
|
||||
inline Next_border_elt* get_border_elt(Vertex_handle v) const
|
||||
{
|
||||
if (_incident_border == NULL) return NULL;
|
||||
if (_incident_border->first->first == v) return _incident_border->first;
|
||||
if (_incident_border->second->first == v) return _incident_border->second;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline Next_border_elt* first_incident() const
|
||||
{
|
||||
if (_incident_border == NULL) return NULL;
|
||||
return _incident_border->first;
|
||||
}
|
||||
|
||||
inline Next_border_elt* second_incident() const
|
||||
{
|
||||
if (_incident_border == NULL) return NULL;
|
||||
return _incident_border->second;
|
||||
}
|
||||
|
||||
|
||||
inline void set_next_border_elt(const Next_border_elt& elt)
|
||||
{
|
||||
if (_incident_border->first->first == NULL)
|
||||
*_incident_border->first = elt;
|
||||
else
|
||||
{
|
||||
if (_incident_border->second->first != NULL)
|
||||
std::cerr << "+++probleme de MAJ du bord <Vertex_base>" << std::endl;
|
||||
*_incident_border->second = elt;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// pour gerer certaines aretes interieures: a savoir celle encore connectee au
|
||||
// bord (en fait seule, les aretes interieures reliant 2 bords nous
|
||||
// interressent...)
|
||||
|
||||
inline bool is_interior_edge(Vertex_handle v) const
|
||||
{
|
||||
|
||||
bool r1;
|
||||
if(ie_first == interior_edges.end()){
|
||||
r1 = false;
|
||||
}else {
|
||||
typename std::list<Vertex_handle>::iterator b(ie_first), e(ie_last);
|
||||
e++;
|
||||
typename std::list<Vertex_handle>::iterator r = std::find(b, e, v);
|
||||
r1 = ( r != e);
|
||||
}
|
||||
|
||||
return r1;
|
||||
}
|
||||
|
||||
inline void set_interior_edge(Vertex_handle v)
|
||||
{
|
||||
if(ie_last == interior_edges.end()){ // empty set
|
||||
assert(ie_first == ie_last);
|
||||
ie_last = interior_edges.insert(ie_last, v);
|
||||
ie_first = ie_last;
|
||||
} else {
|
||||
typename std::list<Vertex_handle>::iterator e(ie_last);
|
||||
e++;
|
||||
#ifdef DEBUG
|
||||
typename std::list<Vertex_handle>::iterator r = std::find(ie_first, e, v);
|
||||
#endif
|
||||
assert(r == e);
|
||||
ie_last = interior_edges.insert(e, v);
|
||||
}
|
||||
}
|
||||
|
||||
inline void remove_interior_edge(Vertex_handle v)
|
||||
{
|
||||
if(ie_first == interior_edges.end()){
|
||||
assert(ie_last == ie_first);
|
||||
} else if(ie_first == ie_last){ // there is only one element
|
||||
if(*ie_first == v){
|
||||
interior_edges.erase(ie_first);
|
||||
ie_last = interior_edges.end();
|
||||
ie_first = ie_last;
|
||||
}
|
||||
} else {
|
||||
typename std::list<Vertex_handle>::iterator b(ie_first), e(ie_last);
|
||||
e++;
|
||||
typename std::list<Vertex_handle>::iterator r = std::find(b, e, v);
|
||||
if(r != e){
|
||||
if(r == ie_first){
|
||||
ie_first++;
|
||||
}
|
||||
if(r == ie_last){
|
||||
ie_last--;
|
||||
}
|
||||
interior_edges.erase(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
inline void set_incidence_request(const Incidence_request_elt& ir)
|
||||
{
|
||||
if(ir_last == incidence_requests.end()){
|
||||
assert(ir_first == ir_last);
|
||||
ir_last = incidence_requests.insert(ir_last, ir);
|
||||
ir_first = ir_last;
|
||||
} else {
|
||||
typename std::list<Incidence_request_elt>::iterator e(ir_last);
|
||||
e++;
|
||||
ir_last = incidence_requests.insert(e, ir);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool is_incidence_requested() const
|
||||
{
|
||||
if(ir_last == incidence_requests.end()){
|
||||
assert(ir_first == incidence_requests.end());
|
||||
}
|
||||
return (ir_last != incidence_requests.end());
|
||||
}
|
||||
|
||||
inline Incidence_request_iterator incidence_request_begin()
|
||||
{
|
||||
return ir_first;
|
||||
}
|
||||
|
||||
inline Incidence_request_iterator get_incidence_request_end()
|
||||
{
|
||||
if(ir_last != incidence_requests.end()){
|
||||
assert(ir_first != incidence_requests.end());
|
||||
Incidence_request_iterator it(ir_last);
|
||||
it++;
|
||||
return it;
|
||||
}
|
||||
return ir_last;
|
||||
}
|
||||
|
||||
inline void erase_incidence_request()
|
||||
{
|
||||
if(ir_last != incidence_requests.end()){
|
||||
assert(ir_first != incidence_requests.end());
|
||||
ir_last++;
|
||||
incidence_requests.erase(ir_first, ir_last);
|
||||
ir_first = incidence_requests.end();
|
||||
ir_last = incidence_requests.end();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
inline bool is_on_border() const
|
||||
{
|
||||
return (_mark > 0);
|
||||
}
|
||||
|
||||
inline bool not_interior() const
|
||||
{
|
||||
return (_mark != 0);
|
||||
}
|
||||
|
||||
inline int number_of_incident_border() const
|
||||
{
|
||||
return _mark;
|
||||
}
|
||||
|
||||
inline bool is_exterior() const
|
||||
{
|
||||
return (_mark < 0);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
inline void inc_mark()
|
||||
{
|
||||
if (_mark==-1)
|
||||
_mark=1;
|
||||
else
|
||||
_mark++;
|
||||
}
|
||||
|
||||
inline void dec_mark()
|
||||
{
|
||||
_mark--;
|
||||
if(_mark == 0)
|
||||
{
|
||||
delete _incident_border->first;
|
||||
delete _incident_border->second;
|
||||
delete _incident_border;
|
||||
_incident_border = NULL;
|
||||
erase_incidence_request();
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
inline void set_post_mark(const int& i)
|
||||
{
|
||||
_post_mark = i;
|
||||
}
|
||||
|
||||
inline bool is_post_marked(const int& i)
|
||||
{
|
||||
return (_post_mark == i);
|
||||
}
|
||||
};
|
||||
|
||||
template <class K, class VertexBase>
|
||||
std::list<typename AFSR_vertex_base_3<K,VertexBase>::Vertex_handle> AFSR_vertex_base_3<K,VertexBase>::interior_edges;
|
||||
|
||||
template <class K, class VertexBase>
|
||||
std::list<typename AFSR_vertex_base_3<K,VertexBase>::Incidence_request_elt> AFSR_vertex_base_3<K,VertexBase>::incidence_requests;
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif //CGAL_AFSR_VERTEX_BASE_3_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,226 @@
|
|||
#ifndef CGAL_ADVANCING_FRONT_SURFACE_RECONSTRUCTION_CELL_BASE_3_H
|
||||
#define CGAL_ADVANCING_FRONT_SURFACE_RECONSTRUCTION_CELL_BASE_3_H
|
||||
|
||||
#include <CGAL/Triangulation_cell_base_3.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template < class Kernel, class CellBase = Triangulation_cell_base_3<Kernel> >
|
||||
class Advancing_front_surface_reconstruction_cell_base_3 : public CellBase
|
||||
{
|
||||
|
||||
public:
|
||||
template < typename TDS2 >
|
||||
struct Rebind_TDS {
|
||||
typedef typename CellBase::template Rebind_TDS<TDS2>::Other Cb2;
|
||||
typedef Advancing_front_surface_reconstruction_cell_base_3<Kernel,Cb2> Other;
|
||||
};
|
||||
|
||||
typedef typename CellBase::Vertex_handle Vertex_handle;
|
||||
typedef typename CellBase::Cell_handle Cell_handle;
|
||||
|
||||
private:
|
||||
|
||||
#ifdef AFSR_FACET_NUMBER
|
||||
int _facet_number[4];
|
||||
#endif
|
||||
typedef double coord_type;
|
||||
#ifdef AFSR_LAZY
|
||||
typedef typename CGAL::Simple_cartesian<coord_type>::Point_3 D_Point;
|
||||
#endif
|
||||
//-------------------- DATA MEMBERS ---------------------------------
|
||||
|
||||
coord_type* _smallest_radius_facet_tab;
|
||||
unsigned char selected_facet;
|
||||
#ifdef AFSR_LAZY
|
||||
D_Point* _circumcenter;
|
||||
coord_type* _squared_radius;
|
||||
#endif
|
||||
|
||||
//-------------------- CONSTRUCTORS ----------------------------------
|
||||
|
||||
public:
|
||||
|
||||
Advancing_front_surface_reconstruction_cell_base_3()
|
||||
: CellBase(),
|
||||
_smallest_radius_facet_tab(NULL), selected_facet(0)
|
||||
#ifdef AFSR_LAZY
|
||||
, _circumcenter(NULL), _squared_radius(NULL)
|
||||
#endif
|
||||
{
|
||||
#ifdef AFSR_FACET_NUMBER
|
||||
for(int i = 0; i < 4; i++){
|
||||
_facet_number[i] = -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Advancing_front_surface_reconstruction_cell_base_3(Vertex_handle v0, Vertex_handle v1, Vertex_handle v2, Vertex_handle v3)
|
||||
: CellBase( v0, v1, v2, v3),
|
||||
_smallest_radius_facet_tab(NULL), selected_facet(0)
|
||||
#ifdef AFSR_LAZY
|
||||
, _circumcenter(NULL), _squared_radius(NULL)
|
||||
#endif
|
||||
{
|
||||
#ifdef FACET_NUMBER
|
||||
for(int i = 0; i < 4; i++){
|
||||
_facet_number[i] = -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Advancing_front_surface_reconstruction_cell_base_3(Vertex_handle v0, Vertex_handle v1, Vertex_handle v2, Vertex_handle v3,
|
||||
Cell_handle n0, Cell_handle n1, Cell_handle n2, Cell_handle n3)
|
||||
: CellBase(v0, v1, v2, v3,
|
||||
n0, n1, n2, n3),
|
||||
_smallest_radius_facet_tab(NULL), selected_facet(0)
|
||||
#ifdef AFSR_LAZY
|
||||
, _circumcenter(NULL), _squared_radius(NULL)
|
||||
#endif
|
||||
{
|
||||
#ifdef AFSR_FACET_NUMBER
|
||||
for(int i = 0; i < 4; i++){
|
||||
_facet_number[i] = -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-------------------- DESTRUCTOR -----------------------------------
|
||||
|
||||
inline ~Advancing_front_surface_reconstruction_cell_base_3()
|
||||
{
|
||||
if (_smallest_radius_facet_tab != NULL)
|
||||
delete[] _smallest_radius_facet_tab;
|
||||
#ifdef AFSR_LAZY
|
||||
if (_circumcenter != NULL)
|
||||
delete _circumcenter;
|
||||
if (_squared_radius != NULL)
|
||||
delete _squared_radius;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-------------------- MEMBER FUNCTIONS ----------------------------
|
||||
|
||||
public:
|
||||
|
||||
inline void clear()
|
||||
{
|
||||
if (_smallest_radius_facet_tab != NULL)
|
||||
delete[] _smallest_radius_facet_tab;
|
||||
_smallest_radius_facet_tab = NULL;
|
||||
selected_facet = 0;
|
||||
#ifdef AFSR_LAZY
|
||||
if (_circumcenter != NULL)
|
||||
delete _circumcenter;
|
||||
_circumcenter = NULL;
|
||||
if (_squared_radius != NULL)
|
||||
delete _squared_radius;
|
||||
_squared_radius = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
inline coord_type smallest_radius(const int& i)
|
||||
{
|
||||
if (_smallest_radius_facet_tab == NULL)
|
||||
return -1;
|
||||
return _smallest_radius_facet_tab[i];
|
||||
}
|
||||
|
||||
inline void set_smallest_radius(const int& i, const coord_type& c)
|
||||
{
|
||||
if (_smallest_radius_facet_tab == NULL)
|
||||
{
|
||||
_smallest_radius_facet_tab = new coord_type[4];
|
||||
for(int i = 0; i < 4; i++)
|
||||
_smallest_radius_facet_tab[i] = -1;
|
||||
}
|
||||
_smallest_radius_facet_tab[i] = c;
|
||||
}
|
||||
|
||||
// pour un controle de l'allocation memoire... utile???
|
||||
inline bool alloc_smallest_radius_tab(coord_type* ptr)
|
||||
{
|
||||
if (_smallest_radius_facet_tab==NULL)
|
||||
{
|
||||
_smallest_radius_facet_tab = ptr;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
#ifdef FACET_NUMBER
|
||||
void set_facet_number(int i, int n){}
|
||||
{
|
||||
_facet_number[i] = n;
|
||||
}
|
||||
|
||||
int facet_number(int i)
|
||||
{
|
||||
return _facet_number[i];
|
||||
}
|
||||
#else
|
||||
void set_facet_number(int, int){}
|
||||
int facet_number(int){return 0;}
|
||||
#endif
|
||||
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
inline void select_facet(const int& i)
|
||||
{
|
||||
selected_facet |= (1 << i);
|
||||
}
|
||||
|
||||
inline void unselect_facet(const int& i)
|
||||
{
|
||||
selected_facet &= (15 - (1 << i));
|
||||
}
|
||||
|
||||
inline bool is_selected_facet(const int& i)
|
||||
{
|
||||
return (selected_facet & (1 << i)) != 0;
|
||||
}
|
||||
|
||||
inline bool has_facet_on_surface(const int& i)
|
||||
{
|
||||
return (selected_facet & (1 << i)) != 0;
|
||||
}
|
||||
|
||||
#ifdef AFSR_LAZY
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
inline D_Point* lazy_circumcenter()
|
||||
{
|
||||
return _circumcenter;
|
||||
}
|
||||
|
||||
inline void set_lazy_circumcenter(const D_Point& p)
|
||||
{
|
||||
_circumcenter = new D_Point(p);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
inline coord_type* lazy_squared_radius()
|
||||
{
|
||||
return _squared_radius;
|
||||
}
|
||||
|
||||
inline void set_lazy_squared_radius(const coord_type& sr)
|
||||
{
|
||||
_squared_radius = new coord_type(sr);
|
||||
}
|
||||
|
||||
#endif //AFSR_LAZY
|
||||
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_ADVANCING_FRONT_SURFACE_RECONSTRUCTION_CELL_BASE_3_H
|
||||
|
|
@ -0,0 +1,257 @@
|
|||
#ifndef CGAL_ADVANCING_FRONT_SURFACE_RECONSTRUCTION_VERTEX_BASE_WITH_ID_3_H
|
||||
#define CGAL_ADVANCING_FRONT_SURFACE_RECONSTRUCTION_VERTEX_BASE_WITH_ID_3_H
|
||||
|
||||
#include <CGAL/Triangulation_vertex_base_3.h>
|
||||
#include <CGAL/utility.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <list>
|
||||
|
||||
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <class A, class B> class Advancing_front_surface_reconstruction;
|
||||
|
||||
template <class K, class VertexBase = Triangulation_vertex_base_3<K> >
|
||||
class Advancing_front_surface_reconstruction_vertex_base_3 : public VertexBase
|
||||
{
|
||||
public:
|
||||
|
||||
template < typename TDS2 >
|
||||
struct Rebind_TDS {
|
||||
typedef typename VertexBase::template Rebind_TDS<TDS2>::Other Vb2;
|
||||
typedef Advancing_front_surface_reconstruction_vertex_base_3<K,Vb2> Other;
|
||||
};
|
||||
|
||||
|
||||
template <class A, class B > friend class Advancing_front_surface_reconstruction;
|
||||
|
||||
|
||||
typedef VertexBase Base;
|
||||
typedef typename Base::Vertex_handle Vertex_handle;
|
||||
typedef typename Base::Cell_handle Cell_handle;
|
||||
typedef typename VertexBase::Point Point;
|
||||
typedef double coord_type;
|
||||
|
||||
typedef Triple< Cell_handle, int, int > Edge;
|
||||
typedef std::pair< Edge, int > Edge_incident_facet;
|
||||
typedef std::pair< Edge_incident_facet, Edge_incident_facet > IO_edge_type;
|
||||
|
||||
typedef coord_type criteria;
|
||||
|
||||
typedef std::pair< criteria, IO_edge_type > Radius_edge_type;
|
||||
typedef std::pair< Radius_edge_type, int > Border_elt;
|
||||
typedef std::pair< Vertex_handle, Border_elt > Next_border_elt;
|
||||
|
||||
|
||||
//par convention je remplis d'abord first et si necessaire second...
|
||||
typedef std::pair< Next_border_elt*, Next_border_elt*> Intern_successors_type;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
typedef std::pair< criteria, IO_edge_type* > Radius_ptr_type;
|
||||
typedef std::pair< Vertex_handle, Vertex_handle > Edge_like;
|
||||
typedef std::pair< criteria, Edge_like > Incidence_request_elt;
|
||||
typedef std::list< Incidence_request_elt > Incidence_request_type;
|
||||
typedef typename Incidence_request_type::iterator Incidence_request_iterator;
|
||||
|
||||
|
||||
//-------------------- DATA MEMBERS ---------------------------------
|
||||
|
||||
typedef int Info; // so that we are a model of TriangulationVertexBaseWithInfo_3
|
||||
|
||||
private:
|
||||
int m_id;
|
||||
int m_mark;
|
||||
int m_post_mark;
|
||||
Intern_successors_type* m_incident_border;
|
||||
|
||||
// Instead of having a set per vertex, there is a global list
|
||||
// in the surface reconstruction class
|
||||
// and two iterators per vertex in this list
|
||||
// Note that m_ie_last is not past the end
|
||||
// m_ie_first == m_ie_last == interior_edge.end() iff the set is empty
|
||||
typename std::list<Vertex_handle>::iterator m_ie_first, m_ie_last;
|
||||
|
||||
|
||||
// We do the same for the incidence requests
|
||||
typename std::list< Incidence_request_elt >::iterator m_ir_first, m_ir_last;
|
||||
|
||||
|
||||
//-------------------- CONSTRUCTORS ---------------------------------
|
||||
|
||||
public:
|
||||
|
||||
Advancing_front_surface_reconstruction_vertex_base_3()
|
||||
: VertexBase(), m_mark(-1),
|
||||
m_post_mark(-1)
|
||||
{}
|
||||
|
||||
Advancing_front_surface_reconstruction_vertex_base_3(const Point & p)
|
||||
: VertexBase(p), m_mark(-1),
|
||||
m_post_mark(-1)
|
||||
{}
|
||||
|
||||
Advancing_front_surface_reconstruction_vertex_base_3(const Point & p, Cell_handle f)
|
||||
: VertexBase(p, f), m_mark(-1),
|
||||
m_post_mark(-1)
|
||||
{}
|
||||
|
||||
Advancing_front_surface_reconstruction_vertex_base_3(Cell_handle f)
|
||||
: VertexBase(f), m_mark(-1),
|
||||
m_post_mark(-1)
|
||||
{}
|
||||
|
||||
Advancing_front_surface_reconstruction_vertex_base_3(const Advancing_front_surface_reconstruction_vertex_base_3& other)
|
||||
: VertexBase(), m_mark(-1),
|
||||
m_post_mark(-1)
|
||||
{}
|
||||
|
||||
//-------------------- MEMBER FUNCTIONS -----------------------------
|
||||
|
||||
public:
|
||||
|
||||
int& id()
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
const int& id() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
int& info()
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
const int& info() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
private:
|
||||
|
||||
void delete_border()
|
||||
{
|
||||
m_incident_border = NULL;
|
||||
}
|
||||
|
||||
|
||||
inline Next_border_elt* next_on_border(const int& i) const
|
||||
{
|
||||
if (m_incident_border == NULL) return NULL; //vh is interior
|
||||
if (m_incident_border->first->first != NULL)
|
||||
if (m_incident_border->first->second.second == i)
|
||||
return m_incident_border->first;
|
||||
if (m_incident_border->second->first != NULL)
|
||||
if (m_incident_border->second->second.second == i)
|
||||
return m_incident_border->second;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
inline bool is_border_edge(Vertex_handle v) const
|
||||
{
|
||||
if (m_incident_border == NULL) return false;
|
||||
return ((m_incident_border->first->first == v)||
|
||||
(m_incident_border->second->first == v));
|
||||
}
|
||||
|
||||
inline Next_border_elt* border_elt(Vertex_handle v) const
|
||||
{
|
||||
if (m_incident_border == NULL) return NULL;
|
||||
if (m_incident_border->first->first == v) return m_incident_border->first;
|
||||
if (m_incident_border->second->first == v) return m_incident_border->second;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
public:
|
||||
inline Next_border_elt* first_incident() const
|
||||
{
|
||||
if (m_incident_border == NULL) return NULL;
|
||||
return m_incident_border->first;
|
||||
}
|
||||
private:
|
||||
inline Next_border_elt* second_incident() const
|
||||
{
|
||||
if (m_incident_border == NULL) return NULL;
|
||||
return m_incident_border->second;
|
||||
}
|
||||
|
||||
|
||||
inline void set_next_border_elt(const Next_border_elt& elt)
|
||||
{
|
||||
if (m_incident_border->first->first == NULL)
|
||||
*m_incident_border->first = elt;
|
||||
else
|
||||
{
|
||||
if (m_incident_border->second->first != NULL)
|
||||
std::cerr << "+++probleme de MAJ du bord <Vertex_base>" << std::endl;
|
||||
*m_incident_border->second = elt;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
|
||||
inline bool is_on_border() const
|
||||
{
|
||||
return (m_mark > 0);
|
||||
}
|
||||
|
||||
inline bool not_interior() const
|
||||
{
|
||||
return (m_mark != 0);
|
||||
}
|
||||
|
||||
inline int number_of_incident_border() const
|
||||
{
|
||||
return m_mark;
|
||||
}
|
||||
|
||||
inline bool is_exterior() const
|
||||
{
|
||||
return (m_mark < 0);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
private:
|
||||
|
||||
inline void inc_mark()
|
||||
{
|
||||
if (m_mark==-1)
|
||||
m_mark=1;
|
||||
else
|
||||
m_mark++;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
public:
|
||||
inline void set_post_mark(const int& i)
|
||||
{
|
||||
m_post_mark = i;
|
||||
}
|
||||
|
||||
inline bool is_post_marked(const int& i)
|
||||
{
|
||||
return (m_post_mark == i);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_ADVANCING_FRONT_SURFACE_RECONSTRUCTION_VERTEX_BASE_3_H
|
||||
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
#ifndef CGAL_AFSR_VRML_H
|
||||
#define CGAL_AFSR_VRML_H
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template < class Vb, class Fb>
|
||||
void
|
||||
afsr_vrml_output(const Triangulation_data_structure_2<Vb,Fb>& tds,
|
||||
std::ostream& os, double r, double g, double b,
|
||||
typename Triangulation_data_structure_2<Vb,Fb>::Vertex_handle v, bool skip_infinite)
|
||||
{
|
||||
typedef typename Triangulation_data_structure_2<Vb,Fb>::Vertex_handle Vertex_handle;
|
||||
typedef typename Triangulation_data_structure_2<Vb,Fb>::Vertex_iterator Vertex_iterator;
|
||||
typedef typename Triangulation_data_structure_2<Vb,Fb>::Face_iterator Face_iterator;
|
||||
|
||||
// ouput to a vrml file style
|
||||
// Point are assumed to be 3d points with a stream operator <<
|
||||
// if non NULL, v is the vertex to be output first
|
||||
// if skip_inf is true, the point in the first vertex is not output
|
||||
// and the faces incident to v are not output
|
||||
// (it may be for instance the infinite vertex of the terrain)
|
||||
|
||||
os << "#VRML V2.0 utf8" << std::endl;
|
||||
os << "Shape {\n"
|
||||
<< "appearance Appearance {\n"
|
||||
<< "material Material { diffuseColor " << r << " " << g << " " << b << "}}\n";
|
||||
os << "\tgeometry IndexedFaceSet {" << std::endl;
|
||||
os << "\t\tcoord Coordinate {" << std::endl;
|
||||
os << "\t\t\tpoint [" << std::endl;
|
||||
|
||||
std::map<Vertex_handle,int> vmap;
|
||||
Vertex_iterator vit;
|
||||
Face_iterator fit;
|
||||
|
||||
int inum = 0;
|
||||
for( vit= tds.vertices_begin(); vit != tds.vertices_end() ; ++vit) {
|
||||
if ( v != vit) {
|
||||
vmap[vit] = inum++;
|
||||
os << "\t\t\t\t" << *vit << ","<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
os << "\t\t\t]" << std::endl;
|
||||
os << "\t\t}" << std::endl;
|
||||
os << "\t\tsolid FALSE\n"
|
||||
"\t\tcoordIndex [" << std::endl;
|
||||
|
||||
// faces
|
||||
for(fit= tds.faces_begin(); fit != tds.faces_end(); ++fit) {
|
||||
if (!skip_infinite || !fit->has_vertex(v)) {
|
||||
os << "\t\t\t";
|
||||
os << vmap[(*fit).vertex(0)] << ", ";
|
||||
os << vmap[(*fit).vertex(1)] << ", ";
|
||||
os << vmap[(*fit).vertex(2)] << ", ";
|
||||
os << "-1, " << std::endl;
|
||||
}
|
||||
}
|
||||
os << "\t\t]" << std::endl;
|
||||
os << "\t}" << std::endl;
|
||||
os << "}" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,94 @@
|
|||
// Copyright (c) 1997 INRIA Sophia-Antipolis (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org); you may redistribute it under
|
||||
// the terms of the Q Public License version 1.0.
|
||||
// See the file LICENSE.QPL distributed with CGAL.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// $Source: /CVSROOT/CGAL/Packages/Triangulation_2/include/CGAL/Triangulation_vertex_base_2.h,v $
|
||||
// $Revision$ $Date$
|
||||
// $Name: current_submission $
|
||||
//
|
||||
// Author(s) : Mariette Yvinec
|
||||
|
||||
|
||||
#ifndef CGAL_TVB_3_2_H
|
||||
#define CGAL_TVB_3_2_H
|
||||
|
||||
#include <CGAL/basic.h>
|
||||
#include <CGAL/Triangulation_ds_vertex_base_2.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template < typename GT,
|
||||
typename Vb = Triangulation_ds_vertex_base_2<> >
|
||||
class Tvb_3_2
|
||||
: public Vb
|
||||
|
||||
{
|
||||
typedef typename Vb::Triangulation_data_structure Tds;
|
||||
public:
|
||||
typedef GT Geom_traits;
|
||||
typedef typename GT::Point_3 Point;
|
||||
typedef Tds Triangulation_data_structure;
|
||||
typedef typename Tds::Face_handle Face_handle;
|
||||
typedef typename Tds::Vertex_handle Vertex_handle;
|
||||
|
||||
template < typename TDS2 >
|
||||
struct Rebind_TDS {
|
||||
typedef typename Vb::template Rebind_TDS<TDS2>::Other Vb2;
|
||||
typedef Tvb_3_2<GT, Vb2> Other;
|
||||
};
|
||||
|
||||
private:
|
||||
Point _p;
|
||||
|
||||
public:
|
||||
Tvb_3_2 () : Vb() {}
|
||||
Tvb_3_2(const Point & p) : Vb(), _p(p) {}
|
||||
Tvb_3_2(const Point & p, Face_handle f)
|
||||
: Vb(f), _p(p) {}
|
||||
Tvb_3_2(Face_handle f) : Vb(f) {}
|
||||
|
||||
void set_point(const Point & p) { _p = p; }
|
||||
const Point& point() const { return _p; }
|
||||
|
||||
// the non const version of point() is undocument
|
||||
// but needed to make the point iterator works
|
||||
// using Lutz projection scheme
|
||||
Point& point() { return _p; }
|
||||
|
||||
//the following trivial is_valid to allow
|
||||
// the user of derived face base classes
|
||||
// to add their own purpose checking
|
||||
bool is_valid(bool /* verbose */ = false, int /* level */ = 0) const
|
||||
{return true;}
|
||||
};
|
||||
|
||||
template < class GT, class Vb >
|
||||
std::istream&
|
||||
operator>>(std::istream &is, Tvb_3_2<GT, Vb> &v)
|
||||
// non combinatorial information. Default = point
|
||||
{
|
||||
return is >> static_cast<Vb&>(v) >> v.point();
|
||||
}
|
||||
|
||||
template < class GT, class Vb >
|
||||
std::ostream&
|
||||
operator<<(std::ostream &os, const Tvb_3_2<GT, Vb> &v)
|
||||
// non combinatorial information. Default = point
|
||||
{
|
||||
return os << static_cast<const Vb&>(v) << v.point();
|
||||
}
|
||||
|
||||
|
||||
|
||||
} //namespace CGAL
|
||||
|
||||
#endif //CGAL_TVB_3_2_H
|
||||
|
|
@ -0,0 +1 @@
|
|||
INRIA Sophia-Antipolis (France)
|
||||
|
|
@ -0,0 +1 @@
|
|||
Surface reconstruction using an advancing front method.
|
||||
|
|
@ -0,0 +1 @@
|
|||
GPL (v3 or later)
|
||||
|
|
@ -0,0 +1 @@
|
|||
Andreas Fabri <Andreas.Fabri@geometryfactory.com>
|
||||
|
|
@ -387,6 +387,16 @@ note="Conference version: Symp. on Geometry Processing 2003"
|
|||
year="2005"
|
||||
}
|
||||
|
||||
|
||||
@article{ cgal:csd-gdbsra-04
|
||||
, author = "David Cohen-Steiner and Tran Kai Frank Da"
|
||||
, title = "A greedy Delaunay-based surface reconstruction algorithm"
|
||||
, journal = "The Visual Computer"
|
||||
, volume = 20
|
||||
, pages = "4--16"
|
||||
, year = 2004
|
||||
}
|
||||
|
||||
@inproceedings{ cgal:csm-rdtnc-03,
|
||||
author="D. Cohen-Steiner and J.-M. Morvan",
|
||||
title="Restricted {Delaunay} triangulations and normal cycle",
|
||||
|
|
@ -1260,6 +1270,16 @@ ABSTRACT = {We present the first complete, exact and efficient C++ implementatio
|
|||
update = "09.11 penarand"
|
||||
}
|
||||
|
||||
@article{cgal:ml-cfsg-00
|
||||
, author = "G. Medioni and M. Lee and C. Tang"
|
||||
, title = "A Computational Framework for Segmentation and Grouping"
|
||||
, journal = "Elsevier Science
|
||||
|
||||
, year = 2000
|
||||
, pages = ""
|
||||
, update = "12.13 afabri"
|
||||
}
|
||||
|
||||
@book{ cgal:m-cst-93
|
||||
,author = {Robert B. Murray}
|
||||
,title = "{C{\tt ++}} Strategies and Tactics"
|
||||
|
|
|
|||
|
|
@ -113,3 +113,5 @@ IMAGE_PATH = ${CMAKE_SOURCE_DIR}/Documentation/doc/Documentation/fig \
|
|||
${CMAKE_SOURCE_DIR}/Stream_lines_2/doc/Stream_lines_2/fig \
|
||||
${CMAKE_SOURCE_DIR}/Stream_support/doc/Stream_support/fig \
|
||||
${CMAKE_SOURCE_DIR}/Surface_modeling/doc/Surface_modeling/fig \
|
||||
${CMAKE_SOURCE_DIR}/Advancing_front_surface_reconstruction/doc/Advancing_front_surface_reconstruction/fig \
|
||||
|
||||
|
|
|
|||
|
|
@ -80,3 +80,5 @@ Surface_mesh_segmentation
|
|||
Stream_lines_2
|
||||
Stream_support
|
||||
Surface_modeling
|
||||
Advancing_front_surface_reconstruction
|
||||
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ h1 {
|
|||
\package_listing{Surface_reconstruction_points_3}
|
||||
\package_listing{Skin_surface_3}
|
||||
\package_listing{Mesh_3}
|
||||
\package_listing{Advancing_front_surface_reconstruction}
|
||||
|
||||
\section PartGeometryProcessing Geometry Processing
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ Dt::Vertex_handle nearest_neighbor(const Dt& delau, Dt::Vertex_handle v);
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup PkgPointSet2NeighborSearch
|
||||
\ingroup PkgPointSet2NeighborSearch
|
||||
|
||||
computes the `k` nearest neighbors of `p` in `delau`, and places the
|
||||
handles to the corresponding vertices as a sequence of objects of type
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ foreach(DEP_PKG AABB_tree STL_Extension GraphicsView Surface_mesher Filtered_ker
|
|||
endforeach()
|
||||
|
||||
# Include this package's headers first
|
||||
include_directories( BEFORE ./ ./include ../../include ./CGAL_demo)
|
||||
include_directories( BEFORE ./ ./include ../../include ./CGAL_demo ../../../Advancing_front_surface_reconstruction/include)
|
||||
|
||||
add_subdirectory( implicit_functions )
|
||||
|
||||
|
|
@ -354,6 +354,10 @@ if(CGAL_Qt4_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND)
|
|||
polyhedron_demo_plugin(pca_plugin Polyhedron_demo_pca_plugin)
|
||||
target_link_libraries(pca_plugin scene_polyhedron_item scene_basic_objects)
|
||||
|
||||
qt4_wrap_ui( advancing_frontUI_FILES Polyhedron_demo_advancing_front_plugin.ui)
|
||||
polyhedron_demo_plugin(advancing_front_plugin Polyhedron_demo_advancing_front_plugin Polyhedron_demo_advancing_front_plugin_impl ${advancing_frontUI_FILES})
|
||||
target_link_libraries(advancing_front_plugin scene_polygon_soup_item scene_points_with_normal_item)
|
||||
|
||||
if(EIGEN3_FOUND)
|
||||
polyhedron_demo_plugin(parameterization_plugin Polyhedron_demo_parameterization_plugin)
|
||||
target_link_libraries(parameterization_plugin scene_polyhedron_item scene_textured_polyhedron_item )
|
||||
|
|
|
|||
|
|
@ -0,0 +1,117 @@
|
|||
#include "config.h"
|
||||
#include "Scene_points_with_normal_item.h"
|
||||
#include "Polyhedron_demo_plugin_helper.h"
|
||||
#include "Polyhedron_demo_plugin_interface.h"
|
||||
#include <Scene_polyhedron_item.h>
|
||||
|
||||
|
||||
#include <QObject>
|
||||
#include <QAction>
|
||||
#include <QMainWindow>
|
||||
#include <QApplication>
|
||||
#include <QtPlugin>
|
||||
#include <QInputDialog>
|
||||
|
||||
#include "ui_Polyhedron_demo_advancing_front_plugin.h"
|
||||
|
||||
// Reconstructs a surface mesh from a point set and writes facet indices into polygon soup.
|
||||
Polyhedron* advancing_front_reconstruct(const Point_set& points,
|
||||
double sm_perimeter,
|
||||
double sm_area);
|
||||
|
||||
class Polyhedron_demo_advancing_front_plugin :
|
||||
public QObject,
|
||||
public Polyhedron_demo_plugin_helper
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Polyhedron_demo_plugin_interface)
|
||||
QAction* actionAdvancingFrontReconstruction;
|
||||
|
||||
public:
|
||||
void init(QMainWindow* mainWindow, Scene_interface* scene_interface) {
|
||||
|
||||
actionAdvancingFrontReconstruction = new QAction(tr("Advancing Front reconstruction"), mainWindow);
|
||||
actionAdvancingFrontReconstruction->setObjectName("actionAdvancingFrontReconstruction");
|
||||
|
||||
Polyhedron_demo_plugin_helper::init(mainWindow, scene_interface);
|
||||
}
|
||||
|
||||
//! Applicate for Point_sets with normals.
|
||||
bool applicable() const {
|
||||
return qobject_cast<Scene_points_with_normal_item*>(scene->item(scene->mainSelectionIndex()));
|
||||
}
|
||||
|
||||
QList<QAction*> actions() const {
|
||||
return QList<QAction*>() << actionAdvancingFrontReconstruction;
|
||||
}
|
||||
|
||||
public slots:
|
||||
void on_actionAdvancingFrontReconstruction_triggered();
|
||||
}; // end class Polyhedron_demo_advancing_front_plugin
|
||||
|
||||
|
||||
class Polyhedron_demo_advancing_front_plugin_dialog : public QDialog, private Ui::AdvancingFrontDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Polyhedron_demo_advancing_front_plugin_dialog(QWidget* /*parent*/ = 0)
|
||||
{
|
||||
setupUi(this);
|
||||
|
||||
}
|
||||
|
||||
double trianglePerimeter() const { return m_inputPerimeter->value(); }
|
||||
double triangleArea() const { return m_inputArea->value(); }
|
||||
};
|
||||
|
||||
void Polyhedron_demo_advancing_front_plugin::on_actionAdvancingFrontReconstruction_triggered()
|
||||
{
|
||||
const Scene_interface::Item_id index = scene->mainSelectionIndex();
|
||||
|
||||
Scene_points_with_normal_item* point_set_item =
|
||||
qobject_cast<Scene_points_with_normal_item*>(scene->item(index));
|
||||
|
||||
if(point_set_item)
|
||||
{
|
||||
// Gets point set
|
||||
Point_set* points = point_set_item->point_set();
|
||||
if(!points) return;
|
||||
|
||||
// Gets options
|
||||
Polyhedron_demo_advancing_front_plugin_dialog dialog;
|
||||
if(!dialog.exec())
|
||||
return;
|
||||
const double sm_perimeter = dialog.trianglePerimeter();
|
||||
const double sm_area = dialog.triangleArea();
|
||||
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
// Add polyhedron to scene
|
||||
|
||||
// Reconstruct point set as a polyhedron
|
||||
Polyhedron *poly = advancing_front_reconstruct(*points, sm_perimeter, sm_area);
|
||||
|
||||
Scene_polyhedron_item* new_item = new Scene_polyhedron_item(poly);
|
||||
|
||||
|
||||
new_item->setName(tr("%1 Advancing Front (%2 %3)")
|
||||
.arg(point_set_item->name())
|
||||
.arg(sm_perimeter)
|
||||
.arg(sm_area));
|
||||
new_item->setColor(Qt::lightGray);
|
||||
scene->addItem(new_item);
|
||||
|
||||
// Hide point set
|
||||
point_set_item->setVisible(false);
|
||||
scene->itemChanged(index);
|
||||
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Q_EXPORT_PLUGIN2(Polyhedron_demo_advancing_front_plugin, Polyhedron_demo_advancing_front_plugin)
|
||||
|
||||
#include "Polyhedron_demo_advancing_front_plugin.moc"
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AdvancingFrontDialog</class>
|
||||
<widget class="QDialog" name="AdvancingFrontDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>376</width>
|
||||
<height>170</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Advancing front reconstruction</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Min triangle perimeter:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QDoubleSpinBox" name="m_inputPerimeter">
|
||||
<property name="suffix">
|
||||
<string>* average spacing</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>30.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Max triangle area:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QDoubleSpinBox" name="m_inputArea">
|
||||
<property name="suffix">
|
||||
<string> * average spacing^2</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>20.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>AdvancingFrontDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>177</x>
|
||||
<y>123</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>53</x>
|
||||
<y>125</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>AdvancingFrontDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>257</x>
|
||||
<y>119</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>257</x>
|
||||
<y>143</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
#include "config.h"
|
||||
#include "Scene_points_with_normal_item.h"
|
||||
#include "Polyhedron_demo_plugin_helper.h"
|
||||
#include "Polyhedron_demo_plugin_interface.h"
|
||||
#include <Scene_polyhedron_item.h>
|
||||
|
||||
#include "Kernel_type.h"
|
||||
#include "Polyhedron_type.h"
|
||||
#include "Scene_points_with_normal_item.h"
|
||||
|
||||
#include <CGAL/Advancing_front_surface_reconstruction.h>
|
||||
|
||||
Polyhedron*
|
||||
advancing_front_reconstruct(const Point_set& points,
|
||||
double sm_perimeter,
|
||||
double sm_area)
|
||||
{
|
||||
typedef CGAL::Advancing_front_surface_reconstruction<Kernel> Reconstruction;
|
||||
typedef Reconstruction::Triangulation_3 Triangulation_3;
|
||||
Polyhedron* output_mesh = new Polyhedron;
|
||||
|
||||
Triangulation_3 dt(points.begin(), points.end());
|
||||
|
||||
Reconstruction reconstruction(dt);
|
||||
|
||||
reconstruction();
|
||||
|
||||
CGAL::AFSR::construct_polyhedron(*output_mesh, reconstruction);
|
||||
|
||||
return output_mesh;
|
||||
}
|
||||
|
||||
|
|
@ -311,6 +311,7 @@ QMenu* Scene_points_with_normal_item::contextMenu()
|
|||
actionSelectDuplicatedPoints->setObjectName("actionSelectDuplicatedPoints");
|
||||
connect(actionSelectDuplicatedPoints, SIGNAL(triggered()),this, SLOT(selectDuplicates()));
|
||||
|
||||
|
||||
menu->setProperty(prop_name, true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -413,17 +413,19 @@ Scene_polygon_soup_item::bbox() const {
|
|||
}
|
||||
|
||||
void
|
||||
Scene_polygon_soup_item::new_vertex(const double& x,
|
||||
const double& y,
|
||||
const double& z)
|
||||
Scene_polygon_soup_item::new_vertex(double x,
|
||||
double y,
|
||||
double z)
|
||||
{
|
||||
if(!soup)
|
||||
soup = new Polygon_soup;
|
||||
soup->points.push_back(Point_3(x, y, z));
|
||||
}
|
||||
|
||||
void
|
||||
Scene_polygon_soup_item::new_triangle(const std::size_t i,
|
||||
const std::size_t j,
|
||||
const std::size_t k)
|
||||
Scene_polygon_soup_item::new_triangle(std::size_t i,
|
||||
std::size_t j,
|
||||
std::size_t k)
|
||||
{
|
||||
Polygon_soup::Polygon_3 new_polygon(3);
|
||||
new_polygon[0] = i;
|
||||
|
|
|
|||
|
|
@ -34,10 +34,10 @@ public:
|
|||
bool isFinite() const { return true; }
|
||||
bool isEmpty() const;
|
||||
Bbox bbox() const;
|
||||
|
||||
void new_vertex(const double&, const double&, const double&);
|
||||
void new_triangle(const std::size_t, const std::size_t, const std::size_t);
|
||||
|
||||
|
||||
void new_vertex(double, double, double);
|
||||
void new_triangle(std::size_t, std::size_t, std::size_t);
|
||||
|
||||
public slots:
|
||||
void shuffle_orientations();
|
||||
bool orient();
|
||||
|
|
|
|||
|
|
@ -301,7 +301,9 @@ public:
|
|||
Face_handle f1,
|
||||
Face_handle f2,
|
||||
Face_handle f3);
|
||||
|
||||
void set_adjacency(Face_handle f0, int i0, Face_handle f1, int i1) const;
|
||||
|
||||
void delete_face(Face_handle);
|
||||
void delete_vertex(Vertex_handle);
|
||||
|
||||
|
|
@ -342,10 +344,12 @@ public:
|
|||
// HELPING
|
||||
private:
|
||||
typedef std::pair<Vertex_handle,Vertex_handle> Vh_pair;
|
||||
public:
|
||||
void set_adjacency(Face_handle fh,
|
||||
int ih,
|
||||
std::map< Vh_pair, Edge>& edge_map);
|
||||
void reorient_faces();
|
||||
private:
|
||||
bool dim_down_precondition(Face_handle f, int i);
|
||||
|
||||
public:
|
||||
|
|
@ -2224,24 +2228,24 @@ reorient_faces()
|
|||
std::set<Face_handle> oriented_set;
|
||||
std::stack<Face_handle> st;
|
||||
Face_iterator fit = faces_begin();
|
||||
int nf = std::distance(faces_begin(),faces_end());
|
||||
std::ptrdiff_t nf = std::distance(faces_begin(),faces_end());
|
||||
|
||||
while (static_cast<int>(oriented_set.size()) != nf) {
|
||||
while ( oriented_set.find(fit) != oriented_set.end()){
|
||||
while (0 != nf) {
|
||||
while ( !oriented_set.insert(fit).second ){
|
||||
++fit; // find a germ for non oriented components
|
||||
}
|
||||
// orient component
|
||||
oriented_set.insert(fit);
|
||||
--nf;
|
||||
st.push(fit);
|
||||
while ( ! st.empty()) {
|
||||
Face_handle fh = st.top();
|
||||
st.pop();
|
||||
for(int ih = 0 ; ih < 3 ; ++ih){
|
||||
Face_handle fn = fh->neighbor(ih);
|
||||
if (oriented_set.find(fn) == oriented_set.end()){
|
||||
if (oriented_set.insert(fn).second){
|
||||
int in = fn->index(fh);
|
||||
if (fn->vertex(cw(in)) != fh->vertex(ccw(ih))) fn->reorient();
|
||||
oriented_set.insert(fn);
|
||||
--nf;
|
||||
st.push(fn);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue