Merge branch 'BGL-SurfaceMesh2SurfaceMesh-GF' into Polygon_mesh_processing-local_remeshing-GF

This commit is contained in:
Sébastien Loriot 2015-11-05 19:25:00 +01:00
commit 54ca52b538
226 changed files with 8062 additions and 2738 deletions

View File

@ -148,7 +148,7 @@ namespace CGAL {
if(first_vertex != S.triangulation_3().finite_vertices_end()) {
pos = first_vertex;
pos->set_post_mark(mark);
assert(pos->is_on_border());
CGAL_assertion(pos->is_on_border());
} else {
pos = NULL;
@ -469,7 +469,7 @@ namespace CGAL {
inline void set_interior_edge(Vertex_handle w, Vertex_handle v)
{
if(w->m_ie_last == ie_sentinel){ // empty set
assert(w->m_ie_first == w->m_ie_last);
CGAL_assertion(w->m_ie_first == w->m_ie_last);
w->m_ie_last = interior_edges.insert(w->m_ie_last, v);
w->m_ie_first = w->m_ie_last;
} else {
@ -477,7 +477,7 @@ namespace CGAL {
e++;
#ifdef DEBUG
typename std::list<Vertex_handle>::iterator r = std::find(w->m_ie_first, e, v);
assert(r == e);
CGAL_assertion(r == e);
#endif
w->m_ie_last = interior_edges.insert(e, v);
}
@ -487,7 +487,7 @@ namespace CGAL {
inline void remove_interior_edge(Vertex_handle w, Vertex_handle v)
{
if(w->m_ie_first == ie_sentinel){
assert(w->m_ie_last == w->m_ie_first);
CGAL_assertion(w->m_ie_last == w->m_ie_first);
} else if(w->m_ie_first == w->m_ie_last){ // there is only one element
if(*(w->m_ie_first) == v){
interior_edges.erase(w->m_ie_first);
@ -516,7 +516,7 @@ namespace CGAL {
inline void set_incidence_request(Vertex_handle w, const Incidence_request_elt& ir)
{
if(w->m_ir_last == sentinel ){
assert(w->m_ir_first == w->m_ir_last);
CGAL_assertion(w->m_ir_first == w->m_ir_last);
w->m_ir_last = incidence_requests.insert(w->m_ir_last, ir);
w->m_ir_first = w->m_ir_last;
} else {
@ -529,7 +529,7 @@ namespace CGAL {
inline bool is_incidence_requested(Vertex_handle w) const
{
if(w->m_ir_last == sentinel ){
assert(w->m_ir_first == sentinel );
CGAL_assertion(w->m_ir_first == sentinel );
}
return (w->m_ir_last != sentinel );
}
@ -542,7 +542,7 @@ namespace CGAL {
inline Incidence_request_iterator incidence_request_end(Vertex_handle w)
{
if(w->m_ir_last != sentinel ){
assert(w->m_ir_first != sentinel );
CGAL_assertion(w->m_ir_first != sentinel );
Incidence_request_iterator it(w->m_ir_last);
it++;
return it;
@ -553,7 +553,7 @@ namespace CGAL {
inline void erase_incidence_request(Vertex_handle w)
{
if(w->m_ir_last != sentinel ){
assert(w->m_ir_first != sentinel );
CGAL_assertion(w->m_ir_first != sentinel );
w->m_ir_last++;
incidence_requests.erase(w->m_ir_first, w->m_ir_last);
w->m_ir_first = sentinel ;
@ -570,7 +570,7 @@ namespace CGAL {
}
if(w->m_ir_first != sentinel ){
assert(w->m_ir_last != sentinel );
CGAL_assertion(w->m_ir_last != sentinel );
typename std::list< Incidence_request_elt >::iterator b(w->m_ir_first), e(w->m_ir_last);
e++;
incidence_requests.erase(b, e);
@ -627,14 +627,14 @@ namespace CGAL {
w->delete_border();
}
if(w->m_ir_first != sentinel ){
assert(w->m_ir_last != sentinel );
CGAL_assertion(w->m_ir_last != sentinel );
typename std::list< Incidence_request_elt >::iterator b(w->m_ir_first), e(w->m_ir_last);
e++;
incidence_requests.erase(b, e);
}
if(w->m_ie_first != ie_sentinel){
assert(w->m_ie_last != ie_sentinel);
CGAL_assertion(w->m_ie_last != ie_sentinel);
typename std::list<Vertex_handle>::iterator b(w->m_ie_first), e(w->m_ie_last);
e++;
interior_edges.erase(b, e);
@ -746,7 +746,7 @@ namespace CGAL {
void run(double radius_ratio_bound=5, double beta= 0.52)
{
K = radius_ratio_bound;
COS_BETA = acos(beta);
COS_BETA = cos(beta);
if(T.dimension() < 3){
return;
}
@ -2186,7 +2186,7 @@ namespace CGAL {
{
_facet_number--;
assert(c->is_selected_facet(index));
CGAL_assertion(c->is_selected_facet(index));
unselect_facet(c, index);
Facet f32 =

View File

@ -134,7 +134,7 @@ namespace CGAL {
tds.set_adjacency(fn, 2, inf_edge_map);
edge_map.erase(edge_map.begin());
}
CGAL_triangulation_assertion(inf_edge_map.empty());
CGAL_assertion(inf_edge_map.empty());
}
tds.reorient_faces();
return vinf;

View File

@ -122,7 +122,7 @@ namespace CGAL {
tds.set_adjacency(fn, 2, inf_edge_map);
edge_map.erase(edge_map.begin());
}
CGAL_triangulation_assertion(inf_edge_map.empty());
CGAL_assertion(inf_edge_map.empty());
}

View File

@ -35,6 +35,7 @@
#include <CGAL/basic.h>
#include <CGAL/assertions.h>
#include <CGAL/Cache.h>
#include <CGAL/function_objects.h>
#include <CGAL/Handle_with_policy.h>
@ -904,7 +905,7 @@ private:
break;
}
default:{
assert(false); // !!! Never reached
CGAL_assertion(false); // !!! Never reached
}
}
}

View File

@ -20,7 +20,7 @@
#ifndef CGAL_INTERNAL_LAZY_ALPHA_NT_2_H
#define CGAL_INTERNAL_LAZY_ALPHA_NT_2_H
#include <CGAL/assertions.h>
#include <CGAL/Weighted_alpha_shape_euclidean_traits_2.h>
#include <boost/shared_ptr.hpp>
#include <boost/mpl/has_xxx.hpp>
@ -139,7 +139,7 @@ public:
exact_ = Exact_squared_radius()( to_exact(*data()[0]),to_exact(*data()[1]),to_exact(*data()[2]) );
break;
default:
assert(false);
CGAL_assertion(false);
}
updated=true;
}
@ -156,7 +156,7 @@ public:
approx_ = Approx_squared_radius()( to_approx(*data()[0]),to_approx(*data()[1]),to_approx(*data()[2]) );
break;
default:
assert(false);
CGAL_assertion(false);
}
}

View File

@ -21,6 +21,7 @@
#ifndef CGAL_INTERNAL_LAZY_ALPHA_NT_3_H
#define CGAL_INTERNAL_LAZY_ALPHA_NT_3_H
#include <CGAL/assertions.h>
#include <CGAL/Regular_triangulation_euclidean_traits_3.h>
#include <boost/shared_ptr.hpp>
#include <boost/type_traits.hpp>
@ -140,7 +141,7 @@ public:
exact_ = Exact_squared_radius()( to_exact(*data()[0]),to_exact(*data()[1]),to_exact(*data()[2]),to_exact(*data()[3]) );
break;
default:
assert(false);
CGAL_assertion(false);
}
updated=true;
}
@ -160,7 +161,7 @@ public:
approx_ = Approx_squared_radius()( to_approx(*data()[0]),to_approx(*data()[1]),to_approx(*data()[2]),to_approx(*data()[3]) );
break;
default:
assert(false);
CGAL_assertion(false);
}
}

View File

@ -553,13 +553,13 @@ public:
Comparison_result operator() (const Vertical_segment & cv1,
const Non_vertical_x_curve_2 & cv2) const
{
assert(false);
CGAL_assertion(false);
return CGAL::SMALLER;
}
Comparison_result operator() (const Non_vertical_x_curve_2& cv1,
const Vertical_segment & cv2) const
{
assert(false);
CGAL_assertion(false);
return CGAL::LARGER;
}
Comparison_result operator() (const Vertical_segment & cv1,

View File

@ -24,6 +24,7 @@
#include <CGAL/Arr_rat_arc/Base_rational_arc_ds_1.h>
#include <CGAL/Arr_rat_arc/Rational_function.h>
#include <CGAL/Handle_with_policy.h>
#include <CGAL/assertions.h>
namespace CGAL {
namespace Arr_rational_arc {
@ -69,7 +70,7 @@ public:
#if 1
solve_1(_resultant,std::back_inserter(rm_vec));
#else
assert(false);
CGAL_assertion(false);
// don't use this code yet since g and resultant/g may still have a
// common root
if( CGAL::internal::may_have_common_factor(_f.denom(),_g.denom())){

View File

@ -20,9 +20,11 @@
#ifndef SINGLETON_H_
#ifndef CGAL_SINGLETON_H_
#define SINGLETON_H_
#include <CGAL/assertions.h>
namespace CGAL {
namespace Arr_rational_arc {
template <class T>
@ -33,7 +35,7 @@ public:
{
if(!m_pInstance)
m_pInstance = new T;
assert(m_pInstance !=NULL);
CGAL_assertion(m_pInstance !=NULL);
return m_pInstance;
}
@ -53,4 +55,4 @@ template <class T> T* Singleton<T>::m_pInstance=NULL;
} // namespace Arr_rational_arc
} //namespace CGAL {
#endif // SINGLETON_H_
#endif // CGAL_SINGLETON_H_

View File

@ -21,6 +21,7 @@
#ifndef CGAL_ARR_RATIONAL_ARC_TRAITS_D_1_H
#define CGAL_ARR_RATIONAL_ARC_TRAITS_D_1_H
#include <CGAL/assertions.h>
#include <CGAL/tags.h>
#include <CGAL/Fraction_traits.h>
#include <CGAL/Arr_tags.h>
@ -1295,7 +1296,7 @@ public:
Approximate_number_type operator()(const Point_2& p, int i){
if(i==0) return approx_x(p);
if(i==1) return approx_y(p);
assert(false);
CGAL_assertion(false);
return Approximate_number_type(0);
}
};

View File

@ -34,6 +34,7 @@
#include <CGAL/Arr_topology_traits/Arr_unb_planar_batched_pl_helper.h>
#include <CGAL/Arr_topology_traits/Arr_unb_planar_vert_decomp_helper.h>
#include <CGAL/Arr_topology_traits/Arr_inc_insertion_zone_visitor.h>
#include <CGAL/assertions.h>
namespace CGAL {
@ -507,7 +508,7 @@ public:
*/
const Face* reference_face() const
{
assert(v_tr->halfedge()->direction() == ARR_LEFT_TO_RIGHT);
CGAL_assertion(v_tr->halfedge()->direction() == ARR_LEFT_TO_RIGHT);
return v_tr->halfedge()->outer_ccb()->face();
}
@ -519,7 +520,7 @@ public:
*/
Face* reference_face()
{
assert(v_tr->halfedge()->direction() == ARR_LEFT_TO_RIGHT);
CGAL_assertion(v_tr->halfedge()->direction() == ARR_LEFT_TO_RIGHT);
return v_tr->halfedge()->outer_ccb()->face();
}

View File

@ -131,12 +131,14 @@ user might encounter.
- `CGAL::is_bivalent_mesh()`
- `CGAL::is_trivalent()`
- `CGAL::is_trivalent_mesh()`
- `CGAL::is_isolated_triangle()`
- `CGAL::is_closed()`
- `CGAL::is_triangle()`
- `CGAL::is_triangle_mesh()`
- `CGAL::is_quad()`
- `CGAL::is_quad_mesh()`
- `CGAL::is_isolated_quad()`
- `CGAL::is_tetrahedron()`
- `CGAL::is_hexahedron()`
@ -150,10 +152,16 @@ user might encounter.
- `CGAL::Halfedge_around_target_iterator`
- `CGAL::Halfedge_around_face_iterator`
- `CGAL::Vertex_around_target_iterator`
- `CGAL::Vertex_around_face_iterator`
- `CGAL::Face_around_face_iterator`
- `CGAL::Face_around_target_iterator`
- `CGAL::halfedges_around_source`
- `CGAL::halfedges_around_target`
- `CGAL::halfedges_around_face`
- `CGAL::halfedges_around_source()`
- `CGAL::halfedges_around_target()`
- `CGAL::halfedges_around_face()`
- `CGAL::faces_around_face()`
- `CGAL::faces_around_target()`
- `CGAL::vertices_around_face()`
- `CGAL::vertices_around_target()`
## Circulators ##
- `CGAL::Halfedge_around_source_circulator`
@ -161,26 +169,29 @@ user might encounter.
- `CGAL::Halfedge_around_face_circulator`
- `CGAL::Vertex_around_target_circulator`
- `CGAL::Face_around_target_circulator`
- `CGAL::Face_around_face_circulator`
## Euler Operations ##
- `CGAL::Euler::join_vertex()`
- `CGAL::Euler::split_vertex()`
- `CGAL::Euler::split_edge()`
- `CGAL::Euler::join_face()`
- `CGAL::Euler::split_face()`
- `CGAL::Euler::join_loop()`
- `CGAL::Euler::split_loop()`
- `CGAL::Euler::remove_face()`
- `CGAL::Euler::make_hole()`
- `CGAL::Euler::fill_hole()`
- `CGAL::Euler::add_center_vertex()`
- `CGAL::Euler::add_edge()`
- `CGAL::Euler::add_face()`
- `CGAL::Euler::add_face_to_border()`
- `CGAL::Euler::add_vertex_and_face_to_border()`
- `CGAL::Euler::collapse_edge()`
- `CGAL::Euler::does_satisfy_link_condition()`
- `CGAL::Euler::fill_hole()`
- `CGAL::Euler::flip_edge()`
- `CGAL::Euler::join_face()`
- `CGAL::Euler::join_loop()`
- `CGAL::Euler::join_vertex()`
- `CGAL::Euler::make_hole()`
- `CGAL::Euler::remove_center_vertex()`
- `CGAL::Euler::add_vertex_and_face_to_border()`
- `CGAL::Euler::add_face_to_border()`
- `CGAL::Euler::collapse_edge()`
- `CGAL::Euler::does_satisfy_link_condition()`
- `CGAL::Euler::remove_face()`
- `CGAL::Euler::split_edge()`
- `CGAL::Euler::split_face()`
- `CGAL::Euler::split_loop()`
- `CGAL::Euler::split_vertex()`
*/

View File

@ -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()

View File

@ -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;
}

View File

@ -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()

View File

@ -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, char* argv[])
{
Source S;
Target T;
std::ifstream in(argv[1]);
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");
}
{
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;
}

View File

@ -1095,7 +1095,7 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor v0v1,
remove_vertex(p,g);
Halfedge_around_target_circulator<Graph> beg(ppt,g), end(pqb,g);
while(beg != end){
assert(target(*beg,g) == p);
CGAL_assertion(target(*beg,g) == p);
set_target(*beg,q,g);
--beg;
}
@ -1322,7 +1322,7 @@ flip_edge(typename boost::graph_traits<Graph>::halfedge_descriptor h,
vertex_descriptor s2 = target(nh,g), t2 = target(noh,g);
face_descriptor fh = face(h,g), foh = face(oh,g);
assert(fh != Traits::null_face() && foh != Traits::null_face());
CGAL_assertion(fh != Traits::null_face() && foh != Traits::null_face());
if(halfedge(s,g) == oh){
set_halfedge(s,nnh,g);
@ -1455,6 +1455,7 @@ bool
}
#ifndef CGAL_NO_DEPRECATED_CODE
/// \cond SKIP_IN_MANUAL
template<typename Graph>
bool
satisfies_link_condition(typename boost::graph_traits<Graph>::edge_descriptor e,
@ -1462,6 +1463,7 @@ bool
{
return does_satisfy_link_condition(e, g);
}
/// \endcond
#endif
/// @}

View File

@ -0,0 +1,64 @@
#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>
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 boost::graph_traits<SourceMesh>::vertex_descriptor sm_vertex_descriptor;
typedef boost::graph_traits<TargetMesh>::vertex_descriptor tm_vertex_descriptor;
typedef boost::graph_traits<SourceMesh>::face_descriptor sm_face_descriptor;
typedef boost::graph_traits<TargetMesh>::face_descriptor tm_face_descriptor;
typedef boost::graph_traits<SourceMesh>::halfedge_descriptor sm_halfedge_descriptor;
typedef 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

View File

@ -30,6 +30,7 @@
#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/PolyMesh_ArrayKernelT.hh>
@ -354,6 +355,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));
@ -540,7 +544,7 @@ template <typename K>
void
clear_vertex(typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::vertex_descriptor,
OpenMesh::PolyMesh_ArrayKernelT<K>&) {
assert(false);
CGAL_assert(false);
}
*/
@ -606,12 +610,12 @@ remove_face(typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::f
sm.request_face_status();
sm.request_vertex_status();
sm.request_halfedge_status();
set_halfedge(f, typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::halfedge_descriptor(), sm);
set_halfedge(f, typename boost::graph_traits<OpenMesh::PolyMesh_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::PolyMesh_ArrayKernelT<K> >::edge_descriptor,
bool>
@ -621,6 +625,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

View File

@ -29,7 +29,7 @@
#include <CGAL/boost/graph/iterator.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/assertions.h>
namespace boost {
@ -445,7 +445,7 @@ template <typename P>
void
clear_vertex(typename boost::graph_traits<CGAL::Surface_mesh<P> >::vertex_descriptor,
CGAL::Surface_mesh<P>&) {
assert(false);
CGAL_assertion(false);
}
*/

View File

@ -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

View File

@ -872,7 +872,16 @@ halfedges_around_face(typename boost::graph_traits<Graph>::halfedge_descriptor h
return make_range(I(h,g), I(h,g,1));
}
/**
* \ingroup PkgBGLIterators
* A bidirectional iterator with value type `boost::graph_traits<Graph>::%face_descriptor`.
* It iterates over the same halfedges as the `Halfedge_around_face_iterator`,
* and provides the face descriptor associated to the opposite halfedge. The face descriptor
* may be the null face, and it may be several times the same face descriptor.
*
* \tparam Graph must be a model of the concept `HalfedgeGraph`
* \cgalModels `BidirectionalCirculator`
*/
template <typename Graph>
class Face_around_face_iterator
#ifndef DOXYGEN_RUNNING
@ -1023,6 +1032,13 @@ private:
#endif
};
/**
* \ingroup PkgBGLIterators
* A bidirectional iterator with value type `boost::graph_traits<Graph>::%vertex_descriptor`
* over all vertices incident to the same face or border.
* \tparam Graph must be a model of the concept `HalfedgeGraph`
* \cgalModels `BidirectionalIterator`
*/
template <typename Graph>
class Vertex_around_face_iterator
#ifndef DOXYGEN_RUNNING
@ -1111,7 +1127,7 @@ opposite_edges_around_face(typename boost::graph_traits<Graph>::halfedge_descrip
/**
* \ingroup PkgBGLIterators
* A bidirectional circulator with value type `boost::graph_traits<Graph>::%vertex_descriptor` over all vertices adjacent to the same vertex.
* A bidirectional circulator with value type `boost::graph_traits<Graph>::%vertex_descriptor` over all vertices adjacent to the same vertex.
* It circulates over the same halfedges as the `Halfedge_around_target_circulator`.
*
* \tparam Graph must be a model of the concept `HalfedgeGraph`

View File

@ -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 Mesh::edge_descriptor> type;
typedef CGAL::OM_index_pmap<K, typename 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 Mesh::halfedge_descriptor> type;
typedef CGAL::OM_index_pmap<K, typename 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,13 +295,15 @@ 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>&)
{
typedef OpenMesh::PolyMesh_ArrayKernelT<K> Mesh;
return CGAL::OM_index_pmap<K, typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::face_descriptor>();
}
@ -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

View File

@ -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 */

View File

@ -10,7 +10,7 @@
\cgalPkgPicture{barcoord_thumb.png}
\cgalPkgSummaryBegin
\cgalPkgAuthors{Dmitry Anisimov, David Bommes, Kai Hormann, and Pierre Alliez}
\cgalPkgDesc{The package 2D Generalized Barycentric Coordinates offers an efficient and robust implementation of two-dimensional closed-form generalized barycentric coordinates defined for simple two-dimensional polygons. If coordinates with respect to multivariate scattered points instead of a polygon are required, please refer to natural neighbour coordinates from the package 2D and Surface Function Interpolation.}
\cgalPkgDesc{The package 2D Generalized Barycentric Coordinates offers an efficient and robust implementation of two-dimensional closed-form generalized barycentric coordinates defined for simple two-dimensional polygons. If coordinates with respect to multivariate scattered points instead of a polygon are required, please refer to natural neighbor coordinates from the Package \ref PkgInterpolation2Summary.}
\cgalPkgManuals{Chapter_2D_Generalized_Barycentric_Coordinates, PkgBarycentric_coordinates_2}
\cgalPkgSummaryEnd
\cgalPkgShortInfoBegin

View File

@ -36,6 +36,7 @@
#define _CORE_BIGFLOAT_H_
#include <CGAL/CORE/BigFloatRep.h>
#include <CGAL/assertions.h>
namespace CORE {
@ -246,7 +247,7 @@ public:
/** \note This is only the sign of the mantissa, it can be taken to be
the sign of the BigFloat only if !(isZeroIn()). */
int sign() const {
assert((err() == 0 && m() == 0) || !(isZeroIn()));
CGAL_assertion((err() == 0 && m() == 0) || !(isZeroIn()));
return rep->signM();
}
/// check whether contains zero
@ -553,7 +554,7 @@ inline bool isDivisible(double x, double y) {
// normalizing it then we get zero.
inline BigFloat div_exact(const BigFloat& x, const BigFloat& y) {
BigInt z;
assert (isDivisible(x,y));
CGAL_assertion (isDivisible(x,y));
unsigned long bin_x = getBinExpo(x.m());
unsigned long bin_y = getBinExpo(y.m());

View File

@ -40,6 +40,7 @@
#define _CORE_EXPR_H_
#include <CGAL/CORE/ExprRep.h>
#include <CGAL/assertions.h>
namespace CORE {
@ -534,7 +535,7 @@ inline Expr rootOf(const Polynomial<NT>& p, int x, int y) {
* */
template <class NT>
inline Expr radical(const NT& n, int m) {
assert(n>=0 && m>=1);
CGAL_assertion(n>=0 && m>=1);
if (n == 0 || n == 1 || m == 1)
return Expr(n);
Polynomial<NT> Q(m);

View File

@ -39,6 +39,7 @@
#define _CORE_FILTER_H_
#include <CGAL/config.h>
#include <CGAL/assertions.h>
#include <CGAL/CORE/Real.h>
#include <cmath>
@ -111,7 +112,7 @@ public:
before call this function.) */
int sign() const {
#ifdef CORE_DEBUG
assert(isOK());
CGAL_assertion(isOK());
#endif
if (fpVal == 0.0)
return 0;

View File

@ -36,6 +36,7 @@
#include <new> // for placement new
#include <cassert>
#include <CGAL/assertions.h>
namespace CORE {
@ -96,7 +97,7 @@ void* MemoryPool< T, nObjects >::allocate(std::size_t) {
template< class T, int nObjects >
void MemoryPool< T, nObjects >::free(void* t) {
assert(t != 0);
CGAL_assertion(t != 0);
if (t == 0) return; // for safety
// recycle the object memory, by putting it back into the chain

View File

@ -192,7 +192,7 @@ BiPoly<NT>::~BiPoly(){
//Sets the input BiPoly to X^n
template <class NT>
void BiPoly<NT>::constructX(int n, BiPoly<NT>& P){
assert(n>= -1);
CGAL_assertion(n>= -1);
P.deleteCoeffX();//Clear the present coeffecients
Polynomial<NT> q(n);//Nominal degree n
q.setCoeff(n,NT(1));
@ -807,7 +807,7 @@ BiPoly<NT> & BiPoly<NT>::differentiateX() {
template <class NT>
BiPoly<NT> & BiPoly<NT>::differentiateXY(int m, int n) {//m times wrt X and n times wrt Y
assert(m >=0); assert(n >=0);
CGAL_assertion(m >=0); CGAL_assertion(n >=0);
for(int i=1; i <=m; i++)
(*this).differentiateX();
for(int i=1; i <=n; i++)
@ -1158,7 +1158,7 @@ int Curve<NT>::verticalIntersections(const BigFloat & x, BFVecInterval & vI,
// This returns a NULL vI, which should be caught by caller
Polynomial<Expr> PY = this->yExprPolynomial(x); // should be replaced
// assert(x.isExact());
// CGAL_assertion(x.isExact());
// Polynomial<BigFloat> PY = yBFPolynomial(x); // unstable still
d = PY.getTrueDegree();
@ -1205,9 +1205,9 @@ int Curve<NT>::plot( BigFloat eps, BigFloat x1,
const char* filename[] = {"data/input", "data/plot", "data/plot2"};
assert(eps.isExact()); // important for plotting...
assert(x1.isExact());
assert(y1.isExact());
CGAL_assertion(eps.isExact()); // important for plotting...
CGAL_assertion(x1.isExact());
CGAL_assertion(y1.isExact());
ofstream outFile;
outFile.open(filename[fileNo]); // ought to check if open is successful!
@ -1230,7 +1230,7 @@ int Curve<NT>::plot( BigFloat eps, BigFloat x1,
outFile << "0.99 \t 0.99 \t 0.99" << std::endl;
outFile << 0 << "\t" << y1 << std::endl;
outFile << 0 << "\t" << y2 << std::endl;
// assert(eps>0)
// CGAL_assertion(eps>0)
int aprec = -(eps.lMSB()).toLong(); // By definition, eps.lMSB() <= lg(eps)
BigFloat xCurr = x1;

View File

@ -60,6 +60,7 @@
#include <CGAL/CORE/BigFloat.h>
#include <CGAL/CORE/Promote.h>
#include <vector>
#include <CGAL/assertions.h>
namespace CORE {
using namespace std;
@ -412,7 +413,7 @@ template < class NT >
CORE_INLINE
const NT& Polynomial<NT>::getCoeff(int i) const {
//if (i > degree) return NULL;
assert(i <= degree);
CGAL_assertion(i <= degree);
return coeff[i];
}
// set functions

View File

@ -67,7 +67,7 @@ Polynomial<NT>::Polynomial(void) {
//Creates a polynomial with nominal degree n
template <class NT>
Polynomial<NT>::Polynomial(int n) {
assert(n>= -1);
CGAL_assertion(n>= -1);
degree = n;
if (n == -1)
return; // return the zero polynomial!
@ -80,7 +80,7 @@ Polynomial<NT>::Polynomial(int n) {
template <class NT>
Polynomial<NT>::Polynomial(int n, const NT * c) {
//assert("array c has n+1 elements");
//CGAL_assertion("array c has n+1 elements");
degree = n;
if (n >= 0) {
coeff = new NT[n+1];
@ -113,7 +113,7 @@ Polynomial<NT>::Polynomial(const Polynomial<NT> & p):degree(-1) {
///////////////////////////////////////
template <class NT>
Polynomial<NT>::Polynomial(int n, const char * s[]) {
//assert("array s has n+1 elements");
//CGAL_assertion("array s has n+1 elements");
degree = n;
if (n >= 0) {
coeff = new NT[n+1];
@ -826,7 +826,7 @@ template <>
CORE_INLINE
BigFloat Polynomial<BigInt>::evalApprox(const BigFloat& /*f*/,
const extLong& /*r*/, const extLong& /*a*/) const { // evaluation
assert(0);
CGAL_assertion(0);
return BigFloat(0);
}
@ -861,7 +861,7 @@ BigFloat Polynomial<BigInt>::evalApprox(const BigFloat& /*f*/,
template <class NT>
BigFloat Polynomial<NT>::evalExactSign(const BigFloat& val,
const extLong& oldMSB) const {
assert(val.isExact());
CGAL_assertion(val.isExact());
if (getTrueDegree() == -1)
return BigFloat(0);
@ -1063,7 +1063,7 @@ Polynomial<NT> & Polynomial<NT>::differentiate() { // self-differentiation
// multi-differentiate
template <class NT>
Polynomial<NT> & Polynomial<NT>::differentiate(int n) {
assert(n >= 0);
CGAL_assertion(n >= 0);
for (int i=1; i<=n; i++)
this->differentiate();
return *this;
@ -1128,7 +1128,7 @@ template <class NT>
Polynomial<NT> & Polynomial<NT>::primPart() {
// ASSERT: GCD must be provided by NT
int d = getTrueDegree();
assert (d >= 0);
CGAL_assertion (d >= 0);
if (d == 0) {
if (coeff[0] > 0) coeff[0] = 1;
else coeff[0] = -1;
@ -1371,7 +1371,7 @@ Polynomial<NT> differentiate(const Polynomial<NT> & p) { // differentiate
template <class NT>
Polynomial<NT> differentiate(const Polynomial<NT> & p, int n) {//multi-differentiate
Polynomial<NT> q(p);
assert(n >= 0);
CGAL_assertion(n >= 0);
for (int i=1; i<=n; i++)
q.differentiate();
return q;
@ -1491,7 +1491,7 @@ NT res(Polynomial<NT> p, Polynomial<NT> q) {
template <class NT>
NT psc(int i,Polynomial<NT> p, Polynomial<NT> q) {
assert(i >= 0);
CGAL_assertion(i >= 0);
if(i == 0)
return res(p,q);

View File

@ -59,6 +59,7 @@
#ifndef CORE_STURM_H
#define CORE_STURM_H
#include <CGAL/assertions.h>
#include "CGAL/CORE/BigFloat.h"
#include "CGAL/CORE/Expr.h"
#include "CGAL/CORE/poly/Poly.h"
@ -205,7 +206,7 @@ public:
// where sx = sign of evaluating seq[0] at x
// PRE-CONDITION: sx != 0 and len > 0
int signVariations(const BigFloat & x, int sx) const {
assert((sx != 0) && (len >0));
CGAL_assertion((sx != 0) && (len >0));
int cnt = 0;
int last_sign = sx;
for (int i=1; i<=len; i++) {// Chee (4/29/04): Bug fix,
@ -237,7 +238,7 @@ public:
if (len <= 0) return len;
int cnt = 0;
int last_sign = sign(seq[0].coeff[seq[0].getTrueDegree()]);
assert(last_sign != 0);
CGAL_assertion(last_sign != 0);
for (int i=1; i<=len; i++) {
int sgn = sign(seq[i].coeff[seq[i].getTrueDegree()]);
if (sgn*last_sign < 0)
@ -255,7 +256,7 @@ public:
int last_sign = sign(seq[0].coeff[seq[0].getTrueDegree()]);
if (seq[0].getTrueDegree() % 2 != 0)
last_sign *= -1;
assert(last_sign != 0);
CGAL_assertion(last_sign != 0);
for (int i=1; i<=len; i++) {
int parity = (seq[i].getTrueDegree() % 2 == 0) ? 1 : -1;
int sgn = parity * sign(seq[i].coeff[seq[i].getTrueDegree()]);
@ -275,7 +276,7 @@ public:
// "x.makeExact(); y.makeExact()" before calling].
///////////////////////////////////////////
int numberOfRoots(const BigFloat &x, const BigFloat &y) const {
assert(x <= y); // we allow x=y
CGAL_assertion(x <= y); // we allow x=y
if (len <= 0) return len; // return of -1 means infinity of roots!
int signx = sign(seq[0].evalExactSign(x));
if (x == y) return ((signx == 0) ? 1 : 0);
@ -354,7 +355,7 @@ public:
*/
void isolateRoots(const BigFloat &x, const BigFloat &y,
BFVecInterval &v) const {
assert(x<=y);
CGAL_assertion(x<=y);
int n = numberOfRoots(x,y);
if (n == 0) return;
@ -767,7 +768,7 @@ public:
// says that z is a robust approximate zero).
//
bool smaleBoundTest(const BigFloat& z){
assert(z.isExact()); // the bound only makes sense for exact z
CGAL_assertion(z.isExact()); // the bound only makes sense for exact z
#ifdef CORE_DEBUG
std::cout <<"Computing Smale's bound = " << std::endl;
@ -869,7 +870,7 @@ std::cout << "In newtonRefine, input J=" << J.first
return J;
}
assert( leftSign * rightSign < 0 );
CGAL_assertion( leftSign * rightSign < 0 );
//N is number of times Newton is called without checking
// whether the result is still in the interval or not
@ -1060,7 +1061,7 @@ std::cout << "In newtonRefine, input J=" << J.first
<< J.first.err() << " Err at end = " << J.second.err() << std::endl;
#endif
assert( (seq[0].evalExactSign(J.first) * seq[0].evalExactSign(J.second) <= 0) );
CGAL_assertion( (seq[0].evalExactSign(J.first) * seq[0].evalExactSign(J.second) <= 0) );
#ifdef CORE_DEBUG_NEWTON
if (seq[0].evalExactSign(J.first) * seq[0].evalExactSign(J.second) > 0)

View File

@ -37,6 +37,7 @@ typedef unsigned int uint;
#include <CGAL/tuple.h>
#include<CGAL/Exact_circular_kernel_2.h>
#include <CGAL/Cartesian_converter.h>
#include <CGAL/assertions.h>
#include <boost/utility.hpp>
@ -538,10 +539,10 @@ public:
++next_s; if (next_s==map_theta.end()) next_s=map_theta.begin();
do{
if (current->second.first==OTRG) return;
assert(current->second.first==SRC);
CGAL_assertion(current->second.first==SRC);
draw_in_ipe(Circular_arc_2(circle,*(current->second.second),*(next_s->second.second),CGAL::COUNTERCLOCKWISE));
if (next_s->second.first==OTRG) return;
assert(next_s->second.first==TRG);
CGAL_assertion(next_s->second.first==TRG);
++next_s; if (next_s==map_theta.end()) next_s=map_theta.begin();
current=next_s;
++next_s; if (next_s==map_theta.end()) next_s=map_theta.begin();
@ -843,7 +844,7 @@ public:
switch (ints.size()){
case 1:
ok=CGAL::assign(tmp_pt,ints[0]);
assert(ok);
CGAL_assertion(ok);
points.push_back(tmp_pt);
index=points.size()-1;
indices[i]=index;
@ -852,12 +853,12 @@ public:
case 2:
int right_ind=i<2?0:1;
ok=CGAL::assign(tmp_pt,ints[right_ind]);
assert(ok);
CGAL_assertion(ok);
points.push_back(tmp_pt);
index=points.size()-1;
indices[i]=index;
ok=CGAL::assign(tmp_pt,ints[(right_ind+1)%2]);
assert(ok);
CGAL_assertion(ok);
points.push_back(tmp_pt);
index=points.size()-1;
indices[(i+1)%4+4]=index;
@ -900,7 +901,7 @@ public:
*out++=build_arc(exact_circle,points[ indices[pair[1]] ].first,points[ indices[pair[0]] ].first);
return;
}
assert (rem_pt==0);
CGAL_assertion (rem_pt==0);
}
};

View File

@ -37,6 +37,8 @@ typedef unsigned int uint;
#include <CGAL/tuple.h>
#include<CGAL/Exact_circular_kernel_2.h>
#include <CGAL/Cartesian_converter.h>
#include <CGAL/assertions.h>
#include <CGAL/use.h>
#include <boost/utility.hpp>
@ -546,10 +548,10 @@ public:
++next_s; if (next_s==map_theta.end()) next_s=map_theta.begin();
do{
if (current->second.first==OTRG) return;
assert(current->second.first==SRC);
CGAL_assertion(current->second.first==SRC);
draw_in_ipe(Circular_arc_2(circle,*(current->second.second),*(next_s->second.second),CGAL::COUNTERCLOCKWISE));
if (next_s->second.first==OTRG) return;
assert(next_s->second.first==TRG);
CGAL_assertion(next_s->second.first==TRG);
++next_s; if (next_s==map_theta.end()) next_s=map_theta.begin();
current=next_s;
++next_s; if (next_s==map_theta.end()) next_s=map_theta.begin();
@ -848,7 +850,7 @@ public:
switch (ints.size()){
case 1:
ok=CGAL::assign(tmp_pt,ints[0]);
assert(ok);
CGAL_assertion(ok); CGAL_USE(ok);
points.push_back(tmp_pt);
index=points.size()-1;
indices[i]=index;
@ -857,12 +859,12 @@ public:
case 2:
int right_ind=i<2?0:1;
ok=CGAL::assign(tmp_pt,ints[right_ind]);
assert(ok);
CGAL_assertion(ok); CGAL_USE(ok);
points.push_back(tmp_pt);
index=points.size()-1;
indices[i]=index;
ok=CGAL::assign(tmp_pt,ints[(right_ind+1)%2]);
assert(ok);
CGAL_assertion(ok); CGAL_USE(ok);
points.push_back(tmp_pt);
index=points.size()-1;
indices[(i+1)%4+4]=index;
@ -905,7 +907,7 @@ public:
*out++=build_arc(exact_circle,points[ indices[pair[1]] ].first,points[ indices[pair[0]] ].first);
return;
}
assert (rem_pt==0);
CGAL_assertion (rem_pt==0);
}
};

View File

@ -22,7 +22,6 @@
#include <CGAL/Compact_container.h>
#include <CGAL/internal/Combinatorial_map_utility.h>
#include <CGAL/internal/Combinatorial_map_internal_functors.h>
#include <CGAL/internal/Combinatorial_map_group_functors.h>
#include <CGAL/internal/Combinatorial_map_copy_functors.h>
#include <CGAL/internal/Combinatorial_map_sewable.h>
@ -350,6 +349,18 @@ namespace CGAL {
bool is_empty() const
{ return mdarts.empty(); }
friend std::ostream& operator<< (std::ostream& os, const Self& amap)
{
save_combinatorial_map(amap, os);
return os;
}
friend std::ifstream& operator>> (std::ifstream& is, Self& amap)
{
load_combinatorial_map(is, amap);
return is;
}
/** Create a new dart and add it to the map.
* The marks of the darts are initialised with mmask_marks, i.e. the dart
* is unmarked for all the marks.

View File

@ -0,0 +1,800 @@
// Copyright (c) 2010-2011 CNRS and LIRIS' Establishments (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) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
// Guillaume Castano <guillaume.castano@gmail.com>
// Pascal Khieu <pascal.khieu@gmail.com>
//
#ifndef CGAL_COMBINATORIAL_MAP_SAVE_LOAD_H
#define CGAL_COMBINATORIAL_MAP_SAVE_LOAD_H
#include <boost/foreach.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/lexical_cast.hpp>
#include <CGAL/Combinatorial_map.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Cell_attribute_with_point.h>
#include <algorithm>
#include <map>
#include <vector>
#include <cstdlib>
#include <iostream>
#include <typeinfo>
namespace CGAL {
typedef Exact_predicates_inexact_constructions_kernel::Point_3 RPoint_3;
typedef Exact_predicates_exact_constructions_kernel::Point_3 EPoint_3;
// Tags used in xml tree:
// For darts:
// <darts>
// <d> // new dart
// <b i="1"> neighbor dart index for beta1 </b>
// ...
// <v> value of dart (optional) </v>
// </d>
// ...
// </darts>
// For attributes:
// <attributes>
// <dimension index="1"> // new type of non void attribute
// <type>type of the info associated</type>
// <a> // new attribute
// <d> dart index </d>
// <v> value of attribute </v>
// </a>
// ...
// </attributes>
// Here T is a Dart_const_handle so we don't need &
template<typename T>
void write_cmap_dart_node(boost::property_tree::ptree & /*node*/, T)
{}
template<typename T>
void write_cmap_attribute_node(boost::property_tree::ptree & /*node*/, const T&)
{}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
char val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
unsigned char val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
short int val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
unsigned short int val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
int val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
unsigned int val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
long int val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
unsigned long int val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
float val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
double val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
long double val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
bool val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
const std::string& val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
const RPoint_3& val)
{
node.add("p.x",val.x());
node.add("p.y",val.y());
node.add("p.z",val.z());
}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
const EPoint_3& val)
{
node.add("p.x",CGAL::to_double(val.x()));
node.add("p.y",CGAL::to_double(val.y()));
node.add("p.z",CGAL::to_double(val.z()));
}
template<typename CMap, unsigned int i,
bool WithInfo=CGAL::Is_attribute_has_non_void_info
<typename CMap::template Attribute_type<i>::type>::value,
bool WithPoint=CGAL::Is_attribute_has_point
<typename CMap::template Attribute_type<i>::type >::value >
struct My_functor_cmap_save_one_attrib;
// An attrib with point and with info
template<typename CMap, unsigned int i>
struct My_functor_cmap_save_one_attrib<CMap, i, true, true>
{
static void run(const CMap* amap, boost::property_tree::ptree* ptree,
std::map<typename CMap::Dart_const_handle, typename CMap::size_type>* myDarts)
{
// to check all i-cells of the map
typename CMap::template Attribute_range<i>::type::const_iterator
it_attrib, itend_attrib;
it_attrib=amap->template attributes<i>().begin();
itend_attrib=amap->template attributes<i>().end();
// add dimension & type
boost::property_tree::ptree & ndim = ptree->add("dimension", "");
ndim.put("<xmlattr>.index", i);
ndim.add("type", typeid(typename CMap::template Attribute_type<i>::type::Info).name());
ndim.add("type_point", typeid(RPoint_3).name());
// for every attribute of the dimension
for (; it_attrib!=itend_attrib; ++it_attrib)
{
// make composant, dart and property node
boost::property_tree::ptree & nattr = ndim.add("a", "");
/* boost::property_tree::ptree & ndarts = */
nattr.add("d", (*myDarts)[it_attrib->dart()]);
// update property node to add a value node (from basic or custom type
write_cmap_attribute_node(nattr, it_attrib->info());
write_cmap_attribute_node(nattr, it_attrib->point());
}
}
};
// An attribute with point and without info
template<typename CMap, unsigned int i>
struct My_functor_cmap_save_one_attrib<CMap, i, false, true>
{
static void run(const CMap* amap, boost::property_tree::ptree* ptree,
std::map<typename CMap::Dart_const_handle, typename CMap::size_type>* myDarts)
{
// to check all i-cells of the map
typename CMap::template Attribute_range<i>::type::const_iterator
it_attrib, itend_attrib;
it_attrib=amap->template attributes<i>().begin();
itend_attrib=amap->template attributes<i>().end();
// add dimension & type
boost::property_tree::ptree & ndim = ptree->add("dimension", "");
ndim.put("<xmlattr>.index", i);
ndim.add("type", "void");
ndim.add("type_point", typeid(RPoint_3).name());
// for every attribute of the dimension
for (; it_attrib!=itend_attrib; ++it_attrib)
{
// make composant, dart and property node
boost::property_tree::ptree & nattr = ndim.add("a", "");
/* boost::property_tree::ptree & ndarts = */
nattr.add("d", (*myDarts)[it_attrib->dart()]);
// update property node to add a value node (from basic or custom type
write_cmap_attribute_node(nattr, it_attrib->point());
}
}
};
// An attribute without point and with info
template<typename CMap, unsigned int i>
struct My_functor_cmap_save_one_attrib<CMap, i, true, false>
{
static void run(const CMap* amap, boost::property_tree::ptree* ptree,
std::map<typename CMap::Dart_const_handle, typename CMap::size_type>* myDarts)
{
// to check all i-cells of the map
typename CMap::template Attribute_range<i>::type::const_iterator
it_attrib, itend_attrib;
it_attrib=amap->template attributes<i>().begin();
itend_attrib=amap->template attributes<i>().end();
// add dimension & type
boost::property_tree::ptree & ndim = ptree->add("dimension", "");
ndim.put("<xmlattr>.index", i);
ndim.add("type", typeid(typename CMap::template Attribute_type<i>::type::Info).name());
ndim.add("type_point", "void");
// for every attribute of the dimension
for (; it_attrib!=itend_attrib; ++it_attrib)
{
// make composant, dart and property node
boost::property_tree::ptree & nattr = ndim.add("a", "");
/* boost::property_tree::ptree & ndarts = */
nattr.add("d", (*myDarts)[it_attrib->dart()]);
// update property node to add a value node (from basic or custom type
write_cmap_attribute_node(nattr, it_attrib->info());
}
}
};
// An attrib without point and without info
template<typename CMap, unsigned int i>
struct My_functor_cmap_save_one_attrib<CMap, i, false, false>
{
static void run(const CMap* amap, boost::property_tree::ptree* ptree,
std::map<typename CMap::Dart_const_handle, typename CMap::size_type>* myDarts)
{
// to check all i-cells of the map
typename CMap::template Attribute_range<i>::type::const_iterator
it_attrib, itend_attrib;
it_attrib=amap->template attributes<i>().begin();
itend_attrib=amap->template attributes<i>().end();
// add dimension & type
boost::property_tree::ptree & ndim = ptree->add("dimension", "");
ndim.put("<xmlattr>.index", i);
ndim.add("type", "void");
ndim.add("type_point", "void");
// for every attribute of the dimension
for (; it_attrib!=itend_attrib; ++it_attrib)
{
// make composant, dart and property node
boost::property_tree::ptree & nattr = ndim.add("a", "");
/* boost::property_tree::ptree & ndarts = */
nattr.add("d", (*myDarts)[it_attrib->dart()]);
}
}
};
template<typename CMap>
struct My_functor_cmap_save_attrib
{
template <unsigned int i>
static void run(const CMap* amap, boost::property_tree::ptree* ptree,
std::map<typename CMap::Dart_const_handle, typename CMap::size_type>* myDarts)
{
My_functor_cmap_save_one_attrib<CMap, i>::run(amap, ptree, myDarts);
}
};
template < class CMap >
boost::property_tree::ptree cmap_save_darts
(const CMap& amap, std::map<typename CMap::Dart_const_handle, typename CMap::size_type>& myDarts)
{
assert( myDarts.empty() );
// First we numbered each dart by using the std::map.
typename CMap::Dart_range::const_iterator it(amap.darts().begin());
for(typename CMap::size_type num=1; num<=amap.number_of_darts();
++num, ++it)
{
myDarts[it] = num;
}
// make a tree
using boost::property_tree::ptree;
ptree pt;
// Now we save each dart, and its neighbors.
it=amap.darts().begin();
for(typename CMap::size_type num=0; num<amap.number_of_darts(); ++num, ++it)
{
// make a dart node
ptree & ndart = pt.add("d", "");
// the beta, only for non free sews
for(unsigned int dim=1; dim<=amap.dimension; dim++)
{
if(!amap.is_free(it, dim))
{
ptree & currentNext = ndart.add("b", myDarts[amap.beta(it, dim)]);
currentNext.put("<xmlattr>.i", dim);
}
}
// update property node to add a value node (if user defined its own
// function)
write_cmap_dart_node(ndart, it);
}
return pt;
}
template < class CMap >
boost::property_tree::ptree cmap_save_attributes
(const CMap& amap, std::map<typename CMap::Dart_const_handle, typename CMap::size_type>& myDarts)
{
using boost::property_tree::ptree;
ptree pt;
// update pt adding nodes containing attributes informations
CMap::Helper::template Foreach_enabled_attributes
<My_functor_cmap_save_attrib<CMap> >::run(&amap, &pt, &myDarts);
return pt;
}
template < class CMap >
bool save_combinatorial_map(const CMap& amap, std::ostream & output)
{
using boost::property_tree::ptree;
ptree data;
// map dart => number
std::map<typename CMap::Dart_const_handle, typename CMap::size_type> myDarts;
// Get darts
ptree pt_darts;
pt_darts = cmap_save_darts(amap, myDarts);
data.add_child("data.darts",pt_darts);
// Get attributes
ptree pt_attr;
pt_attr = cmap_save_attributes(amap, myDarts);
data.add_child("data.attributes", pt_attr);
// save data in output
write_xml(output, data);
return true;
}
template < class CMap >
bool save_combinatorial_map(const CMap& amap, const char* filename)
{
std::ofstream output(filename);
if (!output) return false;
return save_combinatorial_map(amap, output);
}
// Here T is a Dart_handle so no need of &
template<typename T>
void read_cmap_dart_node
(const boost::property_tree::ptree::value_type &/*v*/, T /*val*/)
{}
template<typename T>
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &/*v*/, T &/*val*/)
{}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,char &val)
{val=boost::lexical_cast< char >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,unsigned char &val)
{val=boost::lexical_cast< unsigned char >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,short int &val)
{val=boost::lexical_cast< short int >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,unsigned short int &val)
{val=boost::lexical_cast< unsigned short int >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,int &val)
{val=boost::lexical_cast< int >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,unsigned int &val)
{val=boost::lexical_cast< unsigned int >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,long int &val)
{val=boost::lexical_cast< long int >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,unsigned long int &val)
{val=boost::lexical_cast< unsigned long int >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,float &val)
{val=boost::lexical_cast< float >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,double &val)
{val=boost::lexical_cast< double >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,long double &val)
{val=boost::lexical_cast< long double >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,bool &val)
{val=boost::lexical_cast< bool >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,std::string &val)
{val=boost::lexical_cast< std::string >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,RPoint_3 &val)
{
double x=v.second.get<double>("x");
double y=v.second.get<double>("y");
double z=v.second.get<double>("z");
val = RPoint_3(x,y,z);
}
template<typename CMap, unsigned int i,
bool WithInfo=CGAL::Is_attribute_has_non_void_info
<typename CMap::template Attribute_type<i>::type>::value,
bool WithPoint=CGAL::Is_attribute_has_point
<typename CMap::template Attribute_type<i>::type >::value >
struct My_functor_cmap_load_one_attrib;
// An attrib with point and with info
template<typename CMap, unsigned int i>
struct My_functor_cmap_load_one_attrib<CMap, i, true, true>
{
static void run(const boost::property_tree::ptree& pt, CMap* amap,
const std::vector<typename CMap::Dart_handle>& myDarts)
{
BOOST_FOREACH( const boost::property_tree::ptree::value_type &v0,
pt.get_child("data.attributes") )
{
// <dimension>
if (v0.first == "dimension")
{
int dimension=v0.second.get("<xmlattr>.index", -1);
// if map.dimension == dimension saved in the xml file
if (dimension==i)
{
unsigned int id_dart_cellule=0;
std::string type = v0.second.get<std::string>("type");
std::string type_map=std::string
(typeid(typename CMap::template Attribute_type<i>::type::Info).name());
std::string ptype = v0.second.get<std::string>("type_point");
std::string ptype_map= std::string
(typeid(typename CMap::template Attribute_type<i>::type::Point).name());
// std::cout<<"ptype="<<ptype<<" and type_map="<<type_map<<std::endl;
/* if(type!=type_map && ptype!=ptype_map)
{
// std::cout<<"Not loaded."<<std::endl;
return;
}*/
BOOST_FOREACH(const boost::property_tree::ptree::value_type &v1,
v0.second )
{
if( v1.first == "a" )
{
id_dart_cellule=v1.second.get<unsigned int>("d")-1;
BOOST_FOREACH(const boost::property_tree::ptree::value_type &v2,
v1.second )
{
if( type==type_map && v2.first == "v" )
{
if (myDarts[id_dart_cellule]->
template attribute<i>()==NULL )
amap->template set_attribute<i>
(myDarts[id_dart_cellule],
amap->template create_attribute<i>());
read_cmap_attribute_node
(v2,
myDarts[id_dart_cellule]->
template attribute<i>()->info());
}
if( ptype==ptype_map && v2.first == "p" )
{
if (myDarts[id_dart_cellule]->
template attribute<i>()==NULL )
amap->template set_attribute<i>
(myDarts[id_dart_cellule],
amap->template create_attribute<i>());
read_cmap_attribute_node
(v2,
myDarts[id_dart_cellule]->
template attribute<i>()->point());
}
}
}
}
}
}
}
}
};
// An attribute with point and without info
template<typename CMap, unsigned int i>
struct My_functor_cmap_load_one_attrib<CMap, i, false, true>
{
static void run(const boost::property_tree::ptree& pt, CMap* amap,
const std::vector<typename CMap::Dart_handle>& myDarts)
{
BOOST_FOREACH( const boost::property_tree::ptree::value_type &v0,
pt.get_child("data.attributes") )
{
// <dimension>
if (v0.first == "dimension")
{
int dimension=v0.second.get("<xmlattr>.index", -1);
// if map.dimension == dimension saved in the xml file
if (dimension==i)
{
unsigned int id_dart_cellule=0;
std::string ptype = v0.second.get<std::string>("type_point");
std::string type_map= typeid
(typename CMap::template Attribute_type<i>::type::Point).name();
// std::cout<<"ptype="<<ptype<<" and type_map="<<type_map<<std::endl;
/* if(ptype!=type_map)
{
// std::cout<<"Not loaded."<<std::endl;
return;
}*/
BOOST_FOREACH(const boost::property_tree::ptree::value_type &v1,
v0.second )
{
if( v1.first == "a" )
{
id_dart_cellule=v1.second.get<unsigned int>("d")-1;
BOOST_FOREACH(const boost::property_tree::ptree::value_type &v2,
v1.second )
{
if( v2.first == "p" )
{
if (myDarts[id_dart_cellule]->
template attribute<i>()==NULL )
amap->template set_attribute<i>
(myDarts[id_dart_cellule],
amap->template create_attribute<i>());
read_cmap_attribute_node
(v2,
myDarts[id_dart_cellule]->
template attribute<i>()->point());
}
}
}
}
}
}
}
}
};
// An attribute without point and with info
template<typename CMap, unsigned int i>
struct My_functor_cmap_load_one_attrib<CMap, i, true, false>
{
static void run(const boost::property_tree::ptree& pt, CMap* amap,
const std::vector<typename CMap::Dart_handle>& myDarts)
{
BOOST_FOREACH( const boost::property_tree::ptree::value_type &v0,
pt.get_child("data.attributes") )
{
// <dimension>
if (v0.first == "dimension")
{
int dimension=v0.second.get("<xmlattr>.index", -1);
// if map.dimension == dimension saved in the xml file
if (dimension==i)
{
unsigned int id_dart_cellule=0;
std::string ptype = v0.second.get<std::string>("type");
std::string type_map= typeid
(typename CMap::template Attribute_type<i>::type::Info).name();
// std::cout<<"ptype="<<ptype<<" and type_map="<<type_map<<std::endl;
/* if(ptype!=type_map)
{
// std::cout<<"Not loaded."<<std::endl;
return;
} */
BOOST_FOREACH(const boost::property_tree::ptree::value_type &v1,
v0.second )
{
if( v1.first == "a" )
{
id_dart_cellule=v1.second.get<unsigned int>("d")-1;
BOOST_FOREACH(const boost::property_tree::ptree::value_type &v2,
v1.second )
{
if( v2.first == "v" )
{
if (myDarts[id_dart_cellule]->
template attribute<i>()==NULL )
amap->template set_attribute<i>
(myDarts[id_dart_cellule],
amap->template create_attribute<i>());
read_cmap_attribute_node
(v2,
myDarts[id_dart_cellule]->
template attribute<i>()->info());
}
}
}
}
}
}
}
}
};
// An attribute without point and without info
template<typename CMap, unsigned int i>
struct My_functor_cmap_load_one_attrib<CMap, i, false, false>
{
static void run(const boost::property_tree::ptree& pt, CMap* amap,
const std::vector<typename CMap::Dart_handle>& myDarts)
{
BOOST_FOREACH( const boost::property_tree::ptree::value_type &v0,
pt.get_child("data.attributes") )
{
// <dimension>
if (v0.first == "dimension")
{
int dimension=v0.second.get("<xmlattr>.index", -1);
// if map.dimension == dimension saved in the xml file
if (dimension==i)
{
unsigned int id_dart_cellule=0;
BOOST_FOREACH(const boost::property_tree::ptree::value_type &v1,
v0.second )
{
if( v1.first == "a" )
{
id_dart_cellule=v1.second.get<unsigned int>("d")-1;
if (myDarts[id_dart_cellule]->
template attribute<i>()==NULL )
amap->template set_attribute<i>
(myDarts[id_dart_cellule],
amap->template create_attribute<i>());
}
}
}
}
}
}
};
/** Functor called to load i-attributes.
* @param pt a boost::property_tree::ptree load from an xml file
* @param amap a pointer to the map to load into
* @param myDarts an array of Dart_handle st myDarts[i] is the ith dart.
*/
template<class CMap>
struct My_functor_cmap_load_attrib
{
template <unsigned int i>
static void run(const boost::property_tree::ptree& pt, CMap* amap,
const std::vector<typename CMap::Dart_handle>& myDarts)
{
My_functor_cmap_load_one_attrib<CMap, i>::run(pt, amap, myDarts);
}
};
template < class CMap >
bool cmap_load_darts(boost::property_tree::ptree &pt, CMap& amap,
std::vector<typename CMap::Dart_handle>& myDarts)
{
// use a boost::property_tree
using boost::property_tree::ptree;
// make darts
BOOST_FOREACH( const ptree::value_type &v, pt.get_child("data.darts") )
{
if( v.first == "d" )
myDarts.push_back(amap.create_dart());
}
// update beta links
unsigned int index;
unsigned int currentDartInt = 0;
unsigned int nextDartInt;
BOOST_FOREACH( const ptree::value_type &v, pt.get_child("data.darts") )
{
if( v.first == "d" )
{
BOOST_FOREACH( const ptree::value_type &v2, v.second )
{
if (v2.first == "b")
{
index = v2.second.get("<xmlattr>.i", 0);
nextDartInt = boost::lexical_cast< int >(v2.second.data())-1;
if ( index<=amap.dimension )
{
// A->B
amap.basic_link_beta(myDarts[currentDartInt],
myDarts[nextDartInt],
index);
//B->A
amap.basic_link_beta(myDarts[nextDartInt],
myDarts[currentDartInt],
CGAL_BETAINV(index));
}
}
else if (v2.first=="v")
read_cmap_dart_node(v2,myDarts[currentDartInt]);
}
}
++currentDartInt;
}
return true;
}
template < class CMap >
void cmap_load_attributes(const boost::property_tree::ptree& pt, CMap& amap,
const std::vector<typename CMap::Dart_handle>& myDarts)
{
CMap::Helper::template Foreach_enabled_attributes
<My_functor_cmap_load_attrib<CMap> >::run(pt,&amap,myDarts);
}
template < class CMap >
bool load_combinatorial_map(std::ifstream & input, CMap& amap)
{
using boost::property_tree::ptree;
ptree pt;
read_xml(input, pt);
std::vector<typename CMap::Dart_handle> myDarts;
cmap_load_darts(pt,amap,myDarts);
cmap_load_attributes(pt,amap,myDarts);
return true;
}
template < class CMap >
bool load_combinatorial_map(const char* filename, CMap& amap)
{
std::ifstream input(filename);
if (!input) return false;
return load_combinatorial_map(input, amap);
}
} // namespace CGAL
#endif // CGAL_COMBINATORIAL_MAP_SAVE_LOAD_H //
// EOF //

View File

@ -55,14 +55,10 @@ bool test2D()
dh = map.create_dart ();
dh2 = map.create_dart();
if (!map.is_dart_used(dh) ) return false;
if ( map.is_valid() ) cout << "Map valid." << endl;
cout << "Nombre de brins : " << map.number_of_darts() << endl;
map.clear();
if ( map.is_dart_used(dh) ) return false;
cout << "***************************** TEST BASIC CREATION 2D DONE."
<< endl;

View File

@ -26,6 +26,7 @@
#include <CGAL/Polyhedron_incremental_builder_3.h>
#include <CGAL/Origin.h>
#include <CGAL/convex_hull_3.h>
#include <CGAL/assertions.h>
// For interior_polyhedron_3
#include <CGAL/Convex_hull_3/dual/interior_polyhedron_3.h>
@ -87,7 +88,7 @@ namespace CGAL
for (Vertex_const_iterator it = _primal.vertices_begin();
it != _primal.vertices_end(); ++it)
{
assert (it->is_bivalent() == false);
CGAL_assertion (it->is_bivalent() == false);
typename Polyhedron::Halfedge_around_vertex_const_circulator
h0 = it->vertex_begin(), hf = h0;

View File

@ -28,6 +28,7 @@
#include <CGAL/QP_models.h>
#include <limits>
#include <CGAL/number_utils.h>
#include <CGAL/assertions.h>
// Description taken from http://www.qhull.org/html/qhalf.htm
@ -109,10 +110,10 @@ class Interior_polyhedron_3 {
const double cj = CGAL::to_double(plane.c());
const double dj = CGAL::to_double(plane.d());
assert(!isinf(aj));
assert(!isinf(bj));
assert(!isinf(cj));
assert(!isinf(dj));
CGAL_assertion(!isinf(aj));
CGAL_assertion(!isinf(bj));
CGAL_assertion(!isinf(cj));
CGAL_assertion(!isinf(dj));
// plane defined the halfspace: aj * x1 + bj * x2 + cj * x3 + dj <= 0
// <=> - (aj * x1 + bj * x2 + cj * x3 + dj) >= 0

View File

@ -552,7 +552,7 @@ ch_quickhull_3_scan(TDS_2& tds,
border.erase(it);
while(! border.empty()){
it = border.find(e.first->vertex(TDS_2::ccw(e.second)));
assert(it != border.end());
CGAL_ch_assertion(it != border.end());
e = it->second;
e.first->info() = 0;
edges.push_back(e);

View File

@ -35,7 +35,6 @@ function(configure_doxygen_package CGAL_PACKAGE_NAME)
file(APPEND ${CGAL_DOC_PACKAGE_DEFAULTS} "GENERATE_BUGLIST = NO\n")
endif()
file(APPEND ${CGAL_DOC_PACKAGE_DEFAULTS} "IMAGE_PATH = ${CGAL_PACKAGE_DIR}/doc/${CGAL_PACKAGE_NAME}/fig\n")
file(APPEND ${CGAL_DOC_PACKAGE_DEFAULTS} "EXAMPLE_PATH = ${CGAL_PACKAGE_DIR}/examples\n")
file(APPEND ${CGAL_DOC_PACKAGE_DEFAULTS} "GENERATE_TAGFILE = ${CGAL_DOC_TAG_GEN_DIR}/${CGAL_PACKAGE_NAME}.tag\n")
file(APPEND ${CGAL_DOC_PACKAGE_DEFAULTS} "STRIP_FROM_PATH = ${CGAL_PACKAGE_DIR}/doc/${CGAL_PACKAGE_NAME}/\n")
@ -44,19 +43,45 @@ function(configure_doxygen_package CGAL_PACKAGE_NAME)
file(APPEND ${CGAL_DOC_PACKAGE_DEFAULTS} "STRIP_FROM_INC_PATH += ${CGAL_PACKAGE_DIR}/include/\n")
file(APPEND ${CGAL_DOC_PACKAGE_DEFAULTS} "ALIASES += \"cgalPkgDescriptionBegin{2}=\\details \"\n")
file(APPEND ${CGAL_DOC_PACKAGE_DEFAULTS} "ALIASES += \"cgalPkgManuals{2}=<BR>\"\n")
# figure out the dependencies
if(EXISTS ${CGAL_PACKAGE_DIR}/doc/${CGAL_PACKAGE_NAME}/dependencies)
file(STRINGS ${CGAL_PACKAGE_DIR}/doc/${CGAL_PACKAGE_NAME}/dependencies DEPENDENCIES)
# IMAGE_PATH is set by default. For Documentation, we generate the extra path using packages.txt
set(IMAGE_PATH_VALUES "IMAGE_PATH = ${CGAL_PACKAGE_DIR}/doc/${CGAL_PACKAGE_NAME}/fig")
set(DEPENDENCIES "")
# figure out the dependencies, using the file `dependencies` or `packages.txt` for Documentation
if (${CGAL_PACKAGE_NAME} STREQUAL "Documentation")
set(PackageFile ${CGAL_PACKAGE_DIR}/doc/${CGAL_PACKAGE_NAME}/packages.txt)
file(READ ${PackageFile} Entries)
string(REPLACE "\n" ";" EntriesAsList ${Entries})
foreach(Line ${EntriesAsList})
if("${Line}" MATCHES "^\\\\package_listing{.+}$")
string(REGEX REPLACE "^\\\\package_listing{(.*/)?(.+)}$" "\\2" PKG "${Line}")
list(APPEND DEPENDENCIES ${PKG})
# update IMAGE_PATH
SET(PKG_DIR "${PKG}")
if("${Line}" MATCHES "^\\\\package_listing{.+/.+}$")
string(REGEX REPLACE "^\\\\package_listing{(.+)/.+}$" "\\1" PKG_DIR "${Line}")
endif()
SET(IMG_DIR "${CMAKE_SOURCE_DIR}/${PKG_DIR}/doc/${PKG}/fig")
if(EXISTS ${IMG_DIR})
string(CONCAT IMAGE_PATH_VALUES "${IMAGE_PATH_VALUES}" " \\\n ${IMG_DIR}" )
endif()
endif()
endforeach()
set(DOCUMENTATION_DEPENDENCIES ${DEPENDENCIES} PARENT_SCOPE)
else()
set(DEPENDENCIES "")
if(EXISTS ${CGAL_PACKAGE_DIR}/doc/${CGAL_PACKAGE_NAME}/dependencies)
file(STRINGS ${CGAL_PACKAGE_DIR}/doc/${CGAL_PACKAGE_NAME}/dependencies DEPENDENCIES)
endif()
endif()
foreach(depend ${DEPENDENCIES})
file(APPEND ${CGAL_DOC_PACKAGE_DEFAULTS}
"TAGFILES += ${CGAL_DOC_TAG_DIR}/${depend}.tag=../${depend}\n")
endforeach()
#now write IMAGE_PATH
file(APPEND ${CGAL_DOC_PACKAGE_DEFAULTS} "${IMAGE_PATH_VALUES}\n")
configure_file(${CGAL_PACKAGE_DIR}/doc/${CGAL_PACKAGE_NAME}/Doxyfile.in
${CGAL_DOC_DXY_DIR}/${CGAL_PACKAGE_NAME}.dxy)
@ -197,8 +222,7 @@ if(DOXYGEN_FOUND)
set_target_properties(Documentation_doc PROPERTIES FOLDER Documentation)
# hard-code that doc depends on all packages
file(STRINGS ${CMAKE_SOURCE_DIR}/Documentation/doc/Documentation/dependencies DEPENDENCIES)
foreach(depend ${DEPENDENCIES})
foreach(depend ${DOCUMENTATION_DEPENDENCIES})
add_dependencies(doc_pre ${depend}_internal_doxygen_run)
add_dependencies(doc_post ${depend}_copy_doc_tags)
add_dependencies(${depend}_copy_doc_tags doc_pre)

View File

@ -30,99 +30,3 @@ SEARCHENGINE = true
ALIASES += "cgalPkgDescriptionBegin{2}=\subsection \2 \1"
ALIASES += "cgalPkgManuals{2}=<div class=\"PkgManuals\"> <span> \ref \1 \"User Manual\" </span> <span style=\"padding-left: 20px;\">\ref \2 \"Reference Manual\" </span> </div>"
ALIASES += "cgalReleaseNumber=${CGAL_CREATED_VERSION_NUM}"
# all image paths, maybe auto-generate this?
IMAGE_PATH = ${CMAKE_SOURCE_DIR}/Documentation/doc/Documentation/fig \
${CMAKE_SOURCE_DIR}/Advancing_front_surface_reconstruction/doc/Advancing_front_surface_reconstruction/fig \
${CMAKE_SOURCE_DIR}/Algebraic_foundations/doc/Algebraic_foundations/fig \
${CMAKE_SOURCE_DIR}/AABB_tree/doc/AABB_tree/fig \
${CMAKE_SOURCE_DIR}/Polygon/doc/Polygon/fig \
${CMAKE_SOURCE_DIR}/Polygon_mesh_processing/doc/Polygon_mesh_processing/fig \
${CMAKE_SOURCE_DIR}/Polyline_simplification_2/doc/Polyline_simplification_2/fig \
${CMAKE_SOURCE_DIR}/Number_types/doc/Number_types/fig \
${CMAKE_SOURCE_DIR}/Alpha_shapes_2/doc/Alpha_shapes_2/fig \
${CMAKE_SOURCE_DIR}/Alpha_shapes_3/doc/Alpha_shapes_3/fig \
${CMAKE_SOURCE_DIR}/Apollonius_graph_2/doc/Apollonius_graph_2/fig \
${CMAKE_SOURCE_DIR}/Bounding_volumes/doc/Bounding_volumes/fig \
${CMAKE_SOURCE_DIR}/Inscribed_areas/doc/Inscribed_areas/fig \
${CMAKE_SOURCE_DIR}/Matrix_search/doc/Matrix_search/fig \
${CMAKE_SOURCE_DIR}/Box_intersection_d/doc/Box_intersection_d/fig \
${CMAKE_SOURCE_DIR}/CGAL_ipelets/doc/CGAL_ipelets/fig \
${CMAKE_SOURCE_DIR}/Circulator/doc/Circulator/fig \
${CMAKE_SOURCE_DIR}/Convex_decomposition_3/doc/Convex_decomposition_3/fig \
${CMAKE_SOURCE_DIR}/Convex_hull_2/doc/Convex_hull_2/fig \
${CMAKE_SOURCE_DIR}/Convex_hull_3/doc/Convex_hull_3/fig \
${CMAKE_SOURCE_DIR}/Convex_hull_d/doc/Convex_hull_d/fig \
${CMAKE_SOURCE_DIR}/Envelope_2/doc/Envelope_2/fig \
${CMAKE_SOURCE_DIR}/Envelope_3/doc/Envelope_3/fig \
${CMAKE_SOURCE_DIR}/Generator/doc/Generator/fig \
${CMAKE_SOURCE_DIR}/Geomview/doc/Geomview/fig \
${CMAKE_SOURCE_DIR}/GraphicsView/doc/GraphicsView/fig \
${CMAKE_SOURCE_DIR}/HalfedgeDS/doc/HalfedgeDS/fig \
${CMAKE_SOURCE_DIR}/BGL/doc/BGL/fig \
${CMAKE_SOURCE_DIR}/Combinatorial_map/doc/Combinatorial_map/fig \
${CMAKE_SOURCE_DIR}/Linear_cell_complex/doc/Linear_cell_complex/fig \
${CMAKE_SOURCE_DIR}/Interval_skip_list/doc/Interval_skip_list/fig \
${CMAKE_SOURCE_DIR}/Nef_2/doc/Nef_2/fig \
${CMAKE_SOURCE_DIR}/Nef_S2/doc/Nef_S2/fig \
${CMAKE_SOURCE_DIR}/Nef_3/doc/Nef_3/fig \
${CMAKE_SOURCE_DIR}/QP_solver/doc/QP_solver/fig \
${CMAKE_SOURCE_DIR}/Mesh_2/doc/Mesh_2/fig \
${CMAKE_SOURCE_DIR}/Surface_mesher/doc/Surface_mesher/fig \
${CMAKE_SOURCE_DIR}/Mesh_3/doc/Mesh_3/fig \
${CMAKE_SOURCE_DIR}/Jet_fitting_3/doc/Jet_fitting_3/fig \
${CMAKE_SOURCE_DIR}/Minkowski_sum_2/doc/Minkowski_sum_2/fig \
${CMAKE_SOURCE_DIR}/Minkowski_sum_3/doc/Minkowski_sum_3/fig \
${CMAKE_SOURCE_DIR}/Miscellany/doc/Miscellany/fig \
${CMAKE_SOURCE_DIR}/Modular_arithmetic/doc/Modular_arithmetic/fig \
${CMAKE_SOURCE_DIR}/Partition_2/doc/Partition_2/fig \
${CMAKE_SOURCE_DIR}/Interpolation/doc/Interpolation/fig \
${CMAKE_SOURCE_DIR}/Kernel_23/doc/Kernel_23/fig \
${CMAKE_SOURCE_DIR}/Circular_kernel_2/doc/Circular_kernel_2/fig \
${CMAKE_SOURCE_DIR}/Circular_kernel_3/doc/Circular_kernel_3/fig \
${CMAKE_SOURCE_DIR}/Algebraic_kernel_d/doc/Algebraic_kernel_d/fig \
${CMAKE_SOURCE_DIR}/Kernel_d/doc/Kernel_d/fig \
${CMAKE_SOURCE_DIR}/Point_set_2/doc/Point_set_2/fig \
${CMAKE_SOURCE_DIR}/SearchStructures/doc/SearchStructures/fig \
${CMAKE_SOURCE_DIR}/Polytope_distance_d/doc/Polytope_distance_d/fig \
${CMAKE_SOURCE_DIR}/Polyhedron/doc/Polyhedron/fig \
${CMAKE_SOURCE_DIR}/Polynomial/doc/Polynomial/fig \
${CMAKE_SOURCE_DIR}/Principal_component_analysis/doc/Principal_component_analysis/fig \
${CMAKE_SOURCE_DIR}/STL_Extension/doc/STL_Extension/fig \
${CMAKE_SOURCE_DIR}/Skin_surface_3/doc/Skin_surface_3/fig \
${CMAKE_SOURCE_DIR}/Snap_rounding_2/doc/Snap_rounding_2/fig \
${CMAKE_SOURCE_DIR}/Arrangement_on_surface_2/doc/Sweep_line_2/fig \
${CMAKE_SOURCE_DIR}/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/fig \
${CMAKE_SOURCE_DIR}/Boolean_set_operations_2/doc/Boolean_set_operations_2/fig \
${CMAKE_SOURCE_DIR}/Triangulation_2/doc/TDS_2/fig \
${CMAKE_SOURCE_DIR}/Triangulation_2/doc/Triangulation_2/fig \
${CMAKE_SOURCE_DIR}/Triangulation_3/doc/TDS_3/fig \
${CMAKE_SOURCE_DIR}/Triangulation_3/doc/Triangulation_3/fig \
${CMAKE_SOURCE_DIR}/Triangulation/doc/Triangulation/fig \
${CMAKE_SOURCE_DIR}/Ridges_3/doc/Ridges_3/fig \
${CMAKE_SOURCE_DIR}/Point_set_processing_3/doc/Point_set_processing_3/fig \
${CMAKE_SOURCE_DIR}/Point_set_processing_3/doc/Property_map/fig \
${CMAKE_SOURCE_DIR}/Point_set_shape_detection_3/doc/Point_set_shape_detection_3/fig \
${CMAKE_SOURCE_DIR}/Kinetic_data_structures/doc/Kinetic_framework/fig \
${CMAKE_SOURCE_DIR}/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig \
${CMAKE_SOURCE_DIR}/Periodic_3_triangulation_3/doc/Periodic_3_triangulation_3/fig \
${CMAKE_SOURCE_DIR}/Scale_space_reconstruction_3/doc/Scale_space_reconstruction_3/fig \
${CMAKE_SOURCE_DIR}/Spatial_searching/doc/Spatial_searching/fig \
${CMAKE_SOURCE_DIR}/Spatial_sorting/doc/Spatial_sorting/fig \
${CMAKE_SOURCE_DIR}/Segment_Delaunay_graph_2/doc/Segment_Delaunay_graph_2/fig \
${CMAKE_SOURCE_DIR}/Segment_Delaunay_graph_Linf_2/doc/Segment_Delaunay_graph_Linf_2/fig \
${CMAKE_SOURCE_DIR}/Straight_skeleton_2/doc/Straight_skeleton_2/fig \
${CMAKE_SOURCE_DIR}/Visibility_2/doc/Visibility_2/fig \
${CMAKE_SOURCE_DIR}/Voronoi_diagram_2/doc/Voronoi_diagram_2/fig \
${CMAKE_SOURCE_DIR}/Surface_mesh_simplification/doc/Surface_mesh_simplification/fig \
${CMAKE_SOURCE_DIR}/Surface_mesh_skeletonization/doc/Surface_mesh_skeletonization/fig \
${CMAKE_SOURCE_DIR}/Surface_mesh_segmentation/doc/Surface_mesh_segmentation/fig \
${CMAKE_SOURCE_DIR}/Subdivision_method_3/doc/Subdivision_method_3/fig \
${CMAKE_SOURCE_DIR}/Surface_mesh_parameterization/doc/Surface_mesh_parameterization/fig \
${CMAKE_SOURCE_DIR}/Surface_mesh/doc/Surface_mesh/fig \
${CMAKE_SOURCE_DIR}/Surface_reconstruction_points_3/doc/Surface_reconstruction_points_3/fig \
${CMAKE_SOURCE_DIR}/Stream_lines_2/doc/Stream_lines_2/fig \
${CMAKE_SOURCE_DIR}/Stream_support/doc/Stream_support/fig \
${CMAKE_SOURCE_DIR}/Surface_modeling/doc/Surface_modeling/fig \
${CMAKE_SOURCE_DIR}/Barycentric_coordinates_2/doc/Barycentric_coordinates_2/fig \
${CMAKE_SOURCE_DIR}/Surface_mesh_shortest_path/doc/Surface_mesh_shortest_path/fig \

View File

@ -159,7 +159,7 @@ In order to build the \cgal libraries, you need a \cpp compiler.
|\sc{Gnu} `g++` 4.1 or later\cgalFootnote{<A HREF="http://gcc.gnu.org/">`http://gcc.gnu.org/`</A>} | Linux / MacOS X |
| | \sc{MS} Windows 95/98/2000/XP/NT4 |
| \sc{Intel} `C++` 15.0\cgalFootnote{<A HREF="http://software.intel.com/en-us/intel-compilers/">`http://software.intel.com/en-us/intel-compilers/`</A>} | Linux |
|\sc{MS} Visual `C++` 10.0, 11.0, 12.0 (\sc{Visual Studio} 2010, 2012, and 2013)\cgalFootnote{<A HREF="http://msdn.microsoft.com/en-us/vstudio/">`http://msdn.microsoft.com/en-us/vstudio/`</A>} | \sc{MS} Windows 95/98/2000/XP/NT4/Vista/7/8 |
|\sc{MS} Visual `C++` 10.0, 11.0, 12.0, 14.0 (\sc{Visual Studio} 2010, 2012, 2013, and 2015)\cgalFootnote{<A HREF="http://msdn.microsoft.com/en-us/vstudio/">`http://msdn.microsoft.com/en-us/vstudio/`</A>} | \sc{MS} Windows 95/98/2000/XP/NT4/Vista/7/8 |
| `Clang` \cgalFootnote{<A HREF="http://clang.llvm.org/">`http://clang.llvm.org/`</A>} compiler version 3.5 and 3.6.2 | Linux / MacOS X |
| Apple `Clang` compiler version 6.0 and 4.2 | MacOS X |

View File

@ -1,97 +0,0 @@
Algebraic_foundations
Advancing_front_surface_reconstruction
AABB_tree
Polygon
Number_types
Alpha_shapes_2
Alpha_shapes_3
Apollonius_graph_2
Bounding_volumes
Inscribed_areas
Matrix_search
Box_intersection_d
CGAL_ipelets
Circulator
Convex_decomposition_3
Convex_hull_2
Convex_hull_3
Convex_hull_d
Envelope_2
Envelope_3
Generator
Geomview
GraphicsView
HalfedgeDS
BGL
Combinatorial_map
Linear_cell_complex
Interval_skip_list
Nef_2
Nef_S2
Nef_3
QP_solver
Mesh_2
Surface_mesher
Mesh_3
Jet_fitting_3
Minkowski_sum_2
Minkowski_sum_3
Miscellany
Modular_arithmetic
Partition_2
Interpolation
Kernel_23
Circular_kernel_2
Circular_kernel_3
Algebraic_kernel_d
Kernel_d
Point_set_2
SearchStructures
Surface_mesh_skeletonization
Polytope_distance_d
Polyhedron
Polynomial
Principal_component_analysis
STL_Extension
Skin_surface_3
Snap_rounding_2
Sweep_line_2
Arrangement_on_surface_2
Boolean_set_operations_2
TDS_2
Triangulation_2
TDS_3
Triangulation_3
Triangulation
Ridges_3
Point_set_processing_3
Point_set_shape_detection_3
Polyline_simplification_2
Property_map
Kinetic_framework
Kinetic_data_structures
Periodic_2_triangulation_2
Periodic_3_triangulation_3
Scale_space_reconstruction_3
Spatial_searching
Spatial_sorting
Segment_Delaunay_graph_2
Segment_Delaunay_graph_Linf_2
Straight_skeleton_2
Visibility_2
Voronoi_diagram_2
Surface_mesh_simplification
Subdivision_method_3
Surface_mesh_parameterization
Surface_reconstruction_points_3
Surface_mesh_segmentation
Stream_lines_2
Stream_support
Surface_modeling
Barycentric_coordinates_2
Surface_mesh
Surface_mesh_shortest_path
Polygon_mesh_processing

View File

@ -43,7 +43,7 @@ Manuals for the Previous Releases
For releases >= 4.2, visit [http://doc.cgal.org/X.Y](http://doc.cgal.org/4.2)
For releases X.Y, with 3.1 <= X.Y <= 4.1 visit
[http://www.cgal.org/Manual/X.Y/doc_html/cgal_manual/contents.html](http://www.cgal.org/Manual/3.1/doc_html/cgal_manual/contents.html)
[http://doc.cgal.org/Manual/X.Y/doc_html/cgal_manual/packages.html](http://doc.cgal.org/Manual/3.1/doc_html/cgal_manual/packages.html)

View File

@ -47,6 +47,7 @@ h1 {
\package_listing{Straight_skeleton_2}
\package_listing{Minkowski_sum_2}
\package_listing{Polyline_simplification_2}
\package_listing{Visibility_2}
\section PartPolyhedra Cell Complexes and Polyhedra
@ -68,7 +69,6 @@ h1 {
\package_listing{Snap_rounding_2}
\package_listing{Envelope_2}
\package_listing{Envelope_3}
\package_listing{Visibility_2}
\section PartTriangulationsAndDelaunayTriangulations Triangulations and Delaunay Triangulations

View File

@ -18,7 +18,7 @@
\cgalPkgSummaryEnd
\cgalPkgShortInfoBegin
\cgalPkgSince{3.4}
\cgalPkgDependsOn{\ref thirdpartyQt}
\cgalPkgDependsOn{\sc{Qt} 5}
\cgalPkgBib{cgal:fr-cqgvf}
\cgalPkgLicense{\ref licensesGPL "GPL"}
\cgalPkgShortInfoEnd

View File

@ -1,7 +1,7 @@
-------------------------------- Release 4.7 --------------------------------
Release date: September 2015
Release date: October 2015
* Installation
@ -20,13 +20,10 @@ Release date: September 2015
- The code of the 3D demos now use modern OpenGL, with shaders, instead of
the fixed pipeline API of OpenGL-1.
- Initial support of the Microsoft Windows Visual C++ compiler 2015 (VC14).
* General
- Support for unordered sets and maps of the stdlib and of boost for handle
and index classes.
- The Microsoft Windows Visual C++ compiler 2015 (VC14) is now supported.
However, since this compiler is not officially supported by Intel TBB 4.4
and Qt 5.5 (the latest versions available at the time of this release), the
parallelism features of CGAL and Qt5 demos will not work.
* L Infinity Segment Delaunay Graphs (new package)
@ -93,6 +90,12 @@ Release date: September 2015
mesh processing.
* General
- Support for unordered sets and maps of the stdlib and of boost for handle
and index classes.
* Approximation of Ridges and Umbilics on Triangulated Surface Meshes
- This package now supports any model of the concept FaceGraph.
@ -102,8 +105,6 @@ Release date: September 2015
FaceGraph.
* dD Geometry Kernel
- Epick_d gains 3 new functors: Construct_circumcenter_d,
@ -111,8 +112,6 @@ Release date: September 2015
the computation of alpha-shapes.
* 2D Arrangements
- Introduced a new traits class, called
@ -154,18 +153,16 @@ Release date: September 2015
* 3D Periodic Triangulations
- Rename Periodic_3_triangulation_traits_3
- Rename Periodic_3_triangulation_traits_3 to
Periodic_3_Delaunay_triangulation_traits_3.
- Rename the concept Periodic_3TriangulationTraits_3
- Rename the concept Periodic_3TriangulationTraits_3 to
Periodic_3DelaunayTriangulationTraits_3.
- Create Periodic_3_triangulation_traits_3 and the concept
Periodic_3TriangulationTraits_3.
* 2D Conforming Triangulations and Meshes
- Add an optimization method CGAL::lloyd_optimize_mesh_2() that implements
@ -192,8 +189,6 @@ Release date: September 2015
spatial_sort_on_sphere.
* Geometric Object Generators
- Add new random generator of points in a 2D and 3D triangle and in a

View File

@ -59,7 +59,7 @@
<td width="28%">
<table CELLSPACING=0>
<tr><td><a href="#release4.7">4.7</a>&nbsp;<td> (September 2015)
<tr><td><a href="#release4.7">4.7</a>&nbsp;<td> (October 2015)
<tr><td><a href="#release4.6.2">4.6.2</a>&nbsp;<td> (August 2015)
<tr><td><a href="#release4.6.1">4.6.1</a>&nbsp;<td> (June 2015)
<tr><td><a href="#release4.6">4.6</a>&nbsp;<td> (April 2015)
@ -114,37 +114,67 @@ and <code>src/</code> directories).
</table>
<HR>
<h2 id="release4.7">Release 4.7 </h2>
<!-- to remove once 4.7 is published
<h2 id="release4.8">Release 4.8 </h2>
<div>
<p>Release date: September 2015 </p>
to remove once 4.7 is published: -->
<!-- Installation (and general changes) -->
<!-- New packages -->
<!-- Major and breaking changes -->
<!-- Arithmetic and Algebra -->
<!-- Combinatorial Algorithms -->
<!-- Geometry Kernels -->
<!-- Convex Hull Algorithms -->
<!-- Polygons -->
<!-- Cell Complexes and Polyhedra -->
<!-- Arrangements -->
<!-- Triangulations and Delaunay Triangulations -->
<!-- Voronoi Diagrams -->
<!-- Mesh Generation -->
<!-- Geometry Processing -->
<!-- Spatial Searching and Sorting -->
<!-- Geometric Optimization -->
<!-- Interpolation -->
<!-- Support Library -->
<!-- end of the div for 4.8 -->
<!-- to remove once 4.7 is published
</div>
to remove once 4.7 is published: -->
<h2 id="release4.7">Release 4.7 </h2>
<div>
<p>Release date: October 2015 </p>
<h3>Installation</h3>
<ul>
<li>The minimum required version of CMake is now 2.8.11. CMake versions
3.1, 3.2, and 3.3 are supported.</li>
3.1, 3.2, and 3.3 are supported.</li>
<li>All Qt4 demos have been updated and now require Qt5 to be
compiled. Qt5 version 5.3 or higher is required.
The support for Qt4 is dropped. To compile libCGAL_Qt5 and demos,
you must set the cmake or environment variable <code>Qt5_DIR</code> to point to
the path to the directory containing the file <code>Qt5Config.cmake</code> created
by your Qt5 installation.
If you are using the open source edition it should be
compiled. Qt5 version 5.3 or higher is required. The support for Qt4
is dropped. To compile libCGAL_Qt5 and demos, you must set the cmake
or environment variable <code>Qt5_DIR</code> to point to the path to
the directory containing the file <code>Qt5Config.cmake</code>
created by your Qt5 installation. If you are using the open source
edition it should be
<code>/path-to/qt-everywhere-opensource-src-&lt;version&gt;/qtbase/lib/cmake/Qt5</code>.
</li>
<li>The code of the 3D demos now use modern OpenGL, with shaders,
instead of the fixed pipeline API of OpenGL-1.</li>
<li>Initial support of the Microsoft Windows Visual C++ compiler 2015
(VC14).</li>
</ul>
<h3>General</h3>
<ul>
<li>Support for unordered sets and maps of the stdlib and of boost for
handle and index classes.
<li>The Microsoft Windows Visual C++ compiler 2015 (VC14) is now
supported. However, since this compiler is not officially supported
by Intel TBB 4.4 and Qt 5.5 (the latest versions available at the
time of this release), the parallelism features of CGAL and Qt5 demos
will not work.
</li>
</ul>
<!-- New packages -->
<h3>L Infinity Segment Delaunay Graphs (new package)</h3>
<ul>
@ -186,25 +216,25 @@ and <code>src/</code> directories).
<h3>Triangulated Surface Mesh Skeletonization (new package)</h3>
<ul>
<li>
This package provides a (1D) curve skeleton extraction algorithm
for a triangulated polygonal mesh without borders based on the
mean curvature flow. The particularity of this skeleton is that
it captures the topology of the input. For each skeleton vertex
one can obtain its location and its corresponding vertices from
the input mesh. The code is generic and works with any model of
the `FaceListGraph` concept.
This package provides a (1D) curve skeleton extraction algorithm for
a triangulated polygonal mesh without borders based on the mean
curvature flow. The particularity of this skeleton is that it
captures the topology of the input. For each skeleton vertex one can
obtain its location and its corresponding vertices from the input
mesh. The code is generic and works with any model of the
`FaceListGraph` concept.
</li>
</ul>
<h3>3D Point-Set Shape Detection (new package)</h3>
<ul>
<li>
This package implements the efficient RANSAC method for shape detection,
contributed by Schnabel et al. From an unstructured point set with
unoriented normals, the algorithm detects a set of shapes. Five
types of primitive shapes are provided by this package: plane,
sphere, cylinder, cone and torus. Detecting other types of shapes
is possible by implementing a class derived from a base shape.
This package implements the efficient RANSAC method for shape
detection, contributed by Schnabel et al. From an unstructured point
set with unoriented normals, the algorithm detects a set of
shapes. Five types of primitive shapes are provided by this package:
plane, sphere, cylinder, cone and torus. Detecting other types of
shapes is possible by implementing a class derived from a base shape.
</li>
</ul>
@ -217,126 +247,134 @@ and <code>src/</code> directories).
<h3>Polygon Mesh Processing (new package)</h3>
<ul>
<li>
This package implements a collection of methods and classes
for polygon mesh processing, ranging from basic operations on simplices,
to complex geometry processing algorithms.
The implementation of this package mainly follows algorithms and references
given in Botsch et al.'s book on polygon mesh processing.
</li>
<li> This package implements a collection of methods and classes for
polygon mesh processing, ranging from basic operations on simplices,
to complex geometry processing algorithms. The implementation of
this package mainly follows algorithms and references given in Botsch
et al.'s book on polygon mesh processing.
</li>
</ul>
<h3>General</h3>
<ul>
<li>Support for unordered sets and maps of the stdlib and of boost for
handle and index classes.
</li>
</ul>
<!-- Major and breaking changes -->
<h3>Approximation of Ridges and Umbilics on Triangulated Surface Meshes</h3>
<ul>
<li> This package now supports any model of the concept <code>FaceGraph</code>.
<li> <b>Breaking change:</b> The package no longer support models
of <code>TriangulatedSurfaceMesh</code> which are not at the same time
model of the concept <code>FaceGraph</code>.
</li>
</ul>
<!-- Arithmetic and Algebra -->
<!-- Combinatorial Algorithms -->
<!-- Geometry Kernels -->
<ul>
<li> This package now supports any model of the
concept <code>FaceGraph</code>.
<li> <b>Breaking change:</b> The package no longer support models
of <code>TriangulatedSurfaceMesh</code> which are not at the same
time model of the concept <code>FaceGraph</code>.
</li>
</ul>
<h3>dD Geometry Kernel</h3>
<ul>
<li>
Epick_d gains 3 new functors: <code>Construct_circumcenter_d</code>,
<code>Compute_squared_radius_d</code>, <code>Side_of_bounded_sphere_d</code>.
<code>Compute_squared_radius_d</code>,
<code>Side_of_bounded_sphere_d</code>.
Those are essential for the computation of alpha-shapes.
</li>
</ul>
<!-- Convex Hull Algorithms -->
<!-- Polygons -->
<!-- Cell Complexes and Polyhedra -->
<!-- Arrangements -->
<h3>2D Arrangements</h3>
<ul>
<li>Introduced a new traits class, called
<code>Arr_polycurve_traits_2&lt;SubcurveTraits&gt;</code>, which handles
general piece-wise (polycurve) curves. The pieces do not necessarily
have to be linear.</li>
<code>Arr_polycurve_traits_2&lt;SubcurveTraits&gt;</code>, which
handles general piece-wise (polycurve) curves. The pieces do not
necessarily have to be linear.</li>
<li>Introduced two new concepts called
<code>ArrangementApproximateTraits_2</code> and
<code>ArrangementConstructXMonotoneCurveTraits_2</code>.
<ul>
<li>The existing <code>ArrangementLandmarkTraits_2</code> concept,
which has two requirements, now refines the two respective concepts
above.</li>
which has two requirements, now refines the two respective
concepts above.</li>
<li>The template parameter of the exsting
<code>Arr_polyline_traits_2&lt;SegmentTraits&gt;</code> template must
be substituted with a traits class that is a model of
the <code>ArrangementConstructXMonotoneTraits_2</code> concept among
the other when <code>Arr_polyline_traits_2</code> is
instantiated.</li>
</ul></li>
<code>Arr_polyline_traits_2&lt;SegmentTraits&gt;</code> template
must be substituted with a traits class that is a model of
the <code>ArrangementConstructXMonotoneTraits_2</code> concept
among the other when <code>Arr_polyline_traits_2</code> is
instantiated.
</li>
</ul>
</li>
</ul>
<h3>2D Minkowski Sums</h3>
<ul>
<li>Added support for polygons with holes and optimized the construction
of Minkowski sums.
<ul>
<li>Introduced an implementation of the "reduced convolution" method, a
variant of the method described in "2D Minkowski Sum of Polygons Using
Reduced Convolution" by Behar and Lien. The new method supports polygons
with holes and in many cases out pergorms the implementation of the
exsisting (full) convolution method.</li>
<li>Introduced two new classes that decompose polygons into convex pieces
(models of the <code>PolygonConvexDecomposition_2</code> concept) based
on vertical decomposition and constrained Delaunay triangulation,
respectively. These new models also support the convex decomposition of
polygons with holes.</li>
</ul></li>
<li>Added support for polygons with holes and optimized the
construction of Minkowski sums.
<ul>
<li>Introduced an implementation of the "reduced convolution"
method, a variant of the method described in "2D Minkowski Sum of
Polygons Using Reduced Convolution" by Behar and Lien. The new
method supports polygons with holes and in many cases out
pergorms the implementation of the exsisting (full) convolution
method.</li>
<li>Introduced two new classes that decompose polygons into convex
pieces (models of the <code>PolygonConvexDecomposition_2</code>
concept) based on vertical decomposition and constrained Delaunay
triangulation, respectively. These new models also support the
convex decomposition of polygons with holes.
</li>
</ul>
</li>
</ul>
<!-- Triangulations and Delaunay Triangulations -->
<h3>3D Periodic Triangulations</h3>
<ul>
<li>Rename Periodic_3_triangulation_traits_3 Periodic_3_Delaunay_triangulation_traits_3.
<li>Rename <code>Periodic_3_triangulation_traits_3</code> to
<code>Periodic_3_Delaunay_triangulation_traits_3</code>.
</li>
<li>Rename the concept Periodic_3TriangulationTraits_3 Periodic_3DelaunayTriangulationTraits_3.
<li>Rename the concept <code>Periodic_3TriangulationTraits_3</code> to
<code>Periodic_3DelaunayTriangulationTraits_3</code>.
</li>
<li>Create Periodic_3_triangulation_traits_3 and the concept Periodic_3TriangulationTraits_3.
<li>Create <code>Periodic_3_triangulation_traits_3</code> and the
concept <code>Periodic_3TriangulationTraits_3</code>.
</li>
</ul>
<!-- Voronoi Diagrams -->
<!-- Mesh Generation -->
<h3>2D Conforming Triangulations and Meshes</h3>
<ul>
<li>
Add an optimization method <code>CGAL::lloyd_optimize_mesh_2()</code>
that implements the Lloyd (or Centroidal Voronoi Tesselation)
optimization algorithm in a Constrained Delaunay Triangulation. For
optimization, the triangulation data structure on which the mesher
relies needs its <code>VertexBase</code> template parameter to be a
model of the new concept <code>DelaunayMeshVertexBase_2</code>.
Add an optimization method <code>CGAL::lloyd_optimize_mesh_2()</code>
that implements the Lloyd (or Centroidal Voronoi Tesselation)
optimization algorithm in a Constrained Delaunay Triangulation. For
optimization, the triangulation data structure on which the mesher
relies needs its <code>VertexBase</code> template parameter to be a
model of the new concept <code>DelaunayMeshVertexBase_2</code>.
</li>
</ul>
<!-- Geometry Processing -->
<h3>Point Set Processing and Surface Reconstruction from Point Sets</h3>
<ul>
<li>
Add the function <code>CGAL::compute_vcm()</code> for computing the
Voronoi Covariance Measure (VCM) of a point set. The output of this function
can be used with the function <code>CGAL::vcm_is_on_feature_edge()</code>
to determine whether a point is on or close to a feature edge. The former
function is also internally used by <code>CGAL::vcm_estimate_normals()</code>
to estimate the normals of a point set and it is particularly suited to point
set with noise.
Add the function <code>CGAL::compute_vcm()</code> for computing the
Voronoi Covariance Measure (VCM) of a point set. The output of this
function can be used with the
function <code>CGAL::vcm_is_on_feature_edge()</code> to determine
whether a point is on or close to a feature edge. The former function
is also internally used by <code>CGAL::vcm_estimate_normals()</code>
to estimate the normals of a point set and it is particularly suited
to point set with noise.
</li>
</ul>
<!-- Spatial Searching and Sorting -->
<h3>Spatial Sorting</h3>
<ul>
<li>Add the possibility to sort points on a sphere along
a space-filling curve using the functions
<code>CGAL::hilbert_sort_on_sphere</code> and
<code>CGAL::spatial_sort_on_sphere</code>.</li>
<li>Add the possibility to sort points on a sphere along
a space-filling curve using the functions
<code>CGAL::hilbert_sort_on_sphere</code> and
<code>CGAL::spatial_sort_on_sphere</code>.</li>
</ul>
<!-- Geometric Optimization -->
<!-- Interpolation -->
<!-- Support Library -->
<h3>Geometric Object Generators</h3>
<ul>
<li>Add new random generator of points in a 2D and 3D triangle and in a
@ -347,7 +385,6 @@ model of the concept <code>FaceGraph</code>.
</li>
</ul>
<!-- end of the div for 4.7 -->
</div>

View File

@ -102,6 +102,17 @@ if (WIN32)
if(MSVC11)
set(_TBB_COMPILER "vc11")
endif(MSVC11)
if(MSVC12)
set(_TBB_COMPILER "vc12")
endif(MSVC12)
#note there was no MSVC13
if(MSVC14)
if(RUNNING_CGAL_AUTO_TEST)
set (TBB_FOUND "NO")
return()#binaries for TBB not publicly available when CGAL-4.7 is published
endif(RUNNING_CGAL_AUTO_TEST)
message(STATUS "[Warning] FindTBB.cmake: TBB 4.4 (latest available when CGAL-4.7 is published) does not provide support for MSVC 2015.")
endif(MSVC14)
# Todo: add other Windows compilers such as ICL.
set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE})
endif (WIN32)

View File

@ -191,7 +191,7 @@ Kernel::FT area() const;
/*!
returns a bounding box containing `r`.
*/
Bbox bbox() const;
Bbox_2 bbox() const;
/*!
returns the iso-oriented rectangle obtained by applying `t` on

View File

@ -22,7 +22,7 @@ side is the bounded interior of the sphere.
\pre `A` contains \f$ d+1\f$ points in \f$ d\f$-space.
\cgalRequires The value type of `ForwardIterator` is `Kernel_d::Point_d`.
*/
template <class ForwardIterator> Bounded_side
template <class ForwardIterator> Oriented_side
operator()( ForwardIterator first, ForwardIterator last, const
Kernel_d::Point_d& p);

View File

@ -28,7 +28,7 @@
\cgalPkgSummaryEnd
\cgalPkgShortInfoBegin
\cgalPkgSince{3.2}
\cgalPkgDependsOn{\ref PkgKdsFrameworkSummary. Two dimensional visualization depends on \ref thirdpartyQt\, three dimensional visualization depends on \ref thirdpartyCoin.}
\cgalPkgDependsOn{\ref PkgKdsFrameworkSummary. Two dimensional visualization depends on \sc{Qt} 3, three dimensional visualization depends on \ref thirdpartyCoin.}
\cgalPkgBib{cgal:r-kds}
\cgalPkgLicense{\ref licensesLGPL "LGPL"}
\cgalPkgShortInfoEnd

View File

@ -31,7 +31,7 @@
\cgalPkgSummaryEnd
\cgalPkgShortInfoBegin
\cgalPkgSince{3.2}
\cgalPkgDependsOn{Two dimensional visualization depends on \ref thirdpartyQt\, three dimensional visualization depends on \ref thirdpartyCoin.}
\cgalPkgDependsOn{Two dimensional visualization depends on \sc{Qt} 3, three dimensional visualization depends on \ref thirdpartyCoin.}
\cgalPkgBib{cgal:r-kdsf}
\cgalPkgLicense{\ref licensesLGPL "LGPL"}
\cgalPkgShortInfoEnd

View File

@ -16,6 +16,7 @@ endif()
## To add expensive tests
# add_definitions("-DCGAL_CHECK_EXPENSIVE")
# add_definitions("-Wall -Wextra")
## For profilling with gprof
# add_definitions("-pg")
@ -72,7 +73,6 @@ target_link_libraries(Linear_cell_complex_3_demo ${CGAL_LIBRARIES}
${CGAL_3RD_PARTY_LIBRARIES})
target_link_libraries(Linear_cell_complex_3_demo ${QT_LIBRARIES}
${QGLVIEWER_LIBRARIES} )
target_link_libraries(Linear_cell_complex_3_demo ${OPENGL_gl_LIBRARY}
${OPENGL_glu_LIBRARY} )
target_link_libraries(Linear_cell_complex_3_demo ${OPENGL_gl_LIBRARY} )
endif()

View File

@ -24,6 +24,7 @@
#include <QSettings>
#include <CGAL/Timer.h>
#include <CGAL/ipower.h>
#include "import_moka.h"
// Function defined in Linear_cell_complex_3_subivision.cpp
void subdivide_lcc_3 (LCC & m);
@ -58,7 +59,7 @@ MainWindow::MainWindow (QWidget * parent):CGAL::Qt::DemosMainWindow (parent),
labels.append(QString(tr("Hidden")));
volumeList->setHorizontalHeaderLabels(labels);
//volumeList->resizeColumnsToContents();
volumeList->setFixedWidth(200);
volumeList->setFixedWidth(220);
/* volumeList->setColumnWidth(0,85);
volumeList->setColumnWidth(1,35);
volumeList->setColumnWidth(2,35);*/
@ -82,7 +83,7 @@ MainWindow::MainWindow (QWidget * parent):CGAL::Qt::DemosMainWindow (parent),
this->addRecentFiles (this->menuFile, this->actionQuit);
connect (this, SIGNAL (openRecentFile (QString)),
this, SLOT (load_off (QString)));
this, SLOT (load_depend_on_extension(QString)));
statusMessage = new QLabel
("Darts: 0, Vertices: 0 (Points: 0), Edges: 0, Facets: 0,"
@ -223,6 +224,32 @@ void MainWindow::init_all_new_volumes()
{ on_new_volume(it); }
}
void MainWindow::on_actionSave_triggered ()
{
QString fileName = QFileDialog::getSaveFileName (this,
tr ("Save"),
"save.3map",
tr ("3-map files (*.3map)"));
if (!fileName.isEmpty ())
{
save(fileName);
}
}
void MainWindow::on_actionLoad_triggered ()
{
QString fileName = QFileDialog::getOpenFileName (this,
tr ("Load"),
"./3map",
tr ("3-map files (*.3map)"));
if (!fileName.isEmpty ())
{
load(fileName, true);
}
}
void MainWindow::on_actionImportOFF_triggered ()
{
QString fileName = QFileDialog::getOpenFileName (this,
@ -236,6 +263,19 @@ void MainWindow::on_actionImportOFF_triggered ()
}
}
void MainWindow::on_actionImportMoka_triggered()
{
QString fileName = QFileDialog::getOpenFileName (this,
tr ("Import Moka"),
"./moka",
tr ("Moka files (*.moka)"));
if (!fileName.isEmpty ())
{
load_moka(fileName, true);
}
}
void MainWindow::on_actionImport3DTDS_triggered ()
{
QString fileName = QFileDialog::getOpenFileName (this,
@ -264,6 +304,84 @@ void MainWindow::on_actionAddOFF_triggered()
}
}
void MainWindow::load_depend_on_extension(const QString & fileName, bool clear)
{
QString ext = QFileInfo(fileName).suffix();
if ( ext=="3map")
{
load(fileName, clear);
}
else if (ext=="off")
{
load_off(fileName, clear);
}
else if (ext=="moka")
{
load_moka(fileName, clear);
}
else
{
std::cout<<"Extension not considered."<<std::endl;
}
}
void MainWindow::load(const QString & fileName, bool clear)
{
QApplication::setOverrideCursor (Qt::WaitCursor);
if (clear) this->clear_all();
#ifdef CGAL_PROFILE_LCC_DEMO
CGAL::Timer timer;
timer.start();
#endif
bool res = load_combinatorial_map(fileName.toStdString().c_str(), *(scene.lcc));
#ifdef CGAL_PROFILE_LCC_DEMO
timer.stop();
std::cout<<"Time to load 3-map "<<qPrintable(fileName)<<": "
<<timer.time()<<" seconds."<<std::endl;
#endif
recreate_whole_volume_list();
this->addToRecentFiles(fileName);
QApplication::restoreOverrideCursor ();
if (res)
statusBar ()->showMessage (QString ("3-map loaded ") + fileName,
DELAY_STATUSMSG);
else
statusBar ()->showMessage (QString ("Problem: 3-map not loaded ") + fileName,
DELAY_STATUSMSG);
Q_EMIT (sceneChanged ());
}
void MainWindow::save(const QString & fileName)
{
QApplication::setOverrideCursor (Qt::WaitCursor);
#ifdef CGAL_PROFILE_LCC_DEMO
CGAL::Timer timer;
timer.start();
#endif
if ( save_combinatorial_map(*(scene.lcc), fileName.toStdString().c_str()) )
statusBar ()->showMessage (QString ("3-map saved ") + fileName,
DELAY_STATUSMSG);
else
statusBar ()->showMessage (QString ("Problem: 3-map not saved ") + fileName,
DELAY_STATUSMSG);
QApplication::restoreOverrideCursor ();
#ifdef CGAL_PROFILE_LCC_DEMO
timer.stop();
std::cout<<"Time to save 3-map "<<qPrintable(fileName)<<": "
<<timer.time()<<" seconds."<<std::endl;
#endif
}
void MainWindow::load_off (const QString & fileName, bool clear)
{
QApplication::setOverrideCursor (Qt::WaitCursor);
@ -333,6 +451,40 @@ void MainWindow::load_3DTDS (const QString & fileName, bool clear)
Q_EMIT (sceneChanged ());
}
void MainWindow::load_moka(const QString & fileName, bool clear)
{
QApplication::setOverrideCursor (Qt::WaitCursor);
if (clear) this->clear_all();
#ifdef CGAL_PROFILE_LCC_DEMO
CGAL::Timer timer;
timer.start();
#endif
CGAL::import_from_moka < LCC > (*scene.lcc, qPrintable (fileName));
#ifdef CGAL_PROFILE_LCC_DEMO
timer.stop();
std::cout<<"Time to load off "<<qPrintable(fileName)<<": "
<<timer.time()<<" seconds."<<std::endl;
#endif
init_all_new_volumes();
recreate_whole_volume_list();
this->addToRecentFiles (fileName);
QApplication::restoreOverrideCursor ();
if (clear)
statusBar ()->showMessage (QString ("Load off file") + fileName,
DELAY_STATUSMSG);
else
statusBar ()->showMessage (QString ("Add off file") + fileName,
DELAY_STATUSMSG);
Q_EMIT (sceneChanged ());
}
Dart_handle MainWindow::make_iso_cuboid(const Point_3 basepoint, LCC::FT lg)
{
return scene.lcc->make_hexahedron(basepoint,
@ -783,7 +935,7 @@ void MainWindow::on_actionRemove_filled_volumes_triggered()
DELAY_STATUSMSG);
}
void MainWindow::on_actionTriangulate_all_facets_triggered()
void MainWindow::on_actionInsert_center_vertices_triggered()
{
QApplication::setOverrideCursor (Qt::WaitCursor);
@ -805,17 +957,113 @@ void MainWindow::on_actionTriangulate_all_facets_triggered()
#ifdef CGAL_PROFILE_LCC_DEMO
timer.stop();
std::cout<<"Time to triangulate all filled faces: "
std::cout<<"Time to insert center vertices in all filled faces: "
<<timer.time()<<" seconds."<<std::endl;
#endif
QApplication::restoreOverrideCursor ();
Q_EMIT (sceneChanged ());
statusBar()->showMessage
(QString ("Facets of visible and filled volume(s) triangulated"),
(QString ("Vertices are inserted in center of facets of visible and filled volume(s)"),
DELAY_STATUSMSG);
}
double compute_angle3d(const Vector_3& v1, const Vector_3& v2)
{
double a = CGAL::to_double( (v1*v2) /
( sqrt(v1.squared_length()) * sqrt(v2.squared_length()) ) ) ;
if (a < -1.0) return acos(-1.0)/M_PI*180.0;
else if (a > 1.0) return acos(1.0)/M_PI*180.0;
else return acos(a)/M_PI*180.0;
}
void MainWindow::on_actionMerge_coplanar_faces_triggered()
{
QApplication::setOverrideCursor (Qt::WaitCursor);
#ifdef CGAL_PROFILE_LCC_DEMO
CGAL::Timer timer;
timer.start();
#endif
scene.lcc->set_update_attributes(false);
std::vector<Dart_handle> edges;
int treated = scene.lcc->get_new_mark();
int treated2 = scene.lcc->get_new_mark();
for ( LCC::Dart_range::iterator it= scene.lcc->darts().begin(),
itend = scene.lcc->darts().end(); it!=itend; ++it )
{
if (!scene.lcc->is_marked(it, treated) )
{
if ( CGAL::is_removable<LCC, 1>(*scene.lcc, it) )
{
LCC::Vector normal1 = CGAL::compute_normal_of_cell_2(*scene.lcc,it);
LCC::Vector normal2 = CGAL::compute_normal_of_cell_2(*scene.lcc, scene.lcc->beta<2>(it) );
double angle = compute_angle3d(normal1, normal2);
if ( ((angle<5.0 || angle>355.0) || (angle<185.0 && angle>175.0)) )
{
edges.push_back(it);
}
}
CGAL::mark_cell<LCC, 1>(*scene.lcc, it, treated);
}
}
for (std::vector<Dart_handle>::iterator it=edges.begin(),
itend=edges.end(); it!=itend; ++it)
{
CGAL::mark_cell<LCC, 1>(*scene.lcc, *it, treated2);
if ( scene.lcc->beta<0, 2>(*it)==*it || scene.lcc->beta<1, 2>(*it)==*it)
{ // To process dangling edges
Dart_handle actu = *it, prev=NULL;
do
{
if ( scene.lcc->beta<0, 2>(actu)==actu ) prev = scene.lcc->beta<1>(actu);
else prev = scene.lcc->beta<0>(actu);
if (scene.lcc->is_marked(actu, treated2) &&
(scene.lcc->beta<0, 2>(actu)!=actu || scene.lcc->beta<1, 2>(actu)!=actu) )
{
CGAL::remove_cell<LCC, 1>(*scene.lcc, actu);
actu = prev;
}
else
actu = NULL;
}
while (actu!=NULL && (scene.lcc->beta<0, 2>(actu)==actu || scene.lcc->beta<1, 2>(actu)==actu));
}
else if ( !CGAL::belong_to_same_cell<LCC, 2>(*scene.lcc, *it,
scene.lcc->beta<2>(*it)) )
CGAL::remove_cell<LCC, 1>(*scene.lcc, *it);
}
assert(scene.lcc->is_whole_map_marked(treated));
scene.lcc->free_mark(treated);
scene.lcc->free_mark(treated2);
scene.lcc->set_update_attributes(true);
#ifdef CGAL_PROFILE_LCC_DEMO
timer.stop();
std::cout<<"Time to merge all coplanar faces: "
<<timer.time()<<" seconds."<<std::endl;
#endif
recreate_whole_volume_list();
QApplication::restoreOverrideCursor ();
Q_EMIT (sceneChanged ());
statusBar()->showMessage
(QString ("Coplanar face(s) merged"), DELAY_STATUSMSG);
}
void MainWindow::on_actionMerge_all_volumes_triggered()
{
QApplication::setOverrideCursor (Qt::WaitCursor);
@ -861,6 +1109,179 @@ void MainWindow::on_actionMerge_all_volumes_triggered()
(QString ("Visible and filled volume(s) merged"), DELAY_STATUSMSG);
}
bool is_external(CDT::Face_handle fh)
{
return fh->info().is_external;
}
int number_of_existing_edge(CDT::Face_handle fh)
{
unsigned res=0;
for (int i=0; i<3; ++i)
if (fh->info().exist_edge[i]) ++res;
return res;
}
int get_free_edge(CDT::Face_handle fh)
{
CGAL_assertion( number_of_existing_edge(fh)==2 );
for (int i=0; i<3; ++i)
if (!fh->info().exist_edge[i]) return i;
CGAL_assertion(false);
return -1;
}
void constrained_delaunay_triangulation(LCC &lcc, Dart_handle d1)
{
Vector_3 normal = CGAL::compute_normal_of_cell_2(lcc,d1);
P_traits cdt_traits(normal);
CDT cdt(cdt_traits);
//inserting the constraints edge by edge
LCC::Dart_of_orbit_range<1>::iterator
it(lcc.darts_of_orbit<1>(d1).begin());
CDT::Vertex_handle previous=LCC::null_handle, first=LCC::null_handle,
vh=LCC::null_handle;
for (LCC::Dart_of_orbit_range<1>::iterator
itend(lcc.darts_of_orbit<1>(d1).end()); it!=itend; ++it)
{
vh = cdt.insert(lcc.point(it));
vh->info()=it;
if( first==NULL )
{
first=vh;
}
if( previous!=NULL)
{
CGAL_assertion( previous !=vh );
cdt.insert_constraint(previous,vh);
}
previous=vh;
}
cdt.insert_constraint(previous,first);
CGAL_assertion(cdt.is_valid());
// sets mark is_external
for( CDT::All_faces_iterator fit = cdt.all_faces_begin(),
fitend = cdt.all_faces_end(); fit != fitend; ++fit)
{
fit->info().is_external = false;
fit->info().exist_edge[0]=false;
fit->info().exist_edge[1]=false;
fit->info().exist_edge[2]=false;
}
std::queue<CDT::Face_handle> face_queue;
face_queue.push(cdt.infinite_vertex()->face());
while(! face_queue.empty() )
{
CDT::Face_handle fh = face_queue.front();
face_queue.pop();
if(!fh->info().is_external)
{
fh->info().is_external = true;
for(int i = 0; i <3; ++i)
{
if(!cdt.is_constrained(std::make_pair(fh, i)))
{
face_queue.push(fh->neighbor(i));
}
}
}
}
for( CDT::Finite_edges_iterator eit = cdt.finite_edges_begin(),
eitend = cdt.finite_edges_end(); eit != eitend; ++eit)
{
CDT::Face_handle fh = eit->first;
int index = eit->second;
CDT::Face_handle opposite_fh = fh->neighbor(index);
if(cdt.is_constrained(std::make_pair(fh, index)))
{
fh->info().exist_edge[index]=true;
opposite_fh->info().exist_edge[cdt.mirror_index(fh,index)]=true;
if ( !fh->info().is_external && number_of_existing_edge(fh)==2 )
face_queue.push(fh);
if ( !opposite_fh->info().is_external &&
number_of_existing_edge(opposite_fh)==2 )
face_queue.push(opposite_fh);
}
}
while( !face_queue.empty() )
{
CDT::Face_handle fh = face_queue.front();
face_queue.pop();
CGAL_assertion( number_of_existing_edge(fh)>=2 ); // i.e. ==2 or ==3
CGAL_assertion( !fh->info().is_external );
if (number_of_existing_edge(fh)==2)
{
int index = get_free_edge(fh);
CDT::Face_handle opposite_fh = fh->neighbor(index);
CGAL_assertion( !fh->info().exist_edge[index] );
CGAL_assertion( !opposite_fh->info().
exist_edge[cdt.mirror_index(fh,index)] );
const CDT::Vertex_handle va = fh->vertex(cdt. cw(index));
const CDT::Vertex_handle vb = fh->vertex(cdt.ccw(index));
Dart_handle ndart=
CGAL::insert_cell_1_in_cell_2(lcc,va->info(),vb->info());
va->info()=lcc.beta<2>(ndart);
fh->info().exist_edge[index]=true;
opposite_fh->info().exist_edge[cdt.mirror_index(fh,index)]=true;
if ( !opposite_fh->info().is_external &&
number_of_existing_edge(opposite_fh)==2 )
face_queue.push(opposite_fh);
}
}
}
void MainWindow::on_actionTriangulate_all_facets_triggered()
{
QApplication::setOverrideCursor (Qt::WaitCursor);
#ifdef CGAL_PROFILE_LCC_DEMO
CGAL::Timer timer;
timer.start();
#endif
std::vector<LCC::Dart_handle> v;
for (LCC::One_dart_per_cell_range<2>::iterator
it(scene.lcc->one_dart_per_cell<2>().begin()); it.cont(); ++it)
{
if ( scene.lcc->info<3>(it).is_filled_and_visible() ||
(!scene.lcc->is_free<3>(it) &&
scene.lcc->info<3>(scene.lcc->beta<3>(it)).is_filled_and_visible()) )
v.push_back(it);
}
for (std::vector<LCC::Dart_handle>::iterator itv(v.begin());
itv!=v.end(); ++itv)
constrained_delaunay_triangulation(*scene.lcc, *itv);
#ifdef CGAL_PROFILE_LCC_DEMO
timer.stop();
std::cout<<"Time to triangulate all filled faces: "
<<timer.time()<<" seconds."<<std::endl;
#endif
recreate_whole_volume_list();
QApplication::restoreOverrideCursor ();
Q_EMIT (sceneChanged ());
statusBar()->showMessage
(QString ("All visible and filled faces were triangulated"), DELAY_STATUSMSG);
}
bool MainWindow::is_volume_in_list(LCC::Attribute_handle<3>::type ah)
{
for(int row=0; row < volumeList->rowCount(); ++row)
@ -975,6 +1396,8 @@ void MainWindow::recreate_whole_volume_list()
void MainWindow::onCellChanged(int row, int col)
{
volumeList->disconnect(this);
LCC::Attribute_type<3>::type* ptr=
reinterpret_cast<LCC::Attribute_type<3>::type*>
( volumeList->item(row,3)->data(Qt::UserRole).value<quintptr>() );
@ -994,6 +1417,7 @@ void MainWindow::onCellChanged(int row, int col)
(volumeList->item(row,1)->flags()|Qt::ItemIsEnabled);
}
connectVolumeListHandlers();
Q_EMIT( sceneChanged());
}
@ -1875,64 +2299,6 @@ void MainWindow::onSierpinskiCarpetUpdateAttributes(bool newValue)
sierpinskiCarpetUpdateAttributes = newValue;
}
/*void MainWindow::onSierpinskiCarpetNeverUpdateAttributes(bool newValue)
{
if (afterConstructionUpdateAttributes)
{
dialogsierpinskicarpet.groupBox2->setEnabled(false);
}
neverUpdateAttributes = true;
duringConstructionUpdateAttributes = false;
afterConstructionUpdateAttributes = false;
}
void MainWindow::onSierpinskiCarpetDuringConstructionUpdateAttributes(bool newValue)
{
if (afterConstructionUpdateAttributes)
{
dialogsierpinskicarpet.groupBox2->setEnabled(false);
}
neverUpdateAttributes = false;
duringConstructionUpdateAttributes = true;
afterConstructionUpdateAttributes = false;
}
void MainWindow::onSierpinskiCarpetAfterConstructionUpdateAttributes(bool newValue)
{
if (!afterConstructionUpdateAttributes)
{
dialogsierpinskicarpet.groupBox2->setEnabled(true);
}
neverUpdateAttributes = false;
duringConstructionUpdateAttributes = false;
afterConstructionUpdateAttributes = true;
}
void MainWindow::onSierpinskiCarpetUpdateAttributesMethodStdMap(bool newValue)
{
updateAttributesMethodStdMap = true;
updateAttributesMethodTraversal = false;
}
void MainWindow::onSierpinskiCarpetUpdateAttributesMethodTraversal(bool newValue)
{
updateAttributesMethodStdMap = false;
updateAttributesMethodTraversal = true;
}
void MainWindow::onSierpinskiCarpetComputeGeometry(bool newValue)
{
sierpinski_carpet_compute_geometry();
computeGeometry = false;
dialogsierpinskicarpet.computeGeometry->setEnabled(false);
Q_EMIT( sceneChanged());
}*/
void MainWindow::onSierpinskiCarpetInc()
{
QApplication::setOverrideCursor (Qt::WaitCursor);

View File

@ -110,9 +110,12 @@ public:
public Q_SLOTS:
// File menu
void on_actionSave_triggered();
void on_actionLoad_triggered();
void on_actionImportOFF_triggered();
void on_actionAddOFF_triggered();
void on_actionImport3DTDS_triggered();
void on_actionImportMoka_triggered();
void on_actionCompute_Voronoi_3D_triggered();
void on_actionClear_triggered();
@ -130,19 +133,25 @@ public Q_SLOTS:
void on_actionSubdivide_pqq_triggered();
void on_actionDual_3_triggered();
void on_actionClose_volume_triggered();
void on_actionTriangulate_all_facets_triggered();
void on_actionSew3_same_facets_triggered();
void on_actionUnsew3_all_triggered();
void on_actionMerge_coplanar_faces_triggered();
void on_actionMerge_all_volumes_triggered();
void on_actionRemove_filled_volumes_triggered();
void on_actionInsert_center_vertices_triggered();
void on_actionTriangulate_all_facets_triggered();
// View menu
void on_actionExtend_filled_volumes_triggered();
void on_actionExtend_hidden_volumes_triggered();
// Other slots
void load_depend_on_extension(const QString& fileName, bool clear=true);
void load(const QString& fileName, bool clear=true);
void save(const QString& fileName);
void load_off(const QString& fileName, bool clear=true);
void load_3DTDS(const QString& fileName, bool clear=true);
void load_moka(const QString& fileName, bool clear=true);
void onSceneChanged();

View File

@ -33,15 +33,19 @@
<x>0</x>
<y>0</y>
<width>635</width>
<height>22</height>
<height>25</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>&amp;File</string>
</property>
<addaction name="actionLoad"/>
<addaction name="actionSave"/>
<addaction name="separator"/>
<addaction name="actionImportOFF"/>
<addaction name="actionAddOFF"/>
<addaction name="actionImportMoka"/>
<addaction name="separator"/>
<addaction name="actionImport3DTDS"/>
<addaction name="actionCompute_Voronoi_3D"/>
@ -54,12 +58,15 @@
<property name="title">
<string>&amp;Operations</string>
</property>
<addaction name="actionInsert_center_vertices"/>
<addaction name="actionTriangulate_all_facets"/>
<addaction name="actionSew3_same_facets"/>
<addaction name="actionUnsew3_all"/>
<addaction name="actionMerge_coplanar_faces"/>
<addaction name="actionMerge_all_volumes"/>
<addaction name="actionRemove_filled_volumes"/>
<addaction name="separator"/>
<addaction name="actionSew3_same_facets"/>
<addaction name="actionUnsew3_all"/>
<addaction name="separator"/>
<addaction name="actionSubdivide"/>
<addaction name="actionSubdivide_pqq"/>
<addaction name="actionClose_volume"/>
@ -221,6 +228,31 @@
<string>Create Sierpinski Triangle</string>
</property>
</action>
<action name="actionLoad">
<property name="text">
<string>&amp;Load</string>
</property>
</action>
<action name="actionSave">
<property name="text">
<string>&amp;Save</string>
</property>
</action>
<action name="actionImportMoka">
<property name="text">
<string>Import Moka</string>
</property>
</action>
<action name="actionMerge_coplanar_faces">
<property name="text">
<string>Merge coplanar faces</string>
</property>
</action>
<action name="actionInsert_center_vertices">
<property name="text">
<string>Insert center vertices in faces</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

File diff suppressed because it is too large Load Diff

View File

@ -22,57 +22,29 @@
#define VIEWER_H
#include "typedefs.h"
#include <vector>
#include <QGLViewer/qglviewer.h>
#include <QKeyEvent>
#include <QOpenGLFunctions_2_1>
#include <QOpenGLVertexArrayObject>
#include <QGLBuffer>
#include <QOpenGLShaderProgram>
class Viewer : public QGLViewer, QOpenGLFunctions_2_1
class Viewer : public QGLViewer, public QOpenGLFunctions_2_1
{
Q_OBJECT
CGAL::Timer timer;
Scene* scene;
bool wireframe;
bool flatShading;
bool edges;
bool vertices;
CGAL::Bbox_3 bb;
GLuint m_dlFaces;
GLuint m_dlFacesFlat;
GLuint m_dlEdges;
GLuint m_dlVertices;
bool m_displayListCreated;
typedef LCC::Dart_handle Dart_handle;
typedef LCC::Dart_const_handle Dart_const_handle;
public:
Viewer(QWidget* parent);
~Viewer()
{
buffers[0].destroy();
buffers[1].destroy();
buffers[2].destroy();
buffers[3].destroy();
buffers[4].destroy();
buffers[5].destroy();
buffers[6].destroy();
buffers[7].destroy();
vao[0].destroy();
vao[1].destroy();
vao[2].destroy();
vao[3].destroy();
}
~Viewer();
void setScene(Scene* scene_)
{
scene = scene_;
}
{ scene = scene_; }
public:
void draw();
@ -87,12 +59,27 @@ public Q_SLOTS:
void sceneChanged();
private:
void initialize_buffers();
void attrib_buffers(QGLViewer*);
void compile_shaders();
void compute_elements();
void compute_faces(Dart_handle dh);
void compute_edges(Dart_handle dh);
void compute_vertices(Dart_handle dh, bool empty);
private:
Scene* scene;
bool wireframe;
bool flatShading;
bool edges;
bool vertices;
CGAL::Bbox_3 bb;
bool m_previous_scene_empty;
bool are_buffers_initialized;
//Shaders elements
//Shaders elements
int vertexLocation[3];
int normalsLocation;
int mvpLocation[2];
@ -101,24 +88,17 @@ private:
int colorsLocation;
int lightLocation[5];
std::vector<float> pos_points;
std::vector<float> pos_lines;
std::vector<float> pos_facets;
std::vector<float> smooth_normals;
std::vector<float> flat_normals;
std::vector <float> colors;
std::vector<float> colors;
QGLBuffer buffers[10];
QOpenGLVertexArrayObject vao[10];
QOpenGLShaderProgram rendering_program;
QOpenGLShaderProgram rendering_program_p_l;
void initialize_buffers();
void compute_elements();
void attrib_buffers(QGLViewer*);
void compile_shaders();
void triangulate_facet();
bool is_Triangulated();
};
#endif

View File

@ -0,0 +1,192 @@
// Copyright (c) 2011 CNRS and LIRIS' Establishments (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) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
//
#ifndef IMPORT_MOKA_H
#define IMPORT_MOKA_H
namespace CGAL
{
struct GDart
{
unsigned int alpha[4];
Dart_handle dh;
LCC::Vertex_attribute_handle vh;
GDart() : dh(NULL), vh(NULL)
{}
GDart(const GDart& adart) : dh(adart.dh),
vh(adart.vh)
{
for (unsigned int i=0; i<4; ++i)
alpha[i]=adart.alpha[i];
}
};
template<typename LCC>
bool import_from_moka(LCC& lcc, const char* filename)
{
typedef typename LCC::Point Point;
std::ifstream ifile(filename);
if (!ifile)
{
std::cout<<"Error opening file "<<filename<<"."<<std::endl;
return false;
}
std::string line;
std::getline(ifile, line);
if ( line == "Moka file [binary]" )
{
std::cout<<"Binary file not (yet) considered.\n";
return false;
}
else if ( line != "Moka file [ascii]" )
{
std::cout<<"File "<<filename<<" is not a moka file.\n";
std::cout<< line;
return false;
}
// To skip the masks mark (TODO read the marks ?)
std::getline(ifile, line);
std::vector<GDart> gdarts;
unsigned int nbLoaded = 0;
unsigned int number;
double x,y,z;
// First load all the gdarts, and create vertex attributes
while(ifile)
{
GDart agdart;
ifile>>agdart.alpha[0]>>agdart.alpha[1]
>>agdart.alpha[2]>>agdart.alpha[3]; // the 4 alpha
ifile>>number>>number>>number>>number; // to skip the 4*8 marks
if ( agdart.alpha[0]==nbLoaded )
{
std::cout<<"Impossible to load a moka file with 0-free darts.\n";
return false;
}
if ( ifile )
{
ifile>>number; // bool to know if dart has a vertex of not.
if (number)
{
ifile>>x>>y>>z;
agdart.vh = lcc.create_vertex_attribute(Point(x, y, z));
}
gdarts.push_back(agdart);
++nbLoaded;
}
}
ifile.close();
// Second orient the gmap, and create oriented darts.
std::stack<unsigned int> totreat;
for (unsigned int startingdart = 0; startingdart<nbLoaded; ++startingdart)
{
bool orient=(gdarts[startingdart].dh==NULL);
for (unsigned int dim=0; orient && dim<4; ++dim)
if (gdarts[gdarts[startingdart].alpha[dim]].dh!=NULL) orient=false;
if ( orient )
{
totreat.push(startingdart);
gdarts[startingdart].dh=lcc.create_dart();
while ( !totreat.empty() )
{
unsigned int i=totreat.top();
totreat.pop();
assert(gdarts[i].dh!=NULL);
for (unsigned int dim=1; dim<4; ++dim)
{
if (gdarts[i].alpha[dim]!=i &&
gdarts[gdarts[i].alpha[dim]].vh!=NULL)
{
gdarts[i].vh = gdarts[gdarts[i].alpha[dim]].vh;
gdarts[gdarts[i].alpha[dim]].vh = NULL;
}
unsigned int alpha0 = gdarts[i].alpha[0];
assert( alpha0!=i );
if (gdarts[alpha0].alpha[dim]!=alpha0)
{
if ( gdarts[gdarts[alpha0].alpha[dim]].dh==NULL )
{
totreat.push(gdarts[alpha0].alpha[dim]);
gdarts[gdarts[alpha0].alpha[dim]].dh = lcc.create_dart();
lcc.basic_link_beta(gdarts[i].dh,
gdarts[gdarts[alpha0].alpha[dim]].dh,
dim);
}
else if (lcc.is_free(gdarts[i].dh, dim))
{
lcc.basic_link_beta(gdarts[i].dh,
gdarts[gdarts[alpha0].alpha[dim]].dh,
dim);
}
}
}
}
}
}
// Test that the gmap was orientable.
bool orientable = true;
for (unsigned int i = 0; i<nbLoaded; ++i)
{
if (gdarts[i].dh!=NULL)
{
for (unsigned int dim=0; dim<4; ++dim)
{
if (orientable &&
gdarts[i].alpha[dim]!=i &&
gdarts[gdarts[i].alpha[dim]].dh!=NULL)
{
std::cout<<"Pb, the gmap is NOT orientable."<<std::endl;
orientable=false;
// lcc.clear();
}
}
if ( gdarts[i].dh->attribute<3>() == NULL )
{
lcc.template set_attribute<3>(gdarts[i].dh, lcc.template create_attribute<3>());
}
}
if (gdarts[i].vh!=NULL)
{
lcc.set_vertex_attribute(gdarts[i].dh, gdarts[i].vh);
}
}
return true;
}
}
#endif

View File

@ -24,6 +24,13 @@
#include <CGAL/Linear_cell_complex_constructors.h>
#include <CGAL/Linear_cell_complex_operations.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Combinatorial_map_save_load.h>
#include <CGAL/Triangulation_2_filtered_projection_traits_3.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
#include <CGAL/Triangulation_face_base_with_info_2.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <CGAL/Constrained_triangulation_plus_2.h>
#include <CGAL/IO/Color.h>
#include <CGAL/Timer.h>
@ -45,6 +52,11 @@ extern CGAL::Random myrandom;
class Volume_info
{
friend void CGAL::read_cmap_attribute_node<Volume_info>
(const boost::property_tree::ptree::value_type &v,Volume_info &val);
friend void CGAL::write_cmap_attribute_node<Volume_info>(boost::property_tree::ptree & node,
const Volume_info& arg);
public:
Volume_info() : m_color(CGAL::Color(myrandom.get_int(0,256),
myrandom.get_int(0,256),
@ -91,22 +103,61 @@ public:
void negate_filled()
{ set_filled(!is_filled()); }
private:
private:
CGAL::Color m_color;
char m_status;
};
namespace CGAL
{
template<>
inline void read_cmap_attribute_node<Volume_info>
(const boost::property_tree::ptree::value_type &v,Volume_info &val)
{
try
{
val.m_status = v.second.get<int>("status");
}
catch(const std::exception & )
{}
try
{
char r = v.second.get<int>("color-r");
char g = v.second.get<int>("color-g");
char b = v.second.get<int>("color-b");
val.m_color = CGAL::Color(r,g,b);
}
catch(const std::exception & )
{}
}
// Definition of function allowing to save custon information.
template<>
inline void write_cmap_attribute_node<Volume_info>(boost::property_tree::ptree & node,
const Volume_info& arg)
{
boost::property_tree::ptree & nValue = node.add("v","");
nValue.add("status",(int)arg.m_status);
nValue.add("color-r",(int)arg.m_color.r());
nValue.add("color-g",(int)arg.m_color.g());
nValue.add("color-b",(int)arg.m_color.b());
}
}
class Myitems
{
public:
template < class Refs >
struct Dart_wrapper
struct Dart_wrapper
{
typedef CGAL::Dart<3, Refs > Dart;
typedef CGAL::Cell_attribute_with_point< Refs > Vertex_attrib;
typedef CGAL::Cell_attribute< Refs, Volume_info> Volume_attrib;
typedef CGAL::cpp11::tuple<Vertex_attrib,void,void,
Volume_attrib> Attributes;
};
@ -124,6 +175,22 @@ typedef LCC::Vector Vector_3;
typedef CGAL::Timer Timer;
typedef CGAL::Triangulation_2_filtered_projection_traits_3<Mytraits> P_traits;
typedef CGAL::Triangulation_vertex_base_with_info_2<Dart_handle,P_traits> Vb;
struct Face_info {
bool exist_edge[3];
bool is_external;
};
typedef CGAL::Triangulation_face_base_with_info_2<Face_info,P_traits> Fb1;
typedef CGAL::Constrained_triangulation_face_base_2<P_traits, Fb1> Fb;
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
typedef CGAL::No_intersection_tag Itag;
typedef CGAL::Constrained_Delaunay_triangulation_2<P_traits, TDS,
Itag> CDT;
struct Scene {
LCC* lcc;
};

View File

@ -21,7 +21,7 @@ LC_CTYPE=en_US.UTF-8
# "master" alone
0 21 * * Sun cd $HOME/CGAL/create_internal_release && $HOME/bin/create_release $HOME/CGAL/branches/master.git --public --do-it
# "integration"
0 21 * * Mon,Tue,Wed,Thu,Fri cd $HOME/CGAL/create_internal_release && $HOME/bin/create_release $HOME/CGAL/branches/integration.git $HOME/CGAL/branches/empty-dir --do-it --public
0 21 * * Mon,Tue,Wed,Thu,Fri cd $HOME/CGAL/create_internal_release && $HOME/bin/create_release $HOME/CGAL/branches/integration.git $HOME/CGAL/branches/empty-dir --do-it
# from branch 4.6
0 21 * * Sat cd $HOME/CGAL/create_internal_release-4.6-branch && $HOME/bin/create_release $HOME/CGAL/branches/CGAL-4.6-branch.git --public --do-it
# from branch 4.5

View File

@ -1,28 +1,41 @@
Subject: CGAL 4.7 Beta 1 Released, Computational Geometry Algorithms Library
Subject: CGAL 4.7 Beta 2 Released, Computational Geometry Algorithms Library
Content-Type: text/plain; charset="utf-8"
Body:
The CGAL Open Source Project is pleased to announce the release 4.7 Beta 1
The CGAL Open Source Project is pleased to announce the release 4.7 Beta 2
of CGAL, the Computational Geometry Algorithms Library.
CGAL version 4.7 Beta 1 is a public testing release. It should provide
CGAL version 4.7 Beta 2 is a public testing release. It should provide
a solid ground to report bugs that need to be tackled before the
release of the final version of CGAL 4.7 in September.
release of the final version of CGAL 4.7 in October.
That is the second "beta" release for CGAL-4.7. The reason is that the
switches from Qt4 to Qt5, and from OpenGL 1 to modern OpenGL with shaders,
were not as smooth as we hopped. A lot of bugs have been fixed in the Qt5
demos since CGAL-4.7-beta1.
You can find the detailed description of all changes here on Github:
https://github.com/CGAL/cgal/issues?q=milestone%3A4.7-beta2
Besides fixes to existing packages, the following has changed since
CGAL 4.6:
As a reminder, you can find below the major changes since CGAL 4.6:
o Installation
- The minimum required version of CMake is now 2.8.11. CMake versions 3.1,
3.2, and 3.3 are supported.
- The minimum required version of CMake is now 2.8.11. CMake versions
3.1, 3.2, and 3.3 are supported.
- All Qt4 demos have been updated and now require Qt5 to be
compiled. Qt5 version 5.3 or higher is required. The support for Qt4
is dropped. The code of the 3D demos now use modern OpenGL, with
shaders, instead of the fixed pipeline API of OpenGL-1.
- The Microsoft Windows Visual C++ compiler 2015 (VC14) is now
supported. However, since this compiler is not officially supported
by Intel TBB 4.4 and Qt 5.5 (the latest versions available at the
time of this release), the parallelism features of CGAL and Qt5 demos
will not work.
o Advancing Front Surface Reconstruction (new package)
@ -89,104 +102,6 @@ CGAL 4.6:
of a point within polygonal regions in two dimensions.
See http://www.cgal.org/releases.html for a complete list of changes.
The CGAL project is a collaborative effort to develop a robust,
easy-to-use, and efficient C++ software library of geometric data
structures and algorithms, like
- triangulations (2D constrained triangulations, Delaunay triangulations
and periodic triangulations in 2D and 3D),The CGAL Open Source Project is pleased to announce the release 4.7 Beta 1
of CGAL, the Computational Geometry Algorithms Library.
CGAL version 4.7 Beta 1 is a public testing release. It should provide
a solid ground to report bugs that need to be tackled before the
release of the final version of CGAL 4.7 in September.
Besides fixes to existing packages, the following has changed since
CGAL 4.6:
o Installation
- The minimum required version of CMake is now 2.8.11. CMake versions 3.1,
3.2, and 3.3 are supported.
- All Qt4 demos have been updated and now require Qt5 to be
compiled. Qt5 version 5.3 or higher is required. The support for Qt4
is dropped. The code of the 3D demos now use modern OpenGL, with
shaders, instead of the fixed pipeline API of OpenGL-1.
o Advancing Front Surface Reconstruction (new package)
This package provides a greedy algorithm for surface reconstruction
from an unorganized point set. Starting from a seed facet, a piecewise
linear surface is grown by adding Delaunay triangles one by one. The
most plausible triangles are added first, in a way that avoids the
appearance of topological singularities.
o Triangulated Surface Mesh Shortest Paths (new package)
The package provides methods for computing shortest path on
triangulated surface meshes. Given a set of source points on the
surface, this package provides a data structure that can efficiently
provides the shortest path from any point on the surface to the sources
points. There is no restriction on the genus or the number of
connected components of the mesh.
o Triangulated Surface Mesh Skeletonization (new package)
This package provides a (1D) curve skeleton extraction algorithm for a
triangulated polygonal mesh without borders based on the mean curvature
flow. The particularity of this skeleton is that it captures the
topology of the input. For each skeleton vertex one can obtain its
location and its corresponding vertices from the input mesh. The code
is generic and works with any model of the `FaceListGraph` concept.
o Polygon Mesh Processing (new package)
This package implements a collection of methods and classes for polygon
mesh processing, ranging from basic operations on simplices, to complex
geometry processing algorithms. The implementation of this package
mainly follows algorithms and references given in Botsch et al.'s book
on polygon mesh processing.
o 3D Point-Set Shape Detection (new package)
This package implements the efficient RANSAC method for shape
detection, contributed by Schnabel et al. From an unstructured point
set with unoriented normals, the algorithm detects a set of
shapes. Five types of primitive shapes are provided by this package:
plane, sphere, cylinder, cone and torus. Detecting other types of
shapes is possible by implementing a class derived from a base shape.
o L Infinity Segment Delaunay Graphs (new package)
The package provides the geometric traits for constructing the segment
Delaunay graph in the max-norm (L Infinity). The traits also contain
methods to draw the edges of the dual of the segment Delaunay graph in
the max-norm i.e., the segment Voronoi diagram in the max-norm. The
algorithm and traits rely on the segment Delaunay graph algorithm and
traits under the Euclidean distance. The segment Voronoi diagram in the
max-norm has applications in VLSI CAD.
o 2D Visibility (new package)
This package provides several variants to compute the visibility area
of a point within polygonal regions in two dimensions.
See http://www.cgal.org/releases.html for a complete list of changes.
@ -217,40 +132,6 @@ structures and algorithms, like
Some modules are distributed under the terms of the LGPL Open Source
license (GNU Lesser General Public License v3 or later versions).
Most modules are distributed under the terms of the GPL Open Source
license (GNU General Public License v3 or later versions).
If your intended usage does not meet the criteria of the
aforementioned licenses, a commercial license can be purchased from
GeometryFactory (http://www.geometryfactory.com/).
For further information and for downloading the library and its
documentation, please visit the CGAL web site: http://www.cgal.org/
- Voronoi diagrams (for 2D and 3D points, 2D additively weighted
Voronoi diagrams, and segment Voronoi diagrams),
- Boolean operations on polygons and polyhedra,
- regularized Boolean operations on polygons with curved arcs
- arrangements of curves,
- mesh generation (2D, 3D and surface mesh generation,
surface mesh subdivision and parametrization),
- alpha shapes (in 2D and 3D),
- convex hull algorithms (in 2D, 3D and dD),
- operations on polygons (straight skeleton and offset polygon),
- search structures (kd trees for nearest neighbor search, and
range and segment trees),
- interpolation (natural neighbor interpolation and placement of
streamlines),
- optimization algorithms (smallest enclosing sphere of points or
spheres, smallest enclosing ellipsoid of points, principal
component analysis),
- kinetic data structures
Some modules are distributed under the terms of the LGPL Open Source
license (GNU Lesser General Public License v3 or later versions).
Most modules are distributed under the terms of the GPL Open Source

View File

@ -1,15 +1,21 @@
Subject: CGAL 4.6.2 Released, Computational Geometry Algorithms Library
Subject: CGAL 4.6.3 Released, Computational Geometry Algorithms Library
From: Laurent Rineau <laurent.rineau@cgal.org>
Content-Type: text/plain; charset="utf-8"
Body:
The CGAL Open Source Project is pleased to announce the release 4.6.2
The CGAL Open Source Project is pleased to announce the release 4.6.3
of CGAL, the Computational Geometry Algorithms Library.
Version 4.6.2 is a bug-fix release for version 4.6. The list of fixed bugs
Version 4.6.3 is a bug-fix release for version 4.6. The list of fixed bugs
can be seen Github:
- fixed in CGAL-4.6.2:
- fixed in CGAL-4.6.3:
https://github.com/CGAL/cgal/issues?q=milestone%3A4.6.3
- fixed earlier in CGAL-4.6.2:
https://github.com/CGAL/cgal/issues?q=milestone%3A4.6.2

View File

@ -58,7 +58,15 @@ rm -rf Surface_modeling_Demo
# Demo not announced in the CGAL manual, from CGAL-3.8:
rm -rf Circular_kernel_3_Demo
# CGAL-4.6
pushd Polyline_simplification_2_Demo; zip ../polyline_simplification_2.zip *; popd
# CGAL-4.7
pushd Segment_Delaunay_graph_Linf_2_Demo; zip ../segment_voronoi_diagram_2.zip *; popd
# check
echo CHECK now
echo CHECK now. The following lines should be empty.
for f in *zip; do unzip -qql $f; done | awk '{print $4}' >| done
for f in */**/*(.); do grep -qF ${f:t} done || ls $f; done
echo

View File

@ -1 +1 @@
7
8

View File

@ -1 +1 @@
CGAL-4.7-beta2
CGAL-4.8-dev

View File

@ -62,13 +62,13 @@ if ( CGAL_FOUND )
create_single_source_cgal_program( "mesh_polyhedral_domain.cpp" )
create_single_source_cgal_program( "mesh_polyhedral_domain_with_features.cpp" )
if( WITH_CGAL_ImageIO )
create_single_source_cgal_program( "mesh_optimization_example.cpp" )
create_single_source_cgal_program( "mesh_optimization_lloyd_example.cpp" )
if( CGAL_ImageIO_USE_ZLIB )
create_single_source_cgal_program( "mesh_optimization_example.cpp" )
create_single_source_cgal_program( "mesh_optimization_lloyd_example.cpp" )
create_single_source_cgal_program( "mesh_3D_image.cpp" )
create_single_source_cgal_program( "mesh_3D_image_variable_size.cpp" )
else()
message( STATUS "NOTICE: The examples mesh_3D_image.cpp and mesh_3D_image_variable_size.cpp need CGAL_ImageIO to be configured with ZLIB support, and will not be compiled." )
message( STATUS "NOTICE: The examples mesh_3D_image.cpp, mesh_3D_image_variable_size.cpp, mesh_optimization_example.cpp and mesh_optimization_lloyd_example.cpp need CGAL_ImageIO to be configured with ZLIB support, and will not be compiled." )
endif()
else()
message( STATUS "NOTICE: Some examples need the CGAL_ImageIO library, and will not be compiled." )

View File

@ -173,7 +173,7 @@ public:
Implicit_multi_domain_to_labeling_function_wrapper (const Function_vector& vf, const std::vector<std::vector<Sign> >& vps)
: funcs(vf), bmasks(vps.size(), Bmask(funcs.size() * 2, false))
{
assert(funcs.size());
CGAL_assertion(funcs.size() != 0);
std::size_t mask_index = 0;
for (std::vector<std::vector<Sign> >::const_iterator mask_iter = vps.begin(), mask_end_iter = vps.end();
@ -181,14 +181,14 @@ public:
++mask_iter)
{
const std::vector<Sign>& mask = *mask_iter;
assert(funcs.size() == mask.size());
CGAL_assertion(funcs.size() == mask.size());
Bmask& bmask = bmasks[mask_index++];
typename Bmask::size_type bit_index = 0;
for (std::vector<Sign>::const_iterator iter = mask.begin(), endIter = mask.end(); iter != endIter; ++iter)
{
std::string::value_type character = *iter;
assert(character == POSITIVE || character == NEGATIVE);
CGAL_assertion(character == POSITIVE || character == NEGATIVE);
bmask[bit_index] = (character == POSITIVE);
++bit_index;
@ -202,7 +202,7 @@ public:
Implicit_multi_domain_to_labeling_function_wrapper (const Function_vector& vf)
: funcs(vf)
{
assert(funcs.size());
CGAL_assertion(funcs.size() != 0);
bmasks.reserve((1 << funcs.size()) - 1);
bmasks.push_back(Bmask(std::string("10")));
@ -228,7 +228,7 @@ public:
Implicit_multi_domain_to_labeling_function_wrapper (const Function_vector& vf, const std::vector<std::string>& vps)
: funcs(vf), bmasks(vps.size(), Bmask(funcs.size() * 2, false))
{
assert(funcs.size());
CGAL_assertion(funcs.size() != 0);
std::size_t mask_index = 0;
for (std::vector<std::string>::const_iterator mask_iter = vps.begin(), mask_end_iter = vps.end();
@ -236,14 +236,14 @@ public:
++mask_iter)
{
const std::string& mask_str = *mask_iter;
assert(funcs.size() == mask_str.length());
CGAL_assertion(funcs.size() == mask_str.length());
Bmask& bmask = bmasks[mask_index++];
typename Bmask::size_type bit_index = 0;
for (std::string::const_iterator iter = mask_str.begin(), endIter = mask_str.end(); iter != endIter; ++iter)
{
std::string::value_type character = *iter;
assert(character == '+' || character == '-');
CGAL_assertion(character == '+' || character == '-');
bmask[bit_index] = (character == '+');
++bit_index;

View File

@ -1162,7 +1162,7 @@ private:
Subdomain operator()(const Cell_handle& ch, const bool update = true) const
{
if ( c3t3_.triangulation().is_infinite(ch) )
return false;
return Subdomain();
// treat cell
const Subdomain subdomain =

View File

@ -1185,7 +1185,7 @@ public:
/*!
creates a Nef polyhedron consisting of a single polygon
spanned by the list of points in the iterator range
`[begin,end)`. If the points do not on a common
`[begin,end)`. If the points do not lie on a common
supporting plane, the constructor tries to triangulate
the polygon into multiple facets.If the construction does
not succeed, the empty set is created.
@ -1193,8 +1193,10 @@ public:
Nef_polyhedron_3(Input_iterator begin, Input_iterator end);
/*!
The iterator range [it, end) defines a set point
ranges, each of which defines a polyline.
creates a Nef polyhedron consisting of polylines.
The iterator range [it, end) defines a range of polylines.
Each polyline is defined as a range of points, first and
past-the-end iterators being provided as a `std::pair` of iterators.
*/
template <class Forward_iterator>
Nef_polyhedron_3(Forward_iterator it, Forward_iterator end,

View File

@ -483,7 +483,7 @@ struct Mpzf {
}
#endif
if(u.s.sig) size=-size;
//assert(to_double()==IA_force_to_double(d));
//CGAL_assertion(to_double()==IA_force_to_double(d));
}
#ifdef CGAL_USE_GMPXX

View File

@ -27,6 +27,7 @@
#include <CGAL/convert_to_bfi.h>
#include <CGAL/Coercion_traits.h>
#include <CGAL/Sqrt_extension/Sqrt_extension_type.h>
#include <CGAL/assertions.h>
// Disbale SQRT_EXTENSION_TO_BFI_CACHE by default
@ -92,8 +93,8 @@ convert_to_bfi(const CGAL::Sqrt_extension<NT,ROOT,ACDE_TAG,FP_TAG>& x) {
}else{
result_ = convert_to_bfi(x.a0());
}
assert(lower(result) == lower(result_));
assert(upper(result) == upper(result_));
CGAL_assertion(lower(result) == lower(result_));
CGAL_assertion(upper(result) == upper(result_));
#endif
return result;
}

View File

@ -1396,7 +1396,7 @@ class Intersection_of_Polyhedra_3{
switch(type){
case internal_IOP::COPLNR:
#ifndef DO_NOT_HANDLE_COPLANAR_FACETS
assert(!"COPLNR : this point should never be reached!");
CGAL_assertion(!"COPLANR : this point should never be reached!");
#else
//nothing need to be done, cf. comments at the beginning of the file
#endif

View File

@ -29,7 +29,7 @@
\cgalPkgShortInfoBegin
\cgalPkgSince{4.3}
\cgalPkgDependsOn{\ref PkgTDS2Summary and \ref PkgTriangulation2Summary}
\cgalPkgDependsOn{\ref PkgTriangulation2Summary}
\cgalPkgBib{cgal:k-pt2-13}
\cgalPkgLicense{\ref licensesGPL "GPL"}
\cgalPkgDemo{Periodic Delaunay Triangulation,Periodic_2_Delaunay_triangulation_2.zip}

View File

@ -23,7 +23,7 @@
\cgalPkgSummaryEnd
\cgalPkgShortInfoBegin
\cgalPkgSince{3.5}
\cgalPkgDependsOn{\ref PkgTriangulation3Summary and \ref PkgTDS3Summary}
\cgalPkgDependsOn{\ref PkgTDS3Summary}
\cgalPkgBib{cgal:ct-pt3}
\cgalPkgLicense{\ref licensesGPL "GPL"}
\cgalPkgDemo{3D Periodic Delaunay Triangulation,periodic_3_triangulation_3.zip,3D Periodic Lloyd,periodic_3_lloyd.zip}

View File

@ -46,7 +46,7 @@ namespace CGAL {
///
/// @tparam ForwardIterator iterator over input points.
/// @tparam PointPMap is a model of `ReadablePropertyMap` with a value type = `Point_3<Kernel>`.
/// It can be omitted if the value type of `ForwardIterator value_type is convertible to `Point_3<Kernel>`.
/// It can be omitted if the value type of `ForwardIterator` is convertible to `Point_3<Kernel>`.
/// @tparam NormalPMap is a model of `ReadablePropertyMap` with a value type `Vector_3<Kernel>`.
/// @tparam Kernel Geometric traits class.
/// It can be omitted and deduced automatically from the value type of `PointPMap`.

View File

@ -449,9 +449,9 @@ bilateral_smooth_point_set(
CGAL_point_set_processing_precondition(n.squared_length() > 1e-10);
pwns.push_back(Pwn(p, n));
}
}
unsigned int nb_points = pwns.size();
std::size_t nb_points = pwns.size();
#ifdef CGAL_PSP3_VERBOSE
std::cout << "Initialization and compute max spacing: " << std::endl;

View File

@ -153,7 +153,7 @@ update_new_point(
typedef typename Kernel::FT FT;
typedef typename rich_grid_internal::Rich_point<Kernel> Rich_point;
CGAL_assertion_code( unsigned int size = rich_point_set.size() );
CGAL_assertion_code( unsigned int size = static_cast<unsigned int>(rich_point_set.size()) );
CGAL_point_set_processing_precondition(father_index >= 0 &&
father_index < size);
CGAL_point_set_processing_precondition(mother_index >= 0 &&
@ -431,7 +431,7 @@ edge_aware_upsample_point_set(
std::cout << "current radius: " << current_radius << std::endl;
#endif
unsigned int current_size = rich_point_set.size();
std::size_t current_size = rich_point_set.size();
std::vector<bool> is_pass_threshold(current_size, false);
if (iter_time == 0)
@ -533,7 +533,7 @@ edge_aware_upsample_point_set(
Rich_point& base = rich_point_set[mother_index];
Vector diff_v_base = base.pt - v.pt;
new_v.pt = v.pt + (diff_v_base * FT(0.5));
new_v.index = rich_point_set.size();
new_v.index = static_cast<unsigned int>(rich_point_set.size());
unsigned int new_point_index = new_v.index;
rich_point_set.push_back(new_v);
@ -570,7 +570,7 @@ edge_aware_upsample_point_set(
}
}
for (unsigned int i = number_of_input; i < rich_point_set.size(); ++i)
for (std::size_t i = number_of_input; i < rich_point_set.size(); ++i)
{
Rich_point& v = rich_point_set[i];
Point point = v.pt;

View File

@ -28,7 +28,7 @@ ranging from basic operations on simplices, to complex geometry processing algor
\cgalPkgShortInfoBegin
\cgalPkgSince{4.7}
\cgalPkgDependsOn{\ref PkgTriangulation3Summary, Sparse square solver such as those from \ref thirdpartyEigen}
\cgalPkgDependsOn{documented for each function; Sparse square solver such as those from \ref thirdpartyEigen}
\cgalPkgBib{cgal:lty-pmp}
\cgalPkgLicense{\ref licensesGPL "GPL"}
\cgalPkgDemo{Operations on Polyhedra,polyhedron_3.zip}
@ -72,6 +72,7 @@ and provides a list of the parameters that are used in this package.
- \link stitching_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
- `CGAL::Polygon_mesh_processing::remove_isolated_vertices()`
@ -99,4 +100,6 @@ It can be made short to PM. And TriangleMesh (or TM) specifies when the paramete
\todo document `BGL/include/CGAL/boost/graph/split_graph_into_polylines.h`
\todo add in BGL `clear(pmesh)` and use it in `keep_largest_connected_components(pmesh, 0);`
\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`
*/

View File

@ -270,6 +270,7 @@ with duplicated border edges.
\cgalExample{Polygon_mesh_processing/stitch_borders_example.cpp}
*******************
<!---
\subsection DegenerateFaces Removing Degenerate Faces
Some degenerate faces may be part of a given triangle mesh.
@ -289,7 +290,7 @@ are removed, the connectivity is fixed, and the number of removed faces
is output.
\cgalExample{Polygon_mesh_processing/remove_degeneracies_example.cpp}
--->
*******************
\subsection PolygonSoups Polygon Soups
@ -457,7 +458,6 @@ 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_degenerate_faces()` | yes | no | no
`remove_isolated_vertices()` | no | no | no
`compute_face_normal()` | no | no | no
`compute_face_normals()` | no | no | no
@ -471,6 +471,9 @@ Function or Class | Pure Triangle | Self-Intersection Free
`keep_connected_components()` | no | no | no
`remove_connected_components()` | no | no | no
</center>
<!---
`remove_degenerate_faces()` | yes | no | no
--->
****************************************
\section PMPHistory Implementation History

View File

@ -11,6 +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/remove_degeneracies_example.cpp
*/

View File

@ -0,0 +1,2 @@
examples/Polygon_mesh_processing/remove_degeneracies_example.cpp
examples/Polygon_mesh_processing/remove_degeneracies_example_OM.cpp

View File

@ -81,7 +81,7 @@ create_single_source_cgal_program( "connected_components_example.cpp")
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( "remove_degeneracies_example.cpp")
create_single_source_cgal_program( "isotropic_remeshing_example.cpp")
if(NOT (${EIGEN3_VERSION} VERSION_LESS 3.2.0))
@ -105,8 +105,8 @@ target_link_libraries( point_inside_example_OM ${OPENMESH_LIBRARIES} )
create_single_source_cgal_program( "stitch_borders_example_OM.cpp" )
target_link_libraries( stitch_borders_example_OM ${OPENMESH_LIBRARIES} )
create_single_source_cgal_program( "remove_degeneracies_example_OM.cpp")
target_link_libraries( remove_degeneracies_example_OM ${OPENMESH_LIBRARIES} )
#create_single_source_cgal_program( "remove_degeneracies_example_OM.cpp")
#target_link_libraries( remove_degeneracies_example_OM ${OPENMESH_LIBRARIES} )
create_single_source_cgal_program( "triangulate_faces_example_OM.cpp")
target_link_libraries( triangulate_faces_example_OM ${OPENMESH_LIBRARIES} )

View File

@ -32,6 +32,7 @@
#include <CGAL/boost/graph/iterator.h>
#include <CGAL/boost/graph/helpers.h>
#include <CGAL/assertions.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/Polyhedron_incremental_builder_3.h>
#include <CGAL/Union_find.h>
@ -724,7 +725,7 @@ void keep_or_remove_connected_components(PolygonMesh& pmesh
}
else {
// no face kept
assert((is_border(h, pmesh) || !get(fcm,fh)) && (is_border(oh, pmesh) || !get(fcm,ofh)));
CGAL_assertion((is_border(h, pmesh) || !get(fcm,fh)) && (is_border(oh, pmesh) || !get(fcm,ofh)));
// vertices pointing to e must change their halfedge
if (halfedge(v, pmesh) == oh){
set_halfedge(v, prev(h, pmesh), pmesh);
@ -746,7 +747,7 @@ void keep_or_remove_connected_components(PolygonMesh& pmesh
remove_edge(e, pmesh);
}
else {
assert(keep_vertex[w]);
CGAL_assertion(keep_vertex[w]);
if (halfedge(w, pmesh) == h){
set_halfedge(w, prev(oh, pmesh), pmesh);
}

View File

@ -14,7 +14,7 @@
//
// $URL$
// $Id$
//
//
//
// Author(s) : Laurent Rineau and Ilker O. Yaz
@ -91,6 +91,42 @@ public:
};
}//end namespace internal
/// \cond SKIP_IN_MANUAL
/**
* \ingroup PkgPolygonMeshProcessing
* returns `true` if the soup of polygons defines a valid polygon mesh
* that can be handled by `CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh()`.
*
* @tparam Polygon a `std::vector<std::size_t>` containing the indices
* of the points of the polygon face
*
* @param polygons each element in the vector describes a polygon using the index of the vertices
*
*/
template<class Polygon>
bool is_polygon_soup_a_polygon_mesh(const std::vector<Polygon>& polygons)
{
typedef typename std::iterator_traits<
typename Polygon::iterator >::value_type V_ID;
std::set< std::pair<V_ID, V_ID> > edge_set;
BOOST_FOREACH(const Polygon& polygon, polygons)
{
std::size_t nb_edges = polygon.size();
if (nb_edges<3) return false;
V_ID prev=polygon.back();
BOOST_FOREACH(V_ID id, polygon)
if (! edge_set.insert(std::pair<V_ID, V_ID>(prev,id)).second )
return false;
else
prev=id;
}
return true;
}
/// \endcond
/**
* \ingroup PkgPolygonMeshProcessing
* builds a polygon mesh from a soup of polygons.

View File

@ -33,6 +33,61 @@
namespace CGAL{
namespace Polygon_mesh_processing {
namespace debug{
template <class TriangleMesh, class VertexPointMap>
std::ostream& dump_edge_neighborhood(
typename boost::graph_traits<TriangleMesh>::edge_descriptor ed,
TriangleMesh& tmesh,
const VertexPointMap& vpmap,
std::ostream& out)
{
typedef boost::graph_traits<TriangleMesh> GT;
typedef typename GT::halfedge_descriptor halfedge_descriptor;
typedef typename GT::vertex_descriptor vertex_descriptor;
typedef typename GT::face_descriptor face_descriptor;
halfedge_descriptor h = halfedge(ed, tmesh);
std::map<vertex_descriptor, int> vertices;
std::set<face_descriptor> faces;
int vindex=0;
BOOST_FOREACH(halfedge_descriptor hd, halfedges_around_target(h, tmesh))
{
if ( vertices.insert(std::make_pair(source(hd, tmesh), vindex)).second )
++vindex;
if (!is_border(hd, tmesh))
faces.insert( face(hd, tmesh) );
}
h=opposite(h, tmesh);
BOOST_FOREACH(halfedge_descriptor hd, halfedges_around_target(h, tmesh))
{
if ( vertices.insert(std::make_pair(source(hd, tmesh), vindex)).second )
++vindex;
if (!is_border(hd, tmesh))
faces.insert( face(hd, tmesh) );
}
std::vector<vertex_descriptor> ordered_vertices(vertices.size());
typedef std::pair<const vertex_descriptor, int> Pair_type;
BOOST_FOREACH(const Pair_type& p, vertices)
ordered_vertices[p.second]=p.first;
out << "OFF\n" << ordered_vertices.size() << " " << faces.size() << " 0\n";
BOOST_FOREACH(vertex_descriptor vd, ordered_vertices)
out << get(vpmap, vd) << "\n";
BOOST_FOREACH(face_descriptor fd, faces)
{
out << "3";
h=halfedge(fd,tmesh);
BOOST_FOREACH(halfedge_descriptor hd, halfedges_around_face(h, tmesh))
out << " " << vertices[target(hd, tmesh)];
out << "\n";
}
return out;
}
} //end of namespace debug
template <class HalfedgeGraph, class VertexPointMap, class Traits>
struct Less_vertex_point{
typedef typename boost::graph_traits<HalfedgeGraph>::vertex_descriptor vertex_descriptor;
@ -87,155 +142,300 @@ bool is_degenerated(
return is_degenerated(halfedge(fd,tmesh), tmesh, vpmap, traits);
}
#if 0
namespace internal {
///\cond SKIP_IN_MANUAL
template <class EdgeRange, class TriangleMesh, class NamedParameters>
std::size_t remove_null_edges(
const EdgeRange& edge_range,
TriangleMesh& tmesh,
const NamedParameters& np)
{
CGAL_assertion(CGAL::is_triangle_mesh(tmesh));
// hbase is an edge of length 0 we cannot contract because
// the link condition is not satisfied.
// In this function we look whether the condition is not
// satisfied because of some faces on the "side" of hbase.
// Here we look for two halfedges that together with hbase
// enclose a set of degenerate faces so as to replace that
// set with only one triangle
template <class Traits, class TriangleMesh, class VertexPointMap>
boost::optional<
std::pair<
typename boost::graph_traits<TriangleMesh>::halfedge_descriptor,
typename boost::graph_traits<TriangleMesh>::halfedge_descriptor >
>
find_larger_triangle(
typename boost::graph_traits<TriangleMesh>::halfedge_descriptor hbase,
TriangleMesh& tmesh,
const VertexPointMap& vpmap,
const Traits& traits)
using boost::choose_const_pmap;
using boost::get_param;
using boost::choose_param;
typedef TriangleMesh TM;
typedef typename boost::graph_traits<TriangleMesh> GT;
typedef typename GT::edge_descriptor edge_descriptor;
typedef typename GT::halfedge_descriptor halfedge_descriptor;
typedef typename GT::face_descriptor face_descriptor;
typedef typename GT::vertex_descriptor vertex_descriptor;
typedef typename GetVertexPointMap<TM, NamedParameters>::type VertexPointMap;
VertexPointMap vpmap = choose_pmap(get_param(np, boost::vertex_point),
tmesh,
boost::vertex_point);
typedef typename GetGeomTraits<TM, NamedParameters>::type Traits;
Traits traits = choose_param(get_param(np, geom_traits), Traits());
std::size_t nb_deg_faces = 0;
// collect edges of length 0
std::set<edge_descriptor> null_edges_to_remove;
BOOST_FOREACH(edge_descriptor ed, edge_range)
{
typedef typename boost::graph_traits<TriangleMesh> GT;
typedef typename GT::halfedge_descriptor halfedge_descriptor;
if ( traits.equal_3_object()(get(vpmap, target(ed, tmesh)), get(vpmap, source(ed, tmesh))) )
null_edges_to_remove.insert(ed);
}
bool no_pb=false;
// hbase = v0 -> v1
// consider hedges with v0 as target
halfedge_descriptor left_hedge = prev(hbase, tmesh), o_right_hedge=left_hedge;
do
while (!null_edges_to_remove.empty())
{
edge_descriptor ed = *null_edges_to_remove.begin();
null_edges_to_remove.erase(null_edges_to_remove.begin());
halfedge_descriptor h = halfedge(ed, tmesh);
if (CGAL::Euler::does_satisfy_link_condition(ed,tmesh))
{
left_hedge = prev( opposite(left_hedge, tmesh), tmesh );
if ( face(left_hedge, tmesh) == GT::null_face() ||
!is_degenerated(left_hedge, tmesh, vpmap, traits) )
// remove edges that could also be set for removal
if ( face(h, tmesh)!=GT::null_face() )
{
no_pb=true;
break;
++nb_deg_faces;
null_edges_to_remove.erase(edge(prev(h, tmesh), tmesh));
}
// look for a halfedge with v1 as target
BOOST_FOREACH(o_right_hedge, halfedges_around_source(left_hedge, tmesh) )
if (face(opposite(h, tmesh), tmesh)!=GT::null_face())
{
if ( target(o_right_hedge, tmesh) == target(hbase, tmesh) )
++nb_deg_faces;
null_edges_to_remove.erase(edge(prev(opposite(h, tmesh), tmesh), tmesh));
}
//now remove the edge
CGAL::Euler::collapse_edge(ed, tmesh);
}
else{
//handle the case when the edge is incident to a triangle hole
//we first fill the hole and try again
if ( is_border(ed, tmesh) )
{
halfedge_descriptor hd = halfedge(ed,tmesh);
if (!is_border(hd,tmesh)) hd=opposite(hd,tmesh);
if (is_triangle(hd, tmesh))
{
if ( !is_degenerated( opposite(o_right_hedge, tmesh), tmesh, vpmap, traits) )
no_pb=true;
break;
Euler::fill_hole(hd, tmesh);
null_edges_to_remove.insert(ed);
continue;
}
}
if ( target(o_right_hedge, tmesh) == target(hbase, tmesh) )
break;
}
while(true);
if (!no_pb)
return std::make_pair(left_hedge, opposite(o_right_hedge, tmesh));
return boost::none;
}
// When the edge does not satisfy the link condition, it means that it cannot be
// collapsed as is. In the following we assume that there is no topological issue
// with contracting the edge (no volume will disappear).
// We start by marking the faces that are incident to an edge endpoint.
// If the set of marked faces is a topologically disk, then we simply remove all the simplicies
// inside the disk and star the hole with the edge vertex kept.
// If the set of marked faces is not a topological disk, it has some non-manifold vertices
// on its boundary. We need to mark additional faces to make it a topological disk.
// We can then apply the star hole procedure.
// Right now we additionally mark the smallest connected components of non-marked faces
// (using the numnber of faces)
// h2 is a halfedge of length 0 but collapsing the edge
// is not directly possible because the link condition is not
// satisfied. We remove all simplices bounded by h1, h2 and h3
// so as to keep only that triangle
template <class TriangleMesh, class EdgeMap>
void
remove_faces_inside_triangle(
typename boost::graph_traits<TriangleMesh>::halfedge_descriptor h1,
typename boost::graph_traits<TriangleMesh>::halfedge_descriptor h2,
typename boost::graph_traits<TriangleMesh>::halfedge_descriptor h3,
TriangleMesh& tmesh,
EdgeMap& edge_map1,
EdgeMap& edge_map2)
{
typedef typename boost::graph_traits<TriangleMesh> GT;
typedef typename GT::edge_descriptor edge_descriptor;
typedef typename GT::halfedge_descriptor halfedge_descriptor;
typedef typename GT::face_descriptor face_descriptor;
typedef typename GT::vertex_descriptor vertex_descriptor;
//backup central point
typename Traits::Point_3 pt = get(vpmap, source(ed, tmesh));
CGAL_assertion( source(h1,tmesh) == target(h3, tmesh) );
CGAL_assertion( source(h2,tmesh) == target(h1, tmesh) );
CGAL_assertion( source(h3,tmesh) == target(h2, tmesh) );
// mark faces of the link of each endpoints of the edge which collapse is not topologically valid
std::set<face_descriptor> marked_faces;
// first endpoint
BOOST_FOREACH( halfedge_descriptor hd, CGAL::halfedges_around_target(halfedge(ed,tmesh), tmesh) )
if (!is_border(hd,tmesh)) marked_faces.insert( face(hd, tmesh) );
// second endpoint
BOOST_FOREACH( halfedge_descriptor hd, CGAL::halfedges_around_target(opposite(halfedge(ed, tmesh), tmesh), tmesh) )
if (!is_border(hd,tmesh)) marked_faces.insert( face(hd, tmesh) );
std::set<face_descriptor> all_faces;
all_faces.insert(face(h1, tmesh));
all_faces.insert(face(h2, tmesh));
all_faces.insert(face(h3, tmesh));
// extract the halfedges on the boundary of the marked region
std::vector<halfedge_descriptor> border;
BOOST_FOREACH(face_descriptor fd, marked_faces)
BOOST_FOREACH(halfedge_descriptor hd, CGAL::halfedges_around_face(halfedge(fd,tmesh), tmesh))
{
halfedge_descriptor hd_opp = opposite(hd, tmesh);
if ( is_border(hd_opp, tmesh) ||
marked_faces.count( face(hd, tmesh) )!=
marked_faces.count( face(hd_opp, tmesh) ) )
{
border.push_back( hd );
}
}
std::vector<halfedge_descriptor> queue;
queue.push_back( opposite(prev(h1,tmesh), tmesh) );
queue.push_back( opposite(next(h1,tmesh), tmesh) );
queue.push_back( opposite(prev(h2,tmesh), tmesh) );
queue.push_back( opposite(next(h2,tmesh), tmesh) );
queue.push_back( opposite(prev(h3,tmesh), tmesh) );
queue.push_back( opposite(next(h3,tmesh), tmesh) );
// define cc of border halfedges: two halfedges are in the same cc
// if they are on the border of the cc of non-marked faces.
typedef CGAL::Union_find<halfedge_descriptor> UF_ds;
UF_ds uf;
std::map<halfedge_descriptor, typename UF_ds::handle> handles;
// one cc per border halfedge
BOOST_FOREACH(halfedge_descriptor hd, border)
handles.insert( std::make_pair(hd, uf.make_set(hd)) );
std::set<edge_descriptor> all_edges;
while(!queue.empty())
{
halfedge_descriptor back=queue.back();
queue.pop_back();
all_edges.insert( edge(back, tmesh) );
if ( all_faces.insert( face(back, tmesh) ).second )
// join cc's
BOOST_FOREACH(halfedge_descriptor hd, border)
{
queue.push_back( opposite(prev(back,tmesh), tmesh) );
queue.push_back( opposite(next(back,tmesh), tmesh) );
CGAL_assertion( marked_faces.count( face( hd, tmesh) ) > 0);
CGAL_assertion( marked_faces.count( face( opposite(hd, tmesh), tmesh) ) == 0 );
halfedge_descriptor candidate = hd;
do{
candidate = prev( opposite(candidate, tmesh), tmesh );
} while( !marked_faces.count( face( opposite(candidate, tmesh), tmesh) ) );
uf.unify_sets( handles[hd], handles[opposite(candidate, tmesh)] );
}
}
std::set<vertex_descriptor> all_vertices;
BOOST_FOREACH(edge_descriptor ed, all_edges)
{
all_vertices.insert( source(ed, tmesh) );
all_vertices.insert( target(ed, tmesh) );
}
all_vertices.erase( target(h1, tmesh) );
all_vertices.erase( target(h2, tmesh) );
all_vertices.erase( target(h3, tmesh) );
std::size_t nb_cc = uf.number_of_sets();
if ( nb_cc != 1 )
{
// if more than one connected component is found then the patch
// made of marked faces contains "non-manifold" vertices.
// The smallest components need to be marked so that the patch
// made of marked faces is a topological disk
// create the triangle
face_descriptor remaining_face = *all_faces.begin();
all_faces.erase(all_faces.begin());
// update next-prev pointers
set_next(h1, h2, tmesh);
set_next(h2, h3, tmesh);
set_next(h3, h1, tmesh);
// update vertex pointers
set_halfedge(target(h1,tmesh), h1, tmesh);
set_halfedge(target(h2,tmesh), h2, tmesh);
set_halfedge(target(h3,tmesh), h3, tmesh);
// update face-halfedge pointers
set_face(h1, remaining_face, tmesh);
set_face(h2, remaining_face, tmesh);
set_face(h3, remaining_face, tmesh);
set_halfedge(remaining_face, h2, tmesh);
// we will explore in parallel the connected components and will stop
// when all but one connected component have been entirely explored.
// We add one face at a time for each cc in order to not explore a
// potentially very large cc.
std::vector< std::vector<halfedge_descriptor> > stacks_per_cc(nb_cc);
std::vector< std::set<face_descriptor> > faces_per_cc(nb_cc);
std::vector< bool > exploration_finished(nb_cc, false);
// remove interior simplices
BOOST_FOREACH(edge_descriptor ed, all_edges){
edge_map1.erase(ed);
edge_map2.erase(ed);
remove_edge(ed, tmesh);
// init the stacks of halfedges using the cc of the boundary
std::size_t index=0;
std::map< halfedge_descriptor, std::size_t > ccs;
typedef std::pair<const halfedge_descriptor, typename UF_ds::handle> Pair_type;
BOOST_FOREACH(Pair_type p, handles)
{
halfedge_descriptor opp_hedge = opposite(p.first, tmesh);
if (is_border(opp_hedge, tmesh)) continue; // nothing to do on the boundary
typedef typename std::map< halfedge_descriptor, std::size_t >::iterator Map_it;
std::pair<Map_it, bool> insert_res=
ccs.insert( std::make_pair(*uf.find( p.second ), index) );
if (insert_res.second) ++index;
stacks_per_cc[ insert_res.first->second ].push_back( prev(opp_hedge, tmesh) );
stacks_per_cc[ insert_res.first->second ].push_back( next(opp_hedge, tmesh) );
faces_per_cc[ insert_res.first->second ].insert( face(opp_hedge, tmesh) );
}
std::size_t nb_ccs_to_be_explored = nb_cc;
index=0;
//explore the cc's
do{
// try to extract one more face for a given cc
do{
CGAL_assertion( !exploration_finished[index] );
halfedge_descriptor hd = stacks_per_cc[index].back();
stacks_per_cc[index].pop_back();
hd = opposite(hd, tmesh);
if ( !is_border(hd,tmesh) && !marked_faces.count(face(hd, tmesh) ) )
{
if ( faces_per_cc[index].insert( face(hd, tmesh) ).second )
{
stacks_per_cc[index].push_back( next(hd, tmesh) );
stacks_per_cc[index].push_back( prev(hd, tmesh) );
break;
}
}
if (stacks_per_cc[index].empty()) break;
}
while(true);
// the exploration of a cc is finished when its stack is empty
exploration_finished[index]=stacks_per_cc[index].empty();
if ( exploration_finished[index] ) --nb_ccs_to_be_explored;
if ( nb_ccs_to_be_explored==1 ) break;
while ( exploration_finished[(++index)%nb_cc] );
index=index%nb_cc;
}while(true);
/// \todo use the area criteria? this means maybe continue exploration of larger cc
// mark faces of completetly explored cc
for (index=0; index< nb_cc; ++index)
if( exploration_finished[index] )
{
BOOST_FOREACH(face_descriptor fd, faces_per_cc[index])
marked_faces.insert(fd);
}
}
// collect simplices to be removed
std::set<vertex_descriptor> vertices_to_keep;
std::set<halfedge_descriptor> halfedges_to_keep;
BOOST_FOREACH(halfedge_descriptor hd, border)
if ( !marked_faces.count(face(opposite(hd, tmesh), tmesh)) )
{
halfedges_to_keep.insert( hd );
vertices_to_keep.insert( target(hd, tmesh) );
}
// backup next,prev relationships to set after patch removal
std::vector< std::pair<halfedge_descriptor, halfedge_descriptor> > next_prev_halfedge_pairs;
halfedge_descriptor first_border_hd=*( halfedges_to_keep.begin() );
halfedge_descriptor current_border_hd=first_border_hd;
do{
halfedge_descriptor prev_border_hd=current_border_hd;
current_border_hd=next(current_border_hd, tmesh);
while( marked_faces.count( face( opposite(current_border_hd, tmesh), tmesh) ) )
current_border_hd=next(opposite(current_border_hd, tmesh), tmesh);
next_prev_halfedge_pairs.push_back( std::make_pair(prev_border_hd, current_border_hd) );
}while(current_border_hd!=first_border_hd);
// collect vertices and edges to remove and do remove faces
std::set<edge_descriptor> edges_to_remove;
std::set<vertex_descriptor> vertices_to_remove;
BOOST_FOREACH(face_descriptor fd, marked_faces)
{
halfedge_descriptor hd=halfedge(fd, tmesh);
for(int i=0; i<3; ++i)
{
if ( !halfedges_to_keep.count(hd) )
edges_to_remove.insert( edge(hd, tmesh) );
if ( !vertices_to_keep.count(target(hd,tmesh)) )
vertices_to_remove.insert( target(hd,tmesh) );
hd=next(hd, tmesh);
}
remove_face(fd, tmesh);
}
// remove vertices
BOOST_FOREACH(vertex_descriptor vd, vertices_to_remove)
remove_vertex(vd, tmesh);
// remove edges
BOOST_FOREACH(edge_descriptor ed, edges_to_remove)
{
null_edges_to_remove.erase(ed);
remove_edge(ed, tmesh);
}
// add a new face, set all border edges pointing to it
// and update halfedge vertex of patch boundary vertices
face_descriptor new_face = add_face(tmesh);
typedef std::pair<halfedge_descriptor, halfedge_descriptor> Pair_type;
BOOST_FOREACH(const Pair_type& p, next_prev_halfedge_pairs)
{
set_face(p.first, new_face, tmesh);
set_next(p.first, p.second, tmesh);
set_halfedge(target(p.first, tmesh), p.first, tmesh);
}
set_halfedge(new_face, first_border_hd, tmesh);
// triangulate the new face and update the coordinate of the central vertex
halfedge_descriptor new_hd=Euler::add_center_vertex(first_border_hd, tmesh);
put(vpmap, target(new_hd, tmesh), pt);
BOOST_FOREACH(halfedge_descriptor hd, halfedges_around_target(new_hd, tmesh))
if ( traits.equal_3_object()(get(vpmap, target(hd, tmesh)), get(vpmap, source(hd, tmesh))) )
null_edges_to_remove.insert(edge(hd, tmesh));
CGAL_assertion( is_valid(tmesh) );
}
BOOST_FOREACH(vertex_descriptor vd, all_vertices)
remove_vertex(vd, tmesh);
BOOST_FOREACH(face_descriptor fd, all_faces)
remove_face(fd, tmesh);
}
} // end of namespace internal
#endif
return nb_deg_faces;
}
template <class EdgeRange, class TriangleMesh>
std::size_t remove_null_edges(
const EdgeRange& edge_range,
TriangleMesh& tmesh)
{
return remove_null_edges(edge_range, tmesh,
parameters::all_default());
}
/// \ingroup PkgPolygonMeshProcessing
/// removes the degenerate faces from a triangulated surface mesh.
@ -266,7 +466,7 @@ namespace internal {
/// \cgalNamedParamsEnd
///
/// \return number of removed degenerate faces
///
/// \endcond
template <class TriangleMesh, class NamedParameters>
std::size_t remove_degenerate_faces(TriangleMesh& tmesh,
const NamedParameters& np)
@ -291,286 +491,10 @@ std::size_t remove_degenerate_faces(TriangleMesh& tmesh,
typedef typename GetGeomTraits<TM, NamedParameters>::type Traits;
Traits traits = choose_param(get_param(np, geom_traits), Traits());
std::size_t nb_deg_faces = 0;
// First remove edges of length 0
std::set<edge_descriptor> null_edges_to_remove;
std::size_t nb_deg_faces = remove_null_edges(edges(tmesh), tmesh, np);
BOOST_FOREACH(edge_descriptor ed, edges(tmesh))
{
if ( traits.equal_3_object()(get(vpmap, target(ed, tmesh)), get(vpmap, source(ed, tmesh))) )
null_edges_to_remove.insert(ed);
}
std::size_t nb_edges_previously_skipped = 0;
do{
std::set<edge_descriptor> edges_to_remove_skipped;
while (!null_edges_to_remove.empty())
{
edge_descriptor ed = *null_edges_to_remove.begin();
null_edges_to_remove.erase(null_edges_to_remove.begin());
halfedge_descriptor h = halfedge(ed, tmesh);
if (CGAL::Euler::does_satisfy_link_condition(ed,tmesh))
{
// remove edges that could also be set for removal
if ( face(h, tmesh)!=GT::null_face() )
{
++nb_deg_faces;
null_edges_to_remove.erase(edge(prev(h, tmesh), tmesh));
edges_to_remove_skipped.erase(edge(prev(h, tmesh), tmesh));
}
if (face(opposite(h, tmesh), tmesh)!=GT::null_face())
{
++nb_deg_faces;
null_edges_to_remove.erase(edge(prev(opposite(h, tmesh), tmesh), tmesh));
edges_to_remove_skipped.erase(edge(prev(opposite(h, tmesh), tmesh), tmesh));
}
//now remove the edge
CGAL::Euler::collapse_edge(ed, tmesh);
}
else{
//backup central point
typename Traits::Point_3 pt = get(vpmap, source(ed, tmesh));
// mark faces of the link of each endpoints of the edge which collapse is not topologically valid
std::set<face_descriptor> marked_faces;
std::vector<halfedge_descriptor> candidate_border;
// first endpoint
BOOST_FOREACH( halfedge_descriptor hd, CGAL::halfedges_around_target(halfedge(ed,tmesh), tmesh) )
{
marked_faces.insert( face(hd, tmesh) );
candidate_border.push_back( prev(hd, tmesh) );
}
// second endpoint
BOOST_FOREACH( halfedge_descriptor hd, CGAL::halfedges_around_target(opposite(halfedge(ed, tmesh), tmesh), tmesh) )
{
marked_faces.insert( face(hd, tmesh) );
candidate_border.push_back( prev(hd, tmesh) );
}
// extract the halfedge on the boundary of the marked region
std::vector<halfedge_descriptor> border;
BOOST_FOREACH(halfedge_descriptor hd, candidate_border)
{
if ( marked_faces.count( face(hd, tmesh) )!=
marked_faces.count( face(opposite(hd, tmesh), tmesh) ) )
{
border.push_back( hd );
}
}
// define cc of border halfedges: two halfedges are in the same cc
// if they are on the border of a set of non-marked faces sharing
// a common vertex
typedef CGAL::Union_find<halfedge_descriptor> UF_ds;
UF_ds uf;
std::map<halfedge_descriptor, typename UF_ds::handle> handles;
// one cc per border halfedge
BOOST_FOREACH(halfedge_descriptor hd, border)
handles.insert( std::make_pair(hd, uf.make_set(hd)) );
// join cc's
BOOST_FOREACH(halfedge_descriptor hd, border)
{
CGAL_assertion( marked_faces.count( face( hd, tmesh) ) > 0);
CGAL_assertion( marked_faces.count( face( opposite(hd, tmesh), tmesh) ) == 0 );
halfedge_descriptor candidate = hd;
do{
candidate = prev( opposite(candidate, tmesh), tmesh );
} while( !marked_faces.count( face( opposite(candidate, tmesh), tmesh) ) );
uf.unify_sets( handles[hd], handles[opposite(candidate, tmesh)] );
}
std::size_t nb_cc = uf.number_of_sets();
if ( nb_cc != 1 )
{
// if more than one connected component is found then the patch
// made of marked faces contains "non-manifold" vertices.
// The smallest components need to be marked so that the patch
// made of marked faces is a topological disk
// extract one border halfedge per cc
std::set< halfedge_descriptor > ccs;
BOOST_FOREACH(halfedge_descriptor hd, border)
ccs.insert( *uf.find( handles[hd] ) );
// we will explore in parallel the connected components and will stop
// when all but one connected component have been entirely explored.
// We have one face at a time for each cc in order to not explore a
// potentially very large cc.
std::vector< std::vector<halfedge_descriptor> > stacks_per_cc(nb_cc);
std::vector< std::set<face_descriptor> > faces_per_cc(nb_cc);
std::vector< bool > exploration_finished(nb_cc, false);
// init stacks
std::size_t index=0;
BOOST_FOREACH( halfedge_descriptor hd, ccs)
{
halfedge_descriptor opp_hedge = opposite(hd, tmesh);
stacks_per_cc[ index ].push_back( prev(opp_hedge, tmesh) );
stacks_per_cc[ index ].push_back( next(opp_hedge, tmesh) );
faces_per_cc[ index ].insert( face(opp_hedge, tmesh) );
++index;
}
std::size_t nb_ccs_to_be_explored = nb_cc;
index=0;
//explore the cc's
do{
// try to extract one more face for a given cc
do{
CGAL_assertion( !exploration_finished[index] );
halfedge_descriptor hd = stacks_per_cc[index].back();
stacks_per_cc[index].pop_back();
hd = opposite(hd, tmesh);
if ( !marked_faces.count(face(hd, tmesh) ) )
{
if ( faces_per_cc[index].insert( face(hd, tmesh) ).second )
{
stacks_per_cc[index].push_back( next(hd, tmesh) );
stacks_per_cc[index].push_back( prev(hd, tmesh) );
break;
}
}
if (stacks_per_cc[index].empty()) break;
}
while(true);
// the exploration of a cc is finished when its stack is empty
exploration_finished[index]=stacks_per_cc[index].empty();
if ( exploration_finished[index] ) --nb_ccs_to_be_explored;
if ( nb_ccs_to_be_explored==1 ) break;
while ( exploration_finished[(++index)%nb_cc] );
index=index%nb_cc;
}while(true);
/// \todo use the area criteria? this means maybe continue exploration of larger cc
// mark faces of completetly explored cc
for (index=0; index< nb_cc; ++index)
if( exploration_finished[index] )
{
BOOST_FOREACH(face_descriptor fd, faces_per_cc[index])
marked_faces.insert(fd);
}
}
// collect simplices to be removed
std::set<vertex_descriptor> vertices_to_keep;
std::set<halfedge_descriptor> halfedges_to_keep;
BOOST_FOREACH(halfedge_descriptor hd, border)
if ( !marked_faces.count(face(opposite(hd, tmesh), tmesh)) )
{
halfedges_to_keep.insert( hd );
vertices_to_keep.insert( target(hd, tmesh) );
}
// backup next,prev relationships to set after patch removal
std::vector< std::pair<halfedge_descriptor, halfedge_descriptor> > next_prev_halfedge_pairs;
halfedge_descriptor first_border_hd=*( halfedges_to_keep.begin() );
halfedge_descriptor current_border_hd=first_border_hd;
do{
halfedge_descriptor prev_border_hd=current_border_hd;
current_border_hd=next(current_border_hd, tmesh);
while( marked_faces.count( face( opposite(current_border_hd, tmesh), tmesh) ) )
current_border_hd=next(opposite(current_border_hd, tmesh), tmesh);
next_prev_halfedge_pairs.push_back( std::make_pair(prev_border_hd, current_border_hd) );
}while(current_border_hd!=first_border_hd);
// collect vertices and edges to remove and do remove faces
std::set<edge_descriptor> edges_to_remove;
std::set<vertex_descriptor> vertices_to_remove;
BOOST_FOREACH(face_descriptor fd, marked_faces)
{
halfedge_descriptor hd=halfedge(fd, tmesh);
for(int i=0; i<3; ++i)
{
if ( !halfedges_to_keep.count(hd) )
edges_to_remove.insert( edge(hd, tmesh) );
if ( !vertices_to_keep.count(target(hd,tmesh)) )
vertices_to_remove.insert( target(hd,tmesh) );
hd=next(hd, tmesh);
}
remove_face(fd, tmesh);
}
// remove vertices
BOOST_FOREACH(vertex_descriptor vd, vertices_to_remove)
remove_vertex(vd, tmesh);
// remove edges
BOOST_FOREACH(edge_descriptor ed, edges_to_remove)
{
null_edges_to_remove.erase(ed);
remove_edge(ed, tmesh);
}
// add a new face, set all border edges pointing to it
// and update halfedge vertex of patch boundary vertices
face_descriptor new_face = add_face(tmesh);
typedef std::pair<halfedge_descriptor, halfedge_descriptor> Pair_type;
BOOST_FOREACH(const Pair_type& p, next_prev_halfedge_pairs)
{
set_face(p.first, new_face, tmesh);
set_next(p.first, p.second, tmesh);
set_halfedge(target(p.first, tmesh), p.first, tmesh);
}
set_halfedge(new_face, first_border_hd, tmesh);
// triangulate the new face and update the coordinate of the central vertex
halfedge_descriptor new_hd=Euler::add_center_vertex(first_border_hd, tmesh);
put(vpmap, target(new_hd, tmesh), pt);
BOOST_FOREACH(halfedge_descriptor hd, halfedges_around_target(new_hd, tmesh))
if ( traits.equal_3_object()(get(vpmap, target(hd, tmesh)), get(vpmap, source(hd, tmesh))) )
null_edges_to_remove.insert(edge(hd, tmesh));
#if 0
// the following test filters in particular cases where the
// detection of the vertex that breaks the link condition
// is not correctly detected by find_larger_triangle
// (i.e. when the hedges detected should be used with the opposite edge)
if ( traits.collinear_3_object()(
get(vpmap, target(h, tmesh)),
get(vpmap, target(next(h, tmesh), tmesh)),
get(vpmap, target(next(opposite(h, tmesh), tmesh), tmesh)) ) )
{
// we handle this case in the next loop removing set of degenerated
// triangles which points are collinear
edges_to_remove_skipped.insert(ed);
continue;
}
do{
// improve the link condition on h's side
boost::optional< std::pair<halfedge_descriptor, halfedge_descriptor> >
res = internal::find_larger_triangle(h, tmesh, vpmap, traits);
if (res)
internal::remove_faces_inside_triangle(res->first, h, res->second, tmesh, null_edges_to_remove, edges_to_remove_skipped);
// improve the link condition on opposite(h)'s side
h=opposite(h, tmesh);
res = internal::find_larger_triangle(h, tmesh, vpmap, traits);
if (res)
internal::remove_faces_inside_triangle(res->first, h, res->second, tmesh, null_edges_to_remove, edges_to_remove_skipped);
h=opposite(h, tmesh);
ed=edge(h, tmesh);
} while(!CGAL::Euler::does_satisfy_link_condition(ed,tmesh));
null_edges_to_remove.insert( ed );
#endif
}
}
// check if some edges were skipped due to link condition not satisfied
// that could now be satisfied
if (edges_to_remove_skipped.empty() ||
edges_to_remove_skipped.size()==nb_edges_previously_skipped) break;
null_edges_to_remove.swap(edges_to_remove_skipped);
nb_edges_previously_skipped = null_edges_to_remove.size();
} while(true);
// remove triangles made of 3 collinear points
// Then, remove triangles made of 3 collinear points
std::set<face_descriptor> degenerate_face_set;
BOOST_FOREACH(face_descriptor fd, faces(tmesh))
if ( is_degenerated(fd, tmesh, vpmap, traits) )

View File

@ -0,0 +1,16 @@
OFF
7 7 0
1 0 0
0 1 0
1 1 0
2 1 0
1 1 0
1 2 0
0.5 1 0
3 0 2 1
3 0 3 2
3 4 3 5
3 1 4 5
3 1 2 6
3 6 2 4
3 6 4 1

View File

@ -32,6 +32,7 @@ int main()
fix("data_degeneracies/degtri_on_border.off");
fix("data_degeneracies/degtri_three.off");
fix("data_degeneracies/degtri_single.off");
fix("data_degeneracies/trihole.off");
return 0;
}

View File

@ -12,6 +12,7 @@ class Scene_item;
// OpenGL rendering mode
enum RenderingMode { Points = 0,
PointsPlusNormals,
Splatting,
Wireframe,
Flat,
FlatPlusEdges,

View File

@ -32,8 +32,10 @@ public:
virtual bool inFastDrawing() const = 0;
typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORARBPROC) (GLuint index, GLuint divisor);
typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLuint target, GLuint attachment, GLuint textarget, GLuint texture, GLint level);
PFNGLDRAWARRAYSINSTANCEDARBPROC glDrawArraysInstanced;
PFNGLVERTEXATTRIBDIVISORARBPROC glVertexAttribDivisor;
PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2D;
bool extension_is_found;
GLfloat pickMatrix_[16];

View File

@ -62,6 +62,20 @@ if (EIGEN3_FOUND)
include( ${EIGEN3_USE_FILE} )
endif(EIGEN3_FOUND)
# Activate concurrency?
option(POLYHEDRON_DEMO_ACTIVATE_CONCURRENCY
"Enable concurrency"
ON)
if( POLYHEDRON_DEMO_ACTIVATE_CONCURRENCY )
find_package( TBB )
if( TBB_FOUND )
include( ${TBB_USE_FILE} )
list( APPEND CGAL_3RD_PARTY_LIBRARIES ${TBB_LIBRARIES} )
else()
message( STATUS "NOTICE: Intel TBB was not found. Bilateral smoothing and WLOP plugins are faster if TBB is linked." )
endif()
endif()
if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND)
@ -101,6 +115,11 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND)
qt5_add_resources ( RESOURCE_FILES Polyhedron_3.qrc )
qt5_add_resources(gl_splat_rc GlSplat/glsplat.qrc)
add_library(gl_splat SHARED
GlSplat/GlSplat.cpp GlSplat/Shader.cpp ${gl_splat_rc})
qt5_use_modules(gl_splat OpenGL Gui Xml)
target_link_libraries(gl_splat ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY} ${GLEW_LIBRARIES})
qt5_generate_moc( "CGAL_demo/Viewer_interface.h" "${CMAKE_CURRENT_BINARY_DIR}/Viewer_interface_moc.cpp" )
@ -187,6 +206,8 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND)
target_link_libraries(scene_nef_polyhedron_item scene_polyhedron_item)
add_item(scene_points_with_normal_item Scene_points_with_normal_item.cpp)# Scene_points_with_normal_item.moc)
target_link_libraries( scene_points_with_normal_item gl_splat ${GLEW_LIBRARIES} )
target_link_libraries( demo_framework gl_splat ${GLEW_LIBRARIES} )
foreach( lib
demo_framework
@ -228,6 +249,7 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND)
target_link_libraries( Polyhedron_3 ${QT_LIBRARIES} )
target_link_libraries( Polyhedron_3 demo_framework )
target_link_libraries( Polyhedron_3 point_dialog )
target_link_libraries( Polyhedron_3 gl_splat ${GLEW_LIBRARIES})
# Link with CGAL
target_link_libraries( Polyhedron_3 ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES} )
@ -235,6 +257,7 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND)
# Link with libQGLViewer, OpenGL
target_link_libraries( Polyhedron_3 ${QGLVIEWER_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} )
add_to_cached_list( CGAL_EXECUTABLE_TARGETS Polyhedron_3 )
@ -439,6 +462,20 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND)
polyhedron_demo_plugin(point_set_shape_detection_plugin Polyhedron_demo_point_set_shape_detection_plugin ${point_set_shape_detectionUI_FILES})
target_link_libraries(point_set_shape_detection_plugin scene_polyhedron_item scene_points_with_normal_item)
qt5_wrap_ui(point_set_wlopFILES Polyhedron_demo_point_set_wlop_plugin.ui)
polyhedron_demo_plugin(point_set_wlop_plugin Polyhedron_demo_point_set_wlop_plugin ${point_set_wlopFILES})
target_link_libraries(point_set_wlop_plugin scene_points_with_normal_item)
qt5_wrap_ui(point_set_bilateral_smoothingUI_FILES Polyhedron_demo_point_set_bilateral_smoothing_plugin.ui)
polyhedron_demo_plugin(point_set_bilateral_smoothing_plugin Polyhedron_demo_point_set_bilateral_smoothing_plugin ${point_set_bilateral_smoothingUI_FILES})
target_link_libraries(point_set_bilateral_smoothing_plugin scene_points_with_normal_item)
qt5_wrap_ui(point_set_upsamplingUI_FILES Polyhedron_demo_point_set_upsampling_plugin.ui)
polyhedron_demo_plugin(point_set_upsampling_plugin Polyhedron_demo_point_set_upsampling_plugin ${point_set_upsamplingUI_FILES})
target_link_libraries(point_set_upsampling_plugin scene_points_with_normal_item)
qt5_wrap_ui( ps_outliers_removal_UI_FILES Polyhedron_demo_point_set_outliers_removal_plugin.ui)
polyhedron_demo_plugin(point_set_outliers_removal_plugin Polyhedron_demo_point_set_outliers_removal_plugin ${ps_outliers_removal_UI_FILES})
target_link_libraries(point_set_outliers_removal_plugin scene_points_with_normal_item)
@ -486,6 +523,12 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND)
NAMESPACE Polyhedron_
APPEND FILE polyhedron_demo_targets.cmake)
export(
TARGETS
gl_splat
NAMESPACE Polyhedron_
APPEND FILE polyhedron_demo_targets.cmake)
configure_file(CGAL_polyhedron_demoConfig.cmake.in CGAL_polyhedron_demoConfig.cmake)
else (CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND)

View File

@ -0,0 +1,35 @@
project(GlSplat)
cmake_minimum_required(VERSION 2.6.0)
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER 2.8.3)
cmake_policy(VERSION 2.8.4)
else()
cmake_policy(VERSION 2.6)
endif()
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
find_package(Qt4 REQUIRED)
find_package(GLEW REQUIRED)
set(QT_USE_QTOPENGL TRUE)
set(QT_USE_QTXML TRUE)
include(${QT_USE_FILE})
include_directories( ${QT_QTOPENGL_INCLUDE_DIR} ${QT_QTXML_INCLUDE_DIR} ${GLEW_INCLUDE_DIR})
set(srcs Shader.cpp GlSplat.cpp)
qt4_automoc( ${srcs})
qt4_add_resources(srcs glsplat.qrc)
add_library(GlSplat SHARED ${srcs})
target_link_libraries(GlSplat ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY} ${GLEW_LIBRARIES})
find_package(QGLViewer)
if(QGLVIEWER_FOUND)
include_directories( ${QGLViewer_INCLUDES})
add_executable(demo demo.cpp)
target_link_libraries(demo ${QT_QTXML_LIBRARY} ${QGLViewer_LIBRARIES} GlSplat)
else()
message("QGLViewer not found, demo won't be built")
endif()

View File

@ -0,0 +1,535 @@
// This file is part of GlSplat, a simple splatting C++ library
//
// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
//
// GlSplat is free software; 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 2.1 of the License, or (at your option) any later version.
//
// GlSplat is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with GlSplat. If not, see <http://www.gnu.org/licenses/>.
#include <QtGui>
#include <math.h>
#include <stdlib.h>
#include <iostream>
#include "GlSplat.h"
#include "Shader.h"
#include <QGLWidget>
#include <QTextStream>
#include <QGLFramebufferObject>
namespace GlSplat {
SplatRenderer::SplatRenderer()
{
mNormalTextureID = 0;
mDepthTextureID = 0;
mIsSupported = false;
viewer_is_set = false;
mRenderBuffer = 0;
mWorkaroundATI = false;
mBuggedAtiBlending = false;
mDummyTexId = 0;
mIsInitialized = false;
mFlags = DEFERRED_SHADING_BIT | DEPTH_CORRECTION_BIT | FLOAT_BUFFER_BIT | OUTPUT_DEPTH_BIT;
mCachedFlags = ~mFlags;
// union of bits which controls the render buffer
mRenderBufferMask = DEFERRED_SHADING_BIT | FLOAT_BUFFER_BIT;
}
QString SplatRenderer::loadSource(const QString& func,const QString& filename)
{
QString res;
QFile f(":/SplatRenderer/shaders/" + filename);
if (!f.open(QFile::ReadOnly))
{
std::cerr << "failed to load shader file " << filename.toLatin1().data() << "\n";
return res;
}
else qDebug("Succesfully loaded shader func '%s' in file '%s'",qPrintable(func),qPrintable(filename));
QTextStream stream(&f);
res = stream.readAll();
f.close();
res = QString("#define GLSPLAT__%1__ 1\n").arg(func)
+ QString("#define %1 main\n").arg(func)
+ res;
return res;
}
void SplatRenderer::configureShaders()
{
// const char* passNames[3] = {"Visibility","Attribute","Finalization"};
QString defines = "";
if (mFlags & DEFERRED_SHADING_BIT)
defines += "#define ES_DEFERRED_SHADING\n";
if (mFlags & DEPTH_CORRECTION_BIT)
defines += "#define ES_DEPTH_CORRECTION\n";
if (mFlags & OUTPUT_DEPTH_BIT)
defines += "#define ES_OUTPUT_DEPTH 1\n";
if (mFlags & BACKFACE_SHADING_BIT)
defines += "#define ES_BACKFACE_SHADING\n";
if (mWorkaroundATI)
defines += "#define ES_ATI_WORKAROUND\n";
QString shading =
"vec4 meshlabLighting(vec4 color, vec3 eyePos, vec3 normal)"
"{"
" normal = normalize(normal);"
" vec3 lightVec = normalize(gl_LightSource[0].position.xyz);"
" vec3 halfVec = normalize( lightVec - normalize(eyePos) );"
" float aux_dot = dot(normal,lightVec);"
" float diffuseCoeff = clamp(aux_dot, 0.0, 1.0);"
" float specularCoeff = aux_dot>0.0 ? clamp(pow(clamp(dot(halfVec, normal),0.0,1.0),gl_FrontMaterial.shininess), 0.0, 1.0) : 0.0;"
" return vec4(color.rgb * ( gl_FrontLightProduct[0].ambient.rgb + diffuseCoeff * gl_FrontLightProduct[0].diffuse.rgb) + specularCoeff * gl_FrontLightProduct[0].specular.rgb, 1.0);"
"}\n";
for (int k=0;k<3;++k)
{
QString vsrc = shading + defines + mShaderSrcs[k*2+0];
QString fsrc = shading + defines + mShaderSrcs[k*2+1];
if(!mShaders[k].loadSources(mShaderSrcs[k*2+0]!="" ? vsrc.toLatin1().data() : 0,
mShaderSrcs[k*2+1]!="" ? fsrc.toLatin1().data() : 0/*,
Shader::Warnings*/))
mIsSupported = false;
}
}
void SplatRenderer::init(QGLWidget *qglw)
{
mIsSupported = true;
if(qglw)
qglw->makeCurrent();
//glewInit();
const char* rs = (const char*)glGetString(GL_RENDERER);
QString rendererString("");
if(rs)
rendererString = QString(rs);
mWorkaroundATI = rendererString.startsWith("ATI") || rendererString.startsWith("AMD");
// FIXME: maybe some recent HW correctly supports floating point blending...
mBuggedAtiBlending = rendererString.startsWith("ATI") || rendererString.startsWith("AMD");
if (mWorkaroundATI && mDummyTexId==0)
{
viewer->glActiveTexture(GL_TEXTURE0);
viewer->glGenTextures(1,&mDummyTexId);
viewer->glBindTexture(GL_TEXTURE_2D, mDummyTexId);
viewer->glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 4, 4, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0);
}
// let's check the GPU capabilities
mSupportedMask = DEPTH_CORRECTION_BIT | BACKFACE_SHADING_BIT;
if (!QGLFramebufferObject::hasOpenGLFramebufferObjects ())
{
std::cout << "SplatRenderer: error OpenGL frame buffer objects are not supported. (please, try to update your drivers)\n";
mIsSupported = false;
return;
}
//if (GLEW_ARB_texture_float)
mSupportedMask |= FLOAT_BUFFER_BIT;
//else
// std::cout << "SplatRenderer: warning floating point textures are not supported.\n";
// if (GLEW_ARB_draw_buffers && (!mBuggedAtiBlending))
mSupportedMask |= DEFERRED_SHADING_BIT;
//else
// std::cout << "SplatRenderer: warning deferred shading is not supported.\n";
//if (GLEW_ARB_shadow)
mSupportedMask |= OUTPUT_DEPTH_BIT;
//else
// std::cerr << "SplatRenderer: warning copy of the depth buffer is not supported.\n";
mFlags = mFlags & mSupportedMask;
// load shader source
mShaderSrcs[0] = loadSource("VisibilityVP","Raycasting.glsl");
mShaderSrcs[1] = loadSource("VisibilityFP","Raycasting.glsl");
mShaderSrcs[2] = loadSource("AttributeVP","Raycasting.glsl");
mShaderSrcs[3] = loadSource("AttributeFP","Raycasting.glsl");
mShaderSrcs[4] = "";
mShaderSrcs[5] = loadSource("Finalization","Finalization.glsl");
mCurrentPass = 2;
mBindedPass = -1;
mIsInitialized = true;
}
void SplatRenderer::updateRenderBuffer()
{
if ( (!mRenderBuffer)
|| (mRenderBuffer->width()!=mCachedVP[2])
|| (mRenderBuffer->height()!=mCachedVP[3])
|| ( (mCachedFlags & mRenderBufferMask) != (mFlags & mRenderBufferMask) ))
{
delete mRenderBuffer;
GLenum fmt = (mFlags&FLOAT_BUFFER_BIT) ? GL_RGBA16F_ARB : GL_RGBA;
mRenderBuffer = new QGLFramebufferObject(mCachedVP[2], mCachedVP[3],
(mFlags&OUTPUT_DEPTH_BIT) ? QGLFramebufferObject::NoAttachment : QGLFramebufferObject::Depth,
GL_TEXTURE_RECTANGLE_ARB, fmt);
if (!mRenderBuffer->isValid())
{
std::cout << "SplatRenderer: invalid FBO\n";
}
if (mFlags&DEFERRED_SHADING_BIT)
{
// in deferred shading mode we need an additional buffer to accumulate the normals
if (mNormalTextureID==0)
viewer->glGenTextures(1,&mNormalTextureID);
//glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mNormalTextureID);
viewer->glBindTexture(GL_TEXTURE_RECTANGLE, mNormalTextureID);
//glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, fmt, mCachedVP[2], mCachedVP[3], 0, GL_RGBA, GL_FLOAT, 0);
viewer->glTexImage2D(GL_TEXTURE_RECTANGLE, 0, fmt, mCachedVP[2], mCachedVP[3], 0, GL_RGBA, GL_FLOAT, 0);
//glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
viewer->glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
viewer->glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
mRenderBuffer->bind();
viewer->glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)viewer->context()->getProcAddress("glFramebufferTexture2DEXT");
viewer->glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, mNormalTextureID, 0);
mRenderBuffer->release();
}
if (mFlags&OUTPUT_DEPTH_BIT)
{
// to output the depth values to the final depth buffer we need to
// attach a depth buffer as a texture
if (mDepthTextureID==0)
viewer->glGenTextures(1,&mDepthTextureID);
//glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mDepthTextureID);
viewer->glBindTexture(GL_TEXTURE_RECTANGLE, mDepthTextureID);
//glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24_ARB, mCachedVP[2], mCachedVP[3], 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
viewer->glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_DEPTH_COMPONENT24, mCachedVP[2], mCachedVP[3], 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
//glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
viewer->glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
viewer->glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
mRenderBuffer->bind();
viewer->glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, mDepthTextureID, 0);
mRenderBuffer->release();
}
}
}
bool SplatRenderer::beginVisibilityPass()
{
if (!mIsInitialized)
{
init();
}
if (!isSupported())
{
std::cerr << "SplatRenderer error: not supported hardware\n";
return false;
}
if (mCurrentPass!=2)
{
std::cerr << "SplatRenderer error: programming error when calling beginVisibilityPass\n";
return false;
}
viewer->glPushAttrib(GL_ALL_ATTRIB_BITS);
mCurrentPass = 0;
// grab projection info
viewer->glGetIntegerv(GL_VIEWPORT, mCachedVP);
viewer->glGetFloatv(GL_MODELVIEW_MATRIX, mCachedMV);
viewer->glGetFloatv(GL_PROJECTION_MATRIX, mCachedProj);
updateRenderBuffer();
if (mCachedFlags != mFlags)
configureShaders();
// configureShaders may detect that shaders are actually not supported.
if (!isSupported())
{
std::cerr << "SplatRenderer error: not supported hardware\n";
return false;
}
mCachedFlags = mFlags;
mParams.update(mCachedMV, mCachedProj, mCachedVP);
mParams.loadTo(mShaders[mCurrentPass]);
mRenderBuffer->bind();
if (mFlags & DEFERRED_SHADING_BIT)
{
//GLenum buf[2] = {GL_COLOR_ATTACHMENT0_EXT,GL_COLOR_ATTACHMENT1_EXT};
GLenum buf[2] = {GL_COLOR_ATTACHMENT0,GL_COLOR_ATTACHMENT1};
//glDrawBuffersARB(2, buf);
viewer->glDrawBuffers(2, buf);
}
viewer->glViewport(mCachedVP[0],mCachedVP[1],mCachedVP[2],mCachedVP[3]);
viewer->glClearColor(0,0,0,0);
viewer->glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
enablePass(mCurrentPass);
;
return true;
}
bool SplatRenderer::beginAttributePass()
{
if (!isSupported())
{
std::cerr << "SplatRenderer error: not supported hardware\n";
return false;
}
if (mCurrentPass!=0)
{
std::cerr << "SplatRenderer error: programming error when calling beginAttributePass (must be called after the visiblity pass)\n";
return false;
}
mCurrentPass = 1;
mParams.loadTo(mShaders[mCurrentPass]);
enablePass(mCurrentPass);
;
return true;
}
bool SplatRenderer::finalize()
{
if (!isSupported())
{
std::cerr << "SplatRenderer error: not supported hardware\n";
return false;
}
// this is the last pass: normalization by the sum of weights + deferred shading
mShaders[mCurrentPass].release();
mRenderBuffer->release();
if ( (mCurrentPass!=0) && (mCurrentPass!=1))
{
std::cerr << "SplatRenderer error: programming error when calling finalize (must be called after the visiblity or attribute pass)\n";
return false;
}
mCurrentPass = 2;
if (mFlags&DEFERRED_SHADING_BIT)
viewer->glDrawBuffer(GL_BACK);
enablePass(mCurrentPass);
// switch to normalized 2D rendering mode
viewer->glMatrixMode(GL_PROJECTION);
viewer->glPushMatrix();
viewer->glLoadIdentity();
viewer->glMatrixMode(GL_MODELVIEW);
viewer->glPushMatrix();
viewer->glLoadIdentity();
mShaders[2].setUniform("viewport",float(mCachedVP[0]),float(mCachedVP[1]),float(mCachedVP[2]),float(mCachedVP[3]));
mShaders[2].setUniform("ColorWeight",0); // this is a texture unit
viewer->glActiveTexture(GL_TEXTURE0);
//glBindTexture(GL_TEXTURE_RECTANGLE_ARB,mRenderBuffer->texture());
viewer->glBindTexture(GL_TEXTURE_RECTANGLE,mRenderBuffer->texture());
if (mFlags&DEFERRED_SHADING_BIT)
{
mShaders[2].setUniform("unproj", mCachedProj[10], mCachedProj[14]);
mShaders[2].setUniform("NormalWeight",1); // this is a texture unit
viewer->glActiveTexture(GL_TEXTURE1);
//glBindTexture(GL_TEXTURE_RECTANGLE_ARB,mNormalTextureID);
viewer->glBindTexture(GL_TEXTURE_RECTANGLE,mNormalTextureID);
}
if (mFlags&OUTPUT_DEPTH_BIT)
{
mShaders[2].setUniform("Depth",2); // this is a texture unit
viewer->glActiveTexture(GL_TEXTURE2);
//glBindTexture(GL_TEXTURE_RECTANGLE_ARB,mDepthTextureID);
viewer->glBindTexture(GL_TEXTURE_RECTANGLE,mDepthTextureID);
}
else
{
viewer->glDisable(GL_DEPTH_TEST);
viewer->glDepthMask(GL_FALSE);
}
// draw a quad covering the whole screen
float viewVec[] = {1.f/mCachedProj[0], 1.f/mCachedProj[5], -1};
viewer->glBegin(GL_QUADS);
viewer->glColor3f(1, 0, 0);
viewer->glTexCoord3f(viewVec[0],viewVec[1],viewVec[2]);
viewer->glMultiTexCoord2f(GL_TEXTURE1,1.,1.);
viewer->glVertex3f(1,1,0);
viewer->glColor3f(1, 1, 0);
viewer->glTexCoord3f(-viewVec[0],viewVec[1],viewVec[2]);
viewer->glMultiTexCoord2f(GL_TEXTURE1,0.,1.);
viewer->glVertex3f(-1,1,0);
viewer->glColor3f(0, 1, 1);
viewer->glTexCoord3f(-viewVec[0],-viewVec[1],viewVec[2]);
viewer->glMultiTexCoord2f(GL_TEXTURE1,0.,0.);
viewer->glVertex3f(-1,-1,0);
viewer->glColor3f(1, 0, 1);
viewer->glTexCoord3f(viewVec[0],-viewVec[1],viewVec[2]);
viewer->glMultiTexCoord2f(GL_TEXTURE1,1.,0.);
viewer->glVertex3f(1,-1,0);
viewer->glEnd();
if (!(mFlags&OUTPUT_DEPTH_BIT))
{
viewer->glEnable(GL_DEPTH_TEST);
viewer->glDepthMask(GL_TRUE);
}
mShaders[mCurrentPass].release();
// restore matrices
viewer->glMatrixMode(GL_PROJECTION);
viewer->glPopMatrix();
viewer->glMatrixMode(GL_MODELVIEW);
viewer->glPopMatrix();
viewer->glPopAttrib();
return true;
}
void SplatRenderer::enablePass(int n)
{
if (!isSupported())
{
return;
}
if (mBindedPass!=n)
{
if (mBindedPass>=0)
mShaders[mBindedPass].release();
mShaders[n].activate();
mBindedPass = n;
// set GL states
if (n==0)
{
viewer->glDisable(GL_LIGHTING);
// glDisable(GL_POINT_SMOOTH);
viewer->glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
viewer->glAlphaFunc(GL_LESS,1);
viewer->glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
viewer->glDepthMask(GL_TRUE);
viewer->glDisable(GL_BLEND);
viewer->glEnable(GL_ALPHA_TEST);
viewer->glEnable(GL_DEPTH_TEST);
// glActiveTexture(GL_TEXTURE0);
// glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
// glEnable(GL_POINT_SPRITE_ARB);
}
if (n==1)
{
viewer->glDisable(GL_LIGHTING);
viewer->glEnable(GL_POINT_SMOOTH);
viewer->glActiveTexture(GL_TEXTURE0);
viewer->glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
viewer->glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
viewer->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE,GL_ONE);
// //glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE,GL_ZERO);
// glBlendFunc(GL_ONE,GL_ZERO);
viewer->glDepthMask(GL_FALSE);
viewer->glEnable(GL_BLEND);
viewer->glEnable(GL_DEPTH_TEST);
viewer->glDisable(GL_ALPHA_TEST);
// glActiveTexture(GL_TEXTURE0);
}
if ( (n==0) || (n==1) )
{
// enable point sprite rendering mode
viewer->glActiveTexture(GL_TEXTURE0);
if (mWorkaroundATI)
{
viewer->glBindTexture(GL_TEXTURE_2D, mDummyTexId);
viewer->glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 2, 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0);
viewer->glPointParameterf(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
// hm... ^^^^
}
viewer->glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
viewer->glEnable(GL_POINT_SPRITE_ARB);
}
if (n==2)
{
viewer->glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
viewer->glDepthMask(GL_TRUE);
viewer->glDisable(GL_LIGHTING);
viewer->glDisable(GL_BLEND);
}
}
}
void SplatRenderer::UniformParameters::update(float* mv, float* proj, GLint* vp)
{
// extract the uniform scale
float scale = sqrtf(mv[0]*mv[0]+mv[1]*mv[1]+mv[2]*mv[2]);
radiusScale = scale;
preComputeRadius = - (std::max)(proj[0]*vp[2], proj[5]*vp[3]);
depthOffset = 2.0;
oneOverEwaRadius = 0.70710678118654f;
halfVp[0] = 0.5*vp[2];
halfVp[1] = 0.5*vp[3];
rayCastParameter1[0] = 2./(proj[0]*vp[2]);
rayCastParameter1[1] = 2./(proj[5]*vp[3]);
rayCastParameter1[2] = 0.0;
rayCastParameter2[0] = -1./proj[0];
rayCastParameter2[1] = -1./proj[5];
rayCastParameter2[2] = -1.0;
depthParameterCast[0] = 0.5*proj[14];
depthParameterCast[1] = 0.5-0.5*proj[10];
}
void SplatRenderer::UniformParameters::loadTo(Shader& prg)
{
prg.activate();
prg.setUniform("expeRadiusScale", radiusScale);
prg.setUniform("expePreComputeRadius", preComputeRadius);
prg.setUniform("expeDepthOffset", depthOffset);
prg.setUniform("oneOverEwaRadius", oneOverEwaRadius);
prg.setUniform2("halfVp", halfVp);
prg.setUniform3("rayCastParameter1", rayCastParameter1);
prg.setUniform3("rayCastParameter2", rayCastParameter2);
prg.setUniform2("depthParameterCast", depthParameterCast);
}
void SplatRenderer::setRadiusScale(float v)
{
mParams.radiusScale = v;
}
void SplatRenderer::setViewer(Viewer_interface *v)
{
viewer = v;
for(int i=0; i<3; i++)
mShaders[i].setViewer(v);
viewer_is_set = true;
}
} // namepsace GlSplat

View File

@ -0,0 +1,153 @@
// This file is part of GlSplat, a simple splatting C++ library
//
// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
//
// GlSplat is free software; 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 2.1 of the License, or (at your option) any later version.
//
// GlSplat is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with GlSplat. If not, see <http://www.gnu.org/licenses/>.
#ifndef _GLSPLAT_SPLATRENDERER_H_
#define _GLSPLAT_SPLATRENDERER_H_
#include "GlSplat_config.h"
#include "Shader.h"
#include <QObject>
#include <QAction>
#include <QString>
#include <map>
class QGLFramebufferObject;
class QGLWidget;
namespace GlSplat {
/** \class SplatRenderer
* \brief Helper class to render a set of points using a splatting alogirthm
*
* This class aims to render a set of oriented point with radius (called splats) using an
* OpenGL based splating algorithm. This class is only responsible for the managing of the
* OpenGL stats and shaders related to the splatting. The drawing of the geometry, i.e.,
* sending the point data to the GPU has to be done by the user.
*
* Here is an example:
* \code
* SplatRenderer renderer;
* renderer.init();
*
* renderer.beginVisibilityPass();
* drawpoints();
* renderer.beginAttributePass();
* drawpoints();
* renderer.finalize();
* \endcode
*
* Have a look at the demo to see a complete example based on QGLviewer.
*/
class GLSPLAT_EXPORT SplatRenderer
{
bool mIsSupported;
enum {
DEFERRED_SHADING_BIT = 0x000001,
DEPTH_CORRECTION_BIT = 0x000002,
OUTPUT_DEPTH_BIT = 0x000004,
BACKFACE_SHADING_BIT = 0x000008,
FLOAT_BUFFER_BIT = 0x000010
};
int mFlags;
int mCachedFlags;
int mRenderBufferMask;
int mSupportedMask;
int mCurrentPass;
int mBindedPass;
GLuint mDummyTexId; // on ATI graphics card we need to bind a texture to get point sprite working !
bool mWorkaroundATI;
bool mBuggedAtiBlending;
bool mIsInitialized;
GLuint mNormalTextureID;
GLuint mDepthTextureID;
Shader mShaders[3];
QString mShaderSrcs[6];
QGLFramebufferObject* mRenderBuffer;
float mCachedMV[16]; // modelview matrix
float mCachedProj[16]; // projection matrix
GLint mCachedVP[4]; // viewport
struct UniformParameters
{
float radiusScale;
float preComputeRadius;
float depthOffset;
float oneOverEwaRadius;
float halfVp[2];
float rayCastParameter1[3];
float rayCastParameter2[3];
float depthParameterCast[2];
void loadTo(Shader& prg);
void update(float* mv, float* proj, GLint* vp);
};
UniformParameters mParams;
QString loadSource(const QString& func,const QString& file);
void configureShaders();
void updateRenderBuffer();
void enablePass(int n);
public:
bool viewer_is_set;
SplatRenderer();
~SplatRenderer()
{
}
/** Must be called once an OpenGL context has been activated.
* The main OpenGL context must be enabled, or, if you are using a QGLwiget,
* you can pass it to this function without caring about the OpenGL context.
*/
void init(QGLWidget *qglw = 0);
/** \returns true is the hardware is supported
* Must be called after init.
*/
bool isSupported() { return mIsSupported; }
/** Starts the first rendering pass
* \returns false if an error occured
*/
bool beginVisibilityPass();
/** Starts the (optional) second rendering pass
* \returns false if an error occured
*/
bool beginAttributePass();
/** Draw the rendered splats inside the main render target.
* \returns false if an error occured
*/
bool finalize();
/** Sets a global scale factor for the splat radii
* Default value is 1
*/
void setRadiusScale(float v);
void setViewer(Viewer_interface *v);
private :
Viewer_interface *viewer;
};
} // namepsace GlSplat
#endif // _GLSPLAT_SPLATRENDERER_H_

View File

@ -0,0 +1,12 @@
#ifndef GLSPLAT_CONFIG_H
#define GLSPLAT_CONFIG_H
#include <CGAL/export/helpers.h>
#ifdef gl_splat_EXPORTS
#define GLSPLAT_EXPORT CGAL_DLL_EXPORT
#else
#define GLSPLAT_EXPORT CGAL_DLL_IMPORT
#endif
#endif // GLSPLAT_CONFIG_H

View File

@ -0,0 +1,140 @@
// This file is part of GlSplat, a simple splatting C++ library
//
// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
//
// GlSplat is free software; 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 2.1 of the License, or (at your option) any later version.
//
// GlSplat is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with GlSplat. If not, see <http://www.gnu.org/licenses/>.
#include "Shader.h"
#include <iostream>
#include <qfile.h>
#include <qtextstream.h>
#include <assert.h>
#include <QDebug>
namespace GlSplat {
void Shader::define(const char* name, const char* value)
{
mDefines[std::string(name)] = value;
}
//--------------------------------------------------------------------------------
bool Shader::loadSources(const char* vsrc, const char* fsrc)
{
bool allIsOk = true;
mProgramID = viewer->glCreateProgram();
std::string defineStr = "";
for(DefineMap::iterator it = mDefines.begin() ; it!=mDefines.end() ; ++it)
{
defineStr += "#define " + it->first + " " + it->second + "\n";
}
if(vsrc)
{
GLuint shaderID = viewer->glCreateShader(GL_VERTEX_SHADER);
std::string source = defineStr + std::string(vsrc);
const GLchar * arbSource = source.c_str();
viewer->glShaderSource(shaderID, 1, (const GLchar **)&arbSource, 0);
viewer->glCompileShader(shaderID);
int compiled;
viewer->glGetShaderiv(shaderID,GL_COMPILE_STATUS,&compiled);
allIsOk = allIsOk && compiled;
//printInfoLog(shaderID);
viewer->glAttachShader(mProgramID, shaderID);
}
if(fsrc)
{
GLuint shaderID = viewer->glCreateShader(GL_FRAGMENT_SHADER);
std::string source = defineStr + std::string(fsrc);
const GLchar * arbSource = source.c_str();
viewer->glShaderSource(shaderID, 1, (const GLchar **)&arbSource, 0);
viewer->glCompileShader(shaderID);
int compiled;
viewer->glGetShaderiv(shaderID,GL_COMPILE_STATUS,&compiled);
allIsOk = allIsOk && compiled;
//printInfoLog(shaderID);
viewer->glAttachShader(mProgramID, shaderID);
}
viewer->glLinkProgram(mProgramID);
int isLinked;
viewer->glGetProgramiv(mProgramID, GL_LINK_STATUS, &isLinked);
allIsOk = allIsOk && isLinked;
mIsValid = isLinked == GL_TRUE;
printInfoLog(mProgramID);
return allIsOk;
}
//--------------------------------------------------------------------------------
void Shader::activate()
{
assert(mIsValid);
viewer->glUseProgram(mProgramID);
}
void Shader::release(void)
{
viewer->glUseProgram(0);
}
//--------------------------------------------------------------------------------
int Shader::getUniformLocation(const char* name)
{
assert(mIsValid);
int loc = viewer->glGetUniformLocation(mProgramID, name);
return loc;
}
//--------------------------------------------------------------------------------
void Shader::setSamplerUnit(const char* sampler, int unit)
{
activate();
viewer->glUniform1i(getUniformLocation(sampler), unit);
release();
}
//--------------------------------------------------------------------------------
int Shader::getAttribLocation(const char* name)
{
assert(mIsValid);
int loc = viewer->glGetAttribLocation(mProgramID, name);
return loc;
}
//--------------------------------------------------------------------------------
void Shader::printInfoLog(GLuint objectID)
{
int infologLength, charsWritten;
GLchar *infoLog;
viewer->glGetProgramiv(objectID,GL_INFO_LOG_LENGTH, &infologLength);
if(infologLength > 0)
{
infoLog = new GLchar[infologLength];
viewer->glGetProgramInfoLog(objectID, infologLength, &charsWritten, infoLog);
if (charsWritten>0)
std::cerr << "Shader info : \n" << infoLog << std::endl;
delete[] infoLog;
}
}
void Shader::setViewer(Viewer_interface *v)
{
viewer = v;
}
} // namepsace GlSplat

View File

@ -0,0 +1,139 @@
// This file is part of GlSplat, a simple splatting C++ library
//
// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
//
// GlSplat is free software; 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 2.1 of the License, or (at your option) any later version.
//
// GlSplat is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with GlSplat. If not, see <http://www.gnu.org/licenses/>.
#ifndef _GLSPLAT_Shader_h_
#define _GLSPLAT_Shader_h_
#include <string>
#include <map>
#include <QOpenGLFunctions_3_3_Core>
#include "Viewer_interface.h"
namespace GlSplat {
/** Permet de manipuler des shaders en GLSL (OpenGL2.0)
Exemple d'utilisation:
\code
// shader creation:
Shader* myShader = new Shader();
// loading from files (compilation + linking):
myShader->loadFromFiles("myShaderFile.vtx", "myShaderFile.frg");
// ...
// at rending time:
myShader->enable();
// draw objects
myShader->disable();
\endcode
*/
class Shader
{
public:
Shader(void)
: mIsValid(false)
{ }
~Shader()
{
}
void setViewer(Viewer_interface *);
/** add a \#define
*/
void define(const char* name, const char* value);
/** Compiles and links the shader from 2 source files
\param fileV vertex shader ("" if no vertex shader)
\param fileF fragment shader ("" if no fragment shader)
\return true if no error occurs
*/
// bool loadFromFiles(const std::string& fileV, const std::string& fileF);
bool loadSources(const char* vsrc, const char* fsrc);
/** Enable the shader
*/
void activate();
/** Releases the shader
*/
void release() ;
/** \return the index of the uniform variable \a name
*/
int getUniformLocation(const char* name);
/** Forces a sampler to a given unit
Example:
\code
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE2D, myTextureID);
myShader->setSamplerUnit("mySampler", 2);
\endcode
*/
void setSamplerUnit(const char* samplerName, int textureUnit);
/** \returns the index of the generic attribute \a name
Tp be used with glVertexAttrib*(...) ou glVertexAttribPointer(...)
Example:
\code
int tangentAttribID = myShader->getAttribLocation("tangent");
Vector3 tangent(...);
glVertexAttrib3fv(tangentAttribID, tangent);
// ou
Vector3* tangents = new Vector3[...];
glVertexAttribPointer(tangentAttribID, 3, GL_FLOAT, GL_FALSE, 0, tangents);
glEnableVertexAttribArray(tangentAttribID);
\endcode
*/
int getAttribLocation(const char* name);
inline void setUniform(const char* name, float a)
{ viewer->glUniform1f(viewer->glGetUniformLocation(mProgramID, name), a); }
inline void setUniform(const char* name, int a)
{ viewer->glUniform1i(viewer->glGetUniformLocation(mProgramID, name), a); }
inline void setUniform2(const char* name, float* a)
{ viewer->glUniform2fv(viewer->glGetUniformLocation(mProgramID, name), 1, a); }
inline void setUniform3(const char* name, float* a)
{ viewer->glUniform3fv(viewer->glGetUniformLocation(mProgramID, name), 1, a); }
inline void setUniform4(const char* name, float* a)
{ viewer->glUniform4fv(viewer->glGetUniformLocation(mProgramID, name), 1, a); }
inline void setUniform(const char* name, float a, float b)
{ viewer->glUniform2f(viewer->glGetUniformLocation(mProgramID, name), a, b); }
inline void setUniform(const char* name, float a, float b, float c)
{ viewer->glUniform3f(viewer->glGetUniformLocation(mProgramID, name), a, b, c); }
inline void setUniform(const char* name, float a, float b, float c, float d)
{ viewer->glUniform4f(viewer->glGetUniformLocation(mProgramID, name), a, b, c, d); }
Viewer_interface *viewer;
protected:
bool mIsValid;
typedef std::map<std::string,std::string> DefineMap;
DefineMap mDefines;
void printInfoLog(GLuint objectID);
GLuint mProgramID;
};
} // namepsace GlSplat
#endif

Some files were not shown because too many files have changed in this diff Show More