merge from next

This commit is contained in:
Eric Berberich 2011-06-07 15:54:55 +00:00
commit 8d9c812cb4
139 changed files with 6179 additions and 1158 deletions

39
.gitattributes vendored
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,3 +1,2 @@
Combinatorial_map-gdamiand
unique_sqrt_extension-sloriot
spatial_sorting-increase_dim_and_add_info-sloriot

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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\ .}

View File

@ -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\ .}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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&amp;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>&amp;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>&amp;Remeshing</string>
</property>
</action>
<action name="actionConvexDecomposition">
<property name="text">
<string>Convex Decomposition</string>
</property>
</action>
<action name="actionMVC">
<property name="text">
<string>Mean &amp;value coordinates</string>
@ -489,6 +539,19 @@
<string>Ctrl+T</string>
</property>
</action>
<action name="actionRecenterScene">
<property name="text">
<string>Re&amp;center scene</string>
</property>
<property name="shortcut">
<string>Ctrl+C</string>
</property>
</action>
<action name="actionSetBackgroundColor">
<property name="text">
<string>Change &amp;background color...</string>
</property>
</action>
<action name="actionMinkowskiSum">
<property name="text">
<string>&amp;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>&amp;Look at...</string>
</property>
</action>
<action name="actionDumpCamera">
<property name="text">
<string>&amp;Dump camera coordinates</string>
</property>
</action>
<action name="action_Copy_camera">
<property name="text">
<string>&amp;Copy camera</string>
</property>
</action>
<action name="action_Paste_camera">
<property name="text">
<string>&amp;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>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 &amp;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>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu LGC Sans'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Paste here the coordinates of a point. It can be for example:&lt;/p&gt;
&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&amp;quot;(10., -2e-2, .4)&amp;quot;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;or:&lt;/p&gt;
&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&amp;quot;-2 3 5&amp;quot;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;or even something with garbage around:&lt;/p&gt;
&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&amp;quot;point (-2, 5, 0) and...&amp;quot;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,3 +0,0 @@
examples/Spatial_sorting/*.cmd
examples/Spatial_sorting/data/input.cin
examples/Spatial_sorting/data

View File

@ -1,8 +0,0 @@
1 0
3 2
4 5
9 8
7 4
5 2
6 3
10 1

View File

@ -1 +0,0 @@
< data/input.cin

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