mirror of https://github.com/CGAL/cgal
Merge pull request #457 from janetournois/Polygon_mesh_processing-local_remeshing-GF
Polygon mesh processing - add isotropic remeshing
This commit is contained in:
commit
d605b6b95f
|
|
@ -0,0 +1,57 @@
|
|||
# Created by the script cgal_create_CMakeLists
|
||||
# This is the CMake script for compiling a set of CGAL applications.
|
||||
|
||||
project( BGL_OpenMesh )
|
||||
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.11)
|
||||
|
||||
# CGAL and its components
|
||||
find_package( CGAL QUIET COMPONENTS )
|
||||
|
||||
if ( NOT CGAL_FOUND )
|
||||
|
||||
message(STATUS "This project requires the CGAL library, and will not be compiled.")
|
||||
return()
|
||||
|
||||
endif()
|
||||
|
||||
# include helper file
|
||||
include( ${CGAL_USE_FILE} )
|
||||
|
||||
|
||||
# Boost and its components
|
||||
find_package( Boost REQUIRED )
|
||||
|
||||
if ( NOT Boost_FOUND )
|
||||
|
||||
message(STATUS "This project requires the Boost library, and will not be compiled.")
|
||||
|
||||
return()
|
||||
|
||||
endif()
|
||||
|
||||
find_package( OpenMesh QUIET )
|
||||
|
||||
if ( OpenMesh_FOUND )
|
||||
include( UseOpenMesh )
|
||||
else()
|
||||
message(STATUS "Examples that use OpenMesh will not be compiled.")
|
||||
endif()
|
||||
|
||||
# include for local directory
|
||||
|
||||
# include for local package
|
||||
include_directories( BEFORE ../../include )
|
||||
|
||||
|
||||
# Creating entries for all C++ files with "main" routine
|
||||
# ##########################################################
|
||||
|
||||
include( CGAL_CreateSingleSourceCGALProgram )
|
||||
|
||||
if(OpenMesh_FOUND)
|
||||
create_single_source_cgal_program( "TriMesh.cpp" )
|
||||
target_link_libraries( TriMesh ${OPENMESH_LIBRARIES} )
|
||||
endif()
|
||||
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||
|
||||
#include <CGAL/boost/graph/graph_traits_TriMesh_ArrayKernelT.h>
|
||||
#include <CGAL/boost/graph/iterator.h>
|
||||
#include <CGAL/boost/graph/Euler_operations.h>
|
||||
|
||||
#include <CGAL/mesh_segmentation.h>
|
||||
|
||||
#include <CGAL/property_map.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
|
||||
typedef OpenMesh::TriMesh_ArrayKernelT</* MyTraits*/> Mesh;
|
||||
|
||||
typedef boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
|
||||
typedef boost::graph_traits<Mesh>::face_descriptor face_descriptor;
|
||||
typedef boost::graph_traits<Mesh>::halfedge_descriptor halfedge_descriptor;
|
||||
|
||||
|
||||
int main(int argc, char** argv )
|
||||
{
|
||||
Mesh mesh;
|
||||
|
||||
std::vector<vertex_descriptor> V;
|
||||
V.push_back(add_vertex(mesh));
|
||||
V.push_back(add_vertex(mesh));
|
||||
V.push_back(add_vertex(mesh));
|
||||
add_face(V.begin(), V.end(), mesh);
|
||||
|
||||
// OpenMesh::IO::read_mesh(mesh, (argc>1)?argv[1]:"in.off");
|
||||
|
||||
BOOST_FOREACH(vertex_descriptor vd, vertices(mesh)){
|
||||
BOOST_FOREACH(halfedge_descriptor hd, CGAL::halfedges_around_target(vd,mesh)){
|
||||
if(! CGAL::is_border(edge(hd,mesh),mesh)){
|
||||
CGAL::Euler::flip_edge(hd,mesh);
|
||||
OpenMesh::IO::write_mesh(mesh, (argc>2)?argv[2]:"out.off");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
# Created by the script cgal_create_CMakeLists
|
||||
# This is the CMake script for compiling a set of CGAL applications.
|
||||
|
||||
project( BGL_polyhedron_3 )
|
||||
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.11)
|
||||
|
||||
# CGAL and its components
|
||||
find_package( CGAL QUIET COMPONENTS )
|
||||
|
||||
if ( NOT CGAL_FOUND )
|
||||
|
||||
message(STATUS "This project requires the CGAL library, and will not be compiled.")
|
||||
return()
|
||||
|
||||
endif()
|
||||
|
||||
# include helper file
|
||||
include( ${CGAL_USE_FILE} )
|
||||
|
||||
|
||||
# Boost and its components
|
||||
find_package( Boost REQUIRED )
|
||||
|
||||
if ( NOT Boost_FOUND )
|
||||
|
||||
message(STATUS "This project requires the Boost library, and will not be compiled.")
|
||||
|
||||
return()
|
||||
|
||||
endif()
|
||||
|
||||
find_package( OpenMesh QUIET )
|
||||
|
||||
if ( OpenMesh_FOUND )
|
||||
include( UseOpenMesh )
|
||||
else()
|
||||
message(STATUS "Examples that use OpenMesh will not be compiled.")
|
||||
endif()
|
||||
|
||||
# include for local directory
|
||||
|
||||
# include for local package
|
||||
include_directories( BEFORE ../../include )
|
||||
|
||||
|
||||
# Creating entries for all C++ files with "main" routine
|
||||
# ##########################################################
|
||||
|
||||
include( CGAL_CreateSingleSourceCGALProgram )
|
||||
|
||||
create_single_source_cgal_program( "distance.cpp" )
|
||||
|
||||
create_single_source_cgal_program( "incident_vertices.cpp" )
|
||||
|
||||
create_single_source_cgal_program( "kruskal.cpp" )
|
||||
|
||||
create_single_source_cgal_program( "kruskal_with_stored_id.cpp" )
|
||||
|
||||
create_single_source_cgal_program( "normals.cpp" )
|
||||
|
||||
create_single_source_cgal_program( "range.cpp" )
|
||||
|
||||
create_single_source_cgal_program( "transform_iterator.cpp" )
|
||||
|
||||
|
||||
|
||||
if(OpenMesh_FOUND)
|
||||
create_single_source_cgal_program( "polyhedron_2_OpenMesh.cpp" )
|
||||
target_link_libraries( polyhedron_2_OpenMesh ${OPENMESH_LIBRARIES} )
|
||||
endif()
|
||||
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <CGAL/Polyhedron_3.h>
|
||||
#include <CGAL/IO/Polyhedron_iostream.h>
|
||||
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
|
||||
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
|
||||
#if 1
|
||||
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
|
||||
#include <CGAL/boost/graph/graph_traits_PolyMesh_ArrayKernelT.h>
|
||||
#else
|
||||
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||
#include <CGAL/boost/graph/graph_traits_TriMesh_ArrayKernelT.h>
|
||||
#endif
|
||||
|
||||
#include <CGAL/boost/graph/convert_surface_mesh.h>
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
typedef Kernel::Vector_3 Vector;
|
||||
typedef Kernel::Point_3 Point;
|
||||
typedef CGAL::Polyhedron_3<Kernel> Source;
|
||||
|
||||
#if 1
|
||||
typedef OpenMesh::PolyMesh_ArrayKernelT</* MyTraits*/> Target;
|
||||
#else
|
||||
typedef OpenMesh::TriMesh_ArrayKernelT</* MyTraits*/> Target;
|
||||
#endif
|
||||
typedef boost::graph_traits<Source>::vertex_descriptor sm_vertex_descriptor;
|
||||
typedef boost::graph_traits<Target>::vertex_descriptor tm_vertex_descriptor;
|
||||
|
||||
typedef boost::graph_traits<Source>::halfedge_descriptor sm_halfedge_descriptor;
|
||||
typedef boost::graph_traits<Target>::halfedge_descriptor tm_halfedge_descriptor;
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
inline std::size_t hash_value(const VertexHandle& i)
|
||||
{
|
||||
return i.idx();
|
||||
}
|
||||
|
||||
inline std::size_t hash_value(const HalfedgeHandle& i)
|
||||
{
|
||||
return i.idx();
|
||||
}
|
||||
|
||||
inline std::size_t hash_value(const FaceHandle& i)
|
||||
{
|
||||
return i.idx();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
Source S;
|
||||
Target T;
|
||||
std::ifstream in((argc>1)?argv[1]:"cube.off");
|
||||
in >> S;
|
||||
|
||||
{
|
||||
boost::unordered_map<sm_vertex_descriptor, tm_vertex_descriptor> v2v;
|
||||
boost::unordered_map<sm_halfedge_descriptor, tm_halfedge_descriptor> h2h;
|
||||
|
||||
convert_surface_mesh(S,T,v2v,h2h);
|
||||
OpenMesh::IO::write_mesh(T, "om.off");
|
||||
}
|
||||
S.clear();
|
||||
{
|
||||
boost::unordered_map<tm_vertex_descriptor, sm_vertex_descriptor> v2v;
|
||||
boost::unordered_map<tm_halfedge_descriptor, sm_halfedge_descriptor> h2h;
|
||||
|
||||
convert_surface_mesh(T,S,v2v,h2h);
|
||||
std::ofstream out("reverse.off");
|
||||
out << S << std::endl;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
// Copyright (c) 2015 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 Lesser General Public License as
|
||||
// published by the Free Software Foundation; either version 3 of the License,
|
||||
// or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s) : Andreas Fabri
|
||||
|
||||
#ifndef CGAL_BOOST_GRAPH_CONVERT_SURFACE_MESH_H
|
||||
#define CGAL_BOOST_GRAPH_CONVERT_SURFACE_MESH_H
|
||||
|
||||
#include <CGAL/boost/graph/Euler_operations.h>
|
||||
#include <CGAL/boost/graph/iterator.h>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <CGAL/boost/graph/helpers.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <typename SourceMesh, typename TargetMesh, typename V2V, typename H2H>
|
||||
void convert_surface_mesh(const SourceMesh& sm, TargetMesh& tm, V2V& v2v, H2H& h2h)
|
||||
{
|
||||
typedef typename boost::graph_traits<SourceMesh>::vertex_descriptor sm_vertex_descriptor;
|
||||
typedef typename boost::graph_traits<TargetMesh>::vertex_descriptor tm_vertex_descriptor;
|
||||
|
||||
typedef typename boost::graph_traits<SourceMesh>::face_descriptor sm_face_descriptor;
|
||||
typedef typename boost::graph_traits<TargetMesh>::face_descriptor tm_face_descriptor;
|
||||
|
||||
typedef typename boost::graph_traits<SourceMesh>::halfedge_descriptor sm_halfedge_descriptor;
|
||||
typedef typename boost::graph_traits<TargetMesh>::halfedge_descriptor tm_halfedge_descriptor;
|
||||
|
||||
typedef typename boost::property_map<SourceMesh, vertex_point_t>::const_type sm_PMap;
|
||||
typedef typename boost::property_map<TargetMesh, vertex_point_t>::type tm_PMap;
|
||||
|
||||
sm_PMap sm_pmap = get(vertex_point, sm);
|
||||
tm_PMap tm_pmap = get(vertex_point, tm);
|
||||
|
||||
|
||||
BOOST_FOREACH(sm_vertex_descriptor svd, vertices(sm)){
|
||||
tm_vertex_descriptor tvd = add_vertex(tm);
|
||||
v2v.insert(std::make_pair(svd, tvd));
|
||||
put(tm_pmap, tvd, get(sm_pmap, svd));
|
||||
}
|
||||
|
||||
boost::unordered_map<sm_face_descriptor, tm_face_descriptor> f2f;
|
||||
BOOST_FOREACH(sm_face_descriptor sfd, faces(sm)){
|
||||
std::vector<tm_vertex_descriptor> tv;
|
||||
BOOST_FOREACH(sm_vertex_descriptor svd, vertices_around_face(halfedge(sfd,sm),sm)){
|
||||
tv.push_back(v2v.at(svd));
|
||||
}
|
||||
f2f[sfd] = Euler::add_face(tv,tm);
|
||||
}
|
||||
|
||||
BOOST_FOREACH(sm_face_descriptor sfd, faces(sm)){
|
||||
sm_halfedge_descriptor shd = halfedge(sfd,sm), done(shd);
|
||||
tm_halfedge_descriptor thd = halfedge(f2f[sfd],tm);
|
||||
tm_vertex_descriptor tvd = v2v.at(target(shd,sm));
|
||||
while(target(thd,tm) != tvd){
|
||||
thd = next(thd,tm);
|
||||
}
|
||||
do {
|
||||
h2h.insert(std::make_pair(shd, thd));
|
||||
shd = next(shd,sm);
|
||||
thd = next(thd,tm);
|
||||
}while(shd != done);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_BOOST_GRAPH_CONVERT_SURFACE_MESH_H
|
||||
|
|
@ -358,6 +358,9 @@ typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::halfedge_desc
|
|||
halfedge(typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::vertex_descriptor v,
|
||||
const OpenMesh::PolyMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
if(sm.halfedge_handle(v) == boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::null_halfedge()){
|
||||
return boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::null_halfedge();
|
||||
}
|
||||
// prev because OpenMesh stores out-going halfedges
|
||||
// return sm.prev_halfedge_handle(sm.halfedge_handle(v));
|
||||
return sm.opposite_halfedge_handle(sm.halfedge_handle(v));
|
||||
|
|
@ -615,7 +618,7 @@ remove_face(typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::f
|
|||
sm.status(f).set_deleted(true);
|
||||
}
|
||||
|
||||
|
||||
#if 0 // conflits with function in Euler_operations.h
|
||||
template<typename K>
|
||||
std::pair<typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::edge_descriptor,
|
||||
bool>
|
||||
|
|
@ -625,6 +628,7 @@ add_edge(typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::vert
|
|||
|
||||
return sm.new_edge(v1, v2);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename K>
|
||||
typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::face_descriptor
|
||||
|
|
|
|||
|
|
@ -515,7 +515,7 @@ add_face(InputIterator begin, InputIterator end, CGAL::Surface_mesh<P>& sm)
|
|||
}
|
||||
|
||||
template<typename P>
|
||||
bool is_valid(CGAL::Surface_mesh<P>& sm, bool verbose = false)
|
||||
bool is_valid(const CGAL::Surface_mesh<P>& sm, bool verbose = false)
|
||||
{
|
||||
return sm.is_valid(verbose);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,614 @@
|
|||
// Copyright (c) 2007 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 Lesser General Public License as
|
||||
// published by the Free Software Foundation; either version 3 of the License,
|
||||
// or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s) : Andreas Fabri, Philipp Moeller
|
||||
|
||||
#ifndef CGAL_BOOST_GRAPH_GRAPH_TRAITS_TRIMESH_ARRAYKERNELT_H
|
||||
#define CGAL_BOOST_GRAPH_GRAPH_TRAITS_TRIMESH_ARRAYKERNELT_H
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
|
||||
#include <CGAL/boost/graph/properties_TriMesh_ArrayKernelT.h>
|
||||
#include <CGAL/boost/graph/graph_traits_PolyMesh_ArrayKernelT.h>
|
||||
#include <CGAL/boost/graph/internal/OM_iterator_from_circulator.h>
|
||||
#include <CGAL/boost/graph/iterator.h>
|
||||
#include <CGAL/Iterator_range.h>
|
||||
#include <CGAL/boost/graph/helpers.h>
|
||||
#include <CGAL/assertions.h>
|
||||
|
||||
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||
|
||||
// http://openmesh.org/Documentation/OpenMesh-Doc-Latest/classOpenMesh_1_1Concepts_1_1KernelT.html
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4267)
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class K>
|
||||
struct graph_traits< OpenMesh::TriMesh_ArrayKernelT<K> >
|
||||
{
|
||||
private:
|
||||
typedef OpenMesh::TriMesh_ArrayKernelT<K> SM;
|
||||
|
||||
struct SM_graph_traversal_category : public virtual boost::bidirectional_graph_tag,
|
||||
public virtual boost::vertex_list_graph_tag,
|
||||
public virtual boost::edge_list_graph_tag
|
||||
{};
|
||||
|
||||
public:
|
||||
// Graph
|
||||
typedef typename SM::VertexHandle vertex_descriptor;
|
||||
typedef typename SM::Point vertex_property_type;
|
||||
typedef typename CGAL::internal::OMesh_edge<typename SM::HalfedgeHandle> edge_descriptor;
|
||||
typedef boost::undirected_tag directed_category;
|
||||
typedef boost::disallow_parallel_edge_tag edge_parallel_category;
|
||||
typedef SM_graph_traversal_category traversal_category;
|
||||
|
||||
// HalfedgeGraph
|
||||
typedef typename SM::HalfedgeHandle halfedge_descriptor;
|
||||
|
||||
// FaceGraph
|
||||
typedef typename SM::FaceHandle face_descriptor;
|
||||
|
||||
// VertexListGraph
|
||||
typedef typename SM::VertexIter vertex_iterator;
|
||||
typedef unsigned int vertices_size_type;
|
||||
// EdgeListGraph
|
||||
typedef boost::transform_iterator<
|
||||
CGAL::internal::Convert_omesh_edge<typename SM::HalfedgeHandle, typename SM::EdgeHandle>,
|
||||
typename SM::EdgeIter,
|
||||
edge_descriptor> edge_iterator;
|
||||
|
||||
typedef unsigned int edges_size_type;
|
||||
// HalfEdgeListGraph
|
||||
typedef typename SM::HalfedgeIter halfedge_iterator;
|
||||
typedef unsigned int halfedges_size_type;
|
||||
// FaceListGraph
|
||||
typedef typename SM::FaceIter face_iterator;
|
||||
typedef unsigned int faces_size_type;
|
||||
|
||||
// IncidenceGraph
|
||||
typedef unsigned int degree_size_type;
|
||||
|
||||
|
||||
typedef CGAL::In_edge_iterator<SM> in_edge_iterator;
|
||||
|
||||
typedef CGAL::Out_edge_iterator<SM> out_edge_iterator;
|
||||
|
||||
// nulls
|
||||
static vertex_descriptor null_vertex() { return vertex_descriptor(); }
|
||||
static face_descriptor null_face() { return face_descriptor(); }
|
||||
static halfedge_descriptor null_halfedge() { return halfedge_descriptor(); }
|
||||
};
|
||||
|
||||
template<typename K>
|
||||
struct graph_traits< const OpenMesh::TriMesh_ArrayKernelT<K> >
|
||||
: public graph_traits< OpenMesh::TriMesh_ArrayKernelT<K> >
|
||||
{ };
|
||||
|
||||
} // namespace boost
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
template <typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertices_size_type
|
||||
num_vertices(const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return sm.n_vertices();
|
||||
}
|
||||
|
||||
|
||||
template <typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::edges_size_type
|
||||
num_edges(const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return sm.n_edges();
|
||||
}
|
||||
|
||||
|
||||
template <typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::degree_size_type
|
||||
degree(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor v,
|
||||
const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return sm.valence(v);
|
||||
}
|
||||
|
||||
|
||||
template <typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::degree_size_type
|
||||
out_degree(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor v,
|
||||
const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return sm.valence(v);
|
||||
}
|
||||
|
||||
|
||||
template <typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::degree_size_type
|
||||
in_degree(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor v,
|
||||
const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return sm.valence(v);
|
||||
}
|
||||
|
||||
|
||||
template <typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor
|
||||
source(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::edge_descriptor e,
|
||||
const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return sm.from_vertex_handle(e.halfedge());
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor
|
||||
source(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor h,
|
||||
const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return sm.from_vertex_handle(h);
|
||||
}
|
||||
|
||||
|
||||
template <typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor
|
||||
target(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::edge_descriptor e,
|
||||
const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return sm.to_vertex_handle(e.halfedge());
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor
|
||||
target(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor h,
|
||||
const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return sm.to_vertex_handle(h);
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
CGAL::Iterator_range<typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_iterator>
|
||||
vertices(const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return CGAL::make_range(sm.vertices_sbegin(), sm.vertices_end());
|
||||
}
|
||||
|
||||
|
||||
template <typename K>
|
||||
CGAL::Iterator_range<typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::edge_iterator>
|
||||
edges(const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
typedef typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::edge_iterator iterator;
|
||||
iterator beg(sm.edges_sbegin());
|
||||
iterator end(sm.edges_end());
|
||||
return CGAL::make_range(beg,end);
|
||||
}
|
||||
|
||||
|
||||
template <typename K>
|
||||
CGAL::Iterator_range<typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::in_edge_iterator>
|
||||
in_edges(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor v,
|
||||
const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
typedef typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::in_edge_iterator Iter;
|
||||
|
||||
return CGAL::make_range(Iter(halfedge(v,sm),sm), Iter(halfedge(v,sm),sm,1));
|
||||
}
|
||||
|
||||
|
||||
template <typename K>
|
||||
CGAL::Iterator_range<typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::out_edge_iterator>
|
||||
out_edges(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor v,
|
||||
const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
typedef typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::out_edge_iterator Iter;
|
||||
return CGAL::make_range(Iter(halfedge(v,sm),sm), Iter(halfedge(v,sm),sm,1));
|
||||
}
|
||||
|
||||
|
||||
template<typename K>
|
||||
std::pair<typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::edge_descriptor,
|
||||
bool>
|
||||
edge(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor u,
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor v,
|
||||
const OpenMesh::TriMesh_ArrayKernelT<K>& sm) {
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::edge_descriptor
|
||||
he(sm.find_halfedge(u, v));
|
||||
return std::make_pair(he, he.is_valid());
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// HalfedgeGraph
|
||||
//
|
||||
template <typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor
|
||||
next(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor h,
|
||||
const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return sm.next_halfedge_handle(h);
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor
|
||||
prev(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor h,
|
||||
const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return sm.prev_halfedge_handle(h);
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor
|
||||
opposite(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor h,
|
||||
const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return sm.opposite_halfedge_handle(h);
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::edge_descriptor
|
||||
edge(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor h,
|
||||
const OpenMesh::TriMesh_ArrayKernelT<K>& /*sm*/)
|
||||
{
|
||||
return typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::edge_descriptor(h);
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor
|
||||
halfedge(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::edge_descriptor e,
|
||||
const OpenMesh::TriMesh_ArrayKernelT<K>&)
|
||||
{
|
||||
return e.halfedge();
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor
|
||||
halfedge(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor v,
|
||||
const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
if(sm.halfedge_handle(v) == boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::null_halfedge()){
|
||||
return boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::null_halfedge();
|
||||
}
|
||||
// prev because OpenMesh stores out-going halfedges
|
||||
// return sm.prev_halfedge_handle(sm.halfedge_handle(v));
|
||||
return sm.opposite_halfedge_handle(sm.halfedge_handle(v));
|
||||
}
|
||||
|
||||
|
||||
template <typename K>
|
||||
std::pair<
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor,
|
||||
bool
|
||||
>
|
||||
halfedge(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor u,
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor v,
|
||||
const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor h = sm.find_halfedge(u, v);
|
||||
return std::make_pair(h, h.is_valid());
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// HalfedgeListGraph
|
||||
//
|
||||
template <typename K>
|
||||
CGAL::Iterator_range<typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_iterator>
|
||||
halfedges(const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return CGAL::make_range(sm.halfedges_sbegin(), sm.halfedges_end());
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedges_size_type
|
||||
num_halfedges(const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return sm.n_halfedges();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// MutableHalfedgeGraph
|
||||
//
|
||||
template<typename K>
|
||||
void
|
||||
set_next(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor h1,
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor h2,
|
||||
OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
sm.set_next_halfedge_handle(h1, h2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename K>
|
||||
void
|
||||
set_target(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor h,
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor v,
|
||||
OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
sm.set_vertex_handle(h, v);
|
||||
}
|
||||
|
||||
|
||||
template<typename K>
|
||||
void
|
||||
set_halfedge(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor v,
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor h,
|
||||
OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
sm.set_halfedge_handle(v, sm.opposite_halfedge_handle(h));
|
||||
}
|
||||
|
||||
|
||||
template<typename K>
|
||||
void
|
||||
adjust_border_halfedge(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor v,
|
||||
OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
sm.adjust_outgoing_halfedge(v);
|
||||
}
|
||||
|
||||
template<typename K>
|
||||
void
|
||||
garbage_collection(OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
sm.garbage_collection();
|
||||
}
|
||||
|
||||
template<typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::edge_descriptor
|
||||
add_edge(OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return edge(sm.new_edge(boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::null_vertex(),
|
||||
boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::null_vertex() ), sm);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// FaceGraph
|
||||
//
|
||||
template<typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor
|
||||
halfedge(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::face_descriptor f,
|
||||
const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return sm.halfedge_handle(f);
|
||||
}
|
||||
|
||||
template<typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::face_descriptor
|
||||
face(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor h,
|
||||
const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return sm.face_handle(h);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// MutableFaceGraph
|
||||
//
|
||||
template<typename K>
|
||||
void
|
||||
set_face(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor h,
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::face_descriptor f,
|
||||
OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
sm.set_face_handle(h, f);
|
||||
}
|
||||
|
||||
|
||||
template<typename K>
|
||||
void
|
||||
set_halfedge(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::face_descriptor f,
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor h,
|
||||
OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
sm.set_halfedge_handle(f, h);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// FaceListGraph
|
||||
//
|
||||
template <typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::faces_size_type
|
||||
num_faces(const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return sm.n_faces();
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
CGAL::Iterator_range<typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::face_iterator>
|
||||
faces(const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return CGAL::make_range(sm.faces_sbegin(), sm.faces_end());
|
||||
}
|
||||
|
||||
|
||||
template <typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor
|
||||
add_vertex(OpenMesh::TriMesh_ArrayKernelT<K>& sm) {
|
||||
return sm.new_vertex();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
// MutableGraph
|
||||
// add a vertex with a default constructed property
|
||||
template <typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor
|
||||
add_vertex(OpenMesh::TriMesh_ArrayKernelT<K>& sm) {
|
||||
return sm.add_vertex(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_property_type());
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor
|
||||
add_vertex(const typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_property_type& p, OpenMesh::TriMesh_ArrayKernelT<K>& sm) {
|
||||
return sm.add_vertex(p);
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
void
|
||||
clear_vertex(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor,
|
||||
OpenMesh::TriMesh_ArrayKernelT<K>&) {
|
||||
CGAL_assert(false);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
template <typename K>
|
||||
void
|
||||
remove_vertex(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor v,
|
||||
OpenMesh::TriMesh_ArrayKernelT<K>& sm) {
|
||||
|
||||
sm.request_face_status();
|
||||
sm.request_vertex_status();
|
||||
sm.request_halfedge_status();
|
||||
sm.set_halfedge_handle(v, typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor());
|
||||
sm.status(v).set_deleted(true);
|
||||
}
|
||||
|
||||
|
||||
template <typename K>
|
||||
void
|
||||
remove_edge(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor u,
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor v,
|
||||
OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::edge_descriptor e = edge(u, v, sm);
|
||||
remove_edge(e,sm);
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
void
|
||||
remove_edge(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::edge_descriptor e,
|
||||
OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
sm.request_face_status();
|
||||
sm.request_vertex_status();
|
||||
sm.request_halfedge_status();
|
||||
sm.request_edge_status();
|
||||
|
||||
typedef typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor halfedge_descriptor;
|
||||
|
||||
halfedge_descriptor h1 = halfedge(e,sm);
|
||||
halfedge_descriptor h2 = opposite(halfedge(e,sm),sm);
|
||||
sm.status(sm.edge_handle(h1)).set_deleted(true);
|
||||
sm.status(h1).set_deleted(true);
|
||||
sm.status(h2).set_deleted(true);
|
||||
|
||||
}
|
||||
|
||||
|
||||
template <typename K>
|
||||
void
|
||||
remove_edge(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::edge_iterator eiter,
|
||||
OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
remove_edge(*eiter, sm);
|
||||
}
|
||||
|
||||
template<typename K>
|
||||
void
|
||||
remove_face(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::face_descriptor f,
|
||||
OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
|
||||
sm.request_face_status();
|
||||
sm.request_vertex_status();
|
||||
sm.request_halfedge_status();
|
||||
|
||||
set_halfedge(f, typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor(), sm);
|
||||
sm.status(f).set_deleted(true);
|
||||
}
|
||||
|
||||
#if 0 // conflits with function in Euler_operations.h
|
||||
template<typename K>
|
||||
std::pair<typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::edge_descriptor,
|
||||
bool>
|
||||
add_edge(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor v1,
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor v2,
|
||||
OpenMesh::TriMesh_ArrayKernelT<K>& sm) {
|
||||
|
||||
return sm.new_edge(v1, v2);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename K>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::face_descriptor
|
||||
add_face(OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return sm.new_face();
|
||||
}
|
||||
|
||||
template<typename K, typename InputIterator>
|
||||
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::face_descriptor
|
||||
add_face(InputIterator begin, InputIterator end, OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
typedef typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor vertex_descriptor;
|
||||
assert(begin!= end);
|
||||
vertex_descriptor u = *begin;
|
||||
++begin;
|
||||
assert(begin!= end);
|
||||
vertex_descriptor v = *begin;
|
||||
++begin;
|
||||
assert(begin!= end);
|
||||
vertex_descriptor w = *begin;
|
||||
|
||||
return sm.add_face(u,v,w);
|
||||
}
|
||||
|
||||
template<typename K>
|
||||
bool is_valid(OpenMesh::TriMesh_ArrayKernelT<K>& sm, bool /* verbose */ = false)
|
||||
{
|
||||
return CGAL::is_valid_polygon_mesh(sm);
|
||||
}
|
||||
|
||||
} // namespace OpenMesh
|
||||
|
||||
|
||||
#ifndef CGAL_NO_DEPRECATED_CODE
|
||||
#include <CGAL/boost/graph/backward_compatibility_functions.h>
|
||||
|
||||
namespace boost {
|
||||
// The following functions were defined in the namespace boost
|
||||
using OpenMesh::vertices;
|
||||
using OpenMesh::edges;
|
||||
using OpenMesh::num_vertices;
|
||||
using OpenMesh::num_edges;
|
||||
using OpenMesh::out_edges;
|
||||
using OpenMesh::in_edges;
|
||||
using OpenMesh::target;
|
||||
using OpenMesh::source;
|
||||
} // namespace boost
|
||||
#endif //CGAL_NO_DEPRECATED_CODE
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // CGAL_BOOST_GRAPH_TRAITS_TRIMESH_ARRAYKERNELT_H
|
||||
|
|
@ -196,7 +196,7 @@ adjust_incoming_halfedge(typename boost::graph_traits<Graph>::vertex_descriptor
|
|||
}
|
||||
do
|
||||
{
|
||||
if(is_border(h, g))
|
||||
if(face(h, g)==boost::graph_traits<Graph>::null_face())
|
||||
{
|
||||
set_halfedge(v, h, g);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -85,17 +85,17 @@ public:
|
|||
};
|
||||
|
||||
|
||||
template <typename K>
|
||||
template <typename OpenMesh>
|
||||
class OM_edge_weight_pmap
|
||||
: public boost::put_get_helper<typename OpenMesh::PolyMesh_ArrayKernelT<K>::Scalar , OM_edge_weight_pmap<K> >
|
||||
: public boost::put_get_helper<typename OpenMesh::Scalar , OM_edge_weight_pmap<OpenMesh> >
|
||||
{
|
||||
public:
|
||||
typedef boost::readable_property_map_tag category;
|
||||
typedef typename OpenMesh::PolyMesh_ArrayKernelT<K>::Scalar value_type;
|
||||
typedef typename OpenMesh::Scalar value_type;
|
||||
typedef value_type reference;
|
||||
typedef typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::edge_descriptor key_type;
|
||||
typedef typename boost::graph_traits<OpenMesh>::edge_descriptor key_type;
|
||||
|
||||
OM_edge_weight_pmap(const OpenMesh::PolyMesh_ArrayKernelT<K>& sm)
|
||||
OM_edge_weight_pmap(const OpenMesh& sm)
|
||||
: sm_(sm)
|
||||
{}
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
const OpenMesh::PolyMesh_ArrayKernelT<K>& sm_;
|
||||
const OpenMesh& sm_;
|
||||
};
|
||||
|
||||
template <typename K, typename VEF>
|
||||
|
|
@ -124,25 +124,25 @@ public:
|
|||
};
|
||||
|
||||
|
||||
template<typename K, typename P>
|
||||
class OM_point_pmap //: public boost::put_get_helper<bool, OM_point_pmap<K> >
|
||||
template<typename OpenMesh, typename P>
|
||||
class OM_point_pmap //: public boost::put_get_helper<bool, OM_point_pmap<OpenMesh> >
|
||||
{
|
||||
public:
|
||||
typedef boost::read_write_property_map_tag category;
|
||||
#if defined(CGAL_USE_OM_POINTS)
|
||||
typedef typename OpenMesh::PolyMesh_ArrayKernelT<K>::Point value_type;
|
||||
typedef const typename OpenMesh::PolyMesh_ArrayKernelT<K>::Point& reference;
|
||||
typedef typename OpenMesh::Point value_type;
|
||||
typedef const typename OpenMesh::Point& reference;
|
||||
#else
|
||||
typedef P value_type;
|
||||
typedef P reference;
|
||||
#endif
|
||||
typedef typename boost::graph_traits< OpenMesh::PolyMesh_ArrayKernelT<K> >::vertex_descriptor key_type;
|
||||
typedef typename boost::graph_traits<OpenMesh>::vertex_descriptor key_type;
|
||||
|
||||
OM_point_pmap()
|
||||
: sm_(NULL)
|
||||
{}
|
||||
|
||||
OM_point_pmap(const OpenMesh::PolyMesh_ArrayKernelT<K>& sm)
|
||||
OM_point_pmap(const OpenMesh& sm)
|
||||
: sm_(&sm)
|
||||
{}
|
||||
|
||||
|
|
@ -156,36 +156,36 @@ public:
|
|||
return sm_->point(v);
|
||||
#else
|
||||
CGAL_assertion(sm_!=NULL);
|
||||
typename OpenMesh::PolyMesh_ArrayKernelT<K>::Point const& omp = sm_->point(v);
|
||||
typename OpenMesh::Point const& omp = sm_->point(v);
|
||||
return value_type(omp[0], omp[1], omp[2]);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline friend reference get(const OM_point_pmap<K,P>& pm, key_type v)
|
||||
inline friend reference get(const OM_point_pmap<OpenMesh,P>& pm, key_type v)
|
||||
{
|
||||
CGAL_precondition(pm.sm_!=NULL);
|
||||
#if defined(CGAL_USE_OM_POINTS)
|
||||
return pm.sm_->point(v);
|
||||
#else
|
||||
CGAL_assertion(pm.sm_!=NULL);
|
||||
typename OpenMesh::PolyMesh_ArrayKernelT<K>::Point const& omp = pm.sm_->point(v);
|
||||
typename OpenMesh::Point const& omp = pm.sm_->point(v);
|
||||
return value_type(omp[0], omp[1], omp[2]);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline friend void put(const OM_point_pmap<K,P>& pm, key_type v, const value_type& p)
|
||||
inline friend void put(const OM_point_pmap<OpenMesh,P>& pm, key_type v, const value_type& p)
|
||||
{
|
||||
CGAL_precondition(pm.sm_!=NULL);
|
||||
#if defined(CGAL_USE_OM_POINTS)
|
||||
const_cast<OpenMesh::PolyMesh_ArrayKernelT<K>&>(*pm.sm_).set_point(v,p);
|
||||
const_cast<OpenMesh&>(*pm.sm_).set_point(v,p);
|
||||
#else
|
||||
const_cast<OpenMesh::PolyMesh_ArrayKernelT<K>&>(*pm.sm_).set_point
|
||||
(v, typename OpenMesh::PolyMesh_ArrayKernelT<K>::Point((float)p[0], (float)p[1], (float)p[2]));
|
||||
const_cast<OpenMesh&>(*pm.sm_).set_point
|
||||
(v, typename OpenMesh::Point((float)p[0], (float)p[1], (float)p[2]));
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
const OpenMesh::PolyMesh_ArrayKernelT<K>* sm_;
|
||||
const OpenMesh* sm_;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -202,8 +202,9 @@ namespace boost {
|
|||
template <typename K>
|
||||
struct property_map<OpenMesh::PolyMesh_ArrayKernelT<K>, boost::edge_weight_t >
|
||||
{
|
||||
typedef CGAL::OM_edge_weight_pmap<K> type;
|
||||
typedef CGAL::OM_edge_weight_pmap<K> const_type;
|
||||
typedef OpenMesh::PolyMesh_ArrayKernelT<K> Mesh;
|
||||
typedef CGAL::OM_edge_weight_pmap<Mesh> type;
|
||||
typedef CGAL::OM_edge_weight_pmap<Mesh> const_type;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -215,8 +216,9 @@ struct property_map<OpenMesh::PolyMesh_ArrayKernelT<K>, boost::edge_weight_t >
|
|||
template <typename K>
|
||||
struct property_map<OpenMesh::PolyMesh_ArrayKernelT<K>, boost::vertex_index_t >
|
||||
{
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::vertex_descriptor> type;
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::vertex_descriptor> const_type;
|
||||
typedef OpenMesh::PolyMesh_ArrayKernelT<K> Mesh;
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<Mesh>::vertex_descriptor> type;
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<Mesh>::vertex_descriptor> const_type;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -227,8 +229,9 @@ struct property_map<OpenMesh::PolyMesh_ArrayKernelT<K>, boost::vertex_index_t >
|
|||
template <typename K>
|
||||
struct property_map<OpenMesh::PolyMesh_ArrayKernelT<K>, boost::face_index_t >
|
||||
{
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::face_descriptor> type;
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::face_descriptor> const_type;
|
||||
typedef OpenMesh::PolyMesh_ArrayKernelT<K> Mesh;
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<Mesh>::face_descriptor> type;
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<Mesh>::face_descriptor> const_type;
|
||||
};
|
||||
|
||||
//
|
||||
|
|
@ -238,8 +241,9 @@ struct property_map<OpenMesh::PolyMesh_ArrayKernelT<K>, boost::face_index_t >
|
|||
template <typename K>
|
||||
struct property_map<OpenMesh::PolyMesh_ArrayKernelT<K>, boost::edge_index_t >
|
||||
{
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::edge_descriptor> type;
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::edge_descriptor> const_type;
|
||||
typedef OpenMesh::PolyMesh_ArrayKernelT<K> Mesh;
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<Mesh>::edge_descriptor> type;
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<Mesh>::edge_descriptor> const_type;
|
||||
};
|
||||
|
||||
//
|
||||
|
|
@ -249,8 +253,9 @@ struct property_map<OpenMesh::PolyMesh_ArrayKernelT<K>, boost::edge_index_t >
|
|||
template <typename K>
|
||||
struct property_map<OpenMesh::PolyMesh_ArrayKernelT<K>, boost::halfedge_index_t >
|
||||
{
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::halfedge_descriptor> type;
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::halfedge_descriptor> const_type;
|
||||
typedef OpenMesh::PolyMesh_ArrayKernelT<K> Mesh;
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<Mesh>::halfedge_descriptor> type;
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<Mesh>::halfedge_descriptor> const_type;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -258,7 +263,8 @@ template<typename K>
|
|||
struct property_map<OpenMesh::PolyMesh_ArrayKernelT<K>, boost::vertex_point_t >
|
||||
{
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel::Point_3 P;
|
||||
typedef CGAL::OM_point_pmap<K,P> type;
|
||||
typedef OpenMesh::PolyMesh_ArrayKernelT<K> Mesh;
|
||||
typedef CGAL::OM_point_pmap<Mesh, P> type;
|
||||
typedef type const_type;
|
||||
};
|
||||
|
||||
|
|
@ -271,7 +277,8 @@ template <typename K>
|
|||
typename boost::property_map<OpenMesh::PolyMesh_ArrayKernelT<K>, boost::edge_weight_t>::const_type
|
||||
get(boost::edge_weight_t, const OpenMesh::PolyMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return CGAL::OM_edge_weight_pmap<K>(sm);
|
||||
typedef OpenMesh::PolyMesh_ArrayKernelT<K> Mesh;
|
||||
return CGAL::OM_edge_weight_pmap<Mesh>(sm);
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
|
|
@ -279,7 +286,8 @@ typename OpenMesh::PolyMesh_ArrayKernelT<K>::Scalar
|
|||
get(boost::edge_weight_t, const OpenMesh::PolyMesh_ArrayKernelT<K>& sm,
|
||||
const typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::edge_descriptor& e)
|
||||
{
|
||||
return CGAL::OM_edge_weight_pmap<K>(sm)[e];
|
||||
typedef OpenMesh::PolyMesh_ArrayKernelT<K> Mesh;
|
||||
return CGAL::OM_edge_weight_pmap<Mesh>(sm)[e];
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -287,14 +295,16 @@ template <typename K>
|
|||
CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::vertex_descriptor>
|
||||
get(const boost::vertex_index_t&, const OpenMesh::PolyMesh_ArrayKernelT<K>&)
|
||||
{
|
||||
return CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::vertex_descriptor>();
|
||||
typedef OpenMesh::PolyMesh_ArrayKernelT<K> Mesh;
|
||||
return CGAL::OM_index_pmap<K, typename boost::graph_traits<Mesh>::vertex_descriptor>();
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
typename boost::property_map<OpenMesh::PolyMesh_ArrayKernelT<K>, boost::face_index_t>::const_type
|
||||
get(const boost::face_index_t&, const OpenMesh::PolyMesh_ArrayKernelT<K>&)
|
||||
{
|
||||
return CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::face_descriptor>();
|
||||
typedef OpenMesh::PolyMesh_ArrayKernelT<K> Mesh;
|
||||
return CGAL::OM_index_pmap<K, typename boost::graph_traits<Mesh>::face_descriptor>();
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
|
|
@ -312,11 +322,12 @@ get(const boost::halfedge_index_t&, const OpenMesh::PolyMesh_ArrayKernelT<K>&)
|
|||
}
|
||||
|
||||
template<typename K>
|
||||
CGAL::OM_point_pmap<K,typename CGAL::Exact_predicates_inexact_constructions_kernel::Point_3>
|
||||
CGAL::OM_point_pmap<OpenMesh::PolyMesh_ArrayKernelT<K>,
|
||||
typename CGAL::Exact_predicates_inexact_constructions_kernel::Point_3>
|
||||
get(boost::vertex_point_t, const OpenMesh::PolyMesh_ArrayKernelT<K>& g)
|
||||
{
|
||||
typedef typename CGAL::Exact_predicates_inexact_constructions_kernel::Point_3 P;
|
||||
return CGAL::OM_point_pmap<K,P>(g);
|
||||
return CGAL::OM_point_pmap<OpenMesh::PolyMesh_ArrayKernelT<K>, P>(g);
|
||||
}
|
||||
|
||||
// get for intrinsic properties
|
||||
|
|
|
|||
|
|
@ -0,0 +1,195 @@
|
|||
// Copyright (c) 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 Lesser General Public License as
|
||||
// published by the Free Software Foundation; either version 3 of the License,
|
||||
// or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s) : Philipp Möller
|
||||
|
||||
|
||||
#ifndef CGAL_PROPERTIES_TRIMESH_ARRAYKERNELT_H
|
||||
#define CGAL_PROPERTIES_TRIMESH_ARRAYKERNELT_H
|
||||
|
||||
#include <CGAL/assertions.h>
|
||||
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||
#include <CGAL/boost/graph/properties.h>
|
||||
#include <CGAL/boost/graph/properties_PolyMesh_ArrayKernelT.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
|
||||
// overloads and specializations in the boost namespace
|
||||
namespace boost {
|
||||
|
||||
//
|
||||
// edge_weight
|
||||
//
|
||||
template <typename K>
|
||||
struct property_map<OpenMesh::TriMesh_ArrayKernelT<K>, boost::edge_weight_t >
|
||||
{
|
||||
typedef OpenMesh::TriMesh_ArrayKernelT<K> Mesh;
|
||||
typedef CGAL::OM_edge_weight_pmap<Mesh> type;
|
||||
typedef CGAL::OM_edge_weight_pmap<Mesh> const_type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//
|
||||
// vertex_index
|
||||
//
|
||||
template <typename K>
|
||||
struct property_map<OpenMesh::TriMesh_ArrayKernelT<K>, boost::vertex_index_t >
|
||||
{
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor> type;
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor> const_type;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// face_index
|
||||
//
|
||||
|
||||
template <typename K>
|
||||
struct property_map<OpenMesh::TriMesh_ArrayKernelT<K>, boost::face_index_t >
|
||||
{
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::face_descriptor> type;
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::face_descriptor> const_type;
|
||||
};
|
||||
|
||||
//
|
||||
// edge_index
|
||||
//
|
||||
|
||||
template <typename K>
|
||||
struct property_map<OpenMesh::TriMesh_ArrayKernelT<K>, boost::edge_index_t >
|
||||
{
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::edge_descriptor> type;
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::edge_descriptor> const_type;
|
||||
};
|
||||
|
||||
//
|
||||
// halfedge_index
|
||||
//
|
||||
|
||||
template <typename K>
|
||||
struct property_map<OpenMesh::TriMesh_ArrayKernelT<K>, boost::halfedge_index_t >
|
||||
{
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor> type;
|
||||
typedef CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor> const_type;
|
||||
};
|
||||
|
||||
|
||||
template<typename K>
|
||||
struct property_map<OpenMesh::TriMesh_ArrayKernelT<K>, boost::vertex_point_t >
|
||||
{
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel::Point_3 P;
|
||||
typedef OpenMesh::TriMesh_ArrayKernelT<K> Mesh;
|
||||
typedef CGAL::OM_point_pmap<Mesh,P> type;
|
||||
typedef type const_type;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
namespace boost {
|
||||
|
||||
|
||||
template <typename K>
|
||||
typename boost::property_map<OpenMesh::TriMesh_ArrayKernelT<K>, boost::edge_weight_t>::const_type
|
||||
get(boost::edge_weight_t, const OpenMesh::TriMesh_ArrayKernelT<K>& sm)
|
||||
{
|
||||
return CGAL::OM_edge_weight_pmap<K>(sm);
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
typename OpenMesh::TriMesh_ArrayKernelT<K>::Scalar
|
||||
get(boost::edge_weight_t, const OpenMesh::TriMesh_ArrayKernelT<K>& sm,
|
||||
const typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::edge_descriptor& e)
|
||||
{
|
||||
return CGAL::OM_edge_weight_pmap<K>(sm)[e];
|
||||
}
|
||||
|
||||
|
||||
template <typename K>
|
||||
CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor>
|
||||
get(const boost::vertex_index_t&, const OpenMesh::TriMesh_ArrayKernelT<K>&)
|
||||
{
|
||||
return CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor>();
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
typename boost::property_map<OpenMesh::TriMesh_ArrayKernelT<K>, boost::face_index_t>::const_type
|
||||
get(const boost::face_index_t&, const OpenMesh::TriMesh_ArrayKernelT<K>&)
|
||||
{
|
||||
return CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::face_descriptor>();
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::edge_descriptor>
|
||||
get(const boost::edge_index_t&, const OpenMesh::TriMesh_ArrayKernelT<K>&)
|
||||
{
|
||||
return CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::edge_descriptor>();
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor>
|
||||
get(const boost::halfedge_index_t&, const OpenMesh::TriMesh_ArrayKernelT<K>&)
|
||||
{
|
||||
return CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::halfedge_descriptor>();
|
||||
}
|
||||
|
||||
template<typename K>
|
||||
CGAL::OM_point_pmap<OpenMesh::TriMesh_ArrayKernelT<K>,
|
||||
typename CGAL::Exact_predicates_inexact_constructions_kernel::Point_3>
|
||||
get(boost::vertex_point_t, const OpenMesh::TriMesh_ArrayKernelT<K>& g)
|
||||
{
|
||||
typedef typename CGAL::Exact_predicates_inexact_constructions_kernel::Point_3 P;
|
||||
typedef OpenMesh::TriMesh_ArrayKernelT<K> Mesh;
|
||||
return CGAL::OM_point_pmap<Mesh, P>(g);
|
||||
}
|
||||
|
||||
// get for intrinsic properties
|
||||
#define CGAL_OM_INTRINSIC_PROPERTY(RET, PROP, TYPE) \
|
||||
template<typename K> \
|
||||
RET \
|
||||
get(PROP p, const OpenMesh::TriMesh_ArrayKernelT<K>& sm, \
|
||||
typename boost::graph_traits< OpenMesh::TriMesh_ArrayKernelT<K> >::TYPE x) \
|
||||
{ return get(get(p, sm), x); } \
|
||||
|
||||
CGAL_OM_INTRINSIC_PROPERTY(int, boost::vertex_index_t, vertex_descriptor)
|
||||
CGAL_OM_INTRINSIC_PROPERTY(int, boost::edge_index_t, edge_descriptor)
|
||||
CGAL_OM_INTRINSIC_PROPERTY(int, boost::halfedge_index_t, halfedge_descriptor)
|
||||
CGAL_OM_INTRINSIC_PROPERTY(int, boost::face_index_t, face_descriptor)
|
||||
// CGAL_OM_INTRINSIC_PROPERTY(std::size_t, boost::halfedge_index_t, face_descriptor)
|
||||
CGAL_OM_INTRINSIC_PROPERTY(typename CGAL::Exact_predicates_inexact_constructions_kernel::Point_3, boost::vertex_point_t, vertex_descriptor)
|
||||
|
||||
#undef CGAL_OM_INTRINSIC_PROPERTY
|
||||
|
||||
// put for intrinsic properties
|
||||
// only available for vertex_point
|
||||
|
||||
template<typename K>
|
||||
void
|
||||
put(boost::vertex_point_t p, OpenMesh::TriMesh_ArrayKernelT<K>& g,
|
||||
typename boost::graph_traits< OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_descriptor vd,
|
||||
const typename K::Point& point)
|
||||
{
|
||||
put(get(p,g), vd, point);
|
||||
}
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
|
||||
#endif /* CGAL_PROPERTIES_TRIMESH_ARRAYKERNELT_H */
|
||||
|
|
@ -0,0 +1,694 @@
|
|||
// Copyright (c) 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 Lesser General Public License as
|
||||
// published by the Free Software Foundation; either version 3 of the License,
|
||||
// or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s) : Jane Tournois
|
||||
|
||||
#ifndef CGAL_BOOST_GRAPH_VISITOR_H
|
||||
#define CGAL_BOOST_GRAPH_VISITOR_H
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template<typename V, typename Graph>
|
||||
struct graph_traits<
|
||||
boost::tuple<boost::reference_wrapper<V>, boost::reference_wrapper<Graph> > >
|
||||
: boost::graph_traits< Graph >
|
||||
{
|
||||
typedef boost::graph_traits<Graph> Base;
|
||||
typedef typename Base::vertex_property_type vertex_property_type;
|
||||
};
|
||||
|
||||
template<typename V, typename Graph>
|
||||
struct graph_traits<
|
||||
boost::tuple<boost::reference_wrapper<V>, boost::reference_wrapper<Graph> > const >
|
||||
: boost::graph_traits< Graph >
|
||||
{};
|
||||
|
||||
template<typename V, typename Graph, class PropertyTag>
|
||||
struct property_map<
|
||||
boost::tuple<boost::reference_wrapper<V>, boost::reference_wrapper<Graph> >,
|
||||
PropertyTag>
|
||||
: public property_map<Graph, PropertyTag>
|
||||
{};
|
||||
|
||||
template<typename V, typename Graph, class PropertyTag>
|
||||
struct property_map<
|
||||
const boost::tuple<boost::reference_wrapper<V>, boost::reference_wrapper<Graph> >,
|
||||
PropertyTag>
|
||||
: public property_map<Graph, PropertyTag>
|
||||
{};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
namespace CGAL
|
||||
{
|
||||
template<typename V, typename Graph>
|
||||
boost::tuple<boost::reference_wrapper<V>,
|
||||
boost::reference_wrapper<Graph> >
|
||||
make_graph_with_visitor(V& v, Graph& g)
|
||||
{
|
||||
return boost::make_tuple(boost::ref(v), boost::ref(g));
|
||||
}
|
||||
|
||||
template<typename Graph>
|
||||
class Visitor_base
|
||||
{
|
||||
public:
|
||||
typedef typename boost::graph_traits<Graph> gt;
|
||||
typedef typename gt::halfedge_descriptor halfedge_descriptor;
|
||||
typedef typename gt::edge_descriptor edge_descriptor;
|
||||
typedef typename gt::vertex_descriptor vertex_descriptor;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
//// OVERLOADS FOR Visitor
|
||||
|
||||
template<typename Graph>
|
||||
void num_vertices(Visitor_base<Graph>& w)
|
||||
{}
|
||||
template<typename Graph>
|
||||
void num_edges(Visitor_base<Graph>& w)
|
||||
{}
|
||||
template<typename Graph>
|
||||
void degree(typename boost::graph_traits<Graph>::vertex_descriptor v
|
||||
, const Visitor_base<Graph>& w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void out_degree(typename boost::graph_traits<Graph>::vertex_descriptor v
|
||||
, const Visitor_base<Graph>& w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void in_degree(typename boost::graph_traits<Graph>::vertex_descriptor v
|
||||
, const Visitor_base<Graph>& w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void source(typename boost::graph_traits<Graph>::edge_descriptor e
|
||||
, const Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void target(typename boost::graph_traits<Graph>::edge_descriptor e
|
||||
, const Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void edge(typename boost::graph_traits<Graph>::vertex_descriptor u
|
||||
, typename boost::graph_traits<Graph>::vertex_descriptor v
|
||||
, const Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
inline void vertices(const Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
inline void edges(const Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
inline void in_edges(typename boost::graph_traits<Graph>::vertex_descriptor u
|
||||
, const Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
inline void out_edges(typename boost::graph_traits<Graph>::vertex_descriptor u
|
||||
, const Visitor_base<Graph> & w)
|
||||
{}
|
||||
|
||||
//
|
||||
// MutableHalfedgeGraph
|
||||
//
|
||||
template <class Graph>
|
||||
void add_vertex(Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void add_vertex(const typename boost::graph_traits<Graph >::vertex_property_type& p
|
||||
, Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void remove_vertex(typename boost::graph_traits< Graph >::vertex_descriptor v
|
||||
, Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void add_edge(Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void remove_edge(typename boost::graph_traits< Graph >::edge_descriptor e
|
||||
, Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void set_target(typename boost::graph_traits< Graph >::halfedge_descriptor h1
|
||||
, typename boost::graph_traits< Graph >::vertex_descriptor v
|
||||
, Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void set_next(typename boost::graph_traits< Graph >::halfedge_descriptor h1
|
||||
, typename boost::graph_traits< Graph >::halfedge_descriptor h2
|
||||
, Visitor_base<Graph> & w)
|
||||
{}
|
||||
|
||||
//
|
||||
// MutableFaceGraph
|
||||
//
|
||||
template <class Graph>
|
||||
void add_face(Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class InputIterator, class Graph>
|
||||
void add_face(InputIterator begin, InputIterator end,
|
||||
Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void remove_face(typename boost::graph_traits< Graph >::face_descriptor f
|
||||
, Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void set_face(typename boost::graph_traits< Graph >::halfedge_descriptor h
|
||||
, typename boost::graph_traits< Graph >::face_descriptor f
|
||||
, const Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void set_halfedge(typename boost::graph_traits< Graph >::face_descriptor f
|
||||
, typename boost::graph_traits< Graph >::halfedge_descriptor h
|
||||
, Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void set_halfedge(typename boost::graph_traits< Graph >::vertex_descriptor v
|
||||
, typename boost::graph_traits< Graph >::halfedge_descriptor h
|
||||
, const Visitor_base<Graph> & w)
|
||||
{}
|
||||
|
||||
//
|
||||
// HalfedgeGraph
|
||||
//
|
||||
template <class Graph>
|
||||
void edge(typename boost::graph_traits< Graph >::halfedge_descriptor h
|
||||
, const Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void halfedge(typename boost::graph_traits< Graph >::edge_descriptor e
|
||||
, const Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void halfedge(typename boost::graph_traits< Graph >::vertex_descriptor v
|
||||
, const Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void halfedge(typename boost::graph_traits< Graph >::vertex_descriptor u
|
||||
, typename boost::graph_traits< Graph >::vertex_descriptor v
|
||||
, const Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void opposite(typename boost::graph_traits< Graph >::halfedge_descriptor h
|
||||
, const Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void source(typename boost::graph_traits< Graph >::halfedge_descriptor h
|
||||
, const Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void target(typename boost::graph_traits< Graph >::halfedge_descriptor h
|
||||
, const Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void next(typename boost::graph_traits< Graph >::halfedge_descriptor outedge
|
||||
, const Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void prev(typename boost::graph_traits< Graph >::halfedge_descriptor outedge
|
||||
, const Visitor_base<Graph> & w)
|
||||
{}
|
||||
|
||||
//
|
||||
// HalfedgeListGraph
|
||||
//
|
||||
template <class Graph>
|
||||
void halfedges(const Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void num_halfedges(const Visitor_base<Graph> & w)
|
||||
{}
|
||||
|
||||
// Graph
|
||||
template <class Graph>
|
||||
void face(typename boost::graph_traits< Graph >::halfedge_descriptor h
|
||||
, const Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void halfedge(typename boost::graph_traits< Graph >::face_descriptor f
|
||||
, const Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void faces(const Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void num_faces(const Visitor_base<Graph> & w)
|
||||
{}
|
||||
template <class Graph>
|
||||
void is_valid(const Visitor_base<Graph> & w, bool verbose = false)
|
||||
{}
|
||||
template <class Graph, class PropertyTag>
|
||||
void get(PropertyTag ptag, const Visitor_base<Graph>& w)
|
||||
{}
|
||||
|
||||
|
||||
//// OVERLOADS FOR TUPLE<Visitor, Graph>
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits<Graph>::vertices_size_type
|
||||
num_vertices(const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
num_vertices(boost::unwrap_ref(w.get<0>()));
|
||||
return num_vertices(boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits<Graph>::edges_size_type
|
||||
num_edges(const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
num_edges(boost::unwrap_ref(w.get<0>()));
|
||||
return num_edges(boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits<Graph>::degree_size_type
|
||||
degree(typename boost::graph_traits<Graph>::vertex_descriptor v
|
||||
, const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
degree(v, boost::unwrap_ref(w.get<0>()));
|
||||
return degree(v, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits<Graph>::degree_size_type
|
||||
out_degree(typename boost::graph_traits<Graph>::vertex_descriptor v
|
||||
, const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
out_degree(v, boost::unwrap_ref(w.get<0>()));
|
||||
return out_degree(v, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits<Graph>::degree_size_type
|
||||
in_degree(typename boost::graph_traits<Graph>::vertex_descriptor v
|
||||
, const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
in_degree(v, boost::unwrap_ref(w.get<0>()));
|
||||
return in_degree(v, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits<Graph>::vertex_descriptor
|
||||
source(typename boost::graph_traits<Graph>::edge_descriptor e
|
||||
, const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> > & w)
|
||||
{
|
||||
source(e, boost::unwrap_ref(w.get<0>()));
|
||||
return source(e, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits<Graph>::vertex_descriptor
|
||||
target(typename boost::graph_traits<Graph>::edge_descriptor e
|
||||
, const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> > & w)
|
||||
{
|
||||
target(e, boost::unwrap_ref(w.get<0>()));
|
||||
return target(e, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
std::pair<typename boost::graph_traits<Graph>::edge_descriptor, bool>
|
||||
edge(typename boost::graph_traits<Graph>::vertex_descriptor u
|
||||
, typename boost::graph_traits<Graph>::vertex_descriptor v
|
||||
, const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> > & w)
|
||||
{
|
||||
edge(u, v, boost::unwrap_ref(w.get<0>()));
|
||||
return edge(u, v, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
inline CGAL::Iterator_range<typename boost::graph_traits<Graph>::vertex_iterator>
|
||||
vertices(const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
vertices(boost::unwrap_ref(w.get<0>()));
|
||||
return vertices(boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
inline CGAL::Iterator_range<typename boost::graph_traits<Graph>::edge_iterator>
|
||||
edges(const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
edges(boost::unwrap_ref(w.get<0>()));
|
||||
return edges(boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
inline CGAL::Iterator_range<typename boost::graph_traits<Graph>::in_edge_iterator>
|
||||
in_edges(typename boost::graph_traits<Graph>::vertex_descriptor u
|
||||
, const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
in_edges(u, boost::unwrap_ref(w.get<0>()));
|
||||
return in_edges(u, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
inline CGAL::Iterator_range<typename boost::graph_traits<Graph>::out_edge_iterator>
|
||||
out_edges(typename boost::graph_traits<Graph>::vertex_descriptor u
|
||||
, const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
out_edges(u, boost::unwrap_ref(w.get<0>()));
|
||||
return out_edges(u, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
//
|
||||
// MutableHalfedgeGraph
|
||||
//
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits< Graph >::vertex_descriptor
|
||||
add_vertex(boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
add_vertex(boost::unwrap_ref(w.get<0>()));
|
||||
return add_vertex(boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits< Graph >::vertex_descriptor
|
||||
add_vertex(const typename boost::graph_traits<Graph >::vertex_property_type& p
|
||||
, boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
add_vertex(p, boost::unwrap_ref(w.get<0>()));
|
||||
return add_vertex(p, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
void
|
||||
remove_vertex(typename boost::graph_traits< Graph >::vertex_descriptor v
|
||||
, boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
remove_vertex(v, boost::unwrap_ref(w.get<0>()));
|
||||
remove_vertex(v, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits< Graph >::edge_descriptor
|
||||
add_edge(boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
add_edge(boost::unwrap_ref(w.get<0>()));
|
||||
return add_edge(boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
void
|
||||
remove_edge(typename boost::graph_traits< Graph >::edge_descriptor e
|
||||
, boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
remove_edge(e, boost::unwrap_ref(w.get<0>()));
|
||||
remove_edge(e, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
void
|
||||
set_target(typename boost::graph_traits< Graph >::halfedge_descriptor h1
|
||||
, typename boost::graph_traits< Graph >::vertex_descriptor v
|
||||
, boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
set_target(h1, v, boost::unwrap_ref(w.get<0>()));
|
||||
set_target(h1, v, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
void
|
||||
set_next(typename boost::graph_traits< Graph >::halfedge_descriptor h1
|
||||
, typename boost::graph_traits< Graph >::halfedge_descriptor h2
|
||||
, boost::tuple<boost::reference_wrapper<Visitor >,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
set_next(h1, h2, boost::unwrap_ref(w.get<0>()));
|
||||
set_next(h1, h2, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
//
|
||||
// MutableFaceGraph
|
||||
//
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits< Graph >::face_descriptor
|
||||
add_face(boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
add_face(boost::unwrap_ref(w.get<0>()));
|
||||
return add_face(boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class InputIterator, class Graph, class Visitor>
|
||||
typename boost::graph_traits< Graph >::face_descriptor
|
||||
add_face(InputIterator begin,
|
||||
InputIterator end,
|
||||
boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
add_face(begin, end, boost::unwrap_ref(w.get<0>()));
|
||||
return add_face(begin, end, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
void
|
||||
remove_face(typename boost::graph_traits< Graph >::face_descriptor f
|
||||
, boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
remove_face(f, boost::unwrap_ref(w.get<0>()));
|
||||
return remove_face(f, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
void
|
||||
set_face(typename boost::graph_traits< Graph >::halfedge_descriptor h
|
||||
, typename boost::graph_traits< Graph >::face_descriptor f
|
||||
, const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
set_face(h, f, boost::unwrap_ref(w.get<0>()));
|
||||
set_face(h, f, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
void
|
||||
set_halfedge(typename boost::graph_traits< Graph >::face_descriptor f
|
||||
, typename boost::graph_traits< Graph >::halfedge_descriptor h
|
||||
, boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
set_halfedge(f, h, boost::unwrap_ref(w.get<0>()));
|
||||
set_halfedge(f, h, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
void
|
||||
set_halfedge(typename boost::graph_traits< Graph >::vertex_descriptor v
|
||||
, typename boost::graph_traits< Graph >::halfedge_descriptor h
|
||||
, const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
set_halfedge(v, h, boost::unwrap_ref(w.get<0>()));
|
||||
set_halfedge(v, h, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
//
|
||||
// HalfedgeGraph
|
||||
//
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits< Graph >::edge_descriptor
|
||||
edge(typename boost::graph_traits< Graph >::halfedge_descriptor h
|
||||
, const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
edge(h, boost::unwrap_ref(w.get<0>()));
|
||||
return edge(h, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits< Graph >::halfedge_descriptor
|
||||
halfedge(typename boost::graph_traits< Graph >::edge_descriptor e
|
||||
, const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
halfedge(e, boost::unwrap_ref(w.get<0>()));
|
||||
return halfedge(e, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits< Graph >::halfedge_descriptor
|
||||
halfedge(typename boost::graph_traits< Graph >::vertex_descriptor v
|
||||
, const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
halfedge(v, boost::unwrap_ref(w.get<0>()));
|
||||
return halfedge(v, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
std::pair< typename boost::graph_traits< Graph >::halfedge_descriptor
|
||||
, bool>
|
||||
halfedge(typename boost::graph_traits< Graph >::vertex_descriptor u
|
||||
, typename boost::graph_traits< Graph >::vertex_descriptor v
|
||||
, const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
halfedge(u, v, boost::unwrap_ref(w.get<0>()));
|
||||
return halfedge(u, v, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits< Graph >::halfedge_descriptor
|
||||
opposite(typename boost::graph_traits< Graph >::halfedge_descriptor h
|
||||
, const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
opposite(h, boost::unwrap_ref(w.get<0>()));
|
||||
return opposite(h, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits< Graph >::vertex_descriptor
|
||||
source(typename boost::graph_traits< Graph >::halfedge_descriptor h
|
||||
, const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
source(h, boost::unwrap_ref(w.get<0>()));
|
||||
return source(h, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits< Graph >::vertex_descriptor
|
||||
target(typename boost::graph_traits< Graph >::halfedge_descriptor h
|
||||
, const boost::tuple<boost::reference_wrapper<Visitor>, boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
target(h, boost::unwrap_ref(w.get<0>()));
|
||||
return target(h, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits< Graph >::halfedge_descriptor
|
||||
next(typename boost::graph_traits< Graph >::halfedge_descriptor outedge
|
||||
, const boost::tuple<boost::reference_wrapper<Visitor>, boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
next(outedge, boost::unwrap_ref(w.get<0>()));
|
||||
return next(outedge, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits< Graph >::halfedge_descriptor
|
||||
prev(typename boost::graph_traits< Graph >::halfedge_descriptor outedge
|
||||
, const boost::tuple<boost::reference_wrapper<Visitor>, boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
prev(outedge, boost::unwrap_ref(w.get<0>()));
|
||||
return prev(outedge, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
//
|
||||
// HalfedgeListGraph
|
||||
//
|
||||
template <class Graph, class Visitor>
|
||||
CGAL::Iterator_range<typename boost::graph_traits< Graph >::halfedge_iterator>
|
||||
halfedges(const boost::tuple<boost::reference_wrapper<Visitor>, boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
halfedges(boost::unwrap_ref(w.get<0>()));
|
||||
return halfedges(boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits< Graph >::halfedges_size_type
|
||||
num_halfedges(const boost::tuple<boost::reference_wrapper<Visitor>, boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
num_halfedges(boost::unwrap_ref(w.get<0>()));
|
||||
return num_halfedges(boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
// Graph
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits< Graph >::face_descriptor
|
||||
face(typename boost::graph_traits< Graph >::halfedge_descriptor h
|
||||
, const boost::tuple<boost::reference_wrapper<Visitor>, boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
face(h, boost::unwrap_ref(w.get<0>()));
|
||||
return face(h, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits< Graph >::halfedge_descriptor
|
||||
halfedge(typename boost::graph_traits< Graph >::face_descriptor f
|
||||
, const boost::tuple<boost::reference_wrapper<Visitor>, boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
halfedge(f, boost::unwrap_ref(w.get<0>()));
|
||||
return halfedge(f, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
inline CGAL::Iterator_range<typename boost::graph_traits<Graph>::face_iterator >
|
||||
faces(const boost::tuple<boost::reference_wrapper<Visitor>, boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
faces(boost::unwrap_ref(w.get<0>()));
|
||||
return faces(boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
typename boost::graph_traits<Graph>::faces_size_type
|
||||
num_faces(const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
num_faces(boost::unwrap_ref(w.get<0>()));
|
||||
return num_faces(boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
template <class Graph, class Visitor>
|
||||
bool is_valid(const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w
|
||||
, bool verbose = false)
|
||||
{
|
||||
is_valid(boost::unwrap_ref(w.get<0>()), verbose);
|
||||
return is_valid(boost::unwrap_ref(w.get<1>()), verbose);
|
||||
}
|
||||
|
||||
template <class Graph, class PropertyTag, class Visitor>
|
||||
typename boost::property_map< Graph, PropertyTag >::type
|
||||
get(PropertyTag ptag,
|
||||
const boost::tuple<boost::reference_wrapper<Visitor>,
|
||||
boost::reference_wrapper<Graph> >& w)
|
||||
{
|
||||
get(ptag, boost::unwrap_ref(w.get<0>()));
|
||||
return get(ptag, boost::unwrap_ref(w.get<1>()));
|
||||
}
|
||||
|
||||
}//end namespace CGAL
|
||||
|
||||
#endif //CGAL_BOOST_GRAPH_VISITOR_H
|
||||
|
|
@ -2597,6 +2597,15 @@ pages = "207--221"
|
|||
publisher={CRC press}
|
||||
}
|
||||
|
||||
@inproceedings{botsch2004remeshing,
|
||||
title={A remeshing approach to multiresolution modeling},
|
||||
author={M. Botsch and L. Kobbelt},
|
||||
booktitle={Proceedings of the 2004 Eurographics/ACM SIGGRAPH symposium on Geometry processing},
|
||||
pages={185--192},
|
||||
year={2004},
|
||||
organization={ACM}
|
||||
}
|
||||
|
||||
@inproceedings{liepa2003filling,
|
||||
title={Filling holes in meshes},
|
||||
author={P. Liepa},
|
||||
|
|
|
|||
|
|
@ -156,12 +156,20 @@ and <code>src/</code> directories).
|
|||
<h3>2D Arrangements</h3>
|
||||
<ul>
|
||||
<li>Speed up the edge removal in case the incident faces contains many holes.</li>
|
||||
<ul>
|
||||
</ul>
|
||||
<!-- Triangulations and Delaunay Triangulations -->
|
||||
<!-- Voronoi Diagrams -->
|
||||
<!-- Mesh Generation -->
|
||||
<!-- Surface Reconstruction -->
|
||||
<!-- Geometry Processing -->
|
||||
<h3>Polygon Mesh Processing</h3>
|
||||
<ul>
|
||||
<li>Add a new triangle-based isotropic remeshing algorithm for
|
||||
triangulated surface meshes,
|
||||
<code>CGAL::Polygon_mesh_processing::isotropic_remeshing()</code>
|
||||
and a helper function for isotropic remeshing :
|
||||
<code>CGAL::Polygon_mesh_processing::split_long_edges()</code></li>
|
||||
</ul>
|
||||
<h3>Surface Mesh Parameterization</h3>
|
||||
<ul>
|
||||
<li><code>LSCM_parameterizer_3</code> now uses by default Eigen
|
||||
|
|
|
|||
|
|
@ -112,15 +112,6 @@ typename CGAL::Kernel_traits<
|
|||
\endcode
|
||||
\cgalNPEnd
|
||||
|
||||
\cgalNPBegin{edge_is_constrained_map} \anchor PMP_edge_is_constrained_map
|
||||
the property map containing information about edges of the input polygon mesh being constrained or not.\n
|
||||
\b Type: a class model of `ReadablePropertyMap` with
|
||||
`boost::graph_traits<PolygonMesh>::%edge_descriptor` as key type and
|
||||
`bool` as value type. It should be default - constructible.\n
|
||||
\b Default: if this parameter is omitted,
|
||||
a default property map where no edge is constrained is provided.
|
||||
\cgalNPEnd
|
||||
|
||||
\cgalNPBegin{face_index_map} \anchor PMP_face_index_map
|
||||
the property map containing the index of each face of the input polygon mesh.\n
|
||||
\b Type: a class model of `ReadablePropertyMap` with
|
||||
|
|
@ -137,6 +128,31 @@ a default property map where no edge is constrained is provided.
|
|||
\b Default value is \code boost::get(CGAL::vertex_index, pmesh)\endcode
|
||||
\cgalNPEnd
|
||||
|
||||
\cgalNPBegin{ number_of_iterations } \anchor PMP_number_of_iterations
|
||||
the number of iterations of the sequence of iterations performed by the isotropic remeshing
|
||||
algorithm.\n
|
||||
\b Type : \c unsigned \c int \n
|
||||
\b Default value is `1`
|
||||
\cgalNPEnd
|
||||
|
||||
\cgalNPBegin{ edge_is_constrained_map } \anchor PMP_edge_is_constrained_map
|
||||
the property map containing information about edges of the input polygon mesh being constrained or not.\n
|
||||
\b Type : a class model of `ReadablePropertyMap` with
|
||||
`boost::graph_traits<PolygonMesh>::%edge_descriptor` as key type and
|
||||
`bool` as value type.It should be default - constructible.\n
|
||||
\b Default : if this parameter is omitted,
|
||||
a default property map where no edge is constrained is provided.
|
||||
\cgalNPEnd
|
||||
|
||||
\cgalNPBegin{protect_constraints} \anchor PMP_protect_constraints
|
||||
enables the protection of constraints listed by \ref PMP_edge_is_constrained_map "edge_is_constrained_map"
|
||||
during isotropic remeshing. If `true`, constraint edges cannot be modified at all
|
||||
during the remeshing process.\n
|
||||
\b Type : boolean \n
|
||||
\b Default value is `false`
|
||||
\cgalNPEnd
|
||||
|
||||
|
||||
\cgalNPTableEnd
|
||||
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@
|
|||
/// path are not marked as constrained.
|
||||
///
|
||||
/// \ingroup PkgPolygonMeshProcessing
|
||||
/// \defgroup remeshing_grp Isotropic remeshing
|
||||
/// \ingroup PkgPolygonMeshProcessing
|
||||
/// \defgroup reverse_face_orientations_grp CGAL::reverse_face_orientations()
|
||||
|
||||
|
||||
/// \defgroup hole_filling_grp Hole Filling
|
||||
|
|
@ -72,6 +75,8 @@ and provides a list of the parameters that are used in this package.
|
|||
- `CGAL::Polygon_mesh_processing::fair()`
|
||||
- `CGAL::Polygon_mesh_processing::refine()`
|
||||
- `CGAL::Polygon_mesh_processing::triangulate_faces()`
|
||||
- \link remeshing_grp `CGAL::Polygon_mesh_processing::isotropic_remeshing()` \endlink
|
||||
- \link remeshing_grp `CGAL::Polygon_mesh_processing::split_long_edges()` \endlink
|
||||
|
||||
## Hole Filling Functions ##
|
||||
- `CGAL::Polygon_mesh_processing::triangulate_hole()`
|
||||
|
|
@ -86,15 +91,13 @@ and provides a list of the parameters that are used in this package.
|
|||
|
||||
## Orientation Functions ##
|
||||
- `CGAL::Polygon_mesh_processing::is_outward_oriented()`
|
||||
- `CGAL::Polygon_mesh_processing::reverse_face_orientations()`
|
||||
- \link reverse_face_orientations_grp `CGAL::Polygon_mesh_processing::reverse_face_orientations()` \endlink
|
||||
- `CGAL::Polygon_mesh_processing::orient_polygon_soup()`
|
||||
|
||||
## Combinatorial Repairing Functions ##
|
||||
- \link PMP_repairing_grp `CGAL::Polygon_mesh_processing::stitch_borders()` \endlink
|
||||
- `CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh()`
|
||||
- `CGAL::Polygon_mesh_processing::orient_polygon_soup()`
|
||||
<!---
|
||||
- \link reverse_face_orientations_grp `CGAL::Polygon_mesh_processing::remove_degenerate_faces()` \endlink
|
||||
--->
|
||||
|
||||
## Normal Computation Functions ##
|
||||
- `CGAL::Polygon_mesh_processing::compute_face_normal()`
|
||||
- `CGAL::Polygon_mesh_processing::compute_face_normals()`
|
||||
|
|
@ -122,4 +125,5 @@ It can be made short to PM. And TriangleMesh (or TM) specifies when the paramete
|
|||
\todo document BGL/include/CGAL/boost/graph/Dual.h and remove the example from dont_submit
|
||||
\todo fix and restore remove_degenerate_faces in the user and the reference manual
|
||||
\todo publish `is_polygon_soup_a_polygon_mesh` defined in `polygon_soup_to_polygon_mesh.h`
|
||||
\todo publish `triangulate_face`. Can be helpful as a preprocessing for isotropic_remeshing
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ BGL \ref namedparameters are used to deal with optional parameters.
|
|||
\subsection PMPOutline Outline
|
||||
The algorithms described in this manual are organized in sections.
|
||||
Section 2 describes \ref PMPMeshing algorithms, including triangulation of non-triangulated
|
||||
meshes, refinement and optimization by fairing of triangulated surface meshes.
|
||||
meshes, refinement, optimization by fairing, and isotropic remeshing of triangulated surface meshes.
|
||||
Section 3 lists the available, \ref PMPHoleFilling algorithms, which can possibly be combined with refinement and fairing.
|
||||
Section 4 gives a list of \ref PMPPredicates that can be evaluated on the processed polygon
|
||||
mesh, including point location and self intersection tests.
|
||||
|
|
@ -70,9 +70,11 @@ The visual results of aforementioned steps are depicted by \cgalFigureRef{Mech_s
|
|||
|
||||
\subsection MeshingAPI API
|
||||
|
||||
Refinement and fairing functions can be applied to an arbitrary region on a polygon mesh, using :
|
||||
- `CGAL::Polygon_mesh_processing::refine()` : given a range of facets on a mesh, refines the region.
|
||||
- `CGAL::Polygon_mesh_processing::fair()` : given a range of vertices on a mesh, fairs the region.
|
||||
\subsubsection Meshing
|
||||
|
||||
Refinement and fairing functions can be applied to an arbitrary region on a mesh, using :
|
||||
- `CGAL::Polygon_mesh_processing::refine()` : given a set of facets on a mesh, refines the region.
|
||||
- `CGAL::Polygon_mesh_processing::fair()` : given a set of vertices on a mesh, fairs the region.
|
||||
|
||||
Fairing needs a sparse linear solver and we recommend the use of \ref thirdpartyEigen 3.2 or later.
|
||||
Note that fairing might fail if fixed vertices, which are used as boundary conditions, do
|
||||
|
|
@ -91,6 +93,35 @@ This choice is made because the constrained Delaunay triangulation
|
|||
is the triangulation that, given the edges of the face to be triangulated,
|
||||
maximizes the minimum angle of all the angles of the triangles in the triangulation.
|
||||
|
||||
\subsubsection Remeshing
|
||||
|
||||
The incremental triangle-based isotropic remeshing algorithm introduced by Botsch et al
|
||||
\cgalCite{botsch2004remeshing}, \cgalCite{botsch2010PMP} is implemented in this package.
|
||||
This algorithm incrementally performs simple operations such as edge splits, edge collapses,
|
||||
edge flips, and Laplacian smoothing. All the vertices of the remeshed patch are reprojected
|
||||
to the original surface to keep a good approximation of the input.
|
||||
|
||||
A triangulated region of a polygon mesh can be remeshed using the function
|
||||
`CGAL::Polygon_mesh_processing::isotropic_remeshing()`, as illustrated
|
||||
by \cgalFigureRef{iso_remeshing}. The algorithm has only two parameters :
|
||||
the target edge length for the remeshed surface patch, and
|
||||
the number of iterations of the abovementioned sequence of operations. The bigger
|
||||
this number, the smoother and closer to target edge length the mesh will be.
|
||||
|
||||
An additional option has been added to \e protect (\e i.\e e. not modify) some given polylines.
|
||||
In some cases, those polylines are too long, and reaching the desired target edge length while protecting them is not
|
||||
possible and leads to an infinite loop of edge splits in the incident faces. To avoid that pitfall, the
|
||||
function `CGAL::Polygon_mesh_processing::split_long_edges()` should be called on the list of
|
||||
constrained edges before remeshing.
|
||||
|
||||
\cgalFigureBegin{iso_remeshing, iso_remeshing.png}
|
||||
Isotropic remeshing. (a) Triangulated input surface mesh.
|
||||
(b) Surface uniformly and entirely remeshed.
|
||||
(c) Selection of a range of faces to be remeshed.
|
||||
(d) Surface mesh with the selection uniformly remeshed.
|
||||
\cgalFigureEnd
|
||||
|
||||
|
||||
\subsection MeshingExamples Meshing Examples
|
||||
|
||||
\subsubsection MeshingExample_1 Refine and Fair a Region on a Polygon Mesh
|
||||
|
|
@ -108,6 +139,18 @@ as shown in the following example.
|
|||
|
||||
\cgalExample{Polygon_mesh_processing/triangulate_faces_example.cpp}
|
||||
|
||||
|
||||
\subsubsection RemeshingExample_1 Isotropic Remeshing of a Region on a Polygon Mesh
|
||||
|
||||
The following example shows a complete example of how the isotropic remeshing function can be used.
|
||||
First, the border of the polygon mesh is collected.
|
||||
Since the boundary edges will be considered as constrained and protected in this example, the function `split_long_edges()` is called first on these edges.
|
||||
|
||||
Once this is done, remeshing is run on all the surface, with protection of constraints activated, for 3 iterations.
|
||||
|
||||
\cgalExample{Polygon_mesh_processing/isotropic_remeshing_example.cpp}
|
||||
|
||||
|
||||
********************************************
|
||||
\section PMPHoleFilling Hole Filling
|
||||
|
||||
|
|
@ -270,6 +313,8 @@ or in general if its three vertices are collinear.
|
|||
The function
|
||||
`CGAL::Polygon_mesh_processing::remove_degenerate_faces()`
|
||||
removes those faces and fixes the connectivity of the newly cleaned up mesh.
|
||||
It is also possible to remove isolated vertices from any polygon mesh, using the function
|
||||
`CGAL::Polygon_mesh_processing::remove_isolated_vertices()`.
|
||||
|
||||
\subsubsection RemoveDegenerateExample Example
|
||||
|
||||
|
|
@ -434,6 +479,8 @@ Function or Class | Pure Triangle | Self-Intersection Free
|
|||
`fair()` | no | no | no
|
||||
`refine()` | no | no | no
|
||||
`triangulate_faces()` | no | no | no
|
||||
`isotropic_remeshing()` | no | no | no
|
||||
`split_long_edges()` | no | no | no
|
||||
`triangulate_hole()` | no | no | no
|
||||
`triangulate_and_refine_hole()` | no | no | no
|
||||
`triangulate_refine_and_fair_hole()` | no | no | no
|
||||
|
|
@ -446,6 +493,7 @@ Function or Class | Pure Triangle | Self-Intersection Free
|
|||
`stitch_borders()` | no | no | no
|
||||
`polygon_soup_to_polygon_mesh()` | no | no | no
|
||||
`orient_polygon_soup()` | no | no | no
|
||||
`remove_isolated_vertices()` | no | no | no
|
||||
`compute_face_normal()` | no | no | no
|
||||
`compute_face_normals()` | no | no | no
|
||||
`compute_vertex_normal()` | no | no | no
|
||||
|
|
|
|||
|
|
@ -11,5 +11,5 @@
|
|||
\example Polygon_mesh_processing/triangulate_polyline_example.cpp
|
||||
\example Polygon_mesh_processing/refine_fair_example.cpp
|
||||
\example Polygon_mesh_processing/mesh_slicer_example.cpp
|
||||
|
||||
\example Polygon_mesh_processing/isotropic_remeshing_example.cpp
|
||||
*/
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 127 KiB |
|
|
@ -82,6 +82,7 @@ create_single_source_cgal_program( "polygon_soup_example.cpp")
|
|||
create_single_source_cgal_program( "triangulate_polyline_example.cpp")
|
||||
create_single_source_cgal_program( "mesh_slicer_example.cpp")
|
||||
#create_single_source_cgal_program( "remove_degeneracies_example.cpp")
|
||||
create_single_source_cgal_program( "isotropic_remeshing_example.cpp")
|
||||
|
||||
if(NOT (${EIGEN3_VERSION} VERSION_LESS 3.2.0))
|
||||
create_single_source_cgal_program( "hole_filling_example.cpp" )
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <CGAL/boost/graph/graph_traits_Surface_mesh.h>
|
||||
|
||||
#include <CGAL/Polygon_mesh_processing/remesh.h>
|
||||
#include <CGAL/Polygon_mesh_processing/border.h>
|
||||
|
||||
#include <boost/function_output_iterator.hpp>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||
typedef CGAL::Surface_mesh<K::Point_3> Mesh;
|
||||
|
||||
typedef boost::graph_traits<Mesh>::halfedge_descriptor halfedge_descriptor;
|
||||
typedef boost::graph_traits<Mesh>::edge_descriptor edge_descriptor;
|
||||
|
||||
struct halfedge2edge
|
||||
{
|
||||
halfedge2edge(const Mesh& m, std::vector<edge_descriptor>& edges)
|
||||
: m_mesh(m), m_edges(edges)
|
||||
{}
|
||||
void operator()(const halfedge_descriptor& h) const
|
||||
{
|
||||
m_edges.push_back(edge(h, m_mesh));
|
||||
}
|
||||
const Mesh& m_mesh;
|
||||
std::vector<edge_descriptor>& m_edges;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
const char* filename = (argc > 1) ? argv[1] : "data/pig.off";
|
||||
std::ifstream input(filename);
|
||||
|
||||
Mesh mesh;
|
||||
if (!input || !(input >> mesh)) {
|
||||
std::cerr << "Not a valid off file." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
double target_edge_length = 0.04;
|
||||
unsigned int nb_iter = 3;
|
||||
|
||||
std::cout << "Split border...";
|
||||
|
||||
std::vector<edge_descriptor> border;
|
||||
PMP::border_halfedges(faces(mesh),
|
||||
boost::make_function_output_iterator(halfedge2edge(mesh, border)),
|
||||
mesh);
|
||||
PMP::split_long_edges(mesh, border, target_edge_length);
|
||||
|
||||
std::cout << "done." << std::endl;
|
||||
|
||||
std::cout << "Start remeshing of " << filename
|
||||
<< " (" << num_faces(mesh) << " faces)..." << std::endl;
|
||||
|
||||
PMP::isotropic_remeshing(mesh,
|
||||
faces(mesh),
|
||||
target_edge_length,
|
||||
PMP::parameters::number_of_iterations(nb_iter)
|
||||
.protect_constraints(true)//i.e. protect border, here
|
||||
);
|
||||
|
||||
std::cout << "Remeshing done." << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
// Copyright (c) 2015 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$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s) : Jane Tournois
|
||||
|
||||
#ifndef CGAL_POLYGON_MESH_PROCESSING_GET_BORDER_H
|
||||
#define CGAL_POLYGON_MESH_PROCESSING_GET_BORDER_H
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <CGAL/Polygon_mesh_processing/internal/named_function_params.h>
|
||||
#include <CGAL/Polygon_mesh_processing/internal/named_params_helper.h>
|
||||
|
||||
#include <set>
|
||||
|
||||
namespace CGAL{
|
||||
namespace Polygon_mesh_processing {
|
||||
|
||||
namespace internal
|
||||
{
|
||||
template<typename PM
|
||||
, typename FaceRange
|
||||
, typename HalfedgeOutputIterator>
|
||||
HalfedgeOutputIterator border_halfedges_impl(const FaceRange& faces
|
||||
, HalfedgeOutputIterator out
|
||||
, const PM& pmesh)
|
||||
{
|
||||
typedef typename boost::graph_traits<PM>::halfedge_descriptor halfedge_descriptor;
|
||||
typedef typename boost::graph_traits<PM>::face_descriptor face_descriptor;
|
||||
|
||||
//collect halfedges that appear only once
|
||||
// the bool is true if the halfedge stored is the one of the face,
|
||||
// false if it is its opposite
|
||||
std::map<halfedge_descriptor, bool> border;
|
||||
BOOST_FOREACH(face_descriptor f, faces)
|
||||
{
|
||||
BOOST_FOREACH(halfedge_descriptor h,
|
||||
halfedges_around_face(halfedge(f, pmesh), pmesh))
|
||||
{
|
||||
//halfedge_descriptor is model of `LessThanComparable`
|
||||
bool from_face = (h < opposite(h, pmesh));
|
||||
halfedge_descriptor he = from_face
|
||||
? h
|
||||
: opposite(h, pmesh);
|
||||
if (border.find(he) != border.end())
|
||||
border.erase(he); //even number of appearances
|
||||
else
|
||||
border.insert(std::make_pair(he, from_face));//odd number of appearances
|
||||
}
|
||||
}
|
||||
//copy them in out
|
||||
typedef typename std::map<halfedge_descriptor, bool>::value_type HD_bool;
|
||||
BOOST_FOREACH(const HD_bool& hd, border)
|
||||
{
|
||||
if (hd.second)
|
||||
*out++ = hd.first;
|
||||
else
|
||||
*out++ = opposite(hd.first, pmesh);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
template<typename PM
|
||||
, typename FaceRange
|
||||
, typename FaceIndexMap
|
||||
, typename HalfedgeOutputIterator>
|
||||
HalfedgeOutputIterator border_halfedges_impl(const FaceRange& faces
|
||||
, const FaceIndexMap& fmap
|
||||
, HalfedgeOutputIterator out
|
||||
, const PM& pmesh)
|
||||
{
|
||||
typedef typename boost::graph_traits<PM>::halfedge_descriptor halfedge_descriptor;
|
||||
typedef typename boost::graph_traits<PM>::face_descriptor face_descriptor;
|
||||
|
||||
std::vector<bool> present(num_faces(pmesh), false);
|
||||
BOOST_FOREACH(face_descriptor fd, faces)
|
||||
present[get(fmap, fd)] = true;
|
||||
|
||||
BOOST_FOREACH(face_descriptor fd, faces)
|
||||
BOOST_FOREACH(halfedge_descriptor hd,
|
||||
halfedges_around_face(halfedge(fd, pmesh), pmesh))
|
||||
{
|
||||
halfedge_descriptor opp=opposite(hd, pmesh);
|
||||
if (is_border(opp, pmesh) || !present[get(fmap,face(opp,pmesh))])
|
||||
*out++ = opp;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
struct Dummy_PM
|
||||
{
|
||||
public:
|
||||
typedef bool vertex_property_type;
|
||||
};
|
||||
|
||||
}//end namespace internal
|
||||
|
||||
#ifdef PMP_TODO_DOC
|
||||
/*!
|
||||
\ingroup PkgPolygonMeshProcessing
|
||||
* collects the border of a surface patch
|
||||
* defined as a face range. The border is "seen from inside" the patch,
|
||||
* i.e. the collected halfedges are
|
||||
* the ones that belong to the input faces.
|
||||
*
|
||||
* @tparam PolygonMesh model of `HalfedgeGraph`
|
||||
* @tparam FaceRange range of
|
||||
`boost::graph_traits<PolygonMesh>::%face_descriptor`, model of `Range`.
|
||||
Its iterator type is `InputIterator`.
|
||||
* @tparam HalfedgeOutputIterator model of `OutputIterator`
|
||||
holding `boost::graph_traits<PolygonMesh>::%halfedge_descriptor`
|
||||
for patch border
|
||||
* @tparam NamedParameters a sequence of \ref namedparameters
|
||||
*
|
||||
* @param pmesh the polygon mesh to which `faces` belong
|
||||
* @param faces the range of faces defining the patch
|
||||
* around which the border is collected
|
||||
* @param out the output iterator that collects halfedges that form the border
|
||||
* of `faces`, seen from inside the surface patch
|
||||
* @param np optional sequence of \ref namedparameters among
|
||||
the ones listed below
|
||||
|
||||
* \cgalNamedParamsBegin
|
||||
\cgalParamBegin{face_index_map} a property map containing the index of each face of `pmesh` \cgalParamEnd
|
||||
\cgalNamedParamsEnd
|
||||
*
|
||||
* @returns `out`
|
||||
*/
|
||||
#endif
|
||||
template<typename PolygonMesh
|
||||
, typename FaceRange
|
||||
, typename HalfedgeOutputIterator
|
||||
, typename NamedParameters>
|
||||
HalfedgeOutputIterator border_halfedges(const FaceRange& faces
|
||||
, HalfedgeOutputIterator out
|
||||
, const PolygonMesh& pmesh
|
||||
, const NamedParameters& np)
|
||||
{
|
||||
typedef PolygonMesh PM;
|
||||
typedef typename GetFaceIndexMap<PM, NamedParameters>::type FIMap;
|
||||
typedef typename boost::property_map<typename internal::Dummy_PM,
|
||||
CGAL::face_index_t>::type Unset_FIMap;
|
||||
|
||||
if (boost::is_same<FIMap, Unset_FIMap>::value)
|
||||
{
|
||||
//face index map is not given in named parameters, nor as an internal property map
|
||||
return internal::border_halfedges_impl(faces, out, pmesh);
|
||||
}
|
||||
//face index map given as a named parameter, or as an internal property map
|
||||
FIMap fim = choose_param(get_param(np, face_index),
|
||||
get(CGAL::face_index, pmesh));
|
||||
return internal::border_halfedges_impl(faces, fim, out, pmesh);
|
||||
}
|
||||
|
||||
template<typename PolygonMesh
|
||||
, typename HalfedgeOutputIterator>
|
||||
HalfedgeOutputIterator border_halfedges(HalfedgeOutputIterator out
|
||||
, const PolygonMesh& pmesh)
|
||||
{
|
||||
typedef PolygonMesh PM;
|
||||
typedef typename boost::graph_traits<PM>::halfedge_descriptor halfedge_descriptor;
|
||||
BOOST_FOREACH(halfedge_descriptor hd, halfedges(pmesh))
|
||||
if (is_border(hd, pmesh))
|
||||
*out++ = hd;
|
||||
return out;
|
||||
}
|
||||
|
||||
template<typename PolygonMesh
|
||||
, typename FaceRange
|
||||
, typename HalfedgeOutputIterator>
|
||||
HalfedgeOutputIterator border_halfedges(const FaceRange& faces
|
||||
, HalfedgeOutputIterator out
|
||||
, const PolygonMesh& pmesh)
|
||||
{
|
||||
return border_halfedges(faces, out, pmesh,
|
||||
CGAL::Polygon_mesh_processing::parameters::all_default());
|
||||
}
|
||||
|
||||
}
|
||||
} // end of namespace CGAL::Polygon_mesh_processing
|
||||
|
||||
|
||||
#endif //CGAL_POLYGON_MESH_PROCESSING_GET_BORDER_H
|
||||
|
|
@ -94,11 +94,11 @@ compute_face_normal(typename boost::graph_traits<PolygonMesh>::face_descriptor f
|
|||
typedef typename Kernel::Vector_3 Vector;
|
||||
|
||||
using boost::get_param;
|
||||
using boost::choose_param;
|
||||
using boost::choose_const_pmap;
|
||||
|
||||
Vector normal = CGAL::NULL_VECTOR;
|
||||
sum_normals<Point>(pmesh, f
|
||||
, choose_param(get_param(np, vertex_point), get(CGAL::vertex_point, pmesh))
|
||||
, choose_const_pmap(get_param(np, CGAL::vertex_point), pmesh, CGAL::vertex_point)
|
||||
, normal);
|
||||
|
||||
return normal / FT( std::sqrt( to_double(normal * normal) ) );
|
||||
|
|
|
|||
|
|
@ -438,7 +438,8 @@ connected_component(typename boost::graph_traits<PolygonMesh>::face_descriptor s
|
|||
internal::No_constraint<PolygonMesh>//default
|
||||
> ::type EdgeConstraintMap;
|
||||
EdgeConstraintMap ecmap
|
||||
= choose_param(get_param(np, edge_is_constrained), EdgeConstraintMap());
|
||||
= choose_param(get_param(np, edge_is_constrained),
|
||||
internal::No_constraint<PolygonMesh>());
|
||||
|
||||
typedef typename boost::graph_traits<PolygonMesh>::face_descriptor face_descriptor;
|
||||
typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ namespace CGAL{
|
|||
enum fairing_continuity_t { fairing_continuity };
|
||||
enum sparse_linear_solver_t { sparse_linear_solver };
|
||||
enum geom_traits_t { geom_traits };
|
||||
enum number_of_iterations_t { number_of_iterations };
|
||||
enum protect_constraints_t { protect_constraints };
|
||||
|
||||
//internal
|
||||
enum weight_calculator_t { weight_calculator };
|
||||
|
|
@ -112,6 +114,22 @@ namespace CGAL{
|
|||
return Params(k, *this);
|
||||
}
|
||||
|
||||
template<typename NT>
|
||||
pmp_bgl_named_params<NT, number_of_iterations_t, self>
|
||||
number_of_iterations(const NT& n) const
|
||||
{
|
||||
typedef pmp_bgl_named_params<NT, number_of_iterations_t, self> Params;
|
||||
return Params(n, *this);
|
||||
}
|
||||
|
||||
template<typename Boolean>
|
||||
pmp_bgl_named_params<Boolean, protect_constraints_t, self>
|
||||
protect_constraints(const Boolean b) const
|
||||
{
|
||||
typedef pmp_bgl_named_params<Boolean, protect_constraints_t, self> Params;
|
||||
return Params(b, *this);
|
||||
}
|
||||
|
||||
//overload
|
||||
template <typename EdgeIsConstrained>
|
||||
pmp_bgl_named_params<EdgeIsConstrained, edge_is_constrained_t, self>
|
||||
|
|
@ -218,6 +236,22 @@ namespace parameters{
|
|||
return Params(k);
|
||||
}
|
||||
|
||||
template<typename NT>
|
||||
pmp_bgl_named_params<NT, number_of_iterations_t>
|
||||
number_of_iterations(const NT& n)
|
||||
{
|
||||
typedef pmp_bgl_named_params<NT, number_of_iterations_t> Params;
|
||||
return Params(n);
|
||||
}
|
||||
|
||||
template <typename Boolean>
|
||||
pmp_bgl_named_params<Boolean, protect_constraints_t>
|
||||
protect_constraints(const Boolean b)
|
||||
{
|
||||
typedef pmp_bgl_named_params<Boolean, protect_constraints_t> Params;
|
||||
return Params(b);
|
||||
}
|
||||
|
||||
//overload
|
||||
template <typename EdgeIsConstrained>
|
||||
pmp_bgl_named_params<EdgeIsConstrained, edge_is_constrained_t>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,269 @@
|
|||
// Copyright (c) 2015 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$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s) : Jane Tournois
|
||||
|
||||
#ifndef CGAL_POLYGON_MESH_PROCESSING_REMESH_H
|
||||
#define CGAL_POLYGON_MESH_PROCESSING_REMESH_H
|
||||
|
||||
#include <CGAL/Polygon_mesh_processing/internal/remesh_impl.h>
|
||||
|
||||
#include <CGAL/Polygon_mesh_processing/internal/named_function_params.h>
|
||||
#include <CGAL/Polygon_mesh_processing/internal/named_params_helper.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
namespace Polygon_mesh_processing {
|
||||
|
||||
/*!
|
||||
* \ingroup remeshing_grp
|
||||
* @brief remeshes a triangulated region of a polygon mesh.
|
||||
* This operation sequentially performs edge splits, edge collapses,
|
||||
* edge flips, Laplacian smoothing and projection to the initial surface
|
||||
* to generate a smooth mesh with a prescribed edge length.
|
||||
*
|
||||
* @tparam PolygonMesh model of `MutableFaceGraph` that
|
||||
* has an internal property map for `CGAL::vertex_point_t`.
|
||||
* @tparam FaceRange range of `boost::graph_traits<PolygonMesh>::%face_descriptor`,
|
||||
model of `Range`. Its iterator type is `InputIterator`.
|
||||
* @tparam NamedParameters a sequence of \ref namedparameters
|
||||
*
|
||||
* @param pmesh a polygon mesh with triangulated surface patches to be remeshed
|
||||
* @param faces the range of triangular faces defining one or several surface patches to be remeshed
|
||||
* @param target_edge_length the edge length that is targetted in the remeshed patch
|
||||
* @param np optional sequence of \ref namedparameters among the ones listed below
|
||||
*
|
||||
* @pre if constraints protection is activated, the constrained edges should
|
||||
* not be longer than 4/3*`target_edge_length`
|
||||
*
|
||||
* \cgalNamedParamsBegin
|
||||
* \cgalParamBegin{vertex_point_map} the property map with the points associated
|
||||
* to the vertices of `pmesh`. Instance of a class model of `ReadWritePropertyMap`.
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{number_of_iterations} the number of iterations for the
|
||||
* sequence of atomic operations performed (listed in the above description)
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{geom_traits} a geometric traits class instance, model of `Kernel`
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{edge_is_constrained_map} a property map containing the
|
||||
* constrained-or-not status of each edge of pmesh. A constrained edge can be splitted
|
||||
* or collapsed, but not flipped, nor its endpoints moved by smoothing.
|
||||
* Note that patch boundary edges (i.e. incident to only one face in the range)
|
||||
* are always considered as constrained edges.
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{protect_constraints} If `true`, the edges set as constrained
|
||||
* in `edge_is_constrained_map` (or by default the boundary edges)
|
||||
* are not splitted nor collapsed during remeshing.
|
||||
* Note that around constrained edges that have their length higher than
|
||||
* twice `target_edge_length`, remeshing will fail to provide
|
||||
* good quality results. It can even fail to terminate because of cascading vertex
|
||||
* insertions.
|
||||
* \cgalParamEnd
|
||||
* \cgalNamedParamsEnd
|
||||
*
|
||||
* @sa `split_long_edges()`
|
||||
*
|
||||
*@todo add possibility to provide a functor that projects to a prescribed surface
|
||||
*/
|
||||
template<typename PolygonMesh
|
||||
, typename FaceRange
|
||||
, typename NamedParameters>
|
||||
void isotropic_remeshing(PolygonMesh& pmesh
|
||||
, const FaceRange& faces
|
||||
, const double& target_edge_length
|
||||
, const NamedParameters& np)
|
||||
{
|
||||
typedef PolygonMesh PM;
|
||||
using boost::choose_pmap;
|
||||
using boost::get_param;
|
||||
using boost::choose_param;
|
||||
|
||||
typedef typename GetGeomTraits<PM, NamedParameters>::type GT;
|
||||
|
||||
typedef typename GetVertexPointMap<PM, NamedParameters>::type VPMap;
|
||||
VPMap vpmap = choose_pmap(get_param(np, boost::vertex_point),
|
||||
pmesh,
|
||||
boost::vertex_point);
|
||||
|
||||
typedef typename boost::lookup_named_param_def <
|
||||
CGAL::edge_is_constrained_t,
|
||||
NamedParameters,
|
||||
internal::Border_constraint_pmap<PM, FaceRange>//default
|
||||
> ::type ECMap;
|
||||
ECMap ecmap
|
||||
= choose_param(get_param(np, edge_is_constrained),
|
||||
internal::Border_constraint_pmap<PM, FaceRange>(pmesh, faces));
|
||||
|
||||
double low = 4. / 5. * target_edge_length;
|
||||
double high = 4. / 3. * target_edge_length;
|
||||
|
||||
bool protect = choose_param(get_param(np, protect_constraints), false);
|
||||
if(protect)
|
||||
{
|
||||
std::string msg("Isotropic remeshing : protect_constraints cannot be set to");
|
||||
msg.append(" true with constraints larger than 4/3 * target_edge_length.");
|
||||
msg.append(" Remeshing aborted.");
|
||||
CGAL_precondition_msg(
|
||||
internal::constraints_are_short_enough(pmesh, ecmap, vpmap, high),
|
||||
msg.c_str());
|
||||
}
|
||||
|
||||
typename internal::Incremental_remesher<PM, VPMap, GT>
|
||||
remesher(pmesh, vpmap, protect);
|
||||
remesher.init_faces_remeshing(faces, ecmap);
|
||||
|
||||
unsigned int nb_iterations = choose_param(get_param(np, number_of_iterations), 1);
|
||||
|
||||
#ifdef CGAL_PMP_REMESHING_VERBOSE
|
||||
std::cout << std::endl;
|
||||
std::cout << "Remeshing (size = " << target_edge_length;
|
||||
std::cout << ", #iter = " << nb_iterations << ")..." << std::endl;
|
||||
#endif
|
||||
|
||||
for (unsigned int i = 0; i < nb_iterations; ++i)
|
||||
{
|
||||
#ifdef CGAL_PMP_REMESHING_VERBOSE
|
||||
std::cout << " * Iteration " << (i + 1) << " *" << std::endl;
|
||||
#endif
|
||||
|
||||
remesher.split_long_edges(high);
|
||||
remesher.collapse_short_edges(low, high);
|
||||
remesher.equalize_valences();
|
||||
remesher.tangential_relaxation();
|
||||
remesher.project_to_surface();
|
||||
|
||||
#ifdef CGAL_PMP_REMESHING_VERBOSE
|
||||
std::cout << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CGAL_PMP_REMESHING_VERBOSE
|
||||
std::cout << "Remeshing done (size = " << target_edge_length;
|
||||
std::cout << ", #iter = " << nb_iterations << ")." << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename PolygonMesh
|
||||
, typename FaceRange>
|
||||
void isotropic_remeshing(PolygonMesh& pmesh
|
||||
, const FaceRange& faces
|
||||
, const double& target_edge_length)
|
||||
{
|
||||
isotropic_remeshing(pmesh,
|
||||
faces,
|
||||
target_edge_length,
|
||||
parameters::all_default());
|
||||
}
|
||||
|
||||
/*!
|
||||
* \ingroup remeshing_grp
|
||||
* @brief splits the edges listed in `edges` into sub-edges
|
||||
* that are not longer than the given threshold `max_length`.
|
||||
*
|
||||
* Note this function is useful to split constrained edges before
|
||||
* calling `isotropic_remeshing()` with protection of constraints
|
||||
* activated (to match the constrained edge length required by the
|
||||
* remeshing algorithm to be guaranteed to terminate)
|
||||
*
|
||||
* @tparam PolygonMesh model of `MutableFaceGraph` that
|
||||
* has an internal property map for `CGAL::vertex_point_t`.
|
||||
* @tparam EdgeRange range of `boost::graph_traits<PolygonMesh>::%edge_descriptor`,
|
||||
* model of `Range`. Its iterator type is `InputIterator`.
|
||||
* @tparam NamedParameters a sequence of \ref namedparameters
|
||||
*
|
||||
* @param pmesh a polygon mesh
|
||||
* @param edges the range of edges to be split if they are longer than given threshold
|
||||
* @param max_length the edge length above which an edge from `edges` is split
|
||||
* into to sub-edges
|
||||
* @param np optional \ref namedparameters described below
|
||||
|
||||
* \cgalNamedParamsBegin
|
||||
* \cgalParamBegin{vertex_point_map} the property map with the points associated
|
||||
* to the vertices of `pmesh`. Instance of a class model of `ReadWritePropertyMap`.
|
||||
* \cgalParamEnd
|
||||
* \cgalNamedParamsEnd
|
||||
*
|
||||
* @sa `isotropic_remeshing()`
|
||||
*
|
||||
*/
|
||||
template<typename PolygonMesh
|
||||
, typename EdgeRange
|
||||
, typename NamedParameters>
|
||||
void split_long_edges(PolygonMesh& pmesh
|
||||
, EdgeRange& edges
|
||||
, const double& max_length
|
||||
, const NamedParameters& np)
|
||||
{
|
||||
typedef PolygonMesh PM;
|
||||
using boost::choose_pmap;
|
||||
using boost::get_param;
|
||||
|
||||
typedef typename GetGeomTraits<PM, NamedParameters>::type GT;
|
||||
typedef typename GetVertexPointMap<PM, NamedParameters>::type VPMap;
|
||||
VPMap vpmap = choose_pmap(get_param(np, boost::vertex_point),
|
||||
pmesh,
|
||||
boost::vertex_point);
|
||||
|
||||
typename internal::Incremental_remesher<PM, VPMap, GT>
|
||||
remesher(pmesh, vpmap, false/*protect constraints*/);
|
||||
|
||||
remesher.split_long_edges(edges, max_length, Emptyset_iterator());
|
||||
}
|
||||
|
||||
template<typename PolygonMesh, typename EdgeRange>
|
||||
void split_long_edges(PolygonMesh& pmesh
|
||||
, EdgeRange& edges
|
||||
, const double& max_length)
|
||||
{
|
||||
split_long_edges(pmesh,
|
||||
edges,
|
||||
max_length,
|
||||
parameters::all_default());
|
||||
}
|
||||
|
||||
//used in the Polyhedron demo
|
||||
template<typename PolygonMesh
|
||||
, typename EdgeRange
|
||||
, typename OutputIterator
|
||||
, typename NamedParameters>
|
||||
void split_long_edges(PolygonMesh& pmesh
|
||||
, EdgeRange& edge_range
|
||||
, const double& max_length
|
||||
, OutputIterator out//edges after splitting, all shorter than target_length
|
||||
, const NamedParameters& np)
|
||||
{
|
||||
typedef PolygonMesh PM;
|
||||
using boost::choose_pmap;
|
||||
using boost::get_param;
|
||||
|
||||
typedef typename GetGeomTraits<PM, NamedParameters>::type GT;
|
||||
typedef typename GetVertexPointMap<PM, NamedParameters>::type VPMap;
|
||||
VPMap vpmap = choose_pmap(get_param(np, boost::vertex_point),
|
||||
pmesh,
|
||||
boost::vertex_point);
|
||||
|
||||
typename internal::Incremental_remesher<PM, VPMap, GT>
|
||||
remesher(pmesh, vpmap, false/*protect constraints*/);
|
||||
|
||||
remesher.split_long_edges(edge_range, max_length, out);
|
||||
}
|
||||
|
||||
} //end namespace Polygon_mesh_processing
|
||||
} //end namespace CGAL
|
||||
|
||||
#endif
|
||||
|
|
@ -124,6 +124,8 @@ bool is_degenerated(
|
|||
const VertexPointMap& vpmap,
|
||||
const Traits& traits)
|
||||
{
|
||||
CGAL_assertion(!is_border(hd, tmesh));
|
||||
|
||||
const typename Traits::Point_3& p1 = get(vpmap, target( hd, tmesh) );
|
||||
const typename Traits::Point_3& p2 = get(vpmap, target(next(hd, tmesh), tmesh) );
|
||||
const typename Traits::Point_3& p3 = get(vpmap, source( hd, tmesh) );
|
||||
|
|
@ -806,6 +808,40 @@ std::size_t remove_degenerate_faces(TriangleMesh& tmesh)
|
|||
}
|
||||
/// \endcond
|
||||
|
||||
|
||||
#ifdef PMP_TODO_DOC
|
||||
/// \ingroup PkgPolygonMeshProcessing
|
||||
/// removes the isolated vertices from any polygon mesh.
|
||||
/// A vertex is considered isolated if it is not incident to any simplex
|
||||
/// of higher dimension.
|
||||
///
|
||||
/// @tparam PolygonMesh a model of `FaceListGraph` and `MutableFaceGraph`
|
||||
///
|
||||
/// @param pmesh the polygon mesh to be repaired
|
||||
///
|
||||
/// @return number of removed isolated vertices
|
||||
///
|
||||
#endif
|
||||
template <class PolygonMesh>
|
||||
std::size_t remove_isolated_vertices(PolygonMesh& pmesh)
|
||||
{
|
||||
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
|
||||
std::vector<vertex_descriptor> to_be_removed;
|
||||
|
||||
BOOST_FOREACH(vertex_descriptor v, vertices(pmesh))
|
||||
{
|
||||
if (CGAL::halfedges_around_target(v, pmesh).first
|
||||
== CGAL::halfedges_around_target(v, pmesh).second)
|
||||
to_be_removed.push_back(v);
|
||||
}
|
||||
std::size_t nb_removed = to_be_removed.size();
|
||||
BOOST_FOREACH(vertex_descriptor v, to_be_removed)
|
||||
{
|
||||
remove_vertex(v, pmesh);
|
||||
}
|
||||
return nb_removed;
|
||||
}
|
||||
|
||||
} } // end of CGAL::Polygon_mesh_processing
|
||||
|
||||
#endif // CGAL_POLYGON_MESH_PROCESSING_REPAIR_H
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ if (EIGEN3_FOUND)
|
|||
create_single_source_cgal_program("test_stitching.cpp")
|
||||
create_single_source_cgal_program("remove_degeneracies_test.cpp")
|
||||
create_single_source_cgal_program("test_pmp_bgl_named_params.cpp")
|
||||
create_single_source_cgal_program("remeshing_test.cpp" )
|
||||
|
||||
if(NOT (${EIGEN3_VERSION} VERSION_LESS 3.2.0))
|
||||
create_single_source_cgal_program("fairing_test.cpp")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
576 574 570 568 572 566 564 562 500 498 496 494 462 460 448 165 164 163 162 154 153
|
||||
913 910 905 903 899 893 887 873 884 867 861 858 855 853 851 848 845 842 839 833 827 821 819 810 807 798 795 792 789 783 780 881 774 830 771 765 762 748 743 741 738 735 732 729 727 724 721 718 712 706 703 700 697 694 691 688 686 682 677 653 650 640 634 801 622 610 606 600 514 511 509 507 503 501 499 497 491 759 489 487 485 480 478 777 472 470 756 466 464 459 457 455 451 449 505 447 804 445 438 430 427 426 423 646 421 419 414 824 408 404 402 400 398 619 396 394 391 389 387 517 385 383 379 377 432 375 373 371 474 369 365 363 361 359 495 357 355 353 468 350 346 344 341 381 337 333 483 332 330 327 324 321 751 319 318 313 312 348 305 302 443 412 301 299 297 864 291 289 286 786 284 417 282 280 277 316 275 493 271 267 255 252 250 244 434 242 513 453 240 462 238 236 234 231 226 224 896 261 217 195 204 193 176 288 169 165 410 161 156 146 144 878 142 140 135 133 715 131 642 406 129 870 608 294 127 125 123 121 263 117 115 113 111 109 107 105 103 101 248 99 97 93 89 875 87 367 85 813 83 81 311 269 119 79 77 709 75 73 71 65 63 246 61 59 57 440 67 55 53 95 51 49 47 45 43 41 39 37 753 35 890 32 30 28 745 25 816 768 23 21 138 19 436 259 17 15 91 13 11 9 7 5 476 69 3 836 0
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
608 604 602 596 594 593 600 591 587 581 579 577 585 575 571 569 567 583 563 512 510 509 589 565 503 573 501 507 505 499 497 470 468 467 465 606 461 451 449 516 514 495 463 168 598 167
|
||||
913 905 903 899 893 890 884 875 867 861 848 845 842 833 830 827 824 819 816 813 807 804 801 798 795 792 789 786 783 777 774 771 768 765 762 759 756 753 748 745 743 741 738 729 724 703 700 688 677 653 646 642 634 709 619 650 610 600 715 517 514 513 511 509 896 507 503 499 495 735 493 491 489 751 487 483 480 478 476 472 466 464 697 474 462 459 457 810 455 453 449 694 447 438 434 432 427 878 423 430 421 436 419 417 414 836 412 732 404 402 400 398 396 851 394 391 389 387 385 721 383 910 691 381 379 377 375 712 373 371 363 361 359 355 353 348 346 485 344 686 341 337 333 332 330 327 324 319 682 318 316 313 312 311 858 302 887 299 780 291 369 289 321 297 288 286 284 497 280 470 277 410 275 367 271 269 267 853 263 261 259 255 864 252 248 246 244 242 240 357 234 226 224 217 204 195 440 176 169 165 282 161 156 146 144 640 406 140 138 135 718 445 294 133 131 873 129 250 127 125 123 727 121 236 119 117 238 115 111 109 107 105 365 103 101 99 193 97 95 93 91 87 85 83 608 305 81 426 79 501 77 75 821 73 443 71 69 67 622 65 468 63 61 59 706 57 55 505 53 51 49 47 881 231 45 451 43 142 41 39 37 113 35 89 32 855 30 606 301 28 350 25 839 23 870 408 21 19 17 15 13 11 9 7 5 3 0
|
||||
|
|
@ -0,0 +1,917 @@
|
|||
OFF
|
||||
303 610 0
|
||||
|
||||
0.18987 0.5 0.0145757
|
||||
0.18987 -0.5 0.0145757
|
||||
0.160511 -0.5 0.0325677
|
||||
0.160511 0.5 0.0325677
|
||||
0.128697 -0.5 0.0457447
|
||||
0.128697 0.5 0.0457447
|
||||
0.0952137 -0.5 0.0537838
|
||||
0.0952137 0.5 0.0537838
|
||||
0.0608858 -0.5 0.0564848
|
||||
0.0608858 0.5 0.0564848
|
||||
0.0265575 -0.5 0.0537838
|
||||
0.0265575 0.5 0.0537838
|
||||
-0.0069256 -0.5 0.0457447
|
||||
-0.0069256 0.5 0.0457447
|
||||
-0.038739 -0.5 0.0325677
|
||||
-0.038739 0.5 0.0325677
|
||||
-0.0680987 -0.5 0.0145757
|
||||
-0.0680987 0.5 0.0145757
|
||||
-0.0942827 -0.5 -0.00778743
|
||||
-0.0942827 0.5 -0.00778743
|
||||
-0.116646 -0.5 -0.0339725
|
||||
-0.116646 0.5 -0.0339725
|
||||
-0.134639 -0.5 -0.0633324
|
||||
-0.134639 0.5 -0.0633324
|
||||
-0.147815 -0.5 -0.0951457
|
||||
-0.147815 0.5 -0.0951457
|
||||
-0.155855 -0.5 -0.128628
|
||||
-0.155855 0.5 -0.128628
|
||||
-0.158556 -0.5 -0.162956
|
||||
-0.158556 0.5 -0.162956
|
||||
-0.155855 -0.5 -0.197285
|
||||
-0.155855 0.5 -0.197285
|
||||
-0.147815 -0.5 -0.230768
|
||||
-0.147815 0.5 -0.230768
|
||||
-0.134639 -0.5 -0.262581
|
||||
-0.134639 0.5 -0.262581
|
||||
-0.116646 -0.5 -0.291941
|
||||
-0.116646 0.5 -0.291941
|
||||
-0.0942827 -0.5 -0.318125
|
||||
-0.0942827 0.5 -0.318125
|
||||
-0.0680987 -0.5 -0.340488
|
||||
-0.0680987 0.5 -0.340488
|
||||
-0.038739 -0.5 -0.358481
|
||||
-0.038739 0.5 -0.358481
|
||||
-0.0069256 -0.5 -0.371658
|
||||
-0.0069256 0.5 -0.371658
|
||||
0.0265574 -0.5 -0.379697
|
||||
0.0265574 0.5 -0.379697
|
||||
0.0608857 -0.5 -0.382398
|
||||
0.0608857 0.5 -0.382398
|
||||
0.0952137 -0.5 -0.379697
|
||||
0.0952137 0.5 -0.379697
|
||||
0.128696 -0.5 -0.371658
|
||||
0.128696 0.5 -0.371658
|
||||
0.16051 -0.5 -0.358481
|
||||
0.16051 0.5 -0.358481
|
||||
0.18987 -0.5 -0.340488
|
||||
0.18987 0.5 -0.340488
|
||||
0.216054 -0.5 -0.318125
|
||||
0.216054 0.5 -0.318125
|
||||
0.238418 -0.5 -0.291941
|
||||
0.238418 0.5 -0.291941
|
||||
0.25641 -0.5 -0.262581
|
||||
0.25641 0.5 -0.262581
|
||||
0.269587 -0.5 -0.230768
|
||||
0.269587 0.5 -0.230768
|
||||
0.277626 -0.5 -0.197285
|
||||
0.277626 0.5 -0.197285
|
||||
0.280327 -0.5 -0.162956
|
||||
0.280327 0.5 -0.162956
|
||||
0.277626 -0.5 -0.128628
|
||||
0.277626 0.5 -0.128628
|
||||
0.269587 -0.5 -0.0951457
|
||||
0.269587 0.5 -0.0951457
|
||||
0.25641 -0.5 -0.0633324
|
||||
0.25641 0.5 -0.0633324
|
||||
0.238418 -0.5 -0.0339725
|
||||
0.238418 0.5 -0.0339725
|
||||
0.216054 -0.5 -0.00778851
|
||||
0.216054 0.5 -0.00778851
|
||||
0.157965 -0.5 -0.461734
|
||||
0.203507 -0.5 -0.442869
|
||||
0.24554 -0.5 -0.417111
|
||||
0.283026 -0.5 -0.385097
|
||||
0.315041 -0.5 -0.347611
|
||||
0.340798 -0.5 -0.305579
|
||||
0.359662 -0.5 -0.260035
|
||||
0.371171 -0.5 -0.212101
|
||||
0.375039 -0.5 -0.162956
|
||||
0.371171 -0.5 -0.113812
|
||||
0.359662 -0.5 -0.0658783
|
||||
0.340799 -0.5 -0.0203345
|
||||
0.315041 -0.5 0.0216976
|
||||
0.283026 -0.5 0.0591838
|
||||
0.245541 -0.5 0.0911989
|
||||
0.203508 -0.5 0.116956
|
||||
0.157965 -0.5 0.13582
|
||||
0.11003 -0.5 0.147329
|
||||
0.0608858 -0.5 0.151196
|
||||
-0.375039 -0.5 -0.162956
|
||||
0.0608858 -0.5 -0.47711
|
||||
0.11003 -0.5 -0.473241
|
||||
0.203508 0.5 0.116956
|
||||
0.245541 0.5 0.0911989
|
||||
0.283026 0.5 0.0591838
|
||||
0.315041 0.5 0.0216986
|
||||
0.340799 0.5 -0.0203345
|
||||
0.359662 0.5 -0.0658783
|
||||
0.371171 0.5 -0.113812
|
||||
0.375039 0.5 -0.162956
|
||||
0.371171 0.5 -0.212101
|
||||
0.359662 0.5 -0.260035
|
||||
0.340798 0.5 -0.305579
|
||||
0.315041 0.5 -0.347611
|
||||
0.283026 0.5 -0.385097
|
||||
0.24554 0.5 -0.417111
|
||||
0.203507 0.5 -0.442869
|
||||
0.157965 0.5 -0.461734
|
||||
0.11003 0.5 -0.473241
|
||||
0.0608858 0.5 -0.47711
|
||||
-0.375039 0.5 -0.162956
|
||||
0.0608858 0.5 0.151196
|
||||
0.11003 0.5 0.147329
|
||||
0.157965 0.5 0.13582
|
||||
-0.375039 -0.5 -0.47711
|
||||
-0.157078 -0.5 0.151196
|
||||
-0.375039 -0.5 0.151196
|
||||
-0.375039 0.5 -0.47711
|
||||
-0.375039 -0.185847 0.47711
|
||||
-0.157078 -0.185847 0.47711
|
||||
-0.157078 0.5 0.47711
|
||||
-0.375039 0.5 0.47711
|
||||
-0.375039 0.5 0.151196
|
||||
-0.157078 0.5 0.151196
|
||||
-0.375039 -0.185847 0.151196
|
||||
-0.375039 -0.5 0.47711
|
||||
-0.157078 -0.5 0.47711
|
||||
0.0608859 -0.5 0.47711
|
||||
0.0608859 -0.185847 0.47711
|
||||
-0.157078 -0.185847 0.151196
|
||||
0.0608858 -0.185847 0.151196
|
||||
-0.375039 -0.315312 0.400904
|
||||
-0.375039 -0.329311 0.404264
|
||||
-0.375039 -0.343663 0.405393
|
||||
-0.375039 -0.358016 0.404264
|
||||
-0.375039 -0.372015 0.400904
|
||||
-0.375039 -0.385316 0.395395
|
||||
-0.375039 -0.397591 0.387872
|
||||
-0.375039 -0.408538 0.378521
|
||||
-0.375039 -0.417888 0.367575
|
||||
-0.375039 -0.42541 0.355299
|
||||
-0.375039 -0.43092 0.341999
|
||||
-0.375039 -0.434281 0.328
|
||||
-0.375039 -0.43541 0.313648
|
||||
-0.375039 -0.434281 0.299295
|
||||
-0.375039 -0.43092 0.285296
|
||||
-0.375039 -0.42541 0.271996
|
||||
-0.375039 -0.417888 0.25972
|
||||
-0.375039 -0.408538 0.248773
|
||||
-0.375039 -0.397591 0.239422
|
||||
-0.375039 -0.385316 0.2319
|
||||
-0.375039 -0.372015 0.22639
|
||||
-0.375039 -0.358016 0.223031
|
||||
-0.375039 -0.343663 0.221901
|
||||
-0.375039 -0.329311 0.223031
|
||||
-0.375039 -0.315312 0.22639
|
||||
-0.375039 -0.302011 0.2319
|
||||
-0.375039 -0.289736 0.239422
|
||||
-0.375039 -0.278789 0.248773
|
||||
-0.375039 -0.269439 0.25972
|
||||
-0.375039 -0.261916 0.271996
|
||||
-0.375039 -0.256407 0.285296
|
||||
-0.375039 -0.253046 0.299295
|
||||
-0.375039 -0.251917 0.313648
|
||||
-0.375039 -0.253046 0.328
|
||||
-0.375039 -0.256407 0.341999
|
||||
-0.375039 -0.261916 0.355299
|
||||
-0.375039 -0.269439 0.367575
|
||||
-0.375039 -0.278789 0.378521
|
||||
-0.375039 -0.289736 0.387872
|
||||
-0.375039 -0.302011 0.395395
|
||||
0.0608859 -0.302011 0.395395
|
||||
0.0608859 -0.289736 0.387872
|
||||
0.0608859 -0.278789 0.378521
|
||||
0.0608859 -0.269439 0.367575
|
||||
0.0608859 -0.261916 0.355299
|
||||
0.0608859 -0.256407 0.341999
|
||||
0.0608859 -0.253046 0.328
|
||||
0.0608859 -0.251917 0.313648
|
||||
0.0608859 -0.253046 0.299295
|
||||
0.0608859 -0.256407 0.285296
|
||||
0.0608859 -0.261916 0.271996
|
||||
0.0608859 -0.269439 0.25972
|
||||
0.0608859 -0.278789 0.248773
|
||||
0.0608859 -0.289736 0.239422
|
||||
0.0608859 -0.302011 0.2319
|
||||
0.0608859 -0.315312 0.22639
|
||||
0.0608859 -0.329311 0.223031
|
||||
0.0608859 -0.343663 0.221901
|
||||
0.0608859 -0.358016 0.223031
|
||||
0.0608859 -0.372015 0.22639
|
||||
0.0608859 -0.385316 0.2319
|
||||
0.0608859 -0.397591 0.239422
|
||||
0.0608859 -0.408538 0.248773
|
||||
0.0608859 -0.417888 0.25972
|
||||
0.0608859 -0.42541 0.271996
|
||||
0.0608859 -0.43092 0.285296
|
||||
0.0608859 -0.434281 0.299295
|
||||
0.0608859 -0.43541 0.313648
|
||||
0.0608859 -0.434281 0.328
|
||||
0.0608859 -0.43092 0.341999
|
||||
0.0608859 -0.42541 0.355299
|
||||
0.0608859 -0.417888 0.367575
|
||||
0.0608859 -0.408538 0.378521
|
||||
0.0608859 -0.397591 0.387872
|
||||
0.0608859 -0.385316 0.395395
|
||||
0.0608859 -0.372015 0.400904
|
||||
0.0608859 -0.358016 0.404264
|
||||
0.0608859 -0.343663 0.405393
|
||||
0.0608859 -0.329311 0.404264
|
||||
0.0608859 -0.315312 0.400904
|
||||
-0.375039 0 -0.47711
|
||||
-0.157078 0.1570765 0.47711
|
||||
-0.157078 0.1570765 0.151196
|
||||
-0.375039 -0.25 -0.47711
|
||||
-0.375039 0.25 -0.47711
|
||||
-0.1570766 -0.5 -0.47711
|
||||
-0.1570766 0.5 -0.47711
|
||||
-0.157078 -0.01438525 0.47711
|
||||
-0.157078 0.32853825 0.47711
|
||||
-0.157078 0.32853825 0.151196
|
||||
-0.157078 -0.01438525 0.151196
|
||||
-0.157078 0.5 0.314153
|
||||
-0.157078 -0.185847 0.314153
|
||||
0.0608858 -0.3429235 0.151196
|
||||
-0.375039 -0.375 -0.47711
|
||||
-0.375039 -0.125 -0.47711
|
||||
-0.375039 0.125 -0.47711
|
||||
-0.375039 0.375 -0.47711
|
||||
-0.0480961 -0.185847 0.151196
|
||||
-0.0480961 0.5 0.151196
|
||||
-0.0480954 -0.5 -0.47711
|
||||
-0.2660578 -0.5 -0.47711
|
||||
-0.2660578 0.5 -0.47711
|
||||
-0.0480954 0.5 -0.47711
|
||||
-0.157078 -0.100116125 0.47711
|
||||
-0.157078 0.071345625 0.47711
|
||||
-0.157078 0.242807375 0.47711
|
||||
-0.157078 0.414269125 0.47711
|
||||
-0.157078 0.414269125 0.151196
|
||||
-0.157078 0.242807375 0.151196
|
||||
-0.157078 0.071345625 0.151196
|
||||
-0.157078 -0.100116125 0.151196
|
||||
-0.157078 0.5 0.2326745
|
||||
-0.157078 0.5 0.3956315
|
||||
-0.157078 -0.185847 0.3956315
|
||||
-0.157078 -0.185847 0.2326745
|
||||
0.0608858 -0.42146175 0.151196
|
||||
0.0608858 -0.26438525 0.151196
|
||||
-0.375039 -0.4375 -0.47711
|
||||
-0.375039 -0.3125 -0.47711
|
||||
-0.375039 -0.1875 -0.47711
|
||||
-0.375039 -0.0625 -0.47711
|
||||
-0.375039 0.0625 -0.47711
|
||||
-0.375039 0.1875 -0.47711
|
||||
-0.375039 0.3125 -0.47711
|
||||
-0.375039 0.4375 -0.47711
|
||||
0.00639485 -0.185847 0.151196
|
||||
-0.10258705 -0.185847 0.151196
|
||||
-0.10258705 0.5 0.151196
|
||||
0.00639485 0.5 0.151196
|
||||
0.0063952 -0.5 -0.47711
|
||||
-0.102586 -0.5 -0.47711
|
||||
-0.2115672 -0.5 -0.47711
|
||||
-0.3205484 -0.5 -0.47711
|
||||
-0.3205484 0.5 -0.47711
|
||||
-0.2115672 0.5 -0.47711
|
||||
-0.102586 0.5 -0.47711
|
||||
0.0063952 0.5 -0.47711
|
||||
-0.157078 -0.1429815625 0.47711
|
||||
-0.157078 -0.0572506875 0.47711
|
||||
-0.157078 0.0284801875 0.47711
|
||||
-0.157078 0.1142110625 0.47711
|
||||
-0.157078 0.1999419375 0.47711
|
||||
-0.157078 0.2856728125 0.47711
|
||||
-0.157078 0.3714036875 0.47711
|
||||
-0.157078 0.4571345625 0.47711
|
||||
-0.157078 0.4571345625 0.151196
|
||||
-0.157078 0.3714036875 0.151196
|
||||
-0.157078 0.2856728125 0.151196
|
||||
-0.157078 0.1999419375 0.151196
|
||||
-0.157078 0.1142110625 0.151196
|
||||
-0.157078 0.0284801875 0.151196
|
||||
-0.157078 -0.0572506875 0.151196
|
||||
-0.157078 -0.1429815625 0.151196
|
||||
-0.157078 0.5 0.19193525
|
||||
-0.157078 0.5 0.27341375
|
||||
-0.157078 0.5 0.35489225
|
||||
-0.157078 0.5 0.43637075
|
||||
-0.157078 -0.185847 0.43637075
|
||||
-0.157078 -0.185847 0.35489225
|
||||
-0.157078 -0.185847 0.27341375
|
||||
-0.157078 -0.185847 0.19193525
|
||||
3 3 0 1
|
||||
3 3 1 2
|
||||
3 5 3 2
|
||||
3 5 2 4
|
||||
3 7 5 4
|
||||
3 7 4 6
|
||||
3 9 7 6
|
||||
3 9 6 8
|
||||
3 11 9 8
|
||||
3 11 8 10
|
||||
3 13 11 10
|
||||
3 13 10 12
|
||||
3 15 13 12
|
||||
3 17 14 16
|
||||
3 19 17 16
|
||||
3 23 21 20
|
||||
3 23 20 22
|
||||
3 25 23 22
|
||||
3 25 22 24
|
||||
3 27 25 24
|
||||
3 27 24 26
|
||||
3 29 27 26
|
||||
3 29 26 28
|
||||
3 31 29 28
|
||||
3 31 28 30
|
||||
3 33 31 30
|
||||
3 33 30 32
|
||||
3 35 33 32
|
||||
3 35 32 34
|
||||
3 37 35 34
|
||||
3 37 34 36
|
||||
3 39 37 36
|
||||
3 39 36 38
|
||||
3 41 39 38
|
||||
3 41 38 40
|
||||
3 43 41 40
|
||||
3 43 40 42
|
||||
3 45 43 42
|
||||
3 45 42 44
|
||||
3 47 45 44
|
||||
3 47 44 46
|
||||
3 49 47 46
|
||||
3 49 46 48
|
||||
3 51 49 48
|
||||
3 51 48 50
|
||||
3 53 51 50
|
||||
3 53 50 52
|
||||
3 55 53 52
|
||||
3 55 52 54
|
||||
3 57 55 54
|
||||
3 57 54 56
|
||||
3 59 57 56
|
||||
3 59 56 58
|
||||
3 61 59 58
|
||||
3 61 58 60
|
||||
3 63 61 60
|
||||
3 63 60 62
|
||||
3 65 63 62
|
||||
3 65 62 64
|
||||
3 67 65 64
|
||||
3 67 64 66
|
||||
3 69 67 66
|
||||
3 69 66 68
|
||||
3 71 69 68
|
||||
3 71 68 70
|
||||
3 73 71 70
|
||||
3 77 75 74
|
||||
3 77 74 76
|
||||
3 79 77 76
|
||||
3 79 76 78
|
||||
3 0 79 78
|
||||
3 0 78 1
|
||||
3 99 28 26
|
||||
3 30 28 99
|
||||
3 99 26 24
|
||||
3 32 30 99
|
||||
3 99 24 22
|
||||
3 34 32 99
|
||||
3 80 52 101
|
||||
3 83 60 58
|
||||
3 90 70 89
|
||||
3 99 22 20
|
||||
3 36 34 99
|
||||
3 20 126 99
|
||||
3 124 38 36
|
||||
3 10 97 98
|
||||
3 97 8 6
|
||||
3 97 6 4
|
||||
3 96 2 95
|
||||
3 89 70 68
|
||||
3 87 66 64
|
||||
3 101 52 50
|
||||
3 101 50 48
|
||||
3 100 48 46
|
||||
3 120 29 31
|
||||
3 27 29 120
|
||||
3 120 31 33
|
||||
3 25 27 120
|
||||
3 120 33 35
|
||||
3 23 25 120
|
||||
3 123 95 102
|
||||
3 55 115 116
|
||||
3 120 35 37
|
||||
3 103 79 0
|
||||
3 113 59 61
|
||||
3 37 39 127
|
||||
3 19 21 120
|
||||
3 118 49 51
|
||||
3 118 51 53
|
||||
3 118 53 55
|
||||
3 111 61 63
|
||||
3 111 63 65
|
||||
3 123 0 3
|
||||
3 123 3 5
|
||||
3 122 123 5
|
||||
3 122 5 7
|
||||
3 122 7 9
|
||||
3 122 9 11
|
||||
3 122 11 13
|
||||
3 13 133 269
|
||||
3 15 17 133
|
||||
3 133 17 19
|
||||
3 88 109 108
|
||||
3 88 108 89
|
||||
3 87 110 109
|
||||
3 87 109 88
|
||||
3 86 111 110
|
||||
3 86 110 87
|
||||
3 85 112 111
|
||||
3 85 111 86
|
||||
3 84 113 112
|
||||
3 84 112 85
|
||||
3 83 113 84
|
||||
3 82 114 83
|
||||
3 81 116 115
|
||||
3 81 115 82
|
||||
3 80 116 81
|
||||
3 101 118 117
|
||||
3 101 117 80
|
||||
3 100 119 118
|
||||
3 100 118 101
|
||||
3 97 122 121
|
||||
3 96 123 122
|
||||
3 96 122 97
|
||||
3 95 123 96
|
||||
3 92 105 104
|
||||
3 92 104 93
|
||||
3 91 106 105
|
||||
3 91 105 92
|
||||
3 90 107 106
|
||||
3 90 106 91
|
||||
3 89 108 107
|
||||
3 89 107 90
|
||||
3 131 128 129
|
||||
3 131 129 279
|
||||
3 119 124 259
|
||||
3 119 100 271
|
||||
3 120 127 266
|
||||
3 120 124 99
|
||||
3 120 99 126
|
||||
3 120 126 134
|
||||
3 120 134 132
|
||||
3 128 135 136
|
||||
3 128 136 129
|
||||
3 129 136 137
|
||||
3 129 137 138
|
||||
3 230 121 270
|
||||
3 231 129 299
|
||||
3 229 133 295
|
||||
3 132 130 298
|
||||
3 130 132 131
|
||||
3 131 132 134
|
||||
3 172 128 131
|
||||
3 135 126 125
|
||||
3 135 125 136
|
||||
3 167 168 134
|
||||
3 134 168 169
|
||||
3 166 167 134
|
||||
3 134 169 170
|
||||
3 165 166 134
|
||||
3 165 134 126
|
||||
3 164 165 126
|
||||
3 163 164 126
|
||||
3 162 163 126
|
||||
3 161 162 126
|
||||
3 160 161 126
|
||||
3 159 160 126
|
||||
3 158 159 126
|
||||
3 157 158 126
|
||||
3 156 157 126
|
||||
3 134 170 171
|
||||
3 134 171 172
|
||||
3 128 172 173
|
||||
3 128 173 174
|
||||
3 128 174 175
|
||||
3 128 175 176
|
||||
3 128 176 177
|
||||
3 128 177 178
|
||||
3 128 178 179
|
||||
3 128 179 180
|
||||
3 128 180 141
|
||||
3 135 128 141
|
||||
3 135 141 142
|
||||
3 135 142 143
|
||||
3 135 143 144
|
||||
3 135 144 145
|
||||
3 135 145 146
|
||||
3 135 146 147
|
||||
3 135 147 148
|
||||
3 135 148 149
|
||||
3 135 149 150
|
||||
3 135 150 151
|
||||
3 155 156 126
|
||||
3 155 126 135
|
||||
3 154 155 135
|
||||
3 153 154 135
|
||||
3 152 153 135
|
||||
3 135 151 152
|
||||
3 136 125 98
|
||||
3 136 98 137
|
||||
3 202 203 98
|
||||
3 98 203 204
|
||||
3 201 202 98
|
||||
3 98 204 205
|
||||
3 200 201 98
|
||||
3 200 98 257
|
||||
3 199 200 140
|
||||
3 198 199 140
|
||||
3 197 198 140
|
||||
3 196 197 140
|
||||
3 195 196 140
|
||||
3 194 195 140
|
||||
3 193 194 140
|
||||
3 192 193 140
|
||||
3 191 192 140
|
||||
3 98 205 206
|
||||
3 137 98 206
|
||||
3 137 206 207
|
||||
3 137 207 208
|
||||
3 137 208 209
|
||||
3 137 209 210
|
||||
3 137 210 211
|
||||
3 137 211 212
|
||||
3 137 212 213
|
||||
3 137 213 214
|
||||
3 137 214 215
|
||||
3 137 215 216
|
||||
3 138 137 216
|
||||
3 138 216 217
|
||||
3 138 217 218
|
||||
3 138 218 219
|
||||
3 138 219 220
|
||||
3 138 220 181
|
||||
3 138 181 182
|
||||
3 138 182 183
|
||||
3 138 183 184
|
||||
3 138 184 185
|
||||
3 138 185 186
|
||||
3 190 191 140
|
||||
3 190 140 138
|
||||
3 189 190 138
|
||||
3 188 189 138
|
||||
3 187 188 138
|
||||
3 138 186 187
|
||||
3 138 140 267
|
||||
3 138 139 302
|
||||
3 184 183 178
|
||||
3 184 178 177
|
||||
3 183 182 179
|
||||
3 183 179 178
|
||||
3 182 181 180
|
||||
3 182 180 179
|
||||
3 181 220 141
|
||||
3 181 141 180
|
||||
3 220 219 142
|
||||
3 220 142 141
|
||||
3 219 218 143
|
||||
3 219 143 142
|
||||
3 218 217 144
|
||||
3 218 144 143
|
||||
3 217 216 145
|
||||
3 217 145 144
|
||||
3 216 215 146
|
||||
3 216 146 145
|
||||
3 215 214 147
|
||||
3 215 147 146
|
||||
3 214 213 148
|
||||
3 214 148 147
|
||||
3 213 212 149
|
||||
3 213 149 148
|
||||
3 212 211 150
|
||||
3 212 150 149
|
||||
3 211 210 151
|
||||
3 211 151 150
|
||||
3 210 209 152
|
||||
3 210 152 151
|
||||
3 209 208 153
|
||||
3 209 153 152
|
||||
3 208 207 154
|
||||
3 208 154 153
|
||||
3 207 206 155
|
||||
3 207 155 154
|
||||
3 206 205 156
|
||||
3 206 156 155
|
||||
3 205 204 157
|
||||
3 205 157 156
|
||||
3 204 203 158
|
||||
3 204 158 157
|
||||
3 203 202 159
|
||||
3 203 159 158
|
||||
3 202 201 160
|
||||
3 202 160 159
|
||||
3 201 200 161
|
||||
3 201 161 160
|
||||
3 200 199 162
|
||||
3 200 162 161
|
||||
3 199 198 163
|
||||
3 199 163 162
|
||||
3 198 197 164
|
||||
3 198 164 163
|
||||
3 197 196 165
|
||||
3 197 165 164
|
||||
3 196 195 166
|
||||
3 196 166 165
|
||||
3 195 194 167
|
||||
3 195 167 166
|
||||
3 194 193 168
|
||||
3 194 168 167
|
||||
3 193 192 169
|
||||
3 193 169 168
|
||||
3 192 191 170
|
||||
3 192 170 169
|
||||
3 191 190 171
|
||||
3 191 171 170
|
||||
3 190 189 172
|
||||
3 190 172 171
|
||||
3 189 188 173
|
||||
3 189 173 172
|
||||
3 188 187 174
|
||||
3 188 174 173
|
||||
3 187 186 175
|
||||
3 187 175 174
|
||||
3 186 185 176
|
||||
3 186 176 175
|
||||
3 185 184 177
|
||||
3 185 177 176
|
||||
3 121 139 268
|
||||
3 97 121 140
|
||||
3 115 55 57
|
||||
3 115 57 59
|
||||
3 113 83 114
|
||||
3 59 113 114
|
||||
3 114 82 115
|
||||
3 114 115 59
|
||||
3 117 118 55
|
||||
3 116 80 117
|
||||
3 116 117 55
|
||||
3 132 133 19
|
||||
3 127 41 43
|
||||
3 39 41 127
|
||||
3 105 75 77
|
||||
3 105 77 79
|
||||
3 103 93 104
|
||||
3 79 103 104
|
||||
3 104 105 79
|
||||
3 106 73 75
|
||||
3 65 67 110
|
||||
3 61 111 112
|
||||
3 112 113 61
|
||||
3 110 67 69
|
||||
3 69 71 109
|
||||
3 109 110 69
|
||||
3 108 109 71
|
||||
3 71 73 107
|
||||
3 106 107 73
|
||||
3 75 105 106
|
||||
3 13 15 133
|
||||
3 121 122 13
|
||||
3 102 103 0
|
||||
3 0 123 102
|
||||
3 45 47 119
|
||||
3 49 118 119
|
||||
3 47 49 119
|
||||
3 127 43 45
|
||||
3 45 119 278
|
||||
3 97 140 258
|
||||
3 125 16 14
|
||||
3 14 12 98
|
||||
3 15 12 14
|
||||
3 127 120 37
|
||||
3 110 111 65
|
||||
3 107 108 71
|
||||
3 98 125 14
|
||||
3 131 134 172
|
||||
3 94 93 103
|
||||
3 94 102 95
|
||||
3 95 1 94
|
||||
3 93 1 78
|
||||
3 1 93 94
|
||||
3 1 95 2
|
||||
3 4 96 97
|
||||
3 2 96 4
|
||||
3 78 92 93
|
||||
3 92 78 76
|
||||
3 91 76 74
|
||||
3 74 90 91
|
||||
3 88 68 66
|
||||
3 86 64 62
|
||||
3 85 62 60
|
||||
3 85 60 84
|
||||
3 82 58 56
|
||||
3 81 56 54
|
||||
3 80 54 52
|
||||
3 124 36 99
|
||||
3 10 98 12
|
||||
3 60 83 84
|
||||
3 46 124 274
|
||||
3 44 124 46
|
||||
3 42 124 44
|
||||
3 40 124 42
|
||||
3 38 124 40
|
||||
3 97 10 8
|
||||
3 66 87 88
|
||||
3 48 100 101
|
||||
3 102 94 103
|
||||
3 76 91 92
|
||||
3 72 74 75
|
||||
3 68 88 89
|
||||
3 64 86 87
|
||||
3 62 85 86
|
||||
3 58 82 83
|
||||
3 56 81 82
|
||||
3 54 80 81
|
||||
3 126 16 125
|
||||
3 17 15 14
|
||||
3 120 132 19
|
||||
3 21 19 20
|
||||
3 23 120 21
|
||||
3 16 18 19
|
||||
3 19 18 20
|
||||
3 20 18 126
|
||||
3 16 126 18
|
||||
3 90 74 72
|
||||
3 73 70 72
|
||||
3 72 70 90
|
||||
3 72 75 73
|
||||
3 119 221 263
|
||||
3 120 221 262
|
||||
3 131 222 283
|
||||
3 133 222 282
|
||||
3 121 223 291
|
||||
3 129 223 290
|
||||
3 119 224 261
|
||||
3 120 224 260
|
||||
3 227 225 265
|
||||
3 120 225 264
|
||||
3 119 226 273
|
||||
3 46 226 272
|
||||
3 225 227 277
|
||||
3 45 227 276
|
||||
3 131 228 281
|
||||
3 133 228 280
|
||||
3 131 229 285
|
||||
3 133 229 284
|
||||
3 121 230 289
|
||||
3 129 230 288
|
||||
3 121 231 293
|
||||
3 129 231 292
|
||||
3 248 232 297
|
||||
3 132 232 296
|
||||
3 252 233 301
|
||||
3 138 233 300
|
||||
3 200 234 258
|
||||
3 97 234 257
|
||||
3 119 235 260
|
||||
3 120 235 259
|
||||
3 119 236 262
|
||||
3 120 236 261
|
||||
3 119 237 264
|
||||
3 120 237 263
|
||||
3 243 238 266
|
||||
3 120 238 265
|
||||
3 138 239 268
|
||||
3 121 239 267
|
||||
3 13 240 270
|
||||
3 249 240 269
|
||||
3 119 241 272
|
||||
3 46 241 271
|
||||
3 119 242 274
|
||||
3 46 242 273
|
||||
3 238 243 276
|
||||
3 45 243 275
|
||||
3 225 244 278
|
||||
3 45 244 277
|
||||
3 131 245 280
|
||||
3 133 245 279
|
||||
3 131 246 282
|
||||
3 133 246 281
|
||||
3 131 247 284
|
||||
3 133 247 283
|
||||
3 131 248 286
|
||||
3 232 248 285
|
||||
3 240 249 288
|
||||
3 129 249 287
|
||||
3 121 250 290
|
||||
3 129 250 289
|
||||
3 121 251 292
|
||||
3 129 251 291
|
||||
3 121 252 294
|
||||
3 233 252 293
|
||||
3 229 253 296
|
||||
3 132 253 295
|
||||
3 286 254 298
|
||||
3 132 254 297
|
||||
3 231 255 300
|
||||
3 138 255 299
|
||||
3 294 256 302
|
||||
3 138 256 301
|
||||
3 257 234 200
|
||||
3 257 98 97
|
||||
3 258 140 200
|
||||
3 258 234 97
|
||||
3 259 235 119
|
||||
3 259 124 120
|
||||
3 260 224 119
|
||||
3 260 235 120
|
||||
3 261 236 119
|
||||
3 261 224 120
|
||||
3 262 221 119
|
||||
3 262 236 120
|
||||
3 263 237 119
|
||||
3 263 221 120
|
||||
3 264 225 119
|
||||
3 264 237 120
|
||||
3 265 238 227
|
||||
3 265 225 120
|
||||
3 266 127 275
|
||||
3 266 238 120
|
||||
3 267 239 138
|
||||
3 267 140 121
|
||||
3 268 139 138
|
||||
3 268 239 121
|
||||
3 269 240 13
|
||||
3 269 133 287
|
||||
3 270 121 13
|
||||
3 270 240 230
|
||||
3 271 241 119
|
||||
3 271 100 46
|
||||
3 272 226 119
|
||||
3 272 241 46
|
||||
3 273 242 119
|
||||
3 273 226 46
|
||||
3 274 124 119
|
||||
3 274 242 46
|
||||
3 275 243 266
|
||||
3 275 127 45
|
||||
3 276 227 238
|
||||
3 276 243 45
|
||||
3 277 244 225
|
||||
3 277 227 45
|
||||
3 278 119 225
|
||||
3 278 244 45
|
||||
3 279 245 131
|
||||
3 279 129 133
|
||||
3 280 228 131
|
||||
3 280 245 133
|
||||
3 281 246 131
|
||||
3 281 228 133
|
||||
3 282 222 131
|
||||
3 282 246 133
|
||||
3 283 247 131
|
||||
3 283 222 133
|
||||
3 284 229 131
|
||||
3 284 247 133
|
||||
3 285 248 131
|
||||
3 285 229 232
|
||||
3 286 130 131
|
||||
3 286 248 254
|
||||
3 287 249 269
|
||||
3 287 133 129
|
||||
3 288 230 240
|
||||
3 288 249 129
|
||||
3 289 250 121
|
||||
3 289 230 129
|
||||
3 290 223 121
|
||||
3 290 250 129
|
||||
3 291 251 121
|
||||
3 291 223 129
|
||||
3 292 231 121
|
||||
3 292 251 129
|
||||
3 293 252 121
|
||||
3 293 231 233
|
||||
3 294 139 121
|
||||
3 294 252 256
|
||||
3 295 253 229
|
||||
3 295 133 132
|
||||
3 296 232 229
|
||||
3 296 253 132
|
||||
3 297 254 248
|
||||
3 297 232 132
|
||||
3 298 130 286
|
||||
3 298 254 132
|
||||
3 299 255 231
|
||||
3 299 129 138
|
||||
3 300 233 231
|
||||
3 300 255 138
|
||||
3 301 256 252
|
||||
3 301 233 138
|
||||
3 302 139 294
|
||||
3 302 256 138
|
||||
|
||||
|
|
@ -0,0 +1,187 @@
|
|||
// data/joint_refined.off 0.1 5 data/joint-patch.selection.txt
|
||||
|
||||
#define CGAL_PMP_REMESHING_DEBUG
|
||||
//#define CGAL_DUMP_REMESHING_STEPS
|
||||
#define CGAL_PMP_REMESHING_VERBOSE
|
||||
//#define CGAL_PMP_REMESHING_EXPENSIVE_DEBUG
|
||||
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <CGAL/boost/graph/graph_traits_Surface_mesh.h>
|
||||
|
||||
#include <CGAL/Polygon_mesh_processing/remesh.h>
|
||||
#include <CGAL/Polygon_mesh_processing/border.h>
|
||||
#include <CGAL/Polygon_mesh_processing/connected_components.h>
|
||||
#include <CGAL/Polygon_mesh_processing/self_intersections.h>
|
||||
|
||||
#include <CGAL/Timer.h>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||
typedef CGAL::Surface_mesh<K::Point_3> Mesh;
|
||||
|
||||
typedef boost::graph_traits<Mesh>::halfedge_descriptor halfedge_descriptor;
|
||||
typedef boost::graph_traits<Mesh>::edge_descriptor edge_descriptor;
|
||||
typedef boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
|
||||
typedef boost::graph_traits<Mesh>::face_descriptor face_descriptor;
|
||||
|
||||
void collect_patch(const char* file,
|
||||
const Mesh& m,
|
||||
std::set<face_descriptor>& patch)
|
||||
{
|
||||
std::ifstream in(file);
|
||||
if (!in.is_open())
|
||||
return;
|
||||
|
||||
std::string line;
|
||||
std::size_t id;
|
||||
|
||||
if (!std::getline(in, line)) { return ; }
|
||||
std::istringstream vertex_line(line);
|
||||
while (vertex_line >> id) {
|
||||
if (id >= m.number_of_vertices()) { return ; }
|
||||
//do nothing with vertices
|
||||
}
|
||||
|
||||
if (!std::getline(in, line)) { return ; }
|
||||
std::istringstream facet_line(line);
|
||||
while (facet_line >> id) {
|
||||
if (id >= m.number_of_faces()) { return; }
|
||||
patch.insert(Mesh::Face_index(Mesh::size_type(id)));
|
||||
}
|
||||
|
||||
if (!std::getline(in, line)) { return ; }
|
||||
std::istringstream edge_line(line);
|
||||
while (edge_line >> id) {
|
||||
if (id >= m.number_of_edges()) { return; }
|
||||
//do nothing with edges
|
||||
}
|
||||
|
||||
in.close();
|
||||
}
|
||||
|
||||
void test_precondition(const char* filename,
|
||||
const char* bad_selection_file)
|
||||
{
|
||||
Mesh m;
|
||||
std::ifstream input(filename);
|
||||
if (!input || !(input >> m)){
|
||||
std::cerr << "Error: can not read file.\n";
|
||||
return;
|
||||
}
|
||||
std::set<face_descriptor> patch;
|
||||
collect_patch(bad_selection_file, m, patch);
|
||||
|
||||
std::cout << "Start remeshing of " << bad_selection_file
|
||||
<< " (" << patch.size() << " faces)..." << std::endl;
|
||||
|
||||
#ifndef CGAL_NDEBUG //o.w. CGAL_precondition not tested
|
||||
bool exception_caught = false;
|
||||
try
|
||||
{
|
||||
PMP::isotropic_remeshing(m, patch, 0.079,
|
||||
PMP::parameters::protect_constraints(true));
|
||||
}
|
||||
catch (const std::exception &)
|
||||
{
|
||||
exception_caught = true;
|
||||
}
|
||||
CGAL_assertion(exception_caught);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct halfedge2edge
|
||||
{
|
||||
halfedge2edge(const Mesh& m, std::vector<edge_descriptor>& edges)
|
||||
: m_mesh(m), m_edges(edges)
|
||||
{}
|
||||
void operator()(const halfedge_descriptor& h) const
|
||||
{
|
||||
m_edges.push_back(edge(h, m_mesh));
|
||||
}
|
||||
const Mesh& m_mesh;
|
||||
std::vector<edge_descriptor>& m_edges;
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
#ifdef CGAL_PMP_REMESHING_DEBUG
|
||||
std::cout.precision(17);
|
||||
#endif
|
||||
|
||||
const char* filename = (argc > 1) ? argv[1]
|
||||
: "data/joint_refined.off";
|
||||
std::ifstream input(filename);
|
||||
|
||||
Mesh m;
|
||||
if (!input || !(input >> m)){
|
||||
std::cerr << "Error: can not read file.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
double target_edge_length = (argc > 2) ? atof(argv[2]) : 0.079;
|
||||
unsigned int nb_iter = (argc > 3) ? atoi(argv[3]) : 1;
|
||||
const char* selection_file = (argc > 4) ? argv[4]
|
||||
: "data/joint-patch.selection.txt";
|
||||
|
||||
std::set<face_descriptor> pre_patch;
|
||||
collect_patch(selection_file, m, pre_patch);
|
||||
|
||||
std::cout << "Test self intersections...";
|
||||
std::vector<std::pair<face_descriptor, face_descriptor> > facets;
|
||||
PMP::self_intersections(pre_patch,
|
||||
m,
|
||||
std::back_inserter(facets));
|
||||
if(!facets.empty())
|
||||
{
|
||||
std::cout << "Input is self intersecting. STOP" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
std::cout << "OK." << std::endl;
|
||||
|
||||
std::cout << "Split border...";
|
||||
|
||||
std::vector<edge_descriptor> border;
|
||||
PMP::border_halfedges(pre_patch,
|
||||
boost::make_function_output_iterator(halfedge2edge(m, border)),
|
||||
m);
|
||||
PMP::split_long_edges(m, border, target_edge_length);
|
||||
|
||||
std::cout << "done." << std::endl;
|
||||
|
||||
std::set<face_descriptor> patch;
|
||||
std::copy(pre_patch.begin(), pre_patch.end(),
|
||||
std::inserter(patch, patch.begin()));
|
||||
|
||||
std::cout << "Start remeshing of " << selection_file
|
||||
<< " (" << patch.size() << " faces)..." << std::endl;
|
||||
|
||||
CGAL::Timer t;
|
||||
t.start();
|
||||
|
||||
PMP::isotropic_remeshing(m,
|
||||
patch,
|
||||
target_edge_length,
|
||||
PMP::parameters::number_of_iterations(nb_iter)
|
||||
.protect_constraints(true)
|
||||
);
|
||||
|
||||
t.stop();
|
||||
std::cout << "Remeshing took " << t.time() << std::endl;
|
||||
|
||||
std::ofstream out("remeshed.off");
|
||||
out << m;
|
||||
out.close();
|
||||
|
||||
//this test should make the precondition fail
|
||||
test_precondition("data/joint_refined.off",
|
||||
"data/joint-patch-toolargeconstraints.selection.txt");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -91,6 +91,7 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND)
|
|||
Polyhedron_demo_mesh_3_local_optimizers_dialog.ui
|
||||
Polyhedron_demo_mesh_3_smoother_dialog.ui )
|
||||
qt5_wrap_ui( cameraUI_FILES Camera_positions_list.ui )
|
||||
qt5_wrap_ui( isotropicRemeshingUI_FILES Polyhedron_demo_isotropic_remeshing_dialog.ui)
|
||||
qt5_wrap_ui( PreferencesUI_FILES Preferences.ui )
|
||||
qt5_wrap_ui( point_inside_polyhedronUI_FILES Point_inside_polyhedron_widget.ui)
|
||||
qt5_wrap_ui( point_set_selectionUI_FILES Point_set_selection_widget.ui)
|
||||
|
|
@ -442,8 +443,11 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND)
|
|||
polyhedron_demo_plugin(corefinement_plugin Polyhedron_demo_corefinement_plugin)
|
||||
target_link_libraries(corefinement_plugin scene_polyhedron_item scene_combinatorial_map_item scene_polylines_item)
|
||||
|
||||
polyhedron_demo_plugin(trivial_plugin Polyhedron_demo_trivial_plugin)
|
||||
polyhedron_demo_plugin(repair_polyhedron_plugin Polyhedron_demo_repair_polyhedron_plugin)
|
||||
target_link_libraries(repair_polyhedron_plugin scene_polyhedron_item)
|
||||
|
||||
polyhedron_demo_plugin(trivial_plugin Polyhedron_demo_trivial_plugin)
|
||||
|
||||
# Edit polyhedron scene item and plugin
|
||||
if ( EIGEN3_FOUND AND "${EIGEN3_VERSION}" VERSION_GREATER "3.1.90" )
|
||||
qt5_wrap_ui( editionUI_FILES Deform_mesh.ui )
|
||||
|
|
@ -513,6 +517,14 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND)
|
|||
|
||||
polyhedron_demo_plugin(shortest_path_plugin Polyhedron_demo_shortest_path_plugin ${shortestPathUI_FILES})
|
||||
target_link_libraries(shortest_path_plugin scene_polyhedron_item scene_polylines_item scene_polyhedron_selection_item scene_polyhedron_shortest_path_item scene_basic_objects)
|
||||
|
||||
polyhedron_demo_plugin(detect_sharp_edges_plugin Polyhedron_demo_detect_sharp_edges_plugin)
|
||||
target_link_libraries(detect_sharp_edges_plugin scene_polyhedron_item)
|
||||
|
||||
|
||||
polyhedron_demo_plugin(isotropic_remeshing_plugin Polyhedron_demo_isotropic_remeshing_plugin ${isotropicRemeshingUI_FILES})
|
||||
target_link_libraries(isotropic_remeshing_plugin scene_polyhedron_item scene_polyhedron_selection_item)
|
||||
|
||||
|
||||
|
||||
qt5_wrap_ui( exampleUI_FILES Polyhedron_demo_example_plugin.ui dock_example.ui)
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>357</width>
|
||||
<height>491</height>
|
||||
<width>568</width>
|
||||
<height>588</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
<string>Selection</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="2" column="1" rowspan="2" colspan="3">
|
||||
<item row="2" column="1" rowspan="2" colspan="2">
|
||||
<layout class="QVBoxLayout" name="RingLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
|
|
@ -57,7 +57,7 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="5">
|
||||
<item row="4" column="0" colspan="4">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QPushButton" name="SelectAllVerticesPushButton">
|
||||
|
|
@ -104,7 +104,7 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="4" rowspan="2">
|
||||
<item row="2" column="3" rowspan="2">
|
||||
<widget class="QGroupBox" name="InsertEraseGroupBox">
|
||||
<layout class="QVBoxLayout" name="InsertRemoveLayout">
|
||||
<item>
|
||||
|
|
@ -127,6 +127,47 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="4">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="ReadROIPushButton">
|
||||
<property name="text">
|
||||
<string>Load ROI / Control Vertices</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="ShowAsSphereCheckBox">
|
||||
<property name="text">
|
||||
<string>Show As Sphere</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="ShowROICheckBox">
|
||||
<property name="text">
|
||||
<string>Show ROI</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="SaveROIPushButton">
|
||||
<property name="text">
|
||||
<string>Save ROI / Control Vertices</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -178,6 +219,78 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="remeshing_groupBox">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::DefaultContextMenu</enum>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Remeshing</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_10">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9" stretch="0,0,0">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="RemeshingCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Warning : after remeshing all ROI and control vertices will be unselected. "Discard changes" will be unavailable.</string>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remesh after deformation</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="remeshingEdgeLengthInput_checkBox">
|
||||
<property name="toolTip">
|
||||
<string>If unchecked, automatic value is used (the average edge length at ROI boundary)</string>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::RightToLeft</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Target edge length</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::RightToLeft</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Nb. iterations</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="remeshing_edge_length_spinbox"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="remeshing_iterations_spinbox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="CtrlVertGroupNavigationGroupBox">
|
||||
<property name="title">
|
||||
|
|
@ -227,45 +340,26 @@
|
|||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="ActivatePivotingCheckBox">
|
||||
<property name="text">
|
||||
<string>Activate Pivoting </string>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_11">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="ActivatePivotingCheckBox">
|
||||
<property name="text">
|
||||
<string>Activate Pivoting </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="ActivateFixedPlaneCheckBox">
|
||||
<property name="text">
|
||||
<string>Activate Fixed Plane Deformation</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="OverwritePushButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Update Original Positions</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
|
|
@ -273,75 +367,51 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="ShowROICheckBox">
|
||||
<property name="text">
|
||||
<string>Show ROI</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="ShowAsSphereCheckBox">
|
||||
<property name="text">
|
||||
<string>Show As Sphere</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="QPushButton" name="SaveROIPushButton">
|
||||
<property name="text">
|
||||
<string>Save ROI / Control Vertices</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="ReadROIPushButton">
|
||||
<property name="text">
|
||||
<string>Load ROI / Control Vertices</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="ApplyAndCloseLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="ApplyAndClosePushButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Apply and Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="2" column="0">
|
||||
<widget class="QPushButton" name="DiscardChangesPushButton">
|
||||
<property name="toolTip">
|
||||
<string>Reset mesh to last version saved by "Overwrite Initial Geometry". Not available when Remeshing is ON.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Discard changes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="OverwritePushButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Overwrite Initial Geometry</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="ApplyAndClosePushButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Apply and Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
#ifndef POLYHEDRON_DEMO_DETECT_SHARP_EDGES_H
|
||||
#define POLYHEDRON_DEMO_DETECT_SHARP_EDGES_H
|
||||
|
||||
#include <CGAL/Mesh_3/Detect_features_in_polyhedra.h>
|
||||
|
||||
namespace CGAL
|
||||
{
|
||||
template<typename Polyhedron>
|
||||
void reset_sharp_edges(Polyhedron* pMesh)
|
||||
{
|
||||
for (typename Polyhedron::Edge_iterator
|
||||
eit = pMesh->edges_begin(),
|
||||
end = pMesh->edges_end(); eit != end; ++eit)
|
||||
{
|
||||
eit->set_feature_edge(false);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Polyhedron>
|
||||
void detect_sharp_edges(Polyhedron* pMesh, const double angle)
|
||||
{
|
||||
reset_sharp_edges(pMesh);
|
||||
|
||||
// Detect edges in current polyhedron
|
||||
CGAL::Mesh_3::Detect_features_in_polyhedra<Polyhedron> detect_features;
|
||||
detect_features.detect_sharp_edges(*pMesh, angle);
|
||||
}
|
||||
|
||||
}//end namespace CGAL
|
||||
|
||||
#endif //POLYHEDRON_DEMO_DETECT_SHARP_EDGES_H
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
#include <QApplication>
|
||||
#include <QMainWindow>
|
||||
#include <QAction>
|
||||
#include <QStringList>
|
||||
#include <QInputDialog>
|
||||
#include <QtPlugin>
|
||||
|
||||
#include "Scene_polyhedron_item.h"
|
||||
#include "Scene_polygon_soup_item.h"
|
||||
#include "Polyhedron_type.h"
|
||||
|
||||
#include <CGAL/Three/Polyhedron_demo_plugin_helper.h>
|
||||
#include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
|
||||
|
||||
#include "Polyhedron_demo_detect_sharp_edges.h"
|
||||
|
||||
using namespace CGAL::Three;
|
||||
class Polyhedron_demo_detect_sharp_edges_plugin :
|
||||
public QObject,
|
||||
public Polyhedron_demo_plugin_helper
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
|
||||
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0")
|
||||
|
||||
public:
|
||||
void init(QMainWindow* mainWindow, Scene_interface* scene_interface) {
|
||||
this->scene = scene_interface;
|
||||
this->mw = mainWindow;
|
||||
actionSharEdges = new QAction("Detect sharp features", mw);
|
||||
actionSharEdges->setObjectName("detectSharpFeaturesAction");
|
||||
if(actionSharEdges) {
|
||||
connect(actionSharEdges, SIGNAL(triggered()),
|
||||
this, SLOT(detectSharpEdgesWithInputDialog()));
|
||||
}
|
||||
}
|
||||
|
||||
bool applicable(QAction*) const {
|
||||
Q_FOREACH(int index, scene->selectionIndices())
|
||||
{
|
||||
Scene_polyhedron_item* item =
|
||||
qobject_cast<Scene_polyhedron_item*>(scene->item(index));
|
||||
if (item) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// used by Polyhedron_demo_plugin_helper
|
||||
QList<QAction*> actions() const {
|
||||
return QList<QAction*>() << actionSharEdges;
|
||||
}
|
||||
|
||||
public Q_SLOTS:
|
||||
void detectSharpEdges(bool input_dialog = false, double angle = 60);
|
||||
void detectSharpEdgesWithInputDialog();
|
||||
|
||||
protected:
|
||||
Kernel::Vector_3 facet_normal(Polyhedron::Facet_handle f);
|
||||
bool is_sharp(Polyhedron::Halfedge_handle he);
|
||||
|
||||
private:
|
||||
QAction* actionSharEdges;
|
||||
}; // end Polyhedron_demo_detect_sharp_edges_plugin
|
||||
|
||||
void Polyhedron_demo_detect_sharp_edges_plugin::detectSharpEdgesWithInputDialog()
|
||||
{
|
||||
detectSharpEdges(true);
|
||||
}
|
||||
|
||||
void Polyhedron_demo_detect_sharp_edges_plugin::detectSharpEdges(bool input_dialog,
|
||||
double angle)
|
||||
{
|
||||
typedef std::pair<int,Polyhedron*> Poly_tuple;
|
||||
|
||||
// Get selected items
|
||||
QList<Poly_tuple> polyhedrons;
|
||||
Q_FOREACH(int index, scene->selectionIndices())
|
||||
{
|
||||
Scene_polyhedron_item* item =
|
||||
qobject_cast<Scene_polyhedron_item*>(scene->item(index));
|
||||
if(!item)
|
||||
return;
|
||||
|
||||
Polyhedron* pMesh = item->polyhedron();
|
||||
if(!pMesh)
|
||||
return;
|
||||
item->show_feature_edges(true);
|
||||
polyhedrons << make_pair(index, pMesh);
|
||||
}
|
||||
|
||||
if(input_dialog) {
|
||||
bool ok = true;
|
||||
angle = QInputDialog::getDouble(NULL,
|
||||
tr("Sharp edges max angle"),
|
||||
tr("Angle in degrees between 0 and 180:"),
|
||||
angle, // value
|
||||
0., // min
|
||||
180., // max
|
||||
2, // decimals
|
||||
&ok);
|
||||
if(!ok) return;
|
||||
}
|
||||
// Detect edges
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
Q_FOREACH(Poly_tuple tuple, polyhedrons)
|
||||
{
|
||||
Polyhedron* pMesh = tuple.second;
|
||||
if (!pMesh) continue;
|
||||
|
||||
CGAL::detect_sharp_edges(pMesh, angle);
|
||||
|
||||
// update scene
|
||||
scene->itemChanged(tuple.first);
|
||||
}
|
||||
|
||||
// default cursor
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
//Q_EXPORT_PLUGIN2(Polyhedron_demo_detect_sharp_edges_plugin, Polyhedron_demo_detect_sharp_edges_plugin)
|
||||
|
||||
#include "Polyhedron_demo_detect_sharp_edges_plugin.moc"
|
||||
|
|
@ -39,6 +39,7 @@ public Q_SLOTS:
|
|||
void on_SelectAllVerticesPushButton_clicked();
|
||||
void on_DeleteCtrlVertPushButton_clicked();
|
||||
void on_ApplyAndClosePushButton_clicked();
|
||||
void on_DiscardChangesPushButton_clicked();
|
||||
void on_ClearROIPushButton_clicked();
|
||||
void on_ShowROICheckBox_stateChanged(int state);
|
||||
void on_ShowAsSphereCheckBox_stateChanged(int state);
|
||||
|
|
@ -113,6 +114,7 @@ void Polyhedron_demo_edit_polyhedron_plugin::init(QMainWindow* mainWindow, CGAL:
|
|||
connect(ui_widget.SelectAllVerticesPushButton, SIGNAL(clicked()), this, SLOT(on_SelectAllVerticesPushButton_clicked()));
|
||||
connect(ui_widget.DeleteCtrlVertPushButton, SIGNAL(clicked()), this, SLOT(on_DeleteCtrlVertPushButton_clicked()));
|
||||
connect(ui_widget.ApplyAndClosePushButton, SIGNAL(clicked()), this, SLOT(on_ApplyAndClosePushButton_clicked()));
|
||||
connect(ui_widget.DiscardChangesPushButton, SIGNAL(clicked()), this, SLOT(on_DiscardChangesPushButton_clicked()));
|
||||
connect(ui_widget.ClearROIPushButton, SIGNAL(clicked()), this, SLOT(on_ClearROIPushButton_clicked()));
|
||||
connect(ui_widget.ShowROICheckBox, SIGNAL(stateChanged(int)), this, SLOT(on_ShowROICheckBox_stateChanged(int)));
|
||||
connect(ui_widget.ShowAsSphereCheckBox, SIGNAL(stateChanged(int)), this, SLOT(on_ShowAsSphereCheckBox_stateChanged(int)));
|
||||
|
|
@ -201,6 +203,15 @@ void Polyhedron_demo_edit_polyhedron_plugin::on_ApplyAndClosePushButton_clicked(
|
|||
{
|
||||
dock_widget->setVisible(false);
|
||||
}
|
||||
void Polyhedron_demo_edit_polyhedron_plugin::on_DiscardChangesPushButton_clicked()
|
||||
{
|
||||
int item_id = scene->mainSelectionIndex();
|
||||
Scene_edit_polyhedron_item* edit_item = qobject_cast<Scene_edit_polyhedron_item*>(scene->item(item_id));
|
||||
if (!edit_item) return; // the selected item is not of the right type
|
||||
|
||||
edit_item->reset_deform_object();
|
||||
scene->itemChanged(edit_item); //for redraw
|
||||
}
|
||||
void Polyhedron_demo_edit_polyhedron_plugin::on_ShowROICheckBox_stateChanged(int /*state*/)
|
||||
{
|
||||
for(CGAL::Three::Scene_interface::Item_id i = 0, end = scene->numberOfEntries(); i < end; ++i)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <CGAL/Polygon_mesh_processing/triangulate_hole.h>
|
||||
#include <CGAL/Polygon_mesh_processing/refine.h>
|
||||
#include <CGAL/Polygon_mesh_processing/internal/named_function_params.h>
|
||||
#include <CGAL/Polyhedron_incremental_builder_3.h>
|
||||
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
|
||||
#include <CGAL/Timer.h>
|
||||
|
|
@ -26,6 +27,8 @@
|
|||
#include <boost/function_output_iterator.hpp>
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
|
||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
|
||||
template<class HDS>
|
||||
class Polyhedron_builder : public CGAL::Modifier_base<HDS> {
|
||||
public:
|
||||
|
|
@ -125,7 +128,9 @@ public Q_SLOTS:
|
|||
|
||||
CGAL::Timer timer; timer.start();
|
||||
std::vector<CGAL::Triple<int, int, int> > patch;
|
||||
CGAL::Polygon_mesh_processing::triangulate_hole_polyline(*it, std::back_inserter(patch), use_DT);
|
||||
CGAL::Polygon_mesh_processing::triangulate_hole_polyline(*it,
|
||||
std::back_inserter(patch),
|
||||
PMP::parameters::use_delaunay_triangulation(use_DT));
|
||||
print_message(QString("Triangulated in %1 sec.").arg(timer.time()));
|
||||
|
||||
if(patch.empty()) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,216 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Isotropic_remeshing_dialog</class>
|
||||
<widget class="QDialog" name="Isotropic_remeshing_dialog">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>414</width>
|
||||
<height>282</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Isotropic remeshing criteria</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="objectName">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>15</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>NO OBJECT</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="objectNameSize">
|
||||
<property name="text">
|
||||
<string>No size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Remesh</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="splitEdgesOnly_checkbox">
|
||||
<property name="text">
|
||||
<string>Split only border/selected edges</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Isotropic remeshing</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2" rowstretch="0,0,0,0" columnstretch="2,0">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="nbIterations_label">
|
||||
<property name="text">
|
||||
<string>Number of iterations</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>nbIterations_spinbox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="edgeLength_dspinbox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>110</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="nbIterations_spinbox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>110</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="protect_checkbox">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="edgeLength_label">
|
||||
<property name="text">
|
||||
<string>Target edge length</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>edgeLength_dspinbox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="protect_label">
|
||||
<property name="text">
|
||||
<string>Protect border/selected edges</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>edgeLength_dspinbox</tabstop>
|
||||
<tabstop>nbIterations_spinbox</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>Isotropic_remeshing_dialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>388</x>
|
||||
<y>288</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>195</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>Isotropic_remeshing_dialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>388</x>
|
||||
<y>288</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>195</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
|
@ -0,0 +1,249 @@
|
|||
//#define CGAL_PMP_REMESHING_VERBOSE
|
||||
//#define CGAL_PMP_REMESHING_DEBUG
|
||||
//#define CGAL_PMP_REMESHING_VERY_VERBOSE
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#include <CGAL/Three/Polyhedron_demo_plugin_helper.h>
|
||||
#include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
|
||||
|
||||
#include "Scene_polyhedron_item.h"
|
||||
#include "Scene_polyhedron_selection_item.h"
|
||||
#include "Polyhedron_type.h"
|
||||
|
||||
#include <CGAL/iterator.h>
|
||||
#include <CGAL/Polygon_mesh_processing/remesh.h>
|
||||
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
|
||||
|
||||
#include <QTime>
|
||||
#include <QAction>
|
||||
#include <QMainWindow>
|
||||
#include <QApplication>
|
||||
#include <QString>
|
||||
#include <QDialog>
|
||||
#include <QtPlugin>
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <queue>
|
||||
#include <sstream>
|
||||
|
||||
#include "ui_Polyhedron_demo_isotropic_remeshing_dialog.h"
|
||||
|
||||
using namespace CGAL::Three;
|
||||
class Polyhedron_demo_isotropic_remeshing_plugin :
|
||||
public QObject,
|
||||
public Polyhedron_demo_plugin_helper
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
|
||||
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0")
|
||||
|
||||
public:
|
||||
void init(QMainWindow* mainWindow, Scene_interface* scene_interface)
|
||||
{
|
||||
this->scene = scene_interface;
|
||||
this->mw = mainWindow;
|
||||
actionIsotropicRemeshing_ = new QAction("Isotropic remeshing", mw);
|
||||
if (actionIsotropicRemeshing_) {
|
||||
connect(actionIsotropicRemeshing_, SIGNAL(triggered()),
|
||||
this, SLOT(isotropic_remeshing()));
|
||||
}
|
||||
}
|
||||
|
||||
QList<QAction*> actions() const {
|
||||
return QList<QAction*>() << actionIsotropicRemeshing_;
|
||||
}
|
||||
|
||||
bool applicable(QAction*) const
|
||||
{
|
||||
return qobject_cast<Scene_polyhedron_item*>(scene->item(scene->mainSelectionIndex()))
|
||||
|| qobject_cast<Scene_polyhedron_selection_item*>(scene->item(scene->mainSelectionIndex()));
|
||||
}
|
||||
|
||||
public Q_SLOTS:
|
||||
void isotropic_remeshing()
|
||||
{
|
||||
const Scene_interface::Item_id index = scene->mainSelectionIndex();
|
||||
|
||||
Scene_polyhedron_item* poly_item =
|
||||
qobject_cast<Scene_polyhedron_item*>(scene->item(index));
|
||||
|
||||
Scene_polyhedron_selection_item* selection_item =
|
||||
qobject_cast<Scene_polyhedron_selection_item*>(scene->item(index));
|
||||
|
||||
if (poly_item || selection_item)
|
||||
{
|
||||
// Create dialog box
|
||||
QDialog dialog(mw);
|
||||
Ui::Isotropic_remeshing_dialog ui;
|
||||
ui.setupUi(&dialog);
|
||||
connect(ui.buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept()));
|
||||
connect(ui.buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject()));
|
||||
|
||||
//connect checkbox to spinbox
|
||||
connect(ui.splitEdgesOnly_checkbox, SIGNAL(toggled(bool)),
|
||||
ui.nbIterations_spinbox, SLOT(setDisabled(bool)));
|
||||
connect(ui.splitEdgesOnly_checkbox, SIGNAL(toggled(bool)),
|
||||
ui.protect_checkbox, SLOT(setDisabled(bool)));
|
||||
|
||||
//Set default parameters
|
||||
bool p_ = (poly_item != NULL);
|
||||
Scene_interface::Bbox bbox = p_ ? poly_item->bbox() : selection_item->bbox();
|
||||
ui.objectName->setText(p_ ? poly_item->name() : selection_item->name());
|
||||
ui.objectNameSize->setText(
|
||||
tr("Object bbox size (w,h,d): <b>%1</b>, <b>%2</b>, <b>%3</b>")
|
||||
.arg(bbox.width(), 0, 'g', 3)
|
||||
.arg(bbox.height(), 0, 'g', 3)
|
||||
.arg(bbox.depth(), 0, 'g', 3));
|
||||
|
||||
double diago_length = bbox.diagonal_length();
|
||||
ui.edgeLength_dspinbox->setDecimals(3);
|
||||
ui.edgeLength_dspinbox->setSingleStep(0.001);
|
||||
ui.edgeLength_dspinbox->setRange(1e-6 * diago_length, //min
|
||||
2. * diago_length);//max
|
||||
ui.edgeLength_dspinbox->setValue(0.05 * diago_length);
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "Diagonal length of the Bbox of the selection to remesh is ";
|
||||
oss << diago_length << "." << std::endl;
|
||||
oss << "Default is 5% of it" << std::endl;
|
||||
ui.edgeLength_dspinbox->setToolTip(QString::fromStdString(oss.str()));
|
||||
|
||||
ui.nbIterations_spinbox->setSingleStep(1);
|
||||
ui.nbIterations_spinbox->setRange(1/*min*/, 1000/*max*/);
|
||||
ui.nbIterations_spinbox->setValue(1);
|
||||
|
||||
ui.protect_checkbox->setChecked(false);
|
||||
|
||||
// Get values
|
||||
int i = dialog.exec();
|
||||
if (i == QDialog::Rejected)
|
||||
{
|
||||
std::cout << "Remeshing aborted" << std::endl;
|
||||
return;
|
||||
}
|
||||
bool edges_only = ui.splitEdgesOnly_checkbox->isChecked();
|
||||
double target_length = ui.edgeLength_dspinbox->value();
|
||||
int nb_iter = ui.nbIterations_spinbox->value();
|
||||
bool protect = ui.protect_checkbox->isChecked();
|
||||
|
||||
// wait cursor
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
QTime time;
|
||||
time.start();
|
||||
|
||||
typedef boost::graph_traits<Polyhedron>::edge_descriptor edge_descriptor;
|
||||
typedef boost::graph_traits<Polyhedron>::halfedge_descriptor halfedge_descriptor;
|
||||
typedef boost::graph_traits<Polyhedron>::face_descriptor face_descriptor;
|
||||
if (selection_item)
|
||||
{
|
||||
std::vector<edge_descriptor> updated_selected_edges;
|
||||
if (edges_only)
|
||||
{
|
||||
const Polyhedron& pmesh = *selection_item->polyhedron();
|
||||
std::vector<edge_descriptor> edges;
|
||||
BOOST_FOREACH(edge_descriptor e, selection_item->selected_edges)
|
||||
{
|
||||
if (selection_item->selected_facets.find(face(halfedge(e, pmesh), pmesh))
|
||||
!= selection_item->selected_facets.end()
|
||||
|| selection_item->selected_facets.find(face(opposite(halfedge(e, pmesh), pmesh), pmesh))
|
||||
!= selection_item->selected_facets.end())
|
||||
edges.push_back(e);
|
||||
}
|
||||
BOOST_FOREACH(face_descriptor f, selection_item->selected_facets)
|
||||
{
|
||||
BOOST_FOREACH(halfedge_descriptor he, halfedges_around_face(halfedge(f, pmesh), pmesh))
|
||||
{
|
||||
if (selection_item->selected_facets.find(face(opposite(he, pmesh), pmesh))
|
||||
== selection_item->selected_facets.end())
|
||||
edges.push_back(edge(he, pmesh));
|
||||
}
|
||||
}
|
||||
CGAL::Polygon_mesh_processing::split_long_edges(
|
||||
*selection_item->polyhedron()
|
||||
, edges
|
||||
, target_length
|
||||
, std::back_inserter(updated_selected_edges)
|
||||
, PMP::parameters::geom_traits(Kernel()));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<bool> selected(
|
||||
selection_item->polyhedron()->size_of_halfedges()/2,
|
||||
false);
|
||||
|
||||
if (selection_item->selected_edges.empty())
|
||||
CGAL::Polygon_mesh_processing::isotropic_remeshing(
|
||||
*selection_item->polyhedron()
|
||||
, selection_item->selected_facets
|
||||
, target_length
|
||||
, CGAL::Polygon_mesh_processing::parameters::number_of_iterations(nb_iter)
|
||||
.protect_constraints(protect));
|
||||
else
|
||||
CGAL::Polygon_mesh_processing::isotropic_remeshing(
|
||||
*selection_item->polyhedron()
|
||||
, selection_item->selected_facets
|
||||
, target_length
|
||||
, CGAL::Polygon_mesh_processing::parameters::number_of_iterations(nb_iter)
|
||||
.protect_constraints(protect)
|
||||
.edge_is_constrained_map(selection_item->selected_edges_pmap(selected))
|
||||
);
|
||||
|
||||
}
|
||||
selection_item->poly_item_changed();
|
||||
selection_item->clear_all();
|
||||
selection_item->selected_edges.insert(updated_selected_edges.begin(),
|
||||
updated_selected_edges.end());
|
||||
selection_item->changed_with_poly_item();
|
||||
}
|
||||
else if (poly_item)
|
||||
{
|
||||
if (edges_only)
|
||||
{
|
||||
const Polyhedron& pmesh = *poly_item->polyhedron();
|
||||
std::vector<halfedge_descriptor> border;
|
||||
CGAL::Polygon_mesh_processing::border_halfedges(
|
||||
faces(*poly_item->polyhedron()),
|
||||
std::back_inserter(border),
|
||||
pmesh);
|
||||
std::vector<edge_descriptor> border_edges;
|
||||
BOOST_FOREACH(halfedge_descriptor h, border)
|
||||
border_edges.push_back(edge(h, pmesh));
|
||||
|
||||
CGAL::Polygon_mesh_processing::split_long_edges(*poly_item->polyhedron()
|
||||
, border_edges
|
||||
, target_length);
|
||||
}
|
||||
else
|
||||
{
|
||||
CGAL::Polygon_mesh_processing::isotropic_remeshing(
|
||||
*poly_item->polyhedron()
|
||||
, faces(*poly_item->polyhedron())
|
||||
, target_length
|
||||
, CGAL::Polygon_mesh_processing::parameters::number_of_iterations(nb_iter)
|
||||
.protect_constraints(protect));
|
||||
}
|
||||
poly_item->invalidate_buffers();
|
||||
Q_EMIT poly_item->itemChanged();
|
||||
}
|
||||
else{
|
||||
std::cout << "Can't remesh that type of thing" << std::endl;
|
||||
}
|
||||
std::cout << "ok (" << time.elapsed() << " ms)" << std::endl;
|
||||
|
||||
// default cursor
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
QAction* actionIsotropicRemeshing_;
|
||||
|
||||
}; // end Polyhedron_demo_isotropic_remeshing_plugin
|
||||
|
||||
//Q_EXPORT_PLUGIN2(Polyhedron_demo_isotropic_remeshing_plugin,
|
||||
// Polyhedron_demo_isotropic_remeshing_plugin)
|
||||
|
||||
#include "Polyhedron_demo_isotropic_remeshing_plugin.moc"
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
#include <QtCore/qglobal.h>
|
||||
|
||||
#include "Scene_polyhedron_item.h"
|
||||
#include <CGAL/Three/Scene_interface.h>
|
||||
#include "Polyhedron_type.h"
|
||||
#include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
|
||||
#include <CGAL/Three/Polyhedron_demo_plugin_helper.h>
|
||||
#include "Messages_interface.h"
|
||||
#include <CGAL/gl.h>
|
||||
|
||||
#include <QAction>
|
||||
#include <QMainWindow>
|
||||
#include <QObject>
|
||||
|
||||
#include <CGAL/Polygon_mesh_processing/repair.h>
|
||||
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
|
||||
|
||||
using namespace CGAL::Three;
|
||||
class Polyhedron_demo_repair_polyhedron_plugin :
|
||||
public QObject,
|
||||
public Polyhedron_demo_plugin_helper
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
|
||||
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0")
|
||||
|
||||
public:
|
||||
// To silent a warning -Woverloaded-virtual
|
||||
// See http://stackoverflow.com/questions/9995421/gcc-woverloaded-virtual-warnings
|
||||
using Polyhedron_demo_plugin_helper::init;
|
||||
|
||||
void init(QMainWindow* mainWindow,
|
||||
Scene_interface* scene_interface,
|
||||
Messages_interface* m)
|
||||
{
|
||||
this->scene = scene_interface;
|
||||
this->mw = mainWindow;
|
||||
this->messages = m;
|
||||
|
||||
actionRemoveIsolatedVertices = new QAction(tr("Remove isolated vertices"), mw);
|
||||
if (actionRemoveIsolatedVertices){
|
||||
connect(actionRemoveIsolatedVertices, SIGNAL(triggered()),
|
||||
this, SLOT(on_actionRemoveIsolatedVertices_triggered()));
|
||||
}
|
||||
|
||||
actionRemoveDegenerateFaces = new QAction(tr("Remove degenerate faces"), mw);
|
||||
if (actionRemoveDegenerateFaces){
|
||||
connect(actionRemoveDegenerateFaces, SIGNAL(triggered()),
|
||||
this, SLOT(on_actionRemoveDegenerateFaces_triggered()));
|
||||
}
|
||||
}
|
||||
|
||||
QList<QAction*> actions() const
|
||||
{
|
||||
return QList<QAction*>() << actionRemoveIsolatedVertices
|
||||
<< actionRemoveDegenerateFaces;
|
||||
}
|
||||
|
||||
bool applicable(QAction*) const
|
||||
{
|
||||
int item_id = scene->mainSelectionIndex();
|
||||
return qobject_cast<Scene_polyhedron_item*>(
|
||||
scene->item(item_id));
|
||||
}
|
||||
|
||||
public Q_SLOTS:
|
||||
void on_actionRemoveIsolatedVertices_triggered();
|
||||
void on_actionRemoveDegenerateFaces_triggered();
|
||||
|
||||
private:
|
||||
QAction* actionRemoveIsolatedVertices;
|
||||
QAction* actionRemoveDegenerateFaces;
|
||||
|
||||
Messages_interface* messages;
|
||||
}; // end Polyhedron_demo_repair_polyhedron_plugin
|
||||
|
||||
|
||||
void Polyhedron_demo_repair_polyhedron_plugin::on_actionRemoveIsolatedVertices_triggered()
|
||||
{
|
||||
const Scene_interface::Item_id index = scene->mainSelectionIndex();
|
||||
|
||||
Scene_polyhedron_item* poly_item =
|
||||
qobject_cast<Scene_polyhedron_item*>(scene->item(index));
|
||||
if (poly_item)
|
||||
{
|
||||
std::size_t nbv =
|
||||
CGAL::Polygon_mesh_processing::remove_isolated_vertices(
|
||||
*poly_item->polyhedron());
|
||||
messages->information(tr(" %1 isolated vertices have been removed.")
|
||||
.arg(nbv));
|
||||
poly_item->invalidate_buffers();
|
||||
Q_EMIT poly_item->itemChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Polyhedron_demo_repair_polyhedron_plugin::on_actionRemoveDegenerateFaces_triggered()
|
||||
{
|
||||
const Scene_interface::Item_id index = scene->mainSelectionIndex();
|
||||
|
||||
Scene_polyhedron_item* poly_item =
|
||||
qobject_cast<Scene_polyhedron_item*>(scene->item(index));
|
||||
if (poly_item)
|
||||
{
|
||||
std::size_t nbv =
|
||||
CGAL::Polygon_mesh_processing::remove_degenerate_faces(
|
||||
*poly_item->polyhedron());
|
||||
messages->information(tr(" %1 degenerate faces have been removed.")
|
||||
.arg(nbv));
|
||||
poly_item->invalidate_buffers();
|
||||
Q_EMIT poly_item->itemChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#include "Polyhedron_demo_repair_polyhedron_plugin.moc"
|
||||
|
|
@ -97,6 +97,8 @@ public:
|
|||
connect(ui_widget.Keep_connected_components_button, SIGNAL(clicked()), this, SLOT(on_Keep_connected_components_button_clicked()));
|
||||
connect(ui_widget.Dilate_erode_button, SIGNAL(clicked()), this, SLOT(on_Dilate_erode_button_clicked()));
|
||||
connect(ui_widget.Create_polyhedron_item_button, SIGNAL(clicked()), this, SLOT(on_Create_polyhedron_item_button_clicked()));
|
||||
connect(ui_widget.Select_sharp_edges_button, SIGNAL(clicked()), this, SLOT(on_Select_sharp_edges_button_clicked()));
|
||||
|
||||
QObject* scene = dynamic_cast<QObject*>(scene_interface);
|
||||
if(scene) {
|
||||
connect(scene, SIGNAL(itemAboutToBeDestroyed(Scene_item*)), this, SLOT(item_about_to_be_destroyed(Scene_item*)));
|
||||
|
|
@ -310,6 +312,19 @@ public Q_SLOTS:
|
|||
print_message("Error: polyhedron item is not created!");
|
||||
}
|
||||
}
|
||||
|
||||
void on_Select_sharp_edges_button_clicked() {
|
||||
Scene_polyhedron_selection_item* selection_item = get_selected_item<Scene_polyhedron_selection_item>();
|
||||
if (!selection_item) {
|
||||
print_message("Error: there is no selected polyhedron selection item!");
|
||||
return;
|
||||
}
|
||||
|
||||
double angle = ui_widget.Sharp_angle_spinbox->value();
|
||||
selection_item->select_sharp_edges(angle);
|
||||
scene->itemChanged(selection_item);
|
||||
}
|
||||
|
||||
void on_Dilate_erode_button_clicked() {
|
||||
Scene_polyhedron_selection_item* selection_item = get_selected_item<Scene_polyhedron_selection_item>();
|
||||
if(!selection_item) {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
//#define CGAL_PMP_REMESHING_VERBOSE
|
||||
|
||||
#include "opengl_tools.h"
|
||||
#include "create_sphere.h"
|
||||
#include "Scene_edit_polyhedron_item.h"
|
||||
|
|
@ -12,7 +14,6 @@ Scene_edit_polyhedron_item::Scene_edit_polyhedron_item
|
|||
: Scene_item(NumberOfBuffers,NumberOfVaos),
|
||||
ui_widget(ui_widget),
|
||||
poly_item(poly_item),
|
||||
deform_mesh(*(poly_item->polyhedron()), Deform_mesh::Vertex_index_map(), Deform_mesh::Hedge_index_map(), Array_based_vertex_point_map(&positions)),
|
||||
is_rot_free(true),
|
||||
own_poly_item(true),
|
||||
k_ring_selector(poly_item, mw, Scene_polyhedron_item_k_ring_selection::Active_handle::VERTEX, true)
|
||||
|
|
@ -30,6 +31,11 @@ Scene_edit_polyhedron_item::Scene_edit_polyhedron_item
|
|||
poly_item->set_color_vector_read_only(true); // to prevent recomputation of color vector in invalidate_buffers()
|
||||
poly_item->update_vertex_indices();
|
||||
|
||||
deform_mesh = new Deform_mesh(*(poly_item->polyhedron()),
|
||||
Deform_mesh::Vertex_index_map(),
|
||||
Deform_mesh::Hedge_index_map(),
|
||||
Array_based_vertex_point_map(&positions));
|
||||
|
||||
length_of_axis = bbox().diagonal_length() / 15.0;
|
||||
|
||||
// interleave events of viewer (there is only one viewer)
|
||||
|
|
@ -44,36 +50,8 @@ Scene_edit_polyhedron_item::Scene_edit_polyhedron_item
|
|||
startTimer(0);
|
||||
|
||||
// Required for drawing functionality
|
||||
positions.resize(num_vertices(*polyhedron())*3);
|
||||
normals.resize(positions.size());
|
||||
Polyhedron::Vertex_iterator vb, ve;
|
||||
std::size_t counter = 0;
|
||||
for(vb=polyhedron()->vertices_begin(), ve = polyhedron()->vertices_end();vb != ve; ++vb, ++counter) {
|
||||
positions[counter*3] = vb->point().x();
|
||||
positions[counter*3+1] = vb->point().y();
|
||||
positions[counter*3+2] = vb->point().z();
|
||||
reset_drawing_data();
|
||||
|
||||
const Polyhedron::Traits::Vector_3& n =
|
||||
CGAL::Polygon_mesh_processing::compute_vertex_normal(vb, deform_mesh.halfedge_graph());
|
||||
|
||||
normals[counter*3] = n.x();
|
||||
normals[counter*3+1] = n.y();
|
||||
normals[counter*3+2] = n.z();
|
||||
}
|
||||
tris.resize(polyhedron()->size_of_facets()*3);
|
||||
counter = 0;
|
||||
for(Polyhedron::Facet_handle fb = polyhedron()->facets_begin(); fb != polyhedron()->facets_end(); ++fb, ++counter) {
|
||||
tris[counter*3] = static_cast<unsigned int>(fb->halfedge()->vertex()->id());
|
||||
tris[counter*3+1] = static_cast<unsigned int>(fb->halfedge()->next()->vertex()->id());
|
||||
tris[counter*3+2] = static_cast<unsigned int>(fb->halfedge()->prev()->vertex()->id());
|
||||
}
|
||||
|
||||
edges.resize(polyhedron()->size_of_halfedges());
|
||||
counter = 0;
|
||||
for(Polyhedron::Edge_iterator eb = polyhedron()->edges_begin(); eb != polyhedron()->edges_end(); ++eb, ++counter) {
|
||||
edges[counter*2] = static_cast<unsigned int>(eb->vertex()->id());
|
||||
edges[counter*2+1] = static_cast<unsigned int>(eb->opposite()->vertex()->id());
|
||||
}
|
||||
//Generates an integer which will be used as ID for each buffer
|
||||
|
||||
const char vertex_shader_source_bbox[] =
|
||||
|
|
@ -109,6 +87,14 @@ Scene_edit_polyhedron_item::Scene_edit_polyhedron_item
|
|||
bbox_program.addShaderFromSourceCode(QOpenGLShader::Fragment,fragment_shader_source);
|
||||
bbox_program.link();
|
||||
|
||||
ui_widget->remeshing_iterations_spinbox->setValue(1);
|
||||
|
||||
ui_widget->remeshing_edge_length_spinbox->setValue(length_of_axis);
|
||||
ui_widget->remeshing_edge_length_spinbox->setDisabled(true);
|
||||
ui_widget->remeshingEdgeLengthInput_checkBox->setChecked(false);
|
||||
connect(ui_widget->remeshingEdgeLengthInput_checkBox, SIGNAL(toggled(bool)),
|
||||
ui_widget->remeshing_edge_length_spinbox, SLOT(setEnabled(bool)));
|
||||
|
||||
//the spheres :
|
||||
create_Sphere(length_of_axis/15.0);
|
||||
invalidate_buffers();
|
||||
|
|
@ -120,8 +106,9 @@ Scene_edit_polyhedron_item::~Scene_edit_polyhedron_item()
|
|||
{
|
||||
delete_ctrl_vertices_group(false);
|
||||
}
|
||||
if (own_poly_item) delete poly_item;
|
||||
|
||||
delete deform_mesh;
|
||||
if (own_poly_item) delete poly_item;
|
||||
}
|
||||
/////////////////////////////
|
||||
/// For the Shader gestion///
|
||||
|
|
@ -305,17 +292,81 @@ void Scene_edit_polyhedron_item::initialize_buffers(CGAL::Three::Viewer_interfac
|
|||
color_lines.resize(0);
|
||||
std::vector<double>(color_lines).swap(color_lines);
|
||||
}
|
||||
//vao for the frame plane
|
||||
{
|
||||
program = getShaderProgram(PROGRAM_WITHOUT_LIGHT, viewer);
|
||||
program->bind();
|
||||
bbox_program.bind();
|
||||
vaos[Frame_plane]->bind();
|
||||
buffers[Frame_vertices].bind();
|
||||
buffers[Frame_vertices].allocate(pos_frame_plane.data(),
|
||||
static_cast<int>(pos_frame_plane.size()*sizeof(double)));
|
||||
bbox_program.enableAttributeArray("vertex");
|
||||
bbox_program.setAttributeBuffer("vertex",GL_DOUBLE,0,3);
|
||||
buffers[Frame_vertices].release();
|
||||
|
||||
vaos[Frame_plane]->release();
|
||||
bbox_program.release();
|
||||
program->release();
|
||||
}
|
||||
are_buffers_filled = true;
|
||||
}
|
||||
|
||||
void Scene_edit_polyhedron_item::reset_drawing_data()
|
||||
{
|
||||
positions.clear();
|
||||
positions.resize(num_vertices(*polyhedron()) * 3);
|
||||
|
||||
normals.clear();
|
||||
normals.resize(positions.size());
|
||||
|
||||
std::size_t counter = 0;
|
||||
BOOST_FOREACH(vertex_descriptor vb, vertices(*polyhedron()))
|
||||
{
|
||||
positions[counter * 3] = vb->point().x();
|
||||
positions[counter * 3 + 1] = vb->point().y();
|
||||
positions[counter * 3 + 2] = vb->point().z();
|
||||
|
||||
const Polyhedron::Traits::Vector_3& n =
|
||||
CGAL::Polygon_mesh_processing::compute_vertex_normal(vb, deform_mesh->halfedge_graph());
|
||||
normals[counter * 3] = n.x();
|
||||
normals[counter * 3 + 1] = n.y();
|
||||
normals[counter * 3 + 2] = n.z();
|
||||
|
||||
++counter;
|
||||
}
|
||||
|
||||
tris.clear();
|
||||
tris.resize(polyhedron()->size_of_facets() * 3);
|
||||
counter = 0;
|
||||
BOOST_FOREACH(face_descriptor fb, faces(*polyhedron()))
|
||||
{
|
||||
tris[counter * 3] = static_cast<unsigned int>(fb->halfedge()->vertex()->id());
|
||||
tris[counter * 3 + 1] = static_cast<unsigned int>(fb->halfedge()->next()->vertex()->id());
|
||||
tris[counter * 3 + 2] = static_cast<unsigned int>(fb->halfedge()->prev()->vertex()->id());
|
||||
++counter;
|
||||
}
|
||||
|
||||
edges.clear();
|
||||
edges.resize(polyhedron()->size_of_halfedges());
|
||||
counter = 0;
|
||||
for (Polyhedron::Edge_iterator eb = polyhedron()->edges_begin();
|
||||
eb != polyhedron()->edges_end(); ++eb, ++counter)
|
||||
{
|
||||
edges[counter * 2] = static_cast<unsigned int>(eb->vertex()->id());
|
||||
edges[counter * 2 + 1] = static_cast<unsigned int>(eb->opposite()->vertex()->id());
|
||||
}
|
||||
}
|
||||
|
||||
void Scene_edit_polyhedron_item::compute_normals_and_vertices(void)
|
||||
{
|
||||
ROI_points.resize(0);
|
||||
control_points.resize(0);
|
||||
control_color.resize(0);
|
||||
BOOST_FOREACH(vertex_descriptor vd, deform_mesh.roi_vertices())
|
||||
pos_frame_plane.resize(0);
|
||||
BOOST_FOREACH(vertex_descriptor vd, deform_mesh->roi_vertices())
|
||||
{
|
||||
if(!deform_mesh.is_control_vertex(vd))
|
||||
if(!deform_mesh->is_control_vertex(vd))
|
||||
{//gl_draw_point( vd->point() );
|
||||
ROI_points.push_back(vd->point().x());
|
||||
ROI_points.push_back(vd->point().y());
|
||||
|
|
@ -374,6 +425,9 @@ void Scene_edit_polyhedron_item::compute_normals_and_vertices(void)
|
|||
color_lines[6] = 1.0; color_lines[9] = 1.0;
|
||||
color_lines[13] = 1.0; color_lines[16] = 1.0;
|
||||
|
||||
if(ui_widget->ActivateFixedPlaneCheckBox->isChecked())
|
||||
draw_frame_plane(viewer);
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
|
@ -384,12 +438,90 @@ void Scene_edit_polyhedron_item::deform()
|
|||
|
||||
for(Ctrl_vertices_group_data_list::iterator it = ctrl_vertex_frame_map.begin(); it != ctrl_vertex_frame_map.end(); ++it)
|
||||
{ it->set_target_positions(); }
|
||||
deform_mesh.deform();
|
||||
deform_mesh->deform();
|
||||
|
||||
poly_item->invalidate_aabb_tree(); // invalidate the AABB-tree of the poly_item
|
||||
Q_EMIT itemChanged();
|
||||
}
|
||||
|
||||
void Scene_edit_polyhedron_item::remesh()
|
||||
{
|
||||
const Polyhedron& g = deform_mesh->halfedge_graph();
|
||||
Array_based_vertex_point_map vpmap(&positions);
|
||||
|
||||
std::set<face_descriptor> roi_facets;
|
||||
std::set<halfedge_descriptor> roi_halfedges;
|
||||
BOOST_FOREACH(vertex_descriptor v, deform_mesh->roi_vertices())
|
||||
{
|
||||
BOOST_FOREACH(face_descriptor fv, CGAL::faces_around_target(halfedge(v, g), g))
|
||||
{
|
||||
roi_facets.insert(fv);
|
||||
BOOST_FOREACH(halfedge_descriptor h, CGAL::halfedges_around_face(halfedge(fv, g), g))
|
||||
{
|
||||
if (roi_halfedges.find(opposite(h, g)) == roi_halfedges.end()) //not already computed
|
||||
roi_halfedges.insert(h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool automatic_target_length = !ui_widget->remeshingEdgeLengthInput_checkBox->isChecked();
|
||||
double sum_len = 0.;
|
||||
std::vector<halfedge_descriptor> roi_border;
|
||||
BOOST_FOREACH(halfedge_descriptor h, roi_halfedges)
|
||||
{
|
||||
if (roi_halfedges.find(opposite(h, g)) == roi_halfedges.end())
|
||||
{
|
||||
roi_border.push_back(opposite(h, g));
|
||||
if (automatic_target_length)
|
||||
sum_len += CGAL::sqrt(CGAL::squared_distance(
|
||||
get(vpmap, source(h, g)), get(vpmap, target(h, g))));
|
||||
}
|
||||
}
|
||||
|
||||
if (roi_border.empty())
|
||||
automatic_target_length = false;
|
||||
|
||||
double target_length = automatic_target_length
|
||||
? sum_len / (0. + roi_border.size())
|
||||
: ui_widget->remeshing_edge_length_spinbox->value();
|
||||
|
||||
unsigned int nb_iter = ui_widget->remeshing_iterations_spinbox->value();
|
||||
|
||||
std::cout << "Remeshing...";
|
||||
CGAL::Polygon_mesh_processing::isotropic_remeshing(
|
||||
*polyhedron()
|
||||
, roi_facets
|
||||
, target_length
|
||||
, CGAL::Polygon_mesh_processing::parameters::number_of_iterations(nb_iter)
|
||||
.protect_constraints(false) //no edge_is_constrained_map
|
||||
.vertex_point_map(vpmap)
|
||||
);
|
||||
std::cout << "done." << std::endl;
|
||||
|
||||
//reset ROI from its outside border roi_border
|
||||
clear_roi();
|
||||
do{
|
||||
delete_ctrl_vertices_group(false);
|
||||
}
|
||||
while(!ctrl_vertex_frame_map.empty());
|
||||
|
||||
poly_item->update_vertex_indices();
|
||||
poly_item->update_halfedge_indices();
|
||||
delete deform_mesh;
|
||||
deform_mesh = new Deform_mesh(*(poly_item->polyhedron()),
|
||||
Deform_mesh::Vertex_index_map(),
|
||||
Deform_mesh::Hedge_index_map(),
|
||||
vpmap);
|
||||
|
||||
reset_drawing_data();
|
||||
compute_normals_and_vertices();
|
||||
|
||||
poly_item->invalidate_aabb_tree(); // invalidate the AABB tree
|
||||
create_ctrl_vertices_group();
|
||||
|
||||
Q_EMIT itemChanged();
|
||||
}
|
||||
|
||||
void Scene_edit_polyhedron_item::timerEvent(QTimerEvent* /*event*/)
|
||||
{ // just handle deformation - paint like selection is handled in eventFilter()
|
||||
if(state.ctrl_pressing && (state.left_button_pressing || state.right_button_pressing)) {
|
||||
|
|
@ -435,12 +567,16 @@ bool Scene_edit_polyhedron_item::eventFilter(QObject* /*target*/, QEvent *event)
|
|||
// check state changes between old and current state
|
||||
bool ctrl_pressed_now = state.ctrl_pressing && !old_state.ctrl_pressing;
|
||||
bool ctrl_released_now = !state.ctrl_pressing && old_state.ctrl_pressing;
|
||||
if(ctrl_pressed_now || ctrl_released_now || event->type() == QEvent::HoverMove)
|
||||
if(ctrl_pressed_now || ctrl_released_now || event->type() == QEvent::HoverMove)
|
||||
{// activate a handle manipulated frame
|
||||
QGLViewer* viewer = *QGLViewer::QGLViewerPool().begin();
|
||||
const QPoint& p = viewer->mapFromGlobal(QCursor::pos());
|
||||
bool need_repaint = activate_closest_manipulated_frame(p.x(), p.y());
|
||||
|
||||
if (ctrl_released_now && ui_widget->RemeshingCheckBox->isChecked()){
|
||||
remesh();
|
||||
}
|
||||
|
||||
if(need_repaint) { Q_EMIT itemChanged(); }
|
||||
}
|
||||
|
||||
|
|
@ -460,6 +596,17 @@ void Scene_edit_polyhedron_item::draw_edges(CGAL::Three::Viewer_interface* viewe
|
|||
program->release();
|
||||
vaos[Edges]->release();
|
||||
|
||||
|
||||
vaos[Frame_plane]->bind();
|
||||
program = getShaderProgram(PROGRAM_WITHOUT_LIGHT);
|
||||
attrib_buffers(viewer,PROGRAM_WITHOUT_LIGHT);
|
||||
program->bind();
|
||||
program->setAttributeValue("colors", QColor(0,0,0));
|
||||
viewer->glDrawArrays(GL_LINE_LOOP, 0, (GLsizei)pos_frame_plane.size()/3);
|
||||
program->release();
|
||||
vaos[Frame_plane]->release();
|
||||
|
||||
|
||||
if(rendering_mode == Wireframe) {
|
||||
draw_ROI_and_control_vertices(viewer);
|
||||
}
|
||||
|
|
@ -479,7 +626,39 @@ void Scene_edit_polyhedron_item::draw(CGAL::Three::Viewer_interface* viewer) con
|
|||
draw_edges(viewer);
|
||||
draw_ROI_and_control_vertices(viewer);
|
||||
|
||||
}
|
||||
|
||||
void Scene_edit_polyhedron_item::draw_frame_plane(QGLViewer* viewer) const
|
||||
{
|
||||
pos_frame_plane.resize(15);
|
||||
for(Ctrl_vertices_group_data_list::const_iterator hgb_data = ctrl_vertex_frame_map.begin(); hgb_data != ctrl_vertex_frame_map.end(); ++hgb_data)
|
||||
{
|
||||
if(hgb_data->frame == viewer->manipulatedFrame())
|
||||
{
|
||||
|
||||
const double diag = scene_diag();
|
||||
qglviewer::Vec base1(1,0,0);
|
||||
qglviewer::Vec base2(0,1,0);
|
||||
|
||||
qglviewer::Quaternion orientation=hgb_data->frame->orientation();
|
||||
base1=orientation.rotate(base1);
|
||||
base2=orientation.rotate(base2);
|
||||
|
||||
qglviewer::Vec center = hgb_data->calculate_initial_center();
|
||||
|
||||
qglviewer::Vec p1 = center - diag*base1 - diag*base2;
|
||||
qglviewer::Vec p2 = center + diag*base1 - diag*base2;
|
||||
qglviewer::Vec p3 = center + diag*base1 + diag*base2;
|
||||
qglviewer::Vec p4 = center - diag*base1 + diag*base2;
|
||||
|
||||
pos_frame_plane[0] = p1.x ; pos_frame_plane[1] = p1.y; pos_frame_plane[2] =p1.z ;
|
||||
pos_frame_plane[3] = p2.x ; pos_frame_plane[4] = p2.y; pos_frame_plane[5] =p2.z ;
|
||||
pos_frame_plane[6] = p3.x ; pos_frame_plane[7] = p3.y; pos_frame_plane[8] =p3.z ;
|
||||
pos_frame_plane[9] = p4.x ; pos_frame_plane[10]= p4.y; pos_frame_plane[11] =p4.z ;
|
||||
pos_frame_plane[12] = p1.x ; pos_frame_plane[13]= p1.y; pos_frame_plane[14] =p1.z ;
|
||||
are_buffers_filled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Scene_edit_polyhedron_item::draw_ROI_and_control_vertices(CGAL::Three::Viewer_interface* viewer) const {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
|
||||
#include <CGAL/boost/graph/properties_Polyhedron_3.h>
|
||||
#include <CGAL/Polygon_mesh_processing/compute_normal.h>
|
||||
#include <CGAL/boost/graph/iterator.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
|
@ -18,7 +18,11 @@
|
|||
#include <QGLViewer/camera.h>
|
||||
|
||||
#include "ui_Deform_mesh.h"
|
||||
|
||||
#include <CGAL/Polygon_mesh_processing/compute_normal.h>
|
||||
#include <CGAL/Surface_mesh_deformation.h>
|
||||
#include <CGAL/Polygon_mesh_processing/remesh.h>
|
||||
|
||||
#include <boost/function_output_iterator.hpp>
|
||||
#include <QGLBuffer>
|
||||
#include <QGLShader>
|
||||
|
|
@ -28,15 +32,15 @@
|
|||
typedef Polyhedron::Vertex_handle Vertex_handle;
|
||||
typedef boost::graph_traits<Polyhedron>::vertex_descriptor vertex_descriptor;
|
||||
typedef boost::graph_traits<Polyhedron>::vertex_iterator vertex_iterator;
|
||||
typedef boost::graph_traits<Polyhedron>::in_edge_iterator in_edge_iterator;
|
||||
typedef boost::graph_traits<Polyhedron>::out_edge_iterator out_edge_iterator;
|
||||
typedef boost::graph_traits<Polyhedron>::face_descriptor face_descriptor;
|
||||
typedef boost::graph_traits<Polyhedron>::halfedge_descriptor halfedge_descriptor;
|
||||
|
||||
struct Array_based_vertex_point_map
|
||||
{
|
||||
public:
|
||||
typedef vertex_descriptor key_type;
|
||||
typedef Polyhedron::Traits::Point_3 value_type;
|
||||
typedef value_type& reference;
|
||||
typedef value_type& reference;
|
||||
typedef boost::read_write_property_map_tag category;
|
||||
Array_based_vertex_point_map(std::vector<double>* positions) : positions(positions) {}
|
||||
std::vector<double>* positions;
|
||||
|
|
@ -54,14 +58,25 @@ inline
|
|||
void
|
||||
put(Array_based_vertex_point_map pmap,
|
||||
Array_based_vertex_point_map::key_type key,
|
||||
Array_based_vertex_point_map::value_type val) {
|
||||
Array_based_vertex_point_map::value_type val)
|
||||
{
|
||||
key->point() = val; // to make things easy (ray selection after deformation, save to polyhedron after close etc),
|
||||
// I also change point() of vertex together with positions list
|
||||
// So that we do not need to pmap everywhere other than draw
|
||||
if (key->id() == std::size_t(-1))
|
||||
{
|
||||
key->id() = pmap.positions->size() / 3;
|
||||
pmap.positions->push_back(val.x());
|
||||
pmap.positions->push_back(val.y());
|
||||
pmap.positions->push_back(val.z());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::size_t pos = key->id() * 3;
|
||||
(*pmap.positions)[pos] = val.x();
|
||||
(*pmap.positions)[pos+1] = val.y();
|
||||
(*pmap.positions)[pos+2] = val.z();
|
||||
}
|
||||
}
|
||||
|
||||
typedef CGAL::Surface_mesh_deformation<Polyhedron, CGAL::Default, CGAL::Default, CGAL::ORIGINAL_ARAP
|
||||
|
|
@ -103,7 +118,7 @@ public:
|
|||
|
||||
bool oldState = frame->blockSignals(true); // do not let it Q_EMIT modified, which will cause a deformation
|
||||
// but we are just adjusting the center so it does not require a deformation
|
||||
frame->setOrientation(qglviewer::Quaternion());
|
||||
// frame->setOrientation(qglviewer::Quaternion());
|
||||
frame->setPosition(frame_initial_center);
|
||||
frame->blockSignals(oldState);
|
||||
}
|
||||
|
|
@ -119,6 +134,18 @@ public:
|
|||
deform_mesh->set_target_position(*hb, Point(rotated_and_translated.x, rotated_and_translated.y, rotated_and_translated.z) );
|
||||
}
|
||||
}
|
||||
qglviewer::Vec calculate_initial_center() const
|
||||
{
|
||||
qglviewer::Vec center_acc(0, 0, 0);
|
||||
if (initial_positions.empty()) { return center_acc; }
|
||||
|
||||
for (std::vector<qglviewer::Vec>::const_iterator it = initial_positions.begin();
|
||||
it != initial_positions.end(); ++it)
|
||||
{
|
||||
center_acc += (*it);
|
||||
}
|
||||
return center_acc / initial_positions.size();
|
||||
}
|
||||
|
||||
private:
|
||||
void reset_initial_positions()
|
||||
|
|
@ -131,17 +158,6 @@ private:
|
|||
initial_positions.push_back(point);
|
||||
}
|
||||
}
|
||||
qglviewer::Vec calculate_initial_center()
|
||||
{
|
||||
qglviewer::Vec center_acc(0, 0, 0);
|
||||
if(initial_positions.empty()) {return center_acc; }
|
||||
|
||||
for(std::vector<qglviewer::Vec>::iterator it = initial_positions.begin(); it != initial_positions.end(); ++it)
|
||||
{
|
||||
center_acc += (*it);
|
||||
}
|
||||
return center_acc / initial_positions.size();
|
||||
}
|
||||
CGAL::Three::Scene_interface::Bbox calculate_initial_bbox()
|
||||
{
|
||||
if(initial_positions.empty()) {return CGAL::Three::Scene_interface::Bbox(0,0,0,0,0,0); }
|
||||
|
|
@ -204,6 +220,7 @@ public:
|
|||
void draw_edges(CGAL::Three::Viewer_interface*) const;
|
||||
void draw_bbox(const CGAL::Three::Scene_interface::Bbox&) const;
|
||||
void draw_ROI_and_control_vertices(CGAL::Three::Viewer_interface *viewer) const;
|
||||
void draw_frame_plane(QGLViewer *viewer) const;
|
||||
|
||||
// Get wrapped polyhedron
|
||||
Polyhedron* polyhedron();
|
||||
|
|
@ -260,6 +277,8 @@ public Q_SLOTS:
|
|||
double dir_z);
|
||||
|
||||
void deform(); // deform the mesh
|
||||
void remesh();
|
||||
|
||||
// members
|
||||
private:
|
||||
Ui::DeformMesh* ui_widget;
|
||||
|
|
@ -279,6 +298,7 @@ private:
|
|||
mutable std::vector<GLdouble> pos_axis;
|
||||
mutable std::vector<GLdouble> pos_sphere;
|
||||
mutable std::vector<GLdouble> normals_sphere;
|
||||
mutable std::vector<GLdouble> pos_frame_plane;
|
||||
mutable QOpenGLShaderProgram *program;
|
||||
mutable QOpenGLShaderProgram bbox_program;
|
||||
mutable std::size_t nb_ROI;
|
||||
|
|
@ -298,7 +318,8 @@ private:
|
|||
Bbox_vertices,
|
||||
Axis_vertices,
|
||||
Axis_colors,
|
||||
NumberOfBuffers = Axis_colors+1
|
||||
Frame_vertices,
|
||||
NumberOfBuffers
|
||||
};
|
||||
enum Vao
|
||||
{
|
||||
|
|
@ -310,7 +331,8 @@ private:
|
|||
Control_points,
|
||||
Control_spheres,
|
||||
Axis,
|
||||
NumberOfVaos= Axis+1
|
||||
Frame_plane,
|
||||
NumberOfVaos
|
||||
};
|
||||
mutable QOpenGLBuffer *in_bu;
|
||||
using Scene_item::initialize_buffers;
|
||||
|
|
@ -318,11 +340,9 @@ private:
|
|||
void compute_normals_and_vertices(void);
|
||||
void compute_bbox(const CGAL::Three::Scene_interface::Bbox&);
|
||||
void create_Sphere(double);
|
||||
void reset_drawing_data();
|
||||
|
||||
|
||||
|
||||
|
||||
Deform_mesh deform_mesh;
|
||||
Deform_mesh* deform_mesh;
|
||||
typedef std::list<Control_vertices_data> Ctrl_vertices_group_data_list;
|
||||
Ctrl_vertices_group_data_list::iterator active_group;
|
||||
Ctrl_vertices_group_data_list ctrl_vertex_frame_map; // keep list of group of control vertices with assoc data
|
||||
|
|
@ -348,7 +368,7 @@ public:
|
|||
return false;
|
||||
} // no group of control vertices to insert
|
||||
|
||||
bool inserted = deform_mesh.insert_control_vertex(v);
|
||||
bool inserted = deform_mesh->insert_control_vertex(v);
|
||||
if(inserted) {
|
||||
active_group->ctrl_vertices_group.push_back(v);
|
||||
active_group->refresh();
|
||||
|
|
@ -358,12 +378,12 @@ public:
|
|||
|
||||
bool insert_roi_vertex(vertex_descriptor v)
|
||||
{
|
||||
return deform_mesh.insert_roi_vertex(v);
|
||||
return deform_mesh->insert_roi_vertex(v);
|
||||
}
|
||||
|
||||
bool erase_control_vertex(vertex_descriptor v)
|
||||
{
|
||||
if(deform_mesh.erase_control_vertex(v)) // API should be safe enough to do that (without checking empty group of control vertices etc.)
|
||||
if(deform_mesh->erase_control_vertex(v)) // API should be safe enough to do that (without checking empty group of control vertices etc.)
|
||||
{
|
||||
refresh_all_group_centers(); // since we don't know which group of control vertices v is erased from, refresh all
|
||||
return true;
|
||||
|
|
@ -376,7 +396,7 @@ public:
|
|||
bool erase_roi_vertex(vertex_descriptor v)
|
||||
{
|
||||
erase_control_vertex(v); // erase control vertex
|
||||
return deform_mesh.erase_roi_vertex(v);
|
||||
return deform_mesh->erase_roi_vertex(v);
|
||||
}
|
||||
|
||||
void set_all_vertices_as_roi()
|
||||
|
|
@ -395,7 +415,7 @@ public:
|
|||
delete it->frame;
|
||||
}
|
||||
ctrl_vertex_frame_map.clear();
|
||||
deform_mesh.clear_roi_vertices();
|
||||
deform_mesh->clear_roi_vertices();
|
||||
|
||||
create_ctrl_vertices_group(); // create one new group of control vertices
|
||||
}
|
||||
|
|
@ -413,7 +433,7 @@ public:
|
|||
qglviewer::ManipulatedFrame* new_frame = new qglviewer::ManipulatedFrame();
|
||||
new_frame->setRotationSensitivity(2.0f);
|
||||
|
||||
Control_vertices_data hgd(&deform_mesh, new_frame);
|
||||
Control_vertices_data hgd(deform_mesh, new_frame);
|
||||
ctrl_vertex_frame_map.push_back(hgd);
|
||||
hgd.refresh();
|
||||
|
||||
|
|
@ -439,7 +459,7 @@ public:
|
|||
{
|
||||
delete it->frame;
|
||||
for(std::vector<vertex_descriptor>::iterator v_it = it->ctrl_vertices_group.begin(); v_it != it->ctrl_vertices_group.end(); ++v_it) {
|
||||
deform_mesh.erase_control_vertex(*v_it);
|
||||
deform_mesh->erase_control_vertex(*v_it);
|
||||
}
|
||||
ctrl_vertex_frame_map.erase(it);
|
||||
break;
|
||||
|
|
@ -504,6 +524,7 @@ public:
|
|||
{
|
||||
is_rot_free=true;
|
||||
rot_constraint.setRotationConstraintType(qglviewer::AxisPlaneConstraint::FREE);
|
||||
rot_constraint.setTranslationConstraintType(qglviewer::AxisPlaneConstraint::FREE);
|
||||
|
||||
// just block signals to prevent deformation
|
||||
for(Ctrl_vertices_group_data_list::iterator it = ctrl_vertex_frame_map.begin(); it != ctrl_vertex_frame_map.end(); ++it)
|
||||
|
|
@ -516,8 +537,8 @@ public:
|
|||
{
|
||||
std::ofstream out(file_name);
|
||||
// save roi
|
||||
out << deform_mesh.roi_vertices().size() << std::endl;
|
||||
BOOST_FOREACH(vertex_descriptor vd, deform_mesh.roi_vertices())
|
||||
out << deform_mesh->roi_vertices().size() << std::endl;
|
||||
BOOST_FOREACH(vertex_descriptor vd, deform_mesh->roi_vertices())
|
||||
{
|
||||
out << vd->id() << " ";
|
||||
}
|
||||
|
|
@ -543,9 +564,9 @@ public:
|
|||
|
||||
// put vertices to vector
|
||||
std::vector<vertex_descriptor> all_vertices;
|
||||
all_vertices.reserve(num_vertices(deform_mesh.halfedge_graph()));
|
||||
all_vertices.reserve(num_vertices(deform_mesh->halfedge_graph()));
|
||||
vertex_iterator vb, ve;
|
||||
for(boost::tie(vb, ve) = vertices(deform_mesh.halfedge_graph()); vb != ve; ++vb) {
|
||||
for(boost::tie(vb, ve) = vertices(deform_mesh->halfedge_graph()); vb != ve; ++vb) {
|
||||
all_vertices.push_back(*vb);
|
||||
}
|
||||
// read roi
|
||||
|
|
@ -577,16 +598,22 @@ public:
|
|||
|
||||
void overwrite_deform_object()
|
||||
{
|
||||
deform_mesh.overwrite_initial_geometry();
|
||||
deform_mesh->overwrite_initial_geometry();
|
||||
|
||||
refresh_all_group_centers();
|
||||
}
|
||||
|
||||
void reset_deform_object()
|
||||
{
|
||||
deform_mesh->reset();
|
||||
refresh_all_group_centers();
|
||||
}
|
||||
|
||||
struct Is_selected {
|
||||
Deform_mesh& dm;
|
||||
Is_selected(Deform_mesh& dm) : dm(dm) {}
|
||||
Deform_mesh* dm;
|
||||
Is_selected(Deform_mesh* dm) : dm(dm) {}
|
||||
bool count(Vertex_handle vh) const {
|
||||
return dm.is_roi_vertex(vh);
|
||||
return dm->is_roi_vertex(vh);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -608,7 +635,7 @@ public:
|
|||
|
||||
boost::optional<std::size_t> select_isolated_components(std::size_t threshold) {
|
||||
typedef boost::function_output_iterator<Select_roi_output> Output_iterator;
|
||||
Output_iterator out(&deform_mesh);
|
||||
Output_iterator out(deform_mesh);
|
||||
|
||||
Travel_isolated_components::Selection_visitor<Output_iterator> visitor(threshold, out);
|
||||
Travel_isolated_components().travel<Vertex_handle>
|
||||
|
|
@ -663,6 +690,9 @@ protected:
|
|||
}
|
||||
if(ctrl_vertex_frame_map.empty()) { return false; }
|
||||
|
||||
rot_constraint.setRotationConstraintType(qglviewer::AxisPlaneConstraint::FREE);
|
||||
rot_constraint.setTranslationConstraintType(qglviewer::AxisPlaneConstraint::FREE);
|
||||
|
||||
QGLViewer* viewer = *QGLViewer::QGLViewerPool().begin();
|
||||
qglviewer::Camera* camera = viewer->camera();
|
||||
|
||||
|
|
@ -696,7 +726,16 @@ protected:
|
|||
min_it->frame->setConstraint(&rot_constraint);
|
||||
}
|
||||
else
|
||||
rot_constraint.setRotationConstraintType(qglviewer::AxisPlaneConstraint::FREE);
|
||||
{
|
||||
if(!ui_widget->ActivatePivotingCheckBox->isChecked() &&
|
||||
ui_widget->ActivateFixedPlaneCheckBox->isChecked())
|
||||
{
|
||||
// the constraint is local to the frame
|
||||
rot_constraint.setTranslationConstraint(qglviewer::AxisPlaneConstraint::PLANE,qglviewer::Vec(0,0,1));
|
||||
rot_constraint.setRotationConstraintType(qglviewer::AxisPlaneConstraint::FORBIDDEN);
|
||||
min_it->frame->setConstraint(&rot_constraint);
|
||||
}
|
||||
}
|
||||
|
||||
if(viewer->manipulatedFrame() == min_it->frame)
|
||||
{ return false; }
|
||||
|
|
@ -708,17 +747,28 @@ protected:
|
|||
bool keyPressEvent(QKeyEvent* e);
|
||||
|
||||
void update_normals() {
|
||||
BOOST_FOREACH(vertex_descriptor vd, deform_mesh.roi_vertices())
|
||||
BOOST_FOREACH(vertex_descriptor vd, deform_mesh->roi_vertices())
|
||||
{
|
||||
std::size_t id = vd->id();
|
||||
const Polyhedron::Traits::Vector_3& n =
|
||||
CGAL::Polygon_mesh_processing::compute_vertex_normal(vd, deform_mesh.halfedge_graph());
|
||||
CGAL::Polygon_mesh_processing::compute_vertex_normal(vd, deform_mesh->halfedge_graph());
|
||||
normals[id*3] = n.x();
|
||||
normals[id*3+1] = n.y();
|
||||
normals[id*3+2] = n.z();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
double scene_diag() const {
|
||||
const double& xdelta = bbox().xmax - bbox().xmin;
|
||||
const double& ydelta = bbox().ymax - bbox().ymin;
|
||||
const double& zdelta = bbox().zmax - bbox().zmin;
|
||||
const double diag = std::sqrt(xdelta*xdelta +
|
||||
ydelta*ydelta +
|
||||
zdelta*zdelta);
|
||||
return diag * 0.5;
|
||||
}
|
||||
|
||||
}; // end class Scene_edit_polyhedron_item
|
||||
|
||||
#endif // SCENE_EDIT_POLYHEDRON_ITEM_H
|
||||
|
|
|
|||
|
|
@ -480,7 +480,7 @@ Scene_polyhedron_item::compute_normals_and_vertices(void) const
|
|||
he != poly->edges_end();
|
||||
he++)
|
||||
{
|
||||
if(he->is_feature_edge()) continue;
|
||||
if (!show_feature_edges_m && he->is_feature_edge()) continue;
|
||||
const Point& a = he->vertex()->point();
|
||||
const Point& b = he->opposite()->vertex()->point();
|
||||
positions_lines.push_back(a.x());
|
||||
|
|
@ -512,11 +512,8 @@ Scene_polyhedron_item::compute_normals_and_vertices(void) const
|
|||
positions_lines.push_back(b.y());
|
||||
positions_lines.push_back(b.z());
|
||||
positions_lines.push_back(1.0);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//set the colors
|
||||
compute_colors();
|
||||
}
|
||||
|
|
@ -593,6 +590,7 @@ Scene_polyhedron_item::Scene_polyhedron_item()
|
|||
: Scene_item(NbOfVbos,NbOfVaos),
|
||||
poly(new Polyhedron),
|
||||
show_only_feature_edges_m(false),
|
||||
show_feature_edges_m(false),
|
||||
facet_picking_m(false),
|
||||
erase_next_picked_facet_m(false),
|
||||
plugin_has_set_color_vector_m(false)
|
||||
|
|
@ -610,6 +608,7 @@ Scene_polyhedron_item::Scene_polyhedron_item(Polyhedron* const p)
|
|||
: Scene_item(NbOfVbos,NbOfVaos),
|
||||
poly(p),
|
||||
show_only_feature_edges_m(false),
|
||||
show_feature_edges_m(false),
|
||||
facet_picking_m(false),
|
||||
erase_next_picked_facet_m(false),
|
||||
plugin_has_set_color_vector_m(false)
|
||||
|
|
@ -627,6 +626,7 @@ Scene_polyhedron_item::Scene_polyhedron_item(const Polyhedron& p)
|
|||
: Scene_item(NbOfVbos,NbOfVaos),
|
||||
poly(new Polyhedron(p)),
|
||||
show_only_feature_edges_m(false),
|
||||
show_feature_edges_m(false),
|
||||
facet_picking_m(false),
|
||||
erase_next_picked_facet_m(false),
|
||||
plugin_has_set_color_vector_m(false)
|
||||
|
|
@ -776,12 +776,20 @@ QMenu* Scene_polyhedron_item::contextMenu()
|
|||
connect(actionShowOnlyFeatureEdges, SIGNAL(toggled(bool)),
|
||||
this, SLOT(show_only_feature_edges(bool)));
|
||||
|
||||
QAction* actionPickFacets =
|
||||
menu->addAction(tr("Facets picking"));
|
||||
actionPickFacets->setCheckable(true);
|
||||
actionPickFacets->setObjectName("actionPickFacets");
|
||||
connect(actionPickFacets, SIGNAL(toggled(bool)),
|
||||
this, SLOT(enable_facets_picking(bool)));
|
||||
QAction* actionShowFeatureEdges =
|
||||
menu->addAction(tr("Show feature edges"));
|
||||
actionShowFeatureEdges->setCheckable(true);
|
||||
actionShowFeatureEdges->setChecked(show_feature_edges_m);
|
||||
actionShowFeatureEdges->setObjectName("actionShowFeatureEdges");
|
||||
connect(actionShowFeatureEdges, SIGNAL(toggled(bool)),
|
||||
this, SLOT(show_feature_edges(bool)));
|
||||
|
||||
QAction* actionPickFacets =
|
||||
menu->addAction(tr("Facets picking"));
|
||||
actionPickFacets->setCheckable(true);
|
||||
actionPickFacets->setObjectName("actionPickFacets");
|
||||
connect(actionPickFacets, SIGNAL(toggled(bool)),
|
||||
this, SLOT(enable_facets_picking(bool)));
|
||||
|
||||
QAction* actionEraseNextFacet =
|
||||
menu->addAction(tr("Erase next picked facet"));
|
||||
|
|
@ -812,6 +820,13 @@ void Scene_polyhedron_item::show_only_feature_edges(bool b)
|
|||
Q_EMIT itemChanged();
|
||||
}
|
||||
|
||||
void Scene_polyhedron_item::show_feature_edges(bool b)
|
||||
{
|
||||
show_feature_edges_m = b;
|
||||
invalidate_buffers();
|
||||
Q_EMIT itemChanged();
|
||||
}
|
||||
|
||||
void Scene_polyhedron_item::enable_facets_picking(bool b)
|
||||
{
|
||||
facet_picking_m = b;
|
||||
|
|
@ -857,14 +872,16 @@ void Scene_polyhedron_item::draw(CGAL::Three::Viewer_interface* viewer) const {
|
|||
}
|
||||
|
||||
// Points/Wireframe/Flat/Gouraud OpenGL drawing in a display list
|
||||
void Scene_polyhedron_item::draw_edges(CGAL::Three::Viewer_interface* viewer) const {
|
||||
if(!are_buffers_filled)
|
||||
void Scene_polyhedron_item::draw_edges(CGAL::Three::Viewer_interface* viewer) const
|
||||
{
|
||||
if (!are_buffers_filled)
|
||||
{
|
||||
compute_normals_and_vertices();
|
||||
initialize_buffers(viewer);
|
||||
}
|
||||
|
||||
vaos[Edges]->bind();
|
||||
|
||||
attrib_buffers(viewer, PROGRAM_WITHOUT_LIGHT);
|
||||
program = getShaderProgram(PROGRAM_WITHOUT_LIGHT);
|
||||
program->bind();
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ public Q_SLOTS:
|
|||
virtual void invalidate_buffers();
|
||||
virtual void selection_changed(bool);
|
||||
virtual void setColor(QColor c);
|
||||
virtual void show_feature_edges(bool);
|
||||
void show_only_feature_edges(bool);
|
||||
void enable_facets_picking(bool);
|
||||
void set_erase_next_picked_facet(bool);
|
||||
|
|
@ -102,9 +103,10 @@ private:
|
|||
typedef std::vector<QColor> Color_vector;
|
||||
typedef Polyhedron::Facet_iterator Facet_iterator;
|
||||
|
||||
Color_vector colors_;
|
||||
|
||||
Color_vector colors_;
|
||||
bool show_only_feature_edges_m;
|
||||
bool show_feature_edges_m;
|
||||
bool facet_picking_m;
|
||||
bool erase_next_picked_facet_m;
|
||||
//the following variable is used to indicate if the color vector must not be automatically updated.
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ class SCENE_POLYHEDRON_ITEM_K_RING_SELECTION_EXPORT Scene_polyhedron_item_k_ring
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
struct Active_handle { enum Type{ VERTEX = 0, FACET = 1, EDGE = 2 }; };
|
||||
struct Active_handle {
|
||||
enum Type{ VERTEX = 0, FACET = 1, EDGE = 2 , CONNECTED_COMPONENT = 3}; };
|
||||
|
||||
typedef boost::graph_traits<Polyhedron>::edge_descriptor edge_descriptor;
|
||||
|
||||
|
|
@ -75,8 +76,9 @@ public Q_SLOTS:
|
|||
void facet_has_been_selected(void* void_ptr)
|
||||
{
|
||||
is_active=true;
|
||||
if(active_handle_type != Active_handle::FACET) { return; }
|
||||
process_selection( static_cast<Polyhedron::Facet*>(void_ptr)->halfedge()->facet() );
|
||||
if (active_handle_type == Active_handle::FACET
|
||||
|| active_handle_type == Active_handle::CONNECTED_COMPONENT)
|
||||
process_selection(static_cast<Polyhedron::Facet*>(void_ptr)->halfedge()->facet());
|
||||
}
|
||||
void edge_has_been_selected(void* void_ptr)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <CGAL/Polygon_mesh_processing/orient_polygon_soup.h>
|
||||
#include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h>
|
||||
#include <CGAL/Polygon_mesh_processing/connected_components.h>
|
||||
#include "Polyhedron_demo_detect_sharp_edges.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <boost/foreach.hpp>
|
||||
|
|
@ -19,6 +20,7 @@
|
|||
#include <boost/property_map/vector_property_map.hpp>
|
||||
|
||||
#include <CGAL/boost/graph/selection.h>
|
||||
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
|
||||
|
||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
|
||||
|
|
@ -252,6 +254,10 @@ public:
|
|||
typedef boost::unordered_set<Facet_handle, CGAL::Handle_hash_function> Selection_set_facet;
|
||||
typedef boost::unordered_set<edge_descriptor, CGAL::Handle_hash_function> Selection_set_edge;
|
||||
|
||||
Polyhedron* polyhedron()
|
||||
{
|
||||
return this->poly_item->polyhedron();
|
||||
}
|
||||
|
||||
using Scene_polyhedron_item_decorator::draw;
|
||||
virtual void draw(CGAL::Three::Viewer_interface*) const;
|
||||
|
|
@ -394,6 +400,7 @@ public:
|
|||
case Active_handle::VERTEX:
|
||||
select_all<Vertex_handle>(); break;
|
||||
case Active_handle::FACET:
|
||||
case Active_handle::CONNECTED_COMPONENT:
|
||||
select_all<Facet_handle>(); break;
|
||||
case Active_handle::EDGE:
|
||||
selected_edges.insert(edges(*polyhedron()).first, edges(*polyhedron()).second);
|
||||
|
|
@ -421,6 +428,7 @@ public:
|
|||
case Active_handle::VERTEX:
|
||||
clear<Vertex_handle>(); break;
|
||||
case Active_handle::FACET:
|
||||
case Active_handle::CONNECTED_COMPONENT:
|
||||
clear<Facet_handle>(); break;
|
||||
case Active_handle::EDGE:
|
||||
clear<edge_descriptor>(); break;
|
||||
|
|
@ -436,6 +444,12 @@ public:
|
|||
Q_EMIT itemChanged();
|
||||
}
|
||||
|
||||
void clear_all(){
|
||||
clear<Vertex_handle>();
|
||||
clear<Facet_handle>();
|
||||
clear<edge_descriptor>();
|
||||
}
|
||||
|
||||
boost::optional<std::size_t> get_minimum_isolated_component() {
|
||||
switch(get_active_handle_type()) {
|
||||
case Active_handle::VERTEX:
|
||||
|
|
@ -490,9 +504,10 @@ public:
|
|||
dilate_selection<Vertex_handle>(steps);
|
||||
break;
|
||||
case Active_handle::FACET:
|
||||
case Active_handle::CONNECTED_COMPONENT:
|
||||
dilate_selection<Facet_handle>(steps);
|
||||
break;
|
||||
default:
|
||||
case Active_handle::EDGE:
|
||||
dilate_selection<edge_descriptor>(steps);
|
||||
}
|
||||
}
|
||||
|
|
@ -503,9 +518,10 @@ public:
|
|||
erode_selection<Vertex_handle>(-steps);
|
||||
break;
|
||||
case Active_handle::FACET:
|
||||
case Active_handle::CONNECTED_COMPONENT:
|
||||
erode_selection<Facet_handle>(-steps);
|
||||
break;
|
||||
default:
|
||||
case Active_handle::EDGE:
|
||||
erode_selection<edge_descriptor>(-steps);
|
||||
}
|
||||
}
|
||||
|
|
@ -551,8 +567,8 @@ public:
|
|||
};
|
||||
|
||||
template <class Handle>
|
||||
void dilate_selection(unsigned int steps) {
|
||||
|
||||
void dilate_selection(unsigned int steps)
|
||||
{
|
||||
typedef Selection_traits<Handle, Scene_polyhedron_selection_item> Tr;
|
||||
Tr tr(this);
|
||||
|
||||
|
|
@ -681,6 +697,19 @@ public:
|
|||
return out->size_of_vertices() > 0;
|
||||
}
|
||||
|
||||
void select_sharp_edges(const double angle)
|
||||
{
|
||||
CGAL::detect_sharp_edges(polyhedron(), angle);
|
||||
|
||||
BOOST_FOREACH(edge_descriptor e, edges(*polyhedron()))
|
||||
{
|
||||
Polyhedron::Halfedge_handle h = halfedge(e, *polyhedron());
|
||||
if (h->is_feature_edge())
|
||||
selected_edges.insert(e);
|
||||
}
|
||||
invalidate_buffers();
|
||||
}
|
||||
|
||||
void changed_with_poly_item() {
|
||||
// no need to update indices
|
||||
poly_item->invalidate_buffers();
|
||||
|
|
@ -746,10 +775,10 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
template<class HandleType>
|
||||
void has_been_selected(const std::set<HandleType>& selection)
|
||||
template<typename HandleRange>
|
||||
bool treat_selection(const HandleRange& selection)
|
||||
{
|
||||
if(!visible()) { return; }
|
||||
typedef typename HandleRange::value_type HandleType;
|
||||
Selection_traits<HandleType, Scene_polyhedron_selection_item> tr(this);
|
||||
|
||||
bool any_change = false;
|
||||
|
|
@ -762,6 +791,48 @@ protected:
|
|||
any_change |= (tr.container().erase(h)!=0);
|
||||
}
|
||||
if(any_change) { invalidate_buffers(); Q_EMIT itemChanged(); }
|
||||
return any_change;
|
||||
}
|
||||
|
||||
Facet_handle face(Facet_handle fh)
|
||||
{ return fh; }
|
||||
Facet_handle face(Vertex_handle)
|
||||
{ return boost::graph_traits<Polyhedron>::null_face(); }
|
||||
Facet_handle face(edge_descriptor)
|
||||
{ return boost::graph_traits<Polyhedron>::null_face(); }
|
||||
|
||||
template<class HandleType>
|
||||
void has_been_selected(const std::set<HandleType>& selection)
|
||||
{
|
||||
if(!visible()) { return; }
|
||||
|
||||
bool any_change = false;
|
||||
|
||||
if (get_active_handle_type() == Active_handle::CONNECTED_COMPONENT)
|
||||
{
|
||||
Selection_traits<edge_descriptor,
|
||||
Scene_polyhedron_selection_item> tr(this);
|
||||
tr.update_indices();
|
||||
|
||||
std::vector<bool> mark(tr.size(), false);
|
||||
BOOST_FOREACH(edge_descriptor e, selected_edges)
|
||||
mark[tr.id(e)] = true;
|
||||
|
||||
std::vector<Facet_handle> selected_cc;
|
||||
CGAL::Polygon_mesh_processing::connected_component(
|
||||
face(*selection.begin()),
|
||||
*polyhedron(),
|
||||
std::back_inserter(selected_cc),
|
||||
CGAL::Polygon_mesh_processing::parameters::edge_is_constrained_map(
|
||||
Is_selected_property_map<edge_descriptor>(mark)));
|
||||
|
||||
any_change = treat_selection(selected_cc);
|
||||
}
|
||||
else
|
||||
{
|
||||
any_change = treat_selection(selection);
|
||||
}
|
||||
if(any_change) { Q_EMIT changed_with_poly_item(); }
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -6,15 +6,15 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>399</width>
|
||||
<height>556</height>
|
||||
<width>455</width>
|
||||
<height>684</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Selection</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
|
|
@ -46,6 +46,11 @@
|
|||
<string>Edge</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Connected component (facet)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
@ -53,165 +58,244 @@
|
|||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string/>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="Insertion_radio_button">
|
||||
<property name="text">
|
||||
<string>Insertion</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="Removal_radio_button">
|
||||
<property name="text">
|
||||
<string>Removal</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Brush &size:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>Brush_size_spin_box</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="Brush_size_spin_box"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QPushButton" name="Select_all_button">
|
||||
<property name="text">
|
||||
<string>Select &All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="Clear_button">
|
||||
<property name="text">
|
||||
<string>&Clear</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Isolated &Component Size:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>Threshold_size_spin_box</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="Threshold_size_spin_box">
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>8</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="Get_minimum_button">
|
||||
<property name="text">
|
||||
<string>&Get Minimum</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="Select_isolated_components_button">
|
||||
<property name="text">
|
||||
<string>Select &Isolated Components Below Threshold</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="Insertion_radio_button">
|
||||
<property name="text">
|
||||
<string>Insertion</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="Removal_radio_button">
|
||||
<property name="text">
|
||||
<string>Removal</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Brush &size:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>Brush_size_spin_box</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="Brush_size_spin_box"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QPushButton" name="Select_all_button">
|
||||
<property name="text">
|
||||
<string>Select &All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="Clear_button">
|
||||
<property name="text">
|
||||
<string>&Clear</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string/>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Dilate or erode selection:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="Dilate_erode_spin_box">
|
||||
<property name="minimum">
|
||||
<number>-50</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>50</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="Dilate_erode_button">
|
||||
<property name="text">
|
||||
<string>Apply</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Isolated &Component Size:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>Threshold_size_spin_box</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="Threshold_size_spin_box">
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>8</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="Get_minimum_button">
|
||||
<property name="text">
|
||||
<string>&Get Minimum</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="Select_isolated_components_button">
|
||||
<property name="text">
|
||||
<string>Select &Isolated Components Below Threshold</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Sharp edges angle:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="Sharp_angle_spinbox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>180</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>60</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="Select_sharp_edges_button">
|
||||
<property name="text">
|
||||
<string>Select</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_1">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Dilate or erode selection:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="Dilate_erode_spin_box">
|
||||
<property name="minimum">
|
||||
<number>-50</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>50</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="Dilate_erode_button">
|
||||
<property name="text">
|
||||
<string>Apply</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="Create_point_set_item_button">
|
||||
|
|
@ -234,6 +318,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="Erase_selected_facets_button">
|
||||
<property name="text">
|
||||
<string>Erase Selected Facets from Polyhedron Item</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="Keep_connected_components_button">
|
||||
<property name="toolTip">
|
||||
|
|
@ -244,13 +335,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="Erase_selected_facets_button">
|
||||
<property name="text">
|
||||
<string>Erase Selected Facets from Polyhedron Item</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
|
|
|
|||
|
|
@ -2474,7 +2474,7 @@ private: //------------------------------------------------------- private data
|
|||
reindex.resize(sm.num_vertices());
|
||||
int n = 0;
|
||||
BOOST_FOREACH(Vertex_index v, sm.vertices()){
|
||||
os << sm.point(v) << std::endl;
|
||||
os << sm.point(v) << '\n';
|
||||
reindex[v]=n++;
|
||||
}
|
||||
|
||||
|
|
@ -2483,7 +2483,7 @@ private: //------------------------------------------------------- private data
|
|||
BOOST_FOREACH(Vertex_index v, CGAL::vertices_around_face(sm.halfedge(f),sm)){
|
||||
os << " " << reindex[v];
|
||||
}
|
||||
os << "\n";
|
||||
os << '\n';
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@
|
|||
|
||||
- `CGAL::Mean_curvature_flow_skeletonization`
|
||||
|
||||
\todo doc+code: mention that to get a better skeleton that is closer to the medial axis,
|
||||
the surface must be sufficiently well sampled so that the Voronoi poles lie on the media axis (see Amenta's paper).
|
||||
Propose the usage of the isotropic remeshing and see if we add a boolean to do it automatically in the api (correspondance would be broken)
|
||||
\todo code: implement the random sampling of surface using the work started by Alexandru during its gsoc to get a better approximation of poles
|
||||
\todo code: expose in polygon mesh processing the function to compute the voronoi pole of a close triangle mesh
|
||||
\todo code: expose in polygon mesh processing the function to remesh locally a triangle mesh with the angle and edge length parameters
|
||||
|
|
|
|||
Loading…
Reference in New Issue