mirror of https://github.com/CGAL/cgal
this commit attempts to improve the projection step
we try to make the projection step keep vertices on the same connected component, wrt constrained edges there are some issues that need to be fixed : - the use of edge_is_constrained_map in the calle to PMP::connected_components() causes compilation errors. So it's commented for now - the patch ids that are stored in the reference aabb_tree (which remains valid through iterations) are not the same as the patch ids computed at the end of each iteration, in the projection step. It should be made consistent to be able to use the Filtered_projection_traits
This commit is contained in:
parent
36a133784d
commit
f4ce0f6eae
|
|
@ -0,0 +1,132 @@
|
|||
// Copyright (c) 2008-2009 INRIA Sophia-Antipolis (France), ETH Zurich (Switzerland).
|
||||
// Copyright (c) 2010 GeometryFactory Sarl (France)
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org); you may redistribute it under
|
||||
// the terms of the Q Public License version 1.0.
|
||||
// See the file LICENSE.QPL distributed with CGAL.
|
||||
//
|
||||
// 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) : Camille Wormser, Pierre Alliez, Stephane Tayeb, Laurent Rineau
|
||||
//
|
||||
// File adapted from <CGAL/internal/AABB_tree/AABB_traversal_traits.h>
|
||||
//
|
||||
|
||||
#ifndef CGAL_AABB_FILTERED_PROJECTION_TRAITS_H
|
||||
#define CGAL_AABB_FILTERED_PROJECTION_TRAITS_H
|
||||
|
||||
#include <CGAL/internal/boost/property_map.h>
|
||||
|
||||
#include <CGAL/AABB_tree.h>
|
||||
#include <CGAL/internal/AABB_tree/AABB_node.h>
|
||||
#include <CGAL/internal/AABB_tree/Primitive_helper.h>
|
||||
|
||||
namespace CGAL {
|
||||
namespace Polygon_mesh_processing {
|
||||
namespace internal {
|
||||
|
||||
/**
|
||||
* @class Projection_traits
|
||||
*/
|
||||
template <typename AABBTraits,
|
||||
typename IndexPropertyMap,
|
||||
bool keep = false>
|
||||
class Filtered_projection_traits
|
||||
{
|
||||
typedef typename AABBTraits::FT FT;
|
||||
typedef typename AABBTraits::Point_3 Point_3;
|
||||
typedef typename AABBTraits::Primitive Primitive;
|
||||
typedef typename AABBTraits::Bounding_box Bounding_box;
|
||||
typedef typename AABBTraits::Primitive::Id Primitive_id;
|
||||
typedef typename AABBTraits::Point_and_primitive_id Point_and_primitive_id;
|
||||
typedef typename AABBTraits::Object_and_primitive_id Object_and_primitive_id;
|
||||
typedef ::CGAL::AABB_node<AABBTraits> Node;
|
||||
typedef typename ::CGAL::AABB_tree<AABBTraits>::size_type size_type;
|
||||
|
||||
typedef typename boost::property_traits<IndexPropertyMap>::value_type Index_type;
|
||||
|
||||
typedef std::set<typename boost::remove_const<Index_type>::type> Set_of_indices;
|
||||
|
||||
public:
|
||||
template <typename IndexToIgnoreIterator>
|
||||
Filtered_projection_traits(IndexToIgnoreIterator begin,
|
||||
IndexToIgnoreIterator end,
|
||||
const AABBTraits& aabb_traits,
|
||||
IndexPropertyMap index_map = IndexPropertyMap())
|
||||
: m_closest_point_initialized(false),
|
||||
set_of_indices(begin, end),
|
||||
aabb_traits(aabb_traits),
|
||||
index_map(index_map)
|
||||
{
|
||||
}
|
||||
|
||||
Filtered_projection_traits(Index_type index,
|
||||
const AABBTraits& aabb_traits,
|
||||
IndexPropertyMap index_map = IndexPropertyMap())
|
||||
: m_closest_point_initialized(false),
|
||||
set_of_indices(),
|
||||
aabb_traits(aabb_traits),
|
||||
index_map(index_map)
|
||||
{
|
||||
set_of_indices.insert(index);
|
||||
}
|
||||
|
||||
bool go_further() const { return true; }
|
||||
|
||||
void intersection(const Point_3& query, const Primitive& primitive)
|
||||
{
|
||||
const Index_type& id = get(index_map, primitive);
|
||||
if(keep != (set_of_indices.count(id) > 0)) return;
|
||||
if(!m_closest_point_initialized) {
|
||||
typedef CGAL::internal::Primitive_helper<AABBTraits> Helper;
|
||||
m_closest_point = Helper::get_reference_point(primitive, aabb_traits);
|
||||
m_closest_primitive = primitive.id();
|
||||
m_closest_point_initialized = true;
|
||||
}
|
||||
Point_3 new_closest_point = aabb_traits.closest_point_object()
|
||||
(query, primitive, m_closest_point);
|
||||
if(new_closest_point != m_closest_point)
|
||||
{
|
||||
m_closest_primitive = primitive.id();
|
||||
m_closest_point = new_closest_point; // this effectively shrinks the sphere
|
||||
}
|
||||
}
|
||||
|
||||
bool do_intersect(const Point_3& query, const Node& node) const
|
||||
{
|
||||
if(!m_closest_point_initialized) return true;
|
||||
return AABBTraits().compare_distance_object()
|
||||
(query, node.bbox(), m_closest_point) == CGAL::SMALLER;
|
||||
}
|
||||
|
||||
bool found() { return m_closest_point_initialized; };
|
||||
|
||||
Point_3 closest_point() const { return m_closest_point; }
|
||||
Point_and_primitive_id closest_point_and_primitive() const
|
||||
{
|
||||
return Point_and_primitive_id(m_closest_point, m_closest_primitive);
|
||||
}
|
||||
|
||||
private:
|
||||
Point_3 m_closest_point;
|
||||
typename Primitive::Id m_closest_primitive;
|
||||
bool m_closest_point_initialized;
|
||||
Set_of_indices set_of_indices;
|
||||
const AABBTraits& aabb_traits;
|
||||
IndexPropertyMap index_map;
|
||||
}; // end Filtered_projection_traits
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace Polygon_mesh_processing
|
||||
} // end namespace CGAL
|
||||
|
||||
#endif // CGAL_MESH_3_AABB_FILTERED_PROJECTION_TRAITS_H
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
// Copyright (c) 2015 GeometryFactory (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s) : Jane Tournois
|
||||
|
||||
#ifndef CGAL_POLYGON_MESH_PROCESSING_AABB_TREE_REMESHING_H
|
||||
#define CGAL_POLYGON_MESH_PROCESSING_AABB_TREE_REMESHING_H
|
||||
|
||||
#include <CGAL/AABB_tree.h>
|
||||
#include <CGAL/AABB_traits.h>
|
||||
#include <CGAL/AABB_face_graph_triangle_primitive.h>
|
||||
#include <CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/AABB_filtered_projection_traits.h>
|
||||
|
||||
#include <CGAL/Polygon_mesh_processing/connected_components.h>
|
||||
|
||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
|
||||
template<typename PolygonMesh
|
||||
, typename VertexPointMap>
|
||||
class AABB_facet_primitive_remeshing
|
||||
: public CGAL::AABB_face_graph_triangle_primitive<PolygonMesh, VertexPointMap>
|
||||
{
|
||||
typedef CGAL::AABB_face_graph_triangle_primitive<PolygonMesh, VertexPointMap> Base;
|
||||
typedef typename boost::graph_traits<PolygonMesh>::face_iterator face_iterator;
|
||||
|
||||
public:
|
||||
AABB_facet_primitive_remeshing(face_iterator it,
|
||||
const PolygonMesh &pmesh,
|
||||
VertexPointMap vpm)
|
||||
: Base(it, pmesh, vpm)
|
||||
{}
|
||||
|
||||
void set_patch_id(const std::size_t& patch_id) {
|
||||
patch_id_ = patch_id;
|
||||
}
|
||||
std::size_t patch_id() const {
|
||||
return patch_id_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t patch_id_;
|
||||
};
|
||||
|
||||
template<typename PolygonMesh
|
||||
, typename VertexPointMap
|
||||
, typename GeomTraits
|
||||
>
|
||||
class AABB_tree_remeshing
|
||||
: public CGAL::AABB_tree<
|
||||
CGAL::AABB_traits<
|
||||
GeomTraits,
|
||||
AABB_facet_primitive_remeshing<PolygonMesh, VertexPointMap> > >
|
||||
{
|
||||
typedef PolygonMesh PM;
|
||||
typedef VertexPointMap VPMap;
|
||||
|
||||
typedef typename boost::graph_traits<PM>::face_iterator face_iterator;
|
||||
typedef typename boost::graph_traits<PM>::face_descriptor face_descriptor;
|
||||
|
||||
public:
|
||||
typedef AABB_facet_primitive_remeshing<PM, VPMap> AABB_primitive;
|
||||
typedef CGAL::AABB_traits<GeomTraits, AABB_primitive> AABB_traits;
|
||||
typedef CGAL::AABB_tree<AABB_traits> AABB_tree;
|
||||
|
||||
public:
|
||||
template<typename FaceIndexMap>
|
||||
void build(face_iterator fbegin,
|
||||
face_iterator fend,
|
||||
const PM& pmesh,
|
||||
VertexPointMap vpmap,
|
||||
FaceIndexMap fccmap)//connected components
|
||||
{
|
||||
for (face_iterator fit = fbegin; fit != fend; ++fit)
|
||||
{
|
||||
face_descriptor f = *fit;
|
||||
AABB_primitive prim(f, pmesh, vpmap);
|
||||
prim.set_patch_id(get(fccmap, f));
|
||||
this->insert(prim);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //CGAL_POLYGON_MESH_PROCESSING_AABB_TREE_REMESHING_H
|
||||
|
|
@ -25,12 +25,10 @@
|
|||
#include <CGAL/Polygon_mesh_processing/border.h>
|
||||
#include <CGAL/Polygon_mesh_processing/repair.h>
|
||||
#include <CGAL/Polygon_mesh_processing/measure.h>
|
||||
#include <CGAL/Polygon_mesh_processing/connected_components.h>
|
||||
#include <CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/AABB_tree_remeshing.h>
|
||||
|
||||
#include <CGAL/iterator.h>
|
||||
#include <CGAL/AABB_tree.h>
|
||||
#include <CGAL/AABB_traits.h>
|
||||
#include <CGAL/AABB_triangle_primitive.h>
|
||||
|
||||
#include <CGAL/boost/graph/Euler_operations.h>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
|
@ -151,11 +149,7 @@ namespace internal {
|
|||
typedef typename GeomTraits::Plane_3 Plane_3;
|
||||
typedef typename GeomTraits::Triangle_3 Triangle_3;
|
||||
|
||||
typedef std::list<Triangle_3> Triangle_list;
|
||||
typedef typename Triangle_list::iterator Tr_iterator;
|
||||
typedef CGAL::AABB_triangle_primitive<GeomTraits, Tr_iterator> Primitive;
|
||||
typedef CGAL::AABB_traits<GeomTraits, Primitive> Traits;
|
||||
typedef CGAL::AABB_tree<Traits> AABB_tree;
|
||||
typedef typename AABB_tree_remeshing<PM, VertexPointMap, GeomTraits> AABB_tree;
|
||||
|
||||
public:
|
||||
Incremental_remesher(PolygonMesh& pmesh
|
||||
|
|
@ -164,26 +158,12 @@ namespace internal {
|
|||
: mesh_(pmesh)
|
||||
, vpmap_(vpmap)
|
||||
, own_tree_(true)
|
||||
, input_triangles_()
|
||||
, halfedge_status_map_()
|
||||
, protect_constraints_(protect_constraints)
|
||||
{
|
||||
CGAL_assertion(CGAL::is_triangle_mesh(mesh_));
|
||||
|
||||
//build AABB tree of input surface
|
||||
//todo : add a constructor with aabb_tree as parameter
|
||||
//todo : do we really need to keep this copy of the input surface?
|
||||
BOOST_FOREACH(face_descriptor f, faces(mesh_))
|
||||
{
|
||||
halfedge_descriptor h = halfedge(f, mesh_);
|
||||
vertex_descriptor v1 = target(h, mesh_);
|
||||
vertex_descriptor v2 = target(next(h, mesh_), mesh_);
|
||||
vertex_descriptor v3 = target(next(next(h, mesh_), mesh_), mesh_);
|
||||
input_triangles_.push_back(
|
||||
Triangle_3(get(vpmap, v1), get(vpmap, v2), get(vpmap, v3)));
|
||||
}
|
||||
tree_ptr_ = new AABB_tree(input_triangles_.begin(), input_triangles_.end());
|
||||
tree_ptr_->accelerate_distance_queries();
|
||||
}
|
||||
|
||||
~Incremental_remesher()
|
||||
|
|
@ -206,6 +186,19 @@ namespace internal {
|
|||
}
|
||||
}
|
||||
tag_halfedges_status(face_range, ecmap);
|
||||
|
||||
//build AABB tree of input surface
|
||||
//collect connected components
|
||||
boost::vector_property_map<int,
|
||||
boost::property_map<PM, boost::face_index_t>::type>
|
||||
fccmap(get(boost::face_index, mesh_));
|
||||
PMP::connected_components(mesh_,
|
||||
fccmap);
|
||||
// PMP::parameters::edge_is_constrained_map(ecmap));
|
||||
|
||||
tree_ptr_ = new AABB_tree();
|
||||
tree_ptr_->build(faces(mesh_).first, faces(mesh_).second, mesh_, vpmap_, fccmap);
|
||||
tree_ptr_->accelerate_distance_queries();
|
||||
}
|
||||
|
||||
// split edges of edge_range that have their length > high
|
||||
|
|
@ -816,7 +809,21 @@ namespace internal {
|
|||
{
|
||||
if (!is_on_patch(v))
|
||||
continue;
|
||||
put(vpmap_, v, tree_ptr_->closest_point(get(vpmap_, v)));
|
||||
|
||||
// if the vertex is not on the destination polyhedron
|
||||
typedef std::map<face_descriptor, std::size_t> FaceCCMap;
|
||||
FaceCCMap f_cc;
|
||||
boost::associative_property_map<FaceCCMap> face_ccmap(f_cc);
|
||||
|
||||
PMP::connected_components(mesh_,
|
||||
face_ccmap);
|
||||
// PMP::parameters::edge_is_constrained_map(Constraint_property_map()));
|
||||
|
||||
Point proj = this->project_vertex_onto(v,
|
||||
get(face_ccmap, face(halfedge(v, mesh_), mesh_)),
|
||||
face_ccmap);
|
||||
|
||||
put(vpmap_, v, proj);
|
||||
}
|
||||
|
||||
CGAL_assertion(is_valid(mesh_));
|
||||
|
|
@ -834,6 +841,59 @@ namespace internal {
|
|||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
//struct Constraint_property_map
|
||||
//{
|
||||
// typedef boost::readable_property_map_tag category;
|
||||
// typedef bool value_type;
|
||||
// typedef bool reference;
|
||||
// typedef edge_descriptor key_type;
|
||||
|
||||
// bool operator[](const edge_descriptor& e) {
|
||||
// return is_on_border(e) || is_on_patch_border(e);
|
||||
// }
|
||||
// friend bool get(const Constraint_property_map& map,
|
||||
// const edge_descriptor& e) {
|
||||
// return is_on_border(e) || is_on_patch_border(e);
|
||||
// }
|
||||
//};
|
||||
|
||||
struct AABB_CC_property_map
|
||||
{
|
||||
typedef boost::readable_property_map_tag category;
|
||||
typedef std::size_t value_type;
|
||||
typedef std::size_t& reference;
|
||||
typedef typename AABB_tree::AABB_primitive key_type;
|
||||
|
||||
value_type operator[](const key_type& f)
|
||||
{
|
||||
return f.patch_id();
|
||||
}
|
||||
friend value_type get(const AABB_CC_property_map& map,
|
||||
const key_type& f) {
|
||||
return f.patch_id();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename FaceCCMap>
|
||||
Point project_vertex_onto(vertex_descriptor v,
|
||||
std::size_t patch_id,
|
||||
const FaceCCMap& fccmap) const
|
||||
{
|
||||
internal::Filtered_projection_traits<typename AABB_tree::AABB_traits,
|
||||
AABB_CC_property_map,
|
||||
true> /* keep primitives with matching IDs */
|
||||
projection_traits(
|
||||
typename boost::property_traits<AABB_CC_property_map>::value_type(patch_id),
|
||||
tree_ptr_->traits(),
|
||||
AABB_CC_property_map());
|
||||
|
||||
tree_ptr_->traversal(get(vpmap_, v), projection_traits);
|
||||
|
||||
CGAL_assertion(projection_traits.found());
|
||||
return projection_traits.closest_point();
|
||||
}
|
||||
|
||||
private:
|
||||
double sqlength(const vertex_descriptor& v1,
|
||||
const vertex_descriptor& v2) const
|
||||
|
|
@ -1223,6 +1283,7 @@ namespace internal {
|
|||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
bool is_on_patch_border(const halfedge_descriptor& h) const
|
||||
{
|
||||
bool res = (status(h) == PATCH_BORDER);
|
||||
|
|
@ -1269,6 +1330,7 @@ namespace internal {
|
|||
return status(h) == MESH;
|
||||
}
|
||||
|
||||
private:
|
||||
void halfedge_added(const halfedge_descriptor& h,
|
||||
const Halfedge_status& s)
|
||||
{
|
||||
|
|
@ -1372,9 +1434,8 @@ namespace internal {
|
|||
private:
|
||||
PolygonMesh& mesh_;
|
||||
VertexPointMap& vpmap_;
|
||||
const AABB_tree* tree_ptr_;
|
||||
AABB_tree* tree_ptr_;
|
||||
bool own_tree_;
|
||||
Triangle_list input_triangles_;
|
||||
boost::unordered_map<halfedge_descriptor, Halfedge_status> halfedge_status_map_;
|
||||
bool protect_constraints_;
|
||||
std::set<edge_descriptor> constrained_edges_;
|
||||
|
|
|
|||
Loading…
Reference in New Issue