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

281 lines
8.8 KiB
C
Raw Normal View History

// Copyright (c) 2005 Rijksuniversiteit Groningen (Netherlands)
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0+
//
//
// Author(s) : Nico Kruithof <Nico@cs.rug.nl>
#ifndef CGAL_MARCHING_TETRAHEDRA_H
#define CGAL_MARCHING_TETRAHEDRA_H
#include <CGAL/license/Skin_surface_3.h>
#include <CGAL/Polyhedron_incremental_builder_3.h>
#include <CGAL/Modifier_base.h>
#include <CGAL/Cartesian_converter.h>
#include <CGAL/Marching_tetrahedra_observer_default_3.h>
namespace CGAL {
// If TriangulationDataStructure_3 only gets a Cell_handle range
// it is not possible to derive the Vertex_handle type.
template <class Vertex_iterator,
class Cell_iterator,
class HalfedgeDS_3,
class MarchingTetrahedraTraits_3,
class MarchingTetrahedraObserver_3 >
class Marching_tetrahedra_builder : public Modifier_base<HalfedgeDS_3> {
public:
typedef HalfedgeDS_3 HDS;
typedef MarchingTetrahedraTraits_3 Traits;
typedef MarchingTetrahedraObserver_3 Observer;
private:
typedef Vertex_iterator T_Vertex_iterator;
typedef Cell_iterator T_Cell_iterator;
typedef typename T_Cell_iterator::value_type T_Cell;
typedef typename T_Cell::Vertex_handle T_Vertex_handle;
typedef typename T_Vertex_iterator::value_type T_Vertex;
typedef typename T_Vertex_iterator::value_type * T_Vertex_pointer;
typedef typename T_Cell_iterator::value_type * T_Cell_pointer;
typedef typename HDS::Face_handle HDS_face_handle;
typedef typename HDS::Vertex_handle HDS_vertex_handle;
typedef std::map<T_Vertex_handle,bool> T_vertex_map;
typedef typename T_vertex_map::iterator T_vertex_map_it;
// First vertex lies inside the surface, the second vertex outside
typedef std::pair<T_Vertex_handle,T_Vertex_handle> T_edge;
typedef std::map<T_edge,int> T_edge_map;
typedef typename T_edge_map::iterator T_edge_map_it;
typedef Polyhedron_incremental_builder_3<HDS> Polyh_incr_builder;
public:
Marching_tetrahedra_builder(
T_Vertex_iterator vertices_begin,
T_Vertex_iterator vertices_end,
T_Cell_iterator cells_begin,
T_Cell_iterator cells_end,
const Traits &traits,
Observer &observer)
: vertices_begin(vertices_begin),
vertices_end(vertices_end),
cells_begin(cells_begin),
cells_end(cells_end),
traits(traits), observer(observer), nVertices(0) {
}
void operator()( HDS& hds) {
// sortedV is an array of vertex indices.
// The first nIn vertices lie inside the surface, the last 4-nIn outside.
int sortedV[4], cellV[4], nIn;
T_edge edge;
Polyh_incr_builder B( hds, true);
B.begin_surface(0,0,0);
for (T_Cell_iterator cit = cells_begin; cit != cells_end; ++cit) {
// Compute signs on vertices and sort them:
nIn = 0;
for (int i=0; i<4; i++) {
if (is_inside(cit,i)) {
sortedV[nIn] = i; nIn++;
} else {
sortedV[3-i+nIn] = i;
}
}
// Process edges whose vertices lie on different sides of the surface
int edgeN=0;
for (int i=0; i<nIn; i++) {
for (int j=nIn; j<4; j++) {
cellV[edgeN++] = process_edge(B, cit,sortedV[i],sortedV[j]);
}
}
// Construct triangles:
CGAL_assertion(!B.error());
if (nIn==1) {
process_cell(B, cellV, (sortedV[0]%2)==1, cit);
CGAL_assertion(!B.error());
} else if (nIn==2) {
bool change_orientation =
(((sortedV[0] == 0) && (sortedV[1]==1)) ||
((sortedV[0] == 0) && (sortedV[1]==3)) ||
((sortedV[0] == 1) && (sortedV[1]==2)) ||
((sortedV[0] == 2) && (sortedV[1]==3)));
process_cell(B, cellV, !change_orientation, cit);
process_cell(B, cellV+1, change_orientation, cit);
CGAL_assertion(!B.error());
} else if (nIn==3) {
process_cell(B, cellV, (sortedV[3]%2) == 1, cit);
CGAL_assertion(!B.error());
}
}
CGAL_assertion(!B.error());
B.end_surface();
}
bool is_inside(T_Cell_iterator ch, int i) {
CGAL_assertion(&*ch != NULL);
//return (traits.sign(ch,i) == POSITIVE);
T_vertex_map_it it = triang_vertex_signs.find((ch->vertex(i)));
if (it == triang_vertex_signs.end()) {
bool side = (traits.sign(ch,i) == POSITIVE);
CGAL_assertion(triang_vertex_signs.find((ch->vertex(i))) ==
triang_vertex_signs.end());
CGAL_assertion(&*ch != NULL);
triang_vertex_signs[(ch->vertex(i))] = side;
CGAL_assertion(triang_vertex_signs.find((ch->vertex(i))) !=
triang_vertex_signs.end());
CGAL_assertion(triang_vertex_signs[(ch->vertex(i))] == side);
return side;
} else {
return it->second;
}
}
int process_edge(Polyh_incr_builder &B,
T_Cell_iterator ch, int i, int j) {
CGAL_assertion(is_inside(ch, i));
CGAL_assertion(!is_inside(ch, j));
T_edge edge = T_edge(ch->vertex(i),ch->vertex(j));
T_edge_map_it edge_it = polyh_vert.find(edge);
if (edge_it == polyh_vert.end()) {
HDS_vertex_handle vh = B.add_vertex(traits.intersection(ch, i, j));
polyh_vert[edge] = nVertices;
nVertices ++;
observer.after_vertex_insertion(ch, i, j, vh);
return nVertices-1;
} else {
return edge_it->second;
}
}
// Orientation is right
void process_cell(
Polyh_incr_builder &B,
int *vs,
bool change_orientation,
T_Cell_iterator ch)
{
CGAL_assertion((vs[0]!=vs[1]) && (vs[0]!=vs[2]) && (vs[1]!=vs[2]));
HDS_face_handle f = B.begin_facet();
if (change_orientation) {
B.add_vertex_to_facet( vs[0] );
B.add_vertex_to_facet( vs[2] );
B.add_vertex_to_facet( vs[1] );
} else {
B.add_vertex_to_facet( vs[0] );
B.add_vertex_to_facet( vs[1] );
B.add_vertex_to_facet( vs[2] );
}
B.end_facet();
observer.after_facet_insertion(ch, f);
}
private:
T_Vertex_iterator vertices_begin, vertices_end;
T_Cell_iterator cells_begin, cells_end;
const Traits &traits;
Observer &observer;
T_edge_map polyh_vert;
T_vertex_map triang_vertex_signs;
int nVertices;
};
template <class Triangulation_3,
class Polyhedron_3,
class MarchingTetrahedraTraits_3>
void marching_tetrahedra_3(
const Triangulation_3 &triangulation,
Polyhedron_3 &polyhedron,
const MarchingTetrahedraTraits_3 &traits) {
typedef Marching_tetrahedra_observer_default_3
<typename Triangulation_3::Finite_vertices_iterator,
typename Triangulation_3::Finite_cells_iterator,
Polyhedron_3>
Observer;
marching_tetrahedra_3(triangulation.finite_vertices_begin(),
triangulation.finite_vertices_end(),
triangulation.finite_cells_begin(),
triangulation.finite_cells_end(),
polyhedron,
traits,
Observer());
}
template <class Triangulation_3,
class Polyhedron_3,
class MarchingTetrahedraTraits_3,
class MarchingTetrahedraObserver_3>
void marching_tetrahedra_3(
const Triangulation_3 &triangulation,
Polyhedron_3 &polyhedron,
const MarchingTetrahedraTraits_3 &traits,
MarchingTetrahedraObserver_3 &observer) {
marching_tetrahedra_3(triangulation.finite_vertices_begin(),
triangulation.finite_vertices_end(),
triangulation.finite_cells_begin(),
triangulation.finite_cells_end(),
polyhedron,
traits,
observer);
}
template <class Vertex_iterator,
class Cell_iterator,
class Polyhedron_3,
class MarchingTetrahedraTraits_3,
class MarchingTetrahedraObserver_3>
void marching_tetrahedra_3(
Vertex_iterator finite_vertices_begin,
Vertex_iterator finite_vertices_end,
Cell_iterator finite_cells_begin,
Cell_iterator finite_cells_end,
Polyhedron_3 &polyhedron,
const MarchingTetrahedraTraits_3 &traits,
MarchingTetrahedraObserver_3 &observer) {
typedef typename Polyhedron_3::HalfedgeDS HDS;
typedef Marching_tetrahedra_builder<
Vertex_iterator, Cell_iterator, HDS,
MarchingTetrahedraTraits_3, MarchingTetrahedraObserver_3> Builder;
Builder builder(finite_vertices_begin, finite_vertices_end,
finite_cells_begin, finite_cells_end,
traits, observer);
polyhedron.delegate(builder);
}
} //namespace CGAL
#endif // CGAL_MARCHING_TETRAHEDRA_H