mirror of https://github.com/CGAL/cgal
merge from next
This commit is contained in:
commit
8d9c812cb4
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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) )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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<CDT> 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<CDT,SF>& 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);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -114,6 +114,16 @@ CGAL 3.9 offers the following improvements and new functionality : </p>
|
|||
<li>Various fixes in the manual.</li>
|
||||
</ul>
|
||||
|
||||
<h3>dD Kernel</h3>
|
||||
<li>The d-dimensional kernel concept and models have been modified
|
||||
to additionally provide two new functors Less_coordinate_d and Point_dimension_d.</li>
|
||||
<h3>Spatial_sorting (major new feature added)</h3>
|
||||
<ul>
|
||||
<li>General dimension is now supported.</li>
|
||||
<li>Hilbert sorting admits now two policies: splitting at
|
||||
median or at middle (see user manual).</li>
|
||||
<li>Using a property map, sorting on keys instead of points is now easier</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="release3.8">Release 3.8 </h2>
|
||||
<DIV>
|
||||
|
|
|
|||
|
|
@ -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}{}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
@ -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}
|
||||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -251,6 +251,8 @@ public:
|
|||
typedef Compare_lexicographicallyCd<Self> Compare_lexicographically_d;
|
||||
typedef Lt_from_compare<Self> Less_lexicographically_d;
|
||||
typedef Le_from_compare<Self> Less_or_equal_lexicographically_d;
|
||||
typedef Less_coordinateCd<Self> Less_coordinate_d;
|
||||
typedef Point_dimensionCd<Self> Point_dimension_d;
|
||||
typedef Eq_from_method<Self> Equal_d;
|
||||
typedef Center_of_sphereCd<Self> Center_of_sphere_d;
|
||||
typedef Contained_in_linear_hullCd<Self> 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
|
||||
|
|
|
|||
|
|
@ -253,6 +253,8 @@ public:
|
|||
typedef Compare_lexicographicallyHd<Self> Compare_lexicographically_d;
|
||||
typedef Lt_from_compare<Self> Less_lexicographically_d;
|
||||
typedef Le_from_compare<Self> Less_or_equal_lexicographically_d;
|
||||
typedef Less_coordinateHd<Self> Less_coordinate_d;
|
||||
typedef Point_dimensionHd<Self> Point_dimension_d;
|
||||
typedef Eq_from_method<Self> Equal_d;
|
||||
typedef Center_of_sphereHd<Self> Center_of_sphere_d;
|
||||
typedef Contained_in_linear_hullHd<Self> 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
|
||||
|
|
|
|||
|
|
@ -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 <typename K>
|
||||
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 <typename K>
|
||||
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)<q.cartesian(i);
|
||||
}
|
||||
};
|
||||
|
||||
template <class R>
|
||||
struct Lift_to_paraboloidCd {
|
||||
typedef typename R::Point_d Point_d;
|
||||
|
|
|
|||
|
|
@ -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 <typename K>
|
||||
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 <typename K>
|
||||
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)<q.cartesian(i)*p.homogeneous(d);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class R>
|
||||
struct Lift_to_paraboloidHd {
|
||||
typedef typename R::Point_d Point_d;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,2 @@
|
|||
Combinatorial_map-gdamiand
|
||||
unique_sqrt_extension-sloriot
|
||||
spatial_sorting-increase_dim_and_add_info-sloriot
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -32,6 +32,10 @@ class Delaunay_mesh_area_criteria_2
|
|||
Delaunay_mesh_size_criteria_2<Tr>. Delaunay_mesh_criteria_2<Tr> is a
|
||||
virtual base class of Delaunay_mesh_size_criteria_2<Tr>. */
|
||||
{
|
||||
typedef typename Tr::Geom_traits Geom_traits;
|
||||
|
||||
protected:
|
||||
Geom_traits traits;
|
||||
public:
|
||||
typedef Delaunay_mesh_criteria_2<Tr> Base;
|
||||
typedef Delaunay_mesh_size_criteria_2<Tr> Private_base;
|
||||
|
|
@ -39,8 +43,9 @@ public:
|
|||
typedef typename Delaunay_mesh_size_criteria_2<Tr>::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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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 )
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ class \ccc{Nef_polyhedron_3<Traits>} 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\ .}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ class \ccc{Nef_polyhedron_S2<Traits>} 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\ .}
|
||||
|
|
|
|||
|
|
@ -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 <typename Object_predicate>
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef _COLOR_MAP_H
|
||||
#define _COLOR_MAP_H
|
||||
|
||||
#include <QColor>
|
||||
|
||||
template <typename Output_color_iterator>
|
||||
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
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef KERNEL_TYPE_H
|
||||
#define KERNEL_TYPE_H
|
||||
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Mesh_3/Robust_intersection_traits_3.h>
|
||||
|
||||
namespace kernel_type_h {
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K1;
|
||||
}
|
||||
|
||||
typedef CGAL::Mesh_3::Robust_intersection_traits_3<kernel_type_h::K1> Kernel;
|
||||
|
||||
#endif // KERNEL_TYPE_H
|
||||
|
|
@ -10,17 +10,94 @@
|
|||
#include <QSettings>
|
||||
#include <QHeaderView>
|
||||
#include <QMenu>
|
||||
#include <QMenuBar>
|
||||
#include <QChar>
|
||||
#include <QAction>
|
||||
#include <QLibrary>
|
||||
#include <QPluginLoader>
|
||||
#include <QMessageBox>
|
||||
#include <QScrollBar>
|
||||
#include <QColor>
|
||||
#include <QColorDialog>
|
||||
#include <QClipboard>
|
||||
#include <QCloseEvent>
|
||||
|
||||
#ifdef QT_SCRIPT_LIB
|
||||
# include <QScriptValue>
|
||||
# ifdef QT_SCRIPTTOOLS_LIB
|
||||
# include <QScriptEngineDebugger>
|
||||
# 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 <QScriptEngine>
|
||||
# include <QScriptValue>
|
||||
|
||||
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<Scene_item*>(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<MainWindow*>(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<Scene_item*>(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<QAction*>()) {
|
||||
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<QScriptEngineDebugger*>("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<QDir> 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<Polyhedron_demo_io_plugin_interface*>(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<QAction*>()) {
|
||||
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 = "<font color=\"" + colorName + "\" >" + message + "</font><br>";
|
||||
message = "<font color=\"" + colorName + "\" style=\"font-style: " + font + ";\" >" +
|
||||
message + "</font><br>";
|
||||
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<QAction*>(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<Scene_item*>(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<int> MainWindow::getSelectedSceneItemIndices() const
|
||||
{
|
||||
QModelIndexList selectedRows = treeView->selectionModel()->selectedRows();
|
||||
QList<int> 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<QWidget*>(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("<br /><i>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);
|
||||
|
|
|
|||
|
|
@ -4,8 +4,14 @@
|
|||
|
||||
#include <QtOpenGL/qgl.h>
|
||||
#include <CGAL/Qt/DemosMainWindow.h>
|
||||
#ifdef QT_SCRIPT_LIB
|
||||
# include <QScriptEngine>
|
||||
#endif
|
||||
|
||||
#include <QVector>
|
||||
#include <QList>
|
||||
#include <QFileInfo>
|
||||
#include <QStringList>
|
||||
|
||||
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<int> getSelectedSceneItemIndices() const;
|
||||
|
||||
private:
|
||||
QString strippedName(const QString &fullFileName);
|
||||
|
|
@ -93,6 +131,16 @@ private:
|
|||
QTreeView* treeView;
|
||||
Ui::MainWindow* ui;
|
||||
QVector<Polyhedron_demo_io_plugin_interface*> 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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
|
|
@ -29,9 +28,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="infoLabel"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
|
|
@ -40,7 +36,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>978</width>
|
||||
<height>26</height>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
|
|
@ -62,6 +58,7 @@
|
|||
<addaction name="actionShowHide"/>
|
||||
<addaction name="actionSetPolyhedronA"/>
|
||||
<addaction name="actionSetPolyhedronB"/>
|
||||
<addaction name="actionSelect_all_items"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuOperations">
|
||||
<property name="title">
|
||||
|
|
@ -124,9 +121,21 @@
|
|||
</property>
|
||||
<addaction name="dummyAction"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuCamera">
|
||||
<property name="title">
|
||||
<string>Ca&mera</string>
|
||||
</property>
|
||||
<addaction name="actionDumpCamera"/>
|
||||
<addaction name="action_Copy_camera"/>
|
||||
<addaction name="action_Paste_camera"/>
|
||||
</widget>
|
||||
<addaction name="actionRecenterScene"/>
|
||||
<addaction name="action_Look_at"/>
|
||||
<addaction name="actionAntiAliasing"/>
|
||||
<addaction name="actionDraw_two_sides"/>
|
||||
<addaction name="actionSetBackgroundColor"/>
|
||||
<addaction name="menuDockWindows"/>
|
||||
<addaction name="menuCamera"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuEdit"/>
|
||||
|
|
@ -139,7 +148,7 @@
|
|||
<locale language="English" country="UnitedStates"/>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Polyhedra</string>
|
||||
<string>Geometric Objects</string>
|
||||
</property>
|
||||
<attribute name="dockWidgetArea">
|
||||
<number>1</number>
|
||||
|
|
@ -206,6 +215,9 @@
|
|||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="indentation">
|
||||
<number>0</number>
|
||||
</property>
|
||||
|
|
@ -238,6 +250,45 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QDockWidget" name="infoDockWidget">
|
||||
<property name="windowTitle">
|
||||
<string>Infos</string>
|
||||
</property>
|
||||
<attribute name="dockWidgetArea">
|
||||
<number>1</number>
|
||||
</attribute>
|
||||
<widget class="QWidget" name="dockWidgetContents_2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="0,0">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="infoLabel">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="displayLabel">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<action name="actionQuit">
|
||||
<property name="text">
|
||||
<string>&Quit</string>
|
||||
|
|
@ -431,17 +482,11 @@
|
|||
<property name="text">
|
||||
<string>Set polyhedron A</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+A</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSetPolyhedronB">
|
||||
<property name="text">
|
||||
<string>Set polyhedron B</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+B</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionInsideOut">
|
||||
<property name="text">
|
||||
|
|
@ -453,6 +498,11 @@
|
|||
<string>&Remeshing</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionConvexDecomposition">
|
||||
<property name="text">
|
||||
<string>Convex Decomposition</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionMVC">
|
||||
<property name="text">
|
||||
<string>Mean &value coordinates</string>
|
||||
|
|
@ -489,6 +539,19 @@
|
|||
<string>Ctrl+T</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRecenterScene">
|
||||
<property name="text">
|
||||
<string>Re&center scene</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+C</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSetBackgroundColor">
|
||||
<property name="text">
|
||||
<string>Change &background color...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionMinkowskiSum">
|
||||
<property name="text">
|
||||
<string>&Minkowski sum</string>
|
||||
|
|
@ -497,9 +560,32 @@
|
|||
<string>Ctrl+O, M</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionConvexDecomposition">
|
||||
<action name="action_Look_at">
|
||||
<property name="text">
|
||||
<string>Convex Decomposition</string>
|
||||
<string>&Look at...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDumpCamera">
|
||||
<property name="text">
|
||||
<string>&Dump camera coordinates</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Copy_camera">
|
||||
<property name="text">
|
||||
<string>&Copy camera</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Paste_camera">
|
||||
<property name="text">
|
||||
<string>&Paste camera</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSelect_all_items">
|
||||
<property name="text">
|
||||
<string>Select all items</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+A</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef POINT_DIALOG_CONFIG_H
|
||||
#define POINT_DIALOG_CONFIG_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -17,6 +17,13 @@
|
|||
#include <CGAL/Dualizer.h>
|
||||
#include <CGAL/translate.h>
|
||||
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <QtDebug>
|
||||
|
||||
#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<QAction*> 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_polygon_soup*>(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_polygon_soup*>(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_polygon_soup*>(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_polyhedron_item*>(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()
|
||||
|
|
|
|||
|
|
@ -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 <QTime>
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,16 @@
|
|||
#include <CGAL/Make_quad_soup.h> // output for plane fitting
|
||||
#include <CGAL/Make_bar.h> // 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
|
||||
|
|
|
|||
|
|
@ -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<Point> polyhedron_points;
|
||||
polyhedron_points.reserve(pMesh->size_of_vertices());
|
||||
std::copy(pMesh->points_begin(), pMesh->points_end(),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include <QApplication>
|
||||
#include <QMessageBox>
|
||||
#include <QMainWindow>
|
||||
#include "Kernel_type.h"
|
||||
#include "Polyhedron_type.h"
|
||||
#include "Scene_polyhedron_item.h"
|
||||
|
||||
|
|
@ -14,6 +15,8 @@
|
|||
#include <CGAL/self_intersect.h>
|
||||
#include <CGAL/Make_triangle_soup.h>
|
||||
|
||||
typedef Kernel::Triangle_3 Triangle;
|
||||
|
||||
class Polyhedron_demo_self_intersection_plugin :
|
||||
public QObject,
|
||||
public Polyhedron_demo_plugin_helper
|
||||
|
|
|
|||
|
|
@ -6,125 +6,9 @@
|
|||
#include "Polyhedron_demo_plugin_helper.h"
|
||||
#include "Scene_polyhedron_item.h"
|
||||
#include "Polyhedron_type.h"
|
||||
#include <CGAL/HalfedgeDS_decorator.h>
|
||||
|
||||
#include <CGAL/assertions_behaviour.h>
|
||||
#include <CGAL/exceptions.h>
|
||||
|
||||
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
|
||||
#include <CGAL/Triangulation_face_base_with_info_2.h>
|
||||
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
|
||||
#include <CGAL/Constrained_triangulation_plus_2.h>
|
||||
#include <CGAL/Triangulation_2_filtered_projection_traits_3.h>
|
||||
|
||||
#include "CGAL/compute_normal.h"
|
||||
|
||||
#include <queue>
|
||||
|
||||
typedef Polyhedron::Halfedge_handle Halfedge_handle;
|
||||
|
||||
typedef CGAL::Triangulation_2_filtered_projection_traits_3<Kernel> Traits;
|
||||
|
||||
typedef CGAL::Triangulation_vertex_base_with_info_2<Halfedge_handle,
|
||||
Traits> Vb;
|
||||
|
||||
struct Face_info {
|
||||
Halfedge_handle e[3];
|
||||
bool is_external;
|
||||
};
|
||||
|
||||
typedef CGAL::Triangulation_face_base_with_info_2<Face_info,
|
||||
Traits> Fb1;
|
||||
|
||||
typedef CGAL::Constrained_triangulation_face_base_2<Traits, Fb1> Fb;
|
||||
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
|
||||
typedef CGAL::No_intersection_tag Itag;
|
||||
typedef CGAL::Constrained_Delaunay_triangulation_2<Traits, TDS,Itag> CDTbase;
|
||||
typedef CGAL::Constrained_triangulation_plus_2<CDTbase> CDT;
|
||||
|
||||
typedef Polyhedron::HalfedgeDS HDS;
|
||||
|
||||
class Triangulate_modifier : public CGAL::Modifier_base<HDS> {
|
||||
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<HDS> 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<Facet, Kernel>(*fh1);
|
||||
Kernel::Vector_3 v1 = compute_facet_normal<Facet, Kernel>(*fh1);
|
||||
Kernel::Vector_3 v2 = compute_facet_normal<Facet, Kernel>(*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_polyhedron_item*>(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<Facet_handle> 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<Facet_handle>::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<Facet,Kernel>(*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<CDT::Face_handle> face_queue;
|
||||
face_queue.push(cdt.infinite_vertex()->face());
|
||||
while(! face_queue.empty() ) {
|
||||
CDT::Face_handle fh = face_queue.front();
|
||||
face_queue.pop();
|
||||
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:
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ QList<QAction*> 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_bbox_item*>(scene->item(i)))
|
||||
|
|
|
|||
|
|
@ -3,27 +3,126 @@
|
|||
|
||||
// CGAL
|
||||
// kernel
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
#include "Kernel_type.h"
|
||||
|
||||
// surface mesh
|
||||
#include <CGAL/Polyhedron_3.h>
|
||||
#include <CGAL/Polyhedron_items_3.h>
|
||||
|
||||
#include <set>
|
||||
|
||||
template <typename Refs, typename Tag, typename Point, typename Patch_id>
|
||||
class Polyhedron_demo_vertex :
|
||||
public CGAL::HalfedgeDS_vertex_base<Refs, Tag, Point>
|
||||
{
|
||||
public:
|
||||
typedef std::set<Patch_id> Set_of_indices;
|
||||
|
||||
private:
|
||||
typedef CGAL::HalfedgeDS_vertex_base<Refs, Tag, Point> 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 Refs, class Tprev, class Tvertex, class Tface>
|
||||
class Polyhedron_demo_halfedge :
|
||||
public CGAL::HalfedgeDS_halfedge_base<Refs,Tprev,Tvertex,Tface>
|
||||
{
|
||||
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 Refs, class T_, class Pln_, class Patch_id_>
|
||||
class Polyhedron_demo_face :
|
||||
public CGAL::HalfedgeDS_face_base<Refs,T_,Pln_>
|
||||
{
|
||||
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 <typename Patch_id>
|
||||
class Polyhedron_demo_items : public CGAL::Polyhedron_items_3 {
|
||||
public:
|
||||
// wrap vertex
|
||||
template<class Refs, class Traits> struct Vertex_wrapper
|
||||
{
|
||||
typedef typename Traits::Point_3 Point;
|
||||
typedef Polyhedron_demo_vertex<Refs,
|
||||
CGAL::Tag_true,
|
||||
Point,
|
||||
Patch_id> Vertex;
|
||||
};
|
||||
|
||||
// wrap face
|
||||
template<class Refs, class Traits> struct Face_wrapper
|
||||
{
|
||||
typedef Polyhedron_demo_face<Refs,
|
||||
CGAL::Tag_true,
|
||||
typename Traits::Plane_3,
|
||||
Patch_id> Face;
|
||||
};
|
||||
|
||||
// wrap halfedge
|
||||
template<class Refs, class Traits> struct Halfedge_wrapper
|
||||
{
|
||||
typedef Polyhedron_demo_halfedge<Refs,
|
||||
CGAL::Tag_true,
|
||||
CGAL::Tag_true,
|
||||
CGAL::Tag_true> 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<Kernel> Polyhedron;
|
||||
typedef CGAL::Polyhedron_3<Kernel, Polyhedron_demo_items<int> > Polyhedron;
|
||||
|
||||
#endif // POLYHEDRON_TYPE_H
|
||||
|
|
|
|||
|
|
@ -8,8 +8,16 @@
|
|||
|
||||
#include <CGAL/Filtered_kernel_fwd.h>
|
||||
|
||||
template <typename Patch_id>
|
||||
class Polyhedron_demo_items;
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
namespace Mesh_3 {
|
||||
template <typename Kernel>
|
||||
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<double>, true > K1;
|
||||
#endif
|
||||
typedef CGAL::Mesh_3::Robust_intersection_traits_3<K1> Kernel;
|
||||
}
|
||||
|
||||
// surface mesh
|
||||
typedef CGAL::Polyhedron_3<Kernel,
|
||||
CGAL::Polyhedron_items_3,
|
||||
typedef CGAL::Polyhedron_3<polyhedron_type_fwd_h::Kernel,
|
||||
Polyhedron_demo_items<int>,
|
||||
// CGAL::Polyhedron_items_3,
|
||||
CGAL::HalfedgeDS_default,
|
||||
std::allocator<int> > Polyhedron;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
#include "Scene.h"
|
||||
#include "Scene_item.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QMetaObject>
|
||||
#include <QString>
|
||||
#include <QGLWidget>
|
||||
#include <QEvent>
|
||||
|
|
@ -10,11 +12,12 @@
|
|||
#include <QColorDialog>
|
||||
#include <QApplication>
|
||||
#include <QPointer>
|
||||
#include <QList>
|
||||
|
||||
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<int> indices)
|
||||
{
|
||||
QList<Scene_item*> 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<int>(entries.value(index.row())->renderingMode());
|
||||
return static_cast<int>(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<int> 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<Scene_item*>(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<QColor>(),
|
||||
0/*,
|
||||
tr("Select color"),
|
||||
QColorDialog::ShowAlphaChannel*/);
|
||||
if (color.isValid()) {
|
||||
model->setData(index, color );
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
|
||||
if(mouseEvent->button() == ::Qt::LeftButton) {
|
||||
QColor color =
|
||||
QColorDialog::getColor(model->data(index).value<QColor>(),
|
||||
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<QMouseEvent*>(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<const Scene*>(scene_interface);
|
||||
if(!scene) return 0;
|
||||
Q_FOREACH(Scene_item* item, scene->entries()) {
|
||||
Scene_item* ptr = qobject_cast<Scene_item*>(metaobj.cast(item));
|
||||
if(ptr && ((ptr->*fn)() == name)) return ptr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Q_DECL_EXPORT
|
||||
QList<Scene_item*>
|
||||
findItems(const Scene_interface* scene_interface,
|
||||
const QMetaObject&,
|
||||
QString name, Scene_item_name_fn_ptr fn)
|
||||
{
|
||||
const Scene* scene = dynamic_cast<const Scene*>(scene_interface);
|
||||
QList<Scene_item*> list;
|
||||
if(!scene) return list;
|
||||
|
||||
Q_FOREACH(Scene_item* item, scene->entries()) {
|
||||
Scene_item* ptr = qobject_cast<Scene_item*>(item);
|
||||
if(ptr && ((ptr->*fn)() == name)) {
|
||||
list << ptr;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
} // end namespace details
|
||||
} // end namespace scene
|
||||
|
||||
#include "Scene.moc"
|
||||
|
|
|
|||
|
|
@ -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<int>);
|
||||
// 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<Scene_item*>& entries() const { return m_entries; }
|
||||
Q_INVOKABLE Scene_item* item(int) const ;
|
||||
int mainSelectionIndex() const;
|
||||
QList<int> 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<int> 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<Scene_item*> Entries;
|
||||
Entries entries;
|
||||
Entries m_entries;
|
||||
int selected_item;
|
||||
QList<int> 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)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef SCENE_CONFIG_H
|
||||
#define SCENE_CONFIG_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#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
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
#ifndef SCENE_FIND_ITEMS
|
||||
#define SCENE_FIND_ITEMS
|
||||
|
||||
#include <QObject>
|
||||
#include <QMetaObject>
|
||||
#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<Scene_item*>
|
||||
findItems(const Scene_interface* scene_interface,
|
||||
const QMetaObject& metaobj,
|
||||
QString name, Scene_item_name_fn_ptr fn); // fwd declaration
|
||||
|
||||
template <typename T>
|
||||
T findItem(const Scene_interface* scene, QString name,
|
||||
Scene_item_name_fn_ptr fn)
|
||||
{
|
||||
return
|
||||
static_cast<T>(findItem(scene,
|
||||
reinterpret_cast<T>(0)->staticMetaObject,
|
||||
name, fn));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
QList<T> findItems(const Scene_interface* scene, QString name,
|
||||
Scene_item_name_fn_ptr fn)
|
||||
{
|
||||
QList<Scene_item*> void_list =
|
||||
findItems(scene, reinterpret_cast<T>(0)->staticMetaObject,
|
||||
name, fn);
|
||||
QList<T> list;
|
||||
Q_FOREACH(Scene_item* ptr, void_list) {
|
||||
list << qobject_cast<T>(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 <typename T>
|
||||
T findItem(const Scene_interface* scene,
|
||||
QString item_name = QString())
|
||||
{ return details::findItem<T>(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 <typename T>
|
||||
QList<T> findItems(const Scene_interface* scene,
|
||||
QString item_name = QString())
|
||||
{ return details::findItems<T>(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 <typename T>
|
||||
T findItemByObjectName(const Scene_interface* scene,
|
||||
QString obj_name = QString())
|
||||
{ return details::findItem<T>(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 <typename T>
|
||||
QList<T> findItemsByObjectName(const Scene_interface* scene,
|
||||
QString obj_name = QString())
|
||||
{ return details::findItems<T>(scene, obj_name, &QObject::objectName); }
|
||||
|
||||
|
||||
// template <typename T>
|
||||
// T scene_findItem(const Scene* scene, QString name, Scene_item_name_fn_ptr fn) {
|
||||
// return
|
||||
// static_cast<T>(scene_findItem(scene, name, fn,
|
||||
// reinterpret_cast<T>(0)->staticMetaObject()));
|
||||
// }
|
||||
|
||||
// template <typename T>
|
||||
// QList<T>
|
||||
// scene_findItems(const Scene* scene, QString name, Scene_item_name_fn_ptr fn) {
|
||||
// QList<void*> void_list =
|
||||
// scene_findItems(scene, name, fn,
|
||||
// reinterpret_cast<T>(0)->staticMetaObject());
|
||||
// QList<T> list;
|
||||
// Q_FOREACH(void* ptr, void_list) {
|
||||
// list << static_cast<T>(ptr);
|
||||
// }
|
||||
// return list;
|
||||
// }
|
||||
|
||||
// } // end scene namespace
|
||||
|
||||
} // end namespace scene
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <QString>
|
||||
#include <QColor>
|
||||
#include <QList>
|
||||
#include <algorithm>
|
||||
|
||||
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<Item_id> 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
|
||||
|
||||
|
|
|
|||
|
|
@ -1,34 +1,104 @@
|
|||
#include "Scene_item.h"
|
||||
#include "Scene_interface.h"
|
||||
#include <QMenu>
|
||||
|
||||
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"
|
||||
|
||||
|
|
|
|||
|
|
@ -4,12 +4,15 @@
|
|||
#include "Scene_item_config.h"
|
||||
#include "Scene_interface.h"
|
||||
#include <QString>
|
||||
#include <QPixmap>
|
||||
#include <QFont>
|
||||
|
||||
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 <QMetaType>
|
||||
Q_DECLARE_METATYPE(Scene_item*)
|
||||
|
||||
#endif // SCENE_ITEM_H
|
||||
|
|
|
|||
|
|
@ -3,6 +3,10 @@
|
|||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifdef demo_framework_EXPORTS
|
||||
# define scene_item_EXPORTS
|
||||
#endif
|
||||
|
||||
#ifdef scene_item_EXPORTS
|
||||
# define SCENE_ITEM_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include <CGAL/Polyhedron_incremental_builder_3.h>
|
||||
// #include <CGAL/OFF_to_nef_3.h>
|
||||
#include <CGAL/IO/Polyhedron_iostream.h>
|
||||
#include <CGAL/IO/Nef_polyhedron_iostream_3.h>
|
||||
#include <CGAL/Inverse_index.h>
|
||||
|
||||
#include <QObject>
|
||||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@
|
|||
#include <cmath>
|
||||
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
#include "Scene_polygon_soup.h"
|
||||
#include "Scene_polyhedron_item.h"
|
||||
#include <CGAL/IO/Polyhedron_iostream.h>
|
||||
#include "Polyhedron_type.h"
|
||||
#include <CGAL/Polyhedron_incremental_builder_3.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QtDebug>
|
||||
|
|
@ -12,11 +15,13 @@
|
|||
|
||||
#include <CGAL/IO/File_scanner_OFF.h>
|
||||
#include <CGAL/IO/File_writer_OFF.h>
|
||||
#include <CGAL/version.h>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
typedef Kernel::Point_3 Point_3;
|
||||
|
||||
struct Polygon_soup {
|
||||
struct Polygon_soup :
|
||||
public CGAL::Modifier_base<Polyhedron::HalfedgeDS>
|
||||
{
|
||||
typedef std::vector<Point_3> Points;
|
||||
typedef std::vector<std::size_t> Polygon_3;
|
||||
typedef std::map<std::pair<std::size_t, std::size_t>, std::set<std::size_t> > 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 <CGAL/IO/generic_print_polyhedron.h>
|
||||
#include <iostream>
|
||||
|
||||
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<Output_HDS> 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"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@
|
|||
#include "Scene_item_with_display_list.h"
|
||||
#include <iostream>
|
||||
|
||||
#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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,39 +1,127 @@
|
|||
#include <CGAL/AABB_intersections.h>
|
||||
#include "Scene_polyhedron_item.h"
|
||||
#include "Kernel_type.h"
|
||||
#include "Polyhedron_type.h"
|
||||
#include <CGAL/IO/Polyhedron_iostream.h>
|
||||
|
||||
#include <CGAL/AABB_tree.h>
|
||||
#include <CGAL/AABB_traits.h>
|
||||
#include <CGAL/AABB_polyhedron_triangle_primitive.h>
|
||||
|
||||
#include <QVariant>
|
||||
#include <list>
|
||||
|
||||
typedef CGAL::AABB_polyhedron_triangle_primitive<Kernel, Polyhedron> Primitive;
|
||||
typedef CGAL::AABB_traits<Kernel, Primitive> AABB_traits;
|
||||
typedef CGAL::AABB_tree<AABB_traits> 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<void*>();
|
||||
return static_cast<Input_facets_AABB_tree*>(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<void*>(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<void*>();
|
||||
Input_facets_AABB_tree* tree = static_cast<Input_facets_AABB_tree*>(ptr);
|
||||
if(tree) {
|
||||
delete tree;
|
||||
tree = 0;
|
||||
}
|
||||
item->setProperty(aabb_property_name, QVariant());
|
||||
}
|
||||
}
|
||||
|
||||
#include <QObject>
|
||||
#include <QMenu>
|
||||
#include <QAction>
|
||||
#include <CGAL/gl_render.h>
|
||||
|
||||
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<QAction*>("actionPickFacets");
|
||||
if(action) action->setChecked(facet_picking_m);
|
||||
action = menu->findChild<QAction*>("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<Object_and_primitive_id> 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<Kernel::Point_3>(&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<Kernel::Point_3>(&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"
|
||||
|
|
|
|||
|
|
@ -6,6 +6,13 @@
|
|||
#include "Polyhedron_type_fwd.h"
|
||||
#include <iostream>
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include <QColor>
|
||||
|
||||
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<QColor> 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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#ifndef SHOW_POINT_DIALOG_H
|
||||
#define SHOW_POINT_DIALOG_H
|
||||
#include "config.h"
|
||||
|
||||
#include "Point_dialog_config.h"
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
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
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Show_point_dialog</class>
|
||||
<widget class="QDialog" name="Show_point_dialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>575</width>
|
||||
<height>151</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Point &coordinates</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>lineEdit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><!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></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_x">
|
||||
<property name="text">
|
||||
<string>x</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="coord_x">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_y">
|
||||
<property name="text">
|
||||
<string>y</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="coord_y">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_z">
|
||||
<property name="text">
|
||||
<string>z</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="coord_z">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>lineEdit</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>Show_point_dialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>423</x>
|
||||
<y>120</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>387</x>
|
||||
<y>139</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>Show_point_dialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>520</x>
|
||||
<y>120</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>512</x>
|
||||
<y>138</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
|
@ -1,46 +1,144 @@
|
|||
#include "Viewer.h"
|
||||
#include "Scene_draw_interface.h"
|
||||
#include <QMouseEvent>
|
||||
#include <QKeyEvent>
|
||||
|
||||
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 <QMouseEvent>
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,26 @@
|
|||
#ifndef VIEWER_H
|
||||
#define VIEWER_H
|
||||
|
||||
#include "Viewer_config.h"
|
||||
|
||||
#include <QGLViewer/qglviewer.h>
|
||||
#include <QPoint>
|
||||
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef VIEWER_CONFIG_H
|
||||
#define VIEWER_CONFIG_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -4,8 +4,25 @@
|
|||
#include <CGAL/gl.h>
|
||||
#include <CGAL/compute_normal.h>
|
||||
|
||||
|
||||
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 <class Polyhedron>
|
||||
void gl_render_facets(Polyhedron& polyhedron)
|
||||
void gl_render_facets(Polyhedron& polyhedron, const std::vector<QColor>& 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
|
||||
|
|
|
|||
|
|
@ -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 <CGAL/Modifier_base.h>
|
||||
#include <CGAL/HalfedgeDS_decorator.h>
|
||||
|
||||
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
|
||||
#include <CGAL/Triangulation_face_base_with_info_2.h>
|
||||
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
|
||||
#include <CGAL/Constrained_triangulation_plus_2.h>
|
||||
#include <CGAL/Triangulation_2_filtered_projection_traits_3.h>
|
||||
|
||||
// TODO: submit this file to CGAL too
|
||||
#include "CGAL/compute_normal.h"
|
||||
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <class Polyhedron>
|
||||
class Triangulate_modifier
|
||||
: public CGAL::Modifier_base<typename Polyhedron::HalfedgeDS>
|
||||
{
|
||||
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<Traits> P_traits;
|
||||
|
||||
typedef CGAL::Triangulation_vertex_base_with_info_2<Halfedge_handle,
|
||||
P_traits> Vb;
|
||||
|
||||
struct Face_info {
|
||||
typename Polyhedron::Halfedge_handle e[3];
|
||||
bool is_external;
|
||||
};
|
||||
|
||||
typedef CGAL::Triangulation_face_base_with_info_2<Face_info,
|
||||
P_traits> Fb1;
|
||||
|
||||
typedef CGAL::Constrained_triangulation_face_base_2<P_traits, Fb1> Fb;
|
||||
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
|
||||
typedef CGAL::No_intersection_tag Itag;
|
||||
typedef CGAL::Constrained_Delaunay_triangulation_2<P_traits,
|
||||
TDS,
|
||||
Itag> CDTbase;
|
||||
typedef CGAL::Constrained_triangulation_plus_2<CDTbase> 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<HDS> 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<Facet_handle> 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<Facet_handle>::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<Facet,Traits>(*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<typename CDT::Face_handle> 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 <typename Polyhedron>
|
||||
void triangulate_polyhedron(Polyhedron& p)
|
||||
{
|
||||
CGAL::Triangulate_modifier<Polyhedron> modifier;
|
||||
p.delegate(modifier);
|
||||
}
|
||||
|
||||
} // end namespace CGAL
|
||||
|
||||
#endif // CGAL_TRIANGULATE_POLYHEDRON_H
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 8.2 KiB |
Binary file not shown.
|
|
@ -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}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,61 +1,218 @@
|
|||
%\begin{ccHtmlOnly}
|
||||
%<center>
|
||||
%<img border=0 src="./saarhull.gif" align=middle>
|
||||
%</center>
|
||||
%\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}
|
||||
<center>
|
||||
<img border=0 src="./fig/Hilbert8.gif" align=middle>
|
||||
</center>
|
||||
\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}
|
||||
<center>
|
||||
<img border=0 src="./fig/Hilbert-middle.gif" align=middle>
|
||||
</center>
|
||||
\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}
|
||||
<center>
|
||||
<img border=0 src="./fig/Hilbert-median.gif" align=middle>
|
||||
</center>
|
||||
\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}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -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<Median>} 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<Middle>} 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<Tag>}
|
||||
|
||||
\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<Median>}
|
||||
or
|
||||
\ccc{Hilbert_policy<Middle>}
|
||||
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<Median>}.
|
||||
|
||||
\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<Middle>}.
|
||||
|
||||
\ccInclude{CGAL/Hilbert_policy_tags.h}
|
||||
|
||||
|
||||
\ccSeeAlso
|
||||
\ccc{Median} \\
|
||||
\ccc{Middle} \\
|
||||
\ccc{Hilbert_sort__median_policy} \\
|
||||
\ccc{Hilbert_policy}
|
||||
|
||||
\end{ccRefClass}
|
||||
|
|
@ -2,9 +2,11 @@
|
|||
% | Reference manual page: Hilbert_sort_2.tex
|
||||
% +------------------------------------------------------------------------+
|
||||
|
||||
\begin{ccRefFunctionObjectClass}{Hilbert_sort_2<Traits>}
|
||||
\begin{ccRefFunctionObjectClass}{Hilbert_sort_2<Traits, PolicyTag>}
|
||||
\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}.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
% +------------------------------------------------------------------------+
|
||||
% | Reference manual page: Hilbert_sort_2.tex
|
||||
% | Reference manual page: Hilbert_sort_3.tex
|
||||
% +------------------------------------------------------------------------+
|
||||
|
||||
\begin{ccRefFunctionObjectClass}{Hilbert_sort_3<Traits>}
|
||||
\begin{ccRefFunctionObjectClass}{Hilbert_sort_3<Traits, PolicyTag>}
|
||||
\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}.
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
% +------------------------------------------------------------------------+
|
||||
% | Reference manual page: Hilbert_sort_d.tex
|
||||
% +------------------------------------------------------------------------+
|
||||
|
||||
\begin{ccRefFunctionObjectClass}{Hilbert_sort_d<Traits, PolicyTag>}
|
||||
\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 <class RandomAccessIterator> 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
|
||||
% +------------------------------------------------------------------------+
|
||||
|
||||
|
|
@ -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<Base_traits,PointPropertyMap>}.
|
||||
|
||||
|
||||
\ccParDims
|
||||
\end{ccRefConcept}
|
||||
|
|
|
|||
|
|
@ -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<Base_traits,PointPropertyMap>}.
|
||||
|
||||
\ccParDims
|
||||
\end{ccRefConcept}
|
||||
|
|
|
|||
|
|
@ -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<Base_traits,PointPropertyMap>}.
|
||||
|
||||
\ccParDims
|
||||
\end{ccRefConcept}
|
||||
|
||||
% +------------------------------------------------------------------------+
|
||||
%%RefPage: end of main body, begin of footer
|
||||
% EOF
|
||||
% +------------------------------------------------------------------------+
|
||||
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
\begin{ccRefClass}{Spatial_sort_traits_adapter_2<Base_traits,PointPropertyMap>}
|
||||
|
||||
\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<PointPropertyMap>::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}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
\begin{ccRefClass}{Spatial_sort_traits_adapter_3<Base_traits,PointPropertyMap>}
|
||||
|
||||
\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<PointPropertyMap>::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}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
\begin{ccRefClass}{Spatial_sort_traits_adapter_d<Base_traits,PointPropertyMap>}
|
||||
|
||||
\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<PointPropertyMap>::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}
|
||||
|
|
@ -21,27 +21,34 @@ along a Hilbert curve.
|
|||
|
||||
\ccInclude{CGAL/hilbert_sort.h}
|
||||
|
||||
\ccGlobalFunction{template <class RandomAccessIterator, class Traits>
|
||||
\ccGlobalFunction{template <class RandomAccessIterator, class Traits, class PolicyTag>
|
||||
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<Traits>} or
|
||||
\ccc{Hilbert_sort_3<Traits>} and calls its \ccc{operator()}.
|
||||
Creates an instance of
|
||||
\ccc{Hilbert_sort_2<Traits, PolicyTag>},
|
||||
\ccc{Hilbert_sort_3<Traits, PolicyTag>}, or
|
||||
\ccc{Hilbert_sort_d<Traits, PolicyTag>}
|
||||
and calls its \ccc{operator()}.
|
||||
|
||||
%\ccc{Some_other_class},
|
||||
%\ccc{some_other_function}.
|
||||
|
|
|
|||
|
|
@ -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<Sort>} \\
|
||||
\ccRefIdfierPage{CGAL::Hilbert_sort_2<Traits>} \\
|
||||
\ccRefIdfierPage{CGAL::Hilbert_sort_3<Traits>} \\
|
||||
\ccRefIdfierPage{CGAL::Hilbert_sort_2<Traits, PolicyTag>} \\
|
||||
\ccRefIdfierPage{CGAL::Hilbert_sort_3<Traits, PolicyTag>} \\
|
||||
\ccRefIdfierPage{CGAL::Hilbert_sort_d<Traits, PolicyTag>} \\
|
||||
|
||||
\ccHeading{Traits classes}
|
||||
\ccRefIdfierPage{CGAL::Spatial_sort_traits_adapter_2<Base_traits,PointPropertyMap>} \\
|
||||
\ccRefIdfierPage{CGAL::Spatial_sort_traits_adapter_3<Base_traits,PointPropertyMap>} \\
|
||||
\ccRefIdfierPage{CGAL::Spatial_sort_traits_adapter_d<Base_traits,PointPropertyMap>} \\
|
||||
|
||||
\ccHeading{Concepts}
|
||||
|
||||
\ccRefIdfierPage{SpatialSortingTraits_2} \\
|
||||
\ccRefIdfierPage{SpatialSortingTraits_3} \\
|
||||
\ccRefIdfierPage{SpatialSortingTraits_d} \\
|
||||
|
||||
|
||||
\ccHeading{Utilities}
|
||||
|
||||
\ccRefIdfierPage{CGAL::Median}\\
|
||||
\ccRefIdfierPage{CGAL::Middle}\\
|
||||
\ccRefIdfierPage{CGAL::Hilbert_policy<Tag>}\\
|
||||
\ccRefIdfierPage{CGAL::Hilbert_sort_median_policy}\\
|
||||
\ccRefIdfierPage{CGAL::Hilbert_sort_middle_policy}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -23,28 +23,50 @@ of being close in the order.
|
|||
|
||||
\ccInclude{CGAL/spatial_sort.h}
|
||||
|
||||
\ccGlobalFunction{template <class RandomAccessIterator, class Traits>
|
||||
\ccGlobalFunction{template <class RandomAccessIterator, class Traits, class PolicyTag>
|
||||
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<Hilbert_sort_2<Traits>>}
|
||||
or \ccc{Multiscale_sort<Hilbert_sort_3<Traits>>} and calls its \ccc{operator()}.
|
||||
Creates an instance of \ccc{Multiscale_sort<Hilbert_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}.
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
examples/Spatial_sorting/*.cmd
|
||||
examples/Spatial_sorting/data/input.cin
|
||||
examples/Spatial_sorting/data
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
1 0
|
||||
3 2
|
||||
4 5
|
||||
9 8
|
||||
7 4
|
||||
5 2
|
||||
6 3
|
||||
10 1
|
||||
|
|
@ -1 +0,0 @@
|
|||
< data/input.cin
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue