mirror of https://github.com/CGAL/cgal
[Small Feature] VTK IO support for Linear_cell_complex (#8998)
## Summary This small feature adds the ability to read and write `.vtk` files (legacy ASCII) for 3D Linear_cell_complex (dimension 3, ambient dimension 3). It supports per-vertex and per-volume scalar fields and handles various VTK cell types. ## Motivation Enable import/export of mesh structures and scalar fields between CGAL and VTK-based visualization tools (ParaView, VisIt, etc.). Simplifies debugging and integration into scientific pipelines. ## API Changes - New functions in `Linear_cell_complex_vtk_io.h`: - `read_lcc_from_vtk()` - `write_lcc_to_vtk()` Header-only implementation, no external dependency. ## Included - Full implementation in `Linear_cell_complex_vtk_io.h` (merged `.impl`) - Minimal example with `.3map` and `.vtk` files - Unit test with scalar field preservation and structure comparison ## Maintainers Feel free to suggest naming adjustments or style corrections. The feature is scoped cleanly and does not affect other packages. * Feature/Small Feature (if any): [Read_write_vtk_for_LCC](https://cgalwiki.geometryfactory.com/CGAL/Members/wiki/Features/Small_Features/Read_write_vtk_for_LCC)
This commit is contained in:
commit
be305f320f
|
|
@ -1068,8 +1068,18 @@ If \link GenericMap::are_attributes_automatically_managed `are_attributes_automa
|
|||
template <unsigned int i>
|
||||
size_type remove_cell(Dart_descriptor d);
|
||||
|
||||
/*!
|
||||
\ingroup PkgCombinatorialMapsRefIO
|
||||
Writes `amap` in `os`, using our own internal file format in XML. Writes both the topology of the combinatorial map and its enabled attributes.
|
||||
*/
|
||||
friend std::ostream& operator<< (std::ostream& os, const GenericMap& amap);
|
||||
|
||||
/*!
|
||||
\ingroup PkgCombinatorialMapsRefIO
|
||||
Reads `amap` from `is`, using our own internal file format in XML. Reads both the topology of the combinatorial map and its enabled attributes which are present in `is`. Note that if `amap` is not empty before the reading, the new map is added in the previous one.
|
||||
*/
|
||||
friend std::ifstream& operator>> (std::ifstream& is, GenericMap& amap);
|
||||
|
||||
/// @}
|
||||
|
||||
}; /* end GenericMap */
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@
|
|||
/// \defgroup PkgCombinatorialMapsClasses Classes
|
||||
/// \ingroup PkgCombinatorialMapsRef
|
||||
|
||||
/// \defgroup PkgCombinatorialMapsRefIO IO Functions for CMap
|
||||
/// \ingroup PkgCombinatorialMapsRef
|
||||
|
||||
/*!
|
||||
\addtogroup PkgCombinatorialMapsRef
|
||||
\cgalPkgDescriptionBegin{Combinatorial Maps,PkgCombinatorialMaps}
|
||||
|
|
@ -36,5 +39,9 @@
|
|||
- `CGAL::Cell_attribute_with_id<CMap,Info_,Tag,OnMerge,OnSplit>`
|
||||
- `CGAL::Generic_map_min_items`
|
||||
|
||||
\cgalCRPSubsection{IO Functions for CMap}
|
||||
- \link PkgCombinatorialMapsRefIO `std::ostream& operator<< (std::ostream& os, const GenericMap& amap)` \endlink
|
||||
- \link PkgCombinatorialMapsRefIO `std::ifstream& operator>> (std::ifstream& is, GenericMap& amap)` \endlink
|
||||
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -255,7 +255,7 @@ namespace CGAL {
|
|||
}
|
||||
}
|
||||
|
||||
// Create an mapping between darts of the two maps (originals->copies).
|
||||
// Creates a mapping between darts of the two maps (originals->copies).
|
||||
// (here we cannot use CGAL::Unique_hash_map because it does not provide
|
||||
// iterators...
|
||||
std::unordered_map<Dart_descriptor_2, Dart_descriptor> local_dartmap;
|
||||
|
|
@ -585,7 +585,7 @@ namespace CGAL {
|
|||
bool copy_perforated_darts=false,
|
||||
size_type mark_perforated=INVALID_MARK)
|
||||
{
|
||||
// Create an mapping between darts of the two maps (originals->copies).
|
||||
// Creates a mapping between darts of the two maps (originals->copies).
|
||||
// (here we cannot use CGAL::Unique_hash_map because it does not provide
|
||||
// iterators...
|
||||
std::unordered_map
|
||||
|
|
@ -661,7 +661,7 @@ namespace CGAL {
|
|||
return is;
|
||||
}
|
||||
|
||||
/** Create a new dart and add it to the map.
|
||||
/** Creates a new dart and add it to the map.
|
||||
* The marks of the darts are initialized with mmask_marks, i.e. the dart
|
||||
* is unmarked for all the marks.
|
||||
* @return a Dart_descriptor on the new dart.
|
||||
|
|
@ -968,7 +968,7 @@ namespace CGAL {
|
|||
size_type number_of_used_marks() const
|
||||
{ return mnb_used_marks; }
|
||||
|
||||
/** Test if a given mark is reserved.
|
||||
/** Tests if a given mark is reserved.
|
||||
* @return true iff the mark is reserved (i.e. in used).
|
||||
*/
|
||||
bool is_reserved(size_type amark) const
|
||||
|
|
@ -997,14 +997,14 @@ namespace CGAL {
|
|||
return number_of_darts() - number_of_marked_darts(amark);
|
||||
}
|
||||
|
||||
/** Test if all the darts are unmarked for a given mark.
|
||||
/** Tests if all the darts are unmarked for a given mark.
|
||||
* @param amark the mark index.
|
||||
* @return true iff all the darts are unmarked for amark.
|
||||
*/
|
||||
bool is_whole_map_unmarked(size_type amark) const
|
||||
{ return number_of_marked_darts(amark) == 0; }
|
||||
|
||||
/** Test if all the darts are marked for a given mark.
|
||||
/** Tests if all the darts are marked for a given mark.
|
||||
* @param amark the mark index.
|
||||
* @return true iff all the darts are marked for amark.
|
||||
*/
|
||||
|
|
@ -1071,7 +1071,7 @@ namespace CGAL {
|
|||
mmask_marks.flip(amark);
|
||||
}
|
||||
|
||||
/** Test if a given dart is marked for a given mark.
|
||||
/** Tests if a given dart is marked for a given mark.
|
||||
* @param adart the dart to test.
|
||||
* @param amark the given mark.
|
||||
* @return true iff adart is marked for the mark amark.
|
||||
|
|
@ -1239,7 +1239,7 @@ namespace CGAL {
|
|||
std::size_t orient(size_type amark) const
|
||||
{ negate_mark(amark); return number_of_darts(); }
|
||||
|
||||
/** Test if this map is without boundary for a given dimension.
|
||||
/** Tests if this map is without boundary for a given dimension.
|
||||
* @param i the dimension.
|
||||
* @return true iff all the darts are not i-free.
|
||||
* @pre 1<=i<=n
|
||||
|
|
@ -1253,7 +1253,7 @@ namespace CGAL {
|
|||
return true;
|
||||
}
|
||||
|
||||
/** Test if this map is without boundary for all the dimensions.
|
||||
/** Tests if this map is without boundary for all the dimensions.
|
||||
* @return true iff all the darts are non free.
|
||||
*/
|
||||
bool is_without_boundary() const
|
||||
|
|
@ -1334,7 +1334,7 @@ namespace CGAL {
|
|||
return res;
|
||||
}
|
||||
|
||||
/** Test if the map is valid.
|
||||
/** Tests if the map is valid.
|
||||
* @return true iff the map is valid.
|
||||
*/
|
||||
bool is_valid(bool show_errors=true) const
|
||||
|
|
@ -1579,7 +1579,7 @@ namespace CGAL {
|
|||
return os;
|
||||
}
|
||||
|
||||
/// Create a new attribute.
|
||||
/// Creates a new attribute.
|
||||
/// @return a descriptor on the new attribute.
|
||||
template<unsigned int i, typename ...Args>
|
||||
typename Attribute_descriptor<i>::type create_attribute(const Args&... args)
|
||||
|
|
@ -1988,7 +1988,7 @@ namespace CGAL {
|
|||
else unlink_beta_for_involution(adart, i);
|
||||
}
|
||||
|
||||
/** Test if it is possible to sew by betai the two given darts
|
||||
/** Tests if it is possible to sew by betai the two given darts
|
||||
* @param adart1 the first dart.
|
||||
* @param adart2 the second dart.
|
||||
* @return true iff \em adart1 can be i-sewn with \em adart2.
|
||||
|
|
@ -3439,7 +3439,7 @@ namespace CGAL {
|
|||
}
|
||||
|
||||
|
||||
/** Test if the connected component of cmap containing dart dh1 is
|
||||
/** Tests if the connected component of cmap containing dart dh1 is
|
||||
* isomorphic to the connected component of map2 containing dart dh2,
|
||||
* starting from dh1 and dh2.
|
||||
* @param dh1 initial dart for this map
|
||||
|
|
@ -3648,7 +3648,7 @@ namespace CGAL {
|
|||
return match;
|
||||
}
|
||||
|
||||
/** Test if this cmap is isomorphic to map2.
|
||||
/** Tests if this cmap is isomorphic to map2.
|
||||
* @pre cmap is connected.
|
||||
* @param map2 the second combinatorial map
|
||||
* @param testDartInfo Boolean to test the equality of dart info (true)
|
||||
|
|
@ -3687,7 +3687,7 @@ namespace CGAL {
|
|||
return false;
|
||||
}
|
||||
|
||||
/** Test if the attributes of this map are automatically updated.
|
||||
/** Tests if the attributes of this map are automatically updated.
|
||||
* @return true iff the boolean automatic_attributes_management is set to true.
|
||||
*/
|
||||
bool are_attributes_automatically_managed() const
|
||||
|
|
@ -3710,13 +3710,13 @@ namespace CGAL {
|
|||
void set_automatic_attributes_management_without_correction(bool newval)
|
||||
{ this->automatic_attributes_management = newval; }
|
||||
|
||||
/** Create a halfedge.
|
||||
* @return a dart of the new halfedge.
|
||||
/** Creates a halfedge.
|
||||
* @return a dart of the new half-edge.
|
||||
*/
|
||||
Dart_descriptor make_half_edge()
|
||||
{ return create_dart(); }
|
||||
|
||||
/** Create an edge.
|
||||
/** Creates an edge.
|
||||
* if closed==true, the edge has no 2-free dart.
|
||||
* (note that for CMap there is no difference between true and false, but
|
||||
* this is not the case for GMap)
|
||||
|
|
@ -3730,7 +3730,7 @@ namespace CGAL {
|
|||
return d1;
|
||||
}
|
||||
|
||||
/** Create an edge given 2 Attribute_descriptor<0>.
|
||||
/** Creates an edge given 2 Attribute_descriptor<0>.
|
||||
* Note that this function can be used only if 0-attributes are non void
|
||||
* @param h0 the first vertex descriptor.
|
||||
* @param h1 the second vertex descriptor.
|
||||
|
|
@ -3751,7 +3751,7 @@ namespace CGAL {
|
|||
return d1;
|
||||
}
|
||||
|
||||
/** Create a combinatorial polygon of length alg
|
||||
/** Creates a combinatorial polygon of length alg
|
||||
* (a cycle of alg darts beta1 links together).
|
||||
* @return a new dart.
|
||||
*/
|
||||
|
|
@ -3772,7 +3772,7 @@ namespace CGAL {
|
|||
return start;
|
||||
}
|
||||
|
||||
/** Test if a face is a combinatorial polygon of length alg
|
||||
/** Tests if a face is a combinatorial polygon of length alg
|
||||
* (a cycle of alg darts beta1 links together).
|
||||
* @param adart an initial dart
|
||||
* @return true iff the face containing adart is a polygon of length alg.
|
||||
|
|
@ -3794,7 +3794,7 @@ namespace CGAL {
|
|||
return (nb==alg);
|
||||
}
|
||||
|
||||
/** Create a triangle given 3 Attribute_descriptor<0>.
|
||||
/** Creates a triangle given 3 Attribute_descriptor<0>.
|
||||
* @param h0 the first descriptor.
|
||||
* @param h1 the second descriptor.
|
||||
* @param h2 the third descriptor.
|
||||
|
|
@ -3814,7 +3814,7 @@ namespace CGAL {
|
|||
return d1;
|
||||
}
|
||||
|
||||
/** Create a quadrangle given 4 Vertex_attribute_descriptor.
|
||||
/** Creates a quadrangle given 4 Vertex_attribute_descriptor.
|
||||
* @param h0 the first vertex descriptor.
|
||||
* @param h1 the second vertex descriptor.
|
||||
* @param h2 the third vertex descriptor.
|
||||
|
|
@ -3837,7 +3837,7 @@ namespace CGAL {
|
|||
return d1;
|
||||
}
|
||||
|
||||
/** Create a combinatorial tetrahedron from 4 triangles.
|
||||
/** Creates a combinatorial tetrahedron from 4 triangles.
|
||||
* @param d1 a dart onto a first triangle.
|
||||
* @param d2 a dart onto a second triangle.
|
||||
* @param d3 a dart onto a third triangle.
|
||||
|
|
@ -3859,9 +3859,9 @@ namespace CGAL {
|
|||
return d1;
|
||||
}
|
||||
|
||||
/** Test if a volume is a combinatorial tetrahedron.
|
||||
* @param adart an initial dart
|
||||
* @return true iff the volume containing adart is a combinatorial tetrahedron.
|
||||
/** Tests if a volume is a combinatorial tetrahedron.
|
||||
* @param d1 an initial dart
|
||||
* @return true iff the volume containing d1 is a combinatorial tetrahedron.
|
||||
*/
|
||||
bool is_volume_combinatorial_tetrahedron(Dart_const_descriptor d1) const
|
||||
{
|
||||
|
|
@ -3892,7 +3892,7 @@ namespace CGAL {
|
|||
return true;
|
||||
}
|
||||
|
||||
/** Create a new combinatorial tetrahedron.
|
||||
/** Creates a new combinatorial tetrahedron.
|
||||
* @return a new dart.
|
||||
*/
|
||||
Dart_descriptor make_combinatorial_tetrahedron()
|
||||
|
|
@ -3905,7 +3905,7 @@ namespace CGAL {
|
|||
return make_combinatorial_tetrahedron(d1, d2, d3, d4);
|
||||
}
|
||||
|
||||
/** Create a combinatorial hexahedron from 6 quadrilaterals.
|
||||
/** Creates a combinatorial hexahedron from 6 quadrilaterals.
|
||||
* @param d1 a dart onto a first quadrilateral.
|
||||
* @param d2 a dart onto a second quadrilateral.
|
||||
* @param d3 a dart onto a third quadrilateral.
|
||||
|
|
@ -3952,9 +3952,9 @@ namespace CGAL {
|
|||
return d1;
|
||||
}
|
||||
|
||||
/** Test if a volume is a combinatorial hexahedron.
|
||||
* @param adart an initial dart
|
||||
* @return true iff the volume containing adart is a combinatorial hexahedron.
|
||||
/** Tests if a volume is a combinatorial hexahedron.
|
||||
* @param d1 an initial dart
|
||||
* @return true iff the volume containing d1 is a combinatorial hexahedron.
|
||||
*/
|
||||
bool is_volume_combinatorial_hexahedron(Dart_const_descriptor d1) const
|
||||
{
|
||||
|
|
@ -4004,7 +4004,7 @@ namespace CGAL {
|
|||
return true;
|
||||
}
|
||||
|
||||
/** Create a new combinatorial hexahedron.
|
||||
/** Creates a new combinatorial hexahedron.
|
||||
* @return a new dart.
|
||||
*/
|
||||
Dart_descriptor make_combinatorial_hexahedron()
|
||||
|
|
@ -4019,7 +4019,362 @@ namespace CGAL {
|
|||
return make_combinatorial_hexahedron(d1, d2, d3, d4, d5, d6);
|
||||
}
|
||||
|
||||
/** Test if an i-cell can be removed.
|
||||
/** Tests if a volume is a combinatorial prism.
|
||||
* @param d1 an initial dart
|
||||
* @return true iff the volume containing d1 is a combinatorial prism.
|
||||
*/
|
||||
bool is_volume_combinatorial_prism(Dart_const_descriptor d1) const
|
||||
{
|
||||
Dart_const_descriptor d2=beta(d1, 2);
|
||||
Dart_const_descriptor d3=beta(d1, 1, 2);
|
||||
Dart_const_descriptor d4=beta(d1, 0, 2);
|
||||
Dart_const_descriptor d5=beta(d2, 1, 1, 2);
|
||||
|
||||
if ( d1==null_dart_descriptor || d2==null_dart_descriptor ||
|
||||
d3==null_dart_descriptor || d4==null_dart_descriptor ||
|
||||
d5==null_dart_descriptor ) { return false; }
|
||||
|
||||
if (!is_face_combinatorial_polygon(d1, 3) ||
|
||||
!is_face_combinatorial_polygon(d2, 4) ||
|
||||
!is_face_combinatorial_polygon(d3, 4) ||
|
||||
!is_face_combinatorial_polygon(d4, 4) ||
|
||||
!is_face_combinatorial_polygon(d5, 3)) { return false; }
|
||||
|
||||
// TODO do better with marks.
|
||||
if (belong_to_same_cell<2,1>(d1, d2) ||
|
||||
belong_to_same_cell<2,1>(d1, d3) ||
|
||||
belong_to_same_cell<2,1>(d1, d4) ||
|
||||
belong_to_same_cell<2,1>(d1, d5) ||
|
||||
belong_to_same_cell<2,1>(d2, d3) ||
|
||||
belong_to_same_cell<2,1>(d2, d4) ||
|
||||
belong_to_same_cell<2,1>(d2, d5) ||
|
||||
belong_to_same_cell<2,1>(d3, d4) ||
|
||||
belong_to_same_cell<2,1>(d3, d5) ||
|
||||
belong_to_same_cell<2,1>(d4, d5))
|
||||
{ return false; }
|
||||
|
||||
if (beta(d2,0,2) !=beta(d3,1) ||
|
||||
beta(d2,1,2) !=beta(d4,0) ||
|
||||
beta(d3,0,2) !=beta(d4,1) ||
|
||||
beta(d3,1,1,2)!=beta(d5,0) ||
|
||||
beta(d4,1,1,2)!=beta(d5,1)) { return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Creates a combinatorial prism from 2 triangles and 3 squares.
|
||||
* @param d1 a dart onto a first triangle.
|
||||
* @param d2 a dart onto a first square.
|
||||
* @param d3 a dart onto a second square.
|
||||
* @param d4 a dart onto a thirth square.
|
||||
* @param d5 a dart onto a second triangle.
|
||||
* @return a new dart.
|
||||
*/
|
||||
Dart_descriptor make_combinatorial_prism(Dart_descriptor d1,
|
||||
Dart_descriptor d2,
|
||||
Dart_descriptor d3,
|
||||
Dart_descriptor d4,
|
||||
Dart_descriptor d5)
|
||||
{
|
||||
// 2-link for first triangle
|
||||
basic_link_beta_for_involution(d1, d2, 2);
|
||||
basic_link_beta_for_involution(beta(d1, 1), d3, 2);
|
||||
basic_link_beta_for_involution(beta(d1, 0), d4, 2);
|
||||
|
||||
// 2-link for quandrangles between them
|
||||
basic_link_beta_for_involution(beta(d2, 0), beta(d3, 1), 2);
|
||||
basic_link_beta_for_involution(beta(d2, 1), beta(d4, 0), 2);
|
||||
basic_link_beta_for_involution(beta(d3, 0), beta(d4, 1), 2);
|
||||
|
||||
// 2-link for second triangle
|
||||
basic_link_beta_for_involution(beta(d2, 1, 1), d5, 2);
|
||||
basic_link_beta_for_involution(beta(d3, 1, 1), beta(d5, 0), 2);
|
||||
basic_link_beta_for_involution(beta(d4, 1, 1), beta(d5, 1), 2);
|
||||
|
||||
return d1;
|
||||
}
|
||||
|
||||
/** Creates a new combinatorial prism.
|
||||
* @return a new dart.
|
||||
*/
|
||||
Dart_descriptor make_combinatorial_prism()
|
||||
{
|
||||
Dart_descriptor d1 = make_combinatorial_polygon(3);
|
||||
Dart_descriptor d2 = make_combinatorial_polygon(4);
|
||||
Dart_descriptor d3 = make_combinatorial_polygon(4);
|
||||
Dart_descriptor d4 = make_combinatorial_polygon(4);
|
||||
Dart_descriptor d5 = make_combinatorial_polygon(3);
|
||||
|
||||
return make_combinatorial_prism( d1, d2, d3, d4, d5);
|
||||
}
|
||||
|
||||
/** Tests if a volume is a combinatorial pyramid.
|
||||
* @param d1 an intial dart
|
||||
* @return true iff the volume containing d1 is a combinatorial pyramid.
|
||||
*/
|
||||
bool is_volume_combinatorial_pyramid(Dart_const_descriptor d1) const
|
||||
{
|
||||
Dart_const_descriptor d2=beta(d1, 2);
|
||||
Dart_const_descriptor d3=beta(d1, 0, 2);
|
||||
Dart_const_descriptor d4=beta(d1, 1, 1, 2);
|
||||
Dart_const_descriptor d5=beta(d1, 1, 2);
|
||||
|
||||
if (d1==null_dart_descriptor || d2==null_dart_descriptor ||
|
||||
d3==null_dart_descriptor || d4==null_dart_descriptor ||
|
||||
d5==null_dart_descriptor) { return false; }
|
||||
|
||||
if (!is_face_combinatorial_polygon(d1, 4) ||
|
||||
!is_face_combinatorial_polygon(d2, 3) ||
|
||||
!is_face_combinatorial_polygon(d3, 3) ||
|
||||
!is_face_combinatorial_polygon(d4, 3) ||
|
||||
!is_face_combinatorial_polygon(d5, 3)) { return false; }
|
||||
|
||||
// TODO do better with marks.
|
||||
if (belong_to_same_cell<2,1>(d1, d2) ||
|
||||
belong_to_same_cell<2,1>(d1, d3) ||
|
||||
belong_to_same_cell<2,1>(d1, d4) ||
|
||||
belong_to_same_cell<2,1>(d1, d5) ||
|
||||
belong_to_same_cell<2,1>(d2, d3) ||
|
||||
belong_to_same_cell<2,1>(d2, d4) ||
|
||||
belong_to_same_cell<2,1>(d2, d5) ||
|
||||
belong_to_same_cell<2,1>(d3, d4) ||
|
||||
belong_to_same_cell<2,1>(d3, d5) ||
|
||||
belong_to_same_cell<2,1>(d4, d5))
|
||||
{ return false; }
|
||||
|
||||
if (beta(d2,1,2)!=beta(d3,0) ||
|
||||
beta(d2,0,2)!=beta(d5,1) ||
|
||||
beta(d5,0,2)!=beta(d4,1) ||
|
||||
beta(d4,0,2)!=beta(d3,1)) { return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Creates a combinatorial pyramid from 1 square and 4 triangles.
|
||||
* @param d1 a dart onto the square.
|
||||
* @param d2 a dart onto a first triangle.
|
||||
* @param d3 a dart onto a second triangle.
|
||||
* @param d4 a dart onto a thirth triangle.
|
||||
* @param d5 a dart onto a fourth triangle.
|
||||
* @return a new dart.
|
||||
*/
|
||||
Dart_descriptor make_combinatorial_pyramid(Dart_descriptor d1,
|
||||
Dart_descriptor d2,
|
||||
Dart_descriptor d3,
|
||||
Dart_descriptor d4,
|
||||
Dart_descriptor d5)
|
||||
{
|
||||
// 2-link for the square
|
||||
basic_link_beta_for_involution(d1, d2, 2);
|
||||
basic_link_beta_for_involution(beta(d1, 1), d5, 2);
|
||||
basic_link_beta_for_involution(beta(d1, 1, 1), d4, 2);
|
||||
basic_link_beta_for_involution(beta(d1, 0), d3, 2);
|
||||
|
||||
// 2-link for first triangle
|
||||
basic_link_beta_for_involution(beta(d2, 1), beta(d3, 0), 2);
|
||||
basic_link_beta_for_involution(beta(d2, 0), beta(d5, 1), 2);
|
||||
|
||||
// 2-link for triangles between them
|
||||
basic_link_beta_for_involution(beta(d5, 0), beta(d4, 1), 2);
|
||||
basic_link_beta_for_involution(beta(d4, 0), beta(d3, 1), 2);
|
||||
|
||||
return d1;
|
||||
}
|
||||
|
||||
/** Creates a new combinatorial pyramid.
|
||||
* @return a new dart.
|
||||
*/
|
||||
Dart_descriptor make_combinatorial_pyramid()
|
||||
{
|
||||
Dart_descriptor d1=make_combinatorial_polygon(4);
|
||||
Dart_descriptor d2=make_combinatorial_polygon(3);
|
||||
Dart_descriptor d3=make_combinatorial_polygon(3);
|
||||
Dart_descriptor d4=make_combinatorial_polygon(3);
|
||||
Dart_descriptor d5=make_combinatorial_polygon(3);
|
||||
|
||||
return make_combinatorial_pyramid(d1, d2, d3, d4, d5);
|
||||
}
|
||||
|
||||
/** Tests if a volume is a combinatorial pentagonal prism.
|
||||
* @param d1 an initial dart
|
||||
* @return true iff the volume containing d1 is a combinatorial pentagonal prism.
|
||||
*/
|
||||
bool is_volume_combinatorial_pentagonal_prism(Dart_const_descriptor d1) const
|
||||
{
|
||||
Dart_const_descriptor d2=beta(d1, 2);
|
||||
Dart_const_descriptor d3=beta(d1, 1, 2);
|
||||
Dart_const_descriptor d4=beta(d1, 1, 1, 2);
|
||||
Dart_const_descriptor d5=beta(d1, 0, 0, 2);
|
||||
Dart_const_descriptor d6=beta(d1, 0, 2);
|
||||
Dart_const_descriptor d7=beta(d2, 1, 1, 2);
|
||||
|
||||
if (d1==null_dart_descriptor || d2==null_dart_descriptor ||
|
||||
d3==null_dart_descriptor || d4==null_dart_descriptor ||
|
||||
d5==null_dart_descriptor || d6==null_dart_descriptor ||
|
||||
d7==null_dart_descriptor)
|
||||
{ return false; }
|
||||
|
||||
if (!is_face_combinatorial_polygon(d1, 5) ||
|
||||
!is_face_combinatorial_polygon(d2, 4) ||
|
||||
!is_face_combinatorial_polygon(d3, 4) ||
|
||||
!is_face_combinatorial_polygon(d4, 4) ||
|
||||
!is_face_combinatorial_polygon(d5, 4) ||
|
||||
!is_face_combinatorial_polygon(d6, 4) ||
|
||||
!is_face_combinatorial_polygon(d7, 5)) { return false; }
|
||||
|
||||
// TODO do better with marks.
|
||||
if (belong_to_same_cell<2,1>(d1, d2) ||
|
||||
belong_to_same_cell<2,1>(d1, d3) ||
|
||||
belong_to_same_cell<2,1>(d1, d4) ||
|
||||
belong_to_same_cell<2,1>(d1, d5) ||
|
||||
belong_to_same_cell<2,1>(d1, d6) ||
|
||||
belong_to_same_cell<2,1>(d1, d7) ||
|
||||
belong_to_same_cell<2,1>(d2, d3) ||
|
||||
belong_to_same_cell<2,1>(d2, d4) ||
|
||||
belong_to_same_cell<2,1>(d2, d5) ||
|
||||
belong_to_same_cell<2,1>(d2, d6) ||
|
||||
belong_to_same_cell<2,1>(d2, d7) ||
|
||||
belong_to_same_cell<2,1>(d3, d4) ||
|
||||
belong_to_same_cell<2,1>(d3, d5) ||
|
||||
belong_to_same_cell<2,1>(d3, d6) ||
|
||||
belong_to_same_cell<2,1>(d3, d7) ||
|
||||
belong_to_same_cell<2,1>(d4, d5) ||
|
||||
belong_to_same_cell<2,1>(d4, d6) ||
|
||||
belong_to_same_cell<2,1>(d4, d7) ||
|
||||
belong_to_same_cell<2,1>(d5, d6) ||
|
||||
belong_to_same_cell<2,1>(d5, d7) ||
|
||||
belong_to_same_cell<2,1>(d6, d7))
|
||||
{ return false; }
|
||||
|
||||
if (beta(d2,0,2) !=beta(d3,1) ||
|
||||
beta(d3,0,2) !=beta(d4,1) ||
|
||||
beta(d4,0,2) !=beta(d5,1) ||
|
||||
beta(d5,0,2) !=beta(d6,1) ||
|
||||
beta(d6,0,2) !=beta(d2,1) ||
|
||||
beta(d3,1,1,2)!=beta(d7,0) ||
|
||||
beta(d4,1,1,2)!=beta(d7,0,0) ||
|
||||
beta(d5,1,1,2)!=beta(d7,1,1) ||
|
||||
beta(d6,1,1,2)!=beta(d7,1)) { return false; }
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/** Tests if a volume is a combinatorial hexagonal prism.
|
||||
* @param d1 an initial dart
|
||||
* @return true iff the volume containing d1 is a combinatorial hexagonal prism.
|
||||
*/
|
||||
bool is_volume_combinatorial_hexagonal_prism(Dart_const_descriptor d1) const
|
||||
{
|
||||
Dart_const_descriptor d2=beta(d1, 2);
|
||||
Dart_const_descriptor d3=beta(d1, 1, 2);
|
||||
Dart_const_descriptor d4=beta(d1, 1, 1, 2);
|
||||
Dart_const_descriptor d5=beta(d1, 1, 1, 1, 2);
|
||||
Dart_const_descriptor d6=beta(d1, 0, 0, 2);
|
||||
Dart_const_descriptor d7=beta(d1, 0, 2);
|
||||
Dart_const_descriptor d8=beta(d2, 1, 1, 2);
|
||||
|
||||
if (d1==null_dart_descriptor || d2==null_dart_descriptor ||
|
||||
d3==null_dart_descriptor || d4==null_dart_descriptor ||
|
||||
d5==null_dart_descriptor || d6==null_dart_descriptor ||
|
||||
d7==null_dart_descriptor || d8==null_dart_descriptor)
|
||||
{ return false; }
|
||||
|
||||
if (!is_face_combinatorial_polygon(d1, 6) ||
|
||||
!is_face_combinatorial_polygon(d2, 4) ||
|
||||
!is_face_combinatorial_polygon(d3, 4) ||
|
||||
!is_face_combinatorial_polygon(d4, 4) ||
|
||||
!is_face_combinatorial_polygon(d5, 4) ||
|
||||
!is_face_combinatorial_polygon(d6, 4) ||
|
||||
!is_face_combinatorial_polygon(d7, 4) ||
|
||||
!is_face_combinatorial_polygon(d8, 6)) { return false; }
|
||||
|
||||
// TODO do better with marks.
|
||||
if (belong_to_same_cell<2,1>(d1, d2) ||
|
||||
belong_to_same_cell<2,1>(d1, d3) ||
|
||||
belong_to_same_cell<2,1>(d1, d4) ||
|
||||
belong_to_same_cell<2,1>(d1, d5) ||
|
||||
belong_to_same_cell<2,1>(d1, d6) ||
|
||||
belong_to_same_cell<2,1>(d1, d7) ||
|
||||
belong_to_same_cell<2,1>(d1, d8) ||
|
||||
belong_to_same_cell<2,1>(d2, d3) ||
|
||||
belong_to_same_cell<2,1>(d2, d4) ||
|
||||
belong_to_same_cell<2,1>(d2, d5) ||
|
||||
belong_to_same_cell<2,1>(d2, d6) ||
|
||||
belong_to_same_cell<2,1>(d2, d7) ||
|
||||
belong_to_same_cell<2,1>(d2, d8) ||
|
||||
belong_to_same_cell<2,1>(d3, d4) ||
|
||||
belong_to_same_cell<2,1>(d3, d5) ||
|
||||
belong_to_same_cell<2,1>(d3, d6) ||
|
||||
belong_to_same_cell<2,1>(d3, d7) ||
|
||||
belong_to_same_cell<2,1>(d3, d8) ||
|
||||
belong_to_same_cell<2,1>(d4, d5) ||
|
||||
belong_to_same_cell<2,1>(d4, d6) ||
|
||||
belong_to_same_cell<2,1>(d4, d7) ||
|
||||
belong_to_same_cell<2,1>(d4, d8) ||
|
||||
belong_to_same_cell<2,1>(d5, d6) ||
|
||||
belong_to_same_cell<2,1>(d5, d7) ||
|
||||
belong_to_same_cell<2,1>(d5, d8) ||
|
||||
belong_to_same_cell<2,1>(d6, d7) ||
|
||||
belong_to_same_cell<2,1>(d6, d8) ||
|
||||
belong_to_same_cell<2,1>(d7, d8))
|
||||
{ return false; }
|
||||
|
||||
if (beta(d2,0,2) !=beta(d3,1) ||
|
||||
beta(d3,0,2) !=beta(d4,1) ||
|
||||
beta(d4,0,2) !=beta(d5,1) ||
|
||||
beta(d5,0,2) !=beta(d6,1) ||
|
||||
beta(d6,0,2) !=beta(d7,1) ||
|
||||
beta(d7,0,2) !=beta(d2,1) ||
|
||||
beta(d3,1,1,2)!=beta(d8,0) ||
|
||||
beta(d4,1,1,2)!=beta(d8,0,0) ||
|
||||
beta(d5,1,1,2)!=beta(d8,0,0,0) ||
|
||||
beta(d6,1,1,2)!=beta(d8,1,1) ||
|
||||
beta(d7,1,1,2)!=beta(d8,1)) { return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Tests if a volume is a combinatorial tetrahedron10.
|
||||
* @param d1 an initial dart
|
||||
* @return true iff the volume containing d1 is a combinatorial tetrahedron10.
|
||||
*/
|
||||
bool is_volume_combinatorial_tetrahedron10(Dart_const_descriptor d1) const
|
||||
{
|
||||
Dart_const_descriptor d2=beta(d1, 2,0);
|
||||
Dart_const_descriptor d3=beta(d2, 0,2);
|
||||
Dart_const_descriptor d4=beta(d2, 1,1,1,2);
|
||||
|
||||
if(d1==null_dart_descriptor || d2==null_dart_descriptor ||
|
||||
d3==null_dart_descriptor || d4==null_dart_descriptor)
|
||||
{ return false; }
|
||||
|
||||
if(!is_face_combinatorial_polygon(d1, 6) ||
|
||||
!is_face_combinatorial_polygon(d2, 6) ||
|
||||
!is_face_combinatorial_polygon(d3, 6) ||
|
||||
!is_face_combinatorial_polygon(d4, 6)) { return false; }
|
||||
|
||||
if(beta(d1, 1,2)!=beta(d1, 2,0) ||
|
||||
beta(d2, 1,2)!=beta(d2, 2,0) ||
|
||||
beta(d3, 1,2)!=beta(d3, 2,0) ||
|
||||
beta(d4, 1,2)!=beta(d4, 2,0)) { return false; }
|
||||
|
||||
// TODO do better with marks (?).
|
||||
if(belong_to_same_cell<2,1>(d1, d2) ||
|
||||
belong_to_same_cell<2,1>(d1, d3) ||
|
||||
belong_to_same_cell<2,1>(d1, d4) ||
|
||||
belong_to_same_cell<2,1>(d2, d3) ||
|
||||
belong_to_same_cell<2,1>(d2, d4) ||
|
||||
belong_to_same_cell<2,1>(d3, d4)) { return false; }
|
||||
|
||||
if(beta(d1,1,1,2)!=beta(d3,0) ||
|
||||
beta(d1,0,2)!=beta(d4,1,1) ||
|
||||
beta(d4,0,2)!=beta(d3,1,1)) { return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Tests if an i-cell can be removed.
|
||||
* An i-cell can be removed if i==dimension or i==dimension-1,
|
||||
* or if there are at most two (i+1)-cell incident to it.
|
||||
* @param adart a dart of the i-cell.
|
||||
|
|
@ -4041,7 +4396,7 @@ namespace CGAL {
|
|||
run(*this,adart,update_attributes);
|
||||
}
|
||||
|
||||
/** Test if an i-cell can be contracted.
|
||||
/** Tests if an i-cell can be contracted.
|
||||
* An i-cell can be contracted if i==1
|
||||
* or if there are at most two (i-1)-cell incident to it.
|
||||
* @param adart a dart of the i-cell.
|
||||
|
|
@ -4407,7 +4762,7 @@ namespace CGAL {
|
|||
return this->template beta<0>(adart1);
|
||||
}
|
||||
|
||||
/** Test if an edge can be inserted onto a 2-cell between two given darts.
|
||||
/** Tests if an edge can be inserted onto a 2-cell between two given darts.
|
||||
* @param adart1 a first dart.
|
||||
* @param adart2 a second dart.
|
||||
* @return true iff an edge can be inserted between adart1 and adart2.
|
||||
|
|
@ -4443,7 +4798,7 @@ namespace CGAL {
|
|||
return generic_insert_cell_1(adart1, adart2, false, update_attributes);
|
||||
}
|
||||
|
||||
/** Test if an edge can be inserted between two different 2-cells
|
||||
/** Tests if an edge can be inserted between two different 2-cells
|
||||
* between two given darts.
|
||||
* @param adart1 a first dart.
|
||||
* @param adart2 a second dart.
|
||||
|
|
@ -4627,7 +4982,7 @@ namespace CGAL {
|
|||
return this->template beta<0>(adart1);
|
||||
}
|
||||
|
||||
/** Test if a 2-cell can be inserted onto a given 3-cell along
|
||||
/** Tests if a 2-cell can be inserted onto a given 3-cell along
|
||||
* a path of edges.
|
||||
* @param afirst iterator on the beginning of the path.
|
||||
* @param alast iterator on the end of the path.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,208 @@
|
|||
// Copyright (c) 2025 CNRS and LIRIS' Establishments (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org)
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef CMAP_ELEMENT_TOPO_H
|
||||
#define CMAP_ELEMENT_TOPO_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace CGAL {
|
||||
namespace CMap {
|
||||
namespace Element_topo {
|
||||
|
||||
enum cell_topo
|
||||
{
|
||||
SQUARE=0,
|
||||
TRIANGLE=1,
|
||||
HEXAHEDRON=2,
|
||||
TETRAHEDRON=3,
|
||||
PRISM=4,
|
||||
PYRAMID=5,
|
||||
GENERIC_2D=6,
|
||||
GENERIC_3D=7,
|
||||
EDGE=8,
|
||||
TETRAHEDRON10=9,
|
||||
PENTAGONAL_PRISM=10,
|
||||
HEXAGONAL_PRISM=11,
|
||||
NO_TYPE=-1
|
||||
};
|
||||
|
||||
inline
|
||||
std::string topo_name(cell_topo t)
|
||||
{
|
||||
switch(t)
|
||||
{
|
||||
case SQUARE: return "SQUARE";
|
||||
case TRIANGLE: return "TRIANGLE";
|
||||
case HEXAHEDRON: return "HEXAHEDRON";
|
||||
case TETRAHEDRON: return "TETRAHEDRON";
|
||||
case PRISM: return "PRISM";
|
||||
case PYRAMID: return "PYRAMID";
|
||||
case GENERIC_2D: return "GENERIC_2D";
|
||||
case GENERIC_3D: return "GENERIC_3D";
|
||||
case EDGE: return "EDGE";
|
||||
case TETRAHEDRON10: return "TETRAHEDRON10";
|
||||
case PENTAGONAL_PRISM: return "PENTAGONAL_PRISM";
|
||||
case HEXAGONAL_PRISM: return "HEXAGONAL_PRISM";
|
||||
case NO_TYPE: return "NO_TYPE";
|
||||
}
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
inline
|
||||
cell_topo topo_from_name(const std::string& t)
|
||||
{
|
||||
if (t=="SQUARE") return SQUARE;
|
||||
if (t=="TRIANGLE") return TRIANGLE;
|
||||
if (t=="HEXAHEDRON") return HEXAHEDRON;
|
||||
if (t=="TETRAHEDRON") return TETRAHEDRON;
|
||||
if (t=="PRISM") return PRISM;
|
||||
if (t=="PYRAMID") return PYRAMID;
|
||||
if (t=="GENERIC_2D") return GENERIC_2D;
|
||||
if (t=="GENERIC_3D") return GENERIC_3D;
|
||||
if (t=="EDGE") return EDGE;
|
||||
if (t=="TETRAHEDRON10") return TETRAHEDRON10;
|
||||
if (t=="PENTAGONAL_PRISM") return PENTAGONAL_PRISM;
|
||||
if (t=="HEXAGONAL_PRISM") return HEXAGONAL_PRISM;
|
||||
if (t=="NO_TYPE") return NO_TYPE;
|
||||
return NO_TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief To get the type of `dimD` cell of the `CMap` of `cmapdim` dimension.
|
||||
*/
|
||||
template<typename CMap, unsigned int dimcell,
|
||||
unsigned int cmapdim=CMap::dimension>
|
||||
struct Get_cell_topo
|
||||
{
|
||||
static cell_topo run(CMap&, typename CMap::Dart_descriptor dh,
|
||||
typename CMap::Dart_descriptor& starting_dart)
|
||||
{
|
||||
starting_dart=dh;
|
||||
return NO_TYPE;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief To get the type associated of an edge. For now only one type.
|
||||
*/
|
||||
template<typename CMap, unsigned int cmapdim>
|
||||
struct Get_cell_topo<CMap, 1, cmapdim>
|
||||
{
|
||||
static cell_topo run(CMap&, typename CMap::Dart_descriptor it,
|
||||
typename CMap::Dart_descriptor& starting_dart)
|
||||
{
|
||||
starting_dart=it;
|
||||
return EDGE;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief To get the type of 2D cell of the CMap of cmapdim dimension.
|
||||
*/
|
||||
template<typename CMap, unsigned int cmapdim>
|
||||
struct Get_cell_topo<CMap, 2, cmapdim>
|
||||
{
|
||||
static cell_topo run(CMap& cmap, typename CMap::Dart_descriptor it,
|
||||
typename CMap::Dart_descriptor& starting_dart)
|
||||
{
|
||||
starting_dart=it;
|
||||
|
||||
if (cmap.is_face_combinatorial_polygon(it, 3))
|
||||
{ return TRIANGLE; }
|
||||
|
||||
else if (cmap.is_face_combinatorial_polygon(it, 4))
|
||||
{ return SQUARE; }
|
||||
|
||||
return GENERIC_2D;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief To get the type of 3D cell of the CMap of dimension 3.
|
||||
*/
|
||||
template<typename CMap>
|
||||
struct Get_cell_topo<CMap, 3, 3>
|
||||
{
|
||||
static cell_topo run(CMap& cmap, typename CMap::Dart_descriptor it,
|
||||
typename CMap::Dart_descriptor& starting_dart)
|
||||
{
|
||||
starting_dart=it;
|
||||
|
||||
if (cmap.is_volume_combinatorial_tetrahedron(it))
|
||||
{ return TETRAHEDRON; }
|
||||
|
||||
else if (cmap.is_volume_combinatorial_hexahedron(it))
|
||||
{ return HEXAHEDRON; }
|
||||
|
||||
else if(cmap.is_volume_combinatorial_tetrahedron10(it))
|
||||
{ return TETRAHEDRON10; }
|
||||
|
||||
// For non symetric object, we need to test all darts
|
||||
for (auto itv=cmap.template darts_of_cell<3>(it).begin(),
|
||||
itvend=cmap.template darts_of_cell<3>(it).end(); itv!=itvend; ++itv)
|
||||
{
|
||||
starting_dart=itv;
|
||||
|
||||
if (cmap.is_volume_combinatorial_prism(itv))
|
||||
{ return PRISM; }
|
||||
|
||||
else if (cmap.is_volume_combinatorial_pentagonal_prism(itv))
|
||||
{ return PENTAGONAL_PRISM; }
|
||||
|
||||
else if (cmap.is_volume_combinatorial_pyramid(itv))
|
||||
{ return PYRAMID; }
|
||||
|
||||
else if (cmap.is_volume_combinatorial_hexagonal_prism(itv))
|
||||
{ return HEXAGONAL_PRISM; }
|
||||
|
||||
}
|
||||
|
||||
return GENERIC_3D;
|
||||
}
|
||||
};
|
||||
|
||||
template<unsigned int dimcell, typename CMap>
|
||||
cell_topo get_cell_topo(CMap& cmap, typename CMap::Dart_descriptor it,
|
||||
typename CMap::Dart_descriptor& starting_dart)
|
||||
{ return Get_cell_topo<CMap, dimcell>::run(cmap, it, starting_dart); }
|
||||
|
||||
template<unsigned int dimcell, typename CMap>
|
||||
cell_topo get_cell_topo(CMap& cmap, typename CMap::Dart_descriptor it)
|
||||
{
|
||||
typename CMap::Dart_descriptor dummy;
|
||||
return get_cell_topo<dimcell, CMap>(cmap, it, dummy);
|
||||
}
|
||||
|
||||
template<unsigned int dimcell, typename CMap>
|
||||
cell_topo get_cell_topo(const CMap& cmap, typename CMap::Dart_const_descriptor it,
|
||||
typename CMap::Dart_const_descriptor& starting_dart)
|
||||
{
|
||||
typename CMap::Dart_descriptor it2=const_cast<CMap&>(cmap).dart_descriptor
|
||||
(cmap.darts().index(it));
|
||||
typename CMap::Dart_descriptor sd2;
|
||||
cell_topo res=Get_cell_topo<CMap, dimcell>::run(const_cast<CMap&>(cmap),
|
||||
it2, sd2);
|
||||
starting_dart=sd2;
|
||||
return res;
|
||||
}
|
||||
|
||||
template<unsigned int dimcell, typename CMap>
|
||||
cell_topo get_cell_topo(const CMap& cmap, typename CMap::Dart_const_descriptor it)
|
||||
{
|
||||
typename CMap::Dart_descriptor it2=it;
|
||||
return Get_cell_topo<CMap, dimcell>::run(const_cast<CMap&>(cmap), it2);
|
||||
}
|
||||
|
||||
} } } // namespace CGAL::CMap::Element_topo
|
||||
|
||||
#endif // CMAP_ELEMENT_TOPO_H
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
namespace CGAL {
|
||||
namespace IO {
|
||||
|
||||
/** \file VTK.h
|
||||
* Functions to import/export 3D Linear_cell_complex from/to VTK legacy ASCII
|
||||
* format.
|
||||
*
|
||||
* Only supports:
|
||||
* - `CGAL::Linear_cell_complex_for_combinatorial_map<3,3>`
|
||||
* - VTK legacy ASCII format (.vtk files)
|
||||
* - Optional scalar fields for vertices and volumes
|
||||
*
|
||||
* Supported VTK cell types:
|
||||
* - VTK_TETRA (10): Tetrahedron
|
||||
* - VTK_VOXEL (11): Voxel (special hexahedron ordering)
|
||||
* - VTK_HEXAHEDRON (12): Hexahedron
|
||||
* - VTK_WEDGE (13): Prism/Wedge
|
||||
* - VTK_PYRAMID (14): Pyramid
|
||||
* - VTK_PENTAGONAL_PRISM (15): Pentagonal prism
|
||||
* - VTK_HEXAGONAL_PRISM (16): Hexagonal prism
|
||||
* - VTK_POLYHEDRON (42): Generic polyhedron
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Reads a VTK legacy ASCII file and load it into a 3D
|
||||
* linear cell complex.
|
||||
* \ingroup PkgLinearCellComplexRefIOVTK
|
||||
*
|
||||
* \tparam LCC must be a `CGAL::Linear_cell_complex_for_combinatorial_map<3,3>`
|
||||
* \tparam VertexScalarType Type for vertex scalar data (default: float)
|
||||
* \tparam VolumeScalarType Type for volume scalar data (default: float)
|
||||
* \param filename Path to the VTK file
|
||||
* \param alcc The linear cell complex to populate (will be cleared first)
|
||||
* \param vertex_scalars Optional output vector to store per-vertex scalar values.
|
||||
* If provided, will be resized to match number of vertices.
|
||||
* \param volume_scalars Optional output vector to store per-volume scalar values.
|
||||
* If provided, will be resized to match number of volumes.
|
||||
* \return `true` if loading was successful, `false` otherwise
|
||||
*/
|
||||
template <typename LCC, typename VertexScalarType, typename VolumeScalarType>
|
||||
bool read_VTK(const char* filename,
|
||||
LCC& alcc,
|
||||
std::vector<VertexScalarType>* vertex_scalars=nullptr,
|
||||
std::vector<VolumeScalarType>* volume_scalars=nullptr);
|
||||
|
||||
/**
|
||||
* \brief Writes a 3D Linear_cell_complex to a VTK legacy ASCII file.
|
||||
* \ingroup PkgLinearCellComplexRefIOVTK
|
||||
*
|
||||
* \tparam LCC must be a `CGAL::Linear_cell_complex_for_combinatorial_map<3,3>`
|
||||
* \tparam VertexScalarType Type for vertex scalar data (default: float)
|
||||
* \tparam VolumeScalarType Type for volume scalar data (default: float)
|
||||
* \param filename Path to the output VTK file
|
||||
* \param alcc The linear cell complex to export
|
||||
* \param vertex_scalars Optional per-vertex scalar data. If provided, must have
|
||||
* same size as number of vertex attributes in the LCC.
|
||||
* \param volume_scalars Optional per-volume scalar data. If provided, must have
|
||||
* same size as number of 3-cells in the LCC.
|
||||
* \return `true` if writing was successful, `false` otherwise
|
||||
*/
|
||||
template <typename LCC, typename VertexScalarType, typename VolumeScalarType>
|
||||
bool write_VTK(const char* filename,
|
||||
const LCC& alcc,
|
||||
const std::vector<VertexScalarType>* vertex_scalars=nullptr,
|
||||
const std::vector<VolumeScalarType>* volume_scalars=nullptr);
|
||||
|
||||
} // namespace IO
|
||||
} // namespace CGAL
|
||||
|
|
@ -289,6 +289,18 @@ The following example shows the use of \link GenericMap::insert_cell_1_between_t
|
|||
Result of the run of the linear_cell_complex_3_insert program. A window shows the 3D cube where one face has a hole.
|
||||
\cgalFigureEnd
|
||||
|
||||
\subsection Linear_cell_complexWriteVTK Writing a Linear Cell Complex to a VTK File
|
||||
\anchor ssecLCCWriteVtK
|
||||
|
||||
This example loads a 3D linear cell complex from a `.3map` file (using the `operator>>`). It computes for each 3-cell (volume) the number of incident vertices (0-cells), stores these values in a `std::vector<std::size_t>`, and writes the result to a `.vtk` file using `CGAL::IO::write_VTK()`, with the computed values as scalars for each volume.
|
||||
|
||||
\cgalExample{Linear_cell_complex/linear_cell_complex_3_vtk_io.cpp}
|
||||
|
||||
\cgalFigureBegin{fig_lcc_export_vtk,lcc-export-vtk.png}
|
||||
Visualization of the VTK file generated by the `linear_cell_complex_3_vtk_io` program, using Paraview. Each volume is colored depending on its number of vertices.
|
||||
\cgalFigureEnd
|
||||
|
||||
|
||||
\section Linear_cell_complexDesign Design and Implementation History
|
||||
|
||||
This package was developed by Guillaume Damiand, with the help of Andreas Fabri, Sébastien Loriot and Laurent Rineau. Monique Teillaud and Bernd Gärtner contributed to the manual.
|
||||
|
|
|
|||
|
|
@ -23,6 +23,14 @@
|
|||
/// \defgroup PkgDrawLinearCellComplex Draw a Linear Cell Complex
|
||||
/// \ingroup PkgLinearCellComplexRef
|
||||
|
||||
/// \defgroup PkgLinearCellComplexRefIO IO Functions for LCC
|
||||
/// \ingroup PkgLinearCellComplexRef
|
||||
|
||||
/*! High-level operations.
|
||||
\cgalInclude{CGAL/Linear_cell_complex/IO/VTK.h}
|
||||
*/
|
||||
/// \defgroup PkgLinearCellComplexRefIOVTK VTK IO Functions for LCC
|
||||
/// \ingroup PkgLinearCellComplexRefIO
|
||||
|
||||
/*!
|
||||
\addtogroup PkgLinearCellComplexRef
|
||||
|
|
@ -74,4 +82,10 @@
|
|||
- \link PkgDrawLinearCellComplex CGAL::draw<LCC>() \endlink
|
||||
- \link PkgDrawLinearCellComplex CGAL::add_in_graphics_scene<LCC, BufferType, DrawingFunctor>() \endlink
|
||||
|
||||
\cgalCRPSubsection{IO Functions for LCC}
|
||||
- \link PkgCombinatorialMapsRefIO `std::ostream& operator<< (std::ostream& os, const GenericMap& amap)` \endlink
|
||||
- \link PkgCombinatorialMapsRefIO `std::ifstream& operator>> (std::ifstream& is, GenericMap& amap)` \endlink
|
||||
- \link PkgLinearCellComplexRefIOVTK `CGAL::IO::Read_VTK<LCC>()` \endlink
|
||||
- \link PkgLinearCellComplexRefIOVTK `CGAL::IO::Write_VTK<LCC>()` \endlink
|
||||
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -6,4 +6,5 @@
|
|||
\example Linear_cell_complex/linear_cell_complex_3_incremental_builder.cpp
|
||||
\example Linear_cell_complex/draw_linear_cell_complex.cpp
|
||||
\example Linear_cell_complex/linear_cell_complex_3_insert.cpp
|
||||
\example Linear_cell_complex/linear_cell_complex_3_vtk_io.cpp
|
||||
*/
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 89 KiB |
|
|
@ -27,6 +27,7 @@ create_single_source_cgal_program("linear_cell_complex_4.cpp")
|
|||
create_single_source_cgal_program("read_plane_graph_in_lcc_2.cpp")
|
||||
create_single_source_cgal_program("voronoi_2.cpp")
|
||||
create_single_source_cgal_program("voronoi_3.cpp")
|
||||
create_single_source_cgal_program("linear_cell_complex_3_vtk_io.cpp")
|
||||
|
||||
create_single_source_cgal_program("draw_linear_cell_complex.cpp")
|
||||
if(CGAL_Qt6_FOUND)
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,34 @@
|
|||
#include <CGAL/Linear_cell_complex_for_combinatorial_map.h>
|
||||
#include <CGAL/Linear_cell_complex/IO/VTK.h>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
|
||||
int main()
|
||||
{
|
||||
CGAL::Linear_cell_complex_for_combinatorial_map<3> lcc;
|
||||
std::ifstream is("data/beam-with-mixed-cells.3map");
|
||||
if(!is)
|
||||
{
|
||||
std::cout<<"Error opening data/beam-with-mixed-cells.3map."<<std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
is>>lcc;
|
||||
// Compute per-volume vertex count
|
||||
std::vector<std::size_t> volume_scalars;
|
||||
for(auto it=lcc.template one_dart_per_cell<3>().begin(),
|
||||
itend=lcc.template one_dart_per_cell<3>().end(); it!=itend; ++it)
|
||||
{
|
||||
std::size_t nbv=lcc.template one_dart_per_incident_cell<0,3>(it).size();
|
||||
volume_scalars.push_back(nbv);
|
||||
}
|
||||
|
||||
if(!CGAL::IO::write_VTK("beam-with-mixed-cells.vtk", lcc, nullptr,
|
||||
&volume_scalars))
|
||||
{
|
||||
std::cout<<"Error for write_VTK."<<std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,719 @@
|
|||
// Copyright (c) 2025 CNRS and LIRIS' Establishments (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org)
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
|
||||
|
||||
#ifndef CGAL_LCC_IO_VTK_H
|
||||
#define CGAL_LCC_IO_VTK_H
|
||||
|
||||
#include <CGAL/Linear_cell_complex_incremental_builder_3.h>
|
||||
#include <CGAL/assertions.h>
|
||||
#include <CGAL/Element_topo.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
namespace CGAL {
|
||||
namespace IO {
|
||||
|
||||
/*
|
||||
* Functions to import/export 3D Linear_cell_complex from/to VTK legacy ASCII
|
||||
* format.
|
||||
*
|
||||
* Only supports:
|
||||
* - Linear_cell_complex_for_combinatorial_map<3,3>
|
||||
* - VTK legacy ASCII format (.vtk files)
|
||||
* - Optional scalar fields for vertices and volumes
|
||||
*
|
||||
* Supported VTK cell types:
|
||||
* - VTK_TETRA (10): Tetrahedron
|
||||
* - VTK_VOXEL (11): Voxel (special hexahedron ordering)
|
||||
* - VTK_HEXAHEDRON (12): Hexahedron
|
||||
* - VTK_WEDGE (13): Prism/Wedge
|
||||
* - VTK_PYRAMID (14): Pyramid
|
||||
* - VTK_PENTAGONAL_PRISM (15): Pentagonal prism
|
||||
* - VTK_HEXAGONAL_PRISM (16): Hexagonal prism
|
||||
* - VTK_POLYHEDRON (42): Generic polyhedron
|
||||
*/
|
||||
|
||||
// ============================================================================
|
||||
// Declarations
|
||||
// ============================================================================
|
||||
|
||||
/*
|
||||
* Read a VTK legacy ASCII file and load it into a 3D Linear_cell_complex.
|
||||
*
|
||||
* \tparam LCC must be a Linear_cell_complex_for_combinatorial_map<3,3>
|
||||
* \tparam VertexScalarType Type for vertex scalar data (default: float)
|
||||
* \tparam VolumeScalarType Type for volume scalar data (default: float)
|
||||
* \param alcc The Linear_cell_complex to populate (will be cleared first)
|
||||
* \param filename Path to the VTK file
|
||||
* \param vertex_scalars Optional output vector to store per-vertex scalar values.
|
||||
* If provided, will be resized to match number of vertices.
|
||||
* \param volume_scalars Optional output vector to store per-volume scalar values.
|
||||
* If provided, will be resized to match number of volumes.
|
||||
* \return `true` if loading was successful, `false` otherwise
|
||||
*/
|
||||
template <typename LCC, typename VertexScalarType,
|
||||
typename VolumeScalarType>
|
||||
bool read_VTK(const char* filename,
|
||||
LCC& alcc,
|
||||
std::vector<VertexScalarType>* vertex_scalars,
|
||||
std::vector<VolumeScalarType>* volume_scalars);
|
||||
|
||||
/*
|
||||
* Write a 3D Linear_cell_complex to a VTK legacy ASCII file.
|
||||
*
|
||||
* \tparam LCC must be a Linear_cell_complex_for_combinatorial_map<3,3>
|
||||
* \tparam VertexScalarType Type for vertex scalar data (default: float)
|
||||
* \tparam VolumeScalarType Type for volume scalar data (default: float)
|
||||
* \param alcc The Linear_cell_complex to export
|
||||
* \param filename Path to the output VTK file
|
||||
* \param vertex_scalars Optional per-vertex scalar data. If provided, must have
|
||||
* same size as number of vertex attributes in the LCC.
|
||||
* \param volume_scalars Optional per-volume scalar data. If provided, must have
|
||||
* same size as number of 3-cells in the LCC.
|
||||
* \return `true` if writing was successful, `false` otherwise
|
||||
*/
|
||||
template <typename LCC, typename VertexScalarType,
|
||||
typename VolumeScalarType>
|
||||
bool write_VTK(const char* filename,
|
||||
const LCC& alcc,
|
||||
const std::vector<VertexScalarType>* vertex_scalars,
|
||||
const std::vector<VolumeScalarType>* volume_scalars);
|
||||
|
||||
// "Advanced" versions with functors
|
||||
template <typename LCC, typename PointFunctor, typename CellFunctor>
|
||||
bool write_VTK_with_fct(const char* filename, const LCC& alcc,
|
||||
PointFunctor ptval, CellFunctor cellval);
|
||||
|
||||
// ============================================================================
|
||||
// Implementation details
|
||||
// ============================================================================
|
||||
|
||||
namespace internal
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// VTK type name mapping
|
||||
// bit, unsigned_char, char, unsigned_short, short, unsigned_int, int,
|
||||
// unsigned_long, long, float, double.
|
||||
template<typename T>
|
||||
struct gettype
|
||||
{ static std::string name() { return "unknown"; }};
|
||||
template<>
|
||||
struct gettype<bool>
|
||||
{ static std::string name() { return "bit"; }};
|
||||
template<>
|
||||
struct gettype<unsigned char>
|
||||
{ static std::string name() { return "unsigned_char"; }};
|
||||
template<>
|
||||
struct gettype<char>
|
||||
{ static std::string name() { return "char"; }};
|
||||
template<>
|
||||
struct gettype<unsigned short int>
|
||||
{ static std::string name() { return "unsigned_short"; }};
|
||||
template<>
|
||||
struct gettype<short int>
|
||||
{ static std::string name() { return "short"; }};
|
||||
template<>
|
||||
struct gettype<unsigned int>
|
||||
{ static std::string name() { return "unsigned_int"; }};
|
||||
template<>
|
||||
struct gettype<int>
|
||||
{ static std::string name() { return "int"; }};
|
||||
template<>
|
||||
struct gettype<unsigned long int>
|
||||
{ static std::string name() { return "unsigned_long"; }};
|
||||
template<>
|
||||
struct gettype<long int>
|
||||
{ static std::string name() { return "long"; }};
|
||||
template<>
|
||||
struct gettype<float>
|
||||
{ static std::string name() { return "float"; }};
|
||||
template<>
|
||||
struct gettype<double>
|
||||
{ static std::string name() { return "double"; }};
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// VTK cell type constants
|
||||
enum VTK_Cell_Type
|
||||
{
|
||||
VTK_TETRA = 10,
|
||||
VTK_VOXEL = 11,
|
||||
VTK_HEXAHEDRON = 12,
|
||||
VTK_WEDGE = 13, // Prism
|
||||
VTK_PYRAMID = 14,
|
||||
VTK_PENTAGONAL_PRISM = 15,
|
||||
VTK_HEXAGONAL_PRISM = 16,
|
||||
VTK_POLYHEDRON = 42 // Generic cell
|
||||
};
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// Write cell_data.
|
||||
template<typename FCT>
|
||||
struct Write_cell_data
|
||||
{
|
||||
/// nb is the number of cells,
|
||||
/// fct is a function having 3 parameters: a lcc, a dart_descriptor,
|
||||
/// an the index of the cell.
|
||||
template<typename LCC>
|
||||
static void run(std::ofstream& fo, LCC& lcc, std::size_t nb, FCT fct)
|
||||
{
|
||||
fo<<"CELL_DATA "<<nb<<std::endl;
|
||||
fo<<"SCALARS cell_scalars "
|
||||
<<gettype<decltype(fct(lcc, lcc.null_dart_descriptor, 0))>::name()
|
||||
<<" 1"<<std::endl;
|
||||
fo<<"LOOKUP_TABLE default"<<std::endl;
|
||||
std::size_t i=0;
|
||||
for(auto itvol=lcc.template one_dart_per_cell<3>().begin(),
|
||||
itvolend=lcc.template one_dart_per_cell<3>().end();
|
||||
itvol!=itvolend; ++itvol, ++i)
|
||||
{ fo<<fct(lcc, itvol, i)<<std::endl; }
|
||||
fo<<std::endl;
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct Write_cell_data<std::nullptr_t>
|
||||
{
|
||||
template<typename LCC>
|
||||
static void run(std::ofstream&, LCC&, std::size_t, std::nullptr_t)
|
||||
{}
|
||||
};
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// Write point_data.
|
||||
template<typename FCT>
|
||||
struct Write_point_data
|
||||
{
|
||||
/// nb is the number of cells,
|
||||
/// fct is a function having 3 parameters: a lcc, a dart_descriptor,
|
||||
/// an the index of the cell.
|
||||
template<typename LCC>
|
||||
static void run(std::ofstream& fo, LCC& lcc, std::size_t nb, FCT fct)
|
||||
{
|
||||
fo<<"POINT_DATA "<<nb<<std::endl;
|
||||
fo<<"SCALARS point_scalars "
|
||||
<<gettype<decltype(fct(lcc, lcc.null_dart_descriptor, 0))>::name()
|
||||
<<" 1"<<std::endl;
|
||||
fo<<"LOOKUP_TABLE default"<<std::endl;
|
||||
std::size_t i=0;
|
||||
for(auto itv=lcc.vertex_attributes().begin(),
|
||||
itvend=lcc.vertex_attributes().end(); itv!=itvend; ++itv, ++i)
|
||||
{ fo<<fct(lcc, lcc.template dart_of_attribute<0>(itv), i)<<std::endl; }
|
||||
fo<<std::endl;
|
||||
}
|
||||
};
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
template<>
|
||||
struct Write_point_data<std::nullptr_t>
|
||||
{
|
||||
template<typename LCC>
|
||||
static void run(std::ofstream&, LCC&, std::size_t, std::nullptr_t)
|
||||
{}
|
||||
};
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Read data, stored values as T.
|
||||
template<typename T>
|
||||
bool read_data(std::istream& fi, std::string& line, std::vector<T>& data)
|
||||
{
|
||||
std::string txt, data_type;
|
||||
std::size_t nb;
|
||||
std::istringstream inputline(line);
|
||||
inputline>>txt>>nb; // "CELL_DATA xxx"
|
||||
fi>>txt>>txt; // "SCALARS cell_scalars "
|
||||
fi>>data_type>>txt; // type for data
|
||||
fi>>txt>>txt; // "LOOKUP_TABLE default"
|
||||
if(!fi.good())
|
||||
{ return false; }
|
||||
data.clear();
|
||||
data.reserve(nb);
|
||||
for(std::size_t i=0; i<nb; ++i)
|
||||
{
|
||||
if(!(fi>>txt))
|
||||
{ return false; }
|
||||
|
||||
std::stringstream ss{txt};
|
||||
T t;
|
||||
ss>>t;
|
||||
|
||||
data.push_back(t);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Helper: detect VTK cell type from a 3-cell
|
||||
template<typename LCC>
|
||||
VTK_Cell_Type get_vtk_cell_type(const LCC& lcc,
|
||||
typename LCC::Dart_const_descriptor itvol,
|
||||
typename LCC::Dart_const_descriptor& sd)
|
||||
{
|
||||
using namespace CGAL::CMap::Element_topo;
|
||||
cell_topo vol_type=get_cell_topo<3>(lcc, itvol, sd);
|
||||
switch(vol_type)
|
||||
{
|
||||
case TETRAHEDRON: return VTK_TETRA;
|
||||
case PYRAMID: return VTK_PYRAMID;
|
||||
case PRISM: return VTK_WEDGE;
|
||||
case HEXAHEDRON: return VTK_HEXAHEDRON;
|
||||
// case PENTAGONAL_PRISM: return VTK_PENTAGONAL_PRISM;
|
||||
// case HEXAGONAL_PRISM: return VTK_HEXAGONAL_PRISM;
|
||||
// 24 QUADRATIC_TETRA
|
||||
// 25 QUADRATIC_HEXAHEDRON
|
||||
// 26 QUADRATIC_WEDGE
|
||||
// 27 QUADRATIC_PYRAMID
|
||||
default: break;
|
||||
}
|
||||
return VTK_POLYHEDRON;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
template <typename LCC, typename VertexScalarType=float,
|
||||
typename CellScalarType=float>
|
||||
bool read_lcc_from_vtk_ascii(std::istream& is, LCC& alcc,
|
||||
std::vector<VertexScalarType>* vertex_scalars=nullptr,
|
||||
std::vector<CellScalarType>* cell_scalars=nullptr)
|
||||
{
|
||||
static_assert(LCC::dimension==3 && LCC::ambient_dimension==3,
|
||||
"read_VTK() only supports 3D Linear_cell_complexes (3,3)");
|
||||
|
||||
using Point=typename LCC::Point;
|
||||
using FT=typename LCC::FT;
|
||||
|
||||
Linear_cell_complex_incremental_builder_3<LCC> ib(alcc);
|
||||
|
||||
std::string line, tmp;
|
||||
std::size_t npoints, ncells;
|
||||
|
||||
// Skip to POINTS section
|
||||
while(std::getline(is, line) && line.find("POINTS")==std::string::npos)
|
||||
{}
|
||||
if(is.eof())
|
||||
{
|
||||
std::cerr<<"[ERROR] read_VTK: POINTS section not found"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::stringstream ss(line);
|
||||
std::getline(ss, tmp, ' '); // skip "POINTS"
|
||||
ss>>npoints;
|
||||
|
||||
// Read points
|
||||
std::vector<typename LCC::Vertex_attribute_descriptor> points(npoints);
|
||||
for(std::size_t i=0; i<npoints; ++i)
|
||||
{
|
||||
FT x, y, z;
|
||||
if(!(is>>x>>y>>z))
|
||||
{
|
||||
std::cerr<<"[ERROR] read_VTK: failed to read point "<<i<<std::endl;
|
||||
return false;
|
||||
}
|
||||
points[i]=ib.add_vertex(Point(x, y, z));
|
||||
}
|
||||
|
||||
// Skip to CELLS section
|
||||
while(std::getline(is, line) && line.find("CELLS")==std::string::npos)
|
||||
{}
|
||||
if(is.eof())
|
||||
{
|
||||
std::cerr<<"[ERROR] read_VTK: CELLS section not found"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
ss=std::stringstream(line);
|
||||
std::getline(ss, tmp, ' '); // skip "CELLS"
|
||||
ss>>ncells;
|
||||
|
||||
// Read connectivity
|
||||
std::vector<std::vector<std::size_t>> faces(ncells);
|
||||
std::size_t points_per_cell;
|
||||
for(std::size_t i=0; i<ncells; ++i)
|
||||
{
|
||||
if(!(is>>points_per_cell))
|
||||
{
|
||||
std::cerr<<"[ERROR] read_VTK: failed to read cell "<<i<<std::endl;
|
||||
return false;
|
||||
}
|
||||
faces[i].resize(points_per_cell);
|
||||
for(std::size_t j=0; j<points_per_cell; ++j)
|
||||
{
|
||||
if(!(is>>faces[i][j]))
|
||||
{
|
||||
std::cerr<<"[ERROR] read_VTK: failed to read cell "<<i<<" vertex "<<j<< std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Skip to CELL_TYPES section
|
||||
while(std::getline(is, line) && line.find("CELL_TYPES")==std::string::npos)
|
||||
{}
|
||||
if(is.eof())
|
||||
{
|
||||
std::cerr<<"[ERROR] read_VTK: CELL_TYPES section not found"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create cells based on types
|
||||
std::size_t cell_type;
|
||||
std::set<std::size_t> error_types;
|
||||
for(std::size_t i = 0; i<ncells; ++i)
|
||||
{
|
||||
if(!(is>>cell_type))
|
||||
{
|
||||
std::cerr<<"[ERROR] read_VTK: failed to read cell type "<<i<< std::endl;
|
||||
return false;
|
||||
}
|
||||
const auto& v=faces[i];
|
||||
switch(cell_type)
|
||||
{
|
||||
case VTK_TETRA:
|
||||
if(v.size()==4)
|
||||
{ make_tetrahedron_with_builder(ib, v[0], v[1], v[2], v[3]); }
|
||||
break;
|
||||
case VTK_VOXEL:
|
||||
if(v.size()==8)
|
||||
{ make_hexahedron_with_builder(ib, v[0], v[1], v[3], v[2], v[4], v[5],
|
||||
v[7], v[6]); }
|
||||
break;
|
||||
case VTK_HEXAHEDRON:
|
||||
if(v.size()==8)
|
||||
{ make_hexahedron_with_builder(ib, v[0], v[1], v[2], v[3], v[4], v[5],
|
||||
v[6], v[7]); }
|
||||
break;
|
||||
case VTK_WEDGE: // PRISM
|
||||
if(v.size()==6)
|
||||
{ make_prism_with_builder(ib, v[0], v[1], v[2], v[3], v[4], v[5]); }
|
||||
break;
|
||||
case VTK_PYRAMID:
|
||||
if(v.size()==5)
|
||||
{ make_pyramid_with_builder(ib, v[0], v[1], v[2], v[3], v[4]); }
|
||||
break;
|
||||
case VTK_PENTAGONAL_PRISM:
|
||||
if(v.size()==10)
|
||||
{ make_pentagonal_prism_with_builder(ib, v[0], v[1], v[2], v[3], v[4],
|
||||
v[5], v[6], v[7], v[8], v[9]); }
|
||||
break;
|
||||
case VTK_HEXAGONAL_PRISM:
|
||||
if(v.size()==12)
|
||||
{ make_hexagonal_prism_with_builder(ib, v[0], v[1], v[2], v[3], v[4],
|
||||
v[5], v[6], v[7], v[8], v[9],
|
||||
v[10], v[11]); }
|
||||
break;
|
||||
case VTK_POLYHEDRON: // GENERIC CELL
|
||||
make_generic_cell_with_builder(ib, v);
|
||||
break;
|
||||
default:
|
||||
if(error_types.count(cell_type)==0)
|
||||
{
|
||||
std::cerr<<"[ERROR] read_VTK: type "<<cell_type<<" unknown."<<std::endl;
|
||||
error_types.insert(cell_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up unused vertex attributes
|
||||
for(auto itv=alcc.vertex_attributes().begin();
|
||||
itv!=alcc.vertex_attributes().end(); ++itv)
|
||||
{
|
||||
if(alcc.template dart_of_attribute<0>(itv)==alcc.null_descriptor)
|
||||
{ alcc.erase_vertex_attribute(itv); }
|
||||
}
|
||||
|
||||
if(vertex_scalars!=nullptr)
|
||||
{ vertex_scalars->clear(); }
|
||||
if(cell_scalars!=nullptr)
|
||||
{ cell_scalars->clear(); }
|
||||
|
||||
while(std::getline(is, line))
|
||||
{
|
||||
// Read POINT_DATA scalars if present
|
||||
if(vertex_scalars!=nullptr && line.find("POINT_DATA")!=std::string::npos)
|
||||
{
|
||||
if(!read_data(is, line, *vertex_scalars))
|
||||
{
|
||||
std::cerr<<"[ERROR] read_VTK: error when reading POINT_DATA."
|
||||
<<std::endl;
|
||||
}
|
||||
}
|
||||
// Read CELL_DATA scalars if present
|
||||
else if(cell_scalars!=nullptr && line.find("CELL_DATA")!=std::string::npos)
|
||||
{
|
||||
if(!read_data(is, line, *cell_scalars))
|
||||
{
|
||||
std::cerr<<"[ERROR] read_VTK: error when reading CELL_DATA."
|
||||
<<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
template<class LCC>
|
||||
bool write_lcc_topo_to_vtk_ascii(std::ostream& os, const LCC& alcc,
|
||||
std::size_t& nbpts, std::size_t& nbcells)
|
||||
{
|
||||
static_assert(LCC::dimension==3 && LCC::ambient_dimension==3,
|
||||
"write_VTK() only supports 3D Linear_cell_complexes (3,3)");
|
||||
|
||||
// Write VTK header
|
||||
os<<"# vtk DataFile Version 2.0\n";
|
||||
os<<"CGAL Linear_cell_complex\n";
|
||||
os<<"ASCII\n";
|
||||
os<<"DATASET UNSTRUCTURED_GRID\n\n";
|
||||
|
||||
// Build vertex index map and write points
|
||||
std::unordered_map<typename LCC::Vertex_attribute_const_descriptor, std::size_t>
|
||||
index;
|
||||
nbpts=0;
|
||||
os<<"POINTS "<<alcc.vertex_attributes().size()<<" double"<<std::endl;
|
||||
for(auto itv=alcc.vertex_attributes().begin(),
|
||||
itvend=alcc.vertex_attributes().end(); itv!=itvend; ++itv)
|
||||
{
|
||||
os<<" "<<itv->point()<<std::endl;
|
||||
index[itv]=nbpts++;
|
||||
}
|
||||
os<<std::endl;
|
||||
|
||||
// Count cells and build connectivity
|
||||
nbcells=0;
|
||||
std::size_t total_size=0;
|
||||
std::ostringstream cell_stream, type_stream;
|
||||
typename LCC::Dart_const_descriptor sd;
|
||||
|
||||
// Write cells section
|
||||
for(typename LCC::template One_dart_per_cell_range<3>::const_iterator
|
||||
itvol=alcc.template one_dart_per_cell<3>().begin(),
|
||||
itvolend=alcc.template one_dart_per_cell<3>().end();
|
||||
itvol!=itvolend; ++itvol)
|
||||
{
|
||||
++nbcells;
|
||||
++total_size; // for the number of vertices
|
||||
VTK_Cell_Type cell_type=get_vtk_cell_type(alcc, itvol, sd);
|
||||
type_stream<<static_cast<int>(cell_type)<<std::endl;
|
||||
|
||||
if(cell_type==VTK_TETRA)
|
||||
{
|
||||
cell_stream<<" 4 "
|
||||
<<index[alcc.vertex_attribute(sd)]<<" "
|
||||
<<index[alcc.vertex_attribute(alcc.template beta<1>(sd))]<<" "
|
||||
<<index[alcc.vertex_attribute(alcc.template beta<0>(sd))]<<" "
|
||||
<<index[alcc.vertex_attribute(alcc.template beta<2, 0>(sd))]<<std::endl;
|
||||
total_size+=4;
|
||||
}
|
||||
else if(cell_type==VTK_PYRAMID)
|
||||
{
|
||||
cell_stream<<" 5 "
|
||||
<<index[alcc.vertex_attribute(sd)]<<" "
|
||||
<<index[alcc.vertex_attribute(alcc.template beta<1>(sd))]<<" "
|
||||
<<index[alcc.vertex_attribute(alcc.template beta<1,1>(sd))]<<" "
|
||||
<<index[alcc.vertex_attribute(alcc.template beta<0>(sd))]<<" "
|
||||
<<index[alcc.vertex_attribute(alcc.template beta<2,0>(sd))]<<std::endl;
|
||||
total_size+=5;
|
||||
}
|
||||
else if(cell_type==VTK_WEDGE)
|
||||
{
|
||||
cell_stream<<" 6 "
|
||||
<<index[alcc.vertex_attribute(sd)]<<" "
|
||||
<<index[alcc.vertex_attribute(alcc.template beta<1>(sd))]<<" "
|
||||
<<index[alcc.vertex_attribute(alcc.template beta<0>(sd))]<<" ";
|
||||
// Move to the up face
|
||||
typename LCC::Dart_const_descriptor d2=alcc.template beta<2, 1, 1, 2>(sd);
|
||||
cell_stream<<index[alcc.vertex_attribute(alcc.template beta<1>(d2))]<<" "
|
||||
<<index[alcc.vertex_attribute(d2)]<<" "
|
||||
<<index[alcc.vertex_attribute(alcc.template beta<0>(d2))]<<std::endl;
|
||||
total_size+=6;
|
||||
}
|
||||
else if(cell_type==VTK_HEXAHEDRON)
|
||||
{
|
||||
cell_stream<<" 8 ";
|
||||
for(unsigned int i=0; i<4; ++i)
|
||||
{
|
||||
cell_stream<<index[alcc.vertex_attribute(sd)]<<" ";
|
||||
sd=alcc.template beta<1>(sd);
|
||||
}
|
||||
typename LCC::Dart_const_descriptor d2=alcc.template beta<2, 1, 1, 2, 1>(sd);
|
||||
// Darts associated with particles 4, 5, 6, 7
|
||||
for(unsigned int i = 0; i < 4; i++)
|
||||
{
|
||||
cell_stream<<index[alcc.vertex_attribute(d2)]<<" ";
|
||||
d2 = alcc.template beta<0>(d2);
|
||||
}
|
||||
cell_stream<<std::endl;
|
||||
total_size+=8;
|
||||
}
|
||||
// TODO: 15 PENTAGONAL_PRISM
|
||||
// 16 HEXAGONAL_PRISM
|
||||
// 24 QUADRATIC_TETRA
|
||||
// 25 QUADRATIC_HEXAHEDRON
|
||||
// 26 QUADRATIC_WEDGE
|
||||
// 27 QUADRATIC_PYRAMID
|
||||
else
|
||||
{
|
||||
// Generic polyhedron format write as face-vertex connectivity
|
||||
std::vector<std::vector<std::size_t>> faces;
|
||||
std::size_t cell_size=1; // Start with 1 for number of faces
|
||||
++total_size; // for the same reason
|
||||
for(auto itface=alcc.template one_dart_per_incident_cell<2, 3, 2>(itvol).begin(),
|
||||
itfaceend=alcc.template one_dart_per_incident_cell<2, 3, 2>(itvol).end();
|
||||
itface!=itfaceend; ++itface)
|
||||
{
|
||||
faces.push_back(std::vector<std::size_t>());
|
||||
typename LCC::Dart_const_descriptor curdh=itface;
|
||||
do
|
||||
{
|
||||
faces.back().push_back(index[alcc.vertex_attribute(curdh)]);
|
||||
curdh=alcc.template beta<1>(curdh);
|
||||
}
|
||||
while(curdh!=itface);
|
||||
cell_size+=faces.back().size()+1; // +1 for the number of vertices in the face
|
||||
}
|
||||
cell_stream<<cell_size<<" "<<faces.size();
|
||||
for(const auto& face : faces)
|
||||
{
|
||||
cell_stream<<" "<<face.size();
|
||||
for(auto v : face)
|
||||
{ cell_stream<<" "<<v; }
|
||||
total_size+=face.size()+1; // +1 for the number of vertices in the face
|
||||
}
|
||||
cell_stream<<std::endl;
|
||||
}
|
||||
}
|
||||
os<<"CELLS "<<nbcells<<" "<<total_size<<std::endl;
|
||||
os<<cell_stream.str()<<std::endl;
|
||||
|
||||
// Write cell types
|
||||
os<<"CELL_TYPES "<<nbcells<<std::endl;
|
||||
os<<type_stream.str()<<std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// ============================================================================
|
||||
// Public interface implementation
|
||||
// ============================================================================
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename LCC, typename VertexScalarType, typename VolumeScalarType>
|
||||
bool read_VTK(const char* filename, LCC& alcc,
|
||||
std::vector<VertexScalarType>* vertex_scalars,
|
||||
std::vector<VolumeScalarType>* volume_scalars)
|
||||
{
|
||||
CGAL_assertion(filename!=nullptr);
|
||||
std::ifstream file(filename);
|
||||
if(!file.is_open())
|
||||
{
|
||||
std::cerr<<"[ERROR] read_VTK: cannot open file "<<filename<<std::endl;
|
||||
return false;
|
||||
}
|
||||
return internal::read_lcc_from_vtk_ascii(file, alcc,
|
||||
vertex_scalars, volume_scalars);
|
||||
}
|
||||
|
||||
template <typename LCC>
|
||||
bool read_VTK(const char* filename, LCC& alcc)
|
||||
{ return read_VTK<LCC, float, float>(filename, alcc, nullptr, nullptr); }
|
||||
|
||||
template <typename LCC, typename VertexScalarType>
|
||||
bool read_VTK(const char* filename, LCC& alcc,
|
||||
std::vector<VertexScalarType>* vertex_scalars)
|
||||
{ return read_VTK<LCC, VertexScalarType, float>
|
||||
(filename, alcc, vertex_scalars, nullptr); }
|
||||
|
||||
template <typename LCC, typename VolumeScalarType>
|
||||
bool read_VTK(const char* filename, LCC& alcc,
|
||||
std::nullptr_t,
|
||||
std::vector<VolumeScalarType>* volume_scalars)
|
||||
{ return read_VTK<LCC, float, VolumeScalarType>
|
||||
(filename, alcc, nullptr, volume_scalars); }
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename LCC, typename PointFunctor, typename CellFunctor>
|
||||
inline bool write_VTK_with_fct(const char* filename, const LCC& alcc,
|
||||
PointFunctor pointfct, CellFunctor cellfct)
|
||||
{
|
||||
CGAL_assertion(filename!=nullptr);
|
||||
std::ofstream file(filename);
|
||||
if(!file.good())
|
||||
{
|
||||
std::cerr<<"[ERROR] write_VTK: cannot open file "<<filename<<std::endl;
|
||||
return false;
|
||||
}
|
||||
std::size_t nbpts=0, nbcells=0;
|
||||
bool res=internal::write_lcc_topo_to_vtk_ascii(file, alcc, nbpts, nbcells);
|
||||
if(res)
|
||||
{
|
||||
if(pointfct)
|
||||
{ internal::Write_point_data<PointFunctor>::
|
||||
run(file, alcc, nbpts, pointfct); }
|
||||
if(cellfct)
|
||||
{ internal::Write_cell_data<CellFunctor>::
|
||||
run(file, alcc, nbcells, cellfct); }
|
||||
}
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename LCC, typename VertexScalarType, typename VolumeScalarType>
|
||||
bool write_VTK(const char* filename, const LCC& alcc,
|
||||
const std::vector<VertexScalarType>* vertex_scalars,
|
||||
const std::vector<VolumeScalarType>* volume_scalars)
|
||||
{
|
||||
std::function<VertexScalarType(const LCC&,
|
||||
typename LCC::Dart_const_descriptor,
|
||||
std::size_t i)> vertexfct;
|
||||
std::function<VolumeScalarType(const LCC&,
|
||||
typename LCC::Dart_const_descriptor,
|
||||
std::size_t i)> cellfct;
|
||||
if(vertex_scalars!=nullptr)
|
||||
{
|
||||
vertexfct=[&vertex_scalars](const LCC&, typename LCC::Dart_const_descriptor,
|
||||
std::size_t i) -> VertexScalarType
|
||||
{ return (*vertex_scalars)[i]; };
|
||||
}
|
||||
|
||||
if(volume_scalars!=nullptr)
|
||||
{
|
||||
cellfct=[&volume_scalars](const LCC&, typename LCC::Dart_const_descriptor,
|
||||
std::size_t i) -> VolumeScalarType
|
||||
{ return (*volume_scalars)[i]; };
|
||||
}
|
||||
|
||||
return write_VTK_with_fct(filename, alcc, vertexfct, cellfct);
|
||||
}
|
||||
|
||||
template <typename LCC>
|
||||
bool write_VTK(const char* filename, const LCC& alcc)
|
||||
{
|
||||
return write_VTK<LCC, float, float>(filename, alcc, nullptr, nullptr);
|
||||
}
|
||||
|
||||
template <typename LCC, typename VertexScalarType>
|
||||
bool write_VTK(const char* filename, const LCC& alcc,
|
||||
const std::vector<VertexScalarType>* vertex_scalars)
|
||||
{
|
||||
return write_VTK<LCC, VertexScalarType, float>(filename, alcc, vertex_scalars,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
template <typename LCC, typename VolumeScalarType>
|
||||
bool write_VTK(const char* filename, const LCC& alcc,
|
||||
std::nullptr_t,
|
||||
const std::vector<VolumeScalarType>* volume_scalars)
|
||||
{
|
||||
return write_VTK<LCC, float, VolumeScalarType>(filename, alcc, nullptr,
|
||||
volume_scalars);
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // namespace IO
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_LCC_IO_VTK_H
|
||||
|
|
@ -213,7 +213,7 @@ namespace CGAL {
|
|||
return *this;
|
||||
}
|
||||
|
||||
/** Create a vertex attribute.
|
||||
/** Creates a vertex attribute.
|
||||
* @return a handle on the new attribute.
|
||||
*/
|
||||
template<typename ...Args>
|
||||
|
|
@ -221,7 +221,7 @@ namespace CGAL {
|
|||
{ return Base::template create_attribute<0>(args...); }
|
||||
|
||||
/**
|
||||
* Create a new dart associated with a handle through an attribute.
|
||||
* Creates a new dart associated with a handle through an attribute.
|
||||
* @param ahandle the point handle to associated with the dart.
|
||||
* @return a Dart_descriptor on the new dart.
|
||||
*/
|
||||
|
|
@ -232,7 +232,7 @@ namespace CGAL {
|
|||
return res;
|
||||
}
|
||||
|
||||
/** Create a new dart associated with a point.
|
||||
/** Creates a new dart associated with a point.
|
||||
* @param apoint the point to associated with the dart.
|
||||
* @return a Dart_descriptor on the new dart.
|
||||
*/
|
||||
|
|
@ -307,7 +307,7 @@ namespace CGAL {
|
|||
return point_of_vertex_attribute(this->template attribute<0>(adart));
|
||||
}
|
||||
|
||||
/** Test if the lcc is valid.
|
||||
/** Tests if the lcc is valid.
|
||||
* A Linear_cell_complex is valid if it is a valid Combinatorial_map with
|
||||
* an attribute associated to each dart.
|
||||
* @return true iff the map is valid.
|
||||
|
|
@ -550,7 +550,7 @@ namespace CGAL {
|
|||
return res;
|
||||
}
|
||||
|
||||
/** Create a segment given 2 points.
|
||||
/** Creates a segment given 2 points.
|
||||
* @param p0 the first point.
|
||||
* @param p1 the second point.
|
||||
* if closed==true, the edge has no 2-free dart.
|
||||
|
|
@ -564,7 +564,7 @@ namespace CGAL {
|
|||
closed);
|
||||
}
|
||||
|
||||
/** Create a triangle given 3 points.
|
||||
/** Creates a triangle given 3 points.
|
||||
* @param p0 the first point.
|
||||
* @param p1 the second point.
|
||||
* @param p2 the third point.
|
||||
|
|
@ -579,7 +579,7 @@ namespace CGAL {
|
|||
create_vertex_attribute(p2));
|
||||
}
|
||||
|
||||
/** Create a quadrangle given 4 points.
|
||||
/** Creates a quadrangle given 4 points.
|
||||
* @param p0 the first point.
|
||||
* @param p1 the second point.
|
||||
* @param p2 the third point.
|
||||
|
|
@ -598,7 +598,7 @@ namespace CGAL {
|
|||
}
|
||||
|
||||
|
||||
/** Create a tetrahedron given 4 Vertex_attribute_descriptor.
|
||||
/** Creates a tetrahedron given 4 Vertex_attribute_descriptor.
|
||||
* @param h0 the first vertex handle.
|
||||
* @param h1 the second vertex handle.
|
||||
* @param h2 the third vertex handle.
|
||||
|
|
@ -619,7 +619,7 @@ namespace CGAL {
|
|||
return this->make_combinatorial_tetrahedron(d1, d2, d3, d4);
|
||||
}
|
||||
|
||||
/** Create a tetrahedron given 4 points.
|
||||
/** Creates a tetrahedron given 4 points.
|
||||
* @param p0 the first point.
|
||||
* @param p1 the second point.
|
||||
* @param p2 the third point.
|
||||
|
|
@ -638,7 +638,7 @@ namespace CGAL {
|
|||
create_vertex_attribute(p3));
|
||||
}
|
||||
|
||||
/** Create an hexahedron given 8 Vertex_attribute_descriptor.
|
||||
/** Creates an hexahedron given 8 Vertex_attribute_descriptor.
|
||||
* (8 vertices, 12 edges and 6 facets)
|
||||
* \verbatim
|
||||
* 4----7
|
||||
|
|
@ -678,7 +678,7 @@ namespace CGAL {
|
|||
return this->make_combinatorial_hexahedron(d1, d2, d3, d4, d5, d6);
|
||||
}
|
||||
|
||||
/** Create an hexahedron given 8 points.
|
||||
/** Creates an hexahedron given 8 points.
|
||||
* \verbatim
|
||||
* 4----7
|
||||
* /| /|
|
||||
|
|
@ -717,6 +717,133 @@ namespace CGAL {
|
|||
create_vertex_attribute(p7));
|
||||
}
|
||||
|
||||
/** Creates a prism given 6 Vertex_attribute_descriptor.
|
||||
* (6 vertices, 9 edges and 5 facets)
|
||||
* \verbatim
|
||||
* 3---4
|
||||
* |\ /|
|
||||
* 0-5-1
|
||||
* \|/
|
||||
* 2
|
||||
* \endverbatim
|
||||
* @param h0 the first vertex handle.
|
||||
* @param h1 the second vertex handle.
|
||||
* @param h2 the third vertex handle.
|
||||
* @param h3 the fourth vertex handle.
|
||||
* @param h4 the fifth vertex handle.
|
||||
* @param h5 the sixth vertex handle.
|
||||
* @return the dart of the new prism incident to h0 and to
|
||||
* the facet (h0,h1,h2).
|
||||
*/
|
||||
Dart_descriptor make_prism(Vertex_attribute_descriptor h0,
|
||||
Vertex_attribute_descriptor h1,
|
||||
Vertex_attribute_descriptor h2,
|
||||
Vertex_attribute_descriptor h3,
|
||||
Vertex_attribute_descriptor h4,
|
||||
Vertex_attribute_descriptor h5)
|
||||
{
|
||||
Dart_descriptor d1=make_triangle(h0, h1, h2);
|
||||
Dart_descriptor d2=make_quadrangle(h1, h0, h3, h4);
|
||||
Dart_descriptor d3=make_quadrangle(h2, h1, h4, h5);
|
||||
Dart_descriptor d4=make_quadrangle(h0, h2, h5, h3);
|
||||
Dart_descriptor d5=make_triangle(h4, h3, h5);
|
||||
|
||||
return make_combinatorial_prism(d1, d2, d3, d4, d5);
|
||||
}
|
||||
|
||||
/** Creates a prism given 6 points.
|
||||
* \verbatim
|
||||
* 3---4
|
||||
* |\ /|
|
||||
* 0-5-1
|
||||
* \|/
|
||||
* 2
|
||||
* \endverbatim
|
||||
* @param p0 the first point.
|
||||
* @param p1 the second point.
|
||||
* @param p2 the third point.
|
||||
* @param p3 the fourth point.
|
||||
* @param p4 the fifth point.
|
||||
* @param p5 the sixth point.
|
||||
* @return the dart of the new prism incident to p0 and to
|
||||
* the facet (p0,p1,p2).
|
||||
*/
|
||||
Dart_descriptor make_prism(const Point& p0,
|
||||
const Point& p1,
|
||||
const Point& p2,
|
||||
const Point& p3,
|
||||
const Point& p4,
|
||||
const Point& p5)
|
||||
{
|
||||
return make_prism(create_vertex_attribute(p0),
|
||||
create_vertex_attribute(p1),
|
||||
create_vertex_attribute(p2),
|
||||
create_vertex_attribute(p3),
|
||||
create_vertex_attribute(p4),
|
||||
create_vertex_attribute(p5));
|
||||
}
|
||||
|
||||
/** Creates a pyramid given 5 Vertex_attribute_descriptor.
|
||||
* (5 vertices, 8 edges and 5 facets)
|
||||
* \verbatim
|
||||
* 4
|
||||
* /|\
|
||||
* 0-|-1
|
||||
* | | |
|
||||
* 3---2
|
||||
* \endverbatim
|
||||
* @param h0 the first vertex handle.
|
||||
* @param h1 the second vertex handle.
|
||||
* @param h2 the third vertex handle.
|
||||
* @param h3 the fourth vertex handle.
|
||||
* @param h4 the fifth vertex handle.
|
||||
* @return the dart of the new pyramid incident to h0 and to
|
||||
* the facet (h0,h1,h2,h3).
|
||||
*/
|
||||
Dart_descriptor make_pyramid(Vertex_attribute_descriptor h0,
|
||||
Vertex_attribute_descriptor h1,
|
||||
Vertex_attribute_descriptor h2,
|
||||
Vertex_attribute_descriptor h3,
|
||||
Vertex_attribute_descriptor h4)
|
||||
{
|
||||
Dart_descriptor d1=make_quadrangle(h0, h1, h2, h3);
|
||||
Dart_descriptor d2=make_triangle(h1, h0, h4);
|
||||
Dart_descriptor d3=make_triangle(h0, h3, h4);
|
||||
Dart_descriptor d4=make_triangle(h3, h2, h4);
|
||||
Dart_descriptor d5=make_triangle(h2, h1, h4);
|
||||
|
||||
return make_combinatorial_pyramid(d1, d2, d3, d4, d5);
|
||||
}
|
||||
|
||||
/** Creates a pyramid given 5 points.
|
||||
* \verbatim
|
||||
* 4
|
||||
* /|\
|
||||
* 0-|-1
|
||||
* | | |
|
||||
* 3---2
|
||||
* \endverbatim
|
||||
* @param p0 the first point.
|
||||
* @param p1 the second point.
|
||||
* @param p2 the third point.
|
||||
* @param p3 the fourth point.
|
||||
* @param p4 the fifth point.
|
||||
* @return the dart of the new pyramid incident to p0 and to
|
||||
* the facet (p0,p1,p2,p3).
|
||||
*/
|
||||
Dart_descriptor make_pyramid(const Point& p0,
|
||||
const Point& p1,
|
||||
const Point& p2,
|
||||
const Point& p3,
|
||||
const Point& p4)
|
||||
{
|
||||
return make_pyramid(create_vertex_attribute(p0),
|
||||
create_vertex_attribute(p1),
|
||||
create_vertex_attribute(p2),
|
||||
create_vertex_attribute(p3),
|
||||
create_vertex_attribute(p4));
|
||||
}
|
||||
|
||||
/** Compute the barycenter of a given cell.
|
||||
* @param adart a dart incident to the cell.
|
||||
* @param adim the dimension of the cell.
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ public:
|
|||
prev_dart =lcc.null_descriptor;
|
||||
}
|
||||
|
||||
void add_vertex_to_facet(size_type i)
|
||||
void add_vertex_to_facet(size_type i, std::vector<DH>* tabdarts = nullptr)
|
||||
{
|
||||
CGAL_assertion(i<vertex_map.size());
|
||||
// std::cout<<i<<" "<<std::flush;
|
||||
|
|
@ -289,6 +289,7 @@ public:
|
|||
{ first_dart=cur_dart; min_vertex=max_vertex=i; min_dart=cur_dart; }
|
||||
|
||||
prev_dart=cur_dart;
|
||||
if(tabdarts != nullptr) { tabdarts->push_back(cur_dart); }
|
||||
}
|
||||
|
||||
// End of the facet. Return the first dart of this facet.
|
||||
|
|
@ -325,11 +326,12 @@ public:
|
|||
return first_dart;
|
||||
}
|
||||
|
||||
DH add_facet(std::initializer_list<size_type> l)
|
||||
DH add_facet(std::initializer_list<size_type> l, std::vector<DH>* tabdarts = nullptr)
|
||||
{
|
||||
if(tabdarts != nullptr) { tabdarts->reserve(tabdarts->size() + l.size()); }
|
||||
begin_facet();
|
||||
for (size_type i:l)
|
||||
{ add_vertex_to_facet(i); }
|
||||
{ add_vertex_to_facet(i, tabdarts); }
|
||||
return end_facet();
|
||||
}
|
||||
|
||||
|
|
@ -404,5 +406,197 @@ private:
|
|||
|
||||
} //namespace CGAL
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/* Create an hexahedron, given the indices of its vertices (in the following
|
||||
* order), the vertex must already have been added in the incremental builder.
|
||||
* 3
|
||||
* /|\
|
||||
* 0-|-2
|
||||
* \|/
|
||||
* 1
|
||||
*/
|
||||
template<typename IncrementalBuilder>
|
||||
typename IncrementalBuilder::LCC::Dart_descriptor
|
||||
make_tetrahedron_with_builder(IncrementalBuilder& ib,
|
||||
std::size_t i0,
|
||||
std::size_t i1,
|
||||
std::size_t i2,
|
||||
std::size_t i3,
|
||||
std::vector<typename IncrementalBuilder::LCC::Dart_descriptor>*
|
||||
tabdarts=nullptr)
|
||||
{
|
||||
ib.begin_surface();
|
||||
ib.add_facet({i0,i1,i2}, tabdarts);
|
||||
ib.add_facet({i1,i0,i3}, tabdarts);
|
||||
ib.add_facet({i2,i1,i3}, tabdarts);
|
||||
ib.add_facet({i0,i2,i3}, tabdarts);
|
||||
return ib.end_surface();
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/* 4
|
||||
* /|\
|
||||
* 0-|-3
|
||||
* | | |
|
||||
* 1---2
|
||||
*/
|
||||
template<typename IncrementalBuilder>
|
||||
typename IncrementalBuilder::LCC::Dart_descriptor
|
||||
make_pyramid_with_builder(IncrementalBuilder& ib,
|
||||
std::size_t i0,
|
||||
std::size_t i1,
|
||||
std::size_t i2,
|
||||
std::size_t i3,
|
||||
std::size_t i4,
|
||||
std::vector<typename IncrementalBuilder::LCC::Dart_descriptor>*
|
||||
tabdarts=nullptr)
|
||||
{
|
||||
ib.begin_surface();
|
||||
ib.add_facet({i0,i1,i2,i3}, tabdarts);
|
||||
ib.add_facet({i1,i0,i4}, tabdarts);
|
||||
ib.add_facet({i2,i1,i4}, tabdarts);
|
||||
ib.add_facet({i3,i2,i4}, tabdarts);
|
||||
ib.add_facet({i0,i3,i4}, tabdarts);
|
||||
return ib.end_surface();
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/* 3
|
||||
* /|\
|
||||
* 4---5
|
||||
* | | |
|
||||
* | 0 |
|
||||
* |/ \|
|
||||
* 1---2
|
||||
*/
|
||||
template<typename IncrementalBuilder>
|
||||
typename IncrementalBuilder::LCC::Dart_descriptor
|
||||
make_prism_with_builder(IncrementalBuilder& ib,
|
||||
std::size_t i0,
|
||||
std::size_t i1,
|
||||
std::size_t i2,
|
||||
std::size_t i3,
|
||||
std::size_t i4,
|
||||
std::size_t i5,
|
||||
std::vector<typename IncrementalBuilder::LCC::Dart_descriptor>*
|
||||
tabdarts=nullptr)
|
||||
{
|
||||
ib.begin_surface();
|
||||
ib.add_facet({i0,i1,i2}, tabdarts);
|
||||
ib.add_facet({i1,i0,i3,i4}, tabdarts);
|
||||
ib.add_facet({i2,i1,i4,i5}, tabdarts);
|
||||
ib.add_facet({i0,i2,i5,i3}, tabdarts);
|
||||
ib.add_facet({i5,i4,i3}, tabdarts);
|
||||
return ib.end_surface();
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/* 7----6
|
||||
* /| /|
|
||||
* 4----5 |
|
||||
* | 3--|-2
|
||||
* |/ |/
|
||||
* 0----1
|
||||
*/
|
||||
template<typename IncrementalBuilder>
|
||||
typename IncrementalBuilder::LCC::Dart_descriptor
|
||||
make_hexahedron_with_builder(IncrementalBuilder& ib,
|
||||
std::size_t i0,
|
||||
std::size_t i1,
|
||||
std::size_t i2,
|
||||
std::size_t i3,
|
||||
std::size_t i4,
|
||||
std::size_t i5,
|
||||
std::size_t i6,
|
||||
std::size_t i7,
|
||||
std::vector<typename IncrementalBuilder::LCC::Dart_descriptor>*
|
||||
tabdarts=nullptr)
|
||||
{
|
||||
ib.begin_surface();
|
||||
ib.add_facet({i0,i1,i2,i3}, tabdarts);
|
||||
ib.add_facet({i1,i0,i4,i5}, tabdarts);
|
||||
ib.add_facet({i2,i1,i5,i6}, tabdarts);
|
||||
ib.add_facet({i3,i2,i6,i7}, tabdarts);
|
||||
ib.add_facet({i0,i3,i7,i4}, tabdarts);
|
||||
ib.add_facet({i7,i6,i5,i4}, tabdarts);
|
||||
return ib.end_surface();
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template<typename IncrementalBuilder>
|
||||
typename IncrementalBuilder::LCC::Dart_descriptor
|
||||
make_pentagonal_prism_with_builder(IncrementalBuilder& ib,
|
||||
std::size_t i0,
|
||||
std::size_t i1,
|
||||
std::size_t i2,
|
||||
std::size_t i3,
|
||||
std::size_t i4,
|
||||
std::size_t i5,
|
||||
std::size_t i6,
|
||||
std::size_t i7,
|
||||
std::size_t i8,
|
||||
std::size_t i9,
|
||||
std::vector<typename IncrementalBuilder::LCC::Dart_descriptor>*
|
||||
tabdarts=nullptr)
|
||||
{
|
||||
ib.begin_surface();
|
||||
ib.add_facet({i0,i1,i2,i3,i4}, tabdarts);
|
||||
ib.add_facet({i1,i0,i5,i6}, tabdarts);
|
||||
ib.add_facet({i2,i1,i6,i7}, tabdarts);
|
||||
ib.add_facet({i3,i2,i7,i8}, tabdarts);
|
||||
ib.add_facet({i4,i3,i8,i9}, tabdarts);
|
||||
ib.add_facet({i0,i4,i9,i5}, tabdarts);
|
||||
ib.add_facet({i9,i8,i7,i6,i5}, tabdarts);
|
||||
return ib.end_surface();
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template<typename IncrementalBuilder>
|
||||
typename IncrementalBuilder::LCC::Dart_descriptor
|
||||
make_hexagonal_prism_with_builder(IncrementalBuilder& ib,
|
||||
std::size_t i0,
|
||||
std::size_t i1,
|
||||
std::size_t i2,
|
||||
std::size_t i3,
|
||||
std::size_t i4,
|
||||
std::size_t i5,
|
||||
std::size_t i6,
|
||||
std::size_t i7,
|
||||
std::size_t i8,
|
||||
std::size_t i9,
|
||||
std::size_t i10,
|
||||
std::size_t i11,
|
||||
std::vector<typename IncrementalBuilder::LCC::Dart_descriptor>*
|
||||
tabdarts=nullptr)
|
||||
{
|
||||
ib.begin_surface();
|
||||
ib.add_facet({i0,i1,i2,i3,i4,i5}, tabdarts);
|
||||
ib.add_facet({i1,i0,i6,i7}, tabdarts);
|
||||
ib.add_facet({i2,i1,i7,i8}, tabdarts);
|
||||
ib.add_facet({i3,i2,i8,i9}, tabdarts);
|
||||
ib.add_facet({i4,i3,i9,i10}, tabdarts);
|
||||
ib.add_facet({i5,i4,i10,i11}, tabdarts);
|
||||
ib.add_facet({i0,i5,i11,i6}, tabdarts);
|
||||
ib.add_facet({i11,i10,i9,i8,i7,i6}, tabdarts);
|
||||
return ib.end_surface();
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template<typename IncrementalBuilder>
|
||||
typename IncrementalBuilder::LCC::Dart_descriptor
|
||||
make_generic_cell_with_builder(IncrementalBuilder& ib,
|
||||
const std::vector<std::size_t>& faces,
|
||||
std::vector<typename IncrementalBuilder::LCC::Dart_descriptor>*
|
||||
tabdarts=nullptr)
|
||||
{
|
||||
ib.begin_surface();
|
||||
std::size_t i=1, end; // Start to 1 because faces[0] is the number of faces
|
||||
for(; i<faces.size(); )
|
||||
{
|
||||
end=i+1+faces[i]; // faces[i] is the number of vertices of the face; +i is the index of the end
|
||||
++i; // I prefer to increment i after its use!
|
||||
ib.begin_facet();
|
||||
for(; i<end; ++i)
|
||||
{ ib.add_vertex_to_facet(faces[i], tabdarts); }
|
||||
ib.end_facet();
|
||||
}
|
||||
return ib.end_surface();
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // CGAL_LINEAR_CELL_COMPLEX_INCREMENTAL_BUILDER_3_H //
|
||||
// EOF //
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ create_single_source_cgal_program(Linear_cell_complex_3_test.cpp ${hfiles})
|
|||
create_single_source_cgal_program(Linear_cell_complex_4_test.cpp ${hfiles})
|
||||
create_single_source_cgal_program(Linear_cell_complex_copy_test.cpp ${hfiles})
|
||||
create_single_source_cgal_program(LCC_3_incremental_builder_test.cpp ${hfiles})
|
||||
create_single_source_cgal_program(Linear_cell_complex_vtk_io_test.cpp ${hfiles})
|
||||
|
||||
# Same targets, defining USE_COMPACT_CONTAINER_WITH_INDEX to test index version
|
||||
add_executable(Linear_cell_complex_2_test_index Linear_cell_complex_2_test.cpp ${hfiles})
|
||||
|
|
|
|||
|
|
@ -5,104 +5,6 @@
|
|||
|
||||
#include "Linear_cell_complex_3_test.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/* 3
|
||||
* /|\
|
||||
* 0-|-2
|
||||
* \|/
|
||||
* 1
|
||||
*/
|
||||
template<typename IncrementalBuilder>
|
||||
void make_tetrahedron_with_builder(IncrementalBuilder& ib,
|
||||
std::size_t i0,
|
||||
std::size_t i1,
|
||||
std::size_t i2,
|
||||
std::size_t i3)
|
||||
{
|
||||
ib.begin_surface();
|
||||
ib.add_facet({i0,i1,i2});
|
||||
ib.add_facet({i1,i0,i3});
|
||||
ib.add_facet({i2,i1,i3});
|
||||
ib.add_facet({i0,i2,i3});
|
||||
ib.end_surface();
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/* 4
|
||||
* /|\
|
||||
* 0-|-3
|
||||
* | | |
|
||||
* 1---2
|
||||
*/
|
||||
template<typename IncrementalBuilder>
|
||||
void make_pyramid_with_builder(IncrementalBuilder& ib,
|
||||
std::size_t i0,
|
||||
std::size_t i1,
|
||||
std::size_t i2,
|
||||
std::size_t i3,
|
||||
std::size_t i4)
|
||||
{
|
||||
ib.begin_surface();
|
||||
ib.add_facet({i0,i1,i2,i3});
|
||||
ib.add_facet({i1,i0,i4});
|
||||
ib.add_facet({i2,i1,i4});
|
||||
ib.add_facet({i3,i2,i4});
|
||||
ib.add_facet({i0,i3,i4});
|
||||
ib.end_surface();
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/* 3
|
||||
* /|\
|
||||
* 4---5
|
||||
* | | |
|
||||
* | 0 |
|
||||
* |/ \|
|
||||
* 1---2
|
||||
*/
|
||||
template<typename IncrementalBuilder>
|
||||
void make_prism_with_builder(IncrementalBuilder& ib,
|
||||
std::size_t i0,
|
||||
std::size_t i1,
|
||||
std::size_t i2,
|
||||
std::size_t i3,
|
||||
std::size_t i4,
|
||||
std::size_t i5)
|
||||
{
|
||||
ib.begin_surface();
|
||||
ib.add_facet({i0,i1,i2});
|
||||
ib.add_facet({i1,i0,i3,i4});
|
||||
ib.add_facet({i2,i1,i4,i5});
|
||||
ib.add_facet({i0,i2,i5,i3});
|
||||
ib.add_facet({i5,i4,i3});
|
||||
ib.end_surface();
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/* 7----6
|
||||
* /| /|
|
||||
* 4----5 |
|
||||
* | 3--|-2
|
||||
* |/ |/
|
||||
* 0----1
|
||||
*/
|
||||
template<typename IncrementalBuilder>
|
||||
void make_hexahedron_with_builder(IncrementalBuilder& ib,
|
||||
std::size_t i0,
|
||||
std::size_t i1,
|
||||
std::size_t i2,
|
||||
std::size_t i3,
|
||||
std::size_t i4,
|
||||
std::size_t i5,
|
||||
std::size_t i6,
|
||||
std::size_t i7)
|
||||
{
|
||||
ib.begin_surface();
|
||||
ib.add_facet({i0,i1,i2,i3});
|
||||
ib.add_facet({i1,i0,i4,i5});
|
||||
ib.add_facet({i2,i1,i5,i6});
|
||||
ib.add_facet({i3,i2,i6,i7});
|
||||
ib.add_facet({i0,i3,i7,i4});
|
||||
ib.add_facet({i7,i6,i5,i4});
|
||||
ib.end_surface();
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template<typename LCC>
|
||||
bool test_ib(const char* filename)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,202 @@
|
|||
#include <CGAL/Linear_cell_complex_for_combinatorial_map.h>
|
||||
#include <CGAL/Linear_cell_complex/IO/VTK.h>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
|
||||
typedef CGAL::Linear_cell_complex_for_combinatorial_map<3, 3> LCC;
|
||||
|
||||
bool test_file(const char* filename)
|
||||
{
|
||||
LCC lcc1, lcc2;
|
||||
std::vector<float> vertex_scalars1, vertex_scalars2;
|
||||
std::vector<std::size_t> volume_scalars1, volume_scalars2;
|
||||
|
||||
bool res=CGAL::IO::read_VTK(filename, lcc1);
|
||||
if(!res)
|
||||
{
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error read_VTK in test_file"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::size_t nb_vertices=lcc1.number_of_vertex_attributes();
|
||||
vertex_scalars1.resize(nb_vertices);
|
||||
for(std::size_t i=0;i<nb_vertices;++i)
|
||||
{ vertex_scalars1[i]=static_cast<float>(i); }
|
||||
|
||||
std::size_t nb_volumes=0;
|
||||
for(auto itvol=lcc1.one_dart_per_cell<3>().begin(),
|
||||
itvolend=lcc1.one_dart_per_cell<3>().end(); itvol!=itvolend; ++itvol)
|
||||
{ ++nb_volumes; }
|
||||
|
||||
volume_scalars1.reserve(nb_volumes);
|
||||
for(auto itvol=lcc1.one_dart_per_cell<3>().begin(),
|
||||
itvolend=lcc1.one_dart_per_cell<3>().end(); itvol!=itvolend; ++itvol)
|
||||
{
|
||||
std::size_t nbv=lcc1.template one_dart_per_incident_cell<0,3>(itvol).size();
|
||||
volume_scalars1.push_back(nbv);
|
||||
}
|
||||
|
||||
res=CGAL::IO::write_VTK("output.vtk", lcc1,
|
||||
&vertex_scalars1, &volume_scalars1);
|
||||
if(!res)
|
||||
{
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error write_VTK in test_file"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
res=CGAL::IO::read_VTK("output.vtk", lcc2,
|
||||
&vertex_scalars2, &volume_scalars2);
|
||||
if(!res)
|
||||
{
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error read_VTK 2 in test_file"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!lcc1.is_isomorphic_to(lcc2, false, true, true))
|
||||
{
|
||||
std::cout<<"LCC1: ";
|
||||
lcc1.display_characteristics(std::cout)<<std::endl;
|
||||
std::cout<<"LCC2: ";
|
||||
lcc2.display_characteristics(std::cout)<<std::endl;
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error lcc1 and lcc2 are not isomorphic in test_file"<<std::endl;
|
||||
res=false;
|
||||
}
|
||||
if(vertex_scalars1!=vertex_scalars2)
|
||||
{
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error vertex_scalars1 and vertex_scalars2 are different in test_file"<<std::endl;
|
||||
res=false;
|
||||
}
|
||||
if(volume_scalars1!=volume_scalars2)
|
||||
{
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error volume_scalars1 and volume_scalars2 are different in test_file"<<std::endl;
|
||||
res=false;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool test_different_scalars()
|
||||
{
|
||||
bool res=true;
|
||||
LCC lcc;
|
||||
std::vector<float> vertex_scalars;
|
||||
std::vector<std::size_t> volume_scalars;
|
||||
|
||||
/// Read the last file generated by test_file("data/beam-with-mixed-cells.vtk")
|
||||
/// i.e. beam-with-mixed-cells.vtk with point and cells scalars.
|
||||
if(!CGAL::IO::read_VTK("output.vtk", lcc,
|
||||
&vertex_scalars, &volume_scalars) ||
|
||||
vertex_scalars.size()!=719 || volume_scalars.size()!=615)
|
||||
{
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error read_VTK in test_different_scalars"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Test write with and without scalars
|
||||
if(!CGAL::IO::write_VTK("output_vol.vtk", lcc, nullptr, &volume_scalars))
|
||||
{
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error write_VTK 1 in test_different_scalars"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!CGAL::IO::write_VTK("output_vertex.vtk", lcc, &vertex_scalars))
|
||||
{
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error write_VTK 2 in test_different_scalars"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!CGAL::IO::write_VTK("output_none.vtk", lcc))
|
||||
{
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error write_VTK 3 in test_different_scalars"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// test read with only some scalars
|
||||
if(!CGAL::IO::read_VTK("output.vtk", lcc, &vertex_scalars) ||
|
||||
vertex_scalars.size()!=719)
|
||||
{
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error read_VTK 2 in test_different_scalars"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!CGAL::IO::read_VTK("output.vtk", lcc,
|
||||
nullptr, &volume_scalars) ||
|
||||
volume_scalars.size()!=615)
|
||||
{
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error read_VTK 3 in test_different_scalars"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!CGAL::IO::read_VTK("output.vtk", lcc))
|
||||
{
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error read_VTK 4 in test_different_scalars"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// test read all scalars when they are not in the file
|
||||
if(!CGAL::IO::read_VTK("output_vertex.vtk", lcc, &vertex_scalars, &volume_scalars) ||
|
||||
vertex_scalars.size()!=719 || volume_scalars.size()!=0)
|
||||
{
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error read_VTK 5 in test_different_scalars"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!CGAL::IO::read_VTK("output_vol.vtk", lcc, &vertex_scalars, &volume_scalars) ||
|
||||
vertex_scalars.size()!=0 || volume_scalars.size()!=615)
|
||||
{
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error read_VTK 6 in test_different_scalars"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!CGAL::IO::read_VTK("output_none.vtk", lcc, &vertex_scalars, &volume_scalars) ||
|
||||
vertex_scalars.size()!=0 || volume_scalars.size()!=0)
|
||||
{
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error read_VTK 7 in test_different_scalars"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
bool res=true;
|
||||
if(!test_file("data/2tetra.vtk"))
|
||||
{
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error for file data/2tetra.vtk"<<std::endl;
|
||||
res=false;
|
||||
}
|
||||
if(!test_file("data/2hexa.vtk"))
|
||||
{
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error for file data/2hexa.vtk"<<std::endl;
|
||||
res=false;
|
||||
}
|
||||
if(!test_file("data/2prism.vtk"))
|
||||
{
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error for file data/2prism.vtk"<<std::endl;
|
||||
res=false;
|
||||
}
|
||||
if(!test_file("data/2pyramid.vtk"))
|
||||
{
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error for file data/2pyramid.vtk"<<std::endl;
|
||||
res=false;
|
||||
}
|
||||
if(!test_file("data/2generic_cell.vtk"))
|
||||
{
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error for file data/2generic_cell.vtk"<<std::endl;
|
||||
res=false;
|
||||
}
|
||||
if(!test_file("data/beam-with-mixed-cells.vtk"))
|
||||
{
|
||||
std::cerr<<"[ERROR] LCC_vtk_io_test error for file data/beam-with-mixed-cells.vtk"<<std::endl;
|
||||
res=false;
|
||||
}
|
||||
|
||||
if(!test_different_scalars())
|
||||
{ res=false; }
|
||||
|
||||
if(!res) { return EXIT_FAILURE; }
|
||||
|
||||
std::cout<<"[OK] all tests in Linear_cell_complex_vtk_io_test.cpp"<<std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# vtk DataFile Version 2.0
|
||||
3D Mesh
|
||||
ASCII
|
||||
DATASET UNSTRUCTURED_GRID
|
||||
POINTS 21 double
|
||||
0.797233 -3.0657 2.80231
|
||||
1.04552 -2.81344 1.77789
|
||||
-0.00261142 -2.87459 1.50879
|
||||
-0.2509 -3.12685 2.53322
|
||||
0.682428 -3.76202 2.31634
|
||||
0.806573 -3.63589 1.80413
|
||||
0.282506 -3.66646 1.66958
|
||||
0.158362 -3.79259 2.1818
|
||||
0.567624 -4.45834 1.83037
|
||||
1.48429 0.147175 1.04918
|
||||
-0.357656 0.0397078 0.576288
|
||||
-0.146018 -1.80958 0.172206
|
||||
1.69593 -1.70211 0.645098
|
||||
-0.66619 -0.27376 1.84928
|
||||
-0.974724 -0.587227 3.12228
|
||||
-0.454552 -2.12305 1.4452
|
||||
-0.763086 -2.43652 2.7182
|
||||
1.38739 -2.01558 1.91809
|
||||
1.07886 -2.32905 3.19109
|
||||
1.17576 -0.166292 2.32218
|
||||
0.867223 -0.47976 3.59517
|
||||
|
||||
CELLS 2 115
|
||||
62 13 3 8 4 5 3 4 8 7 4 5 4 0 1 3 8 5 6 3 7 8 6 4 4 7 3 0 4 1 0 18 17 4 5 1 2 6 4 7 6 2 3 4 0 3 16 18 4 17 18 16 15 4 1 17 15 2 4 3 2 15 16
|
||||
51 10 4 9 19 13 10 4 19 9 12 17 4 13 19 20 14 4 10 13 15 11 4 9 10 11 12 4 17 12 11 15 4 19 17 18 20 4 14 20 18 16 4 13 14 16 15 4 17 15 16 18
|
||||
|
||||
CELL_TYPES 2
|
||||
42
|
||||
42
|
||||
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
# vtk DataFile Version 2.0
|
||||
3D Mesh
|
||||
ASCII
|
||||
DATASET UNSTRUCTURED_GRID
|
||||
POINTS 12 double
|
||||
-1 -1 -1
|
||||
-1 1 -1
|
||||
-1 -1 1
|
||||
-1 1 1
|
||||
1 -1 -1
|
||||
1 1 -1
|
||||
1 -1 1
|
||||
1 1 1
|
||||
3 -1 1
|
||||
3 -1 -1
|
||||
3 1 1
|
||||
3 1 -1
|
||||
|
||||
CELLS 2 18
|
||||
8 0 1 3 2 4 5 7 6
|
||||
8 5 7 6 4 11 10 8 9
|
||||
|
||||
CELL_TYPES 2
|
||||
12
|
||||
12
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# vtk DataFile Version 2.0
|
||||
3D Mesh
|
||||
ASCII
|
||||
DATASET UNSTRUCTURED_GRID
|
||||
POINTS 14 double
|
||||
-1.78261 2.8477 -1.15226
|
||||
-1.6885 2.94623 2.26566
|
||||
0.921521 1.54537 2.23417
|
||||
1.01511 -1.41435 2.31691
|
||||
-1.59491 -0.0134989 2.3484
|
||||
0.920989 -1.51287 -1.10101
|
||||
-1.68903 -0.112022 -1.06953
|
||||
0.827405 1.44685 -1.18375
|
||||
0.921521 1.54537 2.23417
|
||||
1.01511 -1.41435 2.31691
|
||||
-1.59491 -0.0134989 2.3484
|
||||
0.920989 -1.51287 -1.10101
|
||||
-1.68903 -0.112022 -1.06953
|
||||
0.827405 1.44685 -1.18375
|
||||
|
||||
CELLS 3 21
|
||||
6 6 0 7 4 1 2
|
||||
6 2 4 3 7 6 5
|
||||
6 9 8 10 11 13 12
|
||||
|
||||
CELL_TYPES 3
|
||||
13
|
||||
13
|
||||
13
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# vtk DataFile Version 2.0
|
||||
3D Mesh
|
||||
ASCII
|
||||
DATASET UNSTRUCTURED_GRID
|
||||
POINTS 7 double
|
||||
-0.149372 -0.608056 -1.19224
|
||||
-2.05784 -0.0940108 -3.6419
|
||||
-0.607052 -1.32749 -4.22213
|
||||
0.70406 0.167065 -4.12109
|
||||
-0.746726 1.40055 -3.54086
|
||||
-2.13885 -2.38807 -3.52093
|
||||
-1.35014 -2.31961 -1.69441
|
||||
|
||||
CELLS 2 12
|
||||
5 2 1 4 3 0
|
||||
5 2 0 6 5 1
|
||||
|
||||
CELL_TYPES 2
|
||||
14
|
||||
14
|
||||
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
# vtk DataFile Version 2.0
|
||||
CGAL Linear_cell_complex
|
||||
ASCII
|
||||
DATASET UNSTRUCTURED_GRID
|
||||
|
||||
POINTS 5 double
|
||||
-3.38189 0.624914 -0.442232
|
||||
-3.04657 -1.38801 -0.227267
|
||||
-1.24112 -0.450255 -0.494661
|
||||
-1.42311 -1.94845 0.895599
|
||||
-2.49044 0.337128 1.70461
|
||||
|
||||
CELLS 2 10
|
||||
4 1 0 4 2
|
||||
4 1 2 4 3
|
||||
|
||||
CELL_TYPES 2
|
||||
10
|
||||
10
|
||||
|
||||
POINT_DATA 5
|
||||
SCALARS point_scalars float 1
|
||||
LOOKUP_TABLE default
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
CELL_DATA 2
|
||||
SCALARS cell_scalars unsigned_long 1
|
||||
LOOKUP_TABLE default
|
||||
4
|
||||
4
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
|
@ -22,6 +22,7 @@ each specific format.
|
|||
- \ref IOStreamMedit
|
||||
- \ref IOStreamTetgen
|
||||
- \ref IOStreamWKT
|
||||
- \ref IOStreamVTKLCC
|
||||
|
||||
\section IOStreamOFF Object File Format (OFF)
|
||||
|
||||
|
|
@ -504,6 +505,30 @@ The following \cgal data structures can be exported into the `.VTU` file format:
|
|||
- `CGAL::Mesh_complex_3_in_triangulation_3`, using \link CGAL::IO::output_to_vtu() `CGAL::IO::output_to_vtu()` \endlink
|
||||
- `CGAL::Constrained_Delaunay_triangulation_2`, using the function \link CGAL::IO::write_VTU `CGAL::IO::write_VTU()` \endlink
|
||||
|
||||
\section IOStreamVTKLCC VTK Legacy File Format for Linear Cell Complex
|
||||
|
||||
The VTK legacy format, using file extension `.vtk`, is an \ascii format used to store 3D volumetric meshes.
|
||||
This specific implementation supports Linear Cell Complex structures with various 3D cell types including
|
||||
tetrahedra, hexahedra, prisms, pyramids, and generic polyhedra. Optional scalar data can be associated
|
||||
with both vertices and volumes.
|
||||
|
||||
<table class="iotable">
|
||||
<tr>
|
||||
<th colspan="4">VTK Legacy File Format for Linear Cell Complex</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="1" width="75">Input</td>
|
||||
<td rowspan="1" width="175">3D Volumetric Mesh</td>
|
||||
<td width="250">`CGAL::Linear_cell_complex_for_combinatorial_map<3,3>`</td>
|
||||
<td width="550"> \link PkgLinearCellComplexRefIOVTK `CGAL::IO::read_VTK()` \endlink</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="1">Output</td>
|
||||
<td rowspan="1">3D Volumetric Mesh</td>
|
||||
<td>`CGAL::Linear_cell_complex_for_combinatorial_map<3,3>`</td>
|
||||
<td> \link PkgLinearCellComplexRefIOVTK `CGAL::IO::Write_VTK<LCC>()` \endlink</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
\section IOStreamAvizo Avizo File Format
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ Arrangement_on_surface_2
|
|||
BGL
|
||||
Constrained_triangulation_3
|
||||
Kernel_23
|
||||
Linear_cell_complex
|
||||
Manual
|
||||
Mesh_2
|
||||
Mesh_3
|
||||
|
|
|
|||
Loading…
Reference in New Issue