mirror of https://github.com/CGAL/cgal
Merge branch 'Polyhedron_demo-mesh_3_write_c3t3_boundary-GF'
Adding functions to export the boundary of a 3D mesh embedded in a C3T3 See Features/Small_Features/Mesh_3_output_to_off Successfully tested in CGAL-4.6-Ic-26 Approved by the interim release manager
This commit is contained in:
commit
d79eeddfb9
|
|
@ -80,6 +80,21 @@ in medit format.
|
|||
*/
|
||||
void output_to_medit(std::ofstream& os);
|
||||
|
||||
/**
|
||||
* Outputs the outer boundary of the entire domain with facets oriented outward.
|
||||
*/
|
||||
std::ostream& output_boundary_to_off(std::ostream& out) const;
|
||||
|
||||
/**
|
||||
* Outputs the outer boundary of the selected subdomain with facets oriented outward.
|
||||
*/
|
||||
std::ostream& output_boundary_to_off(std::ostream& out, Subdomain_index subdomain) const;
|
||||
|
||||
/**
|
||||
* Outputs the surface facets with a consistent orientation at the interface of two subdomains.
|
||||
*/
|
||||
std::ostream& output_facets_in_complex_to_off(std::ostream& out) const;
|
||||
|
||||
/// @}
|
||||
|
||||
}; /* end Mesh_complex_3_in_triangulation_3 */
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include <boost/iterator/transform_iterator.hpp>
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <CGAL/internal/Mesh_3/Boundary_of_subdomain_of_complex_3_in_triangulation_3_to_off.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
|
|
@ -70,6 +71,7 @@ public:
|
|||
typedef CurveSegmentIndex Curve_segment_index;
|
||||
|
||||
typedef typename Base::Triangulation Triangulation;
|
||||
typedef typename Base::Subdomain_index Subdomain_index;
|
||||
|
||||
using Base::surface_patch_index;
|
||||
|
||||
|
|
@ -332,6 +334,33 @@ public:
|
|||
return Corner_index();
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the outer boundary of the entire domain with facets oriented outward.
|
||||
*/
|
||||
std::ostream& output_boundary_to_off(std::ostream& out) const
|
||||
{
|
||||
internal::output_boundary_of_c3t3_to_off(*this, 0, out, false);
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the outer boundary of the selected subdomain with facets oriented outward.
|
||||
*/
|
||||
std::ostream& output_boundary_to_off(std::ostream& out, Subdomain_index subdomain) const
|
||||
{
|
||||
output_boundary_of_c3t3_to_off(*this, subdomain, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the surface facets with a consistent orientation at the interface of two subdomains.
|
||||
*/
|
||||
std::ostream& output_facets_in_complex_to_off(std::ostream& out) const
|
||||
{
|
||||
internal::output_facets_in_complex_to_off(*this, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills \c out with incident edges (1-dimensional features of \c v.
|
||||
* OutputIterator value type is std::pair<Vertex_handle,Curve_segment_index>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,136 @@
|
|||
// Copyright (c) 2008-2014 GeometryFactory (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL: svn+ssh://sloriot@scm.gforge.inria.fr/svn/cgal/branches/next/Mesh_3/include/CGAL/IO/Complex_3_in_triangulation_3_to_vtk.h $
|
||||
// $Id: Complex_3_in_triangulation_3_to_vtk.h 67117 2012-01-13 18:14:48Z lrineau $
|
||||
//
|
||||
//
|
||||
// Author(s) : Laurent Rineau and Sebastien Loriot
|
||||
|
||||
#ifndef CGAL_INTERNAL_MESH_3_BOUNDARY_OF_SUDDOMAIN_OF_COMPLEX_3_IN_TRIANGULATION_3_TO_OFF_H
|
||||
#define CGAL_INTERNAL_MESH_3_BOUNDARY_OF_SUDDOMAIN_OF_COMPLEX_3_IN_TRIANGULATION_3_TO_OFF_H
|
||||
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
|
||||
#include <CGAL/array.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
namespace internal{
|
||||
|
||||
namespace mesh_3_export{
|
||||
template <class Vertex_handle>
|
||||
std::size_t get_vertex_index(Vertex_handle v,std::map<Vertex_handle, std::size_t>& V,std::size_t& inum,std::stringstream& vertex_buffer){
|
||||
std::pair<typename std::map<Vertex_handle, std::size_t>::iterator,bool> res=
|
||||
V.insert(std::make_pair(v,inum));
|
||||
if (res.second){
|
||||
++inum;
|
||||
vertex_buffer << res.first->first->point().point() <<"\n"; //point is weighted!
|
||||
}
|
||||
return res.first->second;
|
||||
}
|
||||
} // end of namespace mesh_3_export
|
||||
|
||||
template <typename C3T3>
|
||||
std::ostream&
|
||||
output_boundary_of_c3t3_to_off(const C3T3& c3t3,
|
||||
typename C3T3::Subdomain_index sd_index,
|
||||
std::ostream& output,
|
||||
bool normals_point_outside_of_the_subdomain=true)
|
||||
{
|
||||
typedef typename C3T3::Triangulation Triangulation;
|
||||
typedef typename Triangulation::Vertex_handle Vertex_handle;
|
||||
|
||||
std::map<Vertex_handle, std::size_t> V;
|
||||
|
||||
std::size_t inum = 0;
|
||||
std::size_t nfacets = 0;
|
||||
cpp0x::array<std::size_t,3> indices={{0,0,0}};
|
||||
std::stringstream facet_buffer,vertex_buffer;
|
||||
for(typename C3T3::Facets_in_complex_iterator
|
||||
fit = c3t3.facets_in_complex_begin(),
|
||||
end = c3t3.facets_in_complex_end();
|
||||
fit != end; ++fit)
|
||||
{
|
||||
typename C3T3::Subdomain_index cell_sd=c3t3.subdomain_index(fit->first);
|
||||
typename C3T3::Subdomain_index opp_sd=c3t3.subdomain_index(fit->first->neighbor(fit->second));
|
||||
|
||||
if (cell_sd!=sd_index && opp_sd!=sd_index) continue;
|
||||
|
||||
++nfacets;
|
||||
int j=-1;
|
||||
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
if (i != fit->second)
|
||||
indices[++j]=mesh_3_export::get_vertex_index((*fit).first->vertex(i), V, inum,vertex_buffer);
|
||||
if ( ( (cell_sd==sd_index) == (fit->second%2 == 1) ) == normals_point_outside_of_the_subdomain )
|
||||
std::swap(indices[0],indices[1]);
|
||||
facet_buffer << "3" << " " << indices[0] <<" " << indices[1] <<" " << indices[2] << "\n";
|
||||
}
|
||||
|
||||
output << "OFF " << inum << " " << nfacets << " 0\n";
|
||||
output << vertex_buffer.str();
|
||||
output << facet_buffer.str();
|
||||
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
template <typename C3T3>
|
||||
std::ostream&
|
||||
output_facets_in_complex_to_off(const C3T3& c3t3,
|
||||
std::ostream& output)
|
||||
{
|
||||
typedef typename C3T3::Triangulation Triangulation;
|
||||
typedef typename Triangulation::Vertex_handle Vertex_handle;
|
||||
|
||||
std::map<Vertex_handle, std::size_t> V;
|
||||
|
||||
std::size_t inum = 0;
|
||||
std::size_t nfacets = 0;
|
||||
cpp0x::array<std::size_t,3> indices={{0,0,0}};
|
||||
std::stringstream facet_buffer,vertex_buffer;
|
||||
for(typename C3T3::Facets_in_complex_iterator
|
||||
fit = c3t3.facets_in_complex_begin(),
|
||||
end = c3t3.facets_in_complex_end();
|
||||
fit != end; ++fit)
|
||||
{
|
||||
typename C3T3::Subdomain_index cell_sd=c3t3.subdomain_index(fit->first);
|
||||
typename C3T3::Subdomain_index opp_sd=c3t3.subdomain_index(fit->first->neighbor(fit->second));
|
||||
|
||||
++nfacets;
|
||||
int j=-1;
|
||||
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
if (i != fit->second)
|
||||
indices[++j]=mesh_3_export::get_vertex_index((*fit).first->vertex(i), V, inum,vertex_buffer);
|
||||
if ( (cell_sd > opp_sd) == (fit->second%2 == 1) ) std::swap(indices[0],indices[1]);
|
||||
facet_buffer << "3" << " " << indices[0] <<" " << indices[1] <<" " << indices[2] << "\n";
|
||||
}
|
||||
|
||||
output << "OFF " << inum << " " << nfacets << " 0\n";
|
||||
output << vertex_buffer.str();
|
||||
output << facet_buffer.str();
|
||||
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
} } // end of namespace CGAL::internal
|
||||
|
||||
|
||||
#endif // CGAL_INTERNAL_MESH_3_BOUNDARY_OF_SUDDOMAIN_OF_COMPLEX_3_IN_TRIANGULATION_3_TO_OFF_H
|
||||
|
|
@ -53,6 +53,7 @@ if ( CGAL_FOUND )
|
|||
create_single_source_cgal_program( "test_meshing_unit_tetrahedron.cpp" )
|
||||
create_single_source_cgal_program( "test_robust_weighted_circumcenter.cpp" )
|
||||
create_single_source_cgal_program( "test_meshing_determinism.cpp" )
|
||||
create_single_source_cgal_program( "test_c3t3_extract_subdomains_boundaries.cpp" )
|
||||
|
||||
else()
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <CGAL/Mesh_triangulation_3.h>
|
||||
#include <CGAL/Mesh_complex_3_in_triangulation_3.h>
|
||||
#include <CGAL/Mesh_criteria_3.h>
|
||||
|
||||
#include <CGAL/Implicit_to_labeling_function_wrapper.h>
|
||||
#include <CGAL/Labeled_mesh_domain_3.h>
|
||||
#include <CGAL/make_mesh_3.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using namespace CGAL::parameters;
|
||||
|
||||
// Domain
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||
typedef K::FT FT;
|
||||
|
||||
template <int Sq_radius>
|
||||
double sphere_function (double x, double y, double z) // (c=(0,0,0), r=Sq_radius)
|
||||
{
|
||||
double x2=x*x, y2=y*y, z2=z*z;
|
||||
return (x2+y2+z2)/Sq_radius - 1;
|
||||
}
|
||||
|
||||
template <typename FT, typename P>
|
||||
class FT_to_point_function_wrapper : public std::unary_function<P, FT>
|
||||
{
|
||||
typedef FT (*Implicit_function)(FT, FT, FT);
|
||||
Implicit_function function;
|
||||
public:
|
||||
typedef P Point;
|
||||
FT_to_point_function_wrapper(Implicit_function f) : function(f) {}
|
||||
FT operator()(Point p) const { return function(p.x(), p.y(), p.z()); }
|
||||
};
|
||||
|
||||
double torus_function (double x, double y, double z) {
|
||||
double x2=x*x, y2=y*y, z2=z*z;
|
||||
double x4=x2*x2, y4=y2*y2, z4=z2*z2;
|
||||
|
||||
return x4 + y4 + z4 + 2 *x2* y2 + 2*
|
||||
x2*z2 + 2*y2* z2 - 5 *x2 + 4* y2 - 5*z2+4;
|
||||
}
|
||||
|
||||
typedef FT_to_point_function_wrapper<K::FT, K::Point_3> Function;
|
||||
typedef CGAL::Implicit_multi_domain_to_labeling_function_wrapper<Function>
|
||||
Function_wrapper;
|
||||
typedef Function_wrapper::Function_vector Function_vector;
|
||||
typedef CGAL::Labeled_mesh_domain_3<Function_wrapper, K> Mesh_domain;
|
||||
|
||||
// Triangulation
|
||||
typedef CGAL::Mesh_triangulation_3<Mesh_domain>::type Tr;
|
||||
typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3;
|
||||
|
||||
// Mesh Criteria
|
||||
typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria;
|
||||
typedef Mesh_criteria::Facet_criteria Facet_criteria;
|
||||
typedef Mesh_criteria::Cell_criteria Cell_criteria;
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
// Define functions
|
||||
Function f1(&torus_function);
|
||||
Function f2(&sphere_function<3>);
|
||||
|
||||
Function_vector v;
|
||||
v.push_back(f1);
|
||||
v.push_back(f2);
|
||||
// Domain (Warning: Sphere_3 constructor uses square radius !)
|
||||
Mesh_domain domain(v, K::Sphere_3(CGAL::ORIGIN, 5.*5.), 1e-6);
|
||||
|
||||
// Set mesh criteria
|
||||
Facet_criteria facet_criteria(30, 0.2, 0.02); // angle, size, approximation
|
||||
Cell_criteria cell_criteria(2., 0.4); // radius-edge ratio, size
|
||||
Mesh_criteria criteria(facet_criteria, cell_criteria);
|
||||
|
||||
// Mesh generation
|
||||
C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria, no_exude(), no_perturb());
|
||||
|
||||
// Output
|
||||
std::stringstream off_file;
|
||||
c3t3.output_boundary_to_off(off_file);
|
||||
assert( off_file.str().size() > 20 );
|
||||
|
||||
off_file.str("");
|
||||
c3t3.output_facets_in_complex_to_off(off_file);
|
||||
assert( off_file.str().size() > 20 );
|
||||
|
||||
for (int i=0;i<4; ++i){
|
||||
off_file.str("");
|
||||
c3t3.output_boundary_to_off(off_file,i);
|
||||
assert( off_file.str().size() > 20 );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -301,7 +301,7 @@ if(CGAL_Qt4_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND)
|
|||
polyhedron_demo_plugin(mesh_3_plugin Polyhedron_demo_mesh_3_plugin
|
||||
Polyhedron_demo_mesh_3_plugin_cgal_code.cpp Scene_c3t3_item.moc
|
||||
${meshingUI_FILES})
|
||||
target_link_libraries(mesh_3_plugin scene_polyhedron_item ${QGLVIEWER_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY})
|
||||
target_link_libraries(mesh_3_plugin scene_polyhedron_item scene_polygon_soup_item ${QGLVIEWER_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY})
|
||||
else( Boost_VERSION GREATER 103400 )
|
||||
message(STATUS "warning: the plugin mesh_3_plugin requires Boost>=1.34.1 and will not be compiled.")
|
||||
endif( Boost_VERSION GREATER 103400 )
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ Scene_item* cgal_code_mesh_3(const Polyhedron*,
|
|||
const double approx,
|
||||
const double tets_sizing,
|
||||
const double tet_shape,
|
||||
const bool protect_features);
|
||||
const bool protect_features,
|
||||
Scene_interface* scene);
|
||||
|
||||
class Polyhedron_demo_mesh_3_plugin :
|
||||
public QObject,
|
||||
|
|
@ -163,7 +164,8 @@ void Polyhedron_demo_mesh_3_plugin::mesh_3()
|
|||
approx,
|
||||
tet_sizing,
|
||||
radius_edge,
|
||||
protect_features);
|
||||
protect_features,
|
||||
scene);
|
||||
if(result_item) {
|
||||
result_item->setName(tr("%1 3d mesh (%2 %3 %4 %5)")
|
||||
.arg(item->name())
|
||||
|
|
|
|||
|
|
@ -10,10 +10,14 @@
|
|||
#include <CGAL/Polyhedral_mesh_domain_with_features_3.h>
|
||||
#include <CGAL/make_mesh_3.h>
|
||||
|
||||
#include <Scene_polyhedron_item.h>
|
||||
#include <Scene_polygon_soup_item.h>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include <CGAL/Timer.h>
|
||||
|
||||
#include <QMenu>
|
||||
|
||||
typedef CGAL::Polyhedral_mesh_domain_with_features_3<Kernel,
|
||||
Polyhedron> Mesh_domain;
|
||||
|
|
@ -52,8 +56,7 @@ public:
|
|||
typedef qglviewer::ManipulatedFrame ManipulatedFrame;
|
||||
|
||||
Scene_c3t3_item(const C3t3& c3t3)
|
||||
: c3t3_(c3t3), frame(new ManipulatedFrame())
|
||||
|
||||
: c3t3_(c3t3), frame(new ManipulatedFrame()), last_known_scene(NULL)
|
||||
{}
|
||||
|
||||
~Scene_c3t3_item()
|
||||
|
|
@ -274,9 +277,65 @@ private:
|
|||
return diag * 0.7;
|
||||
}
|
||||
|
||||
C3t3 c3t3_;
|
||||
public slots:
|
||||
void export_facets_in_complex()
|
||||
{
|
||||
std::stringstream off_sstream;
|
||||
c3t3().output_facets_in_complex_to_off(off_sstream);
|
||||
std::string backup = off_sstream.str();
|
||||
// Try to read .off in a polyhedron
|
||||
Scene_polyhedron_item* item = new Scene_polyhedron_item();
|
||||
if(!item->load(off_sstream))
|
||||
{
|
||||
delete item;
|
||||
off_sstream.str(backup);
|
||||
|
||||
// Try to read .off in a polygon soup
|
||||
Scene_polygon_soup_item* soup_item = new Scene_polygon_soup_item;
|
||||
|
||||
if(!soup_item->load(off_sstream)) {
|
||||
delete soup_item;
|
||||
return;
|
||||
}
|
||||
|
||||
soup_item->setName(QString("%1_%2").arg(this->name()).arg("facets"));
|
||||
last_known_scene->addItem(soup_item);
|
||||
}
|
||||
else{
|
||||
item->setName(QString("%1_%2").arg(this->name()).arg("facets"));
|
||||
last_known_scene->addItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
QMenu* contextMenu()
|
||||
{
|
||||
const char* prop_name = "Menu modified by Scene_c3t3_item.";
|
||||
|
||||
QMenu* menu = Scene_item::contextMenu();
|
||||
|
||||
// Use dynamic properties:
|
||||
// http://doc.trolltech.com/lastest/qobject.html#property
|
||||
bool menuChanged = menu->property(prop_name).toBool();
|
||||
|
||||
if(!menuChanged) {
|
||||
QAction* actionExportFacetsInComplex =
|
||||
menu->addAction(tr("Export facets in complex"));
|
||||
actionExportFacetsInComplex->setObjectName("actionExportFacetsInComplex");
|
||||
connect(actionExportFacetsInComplex,
|
||||
SIGNAL(triggered()),this,
|
||||
SLOT(export_facets_in_complex()));
|
||||
}
|
||||
return menu;
|
||||
}
|
||||
|
||||
void set_scene(Scene_interface* scene){ last_known_scene=scene; }
|
||||
|
||||
private:
|
||||
C3t3 c3t3_;
|
||||
qglviewer::ManipulatedFrame* frame;
|
||||
Scene_interface* last_known_scene;
|
||||
};
|
||||
|
||||
Scene_item* cgal_code_mesh_3(const Polyhedron* pMesh,
|
||||
|
|
@ -286,7 +345,8 @@ Scene_item* cgal_code_mesh_3(const Polyhedron* pMesh,
|
|||
const double approx,
|
||||
const double tet_sizing,
|
||||
const double tet_shape,
|
||||
const bool protect_features)
|
||||
const bool protect_features,
|
||||
Scene_interface* scene)
|
||||
{
|
||||
if(!pMesh) return 0;
|
||||
|
||||
|
|
@ -322,13 +382,14 @@ Scene_item* cgal_code_mesh_3(const Polyhedron* pMesh,
|
|||
|
||||
Scene_c3t3_item* new_item =
|
||||
new Scene_c3t3_item(CGAL::make_mesh_3<C3t3>(domain, criteria, features));
|
||||
|
||||
new_item->set_scene(scene);
|
||||
std::cerr << "done (" << timer.time() << " ms, " << new_item->c3t3().triangulation().number_of_vertices() << " vertices)" << std::endl;
|
||||
|
||||
if(new_item->c3t3().triangulation().number_of_vertices() > 0)
|
||||
{
|
||||
std::ofstream medit_out("out.mesh");
|
||||
new_item->c3t3().output_to_medit(medit_out);
|
||||
|
||||
const Scene_item::Bbox& bbox = new_item->bbox();
|
||||
new_item->setPosition((float)(bbox.xmin + bbox.xmax)/2.f,
|
||||
(float)(bbox.ymin + bbox.ymax)/2.f,
|
||||
|
|
|
|||
Loading…
Reference in New Issue