diff --git a/.gitattributes b/.gitattributes index 0f0624be90b..5fddd29d4ff 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1723,6 +1723,8 @@ Kernel_23/include/CGAL/internal/Projection_traits_3.h -text Kernel_23/test/Kernel_23/CMakeLists.txt -text Kernel_d/doc_tex/Kernel_d/hypercube.png -text Kernel_d/doc_tex/Kernel_d_ref/Kernel_Compute_coordinate_d.tex -text +Kernel_d/doc_tex/Kernel_d_ref/Kernel_Less_coordinate_d.tex -text +Kernel_d/doc_tex/Kernel_d_ref/Kernel_Point_dimension_d.tex -text Kernel_d/include/CGAL/Kernel_d/Cartesian_const_iterator_d.h -text Kernel_d/test/Kernel_d/Linear_algebra-test.cmd eol=lf Kinetic_data_structures/demo/Kinetic_data_structures/data/after002 -text @@ -2860,6 +2862,7 @@ Polygon/doc_tex/Polygon/polygon.png -text Polyhedron/demo/Polyhedron/MainWindow.ui -text Polyhedron/demo/Polyhedron/Polyhedron_3.qrc -text Polyhedron/demo/Polyhedron/Remeshing_dialog.ui -text +Polyhedron/demo/Polyhedron/Show_point_dialog.ui -text Polyhedron/demo/Polyhedron/cgal_test_with_cmake eol=lf Polyhedron/demo/Polyhedron/data/anchor.off -text svneol=unset#application/octet-stream Polyhedron/demo/Polyhedron/data/bones.off -text svneol=unset#application/octet-stream @@ -3314,12 +3317,38 @@ Spatial_searching/doc_tex/Spatial_searching/windowQuery.png -text Spatial_searching/include/CGAL/internal/K_neighbor_search.h -text Spatial_searching/include/CGAL/internal/bounded_priority_queue.h -text Spatial_searching/test/Spatial_searching/Compare_methods.cpp -text +Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert-median.gif -text +Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert-median.pdf -text +Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert-middle.gif -text +Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert-middle.pdf -text +Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert8.gif -text +Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert8.pdf -text Spatial_sorting/doc_tex/Spatial_sorting/fig/hilbert.png -text Spatial_sorting/doc_tex/Spatial_sorting/fig/hilbertLarge.jpg -text -Spatial_sorting/dont_submit -text -Spatial_sorting/examples/Spatial_sorting/data/input.cin -text -Spatial_sorting/examples/Spatial_sorting/example_delaunay_2.cmd -text -Spatial_sorting/examples/Spatial_sorting/sort_indices.cmd -text +Spatial_sorting/doc_tex/Spatial_sorting_ref/Hilbert_policy_tags.tex -text +Spatial_sorting/doc_tex/Spatial_sorting_ref/Hilbert_sort_d.tex -text +Spatial_sorting/doc_tex/Spatial_sorting_ref/SpatialSortingTraits_d.tex -text +Spatial_sorting/doc_tex/Spatial_sorting_ref/Spatial_sort_traits_adapter_2.tex -text +Spatial_sorting/doc_tex/Spatial_sorting_ref/Spatial_sort_traits_adapter_3.tex -text +Spatial_sorting/doc_tex/Spatial_sorting_ref/Spatial_sort_traits_adapter_d.tex -text +Spatial_sorting/examples/Spatial_sorting/hilbert.cpp -text +Spatial_sorting/examples/Spatial_sorting/hilbert_policies.cpp -text +Spatial_sorting/examples/Spatial_sorting/small_example_delaunay_2.cpp -text +Spatial_sorting/examples/Spatial_sorting/sp_sort_using_property_map_2.cpp -text +Spatial_sorting/examples/Spatial_sorting/sp_sort_using_property_map_3.cpp -text +Spatial_sorting/examples/Spatial_sorting/sp_sort_using_property_map_d.cpp -text +Spatial_sorting/include/CGAL/Hilbert_policy_tags.h -text +Spatial_sorting/include/CGAL/Hilbert_sort_d.h -text +Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h -text +Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h -text +Spatial_sorting/include/CGAL/Hilbert_sort_median_d.h -text +Spatial_sorting/include/CGAL/Hilbert_sort_middle_2.h -text +Spatial_sorting/include/CGAL/Hilbert_sort_middle_3.h -text +Spatial_sorting/include/CGAL/Hilbert_sort_middle_base.h -text +Spatial_sorting/include/CGAL/Hilbert_sort_middle_d.h -text +Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_2.h -text +Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_3.h -text +Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_d.h -text Straight_skeleton_2/demo/Straight_skeleton_2/data/complex_0.poly -text svneol=unset#application/octet-stream Straight_skeleton_2/demo/Straight_skeleton_2/data/complex_1.poly -text svneol=unset#application/octet-stream Straight_skeleton_2/demo/Straight_skeleton_2/data/complex_2.poly -text svneol=unset#application/octet-stream @@ -4106,7 +4135,7 @@ Triangulation_3/examples/Triangulation_3/info_insert_with_zip_iterator.cpp -text Triangulation_3/include/CGAL/internal/Static_filters/Compare_weighted_squared_radius_3.h -text Triangulation_3/include/CGAL/internal/Static_filters/Power_test_3.h -text Triangulation_3/include/CGAL/internal/Static_filters/Regular_triangulation_static_filters_traits_3.h -text -Triangulation_3/include/CGAL/internal/spatial_sorting_traits_with_indices.h -text +Triangulation_3/include/CGAL/internal/info_check.h -text Triangulation_3/test/Triangulation_3/include/CGAL/_test_remove_cluster.h -text Triangulation_3/test/Triangulation_3/test_regular_insert_range_with_info.cpp -text Triangulation_3/test/Triangulation_3/test_static_filters.cpp -text diff --git a/CGALimageIO/demo/CGALimageIO/CMakeLists.txt b/CGALimageIO/demo/CGALimageIO/CMakeLists.txt index bae0cdad183..0dbff9bf359 100644 --- a/CGALimageIO/demo/CGALimageIO/CMakeLists.txt +++ b/CGALimageIO/demo/CGALimageIO/CMakeLists.txt @@ -30,13 +30,17 @@ endforeach() find_package(CGAL REQUIRED ImageIO) include( ${CGAL_USE_FILE} ) find_package(VTK QUIET) +find_package(Qt3-patched QUIET) -if(VTK_FOUND) +if(QT3_FOUND AND VTK_FOUND) add_definitions(-DCGAL_USE_VTK) include(${VTK_USE_FILE}) + add_definitions(${QT3_DEFINITIONS}) + if(VTK_USE_QVTK) include_directories( ${VTK_QT_INCLUDE_DIR} ) + include_directories( ${QT3_INCLUDE_DIR} ) add_executable( image_to_vtk_viewer image_to_vtk_viewer.cpp ) add_to_cached_list( CGAL_EXECUTABLE_TARGETS image_to_vtk_viewer ) @@ -48,12 +52,16 @@ if(VTK_FOUND) vtkCommon ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES} ${VTK_QT_QT_LIBRARY} + ${QT3_LIBRARIES} ) else(VTK_USE_QVTK) message(STATUS "NOTICE: This demo needs QVTK, and will not be compiled.") endif(VTK_USE_QVTK) -else(VTK_FOUND) - - message(STATUS "NOTICE: This demo needs VTK, and will not be compiled.") - -endif(VTK_FOUND) +else() + if(NOT VTK_FOUND) + message(STATUS "NOTICE: This demo needs VTK, and will not be compiled.") + endif() + if(NOT QT3_FOUND) + message(STATUS "NOTICE: This demo needs Qt3, and will not be compiled.") + endif() +endif() diff --git a/Convex_hull_2/include/CGAL/Convex_hull_2/ch_akl_toussaint_impl.h b/Convex_hull_2/include/CGAL/Convex_hull_2/ch_akl_toussaint_impl.h index 7e75eee7c84..76f7556f02e 100644 --- a/Convex_hull_2/include/CGAL/Convex_hull_2/ch_akl_toussaint_impl.h +++ b/Convex_hull_2/include/CGAL/Convex_hull_2/ch_akl_toussaint_impl.h @@ -98,9 +98,9 @@ ch_akl_toussaint(ForwardIterator first, ForwardIterator last, std::sort( successor(region2.begin() ), region2.end(), ch_traits.less_xy_2_object() ); std::sort( successor(region3.begin() ), region3.end(), - bind(ch_traits.less_xy_2_object(), _2, _1) ); + boost::bind(ch_traits.less_xy_2_object(), _2, _1) ); std::sort( successor(region4.begin() ), region4.end(), - bind(ch_traits.less_xy_2_object(), _2, _1) ); + boost::bind(ch_traits.less_xy_2_object(), _2, _1) ); if (! equal_points(*w,*s) ) { diff --git a/GraphicsView/demo/Triangulation_2/include/CGAL/Lipschitz_sizing_field_criteria_2.h b/GraphicsView/demo/Triangulation_2/include/CGAL/Lipschitz_sizing_field_criteria_2.h index 8085c29c27b..ad4da9f21bf 100644 --- a/GraphicsView/demo/Triangulation_2/include/CGAL/Lipschitz_sizing_field_criteria_2.h +++ b/GraphicsView/demo/Triangulation_2/include/CGAL/Lipschitz_sizing_field_criteria_2.h @@ -24,21 +24,27 @@ public: protected: Sizing_field* sizing_field; + + typedef typename CDT::Geom_traits Geom_traits; + Geom_traits traits; public: typedef Delaunay_mesh_criteria_2 Base; Lipschitz_sizing_field_criteria_2(const double aspect_bound = 0.125, - Sizing_field* sf = 0) - : Base(aspect_bound), sizing_field(sf) + Sizing_field* sf = 0, + const Geom_traits& traits = Geom_traits()) + : Base(aspect_bound), sizing_field(sf), traits(traits) {} Lipschitz_sizing_field_criteria_2& operator =(const Lipschitz_sizing_field_criteria_2& c) { + if(&c == this) return *this; this->sizing_field = c.sizing_field; + this->traits = c.traits; return *this; - } + } inline const Sizing_field* sizing_field_object() { @@ -81,8 +87,9 @@ public: typedef typename Base::Is_bad::Point_2 Point_2; - Is_bad(const double aspect_bound, Sizing_field* sf) - : Base::Is_bad(aspect_bound), sizing_field(sf) + Is_bad(const double aspect_bound, Sizing_field* sf, + const Geom_traits& traits) + : Base::Is_bad(aspect_bound, traits), sizing_field(sf) { } @@ -189,7 +196,7 @@ public: Is_bad is_bad_object() const { - return Is_bad(this->bound(), sizing_field); + return Is_bad(this->bound(), sizing_field, traits); } }; diff --git a/Installation/changes.html b/Installation/changes.html index c1b213e0c4e..48c2733bb31 100644 --- a/Installation/changes.html +++ b/Installation/changes.html @@ -114,6 +114,16 @@ CGAL 3.9 offers the following improvements and new functionality :

  • Various fixes in the manual.
  • +

    dD Kernel

    +
  • The d-dimensional kernel concept and models have been modified + to additionally provide two new functors Less_coordinate_d and Point_dimension_d.
  • +

    Spatial_sorting (major new feature added)

    +

    Release 3.8

    diff --git a/Kernel_d/doc_tex/Kernel_d_ref/Kernel.tex b/Kernel_d/doc_tex/Kernel_d_ref/Kernel.tex index ecdd47bdf6f..00116ee1002 100644 --- a/Kernel_d/doc_tex/Kernel_d_ref/Kernel.tex +++ b/Kernel_d/doc_tex/Kernel_d_ref/Kernel.tex @@ -108,6 +108,8 @@ replacing operators, especially for equality testing. \ccGlue \ccNestedType{Less_or_equal_lexicographically_d}{} \ccGlue +\ccNestedType{Less_coordinate_d}{} +\ccGlue \ccNestedType{Lift_to_paraboloid_d}{} \ccGlue \ccNestedType{Linear_base_d}{} @@ -124,6 +126,8 @@ replacing operators, especially for equality testing. \ccGlue \ccNestedType{Orthogonal_vector_d}{} \ccGlue +\ccNestedType{Point_dimension_d}{} +\ccGlue \ccNestedType{Point_of_sphere_d}{} \ccGlue \ccNestedType{Point_to_vector_d}{} diff --git a/Kernel_d/doc_tex/Kernel_d_ref/Kernel_Less_coordinate_d.tex b/Kernel_d/doc_tex/Kernel_d_ref/Kernel_Less_coordinate_d.tex new file mode 100755 index 00000000000..b47f0e2b256 --- /dev/null +++ b/Kernel_d/doc_tex/Kernel_d_ref/Kernel_Less_coordinate_d.tex @@ -0,0 +1,13 @@ +\begin{ccRefFunctionObjectConcept}{Kernel::Less_coordinate_d} +A model for this must provide: + +\ccCreationVariable{fo} + +\ccMemberFunction{ bool operator()(const Kernel::Point_d& + p,const Kernel::Point_d& + q, int i);} {returns \ccc{true} iff the $i$th cartesian coordinate + of \ccc{p} is + smaller than the $i$th cartesian coordinate of \ccc{q}. \ccPrecond \ccc{p} and \ccc{q} have + the same dimension.} + +\end{ccRefFunctionObjectConcept} diff --git a/Kernel_d/doc_tex/Kernel_d_ref/Kernel_Point_dimension_d.tex b/Kernel_d/doc_tex/Kernel_d_ref/Kernel_Point_dimension_d.tex new file mode 100644 index 00000000000..29b8b175a19 --- /dev/null +++ b/Kernel_d/doc_tex/Kernel_d_ref/Kernel_Point_dimension_d.tex @@ -0,0 +1,9 @@ +\begin{ccRefFunctionObjectConcept}{Kernel::Point_dimension_d} +A model for this must provide: + +\ccCreationVariable{fo} + +\ccMemberFunction{ int operator()(const Kernel::Point_d& + p);} {returns the dimension of $p$} + +\end{ccRefFunctionObjectConcept} diff --git a/Kernel_d/doc_tex/Kernel_d_ref/main.tex b/Kernel_d/doc_tex/Kernel_d_ref/main.tex index 8bd81972aa0..9ad0cc9a3d7 100644 --- a/Kernel_d/doc_tex/Kernel_d_ref/main.tex +++ b/Kernel_d/doc_tex/Kernel_d_ref/main.tex @@ -88,6 +88,7 @@ \input{Kernel_d_ref/Kernel_Intersect_d.tex} \input{Kernel_d_ref/Kernel_Less_lexicographically_d.tex} \input{Kernel_d_ref/Kernel_Less_or_equal_lexicographically_d.tex} +\input{Kernel_d_ref/Kernel_Less_coordinate_d.tex} \input{Kernel_d_ref/Kernel_Lift_to_paraboloid_d.tex} \input{Kernel_d_ref/Kernel_Linearly_independent_d.tex} \input{Kernel_d_ref/Kernel_Linear_base_d.tex} @@ -96,6 +97,7 @@ \input{Kernel_d_ref/Kernel_Orientation_d.tex} \input{Kernel_d_ref/Kernel_Oriented_side_d.tex} \input{Kernel_d_ref/Kernel_Orthogonal_vector_d.tex} +\input{Kernel_d_ref/Kernel_Point_dimension_d.tex} \input{Kernel_d_ref/Kernel_Point_of_sphere_d.tex} \input{Kernel_d_ref/Kernel_Point_to_vector_d.tex} \input{Kernel_d_ref/Kernel_Project_along_d_axis_d.tex} diff --git a/Kernel_d/include/CGAL/Cartesian_d.h b/Kernel_d/include/CGAL/Cartesian_d.h index 6d889e0116d..52097613d40 100644 --- a/Kernel_d/include/CGAL/Cartesian_d.h +++ b/Kernel_d/include/CGAL/Cartesian_d.h @@ -251,6 +251,8 @@ public: typedef Compare_lexicographicallyCd Compare_lexicographically_d; typedef Lt_from_compare Less_lexicographically_d; typedef Le_from_compare Less_or_equal_lexicographically_d; + typedef Less_coordinateCd Less_coordinate_d; + typedef Point_dimensionCd Point_dimension_d; typedef Eq_from_method Equal_d; typedef Center_of_sphereCd Center_of_sphere_d; typedef Contained_in_linear_hullCd Contained_in_linear_hull_d; @@ -260,6 +262,10 @@ public: Compute_coordinate_d compute_coordinate_d_object() const { return Compute_coordinate_d(); } + Point_dimension_d point_dimension_d_object() const + { return Point_dimension_d(); } + Less_coordinate_d less_coordinate_d_object() const + { return Less_coordinate_d(); } Lift_to_paraboloid_d lift_to_paraboloid_d_object() const { return Lift_to_paraboloid_d(); } Project_along_d_axis_d project_along_d_axis_d_object() const diff --git a/Kernel_d/include/CGAL/Homogeneous_d.h b/Kernel_d/include/CGAL/Homogeneous_d.h index 994abdfbc5d..d968a94c4f5 100644 --- a/Kernel_d/include/CGAL/Homogeneous_d.h +++ b/Kernel_d/include/CGAL/Homogeneous_d.h @@ -253,6 +253,8 @@ public: typedef Compare_lexicographicallyHd Compare_lexicographically_d; typedef Lt_from_compare Less_lexicographically_d; typedef Le_from_compare Less_or_equal_lexicographically_d; + typedef Less_coordinateHd Less_coordinate_d; + typedef Point_dimensionHd Point_dimension_d; typedef Eq_from_method Equal_d; typedef Center_of_sphereHd Center_of_sphere_d; typedef Contained_in_linear_hullHd Contained_in_linear_hull_d; @@ -262,6 +264,10 @@ public: Compute_coordinate_d compute_coordinate_d_object() const { return Compute_coordinate_d(); } + Point_dimension_d point_dimension_d_object() const + { return Point_dimension_d(); } + Less_coordinate_d less_coordinate_d_object() const + { return Less_coordinate_d(); } Lift_to_paraboloid_d lift_to_paraboloid_d_object() const { return Lift_to_paraboloid_d(); } Project_along_d_axis_d project_along_d_axis_d_object() const diff --git a/Kernel_d/include/CGAL/Kernel_d/function_objectsCd.h b/Kernel_d/include/CGAL/Kernel_d/function_objectsCd.h index 69edd4b09e0..ae5887d33f1 100644 --- a/Kernel_d/include/CGAL/Kernel_d/function_objectsCd.h +++ b/Kernel_d/include/CGAL/Kernel_d/function_objectsCd.h @@ -42,13 +42,39 @@ class Compute_coordinateCd { typedef typename K::Point_d Point_d; public: typedef FT result_type; - const result_type + result_type operator()(const Point_d& p, int i) const { return p.cartesian(i); } }; +template +class Point_dimensionCd { + typedef typename K::FT FT; + typedef typename K::Point_d Point_d; + public: + typedef int result_type; + result_type + operator()(const Point_d& p) const + { + return p.dimension(); + } +}; + +template +class Less_coordinateCd { + typedef typename K::FT FT; + typedef typename K::Point_d Point_d; + public: + typedef bool result_type; + result_type + operator()(const Point_d& p, const Point_d& q, int i) const + { + return p.cartesian(i) struct Lift_to_paraboloidCd { typedef typename R::Point_d Point_d; diff --git a/Kernel_d/include/CGAL/Kernel_d/function_objectsHd.h b/Kernel_d/include/CGAL/Kernel_d/function_objectsHd.h index eaedbc5ec1e..2e719d9b6b8 100644 --- a/Kernel_d/include/CGAL/Kernel_d/function_objectsHd.h +++ b/Kernel_d/include/CGAL/Kernel_d/function_objectsHd.h @@ -41,13 +41,41 @@ class Compute_coordinateHd { typedef typename K::Point_d Point_d; public: typedef FT result_type; - const result_type + result_type operator()(const Point_d& p, int i) const { return p.cartesian(i); } }; +template +class Point_dimensionHd { + typedef typename K::RT RT; + typedef typename K::Point_d Point_d; + public: + typedef int result_type; + result_type + operator()(const Point_d& p) const + { + return p.dimension(); + } +}; + +template +class Less_coordinateHd { + typedef typename K::RT RT; + typedef typename K::Point_d Point_d; + public: + typedef bool result_type; + result_type + operator()(const Point_d& p, const Point_d& q, int i) const + { + int d = p.dimension(); + return p.cartesian(i)*q.homogeneous(d) struct Lift_to_paraboloidHd { typedef typename R::Point_d Point_d; diff --git a/Maintenance/test_handling/candidate_branches b/Maintenance/test_handling/candidate_branches index 207a38270ad..6ad05bd1130 100644 --- a/Maintenance/test_handling/candidate_branches +++ b/Maintenance/test_handling/candidate_branches @@ -1,3 +1,2 @@ Combinatorial_map-gdamiand unique_sqrt_extension-sloriot -spatial_sorting-increase_dim_and_add_info-sloriot diff --git a/Manual/doc_tex/Manual/geom.bib b/Manual/doc_tex/Manual/geom.bib index f2f52a5f4ea..aa71e56cfe3 100644 --- a/Manual/doc_tex/Manual/geom.bib +++ b/Manual/doc_tex/Manual/geom.bib @@ -1755,7 +1755,7 @@ cell neighborhood in $O(m)$ time." @inproceedings{acr-icb-03 , author = "Nina Amenta and Sunghee Choi and G{\"u}nter Rote" -, title = "Incremental constructions con BRIO" +, title = "Incremental constructions con {BRIO}" , booktitle = "Proc. 19th Annu. Sympos. Comput. Geom." , year = 2003 , pages = "211-219" diff --git a/Mesh_2/include/CGAL/Delaunay_mesh_area_criteria_2.h b/Mesh_2/include/CGAL/Delaunay_mesh_area_criteria_2.h index 4dadb89309f..1d99ea90c93 100644 --- a/Mesh_2/include/CGAL/Delaunay_mesh_area_criteria_2.h +++ b/Mesh_2/include/CGAL/Delaunay_mesh_area_criteria_2.h @@ -32,6 +32,10 @@ class Delaunay_mesh_area_criteria_2 Delaunay_mesh_size_criteria_2. Delaunay_mesh_criteria_2 is a virtual base class of Delaunay_mesh_size_criteria_2. */ { + typedef typename Tr::Geom_traits Geom_traits; + +protected: + Geom_traits traits; public: typedef Delaunay_mesh_criteria_2 Base; typedef Delaunay_mesh_size_criteria_2 Private_base; @@ -39,8 +43,9 @@ public: typedef typename Delaunay_mesh_size_criteria_2::Quality Quality; Delaunay_mesh_area_criteria_2(const double aspect_bound = 0.125, - const double area_bound = 0) - : Private_base(aspect_bound, area_bound) {} + const double area_bound = 0, + const Geom_traits& traits = Geom_traits()) + : Private_base(aspect_bound, area_bound, traits), traits(traits) {} inline double area_bound() const { return this->sizebound; } @@ -58,8 +63,9 @@ public: typedef typename Tr::Face_handle Face_handle; Is_bad(const double aspect_bound, - const double area_bound) - : Is_bad_base(aspect_bound, area_bound) {} + const double area_bound, + const Geom_traits& traits) + : Is_bad_base(aspect_bound, area_bound, traits) {} Mesh_2::Face_badness operator()(Quality q) { @@ -126,7 +132,7 @@ public: }; // end class Is_bad Is_bad is_bad_object() const - { return Is_bad(this->bound(), area_bound()); } + { return Is_bad(this->bound(), area_bound(), traits); } }; } //end namespace diff --git a/Mesh_2/include/CGAL/Delaunay_mesh_criteria_2.h b/Mesh_2/include/CGAL/Delaunay_mesh_criteria_2.h index 7a29d19c50c..c67a13fed72 100644 --- a/Mesh_2/include/CGAL/Delaunay_mesh_criteria_2.h +++ b/Mesh_2/include/CGAL/Delaunay_mesh_criteria_2.h @@ -31,7 +31,7 @@ class Delaunay_mesh_criteria_2 protected: typedef typename Tr::Geom_traits Geom_traits; - const Geom_traits& traits; + Geom_traits traits; public: typedef typename Tr::Face_handle Face_handle; diff --git a/Mesh_2/include/CGAL/Delaunay_mesh_local_size_criteria_2.h b/Mesh_2/include/CGAL/Delaunay_mesh_local_size_criteria_2.h index 1fde2bbbf27..a8ae1d36fc7 100644 --- a/Mesh_2/include/CGAL/Delaunay_mesh_local_size_criteria_2.h +++ b/Mesh_2/include/CGAL/Delaunay_mesh_local_size_criteria_2.h @@ -41,13 +41,16 @@ public: private: bool local; Segment _s; + Geom_traits traits; public: Delaunay_mesh_local_size_criteria_2(const double aspect_bound = 0.125, const double size_bound = 0, const bool is_local_size = false, - const Segment s = Segment()) - : Base(aspect_bound, size_bound), local(is_local_size), _s(s) {} + const Segment s = Segment(), + const Geom_traits& traits = Geom_traits()) + : Base(aspect_bound, size_bound), local(is_local_size), _s(s) + , traits(traits) {} inline Segment segment() const { return _s; } @@ -82,8 +85,9 @@ public: Is_bad(const double aspect_bound, const double size_bound, const bool l, - const Segment_2 _s) - : Base::Is_bad(aspect_bound, size_bound), local(l), s(_s) {} + const Segment_2 _s, + const Geom_traits& traits) + : Base::Is_bad(aspect_bound, size_bound, traits), local(l), s(_s) {} Mesh_2::Face_badness operator()(Quality q) const { @@ -119,7 +123,7 @@ public: }; Is_bad is_bad_object() const - { return Is_bad(this->bound(), this->size_bound(), local, segment()); } + { return Is_bad(this->bound(), this->size_bound(), local, segment(), traits); } }; } //end namespace diff --git a/Mesh_3/demo/Mesh_3/CMakeLists.txt b/Mesh_3/demo/Mesh_3/CMakeLists.txt index 13e544eab66..545ad51d313 100644 --- a/Mesh_3/demo/Mesh_3/CMakeLists.txt +++ b/Mesh_3/demo/Mesh_3/CMakeLists.txt @@ -11,6 +11,9 @@ if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER 2.6) endif() endif() +# Let plugins be compiled in the same directory as the executable. +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") + #option(MESH_3_DEMO_ENABLE_FORWARD_DECL "In the Mesh_3 demo, enable " OFF) #mark_as_advanced(MESH_3_DEMO_ENABLE_FORWARD_DECL) diff --git a/Mesh_3/demo/Mesh_3/implicit_functions/CMakeLists.txt b/Mesh_3/demo/Mesh_3/implicit_functions/CMakeLists.txt index 4f9b7ebcfb1..3a08b852110 100644 --- a/Mesh_3/demo/Mesh_3/implicit_functions/CMakeLists.txt +++ b/Mesh_3/demo/Mesh_3/implicit_functions/CMakeLists.txt @@ -11,6 +11,9 @@ if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER 2.6) endif() endif() +# Let plugins be compiled in the same directory as the executable. +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") + # Include directory of demo includes include_directories( BEFORE ${Mesh_3_implicit_functions_BINARY_DIR} ../include ) diff --git a/Nef_3/doc_tex/Nef_3_ref/Nef_polyhedron_3.tex b/Nef_3/doc_tex/Nef_3_ref/Nef_polyhedron_3.tex index 662a3a2a9d3..9e2822b0909 100644 --- a/Nef_3/doc_tex/Nef_3_ref/Nef_polyhedron_3.tex +++ b/Nef_3/doc_tex/Nef_3_ref/Nef_polyhedron_3.tex @@ -105,7 +105,7 @@ template parameters. \ccGlue \ccNestedType{SHalfedge_around_sface_const_circulator}{non-mutable circulator of shalfedges around a sface (ccw).} \ccGlue -\ccNestedType{SHalfedge_aroud_facet_const_circulator}{non-mutable circulator of shalfedges around a halffacet (ccw).} +\ccNestedType{SHalfedge_around_facet_const_circulator}{non-mutable circulator of shalfedges around a halffacet (ccw).} \ccGlue \ccNestedType{SFace_cycle_const_iterator}{non-mutable iterator over the cylces of a sface.} \ccGlue diff --git a/Nef_3/doc_tex/Nef_3_ref/Nef_polyhedron_3_Halfedge.tex b/Nef_3/doc_tex/Nef_3_ref/Nef_polyhedron_3_Halfedge.tex index d79b00da4a9..b4ecd69a550 100644 --- a/Nef_3/doc_tex/Nef_3_ref/Nef_polyhedron_3_Halfedge.tex +++ b/Nef_3/doc_tex/Nef_3_ref/Nef_polyhedron_3_Halfedge.tex @@ -91,7 +91,7 @@ class \ccc{Nef_polyhedron_3} manages the needed halfedges internally. \ccMethod{Halfedge_const_handle twin() const;}{the twin of \ccVar\ .} \ccMethod{SHalfedge_const_handle out_sedge() const;} -{the first out sedege of \ccVar\ .} +{the first out sedge of \ccVar\ .} \ccMethod{SFace_const_handle incident_sface() const;} {the incident sface of \ccVar\ .} diff --git a/Nef_S2/doc_tex/Nef_S2_ref/Nef_polyhedron_S2_SVertex.tex b/Nef_S2/doc_tex/Nef_S2_ref/Nef_polyhedron_S2_SVertex.tex index e93bec58c52..075a5376472 100644 --- a/Nef_S2/doc_tex/Nef_S2_ref/Nef_polyhedron_S2_SVertex.tex +++ b/Nef_S2/doc_tex/Nef_S2_ref/Nef_polyhedron_S2_SVertex.tex @@ -60,7 +60,7 @@ class \ccc{Nef_polyhedron_S2} manages the needed svertices internally. \ccMethod{SVertex_const_handle twin() const;}{the twin of \ccVar\ .} \ccMethod{SHalfedge_const_handle out_sedge() const;} -{the first out sedege of \ccVar\ .} +{the first out sedge of \ccVar\ .} \ccMethod{SFace_const_handle incident_sface() const;} {the incident sface of \ccVar\ .} diff --git a/Nef_S2/include/CGAL/Nef_S2/SM_point_locator.h b/Nef_S2/include/CGAL/Nef_S2/SM_point_locator.h index 69f54b2ebe1..494cd701075 100644 --- a/Nef_S2/include/CGAL/Nef_S2/SM_point_locator.h +++ b/Nef_S2/include/CGAL/Nef_S2/SM_point_locator.h @@ -92,9 +92,8 @@ public: typedef typename Decorator_traits::SVertex_handle SVertex_handle; typedef typename Decorator_traits::SHalfedge_handle SHalfedge_handle; typedef typename Decorator_traits::SHalfloop_handle SHalfloop_handle; - typedef typename Decorator_traits::SHalfloop_const_handle SHalfloop_const_handle; typedef typename Decorator_traits::SFace_handle SFace_handle; - typedef typename Decorator_traits::SFace_const_handle SFace_const_handle; + typedef typename Decorator_traits::SVertex_iterator SVertex_iterator; typedef typename Decorator_traits::SHalfedge_iterator SHalfedge_iterator; @@ -182,7 +181,7 @@ public: enum SOLUTION { is_vertex_, is_edge_, is_loop_ }; // enumeration for internal use - Object_handle locate(const Sphere_point& p, bool skipVEL = false) const + Object_handle locate(const Sphere_point& p, bool skipVEL = false) /*{\Mop returns a generic handle |h| to an object (vertex, halfedge, face) of the underlying plane map |P| which contains the point |p = s.source()| in its relative interior. |s.target()| must be a point @@ -209,7 +208,7 @@ public: if ( this->has_shalfloop() && this->shalfloop()->circle().has_on(p)) { CGAL_NEF_TRACEN( " on loop"); - return make_object(SHalfloop_const_handle(this->shalfloop())); + return make_object(SHalfloop_handle(this->shalfloop())); } } @@ -224,7 +223,7 @@ public: SVertex_handle v_res; SHalfedge_handle e_res; - SHalfloop_const_handle l_res(this->shalfloop()); + SHalfloop_handle l_res(this->shalfloop()); SOLUTION solution; CGAL_NEF_TRACEN(" on face..."); @@ -312,7 +311,7 @@ public: case is_edge_: return make_object(SFace_handle(e_res->incident_sface())); case is_loop_: - return make_object(SFace_const_handle(l_res->incident_sface())); + return make_object(SFace_handle(l_res->incident_sface())); case is_vertex_: return make_object(SFace_handle(v_res->incident_sface())); default: CGAL_error_msg("missing solution."); @@ -320,6 +319,7 @@ public: return Object_handle(); // never reached! } +#if 0 //THIS CODE DOES NOT SEEM TO BE USED template Object_handle ray_shoot(const Sphere_point& p, const Sphere_direction& d, @@ -336,7 +336,7 @@ public: { Sphere_circle c(d.circle()); Sphere_segment s; - Object_handle h = this->locate(p); + Object_handle h = locate(p); SVertex_handle v; SHalfedge_handle e; SHalfloop_handle l; @@ -404,7 +404,8 @@ public: CGAL_error_msg("not yet correct"); return h; } - +#endif + Object_handle ray_shoot(const Sphere_point& p, const Sphere_circle& c, Sphere_point& ip, diff --git a/Polyhedron/demo/Polyhedron/CMakeLists.txt b/Polyhedron/demo/Polyhedron/CMakeLists.txt index 076e343bed6..c482d9904bb 100644 --- a/Polyhedron/demo/Polyhedron/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/CMakeLists.txt @@ -36,11 +36,17 @@ include_directories( BEFORE ./ ./include ../../include ) find_package(CGAL COMPONENTS Qt4) include( ${CGAL_USE_FILE} ) +option( POLYHEDRON_QTSCRIPT_DEBUGGER + "Activate the use of Qt Script Debugger in Polyhedron_3 demo" OFF) + # Find Qt4 itself set( QT_USE_QTXML TRUE ) set( QT_USE_QTMAIN TRUE ) set( QT_USE_QTSCRIPT TRUE ) set( QT_USE_QTOPENGL TRUE ) +if( POLYHEDRON_QTSCRIPT_DEBUGGER) + set( QT_USE_QTSCRIPTTOOLS TRUE ) +endif() find_package(Qt4) # Find OpenGL @@ -49,6 +55,7 @@ find_package(OpenGL) # Find QGLViewer if(QT4_FOUND) include(${QT_USE_FILE}) + include_directories( ${QT_INCLUDE_DIR}/QtScriptTools ) find_package(QGLViewer ) endif(QT4_FOUND) @@ -80,9 +87,10 @@ if(CGAL_Qt4_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND) message(STATUS "NOTICE: LAPACK is not found. curvatures estimation will not be available.") endif(LAPACK_FOUND) - qt4_wrap_ui( UI_FILES MainWindow.ui ) - + qt4_wrap_ui( MainWindowUI_files MainWindow.ui ) + qt4_wrap_ui( Show_point_dialogUI_FILES Show_point_dialog.ui ) qt4_wrap_ui( remeshingUI_FILES Remeshing_dialog.ui) + qt4_wrap_ui( meshingUI_FILES Meshing_dialog.ui Meshing_pause_widget.ui ) include(AddFileDependencies) @@ -92,62 +100,80 @@ if(CGAL_Qt4_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND) qt4_generate_moc( "Viewer.h" "${CMAKE_CURRENT_BINARY_DIR}/Viewer_moc.cpp" ) add_file_dependencies( Viewer_moc.cpp "${CMAKE_CURRENT_SOURCE_DIR}/Viewer.h" ) - qt4_generate_moc( "Scene.h" "${CMAKE_CURRENT_BINARY_DIR}/Scene_moc.cpp" ) - add_file_dependencies( Scene_moc.cpp "${CMAKE_CURRENT_SOURCE_DIR}/Scene.h" ) - - qt4_generate_moc( "Polyhedron_demo_remeshing_plugin_cgal_code.cpp" "${CMAKE_CURRENT_BINARY_DIR}/Polyhedron_demo_remeshing_plugin_cgal_code.moc" ) qt4_add_resources ( RESOURCE_FILES Polyhedron_3.qrc ) - qt4_automoc(Scene_item.cpp + qt4_automoc(Scene.cpp + Scene_item.cpp Scene_plane_item.cpp Scene_polygon_soup.cpp Scene_polyhedron_item.cpp Scene_textured_polyhedron_item.cpp Scene_c2t3_item.cpp - Scene_nef_polyhedron_item.cpp) + Scene_nef_polyhedron_item.cpp + Show_point_dialog.cpp + ) # AUXILIARY LIBRARIES # put plugins (which are shared libraries) at the same location as # executable files - set(LIBRARY_OUTPUT_PATH ${RUNTIME_OUTPUT_PATH}) - add_library(scene_item SHARED + add_library(demo_framework SHARED + Scene.cpp + Viewer.cpp Viewer_moc.cpp Scene_item.cpp Scene_item.moc Scene_item_with_display_list.cpp Polyhedron_demo_plugin_helper.cpp) + target_link_libraries(demo_framework + ${QGLVIEWER_LIBRARIES} + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} + ) + add_library(scene_basic_objects SHARED Scene_plane_item.cpp Scene_plane_item.moc) - target_link_libraries(scene_basic_objects scene_item ${QGLVIEWER_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY}) + target_link_libraries(scene_basic_objects + demo_framework + ${QGLVIEWER_LIBRARIES} + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} + ) + + add_library(point_dialog SHARED Show_point_dialog.cpp Show_point_dialog.ui ${Show_point_dialogUI_FILES} ) add_library(scene_c2t3_item SHARED Scene_c2t3_item.cpp Scene_c2t3_item.moc) - target_link_libraries(scene_c2t3_item scene_item) + target_link_libraries(scene_c2t3_item demo_framework) add_library(scene_polyhedron_item SHARED Scene_polyhedron_item.cpp Scene_polyhedron_item.moc) - target_link_libraries(scene_polyhedron_item scene_item) + target_link_libraries(scene_polyhedron_item demo_framework) if(TAUCS_FOUND) add_library(scene_textured_polyhedron_item SHARED Scene_textured_polyhedron_item.cpp texture.cpp Scene_textured_polyhedron_item.moc) - target_link_libraries(scene_textured_polyhedron_item scene_item) + target_link_libraries(scene_textured_polyhedron_item demo_framework) endif(TAUCS_FOUND) - add_library(polygon_soup SHARED + add_library(scene_polygon_soup_item SHARED Scene_polygon_soup.cpp Scene_polygon_soup.moc) - target_link_libraries(polygon_soup scene_item) + target_link_libraries(scene_polygon_soup_item demo_framework scene_polyhedron_item) add_library(scene_nef_polyhedron_item SHARED Scene_nef_polyhedron_item.cpp Scene_nef_polyhedron_item.moc Scene_nef_rendering.cpp) - target_link_libraries(scene_nef_polyhedron_item scene_polyhedron_item) + target_link_libraries(scene_nef_polyhedron_item demo_framework scene_polyhedron_item) - foreach( lib scene_item scene_basic_objects scene_polyhedron_item polygon_soup scene_nef_polyhedron_item ) + foreach( lib + demo_framework + scene_basic_objects + scene_polyhedron_item + scene_polygon_soup_item + scene_nef_polyhedron_item ) add_to_cached_list( CGAL_EXECUTABLE_TARGETS ${lib} ) endforeach() @@ -156,13 +182,12 @@ if(CGAL_Qt4_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND) add_definitions(-DUSE_FORWARD_DECL) add_executable ( Polyhedron_3 MainWindow.cpp Polyhedron_3.cpp - Viewer.cpp - Scene.cpp +# Viewer.cpp +# Scene.cpp # MainWindow_curvature_estimation.cpp MainWindow_moc.cpp - Scene_moc.cpp - Viewer_moc.cpp - ${UI_FILES} ${RESOURCE_FILES} ) +# Viewer_moc.cpp + ${MainWindowUI_files} ${RESOURCE_FILES} ) add_to_cached_list( CGAL_EXECUTABLE_TARGETS Polyhedron_3 ) if(TAUCS_FOUND) # add_executable( Polyhedron_3 Scene_tex_rendering.cpp Scene_tex_polyhedron_operations.cpp ) @@ -176,7 +201,13 @@ if(CGAL_Qt4_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND) # Link with Qt libraries + if( POLYHEDRON_QTSCRIPT_DEBUGGER ) + add_definitions( -DQT_SCRIPTTOOLS_LIB ) + target_link_libraries( Polyhedron_3 QtScriptTools ) + endif() target_link_libraries( Polyhedron_3 ${QT_LIBRARIES} ) + target_link_libraries( Polyhedron_3 demo_framework ) + target_link_libraries( Polyhedron_3 point_dialog ) # Link with CGAL target_link_libraries( Polyhedron_3 ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES} ) @@ -184,9 +215,6 @@ if(CGAL_Qt4_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND) # Link with libQGLViewer, OpenGL target_link_libraries( Polyhedron_3 ${QGLVIEWER_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ) - # Link with the scene_item library. -# target_link_libraries( Polyhedron_3 scene_item ) - add_to_cached_list( CGAL_EXECUTABLE_TARGETS Polyhedron_3 ) @@ -198,26 +226,37 @@ if(CGAL_Qt4_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND) macro(polyhedron_demo_plugin plugin_name plugin_implementation_base_name) list_split(option ARGN_TAIL ${ARGN} ) if(NOT ${option} STREQUAL "EXCLUDE_FROM_ALL") - set(other_sources ${ARGN}) - set(option "") + if(NOT ${option} STREQUAL "NO_MOC") + set(other_sources ${ARGN}) + set(option "") + else() + set(other_sources ${ARGN_TAIL}) + endif() else() set(other_sources ${ARGN_TAIL}) endif() - qt4_generate_moc( ${plugin_implementation_base_name}.cpp "${CMAKE_CURRENT_BINARY_DIR}/${plugin_implementation_base_name}.moc" ) - add_file_dependencies( ${plugin_implementation_base_name}.moc "${CMAKE_CURRENT_SOURCE_DIR}/${plugin_implementation_base_name}.cpp" ) + if("${option}" STREQUAL "NO_MOC") + set(option "") + set(moc_file_name "") + else() + set(moc_file_name ${plugin_implementation_base_name}.moc ) + qt4_generate_moc( ${plugin_implementation_base_name}.cpp "${CMAKE_CURRENT_BINARY_DIR}/${moc_file_name}" ) + add_file_dependencies( ${moc_file_name} "${CMAKE_CURRENT_SOURCE_DIR}/${plugin_implementation_base_name}.cpp" ) + endif() - add_library(${plugin_name} MODULE ${option} ${plugin_implementation_base_name}.moc ${plugin_implementation_base_name}.cpp ${other_sources}) + add_library(${plugin_name} MODULE ${option} ${moc_file_name} ${plugin_implementation_base_name}.cpp ${other_sources}) add_to_cached_list( CGAL_EXECUTABLE_TARGETS ${plugin_name} ) # Link with Qt target_link_libraries( ${plugin_name} ${QT_LIBRARIES} ) - # Link with scene_item - target_link_libraries( ${plugin_name} scene_item) + # Link with the demo_framework + target_link_libraries( ${plugin_name} demo_framework) # Link with CGAL target_link_libraries( ${plugin_name} ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES} ) + add_dependencies( ${plugin_name} Polyhedron_3 ) endmacro(polyhedron_demo_plugin) polyhedron_demo_plugin(remeshing_plugin Polyhedron_demo_remeshing_plugin Polyhedron_demo_remeshing_plugin_cgal_code.cpp Polyhedron_demo_remeshing_plugin_cgal_code.moc ${remeshingUI_FILES}) - target_link_libraries(remeshing_plugin scene_polyhedron_item polygon_soup scene_c2t3_item) + target_link_libraries(remeshing_plugin scene_polyhedron_item scene_polygon_soup_item scene_c2t3_item) if ( Boost_VERSION GREATER 103400 ) qt4_generate_moc( "Polyhedron_demo_mesh_3_plugin_cgal_code.cpp" "${CMAKE_CURRENT_BINARY_DIR}/Scene_c3t3_item.moc" ) @@ -230,13 +269,13 @@ if(CGAL_Qt4_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND) endif( Boost_VERSION GREATER 103400 ) polyhedron_demo_plugin(inside_out_plugin Polyhedron_demo_inside_out_plugin) - target_link_libraries(inside_out_plugin scene_polyhedron_item polygon_soup) + target_link_libraries(inside_out_plugin scene_polyhedron_item scene_polygon_soup_item) polyhedron_demo_plugin(off_plugin Polyhedron_demo_off_plugin) - target_link_libraries(off_plugin scene_polyhedron_item polygon_soup) + target_link_libraries(off_plugin scene_polyhedron_item scene_polygon_soup_item) polyhedron_demo_plugin(orient_soup_plugin Polyhedron_demo_orient_soup_plugin) - target_link_libraries(orient_soup_plugin polygon_soup) + target_link_libraries(orient_soup_plugin scene_polygon_soup_item scene_polyhedron_item) polyhedron_demo_plugin(triangulate_facets_plugin Polyhedron_demo_triangulate_facets_plugin) target_link_libraries(triangulate_facets_plugin scene_polyhedron_item) diff --git a/Polyhedron/demo/Polyhedron/Color_map.h b/Polyhedron/demo/Polyhedron/Color_map.h new file mode 100644 index 00000000000..fb89f4d2c3f --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Color_map.h @@ -0,0 +1,26 @@ +#ifndef _COLOR_MAP_H +#define _COLOR_MAP_H + +#include + +template +Output_color_iterator +compute_color_map(QColor base_color, + unsigned nb_of_colors, + Output_color_iterator out) +{ + qreal hue = base_color.hueF(); + const qreal step = ((qreal)1) / nb_of_colors; + + qreal h = hue; + for(unsigned i = 0; i < nb_of_colors; ++i) { + h += step; + if ( h > 1 ) { h -= 1; } + *out++ = QColor::fromHsvF(h, + base_color.saturationF(), + base_color.valueF()); + } + return out; +} + +#endif diff --git a/Polyhedron/demo/Polyhedron/Kernel_type.h b/Polyhedron/demo/Polyhedron/Kernel_type.h new file mode 100644 index 00000000000..6da8cc541a5 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Kernel_type.h @@ -0,0 +1,13 @@ +#ifndef KERNEL_TYPE_H +#define KERNEL_TYPE_H + +#include +#include + +namespace kernel_type_h { + typedef CGAL::Exact_predicates_inexact_constructions_kernel K1; +} + +typedef CGAL::Mesh_3::Robust_intersection_traits_3 Kernel; + +#endif // KERNEL_TYPE_H diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index 6dee0b44be5..a63d0e00fc4 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -10,17 +10,94 @@ #include #include #include +#include +#include #include #include #include #include #include +#include +#include +#include +#include + +#ifdef QT_SCRIPT_LIB +# include +# ifdef QT_SCRIPTTOOLS_LIB +# include +# endif +#endif #include "Polyhedron_demo_plugin_interface.h" #include "Polyhedron_demo_io_plugin_interface.h" #include "ui_MainWindow.h" +#include "Show_point_dialog.h" + +#ifdef QT_SCRIPT_LIB +# include +# include + +QScriptValue +myScene_itemToScriptValue(QScriptEngine *engine, + Scene_item* const &in) +{ + return engine->newQObject(in); +} + +void myScene_itemFromScriptValue(const QScriptValue &object, + Scene_item* &out) +{ + out = qobject_cast(object.toQObject()); +} +#endif // QT_SCRIPT_LIB + +#ifdef QT_SCRIPT_LIB +# ifdef QT_SCRIPTTOOLS_LIB + +const QScriptEngineDebugger::DebuggerWidget debug_widgets[9] = { + QScriptEngineDebugger::ConsoleWidget, + QScriptEngineDebugger::StackWidget, + QScriptEngineDebugger::ScriptsWidget, + QScriptEngineDebugger::LocalsWidget, + QScriptEngineDebugger::CodeWidget, + QScriptEngineDebugger::CodeFinderWidget, + QScriptEngineDebugger::BreakpointsWidget, + QScriptEngineDebugger::DebugOutputWidget, + QScriptEngineDebugger::ErrorLogWidget +}; +const QString debug_widgets_names[9] = { + "Script console", + "Stack", + "Scripts", + "Locals", + "Code", + "CodeFinder", + "Breakpoints", + "DebugOutput", + "ErrorLog" +}; + +# endif +#endif + +QScriptValue myPrintFunction(QScriptContext *context, QScriptEngine *engine) +{ + MainWindow* mw = qobject_cast(engine->parent()); + QString result; + for (int i = 0; i < context->argumentCount(); ++i) { + if (i > 0) + result.append(" "); + result.append(context->argument(i).toString()); + } + + if(mw) mw->message(QString("QtScript: ") + result, ""); + + return engine->undefinedValue(); +} + MainWindow::~MainWindow() { delete ui; @@ -70,6 +147,10 @@ MainWindow::MainWindow(QWidget* parent) connect(scene, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex & )), this, SLOT(updateInfo())); + + connect(scene, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex & )), + this, SLOT(updateDisplayInfo())); + connect(scene, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex & )), viewer, SLOT(updateGL())); @@ -86,12 +167,37 @@ MainWindow::MainWindow(QWidget* parent) SIGNAL(selectionChanged ( const QItemSelection & , const QItemSelection & ) ), this, SLOT(updateInfo())); + connect(treeView->selectionModel(), + SIGNAL(selectionChanged ( const QItemSelection & , const QItemSelection & ) ), + this, SLOT(updateDisplayInfo())); + connect(treeView->selectionModel(), SIGNAL(selectionChanged ( const QItemSelection & , const QItemSelection & ) ), this, SLOT(selectionChanged())); + treeView->setContextMenuPolicy(Qt::CustomContextMenu); + connect(treeView, SIGNAL(customContextMenuRequested(const QPoint & )), + this, SLOT(showSceneContextMenu(const QPoint &))); + connect(viewer, SIGNAL(selected(int)), this, SLOT(selectSceneItem(int))); + connect(viewer, SIGNAL(selectedPoint(double, double, double)), + this, SLOT(showSelectedPoint(double, double, double))); + + connect(viewer, SIGNAL(selectionRay(double, double, double, + double, double, double)), + scene, SIGNAL(selectionRay(double, double, double, + double, double, double))); + + connect(viewer, SIGNAL(requestContextMenu(QPoint)), + this, SLOT(contextMenuRequested(QPoint))); + connect(ui->infoLabel, SIGNAL(customContextMenuRequested(const QPoint & )), + this, SLOT(showSceneContextMenu(const QPoint &))); + + connect(ui->actionRecenterScene, SIGNAL(triggered()), + viewer->camera(), SLOT(interpolateToFitScene())); + connect(ui->actionRecenterScene, SIGNAL(triggered()), + viewer, SLOT(update())); connect(ui->actionAntiAliasing, SIGNAL(toggled(bool)), viewer, SLOT(setAntiAliasing(bool))); @@ -100,7 +206,7 @@ MainWindow::MainWindow(QWidget* parent) viewer, SLOT(setTwoSides(bool))); // enable anti-aliasing by default - ui->actionAntiAliasing->setChecked(true); + // ui->actionAntiAliasing->setChecked(true); // add the "About CGAL..." and "About demo..." entries this->addAboutCGAL(); @@ -116,6 +222,10 @@ MainWindow::MainWindow(QWidget* parent) connect(ui->actionQuit, SIGNAL(triggered()), this, SLOT(quit())); + // Connect "Select all items" + connect(ui->actionSelect_all_items, SIGNAL(triggered()), + this, SLOT(selectAll())); + // Recent files menu this->addRecentFiles(ui->menuFile, ui->actionQuit); connect(this, SIGNAL(openRecentFile(QString)), @@ -124,10 +234,118 @@ MainWindow::MainWindow(QWidget* parent) // Reset the "Operation menu" clearMenu(ui->menuOperations); +#ifdef QT_SCRIPT_LIB + std::cerr << "Enable scripts.\n"; + script_engine = new QScriptEngine(this); + qScriptRegisterMetaType(script_engine, + myScene_itemToScriptValue, + myScene_itemFromScriptValue); +# ifdef QT_SCRIPTTOOLS_LIB + QScriptEngineDebugger* debugger = new QScriptEngineDebugger(this); + debugger->setObjectName("qt script debugger"); + QAction* debuggerMenuAction = + menuBar()->addMenu(debugger->createStandardMenu()); + debuggerMenuAction->setText(tr("Qt Script &debug")); + for(unsigned int i = 0; i < 9; ++i) + { + QDockWidget* dock = new QDockWidget(debug_widgets_names[i], this); + dock->setObjectName(debug_widgets_names[i]); + dock->setWidget(debugger->widget(debug_widgets[i])); + this->addDockWidget(Qt::BottomDockWidgetArea, dock); + dock->hide(); + } + debugger->setAutoShowStandardWindow(false); + debugger->attachTo(script_engine); +# endif // QT_SCRIPTTOOLS_LIB + QScriptValue fun = script_engine->newFunction(myPrintFunction); + script_engine->globalObject().setProperty("print", fun); + + evaluate_script("print('hello', 'world', 'from QtScript!')"); + QScriptValue mainWindowObjectValue = script_engine->newQObject(this); + script_engine->globalObject().setProperty("main_window", mainWindowObjectValue); + + QScriptValue sceneObjectValue = script_engine->newQObject(scene); + mainWindowObjectValue.setProperty("scene", sceneObjectValue); + script_engine->globalObject().setProperty("scene", sceneObjectValue); + + QScriptValue viewerObjectValue = script_engine->newQObject(viewer); + mainWindowObjectValue.setProperty("viewer", viewerObjectValue); + script_engine->globalObject().setProperty("viewer", viewerObjectValue); + + QScriptValue cameraObjectValue = script_engine->newQObject(viewer->camera()); + viewerObjectValue.setProperty("camera", cameraObjectValue); + script_engine->globalObject().setProperty("camera", cameraObjectValue); + + evaluate_script("var plugins = new Array();"); +# ifdef QT_SCRIPTTOOLS_LIB + QScriptValue debuggerObjectValue = script_engine->newQObject(debugger); + script_engine->globalObject().setProperty("debugger", debuggerObjectValue); +# endif +#endif + // Load plugins, and re-enable actions that need it. loadPlugins(); readSettings(); // Among other things, the column widths are stored. + +#ifdef QT_SCRIPT_LIB + // evaluate_script("print(plugins);"); + Q_FOREACH(QAction* action, findChildren()) { + if(action->objectName() != "") { + QScriptValue objectValue = script_engine->newQObject(action); + script_engine->globalObject().setProperty(action->objectName(), + objectValue); + } + } + // debugger->action(QScriptEngineDebugger::InterruptAction)->trigger(); +#endif +} + +#ifdef QT_SCRIPT_LIB +void MainWindow::evaluate_script(QString script, + const QString& filename, + const bool quiet) { + QScriptValue value = script_engine->evaluate(script); + if(script_engine->hasUncaughtException()) { + QTextStream err(stderr); + err << "Qt Script exception:\n" + << script_engine->uncaughtException().toString() + << "\nBacktrace:\n"; + Q_FOREACH(QString line, script_engine->uncaughtExceptionBacktrace()) { + err << " " << line << "\n"; + } + } + else if(!quiet && !value.isNull() && !value.isUndefined()) { + QTextStream(stderr) << "Qt Script evaluated to \"" + << value.toString() << "\"\n"; + } +} + +void MainWindow::evaluate_script_quiet(QString script, + const QString& filename) +{ + evaluate_script(script, filename, true); +} +#endif + +void MainWindow::enableScriptDebugger(bool b /* = true */) +{ + Q_UNUSED(b); +#ifdef QT_SCRIPT_LIB +# ifdef QT_SCRIPTTOOLS_LIB + QScriptEngineDebugger* debugger = + findChild("qt script debugger"); + if(debugger) { + if(b) { + debugger->action(QScriptEngineDebugger::InterruptAction)->trigger(); + } + } + return; +# endif +#endif + // If we are here, then the debugger is not available + this->error(tr("Your version of Qt is too old, and for that reason" + "the Qt Script Debugger is not available.")); } void MainWindow::loadPlugins() @@ -140,7 +358,7 @@ void MainWindow::loadPlugins() QList plugins_directories; plugins_directories << qApp->applicationDirPath(); - QString env_path = ::getenv("POLYHEDRON_DEMO_PLUGINS_PATH"); + QString env_path = qgetenv("POLYHEDRON_DEMO_PLUGINS_PATH"); if(!env_path.isEmpty()) { Q_FOREACH (QString pluginsDir, env_path.split(":", QString::SkipEmptyParts)) { @@ -154,11 +372,15 @@ void MainWindow::loadPlugins() qPrintable(pluginsDir.absolutePath())); Q_FOREACH (QString fileName, pluginsDir.entryList(QDir::Files)) { if(fileName.contains("plugin") && QLibrary::isLibrary(fileName)) { - qDebug("### Loading \"%s\"...", fileName.toUtf8().data()); + qDebug("### Loading \"%s\"...", qPrintable(fileName)); QPluginLoader loader; loader.setFileName(pluginsDir.absoluteFilePath(fileName)); QObject *obj = loader.instance(); if(obj) { + QString name = fileName; + name.remove(QRegExp("^lib")); + name.remove(QRegExp("\\..*")); + obj->setObjectName(name); initPlugin(obj); initIOPlugin(obj); } @@ -172,6 +394,11 @@ void MainWindow::loadPlugins() } } +bool MainWindow::hasPlugin(QString pluginName) +{ + return plugins.contains(pluginName); +} + bool MainWindow::initPlugin(QObject* obj) { QObjectList childs = this->children(); @@ -180,6 +407,13 @@ bool MainWindow::initPlugin(QObject* obj) if(plugin) { // Call plugin's init() method plugin->init(this, this->scene, this); + plugins << obj->objectName(); +#ifdef QT_SCRIPT_LIB + QScriptValue objectValue = + script_engine->newQObject(obj); + script_engine->globalObject().setProperty(obj->objectName(), objectValue); + evaluate_script_quiet(QString("plugins.push(%1);").arg(obj->objectName())); +#endif Q_FOREACH(QAction* action, plugin->actions()) { // If action does not belong to the menus, add it to "Operations" menu @@ -201,6 +435,7 @@ bool MainWindow::initIOPlugin(QObject* obj) qobject_cast(obj); if(plugin) { // std::cerr << "I/O plugin\n"; + plugins << obj->objectName(); io_plugins << plugin; return true; } @@ -240,12 +475,51 @@ void MainWindow::addAction(QAction* action) } } +void MainWindow::addAction(QString actionName, + QString actionText, + QString menuName) { + QMenu* menu = 0; + Q_FOREACH(QAction* action, findChildren()) { + if(!action->menu()) continue; + QString menuText = action->menu()->title(); + if(menuText != menuName) continue; + menu = action->menu(); + } + if(menu == 0) { + menu = new QMenu(menuName, this); + menuBar()->insertMenu(ui->menuView->menuAction(), menu); + } + QAction* action = new QAction(actionText, this); + action->setObjectName(actionName); + menu->addAction(action); +#ifdef QT_SCRIPT_LIB + QScriptValue objectValue = script_engine->newQObject(action); + script_engine->globalObject().setProperty(action->objectName(), + objectValue); +#endif +} + +void MainWindow::viewerShow(float x, float y, float z) { + viewer->camera()->setRevolveAroundPoint(qglviewer::Vec(x, y, z)); + // viewer->camera()->lookAt(qglviewer::Vec(x, y, z)); + + qglviewer::ManipulatedCameraFrame backup_frame(*viewer->camera()->frame()); + viewer->camera()->fitSphere(qglviewer::Vec(x, y, z), + viewer->camera()->sceneRadius()/100); + qglviewer::ManipulatedCameraFrame new_frame(*viewer->camera()->frame()); + *viewer->camera()->frame() = backup_frame; + viewer->camera()->interpolateTo(new_frame, 1.f); + viewer->setVisualHintsMask(1); +} + void MainWindow::message(QString message, QString colorName, QString font) { if (message.endsWith('\n')) { message.remove(message.length()-1, 1); } + std::cerr << qPrintable(message) << std::endl; statusBar()->showMessage(message, 5000); - message = "" + message + "
    "; + message = "" + + message + "
    "; message = "[" + QTime::currentTime().toString() + "] " + message; ui->consoleTextEdit->insertHtml(message); ui->consoleTextEdit->verticalScrollBar()->setValue(ui->consoleTextEdit->verticalScrollBar()->maximum()); @@ -282,21 +556,101 @@ void MainWindow::updateViewerBBox() viewer->camera()->showEntireScene(); } -void MainWindow::open(QString filename) +void MainWindow::reload_item() { + QAction* sender_action = qobject_cast(sender()); + if(!sender_action) return; + + bool ok; + int item_index = sender_action->data().toInt(&ok); + QObject* item_object = scene->item(item_index); + if(!ok || !item_object || sender_action->data().type() != QVariant::Int) { + std::cerr << "Cannot reload item: " + << "the reload action has not item attached\n"; + return; + } + Scene_item* item = qobject_cast(item_object); + if(!item) { + std::cerr << "Cannot reload item: " + << "the reload action has a QObject* pointer attached\n" + << "that is not a Scene_item*\n"; + return; + } + QString filename = item->property("source filename").toString(); + if(filename.isEmpty()) { + std::cerr << "Cannot reload item: " + << "the item has not filename attached\n"; + return; + } + QFileInfo fileinfo(filename); + if(! (fileinfo.isFile() && fileinfo.isReadable()) ) { + std::cerr << "Cannot reload item: " + << "cannot read file " << qPrintable(filename) << " \n"; + return; + } + Scene_item* new_item = load_item(fileinfo); + if(!new_item) { + std::cerr << "Cannot reload item: " + << "file " << qPrintable(filename) << " is not an item\n"; + return; + } + new_item->setName(item->name()); + new_item->setColor(item->color()); + new_item->setRenderingMode(item->renderingMode()); + new_item->setVisible(item->visible()); + new_item->setProperty("source filename", item->property("source filename")); + new_item->changed(); + scene->replaceItem(item_index, new_item); + delete item; +} + +Scene_item* MainWindow::load_item(QFileInfo fileinfo) const { + Scene_item* item = 0; + Q_FOREACH(Polyhedron_demo_io_plugin_interface* plugin, + io_plugins) + { + if(plugin->canLoad()) { + item = plugin->load(fileinfo); + if(item) break; // go out of the loop + } + } + return item; +} + +void MainWindow::open(QString filename, bool no_popup) { +#ifdef QT_SCRIPT_LIB + QString program; + if(filename.startsWith("javascript:")) { + program=filename.right(filename.size() - 11); + } + if(filename.startsWith("qtscript:")) { + program=filename.right(filename.size() - 9); + } + if(filename.endsWith(".js")) { + QFile script_file(filename); + script_file.open(QIODevice::ReadOnly); + program = script_file.readAll(); + } + if(!program.isEmpty()) + { + { + QTextStream(stderr) << "Execution of script \"" + << filename << "\"\n"; + // << filename << "\", with following content:\n" + // << program; + } + evaluate_script(program, filename); + return; + } +#endif + QFileInfo fileinfo(filename); Scene_item* item = 0; if(fileinfo.isFile() && fileinfo.isReadable()) { - Q_FOREACH(Polyhedron_demo_io_plugin_interface* plugin, - io_plugins) - { - if(plugin->canLoad()) { - item = plugin->load(fileinfo); - if(item) break; // go out of the loop - } - } + item = load_item(fileinfo); if(item) { Scene::Item_id index = scene->addItem(item); + item->setProperty("source filename", fileinfo.absoluteFilePath()); QSettings settings; settings.setValue("OFF open directory", fileinfo.absoluteDir().absolutePath()); @@ -304,6 +658,7 @@ void MainWindow::open(QString filename) selectSceneItem(index); } else { + if(no_popup) return; QMessageBox::critical(this, tr("Cannot open file"), tr("File %1 has not a known file format.") @@ -311,6 +666,7 @@ void MainWindow::open(QString filename) } } else { + if(no_popup) return; QMessageBox::critical(this, tr("Cannot open file"), tr("File %1 is not a readable file.") @@ -321,24 +677,68 @@ void MainWindow::open(QString filename) void MainWindow::selectSceneItem(int i) { if(i < 0) return; - if((unsigned int)i >= scene->numberOfEntries()) return; + if(i >= scene->numberOfEntries()) return; treeView->selectionModel()->select(scene->createSelection(i), QItemSelectionModel::ClearAndSelect); } +void MainWindow::showSelectedPoint(double x, double y, double z) +{ + information(QString("Selected point: (%1, %2, %3)"). + arg(x, 0, 'g', 10). + arg(y, 0, 'g', 10). + arg(z, 0, 'g', 10)); +} + +void MainWindow::unSelectSceneItem(int i) +{ + removeSceneItemFromSelection(i); +} + +void MainWindow::addSceneItemInSelection(int i) +{ + treeView->selectionModel()->select(scene->createSelection(i), + QItemSelectionModel::Select); + scene->itemChanged(i); +} + +void MainWindow::removeSceneItemFromSelection(int i) +{ + treeView->selectionModel()->select(scene->createSelection(i), + QItemSelectionModel::Deselect); + scene->itemChanged(i); +} + +void MainWindow::selectAll() +{ + treeView->selectionModel()->select(scene->createSelectionAll(), + QItemSelectionModel::ClearAndSelect); +} + int MainWindow::getSelectedSceneItemIndex() const { QModelIndexList selectedRows = treeView->selectionModel()->selectedRows(); - if(selectedRows.empty()) + if(selectedRows.size() != 1) return -1; else return selectedRows.first().row(); } +QList MainWindow::getSelectedSceneItemIndices() const +{ + QModelIndexList selectedRows = treeView->selectionModel()->selectedRows(); + QList result; + Q_FOREACH(QModelIndex index, selectedRows) { + result << index.row(); + } + return result; +} + void MainWindow::selectionChanged() { scene->setSelectedItem(getSelectedSceneItemIndex()); + scene->setSelectedItemsList(getSelectedSceneItemIndices()); Scene_item* item = scene->item(getSelectedSceneItemIndex()); if(item != NULL && item->manipulatable()) { viewer->setManipulatedFrame(item->manipulatedFrame()); @@ -349,6 +749,53 @@ void MainWindow::selectionChanged() viewer->updateGL(); } +void MainWindow::contextMenuRequested(const QPoint& global_pos) { + int index = scene->mainSelectionIndex(); + showSceneContextMenu(index, global_pos); +} + +void MainWindow::showSceneContextMenu(int selectedItemIndex, + const QPoint& global_pos) +{ + Scene_item* item = scene->item(selectedItemIndex); + if(!item) return; + + const char* prop_name = "Menu modified by MainWindow."; + + QMenu* menu = item->contextMenu(); + if(menu && !item->property("source filename").toString().isEmpty()) { + bool menuChanged = menu->property(prop_name).toBool(); + if(!menuChanged) { + menu->addSeparator(); + QAction* reload = menu->addAction(tr("Reload item from file")); + reload->setData(qVariantFromValue(selectedItemIndex)); + connect(reload, SIGNAL(triggered()), + this, SLOT(reload_item())); + menu->setProperty(prop_name, true); + } + } + if(menu) + menu->exec(global_pos); +} + +void MainWindow::showSceneContextMenu(const QPoint& p) { + QWidget* sender = qobject_cast(this->sender()); + if(!sender) return; + + int index = -1; + if(sender == treeView) { + QModelIndex modelIndex = treeView->indexAt(p); + if(!modelIndex.isValid()) return; + + index = modelIndex.row(); + } + else { + index = scene->mainSelectionIndex(); + } + + showSceneContextMenu(index, sender->mapToGlobal(p)); +} + void MainWindow::removeManipulatedFrame(Scene_item* item) { if(item->manipulatable() && @@ -359,12 +806,26 @@ void MainWindow::removeManipulatedFrame(Scene_item* item) void MainWindow::updateInfo() { Scene_item* item = scene->item(getSelectedSceneItemIndex()); - if(item) - ui->infoLabel->setText(item->toolTip()); + if(item) { + QString item_text = item->toolTip(); + QString item_filename = item->property("source filename").toString(); + if(!item_filename.isEmpty()) { + item_text += QString("
    File: %1").arg(item_filename); + } + ui->infoLabel->setText(item_text); + } else ui->infoLabel->clear(); } +void MainWindow::updateDisplayInfo() { + Scene_item* item = scene->item(getSelectedSceneItemIndex()); + if(item) + ui->displayLabel->setPixmap(item->graphicalToolTip()); + else + ui->displayLabel->clear(); +} + void MainWindow::readSettings() { this->readState("MainWindow", Size|State); @@ -390,12 +851,25 @@ void MainWindow::closeEvent(QCloseEvent *event) void MainWindow::on_actionLoad_triggered() { QStringList filters; + QStringList extensions; Q_FOREACH(Polyhedron_demo_io_plugin_interface* plugin, io_plugins) { if(plugin->canLoad()) { - filters += plugin->nameFilters(); + Q_FOREACH(QString filter, plugin->nameFilters()) { + if(!filter.isEmpty()) { + QRegExp re1("\\((.+)\\)"); + if(re1.indexIn(filter) != -1) { + QString filter_extensions = re1.cap(1); + extensions += filter_extensions.simplified().split(" "); + } + filters << filter; + } + } } } + QStringList sorted_extensions = extensions.toSet().toList(); filters << tr("All files (*)"); + filters.push_front(QString("All know files (%1)") + .arg(sorted_extensions.join(" "))); QSettings settings; QString directory = settings.value("OFF open directory", @@ -444,19 +918,15 @@ void MainWindow::on_actionSaveAs_triggered() QFileDialog::getSaveFileName(this, tr("Save to File..."), QString(), - tr("OFF files (*.off)\n" - "All files (*)")); - QFileInfo fileinfo(filename); - if(!fileinfo.isFile() || - QMessageBox::warning(this, - tr("File exists"), - tr("The file %1 already exists! Continue?") - .arg(filename), - QMessageBox::Yes|QMessageBox::No) == - QMessageBox::Yes) - { + filters.join(";;")); + save(filename, item); +} - Q_FOREACH(Polyhedron_demo_io_plugin_interface* plugin, canSavePlugins) { +void MainWindow::save(QString filename, Scene_item* item) { + QFileInfo fileinfo(filename); + + Q_FOREACH(Polyhedron_demo_io_plugin_interface* plugin, io_plugins) { + if(plugin->canSave(item)) { if(plugin->save(item, fileinfo)) break; } @@ -465,9 +935,9 @@ void MainWindow::on_actionSaveAs_triggered() bool MainWindow::on_actionErase_triggered() { - int index = scene->erase(getSelectedSceneItemIndex()); - selectSceneItem(index); - return index >= 0; + int next_index = scene->erase(scene->selectionIndices()); + selectSceneItem(next_index); + return next_index >= 0; } void MainWindow::on_actionEraseAll_triggered() @@ -505,6 +975,49 @@ void MainWindow::on_actionSetPolyhedronB_triggered() scene->setItemB(i); } +void MainWindow::on_actionSetBackgroundColor_triggered() +{ + QColor c = QColorDialog::getColor(); + if(c.isValid()) { + viewer->setBackgroundColor(c); + } +} + +void MainWindow::on_action_Look_at_triggered() +{ + Show_point_dialog dialog(this); + int i = dialog.exec(); + if( i == QDialog::Accepted && + dialog.has_correct_coordinates() ) + { + viewerShow((float)dialog.get_x(), + (float)dialog.get_y(), + (float)dialog.get_z()); + } +} + +QString MainWindow::camera_string() const +{ + return viewer->dumpCameraCoordinates(); +} + +void MainWindow::on_actionDumpCamera_triggered() +{ + information(QString("Camera: %1") + .arg(camera_string())); +} + +void MainWindow::on_action_Copy_camera_triggered() +{ + qApp->clipboard()->setText(this->camera_string()); +} + +void MainWindow::on_action_Paste_camera_triggered() +{ + QString s = qApp->clipboard()->text(); + viewer->moveCameraToCoordinates(s, 0.5f); +} + void MainWindow::setAddKeyFrameKeyboardModifiers(::Qt::KeyboardModifiers m) { viewer->setAddKeyFrameKeyboardModifiers(m); diff --git a/Polyhedron/demo/Polyhedron/MainWindow.h b/Polyhedron/demo/Polyhedron/MainWindow.h index d6d13bfe50e..e030162fa8f 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.h +++ b/Polyhedron/demo/Polyhedron/MainWindow.h @@ -4,8 +4,14 @@ #include #include +#ifdef QT_SCRIPT_LIB +# include +#endif #include +#include +#include +#include class Scene; class Viewer; @@ -35,22 +41,44 @@ public: public slots: void updateViewerBBox(); - void open(QString filename); + void open(QString filename, bool no_popup = false); + Scene_item* load_item(QFileInfo) const; + void reload_item(); void selectSceneItem(int i); + void showSelectedPoint(double, double, double); + void unSelectSceneItem(int i); + void selectAll(); + void addSceneItemInSelection(int i); + void removeSceneItemFromSelection(int i); // same as unSelectSceneItem void setAddKeyFrameKeyboardModifiers(Qt::KeyboardModifiers); void clearMenu(QMenu*); void addAction(QAction*); + void addAction(QString actionName, + QString actionText, + QString menuName); + void viewerShow(float, float, float); void information(QString); void warning(QString); void error(QString); + void message(QString, QString, QString = QString("normal")); + + bool hasPlugin(QString); + void enableScriptDebugger(bool = true); protected slots: void selectionChanged(); + + void contextMenuRequested(const QPoint& global_pos); + void showSceneContextMenu(int selectedItemIndex, + const QPoint& global_pos); + void showSceneContextMenu(const QPoint& local_pos_of_treeview); + void updateInfo(); + void updateDisplayInfo(); void removeManipulatedFrame(Scene_item*); // settings @@ -73,9 +101,18 @@ protected slots: // save as... void on_actionSaveAs_triggered(); + void save(QString filename, Scene_item* item); + + void on_actionSetBackgroundColor_triggered(); + + void on_action_Look_at_triggered(); + + QString camera_string() const; + void on_actionDumpCamera_triggered(); + void on_action_Copy_camera_triggered(); + void on_action_Paste_camera_triggered(); protected: - void message(QString, QString, QString = QString("normal")); void loadPlugins(); bool initPlugin(QObject*); bool initIOPlugin(QObject*); @@ -84,6 +121,7 @@ protected: bool onePolygonIsSelected() const; int getSelectedSceneItemIndex() const; + QList getSelectedSceneItemIndices() const; private: QString strippedName(const QString &fullFileName); @@ -93,6 +131,16 @@ private: QTreeView* treeView; Ui::MainWindow* ui; QVector io_plugins; + QStringList plugins; +#ifdef QT_SCRIPT_LIB + QScriptEngine* script_engine; +public: + void evaluate_script(QString script, + const QString & fileName = QString(), + const bool quiet = false); + void evaluate_script_quiet(QString script, + const QString & fileName = QString()); +#endif }; #endif // ifndef MAINWINDOW_H diff --git a/Polyhedron/demo/Polyhedron/MainWindow.ui b/Polyhedron/demo/Polyhedron/MainWindow.ui index f48127f67a7..85fe822068d 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.ui +++ b/Polyhedron/demo/Polyhedron/MainWindow.ui @@ -1,4 +1,3 @@ - MainWindow @@ -29,9 +28,6 @@ - - - @@ -40,7 +36,7 @@ 0 0 978 - 26 + 23 @@ -62,6 +58,7 @@ + @@ -124,9 +121,21 @@ + + + Ca&mera + + + + + + + + + @@ -139,7 +148,7 @@ - Polyhedra + Geometric Objects 1 @@ -206,6 +215,9 @@ true + + QAbstractItemView::ExtendedSelection + 0 @@ -238,6 +250,45 @@ + + + Infos + + + 1 + + + + + + + 0 + + + + + Qt::CustomContextMenu + + + 0 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + + + + + + + + &Quit @@ -431,17 +482,11 @@ Set polyhedron A - - Ctrl+A - Set polyhedron B - - Ctrl+B - @@ -453,6 +498,11 @@ &Remeshing + + + Convex Decomposition + + Mean &value coordinates @@ -489,6 +539,19 @@ Ctrl+T + + + Re&center scene + + + Ctrl+C + + + + + Change &background color... + + &Minkowski sum @@ -497,9 +560,32 @@ Ctrl+O, M - + - Convex Decomposition + &Look at... + + + + + &Dump camera coordinates + + + + + &Copy camera + + + + + &Paste camera + + + + + Select all items + + + Ctrl+A diff --git a/Polyhedron/demo/Polyhedron/Point_dialog_config.h b/Polyhedron/demo/Polyhedron/Point_dialog_config.h new file mode 100644 index 00000000000..4133f9776b6 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Point_dialog_config.h @@ -0,0 +1,12 @@ +#ifndef POINT_DIALOG_CONFIG_H +#define POINT_DIALOG_CONFIG_H + +#include + +#ifdef point_dialog_EXPORTS +# define POINT_DIALOG_EXPORT Q_DECL_EXPORT +#else +# define POINT_DIALOG_EXPORT Q_DECL_IMPORT +#endif + +#endif // POINT_DIALOG_CONFIG_H diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_3.cpp b/Polyhedron/demo/Polyhedron/Polyhedron_3.cpp index c03c4b22ffc..ba0eb98f23e 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_3.cpp +++ b/Polyhedron/demo/Polyhedron/Polyhedron_3.cpp @@ -25,11 +25,26 @@ int main(int argc, char **argv) mainWindow.setAddKeyFrameKeyboardModifiers(::Qt::MetaModifier); args.removeAt(0); } - +#ifdef QT_SCRIPT_LIB + if(!args.empty() && args[0] == "--debug-scripts") + { + mainWindow.enableScriptDebugger(); + args.removeAt(0); + } + mainWindow.open("autostart.js", true); +#endif Q_FOREACH(QString filename, args) { mainWindow.open(filename); } - return app.exec(); + + // A Qt Script may have closed the main window + // The following loop launch app.exec() only if there is a visible + // window. + Q_FOREACH (QWidget *widget, QApplication::topLevelWidgets()) { + if(widget->isVisible()) + return app.exec(); + } + return 0; } #ifndef USE_FORWARD_DECL diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_demo_kernel_plugin.cpp b/Polyhedron/demo/Polyhedron/Polyhedron_demo_kernel_plugin.cpp index 3e3d15629f7..d4403303f8b 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_demo_kernel_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Polyhedron_demo_kernel_plugin.cpp @@ -17,6 +17,13 @@ #include #include +#include "Kernel_type.h" +typedef Kernel::Triangle_3 Triangle; +typedef Kernel::Point_3 Point; +typedef Kernel::Vector_3 Vector; +typedef Kernel::Plane_3 Plane; +typedef Kernel::FT FT; + class Polyhedron_demo_kernel_plugin : public QObject, public Polyhedron_demo_plugin_helper diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_demo_off_plugin.cpp b/Polyhedron/demo/Polyhedron/Polyhedron_demo_off_plugin.cpp index 5dc9fba218b..d21a51808e1 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_demo_off_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Polyhedron_demo_off_plugin.cpp @@ -32,7 +32,7 @@ bool Polyhedron_demo_off_plugin::canLoad() const { Scene_item* Polyhedron_demo_off_plugin::load(QFileInfo fileinfo) { - + if(fileinfo.suffix().toLower() != "off") return 0; // Open file std::ifstream in(fileinfo.filePath().toUtf8()); if(!in) { diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_demo_off_to_nef_plugin.cpp b/Polyhedron/demo/Polyhedron/Polyhedron_demo_off_to_nef_plugin.cpp index 77874a6951e..4016bfffddd 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_demo_off_to_nef_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Polyhedron_demo_off_to_nef_plugin.cpp @@ -36,7 +36,7 @@ Polyhedron_demo_off_to_nef_plugin::load(QFileInfo fileinfo) { std::cerr << "Error!\n"; Scene_nef_polyhedron_item* item = new Scene_nef_polyhedron_item(); - if(!item->load(in)) + if(!item->load_from_off(in)) { delete item; return 0; diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_demo_orient_soup_plugin.cpp b/Polyhedron/demo/Polyhedron/Polyhedron_demo_orient_soup_plugin.cpp index eab5c9d82d7..555917c4ddc 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_demo_orient_soup_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Polyhedron_demo_orient_soup_plugin.cpp @@ -6,6 +6,7 @@ #include #include "Scene_polygon_soup.h" +#include "Scene_polyhedron_item.h" #include "Polyhedron_demo_plugin_interface.h" #include "Messages_interface.h" @@ -46,6 +47,7 @@ void Polyhedron_demo_orient_soup_plugin::init(QMainWindow* mainWindow, mw = mainWindow; messages = m; actionOrient = new QAction(tr("Orient polygon soup"), mainWindow); + actionOrient->setObjectName("actionOrient"); connect(actionOrient, SIGNAL(triggered()), this, SLOT(orient())); @@ -67,26 +69,41 @@ QList Polyhedron_demo_orient_soup_plugin::actions() const { void Polyhedron_demo_orient_soup_plugin::orient() { - const Scene_interface::Item_id index = scene->mainSelectionIndex(); - - Scene_polygon_soup* item = - qobject_cast(scene->item(index)); - - if(item) + Q_FOREACH(Scene_interface::Item_id index, scene->selectionIndices()) { -// qDebug() << tr("I have the item %1\n").arg(item->name()); - QApplication::setOverrideCursor(Qt::WaitCursor); - if(!item->orient()) - messages->warning(tr("The polygon soup \"%1\" is not orientable.") - .arg(item->name())); - // QMessageBox::information(mw, tr("Not orientable"), -// tr("The polygon soup \"%1\" is not orientable.") -// .arg(item->name())); + Scene_polygon_soup* item = + qobject_cast(scene->item(index)); - scene->itemChanged(item); - - QApplication::restoreOverrideCursor(); + if(item) + { + // qDebug() << tr("I have the item %1\n").arg(item->name()); + QApplication::setOverrideCursor(Qt::WaitCursor); + if(!item->orient()) { + messages->warning(tr("The polygon soup \"%1\" is not orientable.") + .arg(item->name())); + // QMessageBox::information(mw, tr("Not orientable"), + // tr("The polygon soup \"%1\" is not orientable.") + // .arg(item->name())); + scene->itemChanged(item); + } else { + + Scene_polyhedron_item* poly_item = new Scene_polyhedron_item(); + if(item->exportAsPolyhedron(poly_item->polyhedron())) { + poly_item->setName(item->name()); + poly_item->setColor(item->color()); + poly_item->setRenderingMode(item->renderingMode()); + poly_item->setVisible(item->visible()); + poly_item->changed(); + poly_item->setProperty("source filename", item->property("source filename")); + scene->replaceItem(index, poly_item); + delete item; + } else { + scene->itemChanged(item); + } + } + } } + QApplication::restoreOverrideCursor(); } void Polyhedron_demo_orient_soup_plugin::shuffle() @@ -96,9 +113,26 @@ void Polyhedron_demo_orient_soup_plugin::shuffle() Scene_polygon_soup* item = qobject_cast(scene->item(index)); - if(item) + if(item) { item->shuffle_orientations(); - scene->itemChanged(item); + scene->itemChanged(item); + } + else { + Scene_polyhedron_item* poly_item = + qobject_cast(scene->item(index)); + if(poly_item) { + item = new Scene_polygon_soup(); + item->setName(poly_item->name()); + item->setColor(poly_item->color()); + item->setRenderingMode(poly_item->renderingMode()); + item->setVisible(poly_item->visible()); + item->setProperty("source filename", poly_item->property("source filename")); + item->load(poly_item); + item->shuffle_orientations(); + scene->replaceItem(index, item); + delete poly_item; + } + } } void Polyhedron_demo_orient_soup_plugin::displayNonManifoldEdges() diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_demo_parameterization_plugin.cpp b/Polyhedron/demo/Polyhedron/Polyhedron_demo_parameterization_plugin.cpp index d1b0c5880b6..3291389b87f 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_demo_parameterization_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Polyhedron_demo_parameterization_plugin.cpp @@ -5,6 +5,7 @@ #include "Scene_polyhedron_item.h" #include "Scene_textured_polyhedron_item.h" #include "Textured_polyhedron_type.h" +#include "Polyhedron_type.h" #include diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_demo_pca_plugin.cpp b/Polyhedron/demo/Polyhedron/Polyhedron_demo_pca_plugin.cpp index ae758e747d6..3560a5ea981 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_demo_pca_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Polyhedron_demo_pca_plugin.cpp @@ -14,6 +14,16 @@ #include // output for plane fitting #include // output for line fitting +#include "Kernel_type.h" +typedef Kernel::Plane_3 Plane; +typedef Kernel::Iso_cuboid_3 Iso_cuboid; +typedef Kernel::Triangle_3 Triangle; +typedef Kernel::Line_3 Line; +typedef Kernel::Vector_3 Vector; +typedef Kernel::Point_3 Point; +typedef Kernel::FT FT; + + class Polyhedron_demo_pca_plugin : public QObject, public Polyhedron_demo_plugin_helper diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_demo_remeshing_plugin_cgal_code.cpp b/Polyhedron/demo/Polyhedron/Polyhedron_demo_remeshing_plugin_cgal_code.cpp index 3985513e9ea..a5aaa911898 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_demo_remeshing_plugin_cgal_code.cpp +++ b/Polyhedron/demo/Polyhedron/Polyhedron_demo_remeshing_plugin_cgal_code.cpp @@ -296,6 +296,8 @@ Scene_item* cgal_code_remesh(QWidget* parent, { // new scope for the initialization, so that the vector // polyhedron_points is destroyed as soon as the initialization is // finished + typedef Kernel::Point_3 Point; + std::vector polyhedron_points; polyhedron_points.reserve(pMesh->size_of_vertices()); std::copy(pMesh->points_begin(), pMesh->points_end(), diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_demo_self_intersection_plugin.cpp b/Polyhedron/demo/Polyhedron/Polyhedron_demo_self_intersection_plugin.cpp index cd35942c854..5df1f10acd2 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_demo_self_intersection_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Polyhedron_demo_self_intersection_plugin.cpp @@ -1,6 +1,7 @@ #include #include #include +#include "Kernel_type.h" #include "Polyhedron_type.h" #include "Scene_polyhedron_item.h" @@ -14,6 +15,8 @@ #include #include +typedef Kernel::Triangle_3 Triangle; + class Polyhedron_demo_self_intersection_plugin : public QObject, public Polyhedron_demo_plugin_helper diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_demo_triangulate_facets_plugin.cpp b/Polyhedron/demo/Polyhedron/Polyhedron_demo_triangulate_facets_plugin.cpp index f1198a7013b..ddf73011158 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_demo_triangulate_facets_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Polyhedron_demo_triangulate_facets_plugin.cpp @@ -6,125 +6,9 @@ #include "Polyhedron_demo_plugin_helper.h" #include "Scene_polyhedron_item.h" #include "Polyhedron_type.h" -#include - -#include -#include - -#include -#include -#include -#include -#include #include "CGAL/compute_normal.h" - -#include - -typedef Polyhedron::Halfedge_handle Halfedge_handle; - -typedef CGAL::Triangulation_2_filtered_projection_traits_3 Traits; - -typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; - -struct Face_info { - Halfedge_handle e[3]; - bool is_external; -}; - -typedef CGAL::Triangulation_face_base_with_info_2 Fb1; - -typedef CGAL::Constrained_triangulation_face_base_2 Fb; -typedef CGAL::Triangulation_data_structure_2 TDS; -typedef CGAL::No_intersection_tag Itag; -typedef CGAL::Constrained_Delaunay_triangulation_2 CDTbase; -typedef CGAL::Constrained_triangulation_plus_2 CDT; - -typedef Polyhedron::HalfedgeDS HDS; - -class Triangulate_modifier : public CGAL::Modifier_base { - CDT* cdt; - Polyhedron::Facet_handle fh; - -public: - Triangulate_modifier(CDT* cdt, - Polyhedron::Facet_handle fh) - : cdt(cdt), fh(fh) - { - } - - bool is_external(CDT::Face_handle fh) const { - return fh->info().is_external; - } - - void operator()(HDS& hds) { - CGAL::HalfedgeDS_decorator decorator(hds); - typedef Polyhedron::Halfedge Halfedge; - - decorator.make_hole(fh->halfedge()); - for(CDT::Finite_edges_iterator - eit = cdt->finite_edges_begin(), - end = cdt->finite_edges_end(); - eit != end; ++eit) - { - CDT::Face_handle fh = eit->first; - const int index = eit->second; - CDT::Face_handle opposite_fh = fh->neighbor(eit->second); - const int opposite_index = opposite_fh->index(fh); - const CDT::Vertex_handle va = fh->vertex(cdt-> cw(index)); - const CDT::Vertex_handle vb = fh->vertex(cdt->ccw(index)); - - if( ! (is_external(fh) && is_external(opposite_fh)) && - ! cdt->is_constrained(*eit) ) - { - // strictly internal edge - Halfedge_handle h = hds.edges_push_back(Halfedge(), - Halfedge()); - fh->info().e[index] = h; - opposite_fh->info().e[opposite_index] = h->opposite(); - - decorator.set_vertex(h, va->info()->vertex()); - decorator.set_vertex(h->opposite(), vb->info()->vertex()); - } - if( cdt->is_constrained(*eit) ) - { - if(!is_external(fh)) { - fh->info().e[index] = va->info(); - } - if(!is_external(opposite_fh)) { - opposite_fh->info().e[opposite_index] = vb->info(); - } - } - } - for(CDT::Finite_faces_iterator - fit = cdt->finite_faces_begin(), - end = cdt->finite_faces_end(); - fit != end; ++fit) - { - if(!is_external(fit)) - { - Halfedge_handle h0 = fit->info().e[0]; - Halfedge_handle h1 = fit->info().e[1]; - Halfedge_handle h2 = fit->info().e[2]; - CGAL_assertion( h0 != Halfedge_handle() ); - CGAL_assertion( h1 != Halfedge_handle() ); - CGAL_assertion( h2 != Halfedge_handle() ); - - typedef Halfedge::Base HBase; - h0->HBase::set_next(h1); - decorator.set_prev(h1, h0); - h1->HBase::set_next(h2); - decorator.set_prev(h2, h1); - h2->HBase::set_next(h0); - decorator.set_prev(h0, h2); - - decorator.fill_hole(h0); - } - } - } -}; +#include "CGAL/triangulate_polyhedron.h" class Polyhedron_demo_triangulate_facets_plugin : public QObject, @@ -159,7 +43,6 @@ public: public slots: void untriangulate() { - CGAL::set_error_behaviour(CGAL::ABORT); const Scene_interface::Item_id index = scene->mainSelectionIndex(); Scene_polyhedron_item* item = @@ -187,7 +70,7 @@ public slots: !eit_copy->vertex()->is_bivalent() && !eit_copy->opposite()->vertex()->is_bivalent()) { - Kernel::Vector_3 v1 = compute_facet_normal(*fh1); + Kernel::Vector_3 v1 = compute_facet_normal(*fh1); Kernel::Vector_3 v2 = compute_facet_normal(*fh2); if(v1 * v2 > 0.99) { std::cerr << "join\n"; @@ -206,103 +89,35 @@ public slots: } void triangulate() { - CGAL::set_error_behaviour(CGAL::ABORT); - const Scene_interface::Item_id index = scene->mainSelectionIndex(); - + Q_FOREACH(Scene_interface::Item_id index, scene->selectionIndices()) { + Scene_polyhedron_item* item = qobject_cast(scene->item(index)); if(item) { Polyhedron* pMesh = item->polyhedron(); - if(!pMesh) return; + if(!pMesh) continue; if(pMesh->is_pure_triangle()) { messages->warning(tr("The polyhedron \"%1\" is already triangulated.") .arg(item->name())); - return; + continue; } QApplication::setOverrideCursor(Qt::WaitCursor); - typedef Polyhedron::Facet Facet; - typedef Polyhedron::Facet_iterator Facet_iterator; - typedef Polyhedron::Facet_handle Facet_handle; + CGAL::triangulate_polyhedron(*pMesh); - // One need to store facet handles into a vector, because the list of - // facets of the polyhedron will be modified during the loop, and - // that invalidates the range [facets_begin(), facets_end()[. - std::vector facets; - facets.reserve(pMesh->size_of_facets()); - for(Facet_iterator - fit = pMesh->facets_begin(), - end = pMesh->facets_end(); - fit != end; ++fit) { - facets.push_back(fit); - } - - // Iterates on the vector of facet handles - for(std::vector::iterator - fit_it = facets.begin(), - end = facets.end(); - fit_it != end; ++fit_it) - { - Facet_handle fit = *fit_it; - Kernel::Vector_3 normal = compute_facet_normal(*fit); - - Traits cdt_traits(normal); - CDT cdt(cdt_traits); - - Facet::Halfedge_around_facet_circulator - he_circ = fit->facet_begin(), - he_circ_end(he_circ); - CDT::Vertex_handle previous, first; - do { - CDT::Vertex_handle vh = cdt.insert(he_circ->vertex()->point()); - if(first == 0) { - first = vh; - } - vh->info() = he_circ; - if(previous != 0 && previous != vh) { - cdt.insert_constraint(previous, vh); - } - previous = vh; - } while( ++he_circ != he_circ_end ); - cdt.insert_constraint(previous, first); - - // sets mark is_external - for(CDT::Finite_faces_iterator - fit = cdt.finite_faces_begin(), - end = cdt.finite_faces_end(); - fit != end; ++fit) - { - fit->info().is_external = false; - } - std::queue face_queue; - face_queue.push(cdt.infinite_vertex()->face()); - while(! face_queue.empty() ) { - CDT::Face_handle fh = face_queue.front(); - face_queue.pop(); - CGAL_assertion(cdt.is_infinite(fh)); - if(fh->info().is_external) continue; - std::cerr << (void*)(&*fh) << std::endl; - fh->info().is_external = true; - for(int i = 0; i <3; ++i) { - if(!cdt.is_constrained(std::make_pair(fh, i))) - { - face_queue.push(fh->neighbor(i)); - } - } - } - // then modify the polyhedron - Triangulate_modifier modifier(&cdt, fit); - pMesh->delegate(modifier); - } CGAL_assertion_code(pMesh->normalize_border()); CGAL_assertion(pMesh->is_valid(false, 3)); + scene->itemChanged(item); - // default cursor - QApplication::restoreOverrideCursor(); - } + + } // end of if(item) + + } // end of the loop on the selected items + // default cursor + QApplication::restoreOverrideCursor(); } private: diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_demo_trivial_plugin.cpp b/Polyhedron/demo/Polyhedron/Polyhedron_demo_trivial_plugin.cpp index 3f1912c073f..c81ca089e55 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_demo_trivial_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Polyhedron_demo_trivial_plugin.cpp @@ -125,7 +125,7 @@ QList Polyhedron_demo_trivial_plugin::actions() const { void Polyhedron_demo_trivial_plugin::bbox() { - for(size_t i = 0, end = scene->numberOfEntries(); + for(int i = 0, end = scene->numberOfEntries(); i < end; ++i) { if(qobject_cast(scene->item(i))) diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_type.h b/Polyhedron/demo/Polyhedron/Polyhedron_type.h index a1785386f9a..feaf36eda34 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_type.h +++ b/Polyhedron/demo/Polyhedron/Polyhedron_type.h @@ -3,27 +3,126 @@ // CGAL // kernel -#include - -typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; +#include "Kernel_type.h" // surface mesh #include +#include + +#include + +template +class Polyhedron_demo_vertex : + public CGAL::HalfedgeDS_vertex_base +{ +public: + typedef std::set Set_of_indices; + +private: + typedef CGAL::HalfedgeDS_vertex_base Pdv_base; + + Set_of_indices indices; +public: + int nb_of_feature_edges; + + bool is_corner() const { + return nb_of_feature_edges > 2; + } + + bool is_feature_vertex() const { + return nb_of_feature_edges != 0; + } + + void add_incident_patch(const Patch_id i) { + indices.insert(i); + } + + const Set_of_indices& + incident_patches_ids_set() const { + return indices; + } + + Polyhedron_demo_vertex() : Pdv_base(), nb_of_feature_edges(0) {} + Polyhedron_demo_vertex(const Point& p) : Pdv_base(p), nb_of_feature_edges(0) {} +}; + +template +class Polyhedron_demo_halfedge : + public CGAL::HalfedgeDS_halfedge_base +{ +private: + bool feature_edge; +public: + + Polyhedron_demo_halfedge() + : feature_edge(false) {}; + + bool is_feature_edge() const { + return feature_edge; + } + + void set_feature_edge(const bool b) { + feature_edge = b; + this->opposite()->feature_edge = b; + } +}; + +template +class Polyhedron_demo_face : + public CGAL::HalfedgeDS_face_base +{ +private: + Patch_id_ patch_id_; +public: + typedef Patch_id_ Patch_id; + + Polyhedron_demo_face() + : patch_id_(1) {} + + int patch_id() const { + return patch_id_; + } + + void set_patch_id(const int i) { + patch_id_ = i; + } +}; + +template +class Polyhedron_demo_items : public CGAL::Polyhedron_items_3 { +public: + // wrap vertex + template struct Vertex_wrapper + { + typedef typename Traits::Point_3 Point; + typedef Polyhedron_demo_vertex Vertex; + }; + + // wrap face + template struct Face_wrapper + { + typedef Polyhedron_demo_face Face; + }; + + // wrap halfedge + template struct Halfedge_wrapper + { + typedef Polyhedron_demo_halfedge Halfedge; + }; +}; #include "Polyhedron_type_fwd.h" -// simple geometric types -typedef Kernel::FT FT; -typedef Kernel::Line_3 Line; -typedef Kernel::Point_3 Point; -typedef Kernel::Plane_3 Plane; -typedef Kernel::Sphere_3 Sphere; -typedef Kernel::Vector_3 Vector; -typedef Kernel::Triangle_3 Triangle; -typedef Kernel::Iso_cuboid_3 Iso_cuboid; -typedef Kernel::Plane_3 Plane_3; - // surface mesh -typedef CGAL::Polyhedron_3 Polyhedron; +typedef CGAL::Polyhedron_3 > Polyhedron; #endif // POLYHEDRON_TYPE_H diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_type_fwd.h b/Polyhedron/demo/Polyhedron/Polyhedron_type_fwd.h index b950b1ed784..294e96bdf5b 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_type_fwd.h +++ b/Polyhedron/demo/Polyhedron/Polyhedron_type_fwd.h @@ -8,8 +8,16 @@ #include +template +class Polyhedron_demo_items; + namespace CGAL { + namespace Mesh_3 { + template + struct Robust_intersection_traits_3; + } + template < typename FT_ > struct Simple_cartesian; @@ -32,15 +40,27 @@ namespace CGAL { > class Polyhedron_3; +// changed since CGAL-3.8-Ic-8 +#if CGAL_VERSION_NR > 1030800008 + class Epick; +#endif } // end namespace CGAL // kernel - -typedef CGAL::Epick Kernel; +namespace polyhedron_type_fwd_h { +// changed since CGAL-3.8-Ic-8 +#if CGAL_VERSION_NR > 1030800008 + typedef CGAL::Epick K1; +#else + typedef CGAL::Filtered_kernel< CGAL::Simple_cartesian, true > K1; +#endif + typedef CGAL::Mesh_3::Robust_intersection_traits_3 Kernel; +} // surface mesh -typedef CGAL::Polyhedron_3, + // CGAL::Polyhedron_items_3, CGAL::HalfedgeDS_default, std::allocator > Polyhedron; diff --git a/Polyhedron/demo/Polyhedron/Scene.cpp b/Polyhedron/demo/Polyhedron/Scene.cpp index a53badda303..04a501d3f7d 100644 --- a/Polyhedron/demo/Polyhedron/Scene.cpp +++ b/Polyhedron/demo/Polyhedron/Scene.cpp @@ -2,6 +2,8 @@ #include "Scene.h" #include "Scene_item.h" +#include +#include #include #include #include @@ -10,11 +12,12 @@ #include #include #include +#include namespace { void CGALglcolor(QColor c) { - ::glColor4f(c.red()/255.0, c.green()/255.0, c.blue()/255.0, c.alpha()/255.0); + ::glColor4d(c.red()/255.0, c.green()/255.0, c.blue()/255.0, c.alpha()/255.0); } } @@ -24,29 +27,54 @@ Scene::Scene(QObject* parent) item_A(-1), item_B(-1) { + connect(this, SIGNAL(selectionRay(double, double, double, + double, double, double)), + this, SLOT(setSelectionRay(double, double, double, + double, double, double))); } Scene::Item_id Scene::addItem(Scene_item* item) { - entries.push_back(item); + m_entries.push_back(item); + connect(item, SIGNAL(itemChanged()), + this, SLOT(itemChanged())); emit updated_bbox(); emit updated(); QAbstractListModel::reset(); - return entries.size() - 1; + Item_id id = m_entries.size() - 1; + emit newItem(id); + return id; +} + +Scene_item* +Scene::replaceItem(Scene::Item_id index, Scene_item* item) +{ + if(index < 0 || index >= m_entries.size()) + return 0; + + connect(item, SIGNAL(itemChanged()), + this, SLOT(itemChanged())); + std::swap(m_entries[index], item); + + emit updated_bbox(); + emit updated(); + itemChanged(index); + QAbstractListModel::reset(); + return item; } int Scene::erase(int index) { - if(index < 0 || index >= entries.size()) + if(index < 0 || index >= m_entries.size()) return -1; - Scene_item* item = entries[index]; + Scene_item* item = m_entries[index]; emit itemAboutToBeDestroyed(item); delete item; - entries.removeAt(index); + m_entries.removeAt(index); selected_item = -1; emit updated(); @@ -54,30 +82,62 @@ Scene::erase(int index) if(--index >= 0) return index; - if(!entries.isEmpty()) + if(!m_entries.isEmpty()) + return 0; + return -1; +} + +int +Scene::erase(QList indices) +{ + QList to_be_removed; + + int max_index = -1; + Q_FOREACH(int index, indices) { + if(index < 0 || index >= m_entries.size()) + continue; + max_index = (std::max)(max_index, index); + Scene_item* item = m_entries[index]; + to_be_removed.push_back(item); + emit itemAboutToBeDestroyed(item); + delete item; + } + + Q_FOREACH(Scene_item* item, to_be_removed) { + m_entries.removeAll(item); + } + + selected_item = -1; + emit updated(); + QAbstractListModel::reset(); + + int index = max_index + 1 - indices.size(); + if(index >= 0) + return index; + if(!m_entries.isEmpty()) return 0; return -1; } Scene::~Scene() { - Q_FOREACH(Scene_item* item_ptr, entries) + Q_FOREACH(Scene_item* item_ptr, m_entries) { delete item_ptr; } - entries.clear(); + m_entries.clear(); } Scene_item* Scene::item(Item_id index) const { - return entries.value(index); // QList::value checks bounds + return m_entries.value(index); // QList::value checks bounds } -size_t +int Scene::numberOfEntries() const { - return entries.size(); + return m_entries.size(); } // Duplicate a scene item. @@ -85,17 +145,17 @@ Scene::numberOfEntries() const Scene::Item_id Scene::duplicate(Item_id index) { - if(index < 0 || index >= entries.size()) + if(index < 0 || index >= m_entries.size()) return -1; - const Scene_item* item = entries[index]; + const Scene_item* item = m_entries[index]; Scene_item* new_item = item->clone(); if(new_item) { new_item->setName(tr("%1 (copy)").arg(item->name())); new_item->setColor(item->color()); new_item->setVisible(item->visible()); addItem(new_item); - return entries.size() - 1; + return m_entries.size() - 1; } else return -1; @@ -125,12 +185,12 @@ void Scene::draw_aux(bool with_names) { // Flat/Gouraud OpenGL drawing - for(int index = 0; index < entries.size(); ++index) + for(int index = 0; index < m_entries.size(); ++index) { if(with_names) { ::glPushName(index); } - Scene_item& item = *entries[index]; + Scene_item& item = *m_entries[index]; if(item.visible()) { if(item.renderingMode() == Flat || item.renderingMode() == FlatPlusEdges || item.renderingMode() == Gouraud) @@ -157,12 +217,12 @@ Scene::draw_aux(bool with_names) } // Wireframe OpenGL drawing - for(int index = 0; index < entries.size(); ++index) + for(int index = 0; index < m_entries.size(); ++index) { if(with_names) { ::glPushName(index); } - Scene_item& item = *entries[index]; + Scene_item& item = *m_entries[index]; if(item.visible()) { if(item.renderingMode() == FlatPlusEdges || item.renderingMode() == Wireframe) @@ -185,12 +245,12 @@ Scene::draw_aux(bool with_names) } // Points OpenGL drawing - for(int index = 0; index < entries.size(); ++index) + for(int index = 0; index < m_entries.size(); ++index) { if(with_names) { ::glPushName(index); } - Scene_item& item = *entries[index]; + Scene_item& item = *m_entries[index]; if(item.visible()) { if(item.renderingMode() == Points) @@ -222,7 +282,7 @@ Scene::rowCount(const QModelIndex & parent) const if (parent.isValid()) return 0; else - return entries.size(); + return m_entries.size(); } int @@ -240,33 +300,33 @@ Scene::data(const QModelIndex &index, int role) const if (!index.isValid()) return QVariant(); - if(index.row() < 0 || index.row() >= entries.size()) + if(index.row() < 0 || index.row() >= m_entries.size()) return QVariant(); if(role == ::Qt::ToolTipRole) { - return entries[index.row()]->toolTip(); + return m_entries[index.row()]->toolTip(); } switch(index.column()) { case ColorColumn: if(role == ::Qt::DisplayRole || role == ::Qt::EditRole) - return entries.value(index.row())->color(); + return m_entries.value(index.row())->color(); else if(role == ::Qt::DecorationRole) - return entries.value(index.row())->color(); + return m_entries.value(index.row())->color(); break; case NameColumn: if(role == ::Qt::DisplayRole || role == ::Qt::EditRole) - return entries.value(index.row())->name(); + return m_entries.value(index.row())->name(); if(role == ::Qt::FontRole) - return entries.value(index.row())->font(); + return m_entries.value(index.row())->font(); break; case RenderingModeColumn: if(role == ::Qt::DisplayRole) { - return entries.value(index.row())->renderingModeName(); + return m_entries.value(index.row())->renderingModeName(); } else if(role == ::Qt::EditRole) { - return static_cast(entries.value(index.row())->renderingMode()); + return static_cast(m_entries.value(index.row())->renderingMode()); } else if(role == ::Qt::TextAlignmentRole) { return ::Qt::AlignCenter; @@ -285,7 +345,7 @@ Scene::data(const QModelIndex &index, int role) const break; case VisibleColumn: if(role == ::Qt::DisplayRole || role == ::Qt::EditRole) - return entries.value(index.row())->visible(); + return m_entries.value(index.row())->visible(); break; default: return QVariant(); @@ -350,10 +410,10 @@ Scene::setData(const QModelIndex &index, if( role != ::Qt::EditRole || !index.isValid() ) return false; - if(index.row() < 0 || index.row() >= entries.size()) + if(index.row() < 0 || index.row() >= m_entries.size()) return false; - Scene_item* item = entries[index.row()]; + Scene_item* item = m_entries[index.row()]; if(!item) return false; switch(index.column()) { @@ -397,6 +457,10 @@ Scene::Item_id Scene::mainSelectionIndex() const { return selected_item; } +QList Scene::selectionIndices() const { + return selected_items_list; +} + int Scene::selectionAindex() const { return item_A; } @@ -411,12 +475,25 @@ QItemSelection Scene::createSelection(int i) QAbstractItemModel::createIndex(i, LastColumn)); } +QItemSelection Scene::createSelectionAll() +{ + return QItemSelection(QAbstractItemModel::createIndex(0, 0), + QAbstractItemModel::createIndex(m_entries.size() - 1 , LastColumn)); +} + +void Scene::itemChanged() +{ + Scene_item* item = qobject_cast(sender()); + if(item) + itemChanged(item); +} + void Scene::itemChanged(Item_id i) { - if(i < 0 || i >= entries.size()) + if(i < 0 || i >= m_entries.size()) return; - entries[i]->changed(); + m_entries[i]->changed(); emit dataChanged(QAbstractItemModel::createIndex(i, 0), QAbstractItemModel::createIndex(i, LastColumn)); } @@ -425,7 +502,7 @@ void Scene::itemChanged(Scene_item* item) { item->changed(); emit dataChanged(QAbstractItemModel::createIndex(0, 0), - QAbstractItemModel::createIndex(entries.size() - 1, LastColumn)); + QAbstractItemModel::createIndex(m_entries.size() - 1, LastColumn)); } bool SceneDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, @@ -451,13 +528,16 @@ bool SceneDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, break; case Scene::ColorColumn: if (event->type() == QEvent::MouseButtonPress) { - QColor color = - QColorDialog::getColor(model->data(index).value(), - 0/*, - tr("Select color"), - QColorDialog::ShowAlphaChannel*/); - if (color.isValid()) { - model->setData(index, color ); + QMouseEvent *mouseEvent = static_cast(event); + if(mouseEvent->button() == ::Qt::LeftButton) { + QColor color = + QColorDialog::getColor(model->data(index).value(), + 0/*, + tr("Select color"), + QColorDialog::ShowAlphaChannel*/); + if (color.isValid()) { + model->setData(index, color ); + } } } else if(event->type() == QEvent::MouseButtonDblClick) { @@ -467,10 +547,13 @@ bool SceneDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, break; case Scene::RenderingModeColumn: if (event->type() == QEvent::MouseButtonPress) { - // Switch rendering mode - /*RenderingMode*/int rendering_mode = model->data(index, ::Qt::EditRole).toInt(); - rendering_mode = (rendering_mode+1) % NumberOfRenderingMode; - model->setData(index, rendering_mode); + QMouseEvent *mouseEvent = static_cast(event); + if(mouseEvent->button() == ::Qt::LeftButton) { + // Switch rendering mode + /*RenderingMode*/int rendering_mode = model->data(index, ::Qt::EditRole).toInt(); + rendering_mode = (rendering_mode+1) % NumberOfRenderingMode; + model->setData(index, rendering_mode); + } } else if(event->type() == QEvent::MouseButtonDblClick) { return true; // block double-click @@ -538,13 +621,29 @@ void SceneDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, void Scene::setItemVisible(int index, bool b) { - if( index < 0 || index >= entries.size() ) + if( index < 0 || index >= m_entries.size() ) return; - entries[index]->setVisible(b); + m_entries[index]->setVisible(b); emit dataChanged(QAbstractItemModel::createIndex(index, VisibleColumn), QAbstractItemModel::createIndex(index, VisibleColumn)); } +void Scene::setSelectionRay(double orig_x, + double orig_y, + double orig_z, + double dir_x, + double dir_y, + double dir_z) +{ + Scene_item* item = this->item(selected_item); + if(item) item->select(orig_x, + orig_y, + orig_z, + dir_x, + dir_y, + dir_z); +} + void Scene::setItemA(int i) { item_A = i; @@ -553,7 +652,7 @@ void Scene::setItemA(int i) item_B = -1; } emit dataChanged(QAbstractItemModel::createIndex(0, ABColumn), - QAbstractItemModel::createIndex(entries.size()-1, ABColumn)); + QAbstractItemModel::createIndex(m_entries.size()-1, ABColumn)); } void Scene::setItemB(int i) @@ -565,17 +664,17 @@ void Scene::setItemB(int i) } emit updated(); emit dataChanged(QAbstractItemModel::createIndex(0, ABColumn), - QAbstractItemModel::createIndex(entries.size()-1, ABColumn)); + QAbstractItemModel::createIndex(m_entries.size()-1, ABColumn)); } Scene::Bbox Scene::bbox() const { - if(entries.empty()) + if(m_entries.empty()) return Bbox(); bool bbox_initialized = false; Bbox bbox; - Q_FOREACH(Scene_item* item, entries) + Q_FOREACH(Scene_item* item, m_entries) { if(item->isFinite() && !item->isEmpty()) { if(bbox_initialized) { @@ -589,3 +688,45 @@ Scene::Bbox Scene::bbox() const } return bbox; } + +#include "Scene_find_items.h" + +namespace scene { namespace details { + +Q_DECL_EXPORT +Scene_item* +findItem(const Scene_interface* scene_interface, + const QMetaObject& metaobj, + QString name, Scene_item_name_fn_ptr fn) { + const Scene* scene = dynamic_cast(scene_interface); + if(!scene) return 0; + Q_FOREACH(Scene_item* item, scene->entries()) { + Scene_item* ptr = qobject_cast(metaobj.cast(item)); + if(ptr && ((ptr->*fn)() == name)) return ptr; + } + return 0; +} + +Q_DECL_EXPORT +QList +findItems(const Scene_interface* scene_interface, + const QMetaObject&, + QString name, Scene_item_name_fn_ptr fn) +{ + const Scene* scene = dynamic_cast(scene_interface); + QList list; + if(!scene) return list; + + Q_FOREACH(Scene_item* item, scene->entries()) { + Scene_item* ptr = qobject_cast(item); + if(ptr && ((ptr->*fn)() == name)) { + list << ptr; + } + } + return list; +} + +} // end namespace details +} // end namespace scene + +#include "Scene.moc" diff --git a/Polyhedron/demo/Polyhedron/Scene.h b/Polyhedron/demo/Polyhedron/Scene.h index 3c08c03ccb5..a00a012eea1 100644 --- a/Polyhedron/demo/Polyhedron/Scene.h +++ b/Polyhedron/demo/Polyhedron/Scene.h @@ -1,6 +1,7 @@ #ifndef SCENE_H #define SCENE_H #include "config.h" +#include "Scene_config.h" #include "Scene_interface.h" #include "Scene_draw_interface.h" @@ -21,10 +22,11 @@ class QEvent; class QMouseEvent; -class Scene : +class SCENE_EXPORT Scene : public QAbstractListModel, public Scene_interface, public Scene_draw_interface { Q_OBJECT + Q_PROPERTY(int numberOfEntries READ numberOfEntries) friend class SceneDelegate; @@ -40,19 +42,24 @@ public: Scene(QObject* parent); ~Scene(); - Item_id addItem(Scene_item* item); + int addItem(Scene_item* item); + Scene_item* replaceItem(int index, Scene_item* item); - int erase(int); // Returns the index of the polyhedra just before the - // one that is erased, or just after. Returns -1 if - // the list is empty. + Q_INVOKABLE int erase(int); + int erase(QList); + // Returns the index of the polyhedra just before the + // one that is erased, or just after. Returns -1 if + // the list is empty. // Duplicate a scene item. Return the ID of the new item (-1 on error). - Item_id duplicate(Item_id index); + int duplicate(int index); // Accessors (getters) - size_t numberOfEntries() const; - Scene_item* item(Item_id) const ; - Item_id mainSelectionIndex() const; + int numberOfEntries() const; + const QList& entries() const { return m_entries; } + Q_INVOKABLE Scene_item* item(int) const ; + int mainSelectionIndex() const; + QList selectionIndices() const; int selectionAindex() const; int selectionBindex() const; @@ -83,38 +90,51 @@ public: // auxiliary public function for QMainWindow QItemSelection createSelection(int i); + QItemSelection createSelectionAll(); public slots: // Notify the scene that an item was modified - void itemChanged(Item_id i); + void itemChanged(); // slots called by items themself + void itemChanged(int i); void itemChanged(Scene_item*); - void setSelectedItem(Item_id i ) + void setSelectedItem(int i ) { selected_item = i; }; + void setSelectedItemsList(QList l ) + { + selected_items_list = l; + }; + // Accessors (setters) void setItemVisible(int, bool b); void setItemA(int i); void setItemB(int i); signals: + void newItem(int); void updated_bbox(); void updated(); void itemAboutToBeDestroyed(Scene_item*); + void selectionRay(double, double, double, double, double, double); + +private slots: + void setSelectionRay(double, double, double, double, double, double); private: void draw_aux(bool with_names); typedef QList Entries; - Entries entries; + Entries m_entries; int selected_item; + QList selected_items_list; int item_A; int item_B; }; // end class Scene -class SceneDelegate : public QItemDelegate +class SCENE_EXPORT SceneDelegate : public QItemDelegate { public: SceneDelegate(QObject * parent = 0) diff --git a/Polyhedron/demo/Polyhedron/Scene_config.h b/Polyhedron/demo/Polyhedron/Scene_config.h new file mode 100644 index 00000000000..6c532250add --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Scene_config.h @@ -0,0 +1,16 @@ +#ifndef SCENE_CONFIG_H +#define SCENE_CONFIG_H + +#include + +#ifdef demo_framework_EXPORTS +# define scene_EXPORTS +#endif + +#ifdef scene_EXPORTS +# define SCENE_EXPORT Q_DECL_EXPORT +#else +# define SCENE_EXPORT Q_DECL_IMPORT +#endif + +#endif // SCENE_CONFIG_H diff --git a/Polyhedron/demo/Polyhedron/Scene_find_items.h b/Polyhedron/demo/Polyhedron/Scene_find_items.h new file mode 100644 index 00000000000..00372aca9fb --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Scene_find_items.h @@ -0,0 +1,121 @@ +#ifndef SCENE_FIND_ITEMS +#define SCENE_FIND_ITEMS + +#include +#include +#include "Scene_item.h" // required, to have &Scene_item::name +#include "Scene_config.h" + +class Scene_interface; + +namespace scene { +namespace details { + +typedef QString (Scene_item ::*Scene_item_name_fn_ptr)() const; + +// Declaration only (defined in Scene.cpp) +SCENE_EXPORT +Scene_item* +findItem(const Scene_interface* scene_interface, + const QMetaObject& metaobj, + QString name, Scene_item_name_fn_ptr fn); + +// Declaration only (defined in Scene.cpp) +SCENE_EXPORT +QList +findItems(const Scene_interface* scene_interface, + const QMetaObject& metaobj, + QString name, Scene_item_name_fn_ptr fn); // fwd declaration + +template +T findItem(const Scene_interface* scene, QString name, + Scene_item_name_fn_ptr fn) +{ + return + static_cast(findItem(scene, + reinterpret_cast(0)->staticMetaObject, + name, fn)); +} + +template +QList findItems(const Scene_interface* scene, QString name, + Scene_item_name_fn_ptr fn) +{ + QList void_list = + findItems(scene, reinterpret_cast(0)->staticMetaObject, + name, fn); + QList list; + Q_FOREACH(Scene_item* ptr, void_list) { + list << qobject_cast(ptr); + } + return list; +} + +} // end namespace details + +// Searches + +/** Search the first item that can be cast to T (T must be a pointer + type), and called "name". If "name" is omitted, all names are + accepted. +*/ +template +T findItem(const Scene_interface* scene, + QString item_name = QString()) +{ return details::findItem(scene, item_name, &Scene_item::name); } + +/** Returns all items that can be cast to T (T must be a pointer + type), and called "name". If "name" is omitted, all names are + accepted. +*/ +template +QList findItems(const Scene_interface* scene, + QString item_name = QString()) +{ return details::findItems(scene, item_name, &Scene_item::name); } + +/** Search the first item that can be cast to T (T must be a pointer + type), and that has objectName() equal to "name". If "name" is + omitted, all names are accepted. +*/ +template +T findItemByObjectName(const Scene_interface* scene, + QString obj_name = QString()) +{ return details::findItem(scene, obj_name, &QObject::objectName); } + +/** Returns all items that can be cast to T (T must be a pointer type), + and have objectName() equal to "name". If "name" is omitted, all + names are accepted. +*/ +template +QList findItemsByObjectName(const Scene_interface* scene, + QString obj_name = QString()) +{ return details::findItems(scene, obj_name, &QObject::objectName); } + + +// template +// T scene_findItem(const Scene* scene, QString name, Scene_item_name_fn_ptr fn) { +// return +// static_cast(scene_findItem(scene, name, fn, +// reinterpret_cast(0)->staticMetaObject())); +// } + +// template +// QList +// scene_findItems(const Scene* scene, QString name, Scene_item_name_fn_ptr fn) { +// QList void_list = +// scene_findItems(scene, name, fn, +// reinterpret_cast(0)->staticMetaObject()); +// QList list; +// Q_FOREACH(void* ptr, void_list) { +// list << static_cast(ptr); +// } +// return list; +// } + +// } // end scene namespace + +} // end namespace scene + + + +#endif diff --git a/Polyhedron/demo/Polyhedron/Scene_interface.h b/Polyhedron/demo/Polyhedron/Scene_interface.h index 6c3b85c26d2..52e8be1bb50 100644 --- a/Polyhedron/demo/Polyhedron/Scene_interface.h +++ b/Polyhedron/demo/Polyhedron/Scene_interface.h @@ -3,6 +3,7 @@ #include #include +#include #include class Scene_item; @@ -50,6 +51,7 @@ public: virtual ~Scene_interface() {}; virtual Item_id addItem(Scene_item* item) = 0; + virtual Scene_item* replaceItem(Item_id, Scene_item*) = 0; virtual Item_id erase(Item_id) = 0; // Returns the index of the item just before the one that is erased, @@ -61,9 +63,10 @@ public: // clonable), returns -1. // Accessors (getters) - virtual size_t numberOfEntries() const = 0; + virtual int numberOfEntries() const = 0; virtual Scene_item* item(Item_id) const = 0; virtual Item_id mainSelectionIndex() const = 0; + virtual QList selectionIndices() const = 0; virtual Item_id selectionAindex() const = 0; virtual Item_id selectionBindex() const = 0; @@ -75,6 +78,9 @@ public: // Notify the scene that an item was modified virtual void itemChanged(Item_id i) = 0; virtual void itemChanged(Scene_item*) = 0; + + // Select an item + virtual void setSelectedItem(Item_id) = 0; }; // end interface Scene_interface diff --git a/Polyhedron/demo/Polyhedron/Scene_item.cpp b/Polyhedron/demo/Polyhedron/Scene_item.cpp index 8e8e7b2a9ad..7a4aedde781 100644 --- a/Polyhedron/demo/Polyhedron/Scene_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_item.cpp @@ -1,34 +1,104 @@ #include "Scene_item.h" +#include "Scene_interface.h" +#include const QColor Scene_item::defaultColor = QColor(100, 100, 255); -Scene_item::~Scene_item() {} +Scene_item::~Scene_item() { + delete defaultContextMenu; +} void Scene_item::itemAboutToBeDestroyed(Scene_item* item) { if(this == item) emit aboutToBeDestroyed(); } + +QString modeName(RenderingMode mode) { + switch(mode) + { + case Points: + return QObject::tr("points"); + case Wireframe: + return QObject::tr("wire"); + case Flat: + return QObject::tr("flat"); + case FlatPlusEdges: + return QObject::tr("flat+edges"); + case Gouraud: + return QObject::tr("Gouraud"); + default: + Q_ASSERT(false); + return QObject::tr("unknown"); + } +} + +const char* slotName(RenderingMode mode) { + switch(mode) + { + case Points: + return SLOT(setPointsMode()); + case Wireframe: + return SLOT(setWireframeMode()); + case Flat: + return SLOT(setFlatMode()); + case FlatPlusEdges: + return SLOT(setFlatPlusEdgesMode()); + case Gouraud: + return SLOT(setGouraudMode()); + default: + Q_ASSERT(false); + return ""; + } +} + // Rendering mode as a human readable string QString Scene_item::renderingModeName() const { - switch(renderingMode()) - { - case Points: - return tr("points"); - case Wireframe: - return tr("wire"); - case Flat: - return tr("flat"); - case FlatPlusEdges: - return tr("flat+edges"); - case Gouraud: - return tr("Gouraud"); - default: - Q_ASSERT(false); - return tr("unknown"); - } + return modeName(renderingMode()); } +QMenu* Scene_item::contextMenu() +{ + if(defaultContextMenu) { + defaultContextMenu->setTitle(name()); + return defaultContextMenu; + } + + defaultContextMenu = new QMenu(name()); + // defaultContextMenu->addAction(name()); + // defaultContextMenu->addSeparator(); + // QMenu* modeMenu = new QMenu(QObject::tr("Rendering mode"), + // defaultContextMenu); + for(unsigned int mode = 0; mode < NumberOfRenderingMode; + ++mode) + { + if(!supportsRenderingMode(RenderingMode(mode))) continue; + QString mName = modeName(RenderingMode(mode)); + QAction* action = + defaultContextMenu->addAction(tr("Set %1 mode") + .arg(mName), + this, + slotName(RenderingMode(mode))); + QObject::connect(action, SIGNAL(triggered()), + this, SIGNAL(itemChanged())); + } + // defaultContextMenu->addAction(modeMenu->menuAction()); + return defaultContextMenu; +} + +void Scene_item::changed() { + // emit itemChanged(); +} + +void Scene_item::select(double /*orig_x*/, + double /*orig_y*/, + double /*orig_z*/, + double /*dir_x*/, + double /*dir_y*/, + double /*dir_z*/) +{ +} + #include "Scene_item.moc" diff --git a/Polyhedron/demo/Polyhedron/Scene_item.h b/Polyhedron/demo/Polyhedron/Scene_item.h index 63c9ded36d9..0463b4e3978 100644 --- a/Polyhedron/demo/Polyhedron/Scene_item.h +++ b/Polyhedron/demo/Polyhedron/Scene_item.h @@ -4,12 +4,15 @@ #include "Scene_item_config.h" #include "Scene_interface.h" #include +#include #include namespace qglviewer { class ManipulatedFrame; } +class QMenu; + // This class represents an object in the OpenGL scene class SCENE_ITEM_EXPORT Scene_item : public QObject { Q_OBJECT @@ -28,7 +31,8 @@ public: : name_("unamed"), color_(defaultColor), visible_(true), - rendering_mode(FlatPlusEdges) + rendering_mode(FlatPlusEdges), + defaultContextMenu(0) {}; virtual ~Scene_item(); virtual Scene_item* clone() const = 0; @@ -44,6 +48,7 @@ public: // Functions for displaying meta-data of the item virtual QString toolTip() const = 0; + virtual QPixmap graphicalToolTip() const { return QPixmap(); } virtual QFont font() const { return QFont(); } // Functions that help the Scene to compute its bbox @@ -60,25 +65,63 @@ public: virtual QString name() const { return name_; } virtual bool visible() const { return visible_; } virtual RenderingMode renderingMode() const { return rendering_mode; } - virtual QString renderingModeName() const; // Rendering mode as a human readable string + virtual QString renderingModeName() const; // Rendering mode as a human + // readable string + + // Context menu + virtual QMenu* contextMenu(); public slots: // Call that once you have finished changing something in the item // (either the properties or internal data) - virtual void changed() {} + virtual void changed(); // Setters for the four basic properties virtual void setColor(QColor c) { color_ = c; } + void setRbgColor(int r, int g, int b) { setColor(QColor(r, g, b)); } virtual void setName(QString n) { name_ = n; } virtual void setVisible(bool b) { visible_ = b; } virtual void setRenderingMode(RenderingMode m) { if (supportsRenderingMode(m)) rendering_mode = m; } + void setPointsMode() { + setRenderingMode(Points); + } + + void setWireframeMode() { + setRenderingMode(Wireframe); + } + void setWireframe() { + setRenderingMode(Wireframe); + } + + void setFlat() { + setRenderingMode(Flat); + } + void setFlatMode() { + setRenderingMode(Flat); + } + + void setFlatPlusEdgesMode() { + setRenderingMode(FlatPlusEdges); + } + + void setGouraudMode() { + setRenderingMode(Gouraud); + } virtual void itemAboutToBeDestroyed(Scene_item*); + virtual void select(double orig_x, + double orig_y, + double orig_z, + double dir_x, + double dir_y, + double dir_z); + signals: + void itemChanged(); void aboutToBeDestroyed(); protected: @@ -87,7 +130,12 @@ protected: QColor color_; bool visible_; RenderingMode rendering_mode; + QMenu* defaultContextMenu; }; // end class Scene_item + +#include +Q_DECLARE_METATYPE(Scene_item*) + #endif // SCENE_ITEM_H diff --git a/Polyhedron/demo/Polyhedron/Scene_item_config.h b/Polyhedron/demo/Polyhedron/Scene_item_config.h index ac71781315e..08c864bdce5 100644 --- a/Polyhedron/demo/Polyhedron/Scene_item_config.h +++ b/Polyhedron/demo/Polyhedron/Scene_item_config.h @@ -3,6 +3,10 @@ #include +#ifdef demo_framework_EXPORTS +# define scene_item_EXPORTS +#endif + #ifdef scene_item_EXPORTS # define SCENE_ITEM_EXPORT Q_DECL_EXPORT #else diff --git a/Polyhedron/demo/Polyhedron/Scene_item_with_display_list.cpp b/Polyhedron/demo/Polyhedron/Scene_item_with_display_list.cpp index 07be9511902..f77c1574962 100644 --- a/Polyhedron/demo/Polyhedron/Scene_item_with_display_list.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_item_with_display_list.cpp @@ -69,4 +69,5 @@ void Scene_item_with_display_list::changed() for(int i = 0; i < NB_OF_DISPLAY_LISTS; ++i) { display_list_built[i] = false; } + Scene_item::changed(); } diff --git a/Polyhedron/demo/Polyhedron/Scene_nef_polyhedron_item.cpp b/Polyhedron/demo/Polyhedron/Scene_nef_polyhedron_item.cpp index 83fc94f3d77..16473326d78 100644 --- a/Polyhedron/demo/Polyhedron/Scene_nef_polyhedron_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_nef_polyhedron_item.cpp @@ -5,6 +5,7 @@ #include // #include #include +#include #include #include @@ -49,7 +50,7 @@ Scene_nef_polyhedron_item::clone() const { } bool -Scene_nef_polyhedron_item::load(std::istream& in) +Scene_nef_polyhedron_item::load_from_off(std::istream& in) { // const std::size_t discarded = CGAL::OFF_to_nef_3(in, *nef_poly); // return discarded != 0; @@ -71,6 +72,20 @@ Scene_nef_polyhedron_item::font() const { return font; } +bool +Scene_nef_polyhedron_item::load(std::istream& in) +{ + in >> *nef_poly; + return in; +} + +bool +Scene_nef_polyhedron_item::save(std::ostream& in) const +{ + in << *nef_poly; + return in; +} + QString Scene_nef_polyhedron_item::toolTip() const { diff --git a/Polyhedron/demo/Polyhedron/Scene_nef_polyhedron_item.h b/Polyhedron/demo/Polyhedron/Scene_nef_polyhedron_item.h index 974edfcf202..4e837aa9f8b 100644 --- a/Polyhedron/demo/Polyhedron/Scene_nef_polyhedron_item.h +++ b/Polyhedron/demo/Polyhedron/Scene_nef_polyhedron_item.h @@ -20,7 +20,9 @@ public: ~Scene_nef_polyhedron_item(); Scene_nef_polyhedron_item* clone() const; + bool load_from_off(std::istream& in); bool load(std::istream& in); + bool save(std::ostream& in) const; QFont font() const; QString toolTip() const; diff --git a/Polyhedron/demo/Polyhedron/Scene_plane_item.h b/Polyhedron/demo/Polyhedron/Scene_plane_item.h index 3f94f9db5ac..7d80c1c7ad3 100644 --- a/Polyhedron/demo/Polyhedron/Scene_plane_item.h +++ b/Polyhedron/demo/Polyhedron/Scene_plane_item.h @@ -12,8 +12,8 @@ #include #include -typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; -typedef Kernel::Plane_3 Plane_3; +typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel_epic; +typedef Kernel_epic::Plane_3 Plane_3; class SCENE_BASIC_OBJECTS_EXPORT Scene_plane_item : public Scene_item diff --git a/Polyhedron/demo/Polyhedron/Scene_polygon_soup.cpp b/Polyhedron/demo/Polyhedron/Scene_polygon_soup.cpp index 6f18f295557..f33e6dece1e 100644 --- a/Polyhedron/demo/Polyhedron/Scene_polygon_soup.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_polygon_soup.cpp @@ -1,5 +1,8 @@ #include "Scene_polygon_soup.h" +#include "Scene_polyhedron_item.h" #include +#include "Polyhedron_type.h" +#include #include #include @@ -12,11 +15,13 @@ #include #include +#include -typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; typedef Kernel::Point_3 Point_3; -struct Polygon_soup { +struct Polygon_soup : + public CGAL::Modifier_base +{ typedef std::vector Points; typedef std::vector Polygon_3; typedef std::map, std::set > Edges_map; @@ -86,8 +91,51 @@ struct Polygon_soup { void inverse_orientation(const std::size_t index) { std::reverse(polygons[index].begin(), polygons[index].end()); } + + void operator()(Polyhedron::HalfedgeDS& out_hds); }; +struct Polyhedron_to_polygon_soup_writer { + Polygon_soup* soup; + Polygon_soup::Polygon_3 polygon; + + Polyhedron_to_polygon_soup_writer(Polygon_soup* soup) : soup(soup), polygon() { + } + + void write_header( std::ostream&, + std::size_t vertices, + std::size_t halfedges, + std::size_t facets, + bool normals = false ) { + soup->clear(); + } + + void write_footer() { + } + + void write_vertex( const double& x, const double& y, const double& z) { + soup->points.push_back(Point_3(x, y, z)); + } + + void write_normal( const double& x, const double& y, const double& z) { + } + + void write_facet_header() { + } + + void write_facet_begin( std::size_t no) { + polygon.clear(); + polygon.reserve(no); + } + void write_facet_vertex_index( std::size_t index) { + polygon.push_back(index); + } + void write_facet_end() { + soup->polygons.push_back(polygon); + polygon.clear(); + } +}; // end struct Polyhedron_to_soup_writer + Scene_polygon_soup::Scene_polygon_soup() : Scene_item_with_display_list(), soup(0), @@ -111,13 +159,18 @@ Scene_polygon_soup::clone() const { bool Scene_polygon_soup::load(std::istream& in) { +#if CGAL_VERSION_NR >= 1030700091 + typedef std::size_t indices_t; +#else + typedef CGAL::Integer32 indices_t; +#endif if(!soup) soup = new Polygon_soup; CGAL::File_scanner_OFF scanner(in); soup->clear(); soup->points.resize(scanner.size_of_vertices()); soup->polygons.resize(scanner.size_of_facets()); - for (std::size_t i = 0; i < scanner.size_of_vertices(); ++i) { + for (indices_t i = 0; i < scanner.size_of_vertices(); ++i) { double x, y, z, w; scanner.scan_vertex( x, y, z, w); soup->points[i] = Point_3(x, y, z, w); @@ -126,12 +179,13 @@ Scene_polygon_soup::load(std::istream& in) if(!in) return false; - for (std::size_t i = 0; i < scanner.size_of_facets(); ++i) { - std::size_t no; + for (indices_t i = 0; i < scanner.size_of_facets(); ++i) { + indices_t no; + scanner.scan_facet( no, i); soup->polygons[i].resize(no); - for(std::size_t j = 0; j < no; ++j) { - std::size_t id; + for(indices_t j = 0; j < no; ++j) { + indices_t id; scanner.scan_facet_vertex_index(id, i); if(id < scanner.size_of_vertices()) { @@ -146,6 +200,24 @@ Scene_polygon_soup::load(std::istream& in) return in; } + +#include +#include + +void Scene_polygon_soup::load(Scene_polyhedron_item* poly_item) { + if(!poly_item) return; + if(!poly_item->polyhedron()) return; + + if(!soup) + soup = new Polygon_soup; + + Polyhedron_to_polygon_soup_writer writer(soup); + CGAL::generic_print_polyhedron(std::cerr, + *poly_item->polyhedron(), + writer); + emit changed(); +} + void Scene_polygon_soup::setDisplayNonManifoldEdges(const bool b) { @@ -321,6 +393,44 @@ Scene_polygon_soup::save(std::ostream& out) const return out; } +void +Polygon_soup::operator()(Polyhedron::HalfedgeDS& out_hds) +{ + typedef Polyhedron::HalfedgeDS Output_HDS; + + CGAL::Polyhedron_incremental_builder_3 builder(out_hds); + + typedef Polygon_soup::size_type size_type; + builder.begin_surface(points.size(), + polygons.size(), + edges.size() * 2); + for(size_type i = 0, end = points.size(); + i < end; ++i) + { + builder.add_vertex(points[i]); + } + for(size_type i = 0, end = polygons.size(); + i < end; ++i) + { + const Polygon_soup::Polygon_3& polygon = polygons[i]; + const size_type size = polygon.size(); + builder.begin_facet(); + for(size_type j = 0; j < size; ++j) { + builder.add_vertex_to_facet(polygon[j]); + } + builder.end_facet(); + } + builder.end_surface(); +} + +bool +Scene_polygon_soup::exportAsPolyhedron(Polyhedron* out_polyhedron) +{ + orient(); + out_polyhedron->delegate(*soup); + return out_polyhedron->size_of_vertices() > 0; +} + QString Scene_polygon_soup::toolTip() const { @@ -363,8 +473,11 @@ Scene_polygon_soup::direct_draw() const { } if(soup->display_non_manifold_edges) { double current_color[4]; + GLboolean lightning; ::glGetDoublev(GL_CURRENT_COLOR, current_color); ::glColor3d(1., 0., 0.); // red + ::glGetBooleanv(GL_LIGHTING, &lightning); + ::glDisable(GL_LIGHTING); for(Polygon_soup::size_type i = 0, @@ -379,10 +492,24 @@ Scene_polygon_soup::direct_draw() const { ::glVertex3d(b.x(), b.y(), b.z()); ::glEnd(); } + if(lightning) glEnable(GL_LIGHTING); ::glColor4dv(current_color); } } +void +Scene_polygon_soup::draw_points() const { + if(soup == 0) return; + ::glBegin(GL_POINTS); + for(Polygon_soup::Points::const_iterator pit = soup->points.begin(), + end = soup->points.end(); + pit != end; ++pit) + { + ::glVertex3d(pit->x(), pit->y(), pit->z()); + } + ::glEnd(); +} + bool Scene_polygon_soup::isEmpty() const { return (soup == 0 || soup->points.empty()); @@ -401,4 +528,24 @@ Scene_polygon_soup::bbox() const { bbox.xmax(),bbox.ymax(),bbox.zmax()); } +void +Scene_polygon_soup::new_vertex(const double& x, + const double& y, + const double& z) +{ + soup->points.push_back(Point_3(x, y, z)); +} + +void +Scene_polygon_soup::new_triangle(const std::size_t i, + const std::size_t j, + const std::size_t k) +{ + Polygon_soup::Polygon_3 new_polygon(3); + new_polygon[0] = i; + new_polygon[1] = j; + new_polygon[2] = k; + soup->polygons.push_back(new_polygon); +} + #include "Scene_polygon_soup.moc" diff --git a/Polyhedron/demo/Polyhedron/Scene_polygon_soup.h b/Polyhedron/demo/Polyhedron/Scene_polygon_soup.h index 154b09bc71f..016b327cfc5 100644 --- a/Polyhedron/demo/Polyhedron/Scene_polygon_soup.h +++ b/Polyhedron/demo/Polyhedron/Scene_polygon_soup.h @@ -5,7 +5,10 @@ #include "Scene_item_with_display_list.h" #include +#include "Polyhedron_type_fwd.h" + struct Polygon_soup; +class Scene_polyhedron_item; class SCENE_POLYGON_SOUP_EXPORT Scene_polygon_soup : public Scene_item_with_display_list @@ -17,6 +20,7 @@ public: Scene_polygon_soup* clone() const; bool load(std::istream& in); + void load(Scene_polyhedron_item*); bool save(std::ostream& out) const; QString toolTip() const; @@ -25,17 +29,24 @@ public: virtual bool supportsRenderingMode(RenderingMode m) const { return m != Gouraud; } // CHECK THIS! // OpenGL drawing in a display list void direct_draw() const; + void draw_points() const; bool isFinite() const { return true; } bool isEmpty() const; Bbox bbox() const; + void new_vertex(const double&, const double&, const double&); + void new_triangle(const std::size_t, const std::size_t, const std::size_t); + +public slots: void shuffle_orientations(); bool orient(); + bool exportAsPolyhedron(Polyhedron*); void inside_out(); void setDisplayNonManifoldEdges(const bool); bool displayNonManifoldEdges() const; + private: Polygon_soup* soup; bool oriented; diff --git a/Polyhedron/demo/Polyhedron/Scene_polygon_soup_config.h b/Polyhedron/demo/Polyhedron/Scene_polygon_soup_config.h index 5a568ac4da0..47898403aaa 100644 --- a/Polyhedron/demo/Polyhedron/Scene_polygon_soup_config.h +++ b/Polyhedron/demo/Polyhedron/Scene_polygon_soup_config.h @@ -1,7 +1,7 @@ #ifndef SCENE_POLYGON_SOUP_CONFIG_H #define SCENE_POLYGON_SOUP_CONFIG_H -#ifdef polygon_soup_EXPORTS +#ifdef scene_polygon_soup_item_EXPORTS # define SCENE_POLYGON_SOUP_EXPORT Q_DECL_EXPORT #else # define SCENE_POLYGON_SOUP_EXPORT Q_DECL_IMPORT diff --git a/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.cpp b/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.cpp index 795e0ea5ca7..52a051f87bc 100644 --- a/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.cpp @@ -1,39 +1,127 @@ +#include #include "Scene_polyhedron_item.h" +#include "Kernel_type.h" #include "Polyhedron_type.h" #include +#include +#include +#include + +#include +#include + +typedef CGAL::AABB_polyhedron_triangle_primitive Primitive; +typedef CGAL::AABB_traits AABB_traits; +typedef CGAL::AABB_tree Input_facets_AABB_tree; + +const char* aabb_property_name = "Scene_polyhedron_item aabb tree"; + +Input_facets_AABB_tree* get_aabb_tree(Scene_polyhedron_item* item) +{ + QVariant aabb_tree_property = item->property(aabb_property_name); + if(aabb_tree_property.isValid()) { + void* ptr = aabb_tree_property.value(); + return static_cast(ptr); + } + else { + Polyhedron* poly = item->polyhedron(); + if(poly) { + Input_facets_AABB_tree* tree = + new Input_facets_AABB_tree(poly->facets_begin(), + poly->facets_end()); + item->setProperty(aabb_property_name, + QVariant::fromValue(tree)); + return tree; + } + else return 0; + } +} + +void delete_aabb_tree(Scene_polyhedron_item* item) +{ + QVariant aabb_tree_property = item->property(aabb_property_name); + if(aabb_tree_property.isValid()) { + void* ptr = aabb_tree_property.value(); + Input_facets_AABB_tree* tree = static_cast(ptr); + if(tree) { + delete tree; + tree = 0; + } + item->setProperty(aabb_property_name, QVariant()); + } +} + #include +#include +#include #include Scene_polyhedron_item::Scene_polyhedron_item() : Scene_item_with_display_list(), - poly(new Polyhedron) + poly(new Polyhedron), + show_only_feature_edges_m(false), + facet_picking_m(false), + erase_next_picked_facet_m(false) { + //init(); } Scene_polyhedron_item::Scene_polyhedron_item(Polyhedron* const p) : Scene_item_with_display_list(), - poly(p) + poly(p), + show_only_feature_edges_m(false), + facet_picking_m(false), + erase_next_picked_facet_m(false) { + init(); } Scene_polyhedron_item::Scene_polyhedron_item(const Polyhedron& p) : Scene_item_with_display_list(), - poly(new Polyhedron(p)) + poly(new Polyhedron(p)), + show_only_feature_edges_m(false), + facet_picking_m(false), + erase_next_picked_facet_m(false) { + init(); } // Scene_polyhedron_item::Scene_polyhedron_item(const Scene_polyhedron_item& item) // : Scene_item_with_display_list(item), -// poly(new Polyhedron(*item.poly)) +// poly(new Polyhedron(*item.poly)), +// show_only_feature_edges_m(false) // { // } Scene_polyhedron_item::~Scene_polyhedron_item() { + delete_aabb_tree(this); delete poly; } +#include "Color_map.h" + +void +Scene_polyhedron_item:: +init() +{ + typedef Polyhedron::Facet_iterator Facet_iterator; + + // Fill indices map and get max subdomain value + int max = 0; + for(Facet_iterator fit = poly->facets_begin(), end = poly->facets_end() ; + fit != end; ++fit) + { + max = (std::max)(max, fit->patch_id()); + } + + colors_.clear(); + compute_color_map(this->color(), max + 1, + std::back_inserter(colors_)); +} + + Scene_polyhedron_item* Scene_polyhedron_item::clone() const { return new Scene_polyhedron_item(*poly); @@ -44,13 +132,20 @@ bool Scene_polyhedron_item::load(std::istream& in) { in >> *poly; - return in && !isEmpty(); + + if ( in && !isEmpty() ) + { + changed(); + return true; + } + return false; } // Write polyhedron to .OFF file bool Scene_polyhedron_item::save(std::ostream& out) const { + out.precision(13); out << *poly; return out; } @@ -73,9 +168,100 @@ Scene_polyhedron_item::toolTip() const .arg(this->color().name()); } +QMenu* Scene_polyhedron_item::contextMenu() +{ + const char* prop_name = "Menu modified by Scene_polyhedron_item."; + + QMenu* menu = Scene_item::contextMenu(); + + // Use dynamic properties: + // http://doc.trolltech.com/lastest/qobject.html#property + bool menuChanged = menu->property(prop_name).toBool(); + + if(!menuChanged) { + + QAction* actionShowOnlyFeatureEdges = + menu->addAction(tr("Show only &feature edges")); + actionShowOnlyFeatureEdges->setCheckable(true); + actionShowOnlyFeatureEdges->setObjectName("actionShowOnlyFeatureEdges"); + connect(actionShowOnlyFeatureEdges, SIGNAL(toggled(bool)), + this, SLOT(show_only_feature_edges(bool))); + + QAction* actionPickFacets = + menu->addAction(tr("Facets picking")); + actionPickFacets->setCheckable(true); + actionPickFacets->setObjectName("actionPickFacets"); + connect(actionPickFacets, SIGNAL(toggled(bool)), + this, SLOT(enable_facets_picking(bool))); + + QAction* actionEraseNextFacet = + menu->addAction(tr("Erase next picked facet")); + actionEraseNextFacet->setCheckable(true); + actionEraseNextFacet->setObjectName("actionEraseNextFacet"); + connect(actionEraseNextFacet, SIGNAL(toggled(bool)), + this, SLOT(set_erase_next_picked_facet(bool))); + + menu->setProperty(prop_name, true); + } + QAction* action = menu->findChild("actionPickFacets"); + if(action) action->setChecked(facet_picking_m); + action = menu->findChild("actionEraseNextFacet"); + if(action) action->setChecked(erase_next_picked_facet_m); + return menu; +} + +void Scene_polyhedron_item::show_only_feature_edges(bool b) +{ + show_only_feature_edges_m = b; + emit itemChanged(); +} + +void Scene_polyhedron_item::enable_facets_picking(bool b) +{ + facet_picking_m = b; +} + +void Scene_polyhedron_item::set_erase_next_picked_facet(bool b) +{ + erase_next_picked_facet_m = b; +} + // Points/Wireframe/Flat/Gouraud OpenGL drawing in a display list void Scene_polyhedron_item::direct_draw() const { - gl_render_facets(*poly); + gl_render_facets(*poly,colors_); +} + +// Points/Wireframe/Flat/Gouraud OpenGL drawing in a display list +void Scene_polyhedron_item::direct_draw_edges() const { + typedef Kernel::Point_3 Point; + typedef Polyhedron::Edge_iterator Edge_iterator; + + ::glBegin(GL_LINES); + Edge_iterator he; + if(!show_only_feature_edges_m) { + for(he = poly->edges_begin(); + he != poly->edges_end(); + he++) + { + if(he->is_feature_edge()) continue; + const Point& a = he->vertex()->point(); + const Point& b = he->opposite()->vertex()->point(); + ::glVertex3d(a.x(),a.y(),a.z()); + ::glVertex3d(b.x(),b.y(),b.z()); + } + } + ::glColor3d(1.0, 0.0, 0.0); + for(he = poly->edges_begin(); + he != poly->edges_end(); + he++) + { + if(!he->is_feature_edge()) continue; + const Point& a = he->vertex()->point(); + const Point& b = he->opposite()->vertex()->point(); + ::glVertex3d(a.x(),a.y(),a.z()); + ::glVertex3d(b.x(),b.y(),b.z()); + } + ::glEnd(); } Polyhedron* @@ -90,7 +276,7 @@ Scene_polyhedron_item::isEmpty() const { Scene_polyhedron_item::Bbox Scene_polyhedron_item::bbox() const { - const Point& p = *(poly->points_begin()); + const Kernel::Point_3& p = *(poly->points_begin()); CGAL::Bbox_3 bbox(p.x(), p.y(), p.z(), p.x(), p.y(), p.z()); for(Polyhedron::Point_iterator it = poly->points_begin(); it != poly->points_end(); @@ -101,4 +287,82 @@ Scene_polyhedron_item::bbox() const { bbox.xmax(),bbox.ymax(),bbox.zmax()); } + +void +Scene_polyhedron_item:: +changed() +{ + delete_aabb_tree(this); + init(); + Base::changed(); +} + +void +Scene_polyhedron_item::select(double orig_x, + double orig_y, + double orig_z, + double dir_x, + double dir_y, + double dir_z) +{ + if(facet_picking_m) { + typedef Input_facets_AABB_tree Tree; + typedef Tree::Object_and_primitive_id Object_and_primitive_id; + typedef Tree::Primitive_id Primitive_id; + + Tree* aabb_tree = get_aabb_tree(this); + if(aabb_tree) { + const Kernel::Point_3 ray_origin(orig_x, orig_y, orig_z); + const Kernel::Vector_3 ray_dir(dir_x, dir_y, dir_z); + const Kernel::Ray_3 ray(ray_origin, ray_dir); + + typedef std::list Intersections; + Intersections intersections; + + aabb_tree->all_intersections(ray, std::back_inserter(intersections)); + + Intersections::iterator closest = intersections.begin(); + if(closest != intersections.end()) { + const Kernel::Point_3* closest_point = + CGAL::object_cast(&closest->first); + Kernel::Compare_squared_distance_3 comp_sq_dist = + Kernel().compare_squared_distance_3_object(); + + for(Intersections::iterator + it = boost::next(intersections.begin()), + end = intersections.end(); + it != end; ++it) + { + if(! closest_point) { + closest = it; + } + else { + const Kernel::Point_3* it_point = + CGAL::object_cast(&it->first); + if(it_point && + (ray_dir * (*it_point - *closest_point)) < 0) + { + closest = it; + closest_point = it_point; + } + } + } + if(closest_point) { + Polyhedron::Facet_handle selected_facet = closest->second; + if(erase_next_picked_facet_m) { + polyhedron()->erase_facet(selected_facet->halfedge()); + polyhedron()->normalize_border(); + set_erase_next_picked_facet(false); + changed(); + emit itemChanged(); + } + std::cerr << "Facet selected. patch_id=" + << selected_facet->patch_id() << std::endl; + } + } + } + } + Base::select(orig_x, orig_y, orig_z, dir_x, dir_y, dir_z); +} + #include "Scene_polyhedron_item.moc" diff --git a/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.h b/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.h index 2b8981b25bd..0342d290977 100644 --- a/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.h +++ b/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.h @@ -6,6 +6,13 @@ #include "Polyhedron_type_fwd.h" #include +#include +#include + +#include + +class QMenu; + // This class represents a polyhedron in the OpenGL scene class SCENE_POLYHEDRON_ITEM_EXPORT Scene_polyhedron_item : public Scene_item_with_display_list { @@ -26,10 +33,14 @@ public: // Function for displaying meta-data of the item virtual QString toolTip() const; + // Function to override the context menu + QMenu* contextMenu(); + // Indicate if rendering mode is supported - virtual bool supportsRenderingMode(RenderingMode m) const { return true; } + virtual bool supportsRenderingMode(RenderingMode) const { return true; } // Points/Wireframe/Flat/Gouraud OpenGL drawing in a display list virtual void direct_draw() const; + virtual void direct_draw_edges() const; // Get wrapped polyhedron Polyhedron* polyhedron(); @@ -40,9 +51,34 @@ public: bool isEmpty() const; Bbox bbox() const; +public slots: + virtual void changed(); + void show_only_feature_edges(bool); + void enable_facets_picking(bool); + void set_erase_next_picked_facet(bool); + + void select(double orig_x, + double orig_y, + double orig_z, + double dir_x, + double dir_y, + double dir_z); +private: + // Initialization + void init(); + private: Polyhedron* poly; +private: + typedef Scene_item_with_display_list Base; + typedef std::vector Color_vector; + + Color_vector colors_; + + bool show_only_feature_edges_m; + bool facet_picking_m; + bool erase_next_picked_facet_m; }; // end class Scene_polyhedron_item #endif // SCENE_POLYHEDRON_ITEM_H diff --git a/Polyhedron/demo/Polyhedron/Show_point_dialog.cpp b/Polyhedron/demo/Polyhedron/Show_point_dialog.cpp new file mode 100644 index 00000000000..c0802a85457 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Show_point_dialog.cpp @@ -0,0 +1,73 @@ +#include "Show_point_dialog.h" +#include "ui_Show_point_dialog.h" + +Show_point_dialog::Show_point_dialog(QWidget* parent) + : QDialog(parent) + , ui(new Ui::Show_point_dialog) + , m_has_correct_coordinates(false) +{ + ui->setupUi(this); + + connect(ui->lineEdit, SIGNAL(textChanged(const QString&)), + this, SLOT(interprete_string(const QString&))); +} + +Show_point_dialog::~Show_point_dialog() +{ + delete ui; +} + +void Show_point_dialog::interprete_string(const QString& string) +{ + QString double_re("([-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?)"); + QString not_double_char_re("[^0-9-+.eE]"); + QString full_re = QString("^") + + not_double_char_re + "*" + + double_re + + not_double_char_re + "+" + + double_re + + not_double_char_re + "+" + + double_re + + "(" + not_double_char_re + "*" + + "|" + not_double_char_re + "+" + double_re + + ")" + + "$"; + QRegExp re(full_re); + if(re.exactMatch(string)) { + // const double x = re.cap(1).toDouble(); + // const double y = re.cap(2).toDouble(); + // const double z = re.cap(3).toDouble(); + ui->coord_x->setText(QString(re.cap(1))); + ui->coord_y->setText(QString(re.cap(2))); + ui->coord_z->setText(QString(re.cap(3))); + m_has_correct_coordinates = true; + } + else { + ui->coord_x->setText(QString()); + ui->coord_y->setText(QString()); + ui->coord_z->setText(QString()); + m_has_correct_coordinates = false; + } +} + +double Show_point_dialog::get_x() const +{ + return ui->coord_x->text().toDouble(); +} + +double Show_point_dialog::get_y() const +{ + return ui->coord_y->text().toDouble(); +} + +double Show_point_dialog::get_z() const +{ + return ui->coord_z->text().toDouble(); +} + +bool Show_point_dialog::has_correct_coordinates() const +{ + return m_has_correct_coordinates; +} + +#include "Show_point_dialog.moc" diff --git a/Polyhedron/demo/Polyhedron/Show_point_dialog.h b/Polyhedron/demo/Polyhedron/Show_point_dialog.h new file mode 100644 index 00000000000..5a00b0485de --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Show_point_dialog.h @@ -0,0 +1,35 @@ +#ifndef SHOW_POINT_DIALOG_H +#define SHOW_POINT_DIALOG_H +#include "config.h" + +#include "Point_dialog_config.h" + +#include + +namespace Ui { + class Show_point_dialog; +} + +class POINT_DIALOG_EXPORT Show_point_dialog : + public QDialog +{ + Q_OBJECT +public: + Show_point_dialog(QWidget* parent = 0); + ~Show_point_dialog(); + + bool has_correct_coordinates() const; + + double get_x() const; + double get_y() const; + double get_z() const; + +protected slots: + void interprete_string(const QString&); + +protected: + Ui::Show_point_dialog* ui; + bool m_has_correct_coordinates; +}; + +#endif diff --git a/Polyhedron/demo/Polyhedron/Show_point_dialog.ui b/Polyhedron/demo/Polyhedron/Show_point_dialog.ui new file mode 100644 index 00000000000..5543f27c91f --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Show_point_dialog.ui @@ -0,0 +1,161 @@ + + + Show_point_dialog + + + + 0 + 0 + 575 + 151 + + + + Dialog + + + + + + + + QFormLayout::ExpandingFieldsGrow + + + + + Point &coordinates + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + lineEdit + + + + + + + + 1 + 0 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu LGC Sans'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Paste here the coordinates of a point. It can be for example:</p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">&quot;(10., -2e-2, .4)&quot;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">or:</p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">&quot;-2 3 5&quot;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">or even something with garbage around:</p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">&quot;point (-2, 5, 0) and...&quot;</p></body></html> + + + + + + + x + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + y + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + z + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + lineEdit + + + + + buttonBox + accepted() + Show_point_dialog + accept() + + + 423 + 120 + + + 387 + 139 + + + + + buttonBox + rejected() + Show_point_dialog + reject() + + + 520 + 120 + + + 512 + 138 + + + + + diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index ffe0fc930ba..bd69a082f2c 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -1,46 +1,144 @@ #include "Viewer.h" #include "Scene_draw_interface.h" +#include +#include + +class Viewer_impl { +public: + Scene_draw_interface* scene; + bool antialiasing; + bool twosides; + bool macro_mode; + + void draw_aux(bool with_names); +}; Viewer::Viewer(QWidget* parent, bool antialiasing) - : QGLViewer(parent), - scene(0), - antialiasing(antialiasing), - twosides(false) + : QGLViewer(parent) { - setBackgroundColor(::Qt::white); + d = new Viewer_impl; + d->scene = 0; + d->antialiasing = antialiasing; + d->twosides = false; + d->macro_mode = false; + setShortcut(EXIT_VIEWER, 0); + setMouseBinding(Qt::SHIFT + Qt::LeftButton, SELECT); + setMouseBindingDescription(Qt::SHIFT + Qt::RightButton, + tr("Selects and display context " + "menu of the selected item")); + setKeyDescription(Qt::Key_T, + tr("Turn the camera by 180 degrees")); + setKeyDescription(Qt::Key_M, + tr("Toggle macro mode: useful to view details very near from the camera, " + "but decrease the z-buffer precision")); +} + +Viewer::~Viewer() +{ + delete d; } void Viewer::setScene(Scene_draw_interface* scene) { - this->scene = scene; + d->scene = scene; +} + +bool Viewer::antiAliasing() const +{ + return d->antialiasing; } void Viewer::setAntiAliasing(bool b) { - antialiasing = b; + d->antialiasing = b; updateGL(); } void Viewer::setTwoSides(bool b) { - twosides = b; + d->twosides = b; updateGL(); } void Viewer::draw() { - draw_aux(false); + // ::glFogf(GL_FOG_END, 2*sceneRadius()); + // ::glEnable(GL_FOG); + QGLViewer::draw(); + d->draw_aux(false); + // drawLight(GL_LIGHT0); } void Viewer::initializeGL() { QGLViewer::initializeGL(); - scene->initializeGL(); + setBackgroundColor(::Qt::white); + d->scene->initializeGL(); + + const GLfloat ambient_light[4] = { 0.6f, 0.6f, 0.6f, 1.0f }; + const GLfloat diffuse_light[4] = { 0.6f, 0.6f, 0.6f, 1.0f }; + + ::glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_light); + ::glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_light); + // ::glFogf(GL_FOG_DENSITY, 0.05f); + // ::glHint(GL_FOG_HINT, GL_NICEST); + // ::glFogi(GL_FOG_MODE, GL_LINEAR); + // static const GLfloat fogColor[] = {0.5f, 0.5f, 0.5f, 1}; + // ::glFogfv(GL_FOG_COLOR, fogColor); } -void Viewer::draw_aux(bool with_names) +#include + +void Viewer::mousePressEvent(QMouseEvent* event) +{ + if(event->button() == Qt::RightButton && + event->modifiers().testFlag(Qt::ShiftModifier)) + { + select(event->pos()); + requestContextMenu(event->globalPos()); + event->accept(); + } + else { + QGLViewer::mousePressEvent(event); + } +} + +void Viewer::keyPressEvent(QKeyEvent* e) +{ + if(!e->modifiers()) { + if(e->key() == Qt::Key_T) { + turnCameraBy180Degres(); + return; + } + else if(e->key() == Qt::Key_M) { + d->macro_mode = ! d->macro_mode; + if(d->macro_mode) { + camera()->setZNearCoefficient(0.0005f); + } else { + camera()->setZNearCoefficient(0.005f); + } + this->displayMessage(tr("Macro mode: %1"). + arg(d->macro_mode ? tr("on") : tr("off"))); + return; + } + } + QGLViewer::keyPressEvent(e); +} + +void Viewer::turnCameraBy180Degres() { + qglviewer::Camera* camera = this->camera(); + using qglviewer::ManipulatedCameraFrame; + + ManipulatedCameraFrame frame_from(*camera->frame()); + camera->setViewDirection(-camera->viewDirection()); + ManipulatedCameraFrame frame_to(*camera->frame()); + + camera->setOrientation(frame_from.orientation()); + camera->interpolateTo(frame_to, 0.5f); +} + +void Viewer_impl::draw_aux(bool with_names) { - QGLViewer::draw(); if(scene == 0) return; @@ -48,15 +146,16 @@ void Viewer::draw_aux(bool with_names) ::glPointSize(2.f); ::glEnable(GL_POLYGON_OFFSET_FILL); ::glPolygonOffset(1.0f,1.0f); - ::glClearColor(1.0f,1.0f,1.0f,0.0f); ::glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); + ::glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); + if(twosides) ::glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); else ::glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); - if(antiAliasing()) + if(antialiasing) { ::glEnable(GL_BLEND); ::glEnable(GL_LINE_SMOOTH); @@ -79,10 +178,84 @@ void Viewer::draw_aux(bool with_names) void Viewer::drawWithNames() { - draw_aux(true); + QGLViewer::draw(); + d->draw_aux(true); } -void Viewer::postSelection(const QPoint&) +void Viewer::postSelection(const QPoint& pixel) { - emit selected(this->selectedName()); + bool found = false; + qglviewer::Vec point = camera()->pointUnderPixel(pixel, found); + if(found) { + emit selectedPoint(point.x, + point.y, + point.z); + emit selected(this->selectedName()); + const qglviewer::Vec orig = camera()->position(); + const qglviewer::Vec dir = point - orig; + emit selectionRay(orig.x, orig.y, orig.z, + dir.x, dir.y, dir.z); + } +} + +bool Viewer::readFrame(QString s, qglviewer::Frame& frame) +{ + QStringList list = s.split(" ", QString::SkipEmptyParts); + if(list.size() != 7) + return false; + float vec[3]; + for(int i = 0; i < 3; ++i) + { + bool ok; + vec[i] = list[i].toFloat(&ok); + if(!ok) return false; + } + double orient[4]; + for(int i = 0; i < 4; ++i) + { + bool ok; + orient[i] = list[i + 3].toDouble(&ok); + if(!ok) return false; + } + frame.setPosition(qglviewer::Vec(vec[0], + vec[1], + vec[2])); + frame.setOrientation(orient[0], + orient[1], + orient[2], + orient[3]); + return true; +} + +QString Viewer::dumpFrame(const qglviewer::Frame& frame) { + const qglviewer::Vec pos = frame.position(); + const qglviewer::Quaternion q = frame.orientation(); + + return QString("%1 %2 %3 %4 %5 %6 %7") + .arg(pos[0]) + .arg(pos[1]) + .arg(pos[2]) + .arg(q[0]) + .arg(q[1]) + .arg(q[2]) + .arg(q[3]); +} + +bool Viewer::moveCameraToCoordinates(QString s, float animation_duration) { + qglviewer::Frame new_frame; + if(readFrame(s, new_frame)) { + camera()->interpolateTo(new_frame, animation_duration); + return true; + } + else + return false; +} + +QString Viewer::dumpCameraCoordinates() +{ + if(camera()->frame()) { + return dumpFrame(*camera()->frame()); + } else { + return QString(); + } } diff --git a/Polyhedron/demo/Polyhedron/Viewer.h b/Polyhedron/demo/Polyhedron/Viewer.h index f2396af5ceb..c2ffa7c946e 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.h +++ b/Polyhedron/demo/Polyhedron/Viewer.h @@ -1,18 +1,26 @@ #ifndef VIEWER_H #define VIEWER_H +#include "Viewer_config.h" + #include +#include // forward declarations class QWidget; class Scene_draw_interface; +class QMouseEvent; +class QKeyEvent; -class Viewer : public QGLViewer { +class Viewer_impl; + +class VIEWER_EXPORT Viewer : public QGLViewer { Q_OBJECT public: Viewer(QWidget * parent, bool antialiasing = false); + ~Viewer(); // overload several QGLViewer virtual functions void draw(); @@ -21,21 +29,33 @@ public: void postSelection(const QPoint&); void setScene(Scene_draw_interface* scene); - bool antiAliasing() const { return antialiasing; } + bool antiAliasing() const; + + static bool readFrame(QString, qglviewer::Frame&); + static QString dumpFrame(const qglviewer::Frame&); signals: void selected(int); + void requestContextMenu(QPoint global_pos); + void selectedPoint(double, double, double); + void selectionRay(double, double, double, double, double, double); public slots: void setAntiAliasing(bool b); void setTwoSides(bool b); -private: - void draw_aux(bool with_names); + void turnCameraBy180Degres(); - Scene_draw_interface* scene; - bool antialiasing; - bool twosides; + QString dumpCameraCoordinates(); + bool moveCameraToCoordinates(QString, + float animation_duration = 0.5f); + +protected: + void mousePressEvent(QMouseEvent*); + void keyPressEvent(QKeyEvent*); + +protected: + Viewer_impl* d; }; // end class Viewer #endif // VIEWER_H diff --git a/Polyhedron/demo/Polyhedron/Viewer_config.h b/Polyhedron/demo/Polyhedron/Viewer_config.h new file mode 100644 index 00000000000..2a79ddf681d --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Viewer_config.h @@ -0,0 +1,16 @@ +#ifndef VIEWER_CONFIG_H +#define VIEWER_CONFIG_H + +#include + +#ifdef demo_framework_EXPORTS +# define viewer_EXPORTS +#endif + +#ifdef viewer_EXPORTS +# define VIEWER_EXPORT Q_DECL_EXPORT +#else +# define VIEWER_EXPORT Q_DECL_IMPORT +#endif + +#endif // VIEWER_CONFIG_H diff --git a/Polyhedron/demo/Polyhedron/cgal_test_with_cmake b/Polyhedron/demo/Polyhedron/cgal_test_with_cmake index bd8bf57d219..855f39543e4 100755 --- a/Polyhedron/demo/Polyhedron/cgal_test_with_cmake +++ b/Polyhedron/demo/Polyhedron/cgal_test_with_cmake @@ -144,8 +144,8 @@ if ${MAKE_CMD} -f Makefile help | grep "pca_plugin" > /dev/null; then compile_and_run pca_plugin NEED_CLEAN=y fi -if ${MAKE_CMD} -f Makefile help | grep "polygon_soup" > /dev/null; then - compile_and_run polygon_soup +if ${MAKE_CMD} -f Makefile help | grep "scene_polygon_soup" > /dev/null; then + compile_and_run scene_polygon_soup NEED_CLEAN=y fi if ${MAKE_CMD} -f Makefile help | grep "remeshing_plugin" > /dev/null; then diff --git a/Polyhedron/demo/Polyhedron/include/CGAL/Dualizer.h b/Polyhedron/demo/Polyhedron/include/CGAL/Dualizer.h index 5f9f1f96c8e..5b1eb889b01 100644 --- a/Polyhedron/demo/Polyhedron/include/CGAL/Dualizer.h +++ b/Polyhedron/demo/Polyhedron/include/CGAL/Dualizer.h @@ -19,6 +19,7 @@ private: typedef typename Kernel::Point_3 Point; typedef typename Kernel::Plane_3 Plane; typedef typename Kernel::Vector_3 Vector; + typedef typename Kernel::FT FT; typedef typename HDS::Vertex Vertex; typedef typename HDS::Face_handle Face_handle; diff --git a/Polyhedron/demo/Polyhedron/include/CGAL/Polyhedron_kernel.h b/Polyhedron/demo/Polyhedron/include/CGAL/Polyhedron_kernel.h index 7fe966c7906..c0f023fcb3c 100644 --- a/Polyhedron/demo/Polyhedron/include/CGAL/Polyhedron_kernel.h +++ b/Polyhedron/demo/Polyhedron/include/CGAL/Polyhedron_kernel.h @@ -37,6 +37,7 @@ private: typedef typename Kernel::FT FT; typedef typename Kernel::Point_3 Point; typedef typename Kernel::Plane_3 Plane; + typedef typename Kernel::Vector_3 Vector; typedef typename Kernel::Triangle_3 Triangle; // program and solution types @@ -162,6 +163,8 @@ void get_triangles(Polyhedron& polyhedron, { typedef typename Polyhedron::Facet_iterator Facet_iterator; typedef typename Polyhedron::Halfedge_handle Halfedge_handle; + typedef typename Polyhedron::Point_3 Point; + typedef typename Polyhedron::Traits::Triangle_3 Triangle; for(Facet_iterator f = polyhedron.facets_begin(); f != polyhedron.facets_end(); diff --git a/Polyhedron/demo/Polyhedron/include/CGAL/gl_render.h b/Polyhedron/demo/Polyhedron/include/CGAL/gl_render.h index fe76152afab..28613bc2a8c 100644 --- a/Polyhedron/demo/Polyhedron/include/CGAL/gl_render.h +++ b/Polyhedron/demo/Polyhedron/include/CGAL/gl_render.h @@ -4,8 +4,25 @@ #include #include + +namespace { + void CGALglcolor(QColor c, int dv = 0) + { + if ( 0 != dv ) + { +// workaround for Qt-4.2. +#if QT_VERSION < 0x040300 +# define darker dark +#endif + c = c.darker(dv); +#undef darker + } + ::glColor4f(c.red()/255.0, c.green()/255.0, c.blue()/255.0, c.alpha()/255.0); + } +} + template -void gl_render_facets(Polyhedron& polyhedron) +void gl_render_facets(Polyhedron& polyhedron, const std::vector& colors) { typedef typename Polyhedron::Traits Kernel; typedef typename Kernel::Point_3 Point; @@ -23,6 +40,7 @@ void gl_render_facets(Polyhedron& polyhedron) f != polyhedron.facets_end(); f++) { + CGALglcolor(colors[f->patch_id()]); ::glBegin(GL_POLYGON); // If Flat shading: 1 normal per polygon diff --git a/Polyhedron/demo/Polyhedron/include/CGAL/triangulate_polyhedron.h b/Polyhedron/demo/Polyhedron/include/CGAL/triangulate_polyhedron.h new file mode 100644 index 00000000000..4012c9fd57c --- /dev/null +++ b/Polyhedron/demo/Polyhedron/include/CGAL/triangulate_polyhedron.h @@ -0,0 +1,225 @@ +// Copyright (c) 2010-2011 GeometryFactory Sarl (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you may redistribute it under +// the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Laurent Rineau + +#ifndef CGAL_TRIANGULATE_POLYHEDRON_H + +#include +#include + +#include +#include +#include +#include +#include + +// TODO: submit this file to CGAL too +#include "CGAL/compute_normal.h" + +#include +#include +#include + +namespace CGAL { + +template +class Triangulate_modifier + : public CGAL::Modifier_base +{ + typedef typename Polyhedron::HalfedgeDS HDS; + typedef typename Polyhedron::Traits Traits; + + typedef typename Polyhedron::Halfedge_handle Halfedge_handle; + typedef typename Polyhedron::Facet Facet; + typedef typename Polyhedron::Facet_iterator Facet_iterator; + typedef typename Polyhedron::Facet_handle Facet_handle; + + typedef CGAL::Triangulation_2_filtered_projection_traits_3 P_traits; + + typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; + + struct Face_info { + typename Polyhedron::Halfedge_handle e[3]; + bool is_external; + }; + + typedef CGAL::Triangulation_face_base_with_info_2 Fb1; + + typedef CGAL::Constrained_triangulation_face_base_2 Fb; + typedef CGAL::Triangulation_data_structure_2 TDS; + typedef CGAL::No_intersection_tag Itag; + typedef CGAL::Constrained_Delaunay_triangulation_2 CDTbase; + typedef CGAL::Constrained_triangulation_plus_2 CDT; + +public: + Triangulate_modifier() + { + } + + bool is_external(typename CDT::Face_handle fh) const { + return fh->info().is_external; + } + + void operator()(HDS& hds) { + CGAL::HalfedgeDS_decorator decorator(hds); + typedef typename HDS::Halfedge Halfedge; + + // One need to store facet handles into a vector, because the list of + // facets of the polyhedron will be modified during the loop, and + // that invalidates the range [facets_begin(), facets_end()[. + std::vector facets; + facets.reserve(hds.size_of_faces()); + for(Facet_iterator + fit = hds.faces_begin(), + end = hds.faces_end(); + fit != end; ++fit) { + facets.push_back(fit); + } + + // Iterates on the vector of facet handles + for(typename std::vector::iterator + fit_it = facets.begin(), + end = facets.end(); + fit_it != end; ++fit_it) + { + Facet_handle fit = *fit_it; + typename Traits::Vector_3 normal = + compute_facet_normal(*fit); + + P_traits cdt_traits(normal); + CDT cdt(cdt_traits); + + typename Facet::Halfedge_around_facet_circulator + he_circ = fit->facet_begin(), + he_circ_end(he_circ); + typename CDT::Vertex_handle previous, first; + do { + typename CDT::Vertex_handle vh = cdt.insert(he_circ->vertex()->point()); + if(first == 0) { + first = vh; + } + vh->info() = he_circ; + if(previous != 0 && previous != vh) { + cdt.insert_constraint(previous, vh); + } + previous = vh; + } while( ++he_circ != he_circ_end ); + cdt.insert_constraint(previous, first); + + // sets mark is_external + for(typename CDT::All_faces_iterator + fit = cdt.all_faces_begin(), + end = cdt.all_faces_end(); + fit != end; ++fit) + { + fit->info().is_external = false; + } + std::queue face_queue; + face_queue.push(cdt.infinite_vertex()->face()); + while(! face_queue.empty() ) { + typename CDT::Face_handle fh = face_queue.front(); + face_queue.pop(); + if(fh->info().is_external) continue; + fh->info().is_external = true; + for(int i = 0; i <3; ++i) { + if(!cdt.is_constrained(std::make_pair(fh, i))) + { + face_queue.push(fh->neighbor(i)); + } + } + } + + // then modify the polyhedron + decorator.make_hole(fit->halfedge()); + for(typename CDT::Finite_edges_iterator + eit = cdt.finite_edges_begin(), + end = cdt.finite_edges_end(); + eit != end; ++eit) + { + typename CDT::Face_handle fh = eit->first; + const int index = eit->second; + typename CDT::Face_handle opposite_fh = fh->neighbor(eit->second); + const int opposite_index = opposite_fh->index(fh); + const typename CDT::Vertex_handle va = fh->vertex(cdt. cw(index)); + const typename CDT::Vertex_handle vb = fh->vertex(cdt.ccw(index)); + + if( ! (is_external(fh) && is_external(opposite_fh)) && + ! cdt.is_constrained(*eit) ) + { + // strictly internal edge + Halfedge_handle h = hds.edges_push_back(Halfedge(), + Halfedge()); + fh->info().e[index] = h; + opposite_fh->info().e[opposite_index] = h->opposite(); + + decorator.set_vertex(h, va->info()->vertex()); + decorator.set_vertex(h->opposite(), vb->info()->vertex()); + } + if( cdt.is_constrained(*eit) ) + { + if(!is_external(fh)) { + fh->info().e[index] = va->info(); + } + if(!is_external(opposite_fh)) { + opposite_fh->info().e[opposite_index] = vb->info(); + } + } + } + for(typename CDT::Finite_faces_iterator + fit = cdt.finite_faces_begin(), + end = cdt.finite_faces_end(); + fit != end; ++fit) + { + if(!is_external(fit)) + { + Halfedge_handle h0 = fit->info().e[0]; + Halfedge_handle h1 = fit->info().e[1]; + Halfedge_handle h2 = fit->info().e[2]; + CGAL_assertion( h0 != Halfedge_handle() ); + CGAL_assertion( h1 != Halfedge_handle() ); + CGAL_assertion( h2 != Halfedge_handle() ); + + typedef typename Halfedge::Base HBase; + h0->HBase::set_next(h1); + decorator.set_prev(h1, h0); + h1->HBase::set_next(h2); + decorator.set_prev(h2, h1); + h2->HBase::set_next(h0); + decorator.set_prev(h0, h2); + + decorator.fill_hole(h0); + } + } + } // end loop on facets of the input polyhedron + } +}; // end class Triangulate_modifier + +template +void triangulate_polyhedron(Polyhedron& p) +{ + CGAL::Triangulate_modifier modifier; + p.delegate(modifier); +} + +} // end namespace CGAL + +#endif // CGAL_TRIANGULATE_POLYHEDRON_H diff --git a/Polyhedron/demo/Polyhedron/texture.cpp b/Polyhedron/demo/Polyhedron/texture.cpp index ff574ca5eb6..ae99232bbe7 100644 --- a/Polyhedron/demo/Polyhedron/texture.cpp +++ b/Polyhedron/demo/Polyhedron/texture.cpp @@ -972,7 +972,7 @@ void Texture::GenerateHStripes(unsigned int width, //*************************************** void Texture::GenerateGrid(unsigned int width, unsigned int height, - int size, + int /*size*/, unsigned int thickness, unsigned char r, unsigned char g, @@ -1016,7 +1016,7 @@ void Texture::GenerateGrid(unsigned int width, void Texture::GenerateGradientH(unsigned int width, unsigned int height, - int size) + int /*size*/) { Alloc(width,height,24); @@ -1034,7 +1034,7 @@ void Texture::GenerateGradientH(unsigned int width, } void Texture::GenerateGradientV(unsigned int width, unsigned int height, - int size) + int /*size*/) { Alloc(width,height,24); diff --git a/Spatial_sorting/doc_tex/Spatial_sorting/PkgDescription.tex b/Spatial_sorting/doc_tex/Spatial_sorting/PkgDescription.tex index d35536380eb..959a556c9ca 100644 --- a/Spatial_sorting/doc_tex/Spatial_sorting/PkgDescription.tex +++ b/Spatial_sorting/doc_tex/Spatial_sorting/PkgDescription.tex @@ -1,8 +1,8 @@ \begin{ccPkgDescription}{Spatial Sorting \label{Pkg:SpatialSorting}} -\ccPkgHowToCiteCgal{cgal:d-ss-11} +\ccPkgHowToCiteCgal{cgal:d-ss-10} \ccPkgSummary{This package provides functions -for sorting geometric objects in two and three dimensions, in order to improve +for sorting geometric objects in two, three and higher dimensions, in order to improve efficiency of incremental geometric algorithms.} \ccPkgIntroducedInCGAL{3.3} diff --git a/Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert-median.gif b/Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert-median.gif new file mode 100644 index 00000000000..bcc1aa3052c Binary files /dev/null and b/Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert-median.gif differ diff --git a/Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert-median.pdf b/Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert-median.pdf new file mode 100644 index 00000000000..ddd7002eed6 Binary files /dev/null and b/Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert-median.pdf differ diff --git a/Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert-middle.gif b/Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert-middle.gif new file mode 100644 index 00000000000..96785584337 Binary files /dev/null and b/Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert-middle.gif differ diff --git a/Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert-middle.pdf b/Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert-middle.pdf new file mode 100644 index 00000000000..a5a82746306 Binary files /dev/null and b/Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert-middle.pdf differ diff --git a/Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert8.gif b/Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert8.gif new file mode 100644 index 00000000000..87301238d14 Binary files /dev/null and b/Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert8.gif differ diff --git a/Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert8.pdf b/Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert8.pdf new file mode 100644 index 00000000000..9388fd644a6 Binary files /dev/null and b/Spatial_sorting/doc_tex/Spatial_sorting/fig/Hilbert8.pdf differ diff --git a/Spatial_sorting/doc_tex/Spatial_sorting/main.tex b/Spatial_sorting/doc_tex/Spatial_sorting/main.tex index 442b704f4ef..c184c024ddb 100644 --- a/Spatial_sorting/doc_tex/Spatial_sorting/main.tex +++ b/Spatial_sorting/doc_tex/Spatial_sorting/main.tex @@ -1,12 +1,11 @@ \ccUserChapter{Spatial Sorting \label{chap:spatial_sorting}} -\ccChapterAuthor{Christophe Delage} +\ccChapterAuthor{Christophe Delage \and Olivier Devillers} \input{Spatial_sorting/PkgDescription} \minitoc -\input{Spatial_sorting/spatial_sorting_def} \input{Spatial_sorting/spatial_sorting} diff --git a/Spatial_sorting/doc_tex/Spatial_sorting/spatial_sorting.tex b/Spatial_sorting/doc_tex/Spatial_sorting/spatial_sorting.tex index 7c0a371fba6..58bc26026b0 100644 --- a/Spatial_sorting/doc_tex/Spatial_sorting/spatial_sorting.tex +++ b/Spatial_sorting/doc_tex/Spatial_sorting/spatial_sorting.tex @@ -1,61 +1,218 @@ -%\begin{ccHtmlOnly} -%
    -% -%
    -%\end{ccHtmlOnly} -% -%\begin{ccTexOnly} -%\begin{center} -%\includegraphics[width=6.5cm]{Convex_hull_2/saarhull} -%%\leavevmode\epsfxsize8cm\epsffile{Convex_hull_2/saarhull.eps} -%\end{center} -%\end{ccTexOnly} + +\section{Introduction} + +Many geometric algorithms implemented in \cgal\ are incremental, and thus their +speed is dependent on the order of insertion. This package provides sorting +algorithms that may considerably improve running times of such +algorithms. + +The rationale is to sort objects along a space-filling curve +so that two +objects close geometrically will be close in the insertion order with high +probability. That way, parts of a data structure that will be looked at during +an insertion will probably have been looked at in a recent insertion, and thus +probably will be in cache memory instead of main memory. +As another side-effect, these sorting functions usually improve memory locality +of the data structures produced by incremental algorithms, sometimes leading to +speed ups in other algorithm using these data structures. + +Some algorithms have a good complexity under randomized hypotheses which +contradicts the idea of sorting the input using any sorting criterion. +In such a case, it is possible to introduce just a bit of randomness +to be able to combine the good randomized complexity and the +good effects of locality \cite{acr-icb-03}. + + +The predicates used by this package are comparisons between coordinates, +thus there is no robustness issue involved here, for example to choose the +arithmetic of the kernel. + + +\section{Hilbert Sorting\label{sec:hilbert_sorting}} + + +In 2D, one can construct a space filling curve, that is a mapping $f$ of $[0,1]$ +to the unit square $[0,1]^2$, such that $f(0)=(0,0)$ and $f(1)=(1,0)$ + in the following way: +the unit square is subdivided in four such that\\ +\begin{quote} +$f([0,\frac{1}{4}])=[0,\frac{1}{2}]^2$, +$f([\frac{1}{4},\frac{1}{2}])=[0,\frac{1}{2}]\times[\frac{1}{2},1]$, +$f([\frac{1}{2},\frac{3}{4}])=[\frac{1}{2},1]^2$, +and +$f([\frac{3}{4},1])=[\frac{1}{2},1]\times[0,\frac{1}{2}].$\\ +$f(\frac{1}{4})=(0,\frac{1}{2})$\\ +$f(\frac{1}{2})=(\frac{1}{2},\frac{1}{2})$, and +$f(\frac{3}{4})=(1,\frac{1}{2})$. +\end{quote} + +Then each square is subdivided in the same way recursively. +Figure~\ref{Spatial_sorting_fig_Hilbert8} illustrates this process. + +\begin{figure} +\begin{ccHtmlOnly} +
    + +
    +\end{ccHtmlOnly} +\begin{ccTexOnly} +\begin{center} +\includegraphics[width=11.5cm]{Spatial_sorting/fig/Hilbert8} +\end{center} +\end{ccTexOnly} +\caption{Hilbert mapping +\label{Spatial_sorting_fig_Hilbert8}} +\end{figure} + +Now given a set of 2D points, they can be sorted in the order they have on such +a space filling curve as illustrated in Figure~\ref{Spatial_sorting_fig_Hilbert_middle} : + +\begin{figure}[h] +\begin{ccHtmlOnly} +
    + +
    +\end{ccHtmlOnly} +\begin{ccTexOnly} +\begin{center} +\includegraphics[width=6.5cm]{Spatial_sorting/fig/Hilbert-middle} +\end{center} +\end{ccTexOnly} +\caption{Hilbert sort with middle policy +\label{Spatial_sorting_fig_Hilbert_middle}} +\end{figure} + +\begin{ccTexOnly} +\newpage +\end{ccTexOnly} + +\subsection{Examples} + +The code to use Hilbert sort is as simple as the following example: + +\ccIncludeExampleCode{Spatial_sorting/hilbert.cpp} + + +If instead of subdividing the square in a fixed way at its middle point, + as above, we subdivide it +by splitting at the median point (in $x$ or $y$ directions alternating), +we construct a 2-d tree adapted to the point set. This tree can be visited in a +similar manner and we get also a suitable ordering of the points +(see Figure~\ref{Spatial_sorting_fig_Hilbert_median}). + + +\begin{figure}[t] +\begin{ccHtmlOnly} +
    + +
    +\end{ccHtmlOnly} +\begin{ccTexOnly} +\begin{center} +\includegraphics[width=6.5cm]{Spatial_sorting/fig/Hilbert-median} +\end{center} +\end{ccTexOnly} +\caption{Hilbert sort with median policy +\label{Spatial_sorting_fig_Hilbert_median}} +\end{figure} + + +\cgal\ provides Hilbert sorting for points in 2D, 3D and higher dimensions, +in the middle and the median policies. + +The middle policy is easier to analyze, and is interesting in practice +for well distributed set of points in small dimension (if the number +of points is really smaller than $2^d$). +The median policy should be prefered for high dimension or if +the point set distribution is not regular (or unknown). +Since the median policy cannot be much worse than the middle +policy, while the converse can happen, the median policy is the +default behavior. +Most theoretical results are using the middle policy +\cite{acr-icb-03,b-aahsf-71,bg-sfche-89,pb-scpts-89}. + + +This other example illustrates the use of the two different policies + + +\ccIncludeExampleCode{Spatial_sorting/hilbert_policies.cpp} + \section{Spatial Sorting\label{sec:spatial_sorting}} -\cgal\ provides a small set of sorting algorithms, currently implemented only for 2D and 3D points, although it is easy to extend them to other objects through a traits mechanism. +Hilbert sort cannot be used directly before feeding a randomized algorithm. +Thus, the trick is to organize the point set in random buckets of increasing +sizes, Hilbert sort being used only inside a bucket. -Given an iterator range of points, the function \ccc{hilbert_sort} sorts them -along the space-filling Hilbert curve. -Combined with a \ccc{std::random_shuffle}, the function \ccc{spatial_sort} will -sort points in a way keeping enough randomness to retain theoretical optimality -for some algorithms\footnote{in fact, this has only been proved for Delaunay triangulation}, -and close enough to a space-filling curve to speed-up algorithms. - -The 2D and 3D triangulation classes of \cgal\ internally sort points as described -above, when the points are passed as an iterator range to a constructor or the -\ccc{insert} method. +It has been proved, in the context of Delaunay triangulation, that +such an order provides enough randomness to combine the advantages of a random + order and a space filling curve order \cite{acr-icb-03}. -\section{Examples} +\cgal\ provides spatial sorting for points in 2D, 3D and higher dimensions, +with the middle and the median policies for Hilbert sort in the buckets. -In the following three examples you will see how to apply -spatial sort to \cgal\ points, or on the indices into -a container with points, or on a user defined point class. +\subsection{Basic Example} -\subsection{Sorting Points} +The following example shows that, on particular input, spatial sort +runs much faster than a bad order or than Hilbert sort (below results +with release mode compilation on a 1.8GHz processor). +\begin{verbatim} +$ ./small_example_delaunay_2 +10000 points on a parabola + Delaunay without spatial sort... done in 6.33443 seconds. + Delaunay with median hilbert sort... done in 0.822975 seconds. + Delaunay with median spatial sort... done in 0.022415 seconds. +\end{verbatim} -When you construct a triangulation from an iterator range of -points, the points get spatially sorted internally. +\ccIncludeExampleCode{Spatial_sorting/small_example_delaunay_2.cpp} -If you have a need for inserting the points one by one -you might sort them yourself. - -\ccIncludeExampleCode{Spatial_sorting/example_delaunay_2.cpp} - - -\subsection{Sorting Indices} - -If you do not want to reorder your input, you can -sort indices in your input instead. - -\ccIncludeExampleCode{Spatial_sorting/sort_indices.cpp} - - -\subsection{Sorting User Defined Points} +%Next example describes how a traits class different than CGAL Kernel can be +%used to sort a container of handle on points instead of points directly. +%\ccIncludeExampleCode{Spatial_sorting/sort_indices.cpp} +\subsection{Using Your Own Point Type} If you want to sort points of your own point type, you only have to provide functors that compare -the \ccc{x} and \ccc{y} coordinates of your points. +the \ccc{x} and \ccc{y} coordinates of your points. Note that in case you simply want +to associate an extra information to your point you might consider the example of Section +\ref{sec:sort_any_type_2} +as an alternative. \ccIncludeExampleCode{Spatial_sorting/myPoint.cpp} + +\subsection{Sorting Arbitrary Types} +\label{sec:sort_any_type} +The spatial sorting traits class provides a point type and +functors for comparing, for example, the \ccc{x}-coordinates +of two points. +% +If you want to sort something else than just points, for example +a sequence of tuples containing a point, or a sequence of indices +in a vector of points, you need another level of indirection. +% +We provide the spatial sorting traits class adapters which are templated by +another spatial sorting traits class, and a +\ccAnchor{http://www.boost.org/doc/libs/release/libs/property_map/index.html}{property map}. +which allows to obtain a point from whatever you want to sort. + +The following examples illustrate the usage of these traits class adapters. + +\subsubsection{Sorting Using Pairs of Points and Integers} +\label{sec:sort_any_type_2} +In this example program, the sorted sequence of points is retrieved +using a vector of pairs of points and integers. +\ccIncludeExampleCode{Spatial_sorting/sp_sort_using_property_map_2.cpp} + +\subsubsection{Sorting Using Indices of Points} +In this example program, the sorted sequence of points is retrieved +using the indices of the points in a vector of points. +\ccIncludeExampleCode{Spatial_sorting/sp_sort_using_property_map_3.cpp} + +\subsubsection{Sorting Using Indices of Pairs of Points and Integers} +In this example program, the sorted sequence of points is retrieved +using the indices of the points in a vector of pairs of points and integers. +\ccIncludeExampleCode{Spatial_sorting/sp_sort_using_property_map_d.cpp} + + + diff --git a/Spatial_sorting/doc_tex/Spatial_sorting/spatial_sorting_def.tex b/Spatial_sorting/doc_tex/Spatial_sorting/spatial_sorting_def.tex deleted file mode 100644 index 4de45ea4e99..00000000000 --- a/Spatial_sorting/doc_tex/Spatial_sorting/spatial_sorting_def.tex +++ /dev/null @@ -1,16 +0,0 @@ -\section{Introduction} - -Many geometric algorithms implemented in \cgal\ are incremental, and thus their -speed is dependent on the order of insertion. This package provides sorting -algorithms that may considerably improve running times of such -algorithms. - -The rationale is to sort objects along a space-filling curve so that two -objects close geometrically will be close in the insertion order with high -probability. That way, parts of a data structure that will be looked at during -an insertion will probably have been looked at in a recent insertion, and thus -probably will be in cache memory instead of main memory. - -As another side-effect, these sorting functions usually improve memory locality -of the data structures produced by incremental algorithms, sometimes leading to -speed ups in other algorithm using these data structures. diff --git a/Spatial_sorting/doc_tex/Spatial_sorting_ref/Hilbert_policy_tags.tex b/Spatial_sorting/doc_tex/Spatial_sorting_ref/Hilbert_policy_tags.tex new file mode 100644 index 00000000000..a9dd3231f55 --- /dev/null +++ b/Spatial_sorting/doc_tex/Spatial_sorting_ref/Hilbert_policy_tags.tex @@ -0,0 +1,112 @@ +\begin{ccRefClass}{Median} + +\ccDefinition +\ccRefName\ is a tag class. It can be used to parameterize a strategy policy +in order to specify the strategy for spatial sorting. +\ccc{Hilbert_policy} can be passed to +as parameter to +\ccc{hilbert_sort} to choose the sorting policy. + +\ccInclude{CGAL/Hilbert_policy_tags.h} + +\ccIsModel +\ccc{DefaultConstructible, CopyConstructible} + +\ccSeeAlso +\ccc{Middle} \\ +\ccc{Hilbert_policy} \\ +\ccc{Hilbert_sort__median_policy} \\ +\ccc{Hilbert_sort__middle_policy} + +\end{ccRefClass} + + +\begin{ccRefClass}{Middle} + +\ccDefinition +\ccRefName\ is a tag class. It can be used to parameterize a strategy policy +in order to specify the strategy for spatial sorting. +\ccc{Hilbert_policy} can be passed to +as parameter to +\ccc{hilbert_sort} to choose the sorting policy. + +\ccInclude{CGAL/Hilbert_policy_tags.h} + +\ccIsModel +\ccc{DefaultConstructible, CopyConstructible} + + +\ccSeeAlso +\ccc{Median} \\ +\ccc{Hilbert_policy} \\ +\ccc{Hilbert_sort__median_policy} \\ +\ccc{Hilbert_sort__middle_policy} + +\end{ccRefClass} + + +\begin{ccRefClass}{Hilbert_policy} + +\ccDefinition +\ccRefName\ is a policy class which can be used to parameterize a strategy policy +in order to specify the strategy for spatial sorting. +\ccc{Hilbert_policy} +or +\ccc{Hilbert_policy} +can be passed to +as parameter to +\ccc{hilbert_sort} to choose the sorting policy. + +\ccInclude{CGAL/Hilbert_policy_tags.h} + + + +\ccParameters + +\ccc{Tag} can only be either \ccc{Median} or \ccc{Middle} currently. + +\ccIsModel +\ccc{DefaultConstructible, CopyConstructible} + +\ccSeeAlso +\ccc{Median} \\ +\ccc{Middle} \\ +\ccc{Hilbert_sort__median_policy} \\ +\ccc{Hilbert_sort__middle_policy} + +\end{ccRefClass} + + +\begin{ccRefClass}{Hilbert_sort_median_policy} + +\ccDefinition +A typedef to \ccc{Hilbert_policy}. + +\ccInclude{CGAL/Hilbert_policy_tags.h} + + +\ccSeeAlso +\ccc{Median} \\ +\ccc{Middle} \\ +\ccc{Hilbert_policy} \\ +\ccc{Hilbert_sort__middle_policy} + + +\end{ccRefClass} + + +\begin{ccRefClass}{Hilbert_sort_middle_policy} + +\ccDefinition +A typedef to \ccc{Hilbert_policy}. + +\ccInclude{CGAL/Hilbert_policy_tags.h} + + +\ccSeeAlso +\ccc{Median} \\ +\ccc{Middle} \\ +\ccc{Hilbert_sort__median_policy} \\ +\ccc{Hilbert_policy} + +\end{ccRefClass} diff --git a/Spatial_sorting/doc_tex/Spatial_sorting_ref/Hilbert_sort_2.tex b/Spatial_sorting/doc_tex/Spatial_sorting_ref/Hilbert_sort_2.tex index 3d07eb3e062..26bb805c768 100644 --- a/Spatial_sorting/doc_tex/Spatial_sorting_ref/Hilbert_sort_2.tex +++ b/Spatial_sorting/doc_tex/Spatial_sorting_ref/Hilbert_sort_2.tex @@ -2,9 +2,11 @@ % | Reference manual page: Hilbert_sort_2.tex % +------------------------------------------------------------------------+ -\begin{ccRefFunctionObjectClass}{Hilbert_sort_2} +\begin{ccRefFunctionObjectClass}{Hilbert_sort_2} \ccDefinition The function object \ccRefName\ sorts iterator ranges of -\ccc{Traits::Point_2} along a Hilbert curve. +\ccc{Traits::Point_2} along a Hilbert curve by recursively subdividing +at the median +or the middle depending on the \ccc{PolicyTag}. \ccRequirements \ccc{Traits} is a model for \ccc{SpatialSortingTraits}. diff --git a/Spatial_sorting/doc_tex/Spatial_sorting_ref/Hilbert_sort_3.tex b/Spatial_sorting/doc_tex/Spatial_sorting_ref/Hilbert_sort_3.tex index 9f696e750bc..1b548776765 100644 --- a/Spatial_sorting/doc_tex/Spatial_sorting_ref/Hilbert_sort_3.tex +++ b/Spatial_sorting/doc_tex/Spatial_sorting_ref/Hilbert_sort_3.tex @@ -1,10 +1,11 @@ % +------------------------------------------------------------------------+ -% | Reference manual page: Hilbert_sort_2.tex +% | Reference manual page: Hilbert_sort_3.tex % +------------------------------------------------------------------------+ -\begin{ccRefFunctionObjectClass}{Hilbert_sort_3} +\begin{ccRefFunctionObjectClass}{Hilbert_sort_3} \ccDefinition The function object \ccRefName\ sorts iterator ranges of -\ccc{Traits::Point_3} along a Hilbert curve. +\ccc{Traits::Point_3} along a Hilbert curve by recursively subdividing at the median +or the middle depending on the \ccc{PolicyTag}. \ccRequirements \ccc{Traits} is a model for \ccc{SpatialSortingTraits_3}. diff --git a/Spatial_sorting/doc_tex/Spatial_sorting_ref/Hilbert_sort_d.tex b/Spatial_sorting/doc_tex/Spatial_sorting_ref/Hilbert_sort_d.tex new file mode 100644 index 00000000000..2eecab74e04 --- /dev/null +++ b/Spatial_sorting/doc_tex/Spatial_sorting_ref/Hilbert_sort_d.tex @@ -0,0 +1,29 @@ +% +------------------------------------------------------------------------+ +% | Reference manual page: Hilbert_sort_d.tex +% +------------------------------------------------------------------------+ + +\begin{ccRefFunctionObjectClass}{Hilbert_sort_d} +\ccDefinition The function object \ccRefName\ sorts iterator ranges of +\ccc{Traits::Point_d} along a Hilbert curve by recursively subdividing at the median +or the middle depending on the \ccc{PolicyTag}. + +\ccRequirements \ccc{Traits} is a model for \ccc{SpatialSortingTraits_d}. + +\ccTagFullDeclarations +\ccCreationVariable{o} +\ccCreation +\ccConstructor{Hilbert_sort_d(const Traits &traits = Traits())}{constructs an instance with \ccc{traits} as traits class instance.} +\ccOperations +\ccThree{void;;}{A}{} + +\ccMethod{template void operator() (RandomAccessIterator begin, RandomAccessIterator end) const;}{sorts the range [\ccc{begin}, \ccc{end}). + \ccRequire \ccc{RandomAccessIterator::value_type} equals to \ccc{Traits::Point_d}.} + + \ccTagDefaults + +\end{ccRefFunctionObjectClass} +% +------------------------------------------------------------------------+ +%%RefPage: end of main body, begin of footer +% EOF +% +------------------------------------------------------------------------+ + diff --git a/Spatial_sorting/doc_tex/Spatial_sorting_ref/SpatialSortingTraits_2.tex b/Spatial_sorting/doc_tex/Spatial_sorting_ref/SpatialSortingTraits_2.tex index ea4b1a1b82d..2808c04f27c 100644 --- a/Spatial_sorting/doc_tex/Spatial_sorting_ref/SpatialSortingTraits_2.tex +++ b/Spatial_sorting/doc_tex/Spatial_sorting_ref/SpatialSortingTraits_2.tex @@ -15,12 +15,26 @@ functions and functors. \ccTypes \ccAutoIndexingOff -\ccSetTwoColumns{SpatialSortingTraits_2::Less_x_2}{} +\ccSetTwoColumns{SpatialSortingTraits_2::Compute_x_2}{} \ccNestedType{Point_2}% {The point type on which the sorting algorithms operate.} +\ccNestedType{Compute_x_2}% + {Functor object type returning the $x$ coordinate of a \ccc{Point_2}. + Must provide + \ccc{FT operator()(Point_2 p)} where \ccc{FT} can be used as + argument of \ccc{CGAL::to_double}. + } + +\ccNestedType{Compute_y_2}% + {Functor object type returning the $y$ coordinate of a \ccc{Point_2}. + Must provide + \ccc{FT operator()(Point_2 p)} where \ccc{FT} can be used as + argument of \ccc{CGAL::to_double}. + } + \ccNestedType{Less_x_2}% {Binary predicate object type comparing \ccc{Point_2}s along the $x$ coordinate. @@ -55,6 +69,10 @@ The following member functions to create instances of the above predicate object types must exist. \setlength\parskip{0mm} +\ccMemberFunction{Compute_x_2 compute_x_2_object(); }{} +\ccGlue +\ccMemberFunction{Compute_y_2 compute_y_2_object(); }{} +\ccGlue \ccMemberFunction{Less_x_2 less_x_2_object(); }{} \ccGlue \ccMemberFunction{Less_y_2 less_y_2_object(); }{} @@ -62,7 +80,9 @@ object types must exist. \ccParDims \ccHasModels -Any \cgal{} kernel. +Any \cgal{} kernel.\\ +\ccc{CGAL::Spatial_sort_traits_adapter_2}. + \ccParDims \end{ccRefConcept} diff --git a/Spatial_sorting/doc_tex/Spatial_sorting_ref/SpatialSortingTraits_3.tex b/Spatial_sorting/doc_tex/Spatial_sorting_ref/SpatialSortingTraits_3.tex index 2741ee9ed3e..249a629e96e 100644 --- a/Spatial_sorting/doc_tex/Spatial_sorting_ref/SpatialSortingTraits_3.tex +++ b/Spatial_sorting/doc_tex/Spatial_sorting_ref/SpatialSortingTraits_3.tex @@ -15,12 +15,34 @@ functions and functors. \ccTypes \ccAutoIndexingOff -\ccSetTwoColumns{SpatialSortingTraits_3::Less_x_3}{} +\ccSetTwoColumns{SpatialSortingTraits_3::Compute_x_3}{} \ccNestedType{Point_3}% {The point type on which the sorting algorithms operate.} +\ccNestedType{Compute_x_3}% + {Functor object type returning the $x$ coordinate of a \ccc{Point_3}. + Must provide + \ccc{FT operator()(Point_3 p)} where \ccc{FT} can be used as + argument of \ccc{CGAL::to_double}. + } + +\ccNestedType{Compute_y_3}% + {Functor object type returning the $y$ coordinate of a \ccc{Point_3}. + Must provide + \ccc{FT operator()(Point_3 p)} where \ccc{FT} can be used as + argument of \ccc{CGAL::to_double}. + } + +\ccNestedType{Compute_z_3}% + {Functor object type returning the $z$ coordinate of a \ccc{Point_3}. + Must provide + \ccc{FT operator()(Point_3 p)} where \ccc{FT} can be used as + argument of \ccc{CGAL::to_double}. + } + + \ccNestedType{Less_x_3}% {Binary predicate object type comparing \ccc{Point_3}s along the $x$ coordinate. @@ -65,6 +87,12 @@ The following member functions to create instances of the above predicate object types must exist. \setlength\parskip{0mm} +\ccMemberFunction{Compute_x_3 compute_x_3_object(); }{} +\ccGlue +\ccMemberFunction{Compute_y_3 compute_y_3_object(); }{} +\ccGlue +\ccMemberFunction{Compute_z_3 compute_z_3_object(); }{} +\ccGlue \ccMemberFunction{Less_x_3 less_x_3_object(); }{} \ccGlue \ccMemberFunction{Less_y_3 less_y_3_object(); }{} @@ -74,7 +102,8 @@ object types must exist. \ccParDims \ccHasModels -Any \cgal{} kernel. +Any \cgal{} kernel.\\ +\ccc{CGAL::Spatial_sort_traits_adapter_3}. \ccParDims \end{ccRefConcept} diff --git a/Spatial_sorting/doc_tex/Spatial_sorting_ref/SpatialSortingTraits_d.tex b/Spatial_sorting/doc_tex/Spatial_sorting_ref/SpatialSortingTraits_d.tex new file mode 100644 index 00000000000..ec30e68a776 --- /dev/null +++ b/Spatial_sorting/doc_tex/Spatial_sorting_ref/SpatialSortingTraits_d.tex @@ -0,0 +1,80 @@ +% +------------------------------------------------------------------------+ +% | Reference manual page: SpatialSortingTraits_d.tex +% +------------------------------------------------------------------------+ + + +\begin{ccRefConcept}{SpatialSortingTraits_d} + +\ccDefinition + +All higher dimensional spatial sorting algorithms provided in \cgal{} are parameterized +by a traits class \ccStyle{Traits}, which defines the +primitives (objects and predicates) that the sorting algorithms use. +\ccRefName\ defines the complete set of primitives required in these +functions and functors. + +\ccTypes +\ccAutoIndexingOff +\ccSetTwoColumns{SpatialSortingTraits_3::Compute_coordinate_d}{} + +\ccNestedType{Point_d}% + {The point type on which the sorting algorithms operate. + } + + +\ccNestedType{Point_dimension_d}% + {Functor object type returning the dimension of a \ccc{Point_d}. + Must provide + \ccc{int operator()(Point_d p)} returning the dimension of $p$. + } + +\ccNestedType{Compute_coordinate_d}% + {Functor object type returning the coordinates of a \ccc{Point_d}. + Must provide + \ccc{FT operator()(Point_d p, int i)} returning the $i$th + coordinate of $p$. \ccc{FT} is a type that can be used as + argument of \ccc{CGAL::to_double}. + } + + +\ccNestedType{Less_coordinate_d}% + {Binary predicate object type comparing \ccc{Point_d}s + along some coordinate. + Must provide + \ccc{bool operator()(Point_d p, Point_d q, int i)} where \ccc{true} + is returned iff $p_i < q_i$, + where $p_i$ and $q_i$ denote $i$th coordinate of point $p$ and $q$, + respectively. + } + +\ccCreation +\ccCreationVariable{traits} %% choose variable name + +Only a copy constructor is required. + +\ccConstructor{SpatialSortingTraits_d(const SpatialSortingTraits_d& t);}{} + +\ccOperations + +The following member functions to create instances of the above predicate +object types must exist. + +\setlength\parskip{0mm} +\ccMemberFunction{Point_dimension_d point_dimension_d_object(); }{} +\ccMemberFunction{Compute_coordinate_d compute_coordinate_d_object(); }{} +\ccMemberFunction{Less_coordinate_d less_coordinate_d_object(); }{} + +\ccParDims +\ccHasModels + +Any \cgal{} $d$ dimensional kernel.\\ +\ccc{CGAL::Spatial_sort_traits_adapter_d}. + +\ccParDims +\end{ccRefConcept} + +% +------------------------------------------------------------------------+ +%%RefPage: end of main body, begin of footer +% EOF +% +------------------------------------------------------------------------+ + diff --git a/Spatial_sorting/doc_tex/Spatial_sorting_ref/Spatial_sort_traits_adapter_2.tex b/Spatial_sorting/doc_tex/Spatial_sorting_ref/Spatial_sort_traits_adapter_2.tex new file mode 100644 index 00000000000..1ff3e212beb --- /dev/null +++ b/Spatial_sorting/doc_tex/Spatial_sorting_ref/Spatial_sort_traits_adapter_2.tex @@ -0,0 +1,36 @@ +\begin{ccRefClass}{Spatial_sort_traits_adapter_2} + +\ccDefinition + +Given a property map associating a key to a point, the class \ccRefName\ induces a spatial +reorder of the keys instead of the points, the comparisons being done on the associated points. +In other words, the traits provides to a spatial sort algorithm a point type which is a key, +while the actual point type is \ccc{Base_traits::Point_2}. + +\ccRequirements \ccc{Base_traits} is a model for \ccc{SpatialSortingTraits_2}. +\ccc{PointPropertyMap} is a model of \ccAnchor{http://www.boost.org/doc/libs/release/libs/property_map/doc/ReadablePropertyMap.html}{boost::ReadablePropertyMap} +with \ccc{Base_traits::Point_2} as \ccc{value_type}. + + +\ccInheritsFrom +\ccc{Base_traits} + +\ccIsModel +\ccc{SpatialSortingTraits_2} + +\ccTypes +\ccTypedef{boost::property_traits::key_type Point_2;}{} + +\ccTagFullDeclarations +\ccCreationVariable{o} +\ccCreation +\ccConstructor{Spatial_sort_traits_adapter_2(Base_traits base=Base_traits());}{} +\ccConstructor{Spatial_sort_traits_adapter_2(const PointPropertyMap& ppmap,Base_traits base=Base_traits());}{} + +\ccOperations +\ccThree{void;;}{A}{} + +\ccMethod{const PointPropertyMap& point_property_map() const;}{Returns a const reference to the point property map.} + + +\end{ccRefClass} diff --git a/Spatial_sorting/doc_tex/Spatial_sorting_ref/Spatial_sort_traits_adapter_3.tex b/Spatial_sorting/doc_tex/Spatial_sorting_ref/Spatial_sort_traits_adapter_3.tex new file mode 100644 index 00000000000..c90c6e167e4 --- /dev/null +++ b/Spatial_sorting/doc_tex/Spatial_sorting_ref/Spatial_sort_traits_adapter_3.tex @@ -0,0 +1,35 @@ +\begin{ccRefClass}{Spatial_sort_traits_adapter_3} + +\ccDefinition + +Given a property map associating a key to a point, the class \ccRefName\ induces a spatial +reorder of the keys instead of the points, the comparisons being done on the associated points. +In other words, the traits provides to a spatial sort algorithm a point type which is a key, +while the actual point type is \ccc{Base_traits::Point_3}. + +\ccRequirements \ccc{Base_traits} is a model for \ccc{SpatialSortingTraits_3}. +\ccc{PointPropertyMap} is a model of \ccAnchor{http://www.boost.org/doc/libs/release/libs/property_map/doc/ReadablePropertyMap.html}{boost::ReadablePropertyMap} +with \ccc{Base_traits::Point_3} as \ccc{value_type}. + +\ccInheritsFrom +\ccc{Base_traits} + +\ccIsModel +\ccc{SpatialSortingTraits_3} + +\ccTypes +\ccTypedef{boost::property_traits::key_type Point_3;}{} + +\ccTagFullDeclarations +\ccCreationVariable{o} +\ccCreation +\ccConstructor{Spatial_sort_traits_adapter_3(Base_traits base=Base_traits());}{} +\ccConstructor{Spatial_sort_traits_adapter_3(const PointPropertyMap& ppmap,Base_traits base=Base_traits());}{} + +\ccOperations +\ccThree{void;;}{A}{} + +\ccMethod{const PointPropertyMap& point_property_map() const;}{Returns a const reference to the point property map.} + + +\end{ccRefClass} diff --git a/Spatial_sorting/doc_tex/Spatial_sorting_ref/Spatial_sort_traits_adapter_d.tex b/Spatial_sorting/doc_tex/Spatial_sorting_ref/Spatial_sort_traits_adapter_d.tex new file mode 100644 index 00000000000..f69cff26075 --- /dev/null +++ b/Spatial_sorting/doc_tex/Spatial_sorting_ref/Spatial_sort_traits_adapter_d.tex @@ -0,0 +1,36 @@ +\begin{ccRefClass}{Spatial_sort_traits_adapter_d} + +\ccDefinition + +Given a property map associating a key to a point, the class \ccRefName\ induces a spatial +reorder of the keys instead of the points, the comparisons being done on the associated points. +In other words, the traits provides to a spatial sort algorithm a point type which is a key, +while the actual point type is \ccc{Base_traits::Point_d}. + +\ccRequirements \ccc{Base_traits} is a model for \ccc{SpatialSortingTraits_d}. +\ccc{PointPropertyMap} is a model of \ccAnchor{http://www.boost.org/doc/libs/release/libs/property_map/doc/ReadablePropertyMap.html}{boost::ReadablePropertyMap} +with \ccc{Base_traits::Point_d} as \ccc{value_type}. + + +\ccInheritsFrom +\ccc{Base_traits} + +\ccIsModel +\ccc{SpatialSortingTraits_d} + +\ccTypes +\ccTypedef{boost::property_traits::key_type Point_d;}{} + +\ccTagFullDeclarations +\ccCreationVariable{o} +\ccCreation +\ccConstructor{Spatial_sort_traits_adapter_d(Base_traits base=Base_traits());}{} +\ccConstructor{Spatial_sort_traits_adapter_d(const PointPropertyMap& ppmap,Base_traits base=Base_traits());}{} + +\ccOperations +\ccThree{void;;}{A}{} + +\ccMethod{const PointPropertyMap& point_property_map() const;}{Returns a const reference to the point property map.} + + +\end{ccRefClass} diff --git a/Spatial_sorting/doc_tex/Spatial_sorting_ref/hilbert_sort.tex b/Spatial_sorting/doc_tex/Spatial_sorting_ref/hilbert_sort.tex index 7980faf7ff7..1cdfa31e3f4 100644 --- a/Spatial_sorting/doc_tex/Spatial_sorting_ref/hilbert_sort.tex +++ b/Spatial_sorting/doc_tex/Spatial_sorting_ref/hilbert_sort.tex @@ -21,27 +21,34 @@ along a Hilbert curve. \ccInclude{CGAL/hilbert_sort.h} -\ccGlobalFunction{template +\ccGlobalFunction{template void hilbert_sort( RandomAccessIterator begin, RandomAccessIterator end, - const Traits& traits = Default_traits);}% + const Traits& traits = Default_traits, + PolicyTag policy = Default_policy);} {sorts the range [\ccc{begin},\ccc{end}) in place.} The default traits class \ccc{Default_traits} is the kernel in which the type \ccc{RandomAccessIterator::value_type} is defined. +The default policy is \ccc{Hilbert_sort_median_policy()} and the +other option is \ccc{Hilbert_sort_middle_policy()}. \ccHeading{Requirements} \begin{enumerate} \item \ccc{RandomAccessIterator::value_type} is convertible to -\ccc{Traits::Point_2} or \ccc{Traits::Point_3}. -\item \ccc{Traits} is a model for concept \ccc{SpatialSortingTraits_2} or \ccc{SpatialSortingTraits_3}. +\ccc{Traits::Point_2}, \ccc{Traits::Point_3}, or \ccc{Traits::Point_d}. +\item \ccc{Traits} is a model for concept \ccc{SpatialSortingTraits_2}, + \ccc{SpatialSortingTraits_3}, or \ccc{SpatialSortingTraits_d}. \end{enumerate} \ccImplementation -Creates an instance of \ccc{Hilbert_sort_2} or -\ccc{Hilbert_sort_3} and calls its \ccc{operator()}. +Creates an instance of +\ccc{Hilbert_sort_2}, +\ccc{Hilbert_sort_3}, or +\ccc{Hilbert_sort_d} +and calls its \ccc{operator()}. %\ccc{Some_other_class}, %\ccc{some_other_function}. diff --git a/Spatial_sorting/doc_tex/Spatial_sorting_ref/intro.tex b/Spatial_sorting/doc_tex/Spatial_sorting_ref/intro.tex index 932eb8ad57c..f06bd424fa3 100644 --- a/Spatial_sorting/doc_tex/Spatial_sorting_ref/intro.tex +++ b/Spatial_sorting/doc_tex/Spatial_sorting_ref/intro.tex @@ -7,7 +7,7 @@ \ccRefChapter{Spatial Sorting\label{chap:spatialsortingref}} -\ccChapterAuthor{Christophe Delage} +\ccChapterAuthor{Christophe Delage \and Olivier Devillers} \ccHeading{Functions} @@ -17,11 +17,27 @@ \ccHeading{Function Objects} \ccRefIdfierPage{CGAL::Multiscale_sort} \\ -\ccRefIdfierPage{CGAL::Hilbert_sort_2} \\ -\ccRefIdfierPage{CGAL::Hilbert_sort_3} \\ +\ccRefIdfierPage{CGAL::Hilbert_sort_2} \\ +\ccRefIdfierPage{CGAL::Hilbert_sort_3} \\ +\ccRefIdfierPage{CGAL::Hilbert_sort_d} \\ + +\ccHeading{Traits classes} +\ccRefIdfierPage{CGAL::Spatial_sort_traits_adapter_2} \\ +\ccRefIdfierPage{CGAL::Spatial_sort_traits_adapter_3} \\ +\ccRefIdfierPage{CGAL::Spatial_sort_traits_adapter_d} \\ \ccHeading{Concepts} \ccRefIdfierPage{SpatialSortingTraits_2} \\ \ccRefIdfierPage{SpatialSortingTraits_3} \\ +\ccRefIdfierPage{SpatialSortingTraits_d} \\ + + +\ccHeading{Utilities} + +\ccRefIdfierPage{CGAL::Median}\\ +\ccRefIdfierPage{CGAL::Middle}\\ +\ccRefIdfierPage{CGAL::Hilbert_policy}\\ +\ccRefIdfierPage{CGAL::Hilbert_sort_median_policy}\\ +\ccRefIdfierPage{CGAL::Hilbert_sort_middle_policy} diff --git a/Spatial_sorting/doc_tex/Spatial_sorting_ref/main.tex b/Spatial_sorting/doc_tex/Spatial_sorting_ref/main.tex index 1b92cc657c0..dc005400549 100644 --- a/Spatial_sorting/doc_tex/Spatial_sorting_ref/main.tex +++ b/Spatial_sorting/doc_tex/Spatial_sorting_ref/main.tex @@ -13,6 +13,12 @@ \input{Spatial_sorting_ref/Hilbert_sort_2.tex} \input{Spatial_sorting_ref/SpatialSortingTraits_3.tex} \input{Spatial_sorting_ref/Hilbert_sort_3.tex} +\input{Spatial_sorting_ref/SpatialSortingTraits_d.tex} +\input{Spatial_sorting_ref/Hilbert_sort_d.tex} \input{Spatial_sorting_ref/Multiscale_sort.tex} +\input{Spatial_sorting_ref/Hilbert_policy_tags.tex} +\input{Spatial_sorting_ref/Spatial_sort_traits_adapter_2.tex} +\input{Spatial_sorting_ref/Spatial_sort_traits_adapter_3.tex} +\input{Spatial_sorting_ref/Spatial_sort_traits_adapter_d.tex} %% EOF diff --git a/Spatial_sorting/doc_tex/Spatial_sorting_ref/spatial_sort.tex b/Spatial_sorting/doc_tex/Spatial_sorting_ref/spatial_sort.tex index fe348ab6aa5..3a88692347a 100644 --- a/Spatial_sorting/doc_tex/Spatial_sorting_ref/spatial_sort.tex +++ b/Spatial_sorting/doc_tex/Spatial_sorting_ref/spatial_sort.tex @@ -23,28 +23,50 @@ of being close in the order. \ccInclude{CGAL/spatial_sort.h} -\ccGlobalFunction{template +\ccGlobalFunction{template void spatial_sort( RandomAccessIterator begin, RandomAccessIterator end, - const Traits& traits = Default_traits);}% + const Traits& traits = Default_traits, + PolicyTag policy = Default_policy, + std::ptrdiff_t threshold_hilbert=default, + std::ptrdiff_t threshold_multiscale=default, + double ratio=default);}% {sorts the range [\ccc{begin},\ccc{end}) in place.} The default traits class \ccc{Default_traits} is the kernel in which the type \ccc{RandomAccessIterator::value_type} is defined. +The default policy is \ccc{Hilbert_sort_median_policy()} and the +other option is \ccc{Hilbert_sort_middle_policy()}. + +The default values for the thresholds and the ratio depends on the dimension. + + \ccHeading{Requirements} \begin{enumerate} \item \ccc{RandomAccessIterator::value_type} is convertible to -\ccc{Traits::Point_2} or \ccc{Traits::Point_3}. -\item \ccc{Traits} is a model for concept \ccc{SpatialSortingTraits_2} or \ccc{SpatialSortingTraits_3}. +\ccc{Traits::Point_2}, \ccc{Traits::Point_3}, or \ccc{Traits::Point_d}. +\item \ccc{Traits} is a model for concept \ccc{SpatialSortingTraits_2}, + \ccc{SpatialSortingTraits_3}, or \ccc{SpatialSortingTraits_d}. \end{enumerate} \ccImplementation -Creates an instance of \ccc{Multiscale_sort>} -or \ccc{Multiscale_sort>} and calls its \ccc{operator()}. +Creates an instance of \ccc{Multiscale_sort} +where \ccStyle{Hilbert_sort} is an Hilbert sorting object, +and calls its \ccc{operator()}. + +The \ccStyle{threshold_hilbert} is the minimal size of a point set to be +subdivided recursively during Hilbert sorting, otherwise random order is used. + The \ccStyle{threshold_multiscale} value is the minimal size for a sample to +call Hilbert sort, otherwise random order is used. +The \ccStyle{ratio} value is used to split the original set in two subsets, +spatial sort is applied on the first subset of size +\ccStyle{ratio} +times the original size of the set, Hilbert sort is applied on the +second subset. %\ccc{Some_other_class}, %\ccc{some_other_function}. diff --git a/Spatial_sorting/dont_submit b/Spatial_sorting/dont_submit deleted file mode 100644 index 606782a434f..00000000000 --- a/Spatial_sorting/dont_submit +++ /dev/null @@ -1,3 +0,0 @@ -examples/Spatial_sorting/*.cmd -examples/Spatial_sorting/data/input.cin -examples/Spatial_sorting/data diff --git a/Spatial_sorting/examples/Spatial_sorting/data/input.cin b/Spatial_sorting/examples/Spatial_sorting/data/input.cin deleted file mode 100644 index 2299ded9baf..00000000000 --- a/Spatial_sorting/examples/Spatial_sorting/data/input.cin +++ /dev/null @@ -1,8 +0,0 @@ -1 0 -3 2 -4 5 -9 8 -7 4 -5 2 -6 3 -10 1 diff --git a/Spatial_sorting/examples/Spatial_sorting/example_delaunay_2.cmd b/Spatial_sorting/examples/Spatial_sorting/example_delaunay_2.cmd deleted file mode 100644 index d391bf0a1c3..00000000000 --- a/Spatial_sorting/examples/Spatial_sorting/example_delaunay_2.cmd +++ /dev/null @@ -1 +0,0 @@ -< data/input.cin \ No newline at end of file diff --git a/Spatial_sorting/examples/Spatial_sorting/example_delaunay_2.cpp b/Spatial_sorting/examples/Spatial_sorting/example_delaunay_2.cpp index 42994ea2baf..e421604778f 100644 --- a/Spatial_sorting/examples/Spatial_sorting/example_delaunay_2.cpp +++ b/Spatial_sorting/examples/Spatial_sorting/example_delaunay_2.cpp @@ -1,6 +1,9 @@ #include #include #include +#include +#include +#include #include #include @@ -9,31 +12,68 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Delaunay_triangulation_2 DT; +typedef K::Point_2 Point; +typedef CGAL::Creator_uniform_2 Creator_2; + +void compute_delaunay(std::vector::iterator it, + std::vector::iterator e){ + DT dt; + DT::Face_handle hint; + for( ;it!=e; ++it) hint = dt.insert(*it, hint)->face(); + return; +} + +void test_orders(std::vector::iterator b, + std::vector::iterator e){ + CGAL::Timer cost; + + cost.reset();cost.start(); + std::cout << " Delaunay without spatial sort... "<< std::flush; + compute_delaunay(b,e);cost.stop(); + std::cout << "done in "< v; +{ int size1 = 1000,size2=100000; + std::vector v,w; + v.reserve(size1);w.reserve(size2); - std::cout << "Reading..." << std::endl; - std::istream_iterator begin(std::cin), end; - std::copy(begin, end, std::back_inserter(v)); + std::cout <::const_iterator p = v.begin(); p != v.end(); ++p) - f = dt.insert(*p, f)->face(); - - std::cout << "Delaunay is_valid()..." << std::endl; - dt.is_valid(); - - std::cout << "Ok." << std::endl; - - return 0; + CGAL::Random random (42); + CGAL::Random_points_in_square_2 gen (1.0, random); + std::cout < +#include +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::Point_2 Point; +typedef CGAL::Creator_uniform_2 Creator; + +int main () +{ + std::size_t size = 16; + std::vector v; v.reserve(size); + CGAL::points_on_square_grid_2(3.0, size, // generate points + std::back_inserter(v), Creator()); + + CGAL::hilbert_sort (v.begin(), v.end()); // sort + + for(std::size_t i=0; i +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::Point_2 Point; + +int main () +{ + std::vector v; v.reserve(4); + v.push_back( Point(0.0,0.0)) ; + v.push_back( Point(1.0,1.0)) ; + v.push_back( Point(0.1,0.1)) ; + v.push_back( Point(0.2,0.8)) ; + + std::cout << "Hilbert sort (middle policy)." << std::endl; + CGAL::hilbert_sort (v.begin(), v.end(), CGAL::Hilbert_sort_middle_policy()); + std::cout< points; - points[0] = MyPoint(78,12); - points[1] = MyPoint(3,121); + points.push_back(MyPoint(14,12, 3)); + points.push_back(MyPoint(1,2 , 0)); + points.push_back(MyPoint(414,2, 5)); + points.push_back(MyPoint(4,21 , 1)); + points.push_back(MyPoint(7,74 , 2)); + points.push_back(MyPoint(74,4 , 4)); + MySpatialSortingTraits sst; - CGAL::spatial_sort(points, points+2, sst); + CGAL::spatial_sort(points.begin(), points.end(), sst); + + for (std::vector< MyPoint >::iterator it=points.begin();it!=points.end();++it) + std::cout << it->color << " "; + std::cout << "\n"; + std::cerr << "done" << std::endl; return 0; } diff --git a/Spatial_sorting/examples/Spatial_sorting/small_example_delaunay_2.cpp b/Spatial_sorting/examples/Spatial_sorting/small_example_delaunay_2.cpp new file mode 100644 index 00000000000..a38465e54ae --- /dev/null +++ b/Spatial_sorting/examples/Spatial_sorting/small_example_delaunay_2.cpp @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include +#include +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Delaunay_triangulation_2 DT; +void compute_delaunay(std::vector::iterator it, + std::vector::iterator e){ + DT dt; + DT::Face_handle hint; + for( ;it!=e; ++it) hint = dt.insert(*it, hint)->face(); +} +int main () +{ int size = 1000; + std::vector v; + v.reserve(size); + CGAL::Timer cost; + std::cout < +#include #include - - -typedef CGAL::Simple_cartesian K; -typedef K::Point_2 Point_2; -typedef std::vector::iterator Point_iterator; - - - +#include +// Below is a traits class that allow to dereference before comparing +// coordinates. Requirements are to define in the traits class : +// Point_2, Less_x_2, less_x_2_object, Less_y_2, and less_y_2_object template -struct Sort_traits_2 { - +struct Dereference_traits_2 { Kernel k; - - Sort_traits_2 (const Kernel &kernel = Kernel()) - : k (kernel) - {} - + Dereference_traits_2 (const Kernel &kernel = Kernel()) : k (kernel) {} typedef Iterator Point_2; - struct Less_x_2 { Kernel k; - Less_x_2 (const Kernel &kernel = Kernel()) - : k (kernel) - {} + Less_x_2 (const Kernel &kernel = Kernel()): k (kernel) {} bool operator() (const Point_2 &p, const Point_2 &q) const - { + { // dereference then compare return k.less_x_2_object() (*p, *q); } }; - - Less_x_2 - less_x_2_object() const - { - return Less_x_2(k); - } - - struct Less_y_2 { + Less_x_2 less_x_2_object() const { return Less_x_2(k); } + struct Less_y_2 { // Same stuff for y direction Kernel k; - Less_y_2 (const Kernel &kernel = Kernel()) - : k (kernel) - {} - bool operator() (const Point_2 &p, const Point_2 &q) const - { - return k.less_y_2_object() (*p, *q); - } + Less_y_2 (const Kernel &kernel = Kernel()): k (kernel) {} + bool operator() (const Point_2 &p, const Point_2 &q) const + { return k.less_y_2_object() (*p, *q); } }; - - - Less_y_2 - less_y_2_object() const - { - return Less_y_2(k); - } + Less_y_2 less_y_2_object() const { return Less_y_2(k); } }; - - -typedef CGAL::Hilbert_sort_2 > Hilbert_sort_2; -typedef CGAL::Multiscale_sort Spatial_sort_2; - - - - +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::Point_2 Point; +typedef std::vector::iterator Point_it; +typedef CGAL::Hilbert_sort_2, + CGAL::Hilbert_sort_median_policy > H_sort; +typedef CGAL::Multiscale_sort My_sort; int main () { - Spatial_sort_2 sort_2; + My_sort my_sort; + std::size_t size = 10; + std::vector points; points.reserve(size); + std::vector iterators; iterators.reserve(size); + CGAL::Random_points_in_square_2 gen (10.0); - std::vector points; - std::vector iterators; - - Point_2 p; - while(std::cin >> p){ - points.push_back(p); - } - - iterators.reserve(points.size()); - for(Point_iterator it = points.begin(); it != points.end(); ++it){ + for (std::size_t i = 0; i < size; ++i) points.push_back (*gen++); + for(Point_it it = points.begin(); it != points.end(); ++it) iterators.push_back(it); - } - - sort_2(iterators.begin(), iterators.end()); - - for(std::vector::iterator i = iterators.begin(); - i != iterators.end(); i++) - { - std::cout << **i << std::endl; - } - + my_sort(iterators.begin(), iterators.end()); + for(std::vector::iterator i = iterators.begin(); + i != iterators.end(); i++) std::cout << **i << std::endl; return 0; } diff --git a/Spatial_sorting/examples/Spatial_sorting/sp_sort_using_property_map_2.cpp b/Spatial_sorting/examples/Spatial_sorting/sp_sort_using_property_map_2.cpp new file mode 100644 index 00000000000..cffcfd2f980 --- /dev/null +++ b/Spatial_sorting/examples/Spatial_sorting/sp_sort_using_property_map_2.cpp @@ -0,0 +1,46 @@ +#include +#include +#include +#include + +typedef CGAL::Simple_cartesian Kernel; +typedef Kernel::Point_2 Point_2; +typedef std::pair Point_with_info; +typedef std::vector< Point_with_info > Data_vector; + +//property map +struct First_of_pair{ + //classical typedefs + typedef Point_with_info key_type; + typedef Point_2 value_type; + typedef const Point_2& reference; + typedef boost::readable_property_map_tag category; +}; +//get function for property map +First_of_pair::reference +get(const First_of_pair&, const First_of_pair::key_type& k) { + return k.first; +} + +typedef CGAL::Spatial_sort_traits_adapter_2 Search_traits_2; + +int main() +{ + Data_vector points; + points.push_back(std::make_pair(Point_2(14,12) , 3)); + points.push_back(std::make_pair(Point_2(1,2) , 0)); + points.push_back(std::make_pair(Point_2(414,2) , 5)); + points.push_back(std::make_pair(Point_2(4,21) , 1)); + points.push_back(std::make_pair(Point_2(7,74) , 2)); + points.push_back(std::make_pair(Point_2(74,4) , 4)); + + Search_traits_2 traits; + CGAL::spatial_sort(points.begin(), points.end(), traits); + for (Data_vector::iterator it=points.begin();it!=points.end();++it) + std::cout << it->second << " "; + std::cout << "\n"; + + std::cout << "done" << std::endl; + + return 0; +} diff --git a/Spatial_sorting/examples/Spatial_sorting/sp_sort_using_property_map_3.cpp b/Spatial_sorting/examples/Spatial_sorting/sp_sort_using_property_map_3.cpp new file mode 100644 index 00000000000..ab48feafc9f --- /dev/null +++ b/Spatial_sorting/examples/Spatial_sorting/sp_sort_using_property_map_3.cpp @@ -0,0 +1,38 @@ +#include +#include +#include +#include +#include + +typedef CGAL::Simple_cartesian Kernel; +typedef Kernel::Point_3 Point_3; +//using a pointer as a special property map type +typedef + CGAL::Spatial_sort_traits_adapter_3 Search_traits_3; + +int main() +{ + std::vector points; + points.push_back(Point_3(1,3,11)); + points.push_back(Point_3(14,34,46)); + points.push_back(Point_3(414,34,4)); + points.push_back(Point_3(4,2,56)); + points.push_back(Point_3(744,4154,43)); + points.push_back(Point_3(74,44,1)); + + std::vector indices; + indices.reserve(points.size()); + + std::copy(boost::counting_iterator(0), + boost::counting_iterator(points.size()), + std::back_inserter(indices)); + + CGAL::spatial_sort( indices.begin(),indices.end(),Search_traits_3(&(points[0])) ); + + for (std::vector::iterator it=indices.begin();it!=indices.end();++it) + std::cout << points[*it] << "\n"; + + std::cout << "done" << std::endl; + + return 0; +} diff --git a/Spatial_sorting/examples/Spatial_sorting/sp_sort_using_property_map_d.cpp b/Spatial_sorting/examples/Spatial_sorting/sp_sort_using_property_map_d.cpp new file mode 100644 index 00000000000..64aa5fdf48f --- /dev/null +++ b/Spatial_sorting/examples/Spatial_sorting/sp_sort_using_property_map_d.cpp @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include + +typedef CGAL::Cartesian_d Kernel; +typedef Kernel::Point_d Point_d; +typedef std::pair Point_with_info; +typedef std::vector< Point_with_info > Data_vector; + +//property map and get as friend +// to be allowed to use private member +class Vect_ppmap{ + const Data_vector& points; +public: + //classical typedefs + typedef Data_vector::size_type key_type; + typedef Point_d value_type; + typedef const value_type& reference; + typedef boost::readable_property_map_tag category; + + Vect_ppmap(const Data_vector& points_):points(points_){} + + friend reference get(const Vect_ppmap& vmap, key_type i) { + return vmap.points[i].first; + } +}; + +typedef CGAL::Spatial_sort_traits_adapter_d Search_traits_d; + +int main() +{ + double coords[] ={ 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0 }; + + Data_vector points; + points.push_back(std::make_pair(Point_d(4,coords ,coords+4) , 1)); + points.push_back(std::make_pair(Point_d(4,coords+4,coords+8) , 2)); + + std::vector indices; + indices.reserve(points.size()); + + std::copy( + boost::counting_iterator(0), + boost::counting_iterator(points.size()), + std::back_inserter(indices) ); + + CGAL::spatial_sort( + indices.begin(), + indices.end(), + Search_traits_d(Vect_ppmap(points)) ); + + std::vector::iterator it=indices.begin(); + for (;it!=indices.end();++it) + std::cout << points[*it].second << " "; + std::cout << std::endl; + + std::cout << "done" << std::endl; + + return 0; +} diff --git a/Spatial_sorting/include/CGAL/Hilbert_policy_tags.h b/Spatial_sorting/include/CGAL/Hilbert_policy_tags.h new file mode 100644 index 00000000000..3297a507966 --- /dev/null +++ b/Spatial_sorting/include/CGAL/Hilbert_policy_tags.h @@ -0,0 +1,40 @@ +// Copyright (c) 2011 INRIA Sophia-Antipolis (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; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Olivier Devillers + +#ifndef CGAL_HILBERT_POLICY_H +#define CGAL_HILBERT_POLICY_H + + +namespace CGAL { + +struct Middle {}; +struct Median {}; + + +// A policy to select the sorting strategy. + +template < typename Tag > +struct Hilbert_policy {}; + +typedef Hilbert_policy Hilbert_sort_middle_policy; +typedef Hilbert_policy Hilbert_sort_median_policy; + +} // namespace CGAL + +#endif // CGAL_HILBERT_POLICY_H diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_2.h b/Spatial_sorting/include/CGAL/Hilbert_sort_2.h index 2f1a8d8065d..021b105c7fd 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_2.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_2.h @@ -1,4 +1,4 @@ -// Copyright (c) 2007 INRIA Sophia-Antipolis (France). +// Copyright (c) 2011 INRIA Sophia-Antipolis (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or @@ -15,108 +15,40 @@ // $URL$ // $Id$ // -// Author(s) : Christophe Delage +// Author(s) : Olivier Devillers #ifndef CGAL_HILBERT_SORT_2_H #define CGAL_HILBERT_SORT_2_H -#include -#include -#include -#include +#include +#include +#include namespace CGAL { -namespace internal { - template struct Hilbert_cmp_2; +template + class Hilbert_sort_2; - template - struct Hilbert_cmp_2 - : public std::binary_function - { - typedef typename K::Point_2 Point; - K k; - Hilbert_cmp_2 (const K &_k = K()) : k(_k) {} - bool operator() (const Point &p, const Point &q) const - { - return Hilbert_cmp_2 (k) (q, p); - } - }; - - template - struct Hilbert_cmp_2 - : public std::binary_function - { - typedef typename K::Point_2 Point; - K k; - Hilbert_cmp_2 (const K &_k = K()) : k(_k) {} - bool operator() (const Point &p, const Point &q) const - { - return k.less_x_2_object() (p, q); - } - }; - - template - struct Hilbert_cmp_2 - : public std::binary_function - { - typedef typename K::Point_2 Point; - K k; - Hilbert_cmp_2 (const K &_k = K()) : k(_k) {} - bool operator() (const Point &p, const Point &q) const - { - return k.less_y_2_object() (p, q); - } - }; -} - -template -class Hilbert_sort_2 +template + class Hilbert_sort_2 + : public Hilbert_sort_median_2 { -public: - typedef K Kernel; - typedef typename Kernel::Point_2 Point; - -private: - Kernel _k; - std::ptrdiff_t _limit; - - template struct Cmp : public internal::Hilbert_cmp_2 - { Cmp (const Kernel &k) : internal::Hilbert_cmp_2 (k) {} }; - -public: - Hilbert_sort_2 (const Kernel &k = Kernel(), std::ptrdiff_t limit = 1) - : _k(k), _limit (limit) + public: + Hilbert_sort_2 (const K &k=K() , std::ptrdiff_t limit=1 ) + : Hilbert_sort_median_2 (k,limit) {} - - template - void sort (RandomAccessIterator begin, RandomAccessIterator end) const - { - const int y = (x + 1) % 2; - if (end - begin <= _limit) return; - - RandomAccessIterator m0 = begin, m4 = end; - - RandomAccessIterator m2 = internal::hilbert_split (m0, m4, Cmp< x, upx> (_k)); - RandomAccessIterator m1 = internal::hilbert_split (m0, m2, Cmp< y, upy> (_k)); - RandomAccessIterator m3 = internal::hilbert_split (m2, m4, Cmp< y, !upy> (_k)); - - sort (m0, m1); - sort (m1, m2); - sort (m2, m3); - sort (m3, m4); - } - - template - void operator() (RandomAccessIterator begin, RandomAccessIterator end) const - { - sort <0, false, false> (begin, end); - } }; -} //namespace CGAL +template + class Hilbert_sort_2 + : public Hilbert_sort_middle_2 +{ + public: + Hilbert_sort_2 (const K &k=K() , std::ptrdiff_t limit=1 ) + : Hilbert_sort_middle_2 (k,limit) + {} +}; + +} // namespace CGAL #endif//CGAL_HILBERT_SORT_2_H diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_3.h b/Spatial_sorting/include/CGAL/Hilbert_sort_3.h index 68d606db2a9..76f100f1931 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_3.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_3.h @@ -1,4 +1,4 @@ -// Copyright (c) 2007 INRIA Sophia-Antipolis (France). +// Copyright (c) 2011 INRIA Sophia-Antipolis (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or @@ -15,130 +15,40 @@ // $URL$ // $Id$ // -// Author(s) : Christophe Delage +// Author(s) : Olivier Devillers #ifndef CGAL_HILBERT_SORT_3_H #define CGAL_HILBERT_SORT_3_H -#include -#include -#include -#include +#include +#include +#include namespace CGAL { -namespace internal { - template struct Hilbert_cmp_3; +template + class Hilbert_sort_3; - template - struct Hilbert_cmp_3 - : public std::binary_function - { - typedef typename K::Point_3 Point; - K k; - Hilbert_cmp_3 (const K &_k = K()) : k(_k) {} - bool operator() (const Point &p, const Point &q) const - { - return Hilbert_cmp_3 (k) (q, p); - } - }; - - template - struct Hilbert_cmp_3 - : public std::binary_function - { - typedef typename K::Point_3 Point; - K k; - Hilbert_cmp_3 (const K &_k = K()) : k(_k) {} - bool operator() (const Point &p, const Point &q) const - { - return k.less_x_3_object() (p, q); - } - }; - - template - struct Hilbert_cmp_3 - : public std::binary_function - { - typedef typename K::Point_3 Point; - K k; - Hilbert_cmp_3 (const K &_k = K()) : k(_k) {} - bool operator() (const Point &p, const Point &q) const - { - return k.less_y_3_object() (p, q); - } - }; - - template - struct Hilbert_cmp_3 - : public std::binary_function - { - typedef typename K::Point_3 Point; - K k; - Hilbert_cmp_3 (const K &_k = K()) : k(_k) {} - bool operator() (const Point &p, const Point &q) const - { - return k.less_z_3_object() (p, q); - } - }; -} - -template -class Hilbert_sort_3 +template + class Hilbert_sort_3 + : public Hilbert_sort_median_3 { -public: - typedef K Kernel; - typedef typename Kernel::Point_3 Point; - -private: - Kernel _k; - std::ptrdiff_t _limit; - - template struct Cmp : public internal::Hilbert_cmp_3 - { Cmp (const Kernel &k) : internal::Hilbert_cmp_3 (k) {} }; - -public: - Hilbert_sort_3 (const Kernel &k = Kernel(), std::ptrdiff_t limit = 1) - : _k(k), _limit (limit) + public: + Hilbert_sort_3 (const K &k=K() , std::ptrdiff_t limit=1 ) + : Hilbert_sort_median_3 (k,limit) {} - - template - void sort (RandomAccessIterator begin, RandomAccessIterator end) const - { - const int y = (x + 1) % 3, z = (x + 2) % 3; - if (end - begin <= _limit) return; - - RandomAccessIterator m0 = begin, m8 = end; - - RandomAccessIterator m4 = internal::hilbert_split (m0, m8, Cmp< x, upx> (_k)); - RandomAccessIterator m2 = internal::hilbert_split (m0, m4, Cmp< y, upy> (_k)); - RandomAccessIterator m1 = internal::hilbert_split (m0, m2, Cmp< z, upz> (_k)); - RandomAccessIterator m3 = internal::hilbert_split (m2, m4, Cmp< z, !upz> (_k)); - RandomAccessIterator m6 = internal::hilbert_split (m4, m8, Cmp< y, !upy> (_k)); - RandomAccessIterator m5 = internal::hilbert_split (m4, m6, Cmp< z, upz> (_k)); - RandomAccessIterator m7 = internal::hilbert_split (m6, m8, Cmp< z, !upz> (_k)); - - sort (m0, m1); - sort (m1, m2); - sort (m2, m3); - sort (m3, m4); - sort (m4, m5); - sort (m5, m6); - sort (m6, m7); - sort (m7, m8); - } - - template - void operator() (RandomAccessIterator begin, RandomAccessIterator end) const - { - sort <0, false, false, false> (begin, end); - } }; -} //namespace CGAL +template + class Hilbert_sort_3 + : public Hilbert_sort_middle_3 +{ + public: + Hilbert_sort_3 (const K &k=K() , std::ptrdiff_t limit=1 ) + : Hilbert_sort_middle_3 (k,limit) + {} +}; + +} // namespace CGAL #endif//CGAL_HILBERT_SORT_3_H diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_base.h b/Spatial_sorting/include/CGAL/Hilbert_sort_base.h index 6924700098d..462e989730f 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_base.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_base.h @@ -40,6 +40,6 @@ namespace internal { } } -} //namespace CGAL +} // namespace CGAL #endif//CGAL_HILBERT_SORT_BASE_H diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_d.h b/Spatial_sorting/include/CGAL/Hilbert_sort_d.h new file mode 100644 index 00000000000..aacfcdf8cf1 --- /dev/null +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_d.h @@ -0,0 +1,54 @@ +// Copyright (c) 2011 INRIA Sophia-Antipolis (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; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://odevil@scm.gforge.inria.fr/svn/cgal/trunk/Spatial_sorting/include/CGAL/Hilbert_sort_d.h $ +// $Id: Hilbert_sort_d.h 51456 2009-08-24 17:10:04Z spion $ +// +// Author(s) : Olivier Devillers + +#ifndef CGAL_HILBERT_SORT_d_H +#define CGAL_HILBERT_SORT_d_H + +#include +#include +#include + +namespace CGAL { + +template + class Hilbert_sort_d; + +template + class Hilbert_sort_d + : public Hilbert_sort_median_d +{ + public: + Hilbert_sort_d (const K &k=K() , std::ptrdiff_t limit=1 ) + : Hilbert_sort_median_d (k,limit) + {} +}; + +template + class Hilbert_sort_d + : public Hilbert_sort_middle_d +{ + public: + Hilbert_sort_d (const K &k=K() , std::ptrdiff_t limit=1 ) + : Hilbert_sort_middle_d (k,limit) + {} +}; + +} // namespace CGAL + +#endif//CGAL_HILBERT_SORT_d_H diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h new file mode 100644 index 00000000000..832a54f19e6 --- /dev/null +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h @@ -0,0 +1,122 @@ +// Copyright (c) 2007 INRIA Sophia-Antipolis (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; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://odevil@scm.gforge.inria.fr/svn/cgal/trunk/Spatial_sorting/include/CGAL/Hilbert_sort_2.h $ +// $Id: Hilbert_sort_2.h 51456 2009-08-24 17:10:04Z spion $ +// +// Author(s) : Christophe Delage + +#ifndef CGAL_HILBERT_SORT_MEDIAN_2_H +#define CGAL_HILBERT_SORT_MEDIAN_2_H + +#include +#include +#include +#include + +namespace CGAL { + +namespace internal { + template struct Hilbert_cmp_2; + + template + struct Hilbert_cmp_2 + : public std::binary_function + { + typedef typename K::Point_2 Point; + K k; + Hilbert_cmp_2 (const K &_k = K()) : k(_k) {} + bool operator() (const Point &p, const Point &q) const + { + return Hilbert_cmp_2 (k) (q, p); + } + }; + + template + struct Hilbert_cmp_2 + : public std::binary_function + { + typedef typename K::Point_2 Point; + K k; + Hilbert_cmp_2 (const K &_k = K()) : k(_k) {} + bool operator() (const Point &p, const Point &q) const + { + return k.less_x_2_object() (p, q); + } + }; + + template + struct Hilbert_cmp_2 + : public std::binary_function + { + typedef typename K::Point_2 Point; + K k; + Hilbert_cmp_2 (const K &_k = K()) : k(_k) {} + bool operator() (const Point &p, const Point &q) const + { + return k.less_y_2_object() (p, q); + } + }; +} + +template +class Hilbert_sort_median_2 +{ +public: + typedef K Kernel; + typedef typename Kernel::Point_2 Point; + +private: + Kernel _k; + std::ptrdiff_t _limit; + + template struct Cmp : public internal::Hilbert_cmp_2 + { Cmp (const Kernel &k) : internal::Hilbert_cmp_2 (k) {} }; + +public: + Hilbert_sort_median_2 (const Kernel &k = Kernel(), std::ptrdiff_t limit = 1) + : _k(k), _limit (limit) + {} + + template + void sort (RandomAccessIterator begin, RandomAccessIterator end) const + { + const int y = (x + 1) % 2; + if (end - begin <= _limit) return; + + RandomAccessIterator m0 = begin, m4 = end; + + RandomAccessIterator m2 = internal::hilbert_split (m0, m4, Cmp< x, upx> (_k)); + RandomAccessIterator m1 = internal::hilbert_split (m0, m2, Cmp< y, upy> (_k)); + RandomAccessIterator m3 = internal::hilbert_split (m2, m4, Cmp< y, !upy> (_k)); + + sort (m0, m1); + sort (m1, m2); + sort (m2, m3); + sort (m3, m4); + } + + template + void operator() (RandomAccessIterator begin, RandomAccessIterator end) const + { + sort <0, false, false> (begin, end); + } +}; + +} // namespace CGAL + +#endif//CGAL_HILBERT_SORT_MEDIAN_2_H diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h new file mode 100644 index 00000000000..33b64a20eb8 --- /dev/null +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h @@ -0,0 +1,144 @@ +// Copyright (c) 2007 INRIA Sophia-Antipolis (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; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://odevil@scm.gforge.inria.fr/svn/cgal/trunk/Spatial_sorting/include/CGAL/Hilbert_sort_3.h $ +// $Id: Hilbert_sort_3.h 51456 2009-08-24 17:10:04Z spion $ +// +// Author(s) : Christophe Delage + +#ifndef CGAL_HILBERT_SORT_MEDIAN_3_H +#define CGAL_HILBERT_SORT_MEDIAN_3_H + +#include +#include +#include +#include + +namespace CGAL { + +namespace internal { + template struct Hilbert_cmp_3; + + template + struct Hilbert_cmp_3 + : public std::binary_function + { + typedef typename K::Point_3 Point; + K k; + Hilbert_cmp_3 (const K &_k = K()) : k(_k) {} + bool operator() (const Point &p, const Point &q) const + { + return Hilbert_cmp_3 (k) (q, p); + } + }; + + template + struct Hilbert_cmp_3 + : public std::binary_function + { + typedef typename K::Point_3 Point; + K k; + Hilbert_cmp_3 (const K &_k = K()) : k(_k) {} + bool operator() (const Point &p, const Point &q) const + { + return k.less_x_3_object() (p, q); + } + }; + + template + struct Hilbert_cmp_3 + : public std::binary_function + { + typedef typename K::Point_3 Point; + K k; + Hilbert_cmp_3 (const K &_k = K()) : k(_k) {} + bool operator() (const Point &p, const Point &q) const + { + return k.less_y_3_object() (p, q); + } + }; + + template + struct Hilbert_cmp_3 + : public std::binary_function + { + typedef typename K::Point_3 Point; + K k; + Hilbert_cmp_3 (const K &_k = K()) : k(_k) {} + bool operator() (const Point &p, const Point &q) const + { + return k.less_z_3_object() (p, q); + } + }; +} + +template +class Hilbert_sort_median_3 +{ +public: + typedef K Kernel; + typedef typename Kernel::Point_3 Point; + +private: + Kernel _k; + std::ptrdiff_t _limit; + + template struct Cmp : public internal::Hilbert_cmp_3 + { Cmp (const Kernel &k) : internal::Hilbert_cmp_3 (k) {} }; + +public: + Hilbert_sort_median_3 (const Kernel &k = Kernel(), std::ptrdiff_t limit = 1) + : _k(k), _limit (limit) + {} + + template + void sort (RandomAccessIterator begin, RandomAccessIterator end) const + { + const int y = (x + 1) % 3, z = (x + 2) % 3; + if (end - begin <= _limit) return; + + RandomAccessIterator m0 = begin, m8 = end; + + RandomAccessIterator m4 = internal::hilbert_split (m0, m8, Cmp< x, upx> (_k)); + RandomAccessIterator m2 = internal::hilbert_split (m0, m4, Cmp< y, upy> (_k)); + RandomAccessIterator m1 = internal::hilbert_split (m0, m2, Cmp< z, upz> (_k)); + RandomAccessIterator m3 = internal::hilbert_split (m2, m4, Cmp< z, !upz> (_k)); + RandomAccessIterator m6 = internal::hilbert_split (m4, m8, Cmp< y, !upy> (_k)); + RandomAccessIterator m5 = internal::hilbert_split (m4, m6, Cmp< z, upz> (_k)); + RandomAccessIterator m7 = internal::hilbert_split (m6, m8, Cmp< z, !upz> (_k)); + + sort (m0, m1); + sort (m1, m2); + sort (m2, m3); + sort (m3, m4); + sort (m4, m5); + sort (m5, m6); + sort (m6, m7); + sort (m7, m8); + } + + template + void operator() (RandomAccessIterator begin, RandomAccessIterator end) const + { + sort <0, false, false, false> (begin, end); + } +}; + +} // namespace CGAL + +#endif//CGAL_HILBERT_SORT_MEDIAN_3_H diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_d.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_d.h new file mode 100644 index 00000000000..ea597cc5049 --- /dev/null +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_d.h @@ -0,0 +1,167 @@ +// Copyright (c) 2011 INRIA Sophia-Antipolis (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; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Olivier Devillers + +#ifndef CGAL_HILBERT_SORT_MEDIAN_d_H +#define CGAL_HILBERT_SORT_MEDIAN_d_H + +#include +#include +#include +#include +#include + +namespace CGAL { + +namespace internal { + + template + struct Hilbert_cmp_d + : public std::binary_function + { + typedef typename K::Point_d Point; + K k; + int axe; + bool orient; + Hilbert_cmp_d (int a, bool o, const K &_k = K()) + : k(_k), axe(a), orient(o) {} + bool operator() (const Point &p, const Point &q) const + { + return (orient ? (k.less_coordinate_d_object() (q,p,axe) ) + : (k.less_coordinate_d_object() (p,q,axe) )); + } + }; + +} + +template +class Hilbert_sort_median_d +{ +public: + typedef K Kernel; + typedef typename Kernel::Point_d Point; + typedef std::vector< bool > Starting_position; + +private: + Kernel _k; + std::ptrdiff_t _limit; + mutable int _dimension; + mutable int two_to_dim; + + struct Cmp : public internal::Hilbert_cmp_d + { Cmp (int a, bool dir, const Kernel &k) + : internal::Hilbert_cmp_d (a,dir,k) {} }; + +public: + Hilbert_sort_median_d(const Kernel &k = Kernel(), std::ptrdiff_t limit = 1) + : _k(k), _limit (limit) + {} + + template + void sort (RandomAccessIterator begin, RandomAccessIterator end, + Starting_position start, int direction) const + { + if (end - begin <= _limit) return; + + int nb_directions = _dimension; + int nb_splits = two_to_dim; + + if ( (end-begin) < (two_to_dim/2) ) { // not many points + nb_splits = 1; + nb_directions = 0; + while ( (end-begin) > nb_splits) { + ++nb_directions; + nb_splits *= 2; // compute 2^nb_directions + } + } + + std::vector places(nb_splits +1); + std::vector dir (nb_splits +1); + places[0]=begin; + places[nb_splits]=end; + + int last_dir = (direction + nb_directions) % _dimension; + int current_dir = direction; + int current_level_step =nb_splits; + do{ + int half_step = current_level_step/2; + int left=0; + int middle = half_step; + int right=current_level_step; + bool orient = start[current_dir]; + do{ + dir[middle] = current_dir; + places[middle] = internal::hilbert_split + (places[left], places[right], Cmp (current_dir,orient,_k)); + left =right; + right+=current_level_step; + middle+=current_level_step; + orient = ! orient; + }while( left< nb_splits); + current_level_step = half_step; + current_dir = (current_dir +1) % _dimension; + }while (current_dir != last_dir); + + if ( end-begin < two_to_dim) return; // less than 2^dim points + + /////////////start recursive calls + last_dir = (direction + _dimension -1) % _dimension; + // first step is special + sort( places[0], places[1], start, last_dir); + + for(int i=1; i + void operator() (RandomAccessIterator begin, RandomAccessIterator end) const + { + _dimension = _k.point_dimension_d_object()(*begin); + two_to_dim = 1; + Starting_position start(_dimension); + + typename std::iterator_traits::difference_type N=end-begin; + N*=2; + for (int i=0; i<_dimension; ++i) start[i]=false; // we start below in all coordinates + for (int i=0; i<_dimension; ++i) { + two_to_dim *= 2; // compute 2^_dimension + N/=2; + if (N==0) break; // not many points, this number of dimension is enough + } + + + // we start with direction 0; + sort (begin, end, start, 0); + } +}; + + + + +} // namespace CGAL + +#endif//CGAL_HILBERT_SORT_MEDIAN_d_H diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_middle_2.h b/Spatial_sorting/include/CGAL/Hilbert_sort_middle_2.h new file mode 100644 index 00000000000..303b224432d --- /dev/null +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_middle_2.h @@ -0,0 +1,137 @@ +// Copyright (c) 2011 INRIA Sophia-Antipolis (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; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Olivier Devillers + +#ifndef CGAL_HILBERT_SORT_MIDDLE_2_H +#define CGAL_HILBERT_SORT_MIDDLE_2_H + +#include +#include +#include +#include +#include + +namespace CGAL { + +namespace internal { + template struct Fixed_hilbert_cmp_2; + + template + struct Fixed_hilbert_cmp_2 + : public std::binary_function + { + typedef typename K::Point_2 Point; + K k; + double value; + Fixed_hilbert_cmp_2 (double v, const K &_k = K()) : k(_k),value(v) {} + bool operator() (const Point &p) const + { + return ! Fixed_hilbert_cmp_2 (value, k) (p); + } + }; + + template + struct Fixed_hilbert_cmp_2 + : public std::binary_function + { + typedef typename K::Point_2 Point; + K k; + double value; + Fixed_hilbert_cmp_2 (double v, const K &_k = K()) : k(_k),value(v) {} + bool operator() (const Point &p) const + { + return to_double(k.compute_x_2_object()(p)) < value; + } + }; + + template + struct Fixed_hilbert_cmp_2 + : public std::binary_function + { + typedef typename K::Point_2 Point; + K k; + double value; + Fixed_hilbert_cmp_2 (double v, const K &_k = K()) : k(_k),value(v) {} + bool operator() (const Point &p) const + { + return to_double(k.compute_y_2_object()(p)) < value; + } + }; +} + + +template +class Hilbert_sort_middle_2 +{ +public: + typedef K Kernel; + typedef typename Kernel::Point_2 Point; + +private: + Kernel _k; + std::ptrdiff_t _limit; + + template struct Cmp : public internal::Fixed_hilbert_cmp_2 + { Cmp (double v, const Kernel &k) : internal::Fixed_hilbert_cmp_2 (v, k) {} }; + +public: + Hilbert_sort_middle_2 (const Kernel &k = Kernel(), std::ptrdiff_t limit = 1) + : _k(k), _limit (limit) + {} + + template + void sort (RandomAccessIterator begin, RandomAccessIterator end, + double xmin, double ymin, double xmax, double ymax) const + { + const int y = (x + 1) % 2; + if (end - begin <= _limit) return; + + double xmed= (xmin+xmax)/2; + double ymed= (ymin+ymax)/2; + + RandomAccessIterator m0 = begin, m4 = end; + + RandomAccessIterator m2 = + internal::fixed_hilbert_split (m0, m4, Cmp< x, upx> (xmed,_k)); + RandomAccessIterator m1 = + internal::fixed_hilbert_split (m0, m2, Cmp< y, upy> (ymed,_k)); + RandomAccessIterator m3 = + internal::fixed_hilbert_split (m2, m4, Cmp< y, !upy> (ymed,_k)); + + sort (m0, m1, ymin, xmin, ymed, xmed); + sort (m1, m2, xmin, ymed, xmed, ymax); + sort (m2, m3, xmed, ymed, xmax, ymax); + sort (m3, m4, ymed, xmax, ymin, xmed); + } + + template + void operator() (RandomAccessIterator begin, RandomAccessIterator end) const + { + Bbox_2 box=bbox_2(begin, end); + sort <0, false, false> (begin, end, + box.xmin(), box.ymin(), box.xmax(), box.ymax()); + } +}; + + +} // namespace CGAL + +#endif//CGAL_HILBERT_SORT_MIDDLE_2_H diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_middle_3.h b/Spatial_sorting/include/CGAL/Hilbert_sort_middle_3.h new file mode 100644 index 00000000000..5b5d6d2fd63 --- /dev/null +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_middle_3.h @@ -0,0 +1,185 @@ +// Copyright (c) 2011 INRIA Sophia-Antipolis (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; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Olivier Devillers + +#ifndef CGAL_HILBERT_SORT_MIDDLE_3_H +#define CGAL_HILBERT_SORT_MIDDLE_3_H + +#include +#include +#include +#include + +namespace CGAL { + +namespace internal { + template struct Fixed_hilbert_cmp_3; + + template + struct Fixed_hilbert_cmp_3 + : public std::binary_function + { + typedef typename K::Point_3 Point; + K k; + double value; + Fixed_hilbert_cmp_3 (double v, const K &_k = K()) : k(_k),value(v) {} + bool operator() (const Point &p) const + { + return ! Fixed_hilbert_cmp_3 (value,k) (p); + } + }; + + template + struct Fixed_hilbert_cmp_3 + : public std::binary_function + { + typedef typename K::Point_3 Point; + K k; + double value; + Fixed_hilbert_cmp_3 (double v, const K &_k = K()) : k(_k),value(v) {} + bool operator() (const Point &p) const + { + return to_double(k.compute_x_3_object()(p)) < value; + } + }; + + template + struct Fixed_hilbert_cmp_3 + : public std::binary_function + { + typedef typename K::Point_3 Point; + K k; + double value; + Fixed_hilbert_cmp_3 (double v, const K &_k = K()) : k(_k),value(v) {} + bool operator() (const Point &p) const + { + return to_double(k.compute_y_3_object()(p)) < value; + } + }; + + template + struct Fixed_hilbert_cmp_3 + : public std::binary_function + { + typedef typename K::Point_3 Point; + K k; + double value; + Fixed_hilbert_cmp_3 (double v, const K &_k = K()) : k(_k),value(v) {} + bool operator() (const Point &p) const + { + return to_double(k.compute_z_3_object()(p)) < value ; + } + }; +} + +template +class Hilbert_sort_middle_3 +{ +public: + typedef K Kernel; + typedef typename Kernel::Point_3 Point; + +private: + Kernel _k; + std::ptrdiff_t _limit; + + template struct Cmp : public internal::Fixed_hilbert_cmp_3 + { Cmp (double v,const Kernel &k) : internal::Fixed_hilbert_cmp_3 (v,k) {} }; + +public: + Hilbert_sort_middle_3 (const Kernel &k = Kernel(), std::ptrdiff_t limit = 1) + : _k(k), _limit (limit) + {} + + template + void sort (RandomAccessIterator begin, RandomAccessIterator end, + double xmin, double ymin, double zmin, + double xmax, double ymax, double zmax) const + { + const int y = (x + 1) % 3, z = (x + 2) % 3; + if (end - begin <= _limit) return; + + double xmed= (xmin+xmax)/2; + double ymed= (ymin+ymax)/2; + double zmed= (zmin+zmax)/2; + + + RandomAccessIterator m0 = begin, m8 = end; + + RandomAccessIterator m4 = + internal::fixed_hilbert_split (m0, m8, Cmp< x, upx> (xmed,_k)); + RandomAccessIterator m2 = + internal::fixed_hilbert_split (m0, m4, Cmp< y, upy> (ymed,_k)); + RandomAccessIterator m6 = + internal::fixed_hilbert_split (m4, m8, Cmp< y, !upy> (ymed,_k)); + RandomAccessIterator m1 = + internal::fixed_hilbert_split (m0, m2, Cmp< z, upz> (zmed,_k)); + RandomAccessIterator m3 = + internal::fixed_hilbert_split (m2, m4, Cmp< z, !upz> (zmed,_k)); + RandomAccessIterator m5 = + internal::fixed_hilbert_split (m4, m6, Cmp< z, upz> (zmed,_k)); + RandomAccessIterator m7 = + internal::fixed_hilbert_split (m6, m8, Cmp< z, !upz> (zmed,_k)); + + + sort (m0, m1, zmin, xmin, ymin, zmed, xmed, ymed); + sort (m1, m2, ymin, zmed, xmin, ymed, zmax, xmed); + sort (m2, m3, ymed, zmed, xmin, ymax, zmax, xmed); + sort (m3, m4, xmin, ymax, zmed, xmed, ymed, zmin); + sort (m4, m5, xmed, ymax, zmed, xmax, ymed, zmin); + sort (m5, m6, ymax, zmed, xmax, ymed, zmax, xmed); + sort (m6, m7, ymed, zmed, xmax, ymin, zmax, xmed); + sort (m7, m8, zmed, xmax, ymin, zmin, xmed, ymed); + } + + template + void operator() (RandomAccessIterator begin, RandomAccessIterator end) const + { + K k; + double xmin=to_double(k.compute_x_3_object()(*begin)), + ymin=to_double(k.compute_y_3_object()(*begin)), + zmin=to_double(k.compute_z_3_object()(*begin)), + xmax=xmin, + ymax=ymin, + zmax=zmin; + for(RandomAccessIterator it=begin+1; it xmax) + xmax = to_double(k.compute_x_3_object()(*it)); + if ( to_double(k.compute_y_3_object()(*it)) > ymax) + ymax = to_double(k.compute_y_3_object()(*it)); + if ( to_double(k.compute_z_3_object()(*it)) > zmax) + zmax = to_double(k.compute_z_3_object()(*it)); + } + + sort <0, false, false, false> (begin, end, xmin,ymin,zmin,xmax,ymax,zmax); + } +}; + +} // namespace CGAL + +#endif//CGAL_HILBERT_SORT_MIDDLE_3_H diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_middle_base.h b/Spatial_sorting/include/CGAL/Hilbert_sort_middle_base.h new file mode 100644 index 00000000000..fcda1b94b37 --- /dev/null +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_middle_base.h @@ -0,0 +1,43 @@ +// Copyright (c) 2011 INRIA Sophia-Antipolis (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; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Olivier Devillers + +#ifndef CGAL_HILBERT_SORT_MIDDLE_BASE_H +#define CGAL_HILBERT_SORT_MIDDLE_BASE_H + +#include +#include + +namespace CGAL { + +namespace internal { + + template + RandomAccessIterator + fixed_hilbert_split (RandomAccessIterator begin, RandomAccessIterator end, + Cmp cmp = Cmp ()) + { + if (begin >= end) return begin; + + return std::partition (begin, end, cmp); + } +} + +} // namespace CGAL + +#endif//CGAL_HILBERT_SORT_MIDDLE_BASE_H diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_middle_d.h b/Spatial_sorting/include/CGAL/Hilbert_sort_middle_d.h new file mode 100644 index 00000000000..cf1ae7f9085 --- /dev/null +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_middle_d.h @@ -0,0 +1,186 @@ +// Copyright (c) 2011 INRIA Sophia-Antipolis (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; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Olivier Devillers + +#ifndef CGAL_HILBERT_SORT_MIDDLE_d_H +#define CGAL_HILBERT_SORT_MIDDLE_d_H + +#include +#include +#include +#include + +namespace CGAL { + +namespace internal { + + template + struct Fixed_hilbert_cmp_d + : public std::binary_function + { + typedef typename K::Point_d Point; + K k; + int axe; + bool orient; + double value; + Fixed_hilbert_cmp_d (int a, bool o, double v, const K &_k = K()) + : k(_k), axe(a), orient(o), value(v) {} + bool operator() (const Point &p) const + { + return (orient + ? ( to_double( k.compute_coordinate_d_object() (p,axe) ) > value) + : ( to_double( k.compute_coordinate_d_object() (p,axe) ) <= value)); + } + }; + +} + +template +class Hilbert_sort_middle_d +{ +public: + typedef K Kernel; + typedef typename Kernel::Point_d Point; + typedef std::vector< bool > Starting_position; + typedef std::vector< double > Corner; + +private: + Kernel _k; + std::ptrdiff_t _limit; + mutable int _dimension; + mutable int two_to_dim; + + struct Cmp : public internal::Fixed_hilbert_cmp_d + { Cmp (int a, bool dir, double v, const Kernel &k) + : internal::Fixed_hilbert_cmp_d (a,dir,v,k) {} }; + +public: + Hilbert_sort_middle_d (const Kernel &k = Kernel(), std::ptrdiff_t limit = 1) + : _k(k), _limit (limit) + {} + + template + void sort (RandomAccessIterator begin, RandomAccessIterator end, + Starting_position start, int direction, + Corner min, Corner max) const + { + if (end - begin <= _limit) return; + + Corner med(_dimension); + for( int i=0; i<_dimension; ++i) med[i]=(min[i]+max[i])/2; + Corner cmin=min,cmax=med; + + std::vector places(two_to_dim +1); + std::vector dir (two_to_dim +1); + places[0]=begin; + places[two_to_dim]=end; + + int last_dir = (direction + _dimension) % _dimension; + int current_dir = direction; + int current_level_step =two_to_dim; + do{ + int half_step = current_level_step/2; + int left=0; + int middle = half_step; + int right=current_level_step; + bool orient = start[current_dir]; + do{ + dir[middle] = current_dir; + places[middle] = internal::fixed_hilbert_split + (places[left], places[right], + Cmp (current_dir,orient,med[current_dir],_k)); + left =right; + right+=current_level_step; + middle+=current_level_step; + orient = ! orient; + }while( left< two_to_dim); + current_level_step = half_step; + current_dir = (current_dir +1) % _dimension; + }while (current_dir != last_dir); + + /////////////start recursive calls + last_dir = (direction + _dimension -1) % _dimension; + // first step is special + sort( places[0], places[1], start, last_dir,cmin,cmax); + cmin[last_dir] = med[last_dir]; + cmax[last_dir] = max[last_dir]; + + + for(int i=1; i + void operator() (RandomAccessIterator begin, RandomAccessIterator end) const + { + _dimension = _k.point_dimension_d_object()(*begin); + two_to_dim = 1; + Starting_position start(_dimension); + Corner min(_dimension),max(_dimension); + + for (int i=0; i<_dimension; ++i) + min[i]=max[i]=to_double( _k.compute_coordinate_d_object() (*begin,i) ); + for(RandomAccessIterator it=begin+1; it max[i]) max[i] = d; + } + } + + + for (int i=0; i<_dimension; ++i) { + start[i]=false; // we start below in all coordinates + two_to_dim *= 2; // compute 2^_dimension + if (two_to_dim*2 <= 0) { + CGAL_assertion(end-begin < two_to_dim);//too many points in such dim + break; + } + } + + + + // we start with direction 0; + sort (begin, end, start, 0, min, max); + } +}; + + + + +} // namespace CGAL + +#endif//CGAL_HILBERT_SORT_MIDDLE_d_H diff --git a/Spatial_sorting/include/CGAL/Multiscale_sort.h b/Spatial_sorting/include/CGAL/Multiscale_sort.h index 1786858406e..51c5df33b5d 100644 --- a/Spatial_sorting/include/CGAL/Multiscale_sort.h +++ b/Spatial_sorting/include/CGAL/Multiscale_sort.h @@ -53,6 +53,6 @@ public: } }; -} //namespace CGAL +} // namespace CGAL #endif // CGAL_MULTISCALE_SORT_H diff --git a/Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_2.h b/Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_2.h new file mode 100644 index 00000000000..1bc0d0d642a --- /dev/null +++ b/Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_2.h @@ -0,0 +1,77 @@ +// Copyright (c) 2011 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Sebastien Loriot + + +#ifndef CGAL_SPATIAL_SORT_TRAITS_ADAPTER_2_H +#define CGAL_SPATIAL_SORT_TRAITS_ADAPTER_2_H + +#include +#include +#if BOOST_VERSION >= 104000 + #include +#else + #include +#endif + + +namespace CGAL{ + +using ::get; + +template +class Spatial_sort_traits_adapter_2:public Base_traits{ + PointPropertyMap ppmap_; +public: + Spatial_sort_traits_adapter_2(Base_traits base=Base_traits()):Base_traits(base){} + + Spatial_sort_traits_adapter_2(const PointPropertyMap& ppmap,Base_traits base=Base_traits()) + :Base_traits(base),ppmap_(ppmap){} + + typedef Base_traits Gt; + typedef typename boost::property_traits::key_type Point_2; + typedef typename boost::call_traits::param_type Arg_type; + + struct Less_x_2 : public Base_traits::Less_x_2{ + Less_x_2(const PointPropertyMap& ppmap,const typename Base_traits::Less_x_2& base): + Base_traits::Less_x_2(base),ppmap_(ppmap){} + const PointPropertyMap& ppmap_; + bool operator()(Arg_type p,Arg_type q) const { + return static_cast(this)->operator()(get(ppmap_,p),get(ppmap_,q)); + } + }; + + struct Less_y_2 : public Base_traits::Less_y_2{ + Less_y_2(const PointPropertyMap& ppmap,const typename Base_traits::Less_y_2& base): + Base_traits::Less_y_2(base),ppmap_(ppmap){} + const PointPropertyMap& ppmap_; + bool operator()(Arg_type p,Arg_type q) const { + return static_cast(this)->operator()(get(ppmap_,p),get(ppmap_,q)); + } + }; + + Less_x_2 less_x_2_object () const {return Less_x_2(ppmap_,static_cast(this)->less_x_2_object() );} + Less_y_2 less_y_2_object () const {return Less_y_2(ppmap_,static_cast(this)->less_y_2_object() );} + + const PointPropertyMap& point_property_map() const {return ppmap_;} + +}; + +} //namespace CGAL + +#endif //CGAL_SPATIAL_SORT_TRAITS_ADAPTER_2_H diff --git a/Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_3.h b/Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_3.h new file mode 100644 index 00000000000..2a3f07d0af5 --- /dev/null +++ b/Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_3.h @@ -0,0 +1,87 @@ +// Copyright (c) 2011 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Sebastien Loriot + + +#ifndef CGAL_SPATIAL_SORT_TRAITS_ADAPTER_3_H +#define CGAL_SPATIAL_SORT_TRAITS_ADAPTER_3_H + +#include +#include +#if BOOST_VERSION >= 104000 + #include +#else + #include +#endif + + +namespace CGAL{ + +using ::get; + +template +class Spatial_sort_traits_adapter_3:public Base_traits{ + PointPropertyMap ppmap_; +public: + Spatial_sort_traits_adapter_3(Base_traits base=Base_traits()):Base_traits(base){} + + Spatial_sort_traits_adapter_3(const PointPropertyMap& ppmap,Base_traits base=Base_traits()) + :Base_traits(base),ppmap_(ppmap){} + + typedef Base_traits Gt; + typedef typename boost::property_traits::key_type Point_3; + typedef typename boost::call_traits::param_type Arg_type; + + struct Less_x_3 : public Base_traits::Less_x_3{ + Less_x_3(const PointPropertyMap& ppmap,const typename Base_traits::Less_x_3& base): + Base_traits::Less_x_3(base),ppmap_(ppmap){} + const PointPropertyMap& ppmap_; + bool operator()(Arg_type p,Arg_type q) const { + return static_cast(this)->operator()(get(ppmap_,p),get(ppmap_,q)); + } + }; + + struct Less_y_3 : public Base_traits::Less_y_3{ + Less_y_3(const PointPropertyMap& ppmap,const typename Base_traits::Less_y_3& base): + Base_traits::Less_y_3(base),ppmap_(ppmap){} + const PointPropertyMap& ppmap_; + bool operator()(Arg_type p,Arg_type q) const { + return static_cast(this)->operator()(get(ppmap_,p),get(ppmap_,q)); + } + }; + + struct Less_z_3 : public Base_traits::Less_z_3{ + Less_z_3(const PointPropertyMap& ppmap,const typename Base_traits::Less_z_3& base): + Base_traits::Less_z_3(base),ppmap_(ppmap){} + const PointPropertyMap& ppmap_; + bool operator()(Arg_type p,Arg_type q) const { + return static_cast(this)->operator()(get(ppmap_,p),get(ppmap_,q)); + } + }; + + Less_x_3 less_x_3_object () const {return Less_x_3(ppmap_,static_cast(this)->less_x_3_object() );} + Less_y_3 less_y_3_object () const {return Less_y_3(ppmap_,static_cast(this)->less_y_3_object() );} + Less_z_3 less_z_3_object () const {return Less_z_3(ppmap_,static_cast(this)->less_z_3_object() );} + + const PointPropertyMap& point_property_map() const {return ppmap_;} + +}; + +} //namespace CGAL + +#endif //CGAL_SPATIAL_SORT_TRAITS_ADAPTER_3_H diff --git a/Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_d.h b/Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_d.h new file mode 100644 index 00000000000..3c0c11934d0 --- /dev/null +++ b/Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_d.h @@ -0,0 +1,92 @@ +// Copyright (c) 2011 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Sebastien Loriot + + +#ifndef CGAL_SPATIAL_SORT_TRAITS_ADAPTER_D_H +#define CGAL_SPATIAL_SORT_TRAITS_ADAPTER_D_H + +#include +#include +#if BOOST_VERSION >= 104000 + #include +#else + #include +#endif + + +namespace CGAL{ + +using ::get; + +template +class Spatial_sort_traits_adapter_d:public Base_traits{ + PointPropertyMap ppmap_; +public: + Spatial_sort_traits_adapter_d(Base_traits base=Base_traits()):Base_traits(base){} + + Spatial_sort_traits_adapter_d(const PointPropertyMap& ppmap,Base_traits base=Base_traits()) + :Base_traits(base),ppmap_(ppmap){} + + typedef Base_traits Gt; + typedef typename boost::property_traits::key_type Point_d; + typedef typename boost::call_traits::param_type Arg_type; + + + + struct Point_dimension_d: public Base_traits::Point_dimension_d{ + Point_dimension_d(const PointPropertyMap& ppmap,const typename Base_traits::Point_dimension_d& base): + Base_traits::Point_dimension_d(base),ppmap_(ppmap){} + const PointPropertyMap& ppmap_; + int operator()(Arg_type p) const { + return static_cast(this)->operator()(get(ppmap_,p)); + } + }; + + struct Less_coordinate_d: public Base_traits::Less_coordinate_d{ + Less_coordinate_d(const PointPropertyMap& ppmap,const typename Base_traits::Less_coordinate_d& base): + Base_traits::Less_coordinate_d(base),ppmap_(ppmap){} + const PointPropertyMap& ppmap_; + bool operator()(Arg_type p,Arg_type q,int i) const { + return static_cast(this)->operator()(get(ppmap_,p),get(ppmap_,q),i); + } + }; + + + struct Compute_coordinate_d: public Base_traits::Compute_coordinate_d{ + Compute_coordinate_d(const PointPropertyMap& ppmap,const typename Base_traits::Compute_coordinate_d& base): + Base_traits::Compute_coordinate_d(base),ppmap_(ppmap){} + const PointPropertyMap& ppmap_; + bool operator()(Arg_type p,int i) const { + return static_cast(this)->operator()(get(ppmap_,p),i); + } + }; + + + + Point_dimension_d point_dimension_d_object () const {return Point_dimension_d(ppmap_,static_cast(this)->point_dimension_d_object() );} + Less_coordinate_d less_coordinate_d_object () const {return Less_coordinate_d(ppmap_,static_cast(this)->less_coordinate_d_object() );} + Compute_coordinate_d compute_coordinate_d_object () const {return Compute_coordinate_d(ppmap_,static_cast(this)->compute_coordinate_d_object() );} + + const PointPropertyMap& point_property_map() const {return ppmap_;} + +}; + +} //namespace CGAL + +#endif //CGAL_SPATIAL_SORT_TRAITS_ADAPTER_D_H diff --git a/Spatial_sorting/include/CGAL/hilbert_sort.h b/Spatial_sorting/include/CGAL/hilbert_sort.h index d7956c41699..0f28b74dca2 100644 --- a/Spatial_sorting/include/CGAL/hilbert_sort.h +++ b/Spatial_sorting/include/CGAL/hilbert_sort.h @@ -1,4 +1,4 @@ -// Copyright (c) 2007 INRIA Sophia-Antipolis (France). +// Copyright (c) 2007-2011 INRIA Sophia-Antipolis (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or @@ -16,14 +16,17 @@ // $Id$ // // Author(s) : Christophe Delage +// : Olivier Devillers #ifndef CGAL_HILBERT_SORT_H #define CGAL_HILBERT_SORT_H #include +#include #include #include +#include #include #include @@ -32,50 +35,81 @@ namespace CGAL { + namespace internal { - template - void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end, - const Kernel &k, typename Kernel::Point_2 *) + template + void hilbert_sort (RandomAccessIterator begin, + RandomAccessIterator end, + Policy /*policy*/, + const Kernel &k, typename Kernel::Point_2 *) { boost::rand48 random; boost::random_number_generator rng(random); std::random_shuffle(begin,end, rng); - (Hilbert_sort_2 (k)) (begin, end); + (Hilbert_sort_2 (k))(begin, end); } - - template - void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end, - const Kernel &k, typename Kernel::Point_3 *) + + template + void hilbert_sort (RandomAccessIterator begin, + RandomAccessIterator end, + Policy /*policy*/, + const Kernel &k, typename Kernel::Point_3 *) { boost::rand48 random; boost::random_number_generator rng(random); std::random_shuffle(begin,end, rng); - (Hilbert_sort_3 (k)) (begin, end); + (Hilbert_sort_3 (k))(begin, end); } -} -template -void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end, - const Kernel &k) -{ - typedef std::iterator_traits ITraits; - typedef typename ITraits::value_type value_type; + template + void hilbert_sort (RandomAccessIterator begin, + RandomAccessIterator end, + Policy /*policy*/, + const Kernel &k, typename Kernel::Point_d *) + { + boost::rand48 random; + boost::random_number_generator rng(random); + std::random_shuffle(begin,end, rng); + (Hilbert_sort_d (k))(begin, end); + } + + - internal::hilbert_sort (begin, end, k, static_cast (0)); } template void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end) +{ + hilbert_sort (begin, end, Hilbert_sort_median_policy()); +} + +template +void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end, + Policy policy) { typedef std::iterator_traits ITraits; typedef typename ITraits::value_type value_type; typedef CGAL::Kernel_traits KTraits; typedef typename KTraits::Kernel Kernel; - hilbert_sort (begin, end, Kernel()); + internal::hilbert_sort(begin, end, policy, Kernel(), + static_cast (0)); } -} //namespace CGAL + +template +void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end, + Policy policy, const Kernel &k ) +{ + typedef std::iterator_traits ITraits; + typedef typename ITraits::value_type value_type; + + internal::hilbert_sort(begin, end, + policy, k, static_cast (0)); +} + +} // namespace CGAL #endif//CGAL_HILBERT_SORT_H + diff --git a/Spatial_sorting/include/CGAL/spatial_sort.h b/Spatial_sorting/include/CGAL/spatial_sort.h index 3640c6492aa..6374f546ea7 100644 --- a/Spatial_sorting/include/CGAL/spatial_sort.h +++ b/Spatial_sorting/include/CGAL/spatial_sort.h @@ -1,4 +1,4 @@ -// Copyright (c) 2007 INRIA Sophia-Antipolis (France). +// Copyright (c) 2007-2011 INRIA Sophia-Antipolis (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or @@ -16,15 +16,14 @@ // $Id$ // // Author(s) : Christophe Delage +// : Olivier Devillers #ifndef CGAL_SPATIAL_SORT_H #define CGAL_SPATIAL_SORT_H #include -#include -#include - +#include #include #include @@ -34,54 +33,151 @@ namespace CGAL { + namespace internal { - template - void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, - const Kernel &k, typename Kernel::Point_2 *) + template + void spatial_sort ( + RandomAccessIterator begin, RandomAccessIterator end, + const Kernel &k, + Policy /*policy*/, + typename Kernel::Point_2 *, + std::ptrdiff_t threshold_hilbert, + std::ptrdiff_t threshold_multiscale, + double ratio) { - typedef Hilbert_sort_2 Sort; + typedef Hilbert_sort_2 Sort; boost::rand48 random; boost::random_number_generator rng(random); std::random_shuffle(begin,end,rng); - (Multiscale_sort (Sort (k, 4), 16, 0.25)) (begin, end); + if (threshold_hilbert==0) threshold_hilbert=4; + if (threshold_multiscale==0) threshold_multiscale=16; + if (ratio==0.0) ratio=0.25; + + (Multiscale_sort (Sort (k, threshold_hilbert), + threshold_multiscale, ratio)) (begin, end); } - template - void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, - const Kernel &k, typename Kernel::Point_3 *) + template + void spatial_sort ( + RandomAccessIterator begin, RandomAccessIterator end, + const Kernel &k, + Policy /*policy*/, + typename Kernel::Point_3 *, + std::ptrdiff_t threshold_hilbert, + std::ptrdiff_t threshold_multiscale, + double ratio) { - typedef Hilbert_sort_3 Sort; + typedef Hilbert_sort_3 Sort; boost::rand48 random; boost::random_number_generator rng(random); std::random_shuffle(begin,end, rng); - (Multiscale_sort (Sort (k, 8), 64, 0.125)) (begin, end); + if (threshold_hilbert==0) threshold_hilbert=8; + if (threshold_multiscale==0) threshold_multiscale=64; + if (ratio==0.0) ratio=0.125; + + (Multiscale_sort (Sort (k, threshold_hilbert), + threshold_multiscale, ratio)) (begin, end); } + + template + void spatial_sort ( + RandomAccessIterator begin, RandomAccessIterator end, + const Kernel &k, + Policy /*policy*/, + typename Kernel::Point_d *, + std::ptrdiff_t threshold_hilbert, + std::ptrdiff_t threshold_multiscale, + double ratio) + { + typedef Hilbert_sort_d Sort; + boost::rand48 random; + boost::random_number_generator rng(random); + std::random_shuffle(begin,end, rng); + + if (threshold_hilbert==0) threshold_hilbert=10; + if (threshold_multiscale==0) threshold_multiscale=500; + if (ratio==0.0) ratio=0.05; + + (Multiscale_sort (Sort (k, threshold_hilbert), + threshold_multiscale, ratio)) (begin, end); + } + } -template + +template void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, - const Kernel &k) + const Kernel &k, + Policy policy, + std::ptrdiff_t threshold_hilbert=0, + std::ptrdiff_t threshold_multiscale=0, + double ratio=0.0) { typedef std::iterator_traits ITraits; typedef typename ITraits::value_type value_type; - internal::spatial_sort (begin, end, k, static_cast (0)); + internal::spatial_sort(begin, end, k, policy, static_cast (0), + threshold_hilbert,threshold_multiscale,ratio); } template -void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end) +void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, + Hilbert_sort_median_policy policy, + std::ptrdiff_t threshold_hilbert=0, + std::ptrdiff_t threshold_multiscale=0, + double ratio=0.0) { typedef std::iterator_traits ITraits; typedef typename ITraits::value_type value_type; typedef CGAL::Kernel_traits KTraits; typedef typename KTraits::Kernel Kernel; - spatial_sort (begin, end, Kernel()); + spatial_sort (begin, end, Kernel(), policy, + threshold_hilbert,threshold_multiscale,ratio); +} +template +void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, + Hilbert_sort_middle_policy policy, + std::ptrdiff_t threshold_hilbert=0, + std::ptrdiff_t threshold_multiscale=0, + double ratio=0.0) +{ + typedef std::iterator_traits ITraits; + typedef typename ITraits::value_type value_type; + typedef CGAL::Kernel_traits KTraits; + typedef typename KTraits::Kernel Kernel; + + spatial_sort (begin, end, Kernel(), policy, + threshold_hilbert,threshold_multiscale,ratio); } -} //namespace CGAL + +template +void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, + const Kernel &k, + std::ptrdiff_t threshold_hilbert=0, + std::ptrdiff_t threshold_multiscale=0, + double ratio=0.0) +{ + spatial_sort (begin, end, k, + Hilbert_sort_median_policy(), + threshold_hilbert,threshold_multiscale,ratio); +} + +template +void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, + std::ptrdiff_t threshold_hilbert=0, + std::ptrdiff_t threshold_multiscale=0, + double ratio=0.0) +{ + spatial_sort (begin, end, + Hilbert_sort_median_policy(), + threshold_hilbert,threshold_multiscale,ratio); +} + +} // namespace CGAL #endif//CGAL_SPATIAL_SORT_H diff --git a/Spatial_sorting/package_info/Spatial_sorting/maintainer b/Spatial_sorting/package_info/Spatial_sorting/maintainer index 7e028c78627..99303a0d3ce 100644 --- a/Spatial_sorting/package_info/Spatial_sorting/maintainer +++ b/Spatial_sorting/package_info/Spatial_sorting/maintainer @@ -1 +1 @@ -cgal-develop +odevil diff --git a/Spatial_sorting/test/Spatial_sorting/test_hilbert.cpp b/Spatial_sorting/test/Spatial_sorting/test_hilbert.cpp index 33b7511ce28..23ab7cbfb5d 100644 --- a/Spatial_sorting/test/Spatial_sorting/test_hilbert.cpp +++ b/Spatial_sorting/test/Spatial_sorting/test_hilbert.cpp @@ -4,37 +4,47 @@ #include #include +#include #include #include #include +#include +#include #include #include #include -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef K::Point_2 Point_2; -typedef K::Point_3 Point_3; +#include -typedef CGAL::Creator_uniform_2 Creator_2; -typedef CGAL::Creator_uniform_3 Creator_3; +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::Point_2 Point_2; +typedef K::Point_3 Point_3; +typedef CGAL::Creator_uniform_2 Creator_2; +typedef CGAL::Creator_uniform_3 Creator_3; + +typedef CGAL::Cartesian_d Kd; +typedef Kd::Point_d Point; +typedef CGAL::Creator_uniform_d::iterator, Point>Creator_d; int main () { - const int nb_points_2 = 50000, nb_points_3 = 50000; - CGAL::Random random (42); + int nb_points_2 = 5000, nb_points_3 = 5000, + nb_points_d=10000, small_nb_points_d=3; + CGAL::Random random (42); + CGAL::Timer cost; std::cout << "Testing Hilbert sort." << std::endl; { - std::cout << "Testing 2D: Generating points... " << std::flush; + std::cout << "Testing 2D: Generating "< v; v.reserve (nb_points_2); - CGAL::Random_points_in_square_2 gen (1.0, random); + CGAL::Random_points_in_square_2 gen (1.0, random); for (int i = 0; i < nb_points_2; ++i) v.push_back (*gen++); @@ -45,9 +55,11 @@ int main () std::cout << " Sorting points... " << std::flush; + cost.reset();cost.start(); CGAL::hilbert_sort (v.begin(), v.end()); + cost.stop(); - std::cout << "done." << std::endl; + std::cout << "done in "< v; + v.reserve(size); + + CGAL::points_on_square_grid_2 (box_size, (std::size_t)size, + std::back_inserter(v), Creator_2() ); + + std::cout << "done." << std::endl; + + std::cout << " Sorting points... " << std::flush; + + cost.reset();cost.start(); + CGAL::hilbert_sort (v.begin(), v.end()); + cost.stop(); + + std::cout << "done in "< v; + v.reserve (nb_points_2); + + CGAL::Random_points_in_square_2 gen (1.0, random); + + for (int i = 0; i < nb_points_2; ++i) + v.push_back (*gen++); + + std::cout << "done." << std::endl; + + std::vector v2 (v); + + std::cout << " Sorting points... " << std::flush; + + cost.reset();cost.start(); + CGAL::hilbert_sort(v.begin(),v.end(),CGAL::Hilbert_sort_middle_policy()); + cost.stop(); + + std::cout << "done in "< v; + v.reserve(size); + + CGAL::points_on_square_grid_2 (box_size, (std::size_t)size, + std::back_inserter(v), Creator_2() ); + + std::cout << "done." << std::endl; + + std::cout << " Sorting points... " << std::flush; + + cost.reset();cost.start(); + CGAL::hilbert_sort(v.begin(),v.end(),CGAL::Hilbert_sort_middle_policy()); + cost.stop(); + + std::cout << "done in "< v; v.reserve (nb_points_3); - CGAL::Random_points_in_cube_3 gen (1.0, random); + CGAL::Random_points_in_cube_3 gen (1.0, random); for (int i = 0; i < nb_points_3; ++i) v.push_back (*gen++); @@ -75,9 +174,11 @@ int main () std::cout << " Sorting points... " << std::flush; + cost.reset();cost.start(); CGAL::hilbert_sort (v.begin(), v.end()); + cost.stop(); - std::cout << "done." << std::endl; + std::cout << "done in "< v; + v.reserve(size); + + CGAL::points_on_cube_grid_3 (box_size, (std::size_t)size, + std::back_inserter(v), Creator_3() ); + + std::cout << "done." << std::endl; + + std::cout << " Sorting points... " << std::flush; + + cost.reset();cost.start(); + CGAL::hilbert_sort (v.begin(), v.end()); + cost.stop(); + + std::cout << "done in "< v; + v.reserve (nb_points_3); + + CGAL::Random_points_in_cube_3 gen (1.0, random); + + for (int i = 0; i < nb_points_3; ++i) + v.push_back (*gen++); + + std::cout << "done." << std::endl; + + std::vector v2 (v); + + std::cout << " Sorting points... " << std::flush; + + cost.reset();cost.start(); + CGAL::hilbert_sort(v.begin(),v.end(),CGAL::Hilbert_sort_middle_policy()); + cost.stop(); + + std::cout << "done in "< v; + v.reserve(size); + + CGAL::points_on_cube_grid_3 (box_size, (std::size_t)size, + std::back_inserter(v), Creator_3() ); + + std::cout << "done." << std::endl; + + std::cout << " Sorting points... " << std::flush; + + cost.reset();cost.start(); + CGAL::hilbert_sort(v.begin(),v.end(),CGAL::Hilbert_sort_middle_policy()); + cost.stop(); + + std::cout << "done in "< v; + v.reserve (nb_points_d); + + CGAL::Random_points_in_cube_d gen (dim, 1.0, random); + + for (int i = 0; i < nb_points_d; ++i) + v.push_back (*gen++); + + std::cout << "done." << std::endl; + + std::vector v2 (v); + + std::cout << " Sorting points... " << std::flush; + + cost.reset();cost.start(); + CGAL::hilbert_sort (v.begin(), v.end(),CGAL::Hilbert_sort_median_policy()); + cost.stop(); + + std::cout << "done in "< v; + v.reserve (nb_points_d); + + CGAL::Random_points_in_cube_d gen (dim, 1.0, random); + + for (int i = 0; i < nb_points_d; ++i) + v.push_back (*gen++); + + std::cout << "done." << std::endl; + + std::vector v2 (v); + + std::cout << " Sorting points... " << std::flush; + + cost.reset();cost.start(); + CGAL::hilbert_sort (v.begin(), v.end()); + cost.stop(); + + std::cout << "done in "< v; + v.reserve (nb_points_d); + + CGAL::Random_points_in_cube_d gen (dim, 1.0, random); + + for (int i = 0; i < nb_points_d; ++i) + v.push_back (*gen++); + + std::cout << "done." << std::endl; + + std::vector v2 (v); + + std::cout << " Sorting points ... " << std::flush; + + cost.reset();cost.start(); + CGAL::hilbert_sort (v.begin(), v.end(), + CGAL::Hilbert_sort_middle_policy()); + cost.stop(); + + std::cout << "done in "< v; + v.reserve (nb_points_d); + + CGAL::Random_points_in_cube_d gen (dim, 1.0, random); + + for (int i = 0; i < nb_points_d; ++i) + v.push_back (*gen++); + + std::cout << "done." << std::endl; + + std::vector v2 (v); + + std::cout << " Sorting points... " << std::flush; + + cost.reset();cost.start(); + CGAL::hilbert_sort (v.begin(), v.end()); + cost.stop(); + + std::cout << "done in "< v(size); + + CGAL::points_on_cube_grid_d (dim, box_size, (std::size_t)size, + v.begin(), Creator_d(dim) ); + + std::cout << "done." << std::endl; + + std::cout << " Sorting points... " << std::flush; + + cost.reset();cost.start(); + CGAL::hilbert_sort (v.begin(), v.begin()+size); + cost.stop(); + + std::cout << "done in "< v(size); + + CGAL::points_on_cube_grid_d (dim, box_size, (std::size_t)size, + v.begin(), Creator_d(dim) ); + + std::cout << "done." << std::endl; + + std::cout << " Sorting points... " << std::flush; + + cost.reset();cost.start(); + CGAL::hilbert_sort (v.begin(), v.begin()+size, + CGAL::Hilbert_sort_middle_policy()); + cost.stop(); + + std::cout << "done in "< v(size); + + CGAL::points_on_cube_grid_d (dim, box_size, (std::size_t)size, + v.begin(), Creator_d(dim) ); + + std::cout << "done." << std::endl; + + std::cout << " Sorting points... " << std::flush; + + cost.reset();cost.start(); + CGAL::hilbert_sort (v.begin(), v.begin()+size, + CGAL::Hilbert_sort_middle_policy()); + cost.stop(); + + std::cout << "done in "< v; + v.reserve (nb_points_d); + + CGAL::Random_points_in_cube_d gen (dim, 1.0, random); + + for (int i = 0; i < nb_points_d; ++i) + v.push_back (*gen++); + + std::cout << "done." << std::endl; + + std::vector v2 (v); + + std::cout << " Sorting points... " << std::flush; + + cost.reset();cost.start(); + CGAL::hilbert_sort (v.begin(), v.end()); + cost.stop(); + + std::cout << "done in "< #include +#include #include #include #include +#include +#include #include #include @@ -21,9 +24,12 @@ typedef K::Point_3 Point_3; typedef CGAL::Creator_uniform_2 Creator_2; typedef CGAL::Creator_uniform_3 Creator_3; +typedef CGAL::Cartesian_d Kd; +typedef Kd::Point_d Point; + int main () { - const int nb_points_2 = 50000, nb_points_3 = 50000; + const int nb_points_2 = 50000, nb_points_3 = 50000, nb_points_d=50000; CGAL::Random random (42); std::cout << "Testing Multiscale sort." << std::endl; @@ -55,7 +61,7 @@ int main () std::sort (v2.begin(), v2.end(), K().less_xy_2_object()); assert(v == v2); - std::cout << "OK." << std::endl; + std::cout << "no points lost." << std::endl; } { @@ -85,7 +91,38 @@ int main () std::sort (v2.begin(), v2.end(), K().less_xyz_3_object()); assert(v == v2); - std::cout << "OK." << std::endl; + std::cout << "no points lost." << std::endl; + } + + { + int dim=5; + std::cout << "Testing "< v; + v.reserve (nb_points_d); + + CGAL::Random_points_in_cube_d gen (dim, 1.0, random); + + for (int i = 0; i < nb_points_d; ++i) + v.push_back (*gen++); + + std::cout << "done." << std::endl; + + std::vector v2 (v); + + std::cout << " Sorting points... " << std::flush; + + CGAL::spatial_sort (v.begin(), v.end()); + + std::cout << "done." << std::endl; + + std::cout << " Checking... " << std::flush; + + std::sort (v.begin(), v.end(), Kd().less_lexicographically_d_object()); + std::sort (v2.begin(), v2.end(),Kd().less_lexicographically_d_object()); + assert(v == v2); + + std::cout << "no points lost." << std::endl; } return 0; diff --git a/Triangulation_2/doc_tex/Triangulation_2_ref/TriangulationVertexBaseWithInfo_2.tex b/Triangulation_2/doc_tex/Triangulation_2_ref/TriangulationVertexBaseWithInfo_2.tex index de8810a3a2a..0899f90898a 100644 --- a/Triangulation_2/doc_tex/Triangulation_2_ref/TriangulationVertexBaseWithInfo_2.tex +++ b/Triangulation_2/doc_tex/Triangulation_2_ref/TriangulationVertexBaseWithInfo_2.tex @@ -22,8 +22,7 @@ and provides an additional information storage. \ccRefines{\ccc{TriangulationVertexBase_2}} \ccTypes -\ccNestedType{Info} -{.} +\ccNestedType{Info}{A type which is \ccc{DefaultConstructible} and \ccc{Assignable}.} \ccCreationVariable{v} %% choose variable name diff --git a/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h b/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h index 20559f7a137..2b87d0c42fe 100644 --- a/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h @@ -28,7 +28,8 @@ #include #ifndef CGAL_TRIANGULATION_2_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO -#include +#include +#include #include #include @@ -307,6 +308,7 @@ public: #ifndef CGAL_TRIANGULATION_2_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO private: + //top stands for tuple-or-pair template const Point& top_get_first(const std::pair& pair) const { return pair.first; } template @@ -320,10 +322,10 @@ private: std::ptrdiff_t insert_with_info(InputIterator first,InputIterator last) { size_type n = this->number_of_vertices(); - std::vector indices; + std::vector indices; std::vector points; std::vector infos; - std::size_t index=0; + std::ptrdiff_t index=0; for (InputIterator it=first;it!=last;++it){ Tuple_or_pair value=*it; points.push_back( top_get_first(value) ); @@ -331,14 +333,13 @@ private: indices.push_back(index++); } - typedef internal::Vector_property_map Point_pmap; - typedef internal::Spatial_sort_traits_with_property_map_2 Search_traits; + typedef Spatial_sort_traits_adapter_2 Search_traits; - spatial_sort(indices.begin(),indices.end(),Search_traits(Point_pmap(points),geom_traits())); + spatial_sort(indices.begin(),indices.end(),Search_traits(&(points[0]),geom_traits())); Vertex_handle v_hint; Face_handle hint; - for (typename std::vector::const_iterator + for (typename std::vector::const_iterator it = indices.begin(), end = indices.end(); it != end; ++it){ v_hint = insert(points[*it], hint); diff --git a/Triangulation_2/include/CGAL/Regular_triangulation_2.h b/Triangulation_2/include/CGAL/Regular_triangulation_2.h index 4280f6fcec3..a364dba8697 100644 --- a/Triangulation_2/include/CGAL/Regular_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Regular_triangulation_2.h @@ -28,7 +28,8 @@ #include #ifndef CGAL_TRIANGULATION_2_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO -#include +#include +#include #include #include @@ -383,6 +384,7 @@ public: #ifndef CGAL_TRIANGULATION_2_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO private: + //top stands for tuple-or-pair template const Weighted_point& top_get_first(const std::pair& pair) const { return pair.first; } template @@ -396,10 +398,10 @@ private: std::ptrdiff_t insert_with_info(InputIterator first,InputIterator last) { int n = number_of_vertices(); - std::vector indices; + std::vector indices; std::vector points; std::vector infos; - std::size_t index=0; + std::ptrdiff_t index=0; for (InputIterator it=first;it!=last;++it){ Tuple_or_pair pair = *it; points.push_back( top_get_first(pair) ); @@ -407,14 +409,13 @@ private: indices.push_back(index++); } - typedef internal::Vector_property_map Point_pmap; - typedef internal::Spatial_sort_traits_with_property_map_2 Search_traits; + typedef Spatial_sort_traits_adapter_2 Search_traits; - spatial_sort(indices.begin(),indices.end(),Search_traits(Point_pmap(points),geom_traits())); + spatial_sort(indices.begin(),indices.end(),Search_traits(&(points[0]),geom_traits())); Face_handle hint; Vertex_handle v_hint; - for (typename std::vector::const_iterator + for (typename std::vector::const_iterator it = indices.begin(), end = indices.end(); it != end; ++it) { diff --git a/Triangulation_3/doc_tex/Triangulation_3_ref/TriangulationVertexBaseWithInfo_3.tex b/Triangulation_3/doc_tex/Triangulation_3_ref/TriangulationVertexBaseWithInfo_3.tex index 54d8ad10635..88b429d5247 100644 --- a/Triangulation_3/doc_tex/Triangulation_3_ref/TriangulationVertexBaseWithInfo_3.tex +++ b/Triangulation_3/doc_tex/Triangulation_3_ref/TriangulationVertexBaseWithInfo_3.tex @@ -22,8 +22,8 @@ and provides an additional information storage. \ccRefines{\ccc{TriangulationVertexBase_3}} \ccTypes -\ccNestedType{Info} -{.} +\ccNestedType{Info}{A type which is \ccc{DefaultConstructible} and \ccc{Assignable}.} + \ccCreationVariable{v} %% choose variable name diff --git a/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h b/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h index 0e52632eb40..62f59e96751 100644 --- a/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h @@ -32,7 +32,8 @@ #include #ifndef CGAL_TRIANGULATION_3_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO -#include +#include +#include #include #include @@ -243,6 +244,7 @@ public: #ifndef CGAL_TRIANGULATION_3_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO private: + //top stands for tuple-or-pair template const Point& top_get_first(const std::pair& pair) const { return pair.first; } template @@ -256,10 +258,10 @@ private: std::ptrdiff_t insert_with_info(InputIterator first,InputIterator last) { size_type n = number_of_vertices(); - std::vector indices; + std::vector indices; std::vector points; std::vector infos; - std::size_t index=0; + std::ptrdiff_t index=0; for (InputIterator it=first;it!=last;++it){ Tuple_or_pair value=*it; points.push_back( top_get_first(value) ); @@ -267,13 +269,12 @@ private: indices.push_back(index++); } - typedef internal::Vector_property_map Point_pmap; - typedef internal::Spatial_sort_traits_with_property_map_3 Search_traits; + typedef Spatial_sort_traits_adapter_3 Search_traits; - spatial_sort(indices.begin(),indices.end(),Search_traits(Point_pmap(points),geom_traits())); + spatial_sort(indices.begin(),indices.end(),Search_traits(&(points[0]),geom_traits())); Vertex_handle hint; - for (typename std::vector::const_iterator + for (typename std::vector::const_iterator it = indices.begin(), end = indices.end(); it != end; ++it){ hint = insert(points[*it], hint); diff --git a/Triangulation_3/include/CGAL/Regular_triangulation_3.h b/Triangulation_3/include/CGAL/Regular_triangulation_3.h index 5583161da8c..203a905ea95 100644 --- a/Triangulation_3/include/CGAL/Regular_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Regular_triangulation_3.h @@ -31,7 +31,8 @@ #include #ifndef CGAL_TRIANGULATION_3_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO -#include +#include +#include #include #include @@ -200,6 +201,7 @@ public: #ifndef CGAL_TRIANGULATION_3_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO private: + //top stands for tuple-or-pair template const Weighted_point& top_get_first(const std::pair& pair) const { return pair.first; } template @@ -213,10 +215,10 @@ private: std::ptrdiff_t insert_with_info(InputIterator first,InputIterator last) { size_type n = number_of_vertices(); - std::vector indices; + std::vector indices; std::vector points; std::vector infos; - std::size_t index=0; + std::ptrdiff_t index=0; for (InputIterator it=first;it!=last;++it){ Tuple_or_pair pair = *it; points.push_back( top_get_first(pair) ); @@ -224,13 +226,12 @@ private: indices.push_back(index++); } - typedef internal::Vector_property_map Point_pmap; - typedef internal::Spatial_sort_traits_with_property_map_3 Search_traits; + typedef Spatial_sort_traits_adapter_3 Search_traits; - spatial_sort(indices.begin(),indices.end(),Search_traits(Point_pmap(points),geom_traits())); + spatial_sort( indices.begin(),indices.end(),Search_traits(&(points[0]),geom_traits()) ); Cell_handle hint; - for (typename std::vector::const_iterator + for (typename std::vector::const_iterator it = indices.begin(), end = indices.end(); it != end; ++it) { diff --git a/Triangulation_3/include/CGAL/internal/info_check.h b/Triangulation_3/include/CGAL/internal/info_check.h new file mode 100644 index 00000000000..31d86a738bf --- /dev/null +++ b/Triangulation_3/include/CGAL/internal/info_check.h @@ -0,0 +1,44 @@ +// Copyright (c) 2010 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you may redistribute it under +// the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Sebastien Loriot +// + +#ifndef CGAL_INTERNAL_INFO_CHECK_H +#define CGAL_INTERNAL_INFO_CHECK_H + +#include + +namespace CGAL { + +namespace internal{ + +BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Has_typedef_Info,Info,false) + +template ::value> + struct Info_check{ + struct type{}; +}; + +template +struct Info_check{ + typedef typename T::Info type; +}; + +} } //namespace CGAL::internal + +#endif //CGAL_INTERNAL_INFO_CHECK_H diff --git a/Triangulation_3/include/CGAL/internal/spatial_sorting_traits_with_indices.h b/Triangulation_3/include/CGAL/internal/spatial_sorting_traits_with_indices.h deleted file mode 100644 index b2da4a9f508..00000000000 --- a/Triangulation_3/include/CGAL/internal/spatial_sorting_traits_with_indices.h +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (c) 2010 GeometryFactory (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org); you may redistribute it under -// the terms of the Q Public License version 1.0. -// See the file LICENSE.QPL distributed with CGAL. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -// -// $URL$ -// $Id$ -// -// -// Author(s) : Sebastien Loriot -// - -#ifndef CGAL_INTERNAL_SPATIAL_SORTING_TRAITS_WITH_INDICES -#define CGAL_INTERNAL_SPATIAL_SORTING_TRAITS_WITH_INDICES - -#include -#include - -namespace CGAL { - -namespace internal{ - -BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Has_typedef_Info,Info,false) - -template ::value> - struct Info_check{ - struct type{}; -}; - -template -struct Info_check{ - typedef typename T::Info type; -}; - -template sizeof(int*))> -struct Arg_type_selection; - -template -struct Arg_type_selection{ - typedef T type; -}; - -template -struct Arg_type_selection{ - typedef const T& type; -}; - -template -class Vector_property_map{ - const std::vector& data; -public: - typedef std::size_t key_type; - Vector_property_map(const std::vector& input):data(input){} - - const T& operator[](key_type i) const{ - return data[i]; - } -}; - -template -class Spatial_sort_traits_with_property_map_3:public Base_traits{ - PointPropertyMap accessor_; -public: - Spatial_sort_traits_with_property_map_3(const PointPropertyMap& accessor,Base_traits base=Base_traits()) - :Base_traits(base),accessor_(accessor){} - - typedef Base_traits Gt; - typedef typename PointPropertyMap::key_type Point_3; - typedef typename Arg_type_selection::type Arg_type; - - struct Less_x_3 : public Base_traits::Less_x_3{ - Less_x_3(const PointPropertyMap& accessor,const typename Base_traits::Less_x_3& base): - Base_traits::Less_x_3(base),accessor_(accessor){} - const PointPropertyMap& accessor_; - bool operator()(Arg_type p,Arg_type q) const { - return static_cast(this)->operator()(accessor_[p],accessor_[q]); - } - }; - - struct Less_y_3 : public Base_traits::Less_y_3{ - Less_y_3(const PointPropertyMap& accessor,const typename Base_traits::Less_y_3& base): - Base_traits::Less_y_3(base),accessor_(accessor){} - const PointPropertyMap& accessor_; - bool operator()(Arg_type p,Arg_type q) const { - return static_cast(this)->operator()(accessor_[p],accessor_[q]); - } - }; - - struct Less_z_3 : public Base_traits::Less_z_3{ - Less_z_3(const PointPropertyMap& accessor,const typename Base_traits::Less_z_3& base): - Base_traits::Less_z_3(base),accessor_(accessor){} - const PointPropertyMap& accessor_; - bool operator()(Arg_type p,Arg_type q) const { - return static_cast(this)->operator()(accessor_[p],accessor_[q]); - } - }; - - Less_x_3 less_x_3_object () const {return Less_x_3(accessor_,static_cast(this)->less_x_3_object() );} - Less_y_3 less_y_3_object () const {return Less_y_3(accessor_,static_cast(this)->less_y_3_object() );} - Less_z_3 less_z_3_object () const {return Less_z_3(accessor_,static_cast(this)->less_z_3_object() );} -}; - -template -class Spatial_sort_traits_with_property_map_2:public Base_traits{ - PointPropertyMap accessor_; -public: - Spatial_sort_traits_with_property_map_2(const PointPropertyMap& accessor,Base_traits base=Base_traits()) - :Base_traits(base),accessor_(accessor){} - - typedef Base_traits Gt; - typedef typename PointPropertyMap::key_type Point_2; - typedef typename Arg_type_selection::type Arg_type; - - struct Less_x_2 : public Base_traits::Less_x_2{ - Less_x_2(const PointPropertyMap& accessor,const typename Base_traits::Less_x_2& base): - Base_traits::Less_x_2(base),accessor_(accessor){} - const PointPropertyMap& accessor_; - bool operator()(Arg_type p,Arg_type q) const { - return static_cast(this)->operator()(accessor_[p],accessor_[q]); - } - }; - - struct Less_y_2 : public Base_traits::Less_y_2{ - Less_y_2(const PointPropertyMap& accessor,const typename Base_traits::Less_y_2& base): - Base_traits::Less_y_2(base),accessor_(accessor){} - const PointPropertyMap& accessor_; - bool operator()(Arg_type p,Arg_type q) const { - return static_cast(this)->operator()(accessor_[p],accessor_[q]); - } - }; - - Less_x_2 less_x_2_object () const {return Less_x_2(accessor_,static_cast(this)->less_x_2_object() );} - Less_y_2 less_y_2_object () const {return Less_y_2(accessor_,static_cast(this)->less_y_2_object() );} - -}; -} } //namespace CGAL::internal - -#endif //CGAL_INTERNAL_SPATIAL_SORTING_TRAITS_WITH_INDICES