From a764322b7df6d9b470c7d10585ca29767497a63f Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 17 Jul 2018 10:04:14 +0200 Subject: [PATCH 01/84] Create a dummy traits and fix AABB_traits and AABBTraits implem/doc problems. --- AABB_tree/doc/AABB_tree/Concepts/AABBTraits.h | 40 ++--- AABB_tree/include/CGAL/AABB_traits.h | 6 +- .../include/CGAL/AABB_transformed_traits.h | 138 ++++++++++++++++++ .../CGAL/internal/AABB_tree/AABB_node.h | 2 +- .../test/AABB_tree/aabb_any_all_benchmark.cpp | 4 +- .../Minkowski_sum_2/AABB_node_with_join.h | 2 +- .../CGAL/Minkowski_sum_2/AABB_traits_2.h | 6 +- 7 files changed, 160 insertions(+), 38 deletions(-) create mode 100644 AABB_tree/include/CGAL/AABB_transformed_traits.h diff --git a/AABB_tree/doc/AABB_tree/Concepts/AABBTraits.h b/AABB_tree/doc/AABB_tree/Concepts/AABBTraits.h index 123bda80c47..2b46d8dea03 100644 --- a/AABB_tree/doc/AABB_tree/Concepts/AABBTraits.h +++ b/AABB_tree/doc/AABB_tree/Concepts/AABBTraits.h @@ -75,25 +75,17 @@ using Intersection_and_primitive_id = unspecified_type; /// \name Splitting /// During the construction of the AABB tree, the primitives are -/// sorted according to some comparison functions related to the \f$x\f$, -/// \f$ y\f$ or \f$ z\f$ coordinate axis: +/// splitted according to some comparison functions related to the longest axis: /// @{ /*! -A functor object to split a range of primitives into two sub-ranges along the X-axis. Provides the operator: -`void operator()(InputIterator first, InputIterator beyond);` %Iterator type `InputIterator` must be a model of RandomAccessIterator and have `Primitive` as value type. The operator is used for determining the primitives assigned to the two children nodes of a given node, assuming that the goal is to split the X-dimension of the bounding box of the node. The primitives assigned to this node are passed as argument to the operator. It should modify the iterator range in such a way that its first half and its second half correspond to the two children nodes. +A functor object to split a range of primitives into two sub-ranges along the longest axis. Provides the operator: + `void operator()(InputIterator first, InputIterator beyond);` %Iterator type `InputIterator` must be a model of RandomAccessIterator + and have `Primitive` as value type. The operator is used for determining the primitives assigned to the two children nodes of a given node, + assuming that the goal is to split the chosen axis dimension of the bounding box of the node. The primitives assigned to this node are passed as argument + to the operator. It should modify the iterator range in such a way that its first half and its second half correspond to the two children nodes. */ -typedef unspecified_type Split_primitives_along_x_axis; - -/*! -A functor object to split a range of primitives into two sub-ranges along the Y-axis. See `Split_primitives_along_x_axis` for the detailed description. -*/ -typedef unspecified_type Split_primitives_along_y_axis; - -/*! -A functor object to split a range of primitives into two sub-ranges along the Z-axis. See `Split_primitives_along_x_axis` for the detailed description. -*/ -typedef unspecified_type Split_primitives_along_z_axis; +typedef unspecified_type Split_primitives; /*! A functor object to compute the bounding box of a set of primitives. Provides the operator: @@ -132,7 +124,7 @@ A functor object to compute the intersection of a query and a primitive. Provide \cgalHeading{Note on Backward Compatibility} Before the release 4.3 of \cgal, the return type of this function used to be `boost::optional`. */ -typedef unspecified_type Intersect; +typedef unspecified_type Intersection; /// \name Distance Queries /// The following predicates are required for each @@ -170,19 +162,9 @@ typedef unspecified_type Equal_3; /// @{ /*! -Returns the primitive splitting functor for the X axis. +Returns the primitive splitting functor. */ -Split_primitives_along_x_axis split_primitives_along_x_axis_object(); - -/*! -Returns the primitive splitting functor for the Y axis. -*/ -Split_primitives_along_y_axis split_primitives_along_y_axis_object(); - -/*! -Returns the primitive splitting functor for the Z axis. -*/ -Split_primitives_along_z_axis split_primitives_along_z_axis_object(); +Split_primitives split_primitives_object(); /*! Returns the bounding box constructor. @@ -197,7 +179,7 @@ Do_intersect do_intersect_object(); /*! Returns the intersection constructor. */ -Intersect intersect_object(); +Intersection intersection_object(); /*! Returns the distance comparison functor. diff --git a/AABB_tree/include/CGAL/AABB_traits.h b/AABB_tree/include/CGAL/AABB_traits.h index 632f2256d4b..42540c0a764 100644 --- a/AABB_tree/include/CGAL/AABB_traits.h +++ b/AABB_tree/include/CGAL/AABB_traits.h @@ -289,12 +289,12 @@ public: * Sorts the range defined by [first,beyond[. Sort is achieved on bbox longuest * axis, using the comparison function `_less_than` (dim in {x,y,z}) */ - class Sort_primitives + class Split_primitives { typedef AABB_traits Traits; const Traits& m_traits; public: - Sort_primitives(const AABB_traits& traits) + Split_primitives(const AABB_traits& traits) : m_traits(traits) {} template @@ -320,7 +320,7 @@ public: } }; - Sort_primitives sort_primitives_object() const {return Sort_primitives(*this);} + Split_primitives split_primitives_object() const {return Split_primitives(*this);} /* diff --git a/AABB_tree/include/CGAL/AABB_transformed_traits.h b/AABB_tree/include/CGAL/AABB_transformed_traits.h new file mode 100644 index 00000000000..b78aad44f54 --- /dev/null +++ b/AABB_tree/include/CGAL/AABB_transformed_traits.h @@ -0,0 +1,138 @@ + +// Copyright (c) 2018 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$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Maxime Gimeno +// + +#ifndef CGAL_AABB_TRANSFORMED_TRAITS_H +#define CGAL_AABB_TRANSFORMED_TRAITS_H + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +/// \file AABB_transformed_traits.h + +namespace CGAL { + +/// \addtogroup PkgAABB_tree +/// @{ + +/// \tparam BaseTraits a model of `CGAL::AABBTraits` +/// +/// \sa `AABBTraits` +/// \sa `AABB_tree` +/// \sa `AABBPrimitive` +/// \sa `AABBPrimitiveWithSharedData` + + template +class AABB_transformed_traits: + public BaseTraits +{ + typedef typename CGAL::Object Object; +public: + typedef BaseTraits Geom_traits; + + // AABBTraits concept types + typedef typename BaseTraits::FT FT; + typedef typename BaseTraits::Point_3 Point_3; + typedef typename BaseTraits::Primitive Primitive; + typedef typename BaseTraits::Bounding_box Bounding_box; + typedef typename BaseTraits::Point_and_primitive_id Point_and_primitive_id; + typedef typename BaseTraits::Object_and_primitive_id Object_and_primitive_id; + template + struct Intersection_and_primitive_id { + typedef typename BaseTraits::template Intersection_and_primitive_id::Intersection_type Intersection_type; + + typedef typename BaseTraits::template Intersection_and_primitive_id::Type Type; + }; + + //SearchGeomTriats_3 concept types + typedef typename BaseTraits::Iso_cuboid_3 Iso_cuboid_3; + typedef typename BaseTraits::Sphere_3 Sphere_3; + typedef typename BaseTraits::Construct_iso_cuboid_3 Construct_iso_cuboid_3; + typedef typename BaseTraits::Construct_min_vertex_3 Construct_min_vertex_3; + typedef typename BaseTraits::Construct_max_vertex_3 Construct_max_vertex_3; + typedef typename BaseTraits::Construct_center_3 Construct_center_3; + typedef typename BaseTraits::Compute_squared_radius_3 Compute_squared_radius_3; + typedef typename BaseTraits::Cartesian_const_iterator_3 Cartesian_const_iterator_3; + typedef typename BaseTraits::Construct_cartesian_const_iterator_3 Construct_cartesian_const_iterator_3; + + //Splitting + typedef typename BaseTraits::Split_primitives Split_primitives; + typedef typename BaseTraits::Compute_bbox Compute_bbox; + + //Intersections + typedef typename BaseTraits::Do_intersect Do_intersect; + //typedef typename BaseTraits::Intersect Intersect; + typedef typename BaseTraits::Intersection Intersection; + + //Distance Queries + typedef typename BaseTraits::Compare_distance Compare_distance; + typedef typename BaseTraits::Closest_point Closest_point ; + typedef typename BaseTraits::Squared_distance Squared_distance; + typedef typename BaseTraits::Equal_3 Equal_3 ; + + //Operations + Split_primitives split_primitives_object() const { + return BaseTraits::split_primitives_object(); + } + + Compute_bbox compute_bbox_object() const{ + return BaseTraits::compute_bbox_object(); + } + Do_intersect do_intersect_3_object() const{ + return BaseTraits::do_intersect_3_object(); + } + + Intersection intersection_object() const{ + return BaseTraits::intersection_object(); + } + + Compare_distance compare_distance_object() const{ + return BaseTraits::compare_distance_object(); + } + Closest_point closest_point_object() const{ + return BaseTraits::closest_point_object(); + } + Squared_distance squared_distance_object() const{ + return BaseTraits::squared_distance_object(); + } + Equal_3 equal_3_object() const{ + return BaseTraits::equal_3_object; + } +}; + + +} // end namespace CGAL + +#include + +#endif // CGAL_AABB_TRANSFORMED_TRAITS_H diff --git a/AABB_tree/include/CGAL/internal/AABB_tree/AABB_node.h b/AABB_tree/include/CGAL/internal/AABB_tree/AABB_node.h index e3504a615ab..5d0cf5ce4d2 100644 --- a/AABB_tree/include/CGAL/internal/AABB_tree/AABB_node.h +++ b/AABB_tree/include/CGAL/internal/AABB_tree/AABB_node.h @@ -138,7 +138,7 @@ AABB_node::expand(ConstPrimitiveIterator first, m_bbox = traits.compute_bbox_object()(first, beyond); // sort primitives along longest axis aabb - traits.sort_primitives_object()(first, beyond, m_bbox); + traits.split_primitives_object()(first, beyond, m_bbox); switch(range) { diff --git a/AABB_tree/test/AABB_tree/aabb_any_all_benchmark.cpp b/AABB_tree/test/AABB_tree/aabb_any_all_benchmark.cpp index 394bce109b5..5a14a58a893 100644 --- a/AABB_tree/test/AABB_tree/aabb_any_all_benchmark.cpp +++ b/AABB_tree/test/AABB_tree/aabb_any_all_benchmark.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -70,7 +71,8 @@ boost::tuple test(const char* name) typedef CGAL::Polyhedron_3 Polyhedron; typedef CGAL::AABB_face_graph_triangle_primitive Primitive; - typedef CGAL::AABB_traits Traits; + typedef CGAL::AABB_traits Base_Traits; + typedef CGAL::AABB_transformed_traits Traits; typedef CGAL::AABB_tree Tree; std::ifstream ifs(name); diff --git a/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/AABB_node_with_join.h b/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/AABB_node_with_join.h index d2ae2d1303f..85e40e511ca 100644 --- a/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/AABB_node_with_join.h +++ b/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/AABB_node_with_join.h @@ -151,7 +151,7 @@ AABB_node_with_join::expand(ConstPrimitiveIterator first, m_bbox = traits.compute_bbox_object()(first, beyond); // sort primitives along longest axis aabb - traits.sort_primitives_object()(first, beyond, m_bbox); + traits.split_primitives_object()(first, beyond, m_bbox); switch(range) { diff --git a/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/AABB_traits_2.h b/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/AABB_traits_2.h index 1eb99e9e72a..b0f65bc63a3 100644 --- a/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/AABB_traits_2.h +++ b/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/AABB_traits_2.h @@ -90,7 +90,7 @@ public: // Put the n/2 smallest primitives in the front, the n/2 largest primitives // in the back. They are compared along the bbox' longest axis. - class Sort_primitives + class Split_primitives { public: template @@ -111,9 +111,9 @@ public: } }; - Sort_primitives sort_primitives_object() const + Split_primitives split_primitives_object() const { - return Sort_primitives(); + return Split_primitives(); } // Computes the bounding box of a set of primitives From d2f4e19e36d2be6b3d31ed2bc9585038792ef149 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 17 Jul 2018 13:52:24 +0200 Subject: [PATCH 02/84] Add transformations to the new traits and add a test for it. --- .../include/CGAL/AABB_transformed_traits.h | 70 +++++++++++++++---- .../test/AABB_tree/aabb_any_all_benchmark.cpp | 4 +- .../aabb_test_transformed_traits.cpp | 61 ++++++++++++++++ 3 files changed, 118 insertions(+), 17 deletions(-) create mode 100644 AABB_tree/test/AABB_tree/aabb_test_transformed_traits.cpp diff --git a/AABB_tree/include/CGAL/AABB_transformed_traits.h b/AABB_tree/include/CGAL/AABB_transformed_traits.h index b78aad44f54..20788e833d9 100644 --- a/AABB_tree/include/CGAL/AABB_transformed_traits.h +++ b/AABB_tree/include/CGAL/AABB_transformed_traits.h @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -52,14 +53,17 @@ namespace CGAL { /// \sa `AABBPrimitive` /// \sa `AABBPrimitiveWithSharedData` - template + template class AABB_transformed_traits: public BaseTraits { - typedef typename CGAL::Object Object; public: - typedef BaseTraits Geom_traits; + //Constructor + AABB_transformed_traits(const Aff_transformation_3& transf = Aff_transformation_3(IDENTITY)) + :m_transfo(transf) + {} // AABBTraits concept types typedef typename BaseTraits::FT FT; typedef typename BaseTraits::Point_3 Point_3; @@ -86,19 +90,45 @@ public: typedef typename BaseTraits::Construct_cartesian_const_iterator_3 Construct_cartesian_const_iterator_3; //Splitting - typedef typename BaseTraits::Split_primitives Split_primitives; - typedef typename BaseTraits::Compute_bbox Compute_bbox; + typedef typename BaseTraits::Split_primitives Split_primitives; + + typedef typename BaseTraits::Compute_bbox Compute_bbox; //Intersections - typedef typename BaseTraits::Do_intersect Do_intersect; - //typedef typename BaseTraits::Intersect Intersect; - typedef typename BaseTraits::Intersection Intersection; + class Do_intersect { + const AABB_transformed_traits& m_traits; + public: + Do_intersect(const AABB_transformed_traits& traits) + :m_traits(traits) {} + + template + bool operator()(const Query& q, const Bounding_box& bbox) const + { + Point_3 min(bbox.xmin(), bbox.ymin(), bbox.zmin()), + max(bbox.xmax(), bbox.ymax(), bbox.zmax()); + + min = m_traits.transformation().transform(min); + max = m_traits.transformation().transform(max); + Bounding_box transfo_box(to_double(min.x()), to_double(min.y()), to_double(min.z()), + to_double(max.x()), to_double(max.y()), to_double(max.z())); + bool res = CGAL::do_intersect(q, transfo_box); + return res; + } + + template + bool operator()(const Query& q, const Primitive& pr) const + { + return Kernel().do_intersect_3_object()(q, internal::Primitive_helper::get_datum(pr,m_traits).transform(m_traits.transformation())); + } + }; + + typedef typename BaseTraits::Intersection Intersection; //Distance Queries - typedef typename BaseTraits::Compare_distance Compare_distance; - typedef typename BaseTraits::Closest_point Closest_point ; - typedef typename BaseTraits::Squared_distance Squared_distance; - typedef typename BaseTraits::Equal_3 Equal_3 ; + typedef typename BaseTraits::Compare_distance Compare_distance; + typedef typename BaseTraits::Closest_point Closest_point ; + typedef typename BaseTraits::Squared_distance Squared_distance; + typedef typename BaseTraits::Equal_3 Equal_3 ; //Operations Split_primitives split_primitives_object() const { @@ -108,8 +138,8 @@ public: Compute_bbox compute_bbox_object() const{ return BaseTraits::compute_bbox_object(); } - Do_intersect do_intersect_3_object() const{ - return BaseTraits::do_intersect_3_object(); + Do_intersect do_intersect_object() const{ + return Do_intersect(*this); } Intersection intersection_object() const{ @@ -128,6 +158,18 @@ public: Equal_3 equal_3_object() const{ return BaseTraits::equal_3_object; } + + //Specific + void set_transformation(const Aff_transformation_3& trans) const + { + m_transfo = trans; + } + + const Aff_transformation_3& transformation() const { return m_transfo; } + +private: + mutable Aff_transformation_3 m_transfo; + }; diff --git a/AABB_tree/test/AABB_tree/aabb_any_all_benchmark.cpp b/AABB_tree/test/AABB_tree/aabb_any_all_benchmark.cpp index 5a14a58a893..394bce109b5 100644 --- a/AABB_tree/test/AABB_tree/aabb_any_all_benchmark.cpp +++ b/AABB_tree/test/AABB_tree/aabb_any_all_benchmark.cpp @@ -13,7 +13,6 @@ #include #include -#include #include #include @@ -71,8 +70,7 @@ boost::tuple test(const char* name) typedef CGAL::Polyhedron_3 Polyhedron; typedef CGAL::AABB_face_graph_triangle_primitive Primitive; - typedef CGAL::AABB_traits Base_Traits; - typedef CGAL::AABB_transformed_traits Traits; + typedef CGAL::AABB_traits Traits; typedef CGAL::AABB_tree Tree; std::ifstream ifs(name); diff --git a/AABB_tree/test/AABB_tree/aabb_test_transformed_traits.cpp b/AABB_tree/test/AABB_tree/aabb_test_transformed_traits.cpp new file mode 100644 index 00000000000..afbb9c28ba5 --- /dev/null +++ b/AABB_tree/test/AABB_tree/aabb_test_transformed_traits.cpp @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef CGAL::Epick K; +typedef K::FT FT; +typedef K::Point_3 Point; +typedef K::Vector_3 Vector; +typedef K::Segment_3 Segment; +typedef K::Ray_3 Ray; +typedef CGAL::Polyhedron_3 Polyhedron; +typedef CGAL::AABB_face_graph_triangle_primitive Primitive; +typedef CGAL::AABB_traits Base_traits; +typedef CGAL::AABB_transformed_traits Traits; +typedef CGAL::AABB_tree Tree; +typedef Tree::Primitive_id Primitive_id; + +int main() +{ + typedef std::vector< Tree::Intersection_and_primitive_id::Type > IntersectionVector; + Polyhedron polyhedron; + std::ifstream in("data/bunny00.off"); + if(in) + in >> polyhedron; + else{ + std::cout << "error reading bunny" << std::endl; + return 1; + } + CGAL::Aff_transformation_3 transfo(CGAL::TRANSLATION, Vector(250,300,1)); + IntersectionVector all_intersections; + Tree tree(faces(polyhedron).first, faces(polyhedron).second, polyhedron); + tree.traits().set_transformation(transfo); + tree.build(); + tree.traits().set_transformation(CGAL::Aff_transformation_3(CGAL::IDENTITY)); + Point bunny_center = + CGAL::centroid(polyhedron.points_begin(), polyhedron.points_end()); + + Ray ray1(Point(0,0,-10),bunny_center); + tree.all_intersections(ray1, std::back_inserter(all_intersections)); + std::size_t nb_inter = all_intersections.size(); + std::cout< Date: Tue, 17 Jul 2018 14:08:30 +0200 Subject: [PATCH 03/84] add a naive way to intersect two AABB-trees --- AABB_tree/include/CGAL/AABB_traits.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/AABB_tree/include/CGAL/AABB_traits.h b/AABB_tree/include/CGAL/AABB_traits.h index 42540c0a764..827fdd23afd 100644 --- a/AABB_tree/include/CGAL/AABB_traits.h +++ b/AABB_tree/include/CGAL/AABB_traits.h @@ -176,6 +176,10 @@ struct AABB_traits_base_2{ /// \addtogroup PkgAABB_tree /// @{ +// forward declaration +template< typename AABBTraits> +class AABB_tree; + /// This traits class handles any type of 3D geometric /// primitives provided that the proper intersection tests and /// constructions are implemented. It handles points, rays, lines and @@ -369,6 +373,19 @@ public: { return GeomTraits().do_intersect_3_object()(q, internal::Primitive_helper::get_datum(pr,m_traits)); } + + // intersection with AABB-tree + template + bool operator()(const CGAL::AABB_tree& other_tree, const Primitive& pr) const + { + return other_tree.do_intersect( internal::Primitive_helper::get_datum(pr,m_traits) ); + } + + template + bool operator()(const CGAL::AABB_tree& other_tree, const Bounding_box& bbox) const + { + return other_tree.do_intersect(bbox); + } }; Do_intersect do_intersect_object() const {return Do_intersect(*this);} From 36fd62f8c6ae0be6ca26d27279e1830b8d883036 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 17 Jul 2018 16:59:22 +0200 Subject: [PATCH 04/84] Add benchmark for tree intersection --- AABB_tree/benchmark/AABB_tree/CMakeLists.txt | 41 + AABB_tree/benchmark/AABB_tree/data/handle.off | 3495 +++++++++++++++++ AABB_tree/benchmark/AABB_tree/test.cpp | 100 + .../include/CGAL/AABB_transformed_traits.h | 26 +- 4 files changed, 3660 insertions(+), 2 deletions(-) create mode 100644 AABB_tree/benchmark/AABB_tree/CMakeLists.txt create mode 100644 AABB_tree/benchmark/AABB_tree/data/handle.off create mode 100644 AABB_tree/benchmark/AABB_tree/test.cpp diff --git a/AABB_tree/benchmark/AABB_tree/CMakeLists.txt b/AABB_tree/benchmark/AABB_tree/CMakeLists.txt new file mode 100644 index 00000000000..077df0007ca --- /dev/null +++ b/AABB_tree/benchmark/AABB_tree/CMakeLists.txt @@ -0,0 +1,41 @@ +# Created by the script cgal_create_CMakeLists +# This is the CMake script for compiling a set of CGAL applications. + +project( AABB_traits_benchmark) + + +cmake_minimum_required(VERSION 3.1) + cmake_policy(VERSION 3.1) + + +if ( COMMAND cmake_policy ) + + cmake_policy( SET CMP0003 NEW ) + +endif() + +# CGAL and its components +find_package( CGAL QUIET) +if ( CGAL_FOUND ) + include( ${CGAL_USE_FILE} ) +else () + message(STATUS "This project requires the CGAL library, and will not be compiled.") + return() + +endif() + + +# Boost and its components +find_package( Boost REQUIRED ) +# include for local directory +if ( NOT Boost_FOUND ) + message(STATUS "This project requires the Boost library, and will not be compiled.") + return() +endif() + +# include for local package +include_directories( BEFORE ../../include ) + +add_executable (test_ test.cpp) + + diff --git a/AABB_tree/benchmark/AABB_tree/data/handle.off b/AABB_tree/benchmark/AABB_tree/data/handle.off new file mode 100644 index 00000000000..1b4c7ffbfe2 --- /dev/null +++ b/AABB_tree/benchmark/AABB_tree/data/handle.off @@ -0,0 +1,3495 @@ +OFF +1165 2326 0 + +-0.5 -0.153364 0 +-0.5 -0.145472 -0.123072 +-0.5 -0.145472 0.123072 +-0.5 -0.131604 -0.204475 +-0.5 -0.122132 -0.245084 +-0.5 -0.122132 0.245084 +-0.5 -0.06 0 +-0.5 -0.0588999 -0.01144 +-0.5 -0.0588999 0.01144 +-0.5 -0.0557159 -0.022268 +-0.5 -0.0557159 0.022268 +-0.5 -0.052588 -0.0288879 +-0.5 -0.050768 0.0319758 +-0.5 -0.0474238 -0.0367521 +-0.5 -0.0422279 0.0426238 +-0.5 -0.0398639 -0.0448439 +-0.5 -0.03388 0.0495199 +-0.5 -0.0333279 -0.0498919 +-0.5 -0.026544 0.053808 +-0.5 -0.0259439 -0.0540999 +-0.5 -0.018904 0.056944 +-0.5 -0.015804 -0.0578799 +-0.5 -0.00754798 0.059524 +-0.5 -0.002308 -0.0599558 +-0.5 0.00308399 0.0599199 +-0.5 0.008572 -0.0593841 +-0.5 0.01408 0.0583239 +-0.5 0.0195399 -0.0567281 +-0.5 0.024872 0.0546 +-0.5 0.03 -0.0519599 +-0.5 0.034848 0.0488401 +-0.5 0.039356 -0.0452879 +-0.5 0.0434681 0.0413558 +-0.5 0.0471437 -0.037116 +-0.5 0.050352 0.0326319 +-0.5 0.0513119 -0.031096 +-0.5 0.055324 0.023224 +-0.5 0.055544 -0.0226959 +-0.5 0.0587678 -0.0121 +-0.5 0.0587678 0.0121 +-0.5 0.06 0 +-0.5 0.122132 -0.245084 +-0.5 0.122132 0.245084 +-0.5 0.131604 0.204475 +-0.5 0.145472 -0.123072 +-0.5 0.145472 0.123072 +-0.5 0.153364 0 +-0.499816 -0.126076 0.245176 +-0.499816 0.126076 -0.245176 +-0.499583 -0.12108 -0.250841 +-0.499583 0.12108 0.250841 +-0.499477 0.124444 -0.25072 +-0.499458 0.122748 -0.251432 +-0.499458 0.12602 -0.249804 +-0.499417 0.127408 -0.248739 +-0.499399 -0.137264 -0.210963 +-0.499399 0.137264 0.210963 +-0.499396 -0.152344 -0.123952 +-0.499396 -0.152344 0.123952 +-0.499396 0.152344 -0.123952 +-0.499396 0.152344 0.123952 +-0.499392 -0.160308 0 +-0.499392 0.160308 0 +-0.49934 0.128816 -0.247291 +-0.499246 -0.12088 0.252811 +-0.499246 0.12088 -0.252811 +-0.499227 -0.130112 -0.245444 +-0.499227 0.130112 0.245444 +-0.498925 -0.131512 0.245571 +-0.498925 0.131512 -0.245571 +-0.498835 -0.129156 0.25086 +-0.498801 -0.120744 -0.2548 +-0.498801 0.120744 0.2548 +-0.498433 -0.129056 -0.253028 +-0.498433 0.12906 0.253028 +-0.498128 0.126868 -0.255655 +-0.4981 -0.12884 0.254631 +-0.4981 0.123844 -0.25688 +-0.498056 0.129668 -0.254044 +-0.49791 0.13212 -0.252139 +-0.497657 0.134556 -0.24954 +-0.497467 -0.144212 -0.212476 +-0.497467 0.144212 0.212476 +-0.497442 -0.159432 -0.12486 +-0.497442 -0.159432 0.12486 +-0.497442 0.159432 -0.12486 +-0.497442 0.159432 0.12486 +-0.49743 -0.167467 0 +-0.49743 0.167467 0 +-0.497171 -0.120668 0.25986 +-0.497171 0.120668 -0.25986 +-0.497087 -0.137288 -0.246275 +-0.497087 0.137288 0.246275 +-0.496623 -0.13838 0.246439 +-0.496623 0.13838 -0.246439 +-0.496592 0.135432 0.253396 +-0.496526 -0.120712 -0.261387 +-0.496526 0.120712 0.261387 +-0.496427 -0.135844 -0.253427 +-0.496402 0.128968 -0.259603 +-0.496383 0.124964 -0.261172 +-0.496321 -0.12888 -0.25996 +-0.496314 0.128888 0.259955 +-0.496252 0.132664 -0.257492 +-0.496249 -0.137512 0.25136 +-0.495969 0.135876 -0.25496 +-0.495928 -0.128764 0.260992 +-0.495545 -0.137216 0.254795 +-0.495517 0.139024 -0.251484 +-0.49447 0.135236 0.259987 +-0.494311 -0.135636 -0.259992 +-0.494177 -0.120972 0.265864 +-0.494177 0.120972 -0.265864 +-0.494074 -0.150996 -0.213951 +-0.494074 0.150996 0.213951 +-0.494015 -0.166348 -0.125748 +-0.494015 -0.166348 0.125748 +-0.494015 0.166348 -0.125748 +-0.494015 0.166348 0.125748 +-0.493984 -0.17446 0 +-0.493984 0.17446 0 +-0.493984 -0.143332 -0.247299 +-0.493984 0.143332 0.247299 +-0.493741 -0.143712 0.247376 +-0.493741 0.143712 -0.247376 +-0.493489 -0.13708 0.260624 +-0.493327 -0.142968 0.251887 +-0.49332 0.142076 0.2539 +-0.493274 -0.129116 -0.265888 +-0.493274 0.129124 0.265884 +-0.492704 -0.14304 -0.253991 +-0.492648 -0.142688 0.255028 +-0.492202 0.127068 -0.268071 +-0.492109 0.132524 -0.266076 +-0.491744 0.13752 -0.263231 +-0.491467 0.135364 0.265615 +-0.491314 -0.135752 -0.265599 +-0.491308 -0.121372 -0.269979 +-0.491308 0.121372 0.269979 +-0.491242 0.141816 0.259925 +-0.491183 0.141804 -0.259736 +-0.490806 -0.12924 0.269464 +-0.490691 -0.1425 0.260347 +-0.490644 -0.142756 -0.259917 +-0.490358 0.14588 -0.254872 +-0.489488 -0.121628 0.272111 +-0.489488 0.121628 -0.272111 +-0.489255 -0.15718 -0.2153 +-0.489255 0.15718 0.2153 +-0.489143 -0.172648 -0.126556 +-0.489143 -0.172648 0.126556 +-0.489143 0.172648 -0.126556 +-0.489143 0.172648 0.126556 +-0.489087 -0.180824 0 +-0.489087 0.180824 0 +-0.488915 -0.149724 0.248715 +-0.488915 0.149724 -0.248715 +-0.488915 -0.149724 -0.248715 +-0.488915 0.149724 0.248715 +-0.488629 -0.137304 0.268477 +-0.488526 0.14836 0.254412 +-0.488501 -0.129572 -0.272052 +-0.488495 0.129588 0.272048 +-0.488435 -0.149128 0.252623 +-0.488382 0.141792 0.265048 +-0.487819 -0.142696 -0.264951 +-0.487772 -0.148868 0.255319 +-0.487557 0.12876 -0.273191 +-0.487526 -0.121888 -0.274107 +-0.487526 0.121888 0.274107 +-0.487248 0.1352 -0.270971 +-0.487083 -0.14982 -0.254547 +-0.487018 -0.129576 0.2736 +-0.486775 0.135616 0.271463 +-0.486635 0.141052 -0.267636 +-0.486635 -0.135976 -0.271423 +-0.486566 0.148028 0.259632 +-0.486114 -0.142532 0.267536 +-0.485971 -0.148616 0.259863 +-0.485815 0.14602 -0.263451 +-0.485432 -0.122144 0.275956 +-0.485432 0.122144 -0.275956 +-0.485174 -0.149456 -0.259544 +-0.484996 -0.137436 0.272355 +-0.484691 0.150648 -0.257584 +-0.484367 -0.129884 -0.275836 +-0.484364 0.1299 0.275832 +-0.484289 -0.16158 -0.216256 +-0.484289 0.16158 0.216256 +-0.484195 -0.15378 0.249844 +-0.484195 0.15378 -0.249844 +-0.484124 -0.17712 -0.127128 +-0.484124 -0.17712 0.127128 +-0.484124 0.17712 -0.127128 +-0.484124 0.17712 0.127128 +-0.484043 -0.185331 0 +-0.484043 0.185331 0 +-0.483971 0.147848 0.264048 +-0.483959 0.141784 0.27036 +-0.483672 -0.153276 0.253192 +-0.483454 -0.14264 -0.270172 +-0.483236 0.153092 0.254764 +-0.483114 0.129912 -0.27676 +-0.483036 -0.153028 0.255483 +-0.482731 0.135744 0.275051 +-0.482703 -0.142516 0.271103 +-0.482672 -0.154832 -0.25018 +-0.482672 0.154832 0.25018 +-0.482669 -0.14922 -0.263763 +-0.482606 -0.136088 -0.274997 +-0.482572 0.136964 -0.274419 +-0.481874 -0.148416 0.265991 +-0.481871 -0.122496 -0.278576 +-0.481871 0.122496 0.278576 +-0.481728 0.14334 -0.270767 +-0.481569 -0.15426 -0.254864 +-0.48146 0.152696 0.259124 +-0.481391 -0.152724 0.259323 +-0.481267 -0.129888 0.278123 +-0.4807 0.148716 -0.266128 +-0.480176 0.141696 0.273624 +-0.480021 0.1476 0.268624 +-0.479865 -0.15384 -0.258968 +-0.479728 -0.142512 -0.273379 +-0.479457 -0.137428 0.276636 +-0.479366 0.153656 -0.259592 +-0.479195 0.152396 0.262796 +-0.478874 -0.1489 -0.26814 +-0.478855 -0.14824 0.269047 +-0.478089 -0.165388 -0.217084 +-0.478089 0.165388 0.217084 +-0.477865 -0.180972 -0.12762 +-0.477865 -0.180972 0.12762 +-0.477865 0.180972 -0.12762 +-0.477865 0.180972 0.12762 +-0.477849 -0.157516 0.251172 +-0.477849 0.157516 -0.251172 +-0.477787 -0.152364 0.264483 +-0.477746 -0.189212 0 +-0.477746 0.189212 0 +-0.477715 -0.153504 -0.262424 +-0.477497 -0.142296 0.275072 +-0.47731 -0.157096 0.253792 +-0.477307 0.13084 -0.280132 +-0.476737 -0.156856 0.255568 +-0.476693 0.157032 0.255007 +-0.476668 0.147328 0.271444 +-0.476441 0.138376 -0.277695 +-0.475818 0.151988 0.266604 +-0.475668 -0.14858 -0.270836 +-0.475534 -0.1585 -0.251612 +-0.475534 0.1585 0.251612 +-0.475466 -0.157588 -0.255047 +-0.47535 -0.156504 0.25852 +-0.475329 0.145168 -0.273784 +-0.47522 0.156592 0.258339 +-0.475167 -0.152092 0.267063 +-0.47512 -0.122816 0.282116 +-0.47512 0.122816 -0.282116 +-0.474531 -0.153048 -0.266007 +-0.474269 -0.147812 0.272484 +-0.474089 0.150864 -0.268756 +-0.474067 -0.12282 -0.282528 +-0.474067 0.12282 0.282528 +-0.474058 -0.15714 -0.2582 +-0.473896 -0.130032 -0.281823 +-0.473892 0.130056 0.28182 +-0.473428 0.156216 0.261132 +-0.473272 -0.167396 -0.21752 +-0.473272 0.167396 0.21752 +-0.47322 -0.129772 0.282127 +-0.473008 -0.182992 -0.12788 +-0.473008 -0.182992 0.12788 +-0.473008 0.182992 -0.12788 +-0.473008 0.182992 0.12788 +-0.47298 0.151612 0.268963 +-0.472871 -0.191236 0 +-0.472871 0.191236 0 +-0.472581 0.156048 -0.261637 +-0.472534 0.135456 0.280732 +-0.472531 -0.159528 0.252152 +-0.472531 0.159528 -0.252152 +-0.47245 -0.156012 0.262456 +-0.472444 -0.13576 -0.280655 +-0.47236 -0.156748 -0.260839 +-0.472036 -0.159164 0.254171 +-0.471861 -0.15264 -0.268235 +-0.471643 -0.136876 0.280491 +-0.471628 0.159036 0.255088 +-0.471543 -0.15894 0.255531 +-0.471219 -0.151568 0.269979 +-0.471207 -0.159164 -0.2551 +-0.470799 0.155716 0.26404 +-0.470774 0.13116 -0.282592 +-0.470684 0.140948 0.278827 +-0.470444 0.1586 0.257635 +-0.470419 -0.15858 0.257775 +-0.470391 -0.15568 0.264424 +-0.470381 -0.14168 -0.278507 +-0.470151 -0.141488 0.278708 +-0.470048 -0.158728 -0.257592 +-0.46988 -0.15624 -0.263591 +-0.469543 0.13898 -0.280108 +-0.469039 0.158212 0.259775 +-0.468677 -0.15834 -0.25968 +-0.468612 0.1553 0.265856 +-0.468503 -0.160488 -0.252832 +-0.468503 0.160488 0.252832 +-0.468334 0.14624 0.276013 +-0.468257 -0.122512 0.284224 +-0.468257 0.122512 -0.284224 +-0.468154 0.146004 -0.276075 +-0.468151 -0.158056 0.260755 +-0.467833 -0.146808 0.275712 +-0.467817 -0.15582 -0.265311 +-0.467696 -0.147404 -0.275239 +-0.467316 -0.155128 0.266671 +-0.467029 -0.129456 -0.283796 +-0.467023 0.12948 0.283791 +-0.467014 0.15772 0.262008 +-0.466711 0.151872 -0.270856 +-0.466708 -0.157848 -0.261863 +-0.466562 -0.157724 0.262244 +-0.465967 0.1504 0.272863 +-0.465904 0.13466 0.282624 +-0.465836 -0.13494 -0.282544 +-0.465721 -0.15054 0.272791 +-0.465403 -0.122132 -0.284716 +-0.465403 0.122132 -0.284716 +-0.465403 0.122132 0.284716 +-0.465403 -0.122132 0.284716 +-0.465344 0.157332 0.263411 +-0.465294 -0.169264 -0.217928 +-0.465294 0.169264 0.217928 +-0.465278 -0.1514 -0.271944 +-0.465079 -0.157456 -0.263239 +-0.465029 0.157204 -0.263411 +-0.464973 -0.184839 -0.128116 +-0.464973 -0.184839 0.128116 +-0.464973 0.184839 -0.128116 +-0.464973 0.184839 0.128116 +-0.464892 -0.160976 0.253408 +-0.464892 0.160976 -0.253408 +-0.464808 -0.193076 0 +-0.464808 0.193076 0 +-0.464555 0.139932 0.280627 +-0.464531 -0.16072 0.254555 +-0.464359 -0.140624 -0.2803 +-0.46434 -0.160608 -0.255063 +-0.46434 0.160608 0.25506 +-0.464222 -0.15722 0.263951 +-0.464213 -0.160552 0.255327 +-0.464157 0.129284 0.28422 +-0.463917 -0.130532 0.283995 +-0.463898 -0.130612 -0.283979 +-0.463898 0.130612 -0.283979 +-0.46363 -0.160272 -0.256507 +-0.46363 0.160276 0.2565 +-0.463515 -0.160264 0.256584 +-0.463253 0.154152 0.268931 +-0.463076 -0.154204 0.268891 +-0.462982 0.145116 0.277704 +-0.462823 -0.159972 -0.257716 +-0.462823 0.159976 0.257705 +-0.462776 -0.154684 -0.268251 +-0.462739 0.136324 0.28238 +-0.462586 -0.146256 -0.2769 +-0.462468 -0.137572 0.281899 +-0.462396 0.137892 -0.281772 +-0.462262 -0.138484 -0.28152 +-0.4622 -0.159848 0.25824 +-0.46168 -0.159608 -0.258987 +-0.46168 0.159612 0.258976 +-0.46159 -0.161129 -0.253912 +-0.46159 0.161129 0.253912 +-0.461477 0.14932 0.274403 +-0.461303 -0.1596 0.259068 +-0.461256 0.156348 0.265835 +-0.461213 -0.142952 0.279216 +-0.461188 0.143052 0.279155 +-0.4611 -0.15648 -0.26562 +-0.461066 -0.150332 -0.273449 +-0.461019 -0.15646 0.26566 +-0.46097 0.143916 -0.27862 +-0.460748 -0.159332 -0.259799 +-0.460745 0.15934 0.259783 +-0.460555 -0.145528 -0.277524 +-0.460004 -0.15926 0.260019 +-0.459814 0.153244 0.27024 +-0.459592 -0.14902 0.274696 +-0.45954 -0.153808 -0.269516 +-0.459511 0.1493 0.27444 +-0.45929 0.150032 -0.273736 +-0.458876 -0.151396 -0.272328 +-0.45862 0.155628 0.266912 +-0.458536 -0.155772 -0.266684 +-0.458468 -0.158708 -0.261236 +-0.458462 0.15872 0.261212 +-0.458312 -0.15314 0.270296 +-0.458247 -0.158808 0.260987 +-0.458069 0.153848 0.269388 +-0.45772 0.154824 -0.26802 +-0.456988 -0.1583 -0.261903 +-0.456985 0.158312 0.261879 +-0.456969 -0.156776 -0.264851 +-0.45653 0.157784 0.262887 +-0.456514 -0.15782 0.262811 +-0.456271 0.158344 -0.261659 +-0.454972 -0.160592 -0.254859 +-0.454972 0.160592 -0.254859 +-0.454972 0.160592 0.254859 +-0.454972 -0.160592 0.254859 +-0.454726 -0.170388 -0.212715 +-0.454726 0.170388 0.212715 +-0.454383 -0.184756 -0.128108 +-0.454383 -0.184756 0.128108 +-0.454383 0.184756 -0.128108 +-0.454383 0.184756 0.128108 +-0.454197 -0.192939 0 +-0.454197 0.192939 0 +-0.407823 0.12186 -0.291647 +-0.407823 0.12186 0.291647 +-0.406527 0.128916 0.28954 +-0.406246 0.130292 -0.288948 +-0.405387 0.134304 0.286847 +-0.405091 0.135588 -0.286043 +-0.403901 0.140388 0.282324 +-0.403598 0.141488 -0.281284 +-0.402707 0.144516 0.277927 +-0.402414 0.145432 -0.276744 +-0.401013 0.149216 -0.270452 +-0.401013 0.149216 0.270452 +-0.397539 0.111812 0.293972 +-0.397539 0.111812 -0.293972 +-0.388108 -0.1504 0.26408 +-0.388108 0.1504 -0.26408 +-0.383578 -0.159856 -0.221235 +-0.383578 -0.159856 0.221235 +-0.383578 0.159856 -0.221235 +-0.383578 0.159856 0.221235 +-0.378893 -0.172355 -0.147492 +-0.378893 -0.172355 0.147492 +-0.378893 0.172355 -0.147492 +-0.378893 0.172355 0.147492 +-0.37608 -0.179856 -0.0737438 +-0.37608 -0.179856 0.0737438 +-0.37608 0.179856 -0.0737438 +-0.37608 0.179856 0.0737438 +-0.375145 -0.182356 0 +-0.375145 0.182356 0 +-0.26712 -0.147256 -0.232476 +-0.26712 -0.147256 0.232476 +-0.26712 0.147256 -0.232476 +-0.26712 0.147256 0.232476 +-0.261492 -0.0965677 0.312524 +-0.261492 -0.0965677 -0.312524 +-0.261492 0.0965677 -0.312524 +-0.261492 0.0965677 0.312524 +-0.260656 -0.105052 0.311711 +-0.260656 -0.105052 -0.311711 +-0.260656 0.105052 -0.311711 +-0.260656 0.105052 0.311711 +-0.26 -0.06 0 +-0.26 -0.0588999 0.01144 +-0.26 -0.0588999 -0.01144 +-0.26 -0.0557159 0.022268 +-0.26 -0.0557159 -0.022268 +-0.26 -0.052588 0.0288879 +-0.26 -0.050768 -0.0319758 +-0.26 -0.0474238 0.0367521 +-0.26 -0.0422279 -0.0426238 +-0.26 -0.0398639 0.0448439 +-0.26 -0.03388 -0.0495199 +-0.26 -0.0333279 0.0498919 +-0.26 -0.026544 -0.053808 +-0.26 -0.0259439 0.0540999 +-0.26 -0.018904 -0.056944 +-0.26 -0.015804 0.0578799 +-0.26 -0.00754798 -0.059524 +-0.26 -0.002308 0.0599558 +-0.26 0.00308399 -0.0599199 +-0.26 0.008572 0.0593841 +-0.26 0.01408 -0.0583239 +-0.26 0.0195399 0.0567281 +-0.26 0.024872 -0.0546 +-0.26 0.03 0.0519599 +-0.26 0.034848 -0.0488401 +-0.26 0.039356 0.0452879 +-0.26 0.0434681 -0.0413558 +-0.26 0.0471437 0.037116 +-0.26 0.050352 -0.0326319 +-0.26 0.0513119 0.031096 +-0.26 0.055324 -0.023224 +-0.26 0.055544 0.0226959 +-0.26 0.0587678 0.0121 +-0.26 0.0587678 -0.0121 +-0.26 0.06 0 +-0.259756 -0.112164 0.30954 +-0.259756 0.112164 0.30954 +-0.259556 -0.113556 -0.308939 +-0.259556 0.113556 -0.308939 +-0.25892 -0.117596 0.306799 +-0.25892 0.117596 0.306799 +-0.258696 -0.118892 -0.30598 +-0.258696 0.118892 -0.30598 +-0.257772 -0.123728 0.302212 +-0.257772 0.123728 0.302212 +-0.257743 -0.159756 -0.154984 +-0.257743 -0.159756 0.154984 +-0.257743 0.159756 -0.154984 +-0.257743 0.159756 0.154984 +-0.257533 -0.124836 -0.301156 +-0.257533 0.124836 -0.301156 +-0.256812 -0.127888 0.297764 +-0.256812 0.127888 0.297764 +-0.256568 -0.128804 -0.296568 +-0.256568 0.128804 -0.296568 +-0.25538 -0.132612 0.290228 +-0.25538 -0.132612 -0.290228 +-0.25538 0.132612 -0.290228 +-0.25538 0.132612 0.290228 +-0.254052 -0.135408 0.282243 +-0.254052 0.135408 0.282243 +-0.254052 -0.135408 -0.282243 +-0.254052 0.135408 -0.282243 +-0.25212 -0.167257 -0.0774917 +-0.25212 -0.167257 0.0774917 +-0.25212 0.167257 -0.0774917 +-0.25212 0.167257 0.0774917 +-0.250244 -0.169756 0 +-0.250244 0.169756 0 +-0.15062 -0.139692 -0.243719 +-0.15062 -0.139692 0.243719 +-0.15062 0.139692 -0.243719 +-0.15062 0.139692 0.243719 +-0.136556 -0.152192 -0.162481 +-0.136556 -0.152192 0.162481 +-0.136556 0.152192 -0.162481 +-0.136556 0.152192 0.162481 +-0.12812 -0.159692 -0.08124 +-0.12812 -0.159692 0.08124 +-0.12812 0.159692 -0.08124 +-0.12812 0.159692 0.08124 +-0.125308 -0.162191 0 +-0.125308 0.162191 0 +-0.0564879 -0.0874238 0.340479 +-0.0564879 0.0874238 0.340479 +-0.0564879 -0.0874238 -0.340479 +-0.0564879 0.0874238 -0.340479 +-0.0563278 -0.0960599 0.339548 +-0.0563278 0.0960599 0.339548 +-0.0563278 -0.0960599 -0.339548 +-0.0563278 0.0960599 -0.339548 +-0.0559839 -0.103304 0.337227 +-0.0559839 0.103304 0.337227 +-0.055892 -0.10472 -0.336591 +-0.055892 0.10472 -0.336591 +-0.0555679 -0.108828 0.334339 +-0.0555679 0.108828 0.334339 +-0.055444 -0.11014 -0.333479 +-0.055444 0.11014 -0.333479 +-0.0548878 -0.115036 0.329535 +-0.0548878 0.115036 0.329535 +-0.0547321 -0.116152 -0.328435 +-0.0547321 0.116152 -0.328435 +-0.0542398 -0.119216 0.324911 +-0.0542398 0.119216 0.324911 +-0.0540679 -0.120136 -0.323671 +-0.0540679 0.120136 -0.323671 +-0.05316 -0.123904 0.317119 +-0.05316 -0.123904 -0.317119 +-0.05316 0.123904 -0.317119 +-0.05316 0.123904 0.317119 +-0.0520319 -0.126588 0.308931 +-0.0520319 0.126588 0.308931 +-0.0520319 -0.126588 -0.308931 +-0.0520319 0.126588 -0.308931 +-0.034076 -0.137172 -0.254967 +-0.034076 -0.137172 0.254967 +-0.034076 0.137172 -0.254967 +-0.034076 0.137172 0.254967 +-0.015328 -0.149672 -0.169976 +-0.015328 -0.149672 0.169976 +-0.015328 0.149672 -0.169976 +-0.015328 0.149672 0.169976 +-0.00407599 -0.157172 -0.0849878 +-0.00407599 -0.157172 0.0849878 +-0.00407599 0.157172 -0.0849878 +-0.00407599 0.157172 0.0849878 +-0.000327999 -0.159672 0 +-0.000327999 0.159672 0 +0.0825039 -0.139692 -0.266219 +0.0825039 -0.139692 0.266219 +0.0825039 0.139692 -0.266219 +0.0825039 0.139692 0.266219 +0.105944 -0.152192 -0.17748 +0.105944 -0.152192 0.17748 +0.105944 0.152192 -0.17748 +0.105944 0.152192 0.17748 +0.120004 -0.159692 -0.0887398 +0.120004 -0.159692 0.0887398 +0.120004 0.159692 -0.0887398 +0.120004 0.159692 0.0887398 +0.124692 -0.162191 0 +0.124692 0.162191 0 +0.14804 -0.11266 -0.364188 +0.14804 0.11266 -0.364188 +0.148044 -0.116848 0.361761 +0.148044 0.116848 0.361761 +0.148056 -0.111216 0.364876 +0.148056 0.111216 0.364876 +0.148064 -0.118184 -0.360839 +0.148064 0.118184 -0.360839 +0.148256 -0.123132 0.356627 +0.148256 0.123132 0.356627 +0.148288 -0.103812 0.3674 +0.148288 0.103812 0.3674 +0.148288 -0.103812 -0.3674 +0.148288 0.103812 -0.3674 +0.148328 -0.124256 -0.355455 +0.148328 0.124256 -0.355455 +0.1486 -0.127312 0.351714 +0.1486 0.127312 0.351714 +0.148708 -0.12822 -0.350402 +0.148708 0.12822 -0.350402 +0.148824 -0.0949838 0.368478 +0.148824 0.0949838 0.368478 +0.148824 -0.0949838 -0.368478 +0.148824 0.0949838 -0.368478 +0.149364 -0.131876 0.34351 +0.149364 -0.131876 -0.34351 +0.149364 0.131876 -0.34351 +0.149364 0.131876 0.34351 +0.150336 -0.134316 0.334999 +0.150336 -0.134316 -0.334999 +0.150336 0.134316 -0.334999 +0.150336 0.134316 0.334999 +0.199129 -0.147256 -0.277475 +0.199129 -0.147256 0.277475 +0.199129 0.147256 -0.277475 +0.199129 0.147256 0.277475 +0.227255 -0.159756 -0.184984 +0.227255 -0.159756 0.184984 +0.227255 0.159756 -0.184984 +0.227255 0.159756 0.184984 +0.244127 -0.167257 -0.0924917 +0.244127 -0.167257 0.0924917 +0.244127 0.167257 -0.0924917 +0.244127 0.167257 0.0924917 +0.249755 -0.169756 0 +0.249755 0.169756 0 +0.284912 0.148592 0.352041 +0.284912 -0.148592 -0.352041 +0.28532 -0.109284 -0.38709 +0.28532 -0.109284 0.38709 +0.292052 -0.139 0.375668 +0.292068 -0.140124 -0.374435 +0.29212 -0.134024 -0.38012 +0.292168 -0.132672 0.381095 +0.292195 -0.143156 0.3705 +0.29226 -0.144048 -0.369123 +0.292391 -0.128432 -0.383672 +0.292491 -0.126964 0.384404 +0.292764 -0.14758 0.361935 +0.292764 -0.14758 -0.361935 +0.29314 -0.11944 0.387108 +0.29314 -0.11944 -0.387108 +0.315795 -0.159856 -0.288736 +0.315795 -0.159856 0.288736 +0.315795 0.159856 -0.288736 +0.315795 0.159856 0.288736 +0.3481 0.15234 -0.376562 +0.348149 -0.150804 0.378949 +0.348168 0.153492 0.37455 +0.34823 -0.15396 0.373656 +0.348237 -0.149856 -0.38026 +0.348237 0.14988 0.380236 +0.348327 -0.154436 -0.37269 +0.34848 0.148088 -0.382479 +0.348495 0.155044 -0.371378 +0.348561 0.155224 0.370964 +0.348607 -0.172355 -0.192491 +0.348607 -0.172355 0.192491 +0.348607 0.172355 -0.192491 +0.348607 0.172355 0.192491 +0.348716 -0.146748 0.383983 +0.348829 -0.146168 -0.384588 +0.348944 0.145588 0.38517 +0.3491 -0.156296 0.368275 +0.349255 0.1441 -0.386575 +0.34934 -0.156624 -0.36735 +0.34976 0.157084 -0.365942 +0.349869 0.15718 0.365621 +0.350072 -0.15412 0.374079 +0.350075 -0.155828 0.370166 +0.350097 -0.140404 0.38952 +0.350168 -0.140096 -0.389735 +0.350252 -0.157492 -0.364546 +0.350393 -0.15216 0.377647 +0.350433 0.138972 0.390482 +0.350636 -0.157332 0.365577 +0.351196 0.135652 -0.392389 +0.351355 -0.148488 0.382781 +0.351436 0.157508 0.3654 +0.351455 -0.13448 0.392959 +0.351495 0.156164 0.369883 +0.351536 -0.134124 -0.393124 +0.351707 -0.157568 0.365328 +0.351785 0.132944 0.393635 +0.351966 0.154588 0.373737 +0.351981 -0.156276 0.369764 +0.352153 0.158448 0.360484 +0.352153 -0.158448 -0.360484 +0.352153 -0.158448 0.360484 +0.352153 0.158448 -0.360484 +0.352536 0.129052 -0.394997 +0.352611 -0.154744 0.373587 +0.352692 0.15274 0.37727 +0.352735 -0.143972 0.387407 +0.352767 0.1578 0.364995 +0.352857 -0.12706 -0.395508 +0.352966 -0.126268 0.395676 +0.352966 0.126268 0.395676 +0.353038 -0.157856 0.364895 +0.353119 0.125072 -0.395897 +0.353474 -0.152928 0.377104 +0.353496 -0.119196 -0.396383 +0.353496 0.119196 -0.396383 +0.353496 -0.119196 0.396383 +0.353496 0.119196 0.396383 +0.35382 0.158028 0.364571 +0.353866 0.156704 0.369194 +0.354197 0.149192 0.382407 +0.354352 -0.156812 0.36902 +0.35438 0.126832 -0.395782 +0.354383 -0.152824 -0.377513 +0.354496 0.13788 -0.391859 +0.354527 -0.137968 0.391732 +0.354536 0.133132 -0.394028 +0.354583 -0.158192 0.364203 +0.354617 0.145932 -0.386083 +0.35467 -0.148496 -0.383363 +0.354767 -0.155556 -0.372369 +0.355119 0.150636 -0.380908 +0.355134 0.155324 0.372852 +0.355159 -0.14942 0.382223 +0.355312 -0.144424 -0.387401 +0.355327 0.158352 0.363783 +0.35567 0.126356 -0.396018 +0.355686 -0.158428 0.363555 +0.355748 0.157112 0.368453 +0.355782 -0.155464 0.372624 +0.355863 -0.132804 0.394233 +0.355932 -0.157604 -0.366973 +0.356028 0.144724 0.387096 +0.356408 0.154804 -0.374254 +0.356536 0.153632 0.376248 +0.356652 -0.129044 0.395467 +0.356708 0.125744 -0.396208 +0.35672 0.158652 0.36282 +0.356888 -0.158684 0.362686 +0.356898 -0.1358 -0.393056 +0.356957 0.1323 -0.394576 +0.357103 -0.1574 0.367789 +0.35715 -0.144964 0.386918 +0.357321 -0.1538 0.375977 +0.357652 0.155864 0.371867 +0.357792 0.136804 -0.392729 +0.357829 0.12478 -0.396402 +0.357963 -0.129096 -0.39552 +0.358247 0.138636 0.391523 +0.358402 -0.125076 -0.396336 +0.358424 0.157672 0.367029 +0.358443 0.157412 -0.36792 +0.358524 0.123964 -0.396511 +0.35887 0.158948 -0.361736 +0.35887 -0.158948 0.361736 +0.358895 0.131196 -0.395015 +0.358938 0.150256 0.381239 +0.35906 -0.1578 0.366621 +0.359462 -0.156236 0.370976 +0.359511 -0.138848 0.391364 +0.359515 0.122276 -0.396657 +0.359527 0.144576 -0.387588 +0.359583 0.154276 0.375067 +0.359789 -0.119196 -0.396744 +0.359789 0.119196 0.396744 +0.359823 0.1333 0.394102 +0.359907 -0.150456 0.380915 +0.359994 0.120988 -0.396707 +0.360184 0.120252 -0.396723 +0.36044 0.135336 -0.393433 +0.360723 0.129388 0.39537 +0.360854 -0.152328 -0.378463 +0.36087 0.158156 0.365269 +0.361001 0.129432 -0.395467 +0.361032 -0.14802 -0.383993 +0.361051 0.149188 -0.382831 +0.361128 0.158844 0.362315 +0.361128 -0.158844 -0.362315 +0.361156 -0.158212 0.365023 +0.361172 -0.133456 0.393959 +0.361216 0.15658 0.369951 +0.361231 -0.155056 -0.373575 +0.361515 -0.143976 -0.387784 +0.36154 0.145844 0.385862 +0.36178 -0.154708 0.373983 +0.361879 -0.119196 0.396638 +0.361879 0.119196 -0.396638 +0.36206 -0.15674 0.369397 +0.362113 -0.1295 0.395233 +0.362287 -0.157104 -0.368431 +0.362303 0.127928 -0.395722 +0.362664 -0.146056 0.385504 +0.362705 0.151008 0.379812 +0.36272 -0.135448 -0.393056 +0.363259 0.153324 -0.376537 +0.363303 0.132964 -0.394159 +0.363387 0.158596 -0.362967 +0.363387 -0.158596 0.362967 +0.363484 0.14256 -0.388868 +0.363496 -0.128852 -0.395311 +0.363783 -0.12492 -0.396056 +0.363892 0.155104 0.37273 +0.363967 -0.119196 -0.39643 +0.363967 0.119196 0.39643 +0.364172 0.12482 -0.39604 +0.364446 0.157176 0.367546 +0.364456 0.139628 0.390298 +0.364823 -0.15724 0.367216 +0.364901 -0.155284 0.372042 +0.365079 0.13094 -0.394576 +0.365098 0.122456 -0.396149 +0.3654 -0.1515 0.378475 +0.365481 0.121116 -0.396165 +0.365721 -0.139816 0.389915 +0.365823 0.155932 -0.370356 +0.365827 0.146896 -0.384516 +0.365898 0.146632 0.384251 +0.366425 0.134032 0.392915 +0.367403 -0.1507 -0.379323 +0.367453 -0.146536 -0.384298 +0.367503 0.129908 0.394208 +0.367627 0.126752 -0.395078 +0.367752 0.139196 -0.390227 +0.367764 -0.142656 -0.387688 +0.367764 -0.134172 0.392529 +0.367764 0.155764 0.369758 +0.367783 -0.15336 -0.374893 +0.367848 0.163779 -0.331591 +0.367852 -0.163779 0.331591 +0.367982 0.151944 0.376908 +0.36821 -0.155836 0.369347 +0.368297 -0.179856 -0.096244 +0.368297 -0.179856 0.096244 +0.368297 0.179856 -0.096244 +0.368297 0.179856 0.096244 +0.368568 -0.134536 -0.39238 +0.368696 0.157376 0.364736 +0.368696 -0.157376 -0.364736 +0.368727 -0.155392 -0.370188 +0.368768 0.150828 -0.378606 +0.36888 -0.130004 0.393816 +0.368898 0.123568 -0.39524 +0.369011 -0.147144 0.3827 +0.369045 -0.128292 -0.394373 +0.369173 -0.12458 -0.395043 +0.369216 -0.152144 0.376042 +0.36935 0.140324 0.388557 +0.369422 0.121768 -0.395258 +0.369503 -0.119196 0.395321 +0.369503 0.119196 -0.395321 +0.37021 0.156848 -0.365291 +0.37021 -0.156848 0.365291 +0.370381 0.136284 -0.391024 +0.37097 0.142984 -0.386348 +0.371213 -0.119196 -0.394813 +0.371213 0.119196 0.394813 +0.371612 0.134548 0.391121 +0.371727 0.153344 -0.37264 +0.371976 0.147604 0.380859 +0.372668 0.152668 0.373151 +0.372824 0.130268 0.392398 +0.37283 -0.140776 0.386837 +0.373204 -0.152744 0.372628 +0.373385 -0.147808 0.379843 +0.373883 -0.143872 -0.38422 +0.373986 -0.147724 -0.380005 +0.373998 -0.14032 -0.387071 +0.374129 0.130192 -0.392015 +0.374129 0.139556 -0.387445 +0.374375 -0.132972 -0.390999 +0.374388 -0.150232 -0.376207 +0.374534 -0.12402 -0.393271 +0.374556 -0.127352 -0.392685 +0.374687 0.146468 -0.380937 +0.374699 0.154764 0.367073 +0.374699 -0.154764 -0.367073 +0.374855 -0.182356 0 +0.374855 0.182356 0 +0.375058 0.162841 -0.340236 +0.375058 -0.162841 0.340236 +0.37522 -0.152196 -0.372132 +0.375294 -0.134884 0.389323 +0.375939 0.125552 -0.392339 +0.376136 0.14118 0.384765 +0.376164 -0.119196 0.392834 +0.376164 0.119196 -0.392834 +0.376597 -0.130508 0.390576 +0.376662 0.122936 -0.39238 +0.377301 0.148352 0.376419 +0.3777 -0.141364 0.383619 +0.37774 -0.119196 -0.39204 +0.37774 0.119196 0.39204 +0.377905 -0.148432 0.375796 +0.378067 0.148736 -0.375301 +0.378301 0.142592 -0.382376 +0.378572 0.132328 -0.388856 +0.378787 0.135184 0.387149 +0.378852 -0.123368 -0.391193 +0.378964 -0.126252 -0.390679 +0.378968 -0.137528 -0.386074 +0.379005 -0.131124 -0.38928 +0.37902 -0.140652 -0.38375 +0.379027 0.151864 -0.368939 +0.379027 -0.151864 0.368939 +0.379279 -0.144088 -0.380301 +0.379718 -0.14636 -0.377164 +0.380167 0.130716 0.388361 +0.380435 -0.13532 0.385937 +0.380482 -0.148192 -0.373755 +0.380669 0.126796 -0.389361 +0.381127 -0.12294 -0.389819 +0.381133 -0.150068 -0.369895 +0.381133 0.150068 0.369895 +0.381276 -0.125528 -0.389351 +0.381413 -0.1299 -0.388115 +0.381463 0.123668 -0.389442 +0.381538 -0.135664 -0.385336 +0.381678 -0.138492 -0.383323 +0.381849 -0.130816 0.387121 +0.381924 0.144604 -0.376999 +0.382018 -0.141624 -0.38032 +0.382021 0.141852 0.37974 +0.382127 0.160815 -0.343588 +0.382127 -0.160815 0.343588 +0.382479 -0.143716 -0.377584 +0.382681 -0.141924 0.379036 +0.382812 -0.119196 0.388825 +0.382812 0.119196 -0.388825 +0.383139 0.148056 -0.370839 +0.383139 -0.148056 0.370839 +0.383211 -0.145432 -0.37459 +0.383276 -0.119196 -0.388473 +0.383276 0.119196 0.388473 +0.383329 0.134336 -0.384314 +0.384725 -0.12212 -0.387183 +0.384902 -0.124136 -0.386797 +0.384971 0.135688 0.381824 +0.385036 -0.14582 -0.371758 +0.385036 0.14582 0.371758 +0.385142 -0.127536 -0.385853 +0.385488 -0.13204 -0.38379 +0.385603 0.127972 -0.385083 +0.385666 -0.135744 0.381077 +0.385741 -0.134272 -0.382307 +0.386174 -0.136768 -0.380086 +0.386417 0.124364 -0.385267 +0.386435 0.158732 -0.345479 +0.386435 -0.158732 0.345479 +0.386485 0.131072 0.382915 +0.38666 -0.138464 -0.378052 +0.387192 -0.131112 0.382148 +0.387239 0.1357 -0.379397 +0.387326 -0.139892 -0.375799 +0.387762 -0.121256 -0.384388 +0.387928 -0.122668 -0.384096 +0.387943 0.141516 -0.373216 +0.387943 -0.141516 0.373216 +0.388189 -0.125048 -0.383423 +0.388619 -0.1282 -0.382021 +0.388775 -0.119196 -0.383351 +0.388775 0.119196 0.383351 +0.388775 -0.119196 0.383351 +0.388775 0.119196 -0.383351 +0.388915 -0.129772 -0.381014 +0.389376 -0.131544 -0.379516 +0.389566 0.12878 -0.380435 +0.389834 -0.132764 -0.378129 +0.390348 0.124844 -0.380746 +0.390383 -0.136576 -0.3745 +0.390383 0.136576 0.3745 +0.390408 -0.133812 -0.376587 +0.390825 -0.12026 -0.380843 +0.390922 -0.120988 -0.380675 +0.391046 0.134856 -0.374858 +0.391046 -0.134856 0.374858 +0.391102 -0.122204 -0.380317 +0.391429 -0.123812 -0.379597 +0.391647 -0.12462 -0.379086 +0.391975 -0.125536 -0.378332 +0.392062 0.154856 -0.347748 +0.392062 -0.154856 0.347748 +0.392283 -0.12618 -0.37764 +0.392644 -0.126748 -0.376858 +0.392648 -0.129316 -0.375762 +0.392651 0.129316 0.375762 +0.393056 -0.127228 0.376005 +0.393056 0.127228 -0.376005 +0.393358 -0.125168 -0.376189 +0.393358 0.125168 0.376189 +0.393732 -0.119196 -0.376419 +0.393732 -0.119196 0.376419 +0.393732 0.119196 0.376419 +0.393732 0.119196 -0.376419 +0.396109 -0.173355 -0.271955 +0.396109 0.173355 -0.271955 +0.396109 0.173355 0.271955 +0.396109 -0.173355 0.271955 +0.39666 0.150424 -0.349371 +0.39666 -0.150424 0.349371 +0.401259 0.144232 -0.350685 +0.401259 -0.144232 0.350685 +0.40467 0.137464 -0.351268 +0.40467 -0.137464 0.351268 +0.405732 -0.173204 -0.276043 +0.405732 0.173204 -0.276043 +0.405732 0.173204 0.276043 +0.405732 -0.173204 0.276043 +0.406848 -0.130532 0.351178 +0.406848 0.130536 -0.351178 +0.409938 -0.124484 0.346526 +0.409938 0.124484 -0.346526 +0.413088 -0.171228 0.2789 +0.413088 -0.171228 -0.2789 +0.413088 0.171228 -0.2789 +0.413088 0.171228 0.2789 +0.417559 0.16916 0.280512 +0.417559 -0.16916 0.280512 +0.417559 -0.16916 -0.280512 +0.417559 0.16916 -0.280512 +0.423375 -0.165279 -0.282431 +0.423375 0.165279 -0.282431 +0.423375 0.165279 0.282431 +0.423375 -0.165279 0.282431 +0.428098 -0.160823 -0.283807 +0.428098 -0.160823 0.283807 +0.428098 0.160823 -0.283807 +0.428098 0.160823 0.283807 +0.428341 -0.184248 -0.181432 +0.428341 -0.184248 0.181432 +0.428341 0.184248 -0.181432 +0.428341 0.184248 0.181432 +0.432784 -0.154584 -0.284903 +0.432784 0.154584 -0.284903 +0.432784 0.154584 0.284903 +0.432784 -0.154584 0.284903 +0.436208 -0.147756 -0.285379 +0.436208 0.147756 -0.285379 +0.436208 0.147756 0.285379 +0.436208 -0.147756 0.285379 +0.438323 -0.14076 -0.285272 +0.438323 -0.14076 0.285272 +0.438323 0.14076 -0.285272 +0.438323 0.14076 0.285272 +0.438473 -0.184236 -0.184323 +0.438473 -0.184236 0.184323 +0.438473 0.184236 -0.184323 +0.438473 0.184236 0.184323 +0.439221 -0.133976 0.284675 +0.439221 -0.133976 -0.284675 +0.439221 0.133976 -0.284675 +0.439221 0.133976 0.284675 +0.446187 -0.182328 -0.186344 +0.446187 -0.182328 0.186344 +0.446187 0.182328 -0.186344 +0.446187 0.182328 0.186344 +0.447819 -0.190811 -0.090152 +0.447819 -0.190811 0.090152 +0.447819 0.190811 -0.090152 +0.447819 0.190811 0.090152 +0.450866 -0.18028 -0.187481 +0.450866 -0.18028 0.187481 +0.450866 0.18028 -0.187481 +0.450866 0.18028 0.187481 +0.454209 -0.192961 0 +0.454209 0.192961 0 +0.456923 0.1764 0.188836 +0.456923 -0.1764 -0.188836 +0.456923 -0.1764 0.188836 +0.456923 0.1764 -0.188836 +0.458303 -0.190904 -0.0916478 +0.458303 -0.190904 0.0916478 +0.458303 0.190904 0.0916478 +0.458303 0.190904 -0.0916478 +0.461811 0.171917 0.1898 +0.461811 -0.171917 -0.1898 +0.461811 -0.171917 0.1898 +0.461811 0.171917 -0.1898 +0.464817 -0.193092 0 +0.464817 0.193092 0 +0.466275 -0.189043 -0.0926918 +0.466275 -0.189043 0.0926918 +0.466275 0.189043 -0.0926918 +0.466275 0.189043 0.0926918 +0.466602 -0.165615 -0.190564 +0.466602 -0.165615 0.190564 +0.466602 0.165615 -0.190564 +0.466602 0.165615 0.190564 +0.470039 -0.158704 -0.19088 +0.470039 -0.158704 0.19088 +0.470039 0.158704 -0.19088 +0.470039 0.158704 0.19088 +0.471101 -0.187011 -0.09328 +0.471101 -0.187011 0.09328 +0.471101 0.187011 -0.09328 +0.471101 0.187011 0.09328 +0.472079 -0.151624 -0.190779 +0.472079 -0.151624 0.190779 +0.472079 0.151624 -0.190779 +0.472079 0.151624 0.190779 +0.472827 0.14476 0.190336 +0.472827 -0.14476 -0.190336 +0.472827 -0.14476 0.190336 +0.472827 0.14476 -0.190336 +0.47288 -0.191252 0 +0.47288 0.191252 0 +0.477332 -0.183132 -0.09398 +0.477332 -0.183132 0.09398 +0.477332 0.183132 -0.09398 +0.477332 0.183132 0.09398 +0.477756 -0.189223 0 +0.477756 0.189223 0 +0.482332 -0.178631 -0.094476 +0.482332 -0.178631 0.094476 +0.482332 0.178631 -0.094476 +0.482332 0.178631 0.094476 +0.484049 -0.185344 0 +0.484049 0.185344 0 +0.487199 -0.172283 -0.0948639 +0.487199 -0.172283 0.0948639 +0.487199 0.172283 -0.0948639 +0.487199 0.172283 0.0948639 +0.489087 -0.180835 0 +0.489087 0.180835 0 +0.490644 -0.165316 -0.0950199 +0.490644 -0.165316 0.0950199 +0.490644 0.165316 -0.0950199 +0.490644 0.165316 0.0950199 +0.492629 -0.158176 -0.0949598 +0.492629 -0.158176 0.0949598 +0.492629 0.158176 -0.0949598 +0.492629 0.158176 0.0949598 +0.493271 -0.151256 -0.094724 +0.493271 -0.151256 0.094724 +0.493271 0.151256 -0.094724 +0.493271 0.151256 0.094724 +0.493987 -0.174473 0 +0.493987 0.174473 0 +0.49743 -0.167483 0 +0.49743 0.167483 0 +0.499392 -0.160324 0 +0.499392 0.160324 0 +0.5 -0.15338 0 +0.5 0.15338 0 +3 1163 1161 1153 +3 1153 1161 1149 +3 1161 1145 1149 +3 1149 1145 1109 +3 1145 1105 1109 +3 1109 1105 1053 +3 1105 1045 1053 +3 1045 959 1053 +3 959 990 1053 +3 1053 990 1057 +3 990 1005 1057 +3 1057 1005 1061 +3 1005 1009 1061 +3 1061 1009 1070 +3 1009 1011 1070 +3 1011 1014 1070 +3 1014 1032 1070 +3 1032 1071 1070 +3 1070 1071 1122 +3 1071 1124 1122 +3 1122 1124 1153 +3 1124 1155 1153 +3 1155 1164 1153 +3 1153 1164 1163 +3 1164 1156 1163 +3 1156 1154 1163 +3 1154 1150 1163 +3 1163 1150 1161 +3 1150 1159 1161 +3 1161 1159 1145 +3 1159 1139 1145 +3 1145 1139 1105 +3 1139 1096 1105 +3 1105 1096 1045 +3 1096 1041 1045 +3 1041 933 1045 +3 1045 933 959 +3 933 952 959 +3 952 974 959 +3 959 974 990 +3 974 992 990 +3 990 992 1005 +3 992 1004 1005 +3 1005 1004 1009 +3 1004 1003 1009 +3 1009 1003 1000 +3 1000 1003 986 +3 1003 988 986 +3 986 988 966 +3 988 971 966 +3 966 971 942 +3 971 946 942 +3 942 946 926 +3 926 946 927 +3 946 952 927 +3 927 952 930 +3 952 933 930 +3 930 933 902 +3 933 897 902 +3 902 897 860 +3 897 859 860 +3 1153 1149 1122 +3 1149 1117 1122 +3 1122 1117 1070 +3 1070 1117 1061 +3 1061 1117 1057 +3 1117 1109 1057 +3 1057 1109 1053 +3 1117 1149 1109 +3 1069 1062 1123 +3 1123 1062 1118 +3 1062 1110 1118 +3 1118 1110 1146 +3 1110 1140 1146 +3 1146 1140 1157 +3 1140 1143 1157 +3 1157 1143 1133 +3 1143 1127 1133 +3 1133 1127 1088 +3 1127 1081 1088 +3 1088 1081 1039 +3 1081 1034 1039 +3 1059 1112 1055 +3 1055 1112 1108 +3 1112 1148 1108 +3 1108 1148 1142 +3 1148 1160 1142 +3 1142 1160 1158 +3 1160 1147 1158 +3 1158 1147 1141 +3 1147 1111 1141 +3 1141 1111 1107 +3 1111 1058 1107 +3 1107 1058 1054 +3 1058 1023 1054 +3 1054 1023 1021 +3 1023 995 1021 +3 1021 995 977 +3 995 973 977 +3 977 973 941 +3 973 916 941 +3 941 916 895 +3 916 875 895 +3 895 875 837 +3 875 820 837 +3 837 820 783 +3 820 767 783 +3 783 767 736 +3 767 738 736 +3 736 738 701 +3 738 715 701 +3 715 618 701 +3 701 618 606 +3 618 552 606 +3 606 552 556 +3 552 460 556 +3 556 460 500 +3 460 420 500 +3 1055 1108 1048 +3 1048 1108 1095 +3 1108 1142 1095 +3 1095 1142 1136 +3 1142 1158 1136 +3 1136 1158 1144 +3 1158 1141 1144 +3 1144 1141 1135 +3 1141 1107 1135 +3 1135 1107 1098 +3 1107 1054 1098 +3 1098 1054 1047 +3 1054 1021 1047 +3 1047 1021 1019 +3 1021 977 1019 +3 1019 977 950 +3 977 941 950 +3 950 941 915 +3 941 895 915 +3 915 895 861 +3 895 837 861 +3 861 837 797 +3 837 783 797 +3 797 783 740 +3 783 736 740 +3 740 736 689 +3 736 701 689 +3 689 701 612 +3 701 606 612 +3 606 556 612 +3 612 556 560 +3 556 500 560 +3 1048 1095 1043 +3 1043 1095 1087 +3 1095 1136 1087 +3 1087 1136 1130 +3 1136 1144 1130 +3 1130 1144 1138 +3 1144 1135 1138 +3 1138 1135 1129 +3 1135 1098 1129 +3 1129 1098 1090 +3 1098 1047 1090 +3 1090 1047 1042 +3 1047 1019 1042 +3 1042 1019 1001 +3 1019 950 1001 +3 1001 950 924 +3 950 915 924 +3 924 915 879 +3 915 861 879 +3 879 861 816 +3 861 797 816 +3 816 797 743 +3 797 740 743 +3 743 740 678 +3 740 689 678 +3 678 689 620 +3 689 612 620 +3 620 612 560 +3 1043 1087 1037 +3 1037 1087 1084 +3 1087 1130 1084 +3 1084 1130 1116 +3 1130 1138 1116 +3 1116 1138 1132 +3 1138 1129 1132 +3 1132 1129 1115 +3 1129 1090 1115 +3 1115 1090 1083 +3 1090 1042 1083 +3 1083 1042 1040 +3 1042 1001 1040 +3 1040 1001 968 +3 1001 924 968 +3 968 924 872 +3 924 879 872 +3 872 879 836 +3 879 816 836 +3 836 816 755 +3 816 743 755 +3 755 743 671 +3 743 678 671 +3 671 678 620 +3 1031 1029 1069 +3 1069 1029 1062 +3 1029 1060 1062 +3 1062 1060 1110 +3 1060 1106 1110 +3 1110 1106 1140 +3 1106 1134 1140 +3 1140 1134 1143 +3 1134 1137 1143 +3 1143 1137 1127 +3 1137 1113 1127 +3 1127 1113 1081 +3 1113 1073 1081 +3 1081 1073 1034 +3 1073 1025 1034 +3 1050 1028 1018 +3 1018 1028 901 +3 1028 945 901 +3 901 945 819 +3 945 873 819 +3 819 873 829 +3 829 873 852 +3 873 884 852 +3 852 884 867 +3 884 885 867 +3 867 885 864 +3 885 883 864 +3 864 883 835 +3 883 846 835 +3 835 846 801 +3 846 810 801 +3 801 810 757 +3 810 807 757 +3 1015 1025 1065 +3 1025 1073 1065 +3 1065 1073 1101 +3 1073 1113 1101 +3 1101 1113 1131 +3 1113 1137 1131 +3 1131 1137 1128 +3 1137 1134 1128 +3 1128 1134 1097 +3 1134 1106 1097 +3 1097 1106 1056 +3 1106 1060 1056 +3 1056 1060 1024 +3 1060 1029 1024 +3 1024 1029 1007 +3 1029 1031 1007 +3 1007 1031 1012 +3 1012 1031 1072 +3 1031 1069 1072 +3 1072 1069 1121 +3 1069 1123 1121 +3 1121 1123 1156 +3 1156 1123 1154 +3 1123 1118 1154 +3 1154 1118 1150 +3 1118 1146 1150 +3 1150 1146 1159 +3 1146 1157 1159 +3 1159 1157 1139 +3 1157 1133 1139 +3 1139 1133 1096 +3 1133 1088 1096 +3 1096 1088 1041 +3 1088 1039 1041 +3 1041 1039 897 +3 1039 1034 897 +3 897 1034 859 +3 1034 1025 859 +3 859 1025 799 +3 1025 1015 799 +3 799 1015 712 +3 1015 667 712 +3 712 667 652 +3 667 637 652 +3 652 637 634 +3 637 591 634 +3 634 591 575 +3 591 577 575 +3 577 531 575 +3 575 531 523 +3 531 450 523 +3 450 436 523 +3 436 408 523 +3 523 408 518 +3 408 404 518 +3 404 515 518 +3 518 515 567 +3 515 563 567 +3 567 563 619 +3 563 611 619 +3 619 611 657 +3 611 661 657 +3 657 661 696 +3 661 706 696 +3 696 706 761 +3 706 769 761 +3 761 769 815 +3 769 821 815 +3 815 821 857 +3 821 865 857 +3 857 865 891 +3 865 894 891 +3 891 894 922 +3 894 920 922 +3 922 920 936 +3 920 935 936 +3 936 935 961 +3 935 957 961 +3 961 957 979 +3 957 976 979 +3 979 976 997 +3 976 994 997 +3 997 994 1009 +3 994 1011 1009 +3 1003 1004 988 +3 1004 992 988 +3 988 992 971 +3 992 974 971 +3 971 974 946 +3 974 952 946 +3 998 999 980 +3 999 985 980 +3 980 985 962 +3 985 965 962 +3 962 965 938 +3 965 939 938 +3 938 939 921 +3 939 923 921 +3 921 923 888 +3 923 886 888 +3 888 886 845 +3 886 841 845 +3 845 841 804 +3 841 796 804 +3 1011 994 993 +3 993 994 975 +3 994 976 975 +3 1011 993 981 +3 993 975 981 +3 1008 989 987 +3 983 1013 982 +3 1013 1010 982 +3 975 976 956 +3 976 957 956 +3 956 957 932 +3 957 935 932 +3 932 935 919 +3 935 920 919 +3 919 920 893 +3 920 894 893 +3 893 894 866 +3 894 865 866 +3 866 865 822 +3 865 821 822 +3 822 821 771 +3 821 769 771 +3 771 769 720 +3 769 706 720 +3 720 706 666 +3 706 661 666 +3 666 661 605 +3 661 611 605 +3 605 611 559 +3 611 563 559 +3 559 563 511 +3 563 515 511 +3 511 515 393 +3 515 404 393 +3 393 404 390 +3 975 956 981 +3 981 956 953 +3 956 932 953 +3 954 970 928 +3 970 918 928 +3 928 918 878 +3 918 868 878 +3 878 868 828 +3 868 805 828 +3 828 805 754 +3 805 732 754 +3 754 732 687 +3 732 676 687 +3 687 676 614 +3 676 622 614 +3 614 622 566 +3 622 572 566 +3 566 572 520 +3 572 574 520 +3 520 574 522 +3 522 574 534 +3 574 580 534 +3 580 538 534 +3 534 538 510 +3 538 528 510 +3 510 528 447 +3 528 449 447 +3 449 419 447 +3 419 417 447 +3 447 417 443 +3 417 413 443 +3 443 413 439 +3 413 410 439 +3 439 410 522 +3 410 431 522 +3 522 431 520 +3 431 514 520 +3 520 514 566 +3 514 562 566 +3 566 562 614 +3 562 608 614 +3 614 608 687 +3 608 699 687 +3 687 699 754 +3 699 770 754 +3 754 770 828 +3 770 839 828 +3 828 839 878 +3 839 882 878 +3 878 882 928 +3 882 913 928 +3 928 913 954 +3 913 948 954 +3 953 984 981 +3 981 984 1011 +3 1011 984 1014 +3 984 989 1014 +3 989 1008 1014 +3 1014 1008 1032 +3 1008 1030 1032 +3 1032 1030 1071 +3 1030 1063 1071 +3 1071 1063 1124 +3 1063 1119 1124 +3 1124 1119 1155 +3 1119 1151 1155 +3 1155 1151 1164 +3 1151 1162 1164 +3 1164 1162 1156 +3 1162 1152 1156 +3 1156 1152 1121 +3 1152 1120 1121 +3 1121 1120 1072 +3 1120 1064 1072 +3 1064 1010 1072 +3 1010 1013 1072 +3 1072 1013 1012 +3 1013 983 1012 +3 1012 983 1007 +3 983 972 1007 +3 972 996 1007 +3 1007 996 1024 +3 996 1022 1024 +3 1024 1022 1056 +3 1022 1046 1056 +3 1056 1046 1097 +3 1046 1089 1097 +3 1097 1089 1128 +3 1089 1114 1128 +3 1128 1114 1131 +3 1114 1125 1131 +3 1131 1125 1101 +3 1125 1091 1101 +3 1101 1091 1065 +3 1091 1049 1065 +3 1065 1049 1015 +3 1049 681 1015 +3 1015 681 667 +3 681 641 667 +3 667 641 637 +3 641 595 637 +3 637 595 591 +3 595 581 591 +3 591 581 577 +3 581 535 577 +3 577 535 531 +3 535 507 531 +3 531 507 450 +3 507 440 450 +3 450 440 436 +3 440 412 436 +3 436 412 408 +3 412 373 408 +3 960 943 991 +3 991 943 958 +3 943 905 958 +3 933 1041 897 +3 967 931 963 +3 963 931 917 +3 931 889 917 +3 917 889 874 +3 889 831 874 +3 874 831 817 +3 831 795 817 +3 817 795 777 +3 795 758 777 +3 777 758 748 +3 926 927 887 +3 887 927 892 +3 927 930 892 +3 930 902 892 +3 892 902 848 +3 902 860 848 +3 932 919 953 +3 919 893 953 +3 949 912 907 +3 912 876 907 +3 907 876 871 +3 876 824 871 +3 871 824 808 +3 824 785 808 +3 808 785 727 +3 785 726 727 +3 726 653 727 +3 727 653 628 +3 653 627 628 +3 627 547 628 +3 628 547 548 +3 548 547 456 +3 547 455 456 +3 456 455 433 +3 455 327 433 +3 433 327 328 +3 934 910 960 +3 960 910 943 +3 910 880 943 +3 943 880 905 +3 880 838 905 +3 937 909 904 +3 904 909 863 +3 909 869 863 +3 863 869 832 +3 869 834 832 +3 832 834 789 +3 834 790 789 +3 887 892 840 +3 892 848 840 +3 896 881 934 +3 934 881 910 +3 881 851 910 +3 910 851 880 +3 851 814 880 +3 880 814 838 +3 814 778 838 +3 904 863 843 +3 863 826 843 +3 843 826 812 +3 826 774 812 +3 812 774 768 +3 768 774 727 +3 774 782 727 +3 727 782 789 +3 789 782 832 +3 782 826 832 +3 832 826 863 +3 854 1050 682 +3 1050 1018 682 +3 682 1018 668 +3 668 1018 850 +3 1018 901 850 +3 850 901 776 +3 901 819 776 +3 776 819 800 +3 819 829 800 +3 800 829 809 +3 829 830 809 +3 809 830 806 +3 830 833 806 +3 806 833 788 +3 833 813 788 +3 788 813 764 +3 813 781 764 +3 764 781 737 +3 781 752 737 +3 737 752 704 +3 752 757 704 +3 704 757 721 +3 757 807 721 +3 721 807 728 +3 807 786 728 +3 728 786 729 +3 786 722 729 +3 729 722 626 +3 722 616 626 +3 626 616 550 +3 616 554 550 +3 550 554 498 +3 554 502 498 +3 498 502 424 +3 502 426 424 +3 424 426 379 +3 426 391 379 +3 391 361 379 +3 379 361 345 +3 361 308 345 +3 829 852 830 +3 852 867 830 +3 830 867 833 +3 867 864 833 +3 833 864 813 +3 864 835 813 +3 813 835 781 +3 835 801 781 +3 781 801 752 +3 801 757 752 +3 858 827 847 +3 827 802 847 +3 847 802 823 +3 802 766 823 +3 823 766 784 +3 766 744 784 +3 784 744 756 +3 744 709 756 +3 799 811 859 +3 859 811 860 +3 811 803 860 +3 860 803 848 +3 803 793 848 +3 848 793 840 +3 793 796 840 +3 796 841 840 +3 840 841 887 +3 841 886 887 +3 887 886 926 +3 886 923 926 +3 926 923 942 +3 923 939 942 +3 942 939 966 +3 939 965 966 +3 966 965 986 +3 965 985 986 +3 986 985 1000 +3 985 999 1000 +3 1000 999 1009 +3 999 998 1009 +3 1009 998 997 +3 997 998 979 +3 998 980 979 +3 979 980 961 +3 980 962 961 +3 961 962 936 +3 962 938 936 +3 936 938 922 +3 938 921 922 +3 922 921 891 +3 921 888 891 +3 891 888 857 +3 888 845 857 +3 857 845 815 +3 845 804 815 +3 815 804 761 +3 761 804 746 +3 804 796 746 +3 746 796 741 +3 796 793 741 +3 741 793 735 +3 793 803 735 +3 735 803 742 +3 803 811 742 +3 742 811 753 +3 811 799 753 +3 753 799 697 +3 799 712 697 +3 712 652 697 +3 697 652 664 +3 652 634 664 +3 664 634 630 +3 634 575 630 +3 630 575 570 +3 575 523 570 +3 523 518 570 +3 518 567 570 +3 570 567 623 +3 567 619 623 +3 623 619 656 +3 619 657 656 +3 656 657 686 +3 657 696 686 +3 686 696 746 +3 696 761 746 +3 798 1017 711 +3 794 798 759 +3 798 711 759 +3 789 790 727 +3 727 790 808 +3 790 834 808 +3 808 834 871 +3 834 869 871 +3 871 869 907 +3 869 909 907 +3 907 909 949 +3 909 937 949 +3 949 937 967 +3 967 937 931 +3 937 904 931 +3 931 904 889 +3 904 843 889 +3 889 843 831 +3 843 812 831 +3 831 812 795 +3 812 768 795 +3 795 768 758 +3 768 724 758 +3 758 724 748 +3 724 734 748 +3 734 762 748 +3 748 762 777 +3 762 791 777 +3 777 791 817 +3 791 844 817 +3 817 844 874 +3 844 890 874 +3 874 890 917 +3 890 955 917 +3 917 955 963 +3 955 987 963 +3 987 989 963 +3 963 989 967 +3 989 984 967 +3 967 984 949 +3 984 953 949 +3 949 953 912 +3 953 893 912 +3 912 893 876 +3 893 866 876 +3 876 866 824 +3 866 822 824 +3 824 822 785 +3 822 771 785 +3 785 771 726 +3 771 720 726 +3 726 720 653 +3 720 666 653 +3 653 666 627 +3 666 617 627 +3 627 617 547 +3 617 551 547 +3 547 551 455 +3 551 459 455 +3 455 459 327 +3 459 354 327 +3 327 354 317 +3 354 325 317 +3 317 325 283 +3 325 298 283 +3 283 298 223 +3 298 249 223 +3 223 249 227 +3 249 259 227 +3 227 259 240 +3 259 284 240 +3 240 284 264 +3 284 300 264 +3 264 300 291 +3 300 348 291 +3 291 348 306 +3 348 373 306 +3 306 373 332 +3 373 412 332 +3 332 412 414 +3 412 440 414 +3 414 440 444 +3 440 507 444 +3 444 507 525 +3 507 535 525 +3 525 535 539 +3 535 581 539 +3 539 581 585 +3 581 595 585 +3 585 595 599 +3 595 641 599 +3 599 641 645 +3 641 681 645 +3 645 681 853 +3 681 1049 853 +3 853 1049 1077 +3 1049 1091 1077 +3 1077 1091 1099 +3 1091 1125 1099 +3 1099 1125 1102 +3 1125 1114 1102 +3 1102 1114 1082 +3 1114 1089 1082 +3 1082 1089 1044 +3 1089 1046 1044 +3 1044 1046 1020 +3 1046 1022 1020 +3 1020 1022 978 +3 1022 996 978 +3 978 996 964 +3 996 972 964 +3 964 972 940 +3 972 983 940 +3 940 983 948 +3 948 983 954 +3 983 982 954 +3 954 982 970 +3 982 1010 970 +3 970 1010 1006 +3 1010 1064 1006 +3 1006 1064 1059 +3 1064 1120 1059 +3 1059 1120 1112 +3 1120 1152 1112 +3 1112 1152 1148 +3 1152 1162 1148 +3 1148 1162 1160 +3 1162 1151 1160 +3 1160 1151 1147 +3 1151 1119 1147 +3 1147 1119 1111 +3 1119 1063 1111 +3 1111 1063 1058 +3 1063 1030 1058 +3 1058 1030 1023 +3 1030 1008 1023 +3 1023 1008 995 +3 1008 987 995 +3 995 987 973 +3 987 955 973 +3 973 955 916 +3 955 890 916 +3 916 890 875 +3 890 844 875 +3 875 844 820 +3 844 791 820 +3 820 791 767 +3 791 762 767 +3 767 762 738 +3 762 734 738 +3 738 734 715 +3 734 724 715 +3 715 724 618 +3 724 628 618 +3 618 628 552 +3 628 548 552 +3 552 548 460 +3 548 456 460 +3 460 456 420 +3 456 433 420 +3 420 433 355 +3 433 328 355 +3 355 328 310 +3 328 327 310 +3 310 327 262 +3 327 317 262 +3 262 317 265 +3 317 283 265 +3 265 283 209 +3 283 223 209 +3 209 223 200 +3 223 227 200 +3 200 227 208 +3 227 240 208 +3 208 240 222 +3 240 264 222 +3 222 264 252 +3 264 291 252 +3 252 291 250 +3 291 306 250 +3 250 306 268 +3 306 332 268 +3 268 332 337 +3 332 414 337 +3 337 414 418 +3 414 444 418 +3 418 444 448 +3 444 525 448 +3 448 525 529 +3 525 539 529 +3 529 539 543 +3 539 585 543 +3 543 585 589 +3 585 599 589 +3 589 599 603 +3 599 645 603 +3 603 645 649 +3 645 853 649 +3 649 853 898 +3 853 1077 898 +3 898 1077 1085 +3 1077 1099 1085 +3 1085 1099 1092 +3 1099 1102 1092 +3 1092 1102 1074 +3 1102 1082 1074 +3 1074 1082 1038 +3 1082 1044 1038 +3 1038 1044 1002 +3 1044 1020 1002 +3 1002 1020 951 +3 1020 978 951 +3 951 978 947 +3 978 964 947 +3 947 964 929 +3 964 940 929 +3 929 940 908 +3 940 948 908 +3 908 948 906 +3 948 913 906 +3 906 913 877 +3 913 882 877 +3 877 882 842 +3 882 839 842 +3 842 839 787 +3 839 770 787 +3 787 770 708 +3 770 699 708 +3 708 699 610 +3 699 608 610 +3 610 608 558 +3 608 562 558 +3 558 562 506 +3 562 514 506 +3 506 514 428 +3 514 431 428 +3 428 431 400 +3 431 405 400 +3 400 405 394 +3 405 403 394 +3 826 782 774 +3 759 747 794 +3 794 747 772 +3 747 730 772 +3 772 730 750 +3 730 719 750 +3 750 719 731 +3 719 703 731 +3 731 703 705 +3 746 741 686 +3 741 675 686 +3 686 675 656 +3 741 735 675 +3 730 747 711 +3 747 759 711 +3 768 727 724 +3 727 628 724 +3 721 728 654 +3 728 729 654 +3 654 729 626 +3 776 713 850 +3 713 668 850 +3 713 776 760 +3 776 800 760 +3 760 800 779 +3 800 809 779 +3 779 809 780 +3 809 806 780 +3 780 806 765 +3 806 788 765 +3 765 788 745 +3 788 764 745 +3 745 764 718 +3 764 737 718 +3 718 737 695 +3 737 704 695 +3 695 704 662 +3 704 665 662 +3 662 665 615 +3 665 625 615 +3 615 625 545 +3 625 546 545 +3 545 546 454 +3 546 457 454 +3 454 457 432 +3 457 421 432 +3 432 421 352 +3 421 365 352 +3 352 365 324 +3 365 345 324 +3 324 345 294 +3 345 308 294 +3 294 308 246 +3 308 275 246 +3 275 248 246 +3 246 248 221 +3 248 226 221 +3 221 226 197 +3 226 216 197 +3 197 216 176 +3 216 201 176 +3 176 201 160 +3 201 158 160 +3 160 158 122 +3 158 148 122 +3 122 148 114 +3 148 152 114 +3 114 152 118 +3 152 154 118 +3 118 154 120 +3 154 151 120 +3 120 151 117 +3 151 124 117 +3 117 124 94 +3 124 108 94 +3 94 108 80 +3 108 105 80 +3 80 105 79 +3 105 103 79 +3 79 103 78 +3 103 99 78 +3 78 99 75 +3 99 100 75 +3 75 100 77 +3 713 760 749 +3 760 779 749 +3 749 779 763 +3 779 780 763 +3 763 780 751 +3 780 765 751 +3 751 765 725 +3 765 745 725 +3 725 745 702 +3 745 718 702 +3 702 718 685 +3 718 695 685 +3 685 695 658 +3 695 662 658 +3 658 662 609 +3 662 615 609 +3 609 615 549 +3 615 545 549 +3 545 454 549 +3 549 454 458 +3 454 330 458 +3 458 330 353 +3 330 309 353 +3 353 309 270 +3 309 257 270 +3 270 257 218 +3 257 180 218 +3 218 180 172 +3 180 145 172 +3 172 145 141 +3 145 111 141 +3 141 111 106 +3 111 89 106 +3 106 89 76 +3 89 64 76 +3 76 64 70 +3 70 64 47 +3 64 5 47 +3 47 5 2 +3 5 22 2 +3 22 20 2 +3 20 18 2 +3 18 16 2 +3 16 14 2 +3 14 12 2 +3 12 10 2 +3 2 10 0 +3 10 8 0 +3 8 6 0 +3 6 7 0 +3 7 9 0 +3 9 11 0 +3 0 11 1 +3 11 13 1 +3 13 15 1 +3 15 17 1 +3 17 19 1 +3 19 21 1 +3 21 23 1 +3 1 23 3 +3 23 25 3 +3 3 25 41 +3 25 44 41 +3 41 44 48 +3 44 59 48 +3 48 59 69 +3 59 85 69 +3 69 85 94 +3 94 85 117 +3 85 88 117 +3 117 88 120 +3 88 86 120 +3 120 86 118 +3 86 82 118 +3 118 82 114 +3 82 92 114 +3 114 92 122 +3 92 127 122 +3 122 127 160 +3 127 139 160 +3 160 139 176 +3 139 164 176 +3 176 164 197 +3 164 198 197 +3 197 198 221 +3 198 220 221 +3 221 220 246 +3 246 220 294 +3 220 279 294 +3 294 279 324 +3 279 318 324 +3 324 318 352 +3 318 329 352 +3 352 329 432 +3 329 330 432 +3 432 330 454 +3 713 749 739 +3 749 763 739 +3 739 763 733 +3 763 751 733 +3 733 751 716 +3 751 725 716 +3 716 725 698 +3 725 702 698 +3 698 702 672 +3 702 685 672 +3 672 685 655 +3 685 658 655 +3 655 658 607 +3 658 609 607 +3 607 609 553 +3 609 549 553 +3 553 549 458 +3 713 739 723 +3 739 733 723 +3 723 733 710 +3 733 716 710 +3 710 716 693 +3 716 698 693 +3 693 698 674 +3 698 672 674 +3 674 672 659 +3 672 655 659 +3 659 655 613 +3 655 607 613 +3 613 607 557 +3 607 553 557 +3 557 553 497 +3 553 458 497 +3 497 458 367 +3 458 353 367 +3 367 353 287 +3 353 270 287 +3 270 218 287 +3 287 218 224 +3 218 172 224 +3 224 172 183 +3 172 141 183 +3 183 141 159 +3 141 106 159 +3 159 106 125 +3 106 76 125 +3 125 76 107 +3 76 70 107 +3 713 723 707 +3 723 710 707 +3 707 710 694 +3 710 693 694 +3 693 674 694 +3 694 674 688 +3 674 663 688 +3 688 663 713 +3 663 633 713 +3 713 633 668 +3 633 638 668 +3 668 638 682 +3 638 642 682 +3 682 642 854 +3 642 646 854 +3 854 646 898 +3 898 646 649 +3 646 600 649 +3 649 600 603 +3 600 586 603 +3 603 586 589 +3 586 540 589 +3 589 540 543 +3 540 526 543 +3 543 526 529 +3 526 445 529 +3 529 445 448 +3 448 445 418 +3 445 415 418 +3 418 415 343 +3 415 338 343 +3 343 338 276 +3 338 272 276 +3 276 272 238 +3 272 232 238 +3 232 195 238 +3 238 195 191 +3 195 149 191 +3 191 149 147 +3 149 113 147 +3 147 113 121 +3 113 91 121 +3 91 98 121 +3 121 98 130 +3 98 110 130 +3 130 110 143 +3 110 136 143 +3 143 136 165 +3 136 175 165 +3 165 175 200 +3 200 175 209 +3 175 185 209 +3 209 185 265 +3 185 212 265 +3 265 212 262 +3 212 258 262 +3 262 258 310 +3 258 293 310 +3 310 293 355 +3 293 368 355 +3 355 368 420 +3 368 423 420 +3 420 423 500 +3 423 504 500 +3 500 504 560 +3 504 564 560 +3 560 564 620 +3 564 624 620 +3 620 624 671 +3 624 679 671 +3 671 679 755 +3 679 773 755 +3 755 773 836 +3 773 818 836 +3 836 818 872 +3 818 944 872 +3 872 944 968 +3 944 1035 968 +3 968 1035 1040 +3 1035 1075 1040 +3 1040 1075 1083 +3 1075 1103 1083 +3 1083 1103 1115 +3 1103 1126 1115 +3 1115 1126 1132 +3 1126 1104 1132 +3 1132 1104 1116 +3 1104 1076 1116 +3 1116 1076 1084 +3 1076 1036 1084 +3 1084 1036 1037 +3 1036 896 1037 +3 1037 896 1043 +3 896 934 1043 +3 1043 934 1048 +3 934 960 1048 +3 1048 960 1055 +3 960 991 1055 +3 1055 991 1059 +3 1059 991 1006 +3 1006 991 970 +3 991 958 970 +3 970 958 918 +3 958 905 918 +3 918 905 868 +3 905 838 868 +3 868 838 805 +3 838 778 805 +3 805 778 732 +3 778 717 732 +3 732 717 676 +3 717 673 676 +3 676 673 622 +3 673 632 622 +3 622 632 572 +3 632 636 572 +3 572 636 574 +3 636 594 574 +3 574 594 580 +3 594 584 580 +3 580 584 538 +3 584 542 538 +3 538 542 528 +3 542 530 528 +3 528 530 449 +3 530 446 449 +3 449 446 419 +3 446 416 419 +3 419 416 344 +3 416 339 344 +3 344 339 277 +3 339 273 277 +3 277 273 239 +3 273 233 239 +3 239 233 196 +3 196 233 193 +3 233 190 193 +3 193 190 156 +3 156 190 144 +3 190 184 144 +3 144 184 179 +3 184 219 179 +3 179 219 214 +3 219 254 214 +3 214 254 247 +3 254 302 247 +3 247 302 293 +3 293 302 368 +3 302 383 368 +3 368 383 423 +3 383 425 423 +3 423 425 504 +3 425 512 504 +3 504 512 564 +3 512 568 564 +3 564 568 624 +3 568 631 624 +3 624 631 679 +3 631 691 679 +3 679 691 773 +3 691 775 773 +3 773 775 818 +3 775 900 818 +3 818 900 944 +3 900 1026 944 +3 944 1026 1035 +3 1026 1067 1035 +3 1035 1067 1075 +3 1067 1094 1075 +3 1075 1094 1103 +3 1094 1100 1103 +3 1103 1100 1126 +3 1100 1093 1126 +3 1126 1093 1104 +3 1093 1068 1104 +3 1104 1068 1076 +3 1068 1027 1076 +3 1076 1027 1036 +3 1027 858 1036 +3 1036 858 896 +3 858 847 896 +3 896 847 881 +3 847 823 881 +3 881 823 851 +3 823 784 851 +3 851 784 814 +3 784 756 814 +3 814 756 778 +3 778 756 717 +3 756 709 717 +3 717 709 673 +3 709 680 673 +3 673 680 632 +3 680 651 632 +3 632 651 636 +3 651 640 636 +3 636 640 594 +3 640 598 594 +3 594 598 584 +3 598 588 584 +3 584 588 542 +3 588 544 542 +3 542 544 530 +3 544 527 530 +3 530 527 446 +3 527 442 446 +3 446 442 416 +3 442 438 416 +3 416 438 409 +3 438 435 409 +3 409 435 407 +3 435 430 407 +3 407 430 401 +3 430 429 401 +3 401 429 392 +3 429 427 392 +3 392 427 425 +3 425 427 512 +3 427 516 512 +3 512 516 568 +3 516 571 568 +3 568 571 631 +3 571 635 631 +3 631 635 691 +3 635 714 691 +3 691 714 775 +3 714 849 775 +3 775 849 900 +3 849 1016 900 +3 900 1016 1026 +3 1016 1051 1026 +3 1026 1051 1067 +3 1051 1079 1067 +3 1067 1079 1094 +3 1079 1086 1094 +3 1094 1086 1100 +3 1086 1080 1100 +3 1100 1080 1093 +3 1080 1052 1093 +3 1093 1052 1068 +3 1052 1017 1068 +3 1068 1017 1027 +3 1017 798 1027 +3 1027 798 858 +3 798 794 858 +3 858 794 827 +3 794 772 827 +3 827 772 802 +3 772 750 802 +3 802 750 766 +3 750 731 766 +3 766 731 744 +3 731 705 744 +3 744 705 709 +3 709 705 680 +3 705 692 680 +3 680 692 651 +3 692 711 651 +3 651 711 670 +3 711 1017 670 +3 670 1017 684 +3 1017 1052 684 +3 684 1052 856 +3 1052 1080 856 +3 856 1080 899 +3 1080 1086 899 +3 1086 1079 899 +3 899 1079 855 +3 1079 1051 855 +3 855 1051 683 +3 1051 1016 683 +3 683 1016 669 +3 1016 849 669 +3 849 714 669 +3 714 635 669 +3 669 635 639 +3 635 593 639 +3 639 593 643 +3 593 597 643 +3 643 597 647 +3 597 601 647 +3 647 601 650 +3 601 604 650 +3 650 604 648 +3 604 602 648 +3 648 602 644 +3 602 598 644 +3 598 640 644 +3 644 640 670 +3 640 651 670 +3 730 711 719 +3 711 692 719 +3 719 692 703 +3 692 705 703 +3 708 792 787 +3 787 792 842 +3 792 825 842 +3 842 825 877 +3 825 870 877 +3 877 870 906 +3 870 862 906 +3 906 862 908 +3 862 903 908 +3 908 903 929 +3 903 911 929 +3 929 911 947 +3 911 914 947 +3 947 914 951 +3 914 925 951 +3 951 925 1002 +3 925 969 1002 +3 1002 969 1038 +3 969 1033 1038 +3 1038 1033 1074 +3 1033 1066 1074 +3 1074 1066 1092 +3 1066 1078 1092 +3 1092 1078 1085 +3 1085 1078 898 +3 898 1078 854 +3 854 1078 1050 +3 1078 1066 1050 +3 1050 1066 1028 +3 1066 1033 1028 +3 1028 1033 945 +3 1033 969 945 +3 945 969 873 +3 969 925 873 +3 873 925 884 +3 925 914 884 +3 884 914 885 +3 914 911 885 +3 885 911 883 +3 911 903 883 +3 883 903 846 +3 903 862 846 +3 846 862 810 +3 862 870 810 +3 810 870 807 +3 870 825 807 +3 807 825 786 +3 825 792 786 +3 786 792 722 +3 792 708 722 +3 722 708 616 +3 708 610 616 +3 616 610 554 +3 610 558 554 +3 554 558 502 +3 558 506 502 +3 502 506 426 +3 506 428 426 +3 426 428 391 +3 428 400 391 +3 400 375 391 +3 391 375 361 +3 375 323 361 +3 361 323 308 +3 323 275 308 +3 704 721 665 +3 721 654 665 +3 665 654 625 +3 654 626 625 +3 625 626 546 +3 626 550 546 +3 546 550 461 +3 550 498 461 +3 461 498 422 +3 498 424 422 +3 424 379 422 +3 422 379 365 +3 379 345 365 +3 707 700 713 +3 700 688 713 +3 707 694 700 +3 694 688 700 +3 742 677 735 +3 735 677 675 +3 677 660 675 +3 675 660 656 +3 660 623 656 +3 670 684 644 +3 644 684 648 +3 684 856 648 +3 648 856 650 +3 856 899 650 +3 650 899 647 +3 899 855 647 +3 647 855 643 +3 855 683 643 +3 643 683 639 +3 683 669 639 +3 664 690 697 +3 697 690 753 +3 753 690 742 +3 742 690 677 +3 690 664 677 +3 677 664 660 +3 664 630 660 +3 660 630 623 +3 630 570 623 +3 674 659 663 +3 663 659 621 +3 659 613 621 +3 621 613 561 +3 613 557 561 +3 561 557 501 +3 557 497 501 +3 501 497 378 +3 497 367 378 +3 378 367 299 +3 367 287 299 +3 299 287 224 +3 633 663 629 +3 663 621 629 +3 629 621 565 +3 621 561 565 +3 565 561 505 +3 561 501 505 +3 505 501 389 +3 501 378 389 +3 389 378 313 +3 378 299 313 +3 313 299 241 +3 299 224 241 +3 224 183 241 +3 241 183 205 +3 183 159 205 +3 666 605 617 +3 605 555 617 +3 617 555 551 +3 555 499 551 +3 551 499 459 +3 499 369 459 +3 459 369 354 +3 354 369 325 +3 369 347 325 +3 325 347 298 +3 347 315 298 +3 298 315 249 +3 315 286 249 +3 249 286 259 +3 286 301 259 +3 259 301 284 +3 301 304 284 +3 284 304 300 +3 304 356 300 +3 300 356 348 +3 348 356 373 +3 356 362 373 +3 373 362 371 +3 362 321 371 +3 371 321 335 +3 321 314 335 +3 335 314 364 +3 314 334 364 +3 364 334 381 +3 334 366 381 +3 381 366 386 +3 366 347 386 +3 347 369 386 +3 386 369 503 +3 369 499 503 +3 499 555 503 +3 503 555 559 +3 555 605 559 +3 602 604 590 +3 604 587 590 +3 590 587 541 +3 587 537 541 +3 541 537 509 +3 509 537 452 +3 537 533 452 +3 452 533 524 +3 533 576 524 +3 524 576 519 +3 576 571 519 +3 519 571 516 +3 604 601 587 +3 601 583 587 +3 587 583 537 +3 537 583 533 +3 583 579 533 +3 533 579 576 +3 579 593 576 +3 593 635 576 +3 576 635 571 +3 598 602 588 +3 602 590 588 +3 588 590 544 +3 590 541 544 +3 544 541 527 +3 541 509 527 +3 527 509 442 +3 442 509 438 +3 509 452 438 +3 438 452 435 +3 452 524 435 +3 435 524 430 +3 524 519 430 +3 430 519 429 +3 519 516 429 +3 429 516 427 +3 601 597 583 +3 583 597 579 +3 597 593 579 +3 573 578 592 +3 592 578 596 +3 596 578 582 +3 582 578 532 +3 578 573 532 +3 532 573 521 +3 573 569 521 +3 521 569 517 +3 569 513 517 +3 517 513 406 +3 513 398 406 +3 406 398 382 +3 398 360 382 +3 382 360 316 +3 360 290 316 +3 316 290 256 +3 290 228 256 +3 256 228 211 +3 228 177 211 +3 211 177 142 +3 582 532 536 +3 532 451 536 +3 536 451 508 +3 508 451 437 +3 451 434 437 +3 437 434 411 +3 411 434 406 +3 406 434 517 +3 517 434 521 +3 434 451 521 +3 521 451 532 +3 559 511 503 +3 503 511 386 +3 511 393 386 +3 386 393 381 +3 496 495 494 +3 495 492 494 +3 494 492 493 +3 492 490 493 +3 493 490 491 +3 490 488 491 +3 491 488 489 +3 488 486 489 +3 489 486 487 +3 486 484 487 +3 487 484 485 +3 484 482 485 +3 485 482 483 +3 482 480 483 +3 483 480 481 +3 480 478 481 +3 481 478 479 +3 478 476 479 +3 479 476 477 +3 476 474 477 +3 477 474 475 +3 474 472 475 +3 475 472 473 +3 472 470 473 +3 473 470 471 +3 470 468 471 +3 471 468 469 +3 468 466 469 +3 469 466 467 +3 466 464 467 +3 467 464 465 +3 464 462 465 +3 465 462 463 +3 546 461 457 +3 457 461 421 +3 461 422 421 +3 421 422 365 +3 447 443 510 +3 443 453 510 +3 510 453 534 +3 534 453 522 +3 522 453 439 +3 453 443 439 +3 526 441 445 +3 441 415 445 +3 417 419 340 +3 419 344 340 +3 340 344 274 +3 344 277 274 +3 413 417 333 +3 417 340 333 +3 333 340 269 +3 340 274 269 +3 269 274 230 +3 230 274 234 +3 274 277 234 +3 234 277 239 +3 431 410 405 +3 410 403 405 +3 410 413 374 +3 413 333 374 +3 374 333 307 +3 333 269 307 +3 307 269 251 +3 269 230 251 +3 251 230 207 +3 207 230 188 +3 230 234 188 +3 188 234 194 +3 234 239 194 +3 194 239 196 +3 416 409 339 +3 409 342 339 +3 339 342 281 +3 342 278 281 +3 281 278 225 +3 278 261 225 +3 225 261 219 +3 219 261 254 +3 261 311 254 +3 254 311 302 +3 302 311 383 +3 311 392 383 +3 383 392 425 +3 409 407 342 +3 407 336 342 +3 342 336 278 +3 336 320 278 +3 278 320 261 +3 261 320 311 +3 311 320 392 +3 392 320 401 +3 320 336 401 +3 401 336 407 +3 411 406 399 +3 406 382 399 +3 399 382 350 +3 382 316 350 +3 350 316 297 +3 316 256 297 +3 297 256 237 +3 256 211 237 +3 237 211 178 +3 211 142 178 +3 178 142 131 +3 142 107 131 +3 131 107 104 +3 107 70 104 +3 104 70 68 +3 70 47 68 +3 68 47 58 +3 47 2 58 +3 58 2 61 +3 2 0 61 +3 61 0 57 +3 0 1 57 +3 57 1 55 +3 1 3 55 +3 55 3 66 +3 3 4 66 +3 66 4 49 +3 4 41 49 +3 41 65 49 +3 49 65 71 +3 71 65 90 +3 90 65 100 +3 65 77 100 +3 408 402 404 +3 402 395 404 +3 411 399 387 +3 399 350 387 +3 387 350 322 +3 350 297 322 +3 322 297 282 +3 297 237 282 +3 282 237 217 +3 237 178 217 +3 217 178 166 +3 178 131 166 +3 166 131 126 +3 131 104 126 +3 126 104 93 +3 104 68 93 +3 93 68 84 +3 68 58 84 +3 58 61 84 +3 84 61 87 +3 61 57 87 +3 87 57 83 +3 57 55 83 +3 83 55 81 +3 55 66 81 +3 404 395 390 +3 400 394 388 +3 393 390 381 +3 381 390 364 +3 364 390 380 +3 390 395 380 +3 380 395 396 +3 395 402 396 +3 396 402 373 +3 402 408 373 +3 400 388 375 +3 388 359 375 +3 375 359 323 +3 359 305 323 +3 323 305 275 +3 305 292 275 +3 275 292 248 +3 292 267 248 +3 248 267 226 +3 267 255 226 +3 226 255 216 +3 255 245 216 +3 216 245 201 +3 245 207 201 +3 201 207 158 +3 207 188 158 +3 158 188 148 +3 188 194 148 +3 148 194 152 +3 194 196 152 +3 152 196 154 +3 196 193 154 +3 154 193 151 +3 193 156 151 +3 151 156 124 +3 156 144 124 +3 124 144 108 +3 144 140 108 +3 108 140 105 +3 140 134 105 +3 105 134 103 +3 134 133 103 +3 103 133 99 +3 133 132 99 +3 99 132 100 +3 132 112 100 +3 100 112 90 +3 112 96 90 +3 90 96 71 +3 96 101 71 +3 71 101 73 +3 101 98 73 +3 73 98 66 +3 98 91 66 +3 66 91 81 +3 91 113 81 +3 81 113 115 +3 113 149 115 +3 115 149 153 +3 149 195 153 +3 153 195 192 +3 195 232 192 +3 192 232 189 +3 232 235 189 +3 189 235 242 +3 235 280 242 +3 242 280 285 +3 280 346 285 +3 285 346 351 +3 346 411 351 +3 411 387 376 +3 387 322 376 +3 376 322 312 +3 322 282 312 +3 312 282 253 +3 282 217 253 +3 253 217 203 +3 217 166 203 +3 203 166 163 +3 166 126 163 +3 163 126 123 +3 126 93 123 +3 123 93 116 +3 93 84 116 +3 84 87 116 +3 116 87 119 +3 87 83 119 +3 119 83 115 +3 83 81 115 +3 380 396 384 +3 396 373 384 +3 373 371 384 +3 371 335 384 +3 384 335 380 +3 335 364 380 +3 411 376 370 +3 376 312 370 +3 370 312 296 +3 312 253 296 +3 296 253 244 +3 253 203 244 +3 244 203 199 +3 203 163 199 +3 199 163 155 +3 163 123 155 +3 155 123 150 +3 123 116 150 +3 116 119 150 +3 150 119 153 +3 119 115 153 +3 410 374 403 +3 374 397 403 +3 403 397 394 +3 397 377 394 +3 394 377 388 +3 388 377 359 +3 377 331 359 +3 359 331 305 +3 331 319 305 +3 305 319 292 +3 319 303 292 +3 292 303 267 +3 303 295 267 +3 267 295 255 +3 295 288 255 +3 255 288 245 +3 288 251 245 +3 245 251 207 +3 411 370 358 +3 370 296 358 +3 358 296 289 +3 296 244 289 +3 289 244 242 +3 244 199 242 +3 242 199 189 +3 199 155 189 +3 189 155 192 +3 155 150 192 +3 192 150 153 +3 363 372 374 +3 372 385 374 +3 374 385 397 +3 397 385 377 +3 377 385 331 +3 385 372 331 +3 331 372 319 +3 372 363 319 +3 319 363 303 +3 303 363 357 +3 363 374 357 +3 357 374 349 +3 374 307 349 +3 349 307 288 +3 307 251 288 +3 411 358 351 +3 358 289 351 +3 351 289 285 +3 289 242 285 +3 347 366 315 +3 366 334 315 +3 315 334 286 +3 334 314 286 +3 286 314 301 +3 314 321 301 +3 301 321 304 +3 321 362 304 +3 304 362 356 +3 411 346 341 +3 346 280 341 +3 418 343 337 +3 343 271 337 +3 337 271 268 +3 271 229 268 +3 268 229 250 +3 229 206 250 +3 250 206 252 +3 206 215 252 +3 252 215 222 +3 215 182 222 +3 222 182 208 +3 182 165 208 +3 208 165 200 +3 330 329 309 +3 329 263 309 +3 309 263 257 +3 263 213 257 +3 257 213 180 +3 213 169 180 +3 180 169 145 +3 169 138 145 +3 145 138 111 +3 138 97 111 +3 111 97 89 +3 97 72 89 +3 89 72 64 +3 72 50 64 +3 64 50 5 +3 50 42 5 +3 5 42 43 +3 42 67 43 +3 43 67 56 +3 67 82 56 +3 82 86 56 +3 56 86 60 +3 86 88 60 +3 60 88 62 +3 88 85 62 +3 85 59 62 +3 59 44 62 +3 62 44 46 +3 44 37 46 +3 37 38 46 +3 38 40 46 +3 40 39 46 +3 39 36 46 +3 46 36 45 +3 36 34 45 +3 34 32 45 +3 32 30 45 +3 30 28 45 +3 28 26 45 +3 26 24 45 +3 45 24 43 +3 24 22 43 +3 43 22 5 +3 329 318 263 +3 263 318 266 +3 318 279 266 +3 279 204 266 +3 266 204 186 +3 204 173 186 +3 186 173 162 +3 173 135 162 +3 162 135 129 +3 135 109 129 +3 129 109 102 +3 109 95 102 +3 102 95 74 +3 95 67 74 +3 74 67 50 +3 67 42 50 +3 389 313 326 +3 326 313 260 +3 313 241 260 +3 260 241 205 +3 303 357 295 +3 357 349 295 +3 295 349 288 +3 339 281 273 +3 281 236 273 +3 273 236 233 +3 233 236 190 +3 190 236 184 +3 236 225 184 +3 184 225 219 +3 343 276 271 +3 276 231 271 +3 271 231 229 +3 231 187 229 +3 229 187 206 +3 187 157 206 +3 206 157 171 +3 157 130 171 +3 130 143 171 +3 171 143 182 +3 143 165 182 +3 263 266 213 +3 266 186 213 +3 213 186 169 +3 186 162 169 +3 169 162 138 +3 162 129 138 +3 138 129 97 +3 129 102 97 +3 97 102 72 +3 102 74 72 +3 72 74 50 +3 276 238 231 +3 238 191 231 +3 231 191 187 +3 191 147 187 +3 187 147 157 +3 147 121 157 +3 157 121 130 +3 236 281 225 +3 232 272 235 +3 235 272 280 +3 272 338 280 +3 280 338 341 +3 341 338 411 +3 338 415 411 +3 411 415 437 +3 415 441 437 +3 437 441 508 +3 441 526 508 +3 526 540 508 +3 508 540 536 +3 540 586 536 +3 536 586 582 +3 586 600 582 +3 582 600 596 +3 600 646 596 +3 646 642 596 +3 596 642 592 +3 642 638 592 +3 638 633 592 +3 592 633 573 +3 633 629 573 +3 573 629 569 +3 629 565 569 +3 569 565 513 +3 565 505 513 +3 513 505 398 +3 505 389 398 +3 398 389 360 +3 389 326 360 +3 360 326 290 +3 326 260 290 +3 290 260 228 +3 260 205 228 +3 228 205 177 +3 205 159 177 +3 159 125 177 +3 177 125 142 +3 125 107 142 +3 279 220 204 +3 220 198 204 +3 204 198 173 +3 198 164 173 +3 173 164 135 +3 164 139 135 +3 135 139 109 +3 139 127 109 +3 109 127 95 +3 127 92 95 +3 95 92 67 +3 92 82 67 +3 210 243 202 +3 243 181 202 +3 182 215 171 +3 215 206 171 +3 144 179 140 +3 140 179 174 +3 179 214 174 +3 174 214 210 +3 214 247 210 +3 210 247 243 +3 247 293 243 +3 293 258 243 +3 243 258 181 +3 258 212 181 +3 181 212 168 +3 212 185 168 +3 168 185 161 +3 185 175 161 +3 175 136 161 +3 161 136 128 +3 136 110 128 +3 128 110 101 +3 110 98 101 +3 140 174 134 +3 134 174 170 +3 174 210 170 +3 210 202 170 +3 170 202 167 +3 202 181 167 +3 167 181 146 +3 181 168 146 +3 146 168 137 +3 168 161 137 +3 161 128 137 +3 137 128 96 +3 128 101 96 +3 134 170 133 +3 170 167 133 +3 133 167 132 +3 167 146 132 +3 132 146 112 +3 146 137 112 +3 112 137 96 +3 94 80 69 +3 69 80 63 +3 80 79 63 +3 79 54 63 +3 63 54 48 +3 54 41 48 +3 79 78 54 +3 78 53 54 +3 54 53 41 +3 78 75 53 +3 75 51 53 +3 53 51 41 +3 75 77 51 +3 71 73 49 +3 73 66 49 +3 77 65 52 +3 65 41 52 +3 69 63 48 +3 77 52 51 +3 52 41 51 +3 62 46 60 +3 46 45 60 +3 60 45 56 +3 45 43 56 +3 39 493 36 +3 493 491 36 +3 36 491 34 +3 491 489 34 +3 34 489 32 +3 489 487 32 +3 32 487 30 +3 487 485 30 +3 30 485 28 +3 485 483 28 +3 28 483 26 +3 483 481 26 +3 26 481 24 +3 481 479 24 +3 24 479 22 +3 479 477 22 +3 22 477 20 +3 477 475 20 +3 20 475 18 +3 475 473 18 +3 18 473 16 +3 473 471 16 +3 16 471 14 +3 471 469 14 +3 14 469 12 +3 469 467 12 +3 12 467 10 +3 467 465 10 +3 10 465 8 +3 465 463 8 +3 8 463 6 +3 463 462 6 +3 6 462 7 +3 462 464 7 +3 7 464 9 +3 464 466 9 +3 9 466 11 +3 466 468 11 +3 11 468 13 +3 468 470 13 +3 13 470 15 +3 470 472 15 +3 15 472 17 +3 472 474 17 +3 17 474 19 +3 474 476 19 +3 19 476 21 +3 476 478 21 +3 21 478 23 +3 478 480 23 +3 23 480 25 +3 480 482 25 +3 25 482 27 +3 482 484 27 +3 27 484 29 +3 484 486 29 +3 29 486 31 +3 486 488 31 +3 31 488 33 +3 488 490 33 +3 33 490 35 +3 490 492 35 +3 35 492 37 +3 492 495 37 +3 37 495 38 +3 38 495 40 +3 495 496 40 +3 40 496 39 +3 496 494 39 +3 39 494 493 +3 37 44 35 +3 35 44 33 +3 33 44 31 +3 31 44 29 +3 29 44 27 +3 44 25 27 +3 41 4 3 + diff --git a/AABB_tree/benchmark/AABB_tree/test.cpp b/AABB_tree/benchmark/AABB_tree/test.cpp new file mode 100644 index 00000000000..ef73cc00348 --- /dev/null +++ b/AABB_tree/benchmark/AABB_tree/test.cpp @@ -0,0 +1,100 @@ +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Surface_mesh Surface_mesh; + +typedef CGAL::AABB_face_graph_triangle_primitive Primitive; +typedef CGAL::AABB_traits AABB_triangle_traits; +typedef CGAL::AABB_transformed_traits Traits; +typedef CGAL::AABB_tree Tree; + +namespace PMP = CGAL::Polygon_mesh_processing; + +void test_no_collision(int k, const char* fname, + int& nb_inter, int& nb_no_inter, int& nb_include) +{ + std::ifstream input(fname); + Surface_mesh tm, tm2; + input >> tm; + copy_face_graph(tm, tm2); + CGAL::Aff_transformation_3 init1(CGAL::SCALING, 6.0); + PMP::transform(init1, tm); + CGAL::Bbox_3 box = PMP::bbox(tm); + Tree tmTree(tm.faces_begin(), tm.faces_end(), tm); + Tree tmTree2(tm2.faces_begin(), tm2.faces_end(), tm2); + CGAL::Aff_transformation_3 init2(CGAL::TRANSLATION, - K::Vector_3( + (box.xmax()-box.xmin()),0,0)); + PMP::transform(init2, tm2); + + std::ofstream out1("/home/gimeno/Data/tmp/m1.off"), + out2("/home/gimeno/Data/tmp/m2.off"); + out1 << tm; + out1.close(); + out2 << tm2; + out2.close(); + tmTree.build(); + tmTree2.build(); + typedef boost::property_map::type VPM; + //VPM vpm = get(CGAL::vertex_point, tm); + + K::Vector_3 unit_vec = (2.0/k * K::Vector_3((box.xmax()-box.xmin()), + 0, + 0)); + CGAL::Aff_transformation_3 trans2(CGAL::TRANSLATION, unit_vec); + CGAL::Side_of_triangle_mesh sotm1(tmTree); + for(int i=1; i trans22(CGAL::TRANSLATION, i*unit_vec); + PMP::transform(trans2, tm2); + box = PMP::bbox(tm2); + tmTree2.traits().set_transformation(trans22); + if(tmTree2.do_intersect(tmTree)) + ++nb_inter; + else + { + if(sotm1(tm2.point(*tm2.vertices().begin())) != CGAL::ON_UNBOUNDED_SIDE) + { + ++nb_include; + } + else + { + CGAL::Side_of_triangle_mesh sotm2(tmTree2); + if(sotm2(tm2.point(*tm2.vertices().begin())) != CGAL::ON_UNBOUNDED_SIDE) + ++nb_include; + else + ++nb_no_inter; + } + } + } +} + +int main(int argc, const char** argv) +{ + int k = atoi(argv[1]); + const char* path = (argc>2)?argv[2]:"data/handle" + ".off"; + std::cout<< k<<" steps in "<(end - start).count() << "μs." << std::endl; +} diff --git a/AABB_tree/include/CGAL/AABB_transformed_traits.h b/AABB_tree/include/CGAL/AABB_transformed_traits.h index 20788e833d9..2fb05307b87 100644 --- a/AABB_tree/include/CGAL/AABB_transformed_traits.h +++ b/AABB_tree/include/CGAL/AABB_transformed_traits.h @@ -42,7 +42,9 @@ /// \file AABB_transformed_traits.h namespace CGAL { - +// forward declaration +template< typename AABBTraits> +class AABB_tree; /// \addtogroup PkgAABB_tree /// @{ @@ -118,7 +120,27 @@ public: template bool operator()(const Query& q, const Primitive& pr) const { - return Kernel().do_intersect_3_object()(q, internal::Primitive_helper::get_datum(pr,m_traits).transform(m_traits.transformation())); + return Kernel().do_intersect_3_object()(q, internal::Primitive_helper::get_datum(pr,m_traits)); + } + + // intersection with AABB-tree + template + bool operator()(const CGAL::AABB_tree& other_tree, const Primitive& pr) const + { + return other_tree.do_intersect( internal::Primitive_helper::get_datum(pr,m_traits)); + } + + template + bool operator()(const CGAL::AABB_tree& other_tree, const Bounding_box& bbox) const + { + Point_3 min(bbox.xmin(), bbox.ymin(), bbox.zmin()), + max(bbox.xmax(), bbox.ymax(), bbox.zmax()); + + min = m_traits.transformation().transform(min); + max = m_traits.transformation().transform(max); + Bounding_box transfo_box(to_double(min.x()), to_double(min.y()), to_double(min.z()), + to_double(max.x()), to_double(max.y()), to_double(max.z())); + return other_tree.do_intersect(transfo_box); } }; From 48c0cc02a21c170e5ea3a3d37d901d3d9d5791f5 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 18 Jul 2018 11:28:19 +0200 Subject: [PATCH 05/84] Add Filtered_predicates support --- AABB_tree/benchmark/AABB_tree/test.cpp | 2 +- .../include/CGAL/AABB_transformed_traits.h | 204 ++++-------------- .../CGAL/AABB_transformed_traits_base.h | 202 +++++++++++++++++ 3 files changed, 245 insertions(+), 163 deletions(-) create mode 100644 AABB_tree/include/CGAL/AABB_transformed_traits_base.h diff --git a/AABB_tree/benchmark/AABB_tree/test.cpp b/AABB_tree/benchmark/AABB_tree/test.cpp index ef73cc00348..beff8c25fcd 100644 --- a/AABB_tree/benchmark/AABB_tree/test.cpp +++ b/AABB_tree/benchmark/AABB_tree/test.cpp @@ -86,7 +86,7 @@ void test_no_collision(int k, const char* fname, int main(int argc, const char** argv) { - int k = atoi(argv[1]); + int k = (argc>1) ? atoi(argv[1]) : 10; const char* path = (argc>2)?argv[2]:"data/handle" ".off"; std::cout<< k<<" steps in "< +#include +#include -#include +namespace CGAL{ +template +class AABB_transformed_traits + :public AABB_transformed_traits_base +{}; -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/// \file AABB_transformed_traits.h - -namespace CGAL { -// forward declaration -template< typename AABBTraits> -class AABB_tree; -/// \addtogroup PkgAABB_tree -/// @{ - -/// \tparam BaseTraits a model of `CGAL::AABBTraits` -/// -/// \sa `AABBTraits` -/// \sa `AABB_tree` -/// \sa `AABBPrimitive` -/// \sa `AABBPrimitiveWithSharedData` - - template -class AABB_transformed_traits: - public BaseTraits +template +class AABB_transformed_traits + :public AABB_transformed_traits_base { -public: - - //Constructor - AABB_transformed_traits(const Aff_transformation_3& transf = Aff_transformation_3(IDENTITY)) - :m_transfo(transf) - {} - // AABBTraits concept types - typedef typename BaseTraits::FT FT; - typedef typename BaseTraits::Point_3 Point_3; - typedef typename BaseTraits::Primitive Primitive; - typedef typename BaseTraits::Bounding_box Bounding_box; - typedef typename BaseTraits::Point_and_primitive_id Point_and_primitive_id; - typedef typename BaseTraits::Object_and_primitive_id Object_and_primitive_id; - template - struct Intersection_and_primitive_id { - typedef typename BaseTraits::template Intersection_and_primitive_id::Intersection_type Intersection_type; - - typedef typename BaseTraits::template Intersection_and_primitive_id::Type Type; - }; + typedef typename Kernel::Exact_kernel EK; + typedef typename Kernel::Approximate_kernel FK; + typedef typename Kernel::C2E C2E; + typedef typename Kernel::C2F C2F; - //SearchGeomTriats_3 concept types - typedef typename BaseTraits::Iso_cuboid_3 Iso_cuboid_3; - typedef typename BaseTraits::Sphere_3 Sphere_3; - typedef typename BaseTraits::Construct_iso_cuboid_3 Construct_iso_cuboid_3; - typedef typename BaseTraits::Construct_min_vertex_3 Construct_min_vertex_3; - typedef typename BaseTraits::Construct_max_vertex_3 Construct_max_vertex_3; - typedef typename BaseTraits::Construct_center_3 Construct_center_3; - typedef typename BaseTraits::Compute_squared_radius_3 Compute_squared_radius_3; - typedef typename BaseTraits::Cartesian_const_iterator_3 Cartesian_const_iterator_3; - typedef typename BaseTraits::Construct_cartesian_const_iterator_3 Construct_cartesian_const_iterator_3; + typedef Filtered_predicate::Split_primitives, + typename AABB_transformed_traits_base::Split_primitives, + C2E,C2F> Split_primitives; - //Splitting - typedef typename BaseTraits::Split_primitives Split_primitives; + typedef Filtered_predicate::Compute_bbox, + typename AABB_transformed_traits_base::Compute_bbox, + C2E,C2F> Compute_bbox; - typedef typename BaseTraits::Compute_bbox Compute_bbox; + typedef Filtered_predicate::Do_intersect, + typename AABB_transformed_traits_base::Do_intersect, + C2E,C2F> Do_intersect; - //Intersections - class Do_intersect { - const AABB_transformed_traits& m_traits; - public: - Do_intersect(const AABB_transformed_traits& traits) - :m_traits(traits) {} - - template - bool operator()(const Query& q, const Bounding_box& bbox) const - { - Point_3 min(bbox.xmin(), bbox.ymin(), bbox.zmin()), - max(bbox.xmax(), bbox.ymax(), bbox.zmax()); - - min = m_traits.transformation().transform(min); - max = m_traits.transformation().transform(max); - Bounding_box transfo_box(to_double(min.x()), to_double(min.y()), to_double(min.z()), - to_double(max.x()), to_double(max.y()), to_double(max.z())); - bool res = CGAL::do_intersect(q, transfo_box); - return res; - } - - template - bool operator()(const Query& q, const Primitive& pr) const - { - return Kernel().do_intersect_3_object()(q, internal::Primitive_helper::get_datum(pr,m_traits)); - } - - // intersection with AABB-tree - template - bool operator()(const CGAL::AABB_tree& other_tree, const Primitive& pr) const - { - return other_tree.do_intersect( internal::Primitive_helper::get_datum(pr,m_traits)); - } - - template - bool operator()(const CGAL::AABB_tree& other_tree, const Bounding_box& bbox) const - { - Point_3 min(bbox.xmin(), bbox.ymin(), bbox.zmin()), - max(bbox.xmax(), bbox.ymax(), bbox.zmax()); - - min = m_traits.transformation().transform(min); - max = m_traits.transformation().transform(max); - Bounding_box transfo_box(to_double(min.x()), to_double(min.y()), to_double(min.z()), - to_double(max.x()), to_double(max.y()), to_double(max.z())); - return other_tree.do_intersect(transfo_box); - } - }; + typedef Filtered_predicate::Intersection, + typename AABB_transformed_traits_base::Intersection, + C2E,C2F> Intersection; - typedef typename BaseTraits::Intersection Intersection; + typedef Filtered_predicate::Compare_distance, + typename AABB_transformed_traits_base::Compare_distance, + C2E,C2F> Compare_distance; - //Distance Queries - typedef typename BaseTraits::Compare_distance Compare_distance; - typedef typename BaseTraits::Closest_point Closest_point ; - typedef typename BaseTraits::Squared_distance Squared_distance; - typedef typename BaseTraits::Equal_3 Equal_3 ; + typedef Filtered_predicate::Closest_point, + typename AABB_transformed_traits_base::Closest_point, + C2E,C2F> Closest_point; - //Operations - Split_primitives split_primitives_object() const { - return BaseTraits::split_primitives_object(); - } + typedef Filtered_predicate::Squared_distance, + typename AABB_transformed_traits_base::Squared_distance, + C2E,C2F> Squared_distance; - Compute_bbox compute_bbox_object() const{ - return BaseTraits::compute_bbox_object(); - } - Do_intersect do_intersect_object() const{ - return Do_intersect(*this); - } + typedef Filtered_predicate::Equal_3, + typename AABB_transformed_traits_base::Equal_3, + C2E,C2F> Equal_3; - Intersection intersection_object() const{ - return BaseTraits::intersection_object(); - } - - Compare_distance compare_distance_object() const{ - return BaseTraits::compare_distance_object(); - } - Closest_point closest_point_object() const{ - return BaseTraits::closest_point_object(); - } - Squared_distance squared_distance_object() const{ - return BaseTraits::squared_distance_object(); - } - Equal_3 equal_3_object() const{ - return BaseTraits::equal_3_object; - } - - //Specific - void set_transformation(const Aff_transformation_3& trans) const - { - m_transfo = trans; - } - - const Aff_transformation_3& transformation() const { return m_transfo; } - -private: - mutable Aff_transformation_3 m_transfo; - }; - - -} // end namespace CGAL - -#include +}//end CGAL #endif // CGAL_AABB_TRANSFORMED_TRAITS_H diff --git a/AABB_tree/include/CGAL/AABB_transformed_traits_base.h b/AABB_tree/include/CGAL/AABB_transformed_traits_base.h new file mode 100644 index 00000000000..1749f625d91 --- /dev/null +++ b/AABB_tree/include/CGAL/AABB_transformed_traits_base.h @@ -0,0 +1,202 @@ + +// Copyright (c) 2018 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$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Maxime Gimeno +// + +#ifndef CGAL_AABB_TRANSFORMED_TRAITS_BASE_H +#define CGAL_AABB_TRANSFORMED_TRAITS_BASE_H + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/// \file AABB_transformed_traits_base.h + +namespace CGAL { +// forward declaration +template< typename AABBTraits> +class AABB_tree; +/// \addtogroup PkgAABB_tree +/// @{ + +/// \tparam BaseTraits a model of `CGAL::AABBTraits` +/// +/// \sa `AABBTraits` +/// \sa `AABB_tree` +/// \sa `AABBPrimitive` +/// \sa `AABBPrimitiveWithSharedData` + + template +class AABB_transformed_traits_base: + public BaseTraits +{ +public: + + //Constructor + AABB_transformed_traits_base(const Aff_transformation_3& transf = Aff_transformation_3(IDENTITY)) + :m_transfo(transf) + {} + // AABBTraits concept types + typedef typename BaseTraits::FT FT; + typedef typename BaseTraits::Point_3 Point_3; + typedef typename BaseTraits::Primitive Primitive; + typedef typename BaseTraits::Bounding_box Bounding_box; + typedef typename BaseTraits::Point_and_primitive_id Point_and_primitive_id; + typedef typename BaseTraits::Object_and_primitive_id Object_and_primitive_id; + template + struct Intersection_and_primitive_id { + typedef typename BaseTraits::template Intersection_and_primitive_id::Intersection_type Intersection_type; + + typedef typename BaseTraits::template Intersection_and_primitive_id::Type Type; + }; + + //SearchGeomTriats_3 concept types + typedef typename BaseTraits::Iso_cuboid_3 Iso_cuboid_3; + typedef typename BaseTraits::Sphere_3 Sphere_3; + typedef typename BaseTraits::Construct_iso_cuboid_3 Construct_iso_cuboid_3; + typedef typename BaseTraits::Construct_min_vertex_3 Construct_min_vertex_3; + typedef typename BaseTraits::Construct_max_vertex_3 Construct_max_vertex_3; + typedef typename BaseTraits::Construct_center_3 Construct_center_3; + typedef typename BaseTraits::Compute_squared_radius_3 Compute_squared_radius_3; + typedef typename BaseTraits::Cartesian_const_iterator_3 Cartesian_const_iterator_3; + typedef typename BaseTraits::Construct_cartesian_const_iterator_3 Construct_cartesian_const_iterator_3; + + //Splitting + typedef typename BaseTraits::Split_primitives Split_primitives; + + typedef typename BaseTraits::Compute_bbox Compute_bbox; + + //Intersections + class Do_intersect { + const AABB_transformed_traits_base& m_traits; + public: + Do_intersect(const AABB_transformed_traits_base& traits) + :m_traits(traits) {} + + template + bool operator()(const Query& q, const Bounding_box& bbox) const + { + Point_3 min(bbox.xmin(), bbox.ymin(), bbox.zmin()), + max(bbox.xmax(), bbox.ymax(), bbox.zmax()); + + min = m_traits.transformation().transform(min); + max = m_traits.transformation().transform(max); + Bounding_box transfo_box(to_double(min.x()), to_double(min.y()), to_double(min.z()), + to_double(max.x()), to_double(max.y()), to_double(max.z())); + bool res = CGAL::do_intersect(q, transfo_box); + return res; + } + + template + bool operator()(const Query& q, const Primitive& pr) const + { + return Kernel().do_intersect_3_object()(q, internal::Primitive_helper::get_datum(pr,m_traits)); + } + + // intersection with AABB-tree + template + bool operator()(const CGAL::AABB_tree& other_tree, const Primitive& pr) const + { + return other_tree.do_intersect( internal::Primitive_helper::get_datum(pr,m_traits)); + } + + template + bool operator()(const CGAL::AABB_tree& other_tree, const Bounding_box& bbox) const + { + Point_3 min(bbox.xmin(), bbox.ymin(), bbox.zmin()), + max(bbox.xmax(), bbox.ymax(), bbox.zmax()); + + min = m_traits.transformation().transform(min); + max = m_traits.transformation().transform(max); + Bounding_box transfo_box(to_double(min.x()), to_double(min.y()), to_double(min.z()), + to_double(max.x()), to_double(max.y()), to_double(max.z())); + return other_tree.do_intersect(transfo_box); + } + }; + + typedef typename BaseTraits::Intersection Intersection; + + //Distance Queries + typedef typename BaseTraits::Compare_distance Compare_distance; + typedef typename BaseTraits::Closest_point Closest_point ; + typedef typename BaseTraits::Squared_distance Squared_distance; + typedef typename BaseTraits::Equal_3 Equal_3 ; + + //Operations + Split_primitives split_primitives_object() const { + return BaseTraits::split_primitives_object(); + } + + Compute_bbox compute_bbox_object() const{ + return BaseTraits::compute_bbox_object(); + } + Do_intersect do_intersect_object() const{ + return Do_intersect(*this); + } + + Intersection intersection_object() const{ + return BaseTraits::intersection_object(); + } + + Compare_distance compare_distance_object() const{ + return BaseTraits::compare_distance_object(); + } + Closest_point closest_point_object() const{ + return BaseTraits::closest_point_object(); + } + Squared_distance squared_distance_object() const{ + return BaseTraits::squared_distance_object(); + } + Equal_3 equal_3_object() const{ + return BaseTraits::equal_3_object; + } + + //Specific + void set_transformation(const Aff_transformation_3& trans) const + { + m_transfo = trans; + } + + const Aff_transformation_3& transformation() const { return m_transfo; } + +private: + mutable Aff_transformation_3 m_transfo; + +}; + + +} // end namespace CGAL + +#include + +#endif // CGAL_AABB_TRANSFORMED_TRAITS_BASE_H From 8e64d49513d8d5d991f6dcc63de535d13cea1e4a Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 18 Jul 2018 13:29:25 +0200 Subject: [PATCH 06/84] WIP: Remove the traits_base --- AABB_tree/include/CGAL/AABB_traits.h | 1 + .../include/CGAL/AABB_transformed_traits.h | 232 ++++++++++++++---- .../CGAL/AABB_transformed_traits_base.h | 202 --------------- 3 files changed, 192 insertions(+), 243 deletions(-) delete mode 100644 AABB_tree/include/CGAL/AABB_transformed_traits_base.h diff --git a/AABB_tree/include/CGAL/AABB_traits.h b/AABB_tree/include/CGAL/AABB_traits.h index 827fdd23afd..88cc6f5d6ca 100644 --- a/AABB_tree/include/CGAL/AABB_traits.h +++ b/AABB_tree/include/CGAL/AABB_traits.h @@ -301,6 +301,7 @@ public: Split_primitives(const AABB_traits& traits) : m_traits(traits) {} + typedef void result_type; template void operator()(PrimitiveIterator first, PrimitiveIterator beyond, diff --git a/AABB_tree/include/CGAL/AABB_transformed_traits.h b/AABB_tree/include/CGAL/AABB_transformed_traits.h index 6aea9fc56d6..7dd9faa35df 100644 --- a/AABB_tree/include/CGAL/AABB_transformed_traits.h +++ b/AABB_tree/include/CGAL/AABB_transformed_traits.h @@ -1,3 +1,4 @@ + // Copyright (c) 2018 GeometryFactory (France). // All rights reserved. // @@ -23,60 +24,209 @@ #ifndef CGAL_AABB_TRANSFORMED_TRAITS_H #define CGAL_AABB_TRANSFORMED_TRAITS_H -#include -#include +#include -namespace CGAL{ -template -class AABB_transformed_traits - :public AABB_transformed_traits_base -{}; +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/// \file AABB_transformed_traits.h + +namespace CGAL { +// forward declaration +template< typename AABBTraits> +class AABB_tree; +/// \addtogroup PkgAABB_tree +/// @{ + +/// \tparam BaseTraits a model of `CGAL::AABBTraits` +/// +/// \sa `AABBTraits` +/// \sa `AABB_tree` +/// \sa `AABBPrimitive` +/// \sa `AABBPrimitiveWithSharedData` + + template +class AABB_transformed_traits: + public BaseTraits +{ +public: + + //Constructor + AABB_transformed_traits(const Aff_transformation_3& transf = Aff_transformation_3(IDENTITY)) + :m_transfo(transf) + {} + // AABBTraits concept types + typedef typename BaseTraits::Point_3 Point_3; + typedef typename BaseTraits::Primitive Primitive; + typedef typename BaseTraits::Bounding_box Bounding_box; + //Intersections + class Do_intersect { + const AABB_transformed_traits& m_traits; + public: + Do_intersect(const AABB_transformed_traits& traits) + :m_traits(traits) {} + + template + bool operator()(const Query& q, const Bounding_box& bbox) const + { + Point_3 min(bbox.xmin(), bbox.ymin(), bbox.zmin()), + max(bbox.xmax(), bbox.ymax(), bbox.zmax()); + + min = m_traits.transformation().transform(min); + max = m_traits.transformation().transform(max); + Bounding_box transfo_box(to_double(min.x()), to_double(min.y()), to_double(min.z()), + to_double(max.x()), to_double(max.y()), to_double(max.z())); + bool res = CGAL::do_intersect(q, transfo_box); + return res; + } + + template + bool operator()(const Query& q, const Primitive& pr) const + { + return Kernel().do_intersect_3_object()(q, internal::Primitive_helper::get_datum(pr,m_traits)); + } + + // intersection with AABB-tree + template + bool operator()(const CGAL::AABB_tree& other_tree, const Primitive& pr) const + { + return other_tree.do_intersect( internal::Primitive_helper::get_datum(pr,m_traits)); + } + + template + bool operator()(const CGAL::AABB_tree& other_tree, const Bounding_box& bbox) const + { + Point_3 min(bbox.xmin(), bbox.ymin(), bbox.zmin()), + max(bbox.xmax(), bbox.ymax(), bbox.zmax()); + + min = m_traits.transformation().transform(min); + max = m_traits.transformation().transform(max); + Bounding_box transfo_box(to_double(min.x()), to_double(min.y()), to_double(min.z()), + to_double(max.x()), to_double(max.y()), to_double(max.z())); + return other_tree.do_intersect(transfo_box); + } + }; + + Do_intersect do_intersect_object() const{ + return Do_intersect(*this); + } + + + //Specific + void set_transformation(const Aff_transformation_3& trans) const + { + m_transfo = trans; + } + + const Aff_transformation_3& transformation() const { return m_transfo; } + +private: + mutable Aff_transformation_3 m_transfo; + +}; + template -class AABB_transformed_traits - :public AABB_transformed_traits_base +class AABB_transformed_traits: +public BaseTraits { typedef typename Kernel::Exact_kernel EK; - typedef typename Kernel::Approximate_kernel FK; + typedef typename Kernel::Approximate_kernel AK; typedef typename Kernel::C2E C2E; - typedef typename Kernel::C2F C2F; + typedef typename Kernel::C2F C2A; +public: + + //Constructor + AABB_transformed_traits(const Aff_transformation_3& transf = Aff_transformation_3(IDENTITY)) + :m_transfo(transf) + {} + // AABBTraits concept types + typedef typename BaseTraits::Point_3 Point_3; + typedef typename BaseTraits::Primitive Primitive; + typedef typename BaseTraits::Bounding_box Bounding_box; + //Intersections +private: + class Unfiltered_do_intersect { + const AABB_transformed_traits& m_traits; + public: + Unfiltered_do_intersect(const AABB_transformed_traits& traits) + :m_traits(traits) {} + + template + bool operator()(const Query& q, const Bounding_box& bbox) const + { + Point_3 min(bbox.xmin(), bbox.ymin(), bbox.zmin()), + max(bbox.xmax(), bbox.ymax(), bbox.zmax()); + + min = m_traits.transformation().transform(min); + max = m_traits.transformation().transform(max); + Bounding_box transfo_box(to_double(min.x()), to_double(min.y()), to_double(min.z()), + to_double(max.x()), to_double(max.y()), to_double(max.z())); + bool res = CGAL::do_intersect(q, transfo_box); + return res; + } + + template + bool operator()(const Query& q, const Primitive& pr) const + { + return Kernel().do_intersect_3_object()(q, internal::Primitive_helper::get_datum(pr,m_traits)); + } + + // intersection with AABB-tree + template + bool operator()(const CGAL::AABB_tree& other_tree, const Primitive& pr) const + { + return other_tree.do_intersect( internal::Primitive_helper::get_datum(pr,m_traits)); + } + + template + bool operator()(const CGAL::AABB_tree& other_tree, const Bounding_box& bbox) const + { + Point_3 min(bbox.xmin(), bbox.ymin(), bbox.zmin()), + max(bbox.xmax(), bbox.ymax(), bbox.zmax()); + + min = m_traits.transformation().transform(min); + max = m_traits.transformation().transform(max); + Bounding_box transfo_box(to_double(min.x()), to_double(min.y()), to_double(min.z()), + to_double(max.x()), to_double(max.y()), to_double(max.z())); + return other_tree.do_intersect(transfo_box); + } + }; +public: + typedef Unfiltered_do_intersect Do_intersect; + typedef typename BaseTraits::Intersection Intersection; - typedef Filtered_predicate::Split_primitives, - typename AABB_transformed_traits_base::Split_primitives, - C2E,C2F> Split_primitives; + Do_intersect do_intersect_object() const{ + return Do_intersect(*this); + } - typedef Filtered_predicate::Compute_bbox, - typename AABB_transformed_traits_base::Compute_bbox, - C2E,C2F> Compute_bbox; - typedef Filtered_predicate::Do_intersect, - typename AABB_transformed_traits_base::Do_intersect, - C2E,C2F> Do_intersect; + //Specific + void set_transformation(const Aff_transformation_3& trans) const + { + m_transfo = trans; + } - typedef Filtered_predicate::Intersection, - typename AABB_transformed_traits_base::Intersection, - C2E,C2F> Intersection; + const Aff_transformation_3& transformation() const { return m_transfo; } - typedef Filtered_predicate::Compare_distance, - typename AABB_transformed_traits_base::Compare_distance, - C2E,C2F> Compare_distance; - - typedef Filtered_predicate::Closest_point, - typename AABB_transformed_traits_base::Closest_point, - C2E,C2F> Closest_point; - - typedef Filtered_predicate::Squared_distance, - typename AABB_transformed_traits_base::Squared_distance, - C2E,C2F> Squared_distance; - - typedef Filtered_predicate::Equal_3, - typename AABB_transformed_traits_base::Equal_3, - C2E,C2F> Equal_3; +private: + mutable Aff_transformation_3 m_transfo; }; +} // end namespace CGAL + +#include -}//end CGAL #endif // CGAL_AABB_TRANSFORMED_TRAITS_H diff --git a/AABB_tree/include/CGAL/AABB_transformed_traits_base.h b/AABB_tree/include/CGAL/AABB_transformed_traits_base.h deleted file mode 100644 index 1749f625d91..00000000000 --- a/AABB_tree/include/CGAL/AABB_transformed_traits_base.h +++ /dev/null @@ -1,202 +0,0 @@ - -// Copyright (c) 2018 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$ -// SPDX-License-Identifier: GPL-3.0+ -// -// -// Author(s) : Maxime Gimeno -// - -#ifndef CGAL_AABB_TRANSFORMED_TRAITS_BASE_H -#define CGAL_AABB_TRANSFORMED_TRAITS_BASE_H - -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/// \file AABB_transformed_traits_base.h - -namespace CGAL { -// forward declaration -template< typename AABBTraits> -class AABB_tree; -/// \addtogroup PkgAABB_tree -/// @{ - -/// \tparam BaseTraits a model of `CGAL::AABBTraits` -/// -/// \sa `AABBTraits` -/// \sa `AABB_tree` -/// \sa `AABBPrimitive` -/// \sa `AABBPrimitiveWithSharedData` - - template -class AABB_transformed_traits_base: - public BaseTraits -{ -public: - - //Constructor - AABB_transformed_traits_base(const Aff_transformation_3& transf = Aff_transformation_3(IDENTITY)) - :m_transfo(transf) - {} - // AABBTraits concept types - typedef typename BaseTraits::FT FT; - typedef typename BaseTraits::Point_3 Point_3; - typedef typename BaseTraits::Primitive Primitive; - typedef typename BaseTraits::Bounding_box Bounding_box; - typedef typename BaseTraits::Point_and_primitive_id Point_and_primitive_id; - typedef typename BaseTraits::Object_and_primitive_id Object_and_primitive_id; - template - struct Intersection_and_primitive_id { - typedef typename BaseTraits::template Intersection_and_primitive_id::Intersection_type Intersection_type; - - typedef typename BaseTraits::template Intersection_and_primitive_id::Type Type; - }; - - //SearchGeomTriats_3 concept types - typedef typename BaseTraits::Iso_cuboid_3 Iso_cuboid_3; - typedef typename BaseTraits::Sphere_3 Sphere_3; - typedef typename BaseTraits::Construct_iso_cuboid_3 Construct_iso_cuboid_3; - typedef typename BaseTraits::Construct_min_vertex_3 Construct_min_vertex_3; - typedef typename BaseTraits::Construct_max_vertex_3 Construct_max_vertex_3; - typedef typename BaseTraits::Construct_center_3 Construct_center_3; - typedef typename BaseTraits::Compute_squared_radius_3 Compute_squared_radius_3; - typedef typename BaseTraits::Cartesian_const_iterator_3 Cartesian_const_iterator_3; - typedef typename BaseTraits::Construct_cartesian_const_iterator_3 Construct_cartesian_const_iterator_3; - - //Splitting - typedef typename BaseTraits::Split_primitives Split_primitives; - - typedef typename BaseTraits::Compute_bbox Compute_bbox; - - //Intersections - class Do_intersect { - const AABB_transformed_traits_base& m_traits; - public: - Do_intersect(const AABB_transformed_traits_base& traits) - :m_traits(traits) {} - - template - bool operator()(const Query& q, const Bounding_box& bbox) const - { - Point_3 min(bbox.xmin(), bbox.ymin(), bbox.zmin()), - max(bbox.xmax(), bbox.ymax(), bbox.zmax()); - - min = m_traits.transformation().transform(min); - max = m_traits.transformation().transform(max); - Bounding_box transfo_box(to_double(min.x()), to_double(min.y()), to_double(min.z()), - to_double(max.x()), to_double(max.y()), to_double(max.z())); - bool res = CGAL::do_intersect(q, transfo_box); - return res; - } - - template - bool operator()(const Query& q, const Primitive& pr) const - { - return Kernel().do_intersect_3_object()(q, internal::Primitive_helper::get_datum(pr,m_traits)); - } - - // intersection with AABB-tree - template - bool operator()(const CGAL::AABB_tree& other_tree, const Primitive& pr) const - { - return other_tree.do_intersect( internal::Primitive_helper::get_datum(pr,m_traits)); - } - - template - bool operator()(const CGAL::AABB_tree& other_tree, const Bounding_box& bbox) const - { - Point_3 min(bbox.xmin(), bbox.ymin(), bbox.zmin()), - max(bbox.xmax(), bbox.ymax(), bbox.zmax()); - - min = m_traits.transformation().transform(min); - max = m_traits.transformation().transform(max); - Bounding_box transfo_box(to_double(min.x()), to_double(min.y()), to_double(min.z()), - to_double(max.x()), to_double(max.y()), to_double(max.z())); - return other_tree.do_intersect(transfo_box); - } - }; - - typedef typename BaseTraits::Intersection Intersection; - - //Distance Queries - typedef typename BaseTraits::Compare_distance Compare_distance; - typedef typename BaseTraits::Closest_point Closest_point ; - typedef typename BaseTraits::Squared_distance Squared_distance; - typedef typename BaseTraits::Equal_3 Equal_3 ; - - //Operations - Split_primitives split_primitives_object() const { - return BaseTraits::split_primitives_object(); - } - - Compute_bbox compute_bbox_object() const{ - return BaseTraits::compute_bbox_object(); - } - Do_intersect do_intersect_object() const{ - return Do_intersect(*this); - } - - Intersection intersection_object() const{ - return BaseTraits::intersection_object(); - } - - Compare_distance compare_distance_object() const{ - return BaseTraits::compare_distance_object(); - } - Closest_point closest_point_object() const{ - return BaseTraits::closest_point_object(); - } - Squared_distance squared_distance_object() const{ - return BaseTraits::squared_distance_object(); - } - Equal_3 equal_3_object() const{ - return BaseTraits::equal_3_object; - } - - //Specific - void set_transformation(const Aff_transformation_3& trans) const - { - m_transfo = trans; - } - - const Aff_transformation_3& transformation() const { return m_transfo; } - -private: - mutable Aff_transformation_3 m_transfo; - -}; - - -} // end namespace CGAL - -#include - -#endif // CGAL_AABB_TRANSFORMED_TRAITS_BASE_H From 2c239593478c7be5a45adcc2ec1ab393a304a0b2 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 18 Jul 2018 15:34:02 +0200 Subject: [PATCH 07/84] rename and transform primitives. Don't transform mesh in test. --- AABB_tree/benchmark/AABB_tree/test.cpp | 6 +- .../include/CGAL/AABB_transformed_traits.h | 232 ------------------ 2 files changed, 2 insertions(+), 236 deletions(-) delete mode 100644 AABB_tree/include/CGAL/AABB_transformed_traits.h diff --git a/AABB_tree/benchmark/AABB_tree/test.cpp b/AABB_tree/benchmark/AABB_tree/test.cpp index beff8c25fcd..75a2b0444c6 100644 --- a/AABB_tree/benchmark/AABB_tree/test.cpp +++ b/AABB_tree/benchmark/AABB_tree/test.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include @@ -19,7 +19,7 @@ typedef CGAL::Surface_mesh Surface_mesh; typedef CGAL::AABB_face_graph_triangle_primitive Primitive; typedef CGAL::AABB_traits AABB_triangle_traits; -typedef CGAL::AABB_transformed_traits Traits; +typedef CGAL::AABB_do_intersect_transform_traits Traits; typedef CGAL::AABB_tree Tree; namespace PMP = CGAL::Polygon_mesh_processing; @@ -54,13 +54,11 @@ void test_no_collision(int k, const char* fname, K::Vector_3 unit_vec = (2.0/k * K::Vector_3((box.xmax()-box.xmin()), 0, 0)); - CGAL::Aff_transformation_3 trans2(CGAL::TRANSLATION, unit_vec); CGAL::Side_of_triangle_mesh sotm1(tmTree); for(int i=1; i trans22(CGAL::TRANSLATION, i*unit_vec); - PMP::transform(trans2, tm2); box = PMP::bbox(tm2); tmTree2.traits().set_transformation(trans22); if(tmTree2.do_intersect(tmTree)) diff --git a/AABB_tree/include/CGAL/AABB_transformed_traits.h b/AABB_tree/include/CGAL/AABB_transformed_traits.h deleted file mode 100644 index 7dd9faa35df..00000000000 --- a/AABB_tree/include/CGAL/AABB_transformed_traits.h +++ /dev/null @@ -1,232 +0,0 @@ - -// Copyright (c) 2018 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$ -// SPDX-License-Identifier: GPL-3.0+ -// -// -// Author(s) : Maxime Gimeno -// - -#ifndef CGAL_AABB_TRANSFORMED_TRAITS_H -#define CGAL_AABB_TRANSFORMED_TRAITS_H - -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/// \file AABB_transformed_traits.h - -namespace CGAL { -// forward declaration -template< typename AABBTraits> -class AABB_tree; -/// \addtogroup PkgAABB_tree -/// @{ - -/// \tparam BaseTraits a model of `CGAL::AABBTraits` -/// -/// \sa `AABBTraits` -/// \sa `AABB_tree` -/// \sa `AABBPrimitive` -/// \sa `AABBPrimitiveWithSharedData` - - template -class AABB_transformed_traits: - public BaseTraits -{ -public: - - //Constructor - AABB_transformed_traits(const Aff_transformation_3& transf = Aff_transformation_3(IDENTITY)) - :m_transfo(transf) - {} - // AABBTraits concept types - typedef typename BaseTraits::Point_3 Point_3; - typedef typename BaseTraits::Primitive Primitive; - typedef typename BaseTraits::Bounding_box Bounding_box; - //Intersections - class Do_intersect { - const AABB_transformed_traits& m_traits; - public: - Do_intersect(const AABB_transformed_traits& traits) - :m_traits(traits) {} - - template - bool operator()(const Query& q, const Bounding_box& bbox) const - { - Point_3 min(bbox.xmin(), bbox.ymin(), bbox.zmin()), - max(bbox.xmax(), bbox.ymax(), bbox.zmax()); - - min = m_traits.transformation().transform(min); - max = m_traits.transformation().transform(max); - Bounding_box transfo_box(to_double(min.x()), to_double(min.y()), to_double(min.z()), - to_double(max.x()), to_double(max.y()), to_double(max.z())); - bool res = CGAL::do_intersect(q, transfo_box); - return res; - } - - template - bool operator()(const Query& q, const Primitive& pr) const - { - return Kernel().do_intersect_3_object()(q, internal::Primitive_helper::get_datum(pr,m_traits)); - } - - // intersection with AABB-tree - template - bool operator()(const CGAL::AABB_tree& other_tree, const Primitive& pr) const - { - return other_tree.do_intersect( internal::Primitive_helper::get_datum(pr,m_traits)); - } - - template - bool operator()(const CGAL::AABB_tree& other_tree, const Bounding_box& bbox) const - { - Point_3 min(bbox.xmin(), bbox.ymin(), bbox.zmin()), - max(bbox.xmax(), bbox.ymax(), bbox.zmax()); - - min = m_traits.transformation().transform(min); - max = m_traits.transformation().transform(max); - Bounding_box transfo_box(to_double(min.x()), to_double(min.y()), to_double(min.z()), - to_double(max.x()), to_double(max.y()), to_double(max.z())); - return other_tree.do_intersect(transfo_box); - } - }; - - Do_intersect do_intersect_object() const{ - return Do_intersect(*this); - } - - - //Specific - void set_transformation(const Aff_transformation_3& trans) const - { - m_transfo = trans; - } - - const Aff_transformation_3& transformation() const { return m_transfo; } - -private: - mutable Aff_transformation_3 m_transfo; - -}; - -template -class AABB_transformed_traits: -public BaseTraits -{ - typedef typename Kernel::Exact_kernel EK; - typedef typename Kernel::Approximate_kernel AK; - typedef typename Kernel::C2E C2E; - typedef typename Kernel::C2F C2A; -public: - - //Constructor - AABB_transformed_traits(const Aff_transformation_3& transf = Aff_transformation_3(IDENTITY)) - :m_transfo(transf) - {} - // AABBTraits concept types - typedef typename BaseTraits::Point_3 Point_3; - typedef typename BaseTraits::Primitive Primitive; - typedef typename BaseTraits::Bounding_box Bounding_box; - //Intersections -private: - class Unfiltered_do_intersect { - const AABB_transformed_traits& m_traits; - public: - Unfiltered_do_intersect(const AABB_transformed_traits& traits) - :m_traits(traits) {} - - template - bool operator()(const Query& q, const Bounding_box& bbox) const - { - Point_3 min(bbox.xmin(), bbox.ymin(), bbox.zmin()), - max(bbox.xmax(), bbox.ymax(), bbox.zmax()); - - min = m_traits.transformation().transform(min); - max = m_traits.transformation().transform(max); - Bounding_box transfo_box(to_double(min.x()), to_double(min.y()), to_double(min.z()), - to_double(max.x()), to_double(max.y()), to_double(max.z())); - bool res = CGAL::do_intersect(q, transfo_box); - return res; - } - - template - bool operator()(const Query& q, const Primitive& pr) const - { - return Kernel().do_intersect_3_object()(q, internal::Primitive_helper::get_datum(pr,m_traits)); - } - - // intersection with AABB-tree - template - bool operator()(const CGAL::AABB_tree& other_tree, const Primitive& pr) const - { - return other_tree.do_intersect( internal::Primitive_helper::get_datum(pr,m_traits)); - } - - template - bool operator()(const CGAL::AABB_tree& other_tree, const Bounding_box& bbox) const - { - Point_3 min(bbox.xmin(), bbox.ymin(), bbox.zmin()), - max(bbox.xmax(), bbox.ymax(), bbox.zmax()); - - min = m_traits.transformation().transform(min); - max = m_traits.transformation().transform(max); - Bounding_box transfo_box(to_double(min.x()), to_double(min.y()), to_double(min.z()), - to_double(max.x()), to_double(max.y()), to_double(max.z())); - return other_tree.do_intersect(transfo_box); - } - }; -public: - typedef Unfiltered_do_intersect Do_intersect; - typedef typename BaseTraits::Intersection Intersection; - - Do_intersect do_intersect_object() const{ - return Do_intersect(*this); - } - - - //Specific - void set_transformation(const Aff_transformation_3& trans) const - { - m_transfo = trans; - } - - const Aff_transformation_3& transformation() const { return m_transfo; } - -private: - mutable Aff_transformation_3 m_transfo; - -}; -} // end namespace CGAL - -#include - -#endif // CGAL_AABB_TRANSFORMED_TRAITS_H From 319893bdb12755a304fbb04255d91a268b6dd078 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 19 Jul 2018 14:10:50 +0200 Subject: [PATCH 08/84] Add Filtered_predicates and manage all Aff_transf --- AABB_tree/benchmark/AABB_tree/test.cpp | 110 ++++++++++++++++-- .../include/CGAL/Cartesian_converter.h | 18 +++ 2 files changed, 118 insertions(+), 10 deletions(-) diff --git a/AABB_tree/benchmark/AABB_tree/test.cpp b/AABB_tree/benchmark/AABB_tree/test.cpp index 75a2b0444c6..6db53a4c822 100644 --- a/AABB_tree/benchmark/AABB_tree/test.cpp +++ b/AABB_tree/benchmark/AABB_tree/test.cpp @@ -15,6 +15,7 @@ #include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +//typedef CGAL::Simple_cartesian K; typedef CGAL::Surface_mesh Surface_mesh; typedef CGAL::AABB_face_graph_triangle_primitive Primitive; @@ -24,6 +25,74 @@ typedef CGAL::AABB_tree Tree; namespace PMP = CGAL::Polygon_mesh_processing; +void naive_test(int k, const char* fname, + int& nb_inter, int& nb_no_inter, int& nb_include) +{ + std::ifstream input(fname); + Surface_mesh tm, tm2; + input >> tm; + copy_face_graph(tm, tm2); + CGAL::Aff_transformation_3 init1(CGAL::SCALING, 6.0); + PMP::transform(init1, tm); + CGAL::Bbox_3 box = PMP::bbox(tm); + Tree tmTree(tm.faces_begin(), tm.faces_end(), tm); + Tree tmTree2(tm2.faces_begin(), tm2.faces_end(), tm2); + CGAL::Aff_transformation_3 init2(CGAL::TRANSLATION, - K::Vector_3( + (box.xmax()-box.xmin()),0,0)); + PMP::transform(init2, tm2); + + std::ofstream out1("/home/gimeno/Data/tmp/m1.off"), + out2("/home/gimeno/Data/tmp/m2.off"); + out1 << tm; + out1.close(); + out2 << tm2; + out2.close(); + tmTree.build(); + K::Vector_3 unit_vec = (2.0/k * K::Vector_3((box.xmax()-box.xmin()), + 0, + 0)); + CGAL::Aff_transformation_3 T0(CGAL::IDENTITY); + K::FT rot[9]; + rot[0] = 1.0; + rot[1] = 0.0; + rot[2] = 0.0; + rot[3] = 0.0; + rot[4] = std::cos(CGAL_PI/4.0); + rot[5] = -std::sin(CGAL_PI/4.0); + rot[6] = 0.0; + rot[7] = std::sin(CGAL_PI/4.0); + rot[8] = std::cos(CGAL_PI/4.0); + CGAL::Aff_transformation_3 R(rot[0], rot[1], rot[2], + rot[3], rot[4], rot[5], + rot[6], rot[7], rot[8]); + + CGAL::Side_of_triangle_mesh sotm1(tm); + for(int i=1; i T1 = CGAL::Aff_transformation_3(CGAL::TRANSLATION, i*unit_vec); + CGAL::Aff_transformation_3 transfo = T0*R*T1; + PMP::transform(transfo, tm2); + tmTree2.build(); + if(tmTree2.do_intersect(tmTree)) + ++nb_inter; + else + { + if(sotm1(tm2.point(*tm2.vertices().begin())) != CGAL::ON_UNBOUNDED_SIDE) + { + ++nb_include; + } + else + { + CGAL::Side_of_triangle_mesh sotm2(tm2); + if(sotm2(tm.point(*tm.vertices().begin())) != CGAL::ON_UNBOUNDED_SIDE) + ++nb_include; + else + ++nb_no_inter; + } + } + T0 = CGAL::Aff_transformation_3(CGAL::TRANSLATION, -i*unit_vec); + } +} void test_no_collision(int k, const char* fname, int& nb_inter, int& nb_no_inter, int& nb_include) { @@ -49,23 +118,37 @@ void test_no_collision(int k, const char* fname, tmTree.build(); tmTree2.build(); typedef boost::property_map::type VPM; - //VPM vpm = get(CGAL::vertex_point, tm); + VPM vpm2 = get(CGAL::vertex_point, tm2); K::Vector_3 unit_vec = (2.0/k * K::Vector_3((box.xmax()-box.xmin()), 0, 0)); + CGAL::Side_of_triangle_mesh sotm1(tmTree); for(int i=1; i trans22(CGAL::TRANSLATION, i*unit_vec); - box = PMP::bbox(tm2); - tmTree2.traits().set_transformation(trans22); + K::FT rot[9]; + rot[0] = 1.0; + rot[1] = 0.0; + rot[2] = 0.0; + rot[3] = 0.0; + rot[4] = std::cos(i*CGAL_PI/4.0); + rot[5] = -std::sin(i*CGAL_PI/4.0); + rot[6] = 0.0; + rot[7] = std::sin(i*CGAL_PI/4.0); + rot[8] = std::cos(i*CGAL_PI/4.0); + CGAL::Aff_transformation_3 R(rot[0], rot[1], rot[2], + rot[3], rot[4], rot[5], + rot[6], rot[7], rot[8]); + CGAL::Aff_transformation_3 T1 = CGAL::Aff_transformation_3(CGAL::TRANSLATION, i*unit_vec); + CGAL::Aff_transformation_3 transfo = R*T1; + tmTree2.traits().set_transformation(transfo); if(tmTree2.do_intersect(tmTree)) ++nb_inter; else { - if(sotm1(tm2.point(*tm2.vertices().begin())) != CGAL::ON_UNBOUNDED_SIDE) + if(sotm1(transfo.transform(vpm2[*tm2.vertices().begin()])) != CGAL::ON_UNBOUNDED_SIDE) { ++nb_include; } @@ -73,7 +156,7 @@ void test_no_collision(int k, const char* fname, { CGAL::Side_of_triangle_mesh sotm2(tmTree2); - if(sotm2(tm2.point(*tm2.vertices().begin())) != CGAL::ON_UNBOUNDED_SIDE) + if(sotm2(tm.point(*tm.vertices().begin())) != CGAL::ON_UNBOUNDED_SIDE) ++nb_include; else ++nb_no_inter; @@ -87,12 +170,19 @@ int main(int argc, const char** argv) int k = (argc>1) ? atoi(argv[1]) : 10; const char* path = (argc>2)?argv[2]:"data/handle" ".off"; + std::cout<< k<<" steps in "<(end - start).count() << "μs." << std::endl; + start = std::chrono::steady_clock::now(); + test_no_collision(k, path,nb_inter, nb_no_inter, nb_include); + end = std::chrono::steady_clock::now(); + std::cout<<"With transform_traits: "<(end - start).count() << "μs." << std::endl; + return 0; } diff --git a/Cartesian_kernel/include/CGAL/Cartesian_converter.h b/Cartesian_kernel/include/CGAL/Cartesian_converter.h index fb25953c85f..33f941b3305 100644 --- a/Cartesian_kernel/include/CGAL/Cartesian_converter.h +++ b/Cartesian_kernel/include/CGAL/Cartesian_converter.h @@ -393,6 +393,24 @@ public: return std::make_pair(operator()(pp.first), operator()(pp.second)); } + typename K2::Aff_transformation_3 + operator()(const typename K1::Aff_transformation_3 &a) const + { + typedef typename K2::Aff_transformation_3 Aff_transformation_3; + typename K2::FT t[12]; + for(int i=0; i< 3; ++i) + { + for(int j=0; j<4; ++j) + { + t[i*4+j] = a.m(i,j); + } + } + return Aff_transformation_3( + t[0],t[1],t[2],t[3], + t[4],t[5],t[6],t[7], + t[8],t[9],t[10],t[11], + a.m(3,3)); + } private: Converter c; K2 k; From f236176d5599c480f48caf2d72915eefb3514e9e Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 19 Jul 2018 17:00:18 +0200 Subject: [PATCH 09/84] Add missing file --- .../CGAL/AABB_do_intersect_transform_traits.h | 203 ++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h diff --git a/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h b/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h new file mode 100644 index 00000000000..b2ca9880f62 --- /dev/null +++ b/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h @@ -0,0 +1,203 @@ + +// Copyright (c) 2018 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$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Maxime Gimeno +// + +#ifndef CGAL_AABB_DO_INTERSECT_TRANSFORM_TRAITS_H +#define CGAL_AABB_DO_INTERSECT_TRANSFORM_TRAITS_H + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/// \file AABB_do_intersect_transform_traits.h + +namespace CGAL { +// forward declaration +template< typename AABBTraits> +class AABB_tree; + +namespace internal_AABB +{ +template +struct Actual_intersect +{ + typedef bool result_type; + template + bool operator()(const Query& q, + const CGAL::Aff_transformation_3& transfo, + const Datum_t& pr) const + { + return Kernel().do_intersect_3_object()(q, + pr.transform(transfo)); + } +}; + + template + struct Filter_test + { + template + bool operator()(const Query& q, + const CGAL::Aff_transformation_3& transfo, + const Datum_t& pr) const + { + return Actual_intersect()(q,transfo,pr); + } + }; + template + struct Filter_test + { + template + bool operator()(const Query& q, + const CGAL::Aff_transformation_3& transfo, + const Datum_t& pr) const + { + typedef typename Kernel::Approximate_kernel FK; + typedef typename Kernel::Exact_kernel EK; + typedef typename Kernel::C2F C2F; + typedef typename Kernel::C2E C2E; + + typedef internal_AABB::Actual_intersect Exactator; + typedef internal_AABB::Actual_intersect Approxator; + typedef CGAL::Filtered_predicate< + Exactator, + Approxator, + C2E, + C2F> Filter; + Filter fi; + return fi(q, transfo,pr); + } + }; + +}//end internal +template +class AABB_do_intersect_transform_traits: + public BaseTraits +{ + mutable Aff_transformation_3 m_transfo; +public: + + //Constructor + AABB_do_intersect_transform_traits(const Aff_transformation_3& transf = Aff_transformation_3(IDENTITY)) + :m_transfo(transf) + {} + // AABBTraits concept types + typedef typename BaseTraits::Point_3 Point_3; + typedef typename BaseTraits::Primitive Primitive; + typedef typename BaseTraits::Bounding_box Bounding_box; + //Intersections + class Do_intersect + { + typedef Simple_cartesian Approximate_kernel; + typedef Cartesian_converter C2F; + + + const AABB_do_intersect_transform_traits& m_traits; + C2F c2f; + public: + Do_intersect(const AABB_do_intersect_transform_traits& traits) + :m_traits(traits) + {} + + template + bool operator()(const Query& q, const Bounding_box& bbox) const + { + Point_3 min(bbox.xmin(), bbox.ymin(), bbox.zmin()), + max(bbox.xmax(), bbox.ymax(), bbox.zmax()); + + typename Approximate_kernel::Point_3 app_min, + app_max; + Bounding_box temp_box = + min.bbox() + max.bbox(); + Point_3 tmin(temp_box.xmin(), temp_box.ymin(), temp_box.zmin()), + tmax(temp_box.xmax(), temp_box.ymax(), temp_box.zmax()); + app_min=c2f(tmin); + app_max = c2f(tmax); + Bounding_box transfo_box(to_double(app_min.x().inf()), to_double(app_min.y().inf()), to_double(app_min.z().inf()), + to_double(app_max.x().sup()), to_double(app_max.y().sup()), to_double(app_max.z().sup())); + + bool res = CGAL::do_intersect(c2f(q), transfo_box); + return res; + } + + template + bool operator()(const Query& q, const Primitive& pr) const + { + internal_AABB::Filter_test f; + return f(q, m_traits.transformation(), internal::Primitive_helper::get_datum(pr,m_traits)); + } + + // intersection with AABB-tree + template + bool operator()(const CGAL::AABB_tree& other_tree, const Primitive& pr) const + { + return other_tree.do_intersect( internal::Primitive_helper::get_datum(pr,m_traits).transform(m_traits.transformation())); + } + + template + bool operator()(const CGAL::AABB_tree& other_tree, const Bounding_box& bbox) const + { + Point_3 min(bbox.xmin(), bbox.ymin(), bbox.zmin()), + max(bbox.xmax(), bbox.ymax(), bbox.zmax()); + + min = m_traits.transformation().transform(min); + max = m_traits.transformation().transform(max); + + Bounding_box temp_box = + min.bbox() + max.bbox(); + min=Point_3(temp_box.xmin(), temp_box.ymin(), temp_box.zmin()); + max=Point_3(temp_box.xmax(), temp_box.ymax(), temp_box.zmax()); + Bounding_box transfo_box(to_double(min.x()), to_double(min.y()), to_double(min.z()), + to_double(max.x()), to_double(max.y()), to_double(max.z())); + return other_tree.do_intersect(transfo_box); + } + }; + + Do_intersect do_intersect_object() const{ + return Do_intersect(*this); + } + + //Specific + void set_transformation(const Aff_transformation_3& trans) const + { + m_transfo = trans; + } + + const Aff_transformation_3& transformation() const { return m_transfo; } + +}; +}//end CGAL +#endif //CGAL_AABB_AABB_do_intersect_transform_traits_H From 622509816b8c3690c3474f5d8460659f83c2b211 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 20 Jul 2018 16:58:37 +0200 Subject: [PATCH 10/84] Fix rotation of boxes --- .../CGAL/AABB_do_intersect_transform_traits.h | 65 +++++++++++++------ 1 file changed, 46 insertions(+), 19 deletions(-) diff --git a/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h b/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h index b2ca9880f62..414f4920462 100644 --- a/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h +++ b/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h @@ -43,6 +43,7 @@ /// \file AABB_do_intersect_transform_traits.h +//! \todo add protector namespace CGAL { // forward declaration template< typename AABBTraits> @@ -121,7 +122,7 @@ public: //Intersections class Do_intersect { - typedef Simple_cartesian Approximate_kernel; + typedef Simple_cartesian > Approximate_kernel; typedef Cartesian_converter C2F; @@ -135,17 +136,32 @@ public: template bool operator()(const Query& q, const Bounding_box& bbox) const { - Point_3 min(bbox.xmin(), bbox.ymin(), bbox.zmin()), - max(bbox.xmax(), bbox.ymax(), bbox.zmax()); + Point_3 ps[8]; + ps[0] = Point_3(bbox.min(0), bbox.min(1), bbox.min(2)); + ps[1] = Point_3(bbox.min(0), bbox.min(1), bbox.max(2)); + ps[2] = Point_3(bbox.min(0), bbox.max(1), bbox.min(2)); + ps[3] = Point_3(bbox.min(0), bbox.max(1), bbox.max(2)); + + ps[4] = Point_3(bbox.max(0), bbox.min(1), bbox.min(2)); + ps[5] = Point_3(bbox.max(0), bbox.min(1), bbox.max(2)); + ps[6] = Point_3(bbox.max(0), bbox.max(1), bbox.min(2)); + ps[7] = Point_3(bbox.max(0), bbox.max(1), bbox.max(2)); + for(int i=0; i<8; ++i) + { + ps[i] = m_traits.transformation().transform(ps[i]); + } + + + Bounding_box temp_box; + for(int i=0; i<8; ++i) + temp_box += ps[i].bbox(); typename Approximate_kernel::Point_3 app_min, app_max; - Bounding_box temp_box = - min.bbox() + max.bbox(); - Point_3 tmin(temp_box.xmin(), temp_box.ymin(), temp_box.zmin()), - tmax(temp_box.xmax(), temp_box.ymax(), temp_box.zmax()); - app_min=c2f(tmin); - app_max = c2f(tmax); + Point_3 tmin(temp_box.xmin(), temp_box.ymin(), temp_box.zmin()), + tmax(temp_box.xmax(), temp_box.ymax(), temp_box.zmax()); + app_min=c2f(tmin); + app_max = c2f(tmax); Bounding_box transfo_box(to_double(app_min.x().inf()), to_double(app_min.y().inf()), to_double(app_min.z().inf()), to_double(app_max.x().sup()), to_double(app_max.y().sup()), to_double(app_max.z().sup())); @@ -170,18 +186,29 @@ public: template bool operator()(const CGAL::AABB_tree& other_tree, const Bounding_box& bbox) const { - Point_3 min(bbox.xmin(), bbox.ymin(), bbox.zmin()), - max(bbox.xmax(), bbox.ymax(), bbox.zmax()); + Point_3 ps[8]; + ps[0] = Point_3(bbox.min(0), bbox.min(1), bbox.min(2)); + ps[1] = Point_3(bbox.min(0), bbox.min(1), bbox.max(2)); + ps[2] = Point_3(bbox.min(0), bbox.max(1), bbox.min(2)); + ps[3] = Point_3(bbox.min(0), bbox.max(1), bbox.max(2)); - min = m_traits.transformation().transform(min); - max = m_traits.transformation().transform(max); + ps[4] = Point_3(bbox.max(0), bbox.min(1), bbox.min(2)); + ps[5] = Point_3(bbox.max(0), bbox.min(1), bbox.max(2)); + ps[6] = Point_3(bbox.max(0), bbox.max(1), bbox.min(2)); + ps[7] = Point_3(bbox.max(0), bbox.max(1), bbox.max(2)); - Bounding_box temp_box = - min.bbox() + max.bbox(); - min=Point_3(temp_box.xmin(), temp_box.ymin(), temp_box.zmin()); - max=Point_3(temp_box.xmax(), temp_box.ymax(), temp_box.zmax()); - Bounding_box transfo_box(to_double(min.x()), to_double(min.y()), to_double(min.z()), - to_double(max.x()), to_double(max.y()), to_double(max.z())); + for(int i=0; i<8; ++i) + { + ps[i] = m_traits.transformation().transform(ps[i]); + } + + Bounding_box temp_box; + for(int i=0; i<8; ++i) + temp_box += ps[i].bbox(); + Point_3 p_min(temp_box.xmin(), temp_box.ymin(), temp_box.zmin()); + Point_3 p_max(temp_box.xmax(), temp_box.ymax(), temp_box.zmax()); + Bounding_box transfo_box(to_double(p_min.x()), to_double(p_min.y()), to_double(p_min.z()), + to_double(p_max.x()), to_double(p_max.y()), to_double(p_max.z())); return other_tree.do_intersect(transfo_box); } }; From 278600266dc66a04d2a88978dfb767b3738c14a3 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 20 Jul 2018 16:58:55 +0200 Subject: [PATCH 11/84] Add external plugin to AABB_tree for do_intersect demo. --- .../demo_plugin/AABB_tree/CMakeLists.txt | 35 ++++ .../AABB_tree/Do_trees_intersect_plugin.cpp | 177 ++++++++++++++++++ .../AABB_tree/Scene_movable_sm_item.cpp | 166 ++++++++++++++++ .../AABB_tree/Scene_movable_sm_item.h | 58 ++++++ .../Scene_item_rendering_helper.cpp | 1 - .../demo/Polyhedron/Triangle_container.cpp | 7 + Polyhedron/demo/Polyhedron/Viewer.cpp | 4 + .../demo/Three/Example_plugin/CMakeLists.txt | 2 +- Three/doc/Three/Three.txt | 8 +- Three/include/CGAL/Three/Triangle_container.h | 5 + 10 files changed, 457 insertions(+), 6 deletions(-) create mode 100644 AABB_tree/demo_plugin/AABB_tree/CMakeLists.txt create mode 100644 AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp create mode 100644 AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.cpp create mode 100644 AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.h diff --git a/AABB_tree/demo_plugin/AABB_tree/CMakeLists.txt b/AABB_tree/demo_plugin/AABB_tree/CMakeLists.txt new file mode 100644 index 00000000000..0ba18742490 --- /dev/null +++ b/AABB_tree/demo_plugin/AABB_tree/CMakeLists.txt @@ -0,0 +1,35 @@ +project( Do_trees_intersect_plugin) +# Find includes in corresponding build directories +set(CMAKE_INCLUDE_CURRENT_DIR ON) +# Instruct CMake to run moc automatically when needed. +set(CMAKE_AUTOMOC ON) +cmake_minimum_required(VERSION 3.1) + +#Find CGAL +find_package(CGAL COMPONENTS Qt5) +include( ${CGAL_USE_FILE} ) +# Find Qt5 itself +find_package(Qt5 + QUIET + COMPONENTS OpenGL Script Svg Xml + OPTIONAL_COMPONENTS ScriptTools) +find_package(CGAL_polyhedron_demo +HINTS "${CGAL_DIR}" "${CGAL_DIR}/Polyhedron/demo/build-ho" +) +include( ${CGAL_POLYHEDRON_DEMO_USE_FILE} ) +#macro add_item +macro(add_item item_name) + add_library(${item_name} SHARED ${ARGN}) + target_link_libraries(${item_name} + PUBLIC Polyhedron_demo_framework ${CGAL_LIBRARIES} ${Boost_LIBRARIES} + Qt5::OpenGL Qt5::Gui Qt5::Script Qt5::Widgets) + cgal_add_compilation_test(${item_name}) +endmacro(add_item) + +add_item(scene_movable_sm_item Scene_movable_sm_item.cpp) + + + +polyhedron_demo_plugin(do_trees_intersect_plugin Do_trees_intersect_plugin) +target_link_libraries(do_trees_intersect_plugin PUBLIC Polyhedron_scene_surface_mesh_item scene_movable_sm_item) + diff --git a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp new file mode 100644 index 00000000000..42ccf1d809c --- /dev/null +++ b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp @@ -0,0 +1,177 @@ +#include +#include +#include +#include +#include +#include +#include "Messages_interface.h" +#include +#include "Scene_surface_mesh_item.h" +#include "Scene_movable_sm_item.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef CGAL::AABB_face_graph_triangle_primitive Primitive; +typedef CGAL::AABB_traits AABB_triangle_traits; +typedef CGAL::AABB_do_intersect_transform_traits Traits; +typedef CGAL::AABB_tree Tree; + +class DoTreesIntersectplugin : + public QObject, + public CGAL::Three::Polyhedron_demo_plugin_interface +{ + Q_OBJECT + Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface) + Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0") +public: + + bool applicable(QAction*) const Q_DECL_OVERRIDE + { + const int indexA = scene->selectionAindex(); + const int indexB = scene->selectionBindex(); + return qobject_cast(scene->item(indexA)) + && qobject_cast(scene->item(indexB)) + && fixed_item == NULL + && moving_item == NULL; + } + + QList actions() const Q_DECL_OVERRIDE + { + return _actions; + } + + void init(QMainWindow* mw, CGAL::Three::Scene_interface* sc, Messages_interface* mi) Q_DECL_OVERRIDE + { + this->messageInterface = mi; + this->scene = sc; + this->mw = mw; + QAction *actionCreateTrees= new QAction(QString("Start Intersection Tests(A/B)"), mw); + actionCreateTrees->setProperty("submenuName", "AABB_tree"); + if(actionCreateTrees) { + connect(actionCreateTrees, SIGNAL(triggered()), + this, SLOT(start())); + _actions << actionCreateTrees; + } + t1 = 0; + t2 = 0; + moving_item = 0; + fixed_item = 0; + } +private Q_SLOTS: + void start() + { + QApplication::setOverrideCursor(Qt::WaitCursor); + const int indexA = scene->selectionAindex(); + const int indexB = scene->selectionBindex(); + Scene_surface_mesh_item* itemA = qobject_cast(scene->item(indexA)); + Scene_surface_mesh_item* itemB = qobject_cast(scene->item(indexB)); + connect(itemA, &Scene_surface_mesh_item::aboutToBeDestroyed, + [this](){ + if(moving_item) + scene->erase(scene->item_id(moving_item)); + cleanup(); + }); + connect(itemB, &Scene_surface_mesh_item::aboutToBeDestroyed, + [this](){ + if(moving_item) + scene->erase(scene->item_id(moving_item)); + cleanup(); + }); + + + SMesh* tm = itemA->face_graph(); + SMesh* tm2 = itemB->face_graph(); + t1 = new Tree (tm->faces_begin(), tm->faces_end(), *tm); + t2 = new Tree (tm2->faces_begin(), tm2->faces_end(), *tm2); + CGAL::qglviewer::Vec pos((itemB->bbox().min(0) + itemB->bbox().max(0))/2.0, + (itemB->bbox().min(1) + itemB->bbox().max(1))/2.0, + (itemB->bbox().min(2) + itemB->bbox().max(2))/2.0); + + moving_item = new Scene_movable_sm_item(pos,tm2,""); + connect(moving_item, &Scene_surface_mesh_item::aboutToBeDestroyed, + [this](){ + cleanup(); + }); + fixed_item = itemA; + connect(moving_item->manipulatedFrame(), &CGAL::qglviewer::ManipulatedFrame::modified, + this, &DoTreesIntersectplugin::update_trees); + moving_item->setRenderingMode(Flat); + moving_item->setName(itemB->name()); + itemB->setVisible(false); + itemA->setRenderingMode(Wireframe); + scene->addItem(moving_item); + update_trees(); + moving_item->redraw(); + QApplication::restoreOverrideCursor(); + } +public Q_SLOTS: + void update_trees() + { + CGAL::Three::Viewer_interface* viewer = static_cast( + CGAL::QGLViewer::QGLViewerPool().first()); + const double* matrix = moving_item->manipulatedFrame()->matrix(); + moving_item->setFMatrix(matrix); + EPICK::Aff_transformation_3 translation(CGAL::TRANSLATION, -EPICK::Vector_3(moving_item->center().x, + moving_item->center().y, + moving_item->center().z)); + EPICK::Aff_transformation_3 rota( + matrix[0], matrix[4], matrix[8],matrix[12], + matrix[1], matrix[5], matrix[9],matrix[13], + matrix[2], matrix[6], matrix[10],matrix[14]); + EPICK::Aff_transformation_3 transfo = + rota*translation; + t2->traits().set_transformation(transfo); + if(t2->do_intersect(*t1)) + moving_item->setColor(QColor(Qt::green)); + else + { + typedef boost::property_map::type VPM; + VPM vpm2 = get(CGAL::vertex_point, *moving_item->getFaceGraph()); + CGAL::Side_of_triangle_mesh sotm1(*t1); + if(sotm1((transfo).transform(vpm2[*moving_item->getFaceGraph()->vertices().begin()])) != CGAL::ON_UNBOUNDED_SIDE) + { + moving_item->setColor(QColor(Qt::blue)); + } + else + { + CGAL::Side_of_triangle_mesh sotm2(*t2); + if(sotm2(fixed_item->face_graph()->point(*fixed_item->face_graph()->vertices().begin())) != CGAL::ON_UNBOUNDED_SIDE) + moving_item->setColor(QColor(Qt::blue)); + else + moving_item->setColor(QColor(Qt::red)); + } + } + viewer->update(); + } + + void cleanup() + { + if(t1) + delete t1; + t1 = NULL; + if(t2) + delete t2; + t2 = NULL; + moving_item = NULL; + fixed_item = NULL; + } + +private: + QList _actions; + Messages_interface* messageInterface; + CGAL::Three::Scene_interface* scene; + QMainWindow* mw; + Tree *t1, *t2; + Scene_movable_sm_item* moving_item; + Scene_surface_mesh_item* fixed_item; +}; +#include "Do_trees_intersect_plugin.moc" diff --git a/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.cpp b/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.cpp new file mode 100644 index 00000000000..289b438d810 --- /dev/null +++ b/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.cpp @@ -0,0 +1,166 @@ +#include +#include "Scene_movable_sm_item.h" +#include +#include +#include +#include +typedef CGAL::Three::Triangle_container Tri; +typedef CGAL::Three::Viewer_interface VI; +struct Scene_movable_sm_item_priv +{ + Scene_movable_sm_item_priv(const CGAL::qglviewer::Vec& pos,SMesh* sm, + const QString name, Scene_movable_sm_item *parent) + : frame(new CGAL::Three::Scene_item::ManipulatedFrame()), + facegraph(sm), + center_(pos), + item_name(name) + { + item = parent; + const CGAL::qglviewer::Vec offset = static_cast(CGAL::QGLViewer::QGLViewerPool().first())->offset(); + frame->setPosition(pos+offset); + item->setTriangleContainer(0, new Triangle_container(VI::PROGRAM_WITH_LIGHT, + false)); + } + ~Scene_movable_sm_item_priv() + { + delete frame; + } + void initialize_buffers(Viewer_interface *viewer) const; + void compute_elements() const; + enum VAOs { + Edges=0, + NbOfVaos + }; + enum VBOs { + Vertices = 0, + NbOfVbos + }; + + CGAL::qglviewer::ManipulatedFrame* frame; + SMesh* facegraph; + CGAL::qglviewer::Vec center_; + Scene_movable_sm_item *item; + QMatrix4x4 f_matrix; + const QString item_name; + + mutable QOpenGLShaderProgram *program; + mutable std::vector flat_normals; + mutable std::vector flat_vertices; +}; + +Scene_movable_sm_item::Scene_movable_sm_item(const CGAL::qglviewer::Vec& pos, SMesh* sm, + const QString name) +{ + d = new Scene_movable_sm_item_priv(pos,sm, name, this); +} + + +void Scene_movable_sm_item_priv::initialize_buffers(CGAL::Three::Viewer_interface *viewer =0) const +{ + item->getTriangleContainer(0)->initializeBuffers(viewer); + item->getTriangleContainer(0)->setFlatDataSize(flat_vertices.size()); + flat_vertices.resize(0); + flat_normals .resize(0); + flat_vertices.shrink_to_fit(); + flat_normals.shrink_to_fit(); + + item->are_buffers_filled = true; +} + + +void Scene_movable_sm_item_priv::compute_elements() const +{ + typedef EPICK::Point_3 Point; + QApplication::setOverrideCursor(Qt::WaitCursor); + + SMesh::Property_map fnormals = + facegraph->add_property_map("f:normal").first; + CGAL::Polygon_mesh_processing::compute_face_normals(*facegraph,fnormals); + const CGAL::qglviewer::Vec o = static_cast(CGAL::QGLViewer::QGLViewerPool().first())->offset(); + EPICK::Vector_3 offset(o.x, o.y, o.z); + SMesh::Property_map positions = + facegraph->points(); + typedef boost::graph_traits::face_descriptor face_descriptor; + typedef boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef CGAL::Buffer_for_vao CPF; + flat_vertices.clear(); + flat_normals.clear(); + BOOST_FOREACH(face_descriptor fd, faces(*facegraph)) + { + BOOST_FOREACH(halfedge_descriptor hd, halfedges_around_face(halfedge(fd, *facegraph),*facegraph)) + { + Point p = positions[source(hd, *facegraph)] + offset; + EPICK::Point_3 pc(p.x() - center_.x, + p.y() - center_.y, + p.z() - center_.z); + CPF::add_point_in_buffer(pc, flat_vertices); + EPICK::Vector_3 n = fnormals[fd]; + CPF::add_normal_in_buffer(n, flat_normals); + } + } + + + item->getTriangleContainer(0)->allocate(Tri::Flat_vertices, flat_vertices.data(), + static_cast(flat_vertices.size()*sizeof(float))); + item->getTriangleContainer(0)->allocate(Tri::Flat_normals, flat_normals.data(), + static_cast(flat_normals.size()*sizeof(float))); + QApplication::restoreOverrideCursor(); +} + +void Scene_movable_sm_item::computeElements() const +{ + d->compute_elements(); +} +void Scene_movable_sm_item::draw(CGAL::Three::Viewer_interface* viewer) const +{ + if(!isInit() && viewer->context()->isValid()) + initGL(); + if(!are_buffers_filled) + d->initialize_buffers(viewer); + getTriangleContainer(0)->setColor(color()); + getTriangleContainer(0)->setSelected(is_selected); + getTriangleContainer(0)->setFrameMatrix(d->f_matrix); + + getTriangleContainer(0)->draw(viewer, true); +} + +QString Scene_movable_sm_item::toolTip() const { + return QObject::tr("

Manipulatable representation of %1

" + "

Keep Ctrl pressed and use the arcball to define an affine transformation.
") + .arg(d->item_name); +} + +void +Scene_movable_sm_item::compute_bbox() const { + SMesh::Property_map pprop = d->facegraph->points(); + CGAL::Bbox_3 bbox; + + BOOST_FOREACH(vertex_descriptor vd,vertices(*d->facegraph)) + { + bbox = bbox + pprop[vd].bbox(); + } + _bbox = Bbox(bbox.xmin(),bbox.ymin(),bbox.zmin(), + bbox.xmax(),bbox.ymax(),bbox.zmax()); + is_bbox_computed = true; +} + + +void Scene_movable_sm_item::invalidateOpenGLBuffers() +{ + d->compute_elements(); + compute_bbox(); + are_buffers_filled = false; +} +CGAL::Three::Scene_item::ManipulatedFrame* Scene_movable_sm_item::manipulatedFrame() { return d->frame; } +const CGAL::qglviewer::Vec& Scene_movable_sm_item::center() const { return d->center_; } +Scene_movable_sm_item::~Scene_movable_sm_item() { delete d; Q_EMIT killed(); } +void Scene_movable_sm_item::setFMatrix(const GLdouble matrix[]) +{ + for (int i=0; i<16; ++i) + d->f_matrix.data()[i] = (float)matrix[i]; +} + +SMesh *Scene_movable_sm_item::getFaceGraph() +{ + return d->facegraph; +} diff --git a/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.h b/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.h new file mode 100644 index 00000000000..1b223d81946 --- /dev/null +++ b/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.h @@ -0,0 +1,58 @@ +#ifndef Scene_movable_sm_item_H +#define Scene_movable_sm_item_H + +#include "SMesh_type.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + + +#if defined( scene_movable_sm_item_EXPORTS) +# define SCENE_MOVABLE_SM_ITEM_EXPORT Q_DECL_EXPORT +#else +# define SCENE_MOVABLE_SM_ITEM_EXPORT Q_DECL_IMPORT +#endif + +using namespace CGAL::Three; +struct Scene_movable_sm_item_priv; +// This class represents a polyhedron in the OpenGL scene +class SCENE_MOVABLE_SM_ITEM_EXPORT Scene_movable_sm_item + : public CGAL::Three::Scene_item_rendering_helper +{ + Q_OBJECT + +public: + Scene_movable_sm_item(const CGAL::qglviewer::Vec& pos, SMesh *sm, + const QString name); + Scene_item* clone() const{return NULL;} + QString toolTip() const; + void draw(CGAL::Three::Viewer_interface *) const; + void compute_bbox() const; + ~Scene_movable_sm_item(); + bool manipulatable() const { return true;} + ManipulatedFrame* manipulatedFrame(); + const CGAL::qglviewer::Vec& center() const; + virtual bool supportsRenderingMode(RenderingMode m) const { return m==Flat ; } + virtual void invalidateOpenGLBuffers(); + void setFMatrix(const GLdouble matrix[16]); + void computeElements() const; + bool isEmpty() const {return false;} + SMesh *getFaceGraph(); + +protected: + friend struct Scene_movable_sm_item_priv; + Scene_movable_sm_item_priv* d; + +Q_SIGNALS: + void stop(); + void killed(); +}; // end class Scene_movable_sm_item + +#endif // Scene_movable_sm_item_H diff --git a/Polyhedron/demo/Polyhedron/Scene_item_rendering_helper.cpp b/Polyhedron/demo/Polyhedron/Scene_item_rendering_helper.cpp index c4b6e12b0e3..78ef1ecbf7b 100644 --- a/Polyhedron/demo/Polyhedron/Scene_item_rendering_helper.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_item_rendering_helper.cpp @@ -134,7 +134,6 @@ void Scene_item_rendering_helper::initGL() const void Scene_item_rendering_helper::processData(Gl_data_names )const { computeElements(); - //redraw(); } diff --git a/Polyhedron/demo/Polyhedron/Triangle_container.cpp b/Polyhedron/demo/Polyhedron/Triangle_container.cpp index 2ea32046f2a..b7ce71308b1 100644 --- a/Polyhedron/demo/Polyhedron/Triangle_container.cpp +++ b/Polyhedron/demo/Polyhedron/Triangle_container.cpp @@ -16,6 +16,7 @@ struct Tri_d{ float shrink_factor; QVector4D plane; float alpha; + QMatrix4x4 f_matrix; }; Triangle_container::Triangle_container(int program, bool indexed) @@ -117,6 +118,8 @@ QOpenGLFramebufferObject* fbo = viewer->depthPeelingFbo(); getVao(viewer)->bind(); if(is_color_uniform) getVao(viewer)->program->setAttributeValue("colors", getColor()); + if(getVao(viewer)->program->property("hasFMatrix").toBool()) + getVao(viewer)->program->setUniformValue("f_matrix", getFrameMatrix()); getVbo(Vertex_indices)->bind(); if(getVao(viewer)->program->property("hasTransparency").toBool()) { @@ -142,6 +145,8 @@ QOpenGLFramebufferObject* fbo = viewer->depthPeelingFbo(); getVao(viewer)->program->setUniformValue("cutplane", d->plane); if(is_color_uniform) getVao(viewer)->program->setAttributeValue("colors", getColor()); + if(getVao(viewer)->program->property("hasFMatrix").toBool()) + getVao(viewer)->program->setUniformValue("f_matrix", getFrameMatrix()); if(getVao(viewer)->program->property("hasTransparency").toBool()) { getVao(viewer)->program->setUniformValue("comparing", viewer->currentPass() > 0); @@ -189,6 +194,8 @@ void Triangle_container::initializeBuffers(Viewer_interface *viewer) float Triangle_container::getShrinkFactor() { return d->shrink_factor ; } QVector4D Triangle_container::getPlane() { return d->plane; } float Triangle_container::getAlpha() { return d->alpha; } +QMatrix4x4 Triangle_container::getFrameMatrix() const { return d->f_matrix; } void Triangle_container::setShrinkFactor(const float& f) { d->shrink_factor = f; } void Triangle_container::setAlpha (const float& f) { d->alpha = f ; } +void Triangle_container::setFrameMatrix(const QMatrix4x4& m) { d->f_matrix = m; } diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index f3e83ae55dd..1948df940d5 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -815,6 +815,9 @@ void Viewer::attribBuffers(int program_name) const { program->bind(); program->setUniformValue("point_size", getGlPointSize()); program->setUniformValue("mvp_matrix", mvp_mat); + QMatrix4x4 id_mat; + id_mat.setToIdentity(); + program->setUniformValue("f_matrix", id_mat); program->setUniformValue("is_clipbox_on", d->clipping); if(d->clipping) { @@ -1068,6 +1071,7 @@ QOpenGLShaderProgram* Viewer::getShaderProgram(int name) const program->setProperty("hasLight", true); program->setProperty("hasNormals", true); program->setProperty("hasTransparency", true); + program->setProperty("hasFMatrix", true); return program; } case PROGRAM_WITHOUT_LIGHT: diff --git a/Three/demo/Three/Example_plugin/CMakeLists.txt b/Three/demo/Three/Example_plugin/CMakeLists.txt index 8dfeda7fd3f..9e05fb0f202 100644 --- a/Three/demo/Three/Example_plugin/CMakeLists.txt +++ b/Three/demo/Three/Example_plugin/CMakeLists.txt @@ -38,6 +38,6 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") polyhedron_demo_plugin(basic_item_plugin Basic_item_plugin) # links the library containing the scene_plane_item with the plugin - target_link_libraries(basic_item_plugin Polyhedron_scene_basic_objects) + target_link_libraries(basic_item_plugin PUBLIC Polyhedron_scene_basic_objects) endif() diff --git a/Three/doc/Three/Three.txt b/Three/doc/Three/Three.txt index 7251e6a62e9..8c615392b71 100644 --- a/Three/doc/Three/Three.txt +++ b/Three/doc/Three/Three.txt @@ -199,7 +199,7 @@ Once your code is written, you will need to link the item's library to your plug polyhedron_demo_plugin(basic_item_plugin Basic_item_plugin) # links the library containing the scene_plane_item with the plugin - target_link_libraries(basic_item_plugin scene_basic_objects) + target_link_libraries(basic_item_plugin PUBLIC scene_basic_objects) \subsubsection exampleCreatingANewTypeItem Creating a new type of item @@ -241,7 +241,7 @@ To display, you need to call the same program that got configured previously, an If you created your item in a specific file and you need to use it outside your plugin (like in another plugin), it is recommended to put it in the demo's root directory, and you will have to define your item in the general Polyhedron_demo's CMakeLists.txt by using the macro add_item : add_item(scene_trivial_item Scene_trivial_item.cpp) - target_link_libraries(scene_trivial_item scene_dependances_item) + target_link_libraries(scene_trivial_item PUBLIC scene_dependances_item) \subsection exampleUsingAGroupItem Using a Scene_group_item @@ -342,7 +342,7 @@ Finally, you can declare your plugin If you need targets from the Polyhedron_demo, you will have to add the prefix 'Polyhedron_' to the target's name, as the exported targets belong to the namespace Polyhedron_ polyhedron_demo_plugin(basic_item_plugin Basic_item_plugin) - target_link_libraries(basic_item_plugin Polyhedron_scene_basic_objects) + target_link_libraries(basic_item_plugin PUBLIC Polyhedron_scene_basic_objects) Notice that an external plugin will not be automatically loaded in the Polyhedron demo. It must be built in its own project. @@ -380,7 +380,7 @@ Notice that an external plugin will not be automatically loaded in the Polyhedro \section example Examples -All the examples have been constructed as external plugins in CGAL/Three/demo/Three/Example_plugin. You will have to use "Load plugin" in the File menu if you want to test it. +All the examples have been constructed as external plugins in CGAL/Three/demo/Three/Example_plugin. You will have to use "Load plugin" in the File menu or set the environment variable POLYHEDRON_DEMO_PLUGINS_PATH if you want to test it. \subsection example1 Creating a Basic Plugin \cgalExample{Three/Example_plugin/Basic_plugin.cpp} diff --git a/Three/include/CGAL/Three/Triangle_container.h b/Three/include/CGAL/Three/Triangle_container.h index ecea0b1ed69..0a5eff72be2 100644 --- a/Three/include/CGAL/Three/Triangle_container.h +++ b/Three/include/CGAL/Three/Triangle_container.h @@ -35,6 +35,7 @@ using namespace CGAL::Three; # define DEMO_FRAMEWORK_EXPORT Q_DECL_IMPORT #endif struct Tri_d; +class QMatrix4x4; namespace CGAL { namespace Three { @@ -95,12 +96,16 @@ struct DEMO_FRAMEWORK_EXPORT Triangle_container :public Primitive_container QVector4D getPlane(); //! getter for the "alpha" parameter float getAlpha(); + //! getter for the "f_matrix" parameter + QMatrix4x4 getFrameMatrix()const; //! setter for the "shrink_factor" parameter void setShrinkFactor(const float&); //! setter for the "plane" parameter void setPlane (const QVector4D&); //! setter for the "alpha" parameter void setAlpha (const float&); + //! setter for the "f_matrix" parameter + void setFrameMatrix(const QMatrix4x4&); ///@} //drawing variables From e6c7c347839906943d211814aad31e9611573fb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 23 Jul 2018 14:29:07 +0200 Subject: [PATCH 12/84] fix bbox computation and factorize --- .../CGAL/AABB_do_intersect_transform_traits.h | 84 ++++++------------- 1 file changed, 27 insertions(+), 57 deletions(-) diff --git a/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h b/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h index 414f4920462..5dd2f9944f5 100644 --- a/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h +++ b/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h @@ -122,12 +122,34 @@ public: //Intersections class Do_intersect { + // TODO: possible optimization using Protector typedef Simple_cartesian > Approximate_kernel; typedef Cartesian_converter C2F; const AABB_do_intersect_transform_traits& m_traits; - C2F c2f; + C2F m_c2f; + + Bounding_box + compute_transformed_bbox(const Bounding_box& bbox) const + { + Approximate_kernel::Aff_transformation_3 af = m_c2f( m_traits.transformation() ); + + //TODO reuse the conversions + typename Approximate_kernel::Point_3 ps[8]; + ps[0] = af( m_c2f( Point_3(bbox.min(0), bbox.min(1), bbox.min(2)) ) ); + ps[1] = af( m_c2f( Point_3(bbox.min(0), bbox.min(1), bbox.max(2)) ) ); + ps[2] = af( m_c2f( Point_3(bbox.min(0), bbox.max(1), bbox.min(2)) ) ); + ps[3] = af( m_c2f( Point_3(bbox.min(0), bbox.max(1), bbox.max(2)) ) ); + + ps[4] = af( m_c2f( Point_3(bbox.max(0), bbox.min(1), bbox.min(2)) ) ); + ps[5] = af( m_c2f( Point_3(bbox.max(0), bbox.min(1), bbox.max(2)) ) ); + ps[6] = af( m_c2f( Point_3(bbox.max(0), bbox.max(1), bbox.min(2)) ) ); + ps[7] = af( m_c2f( Point_3(bbox.max(0), bbox.max(1), bbox.max(2)) ) ); + + return bbox_3(ps, ps+8); + } + public: Do_intersect(const AABB_do_intersect_transform_traits& traits) :m_traits(traits) @@ -136,39 +158,10 @@ public: template bool operator()(const Query& q, const Bounding_box& bbox) const { - Point_3 ps[8]; - ps[0] = Point_3(bbox.min(0), bbox.min(1), bbox.min(2)); - ps[1] = Point_3(bbox.min(0), bbox.min(1), bbox.max(2)); - ps[2] = Point_3(bbox.min(0), bbox.max(1), bbox.min(2)); - ps[3] = Point_3(bbox.min(0), bbox.max(1), bbox.max(2)); - - ps[4] = Point_3(bbox.max(0), bbox.min(1), bbox.min(2)); - ps[5] = Point_3(bbox.max(0), bbox.min(1), bbox.max(2)); - ps[6] = Point_3(bbox.max(0), bbox.max(1), bbox.min(2)); - ps[7] = Point_3(bbox.max(0), bbox.max(1), bbox.max(2)); - - for(int i=0; i<8; ++i) - { - ps[i] = m_traits.transformation().transform(ps[i]); - } - - - Bounding_box temp_box; - for(int i=0; i<8; ++i) - temp_box += ps[i].bbox(); - typename Approximate_kernel::Point_3 app_min, - app_max; - Point_3 tmin(temp_box.xmin(), temp_box.ymin(), temp_box.zmin()), - tmax(temp_box.xmax(), temp_box.ymax(), temp_box.zmax()); - app_min=c2f(tmin); - app_max = c2f(tmax); - Bounding_box transfo_box(to_double(app_min.x().inf()), to_double(app_min.y().inf()), to_double(app_min.z().inf()), - to_double(app_max.x().sup()), to_double(app_max.y().sup()), to_double(app_max.z().sup())); - - bool res = CGAL::do_intersect(c2f(q), transfo_box); - return res; + // TODO use base_traits + return CGAL::do_intersect(q, compute_transformed_bbox(bbox)); } - + template bool operator()(const Query& q, const Primitive& pr) const { @@ -186,30 +179,7 @@ public: template bool operator()(const CGAL::AABB_tree& other_tree, const Bounding_box& bbox) const { - Point_3 ps[8]; - ps[0] = Point_3(bbox.min(0), bbox.min(1), bbox.min(2)); - ps[1] = Point_3(bbox.min(0), bbox.min(1), bbox.max(2)); - ps[2] = Point_3(bbox.min(0), bbox.max(1), bbox.min(2)); - ps[3] = Point_3(bbox.min(0), bbox.max(1), bbox.max(2)); - - ps[4] = Point_3(bbox.max(0), bbox.min(1), bbox.min(2)); - ps[5] = Point_3(bbox.max(0), bbox.min(1), bbox.max(2)); - ps[6] = Point_3(bbox.max(0), bbox.max(1), bbox.min(2)); - ps[7] = Point_3(bbox.max(0), bbox.max(1), bbox.max(2)); - - for(int i=0; i<8; ++i) - { - ps[i] = m_traits.transformation().transform(ps[i]); - } - - Bounding_box temp_box; - for(int i=0; i<8; ++i) - temp_box += ps[i].bbox(); - Point_3 p_min(temp_box.xmin(), temp_box.ymin(), temp_box.zmin()); - Point_3 p_max(temp_box.xmax(), temp_box.ymax(), temp_box.zmax()); - Bounding_box transfo_box(to_double(p_min.x()), to_double(p_min.y()), to_double(p_min.z()), - to_double(p_max.x()), to_double(p_max.y()), to_double(p_max.z())); - return other_tree.do_intersect(transfo_box); + return other_tree.do_intersect(compute_transformed_bbox(bbox)); } }; From 8bac45bebcba127cbc261e6d18c0e37fed9cfebb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 23 Jul 2018 14:30:20 +0200 Subject: [PATCH 13/84] inverse red and green --- .../demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp index 42ccf1d809c..aba3bf6945b 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -129,7 +130,7 @@ public Q_SLOTS: rota*translation; t2->traits().set_transformation(transfo); if(t2->do_intersect(*t1)) - moving_item->setColor(QColor(Qt::green)); + moving_item->setColor(QColor(Qt::red)); else { typedef boost::property_map::type VPM; @@ -147,7 +148,7 @@ public Q_SLOTS: if(sotm2(fixed_item->face_graph()->point(*fixed_item->face_graph()->vertices().begin())) != CGAL::ON_UNBOUNDED_SIDE) moving_item->setColor(QColor(Qt::blue)); else - moving_item->setColor(QColor(Qt::red)); + moving_item->setColor(QColor(Qt::green)); } } viewer->update(); From 3d50da882ec319b61c6359a84d777a877333da4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 23 Jul 2018 14:41:31 +0200 Subject: [PATCH 14/84] cosmetic changes --- .../CGAL/AABB_do_intersect_transform_traits.h | 72 +++++++++---------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h b/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h index 5dd2f9944f5..3ff1192506c 100644 --- a/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h +++ b/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h @@ -52,7 +52,7 @@ class AABB_tree; namespace internal_AABB { template -struct Actual_intersect +struct Transformed_datum_do_intersect_impl { typedef bool result_type; template @@ -65,42 +65,42 @@ struct Actual_intersect } }; - template - struct Filter_test +template +struct Transformed_datum_do_intersect +{ + template + bool operator()(const Query& q, + const CGAL::Aff_transformation_3& transfo, + const Datum_t& pr) const { - template - bool operator()(const Query& q, - const CGAL::Aff_transformation_3& transfo, - const Datum_t& pr) const - { - return Actual_intersect()(q,transfo,pr); - } - }; - template - struct Filter_test + return Transformed_datum_do_intersect_impl()(q,transfo,pr); + } +}; + +template +struct Transformed_datum_do_intersect +{ + template + bool operator()(const Query& q, + const CGAL::Aff_transformation_3& transfo, + const Datum_t& pr) const { - template - bool operator()(const Query& q, - const CGAL::Aff_transformation_3& transfo, - const Datum_t& pr) const - { - typedef typename Kernel::Approximate_kernel FK; - typedef typename Kernel::Exact_kernel EK; - typedef typename Kernel::C2F C2F; - typedef typename Kernel::C2E C2E; - - typedef internal_AABB::Actual_intersect Exactator; - typedef internal_AABB::Actual_intersect Approxator; - typedef CGAL::Filtered_predicate< - Exactator, - Approxator, - C2E, - C2F> Filter; - Filter fi; - return fi(q, transfo,pr); - } - }; + typedef typename Kernel::Approximate_kernel FK; + typedef typename Kernel::Exact_kernel EK; + typedef typename Kernel::C2F C2F; + typedef typename Kernel::C2E C2E; + + // filtered predicate + CGAL::Filtered_predicate< + internal_AABB::Transformed_datum_do_intersect_impl, + internal_AABB::Transformed_datum_do_intersect_impl, + C2E, + C2F > filtered_do_intersect; + + return filtered_do_intersect(q, transfo, pr); + } +}; }//end internal template bool operator()(const Query& q, const Primitive& pr) const { - internal_AABB::Filter_test f; + internal_AABB::Transformed_datum_do_intersect f; return f(q, m_traits.transformation(), internal::Primitive_helper::get_datum(pr,m_traits)); } From 680191dccd80a7d7fc5d51c9367118e4ec170971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 23 Jul 2018 14:43:01 +0200 Subject: [PATCH 15/84] remove trailing whitespaces --- .../CGAL/AABB_do_intersect_transform_traits.h | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h b/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h index 3ff1192506c..56d9da8809e 100644 --- a/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h +++ b/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h @@ -64,7 +64,7 @@ struct Transformed_datum_do_intersect_impl pr.transform(transfo)); } }; - + template struct Transformed_datum_do_intersect @@ -93,9 +93,9 @@ struct Transformed_datum_do_intersect // filtered predicate CGAL::Filtered_predicate< - internal_AABB::Transformed_datum_do_intersect_impl, - internal_AABB::Transformed_datum_do_intersect_impl, - C2E, + internal_AABB::Transformed_datum_do_intersect_impl, + internal_AABB::Transformed_datum_do_intersect_impl, + C2E, C2F > filtered_do_intersect; return filtered_do_intersect(q, transfo, pr); @@ -103,14 +103,14 @@ struct Transformed_datum_do_intersect }; }//end internal -template class AABB_do_intersect_transform_traits: public BaseTraits { mutable Aff_transformation_3 m_transfo; public: - + //Constructor AABB_do_intersect_transform_traits(const Aff_transformation_3& transf = Aff_transformation_3(IDENTITY)) :m_transfo(transf) @@ -125,8 +125,8 @@ public: // TODO: possible optimization using Protector typedef Simple_cartesian > Approximate_kernel; typedef Cartesian_converter C2F; - - + + const AABB_do_intersect_transform_traits& m_traits; C2F m_c2f; @@ -154,7 +154,7 @@ public: Do_intersect(const AABB_do_intersect_transform_traits& traits) :m_traits(traits) {} - + template bool operator()(const Query& q, const Bounding_box& bbox) const { @@ -168,33 +168,33 @@ public: internal_AABB::Transformed_datum_do_intersect f; return f(q, m_traits.transformation(), internal::Primitive_helper::get_datum(pr,m_traits)); } - + // intersection with AABB-tree template bool operator()(const CGAL::AABB_tree& other_tree, const Primitive& pr) const { return other_tree.do_intersect( internal::Primitive_helper::get_datum(pr,m_traits).transform(m_traits.transformation())); } - + template bool operator()(const CGAL::AABB_tree& other_tree, const Bounding_box& bbox) const { return other_tree.do_intersect(compute_transformed_bbox(bbox)); } }; - + Do_intersect do_intersect_object() const{ return Do_intersect(*this); } - + //Specific - void set_transformation(const Aff_transformation_3& trans) const + void set_transformation(const Aff_transformation_3& trans) const { m_transfo = trans; } - + const Aff_transformation_3& transformation() const { return m_transfo; } - + }; }//end CGAL #endif //CGAL_AABB_AABB_do_intersect_transform_traits_H From 2823f46f983f9cb7f2b74cd6fd5d88d273aa2075 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 24 Jul 2018 11:45:36 +0200 Subject: [PATCH 16/84] De-activate inclusion test and make both items movable. --- .../AABB_tree/Do_trees_intersect_plugin.cpp | 110 +++++++++++------- .../AABB_tree/Scene_movable_sm_item.cpp | 41 +++++++ .../AABB_tree/Scene_movable_sm_item.h | 4 +- 3 files changed, 114 insertions(+), 41 deletions(-) diff --git a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp index aba3bf6945b..e708ba8b984 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp @@ -39,8 +39,8 @@ public: const int indexB = scene->selectionBindex(); return qobject_cast(scene->item(indexA)) && qobject_cast(scene->item(indexB)) - && fixed_item == NULL - && moving_item == NULL; + && base_item == NULL + && query_item == NULL; } QList actions() const Q_DECL_OVERRIDE @@ -62,8 +62,8 @@ public: } t1 = 0; t2 = 0; - moving_item = 0; - fixed_item = 0; + query_item = 0; + base_item = 0; } private Q_SLOTS: void start() @@ -75,14 +75,14 @@ private Q_SLOTS: Scene_surface_mesh_item* itemB = qobject_cast(scene->item(indexB)); connect(itemA, &Scene_surface_mesh_item::aboutToBeDestroyed, [this](){ - if(moving_item) - scene->erase(scene->item_id(moving_item)); + if(query_item) + scene->erase(scene->item_id(query_item)); cleanup(); }); connect(itemB, &Scene_surface_mesh_item::aboutToBeDestroyed, [this](){ - if(moving_item) - scene->erase(scene->item_id(moving_item)); + if(query_item) + scene->erase(scene->item_id(query_item)); cleanup(); }); @@ -95,21 +95,31 @@ private Q_SLOTS: (itemB->bbox().min(1) + itemB->bbox().max(1))/2.0, (itemB->bbox().min(2) + itemB->bbox().max(2))/2.0); - moving_item = new Scene_movable_sm_item(pos,tm2,""); - connect(moving_item, &Scene_surface_mesh_item::aboutToBeDestroyed, + query_item = new Scene_movable_sm_item(pos,tm2,""); + connect(query_item, &Scene_surface_mesh_item::aboutToBeDestroyed, [this](){ cleanup(); }); - fixed_item = itemA; - connect(moving_item->manipulatedFrame(), &CGAL::qglviewer::ManipulatedFrame::modified, + connect(query_item->manipulatedFrame(), &CGAL::qglviewer::ManipulatedFrame::modified, this, &DoTreesIntersectplugin::update_trees); - moving_item->setRenderingMode(Flat); - moving_item->setName(itemB->name()); + query_item->setRenderingMode(Flat); + query_item->setName(itemB->name()); itemB->setVisible(false); - itemA->setRenderingMode(Wireframe); - scene->addItem(moving_item); + itemA->setVisible(false); + scene->setSelectedItem(scene->addItem(query_item)); + base_item = new Scene_movable_sm_item(pos,tm,""); + connect(base_item, &Scene_surface_mesh_item::aboutToBeDestroyed, + [this](){ + cleanup(); + }); + connect(base_item->manipulatedFrame(), &CGAL::qglviewer::ManipulatedFrame::modified, + this, &DoTreesIntersectplugin::update_trees); + base_item->setRenderingMode(Wireframe); + base_item->setName(itemA->name()); + scene->addItem(base_item); update_trees(); - moving_item->redraw(); + query_item->redraw(); + base_item->redraw(); QApplication::restoreOverrideCursor(); } public Q_SLOTS: @@ -117,40 +127,60 @@ public Q_SLOTS: { CGAL::Three::Viewer_interface* viewer = static_cast( CGAL::QGLViewer::QGLViewerPool().first()); - const double* matrix = moving_item->manipulatedFrame()->matrix(); - moving_item->setFMatrix(matrix); - EPICK::Aff_transformation_3 translation(CGAL::TRANSLATION, -EPICK::Vector_3(moving_item->center().x, - moving_item->center().y, - moving_item->center().z)); - EPICK::Aff_transformation_3 rota( - matrix[0], matrix[4], matrix[8],matrix[12], - matrix[1], matrix[5], matrix[9],matrix[13], - matrix[2], matrix[6], matrix[10],matrix[14]); - EPICK::Aff_transformation_3 transfo = - rota*translation; - t2->traits().set_transformation(transfo); + + const double* matrixB = base_item->manipulatedFrame()->matrix(); + base_item->setFMatrix(matrixB); + EPICK::Aff_transformation_3 translationB(CGAL::TRANSLATION, -EPICK::Vector_3(base_item->center().x, + base_item->center().y, + base_item->center().z)); + EPICK::Aff_transformation_3 rotaB( + matrixB[0], matrixB[4], matrixB[8],matrixB[12], + matrixB[1], matrixB[5], matrixB[9],matrixB[13], + matrixB[2], matrixB[6], matrixB[10],matrixB[14]); + EPICK::Aff_transformation_3 transfoB = + rotaB*translationB; + t1->traits().set_transformation(transfoB); + + const double* matrixA = query_item->manipulatedFrame()->matrix(); + query_item->setFMatrix(matrixA); + EPICK::Aff_transformation_3 translationA(CGAL::TRANSLATION, -EPICK::Vector_3(query_item->center().x, + query_item->center().y, + query_item->center().z)); + EPICK::Aff_transformation_3 rotaA( + matrixA[0], matrixA[4], matrixA[8],matrixA[12], + matrixA[1], matrixA[5], matrixA[9],matrixA[13], + matrixA[2], matrixA[6], matrixA[10],matrixA[14]); + EPICK::Aff_transformation_3 transfoA = + rotaA*translationA; + t2->traits().set_transformation(transfoA); if(t2->do_intersect(*t1)) - moving_item->setColor(QColor(Qt::red)); + query_item->setColor(QColor(Qt::red)); else { +#if 0 typedef boost::property_map::type VPM; - VPM vpm2 = get(CGAL::vertex_point, *moving_item->getFaceGraph()); + VPM vpm2 = get(CGAL::vertex_point, *query_item->getFaceGraph()); CGAL::Side_of_triangle_mesh sotm1(*t1); - if(sotm1((transfo).transform(vpm2[*moving_item->getFaceGraph()->vertices().begin()])) != CGAL::ON_UNBOUNDED_SIDE) + if(sotm1((transfoA).transform(vpm2[*query_item->getFaceGraph()->vertices().begin()])) != CGAL::ON_UNBOUNDED_SIDE) { - moving_item->setColor(QColor(Qt::blue)); + query_item->setColor(QColor(Qt::blue)); } else { CGAL::Side_of_triangle_mesh sotm2(*t2); - if(sotm2(fixed_item->face_graph()->point(*fixed_item->face_graph()->vertices().begin())) != CGAL::ON_UNBOUNDED_SIDE) - moving_item->setColor(QColor(Qt::blue)); + if(sotm2(base_item->face_graph()->point(*base_item->face_graph()->vertices().begin())) != CGAL::ON_UNBOUNDED_SIDE) + query_item->setColor(QColor(Qt::blue)); else - moving_item->setColor(QColor(Qt::green)); +#endif + query_item->setColor(QColor(Qt::green)); + #if 0 } +#endif + } + viewer->update(); } @@ -162,8 +192,8 @@ public Q_SLOTS: if(t2) delete t2; t2 = NULL; - moving_item = NULL; - fixed_item = NULL; + query_item = NULL; + base_item = NULL; } private: @@ -172,7 +202,7 @@ private: CGAL::Three::Scene_interface* scene; QMainWindow* mw; Tree *t1, *t2; - Scene_movable_sm_item* moving_item; - Scene_surface_mesh_item* fixed_item; + Scene_movable_sm_item* query_item; + Scene_movable_sm_item* base_item; }; #include "Do_trees_intersect_plugin.moc" diff --git a/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.cpp b/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.cpp index 289b438d810..0e03b99bb3a 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.cpp @@ -4,6 +4,7 @@ #include #include #include +#include typedef CGAL::Three::Triangle_container Tri; typedef CGAL::Three::Viewer_interface VI; struct Scene_movable_sm_item_priv @@ -20,6 +21,8 @@ struct Scene_movable_sm_item_priv frame->setPosition(pos+offset); item->setTriangleContainer(0, new Triangle_container(VI::PROGRAM_WITH_LIGHT, false)); + item->setEdgeContainer(0, new Edge_container(VI::PROGRAM_NO_SELECTION, + false)); } ~Scene_movable_sm_item_priv() { @@ -46,6 +49,8 @@ struct Scene_movable_sm_item_priv mutable QOpenGLShaderProgram *program; mutable std::vector flat_normals; mutable std::vector flat_vertices; + mutable std::vector edges_vertices; + }; Scene_movable_sm_item::Scene_movable_sm_item(const CGAL::qglviewer::Vec& pos, SMesh* sm, @@ -59,10 +64,14 @@ void Scene_movable_sm_item_priv::initialize_buffers(CGAL::Three::Viewer_interfac { item->getTriangleContainer(0)->initializeBuffers(viewer); item->getTriangleContainer(0)->setFlatDataSize(flat_vertices.size()); + item->getEdgeContainer(0)->initializeBuffers(viewer); + item->getEdgeContainer(0)->setFlatDataSize(edges_vertices.size()); flat_vertices.resize(0); flat_normals .resize(0); + edges_vertices.resize(0); flat_vertices.shrink_to_fit(); flat_normals.shrink_to_fit(); + edges_vertices.shrink_to_fit(); item->are_buffers_filled = true; } @@ -82,9 +91,12 @@ void Scene_movable_sm_item_priv::compute_elements() const facegraph->points(); typedef boost::graph_traits::face_descriptor face_descriptor; typedef boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef boost::graph_traits::edge_descriptor edge_descriptor; typedef CGAL::Buffer_for_vao CPF; flat_vertices.clear(); flat_normals.clear(); + edges_vertices.clear(); + //faces BOOST_FOREACH(face_descriptor fd, faces(*facegraph)) { BOOST_FOREACH(halfedge_descriptor hd, halfedges_around_face(halfedge(fd, *facegraph),*facegraph)) @@ -98,12 +110,29 @@ void Scene_movable_sm_item_priv::compute_elements() const CPF::add_normal_in_buffer(n, flat_normals); } } + //edges + BOOST_FOREACH(edge_descriptor ed, edges(*facegraph)) + { + Point p = positions[source(ed, *facegraph)] + offset; + EPICK::Point_3 pc(p.x() - center_.x, + p.y() - center_.y, + p.z() - center_.z); + CPF::add_point_in_buffer(pc, edges_vertices); + p = positions[target(ed, *facegraph)] + offset; + pc=EPICK::Point_3(p.x() - center_.x, + p.y() - center_.y, + p.z() - center_.z); + CPF::add_point_in_buffer(pc, edges_vertices); + } + item->getTriangleContainer(0)->allocate(Tri::Flat_vertices, flat_vertices.data(), static_cast(flat_vertices.size()*sizeof(float))); item->getTriangleContainer(0)->allocate(Tri::Flat_normals, flat_normals.data(), static_cast(flat_normals.size()*sizeof(float))); + item->getEdgeContainer(0)->allocate(Tri::Flat_vertices, edges_vertices.data(), + static_cast(edges_vertices.size()*sizeof(float))); QApplication::restoreOverrideCursor(); } @@ -124,6 +153,18 @@ void Scene_movable_sm_item::draw(CGAL::Three::Viewer_interface* viewer) const getTriangleContainer(0)->draw(viewer, true); } +void Scene_movable_sm_item::drawEdges(CGAL::Three::Viewer_interface* viewer) const +{ + if(!isInit() && viewer->context()->isValid()) + initGL(); + if(!are_buffers_filled) + d->initialize_buffers(viewer); + getEdgeContainer(0)->setColor(Qt::black); + getEdgeContainer(0)->setFrameMatrix(d->f_matrix); + + getEdgeContainer(0)->draw(viewer, true); +} + QString Scene_movable_sm_item::toolTip() const { return QObject::tr("

Manipulatable representation of %1

" "

Keep Ctrl pressed and use the arcball to define an affine transformation.
") diff --git a/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.h b/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.h index 1b223d81946..7c2db949c32 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.h +++ b/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.h @@ -34,12 +34,14 @@ public: Scene_item* clone() const{return NULL;} QString toolTip() const; void draw(CGAL::Three::Viewer_interface *) const; + void drawEdges(CGAL::Three::Viewer_interface *) const; void compute_bbox() const; ~Scene_movable_sm_item(); bool manipulatable() const { return true;} ManipulatedFrame* manipulatedFrame(); const CGAL::qglviewer::Vec& center() const; - virtual bool supportsRenderingMode(RenderingMode m) const { return m==Flat ; } + virtual bool supportsRenderingMode(RenderingMode m) const { return m==Flat + || m==Wireframe; } virtual void invalidateOpenGLBuffers(); void setFMatrix(const GLdouble matrix[16]); void computeElements() const; From 0cedb5f0b6719780283d2ea049fcce46af67e091 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 24 Jul 2018 12:16:10 +0200 Subject: [PATCH 17/84] Selected_item has color, other one is wireframe. --- .../AABB_tree/Do_trees_intersect_plugin.cpp | 85 +++++++++++-------- 1 file changed, 48 insertions(+), 37 deletions(-) diff --git a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp index e708ba8b984..33df247a9b2 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp @@ -18,6 +18,7 @@ #include #include #include +#include "Scene.h" typedef CGAL::AABB_face_graph_triangle_primitive Primitive; typedef CGAL::AABB_traits AABB_triangle_traits; @@ -60,8 +61,6 @@ public: this, SLOT(start())); _actions << actionCreateTrees; } - t1 = 0; - t2 = 0; query_item = 0; base_item = 0; } @@ -74,32 +73,22 @@ private Q_SLOTS: Scene_surface_mesh_item* itemA = qobject_cast(scene->item(indexA)); Scene_surface_mesh_item* itemB = qobject_cast(scene->item(indexB)); connect(itemA, &Scene_surface_mesh_item::aboutToBeDestroyed, - [this](){ - if(query_item) - scene->erase(scene->item_id(query_item)); - cleanup(); - }); + this, &DoTreesIntersectplugin::cleanup); connect(itemB, &Scene_surface_mesh_item::aboutToBeDestroyed, - [this](){ - if(query_item) - scene->erase(scene->item_id(query_item)); - cleanup(); - }); + this, &DoTreesIntersectplugin::cleanup); SMesh* tm = itemA->face_graph(); SMesh* tm2 = itemB->face_graph(); - t1 = new Tree (tm->faces_begin(), tm->faces_end(), *tm); - t2 = new Tree (tm2->faces_begin(), tm2->faces_end(), *tm2); + trees[tm] = new Tree (tm->faces_begin(), tm->faces_end(), *tm); + trees[tm2] = new Tree (tm2->faces_begin(), tm2->faces_end(), *tm2); CGAL::qglviewer::Vec pos((itemB->bbox().min(0) + itemB->bbox().max(0))/2.0, (itemB->bbox().min(1) + itemB->bbox().max(1))/2.0, (itemB->bbox().min(2) + itemB->bbox().max(2))/2.0); query_item = new Scene_movable_sm_item(pos,tm2,""); - connect(query_item, &Scene_surface_mesh_item::aboutToBeDestroyed, - [this](){ - cleanup(); - }); + connect(query_item, &Scene_movable_sm_item::aboutToBeDestroyed, + this, &DoTreesIntersectplugin::cleanup); connect(query_item->manipulatedFrame(), &CGAL::qglviewer::ManipulatedFrame::modified, this, &DoTreesIntersectplugin::update_trees); query_item->setRenderingMode(Flat); @@ -107,11 +96,13 @@ private Q_SLOTS: itemB->setVisible(false); itemA->setVisible(false); scene->setSelectedItem(scene->addItem(query_item)); + pos = CGAL::qglviewer::Vec((itemA->bbox().min(0) + itemA->bbox().max(0))/2.0, + (itemA->bbox().min(1) + itemA->bbox().max(1))/2.0, + (itemA->bbox().min(2) + itemA->bbox().max(2))/2.0); + base_item = new Scene_movable_sm_item(pos,tm,""); - connect(base_item, &Scene_surface_mesh_item::aboutToBeDestroyed, - [this](){ - cleanup(); - }); + connect(base_item, &Scene_movable_sm_item::aboutToBeDestroyed, + this, &DoTreesIntersectplugin::cleanup); connect(base_item->manipulatedFrame(), &CGAL::qglviewer::ManipulatedFrame::modified, this, &DoTreesIntersectplugin::update_trees); base_item->setRenderingMode(Wireframe); @@ -120,6 +111,9 @@ private Q_SLOTS: update_trees(); query_item->redraw(); base_item->redraw(); + + connect(static_cast(scene), &Scene::itemIndexSelected, + this, &DoTreesIntersectplugin::update_trees); QApplication::restoreOverrideCursor(); } public Q_SLOTS: @@ -128,6 +122,13 @@ public Q_SLOTS: CGAL::Three::Viewer_interface* viewer = static_cast( CGAL::QGLViewer::QGLViewerPool().first()); + Scene_movable_sm_item* sel_item = qobject_cast(scene->item(scene->mainSelectionIndex())); + if(!sel_item) + return; + Scene_movable_sm_item* other_item = (base_item == sel_item) + ? query_item + : base_item; + const double* matrixB = base_item->manipulatedFrame()->matrix(); base_item->setFMatrix(matrixB); EPICK::Aff_transformation_3 translationB(CGAL::TRANSLATION, -EPICK::Vector_3(base_item->center().x, @@ -139,7 +140,7 @@ public Q_SLOTS: matrixB[2], matrixB[6], matrixB[10],matrixB[14]); EPICK::Aff_transformation_3 transfoB = rotaB*translationB; - t1->traits().set_transformation(transfoB); + trees[base_item->getFaceGraph()]->traits().set_transformation(transfoB); const double* matrixA = query_item->manipulatedFrame()->matrix(); query_item->setFMatrix(matrixA); @@ -152,9 +153,10 @@ public Q_SLOTS: matrixA[2], matrixA[6], matrixA[10],matrixA[14]); EPICK::Aff_transformation_3 transfoA = rotaA*translationA; - t2->traits().set_transformation(transfoA); - if(t2->do_intersect(*t1)) - query_item->setColor(QColor(Qt::red)); + trees[query_item->getFaceGraph()]->traits().set_transformation(transfoA); + + if(trees[sel_item->getFaceGraph()]->do_intersect(*trees[other_item->getFaceGraph()])) + sel_item->setColor(QColor(Qt::red)); else { #if 0 @@ -174,26 +176,35 @@ public Q_SLOTS: query_item->setColor(QColor(Qt::blue)); else #endif - query_item->setColor(QColor(Qt::green)); + sel_item->setColor(QColor(Qt::green)); #if 0 } #endif } - + sel_item->setRenderingMode(Flat); + other_item->setRenderingMode(Wireframe); + sel_item->itemChanged(); + other_item->itemChanged(); viewer->update(); } void cleanup() { - if(t1) - delete t1; - t1 = NULL; - if(t2) - delete t2; - t2 = NULL; - query_item = NULL; - base_item = NULL; + if(query_item) + { + delete trees[query_item->getFaceGraph()]; + trees[query_item->getFaceGraph()] = NULL; + scene->erase(scene->item_id(query_item)); + query_item = NULL; + } + if(base_item) + { + delete trees[base_item->getFaceGraph()]; + trees[base_item->getFaceGraph()] = NULL; + scene->erase(scene->item_id(base_item)); + base_item = NULL; + } } private: @@ -201,7 +212,7 @@ private: Messages_interface* messageInterface; CGAL::Three::Scene_interface* scene; QMainWindow* mw; - Tree *t1, *t2; + std::map trees; Scene_movable_sm_item* query_item; Scene_movable_sm_item* base_item; }; From bdb4ddeada4aeb1af189b497feaa0925b08e6851 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 24 Jul 2018 17:57:46 +0200 Subject: [PATCH 18/84] hide direct usage of bounding boxes behind free functions --- .../Point_inside_vertical_ray_cast.h | 19 +++++++++++++++++-- .../Ray_3_Triangle_3_traversal_traits.h | 3 +-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Side_of_triangle_mesh/Point_inside_vertical_ray_cast.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Side_of_triangle_mesh/Point_inside_vertical_ray_cast.h index 5ce1ae97897..b3d45194891 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Side_of_triangle_mesh/Point_inside_vertical_ray_cast.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Side_of_triangle_mesh/Point_inside_vertical_ray_cast.h @@ -36,6 +36,21 @@ namespace CGAL { namespace internal { +// added for AABB_do_intersect_transform_traits +template +typename AABBTree::Bounding_box +get_tree_bbox(const AABBTree& tree) +{ + return tree.bbox(); +} + +template +typename AABBNode::Bounding_box +get_node_bbox(const AABBNode& node, const AABBTraits&) +{ + return node.bbox(); +} + // internal class for point inside test, using existing AABB tree template class Point_inside_vertical_ray_cast @@ -53,7 +68,7 @@ public: typename Kernel::Construct_ray_3 ray_functor = Kernel().construct_ray_3_object(), typename Kernel::Construct_vector_3 vector_functor = Kernel().construct_vector_3_object() ) const { - const typename Traits::Bounding_box& bbox = tree.bbox(); + typename Traits::Bounding_box bbox = get_tree_bbox(tree); if( point.x() < bbox.xmin() || point.x() > bbox.xmax() || point.y() < bbox.ymin() || point.y() > bbox.ymax() @@ -64,7 +79,7 @@ public: //the direction of the vertical ray depends on the position of the point in the bbox //in order to limit the expected number of nodes visited. - Ray query = ray_functor(point, vector_functor(0,0,(2*point.z() < tree.bbox().zmax()+tree.bbox().zmin()?-1:1))); + Ray query = ray_functor(point, vector_functor(0,0,(2*point.z() < bbox.zmax()+bbox.zmin()?-1:1))); boost::optional res = is_inside_ray_tree_traversal(query, tree); if(res == boost::none) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Side_of_triangle_mesh/Ray_3_Triangle_3_traversal_traits.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Side_of_triangle_mesh/Ray_3_Triangle_3_traversal_traits.h index 9df35906309..bbd3eda72cc 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Side_of_triangle_mesh/Ray_3_Triangle_3_traversal_traits.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Side_of_triangle_mesh/Ray_3_Triangle_3_traversal_traits.h @@ -122,7 +122,7 @@ public: template bool do_intersect(const Query& query, const Node& node) const { - return do_intersect(query,node.bbox()); + return do_intersect(query,get_node_bbox(node, this->m_aabb_traits)); } private: @@ -155,7 +155,6 @@ public: if (orient_2==COLLINEAR){ //in that case the projection of the triangle along the z-axis is a segment. const typename Kernel::Point_2& other_point = p0!=p1?p1:p2; - //~ if ( orientation(p0,other_point,q) != COLLINEAR ) return;///no intersection if ( orientation(p0,other_point,q) != COLLINEAR ) return;///no intersection //check if the ray source is above or below the triangle and compare it From 8486cff63311a16b716f43b942175e01394fde12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 24 Jul 2018 18:02:03 +0200 Subject: [PATCH 19/84] add an extra flag to force the evaluation of the transformation --- .../AABB_tree/Do_trees_intersect_plugin.cpp | 25 ++-- .../CGAL/AABB_do_intersect_transform_traits.h | 122 +++++++++++++----- 2 files changed, 99 insertions(+), 48 deletions(-) diff --git a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp index 33df247a9b2..57484c523f0 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp @@ -154,33 +154,26 @@ public Q_SLOTS: EPICK::Aff_transformation_3 transfoA = rotaA*translationA; trees[query_item->getFaceGraph()]->traits().set_transformation(transfoA); - + if(trees[sel_item->getFaceGraph()]->do_intersect(*trees[other_item->getFaceGraph()])) sel_item->setColor(QColor(Qt::red)); else { -#if 0 - typedef boost::property_map::type VPM; - VPM vpm2 = get(CGAL::vertex_point, *query_item->getFaceGraph()); - CGAL::Side_of_triangle_mesh sotm1(*t1); - if(sotm1((transfoA).transform(vpm2[*query_item->getFaceGraph()->vertices().begin()])) != CGAL::ON_UNBOUNDED_SIDE) + CGAL::Side_of_triangle_mesh side_of_base(*trees[base_item->getFaceGraph()] ); + EPICK::Point_3 query_pt = get(boost::vertex_point, *query_item->getFaceGraph(), *query_item->getFaceGraph()->vertices().begin()); + if(side_of_base(transfoA.transform( query_pt )) != CGAL::ON_UNBOUNDED_SIDE) { - query_item->setColor(QColor(Qt::blue)); + sel_item->setColor(QColor(Qt::blue)); } else { - CGAL::Side_of_triangle_mesh sotm2(*t2); - if(sotm2(base_item->face_graph()->point(*base_item->face_graph()->vertices().begin())) != CGAL::ON_UNBOUNDED_SIDE) - query_item->setColor(QColor(Qt::blue)); + CGAL::Side_of_triangle_mesh side_of_query(*trees[query_item->getFaceGraph()]); + query_pt = get(boost::vertex_point, *base_item->getFaceGraph(), *base_item->getFaceGraph()->vertices().begin()); + if(side_of_query(transfoB.transform(query_pt)) != CGAL::ON_UNBOUNDED_SIDE) + sel_item->setColor(QColor(Qt::blue)); else -#endif sel_item->setColor(QColor(Qt::green)); - #if 0 } -#endif - } sel_item->setRenderingMode(Flat); other_item->setRenderingMode(Wireframe); diff --git a/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h b/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h index 56d9da8809e..9776eb56596 100644 --- a/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h +++ b/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h @@ -26,10 +26,7 @@ #include -#include - #include -#include #include #include #include @@ -38,8 +35,7 @@ #include #include -#include -#include +#include /// \file AABB_do_intersect_transform_traits.h @@ -49,6 +45,9 @@ namespace CGAL { template< typename AABBTraits> class AABB_tree; +template< typename AABBTraits> +class AABB_node; + namespace internal_AABB { template @@ -57,11 +56,10 @@ struct Transformed_datum_do_intersect_impl typedef bool result_type; template bool operator()(const Query& q, - const CGAL::Aff_transformation_3& transfo, + const CGAL::Aff_transformation_3&, // transformation is not used thanks to specialization of Primitive_helper const Datum_t& pr) const { - return Kernel().do_intersect_3_object()(q, - pr.transform(transfo)); + return Kernel().do_intersect_3_object()(q,pr); } }; @@ -104,54 +102,71 @@ struct Transformed_datum_do_intersect }//end internal template + typename Kernel, + typename Apply_transformation_to_primitive = Tag_true> class AABB_do_intersect_transform_traits: public BaseTraits { mutable Aff_transformation_3 m_transfo; + typedef AABB_do_intersect_transform_traits Self; public: //Constructor AABB_do_intersect_transform_traits(const Aff_transformation_3& transf = Aff_transformation_3(IDENTITY)) :m_transfo(transf) {} + // AABBTraits concept types typedef typename BaseTraits::Point_3 Point_3; typedef typename BaseTraits::Primitive Primitive; typedef typename BaseTraits::Bounding_box Bounding_box; - //Intersections - class Do_intersect + + // helper functions + Bbox_3 + static compute_transformed_bbox(const Bbox_3& bbox, const Aff_transformation_3& transfo) { // TODO: possible optimization using Protector typedef Simple_cartesian > Approximate_kernel; typedef Cartesian_converter C2F; + C2F c2f; + Approximate_kernel::Aff_transformation_3 af = c2f(transfo); - const AABB_do_intersect_transform_traits& m_traits; - C2F m_c2f; + //TODO reuse the conversions + typename Approximate_kernel::Point_3 ps[8]; + ps[0] = af( c2f( Point_3(bbox.min(0), bbox.min(1), bbox.min(2)) ) ); + ps[1] = af( c2f( Point_3(bbox.min(0), bbox.min(1), bbox.max(2)) ) ); + ps[2] = af( c2f( Point_3(bbox.min(0), bbox.max(1), bbox.min(2)) ) ); + ps[3] = af( c2f( Point_3(bbox.min(0), bbox.max(1), bbox.max(2)) ) ); + + ps[4] = af( c2f( Point_3(bbox.max(0), bbox.min(1), bbox.min(2)) ) ); + ps[5] = af( c2f( Point_3(bbox.max(0), bbox.min(1), bbox.max(2)) ) ); + ps[6] = af( c2f( Point_3(bbox.max(0), bbox.max(1), bbox.min(2)) ) ); + ps[7] = af( c2f( Point_3(bbox.max(0), bbox.max(1), bbox.max(2)) ) ); + + return bbox_3(ps, ps+8); + } + + Bbox_3 + compute_transformed_bbox(const Bbox_3& bbox) const + { + return compute_transformed_bbox(bbox, m_transfo); + } + + // Do_intersect predicate + class Do_intersect + { + typedef AABB_do_intersect_transform_traits AABBTraits; + const AABBTraits& m_traits; Bounding_box compute_transformed_bbox(const Bounding_box& bbox) const { - Approximate_kernel::Aff_transformation_3 af = m_c2f( m_traits.transformation() ); - - //TODO reuse the conversions - typename Approximate_kernel::Point_3 ps[8]; - ps[0] = af( m_c2f( Point_3(bbox.min(0), bbox.min(1), bbox.min(2)) ) ); - ps[1] = af( m_c2f( Point_3(bbox.min(0), bbox.min(1), bbox.max(2)) ) ); - ps[2] = af( m_c2f( Point_3(bbox.min(0), bbox.max(1), bbox.min(2)) ) ); - ps[3] = af( m_c2f( Point_3(bbox.min(0), bbox.max(1), bbox.max(2)) ) ); - - ps[4] = af( m_c2f( Point_3(bbox.max(0), bbox.min(1), bbox.min(2)) ) ); - ps[5] = af( m_c2f( Point_3(bbox.max(0), bbox.min(1), bbox.max(2)) ) ); - ps[6] = af( m_c2f( Point_3(bbox.max(0), bbox.max(1), bbox.min(2)) ) ); - ps[7] = af( m_c2f( Point_3(bbox.max(0), bbox.max(1), bbox.max(2)) ) ); - - return bbox_3(ps, ps+8); + return m_traits.compute_transformed_bbox(bbox); } public: - Do_intersect(const AABB_do_intersect_transform_traits& traits) + Do_intersect(const AABBTraits& traits) :m_traits(traits) {} @@ -165,15 +180,20 @@ public: template bool operator()(const Query& q, const Primitive& pr) const { - internal_AABB::Transformed_datum_do_intersect f; - return f(q, m_traits.transformation(), internal::Primitive_helper::get_datum(pr,m_traits)); + internal_AABB::Transformed_datum_do_intersect::type > f; + return f(q, m_traits.transformation(), internal::Primitive_helper::get_datum(pr,m_traits)); } // intersection with AABB-tree template bool operator()(const CGAL::AABB_tree& other_tree, const Primitive& pr) const { - return other_tree.do_intersect( internal::Primitive_helper::get_datum(pr,m_traits).transform(m_traits.transformation())); + if (Apply_transformation_to_primitive::value) + return other_tree.do_intersect( internal::Primitive_helper::get_datum(pr,m_traits)); + else + // WARNING this is not robust + return other_tree.do_intersect( internal::Primitive_helper::get_datum(pr,m_traits).transform(m_traits.transformation())); } template @@ -194,7 +214,45 @@ public: } const Aff_transformation_3& transformation() const { return m_transfo; } +}; + +namespace internal { + +template +struct Primitive_helper ,true>{ + +typedef AABB_do_intersect_transform_traits Traits; + + +static typename Traits::Primitive::Datum get_datum(const typename Traits::Primitive& p, + const Traits & traits) +{ + return p.datum(traits.shared_data()).transform(traits.transformation()); +} + +static typename Traits::Point_3 get_reference_point(const typename Traits::Primitive& p,const Traits& traits) { + return p.reference_point(traits.shared_data()).transform(traits.transformation()); +} }; + +template +typename CGAL::AABB_tree >::Bounding_box +get_tree_bbox(const CGAL::AABB_tree >& tree) +{ + return tree.traits().compute_transformed_bbox(tree.bbox()); +} + +template +typename CGAL::AABB_tree >::Bounding_box +get_node_bbox(const CGAL::AABB_node >& node, + const AABB_do_intersect_transform_traits& traits) +{ + return traits.compute_transformed_bbox(node.bbox()); +} + +} // end internal + }//end CGAL + #endif //CGAL_AABB_AABB_do_intersect_transform_traits_H From caa5135c18a5be343e9c102d162f8932130e2ef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 24 Jul 2018 18:20:48 +0200 Subject: [PATCH 20/84] simplify traits and always use transformed primitives --- .../AABB_tree/Do_trees_intersect_plugin.cpp | 3 +- .../CGAL/AABB_do_intersect_transform_traits.h | 113 ++++-------------- 2 files changed, 27 insertions(+), 89 deletions(-) diff --git a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp index 57484c523f0..f098da82eac 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp @@ -21,8 +21,7 @@ #include "Scene.h" typedef CGAL::AABB_face_graph_triangle_primitive Primitive; -typedef CGAL::AABB_traits AABB_triangle_traits; -typedef CGAL::AABB_do_intersect_transform_traits Traits; +typedef CGAL::AABB_do_intersect_transform_traits Traits; typedef CGAL::AABB_tree Tree; class DoTreesIntersectplugin : diff --git a/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h b/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h index 9776eb56596..a3758c3b9df 100644 --- a/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h +++ b/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h @@ -39,76 +39,15 @@ /// \file AABB_do_intersect_transform_traits.h -//! \todo add protector namespace CGAL { -// forward declaration -template< typename AABBTraits> -class AABB_tree; -template< typename AABBTraits> -class AABB_node; - -namespace internal_AABB -{ -template -struct Transformed_datum_do_intersect_impl -{ - typedef bool result_type; - template - bool operator()(const Query& q, - const CGAL::Aff_transformation_3&, // transformation is not used thanks to specialization of Primitive_helper - const Datum_t& pr) const - { - return Kernel().do_intersect_3_object()(q,pr); - } -}; - -template -struct Transformed_datum_do_intersect -{ - template - bool operator()(const Query& q, - const CGAL::Aff_transformation_3& transfo, - const Datum_t& pr) const - { - return Transformed_datum_do_intersect_impl()(q,transfo,pr); - } -}; - -template -struct Transformed_datum_do_intersect -{ - template - bool operator()(const Query& q, - const CGAL::Aff_transformation_3& transfo, - const Datum_t& pr) const - { - typedef typename Kernel::Approximate_kernel FK; - typedef typename Kernel::Exact_kernel EK; - typedef typename Kernel::C2F C2F; - typedef typename Kernel::C2E C2E; - - // filtered predicate - CGAL::Filtered_predicate< - internal_AABB::Transformed_datum_do_intersect_impl, - internal_AABB::Transformed_datum_do_intersect_impl, - C2E, - C2F > filtered_do_intersect; - - return filtered_do_intersect(q, transfo, pr); - } -}; - -}//end internal -template +template class AABB_do_intersect_transform_traits: - public BaseTraits + public AABB_traits { mutable Aff_transformation_3 m_transfo; - typedef AABB_do_intersect_transform_traits Self; + typedef AABB_traits BaseTraits; + typedef AABB_do_intersect_transform_traits Self; public: //Constructor @@ -155,9 +94,11 @@ public: // Do_intersect predicate class Do_intersect + : BaseTraits::Do_intersect { - typedef AABB_do_intersect_transform_traits AABBTraits; + typedef AABB_do_intersect_transform_traits AABBTraits; const AABBTraits& m_traits; + typedef typename BaseTraits::Do_intersect Base; Bounding_box compute_transformed_bbox(const Bounding_box& bbox) const @@ -167,33 +108,31 @@ public: public: Do_intersect(const AABBTraits& traits) - :m_traits(traits) + : Base(static_cast(traits)), + m_traits(traits) {} template bool operator()(const Query& q, const Bounding_box& bbox) const { - // TODO use base_traits - return CGAL::do_intersect(q, compute_transformed_bbox(bbox)); + return + static_cast(this)->operator()( + q, compute_transformed_bbox(bbox)); } template bool operator()(const Query& q, const Primitive& pr) const { - internal_AABB::Transformed_datum_do_intersect::type > f; - return f(q, m_traits.transformation(), internal::Primitive_helper::get_datum(pr,m_traits)); + // transformation is done within Primitive_helper + return do_intersect(q, internal::Primitive_helper::get_datum(pr,m_traits)); } // intersection with AABB-tree template bool operator()(const CGAL::AABB_tree& other_tree, const Primitive& pr) const { - if (Apply_transformation_to_primitive::value) - return other_tree.do_intersect( internal::Primitive_helper::get_datum(pr,m_traits)); - else - // WARNING this is not robust - return other_tree.do_intersect( internal::Primitive_helper::get_datum(pr,m_traits).transform(m_traits.transformation())); + // transformation is done within Primitive_helper + return other_tree.do_intersect( internal::Primitive_helper::get_datum(pr,m_traits)); } template @@ -218,10 +157,10 @@ public: namespace internal { -template -struct Primitive_helper ,true>{ +template +struct Primitive_helper ,true>{ -typedef AABB_do_intersect_transform_traits Traits; +typedef AABB_do_intersect_transform_traits Traits; static typename Traits::Primitive::Datum get_datum(const typename Traits::Primitive& p, @@ -236,17 +175,17 @@ static typename Traits::Point_3 get_reference_point(const typename Traits::Primi }; -template -typename CGAL::AABB_tree >::Bounding_box -get_tree_bbox(const CGAL::AABB_tree >& tree) +template +typename CGAL::AABB_tree >::Bounding_box +get_tree_bbox(const CGAL::AABB_tree >& tree) { return tree.traits().compute_transformed_bbox(tree.bbox()); } -template -typename CGAL::AABB_tree >::Bounding_box -get_node_bbox(const CGAL::AABB_node >& node, - const AABB_do_intersect_transform_traits& traits) +template +typename CGAL::AABB_tree >::Bounding_box +get_node_bbox(const CGAL::AABB_node >& node, + const AABB_do_intersect_transform_traits& traits) { return traits.compute_transformed_bbox(node.bbox()); } From c32820fe8b8e7a98c4bc1ea12c7ba80fbed165ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 24 Jul 2018 18:26:40 +0200 Subject: [PATCH 21/84] reuse conversions --- .../CGAL/AABB_do_intersect_transform_traits.h | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h b/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h index a3758c3b9df..5f86b2aeb6f 100644 --- a/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h +++ b/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h @@ -65,23 +65,26 @@ public: static compute_transformed_bbox(const Bbox_3& bbox, const Aff_transformation_3& transfo) { // TODO: possible optimization using Protector - typedef Simple_cartesian > Approximate_kernel; - typedef Cartesian_converter C2F; + typedef Simple_cartesian > AK; + typedef Cartesian_converter C2F; C2F c2f; - Approximate_kernel::Aff_transformation_3 af = c2f(transfo); + AK::Aff_transformation_3 af = c2f(transfo); - //TODO reuse the conversions - typename Approximate_kernel::Point_3 ps[8]; - ps[0] = af( c2f( Point_3(bbox.min(0), bbox.min(1), bbox.min(2)) ) ); - ps[1] = af( c2f( Point_3(bbox.min(0), bbox.min(1), bbox.max(2)) ) ); - ps[2] = af( c2f( Point_3(bbox.min(0), bbox.max(1), bbox.min(2)) ) ); - ps[3] = af( c2f( Point_3(bbox.min(0), bbox.max(1), bbox.max(2)) ) ); + AK::FT xtrm[6] = { c2f(bbox.min(0)), c2f(bbox.max(0)), + c2f(bbox.min(1)), c2f(bbox.max(1)), + c2f(bbox.min(2)), c2f(bbox.max(2)) }; - ps[4] = af( c2f( Point_3(bbox.max(0), bbox.min(1), bbox.min(2)) ) ); - ps[5] = af( c2f( Point_3(bbox.max(0), bbox.min(1), bbox.max(2)) ) ); - ps[6] = af( c2f( Point_3(bbox.max(0), bbox.max(1), bbox.min(2)) ) ); - ps[7] = af( c2f( Point_3(bbox.max(0), bbox.max(1), bbox.max(2)) ) ); + typename AK::Point_3 ps[8]; + ps[0] = af( AK::Point_3(xtrm[0], xtrm[2], xtrm[4]) ); + ps[1] = af( AK::Point_3(xtrm[0], xtrm[2], xtrm[5]) ); + ps[2] = af( AK::Point_3(xtrm[0], xtrm[3], xtrm[4]) ); + ps[3] = af( AK::Point_3(xtrm[0], xtrm[3], xtrm[5]) ); + + ps[4] = af( AK::Point_3(xtrm[1], xtrm[2], xtrm[4]) ); + ps[5] = af( AK::Point_3(xtrm[1], xtrm[2], xtrm[5]) ); + ps[6] = af( AK::Point_3(xtrm[1], xtrm[3], xtrm[4]) ); + ps[7] = af( AK::Point_3(xtrm[1], xtrm[3], xtrm[5]) ); return bbox_3(ps, ps+8); } From e179770aaba4a2f283434bdaee2369f2bf696f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 24 Jul 2018 18:58:12 +0200 Subject: [PATCH 22/84] add skeleton for collision detection in PMP --- .../include/CGAL/license/GraphicsView.h | 2 +- .../collision_detection.h | 67 ++++++++++ Installation/include/CGAL/license/README.md | 2 +- .../include/CGAL/license/gpl_package_list.txt | 1 + .../CGAL/Rigid_mesh_collision_detection.h | 126 ++++++++++++++++++ 5 files changed, 196 insertions(+), 2 deletions(-) create mode 100644 Installation/include/CGAL/license/Polygon_mesh_processing/collision_detection.h create mode 100644 Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h diff --git a/Installation/include/CGAL/license/GraphicsView.h b/Installation/include/CGAL/license/GraphicsView.h index 270df8f74ad..beeac0d78bc 100644 --- a/Installation/include/CGAL/license/GraphicsView.h +++ b/Installation/include/CGAL/license/GraphicsView.h @@ -14,7 +14,7 @@ // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: LGPL-3.0+ // // Author(s) : Andreas Fabri // diff --git a/Installation/include/CGAL/license/Polygon_mesh_processing/collision_detection.h b/Installation/include/CGAL/license/Polygon_mesh_processing/collision_detection.h new file mode 100644 index 00000000000..db5f1b29126 --- /dev/null +++ b/Installation/include/CGAL/license/Polygon_mesh_processing/collision_detection.h @@ -0,0 +1,67 @@ +// Copyright (c) 2016 GeometryFactory SARL (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$ +// SPDX-License-Identifier: LGPL-3.0+ +// +// Author(s) : Andreas Fabri +// +// Warning: this file is generated, see include/CGAL/licence/README.md + + +#ifndef CGAL_LICENSE_POLYGON_MESH_PROCESSING_COLLISION_DETECTION_H +#define CGAL_LICENSE_POLYGON_MESH_PROCESSING_COLLISION_DETECTION_H + +#include +#include + + + + +#ifdef CGAL_POLYGON_MESH_PROCESSING_COLLISION_DETECTION_COMMERCIAL_LICENSE + +# if CGAL_POLYGON_MESH_PROCESSING_COLLISION_DETECTION_COMMERCIAL_LICENSE < CGAL_RELEASE_DATE + +# if defined(CGAL_LICENSE_WARNING) + + CGAL_pragma_warning("Your commercial license for CGAL does not cover " + "this release of the Polygon Mesh Processing - Collision Detection package.") +# endif + +# ifdef CGAL_LICENSE_ERROR +# error "Your commercial license for CGAL does not cover this release \ +of the Polygon Mesh Processing - Collision Detection package. \ +You get this error, as you defined CGAL_LICENSE_ERROR." +# endif // CGAL_LICENSE_ERROR + +# endif // CGAL_POLYGON_MESH_PROCESSING_COLLISION_DETECTION_COMMERCIAL_LICENSE < CGAL_RELEASE_DATE + +#else // no CGAL_POLYGON_MESH_PROCESSING_COLLISION_DETECTION_COMMERCIAL_LICENSE + +# if defined(CGAL_LICENSE_WARNING) + CGAL_pragma_warning("\nThe macro CGAL_POLYGON_MESH_PROCESSING_COLLISION_DETECTION_COMMERCIAL_LICENSE is not defined." + "\nYou use the CGAL Polygon Mesh Processing - Collision Detection package under " + "the terms of the GPLv3+.") +# endif // CGAL_LICENSE_WARNING + +# ifdef CGAL_LICENSE_ERROR +# error "The macro CGAL_POLYGON_MESH_PROCESSING_COLLISION_DETECTION_COMMERCIAL_LICENSE is not defined.\ + You use the CGAL Polygon Mesh Processing - Collision Detection package under the terms of \ +the GPLv3+. You get this error, as you defined CGAL_LICENSE_ERROR." +# endif // CGAL_LICENSE_ERROR + +#endif // no CGAL_POLYGON_MESH_PROCESSING_COLLISION_DETECTION_COMMERCIAL_LICENSE + +#endif // CGAL_LICENSE_CHECK_POLYGON_MESH_PROCESSING_COLLISION_DETECTION_H diff --git a/Installation/include/CGAL/license/README.md b/Installation/include/CGAL/license/README.md index 5b8e4095532..d39cd5f9bfe 100644 --- a/Installation/include/CGAL/license/README.md +++ b/Installation/include/CGAL/license/README.md @@ -1,3 +1,3 @@ -To generate the `PACKAGE.h` files, from the file `package_list.txt`: +To generate the `PACKAGE.h` files, from the file `gpl_package_list.txt`: cmake -P generate_files.cmake diff --git a/Installation/include/CGAL/license/gpl_package_list.txt b/Installation/include/CGAL/license/gpl_package_list.txt index cb330d930ac..a97a73dc0aa 100644 --- a/Installation/include/CGAL/license/gpl_package_list.txt +++ b/Installation/include/CGAL/license/gpl_package_list.txt @@ -54,6 +54,7 @@ Polygon_mesh_processing/predicate Polygon Mesh Processing - Predicate Polygon_mesh_processing/repair Polygon Mesh Processing - Repair Polygon_mesh_processing/miscellaneous Polygon Mesh Processing - Miscellaneous Polygon_mesh_processing/detect_features Polygon Mesh Processing - Feature Detection +Polygon_mesh_processing/collision_detection Polygon Mesh Processing - Collision Detection Polyhedron 3D Polyhedral Surface Polyline_simplification_2 2D Polyline Simplification Polytope_distance_d Optimal Distances diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h new file mode 100644 index 00000000000..ace05c1de63 --- /dev/null +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -0,0 +1,126 @@ +// Copyright (c) 2018 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$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Maxime Gimeno and Sebastien Loriot + + +#ifndef CGAL_RIGID_MESH_COLLISION_DETECTION_H +#define CGAL_RIGID_MESH_COLLISION_DETECTION_H + +#include + +#include +#include +// TODO: move AABB_do_intersect_transform_traits.h in PMP/internal +#include +#include +#include + + +namespace CGAL { + +template +class Rigid_mesh_collision_detection +{ + typedef CGAL::AABB_face_graph_triangle_primitive Primitive; + typedef CGAL::AABB_do_intersect_transform_traits Traits; + typedef CGAL::AABB_tree Tree; + typedef Side_of_triangle_mesh Side_of_tm; + + + std::vector m_triangle_mesh_ptrs; + // TODO: we probably want an option with external trees + std::vector m_aabb_trees; + std::vector m_is_closed; + +public: + template + Rigid_mesh_collision_detection(const MeshRange& triangle_meshes) + { + init(triangle_meshes); + } + + template + void init(const MeshRange& triangle_meshes) + { + m_triangle_mesh_ptrs.reserve( triangle_meshes.size() ); + m_aabb_trees.reserve( m_triangle_mesh_ptrs.size() ); + m_is_closed.resize(m_triangle_mesh_ptrs.size(), false); + + BOOST_FOREACH(const TriangleMesh& tm, triangle_meshes) + { + if (is_closed(tm)) + m_is_closed[m_triangle_mesh_ptrs.size()]=true; + m_triangle_mesh_ptrs.push_back( &tm ); + m_aabb_trees.push_back( Tree(tm) ); + m_aabb_trees.back.insert(faces(tm).begin(), faces(tm).end(), tm); + } + } + + void set_transformation(std::size_t mesh_id, const Aff_transformation_3& aff_trans) + { + m_aabb_trees[mesh_id].traits().set_transformation(aff_trans); + } + + std::vector + set_transformation_and_all_intersections(std::size_t mesh_id, + const Aff_transformation_3& aff_trans, + bool report_volume_inclusion_as_intersection) + { + set_transformation(mesh_id, aff_trans); + std::vector res; + + // TODO: use a non-naive version + for(std::size_t k=0; k Date: Wed, 25 Jul 2018 11:56:00 +0200 Subject: [PATCH 23/84] Use Rigid_mesh_intersection and make it work for n items. --- .../AABB_tree/Do_trees_intersect_plugin.cpp | 241 ++++++++---------- .../AABB_tree/Scene_movable_sm_item.cpp | 2 +- .../CGAL/Rigid_mesh_collision_detection.h | 73 ++++-- 3 files changed, 159 insertions(+), 157 deletions(-) diff --git a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp index f098da82eac..f322e14fbab 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp @@ -9,21 +9,13 @@ #include #include "Scene_surface_mesh_item.h" #include "Scene_movable_sm_item.h" -#include -#include -#include -#include -#include #include #include #include #include +#include #include "Scene.h" -typedef CGAL::AABB_face_graph_triangle_primitive Primitive; -typedef CGAL::AABB_do_intersect_transform_traits Traits; -typedef CGAL::AABB_tree Tree; - class DoTreesIntersectplugin : public QObject, public CGAL::Three::Polyhedron_demo_plugin_interface @@ -35,12 +27,12 @@ public: bool applicable(QAction*) const Q_DECL_OVERRIDE { - const int indexA = scene->selectionAindex(); - const int indexB = scene->selectionBindex(); - return qobject_cast(scene->item(indexA)) - && qobject_cast(scene->item(indexB)) - && base_item == NULL - && query_item == NULL; + Q_FOREACH(Scene::Item_id i, scene->selectionIndices()) + { + if(! qobject_cast(scene->item(i))) + return false; + } + return items.empty(); } QList actions() const Q_DECL_OVERRIDE @@ -53,68 +45,54 @@ public: this->messageInterface = mi; this->scene = sc; this->mw = mw; - QAction *actionCreateTrees= new QAction(QString("Start Intersection Tests(A/B)"), mw); + QAction *actionCreateTrees= new QAction(QString("Start Intersection Tests"), mw); actionCreateTrees->setProperty("submenuName", "AABB_tree"); if(actionCreateTrees) { connect(actionCreateTrees, SIGNAL(triggered()), this, SLOT(start())); _actions << actionCreateTrees; } - query_item = 0; - base_item = 0; } private Q_SLOTS: void start() { QApplication::setOverrideCursor(Qt::WaitCursor); - const int indexA = scene->selectionAindex(); - const int indexB = scene->selectionBindex(); - Scene_surface_mesh_item* itemA = qobject_cast(scene->item(indexA)); - Scene_surface_mesh_item* itemB = qobject_cast(scene->item(indexB)); - connect(itemA, &Scene_surface_mesh_item::aboutToBeDestroyed, - this, &DoTreesIntersectplugin::cleanup); - connect(itemB, &Scene_surface_mesh_item::aboutToBeDestroyed, - this, &DoTreesIntersectplugin::cleanup); - - - SMesh* tm = itemA->face_graph(); - SMesh* tm2 = itemB->face_graph(); - trees[tm] = new Tree (tm->faces_begin(), tm->faces_end(), *tm); - trees[tm2] = new Tree (tm2->faces_begin(), tm2->faces_end(), *tm2); - CGAL::qglviewer::Vec pos((itemB->bbox().min(0) + itemB->bbox().max(0))/2.0, - (itemB->bbox().min(1) + itemB->bbox().max(1))/2.0, - (itemB->bbox().min(2) + itemB->bbox().max(2))/2.0); - - query_item = new Scene_movable_sm_item(pos,tm2,""); - connect(query_item, &Scene_movable_sm_item::aboutToBeDestroyed, - this, &DoTreesIntersectplugin::cleanup); - connect(query_item->manipulatedFrame(), &CGAL::qglviewer::ManipulatedFrame::modified, - this, &DoTreesIntersectplugin::update_trees); - query_item->setRenderingMode(Flat); - query_item->setName(itemB->name()); - itemB->setVisible(false); - itemA->setVisible(false); - scene->setSelectedItem(scene->addItem(query_item)); - pos = CGAL::qglviewer::Vec((itemA->bbox().min(0) + itemA->bbox().max(0))/2.0, - (itemA->bbox().min(1) + itemA->bbox().max(1))/2.0, - (itemA->bbox().min(2) + itemA->bbox().max(2))/2.0); - - base_item = new Scene_movable_sm_item(pos,tm,""); - connect(base_item, &Scene_movable_sm_item::aboutToBeDestroyed, - this, &DoTreesIntersectplugin::cleanup); - connect(base_item->manipulatedFrame(), &CGAL::qglviewer::ManipulatedFrame::modified, - this, &DoTreesIntersectplugin::update_trees); - base_item->setRenderingMode(Wireframe); - base_item->setName(itemA->name()); - scene->addItem(base_item); - update_trees(); - query_item->redraw(); - base_item->redraw(); - + Q_FOREACH(Scene::Item_id i, scene->selectionIndices()) + { + Scene_surface_mesh_item* item=qobject_cast(scene->item(i)); + connect(item, &Scene_surface_mesh_item::aboutToBeDestroyed, + this, &DoTreesIntersectplugin::cleanup); + + CGAL::qglviewer::Vec pos((item->bbox().min(0) + item->bbox().max(0))/2.0, + (item->bbox().min(1) + item->bbox().max(1))/2.0, + (item->bbox().min(2) + item->bbox().max(2))/2.0); + + Scene_movable_sm_item* mov_item = new Scene_movable_sm_item(pos,item->face_graph(),""); + connect(mov_item, &Scene_movable_sm_item::aboutToBeDestroyed, + this, &DoTreesIntersectplugin::cleanup); + connect(mov_item->manipulatedFrame(), &CGAL::qglviewer::ManipulatedFrame::modified, + this, &DoTreesIntersectplugin::update_trees); + mov_item->setName(item->name()); + mov_item->setRenderingMode(Wireframe); + item->setVisible(false); + items.push_back(mov_item); + scene->setSelectedItem(scene->addItem(mov_item)); + mov_item->redraw(); + } connect(static_cast(scene), &Scene::itemIndexSelected, this, &DoTreesIntersectplugin::update_trees); + Q_FOREACH(Scene_movable_sm_item* item, items) + { + meshes.push_back(*item->getFaceGraph()); + } + col_det = new CGAL::Rigid_mesh_collision_detection(meshes); + update_trees(); + items.back()->setRenderingMode(Wireframe); + QApplication::restoreOverrideCursor(); } + + public Q_SLOTS: void update_trees() { @@ -123,80 +101,85 @@ public Q_SLOTS: Scene_movable_sm_item* sel_item = qobject_cast(scene->item(scene->mainSelectionIndex())); if(!sel_item) - return; - Scene_movable_sm_item* other_item = (base_item == sel_item) - ? query_item - : base_item; - - const double* matrixB = base_item->manipulatedFrame()->matrix(); - base_item->setFMatrix(matrixB); - EPICK::Aff_transformation_3 translationB(CGAL::TRANSLATION, -EPICK::Vector_3(base_item->center().x, - base_item->center().y, - base_item->center().z)); - EPICK::Aff_transformation_3 rotaB( - matrixB[0], matrixB[4], matrixB[8],matrixB[12], - matrixB[1], matrixB[5], matrixB[9],matrixB[13], - matrixB[2], matrixB[6], matrixB[10],matrixB[14]); - EPICK::Aff_transformation_3 transfoB = - rotaB*translationB; - trees[base_item->getFaceGraph()]->traits().set_transformation(transfoB); - - const double* matrixA = query_item->manipulatedFrame()->matrix(); - query_item->setFMatrix(matrixA); - EPICK::Aff_transformation_3 translationA(CGAL::TRANSLATION, -EPICK::Vector_3(query_item->center().x, - query_item->center().y, - query_item->center().z)); - EPICK::Aff_transformation_3 rotaA( - matrixA[0], matrixA[4], matrixA[8],matrixA[12], - matrixA[1], matrixA[5], matrixA[9],matrixA[13], - matrixA[2], matrixA[6], matrixA[10],matrixA[14]); - EPICK::Aff_transformation_3 transfoA = - rotaA*translationA; - trees[query_item->getFaceGraph()]->traits().set_transformation(transfoA); - - if(trees[sel_item->getFaceGraph()]->do_intersect(*trees[other_item->getFaceGraph()])) - sel_item->setColor(QColor(Qt::red)); - else + return; + + std::size_t mesh_id = 0; + std::size_t sel_id = 0; + Q_FOREACH(Scene_movable_sm_item* item, items) { - CGAL::Side_of_triangle_mesh side_of_base(*trees[base_item->getFaceGraph()] ); - EPICK::Point_3 query_pt = get(boost::vertex_point, *query_item->getFaceGraph(), *query_item->getFaceGraph()->vertices().begin()); - if(side_of_base(transfoA.transform( query_pt )) != CGAL::ON_UNBOUNDED_SIDE) - { - sel_item->setColor(QColor(Qt::blue)); - } - else + if(item == sel_item) { - CGAL::Side_of_triangle_mesh side_of_query(*trees[query_item->getFaceGraph()]); - query_pt = get(boost::vertex_point, *base_item->getFaceGraph(), *base_item->getFaceGraph()->vertices().begin()); - if(side_of_query(transfoB.transform(query_pt)) != CGAL::ON_UNBOUNDED_SIDE) - sel_item->setColor(QColor(Qt::blue)); - else - sel_item->setColor(QColor(Qt::green)); + sel_id = mesh_id; + break; } + ++mesh_id; } - sel_item->setRenderingMode(Flat); - other_item->setRenderingMode(Wireframe); + mesh_id = 0; + Q_FOREACH(Scene_movable_sm_item* item, items) + { + if(mesh_id == sel_id) + { + ++mesh_id; + item->setColor(QColor(255,184,61)); + continue; + } + item->setColor(QColor(Qt::green)); + const double* matrix = item->manipulatedFrame()->matrix(); + item->setFMatrix(matrix); + EPICK::Aff_transformation_3 translation(CGAL::TRANSLATION, -EPICK::Vector_3(item->center().x, + item->center().y, + item->center().z)); + EPICK::Aff_transformation_3 rota( + matrix[0], matrix[4], matrix[8],matrix[12], + matrix[1], matrix[5], matrix[9],matrix[13], + matrix[2], matrix[6], matrix[10],matrix[14]); + EPICK::Aff_transformation_3 transfo = + rota*translation; + + col_det->set_transformation(mesh_id++, transfo); + + item->setRenderingMode(Wireframe); + item->itemChanged(); + } + const double* matrix = sel_item->manipulatedFrame()->matrix(); + sel_item->setFMatrix(matrix); + EPICK::Aff_transformation_3 translation(CGAL::TRANSLATION, -EPICK::Vector_3(sel_item->center().x, + sel_item->center().y, + sel_item->center().z)); + EPICK::Aff_transformation_3 rota( + matrix[0], matrix[4], matrix[8],matrix[12], + matrix[1], matrix[5], matrix[9],matrix[13], + matrix[2], matrix[6], matrix[10],matrix[14]); + EPICK::Aff_transformation_3 transfo = + rota*translation; + std::vector > inter_and_incl + = col_det-> + set_transformation_and_all_intersections_and_all_inclusions(sel_id, transfo); + for(std::size_t i=0; isetColor(QColor(Qt::blue)); + else + items[id]->setColor(QColor(Qt::red)); + } + sel_item->setRenderingMode(Wireframe); sel_item->itemChanged(); - other_item->itemChanged(); viewer->update(); } void cleanup() { - if(query_item) - { - delete trees[query_item->getFaceGraph()]; - trees[query_item->getFaceGraph()] = NULL; - scene->erase(scene->item_id(query_item)); - query_item = NULL; - } - if(base_item) - { - delete trees[base_item->getFaceGraph()]; - trees[base_item->getFaceGraph()] = NULL; - scene->erase(scene->item_id(base_item)); - base_item = NULL; - } + Q_FOREACH(Scene_movable_sm_item* item, items) + if(item) + { + scene->erase(scene->item_id(item)); + item = nullptr; + } + items.clear(); + delete col_det; + col_det = nullptr; } private: @@ -204,8 +187,8 @@ private: Messages_interface* messageInterface; CGAL::Three::Scene_interface* scene; QMainWindow* mw; - std::map trees; - Scene_movable_sm_item* query_item; - Scene_movable_sm_item* base_item; + CGAL::Rigid_mesh_collision_detection *col_det; + std::vector items; + std::vector meshes; }; #include "Do_trees_intersect_plugin.moc" diff --git a/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.cpp b/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.cpp index 0e03b99bb3a..f390983ecb1 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.cpp @@ -159,7 +159,7 @@ void Scene_movable_sm_item::drawEdges(CGAL::Three::Viewer_interface* viewer) con initGL(); if(!are_buffers_filled) d->initialize_buffers(viewer); - getEdgeContainer(0)->setColor(Qt::black); + getEdgeContainer(0)->setColor(color()); getEdgeContainer(0)->setFrameMatrix(d->f_matrix); getEdgeContainer(0)->draw(viewer, true); diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index ace05c1de63..41426f8fee2 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -46,7 +46,7 @@ class Rigid_mesh_collision_detection std::vector m_triangle_mesh_ptrs; // TODO: we probably want an option with external trees - std::vector m_aabb_trees; + std::vector m_aabb_trees; std::vector m_is_closed; public: @@ -55,33 +55,36 @@ public: { init(triangle_meshes); } - + ~Rigid_mesh_collision_detection() + { + BOOST_FOREACH(Tree* tree, m_aabb_trees){ + delete tree; + } + } template void init(const MeshRange& triangle_meshes) { m_triangle_mesh_ptrs.reserve( triangle_meshes.size() ); - m_aabb_trees.reserve( m_triangle_mesh_ptrs.size() ); - m_is_closed.resize(m_triangle_mesh_ptrs.size(), false); + m_aabb_trees.reserve( triangle_meshes.size() ); + m_is_closed.resize(triangle_meshes.size(), false); BOOST_FOREACH(const TriangleMesh& tm, triangle_meshes) { if (is_closed(tm)) m_is_closed[m_triangle_mesh_ptrs.size()]=true; m_triangle_mesh_ptrs.push_back( &tm ); - m_aabb_trees.push_back( Tree(tm) ); - m_aabb_trees.back.insert(faces(tm).begin(), faces(tm).end(), tm); + m_aabb_trees.push_back(new Tree(faces(tm).begin(), faces(tm).end(), tm)); } } void set_transformation(std::size_t mesh_id, const Aff_transformation_3& aff_trans) { - m_aabb_trees[mesh_id].traits().set_transformation(aff_trans); + m_aabb_trees[mesh_id]->traits().set_transformation(aff_trans); } std::vector set_transformation_and_all_intersections(std::size_t mesh_id, - const Aff_transformation_3& aff_trans, - bool report_volume_inclusion_as_intersection) + const Aff_transformation_3& aff_trans) { set_transformation(mesh_id, aff_trans); std::vector res; @@ -91,31 +94,47 @@ public: { if(k==mesh_id) continue; // TODO: think about an alternative that is using a traversal traits - if ( m_aabb_trees[k].do_intersect( m_aabb_trees[mesh_id] ) ) + if ( m_aabb_trees[k]->do_intersect( *m_aabb_trees[mesh_id] ) ) res.push_back(k); - else - { - if (report_volume_inclusion_as_intersection) + } + + return res; + } + + std::vector > + set_transformation_and_all_intersections_and_all_inclusions(std::size_t mesh_id, + const Aff_transformation_3& aff_trans) + { + set_transformation(mesh_id, aff_trans); + std::vector > res; + + // TODO: use a non-naive version + for(std::size_t k=0; kdo_intersect( *m_aabb_trees[mesh_id] ) ) + res.push_back(std::make_pair(k, false)); + else{ + if (m_is_closed[mesh_id]) { - if (m_is_closed[mesh_id]) + Side_of_tm side_of_mid(*m_aabb_trees[mesh_id]); + typename Kernel::Point_3 q = get(boost::vertex_point, *m_triangle_mesh_ptrs[k], *boost::begin(vertices(*m_triangle_mesh_ptrs[k]))); + if(side_of_mid(m_aabb_trees[k]->traits().transformation()( q )) == CGAL::ON_BOUNDED_SIDE) { - Side_of_tm side_of_mid(m_aabb_trees[mesh_id]); - typename Kernel::Point_3 q = get(boost::vertex_point, *m_triangle_mesh_ptrs[k], *boost::begin(vertices(*m_triangle_mesh_ptrs[k]))); - if(side_of_mid(m_aabb_trees[k].traits.transformation()( q )) == CGAL::ON_BOUNDED_SIDE) - res.push_back(k); + res.push_back(std::make_pair(k, true)); continue; } - if (m_is_closed[k]) - { - Side_of_tm side_of_mk(m_aabb_trees[k]); - typename Kernel::Point_3 q = get(boost::vertex_point, *m_triangle_mesh_ptrs[mesh_id], *boost::begin(vertices(*m_triangle_mesh_ptrs[mesh_id]))); - if(side_of_mk(m_aabb_trees.traits[mesh_id].transformation()( q )) == CGAL::ON_BOUNDED_SIDE) - res.push_back(k); - } + } + if (m_is_closed[k]) + { + Side_of_tm side_of_mk(*m_aabb_trees[k]); + typename Kernel::Point_3 q = get(boost::vertex_point, *m_triangle_mesh_ptrs[mesh_id], *boost::begin(vertices(*m_triangle_mesh_ptrs[mesh_id]))); + if(side_of_mk(m_aabb_trees[mesh_id]->traits().transformation()( q )) == CGAL::ON_BOUNDED_SIDE) + res.push_back(std::make_pair(k, true)); } } } - return res; } }; @@ -123,4 +142,4 @@ public: } // end of CGAL namespace -#endif // CGAL_RIGID_MESH_COLLISION_DETECTION_H \ No newline at end of file +#endif // CGAL_RIGID_MESH_COLLISION_DETECTION_H From 8f9b5ba86b1ced662566d49cd837102455c99321 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 25 Jul 2018 12:33:59 +0200 Subject: [PATCH 24/84] Add Transparency Mode and make it more robust --- .../AABB_tree/Do_trees_intersect_plugin.cpp | 106 ++++++++++++++---- .../AABB_tree/Scene_movable_sm_item.cpp | 40 ++++--- .../AABB_tree/Scene_movable_sm_item.h | 4 +- 3 files changed, 112 insertions(+), 38 deletions(-) diff --git a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp index f322e14fbab..97e98035bbf 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp @@ -16,7 +16,7 @@ #include #include "Scene.h" -class DoTreesIntersectplugin : +class DoTreesIntersectplugin: public QObject, public CGAL::Three::Polyhedron_demo_plugin_interface { @@ -25,14 +25,29 @@ class DoTreesIntersectplugin : Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0") public: + bool eventFilter(QObject *, QEvent *event) Q_DECL_OVERRIDE + { + if(event->type() != QEvent::KeyPress) + return false; + QKeyEvent * e = static_cast(event); + if (e->key()==Qt::Key_W){ + do_transparency = !do_transparency; + update_trees(); + return true; + } + return false; + } + bool applicable(QAction*) const Q_DECL_OVERRIDE { + if(scene->selectionIndices().size() <2) + return false; Q_FOREACH(Scene::Item_id i, scene->selectionIndices()) { if(! qobject_cast(scene->item(i))) return false; } - return items.empty(); + return (! group_item); } QList actions() const Q_DECL_OVERRIDE @@ -40,6 +55,7 @@ public: return _actions; } + void init(QMainWindow* mw, CGAL::Three::Scene_interface* sc, Messages_interface* mi) Q_DECL_OVERRIDE { this->messageInterface = mi; @@ -52,11 +68,23 @@ public: this, SLOT(start())); _actions << actionCreateTrees; } + do_transparency = false; + group_item = nullptr; } private Q_SLOTS: void start() { QApplication::setOverrideCursor(Qt::WaitCursor); + group_item = new Scene_group_item("Test Items"); + connect(group_item, &Scene_group_item::aboutToBeDestroyed, + this, [this](){ + items.clear(); + meshes.clear(); + delete col_det; + col_det = nullptr; + group_item = nullptr;}); + group_item->setScene(scene); + scene->addItem(group_item); Q_FOREACH(Scene::Item_id i, scene->selectionIndices()) { Scene_surface_mesh_item* item=qobject_cast(scene->item(i)); @@ -68,17 +96,26 @@ private Q_SLOTS: (item->bbox().min(2) + item->bbox().max(2))/2.0); Scene_movable_sm_item* mov_item = new Scene_movable_sm_item(pos,item->face_graph(),""); - connect(mov_item, &Scene_movable_sm_item::aboutToBeDestroyed, - this, &DoTreesIntersectplugin::cleanup); connect(mov_item->manipulatedFrame(), &CGAL::qglviewer::ManipulatedFrame::modified, this, &DoTreesIntersectplugin::update_trees); mov_item->setName(item->name()); - mov_item->setRenderingMode(Wireframe); + if(do_transparency) + { + mov_item->setRenderingMode(Flat); + mov_item->setAlpha(120); + } + else + { + mov_item->setRenderingMode(Wireframe); + } item->setVisible(false); items.push_back(mov_item); - scene->setSelectedItem(scene->addItem(mov_item)); + scene->addItem(mov_item); + scene->changeGroup(mov_item, group_item); + group_item->lockChild(mov_item); mov_item->redraw(); } + scene->setSelectedItem(group_item->getChildren().last()); connect(static_cast(scene), &Scene::itemIndexSelected, this, &DoTreesIntersectplugin::update_trees); Q_FOREACH(Scene_movable_sm_item* item, items) @@ -87,22 +124,35 @@ private Q_SLOTS: } col_det = new CGAL::Rigid_mesh_collision_detection(meshes); update_trees(); - items.back()->setRenderingMode(Wireframe); - + if(do_transparency) + { + items.back()->setRenderingMode(Flat); + items.back()->setAlpha(120); + } + else + { + items.back()->setRenderingMode(Wireframe); + } + static_cast( + CGAL::QGLViewer::QGLViewerPool().first())->installEventFilter(this); QApplication::restoreOverrideCursor(); + messageInterface->information("Press `W` to switch between Wireframe and Transparency mode."); } - public Q_SLOTS: void update_trees() { + if(items.empty()) + return; + Q_FOREACH(Scene_movable_sm_item* item, items) + item->setColor(QColor(Qt::green)); + CGAL::Three::Viewer_interface* viewer = static_cast( CGAL::QGLViewer::QGLViewerPool().first()); - Scene_movable_sm_item* sel_item = qobject_cast(scene->item(scene->mainSelectionIndex())); if(!sel_item) return; - + std::size_t mesh_id = 0; std::size_t sel_id = 0; Q_FOREACH(Scene_movable_sm_item* item, items) @@ -123,7 +173,6 @@ public Q_SLOTS: item->setColor(QColor(255,184,61)); continue; } - item->setColor(QColor(Qt::green)); const double* matrix = item->manipulatedFrame()->matrix(); item->setFMatrix(matrix); EPICK::Aff_transformation_3 translation(CGAL::TRANSLATION, -EPICK::Vector_3(item->center().x, @@ -138,7 +187,15 @@ public Q_SLOTS: col_det->set_transformation(mesh_id++, transfo); - item->setRenderingMode(Wireframe); + if(do_transparency) + { + item->setRenderingMode(Flat); + item->setAlpha(120); + } + else + { + item->setRenderingMode(Wireframe); + } item->itemChanged(); } const double* matrix = sel_item->manipulatedFrame()->matrix(); @@ -164,20 +221,27 @@ public Q_SLOTS: else items[id]->setColor(QColor(Qt::red)); } - sel_item->setRenderingMode(Wireframe); + if(do_transparency) + { + sel_item->setRenderingMode(Flat); + sel_item->setAlpha(120); + } + else + { + sel_item->setRenderingMode(Wireframe); + } sel_item->itemChanged(); viewer->update(); } void cleanup() { - Q_FOREACH(Scene_movable_sm_item* item, items) - if(item) - { - scene->erase(scene->item_id(item)); - item = nullptr; - } + if(!group_item) + return; + scene->erase(scene->item_id(group_item)); + group_item = nullptr; items.clear(); + meshes.clear(); delete col_det; col_det = nullptr; } @@ -189,6 +253,8 @@ private: QMainWindow* mw; CGAL::Rigid_mesh_collision_detection *col_det; std::vector items; + Scene_group_item* group_item; std::vector meshes; + bool do_transparency; }; #include "Do_trees_intersect_plugin.moc" diff --git a/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.cpp b/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.cpp index f390983ecb1..794f09f8304 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.cpp @@ -60,7 +60,7 @@ Scene_movable_sm_item::Scene_movable_sm_item(const CGAL::qglviewer::Vec& pos, SM } -void Scene_movable_sm_item_priv::initialize_buffers(CGAL::Three::Viewer_interface *viewer =0) const +void Scene_movable_sm_item_priv::initialize_buffers(CGAL::Three::Viewer_interface *viewer = nullptr) const { item->getTriangleContainer(0)->initializeBuffers(viewer); item->getTriangleContainer(0)->setFlatDataSize(flat_vertices.size()); @@ -109,20 +109,20 @@ void Scene_movable_sm_item_priv::compute_elements() const EPICK::Vector_3 n = fnormals[fd]; CPF::add_normal_in_buffer(n, flat_normals); } - } + } //edges BOOST_FOREACH(edge_descriptor ed, edges(*facegraph)) { - Point p = positions[source(ed, *facegraph)] + offset; - EPICK::Point_3 pc(p.x() - center_.x, - p.y() - center_.y, - p.z() - center_.z); - CPF::add_point_in_buffer(pc, edges_vertices); - p = positions[target(ed, *facegraph)] + offset; - pc=EPICK::Point_3(p.x() - center_.x, - p.y() - center_.y, - p.z() - center_.z); - CPF::add_point_in_buffer(pc, edges_vertices); + Point p = positions[source(ed, *facegraph)] + offset; + EPICK::Point_3 pc(p.x() - center_.x, + p.y() - center_.y, + p.z() - center_.z); + CPF::add_point_in_buffer(pc, edges_vertices); + p = positions[target(ed, *facegraph)] + offset; + pc=EPICK::Point_3(p.x() - center_.x, + p.y() - center_.y, + p.z() - center_.z); + CPF::add_point_in_buffer(pc, edges_vertices); } @@ -132,13 +132,14 @@ void Scene_movable_sm_item_priv::compute_elements() const item->getTriangleContainer(0)->allocate(Tri::Flat_normals, flat_normals.data(), static_cast(flat_normals.size()*sizeof(float))); item->getEdgeContainer(0)->allocate(Tri::Flat_vertices, edges_vertices.data(), - static_cast(edges_vertices.size()*sizeof(float))); + static_cast(edges_vertices.size()*sizeof(float))); QApplication::restoreOverrideCursor(); } void Scene_movable_sm_item::computeElements() const { d->compute_elements(); + compute_bbox(); } void Scene_movable_sm_item::draw(CGAL::Three::Viewer_interface* viewer) const { @@ -147,7 +148,7 @@ void Scene_movable_sm_item::draw(CGAL::Three::Viewer_interface* viewer) const if(!are_buffers_filled) d->initialize_buffers(viewer); getTriangleContainer(0)->setColor(color()); - getTriangleContainer(0)->setSelected(is_selected); + getTriangleContainer(0)->setAlpha(alpha()); getTriangleContainer(0)->setFrameMatrix(d->f_matrix); getTriangleContainer(0)->draw(viewer, true); @@ -174,7 +175,7 @@ QString Scene_movable_sm_item::toolTip() const { void Scene_movable_sm_item::compute_bbox() const { SMesh::Property_map pprop = d->facegraph->points(); - CGAL::Bbox_3 bbox; + CGAL::Bbox_3 bbox ; BOOST_FOREACH(vertex_descriptor vd,vertices(*d->facegraph)) { @@ -185,11 +186,18 @@ Scene_movable_sm_item::compute_bbox() const { is_bbox_computed = true; } +Scene_item::Bbox Scene_movable_sm_item::bbox() const { + if(!is_bbox_computed) + compute_bbox(); + is_bbox_computed = true; + return _bbox; +} + void Scene_movable_sm_item::invalidateOpenGLBuffers() { d->compute_elements(); - compute_bbox(); + is_bbox_computed = false; are_buffers_filled = false; } CGAL::Three::Scene_item::ManipulatedFrame* Scene_movable_sm_item::manipulatedFrame() { return d->frame; } diff --git a/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.h b/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.h index 7c2db949c32..1d89eaa5a46 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.h +++ b/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.h @@ -31,11 +31,12 @@ class SCENE_MOVABLE_SM_ITEM_EXPORT Scene_movable_sm_item public: Scene_movable_sm_item(const CGAL::qglviewer::Vec& pos, SMesh *sm, const QString name); - Scene_item* clone() const{return NULL;} + Scene_item* clone() const{return nullptr;} QString toolTip() const; void draw(CGAL::Three::Viewer_interface *) const; void drawEdges(CGAL::Three::Viewer_interface *) const; void compute_bbox() const; + Scene_item::Bbox bbox() const ; ~Scene_movable_sm_item(); bool manipulatable() const { return true;} ManipulatedFrame* manipulatedFrame(); @@ -47,7 +48,6 @@ public: void computeElements() const; bool isEmpty() const {return false;} SMesh *getFaceGraph(); - protected: friend struct Scene_movable_sm_item_priv; Scene_movable_sm_item_priv* d; From 7da9adfa901f4eb964fdd13cf07ea89cc7fa7091 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 25 Jul 2018 14:21:53 +0200 Subject: [PATCH 25/84] Addadd_mesh() to the class. --- .../AABB_tree/Do_trees_intersect_plugin.cpp | 2 +- .../include/CGAL/Rigid_mesh_collision_detection.h | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp index 97e98035bbf..970147da491 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp @@ -211,7 +211,7 @@ public Q_SLOTS: rota*translation; std::vector > inter_and_incl = col_det-> - set_transformation_and_all_intersections_and_all_inclusions(sel_id, transfo); + set_transformation_and_get_all_intersections_and_inclusions(sel_id, transfo); for(std::size_t i=0; i& aff_trans) { m_aabb_trees[mesh_id]->traits().set_transformation(aff_trans); } std::vector - set_transformation_and_all_intersections(std::size_t mesh_id, + set_transformation_and_get_all_intersections(std::size_t mesh_id, const Aff_transformation_3& aff_trans) { set_transformation(mesh_id, aff_trans); @@ -102,7 +109,7 @@ public: } std::vector > - set_transformation_and_all_intersections_and_all_inclusions(std::size_t mesh_id, + set_transformation_and_get_all_intersections_and_inclusions(std::size_t mesh_id, const Aff_transformation_3& aff_trans) { set_transformation(mesh_id, aff_trans); From 9522c02639e07148821aca0e0cfb6134cd47f0cd Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 25 Jul 2018 14:44:47 +0200 Subject: [PATCH 26/84] Add remove_mesh() --- .../CGAL/Rigid_mesh_collision_detection.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index fef908056f7..291e305bc91 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -84,6 +84,23 @@ public: m_aabb_trees.push_back(new Tree(faces(tm).begin(), faces(tm).end(), tm)); } + void remove_mesh(std::size_t mesh_id) + { + if(mesh_id >= m_triangle_mesh_ptrs.size()) + return; + std::size_t original_size=m_triangle_mesh_ptrs.size(); + typename std::vector::iterator mesh_it = + (m_triangle_mesh_ptrs.begin()+mesh_id); + typename std::vector::iterator tree_it = + (m_aabb_trees.begin()+mesh_id); + std::vector::iterator bool_it = + (m_is_closed.begin()+mesh_id); + m_triangle_mesh_ptrs.erase(mesh_it); + m_aabb_trees.erase(tree_it); + m_is_closed.erase(bool_it); + + } + void set_transformation(std::size_t mesh_id, const Aff_transformation_3& aff_trans) { m_aabb_trees[mesh_id]->traits().set_transformation(aff_trans); From 3e2d61e29d384addc4b767664af795bdd2edf7f0 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 25 Jul 2018 15:10:22 +0200 Subject: [PATCH 27/84] Move traits in PMP/internal --- AABB_tree/benchmark/AABB_tree/test.cpp | 18 ++---------------- .../AABB_do_intersect_transform_traits.h | 0 .../CGAL/Rigid_mesh_collision_detection.h | 3 +-- 3 files changed, 3 insertions(+), 18 deletions(-) rename {AABB_tree/include/CGAL => Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal}/AABB_do_intersect_transform_traits.h (100%) diff --git a/AABB_tree/benchmark/AABB_tree/test.cpp b/AABB_tree/benchmark/AABB_tree/test.cpp index 6db53a4c822..ae5709dd01f 100644 --- a/AABB_tree/benchmark/AABB_tree/test.cpp +++ b/AABB_tree/benchmark/AABB_tree/test.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include @@ -15,12 +15,10 @@ #include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -//typedef CGAL::Simple_cartesian K; typedef CGAL::Surface_mesh Surface_mesh; typedef CGAL::AABB_face_graph_triangle_primitive Primitive; -typedef CGAL::AABB_traits AABB_triangle_traits; -typedef CGAL::AABB_do_intersect_transform_traits Traits; +typedef CGAL::AABB_do_intersect_transform_traits Traits; typedef CGAL::AABB_tree Tree; namespace PMP = CGAL::Polygon_mesh_processing; @@ -41,12 +39,6 @@ void naive_test(int k, const char* fname, (box.xmax()-box.xmin()),0,0)); PMP::transform(init2, tm2); - std::ofstream out1("/home/gimeno/Data/tmp/m1.off"), - out2("/home/gimeno/Data/tmp/m2.off"); - out1 << tm; - out1.close(); - out2 << tm2; - out2.close(); tmTree.build(); K::Vector_3 unit_vec = (2.0/k * K::Vector_3((box.xmax()-box.xmin()), 0, @@ -109,12 +101,6 @@ void test_no_collision(int k, const char* fname, (box.xmax()-box.xmin()),0,0)); PMP::transform(init2, tm2); - std::ofstream out1("/home/gimeno/Data/tmp/m1.off"), - out2("/home/gimeno/Data/tmp/m2.off"); - out1 << tm; - out1.close(); - out2 << tm2; - out2.close(); tmTree.build(); tmTree2.build(); typedef boost::property_map::type VPM; diff --git a/AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h similarity index 100% rename from AABB_tree/include/CGAL/AABB_do_intersect_transform_traits.h rename to Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index 291e305bc91..e839986287b 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -27,8 +27,7 @@ #include #include -// TODO: move AABB_do_intersect_transform_traits.h in PMP/internal -#include +#include #include #include From c73b0154030107619555c0c7035ffd4a50dc9347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 25 Jul 2018 16:12:55 +0200 Subject: [PATCH 28/84] use the default tree to be fair --- AABB_tree/benchmark/AABB_tree/test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/AABB_tree/benchmark/AABB_tree/test.cpp b/AABB_tree/benchmark/AABB_tree/test.cpp index ae5709dd01f..cf05141d543 100644 --- a/AABB_tree/benchmark/AABB_tree/test.cpp +++ b/AABB_tree/benchmark/AABB_tree/test.cpp @@ -33,6 +33,7 @@ void naive_test(int k, const char* fname, CGAL::Aff_transformation_3 init1(CGAL::SCALING, 6.0); PMP::transform(init1, tm); CGAL::Bbox_3 box = PMP::bbox(tm); + typedef CGAL::AABB_tree > Tree; Tree tmTree(tm.faces_begin(), tm.faces_end(), tm); Tree tmTree2(tm2.faces_begin(), tm2.faces_end(), tm2); CGAL::Aff_transformation_3 init2(CGAL::TRANSLATION, - K::Vector_3( From f77725882b2c2cc80f3941097a66eab8970cb802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 25 Jul 2018 16:26:09 +0200 Subject: [PATCH 29/84] use Interval_nt_advanced with protectors --- AABB_tree/benchmark/AABB_tree/test.cpp | 1 + .../internal/AABB_do_intersect_transform_traits.h | 3 +-- .../include/CGAL/Rigid_mesh_collision_detection.h | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/AABB_tree/benchmark/AABB_tree/test.cpp b/AABB_tree/benchmark/AABB_tree/test.cpp index cf05141d543..9a877a70a1c 100644 --- a/AABB_tree/benchmark/AABB_tree/test.cpp +++ b/AABB_tree/benchmark/AABB_tree/test.cpp @@ -131,6 +131,7 @@ void test_no_collision(int k, const char* fname, CGAL::Aff_transformation_3 T1 = CGAL::Aff_transformation_3(CGAL::TRANSLATION, i*unit_vec); CGAL::Aff_transformation_3 transfo = R*T1; tmTree2.traits().set_transformation(transfo); + CGAL::Interval_nt_advanced::Protector protector; if(tmTree2.do_intersect(tmTree)) ++nb_inter; else diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h index 5f86b2aeb6f..e65b5e23641 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h @@ -64,8 +64,7 @@ public: Bbox_3 static compute_transformed_bbox(const Bbox_3& bbox, const Aff_transformation_3& transfo) { - // TODO: possible optimization using Protector - typedef Simple_cartesian > AK; + typedef Simple_cartesian AK; typedef Cartesian_converter C2F; C2F c2f; diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index e839986287b..0962e6e0aa3 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -109,6 +109,7 @@ public: set_transformation_and_get_all_intersections(std::size_t mesh_id, const Aff_transformation_3& aff_trans) { + CGAL::Interval_nt_advanced::Protector protector; set_transformation(mesh_id, aff_trans); std::vector res; @@ -128,6 +129,7 @@ public: set_transformation_and_get_all_intersections_and_inclusions(std::size_t mesh_id, const Aff_transformation_3& aff_trans) { + CGAL::Interval_nt_advanced::Protector protector; set_transformation(mesh_id, aff_trans); std::vector > res; From 89e3c69db01afadbf1f20026d7c8c932f815bbcd Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 25 Jul 2018 17:09:32 +0200 Subject: [PATCH 30/84] Add a Tag to specify a no_rotation case, which calls a faster transform_bbox() function --- .../AABB_do_intersect_transform_traits.h | 52 +++++++++++++------ .../CGAL/Rigid_mesh_collision_detection.h | 4 +- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h index e65b5e23641..b9e5f88c8ca 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h @@ -41,13 +41,14 @@ namespace CGAL { -template +template class AABB_do_intersect_transform_traits: public AABB_traits { mutable Aff_transformation_3 m_transfo; typedef AABB_traits BaseTraits; - typedef AABB_do_intersect_transform_traits Self; + typedef AABB_do_intersect_transform_traits Self; public: //Constructor @@ -62,7 +63,7 @@ public: // helper functions Bbox_3 - static compute_transformed_bbox(const Bbox_3& bbox, const Aff_transformation_3& transfo) + static compute_transformed_bbox(const Bbox_3& bbox, const Aff_transformation_3& transfo, Tag_true) { typedef Simple_cartesian AK; typedef Cartesian_converter C2F; @@ -88,17 +89,38 @@ public: return bbox_3(ps, ps+8); } + Bbox_3 + static compute_transformed_bbox(const Bbox_3& bbox, const Aff_transformation_3& transfo, Tag_false) + { + // TODO: possible optimization using Protector + typedef Simple_cartesian AK; + typedef Cartesian_converter C2F; + C2F c2f; + + AK::Aff_transformation_3 af = c2f(transfo); + + AK::FT xtrm[6] = { c2f(bbox.min(0)), c2f(bbox.max(0)), + c2f(bbox.min(1)), c2f(bbox.max(1)), + c2f(bbox.min(2)), c2f(bbox.max(2)) }; + + typename AK::Point_3 ps[2]; + ps[0] = af( AK::Point_3(xtrm[0], xtrm[2], xtrm[4]) ); + ps[1] = af( AK::Point_3(xtrm[1], xtrm[3], xtrm[5]) ); + + return bbox_3(ps, ps+2); + } + Bbox_3 compute_transformed_bbox(const Bbox_3& bbox) const { - return compute_transformed_bbox(bbox, m_transfo); + return compute_transformed_bbox(bbox, m_transfo, HAS_ROTATION()); } // Do_intersect predicate class Do_intersect : BaseTraits::Do_intersect { - typedef AABB_do_intersect_transform_traits AABBTraits; + typedef AABB_do_intersect_transform_traits AABBTraits; const AABBTraits& m_traits; typedef typename BaseTraits::Do_intersect Base; @@ -159,10 +181,10 @@ public: namespace internal { -template -struct Primitive_helper ,true>{ +template +struct Primitive_helper ,true>{ -typedef AABB_do_intersect_transform_traits Traits; +typedef AABB_do_intersect_transform_traits Traits; static typename Traits::Primitive::Datum get_datum(const typename Traits::Primitive& p, @@ -177,17 +199,17 @@ static typename Traits::Point_3 get_reference_point(const typename Traits::Primi }; -template -typename CGAL::AABB_tree >::Bounding_box -get_tree_bbox(const CGAL::AABB_tree >& tree) +template +typename CGAL::AABB_tree >::Bounding_box +get_tree_bbox(const CGAL::AABB_tree >& tree) { return tree.traits().compute_transformed_bbox(tree.bbox()); } -template -typename CGAL::AABB_tree >::Bounding_box -get_node_bbox(const CGAL::AABB_node >& node, - const AABB_do_intersect_transform_traits& traits) +template +typename CGAL::AABB_tree >::Bounding_box +get_node_bbox(const CGAL::AABB_node >& node, + const AABB_do_intersect_transform_traits& traits) { return traits.compute_transformed_bbox(node.bbox()); } diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index 0962e6e0aa3..9398ee29e6a 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -34,11 +34,11 @@ namespace CGAL { -template +template class Rigid_mesh_collision_detection { typedef CGAL::AABB_face_graph_triangle_primitive Primitive; - typedef CGAL::AABB_do_intersect_transform_traits Traits; + typedef CGAL::AABB_do_intersect_transform_traits Traits; typedef CGAL::AABB_tree Tree; typedef Side_of_triangle_mesh Side_of_tm; From dd78147d3a6c2e334ea172e79983239d2c568aab Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 25 Jul 2018 17:29:50 +0200 Subject: [PATCH 31/84] Add if test for optimisation if SUPPORTS_ROTATION is Tag_true; --- AABB_tree/benchmark/AABB_tree/test.cpp | 10 ++-- .../AABB_do_intersect_transform_traits.h | 60 ++++++++++++------- 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/AABB_tree/benchmark/AABB_tree/test.cpp b/AABB_tree/benchmark/AABB_tree/test.cpp index 9a877a70a1c..22ebbbb08e5 100644 --- a/AABB_tree/benchmark/AABB_tree/test.cpp +++ b/AABB_tree/benchmark/AABB_tree/test.cpp @@ -40,7 +40,7 @@ void naive_test(int k, const char* fname, (box.xmax()-box.xmin()),0,0)); PMP::transform(init2, tm2); - tmTree.build(); + tmTree.build(); K::Vector_3 unit_vec = (2.0/k * K::Vector_3((box.xmax()-box.xmin()), 0, 0)); @@ -72,13 +72,13 @@ void naive_test(int k, const char* fname, { if(sotm1(tm2.point(*tm2.vertices().begin())) != CGAL::ON_UNBOUNDED_SIDE) { - ++nb_include; + ++nb_include; } else { CGAL::Side_of_triangle_mesh sotm2(tm2); if(sotm2(tm.point(*tm.vertices().begin())) != CGAL::ON_UNBOUNDED_SIDE) - ++nb_include; + ++nb_include; else ++nb_no_inter; } @@ -138,14 +138,14 @@ void test_no_collision(int k, const char* fname, { if(sotm1(transfo.transform(vpm2[*tm2.vertices().begin()])) != CGAL::ON_UNBOUNDED_SIDE) { - ++nb_include; + ++nb_include; } else { CGAL::Side_of_triangle_mesh sotm2(tmTree2); if(sotm2(tm.point(*tm.vertices().begin())) != CGAL::ON_UNBOUNDED_SIDE) - ++nb_include; + ++nb_include; else ++nb_no_inter; } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h index b9e5f88c8ca..c447ad2c742 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h @@ -42,29 +42,31 @@ namespace CGAL { template + typename SUPPORTS_ROTATION = CGAL::Tag_true> class AABB_do_intersect_transform_traits: public AABB_traits { mutable Aff_transformation_3 m_transfo; + mutable bool has_rotation; typedef AABB_traits BaseTraits; - typedef AABB_do_intersect_transform_traits Self; -public: - - //Constructor - AABB_do_intersect_transform_traits(const Aff_transformation_3& transf = Aff_transformation_3(IDENTITY)) - :m_transfo(transf) - {} - - // AABBTraits concept types - typedef typename BaseTraits::Point_3 Point_3; - typedef typename BaseTraits::Primitive Primitive; - typedef typename BaseTraits::Bounding_box Bounding_box; - - // helper functions - Bbox_3 - static compute_transformed_bbox(const Bbox_3& bbox, const Aff_transformation_3& transfo, Tag_true) + typedef AABB_do_intersect_transform_traits Self; + + void set_transformation(const Aff_transformation_3& trans, CGAL::Tag_true) const { + has_rotation = (trans.m(0,1) != 0 + || trans.m(0,2) != 0 + || trans.m(1,0) != 0 + || trans.m(1,2) != 0 + || trans.m(2,0) != 0 + || trans.m(2,1) !=0); + } + void set_transformation(const Aff_transformation_3& trans, CGAL::Tag_false) const + {} + Bbox_3 + compute_transformed_bbox_impl(const Bbox_3& bbox, const Aff_transformation_3& transfo, Tag_true)const + { + if(has_rotation) + return compute_transformed_bbox_impl(bbox, m_transfo, Tag_false()); typedef Simple_cartesian AK; typedef Cartesian_converter C2F; C2F c2f; @@ -90,9 +92,8 @@ public: } Bbox_3 - static compute_transformed_bbox(const Bbox_3& bbox, const Aff_transformation_3& transfo, Tag_false) + compute_transformed_bbox_impl(const Bbox_3& bbox, const Aff_transformation_3& transfo, Tag_false)const { - // TODO: possible optimization using Protector typedef Simple_cartesian AK; typedef Cartesian_converter C2F; C2F c2f; @@ -109,18 +110,34 @@ public: return bbox_3(ps, ps+2); } +public: + + //Constructor + AABB_do_intersect_transform_traits(const Aff_transformation_3& transf = Aff_transformation_3(IDENTITY)) + { + has_rotation = false; + set_transformation(transf, SUPPORTS_ROTATION()); + } + + // AABBTraits concept types + typedef typename BaseTraits::Point_3 Point_3; + typedef typename BaseTraits::Primitive Primitive; + typedef typename BaseTraits::Bounding_box Bounding_box; + + // helper functions + Bbox_3 compute_transformed_bbox(const Bbox_3& bbox) const { - return compute_transformed_bbox(bbox, m_transfo, HAS_ROTATION()); + return compute_transformed_bbox_impl(bbox, m_transfo, SUPPORTS_ROTATION()); } // Do_intersect predicate class Do_intersect : BaseTraits::Do_intersect { - typedef AABB_do_intersect_transform_traits AABBTraits; + typedef AABB_do_intersect_transform_traits AABBTraits; const AABBTraits& m_traits; typedef typename BaseTraits::Do_intersect Base; @@ -174,6 +191,7 @@ public: void set_transformation(const Aff_transformation_3& trans) const { m_transfo = trans; + set_transformation(trans, SUPPORTS_ROTATION()); } const Aff_transformation_3& transformation() const { return m_transfo; } From 7220e43e0706072529b23bd704892e9586c614ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 25 Jul 2018 17:54:56 +0200 Subject: [PATCH 32/84] fix condition + clean up --- .../internal/AABB_do_intersect_transform_traits.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h index c447ad2c742..ac4d78bcf6e 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h @@ -63,15 +63,16 @@ class AABB_do_intersect_transform_traits: void set_transformation(const Aff_transformation_3& trans, CGAL::Tag_false) const {} Bbox_3 - compute_transformed_bbox_impl(const Bbox_3& bbox, const Aff_transformation_3& transfo, Tag_true)const + compute_transformed_bbox_impl(const Bbox_3& bbox, Tag_true) const { - if(has_rotation) - return compute_transformed_bbox_impl(bbox, m_transfo, Tag_false()); + if(!has_rotation) + return compute_transformed_bbox_impl(bbox, Tag_false()); + typedef Simple_cartesian AK; typedef Cartesian_converter C2F; C2F c2f; - AK::Aff_transformation_3 af = c2f(transfo); + AK::Aff_transformation_3 af = c2f(m_transfo); AK::FT xtrm[6] = { c2f(bbox.min(0)), c2f(bbox.max(0)), c2f(bbox.min(1)), c2f(bbox.max(1)), @@ -92,13 +93,13 @@ class AABB_do_intersect_transform_traits: } Bbox_3 - compute_transformed_bbox_impl(const Bbox_3& bbox, const Aff_transformation_3& transfo, Tag_false)const + compute_transformed_bbox_impl(const Bbox_3& bbox, Tag_false) const { typedef Simple_cartesian AK; typedef Cartesian_converter C2F; C2F c2f; - AK::Aff_transformation_3 af = c2f(transfo); + AK::Aff_transformation_3 af = c2f(m_transfo); AK::FT xtrm[6] = { c2f(bbox.min(0)), c2f(bbox.max(0)), c2f(bbox.min(1)), c2f(bbox.max(1)), @@ -130,7 +131,7 @@ public: Bbox_3 compute_transformed_bbox(const Bbox_3& bbox) const { - return compute_transformed_bbox_impl(bbox, m_transfo, SUPPORTS_ROTATION()); + return compute_transformed_bbox_impl(bbox, SUPPORTS_ROTATION()); } // Do_intersect predicate From aff9f5be40f893acc34d01941205ae7e12ef132a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 25 Jul 2018 18:42:45 +0200 Subject: [PATCH 33/84] simplify --- .../CGAL/Rigid_mesh_collision_detection.h | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index 9398ee29e6a..dae8604af84 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -85,18 +85,10 @@ public: void remove_mesh(std::size_t mesh_id) { - if(mesh_id >= m_triangle_mesh_ptrs.size()) - return; - std::size_t original_size=m_triangle_mesh_ptrs.size(); - typename std::vector::iterator mesh_it = - (m_triangle_mesh_ptrs.begin()+mesh_id); - typename std::vector::iterator tree_it = - (m_aabb_trees.begin()+mesh_id); - std::vector::iterator bool_it = - (m_is_closed.begin()+mesh_id); - m_triangle_mesh_ptrs.erase(mesh_it); - m_aabb_trees.erase(tree_it); - m_is_closed.erase(bool_it); + if(mesh_id >= m_triangle_mesh_ptrs.size()) return; + m_triangle_mesh_ptrs.erase( m_triangle_mesh_ptrs.begin()+mesh_id ); + m_aabb_trees.erase( m_aabb_trees.begin()+mesh_id); + m_is_closed.erase(m_is_closed.begin()+mesh_id); } From 6a137a127e1e71fb2e57caff94f0c66a5ff7f3bb Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 26 Jul 2018 09:07:17 +0200 Subject: [PATCH 34/84] Add test for triangle mesh in plugin. --- .../AABB_tree/Do_trees_intersect_plugin.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp index 970147da491..323392ac1e5 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp @@ -75,15 +75,27 @@ private Q_SLOTS: void start() { QApplication::setOverrideCursor(Qt::WaitCursor); + Q_FOREACH(Scene::Item_id i, scene->selectionIndices()) + { + Scene_surface_mesh_item* item=qobject_cast(scene->item(i)); + if (!CGAL::is_triangle_mesh(*item->face_graph())) + { + QApplication::restoreOverrideCursor(); + QMessageBox::warning(mw, "Error", QString("%1 is not pure triangle. Aborting.").arg(item->name())); + return; + } + } group_item = new Scene_group_item("Test Items"); connect(group_item, &Scene_group_item::aboutToBeDestroyed, this, [this](){ items.clear(); meshes.clear(); - delete col_det; + if(col_det) + delete col_det; col_det = nullptr; group_item = nullptr;}); group_item->setScene(scene); + scene->addItem(group_item); Q_FOREACH(Scene::Item_id i, scene->selectionIndices()) { From 19f11b861a16cecc8fa5acfbfd83c3a431f474b8 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 26 Jul 2018 14:21:29 +0200 Subject: [PATCH 35/84] WIP use box_intersection_d --- .../AABB_do_intersect_transform_traits.h | 1 + .../CGAL/Rigid_mesh_collision_detection.h | 55 +++++++++++++++++-- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h index ac4d78bcf6e..e690e003f91 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h @@ -34,6 +34,7 @@ #include #include +#include #include #include diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index dae8604af84..13fa83c9b2e 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -30,8 +30,9 @@ #include #include #include +#include - +#define CGAL_USE_BOX_INTERSECTION_D 1 namespace CGAL { template @@ -47,6 +48,9 @@ class Rigid_mesh_collision_detection // TODO: we probably want an option with external trees std::vector m_aabb_trees; std::vector m_is_closed; +#ifdef CGAL_USE_BOX_INTERSECTION_D + std::vector m_tree_boxes; +#endif public: template @@ -66,13 +70,20 @@ public: m_triangle_mesh_ptrs.reserve( triangle_meshes.size() ); m_aabb_trees.reserve( triangle_meshes.size() ); m_is_closed.resize(triangle_meshes.size(), false); +#ifdef CGAL_USE_BOX_INTERSECTION_D + m_tree_boxes.reserve( triangle_meshes.size() ); +#endif BOOST_FOREACH(const TriangleMesh& tm, triangle_meshes) { if (is_closed(tm)) m_is_closed[m_triangle_mesh_ptrs.size()]=true; m_triangle_mesh_ptrs.push_back( &tm ); - m_aabb_trees.push_back(new Tree(faces(tm).begin(), faces(tm).end(), tm)); + Tree* t = new Tree(faces(tm).begin(), faces(tm).end(), tm); + m_aabb_trees.push_back(t); +#ifdef CGAL_USE_BOX_INTERSECTION_D + m_tree_boxes.push_back(internal::get_tree_bbox(*t)); +#endif } } @@ -95,8 +106,26 @@ public: void set_transformation(std::size_t mesh_id, const Aff_transformation_3& aff_trans) { m_aabb_trees[mesh_id]->traits().set_transformation(aff_trans); +#ifdef CGAL_USE_BOX_INTERSECTION_D + m_tree_boxes[mesh_id] = internal::get_tree_bbox(*m_aabb_trees[mesh_id]); +#endif + } - + + +#ifdef CGAL_USE_BOX_INTERSECTION_D + struct Callback{ + typedef typename CGAL::Box_intersection_d::Box_with_info_d Bbox; + std::vector& res; + Callback(std::vector& res) + :res(res){} + void operator()(const Bbox& , + const Bbox& b) + { + res.push_back(b.info()); + } + }; +#endif std::vector set_transformation_and_get_all_intersections(std::size_t mesh_id, const Aff_transformation_3& aff_trans) @@ -106,6 +135,24 @@ public: std::vector res; // TODO: use a non-naive version +#ifdef CGAL_USE_BOX_INTERSECTION_D + std::vector boxes; + std::vector query; + for(std::size_t k=0; kdo_intersect( *m_aabb_trees[mesh_id] ) ) res.push_back(k); } - +#endif return res; } From 2013885eb496851caf7bb1c0e56a334646797bdd Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 27 Jul 2018 10:07:57 +0200 Subject: [PATCH 36/84] WIP fix plugin --- .../AABB_tree/Do_trees_intersect_plugin.cpp | 93 ++++++++++++++++++- .../CGAL/Rigid_mesh_collision_detection.h | 73 ++++++++------- 2 files changed, 129 insertions(+), 37 deletions(-) diff --git a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp index 323392ac1e5..bd2aa4c839e 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp @@ -135,7 +135,7 @@ private Q_SLOTS: meshes.push_back(*item->getFaceGraph()); } col_det = new CGAL::Rigid_mesh_collision_detection(meshes); - update_trees(); + init_trees(); if(do_transparency) { items.back()->setRenderingMode(Flat); @@ -152,7 +152,7 @@ private Q_SLOTS: } public Q_SLOTS: - void update_trees() + void init_trees() { if(items.empty()) return; @@ -246,6 +246,89 @@ public Q_SLOTS: viewer->update(); } + void update_trees() + { + if(items.empty()) + return; + CGAL::Three::Viewer_interface* viewer = static_cast( + CGAL::QGLViewer::QGLViewerPool().first()); + Scene_movable_sm_item* sel_item = qobject_cast(scene->item(scene->mainSelectionIndex())); + if(!sel_item) + return; + + std::size_t mesh_id = 0; + std::size_t sel_id = 0; + Q_FOREACH(Scene_movable_sm_item* item, items) + { + if(item == sel_item) + { + sel_id = mesh_id; + ++mesh_id; + item->setColor(QColor(255,184,61)); + break; + } + ++mesh_id; + } + for(std::size_t i = 0; i< prev_ids.size(); ++i) + { + std::size_t id = prev_ids[i]; + if(id == sel_id) + { + continue; + } + Scene_movable_sm_item* item = items[id]; + item->setColor(QColor(Qt::green)); + /*if(do_transparency) + { + item->setRenderingMode(Flat); + item->setAlpha(120); + } + else + { + item->setRenderingMode(Wireframe); + }*/ + item->itemChanged(); + } + prev_ids.clear(); + const double* matrix = sel_item->manipulatedFrame()->matrix(); + sel_item->setFMatrix(matrix); + + EPICK::Aff_transformation_3 translation(CGAL::TRANSLATION, -EPICK::Vector_3(sel_item->center().x, + sel_item->center().y, + sel_item->center().z)); + EPICK::Aff_transformation_3 rota( + matrix[0], matrix[4], matrix[8],matrix[12], + matrix[1], matrix[5], matrix[9],matrix[13], + matrix[2], matrix[6], matrix[10],matrix[14]); + EPICK::Aff_transformation_3 transfo = + rota*translation; + std::vector > inter_and_incl + = col_det-> + set_transformation_and_get_all_intersections_and_inclusions(sel_id, transfo); + for(std::size_t i=0; isetColor(QColor(Qt::blue)); + else + items[id]->setColor(QColor(Qt::red)); + prev_ids.push_back(id); + } + /* if(do_transparency) + { + sel_item->setRenderingMode(Flat); + sel_item->setAlpha(120); + } + else + { + sel_item->setRenderingMode(Wireframe); + }*/ + prev_ids.push_back(sel_id); + sel_item->itemChanged(); + viewer->update(); + } + void cleanup() { if(!group_item) @@ -258,6 +341,11 @@ public Q_SLOTS: col_det = nullptr; } + //switch transparent/wireframe. + void change_display() + { + } + private: QList _actions; Messages_interface* messageInterface; @@ -265,6 +353,7 @@ private: QMainWindow* mw; CGAL::Rigid_mesh_collision_detection *col_det; std::vector items; + std::vector prev_ids; Scene_group_item* group_item; std::vector meshes; bool do_transparency; diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index 13fa83c9b2e..655488191e9 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -48,7 +48,18 @@ class Rigid_mesh_collision_detection // TODO: we probably want an option with external trees std::vector m_aabb_trees; std::vector m_is_closed; -#ifdef CGAL_USE_BOX_INTERSECTION_D +#if CGAL_USE_BOX_INTERSECTION_D + struct Callback{ + typedef typename CGAL::Box_intersection_d::Box_with_info_d Bbox; + std::vector& res; + Callback(std::vector& res) + :res(res){} + void operator()(const Bbox& , + const Bbox& b) + { + res.push_back(b.info()); + } + }; std::vector m_tree_boxes; #endif @@ -70,10 +81,9 @@ public: m_triangle_mesh_ptrs.reserve( triangle_meshes.size() ); m_aabb_trees.reserve( triangle_meshes.size() ); m_is_closed.resize(triangle_meshes.size(), false); -#ifdef CGAL_USE_BOX_INTERSECTION_D +#if CGAL_USE_BOX_INTERSECTION_D m_tree_boxes.reserve( triangle_meshes.size() ); #endif - BOOST_FOREACH(const TriangleMesh& tm, triangle_meshes) { if (is_closed(tm)) @@ -81,7 +91,7 @@ public: m_triangle_mesh_ptrs.push_back( &tm ); Tree* t = new Tree(faces(tm).begin(), faces(tm).end(), tm); m_aabb_trees.push_back(t); -#ifdef CGAL_USE_BOX_INTERSECTION_D +#if CGAL_USE_BOX_INTERSECTION_D m_tree_boxes.push_back(internal::get_tree_bbox(*t)); #endif } @@ -106,26 +116,14 @@ public: void set_transformation(std::size_t mesh_id, const Aff_transformation_3& aff_trans) { m_aabb_trees[mesh_id]->traits().set_transformation(aff_trans); -#ifdef CGAL_USE_BOX_INTERSECTION_D +#if CGAL_USE_BOX_INTERSECTION_D m_tree_boxes[mesh_id] = internal::get_tree_bbox(*m_aabb_trees[mesh_id]); #endif } -#ifdef CGAL_USE_BOX_INTERSECTION_D - struct Callback{ - typedef typename CGAL::Box_intersection_d::Box_with_info_d Bbox; - std::vector& res; - Callback(std::vector& res) - :res(res){} - void operator()(const Bbox& , - const Bbox& b) - { - res.push_back(b.info()); - } - }; -#endif + std::vector set_transformation_and_get_all_intersections(std::size_t mesh_id, const Aff_transformation_3& aff_trans) @@ -134,23 +132,16 @@ public: set_transformation(mesh_id, aff_trans); std::vector res; - // TODO: use a non-naive version -#ifdef CGAL_USE_BOX_INTERSECTION_D - std::vector boxes; - std::vector query; - for(std::size_t k=0; k > res; + std::vector > res; +#if CGAL_USE_BOX_INTERSECTION_D + for(std::size_t k=0; kdo_intersect( *m_aabb_trees[mesh_id] ) ) + res.push_back(std::make_pair(k, false)); + } + +#else // TODO: use a non-naive version for(std::size_t k=0; k Date: Fri, 27 Jul 2018 11:25:45 +0200 Subject: [PATCH 37/84] Fix plugin and WIP make precompute boxes --- .../AABB_tree/Do_trees_intersect_plugin.cpp | 42 +++++++------------ .../CGAL/Rigid_mesh_collision_detection.h | 19 +++++++++ 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp index bd2aa4c839e..bec8630094e 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp @@ -32,7 +32,7 @@ public: QKeyEvent * e = static_cast(event); if (e->key()==Qt::Key_W){ do_transparency = !do_transparency; - update_trees(); + change_display(); return true; } return false; @@ -136,15 +136,6 @@ private Q_SLOTS: } col_det = new CGAL::Rigid_mesh_collision_detection(meshes); init_trees(); - if(do_transparency) - { - items.back()->setRenderingMode(Flat); - items.back()->setAlpha(120); - } - else - { - items.back()->setRenderingMode(Wireframe); - } static_cast( CGAL::QGLViewer::QGLViewerPool().first())->installEventFilter(this); QApplication::restoreOverrideCursor(); @@ -278,15 +269,6 @@ public Q_SLOTS: } Scene_movable_sm_item* item = items[id]; item->setColor(QColor(Qt::green)); - /*if(do_transparency) - { - item->setRenderingMode(Flat); - item->setAlpha(120); - } - else - { - item->setRenderingMode(Wireframe); - }*/ item->itemChanged(); } prev_ids.clear(); @@ -315,15 +297,7 @@ public Q_SLOTS: items[id]->setColor(QColor(Qt::red)); prev_ids.push_back(id); } - /* if(do_transparency) - { - sel_item->setRenderingMode(Flat); - sel_item->setAlpha(120); - } - else - { - sel_item->setRenderingMode(Wireframe); - }*/ + /* */ prev_ids.push_back(sel_id); sel_item->itemChanged(); viewer->update(); @@ -344,6 +318,18 @@ public Q_SLOTS: //switch transparent/wireframe. void change_display() { + for(Scene_movable_sm_item* item : items) + { + if(do_transparency) + { + item->setRenderingMode(Flat); + item->setAlpha(120); + } + else + { + item->setRenderingMode(Wireframe); + } + } } private: diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index 655488191e9..d1cafe0cbdc 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -171,6 +171,25 @@ public: //TODO: think about an alternative that is using a traversal traits if ( m_aabb_trees[k]->do_intersect( *m_aabb_trees[mesh_id] ) ) res.push_back(std::make_pair(k, false)); + else{ + if (m_is_closed[mesh_id]) + { + Side_of_tm side_of_mid(*m_aabb_trees[mesh_id]); + typename Kernel::Point_3 q = get(boost::vertex_point, *m_triangle_mesh_ptrs[k], *boost::begin(vertices(*m_triangle_mesh_ptrs[k]))); + if(side_of_mid(m_aabb_trees[k]->traits().transformation()( q )) == CGAL::ON_BOUNDED_SIDE) + { + res.push_back(std::make_pair(k, true)); + continue; + } + } + if (m_is_closed[k]) + { + Side_of_tm side_of_mk(*m_aabb_trees[k]); + typename Kernel::Point_3 q = get(boost::vertex_point, *m_triangle_mesh_ptrs[mesh_id], *boost::begin(vertices(*m_triangle_mesh_ptrs[mesh_id]))); + if(side_of_mk(m_aabb_trees[mesh_id]->traits().transformation()( q )) == CGAL::ON_BOUNDED_SIDE) + res.push_back(std::make_pair(k, true)); + } + } } #else From 939e14561fd316437018e89c5400b03a10e45a75 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 27 Jul 2018 12:01:51 +0200 Subject: [PATCH 38/84] clean-up --- .../CGAL/Rigid_mesh_collision_detection.h | 84 +++++-------------- 1 file changed, 23 insertions(+), 61 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index d1cafe0cbdc..b2f77a5c52e 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -30,9 +30,8 @@ #include #include #include -#include -#define CGAL_USE_BOX_INTERSECTION_D 1 +#define CGAL_CASH_BOXES 0 namespace CGAL { template @@ -48,20 +47,10 @@ class Rigid_mesh_collision_detection // TODO: we probably want an option with external trees std::vector m_aabb_trees; std::vector m_is_closed; -#if CGAL_USE_BOX_INTERSECTION_D - struct Callback{ - typedef typename CGAL::Box_intersection_d::Box_with_info_d Bbox; - std::vector& res; - Callback(std::vector& res) - :res(res){} - void operator()(const Bbox& , - const Bbox& b) - { - res.push_back(b.info()); - } - }; - std::vector m_tree_boxes; +#if CGAL_CASH_BOXES + std::vector m_tree_boxes; #endif + public: template @@ -81,7 +70,7 @@ public: m_triangle_mesh_ptrs.reserve( triangle_meshes.size() ); m_aabb_trees.reserve( triangle_meshes.size() ); m_is_closed.resize(triangle_meshes.size(), false); -#if CGAL_USE_BOX_INTERSECTION_D +#if CGAL_CASH_BOXES m_tree_boxes.reserve( triangle_meshes.size() ); #endif BOOST_FOREACH(const TriangleMesh& tm, triangle_meshes) @@ -91,7 +80,7 @@ public: m_triangle_mesh_ptrs.push_back( &tm ); Tree* t = new Tree(faces(tm).begin(), faces(tm).end(), tm); m_aabb_trees.push_back(t); -#if CGAL_USE_BOX_INTERSECTION_D +#if CGAL_CASH_BOXES m_tree_boxes.push_back(internal::get_tree_bbox(*t)); #endif } @@ -101,7 +90,11 @@ public: { m_is_closed.push_back(is_closed(tm)); m_triangle_mesh_ptrs.push_back( &tm ); - m_aabb_trees.push_back(new Tree(faces(tm).begin(), faces(tm).end(), tm)); + Tree* t = new Tree(faces(tm).begin(), faces(tm).end(), tm); + m_aabb_trees.push_back(t); +#if CGAL_CASH_BOXES + m_tree_boxes.push_back(internal::get_tree_bbox(*t)); +#endif } void remove_mesh(std::size_t mesh_id) @@ -110,13 +103,16 @@ public: m_triangle_mesh_ptrs.erase( m_triangle_mesh_ptrs.begin()+mesh_id ); m_aabb_trees.erase( m_aabb_trees.begin()+mesh_id); m_is_closed.erase(m_is_closed.begin()+mesh_id); +#if CGAL_CASH_BOXES + m_tree_boxes.erase(m_tree_boxes.begin()+mesh_id); +#endif } void set_transformation(std::size_t mesh_id, const Aff_transformation_3& aff_trans) { m_aabb_trees[mesh_id]->traits().set_transformation(aff_trans); -#if CGAL_USE_BOX_INTERSECTION_D +#if CGAL_CASH_BOXES m_tree_boxes[mesh_id] = internal::get_tree_bbox(*m_aabb_trees[mesh_id]); #endif @@ -132,26 +128,19 @@ public: set_transformation(mesh_id, aff_trans); std::vector res; -#if CGAL_USE_BOX_INTERSECTION_D -// Callback callback(res); -// m_tree_boxes.swap(m_tree_boxes.begin()+mesh_id, m_tree_boxes.end() -1); -// CGAL::box_intersection_d( -// m_tree_boxes, m_tree_boxes+m_aabb_trees.size()-1, -// m_tree_boxes.end()-1, -// m_tree_boxes.end(), -// callback); -// m_tree_boxes.swap(m_tree_boxes.begin()+mesh_id, m_tree_boxes.end() -1); -#else + for(std::size_t k=0; kdo_intersect( *m_aabb_trees[mesh_id] ) ) res.push_back(k); } -#endif return res; } @@ -163,40 +152,14 @@ public: set_transformation(mesh_id, aff_trans); std::vector > res; -#if CGAL_USE_BOX_INTERSECTION_D - for(std::size_t k=0; kdo_intersect( *m_aabb_trees[mesh_id] ) ) - res.push_back(std::make_pair(k, false)); - else{ - if (m_is_closed[mesh_id]) - { - Side_of_tm side_of_mid(*m_aabb_trees[mesh_id]); - typename Kernel::Point_3 q = get(boost::vertex_point, *m_triangle_mesh_ptrs[k], *boost::begin(vertices(*m_triangle_mesh_ptrs[k]))); - if(side_of_mid(m_aabb_trees[k]->traits().transformation()( q )) == CGAL::ON_BOUNDED_SIDE) - { - res.push_back(std::make_pair(k, true)); - continue; - } - } - if (m_is_closed[k]) - { - Side_of_tm side_of_mk(*m_aabb_trees[k]); - typename Kernel::Point_3 q = get(boost::vertex_point, *m_triangle_mesh_ptrs[mesh_id], *boost::begin(vertices(*m_triangle_mesh_ptrs[mesh_id]))); - if(side_of_mk(m_aabb_trees[mesh_id]->traits().transformation()( q )) == CGAL::ON_BOUNDED_SIDE) - res.push_back(std::make_pair(k, true)); - } - } - } - -#else + // TODO: use a non-naive version for(std::size_t k=0; kdo_intersect( *m_aabb_trees[mesh_id] ) ) res.push_back(std::make_pair(k, false)); @@ -220,7 +183,6 @@ public: } } } -#endif return res; } }; From beaded520d729c99ab1e96ee618ce9c5512a666a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 27 Jul 2018 12:16:56 +0200 Subject: [PATCH 39/84] add missing protectors and clean-up --- .../AABB_tree/Do_trees_intersect_plugin.cpp | 1 + .../CGAL/Rigid_mesh_collision_detection.h | 26 ++++++++----------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp index bec8630094e..416c93d1ba6 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "Messages_interface.h" #include diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index b2f77a5c52e..ab6c554f3d2 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -50,7 +50,7 @@ class Rigid_mesh_collision_detection #if CGAL_CASH_BOXES std::vector m_tree_boxes; #endif - + public: template @@ -72,6 +72,7 @@ public: m_is_closed.resize(triangle_meshes.size(), false); #if CGAL_CASH_BOXES m_tree_boxes.reserve( triangle_meshes.size() ); + Interval_nt_advanced::Protector protector; #endif BOOST_FOREACH(const TriangleMesh& tm, triangle_meshes) { @@ -93,10 +94,11 @@ public: Tree* t = new Tree(faces(tm).begin(), faces(tm).end(), tm); m_aabb_trees.push_back(t); #if CGAL_CASH_BOXES - m_tree_boxes.push_back(internal::get_tree_bbox(*t)); + Interval_nt_advanced::Protector protector; + m_tree_boxes.push_back(internal::get_tree_bbox(*t)); #endif } - + void remove_mesh(std::size_t mesh_id) { if(mesh_id >= m_triangle_mesh_ptrs.size()) return; @@ -104,21 +106,18 @@ public: m_aabb_trees.erase( m_aabb_trees.begin()+mesh_id); m_is_closed.erase(m_is_closed.begin()+mesh_id); #if CGAL_CASH_BOXES - m_tree_boxes.erase(m_tree_boxes.begin()+mesh_id); + m_tree_boxes.erase(m_tree_boxes.begin()+mesh_id); #endif - + } - + void set_transformation(std::size_t mesh_id, const Aff_transformation_3& aff_trans) { m_aabb_trees[mesh_id]->traits().set_transformation(aff_trans); #if CGAL_CASH_BOXES m_tree_boxes[mesh_id] = internal::get_tree_bbox(*m_aabb_trees[mesh_id]); #endif - } - - std::vector set_transformation_and_get_all_intersections(std::size_t mesh_id, @@ -128,9 +127,6 @@ public: set_transformation(mesh_id, aff_trans); std::vector res; - - - for(std::size_t k=0; k > set_transformation_and_get_all_intersections_and_inclusions(std::size_t mesh_id, const Aff_transformation_3& aff_trans) @@ -157,7 +153,7 @@ public: for(std::size_t k=0; k Date: Fri, 27 Jul 2018 14:18:53 +0200 Subject: [PATCH 40/84] Fix Orange item. --- AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp index 416c93d1ba6..50c6e5cd187 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp @@ -175,6 +175,7 @@ public Q_SLOTS: { ++mesh_id; item->setColor(QColor(255,184,61)); + prev_ids.push_back(sel_id); continue; } const double* matrix = item->manipulatedFrame()->matrix(); @@ -224,6 +225,7 @@ public Q_SLOTS: items[id]->setColor(QColor(Qt::blue)); else items[id]->setColor(QColor(Qt::red)); + prev_ids.push_back(id); } if(do_transparency) { @@ -298,7 +300,6 @@ public Q_SLOTS: items[id]->setColor(QColor(Qt::red)); prev_ids.push_back(id); } - /* */ prev_ids.push_back(sel_id); sel_item->itemChanged(); viewer->update(); From 5f50f5d7e9e464ac05377ab5ca6b051149b9032c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 27 Jul 2018 15:24:58 +0200 Subject: [PATCH 41/84] add protector and API without deformation I added a bitset to avoid changing the rounding-mode too often --- .../CGAL/Rigid_mesh_collision_detection.h | 120 +++++++++++++----- 1 file changed, 86 insertions(+), 34 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index ab6c554f3d2..f90494e647f 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -31,7 +31,14 @@ #include #include -#define CGAL_CASH_BOXES 0 +#ifndef CGAL_CACHE_BOXES +#define CGAL_CACHE_BOXES 0 +#endif + +#if CGAL_CACHE_BOXES +#include +#endif + namespace CGAL { template @@ -47,10 +54,18 @@ class Rigid_mesh_collision_detection // TODO: we probably want an option with external trees std::vector m_aabb_trees; std::vector m_is_closed; -#if CGAL_CASH_BOXES - std::vector m_tree_boxes; +#if CGAL_CACHE_BOXES + boost::dynamic_bitset<> m_bboxes_is_invalid; + std::vector m_bboxes; #endif + void clear_trees() + { + BOOST_FOREACH(Tree* tree, m_aabb_trees){ + delete tree; + } + m_aabb_trees.clear(); + } public: template @@ -58,21 +73,26 @@ public: { init(triangle_meshes); } + ~Rigid_mesh_collision_detection() { - BOOST_FOREACH(Tree* tree, m_aabb_trees){ - delete tree; - } + clear_trees(); } template void init(const MeshRange& triangle_meshes) { - m_triangle_mesh_ptrs.reserve( triangle_meshes.size() ); - m_aabb_trees.reserve( triangle_meshes.size() ); - m_is_closed.resize(triangle_meshes.size(), false); -#if CGAL_CASH_BOXES - m_tree_boxes.reserve( triangle_meshes.size() ); - Interval_nt_advanced::Protector protector; + std::size_t nb_meshes = triangle_meshes.size(); + m_triangle_mesh_ptrs.clear(); + m_triangle_mesh_ptrs.reserve(nb_meshes); + clear_trees(); + m_aabb_trees.reserve(nb_meshes); + m_is_closed.clear(); + m_is_closed.resize(nb_meshes, false); +#if CGAL_CACHE_BOXES + m_bboxes_is_invalid.clear(); + m_bboxes_is_invalid.resize(nb_meshes, true); + m_bboxes.clear(); + m_bboxes.resize(nb_meshes); #endif BOOST_FOREACH(const TriangleMesh& tm, triangle_meshes) { @@ -81,9 +101,6 @@ public: m_triangle_mesh_ptrs.push_back( &tm ); Tree* t = new Tree(faces(tm).begin(), faces(tm).end(), tm); m_aabb_trees.push_back(t); -#if CGAL_CASH_BOXES - m_tree_boxes.push_back(internal::get_tree_bbox(*t)); -#endif } } @@ -93,9 +110,9 @@ public: m_triangle_mesh_ptrs.push_back( &tm ); Tree* t = new Tree(faces(tm).begin(), faces(tm).end(), tm); m_aabb_trees.push_back(t); -#if CGAL_CASH_BOXES - Interval_nt_advanced::Protector protector; - m_tree_boxes.push_back(internal::get_tree_bbox(*t)); +#if CGAL_CACHE_BOXES + m_bboxes.push_back(Bbox_3()); + m_bboxes_is_invalid.resize(m_bboxes_is_invalid.size()+1, true); #endif } @@ -105,33 +122,50 @@ public: m_triangle_mesh_ptrs.erase( m_triangle_mesh_ptrs.begin()+mesh_id ); m_aabb_trees.erase( m_aabb_trees.begin()+mesh_id); m_is_closed.erase(m_is_closed.begin()+mesh_id); -#if CGAL_CASH_BOXES - m_tree_boxes.erase(m_tree_boxes.begin()+mesh_id); +#if CGAL_CACHE_BOXES + // TODO this is a lazy approach that is not optimal + m_bboxes.pop_back(); + m_bboxes_is_invalid.set(); + m_bboxes_is_invalid.resize(m_triangle_mesh_ptrs.size()); #endif - } void set_transformation(std::size_t mesh_id, const Aff_transformation_3& aff_trans) { m_aabb_trees[mesh_id]->traits().set_transformation(aff_trans); -#if CGAL_CASH_BOXES - m_tree_boxes[mesh_id] = internal::get_tree_bbox(*m_aabb_trees[mesh_id]); +#if CGAL_CACHE_BOXES + m_bboxes_is_invalid.set(mesh_id); #endif } +#if CGAL_CACHE_BOXES + void update_bboxes() + { + // protector is supposed to have been set + for (boost::dynamic_bitset<>::size_type i = m_bboxes.find_first(); + i != m_bboxes_is_invalid.npos; + i = m_bboxes_is_invalid.find_next(i)) + { + m_bboxes[i]=internal::get_tree_bbox(*m_aabb_trees[i]); + } + m_bboxes_is_invalid.reset(); + } +#endif + std::vector - set_transformation_and_get_all_intersections(std::size_t mesh_id, - const Aff_transformation_3& aff_trans) + get_all_intersections(std::size_t mesh_id) { CGAL::Interval_nt_advanced::Protector protector; - set_transformation(mesh_id, aff_trans); +#if CGAL_CACHE_BOXES + update_bboxes(); +#endif std::vector res; for(std::size_t k=0; kdo_intersect( *m_aabb_trees[mesh_id] ) ) @@ -140,21 +174,30 @@ public: return res; } - std::vector > - set_transformation_and_get_all_intersections_and_inclusions(std::size_t mesh_id, - const Aff_transformation_3& aff_trans) + std::vector + set_transformation_and_get_all_intersections(std::size_t mesh_id, + const Aff_transformation_3& aff_trans) { CGAL::Interval_nt_advanced::Protector protector; set_transformation(mesh_id, aff_trans); - std::vector > res; + return get_all_intersections(mesh_id); + } + std::vector > + get_all_intersections_and_inclusions(std::size_t mesh_id) + { + CGAL::Interval_nt_advanced::Protector protector; +#if CGAL_CACHE_BOXES + update_bboxes(); +#endif + std::vector > res; // TODO: use a non-naive version for(std::size_t k=0; kdo_intersect( *m_aabb_trees[mesh_id] ) ) @@ -181,6 +224,15 @@ public: } return res; } + + std::vector > + set_transformation_and_get_all_intersections_and_inclusions(std::size_t mesh_id, + const Aff_transformation_3& aff_trans) + { + CGAL::Interval_nt_advanced::Protector protector; + set_transformation(mesh_id, aff_trans); + return get_all_intersections_and_inclusions(mesh_id); + } }; } // end of CGAL namespace From 2f774548820fd321801c211989c170aa03961bcb Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 27 Jul 2018 16:30:35 +0200 Subject: [PATCH 42/84] Fix clean-up() --- AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp index 50c6e5cd187..2a713f4991c 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp @@ -313,6 +313,7 @@ public Q_SLOTS: group_item = nullptr; items.clear(); meshes.clear(); + prev_ids.clear(); delete col_det; col_det = nullptr; } From af39d7f2d273ea44f35613f8363815db8597b2af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 23 Aug 2018 09:13:44 +0200 Subject: [PATCH 43/84] delete the tree when removing a mesh --- .../include/CGAL/Rigid_mesh_collision_detection.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index f90494e647f..57a47f01dee 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -120,6 +120,7 @@ public: { if(mesh_id >= m_triangle_mesh_ptrs.size()) return; m_triangle_mesh_ptrs.erase( m_triangle_mesh_ptrs.begin()+mesh_id ); + delete m_aabb_trees[mesh_id]; m_aabb_trees.erase( m_aabb_trees.begin()+mesh_id); m_is_closed.erase(m_is_closed.begin()+mesh_id); #if CGAL_CACHE_BOXES From 7f65916f54232bc972f187fcfbbdf44f24650563 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 23 Aug 2018 09:47:33 +0200 Subject: [PATCH 44/84] add the possibility to specify with which models to do the intersection test --- .../CGAL/Rigid_mesh_collision_detection.h | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index 57a47f01dee..4e669bd1f55 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -31,6 +31,8 @@ #include #include +#include + #ifndef CGAL_CACHE_BOXES #define CGAL_CACHE_BOXES 0 #endif @@ -153,8 +155,9 @@ public: } #endif + template std::vector - get_all_intersections(std::size_t mesh_id) + get_all_intersections(std::size_t mesh_id, const MeshRangeIds& ids) { CGAL::Interval_nt_advanced::Protector protector; #if CGAL_CACHE_BOXES @@ -162,7 +165,7 @@ public: #endif std::vector res; - for(std::size_t k=0; k + get_all_intersections(std::size_t mesh_id) + { + return get_all_intersections( + mesh_id, + make_range(boost::make_counting_iterator(0), + boost::make_counting_iterator(m_aabb_trees.size()))); + } + std::vector set_transformation_and_get_all_intersections(std::size_t mesh_id, const Aff_transformation_3& aff_trans) @@ -184,8 +196,9 @@ public: return get_all_intersections(mesh_id); } + template std::vector > - get_all_intersections_and_inclusions(std::size_t mesh_id) + get_all_intersections_and_inclusions(std::size_t mesh_id, const MeshRangeIds& ids) { CGAL::Interval_nt_advanced::Protector protector; #if CGAL_CACHE_BOXES @@ -194,7 +207,7 @@ public: std::vector > res; // TODO: use a non-naive version - for(std::size_t k=0; k > + get_all_intersections_and_inclusions(std::size_t mesh_id) + { + return get_all_intersections_and_inclusions( + mesh_id, + make_range(boost::make_counting_iterator(0), + boost::make_counting_iterator(m_aabb_trees.size()))); + } + std::vector > set_transformation_and_get_all_intersections_and_inclusions(std::size_t mesh_id, const Aff_transformation_3& aff_trans) From 773413985ac0f2e36ccb654dad0eba0f883f9ed4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 23 Aug 2018 11:22:00 +0200 Subject: [PATCH 45/84] handle meshes with several CC for inclusion --- .../CGAL/Rigid_mesh_collision_detection.h | 66 +++++++++++++++++-- 1 file changed, 59 insertions(+), 7 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index 4e669bd1f55..8e7b4215a8e 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -28,8 +28,10 @@ #include #include #include +#include #include #include +#include #include @@ -43,6 +45,7 @@ namespace CGAL { +//TODO handle vertex point point in the API template class Rigid_mesh_collision_detection { @@ -56,6 +59,8 @@ class Rigid_mesh_collision_detection // TODO: we probably want an option with external trees std::vector m_aabb_trees; std::vector m_is_closed; + std::vector< std::vector > m_points_per_cc; + #if CGAL_CACHE_BOXES boost::dynamic_bitset<> m_bboxes_is_invalid; std::vector m_bboxes; @@ -69,11 +74,45 @@ class Rigid_mesh_collision_detection m_aabb_trees.clear(); } + void add_cc_points(const TriangleMesh& tm, bool assume_one_CC) + { + m_points_per_cc.resize(m_points_per_cc.size()+1); + if (!assume_one_CC) + { + std::vector CC_ids(num_faces(tm)); + + // TODO use dynamic property if no defaut fid is available + typename boost::property_map::type fid_map + = get(boost::face_index, tm); + + std::size_t nb_cc = + Polygon_mesh_processing::connected_components( + tm, bind_property_maps(fid_map, make_property_map(CC_ids)) ); + if (nb_cc != 1) + { + typedef boost::graph_traits GrT; + std::vector vertex_per_cc(nb_cc, GrT::null_vertex()); + + BOOST_FOREACH(typename GrT::face_descriptor f, faces(tm)) + { + if (vertex_per_cc[get(fid_map, f)]!=GrT::null_vertex()) + { + m_points_per_cc.back().push_back( + get(boost::vertex_point, tm, target( halfedge(f, tm), tm)) ); + } + } + return; + } + } + // only one CC + m_points_per_cc.back().push_back( get(boost::vertex_point, tm, *boost::begin(vertices(tm))) ); + } + public: template - Rigid_mesh_collision_detection(const MeshRange& triangle_meshes) + Rigid_mesh_collision_detection(const MeshRange& triangle_meshes, bool assume_one_CC_per_mesh = false) { - init(triangle_meshes); + init(triangle_meshes, assume_one_CC_per_mesh); } ~Rigid_mesh_collision_detection() @@ -81,11 +120,13 @@ public: clear_trees(); } template - void init(const MeshRange& triangle_meshes) + void init(const MeshRange& triangle_meshes, bool assume_one_CC) { std::size_t nb_meshes = triangle_meshes.size(); m_triangle_mesh_ptrs.clear(); m_triangle_mesh_ptrs.reserve(nb_meshes); + m_points_per_cc.clear(); + m_points_per_cc.reserve(nb_meshes); clear_trees(); m_aabb_trees.reserve(nb_meshes); m_is_closed.clear(); @@ -103,10 +144,11 @@ public: m_triangle_mesh_ptrs.push_back( &tm ); Tree* t = new Tree(faces(tm).begin(), faces(tm).end(), tm); m_aabb_trees.push_back(t); + add_cc_points(tm, assume_one_CC); } } - void add_mesh(const TriangleMesh& tm) + void add_mesh(const TriangleMesh& tm, bool assume_one_CC_per_mesh = false) { m_is_closed.push_back(is_closed(tm)); m_triangle_mesh_ptrs.push_back( &tm ); @@ -116,6 +158,7 @@ public: m_bboxes.push_back(Bbox_3()); m_bboxes_is_invalid.resize(m_bboxes_is_invalid.size()+1, true); #endif + add_cc_points(tm, assume_one_CC_per_mesh); } void remove_mesh(std::size_t mesh_id) @@ -125,6 +168,7 @@ public: delete m_aabb_trees[mesh_id]; m_aabb_trees.erase( m_aabb_trees.begin()+mesh_id); m_is_closed.erase(m_is_closed.begin()+mesh_id); + m_points_per_cc.erase(m_points_per_cc.begin()+mesh_id); #if CGAL_CACHE_BOXES // TODO this is a lazy approach that is not optimal m_bboxes.pop_back(); @@ -196,6 +240,9 @@ public: return get_all_intersections(mesh_id); } + // TODO: document that is a model is composed of several CC on one of them is not closed, + // no inclusion test will be made + // TODO: document that the inclusion can be partial in case there are several CC template std::vector > get_all_intersections_and_inclusions(std::size_t mesh_id, const MeshRangeIds& ids) @@ -230,9 +277,14 @@ public: if (m_is_closed[k]) { Side_of_tm side_of_mk(*m_aabb_trees[k]); - typename Kernel::Point_3 q = get(boost::vertex_point, *m_triangle_mesh_ptrs[mesh_id], *boost::begin(vertices(*m_triangle_mesh_ptrs[mesh_id]))); - if(side_of_mk(m_aabb_trees[mesh_id]->traits().transformation()( q )) == CGAL::ON_BOUNDED_SIDE) - res.push_back(std::make_pair(k, true)); + BOOST_FOREACH(const typename Kernel::Point_3 q, m_points_per_cc[mesh_id]) + { + if(side_of_mk(m_aabb_trees[mesh_id]->traits().transformation()( q )) == CGAL::ON_BOUNDED_SIDE) + { + res.push_back(std::make_pair(k, true)); + break; + } + } } } } From d7e7c747822117002e57c5f0f6ce63fd3b59aab2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 23 Aug 2018 15:34:04 +0200 Subject: [PATCH 46/84] fix inclusion test --- .../include/CGAL/Rigid_mesh_collision_detection.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index 8e7b4215a8e..abd4a9e6991 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -267,17 +267,22 @@ public: if (m_is_closed[mesh_id]) { Side_of_tm side_of_mid(*m_aabb_trees[mesh_id]); - typename Kernel::Point_3 q = get(boost::vertex_point, *m_triangle_mesh_ptrs[k], *boost::begin(vertices(*m_triangle_mesh_ptrs[k]))); - if(side_of_mid(m_aabb_trees[k]->traits().transformation()( q )) == CGAL::ON_BOUNDED_SIDE) + bool stop = false; + BOOST_FOREACH(const typename Kernel::Point_3& q, m_points_per_cc[k]) { - res.push_back(std::make_pair(k, true)); - continue; + if(side_of_mid(m_aabb_trees[k]->traits().transformation()( q )) == CGAL::ON_BOUNDED_SIDE) + { + res.push_back(std::make_pair(k, true)); + stop=true; + break; + } } + if (stop) continue; } if (m_is_closed[k]) { Side_of_tm side_of_mk(*m_aabb_trees[k]); - BOOST_FOREACH(const typename Kernel::Point_3 q, m_points_per_cc[mesh_id]) + BOOST_FOREACH(const typename Kernel::Point_3& q, m_points_per_cc[mesh_id]) { if(side_of_mk(m_aabb_trees[mesh_id]->traits().transformation()( q )) == CGAL::ON_BOUNDED_SIDE) { From df15af614d98f1e8d736e2fd00a06a1f94f3976b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 24 Aug 2018 10:51:21 +0200 Subject: [PATCH 47/84] use a traversal traits instead of a pseudo model of AABBTraits --- .../AABB_do_intersect_transform_traits.h | 305 +++++++++++------- .../Point_inside_vertical_ray_cast.h | 48 ++- .../Ray_3_Triangle_3_traversal_traits.h | 63 ++-- .../CGAL/Rigid_mesh_collision_detection.h | 67 ++-- 4 files changed, 284 insertions(+), 199 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h index e690e003f91..098dd521ef8 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h @@ -1,4 +1,3 @@ - // Copyright (c) 2018 GeometryFactory (France). // All rights reserved. // @@ -19,6 +18,7 @@ // // // Author(s) : Maxime Gimeno +// Sebastien Loriot // #ifndef CGAL_AABB_DO_INTERSECT_TRANSFORM_TRAITS_H @@ -38,204 +38,263 @@ #include #include -/// \file AABB_do_intersect_transform_traits.h - namespace CGAL { -template -class AABB_do_intersect_transform_traits: - public AABB_traits +template +class Traversal_traits_with_transformation_helper { - mutable Aff_transformation_3 m_transfo; - mutable bool has_rotation; - typedef AABB_traits BaseTraits; - typedef AABB_do_intersect_transform_traits Self; - - void set_transformation(const Aff_transformation_3& trans, CGAL::Tag_true) const - { - has_rotation = (trans.m(0,1) != 0 - || trans.m(0,2) != 0 - || trans.m(1,0) != 0 - || trans.m(1,2) != 0 - || trans.m(2,0) != 0 - || trans.m(2,1) !=0); - } - void set_transformation(const Aff_transformation_3& trans, CGAL::Tag_false) const - {} Bbox_3 - compute_transformed_bbox_impl(const Bbox_3& bbox, Tag_true) const + compute_transformed_bbox_impl(const CGAL::Aff_transformation_3& at, + const Bbox_3& bbox, + bool has_rotation, + /*SUPPORTS_ROTATION*/ Tag_true) const { + CGAL_expensive_assertion(FPU_get_cw() == CGAL_FE_UPWARD); + if(!has_rotation) - return compute_transformed_bbox_impl(bbox, Tag_false()); + return compute_transformed_bbox_impl(at, bbox, has_rotation, Tag_false()); typedef Simple_cartesian AK; typedef Cartesian_converter C2F; C2F c2f; - AK::Aff_transformation_3 af = c2f(m_transfo); + AK::Aff_transformation_3 a_at = c2f(at); AK::FT xtrm[6] = { c2f(bbox.min(0)), c2f(bbox.max(0)), c2f(bbox.min(1)), c2f(bbox.max(1)), c2f(bbox.min(2)), c2f(bbox.max(2)) }; typename AK::Point_3 ps[8]; - ps[0] = af( AK::Point_3(xtrm[0], xtrm[2], xtrm[4]) ); - ps[1] = af( AK::Point_3(xtrm[0], xtrm[2], xtrm[5]) ); - ps[2] = af( AK::Point_3(xtrm[0], xtrm[3], xtrm[4]) ); - ps[3] = af( AK::Point_3(xtrm[0], xtrm[3], xtrm[5]) ); + ps[0] = a_at( AK::Point_3(xtrm[0], xtrm[2], xtrm[4]) ); + ps[1] = a_at( AK::Point_3(xtrm[0], xtrm[2], xtrm[5]) ); + ps[2] = a_at( AK::Point_3(xtrm[0], xtrm[3], xtrm[4]) ); + ps[3] = a_at( AK::Point_3(xtrm[0], xtrm[3], xtrm[5]) ); - ps[4] = af( AK::Point_3(xtrm[1], xtrm[2], xtrm[4]) ); - ps[5] = af( AK::Point_3(xtrm[1], xtrm[2], xtrm[5]) ); - ps[6] = af( AK::Point_3(xtrm[1], xtrm[3], xtrm[4]) ); - ps[7] = af( AK::Point_3(xtrm[1], xtrm[3], xtrm[5]) ); + ps[4] = a_at( AK::Point_3(xtrm[1], xtrm[2], xtrm[4]) ); + ps[5] = a_at( AK::Point_3(xtrm[1], xtrm[2], xtrm[5]) ); + ps[6] = a_at( AK::Point_3(xtrm[1], xtrm[3], xtrm[4]) ); + ps[7] = a_at( AK::Point_3(xtrm[1], xtrm[3], xtrm[5]) ); return bbox_3(ps, ps+8); } Bbox_3 - compute_transformed_bbox_impl(const Bbox_3& bbox, Tag_false) const + compute_transformed_bbox_impl(const CGAL::Aff_transformation_3& at, + const Bbox_3& bbox, + bool, + /*SUPPORTS_ROTATION*/ Tag_false) const { + CGAL_expensive_assertion(FPU_get_cw() == CGAL_FE_UPWARD); + typedef Simple_cartesian AK; typedef Cartesian_converter C2F; C2F c2f; - AK::Aff_transformation_3 af = c2f(m_transfo); + AK::Aff_transformation_3 a_at = c2f(at); AK::FT xtrm[6] = { c2f(bbox.min(0)), c2f(bbox.max(0)), c2f(bbox.min(1)), c2f(bbox.max(1)), c2f(bbox.min(2)), c2f(bbox.max(2)) }; typename AK::Point_3 ps[2]; - ps[0] = af( AK::Point_3(xtrm[0], xtrm[2], xtrm[4]) ); - ps[1] = af( AK::Point_3(xtrm[1], xtrm[3], xtrm[5]) ); + ps[0] = a_at( AK::Point_3(xtrm[0], xtrm[2], xtrm[4]) ); + ps[1] = a_at( AK::Point_3(xtrm[1], xtrm[3], xtrm[5]) ); return bbox_3(ps, ps+2); } + public: - //Constructor - AABB_do_intersect_transform_traits(const Aff_transformation_3& transf = Aff_transformation_3(IDENTITY)) + bool has_rotation(const CGAL::Aff_transformation_3& at) const { - has_rotation = false; - set_transformation(transf, SUPPORTS_ROTATION()); + return ( at.m(0,1) != 0 || at.m(0,2) != 0 || at.m(1,0) != 0 + || at.m(1,2) != 0 || at.m(2,0) != 0 || at.m(2,1) !=0); } - // AABBTraits concept types - typedef typename BaseTraits::Point_3 Point_3; - typedef typename BaseTraits::Primitive Primitive; - typedef typename BaseTraits::Bounding_box Bounding_box; + Bbox_3 + compute_transformed_bbox(const CGAL::Aff_transformation_3& at, + const Bbox_3& bbox, + bool has_rotation) const + { + return compute_transformed_bbox_impl(at, bbox, has_rotation, SUPPORTS_ROTATION()); + } +}; - // helper functions +// traversal traits for a tree vs a primitive +template +class Do_intersect_traversal_traits_with_transformation + : public Traversal_traits_with_transformation_helper +{ + typedef typename AABBTraits::Primitive Primitive; + typedef ::CGAL::AABB_node Node; + typedef Traversal_traits_with_transformation_helper Base; + + void register_transformation(CGAL::Tag_true) + { + m_has_rotation = this->has_rotation(m_transfo); + } + + void register_transformation(CGAL::Tag_false) + {} + +public: + + Do_intersect_traversal_traits_with_transformation(const AABBTraits& traits) + : m_is_found(false), m_traits(traits), m_has_rotation(false) + { + } + + bool go_further() const { return !m_is_found; } + + template + void intersection(const Query& query, const Primitive& primitive) + { + if( CGAL::do_intersect(query, + internal::Primitive_helper::get_datum(primitive, m_traits).transform(m_transfo)) ) + m_is_found = true; + } + + template + bool do_intersect(const Query& query, const Node& node) const + { + return m_traits.do_intersect_object()(query, compute_transformed_bbox(node.bbox())); + } + + bool is_intersection_found() const { return m_is_found; } + + void reset() + { + m_is_found = false; + } + + const Aff_transformation_3& + transformation() const + { + return m_transfo; + } + + void set_transformation(const Aff_transformation_3& transfo) + { + m_transfo = transfo; + register_transformation(SUPPORTS_ROTATION()); + } - Bbox_3 compute_transformed_bbox(const Bbox_3& bbox) const { - return compute_transformed_bbox_impl(bbox, SUPPORTS_ROTATION()); + return Base::compute_transformed_bbox(m_transfo, bbox, m_has_rotation); } - // Do_intersect predicate - class Do_intersect - : BaseTraits::Do_intersect + // helper for Point_inside_vertical_ray_cast + class Transformed_tree_helper { - typedef AABB_do_intersect_transform_traits AABBTraits; - const AABBTraits& m_traits; - typedef typename BaseTraits::Do_intersect Base; + typedef AABB_tree Tree; + typedef CGAL::AABB_node Node; + typedef Do_intersect_traversal_traits_with_transformation Traversal_traits; - Bounding_box - compute_transformed_bbox(const Bounding_box& bbox) const - { - return m_traits.compute_transformed_bbox(bbox); - } + Traversal_traits m_tt; public: - Do_intersect(const AABBTraits& traits) - : Base(static_cast(traits)), - m_traits(traits) + + Transformed_tree_helper(const Traversal_traits& tt) + : m_tt(tt) {} - template - bool operator()(const Query& q, const Bounding_box& bbox) const + Bbox_3 get_tree_bbox(const AABB_tree& tree) const { - return - static_cast(this)->operator()( - q, compute_transformed_bbox(bbox)); + return m_tt.compute_transformed_bbox(tree.bbox()); } - template - bool operator()(const Query& q, const Primitive& pr) const + typename AABBTraits::Primitive::Datum + get_primitive_datum(const typename AABBTraits::Primitive& primitive, const AABBTraits& traits) const { - // transformation is done within Primitive_helper - return do_intersect(q, internal::Primitive_helper::get_datum(pr,m_traits)); + return internal::Primitive_helper::get_datum(primitive, traits).transform(m_tt.transformation()); } - // intersection with AABB-tree - template - bool operator()(const CGAL::AABB_tree& other_tree, const Primitive& pr) const + Bbox_3 get_node_bbox(const Node& node) const { - // transformation is done within Primitive_helper - return other_tree.do_intersect( internal::Primitive_helper::get_datum(pr,m_traits)); - } - - template - bool operator()(const CGAL::AABB_tree& other_tree, const Bounding_box& bbox) const - { - return other_tree.do_intersect(compute_transformed_bbox(bbox)); + return m_tt.compute_transformed_bbox(node.bbox()); } }; - Do_intersect do_intersect_object() const{ - return Do_intersect(*this); - } - - //Specific - void set_transformation(const Aff_transformation_3& trans) const + Transformed_tree_helper get_helper() const { - m_transfo = trans; - set_transformation(trans, SUPPORTS_ROTATION()); + return Transformed_tree_helper(*this); } - const Aff_transformation_3& transformation() const { return m_transfo; } +private: + bool m_is_found; + const AABBTraits& m_traits; + Aff_transformation_3 m_transfo; + bool m_has_rotation; }; -namespace internal { -template -struct Primitive_helper ,true>{ - -typedef AABB_do_intersect_transform_traits Traits; - - -static typename Traits::Primitive::Datum get_datum(const typename Traits::Primitive& p, - const Traits & traits) +// traversal traits for a tree +template +class Do_intersect_traversal_traits_for_two_trees + : public Traversal_traits_with_transformation_helper { - return p.datum(traits.shared_data()).transform(traits.transformation()); -} + typedef typename AABBTraits::Primitive Primitive; + typedef ::CGAL::AABB_node Node; + typedef Traversal_traits_with_transformation_helper Base; -static typename Traits::Point_3 get_reference_point(const typename Traits::Primitive& p,const Traits& traits) { - return p.reference_point(traits.shared_data()).transform(traits.transformation()); -} + void register_transformation(CGAL::Tag_true) + { + m_has_rotation = this->has_rotation(m_transfo); + } + void register_transformation(CGAL::Tag_false) + {} + + Bbox_3 + compute_transformed_bbox(const Bbox_3& bbox) const + { + return Base::compute_transformed_bbox(m_transfo, bbox, m_has_rotation); + } + +public: + Do_intersect_traversal_traits_for_two_trees(const AABBTraits& traits, + const Aff_transformation_3& transfo, + Do_intersect_traversal_traits_with_transformation& query_traversal_traits) + : m_is_found(false) + , m_traits(traits) + , m_transfo(transfo) + , m_has_rotation(false) + , m_query_traversal_traits(query_traversal_traits) + + { + register_transformation(SUPPORTS_ROTATION()); + } + + bool go_further() const { return !m_is_found; } + + void intersection(const AABB_tree& query, const Primitive& primitive) + { + query.traversal( internal::Primitive_helper::get_datum(primitive,m_traits).transform(m_transfo), m_query_traversal_traits ); + m_is_found = m_query_traversal_traits.is_intersection_found(); + m_query_traversal_traits.reset(); + } + + bool do_intersect(const AABB_tree& query, const Node& node) const + { + query.traversal( compute_transformed_bbox(node.bbox()), m_query_traversal_traits ); + bool res = m_query_traversal_traits.is_intersection_found(); + m_query_traversal_traits.reset(); + return res; + } + + bool is_intersection_found() const { return m_is_found; } + +private: + bool m_is_found; + const AABBTraits& m_traits; + const Aff_transformation_3& m_transfo; + bool m_has_rotation; + Do_intersect_traversal_traits_with_transformation& m_query_traversal_traits; }; -template -typename CGAL::AABB_tree >::Bounding_box -get_tree_bbox(const CGAL::AABB_tree >& tree) -{ - return tree.traits().compute_transformed_bbox(tree.bbox()); -} - -template -typename CGAL::AABB_tree >::Bounding_box -get_node_bbox(const CGAL::AABB_node >& node, - const AABB_do_intersect_transform_traits& traits) -{ - return traits.compute_transformed_bbox(node.bbox()); -} - -} // end internal - }//end CGAL #endif //CGAL_AABB_AABB_do_intersect_transform_traits_H diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Side_of_triangle_mesh/Point_inside_vertical_ray_cast.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Side_of_triangle_mesh/Point_inside_vertical_ray_cast.h index b3d45194891..2bb77654b4b 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Side_of_triangle_mesh/Point_inside_vertical_ray_cast.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Side_of_triangle_mesh/Point_inside_vertical_ray_cast.h @@ -36,24 +36,32 @@ namespace CGAL { namespace internal { -// added for AABB_do_intersect_transform_traits -template -typename AABBTree::Bounding_box -get_tree_bbox(const AABBTree& tree) +template +struct Default_tree_helper { - return tree.bbox(); -} + typedef typename AABBTree::AABB_traits AABB_traits; + typedef typename CGAL::AABB_node Node; -template -typename AABBNode::Bounding_box -get_node_bbox(const AABBNode& node, const AABBTraits&) -{ - return node.bbox(); -} + Bbox_3 get_tree_bbox(const AABBTree& tree) const + { + return tree.bbox(); + } + + typename AABBTree::Primitive::Datum + get_primitive_datum(const typename AABBTree::Primitive& primitive, const AABB_traits& traits) const + { + return internal::Primitive_helper::get_datum(primitive, traits); + } + + Bbox_3 get_node_bbox(const Node& node) const + { + return node.bbox(); + } +}; // internal class for point inside test, using existing AABB tree -template -class Point_inside_vertical_ray_cast +template > +class Point_inside_vertical_ray_cast { typedef typename Kernel::Point_3 Point; typedef typename Kernel::Ray_3 Ray; @@ -61,14 +69,20 @@ class Point_inside_vertical_ray_cast static const unsigned int seed = 1340818006; + Helper m_helper; + public: + Point_inside_vertical_ray_cast(const Helper& h = Helper()) + : m_helper(h) + {} + Bounded_side operator()( const Point& point, const AABBTree& tree, typename Kernel::Construct_ray_3 ray_functor = Kernel().construct_ray_3_object(), typename Kernel::Construct_vector_3 vector_functor = Kernel().construct_vector_3_object() ) const { - typename Traits::Bounding_box bbox = get_tree_bbox(tree); + typename Traits::Bounding_box bbox = m_helper.get_tree_bbox(tree); if( point.x() < bbox.xmin() || point.x() > bbox.xmax() || point.y() < bbox.ymin() || point.y() > bbox.ymax() @@ -103,8 +117,8 @@ private: std::pair status( boost::logic::tribool(boost::logic::indeterminate), 0); - Ray_3_Triangle_3_traversal_traits > - traversal_traits(status, tree.traits()); + Ray_3_Triangle_3_traversal_traits > + traversal_traits(status, tree.traits(), m_helper); tree.traversal(ray, traversal_traits); diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Side_of_triangle_mesh/Ray_3_Triangle_3_traversal_traits.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Side_of_triangle_mesh/Ray_3_Triangle_3_traversal_traits.h index bbd3eda72cc..c4e94d216f2 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Side_of_triangle_mesh/Ray_3_Triangle_3_traversal_traits.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Side_of_triangle_mesh/Ray_3_Triangle_3_traversal_traits.h @@ -15,7 +15,7 @@ // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0+ -// +// // // Author(s) : Sebastien Loriot @@ -36,7 +36,7 @@ namespace CGAL { namespace internal { -template +template class Ray_3_Triangle_3_traversal_traits { protected: @@ -46,11 +46,13 @@ protected: const AABBTraits& m_aabb_traits; typedef typename AABBTraits::Primitive Primitive; typedef CGAL::AABB_node Node; + Helper m_helper; public: Ray_3_Triangle_3_traversal_traits(std::pair& status, - const AABBTraits& aabb_traits) - :m_status(status),m_stop(false), m_aabb_traits(aabb_traits) + const AABBTraits& aabb_traits, + const Helper& h) + :m_status(status),m_stop(false), m_aabb_traits(aabb_traits), m_helper(h) {m_status.first=true;} bool go_further() const { return !m_stop; } @@ -60,10 +62,8 @@ public: { internal::r3t3_do_intersect_endpoint_position_visitor visitor; std::pair res= - internal::do_intersect( - (internal::Primitive_helper::get_datum(primitive, m_aabb_traits)), - query,Kernel(),visitor); - + internal::do_intersect(m_helper.get_primitive_datum(primitive, m_aabb_traits), query,Kernel(),visitor); + if (res.first){ switch (res.second){ case internal::R3T3_intersection::CROSS_FACET: @@ -79,40 +79,40 @@ public: } } } - + template bool do_intersect(const Query& query, const Node& node) const { - return m_aabb_traits.do_intersect_object()(query, node.bbox()); + return m_aabb_traits.do_intersect_object()(query, m_helper.get_node_bbox(node)); } }; //specialization for vertical ray -template -class Ray_3_Triangle_3_traversal_traits: - public Ray_3_Triangle_3_traversal_traits +template +class Ray_3_Triangle_3_traversal_traits: + public Ray_3_Triangle_3_traversal_traits { - typedef Ray_3_Triangle_3_traversal_traits Base; + typedef Ray_3_Triangle_3_traversal_traits Base; typedef typename Kernel::Point_3 Point; typedef typename Base::Primitive Primitive; typedef CGAL::AABB_node Node; public: - Ray_3_Triangle_3_traversal_traits(std::pair& status, const AABBTraits& aabb_traits) - :Base(status, aabb_traits){} + Ray_3_Triangle_3_traversal_traits(std::pair& status, const AABBTraits& aabb_traits, const TraversalTraits& tt) + :Base(status, aabb_traits, tt){} template bool do_intersect(const Query& query, const Bbox_3& bbox) const { const Point& source=query.point(0); const Point& target=query.point(1); - + bool inc_z=target.z()>source.z(); - + //the ray does not intersect the z-slab if ( ( inc_z && source.z()>bbox.zmax() )|| (!inc_z && source.z() bbox.xmax() || source.x() bool do_intersect(const Query& query, const Node& node) const { - return do_intersect(query,get_node_bbox(node, this->m_aabb_traits)); + return do_intersect(query,this->m_helper.get_node_bbox(node)); } private: @@ -139,44 +139,42 @@ public: template void intersection(const Query& query, const Primitive& primitive) { - typename Kernel::Triangle_3 t - = (internal::Primitive_helper::get_datum(primitive, this->m_aabb_traits)); + typename Kernel::Triangle_3 t = this->m_helper.get_primitive_datum(primitive, this->m_aabb_traits); if ( !do_intersect(query,t.bbox()) ) return; - + typename Kernel::Point_2 p0=z_project(t[0]); typename Kernel::Point_2 p1=z_project(t[1]); typename Kernel::Point_2 p2=z_project(t[2]); int indices[3]={0,1,2}; //to track whether triangle points have been swapt typename Kernel::Point_2 q=z_project( query.source() ); - + Orientation orient_2=orientation(p0,p1,p2); - + //check whether the face has a normal vector in the xy-plane if (orient_2==COLLINEAR){ //in that case the projection of the triangle along the z-axis is a segment. const typename Kernel::Point_2& other_point = p0!=p1?p1:p2; if ( orientation(p0,other_point,q) != COLLINEAR ) return;///no intersection - - //check if the ray source is above or below the triangle and compare it + + //check if the ray source is above or below the triangle and compare it //with the direction of the ray //TODO and if yes return //this is just an optimisation, the current code is valid - + this->m_status.first=boost::logic::indeterminate; this->m_stop=true; return; } - - + //regular case if (orient_2==NEGATIVE){ std::swap(p1,p2); std::swap(indices[1],indices[2]); } - + //check whether the ray intersect the supporting plane Orientation orient_3 = orientation(t[indices[0]],t[indices[1]],t[indices[2]],query.source()); - if ( orient_3!=COPLANAR && + if ( orient_3!=COPLANAR && ( //indicates whether the ray is oriented toward the positive side of the plane ( POSITIVE == CGAL::sign( query.to_vector().z() ) ) @@ -185,7 +183,6 @@ public: (orient_3==POSITIVE) ) ) return; //no intersection - //position against first segment switch( orientation(p0,p1,q) ){ diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index abd4a9e6991..34ca215a573 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -28,9 +28,9 @@ #include #include #include +#include #include #include -#include #include #include @@ -50,17 +50,16 @@ template class Rigid_mesh_collision_detection { typedef CGAL::AABB_face_graph_triangle_primitive Primitive; - typedef CGAL::AABB_do_intersect_transform_traits Traits; + typedef CGAL::AABB_traits Traits; typedef CGAL::AABB_tree Tree; - typedef Side_of_triangle_mesh Side_of_tm; - + typedef Do_intersect_traversal_traits_with_transformation Traversal_traits; std::vector m_triangle_mesh_ptrs; // TODO: we probably want an option with external trees std::vector m_aabb_trees; std::vector m_is_closed; std::vector< std::vector > m_points_per_cc; - + std::vector m_traversal_traits; #if CGAL_CACHE_BOXES boost::dynamic_bitset<> m_bboxes_is_invalid; std::vector m_bboxes; @@ -108,6 +107,25 @@ class Rigid_mesh_collision_detection m_points_per_cc.back().push_back( get(boost::vertex_point, tm, *boost::begin(vertices(tm))) ); } + // precondition A and B does not intersect + bool does_A_contains_a_CC_of_B(std::size_t id_A, std::size_t id_B) + { + typename Kernel::Construct_ray_3 ray_functor; + typename Kernel::Construct_vector_3 vector_functor; + typedef typename Traversal_traits::Transformed_tree_helper Helper; + + BOOST_FOREACH(const typename Kernel::Point_3& q, m_points_per_cc[id_B]) + { + if( internal::Point_inside_vertical_ray_cast(m_traversal_traits[id_A].get_helper())( + m_traversal_traits[id_B].transformation()( q ), *m_aabb_trees[id_A], + ray_functor, vector_functor) == CGAL::ON_BOUNDED_SIDE) + { + return true; + } + } + return false; + } + public: template Rigid_mesh_collision_detection(const MeshRange& triangle_meshes, bool assume_one_CC_per_mesh = false) @@ -131,6 +149,7 @@ public: m_aabb_trees.reserve(nb_meshes); m_is_closed.clear(); m_is_closed.resize(nb_meshes, false); + m_traversal_traits.reserve(m_aabb_trees.size()); #if CGAL_CACHE_BOXES m_bboxes_is_invalid.clear(); m_bboxes_is_invalid.resize(nb_meshes, true); @@ -144,6 +163,7 @@ public: m_triangle_mesh_ptrs.push_back( &tm ); Tree* t = new Tree(faces(tm).begin(), faces(tm).end(), tm); m_aabb_trees.push_back(t); + m_traversal_traits.push_back( Traversal_traits(m_aabb_trees.back()->traits()) ); add_cc_points(tm, assume_one_CC); } } @@ -154,6 +174,7 @@ public: m_triangle_mesh_ptrs.push_back( &tm ); Tree* t = new Tree(faces(tm).begin(), faces(tm).end(), tm); m_aabb_trees.push_back(t); + m_traversal_traits.push_back( Traversal_traits(m_aabb_trees.back()->traits()) ); #if CGAL_CACHE_BOXES m_bboxes.push_back(Bbox_3()); m_bboxes_is_invalid.resize(m_bboxes_is_invalid.size()+1, true); @@ -169,6 +190,7 @@ public: m_aabb_trees.erase( m_aabb_trees.begin()+mesh_id); m_is_closed.erase(m_is_closed.begin()+mesh_id); m_points_per_cc.erase(m_points_per_cc.begin()+mesh_id); + m_traversal_traits.erase(m_traversal_traits.begin()+mesh_id); #if CGAL_CACHE_BOXES // TODO this is a lazy approach that is not optimal m_bboxes.pop_back(); @@ -179,7 +201,7 @@ public: void set_transformation(std::size_t mesh_id, const Aff_transformation_3& aff_trans) { - m_aabb_trees[mesh_id]->traits().set_transformation(aff_trans); + m_traversal_traits[mesh_id].set_transformation(aff_trans); #if CGAL_CACHE_BOXES m_bboxes_is_invalid.set(mesh_id); #endif @@ -189,11 +211,11 @@ public: void update_bboxes() { // protector is supposed to have been set - for (boost::dynamic_bitset<>::size_type i = m_bboxes.find_first(); + for (boost::dynamic_bitset<>::size_type i = m_bboxes_is_invalid.find_first(); i != m_bboxes_is_invalid.npos; i = m_bboxes_is_invalid.find_next(i)) { - m_bboxes[i]=internal::get_tree_bbox(*m_aabb_trees[i]); + m_bboxes[i]=m_traversal_traits[i].get_helper().get_tree_bbox(*m_aabb_trees[i]); } m_bboxes_is_invalid.reset(); } @@ -261,34 +283,27 @@ public: if (!do_overlap(m_bboxes[k], m_bboxes[mesh_id])) continue; #endif // TODO: think about an alternative that is using a traversal traits - if ( m_aabb_trees[k]->do_intersect( *m_aabb_trees[mesh_id] ) ) + + Do_intersect_traversal_traits_for_two_trees traversal_traits( + m_aabb_trees[k]->traits(), m_traversal_traits[k].transformation(), m_traversal_traits[mesh_id]); + m_aabb_trees[k]->traversal(*m_aabb_trees[mesh_id], traversal_traits); + if (traversal_traits.is_intersection_found()) res.push_back(std::make_pair(k, false)); else{ if (m_is_closed[mesh_id]) { - Side_of_tm side_of_mid(*m_aabb_trees[mesh_id]); - bool stop = false; - BOOST_FOREACH(const typename Kernel::Point_3& q, m_points_per_cc[k]) + if ( does_A_contains_a_CC_of_B(mesh_id, k) ) { - if(side_of_mid(m_aabb_trees[k]->traits().transformation()( q )) == CGAL::ON_BOUNDED_SIDE) - { - res.push_back(std::make_pair(k, true)); - stop=true; - break; - } + res.push_back(std::make_pair(k, true)); + continue; } - if (stop) continue; } if (m_is_closed[k]) { - Side_of_tm side_of_mk(*m_aabb_trees[k]); - BOOST_FOREACH(const typename Kernel::Point_3& q, m_points_per_cc[mesh_id]) + if ( does_A_contains_a_CC_of_B(k, mesh_id) ) { - if(side_of_mk(m_aabb_trees[mesh_id]->traits().transformation()( q )) == CGAL::ON_BOUNDED_SIDE) - { - res.push_back(std::make_pair(k, true)); - break; - } + res.push_back(std::make_pair(k, true)); + continue; } } } From 84e2d4a97b7e5f695db40b15ff254577087696ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 24 Aug 2018 10:56:12 +0200 Subject: [PATCH 48/84] rename header --- ...traits.h => AABB_traversal_traits_with_transformation.h} | 6 +++--- .../include/CGAL/Rigid_mesh_collision_detection.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/{AABB_do_intersect_transform_traits.h => AABB_traversal_traits_with_transformation.h} (97%) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h similarity index 97% rename from Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h rename to Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h index 098dd521ef8..b6555317ccc 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_do_intersect_transform_traits.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h @@ -21,10 +21,10 @@ // Sebastien Loriot // -#ifndef CGAL_AABB_DO_INTERSECT_TRANSFORM_TRAITS_H -#define CGAL_AABB_DO_INTERSECT_TRANSFORM_TRAITS_H +#ifndef CGAL_PMP_INTERNAL_AABB_TRAVERSAL_TRAITS_WITH_TRANSFORMATION +#define CGAL_PMP_INTERNAL_AABB_TRAVERSAL_TRAITS_WITH_TRANSFORMATION -#include +#include #include #include diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index 34ca215a573..5adc46f7064 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -27,7 +27,7 @@ #include #include -#include +#include #include #include #include From 5af35234209785fd3cb945479b2df565e7a8c601 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 24 Aug 2018 11:38:34 +0200 Subject: [PATCH 49/84] add the possibility to use an existing AABB-tree --- ...ABB_traversal_traits_with_transformation.h | 11 ++- .../CGAL/Rigid_mesh_collision_detection.h | 68 ++++++++++++++----- 2 files changed, 55 insertions(+), 24 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h index b6555317ccc..5ad67a9e8c8 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h @@ -141,9 +141,8 @@ class Do_intersect_traversal_traits_with_transformation public: Do_intersect_traversal_traits_with_transformation(const AABBTraits& traits) - : m_is_found(false), m_traits(traits), m_has_rotation(false) - { - } + : m_is_found(false), m_traits_ptr(&traits), m_has_rotation(false) + {} bool go_further() const { return !m_is_found; } @@ -151,14 +150,14 @@ public: void intersection(const Query& query, const Primitive& primitive) { if( CGAL::do_intersect(query, - internal::Primitive_helper::get_datum(primitive, m_traits).transform(m_transfo)) ) + internal::Primitive_helper::get_datum(primitive, *m_traits_ptr).transform(m_transfo)) ) m_is_found = true; } template bool do_intersect(const Query& query, const Node& node) const { - return m_traits.do_intersect_object()(query, compute_transformed_bbox(node.bbox())); + return m_traits_ptr->do_intersect_object()(query, compute_transformed_bbox(node.bbox())); } bool is_intersection_found() const { return m_is_found; } @@ -225,7 +224,7 @@ public: private: bool m_is_found; - const AABBTraits& m_traits; + const AABBTraits* m_traits_ptr; Aff_transformation_3 m_transfo; bool m_has_rotation; }; diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index 5adc46f7064..2c2413dcc57 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -54,8 +54,7 @@ class Rigid_mesh_collision_detection typedef CGAL::AABB_tree Tree; typedef Do_intersect_traversal_traits_with_transformation Traversal_traits; - std::vector m_triangle_mesh_ptrs; - // TODO: we probably want an option with external trees + std::vector m_own_aabb_trees; std::vector m_aabb_trees; std::vector m_is_closed; std::vector< std::vector > m_points_per_cc; @@ -67,15 +66,18 @@ class Rigid_mesh_collision_detection void clear_trees() { + int i=0; BOOST_FOREACH(Tree* tree, m_aabb_trees){ - delete tree; + if (m_own_aabb_trees[i]) delete tree; + ++i; } m_aabb_trees.clear(); } - void add_cc_points(const TriangleMesh& tm, bool assume_one_CC) +public: + static + void get_one_point_per_cc(const TriangleMesh& tm, std::vector& points, bool assume_one_CC=false) { - m_points_per_cc.resize(m_points_per_cc.size()+1); if (!assume_one_CC) { std::vector CC_ids(num_faces(tm)); @@ -96,7 +98,7 @@ class Rigid_mesh_collision_detection { if (vertex_per_cc[get(fid_map, f)]!=GrT::null_vertex()) { - m_points_per_cc.back().push_back( + points.push_back( get(boost::vertex_point, tm, target( halfedge(f, tm), tm)) ); } } @@ -104,7 +106,14 @@ class Rigid_mesh_collision_detection } } // only one CC - m_points_per_cc.back().push_back( get(boost::vertex_point, tm, *boost::begin(vertices(tm))) ); + points.push_back( get(boost::vertex_point, tm, *boost::begin(vertices(tm))) ); + } + +private: + void add_cc_points(const TriangleMesh& tm, bool assume_one_CC) + { + m_points_per_cc.resize(m_points_per_cc.size()+1); + get_one_point_per_cc(tm, m_points_per_cc.back(), assume_one_CC); } // precondition A and B does not intersect @@ -127,6 +136,8 @@ class Rigid_mesh_collision_detection } public: + typedef Tree AABB_tree; + template Rigid_mesh_collision_detection(const MeshRange& triangle_meshes, bool assume_one_CC_per_mesh = false) { @@ -141,8 +152,8 @@ public: void init(const MeshRange& triangle_meshes, bool assume_one_CC) { std::size_t nb_meshes = triangle_meshes.size(); - m_triangle_mesh_ptrs.clear(); - m_triangle_mesh_ptrs.reserve(nb_meshes); + m_own_aabb_trees.clear(); + m_own_aabb_trees.reserve(nb_meshes); m_points_per_cc.clear(); m_points_per_cc.reserve(nb_meshes); clear_trees(); @@ -159,8 +170,8 @@ public: BOOST_FOREACH(const TriangleMesh& tm, triangle_meshes) { if (is_closed(tm)) - m_is_closed[m_triangle_mesh_ptrs.size()]=true; - m_triangle_mesh_ptrs.push_back( &tm ); + m_is_closed[m_aabb_trees.size()]=true; + m_own_aabb_trees.push_back( true ); Tree* t = new Tree(faces(tm).begin(), faces(tm).end(), tm); m_aabb_trees.push_back(t); m_traversal_traits.push_back( Traversal_traits(m_aabb_trees.back()->traits()) ); @@ -168,25 +179,46 @@ public: } } - void add_mesh(const TriangleMesh& tm, bool assume_one_CC_per_mesh = false) + std::size_t add_mesh(const TriangleMesh& tm, bool assume_one_CC_per_mesh = false) { + std::size_t id = m_aabb_trees.size(); m_is_closed.push_back(is_closed(tm)); - m_triangle_mesh_ptrs.push_back( &tm ); + m_own_aabb_trees.push_back( true ); Tree* t = new Tree(faces(tm).begin(), faces(tm).end(), tm); m_aabb_trees.push_back(t); m_traversal_traits.push_back( Traversal_traits(m_aabb_trees.back()->traits()) ); #if CGAL_CACHE_BOXES m_bboxes.push_back(Bbox_3()); - m_bboxes_is_invalid.resize(m_bboxes_is_invalid.size()+1, true); + m_bboxes_is_invalid.resize(id+1, true); #endif add_cc_points(tm, assume_one_CC_per_mesh); + + return id; + } + + std::size_t add_mesh(const Tree& tree, + bool is_closed, + const std::vector& points_per_cc) + { + std::size_t id = m_aabb_trees.size(); + m_is_closed.push_back(is_closed); + m_own_aabb_trees.push_back( false ); + m_aabb_trees.push_back( const_cast(&tree)); + m_traversal_traits.push_back( Traversal_traits(m_aabb_trees.back()->traits()) ); +#if CGAL_CACHE_BOXES + m_bboxes.push_back(Bbox_3()); + m_bboxes_is_invalid.resize(id+1, true); +#endif + m_points_per_cc.push_back(points_per_cc); + + return id; } void remove_mesh(std::size_t mesh_id) { - if(mesh_id >= m_triangle_mesh_ptrs.size()) return; - m_triangle_mesh_ptrs.erase( m_triangle_mesh_ptrs.begin()+mesh_id ); - delete m_aabb_trees[mesh_id]; + if(mesh_id >= m_aabb_trees.size()) return; + if (m_own_aabb_trees[mesh_id]) delete m_aabb_trees[mesh_id]; + m_own_aabb_trees.erase( m_own_aabb_trees.begin()+mesh_id ); m_aabb_trees.erase( m_aabb_trees.begin()+mesh_id); m_is_closed.erase(m_is_closed.begin()+mesh_id); m_points_per_cc.erase(m_points_per_cc.begin()+mesh_id); @@ -195,7 +227,7 @@ public: // TODO this is a lazy approach that is not optimal m_bboxes.pop_back(); m_bboxes_is_invalid.set(); - m_bboxes_is_invalid.resize(m_triangle_mesh_ptrs.size()); + m_bboxes_is_invalid.resize(m_aabb_trees.size()); #endif } From ab4759a5f2b88c55ea9263ff9131580506aa6e96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 2 Oct 2018 09:58:37 +0200 Subject: [PATCH 50/84] add AABB-tree as a template parameter --- .../CGAL/Rigid_mesh_collision_detection.h | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index 2c2413dcc57..a5ae0ae845d 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -46,13 +46,20 @@ namespace CGAL { //TODO handle vertex point point in the API -template +template class Rigid_mesh_collision_detection { - typedef CGAL::AABB_face_graph_triangle_primitive Primitive; - typedef CGAL::AABB_traits Traits; - typedef CGAL::AABB_tree Tree; - typedef Do_intersect_traversal_traits_with_transformation Traversal_traits; + // AABB-tree type + typedef AABB_face_graph_triangle_primitive Default_primitive; + typedef AABB_traits Default_tree_traits; + typedef CGAL::AABB_tree Default_tree; + typedef typename Default::Get::type Tree; + typedef typename Tree::AABB_traits Tree_traits; + + typedef Do_intersect_traversal_traits_with_transformation Traversal_traits; std::vector m_own_aabb_trees; std::vector m_aabb_trees; @@ -314,9 +321,8 @@ public: #if CGAL_CACHE_BOXES if (!do_overlap(m_bboxes[k], m_bboxes[mesh_id])) continue; #endif - // TODO: think about an alternative that is using a traversal traits - Do_intersect_traversal_traits_for_two_trees traversal_traits( + Do_intersect_traversal_traits_for_two_trees traversal_traits( m_aabb_trees[k]->traits(), m_traversal_traits[k].transformation(), m_traversal_traits[mesh_id]); m_aabb_trees[k]->traversal(*m_aabb_trees[mesh_id], traversal_traits); if (traversal_traits.is_intersection_found()) From a1ea22b27ef607f38238168046ab047ca0999bcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 2 Oct 2018 09:59:27 +0200 Subject: [PATCH 51/84] rename macro --- .../CGAL/Rigid_mesh_collision_detection.h | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index a5ae0ae845d..e67173c143f 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -35,11 +35,11 @@ #include -#ifndef CGAL_CACHE_BOXES -#define CGAL_CACHE_BOXES 0 +#ifndef CGAL_RMCD_CACHE_BOXES +#define CGAL_RMCD_CACHE_BOXES 0 #endif -#if CGAL_CACHE_BOXES +#if CGAL_RMCD_CACHE_BOXES #include #endif @@ -66,7 +66,7 @@ class Rigid_mesh_collision_detection std::vector m_is_closed; std::vector< std::vector > m_points_per_cc; std::vector m_traversal_traits; -#if CGAL_CACHE_BOXES +#if CGAL_RMCD_CACHE_BOXES boost::dynamic_bitset<> m_bboxes_is_invalid; std::vector m_bboxes; #endif @@ -168,7 +168,7 @@ public: m_is_closed.clear(); m_is_closed.resize(nb_meshes, false); m_traversal_traits.reserve(m_aabb_trees.size()); -#if CGAL_CACHE_BOXES +#if CGAL_RMCD_CACHE_BOXES m_bboxes_is_invalid.clear(); m_bboxes_is_invalid.resize(nb_meshes, true); m_bboxes.clear(); @@ -194,7 +194,7 @@ public: Tree* t = new Tree(faces(tm).begin(), faces(tm).end(), tm); m_aabb_trees.push_back(t); m_traversal_traits.push_back( Traversal_traits(m_aabb_trees.back()->traits()) ); -#if CGAL_CACHE_BOXES +#if CGAL_RMCD_CACHE_BOXES m_bboxes.push_back(Bbox_3()); m_bboxes_is_invalid.resize(id+1, true); #endif @@ -212,7 +212,7 @@ public: m_own_aabb_trees.push_back( false ); m_aabb_trees.push_back( const_cast(&tree)); m_traversal_traits.push_back( Traversal_traits(m_aabb_trees.back()->traits()) ); -#if CGAL_CACHE_BOXES +#if CGAL_RMCD_CACHE_BOXES m_bboxes.push_back(Bbox_3()); m_bboxes_is_invalid.resize(id+1, true); #endif @@ -230,7 +230,7 @@ public: m_is_closed.erase(m_is_closed.begin()+mesh_id); m_points_per_cc.erase(m_points_per_cc.begin()+mesh_id); m_traversal_traits.erase(m_traversal_traits.begin()+mesh_id); -#if CGAL_CACHE_BOXES +#if CGAL_RMCD_CACHE_BOXES // TODO this is a lazy approach that is not optimal m_bboxes.pop_back(); m_bboxes_is_invalid.set(); @@ -241,12 +241,12 @@ public: void set_transformation(std::size_t mesh_id, const Aff_transformation_3& aff_trans) { m_traversal_traits[mesh_id].set_transformation(aff_trans); -#if CGAL_CACHE_BOXES +#if CGAL_RMCD_CACHE_BOXES m_bboxes_is_invalid.set(mesh_id); #endif } -#if CGAL_CACHE_BOXES +#if CGAL_RMCD_CACHE_BOXES void update_bboxes() { // protector is supposed to have been set @@ -265,7 +265,7 @@ public: get_all_intersections(std::size_t mesh_id, const MeshRangeIds& ids) { CGAL::Interval_nt_advanced::Protector protector; -#if CGAL_CACHE_BOXES +#if CGAL_RMCD_CACHE_BOXES update_bboxes(); #endif std::vector res; @@ -273,7 +273,7 @@ public: BOOST_FOREACH(std::size_t k, ids) { if(k==mesh_id) continue; -#if CGAL_CACHE_BOXES +#if CGAL_RMCD_CACHE_BOXES if (!do_overlap(m_bboxes[k], m_bboxes[mesh_id])) continue; #endif // TODO: think about an alternative that is using a traversal traits @@ -309,7 +309,7 @@ public: get_all_intersections_and_inclusions(std::size_t mesh_id, const MeshRangeIds& ids) { CGAL::Interval_nt_advanced::Protector protector; -#if CGAL_CACHE_BOXES +#if CGAL_RMCD_CACHE_BOXES update_bboxes(); #endif std::vector > res; @@ -318,7 +318,7 @@ public: BOOST_FOREACH(std::size_t k, ids) { if(k==mesh_id) continue; -#if CGAL_CACHE_BOXES +#if CGAL_RMCD_CACHE_BOXES if (!do_overlap(m_bboxes[k], m_bboxes[mesh_id])) continue; #endif @@ -370,5 +370,6 @@ public: } // end of CGAL namespace +#undef CGAL_RMCD_CACHE_BOXES #endif // CGAL_RIGID_MESH_COLLISION_DETECTION_H From d206112f017046f421af7a2edbd59064f3703e4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 2 Oct 2018 14:19:57 +0200 Subject: [PATCH 52/84] add vertex point map as parameter --- .../AABB_tree/Do_trees_intersect_plugin.cpp | 4 +- .../CGAL/Rigid_mesh_collision_detection.h | 84 +++++++++++++++---- 2 files changed, 70 insertions(+), 18 deletions(-) diff --git a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp index 2a713f4991c..d26c2a7422b 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp @@ -135,7 +135,7 @@ private Q_SLOTS: { meshes.push_back(*item->getFaceGraph()); } - col_det = new CGAL::Rigid_mesh_collision_detection(meshes); + col_det = new CGAL::Rigid_mesh_collision_detection(meshes); init_trees(); static_cast( CGAL::QGLViewer::QGLViewerPool().first())->installEventFilter(this); @@ -340,7 +340,7 @@ private: Messages_interface* messageInterface; CGAL::Three::Scene_interface* scene; QMainWindow* mw; - CGAL::Rigid_mesh_collision_detection *col_det; + CGAL::Rigid_mesh_collision_detection *col_det; std::vector items; std::vector prev_ids; Scene_group_item* group_item; diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index e67173c143f..13386bc3671 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -45,22 +45,38 @@ namespace CGAL { -//TODO handle vertex point point in the API template class Rigid_mesh_collision_detection { - // AABB-tree type - typedef AABB_face_graph_triangle_primitive Default_primitive; +// Vertex point map type + typedef typename property_map_selector::const_type Default_vpm; + typedef typename Default::Get::type Vpm; + +// Kernel type + typedef typename Kernel_traits< + typename boost::property_traits::value_type>::Kernel Default_kernel; + typedef typename Default::Get::type Kernel; + +// AABB-tree type + typedef AABB_face_graph_triangle_primitive Default_primitive; typedef AABB_traits Default_tree_traits; typedef CGAL::AABB_tree Default_tree; typedef typename Default::Get::type Tree; typedef typename Tree::AABB_traits Tree_traits; - typedef Do_intersect_traversal_traits_with_transformation Traversal_traits; +// Transformed Tree traversal traits + typedef Do_intersect_traversal_traits_with_transformation + Traversal_traits; +// Data members std::vector m_own_aabb_trees; std::vector m_aabb_trees; std::vector m_is_closed; @@ -82,8 +98,14 @@ class Rigid_mesh_collision_detection } public: + typedef Tree AABB_tree; + typedef Vpm Vertex_point_map; + static - void get_one_point_per_cc(const TriangleMesh& tm, std::vector& points, bool assume_one_CC=false) + void get_one_point_per_cc(const TriangleMesh& tm, + Vertex_point_map vpm, + std::vector& points, + const bool assume_one_CC=false) { if (!assume_one_CC) { @@ -98,15 +120,15 @@ public: tm, bind_property_maps(fid_map, make_property_map(CC_ids)) ); if (nb_cc != 1) { - typedef boost::graph_traits GrT; - std::vector vertex_per_cc(nb_cc, GrT::null_vertex()); + typedef boost::graph_traits GrTr; + std::vector vertex_per_cc(nb_cc, GrTr::null_vertex()); - BOOST_FOREACH(typename GrT::face_descriptor f, faces(tm)) + BOOST_FOREACH(typename GrTr::face_descriptor f, faces(tm)) { - if (vertex_per_cc[get(fid_map, f)]!=GrT::null_vertex()) + if (vertex_per_cc[get(fid_map, f)]!=GrTr::null_vertex()) { points.push_back( - get(boost::vertex_point, tm, target( halfedge(f, tm), tm)) ); + get(vpm, target( halfedge(f, tm), tm)) ); } } return; @@ -116,6 +138,14 @@ public: points.push_back( get(boost::vertex_point, tm, *boost::begin(vertices(tm))) ); } + static + void get_one_point_per_cc(const TriangleMesh& tm, + std::vector& points, + const bool assume_one_CC=false) + { + get_one_point_per_cc(tm, get(boost::vertex_point, tm), points, assume_one_CC); + } + private: void add_cc_points(const TriangleMesh& tm, bool assume_one_CC) { @@ -143,8 +173,8 @@ private: } public: - typedef Tree AABB_tree; + // TODO: document that the default vertex point map will be used template Rigid_mesh_collision_detection(const MeshRange& triangle_meshes, bool assume_one_CC_per_mesh = false) { @@ -155,6 +185,8 @@ public: { clear_trees(); } + + // TODO: document that the default vertex point map will be used template void init(const MeshRange& triangle_meshes, bool assume_one_CC) { @@ -186,12 +218,26 @@ public: } } - std::size_t add_mesh(const TriangleMesh& tm, bool assume_one_CC_per_mesh = false) + void reserve(std::size_t size) + { + m_own_aabb_trees.reserve(size); + m_aabb_trees.reserve(size); + m_is_closed.reserve(size); + m_points_per_cc.reserve(size); + m_traversal_traits.reserve(size); +#if CGAL_RMCD_CACHE_BOXES + m_bboxes.reserve(size); +#endif + } + + std::size_t add_mesh(const TriangleMesh& tm, + Vertex_point_map vpm, + const bool assume_one_CC_per_mesh = false) { std::size_t id = m_aabb_trees.size(); m_is_closed.push_back(is_closed(tm)); m_own_aabb_trees.push_back( true ); - Tree* t = new Tree(faces(tm).begin(), faces(tm).end(), tm); + Tree* t = new Tree(faces(tm).begin(), faces(tm).end(), tm, vpm); m_aabb_trees.push_back(t); m_traversal_traits.push_back( Traversal_traits(m_aabb_trees.back()->traits()) ); #if CGAL_RMCD_CACHE_BOXES @@ -203,7 +249,13 @@ public: return id; } - std::size_t add_mesh(const Tree& tree, + std::size_t add_mesh(const TriangleMesh& tm, + const bool assume_one_CC_per_mesh = false) + { + return add_mesh(tm, get(boost::vertex_point, tm), assume_one_CC_per_mesh); + } + + std::size_t add_mesh(const AABB_tree& tree, bool is_closed, const std::vector& points_per_cc) { @@ -301,7 +353,7 @@ public: return get_all_intersections(mesh_id); } - // TODO: document that is a model is composed of several CC on one of them is not closed, + // TODO: document that if a model is composed of several CC on one of them is not closed, // no inclusion test will be made // TODO: document that the inclusion can be partial in case there are several CC template From f8722ef3bee79bc45917d8a49c52f526f1abb332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 2 Oct 2018 14:20:33 +0200 Subject: [PATCH 53/84] update implementation of get_all_intersections to use the traversal traits --- .../include/CGAL/Rigid_mesh_collision_detection.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index 13386bc3671..4e9eed67f09 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -322,14 +322,18 @@ public: #endif std::vector res; + // TODO: use a non-naive version BOOST_FOREACH(std::size_t k, ids) { if(k==mesh_id) continue; #if CGAL_RMCD_CACHE_BOXES - if (!do_overlap(m_bboxes[k], m_bboxes[mesh_id])) continue; + if (!do_overlap(m_bboxes[k], m_bboxes[mesh_id])) continue; #endif - // TODO: think about an alternative that is using a traversal traits - if ( m_aabb_trees[k]->do_intersect( *m_aabb_trees[mesh_id] ) ) + + Do_intersect_traversal_traits_for_two_trees traversal_traits( + m_aabb_trees[k]->traits(), m_traversal_traits[k].transformation(), m_traversal_traits[mesh_id]); + m_aabb_trees[k]->traversal(*m_aabb_trees[mesh_id], traversal_traits); + if (traversal_traits.is_intersection_found()) res.push_back(k); } return res; From 2b350e71e152a56d73fe7934b58965b579f88e0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 2 Oct 2018 14:28:21 +0200 Subject: [PATCH 54/84] use vpm --- .../include/CGAL/Rigid_mesh_collision_detection.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index 4e9eed67f09..4f2c2b1bf96 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -135,7 +135,7 @@ public: } } // only one CC - points.push_back( get(boost::vertex_point, tm, *boost::begin(vertices(tm))) ); + points.push_back( get(vpm, *boost::begin(vertices(tm))) ); } static From a2491fe07c5634c6c3ee0e846adb1453b5be5a06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 2 Oct 2018 14:40:54 +0200 Subject: [PATCH 55/84] really use one point per CC --- .../include/CGAL/Rigid_mesh_collision_detection.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index 4f2c2b1bf96..913fdb24b1f 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -109,7 +109,7 @@ public: { if (!assume_one_CC) { - std::vector CC_ids(num_faces(tm)); + std::vector cc_ids(num_faces(tm)); // TODO use dynamic property if no defaut fid is available typename boost::property_map::type fid_map @@ -117,7 +117,8 @@ public: std::size_t nb_cc = Polygon_mesh_processing::connected_components( - tm, bind_property_maps(fid_map, make_property_map(CC_ids)) ); + tm, bind_property_maps(fid_map, make_property_map(cc_ids)), + parameters::face_index_map(fid_map)); if (nb_cc != 1) { typedef boost::graph_traits GrTr; @@ -125,10 +126,11 @@ public: BOOST_FOREACH(typename GrTr::face_descriptor f, faces(tm)) { - if (vertex_per_cc[get(fid_map, f)]!=GrTr::null_vertex()) + std::size_t cc_id = cc_ids[get(fid_map, f)]; + if (vertex_per_cc[cc_id] == GrTr::null_vertex()) { - points.push_back( - get(vpm, target( halfedge(f, tm), tm)) ); + vertex_per_cc[cc_id] = target( halfedge(f, tm), tm); + points.push_back( get(vpm, vertex_per_cc[cc_id]) ); } } return; From 74c8eaec2954c816aba8ce222ca0f2ac9e203c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 2 Oct 2018 15:33:57 +0200 Subject: [PATCH 56/84] use named parameters I removed the constructor from a range of meshes as it is complicated to specify a range of vertex point map. --- .../AABB_tree/Do_trees_intersect_plugin.cpp | 7 +- .../CGAL/Rigid_mesh_collision_detection.h | 134 ++++++++++-------- 2 files changed, 78 insertions(+), 63 deletions(-) diff --git a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp index d26c2a7422b..6ec471440d4 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp @@ -135,7 +135,12 @@ private Q_SLOTS: { meshes.push_back(*item->getFaceGraph()); } - col_det = new CGAL::Rigid_mesh_collision_detection(meshes); + col_det = new CGAL::Rigid_mesh_collision_detection(); + col_det->reserve(meshes.size()); + Q_FOREACH(const SMesh& sm, meshes) + { + col_det->add_mesh(sm); + } init_trees(); static_cast( CGAL::QGLViewer::QGLViewerPool().first())->installEventFilter(this); diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index 913fdb24b1f..30c5073d4ee 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -101,19 +101,59 @@ public: typedef Tree AABB_tree; typedef Vpm Vertex_point_map; + /* + * \cgalNamedParamsBegin + * \cgalParamBegin{vertex_point_map} + * the property map with the points associated to the vertices of `tm`. + * If this parameter is omitted, an internal property map for + * `CGAL::vertex_point_t` should be available in `TriangleMesh` + * \cgalParamEnd + * \cgalParamBegin{face_index_map} + * a property map containing the index of each face of `tm`. + * \cgalParamEnd + * \cgalParamBegin{apply_per_connected_component} + * if `false`, `tm` is supposed to have only one connected component and might have several connected components otherwise. + * Default is `true`. + * \cgalParamEnd + * \cgalNamedParamsEnd + */ + template static void get_one_point_per_cc(const TriangleMesh& tm, - Vertex_point_map vpm, std::vector& points, - const bool assume_one_CC=false) + const NamedParameters& np) { - if (!assume_one_CC) + using Polygon_mesh_processing::GetVertexPointMap; + using Polygon_mesh_processing::GetFaceIndexMap; + + const bool maybe_several_cc = + boost::choose_param( + boost::get_param(np, internal_np::apply_per_connected_component), true); + + typedef typename GetVertexPointMap::type Local_vpm; + CGAL_USE_TYPE(Local_vpm); + + CGAL_assertion_code( + static const bool same_vpm = (boost::is_same::value); ) + CGAL_static_assertion(same_vpm); + + Vpm vpm = + boost::choose_param(boost::get_param(np, internal_np::vertex_point), + get_const_property_map(boost::vertex_point, tm) ); + + if (maybe_several_cc) { + // used for face cc id map std::vector cc_ids(num_faces(tm)); - // TODO use dynamic property if no defaut fid is available - typename boost::property_map::type fid_map - = get(boost::face_index, tm); + // face index map + typedef typename GetFaceIndexMap::type Fid_map; + + Fid_map fid_map = + boost::choose_param(boost::get_param(np, internal_np::face_index), + get_const_property_map(boost::face_index, tm)); std::size_t nb_cc = Polygon_mesh_processing::connected_components( @@ -122,7 +162,8 @@ public: if (nb_cc != 1) { typedef boost::graph_traits GrTr; - std::vector vertex_per_cc(nb_cc, GrTr::null_vertex()); + std::vector + vertex_per_cc(nb_cc, GrTr::null_vertex()); BOOST_FOREACH(typename GrTr::face_descriptor f, faces(tm)) { @@ -142,17 +183,17 @@ public: static void get_one_point_per_cc(const TriangleMesh& tm, - std::vector& points, - const bool assume_one_CC=false) + std::vector& points) { - get_one_point_per_cc(tm, get(boost::vertex_point, tm), points, assume_one_CC); + get_one_point_per_cc(tm, points, parameters::all_default()); } private: - void add_cc_points(const TriangleMesh& tm, bool assume_one_CC) + template + void add_cc_points(const TriangleMesh& tm, const NamedParameters& np) { m_points_per_cc.resize(m_points_per_cc.size()+1); - get_one_point_per_cc(tm, m_points_per_cc.back(), assume_one_CC); + get_one_point_per_cc(tm, m_points_per_cc.back(), np); } // precondition A and B does not intersect @@ -176,50 +217,6 @@ private: public: - // TODO: document that the default vertex point map will be used - template - Rigid_mesh_collision_detection(const MeshRange& triangle_meshes, bool assume_one_CC_per_mesh = false) - { - init(triangle_meshes, assume_one_CC_per_mesh); - } - - ~Rigid_mesh_collision_detection() - { - clear_trees(); - } - - // TODO: document that the default vertex point map will be used - template - void init(const MeshRange& triangle_meshes, bool assume_one_CC) - { - std::size_t nb_meshes = triangle_meshes.size(); - m_own_aabb_trees.clear(); - m_own_aabb_trees.reserve(nb_meshes); - m_points_per_cc.clear(); - m_points_per_cc.reserve(nb_meshes); - clear_trees(); - m_aabb_trees.reserve(nb_meshes); - m_is_closed.clear(); - m_is_closed.resize(nb_meshes, false); - m_traversal_traits.reserve(m_aabb_trees.size()); -#if CGAL_RMCD_CACHE_BOXES - m_bboxes_is_invalid.clear(); - m_bboxes_is_invalid.resize(nb_meshes, true); - m_bboxes.clear(); - m_bboxes.resize(nb_meshes); -#endif - BOOST_FOREACH(const TriangleMesh& tm, triangle_meshes) - { - if (is_closed(tm)) - m_is_closed[m_aabb_trees.size()]=true; - m_own_aabb_trees.push_back( true ); - Tree* t = new Tree(faces(tm).begin(), faces(tm).end(), tm); - m_aabb_trees.push_back(t); - m_traversal_traits.push_back( Traversal_traits(m_aabb_trees.back()->traits()) ); - add_cc_points(tm, assume_one_CC); - } - } - void reserve(std::size_t size) { m_own_aabb_trees.reserve(size); @@ -232,10 +229,24 @@ public: #endif } + // TODO: copy NP doc from get_one_point_per_cc + template std::size_t add_mesh(const TriangleMesh& tm, - Vertex_point_map vpm, - const bool assume_one_CC_per_mesh = false) + const NamedParameters& np) { + // handle vpm + using Polygon_mesh_processing::GetVertexPointMap; + typedef typename GetVertexPointMap::type Local_vpm; + CGAL_USE_TYPE(Local_vpm); + CGAL_assertion_code( + static const bool same_vpm = (boost::is_same::value); ) + CGAL_static_assertion(same_vpm); + + Vpm vpm = + boost::choose_param(boost::get_param(np, internal_np::vertex_point), + get_const_property_map(boost::vertex_point, tm) ); + // now add the mesh std::size_t id = m_aabb_trees.size(); m_is_closed.push_back(is_closed(tm)); m_own_aabb_trees.push_back( true ); @@ -246,15 +257,14 @@ public: m_bboxes.push_back(Bbox_3()); m_bboxes_is_invalid.resize(id+1, true); #endif - add_cc_points(tm, assume_one_CC_per_mesh); + add_cc_points(tm, np); return id; } - std::size_t add_mesh(const TriangleMesh& tm, - const bool assume_one_CC_per_mesh = false) + std::size_t add_mesh(const TriangleMesh& tm) { - return add_mesh(tm, get(boost::vertex_point, tm), assume_one_CC_per_mesh); + return add_mesh(tm, parameters::all_default()); } std::size_t add_mesh(const AABB_tree& tree, From 649c75c272f7875b162728f3cec19917d6a2dfed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 2 Oct 2018 15:56:31 +0200 Subject: [PATCH 57/84] factorise intersection code + fix constness --- ...ABB_traversal_traits_with_transformation.h | 5 ++- .../CGAL/Rigid_mesh_collision_detection.h | 40 ++++++++++--------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h index 5ad67a9e8c8..63ac86ceb2d 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h @@ -238,6 +238,7 @@ class Do_intersect_traversal_traits_for_two_trees typedef typename AABBTraits::Primitive Primitive; typedef ::CGAL::AABB_node Node; typedef Traversal_traits_with_transformation_helper Base; + typedef Do_intersect_traversal_traits_with_transformation Query_traversal_traits; void register_transformation(CGAL::Tag_true) { @@ -256,12 +257,12 @@ class Do_intersect_traversal_traits_for_two_trees public: Do_intersect_traversal_traits_for_two_trees(const AABBTraits& traits, const Aff_transformation_3& transfo, - Do_intersect_traversal_traits_with_transformation& query_traversal_traits) + const Query_traversal_traits& query_traversal_traits) : m_is_found(false) , m_traits(traits) , m_transfo(transfo) , m_has_rotation(false) - , m_query_traversal_traits(query_traversal_traits) + , m_query_traversal_traits(const_cast(query_traversal_traits)) { register_transformation(SUPPORTS_ROTATION()); diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index 30c5073d4ee..c07a8b5e04c 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -45,6 +45,7 @@ namespace CGAL { +// TODO mention thread-safety issues (const_cast and internal bool in stored traversal traits) template traversal_traits( + m_aabb_trees[id_B]->traits(), m_traversal_traits[id_B].transformation(), m_traversal_traits[id_A]); + m_aabb_trees[id_B]->traversal(*m_aabb_trees[id_A], traversal_traits); + return traversal_traits.is_intersection_found(); + } + public: void reserve(std::size_t size) @@ -326,7 +340,7 @@ public: template std::vector - get_all_intersections(std::size_t mesh_id, const MeshRangeIds& ids) + get_all_intersections(std::size_t mesh_id, const MeshRangeIds& ids) const { CGAL::Interval_nt_advanced::Protector protector; #if CGAL_RMCD_CACHE_BOXES @@ -338,21 +352,15 @@ public: BOOST_FOREACH(std::size_t k, ids) { if(k==mesh_id) continue; -#if CGAL_RMCD_CACHE_BOXES - if (!do_overlap(m_bboxes[k], m_bboxes[mesh_id])) continue; -#endif - Do_intersect_traversal_traits_for_two_trees traversal_traits( - m_aabb_trees[k]->traits(), m_traversal_traits[k].transformation(), m_traversal_traits[mesh_id]); - m_aabb_trees[k]->traversal(*m_aabb_trees[mesh_id], traversal_traits); - if (traversal_traits.is_intersection_found()) + if (does_A_intersect_B(mesh_id, k)) res.push_back(k); } return res; } std::vector - get_all_intersections(std::size_t mesh_id) + get_all_intersections(std::size_t mesh_id) const { return get_all_intersections( mesh_id, @@ -374,7 +382,7 @@ public: // TODO: document that the inclusion can be partial in case there are several CC template std::vector > - get_all_intersections_and_inclusions(std::size_t mesh_id, const MeshRangeIds& ids) + get_all_intersections_and_inclusions(std::size_t mesh_id, const MeshRangeIds& ids) const { CGAL::Interval_nt_advanced::Protector protector; #if CGAL_RMCD_CACHE_BOXES @@ -386,14 +394,8 @@ public: BOOST_FOREACH(std::size_t k, ids) { if(k==mesh_id) continue; -#if CGAL_RMCD_CACHE_BOXES - if (!do_overlap(m_bboxes[k], m_bboxes[mesh_id])) continue; -#endif - Do_intersect_traversal_traits_for_two_trees traversal_traits( - m_aabb_trees[k]->traits(), m_traversal_traits[k].transformation(), m_traversal_traits[mesh_id]); - m_aabb_trees[k]->traversal(*m_aabb_trees[mesh_id], traversal_traits); - if (traversal_traits.is_intersection_found()) + if (does_A_intersect_B(mesh_id, k)) res.push_back(std::make_pair(k, false)); else{ if (m_is_closed[mesh_id]) @@ -418,7 +420,7 @@ public: } std::vector > - get_all_intersections_and_inclusions(std::size_t mesh_id) + get_all_intersections_and_inclusions(std::size_t mesh_id) const { return get_all_intersections_and_inclusions( mesh_id, From 27da7aea886780d3a1c83e8533bd3fef717c0b4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 2 Oct 2018 16:06:53 +0200 Subject: [PATCH 58/84] do not copy meshes --- .../AABB_tree/Do_trees_intersect_plugin.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp index 6ec471440d4..67f7e5ecd3c 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp @@ -90,7 +90,6 @@ private Q_SLOTS: connect(group_item, &Scene_group_item::aboutToBeDestroyed, this, [this](){ items.clear(); - meshes.clear(); if(col_det) delete col_det; col_det = nullptr; @@ -131,15 +130,11 @@ private Q_SLOTS: scene->setSelectedItem(group_item->getChildren().last()); connect(static_cast(scene), &Scene::itemIndexSelected, this, &DoTreesIntersectplugin::update_trees); + col_det = new CGAL::Rigid_mesh_collision_detection(); + col_det->reserve(items.size()); Q_FOREACH(Scene_movable_sm_item* item, items) { - meshes.push_back(*item->getFaceGraph()); - } - col_det = new CGAL::Rigid_mesh_collision_detection(); - col_det->reserve(meshes.size()); - Q_FOREACH(const SMesh& sm, meshes) - { - col_det->add_mesh(sm); + col_det->add_mesh(*item->getFaceGraph()); } init_trees(); static_cast( @@ -317,7 +312,6 @@ public Q_SLOTS: scene->erase(scene->item_id(group_item)); group_item = nullptr; items.clear(); - meshes.clear(); prev_ids.clear(); delete col_det; col_det = nullptr; @@ -349,7 +343,6 @@ private: std::vector items; std::vector prev_ids; Scene_group_item* group_item; - std::vector meshes; bool do_transparency; }; #include "Do_trees_intersect_plugin.moc" From f6d14a78b35e6a0a55f395d64659059b7fa90f3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 2 Oct 2018 16:47:35 +0200 Subject: [PATCH 59/84] get rid of thread safety issue by copying the traversal traits --- .../internal/AABB_traversal_traits_with_transformation.h | 6 +++--- .../include/CGAL/Rigid_mesh_collision_detection.h | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h index 63ac86ceb2d..685d2afb987 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h @@ -262,7 +262,7 @@ public: , m_traits(traits) , m_transfo(transfo) , m_has_rotation(false) - , m_query_traversal_traits(const_cast(query_traversal_traits)) + , m_query_traversal_traits(query_traversal_traits) { register_transformation(SUPPORTS_ROTATION()); @@ -277,7 +277,7 @@ public: m_query_traversal_traits.reset(); } - bool do_intersect(const AABB_tree& query, const Node& node) const + bool do_intersect(const AABB_tree& query, const Node& node) { query.traversal( compute_transformed_bbox(node.bbox()), m_query_traversal_traits ); bool res = m_query_traversal_traits.is_intersection_found(); @@ -292,7 +292,7 @@ private: const AABBTraits& m_traits; const Aff_transformation_3& m_transfo; bool m_has_rotation; - Do_intersect_traversal_traits_with_transformation& m_query_traversal_traits; + Do_intersect_traversal_traits_with_transformation m_query_traversal_traits; }; }//end CGAL diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index c07a8b5e04c..3aaec65940e 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -45,7 +45,6 @@ namespace CGAL { -// TODO mention thread-safety issues (const_cast and internal bool in stored traversal traits) template Date: Tue, 2 Oct 2018 16:51:40 +0200 Subject: [PATCH 60/84] readd destructor removed by error --- .../include/CGAL/Rigid_mesh_collision_detection.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h index 3aaec65940e..1ae6dc53c4b 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h @@ -87,7 +87,12 @@ class Rigid_mesh_collision_detection std::vector m_bboxes; #endif - void clear_trees() + +public: + typedef Tree AABB_tree; + typedef Vpm Vertex_point_map; + + ~Rigid_mesh_collision_detection() { int i=0; BOOST_FOREACH(Tree* tree, m_aabb_trees){ @@ -97,10 +102,6 @@ class Rigid_mesh_collision_detection m_aabb_trees.clear(); } -public: - typedef Tree AABB_tree; - typedef Vpm Vertex_point_map; - /* * \cgalNamedParamsBegin * \cgalParamBegin{vertex_point_map} From 51cb7410e297f44b06793658bb8d9cba808251b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 3 Oct 2018 13:50:47 +0200 Subject: [PATCH 61/84] add document and clean-up API --- .../AABB_tree/Do_trees_intersect_plugin.cpp | 8 +- .../PackageDescription.txt | 3 + .../CGAL/Rigid_mesh_collision_detection.h | 234 +++++++++++++----- 3 files changed, 174 insertions(+), 71 deletions(-) diff --git a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp index 67f7e5ecd3c..753a62858a3 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp @@ -214,9 +214,9 @@ public Q_SLOTS: matrix[2], matrix[6], matrix[10],matrix[14]); EPICK::Aff_transformation_3 transfo = rota*translation; + col_det->set_transformation(sel_id, transfo); std::vector > inter_and_incl - = col_det-> - set_transformation_and_get_all_intersections_and_inclusions(sel_id, transfo); + = col_det->get_all_intersections_and_inclusions(sel_id); for(std::size_t i=0; iset_transformation(sel_id, transfo); std::vector > inter_and_incl - = col_det-> - set_transformation_and_get_all_intersections_and_inclusions(sel_id, transfo); + = col_det->get_all_intersections_and_inclusions(sel_id); for(std::size_t i=0; i + class AABBTree_type = Default, + class HAS_ROTATION = CGAL::Tag_true> class Rigid_mesh_collision_detection { // Vertex point map type @@ -87,10 +106,18 @@ class Rigid_mesh_collision_detection std::vector m_bboxes; #endif - public: +#ifdef DOXYGEN_RUNNING + /// The AABB_tree type representing the triangles of each input mesh + typedef unspecified_type AABB_tree; + /// The vertex point map type used with `TriangleMesh` + typedef unspecified_type Vertex_point_map; +#else typedef Tree AABB_tree; typedef Vpm Vertex_point_map; +#endif + /// Point type + typedef typename boost::property_traits::value_type Point_3; ~Rigid_mesh_collision_detection() { @@ -102,7 +129,17 @@ public: m_aabb_trees.clear(); } - /* + /*! + * fills `points` with one point per connected component of `tm`. This is a helper function + * intended to be used before calling `add_mesh()` overload taking an AABB-tree instead of a mesh + * as input parameter. + * + * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" + * + * @param tm input triangulated surface mesh + * @param [out] points will contain one point per connected component of `tm` + * @param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below + * * \cgalNamedParamsBegin * \cgalParamBegin{vertex_point_map} * the property map with the points associated to the vertices of `tm`. @@ -110,19 +147,21 @@ public: * `CGAL::vertex_point_t` should be available in `TriangleMesh` * \cgalParamEnd * \cgalParamBegin{face_index_map} - * a property map containing the index of each face of `tm`. + * a property map containing the index of each face of `tm`. It must be initialized + * and the value should be unique per face and in the range `[0, num_faces(tm)[`. * \cgalParamEnd * \cgalParamBegin{apply_per_connected_component} - * if `false`, `tm` is supposed to have only one connected component and might have several connected components otherwise. - * Default is `true`. + * if `false`, `tm` is assumed to have only one connected component, avoiding and + * the extraction of connected components. %Default is `true`. * \cgalParamEnd * \cgalNamedParamsEnd */ template static - void get_one_point_per_cc(const TriangleMesh& tm, - std::vector& points, - const NamedParameters& np) + void collect_one_point_per_connected_component( + const TriangleMesh& tm, + std::vector& points, + const NamedParameters& np) { using Polygon_mesh_processing::GetVertexPointMap; using Polygon_mesh_processing::GetFaceIndexMap; @@ -182,19 +221,12 @@ public: points.push_back( get(vpm, *boost::begin(vertices(tm))) ); } - static - void get_one_point_per_cc(const TriangleMesh& tm, - std::vector& points) - { - get_one_point_per_cc(tm, points, parameters::all_default()); - } - private: template void add_cc_points(const TriangleMesh& tm, const NamedParameters& np) { m_points_per_cc.resize(m_points_per_cc.size()+1); - get_one_point_per_cc(tm, m_points_per_cc.back(), np); + collect_one_point_per_connected_component(tm, m_points_per_cc.back(), np); } // precondition A and B does not intersect @@ -231,19 +263,32 @@ private: public: - void reserve(std::size_t size) - { - m_own_aabb_trees.reserve(size); - m_aabb_trees.reserve(size); - m_is_closed.reserve(size); - m_points_per_cc.reserve(size); - m_traversal_traits.reserve(size); -#if CGAL_RMCD_CACHE_BOXES - m_bboxes.reserve(size); -#endif - } - - // TODO: copy NP doc from get_one_point_per_cc + /*! + * adds mesh `tm` in the pool of meshes to be considered for intersection. + * + * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" + * + * \return the id of `tm` used to refer to that mesh. + * + * @param tm triangulated surface mesh to add + * @param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below + * + * \cgalNamedParamsBegin + * \cgalParamBegin{vertex_point_map} + * the property map with the points associated to the vertices of `tm`. + * If this parameter is omitted, an internal property map for + * `CGAL::vertex_point_t` should be available in `TriangleMesh` + * \cgalParamEnd + * \cgalParamBegin{face_index_map} + * a property map containing the index of each face of `tm`. It must be initialized + * and the value should be unique per face and in the range `[0, num_faces(tm)[`. + * \cgalParamEnd + * \cgalParamBegin{apply_per_connected_component} + * if `false`, `tm` is assumed to have only one connected component, avoiding and + * the extraction of connected components. Default is `true`. + * \cgalParamEnd + * \cgalNamedParamsEnd + */ template std::size_t add_mesh(const TriangleMesh& tm, const NamedParameters& np) @@ -276,14 +321,22 @@ public: return id; } - std::size_t add_mesh(const TriangleMesh& tm) - { - return add_mesh(tm, parameters::all_default()); - } - + /*! + * adds an instance of a triangulated surface mesh using an external tree of its faces. + * Note that the tree is not copied and the lifetime of `tree` must be longer than + * that of this class. + * + * \return the id of the instance used to refer to that mesh. + * + * @param tree an AABB-tree of faces of a mesh + * @param is_closed `true` is the mesh in `tree` is closed, and `false` otherwise. + * \link is_closed() `CGAL::is_closed()` \endlink can be used for that purpose. + * @param points_per_cc a vector containing one point of a vertex for each connected + * component of the triangle surface mesh in `tree` + */ std::size_t add_mesh(const AABB_tree& tree, bool is_closed, - const std::vector& points_per_cc) + const std::vector& points_per_cc) { std::size_t id = m_aabb_trees.size(); m_is_closed.push_back(is_closed); @@ -299,23 +352,24 @@ public: return id; } - void remove_mesh(std::size_t mesh_id) + /*! + * increases the capacity of data structures used internally, `size` being the number of meshes expected to be added. + */ + void reserve(std::size_t size) { - if(mesh_id >= m_aabb_trees.size()) return; - if (m_own_aabb_trees[mesh_id]) delete m_aabb_trees[mesh_id]; - m_own_aabb_trees.erase( m_own_aabb_trees.begin()+mesh_id ); - m_aabb_trees.erase( m_aabb_trees.begin()+mesh_id); - m_is_closed.erase(m_is_closed.begin()+mesh_id); - m_points_per_cc.erase(m_points_per_cc.begin()+mesh_id); - m_traversal_traits.erase(m_traversal_traits.begin()+mesh_id); + m_own_aabb_trees.reserve(size); + m_aabb_trees.reserve(size); + m_is_closed.reserve(size); + m_points_per_cc.reserve(size); + m_traversal_traits.reserve(size); #if CGAL_RMCD_CACHE_BOXES - // TODO this is a lazy approach that is not optimal - m_bboxes.pop_back(); - m_bboxes_is_invalid.set(); - m_bboxes_is_invalid.resize(m_aabb_trees.size()); + m_bboxes.reserve(size); #endif } + /*! + * sets the transformation associated to a mesh identified by its id in the pool. + */ void set_transformation(std::size_t mesh_id, const Aff_transformation_3& aff_trans) { m_traversal_traits[mesh_id].set_transformation(aff_trans); @@ -338,6 +392,12 @@ public: } #endif + /*! + * returns a vector of ids of meshes within `ids` that have at least a triangle face + * intersecting a triangle face of the mesh with id `mesh_id`. + * If `mesh_id` is in `ids` it is not reported. + * \tparam MeshRangeIds a range of ids convertible to `std::size_t`. + */ template std::vector get_all_intersections(std::size_t mesh_id, const MeshRangeIds& ids) const @@ -359,6 +419,10 @@ public: return res; } + /*! + * returns a vector of ids of meshes in the pool that have at least a triangle face + * intersecting a triangle face of the mesh with id `mesh_id` + */ std::vector get_all_intersections(std::size_t mesh_id) const { @@ -368,18 +432,25 @@ public: boost::make_counting_iterator(m_aabb_trees.size()))); } - std::vector - set_transformation_and_get_all_intersections(std::size_t mesh_id, - const Aff_transformation_3& aff_trans) - { - CGAL::Interval_nt_advanced::Protector protector; - set_transformation(mesh_id, aff_trans); - return get_all_intersections(mesh_id); - } - - // TODO: document that if a model is composed of several CC on one of them is not closed, - // no inclusion test will be made - // TODO: document that the inclusion can be partial in case there are several CC + /*! + * returns a vector of ids of meshes within `ids` that are intersecting with the mesh with id `mesh_id`, + * considering volume inclusions for closed meshes. + * More precisely, if at least one triangle face of a mesh with id `i` intersects a triangle face + * of the mesh with id `mesh_id`, the pair `(i, false)` is put in the output vector. + * If there is no triangle face intersection, but at least one of the meshes with ids `i` and `mesh_id` is closed, + * and at least one connected component is included in the bounded volume defined by a closed mesh then the pair + * `(i, true)` is put in the output vector (independently of mesh `i` or `mesh_id` being the one including the other). + * The inclusion test is done using `Side_of_triangle_mesh`, in particular surface orientation is ignored and only the + * nesting level of connected components defines a bounded volume. If a mesh has some self-intersection the inclusion + * test may return incorrect results. + * If `mesh_id` is in `ids` it is not reported. + * + * \tparam MeshRangeIds a range of ids convertible to `std::size_t`. + * + * \note If a mesh is made of several connected components and at least component which is not closed, + * then no inclusion test will be made even if some components are closed. + * + */ template std::vector > get_all_intersections_and_inclusions(std::size_t mesh_id, const MeshRangeIds& ids) const @@ -419,6 +490,11 @@ public: return res; } + /*! + * returns a vector of ids of meshes in the pool that are intersecting with the mesh with id `mesh_id`, + * considering volume inclusions for closed meshes. + * See the previous overload for details. + */ std::vector > get_all_intersections_and_inclusions(std::size_t mesh_id) const { @@ -428,14 +504,38 @@ public: boost::make_counting_iterator(m_aabb_trees.size()))); } - std::vector > - set_transformation_and_get_all_intersections_and_inclusions(std::size_t mesh_id, - const Aff_transformation_3& aff_trans) +/// \cond SKIP_IN_MANUAL + // versions without NP + static + void collect_one_point_per_connected_component( + const TriangleMesh& tm, + std::vector& points) { - CGAL::Interval_nt_advanced::Protector protector; - set_transformation(mesh_id, aff_trans); - return get_all_intersections_and_inclusions(mesh_id); + collect_one_point_per_connected_component(tm, points, parameters::all_default()); } + + std::size_t add_mesh(const TriangleMesh& tm) + { + return add_mesh(tm, parameters::all_default()); + } + + void remove_mesh(std::size_t mesh_id) + { + if(mesh_id >= m_aabb_trees.size()) return; + if (m_own_aabb_trees[mesh_id]) delete m_aabb_trees[mesh_id]; + m_own_aabb_trees.erase( m_own_aabb_trees.begin()+mesh_id ); + m_aabb_trees.erase( m_aabb_trees.begin()+mesh_id); + m_is_closed.erase(m_is_closed.begin()+mesh_id); + m_points_per_cc.erase(m_points_per_cc.begin()+mesh_id); + m_traversal_traits.erase(m_traversal_traits.begin()+mesh_id); +#if CGAL_RMCD_CACHE_BOXES + // TODO this is a lazy approach that is not optimal + m_bboxes.pop_back(); + m_bboxes_is_invalid.set(); + m_bboxes_is_invalid.resize(m_aabb_trees.size()); +#endif + } +/// \endcond }; } // end of CGAL namespace From c3943386bc644482616229caecd0f9e606575abd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 3 Oct 2018 13:54:31 +0200 Subject: [PATCH 62/84] rename main class --- .../AABB_tree/Do_trees_intersect_plugin.cpp | 7 +++---- .../doc/Polygon_mesh_processing/PackageDescription.txt | 2 +- ...ion.h => Rigid_triangle_mesh_collision_detection.h} | 10 +++++----- 3 files changed, 9 insertions(+), 10 deletions(-) rename Polygon_mesh_processing/include/CGAL/{Rigid_mesh_collision_detection.h => Rigid_triangle_mesh_collision_detection.h} (98%) diff --git a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp index 753a62858a3..7ed8bb2ee0f 100644 --- a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -14,7 +13,7 @@ #include #include #include -#include +#include #include "Scene.h" class DoTreesIntersectplugin: @@ -130,7 +129,7 @@ private Q_SLOTS: scene->setSelectedItem(group_item->getChildren().last()); connect(static_cast(scene), &Scene::itemIndexSelected, this, &DoTreesIntersectplugin::update_trees); - col_det = new CGAL::Rigid_mesh_collision_detection(); + col_det = new CGAL::Rigid_triangle_mesh_collision_detection(); col_det->reserve(items.size()); Q_FOREACH(Scene_movable_sm_item* item, items) { @@ -339,7 +338,7 @@ private: Messages_interface* messageInterface; CGAL::Three::Scene_interface* scene; QMainWindow* mw; - CGAL::Rigid_mesh_collision_detection *col_det; + CGAL::Rigid_triangle_mesh_collision_detection *col_det; std::vector items; std::vector prev_ids; Scene_group_item* group_item; diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt index 296efe448b8..7fd55c0d214 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt @@ -182,7 +182,7 @@ and provides a list of the parameters that are used in this package. - `CGAL::Polygon_mesh_processing::detect_vertex_incident_patches()` ## Collision Detection -- `CGAL::Rigid_mesh_collision_detection` +- `CGAL::Rigid_triangle_mesh_collision_detection` ## Miscellaneous ## - `CGAL::Polygon_mesh_slicer` diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h similarity index 98% rename from Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h rename to Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h index 58eb487af7d..f418e2fa1d2 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h @@ -20,8 +20,8 @@ // Author(s) : Maxime Gimeno and Sebastien Loriot -#ifndef CGAL_RIGID_MESH_COLLISION_DETECTION_H -#define CGAL_RIGID_MESH_COLLISION_DETECTION_H +#ifndef CGAL_RIGID_TRIANGLE_MESH_COLLISION_DETECTION_H +#define CGAL_RIGID_TRIANGLE_MESH_COLLISION_DETECTION_H #include @@ -69,7 +69,7 @@ template -class Rigid_mesh_collision_detection +class Rigid_triangle_mesh_collision_detection { // Vertex point map type typedef typename property_map_selector::value_type Point_3; - ~Rigid_mesh_collision_detection() + ~Rigid_triangle_mesh_collision_detection() { int i=0; BOOST_FOREACH(Tree* tree, m_aabb_trees){ @@ -542,4 +542,4 @@ public: #undef CGAL_RMCD_CACHE_BOXES -#endif // CGAL_RIGID_MESH_COLLISION_DETECTION_H +#endif // CGAL_RIGID_TRIANGLE_MESH_COLLISION_DETECTION_H From 241d088b5a3b1d7708c34bc2600ccb9168f85369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 3 Oct 2018 14:44:02 +0200 Subject: [PATCH 63/84] update after review of @maxGimeno --- .../Rigid_triangle_mesh_collision_detection.h | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h index f418e2fa1d2..4a4c69cb26f 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h @@ -59,10 +59,11 @@ namespace CGAL { * of `TriangleMesh` if it exists. * @tparam Kernel a model of CGAL Kernel. %Default is the Kernel of the value type of `VertexPointMap` retrieved using * `Kernel_traits`. - * @tparam AABBTree_type a `AABB_tree` that can containing faces of `TriangleMesh`. %Default is using `AABB_traits` with + * @tparam AABBTree_type an `AABB_tree` that can containing faces of `TriangleMesh`. %Default is using `AABB_traits` with * `AABB_face_graph_triangle_primitive` as primitive type. - * @tparam HAS_ROTATION tag indicating whether the transformations applied to meshes may contain a rotation (`Tag_true`) - * or if only translation and scaling are applied (`Tag_false`). + * @tparam HAS_ROTATION tag indicating whether the transformations applied to meshes may contain rotations (`Tag_true`) + * or if only translations and scalings are applied (`Tag_false`). Some optimizations are + * switch on in case there are no rotations. */ template get_all_intersections(std::size_t mesh_id) const @@ -433,11 +434,11 @@ public: } /*! - * returns a vector of ids of meshes within `ids` that are intersecting with the mesh with id `mesh_id`, + * returns a vector of the ids of meshes within `ids` that are intersecting with the mesh with id `mesh_id`, * considering volume inclusions for closed meshes. - * More precisely, if at least one triangle face of a mesh with id `i` intersects a triangle face + * More precisely, if at least one face of a mesh with id `i` intersects a face * of the mesh with id `mesh_id`, the pair `(i, false)` is put in the output vector. - * If there is no triangle face intersection, but at least one of the meshes with ids `i` and `mesh_id` is closed, + * If there is no face intersection, but at least one of the meshes with ids `i` and `mesh_id` is closed, * and at least one connected component is included in the bounded volume defined by a closed mesh then the pair * `(i, true)` is put in the output vector (independently of mesh `i` or `mesh_id` being the one including the other). * The inclusion test is done using `Side_of_triangle_mesh`, in particular surface orientation is ignored and only the @@ -447,7 +448,7 @@ public: * * \tparam MeshRangeIds a range of ids convertible to `std::size_t`. * - * \note If a mesh is made of several connected components and at least component which is not closed, + * \note If a mesh is made of several connected components and at least one component is not closed, * then no inclusion test will be made even if some components are closed. * */ @@ -491,7 +492,7 @@ public: } /*! - * returns a vector of ids of meshes in the pool that are intersecting with the mesh with id `mesh_id`, + * returns a vector of the ids of meshes in the pool that are intersecting with the mesh with id `mesh_id`, * considering volume inclusions for closed meshes. * See the previous overload for details. */ From e868d87507cd1e021b688a1dcc900e611a71fe8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 3 Oct 2018 16:36:27 +0200 Subject: [PATCH 64/84] remove_mesh no longer invalidate mesh ids --- ...ABB_traversal_traits_with_transformation.h | 3 + .../Rigid_triangle_mesh_collision_detection.h | 656 ++++++++++-------- 2 files changed, 354 insertions(+), 305 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h index 685d2afb987..5d11b3e761a 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h @@ -139,6 +139,9 @@ class Do_intersect_traversal_traits_with_transformation {} public: + Do_intersect_traversal_traits_with_transformation(): + m_traits_ptr(NULL) + {} Do_intersect_traversal_traits_with_transformation(const AABBTraits& traits) : m_is_found(false), m_traits_ptr(&traits), m_has_rotation(false) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h index 4a4c69cb26f..f16b669d9c8 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h @@ -102,11 +102,73 @@ class Rigid_triangle_mesh_collision_detection std::vector m_is_closed; std::vector< std::vector > m_points_per_cc; std::vector m_traversal_traits; + std::size_t m_free_id; // position in m_id_pool of the first free element + std::vector m_id_pool; // 0-> m_id_pool-1 are valid mesh ids #if CGAL_RMCD_CACHE_BOXES boost::dynamic_bitset<> m_bboxes_is_invalid; std::vector m_bboxes; #endif +// internal functions + std::size_t get_id_for_new_mesh() + { + if (m_free_id==m_id_pool.size()) + { + m_id_pool.push_back(m_free_id); + ++m_free_id; + m_own_aabb_trees.resize(m_free_id); + m_aabb_trees.resize(m_free_id, NULL); + m_is_closed.resize(m_free_id); + m_points_per_cc.resize(m_free_id); + m_traversal_traits.resize(m_free_id); + #if CGAL_RMCD_CACHE_BOXES + m_bboxes.resize(m_free_id); + m_bboxes_is_invalid.resize(m_free_id, true); + #endif + return m_id_pool.back(); + } + return m_id_pool[m_free_id++]; + } + + template + void add_cc_points(const TriangleMesh& tm, std::size_t id, const NamedParameters& np) + { + m_points_per_cc.resize(m_points_per_cc.size()+1); + collect_one_point_per_connected_component(tm, m_points_per_cc[id], np); + } + + // precondition A and B does not intersect + bool does_A_contains_a_CC_of_B(std::size_t id_A, std::size_t id_B) const + { + typename Kernel::Construct_ray_3 ray_functor; + typename Kernel::Construct_vector_3 vector_functor; + typedef typename Traversal_traits::Transformed_tree_helper Helper; + + BOOST_FOREACH(const typename Kernel::Point_3& q, m_points_per_cc[id_B]) + { + if( internal::Point_inside_vertical_ray_cast(m_traversal_traits[id_A].get_helper())( + m_traversal_traits[id_B].transformation()( q ), *m_aabb_trees[id_A], + ray_functor, vector_functor) == CGAL::ON_BOUNDED_SIDE) + { + return true; + } + } + return false; + } + + // this function expects a protector was initialized + bool does_A_intersect_B(std::size_t id_A, std::size_t id_B) const + { +#if CGAL_RMCD_CACHE_BOXES + if (!do_overlap(m_bboxes[id_B], m_bboxes[id_A])) continue; +#endif + + Do_intersect_traversal_traits_for_two_trees traversal_traits( + m_aabb_trees[id_B]->traits(), m_traversal_traits[id_B].transformation(), m_traversal_traits[id_A]); + m_aabb_trees[id_B]->traversal(*m_aabb_trees[id_A], traversal_traits); + return traversal_traits.is_intersection_found(); + } + public: #ifdef DOXYGEN_RUNNING /// The AABB_tree type representing the triangles of each input mesh @@ -120,16 +182,300 @@ public: /// Point type typedef typename boost::property_traits::value_type Point_3; + Rigid_triangle_mesh_collision_detection() + : m_free_id(0) + {} + ~Rigid_triangle_mesh_collision_detection() { - int i=0; - BOOST_FOREACH(Tree* tree, m_aabb_trees){ - if (m_own_aabb_trees[i]) delete tree; - ++i; + for (std::size_t k=0; k + std::size_t add_mesh(const TriangleMesh& tm, + const NamedParameters& np) + { + // handle vpm + using Polygon_mesh_processing::GetVertexPointMap; + typedef typename GetVertexPointMap::type Local_vpm; + CGAL_USE_TYPE(Local_vpm); + CGAL_assertion_code( + static const bool same_vpm = (boost::is_same::value); ) + CGAL_static_assertion(same_vpm); + + Vpm vpm = + boost::choose_param(boost::get_param(np, internal_np::vertex_point), + get_const_property_map(boost::vertex_point, tm) ); + // now add the mesh + std::size_t id = get_id_for_new_mesh(); + CGAL_assertion( m_aabb_trees[id] == NULL ); + m_is_closed[id] = is_closed(tm); + m_own_aabb_trees[id] = true; + Tree* t = new Tree(faces(tm).begin(), faces(tm).end(), tm, vpm); + m_aabb_trees[id] = t; + m_traversal_traits[id] = Traversal_traits(m_aabb_trees.back()->traits()); + add_cc_points(tm, id, np); + + return id; + } + + /*! + * adds an instance of a triangulated surface mesh using an external tree of its faces. + * Note that the tree is not copied and the lifetime of `tree` must be longer than + * that of this class. + * + * \return the id of the instance used to refer to that mesh. + * + * @param tree an AABB-tree of faces of a mesh + * @param is_closed `true` is the mesh in `tree` is closed, and `false` otherwise. + * \link is_closed() `CGAL::is_closed()` \endlink can be used for that purpose. + * @param points_per_cc a vector containing one point of a vertex for each connected + * component of the triangle surface mesh in `tree` + */ + std::size_t add_mesh(const AABB_tree& tree, + bool is_closed, + const std::vector& points_per_cc) + { + std::size_t id = get_id_for_new_mesh(); + CGAL_assertion( m_aabb_trees[id] == NULL ); + m_is_closed[id] = is_closed; + m_own_aabb_trees[id] = false ; + m_aabb_trees = const_cast(&tree); + m_traversal_traits[id] = Traversal_traits(m_aabb_trees.back()->traits()); + m_points_per_cc[id] = points_per_cc; + + return id; + } + + /*! + * sets the transformation associated to a mesh identified by its id in the pool. + */ + void set_transformation(std::size_t mesh_id, const Aff_transformation_3& aff_trans) + { + CGAL_assertion(m_aabb_trees[mesh_id] != NULL); + m_traversal_traits[mesh_id].set_transformation(aff_trans); +#if CGAL_RMCD_CACHE_BOXES + m_bboxes_is_invalid.set(mesh_id); +#endif + } + +#if CGAL_RMCD_CACHE_BOXES + void update_bboxes() + { + // protector is supposed to have been set + for (boost::dynamic_bitset<>::size_type i = m_bboxes_is_invalid.find_first(); + i != m_bboxes_is_invalid.npos; + i = m_bboxes_is_invalid.find_next(i)) + { + m_bboxes[i]=m_traversal_traits[i].get_helper().get_tree_bbox(*m_aabb_trees[i]); + } + m_bboxes_is_invalid.reset(); + } +#endif + + /*! + * returns a vector of the ids of meshes within `ids` that have at least a face + * intersecting a face of the mesh with id `mesh_id`. + * If `mesh_id` is in `ids` it is not reported. + * \tparam MeshRangeIds a range of ids convertible to `std::size_t`. + */ + template + std::vector + get_all_intersections(std::size_t mesh_id, const MeshRangeIds& ids) const + { + CGAL_assertion(m_aabb_trees[mesh_id] != NULL); + CGAL::Interval_nt_advanced::Protector protector; +#if CGAL_RMCD_CACHE_BOXES + update_bboxes(); +#endif + std::vector res; + + // TODO: use a non-naive version + BOOST_FOREACH(std::size_t k, ids) + { + CGAL_assertion(m_aabb_trees[k] != NULL); + if(k==mesh_id) continue; + + if (does_A_intersect_B(mesh_id, k)) + res.push_back(k); + } + return res; + } + + /*! + * returns a vector of the ids of meshes in the pool that have at least a face + * intersecting a face of the mesh with id `mesh_id` + */ + std::vector + get_all_intersections(std::size_t mesh_id) const + { + return get_all_intersections( + mesh_id, + make_range(m_id_pool.begin(),m_id_pool.begin()+m_free_id) ); + } + + /*! + * returns a vector of the ids of meshes within `ids` that are intersecting with the mesh with id `mesh_id`, + * considering volume inclusions for closed meshes. + * More precisely, if at least one face of a mesh with id `i` intersects a face + * of the mesh with id `mesh_id`, the pair `(i, false)` is put in the output vector. + * If there is no face intersection, but at least one of the meshes with ids `i` and `mesh_id` is closed, + * and at least one connected component is included in the bounded volume defined by a closed mesh then the pair + * `(i, true)` is put in the output vector (independently of mesh `i` or `mesh_id` being the one including the other). + * The inclusion test is done using `Side_of_triangle_mesh`, in particular surface orientation is ignored and only the + * nesting level of connected components defines a bounded volume. If a mesh has some self-intersection the inclusion + * test may return incorrect results. + * If `mesh_id` is in `ids` it is not reported. + * + * \tparam MeshRangeIds a range of ids convertible to `std::size_t`. + * + * \note If a mesh is made of several connected components and at least one component is not closed, + * then no inclusion test will be made even if some components are closed. + * + */ + template + std::vector > + get_all_intersections_and_inclusions(std::size_t mesh_id, const MeshRangeIds& ids) const + { + CGAL_assertion(m_aabb_trees[mesh_id] != NULL); + CGAL::Interval_nt_advanced::Protector protector; +#if CGAL_RMCD_CACHE_BOXES + update_bboxes(); +#endif + std::vector > res; + + // TODO: use a non-naive version + BOOST_FOREACH(std::size_t k, ids) + { + CGAL_assertion(m_aabb_trees[k] != NULL); + if(k==mesh_id) continue; + + if (does_A_intersect_B(mesh_id, k)) + res.push_back(std::make_pair(k, false)); + else{ + if (m_is_closed[mesh_id]) + { + if ( does_A_contains_a_CC_of_B(mesh_id, k) ) + { + res.push_back(std::make_pair(k, true)); + continue; + } + } + if (m_is_closed[k]) + { + if ( does_A_contains_a_CC_of_B(k, mesh_id) ) + { + res.push_back(std::make_pair(k, true)); + continue; + } + } + } + } + return res; + } + + /*! + * returns a vector of the ids of meshes in the pool that are intersecting with the mesh with id `mesh_id`, + * considering volume inclusions for closed meshes. + * See the previous overload for details. + */ + std::vector > + get_all_intersections_and_inclusions(std::size_t mesh_id) const + { + return get_all_intersections_and_inclusions(mesh_id, + make_range(m_id_pool.begin(),m_id_pool.begin()+m_free_id) ); + } + +/// \name Memory Management + /*! + * increases the capacity of data structures used internally, `size` being the number of meshes expected to be added. + */ + void reserve(std::size_t size) + { + m_own_aabb_trees.reserve(size); + m_aabb_trees.reserve(size); + m_is_closed.reserve(size); + m_points_per_cc.reserve(size); + m_traversal_traits.reserve(size); +#if CGAL_RMCD_CACHE_BOXES + m_bboxes.reserve(size); +#endif + } + + /*! + * removes the mesh with id `mesh_id` from the pool, the indices of other meshes are kept unchanged. + */ + void remove_mesh(std::size_t mesh_id) + { + std::vector::iterator itf = + std::find(m_id_pool.begin(), m_id_pool.begin()+m_free_id, mesh_id); + if (itf == m_id_pool.begin()+m_free_id) return; + + if (m_own_aabb_trees[mesh_id]) delete m_aabb_trees[mesh_id]; + m_aabb_trees[mesh_id] = NULL; + if (m_id_pool[m_free_id-1]!=mesh_id) + std::swap(m_id_pool[m_free_id-1], *itf); + --m_free_id; + } + + /*! + * returns the number of meshes in the pool + */ + std::size_t size() const + { + return m_free_id; + } + + /*! + * returns the number of times `add_mesh()` was called minus the number of times `remove_mesh()` (with a valid mesh id) was called + */ + std::size_t size_of_garbage() + { + return m_id_pool.size() - m_free_id; + } + + /*! + * returns `false` if `mesh_id` corresponds to an id not used (removed and/or not affected), and `true` otherwise. + */ + bool is_valid_index(std::size_t mesh_id) + { + if (mesh_id >= m_id_pool.size()) return false; + return m_aabb_trees[mesh_id] != NULL; + } + +/// \name Helper Static Function + /*! * fills `points` with one point per connected component of `tm`. This is a helper function * intended to be used before calling the `add_mesh()` overload taking an AABB-tree instead of a mesh @@ -222,289 +568,6 @@ public: points.push_back( get(vpm, *boost::begin(vertices(tm))) ); } -private: - template - void add_cc_points(const TriangleMesh& tm, const NamedParameters& np) - { - m_points_per_cc.resize(m_points_per_cc.size()+1); - collect_one_point_per_connected_component(tm, m_points_per_cc.back(), np); - } - - // precondition A and B does not intersect - bool does_A_contains_a_CC_of_B(std::size_t id_A, std::size_t id_B) const - { - typename Kernel::Construct_ray_3 ray_functor; - typename Kernel::Construct_vector_3 vector_functor; - typedef typename Traversal_traits::Transformed_tree_helper Helper; - - BOOST_FOREACH(const typename Kernel::Point_3& q, m_points_per_cc[id_B]) - { - if( internal::Point_inside_vertical_ray_cast(m_traversal_traits[id_A].get_helper())( - m_traversal_traits[id_B].transformation()( q ), *m_aabb_trees[id_A], - ray_functor, vector_functor) == CGAL::ON_BOUNDED_SIDE) - { - return true; - } - } - return false; - } - - // this function expects a protector was initialized - bool does_A_intersect_B(std::size_t id_A, std::size_t id_B) const - { -#if CGAL_RMCD_CACHE_BOXES - if (!do_overlap(m_bboxes[id_B], m_bboxes[id_A])) continue; -#endif - - Do_intersect_traversal_traits_for_two_trees traversal_traits( - m_aabb_trees[id_B]->traits(), m_traversal_traits[id_B].transformation(), m_traversal_traits[id_A]); - m_aabb_trees[id_B]->traversal(*m_aabb_trees[id_A], traversal_traits); - return traversal_traits.is_intersection_found(); - } - -public: - - /*! - * adds mesh `tm` in the pool of meshes to be considered for intersection. - * - * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" - * - * \return the id of `tm` used to refer to that mesh. - * - * @param tm triangulated surface mesh to add - * @param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below - * - * \cgalNamedParamsBegin - * \cgalParamBegin{vertex_point_map} - * the property map with the points associated to the vertices of `tm`. - * If this parameter is omitted, an internal property map for - * `CGAL::vertex_point_t` must be available in `TriangleMesh` - * \cgalParamEnd - * \cgalParamBegin{face_index_map} - * a property map containing the index of each face of `tm`. It must be initialized - * and the value must be unique per face and in the range `[0, num_faces(tm)[`. - * \cgalParamEnd - * \cgalParamBegin{apply_per_connected_component} - * if `false`, `tm` is assumed to have only one connected component, avoiding - * the extraction of connected components. Default is `true`. - * \cgalParamEnd - * \cgalNamedParamsEnd - */ - template - std::size_t add_mesh(const TriangleMesh& tm, - const NamedParameters& np) - { - // handle vpm - using Polygon_mesh_processing::GetVertexPointMap; - typedef typename GetVertexPointMap::type Local_vpm; - CGAL_USE_TYPE(Local_vpm); - CGAL_assertion_code( - static const bool same_vpm = (boost::is_same::value); ) - CGAL_static_assertion(same_vpm); - - Vpm vpm = - boost::choose_param(boost::get_param(np, internal_np::vertex_point), - get_const_property_map(boost::vertex_point, tm) ); - // now add the mesh - std::size_t id = m_aabb_trees.size(); - m_is_closed.push_back(is_closed(tm)); - m_own_aabb_trees.push_back( true ); - Tree* t = new Tree(faces(tm).begin(), faces(tm).end(), tm, vpm); - m_aabb_trees.push_back(t); - m_traversal_traits.push_back( Traversal_traits(m_aabb_trees.back()->traits()) ); -#if CGAL_RMCD_CACHE_BOXES - m_bboxes.push_back(Bbox_3()); - m_bboxes_is_invalid.resize(id+1, true); -#endif - add_cc_points(tm, np); - - return id; - } - - /*! - * adds an instance of a triangulated surface mesh using an external tree of its faces. - * Note that the tree is not copied and the lifetime of `tree` must be longer than - * that of this class. - * - * \return the id of the instance used to refer to that mesh. - * - * @param tree an AABB-tree of faces of a mesh - * @param is_closed `true` is the mesh in `tree` is closed, and `false` otherwise. - * \link is_closed() `CGAL::is_closed()` \endlink can be used for that purpose. - * @param points_per_cc a vector containing one point of a vertex for each connected - * component of the triangle surface mesh in `tree` - */ - std::size_t add_mesh(const AABB_tree& tree, - bool is_closed, - const std::vector& points_per_cc) - { - std::size_t id = m_aabb_trees.size(); - m_is_closed.push_back(is_closed); - m_own_aabb_trees.push_back( false ); - m_aabb_trees.push_back( const_cast(&tree)); - m_traversal_traits.push_back( Traversal_traits(m_aabb_trees.back()->traits()) ); -#if CGAL_RMCD_CACHE_BOXES - m_bboxes.push_back(Bbox_3()); - m_bboxes_is_invalid.resize(id+1, true); -#endif - m_points_per_cc.push_back(points_per_cc); - - return id; - } - - /*! - * increases the capacity of data structures used internally, `size` being the number of meshes expected to be added. - */ - void reserve(std::size_t size) - { - m_own_aabb_trees.reserve(size); - m_aabb_trees.reserve(size); - m_is_closed.reserve(size); - m_points_per_cc.reserve(size); - m_traversal_traits.reserve(size); -#if CGAL_RMCD_CACHE_BOXES - m_bboxes.reserve(size); -#endif - } - - /*! - * sets the transformation associated to a mesh identified by its id in the pool. - */ - void set_transformation(std::size_t mesh_id, const Aff_transformation_3& aff_trans) - { - m_traversal_traits[mesh_id].set_transformation(aff_trans); -#if CGAL_RMCD_CACHE_BOXES - m_bboxes_is_invalid.set(mesh_id); -#endif - } - -#if CGAL_RMCD_CACHE_BOXES - void update_bboxes() - { - // protector is supposed to have been set - for (boost::dynamic_bitset<>::size_type i = m_bboxes_is_invalid.find_first(); - i != m_bboxes_is_invalid.npos; - i = m_bboxes_is_invalid.find_next(i)) - { - m_bboxes[i]=m_traversal_traits[i].get_helper().get_tree_bbox(*m_aabb_trees[i]); - } - m_bboxes_is_invalid.reset(); - } -#endif - - /*! - * returns a vector of the ids of meshes within `ids` that have at least a face - * intersecting a face of the mesh with id `mesh_id`. - * If `mesh_id` is in `ids` it is not reported. - * \tparam MeshRangeIds a range of ids convertible to `std::size_t`. - */ - template - std::vector - get_all_intersections(std::size_t mesh_id, const MeshRangeIds& ids) const - { - CGAL::Interval_nt_advanced::Protector protector; -#if CGAL_RMCD_CACHE_BOXES - update_bboxes(); -#endif - std::vector res; - - // TODO: use a non-naive version - BOOST_FOREACH(std::size_t k, ids) - { - if(k==mesh_id) continue; - - if (does_A_intersect_B(mesh_id, k)) - res.push_back(k); - } - return res; - } - - /*! - * returns a vector of the ids of meshes in the pool that have at least a face - * intersecting a face of the mesh with id `mesh_id` - */ - std::vector - get_all_intersections(std::size_t mesh_id) const - { - return get_all_intersections( - mesh_id, - make_range(boost::make_counting_iterator(0), - boost::make_counting_iterator(m_aabb_trees.size()))); - } - - /*! - * returns a vector of the ids of meshes within `ids` that are intersecting with the mesh with id `mesh_id`, - * considering volume inclusions for closed meshes. - * More precisely, if at least one face of a mesh with id `i` intersects a face - * of the mesh with id `mesh_id`, the pair `(i, false)` is put in the output vector. - * If there is no face intersection, but at least one of the meshes with ids `i` and `mesh_id` is closed, - * and at least one connected component is included in the bounded volume defined by a closed mesh then the pair - * `(i, true)` is put in the output vector (independently of mesh `i` or `mesh_id` being the one including the other). - * The inclusion test is done using `Side_of_triangle_mesh`, in particular surface orientation is ignored and only the - * nesting level of connected components defines a bounded volume. If a mesh has some self-intersection the inclusion - * test may return incorrect results. - * If `mesh_id` is in `ids` it is not reported. - * - * \tparam MeshRangeIds a range of ids convertible to `std::size_t`. - * - * \note If a mesh is made of several connected components and at least one component is not closed, - * then no inclusion test will be made even if some components are closed. - * - */ - template - std::vector > - get_all_intersections_and_inclusions(std::size_t mesh_id, const MeshRangeIds& ids) const - { - CGAL::Interval_nt_advanced::Protector protector; -#if CGAL_RMCD_CACHE_BOXES - update_bboxes(); -#endif - std::vector > res; - - // TODO: use a non-naive version - BOOST_FOREACH(std::size_t k, ids) - { - if(k==mesh_id) continue; - - if (does_A_intersect_B(mesh_id, k)) - res.push_back(std::make_pair(k, false)); - else{ - if (m_is_closed[mesh_id]) - { - if ( does_A_contains_a_CC_of_B(mesh_id, k) ) - { - res.push_back(std::make_pair(k, true)); - continue; - } - } - if (m_is_closed[k]) - { - if ( does_A_contains_a_CC_of_B(k, mesh_id) ) - { - res.push_back(std::make_pair(k, true)); - continue; - } - } - } - } - return res; - } - - /*! - * returns a vector of the ids of meshes in the pool that are intersecting with the mesh with id `mesh_id`, - * considering volume inclusions for closed meshes. - * See the previous overload for details. - */ - std::vector > - get_all_intersections_and_inclusions(std::size_t mesh_id) const - { - return get_all_intersections_and_inclusions( - mesh_id, - make_range(boost::make_counting_iterator(0), - boost::make_counting_iterator(m_aabb_trees.size()))); - } - /// \cond SKIP_IN_MANUAL // versions without NP static @@ -519,23 +582,6 @@ public: { return add_mesh(tm, parameters::all_default()); } - - void remove_mesh(std::size_t mesh_id) - { - if(mesh_id >= m_aabb_trees.size()) return; - if (m_own_aabb_trees[mesh_id]) delete m_aabb_trees[mesh_id]; - m_own_aabb_trees.erase( m_own_aabb_trees.begin()+mesh_id ); - m_aabb_trees.erase( m_aabb_trees.begin()+mesh_id); - m_is_closed.erase(m_is_closed.begin()+mesh_id); - m_points_per_cc.erase(m_points_per_cc.begin()+mesh_id); - m_traversal_traits.erase(m_traversal_traits.begin()+mesh_id); -#if CGAL_RMCD_CACHE_BOXES - // TODO this is a lazy approach that is not optimal - m_bboxes.pop_back(); - m_bboxes_is_invalid.set(); - m_bboxes_is_invalid.resize(m_aabb_trees.size()); -#endif - } /// \endcond }; From bfa9844b1afd13940972a350f29264b0a3f6365d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 4 Oct 2018 10:33:11 +0200 Subject: [PATCH 65/84] make default vpm of mesh convertible to default vpm of const mesh --- BGL/include/CGAL/boost/graph/properties.h | 26 ++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/BGL/include/CGAL/boost/graph/properties.h b/BGL/include/CGAL/boost/graph/properties.h index c720256b591..9a86de3f6b8 100644 --- a/BGL/include/CGAL/boost/graph/properties.h +++ b/BGL/include/CGAL/boost/graph/properties.h @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include @@ -267,7 +269,9 @@ struct Edge_index_accessor reference operator[](Handle h) const { return h.id(); } }; -template +template::type >::value> struct Point_accessor : boost::put_get_helper< Reference, Point_accessor > { @@ -279,6 +283,26 @@ struct Point_accessor reference operator[](Handle h) const { return h->point(); } }; +// partial specialization for const map to make them constructible from non-const map +template +struct Point_accessor + : boost::put_get_helper< ConstReference, Point_accessor > +{ + typedef boost::lvalue_property_map_tag category; + typedef ConstReference reference; + typedef ValueType value_type; + typedef Handle key_type; + + typedef typename boost::mpl::if_< boost::is_reference, + ValueType&, + ValueType >::type Reference; + + Point_accessor() {} + Point_accessor(Point_accessor) {} + + reference operator[](Handle h) const { return h->point(); } +}; + } // namespace internal // Needed by PMP::detec_features and Mesh_3 From 4cf7f5e047b2d34781540aeeb3653e89c4be54b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 4 Oct 2018 10:33:45 +0200 Subject: [PATCH 66/84] use Point_accessor instead of a duplicate --- .../graph/graph_traits_HalfedgeDS_default.h | 20 +++---------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/HalfedgeDS/include/CGAL/boost/graph/graph_traits_HalfedgeDS_default.h b/HalfedgeDS/include/CGAL/boost/graph/graph_traits_HalfedgeDS_default.h index 6b3898880b1..aaddbbe254a 100644 --- a/HalfedgeDS/include/CGAL/boost/graph/graph_traits_HalfedgeDS_default.h +++ b/HalfedgeDS/include/CGAL/boost/graph/graph_traits_HalfedgeDS_default.h @@ -25,6 +25,7 @@ #include #include #include +#include namespace CGAL { @@ -446,21 +447,6 @@ num_faces(const HalfedgeDS_default& p) { return p.size_of_faces(); } -namespace internal { - -template -struct HDS_Point_accessor - : boost::put_get_helper< Reference, HDS_Point_accessor > -{ - typedef boost::lvalue_property_map_tag category; - typedef Reference reference; - typedef ValueType value_type; - typedef Handle key_type; - - reference operator[](Handle h) const { return h->point(); } -}; - -} // namespace internal template struct HDS_property_map; @@ -471,13 +457,13 @@ struct HDS_property_map template struct bind_ { - typedef internal::HDS_Point_accessor< + typedef internal::Point_accessor< typename boost::graph_traits< HalfedgeDS_default >::vertex_descriptor, typename T::Point_3, typename T::Point_3&> type; - typedef internal::HDS_Point_accessor< + typedef internal::Point_accessor< typename boost::graph_traits< HalfedgeDS_default >::vertex_descriptor, From baf27bbd6e04b099b4a1dad21150b58d8d315aec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 4 Oct 2018 10:34:41 +0200 Subject: [PATCH 67/84] use const map (non-const map should be convertible to const map in practice) --- AABB_tree/include/CGAL/AABB_face_graph_triangle_primitive.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AABB_tree/include/CGAL/AABB_face_graph_triangle_primitive.h b/AABB_tree/include/CGAL/AABB_face_graph_triangle_primitive.h index 83e01c72d6c..7283f77095a 100644 --- a/AABB_tree/include/CGAL/AABB_face_graph_triangle_primitive.h +++ b/AABB_tree/include/CGAL/AABB_face_graph_triangle_primitive.h @@ -70,17 +70,17 @@ class AABB_face_graph_triangle_primitive FaceGraph, typename Default::Get::type >::type>, + vertex_point_t>::const_type >::type>, One_point_from_face_descriptor_map< FaceGraph, typename Default::Get::type >::type>, + vertex_point_t>::const_type >::type>, OneFaceGraphPerTree, CacheDatum > #endif { - typedef typename Default::Get::type >::type VertexPointPMap_; + typedef typename Default::Get::const_type >::type VertexPointPMap_; typedef typename boost::graph_traits::face_descriptor Id_; typedef Triangle_from_face_descriptor_map Triangle_property_map; From fcc99af1eb0adb650df70691bba34ee1cf3482c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 4 Oct 2018 10:38:00 +0200 Subject: [PATCH 68/84] fix typo and clean-up --- .../CGAL/Rigid_triangle_mesh_collision_detection.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h index f16b669d9c8..79318f4ccd3 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h @@ -228,7 +228,7 @@ public: // handle vpm using Polygon_mesh_processing::GetVertexPointMap; typedef typename GetVertexPointMap::type Local_vpm; + NamedParameters>::const_type Local_vpm; CGAL_USE_TYPE(Local_vpm); CGAL_assertion_code( static const bool same_vpm = (boost::is_same::value); ) @@ -242,7 +242,7 @@ public: CGAL_assertion( m_aabb_trees[id] == NULL ); m_is_closed[id] = is_closed(tm); m_own_aabb_trees[id] = true; - Tree* t = new Tree(faces(tm).begin(), faces(tm).end(), tm, vpm); + Tree* t = new Tree(boost::begin(faces(tm)), boost::end(faces(tm)), tm, vpm); m_aabb_trees[id] = t; m_traversal_traits[id] = Traversal_traits(m_aabb_trees.back()->traits()); add_cc_points(tm, id, np); @@ -271,7 +271,7 @@ public: CGAL_assertion( m_aabb_trees[id] == NULL ); m_is_closed[id] = is_closed; m_own_aabb_trees[id] = false ; - m_aabb_trees = const_cast(&tree); + m_aabb_trees[id] = const_cast(&tree); m_traversal_traits[id] = Traversal_traits(m_aabb_trees.back()->traits()); m_points_per_cc[id] = points_per_cc; @@ -518,7 +518,7 @@ public: boost::get_param(np, internal_np::apply_per_connected_component), true); typedef typename GetVertexPointMap::type Local_vpm; + NamedParameters>::const_type Local_vpm; CGAL_USE_TYPE(Local_vpm); CGAL_assertion_code( From 23c60628e4589850c6998d961ed3d14423a2b2b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 4 Oct 2018 10:38:36 +0200 Subject: [PATCH 69/84] add test --- .../Polygon_mesh_processing/CMakeLists.txt | 1 + .../test_pmp_collision_detection.cpp | 177 ++++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_collision_detection.cpp diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt index 124a9379880..768037fd7b3 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt @@ -103,6 +103,7 @@ endif() create_single_source_cgal_program("extrude_test.cpp") create_single_source_cgal_program("test_merging_border_vertices.cpp") create_single_source_cgal_program("test_shape_predicates.cpp") + create_single_source_cgal_program("test_pmp_collision_detection.cpp") if( TBB_FOUND ) CGAL_target_use_TBB(test_pmp_distance) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_collision_detection.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_collision_detection.cpp new file mode 100644 index 00000000000..e86193090b1 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_collision_detection.cpp @@ -0,0 +1,177 @@ +#include +#include +#include + +#include + +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Surface_mesh Surface_mesh; +typedef CGAL::Polyhedron_3 Polyhedron_3; +namespace params = CGAL::parameters; + +void test_remove() +{ + std::cout << "test_remove()" << std::endl; + Surface_mesh sm; + CGAL::Rigid_triangle_mesh_collision_detection collision_detection; + collision_detection.add_mesh(sm); // 0 + collision_detection.add_mesh(sm); // 1 + collision_detection.add_mesh(sm); // 2 + collision_detection.add_mesh(sm); // 3 + collision_detection.add_mesh(sm); // 4 + + assert( collision_detection.is_valid_index(0) ); + assert( collision_detection.is_valid_index(1) ); + assert( collision_detection.is_valid_index(2) ); + assert( collision_detection.is_valid_index(3) ); + assert( collision_detection.is_valid_index(4) ); + assert(!collision_detection.is_valid_index(5) ); + + assert(collision_detection.size() == 5); + + collision_detection.remove_mesh(4); + assert(collision_detection.size() == 4); + assert(!collision_detection.is_valid_index(4)); + + std::size_t id = collision_detection.add_mesh(sm); + assert(id == 4); + + collision_detection.remove_mesh(2); + assert(collision_detection.size() == 4); + assert(!collision_detection.is_valid_index(2)); + id = collision_detection.add_mesh(sm); + assert(id == 2); + + assert( collision_detection.is_valid_index(0) ); + assert( collision_detection.is_valid_index(1) ); + assert( collision_detection.is_valid_index(2) ); + assert( collision_detection.is_valid_index(3) ); + assert( collision_detection.is_valid_index(4) ); + + collision_detection.remove_mesh(3); + assert( collision_detection.size()==4); + assert( collision_detection.size_of_garbage()==1); + collision_detection.remove_mesh(3); + assert( collision_detection.size()==4); + assert( collision_detection.size_of_garbage()==1); + collision_detection.remove_mesh(2); + assert( collision_detection.size()==3); + assert( collision_detection.size_of_garbage()==2); + collision_detection.remove_mesh(1); + assert( collision_detection.size()==2); + assert( collision_detection.size_of_garbage()==3); + collision_detection.remove_mesh(4); + assert( collision_detection.size()==1); + assert( collision_detection.size_of_garbage()==4); + collision_detection.remove_mesh(0); + assert( collision_detection.size()==0); + assert( collision_detection.size_of_garbage()==5); +} + +template +void test_intersections(Index index, const char* type) +{ + std::cout << "test_intersections<"<()" << std::endl; + TriangleMesh tm1, tm2, tm3; + std::ifstream input("data/small_spheres.off"); + assert(input); + input >> tm1; + input.close(); + input.open("data/blobby.off"); + assert(input); + input >> tm2; + input.close(); + input.open("data-coref/large_cube_coplanar.off"); + assert(input); + input >> tm3; + input.close(); + + CGAL::Rigid_triangle_mesh_collision_detection collision_detection; + collision_detection.add_mesh(tm1, params::face_index_map(get(index, tm1))); // 0 + // add tm1 using an external tree + typename CGAL::Rigid_triangle_mesh_collision_detection::AABB_tree + tm1_tree(boost::begin(faces(tm1)), boost::end(faces(tm1)), tm1, get(boost::vertex_point, tm1)); + std::vector points_per_cc; + collision_detection.collect_one_point_per_connected_component( + tm1, points_per_cc, params::face_index_map(get(index, tm1))); + collision_detection.add_mesh(tm1_tree, true, points_per_cc); // 1 small_spheres + collision_detection.add_mesh(tm2, params::face_index_map(get(index, tm2))); // 2 blobby + collision_detection.add_mesh(tm3, params::face_index_map(get(index, tm3))); // 3 large_cube_coplanar + // pool is 0 1 2 3 + collision_detection.remove_mesh(0); + // pool is now 3 1 2 + std::vector inter_res; + std::vector< std::pair > inter_and_inclus_res; + + // spheres intersects both cube and blobby + inter_res = collision_detection.get_all_intersections(1); + assert(inter_res.size() == 2); + assert(inter_res[0] == 3); + assert(inter_res[1] == 2); + + // blobby intersects only spheres + inter_res = collision_detection.get_all_intersections(2); + assert(inter_res.size() == 1); + assert(inter_res[0] == 1); + + // blobby is included into cube + inter_and_inclus_res = collision_detection.get_all_intersections_and_inclusions(2); + assert(inter_and_inclus_res.size() == 2); + assert(inter_and_inclus_res[0].first == 3 && inter_and_inclus_res[0].second); + assert(inter_and_inclus_res[1].first == 1 && !inter_and_inclus_res[1].second); + + // set transformations + K::Aff_transformation_3 tm1_transf(-0.22115682390903474, 0.97263618730220114, 0.071193443439028392, + -2.3805504333121519, 0.37717228816945586, 0.017983434697950496, + 0.92596849898551192, -4.6543355030238258, 0.89935016777420218, + 0.23163644624001295, -0.37082857562196114, -5.4867495857613582); + + K::Aff_transformation_3 tm2_transf(-0.10062050938738221, -0.92610032901754502, -0.36361200981845854, + -2.1218726603809985, 0.98718082597554757, -0.13844084127856282, + 0.079423864753106477, -4.6627185424110094, -0.1238932198179533, + -0.35095913445824267, 0.92815847570523291, -5.349009707055858); + + K::Aff_transformation_3 tm3_transf(0.8523140340417823, -0.41651563577194606, -0.3163471392835962, + -2.0549216027623891, 0.34883891716890358, 0.90335137983769587, + -0.24953495629622252, -5.8394794922248607, 0.3897078357485903, + 0.10232795171810326, 0.91523592207328008, -5.2436990668816268); + + collision_detection.set_transformation(1, tm1_transf); + collision_detection.set_transformation(2, tm2_transf); + collision_detection.set_transformation(3, tm3_transf); + + // spheres intersects blobby + inter_res = collision_detection.get_all_intersections(1); + assert(inter_res.size() == 1); + assert(inter_res[0] == 2); + + // blobby intersect spheres and cube + inter_res = collision_detection.get_all_intersections(2); + assert(inter_res.size() == 2); + assert(inter_res[0] == 3); + assert(inter_res[1] == 1); + + // cube contains one CC of spheres + inter_and_inclus_res = collision_detection.get_all_intersections_and_inclusions(3); + assert(inter_and_inclus_res.size() == 2); + assert(inter_and_inclus_res[0].first == 1 && inter_and_inclus_res[0].second); + assert(inter_and_inclus_res[1].first == 2 && !inter_and_inclus_res[1].second); + + // one CC of spheres is contained by cube + inter_and_inclus_res = collision_detection.get_all_intersections_and_inclusions(1); + assert(inter_and_inclus_res.size() == 2); + assert(inter_and_inclus_res[0].first == 3 && inter_and_inclus_res[0].second); + assert(inter_and_inclus_res[1].first == 2 && !inter_and_inclus_res[1].second); +} + +int main() +{ + test_remove(); + test_intersections(boost::face_index, "Surface_mesh"); + test_intersections(boost::face_external_index, "Polyhedron_3"); + + return 0; +} \ No newline at end of file From 5154022dc02ba5cb8c71fd0980e21592b7977075 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 4 Oct 2018 11:06:33 +0200 Subject: [PATCH 70/84] simply API and update doc --- .../Rigid_triangle_mesh_collision_detection.h | 94 +++++++++++++------ .../test_pmp_collision_detection.cpp | 5 +- 2 files changed, 68 insertions(+), 31 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h index 79318f4ccd3..1a8b1ec20b9 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h @@ -57,9 +57,9 @@ namespace CGAL { * @tparam VertexPointMap a model of `ReadablePropertyMap` with the vertex descriptor of `TriangleMesh` as key type, * and a point from a CGAL Kernel as value type. %Default is the internal point property map * of `TriangleMesh` if it exists. - * @tparam Kernel a model of CGAL Kernel. %Default is the Kernel of the value type of `VertexPointMap` retrieved using + * @tparam KernelType a model of CGAL Kernel. %Default is the Kernel of the value type of `VertexPointMap` retrieved using * `Kernel_traits`. - * @tparam AABBTree_type an `AABB_tree` that can containing faces of `TriangleMesh`. %Default is using `AABB_traits` with + * @tparam AABBTreeType an `AABB_tree` that can containing faces of `TriangleMesh`. %Default is using `AABB_traits` with * `AABB_face_graph_triangle_primitive` as primitive type. * @tparam HAS_ROTATION tag indicating whether the transformations applied to meshes may contain rotations (`Tag_true`) * or if only translations and scalings are applied (`Tag_false`). Some optimizations are @@ -67,8 +67,8 @@ namespace CGAL { */ template class Rigid_triangle_mesh_collision_detection { @@ -80,14 +80,14 @@ class Rigid_triangle_mesh_collision_detection // Kernel type typedef typename Kernel_traits< typename boost::property_traits::value_type>::Kernel Default_kernel; - typedef typename Default::Get::type Kernel; + typedef typename Default::Get::type Kernel; // AABB-tree type typedef AABB_face_graph_triangle_primitive Default_primitive; typedef AABB_traits Default_tree_traits; typedef CGAL::AABB_tree Default_tree; - typedef typename Default::Get::type Tree; + typedef typename Default::Get::type Tree; typedef typename Tree::AABB_traits Tree_traits; // Transformed Tree traversal traits @@ -252,29 +252,42 @@ public: /*! * adds an instance of a triangulated surface mesh using an external tree of its faces. - * Note that the tree is not copied and the lifetime of `tree` must be longer than - * that of this class. + * \warning The tree is not copied and the lifetime of `tree` must be longer than that of this class. * - * \return the id of the instance used to refer to that mesh. + * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" + * + * \return the id of `tm` used to refer to that mesh. * * @param tree an AABB-tree of faces of a mesh - * @param is_closed `true` is the mesh in `tree` is closed, and `false` otherwise. - * \link is_closed() `CGAL::is_closed()` \endlink can be used for that purpose. - * @param points_per_cc a vector containing one point of a vertex for each connected - * component of the triangle surface mesh in `tree` + * @param tm triangulated surface mesh + * @param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below + * + * \cgalNamedParamsBegin + * \cgalParamBegin{vertex_point_map} + * the property map with the points associated to the vertices of `tm`. + * If this parameter is omitted, an internal property map for + * `CGAL::vertex_point_t` must be available in `TriangleMesh` + * \cgalParamEnd + * \cgalParamBegin{face_index_map} + * a property map containing the index of each face of `tm`. It must be initialized + * and the value must be unique per face and in the range `[0, num_faces(tm)[`. + * \cgalParamEnd + * \cgalParamBegin{apply_per_connected_component} + * if `false`, `tm` is assumed to have only one connected component, avoiding + * the extraction of connected components. Default is `true`. + * \cgalParamEnd + * \cgalNamedParamsEnd */ - std::size_t add_mesh(const AABB_tree& tree, - bool is_closed, - const std::vector& points_per_cc) + template + std::size_t add_mesh(const AABB_tree& tree, const TriangleMesh& tm, const NamedParameters& np) { std::size_t id = get_id_for_new_mesh(); CGAL_assertion( m_aabb_trees[id] == NULL ); - m_is_closed[id] = is_closed; + m_is_closed[id] = is_closed(tm); m_own_aabb_trees[id] = false ; m_aabb_trees[id] = const_cast(&tree); m_traversal_traits[id] = Traversal_traits(m_aabb_trees.back()->traits()); - m_points_per_cc[id] = points_per_cc; - + collect_one_point_per_connected_component(tm, m_points_per_cc[id], np); return id; } @@ -308,11 +321,11 @@ public: * returns a vector of the ids of meshes within `ids` that have at least a face * intersecting a face of the mesh with id `mesh_id`. * If `mesh_id` is in `ids` it is not reported. - * \tparam MeshRangeIds a range of ids convertible to `std::size_t`. + * \tparam MeshIdRange a range of ids convertible to `std::size_t`. */ - template + template std::vector - get_all_intersections(std::size_t mesh_id, const MeshRangeIds& ids) const + get_all_intersections(std::size_t mesh_id, const MeshIdRange& ids) const { CGAL_assertion(m_aabb_trees[mesh_id] != NULL); CGAL::Interval_nt_advanced::Protector protector; @@ -358,15 +371,15 @@ public: * test may return incorrect results. * If `mesh_id` is in `ids` it is not reported. * - * \tparam MeshRangeIds a range of ids convertible to `std::size_t`. + * \tparam MeshIdRange a range of ids convertible to `std::size_t`. * * \note If a mesh is made of several connected components and at least one component is not closed, * then no inclusion test will be made even if some components are closed. * */ - template + template std::vector > - get_all_intersections_and_inclusions(std::size_t mesh_id, const MeshRangeIds& ids) const + get_all_intersections_and_inclusions(std::size_t mesh_id, const MeshIdRange& ids) const { CGAL_assertion(m_aabb_trees[mesh_id] != NULL); CGAL::Interval_nt_advanced::Protector protector; @@ -474,6 +487,7 @@ public: return m_aabb_trees[mesh_id] != NULL; } +#ifndef DOXYGEN_RUNNING /// \name Helper Static Function /*! @@ -568,7 +582,33 @@ public: points.push_back( get(vpm, *boost::begin(vertices(tm))) ); } -/// \cond SKIP_IN_MANUAL + /*! + * adds an instance of a triangulated surface mesh using an external tree of its faces. + * \warning The tree is not copied and the lifetime of `tree` must be longer than that of this class. + * + * \return the id of the instance used to refer to that mesh. + * + * @param tree an AABB-tree of faces of a mesh + * @param is_closed `true` is the mesh in `tree` is closed, and `false` otherwise. + * \link is_closed() `CGAL::is_closed()` \endlink can be used for that purpose. + * @param points_per_cc a vector containing one point of a vertex for each connected + * component of the triangle surface mesh in `tree` + */ + std::size_t add_mesh(const AABB_tree& tree, + bool is_closed, + const std::vector& points_per_cc) + { + std::size_t id = get_id_for_new_mesh(); + CGAL_assertion( m_aabb_trees[id] == NULL ); + m_is_closed[id] = is_closed; + m_own_aabb_trees[id] = false ; + m_aabb_trees[id] = const_cast(&tree); + m_traversal_traits[id] = Traversal_traits(m_aabb_trees.back()->traits()); + m_points_per_cc[id] = points_per_cc; + + return id; + } + // versions without NP static void collect_one_point_per_connected_component( @@ -582,7 +622,7 @@ public: { return add_mesh(tm, parameters::all_default()); } -/// \endcond +#endif }; } // end of CGAL namespace diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_collision_detection.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_collision_detection.cpp index e86193090b1..72058a131cd 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_collision_detection.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_collision_detection.cpp @@ -94,10 +94,7 @@ void test_intersections(Index index, const char* type) // add tm1 using an external tree typename CGAL::Rigid_triangle_mesh_collision_detection::AABB_tree tm1_tree(boost::begin(faces(tm1)), boost::end(faces(tm1)), tm1, get(boost::vertex_point, tm1)); - std::vector points_per_cc; - collision_detection.collect_one_point_per_connected_component( - tm1, points_per_cc, params::face_index_map(get(index, tm1))); - collision_detection.add_mesh(tm1_tree, true, points_per_cc); // 1 small_spheres + collision_detection.add_mesh(tm1_tree, tm1, params::face_index_map(get(index, tm1))); // 1 small_spheres collision_detection.add_mesh(tm2, params::face_index_map(get(index, tm2))); // 2 blobby collision_detection.add_mesh(tm3, params::face_index_map(get(index, tm3))); // 3 large_cube_coplanar // pool is 0 1 2 3 From 2a450cae9f9106158e57ac5f1c4536939fbdb7ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 4 Oct 2018 11:16:16 +0200 Subject: [PATCH 71/84] remove no longer valid test --- .../aabb_test_transformed_traits.cpp | 61 ------------------- 1 file changed, 61 deletions(-) delete mode 100644 AABB_tree/test/AABB_tree/aabb_test_transformed_traits.cpp diff --git a/AABB_tree/test/AABB_tree/aabb_test_transformed_traits.cpp b/AABB_tree/test/AABB_tree/aabb_test_transformed_traits.cpp deleted file mode 100644 index afbb9c28ba5..00000000000 --- a/AABB_tree/test/AABB_tree/aabb_test_transformed_traits.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -typedef CGAL::Epick K; -typedef K::FT FT; -typedef K::Point_3 Point; -typedef K::Vector_3 Vector; -typedef K::Segment_3 Segment; -typedef K::Ray_3 Ray; -typedef CGAL::Polyhedron_3 Polyhedron; -typedef CGAL::AABB_face_graph_triangle_primitive Primitive; -typedef CGAL::AABB_traits Base_traits; -typedef CGAL::AABB_transformed_traits Traits; -typedef CGAL::AABB_tree Tree; -typedef Tree::Primitive_id Primitive_id; - -int main() -{ - typedef std::vector< Tree::Intersection_and_primitive_id::Type > IntersectionVector; - Polyhedron polyhedron; - std::ifstream in("data/bunny00.off"); - if(in) - in >> polyhedron; - else{ - std::cout << "error reading bunny" << std::endl; - return 1; - } - CGAL::Aff_transformation_3 transfo(CGAL::TRANSLATION, Vector(250,300,1)); - IntersectionVector all_intersections; - Tree tree(faces(polyhedron).first, faces(polyhedron).second, polyhedron); - tree.traits().set_transformation(transfo); - tree.build(); - tree.traits().set_transformation(CGAL::Aff_transformation_3(CGAL::IDENTITY)); - Point bunny_center = - CGAL::centroid(polyhedron.points_begin(), polyhedron.points_end()); - - Ray ray1(Point(0,0,-10),bunny_center); - tree.all_intersections(ray1, std::back_inserter(all_intersections)); - std::size_t nb_inter = all_intersections.size(); - std::cout< Date: Thu, 4 Oct 2018 15:11:31 +0200 Subject: [PATCH 72/84] Move plugin in Polyhedron --- .../demo_plugin/AABB_tree/CMakeLists.txt | 35 ------------------- Polyhedron/demo/Polyhedron/CMakeLists.txt | 2 ++ .../Plugins/AABB_tree/CMakeLists.txt | 3 ++ .../AABB_tree/Do_trees_intersect_plugin.cpp | 0 .../AABB_tree/Scene_movable_sm_item.cpp | 0 .../AABB_tree/Scene_movable_sm_item.h | 0 6 files changed, 5 insertions(+), 35 deletions(-) delete mode 100644 AABB_tree/demo_plugin/AABB_tree/CMakeLists.txt rename {AABB_tree/demo_plugin => Polyhedron/demo/Polyhedron/Plugins}/AABB_tree/Do_trees_intersect_plugin.cpp (100%) rename {AABB_tree/demo_plugin => Polyhedron/demo/Polyhedron/Plugins}/AABB_tree/Scene_movable_sm_item.cpp (100%) rename {AABB_tree/demo_plugin => Polyhedron/demo/Polyhedron/Plugins}/AABB_tree/Scene_movable_sm_item.h (100%) diff --git a/AABB_tree/demo_plugin/AABB_tree/CMakeLists.txt b/AABB_tree/demo_plugin/AABB_tree/CMakeLists.txt deleted file mode 100644 index 0ba18742490..00000000000 --- a/AABB_tree/demo_plugin/AABB_tree/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -project( Do_trees_intersect_plugin) -# Find includes in corresponding build directories -set(CMAKE_INCLUDE_CURRENT_DIR ON) -# Instruct CMake to run moc automatically when needed. -set(CMAKE_AUTOMOC ON) -cmake_minimum_required(VERSION 3.1) - -#Find CGAL -find_package(CGAL COMPONENTS Qt5) -include( ${CGAL_USE_FILE} ) -# Find Qt5 itself -find_package(Qt5 - QUIET - COMPONENTS OpenGL Script Svg Xml - OPTIONAL_COMPONENTS ScriptTools) -find_package(CGAL_polyhedron_demo -HINTS "${CGAL_DIR}" "${CGAL_DIR}/Polyhedron/demo/build-ho" -) -include( ${CGAL_POLYHEDRON_DEMO_USE_FILE} ) -#macro add_item -macro(add_item item_name) - add_library(${item_name} SHARED ${ARGN}) - target_link_libraries(${item_name} - PUBLIC Polyhedron_demo_framework ${CGAL_LIBRARIES} ${Boost_LIBRARIES} - Qt5::OpenGL Qt5::Gui Qt5::Script Qt5::Widgets) - cgal_add_compilation_test(${item_name}) -endmacro(add_item) - -add_item(scene_movable_sm_item Scene_movable_sm_item.cpp) - - - -polyhedron_demo_plugin(do_trees_intersect_plugin Do_trees_intersect_plugin) -target_link_libraries(do_trees_intersect_plugin PUBLIC Polyhedron_scene_surface_mesh_item scene_movable_sm_item) - diff --git a/Polyhedron/demo/Polyhedron/CMakeLists.txt b/Polyhedron/demo/Polyhedron/CMakeLists.txt index 519f73f74fb..1ff548d9c2e 100644 --- a/Polyhedron/demo/Polyhedron/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/CMakeLists.txt @@ -278,6 +278,8 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND ) add_item(scene_sm_shortest_path_item Plugins/Surface_mesh/Scene_polyhedron_shortest_path_item.cpp) target_link_libraries(scene_sm_shortest_path_item PUBLIC scene_surface_mesh_item_decorator scene_surface_mesh_item scene_polylines_item) + add_item(scene_movable_sm_item Plugins/AABB_tree/Scene_movable_sm_item.cpp) + if(EIGEN3_FOUND ) add_item(scene_textured_polyhedron_item Scene_textured_polyhedron_item.cpp texture.cpp) add_item(scene_textured_surface_mesh_item Scene_textured_surface_mesh_item.cpp texture.cpp) diff --git a/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/CMakeLists.txt index 367251c51fe..3d0de6de1c6 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/CMakeLists.txt @@ -1,5 +1,8 @@ include( polyhedron_demo_macros ) +polyhedron_demo_plugin(do_trees_intersect_plugin Do_trees_intersect_plugin) +target_link_libraries(do_trees_intersect_plugin PUBLIC scene_surface_mesh_item scene_movable_sm_item) + polyhedron_demo_plugin(cut_plugin Cut_plugin ) target_link_libraries(cut_plugin PUBLIC scene_polyhedron_item scene_surface_mesh_item scene_basic_objects scene_color_ramp) if(TBB_FOUND) diff --git a/AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Do_trees_intersect_plugin.cpp similarity index 100% rename from AABB_tree/demo_plugin/AABB_tree/Do_trees_intersect_plugin.cpp rename to Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Do_trees_intersect_plugin.cpp diff --git a/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.cpp b/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Scene_movable_sm_item.cpp similarity index 100% rename from AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.cpp rename to Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Scene_movable_sm_item.cpp diff --git a/AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.h b/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Scene_movable_sm_item.h similarity index 100% rename from AABB_tree/demo_plugin/AABB_tree/Scene_movable_sm_item.h rename to Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Scene_movable_sm_item.h From 2c8b44e144f5598218dd40053f663108890898b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 4 Oct 2018 16:00:54 +0200 Subject: [PATCH 73/84] update doc after review --- .../Rigid_triangle_mesh_collision_detection.h | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h index 1a8b1ec20b9..3ca45dd2b97 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h @@ -49,7 +49,7 @@ namespace CGAL { * \ingroup PkgPolygonMeshProcessing * This class provides methods to perform some intersection tests between triangle meshes * that undergo affine transformations (rotation, translation, and scaling). - * Meshes are added to an internal pool and are referenced using an id assigned when added to the pool. + * Meshes are added to an internal set and are referenced using an id assigned when added to the set. * Note that the exact predicate framework applies on the meshes after having applied the transformation * to the coordinates of the points of the vertices of each mesh. * @@ -57,9 +57,9 @@ namespace CGAL { * @tparam VertexPointMap a model of `ReadablePropertyMap` with the vertex descriptor of `TriangleMesh` as key type, * and a point from a CGAL Kernel as value type. %Default is the internal point property map * of `TriangleMesh` if it exists. - * @tparam KernelType a model of CGAL Kernel. %Default is the Kernel of the value type of `VertexPointMap` retrieved using + * @tparam Kernel a model of CGAL Kernel. %Default is the kernel of the value type of `VertexPointMap` retrieved using * `Kernel_traits`. - * @tparam AABBTreeType an `AABB_tree` that can containing faces of `TriangleMesh`. %Default is using `AABB_traits` with + * @tparam AABBTree an `AABB_tree` that can containing faces of `TriangleMesh`. %Default is using `AABB_traits` with * `AABB_face_graph_triangle_primitive` as primitive type. * @tparam HAS_ROTATION tag indicating whether the transformations applied to meshes may contain rotations (`Tag_true`) * or if only translations and scalings are applied (`Tag_false`). Some optimizations are @@ -67,8 +67,8 @@ namespace CGAL { */ template class Rigid_triangle_mesh_collision_detection { @@ -80,19 +80,19 @@ class Rigid_triangle_mesh_collision_detection // Kernel type typedef typename Kernel_traits< typename boost::property_traits::value_type>::Kernel Default_kernel; - typedef typename Default::Get::type Kernel; + typedef typename Default::Get::type K; // AABB-tree type typedef AABB_face_graph_triangle_primitive Default_primitive; - typedef AABB_traits Default_tree_traits; + typedef AABB_traits Default_tree_traits; typedef CGAL::AABB_tree Default_tree; - typedef typename Default::Get::type Tree; + typedef typename Default::Get::type Tree; typedef typename Tree::AABB_traits Tree_traits; // Transformed Tree traversal traits typedef Do_intersect_traversal_traits_with_transformation Traversal_traits; @@ -100,7 +100,7 @@ class Rigid_triangle_mesh_collision_detection std::vector m_own_aabb_trees; std::vector m_aabb_trees; std::vector m_is_closed; - std::vector< std::vector > m_points_per_cc; + std::vector< std::vector > m_points_per_cc; std::vector m_traversal_traits; std::size_t m_free_id; // position in m_id_pool of the first free element std::vector m_id_pool; // 0-> m_id_pool-1 are valid mesh ids @@ -140,13 +140,13 @@ class Rigid_triangle_mesh_collision_detection // precondition A and B does not intersect bool does_A_contains_a_CC_of_B(std::size_t id_A, std::size_t id_B) const { - typename Kernel::Construct_ray_3 ray_functor; - typename Kernel::Construct_vector_3 vector_functor; + typename K::Construct_ray_3 ray_functor; + typename K::Construct_vector_3 vector_functor; typedef typename Traversal_traits::Transformed_tree_helper Helper; - BOOST_FOREACH(const typename Kernel::Point_3& q, m_points_per_cc[id_B]) + BOOST_FOREACH(const typename K::Point_3& q, m_points_per_cc[id_B]) { - if( internal::Point_inside_vertical_ray_cast(m_traversal_traits[id_A].get_helper())( + if( internal::Point_inside_vertical_ray_cast(m_traversal_traits[id_A].get_helper())( m_traversal_traits[id_B].transformation()( q ), *m_aabb_trees[id_A], ray_functor, vector_functor) == CGAL::ON_BOUNDED_SIDE) { @@ -163,7 +163,7 @@ class Rigid_triangle_mesh_collision_detection if (!do_overlap(m_bboxes[id_B], m_bboxes[id_A])) continue; #endif - Do_intersect_traversal_traits_for_two_trees traversal_traits( + Do_intersect_traversal_traits_for_two_trees traversal_traits( m_aabb_trees[id_B]->traits(), m_traversal_traits[id_B].transformation(), m_traversal_traits[id_A]); m_aabb_trees[id_B]->traversal(*m_aabb_trees[id_A], traversal_traits); return traversal_traits.is_intersection_found(); @@ -196,7 +196,7 @@ public: } /*! - * adds mesh `tm` in the pool of meshes to be considered for intersection. + * adds mesh `tm` to the set of meshes to be considered for intersection. * * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" * @@ -292,9 +292,9 @@ public: } /*! - * sets the transformation associated to a mesh identified by its id in the pool. + * sets the transformation associated to a mesh identified by its id in the set. */ - void set_transformation(std::size_t mesh_id, const Aff_transformation_3& aff_trans) + void set_transformation(std::size_t mesh_id, const Aff_transformation_3& aff_trans) { CGAL_assertion(m_aabb_trees[mesh_id] != NULL); m_traversal_traits[mesh_id].set_transformation(aff_trans); @@ -347,7 +347,7 @@ public: } /*! - * returns a vector of the ids of meshes in the pool that have at least a face + * returns a vector of the ids of meshes in the set that have at least a face * intersecting a face of the mesh with id `mesh_id` */ std::vector @@ -419,7 +419,7 @@ public: } /*! - * returns a vector of the ids of meshes in the pool that are intersecting with the mesh with id `mesh_id`, + * returns a vector of the ids of meshes in the set that are intersecting with the mesh with id `mesh_id`, * considering volume inclusions for closed meshes. * See the previous overload for details. */ @@ -447,7 +447,7 @@ public: } /*! - * removes the mesh with id `mesh_id` from the pool, the indices of other meshes are kept unchanged. + * removes the mesh with id `mesh_id` from the set, the indices of other meshes are kept unchanged. */ void remove_mesh(std::size_t mesh_id) { @@ -463,13 +463,15 @@ public: } /*! - * returns the number of meshes in the pool + * returns the number of meshes in the set */ std::size_t size() const { return m_free_id; } + +#ifndef DOXYGEN_RUNNING /*! * returns the number of times `add_mesh()` was called minus the number of times `remove_mesh()` (with a valid mesh id) was called */ @@ -487,7 +489,6 @@ public: return m_aabb_trees[mesh_id] != NULL; } -#ifndef DOXYGEN_RUNNING /// \name Helper Static Function /*! @@ -613,7 +614,7 @@ public: static void collect_one_point_per_connected_component( const TriangleMesh& tm, - std::vector& points) + std::vector& points) { collect_one_point_per_connected_component(tm, points, parameters::all_default()); } From 71175e13bdb3dbd8cdeb1f1d30cf8ccd0c6c605b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 4 Oct 2018 16:09:40 +0200 Subject: [PATCH 74/84] naming convention --- .../CGAL/Rigid_triangle_mesh_collision_detection.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h index 3ca45dd2b97..36fb215fd86 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h @@ -61,7 +61,7 @@ namespace CGAL { * `Kernel_traits`. * @tparam AABBTree an `AABB_tree` that can containing faces of `TriangleMesh`. %Default is using `AABB_traits` with * `AABB_face_graph_triangle_primitive` as primitive type. - * @tparam HAS_ROTATION tag indicating whether the transformations applied to meshes may contain rotations (`Tag_true`) + * @tparam Has_rotation tag indicating whether the transformations applied to meshes may contain rotations (`Tag_true`) * or if only translations and scalings are applied (`Tag_false`). Some optimizations are * switch on in case there are no rotations. */ @@ -69,7 +69,7 @@ template + class Has_rotation = CGAL::Tag_true> class Rigid_triangle_mesh_collision_detection { // Vertex point map type @@ -93,7 +93,7 @@ class Rigid_triangle_mesh_collision_detection // Transformed Tree traversal traits typedef Do_intersect_traversal_traits_with_transformation + Has_rotation> Traversal_traits; // Data members @@ -163,7 +163,7 @@ class Rigid_triangle_mesh_collision_detection if (!do_overlap(m_bboxes[id_B], m_bboxes[id_A])) continue; #endif - Do_intersect_traversal_traits_for_two_trees traversal_traits( + Do_intersect_traversal_traits_for_two_trees traversal_traits( m_aabb_trees[id_B]->traits(), m_traversal_traits[id_B].transformation(), m_traversal_traits[id_A]); m_aabb_trees[id_B]->traversal(*m_aabb_trees[id_A], traversal_traits); return traversal_traits.is_intersection_found(); From d7fa388f85d07648b8d3bb72b7796ee8c8e80c0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 8 Oct 2018 10:52:45 +0200 Subject: [PATCH 75/84] avoid passing default map (that is already the default) The c++03 implementation of constructors of AABB-tree expect arguments to be passed by reference and a rvalue can't be taken by const-ref --- .../Polygon_mesh_processing/test_pmp_collision_detection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_collision_detection.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_collision_detection.cpp index 72058a131cd..cc929509a57 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_collision_detection.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_collision_detection.cpp @@ -93,7 +93,7 @@ void test_intersections(Index index, const char* type) collision_detection.add_mesh(tm1, params::face_index_map(get(index, tm1))); // 0 // add tm1 using an external tree typename CGAL::Rigid_triangle_mesh_collision_detection::AABB_tree - tm1_tree(boost::begin(faces(tm1)), boost::end(faces(tm1)), tm1, get(boost::vertex_point, tm1)); + tm1_tree(boost::begin(faces(tm1)), boost::end(faces(tm1)), tm1); collision_detection.add_mesh(tm1_tree, tm1, params::face_index_map(get(index, tm1))); // 1 small_spheres collision_detection.add_mesh(tm2, params::face_index_map(get(index, tm2))); // 2 blobby collision_detection.add_mesh(tm3, params::face_index_map(get(index, tm3))); // 3 large_cube_coplanar From 574df7e7eb390495a13e548428b11be6b4704884 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 9 Oct 2018 10:44:35 +0200 Subject: [PATCH 76/84] add collision detection plugin in PMP submenu --- .../Polyhedron/Plugins/AABB_tree/Do_trees_intersect_plugin.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Do_trees_intersect_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Do_trees_intersect_plugin.cpp index 7ed8bb2ee0f..3ec84028106 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Do_trees_intersect_plugin.cpp @@ -61,7 +61,8 @@ public: this->messageInterface = mi; this->scene = sc; this->mw = mw; - QAction *actionCreateTrees= new QAction(QString("Start Intersection Tests"), mw); + QAction *actionCreateTrees= new QAction(QString("Collision Detection Mode"), mw); + actionCreateTrees->setProperty("subMenuName", "Polygon Mesh Processing"); actionCreateTrees->setProperty("submenuName", "AABB_tree"); if(actionCreateTrees) { connect(actionCreateTrees, SIGNAL(triggered()), From 3ebf53dc893a365f018cad6d6e5295f9a86c7dce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 9 Oct 2018 10:47:51 +0200 Subject: [PATCH 77/84] update changes --- Installation/CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index fcd898c453f..9ef45f77e37 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -19,6 +19,8 @@ Release date: March 2019 - `CGAL::Polygon_mesh_processing::extract_boundary_cycles()` - `CGAL::Polygon_mesh_processing::merge_duplicated_vertices_in_boundary_cycle()` - `CGAL::Polygon_mesh_processing::merge_duplicated_vertices_in_boundary_cycles()` +- Added the class `CGAL::Rigid_triangle_mesh_collision_detection` to detect intersections between meshes + and volumes undergoing affine transformations. Release 4.13 ------------ From 3b3707ad19fc6085c3657bb116c09d243c908dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 9 Oct 2018 10:53:59 +0200 Subject: [PATCH 78/84] remove mode --- .../Polyhedron/Plugins/AABB_tree/Do_trees_intersect_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Do_trees_intersect_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Do_trees_intersect_plugin.cpp index 3ec84028106..91cef460b95 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Do_trees_intersect_plugin.cpp @@ -61,7 +61,7 @@ public: this->messageInterface = mi; this->scene = sc; this->mw = mw; - QAction *actionCreateTrees= new QAction(QString("Collision Detection Mode"), mw); + QAction *actionCreateTrees= new QAction(QString("Collision Detection"), mw); actionCreateTrees->setProperty("subMenuName", "Polygon Mesh Processing"); actionCreateTrees->setProperty("submenuName", "AABB_tree"); if(actionCreateTrees) { From 09be0c65b9649d853c1dbbca5b1d17b87d84d937 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 9 Oct 2018 11:25:23 +0200 Subject: [PATCH 79/84] Fix shader --- Polyhedron/demo/Polyhedron/resources/shader_with_light.v | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/resources/shader_with_light.v b/Polyhedron/demo/Polyhedron/resources/shader_with_light.v index 3ea1ce9c925..47a9c7666be 100644 --- a/Polyhedron/demo/Polyhedron/resources/shader_with_light.v +++ b/Polyhedron/demo/Polyhedron/resources/shader_with_light.v @@ -4,6 +4,7 @@ in vec3 normals; in vec4 colors; uniform mat4 mvp_matrix; uniform mat4 mv_matrix; +uniform mat4 f_matrix; out vec4 fP; out vec3 fN; out vec4 color; @@ -38,11 +39,11 @@ void main(void) // if(is_clipbox_on) compute_distances(); - fP = mv_matrix * vertex; + fP = mv_matrix * f_matrix * vertex; mat3 mv_matrix_3; mv_matrix_3[0] = mv_matrix[0].xyz; mv_matrix_3[1] = mv_matrix[1].xyz; mv_matrix_3[2] = mv_matrix[2].xyz; fN = mv_matrix_3* normals; - gl_Position = mvp_matrix * vertex; + gl_Position = mvp_matrix * f_matrix * vertex; } From a1bcbd4beb82bbf1aa203c874bd5f2af5b1362fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 11 Oct 2018 15:15:12 +0200 Subject: [PATCH 80/84] add missing include directive --- .../internal/AABB_traversal_traits_with_transformation.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h index 5d11b3e761a..818b9c038d8 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include From 4294b71dfb37be29a32364c812540d1ac7db6fcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 15 Oct 2018 17:21:47 +0200 Subject: [PATCH 81/84] add missing convenience function --- .../include/CGAL/Rigid_triangle_mesh_collision_detection.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h index 36fb215fd86..795b6b30af6 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h @@ -623,6 +623,11 @@ public: { return add_mesh(tm, parameters::all_default()); } + + std::size_t add_mesh(const AABB_tree& tree, const TriangleMesh& tm) + { + return add_mesh(tree, tm, parameters::all_default()); + } #endif }; From 74d57925bb6774b210033f744d7a99a8e473fe5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 16 Oct 2018 15:40:06 +0200 Subject: [PATCH 82/84] add missing EOL --- .../Polygon_mesh_processing/test_pmp_collision_detection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_collision_detection.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_collision_detection.cpp index cc929509a57..0ed2887110f 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_collision_detection.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_collision_detection.cpp @@ -171,4 +171,4 @@ int main() test_intersections(boost::face_external_index, "Polyhedron_3"); return 0; -} \ No newline at end of file +} From 80643061af8b401426c80327aa4ff4c79cf0623b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 25 Oct 2018 13:45:57 +0200 Subject: [PATCH 83/84] add missing call to build+fix to use the right traits --- .../include/CGAL/Rigid_triangle_mesh_collision_detection.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h index 795b6b30af6..5639900eb2b 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h @@ -243,8 +243,9 @@ public: m_is_closed[id] = is_closed(tm); m_own_aabb_trees[id] = true; Tree* t = new Tree(boost::begin(faces(tm)), boost::end(faces(tm)), tm, vpm); + t->build(); m_aabb_trees[id] = t; - m_traversal_traits[id] = Traversal_traits(m_aabb_trees.back()->traits()); + m_traversal_traits[id] = Traversal_traits(m_aabb_trees[id]->traits()); add_cc_points(tm, id, np); return id; @@ -286,7 +287,7 @@ public: m_is_closed[id] = is_closed(tm); m_own_aabb_trees[id] = false ; m_aabb_trees[id] = const_cast(&tree); - m_traversal_traits[id] = Traversal_traits(m_aabb_trees.back()->traits()); + m_traversal_traits[id] = Traversal_traits(m_aabb_trees[id]->traits()); collect_one_point_per_connected_component(tm, m_points_per_cc[id], np); return id; } @@ -604,7 +605,7 @@ public: m_is_closed[id] = is_closed; m_own_aabb_trees[id] = false ; m_aabb_trees[id] = const_cast(&tree); - m_traversal_traits[id] = Traversal_traits(m_aabb_trees.back()->traits()); + m_traversal_traits[id] = Traversal_traits(m_aabb_trees[id]->traits()); m_points_per_cc[id] = points_per_cc; return id; From 10fd5a6e0c3114c1b0c25b84b8f40ffd2e1c3dd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 26 Oct 2018 09:46:01 +0200 Subject: [PATCH 84/84] clear points per cc after removal + avoid useless resize --- .../include/CGAL/Rigid_triangle_mesh_collision_detection.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h index 5639900eb2b..71bc10f7f23 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h @@ -133,7 +133,6 @@ class Rigid_triangle_mesh_collision_detection template void add_cc_points(const TriangleMesh& tm, std::size_t id, const NamedParameters& np) { - m_points_per_cc.resize(m_points_per_cc.size()+1); collect_one_point_per_connected_component(tm, m_points_per_cc[id], np); } @@ -457,6 +456,7 @@ public: if (itf == m_id_pool.begin()+m_free_id) return; if (m_own_aabb_trees[mesh_id]) delete m_aabb_trees[mesh_id]; + m_points_per_cc[mesh_id].clear(); m_aabb_trees[mesh_id] = NULL; if (m_id_pool[m_free_id-1]!=mesh_id) std::swap(m_id_pool[m_free_id-1], *itf);