mirror of https://github.com/CGAL/cgal
Merge remote-tracking branch 'upstream/master' into feature/issue_7395
This commit is contained in:
commit
de3ba0f47c
|
|
@ -39,6 +39,7 @@ if(GMP_FOUND)
|
|||
create_single_source_cgal_program("Arithmetic_kernel.cpp")
|
||||
create_single_source_cgal_program("LEDA_arithmetic_kernel.cpp")
|
||||
create_single_source_cgal_program("CORE_arithmetic_kernel.cpp")
|
||||
create_single_source_cgal_program("GMPXX_arithmetic_kernel.cpp")
|
||||
create_single_source_cgal_program("Get_arithmetic_kernel.cpp")
|
||||
|
||||
else()
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ find_package(CGAL REQUIRED)
|
|||
|
||||
# create a target per cppfile
|
||||
file(
|
||||
GLOB_RECURSE cppfiles
|
||||
GLOB cppfiles
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
*.cpp)
|
||||
foreach(cppfile ${cppfiles})
|
||||
|
|
|
|||
|
|
@ -1,125 +0,0 @@
|
|||
#define BOOST_TEST_MODULE graph_traits test
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/floating_point_comparison.hpp>
|
||||
|
||||
BOOST_AUTO_TEST_CASE( edges_test )
|
||||
{
|
||||
edge_iterator eb, ee;
|
||||
vertex_iterator vb, ve;
|
||||
|
||||
Surface_fixture f;
|
||||
boost::tie(eb, ee) = edges(f.m);
|
||||
boost::tie(vb, ve) = vertices(f.m);
|
||||
BOOST_CHECK(std::distance(eb, ee) == 7);
|
||||
BOOST_CHECK(std::distance(vb, ve) == 5);
|
||||
|
||||
Cube_fixture cf;
|
||||
boost::tie(eb, ee) = edges(cf.m);
|
||||
boost::tie(vb, ve) = vertices(cf.m);
|
||||
BOOST_CHECK(std::distance(eb, ee) == 18);
|
||||
BOOST_CHECK(std::distance(vb, ve) == 8);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( out_edges_test )
|
||||
{
|
||||
Surface_fixture f;
|
||||
|
||||
BOOST_CHECK(out_degree(f.u, f.m) == 2);
|
||||
BOOST_CHECK(out_degree(f.v, f.m) == 4);
|
||||
std::pair<out_edge_iterator, out_edge_iterator> out = out_edges(f.v, f.m);
|
||||
BOOST_CHECK(std::distance(out.first, out.second) == 4);
|
||||
out_edge_iterator it = out.first;
|
||||
while(it != out.second) {
|
||||
// the source should always be u
|
||||
BOOST_CHECK(source(*it, f.m) == f.v);
|
||||
// the target never
|
||||
BOOST_CHECK(target(*it, f.m) != f.v);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( in_edges_test )
|
||||
{
|
||||
Surface_fixture f;
|
||||
BOOST_CHECK(in_degree(f.u, f.m) == 2);
|
||||
BOOST_CHECK(in_degree(f.x, f.m) == 3);
|
||||
BOOST_CHECK(in_degree(f.v, f.m) == 4);
|
||||
std::pair<in_edge_iterator, in_edge_iterator> in = in_edges(f.v, f.m);
|
||||
BOOST_CHECK(std::distance(in.first, in.second) == 4);
|
||||
|
||||
in_edge_iterator it = in.first;
|
||||
while(it != in.second) {
|
||||
// the source should never be u
|
||||
BOOST_CHECK(source(*it, f.m) != f.v);
|
||||
// the target must always be u
|
||||
BOOST_CHECK(target(*it, f.m) == f.v);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( in_out_equality )
|
||||
{
|
||||
// in and out degrees must be equal for each vertex
|
||||
Cube_fixture f;
|
||||
for(Sm::Vertex_iterator it = f.m.vertices_begin();
|
||||
it != f.m.vertices_end(); ++it) {
|
||||
BOOST_CHECK(in_degree(*it, f.m) == out_degree(*it, f.m));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( face_test )
|
||||
{
|
||||
Surface_fixture f;
|
||||
std::pair<enclosure_iterator, enclosure_iterator>
|
||||
enc = enclosure(f.f1, f.m);
|
||||
BOOST_CHECK(enc.first != enc.second);
|
||||
BOOST_CHECK(std::distance(enc.first, enc.second) == 3);
|
||||
enclosure_iterator begin = enc.first;
|
||||
while(begin != enc.second)
|
||||
{
|
||||
BOOST_CHECK(face(*begin, f.m) == f.f1);
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( weight_map_test )
|
||||
{
|
||||
Surface_fixture f;
|
||||
Cube_fixture c;
|
||||
|
||||
CGAL::SM_edge_weight_pmap<K> wm1 = boost::get(boost::edge_weight, c.m);
|
||||
edge_iterator eb, ee;
|
||||
boost::test_tools::check_is_close_t check_close;
|
||||
for(boost::tie(eb, ee) = edges(c.m); eb != ee; ++eb) {
|
||||
BOOST_CHECK(
|
||||
check_close(wm1[*eb], 2.0, boost::test_tools::percent_tolerance_t<double>(0.00001))
|
||||
|| check_close(wm1[*eb], 2.82843, boost::test_tools::percent_tolerance_t<double>(0.001)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( vertices_test )
|
||||
{
|
||||
Surface_fixture f;
|
||||
|
||||
// boost::property_map<Sm,boost::vertex_index_t>::type vi_map = get(f.m, boost::vertex_index);
|
||||
|
||||
// vertex_iterator b,e;
|
||||
|
||||
// for(boost::tie(b,e) = vertices(f.m);
|
||||
// b!= e;
|
||||
// ++b){
|
||||
// std::cout << boost::get(vi_map, *(b)) << std::endl;
|
||||
// }
|
||||
|
||||
// boost::property_map<Sm,boost::edge_weight_t>::type ew_map = get(f.m, boost::edge_weight);
|
||||
|
||||
// edge_iterator be, ee;
|
||||
|
||||
// for(boost::tie(be,ee) = edges(f.m);
|
||||
// be!= ee;
|
||||
// ++be){
|
||||
// std::cout << boost::get(ew_map, *(be)) << std::endl;
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
@ -21,18 +21,18 @@ int main()
|
|||
SM sm_in, sm_out;
|
||||
Point_3 p0(0,0,0), p1(1,0,0), p2(0,1,0);
|
||||
CGAL::make_triangle(p0, p1, p2, sm_out);
|
||||
bool ok = CGAL::write_off("tmp.off", sm_out);
|
||||
bool ok = CGAL::write_off("tmp_deprecated.off", sm_out);
|
||||
assert(ok);
|
||||
ok = CGAL::read_off("tmp.off", sm_in);
|
||||
ok = CGAL::read_off("tmp_deprecated.off", sm_in);
|
||||
assert(ok);
|
||||
assert(num_vertices(sm_in) == 3 && num_faces(sm_in) == 1);
|
||||
sm_in.clear();
|
||||
|
||||
std::ofstream os("tmp.off");
|
||||
std::ofstream os("tmp_deprecated.off");
|
||||
ok = CGAL::write_off(os, sm_out);
|
||||
assert(ok);
|
||||
os.close();
|
||||
std::ifstream is("tmp.off");
|
||||
std::ifstream is("tmp_deprecated.off");
|
||||
ok = CGAL::read_off(is, sm_in);
|
||||
assert(ok);
|
||||
assert(num_vertices(sm_in) == 3 && num_faces(sm_in) == 1);
|
||||
|
|
@ -40,18 +40,18 @@ int main()
|
|||
sm_in.clear();
|
||||
#ifdef CGAL_USE_VTK
|
||||
//vtk
|
||||
os.open("tmp.vtp");
|
||||
os.open("tmp_deprecated.vtp");
|
||||
ok = CGAL::write_vtp(os, sm_out);
|
||||
assert(ok);
|
||||
os.close();
|
||||
|
||||
ok = CGAL::IO::read_VTP("tmp.vtp", sm_in);
|
||||
ok = CGAL::IO::read_VTP("tmp_deprecated.vtp", sm_in);
|
||||
assert(ok);
|
||||
assert(num_vertices(sm_in) == 3 && num_faces(sm_in) == 1);
|
||||
sm_in.clear();
|
||||
#endif
|
||||
//wrl
|
||||
os.open("tmp.wrl");
|
||||
os.open("tmp_deprecated.wrl");
|
||||
ok = CGAL::write_wrl(os, sm_out);
|
||||
assert(ok);
|
||||
os.close();
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <CGAL/assertions.h>
|
||||
|
||||
#define CGAL_CLASSIFICATION_IMAGE_SIZE_LIMIT 100000000
|
||||
|
||||
|
|
@ -38,12 +39,15 @@ class Image
|
|||
std::shared_ptr<Map> m_sparse;
|
||||
Type m_default;
|
||||
|
||||
// Forbid using copy constructor
|
||||
Image (const Image&)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
// Forbid using copy constructor
|
||||
// Make it public for a strange VC++ std17 boost-1_82 error
|
||||
// https://github.com/boostorg/core/issues/148
|
||||
Image(const Image&)
|
||||
{
|
||||
CGAL_assertion(false);
|
||||
}
|
||||
|
||||
Image () : m_width(0), m_height(0), m_depth(0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -241,6 +241,18 @@ else()
|
|||
"#EXTRACT_ALL_NO_DETAILED_IF_EMPTY = NO")
|
||||
endif()
|
||||
|
||||
option(CGAL_NO_ADDITIONAL_DETAILS
|
||||
"Use CGAL special doxygen setting NO_ADDITIONAL_DETAILS." ON)
|
||||
if(CGAL_NO_ADDITIONAL_DETAILS)
|
||||
set(CGAL_OPT_NO_ADDITIONAL_DETAILS
|
||||
"NO_ADDITIONAL_DETAILS = YES")
|
||||
else()
|
||||
# The default is NO, so we could leave it out, but it is better to have a commented out placeholder
|
||||
# this will work for versions with and without the setting.
|
||||
set(CGAL_OPT_NO_ADDITIONAL_DETAILS
|
||||
"#NO_ADDITIONAL_DETAILS = NO")
|
||||
endif()
|
||||
|
||||
#we use two directories for the generation/reading of tag files to prevent issues
|
||||
#if the targets are built in parallel
|
||||
set(CGAL_DOC_TAG_GEN_DIR "${CMAKE_BINARY_DIR}/doc_gen_tags")
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ EXTRACT_ALL = YES
|
|||
# the EXTRACT_ALL tag is set to NO.
|
||||
# The default value is: NO.
|
||||
|
||||
EXTRACT_ALL_NO_DETAILED_IF_EMPTY = YES
|
||||
${CGAL_OPT_EXTRACT_ALL_NO_DETAILED_IF_EMPTY}
|
||||
|
||||
# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
|
||||
# included in the documentation.
|
||||
|
|
|
|||
|
|
@ -805,5 +805,5 @@ GENERATE_LEGEND = NO
|
|||
# NO_ADDITIONAL_DETAILS tag is set to YES. This tag has no effect if
|
||||
# the EXTRACT_ALL tag is set to NO.
|
||||
# The default value is: NO.
|
||||
NO_ADDITIONAL_DETAILS = YES
|
||||
${CGAL_OPT_NO_ADDITIONAL_DETAILS}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ create_single_source_cgal_program(Linear_cell_complex_2_test.cpp ${hfiles})
|
|||
create_single_source_cgal_program(Linear_cell_complex_3_test.cpp ${hfiles})
|
||||
create_single_source_cgal_program(Linear_cell_complex_4_test.cpp ${hfiles})
|
||||
create_single_source_cgal_program(Linear_cell_complex_copy_test.cpp ${hfiles})
|
||||
create_single_source_cgal_program(LCC_3_incremental_builder_test.cpp ${hfiles})
|
||||
|
||||
# Same targets, defining USE_COMPACT_CONTAINER_WITH_INDEX to test index version
|
||||
add_executable(Linear_cell_complex_2_test_index Linear_cell_complex_2_test.cpp ${hfiles})
|
||||
|
|
|
|||
|
|
@ -42,12 +42,12 @@ printf "Copy documentation to doc_html/ and doc_html_online/...\n"
|
|||
[ -d "/srv/CGAL/www/${PUBLIC_RELEASE_NAME#CGAL-}/Manual" ] || mkdir -p "/srv/CGAL/www/${PUBLIC_RELEASE_NAME#CGAL-}/Manual"
|
||||
|
||||
cp "$PUBLIC_RELEASE_DIR"/*(.) "${RELEASE_CANDIDATES_DIR}/$PUBLIC_RELEASE_NAME"
|
||||
files=("$MANUAL_TESTS_DIR/$INTERNAL_RELEASE"/output2/*)
|
||||
files=("$MANUAL_TESTS_DIR/$INTERNAL_RELEASE"/output1/*)
|
||||
if ((${#files[@]} == 0)); then
|
||||
printf "ERROR: documentation files are missing\n"
|
||||
error_code=1
|
||||
else
|
||||
rsync -a --exclude xml "$MANUAL_TESTS_DIR/$INTERNAL_RELEASE"/output2/* "$DEST_DIR/doc_html/"
|
||||
rsync -a --exclude xml "$MANUAL_TESTS_DIR/$INTERNAL_RELEASE"/output1/* "$DEST_DIR/doc_html/"
|
||||
pushd "$DEST_DIR/doc_html/Manual/search"
|
||||
for i in g n c s i; do sed -i "s/..\/BGL$i/..\/BGL\/$i/g" *; done
|
||||
popd
|
||||
|
|
|
|||
|
|
@ -49,6 +49,9 @@ target_link_libraries(mesh_hybrid_mesh_domain PUBLIC CGAL::Eigen3_support)
|
|||
create_single_source_cgal_program("mesh_implicit_sphere.cpp")
|
||||
target_link_libraries(mesh_implicit_sphere PUBLIC CGAL::Eigen3_support)
|
||||
|
||||
create_single_source_cgal_program("mesh_implicit_ellipsoid.cpp")
|
||||
target_link_libraries(mesh_implicit_ellipsoid PUBLIC CGAL::Eigen3_support)
|
||||
|
||||
create_single_source_cgal_program("mesh_implicit_sphere_variable_size.cpp")
|
||||
target_link_libraries(mesh_implicit_sphere_variable_size PUBLIC CGAL::Eigen3_support)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,303 +0,0 @@
|
|||
///////////////// Code for functions of famous surfaces /////////////////
|
||||
|
||||
|
||||
// Sphere (r=1)
|
||||
|
||||
double sphere_function (double x, double y, double z) {
|
||||
double x2=x*x, y2=y*y, z2=z*z;
|
||||
|
||||
return x2+y2+z2-1;
|
||||
}
|
||||
|
||||
|
||||
// Ellipsoid (r=1)
|
||||
|
||||
double ellipsoid_function (double x, double y, double z) {
|
||||
double x2=x*x, y2=y*y, z2=z*z;
|
||||
|
||||
return x2+2*y2+4*z2-1;
|
||||
}
|
||||
|
||||
|
||||
// Torus (r=2)
|
||||
|
||||
double torus_function (double x, double y, double z) {
|
||||
double x2=x*x, y2=y*y, z2=z*z;
|
||||
double x4=x2*x2, y4=y2*y2, z4=z2*z2;
|
||||
|
||||
return x4 + y4 + z4 + 2 *x2* y2 + 2*
|
||||
x2*z2 + 2*y2* z2 - 5 *x2 + 4* y2 - 5*z2+4;
|
||||
}
|
||||
|
||||
|
||||
// "Chair" (r=6)
|
||||
|
||||
double chair_function (double x, double y, double z) {
|
||||
double x2=x*x, y2=y*y, z2=z*z;
|
||||
double x4=x2*x2, y4=y2*y2, z4=z2*z2;
|
||||
|
||||
return x4-1.2*x2*y2+3.6*x2*z2-7.50*x2+y4+3.6*y2*z2-7.50*y2+.2*z4-7.50*z2+64.0625-16.0*z*y2+16.0*x2*z;
|
||||
}
|
||||
|
||||
|
||||
// "Tanglecube" (r=4)
|
||||
|
||||
double tanglecube_function (double x, double y, double z) {
|
||||
double x2=x*x, y2=y*y, z2=z*z;
|
||||
double x4=x2*x2, y4=y2*y2, z4=z2*z2;
|
||||
|
||||
return x4 - 5*x2 + y4 - 5*y2 + z4 - 5*z2 + 11.8;
|
||||
}
|
||||
|
||||
double cube_function (double x, double y, double z){
|
||||
if( x < 1 && -x < 1 &&
|
||||
y < 1 && -y < 1 &&
|
||||
z < 1 && -z < 1 )
|
||||
return -1.;
|
||||
return 1.;
|
||||
}
|
||||
|
||||
// Barth's octic surface (degree 8)
|
||||
|
||||
double octic_function (double x, double y, double z) { // r=2
|
||||
double x2=x*x, y2=y*y, z2=z*z;
|
||||
double x4=x2*x2, y4=y2*y2, z4=z2*z2;
|
||||
double x6=x4*x2, y6=y4*y2, z6=z4*z2;
|
||||
double x8=x4*x4, y8=y4*y4, z8=z4*z4;
|
||||
|
||||
return 43.30495169 *x2* y2 + 43.30495169 *x2* z2 + 43.30495169 *y2 * z2 + 44.36067980 *x6* y2 + 44.36067980* x6 * z2 + 66.54101970* x4* y4 + 66.54101970* x4 * z4 + 44.36067980 *x2 * y6 - 11.70820393* x2 - 11.70820393* y2 - 11.70820393* z2 + 37.65247585 *x4 + 37.65247585 *y4 + 37.65247585* z4 + 11.09016995* x8 + 11.09016995 *y8 + 11.09016995* z8 + 133.0820394 *x2* y4* z2 + 133.0820394 *x2 * y2 * z4 + 44.36067980* x2 * z6 + 44.36067980 *y6 * z2 + 66.54101970 *y4 * z4 + 44.36067980 *y2 * z6 + 133.0820394* x4* y2 * z2 - 91.95742756 *x4 * y2 - 91.95742756 *x4 *z2 - 91.95742756* x2 * y4 - 91.95742756 *x2 *z4 - 91.95742756* y4 * z2 - 183.9148551* x2 *y2 *z2 - 30.65247585 *x6 - 30.65247585* y6 - 91.95742756 *y2 * z4 - 30.65247585* z6 + 1.618033988;
|
||||
}
|
||||
|
||||
|
||||
// "Heart"
|
||||
|
||||
double heart_function (double x, double y, double z) { // radius = 2
|
||||
|
||||
return (2*x*x+y*y+z*z-1)*(2*x*x+y*y+z*z-1)*(2*x*x+y*y+z*z-1) - (0.1*x*x+y*y)*z*z*z;
|
||||
}
|
||||
|
||||
|
||||
// Klein's bottle
|
||||
|
||||
double klein_function (double x, double y, double z) { // radius = 4
|
||||
|
||||
return (x*x+y*y+z*z+2*y-1)*((x*x+y*y+z*z-2*y-1)*(x*x+y*y+z*z-2*y-1)-8*z*z)+16*x*z*(x*x+y*y+z*z-2*y-1);
|
||||
}
|
||||
|
||||
|
||||
// Ring
|
||||
|
||||
double ring_function (double x, double y, double z) { // radius = ?
|
||||
double e=0.1;
|
||||
|
||||
double f1 = x*x+y*y+z*z-1;
|
||||
double f2 = x;
|
||||
|
||||
f1 = f1*f1-e*e;
|
||||
f2 = f2*f2-e*e;
|
||||
|
||||
if (f1 < 0 && f2 < 0)
|
||||
return -1.;
|
||||
else if (f1 > 0 || f2 > 0)
|
||||
return 1.;
|
||||
else
|
||||
return 0.;
|
||||
}
|
||||
|
||||
|
||||
// False knot
|
||||
|
||||
double false_knot_function (double x, double y, double z) { // radius = 1
|
||||
double d=1.2, e=0.1;
|
||||
|
||||
double f1 = x*(x*x-z*z)-2*x*z*z-y*y+d*d-x*x-z*z-y*y;
|
||||
|
||||
double m2 = z*(x*x-z*z)+2*x*x*z;
|
||||
double f2 = 4*y*y*(d*d-x*x-z*z-y*y) - m2*m2;
|
||||
|
||||
f1 = f1*f1-e*e;
|
||||
f2 = f2*f2-e*e;
|
||||
|
||||
if (f1 < 0 && f2 < 0)
|
||||
return -1.;
|
||||
else if (f1 > 0 || f2 > 0)
|
||||
return 1.;
|
||||
else
|
||||
return 0.;
|
||||
}
|
||||
|
||||
|
||||
// Knot 1
|
||||
|
||||
void puiss(double& x, double& y, int n) {
|
||||
|
||||
double xx = 1, yy = 0;
|
||||
|
||||
while(n>0) {
|
||||
if (n&1) {
|
||||
double xxx = xx, yyy = yy;
|
||||
xx = xxx*x - yyy*y;
|
||||
yy = xxx*y + yyy*x;
|
||||
}
|
||||
|
||||
double xxx = x, yyy = y;
|
||||
x=xxx*xxx-yyy*yyy;
|
||||
y=2*xxx*yyy;
|
||||
|
||||
n/=2;
|
||||
}
|
||||
|
||||
x = xx;
|
||||
y = yy;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double knot1_function (double a, double b, double c) { // radius = 4
|
||||
double e=0.1;
|
||||
|
||||
double x, y, z, t, den;
|
||||
den=1+a*a+b*b+c*c;
|
||||
x=2*a/den;
|
||||
y=2*b/den;
|
||||
z=2*c/den;
|
||||
t=(1-a*a-b*b-c*c)/den;
|
||||
|
||||
double x3=x, y3=y, z2=z, t2=t;
|
||||
puiss(x3,y3,3);
|
||||
puiss(z2,t2,2);
|
||||
|
||||
double f1 = z2-x3;
|
||||
double f2 = t2-y3;
|
||||
|
||||
f1 = f1*f1;
|
||||
f2 = f2*f2;
|
||||
e=e*e/(den-1);
|
||||
|
||||
if (f1+f2-e < 0)
|
||||
return -1.;
|
||||
else if (f1+f2-e > 0)
|
||||
return 1.;
|
||||
else
|
||||
return 0.;
|
||||
}
|
||||
|
||||
/*
|
||||
double knot1_function (double x, double y, double z) { // radius = 4
|
||||
double e=0.1;
|
||||
|
||||
double c1, c2, c3, c4, den;
|
||||
den=1+x*x+y*y+z*z;
|
||||
c1=2*x/den;
|
||||
c2=2*y/den;
|
||||
c3=2*z/den;
|
||||
c4=(1-x*x-y*y-z*z)/den;
|
||||
|
||||
double f1 = c1*(c1*c1-c2*c2)-2*c1*c2*c2-c3*c3+c4*c4;
|
||||
double f2 = c2*(c1*c1-c2*c2)+2*c1*c1*c2-2*c3*c4;
|
||||
|
||||
f1 = f1*f1;
|
||||
f2 = f2*f2;
|
||||
e=e*e/(den-1);
|
||||
|
||||
if (f1+f2-e < 0)
|
||||
return -1.;
|
||||
else if (f1+f2-e > 0)
|
||||
return 1.;
|
||||
else
|
||||
return 0.;
|
||||
}
|
||||
*/
|
||||
|
||||
double knot1_surf1_function (double x, double y, double z) { // radius = 4
|
||||
double c1, c2, c3, c4, den;
|
||||
den=1+x*x+y*y+z*z;
|
||||
c1=2*x/den;
|
||||
c2=2*y/den;
|
||||
c3=2*z/den;
|
||||
c4=(1-x*x-y*y-z*z)/den;
|
||||
|
||||
return c1*(c1*c1-c2*c2)-2*c1*c2*c2-c3*c3+c4*c4;
|
||||
}
|
||||
|
||||
|
||||
double knot1_surf2_function (double x, double y, double z) { // radius = 4
|
||||
double c1, c2, c3, c4, den;
|
||||
den=1+x*x+y*y+z*z;
|
||||
c1=2*x/den;
|
||||
c2=2*y/den;
|
||||
c3=2*z/den;
|
||||
c4=(1-x*x-y*y-z*z)/den;
|
||||
|
||||
return c2*(c1*c1-c2*c2)+2*c1*c1*c2-2*c3*c4;
|
||||
}
|
||||
|
||||
|
||||
// Knot 2
|
||||
|
||||
double knot2_function (double a, double b, double c) { // radius = 4
|
||||
double e=0.025;
|
||||
|
||||
double x, y, z, t, den;
|
||||
den=1+a*a+b*b+c*c;
|
||||
x=2*a/den;
|
||||
y=2*b/den;
|
||||
z=2*c/den;
|
||||
t=(1-a*a-b*b-c*c)/den;
|
||||
|
||||
double x7=x, y7=y, x13=x, y13=y;
|
||||
puiss(x7,y7,7);
|
||||
puiss(x13,y13,13);
|
||||
|
||||
double z3=z, t3=t;
|
||||
puiss(z3,t3,3);
|
||||
|
||||
double f1t = (z3-x7)*(z3-x7+100*x13) - (t3-y7)*(t3-y7+100*y13);
|
||||
double f2t = (z3-x7)*(t3-y7+100*y13) + (t3-y7)*(z3-x7+100*x13);
|
||||
double f1 = f1t*(z3-x7-100*x13) - f2t*(t3-y7-100*y13);
|
||||
double f2 = f1t*(t3-y7-100*y13) + f2t*(z3-x7-100*x13);
|
||||
|
||||
f1 = f1*f1;
|
||||
f2 = f2*f2;
|
||||
e=e*e/(den-1);
|
||||
|
||||
if (f1+f2-e < 0)
|
||||
return -1.;
|
||||
else if (f1+f2-e > 0)
|
||||
return 1.;
|
||||
else
|
||||
return 0.;
|
||||
}
|
||||
|
||||
|
||||
// Knot 3
|
||||
|
||||
|
||||
double knot3_function (double a, double b, double c) { // radius = 4
|
||||
double e=0.025;
|
||||
|
||||
double x, y, z, t, den;
|
||||
den=1+a*a+b*b+c*c;
|
||||
x=2*a/den;
|
||||
y=2*b/den;
|
||||
z=2*c/den;
|
||||
t=(1-a*a-b*b-c*c)/den;
|
||||
|
||||
double x19=x, y19=y, z17=z, t17=t;
|
||||
puiss(x19,y19,19);
|
||||
puiss(z17,t17,17);
|
||||
|
||||
double f1 = z17-x19;
|
||||
double f2 = t17-y19;
|
||||
|
||||
f1 = f1*f1;
|
||||
f2 = f2*f2;
|
||||
e=e*e/(den-1);
|
||||
|
||||
if (f1+f2-e < 0)
|
||||
return -1.;
|
||||
else if (f1+f2-e > 0)
|
||||
return 1.;
|
||||
else
|
||||
return 0.;
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
///////////////// Definitions of several famous surfaces /////////////////
|
||||
double sphere_function (double, double, double); // (c=(0,0,0), r=1)
|
||||
double ellipsoid_function (double, double, double); // (c=(0,0,0), r=1)
|
||||
double torus_function (double, double, double); // (c=(0,0,0), r=2)
|
||||
double chair_function (double, double, double); // (c=(0,0,0), r=6)
|
||||
double tanglecube_function (double, double, double); // (c=(0,0,0), r=4)
|
||||
double octic_function (double, double, double); // (c=(0,0,0), r=2)
|
||||
double heart_function (double, double, double); // (c=(0,0,0), r=2)
|
||||
double klein_function (double, double, double); // (c=(0,0,0), r=4)
|
||||
double ring_function (double, double, double); // (c=(0,0,0), r=?)
|
||||
double false_knot_function (double, double, double); // (c=(0,0,0), r=1)
|
||||
double knot1_function (double, double, double); // (c=(0,0,0), r=4)
|
||||
double knot2_function (double, double, double); // (c=(0,0,0), r=4)
|
||||
double knot3_function (double, double, double); // (c=(0,0,0), r=4)
|
||||
double cube_function (double, double, double); // (c=(0,0,0), r=2)
|
||||
|
||||
|
||||
template <int Sq_radius>
|
||||
double sphere_function (double x, double y, double z) // (c=(0,0,0), r=Sq_radius)
|
||||
{
|
||||
double x2=x*x, y2=y*y, z2=z*z;
|
||||
return (x2+y2+z2)/Sq_radius - 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename FT, typename P>
|
||||
class FT_to_point_function_wrapper : public CGAL::cpp98::unary_function<P, FT>
|
||||
{
|
||||
typedef FT (*Implicit_function)(FT, FT, FT);
|
||||
Implicit_function function;
|
||||
public:
|
||||
typedef P Point;
|
||||
FT_to_point_function_wrapper(Implicit_function f) : function(f) {}
|
||||
FT operator()(Point p) const { return function(p.x(), p.y(), p.z()); }
|
||||
};
|
||||
|
|
@ -63,6 +63,8 @@ create_single_source_cgal_program("_test_valid_finite_float.cpp")
|
|||
create_single_source_cgal_program("to_interval_test.cpp")
|
||||
create_single_source_cgal_program("unsigned.cpp")
|
||||
create_single_source_cgal_program("utilities.cpp")
|
||||
create_single_source_cgal_program("Exact_rational.cpp")
|
||||
create_single_source_cgal_program("Mpzf_new.cpp")
|
||||
|
||||
find_package( GMP )
|
||||
if( GMP_FOUND AND NOT CGAL_DISABLE_GMP )
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ public:
|
|||
|
||||
/// \name
|
||||
/// A point-offset pair (`p`,`off`) is said to be in conflict with a
|
||||
/// cell `c` iff `dt`.`side_of_circle(c, p, off)` returns
|
||||
/// face `f` iff `dt`.`side_of_circle(f, p, off)` returns
|
||||
/// `ON_BOUNDED_SIDE`. The set of faces that are in conflict with
|
||||
/// (`p`,`off`) is star-shaped.
|
||||
/// @{
|
||||
|
|
@ -309,7 +309,7 @@ public:
|
|||
Checks the combinatorial validity of the triangulation and the
|
||||
validity of its geometric embedding (see
|
||||
Section \ref P2Triangulation2secintro). Also checks that all the
|
||||
circumscribing circles of cells are empty.
|
||||
circumscribing circles of faces are empty.
|
||||
|
||||
When `verbose` is set to true, messages describing the first
|
||||
invalidity encountered are printed.
|
||||
|
|
@ -321,9 +321,9 @@ public:
|
|||
/*!
|
||||
\cgalAdvancedFunction
|
||||
\cgalAdvancedBegin
|
||||
Checks the combinatorial and geometric validity of the cell (see
|
||||
Checks the combinatorial and geometric validity of the face (see
|
||||
Section \ref P2Triangulation2secintro). Also checks that the
|
||||
circumscribing circle of cells is empty.
|
||||
circumscribing circle of faces is empty.
|
||||
|
||||
When `verbose` is set to true, messages are printed to give
|
||||
a precise indication of the kind of invalidity encountered.
|
||||
|
|
|
|||
|
|
@ -65,10 +65,10 @@ concepts `Periodic_2TriangulationFaceBase_2` and
|
|||
A triangulation is stored as a collection of vertices and faces that
|
||||
are linked together through incidence and adjacency relations. Each
|
||||
face gives access to its three incident vertices and to its three
|
||||
adjacent cells. Each vertex gives access to one of its incident
|
||||
adjacent faces. Each vertex gives access to one of its incident
|
||||
faces.
|
||||
|
||||
The three vertices of a cell are indexed with 0, 1, and 2 in positive
|
||||
The three vertices of a face are indexed with 0, 1, and 2 in positive
|
||||
orientation, the positive orientation being defined by the orientation
|
||||
of the underlying space \f$ \mathbb T_c^3\f$. The neighbors of a face are
|
||||
also indexed with 0, 1, 2 in such a way that the neighbor indexed
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ A periodic triangulation is said to be `locally valid` iff
|
|||
data structure, is `locally valid`
|
||||
(see Chapter \ref Chapter_2D_Triangulation_Data_Structure)
|
||||
|
||||
<B>(c)</B> Any cell has its vertices ordered according to positive
|
||||
<B>(c)</B> Any face has its vertices ordered according to positive
|
||||
orientation. See \cgalFigureRef{P2Triangulation2figorient}.
|
||||
|
||||
\section P2T2_Delaunay Delaunay Triangulation
|
||||
|
|
@ -264,7 +264,7 @@ to support periodicity: the vertex and face must be models of
|
|||
`Periodic_2TriangulationVertexBase_2` and `Periodic_2TriangulationFaceBase_2`.
|
||||
A model of such concept is `CGAL::Triangulation_data_structure_2`. It is
|
||||
parameterized by a vertex base class and a face base class, which gives the
|
||||
possibility to customize the vertices and cells used by the triangulation data
|
||||
possibility to customize the vertices and faces used by the triangulation data
|
||||
structure, and hence by the geometric triangulation using it.
|
||||
Basic models of the vertex and face concepts are provided: `CGAL::Periodic_2_triangulation_vertex_base_2`
|
||||
and `CGAL::Periodic_2_triangulation_face_base_2`.
|
||||
|
|
@ -272,7 +272,7 @@ and `CGAL::Periodic_2_triangulation_face_base_2`.
|
|||
A default value for the triangulation data structure parameter is provided in
|
||||
all the triangulation classes, so it does not need to be specified by
|
||||
the user unless he wants to use a different triangulation data
|
||||
structure or a different vertex or cell base class.
|
||||
structure or a different vertex or face base class.
|
||||
|
||||
\subsection P2T2FlexDesign Flexibility of the Design
|
||||
|
||||
|
|
|
|||
|
|
@ -27,24 +27,21 @@ int main()
|
|||
// Gets the conflict region of 100 random points
|
||||
// in the Delaunay tetrahedralization
|
||||
for (int i = 0; i != 100; ++i)
|
||||
{
|
||||
Point p = (*rnd++);
|
||||
{
|
||||
Point p = (*rnd++);
|
||||
|
||||
// Locate the point
|
||||
Delaunay::Locate_type lt;
|
||||
int li;
|
||||
Face_handle f = T.locate(p, lt, li);
|
||||
if (lt == Delaunay::VERTEX)
|
||||
continue; // Point already exists
|
||||
// Locate the point
|
||||
Delaunay::Locate_type lt;
|
||||
int li;
|
||||
Face_handle f = T.locate(p, lt, li);
|
||||
if (lt == Delaunay::VERTEX)
|
||||
continue; // Point already exists
|
||||
|
||||
// Get the cells that conflict with p in a vector V,
|
||||
// and a facet on the boundary of this hole in f.
|
||||
std::vector<Face_handle> V;
|
||||
// Get the faces that conflict with p in a vector V.
|
||||
std::vector<Face_handle> V;
|
||||
|
||||
T.get_conflicts(p,
|
||||
std::back_inserter(V), // Conflict cells in V
|
||||
f);
|
||||
}
|
||||
T.get_conflicts(p, std::back_inserter(V), f);
|
||||
}
|
||||
|
||||
std::cout << "Final triangulation has " << T.number_of_vertices()
|
||||
<< " vertices." << std::endl;
|
||||
|
|
|
|||
|
|
@ -119,12 +119,21 @@ public:
|
|||
/// Unique_vertex_iterator iterates over exactly one representative.
|
||||
typedef Periodic_2_triangulation_unique_vertex_iterator_2<Self>
|
||||
Unique_vertex_iterator;
|
||||
/// Iterator over the canonical edges, i.e. for each set of periodic copies the
|
||||
/// Unique_edge_iterator iterates over exactly one representative.
|
||||
typedef Periodic_2_triangulation_unique_edge_iterator_2<Self>
|
||||
Unique_edge_iterator;
|
||||
/// Iterator over the canonical faces, i.e. for each set of periodic copies the
|
||||
/// Unique_face_iterator iterates over exactly one representative.
|
||||
typedef Periodic_2_triangulation_unique_face_iterator_2<Self>
|
||||
Unique_face_iterator;
|
||||
|
||||
/// \name For compatibility with the Triangulation_2 class
|
||||
// \{
|
||||
typedef Face_iterator Finite_faces_iterator;
|
||||
typedef Edge_iterator Finite_edges_iterator;
|
||||
typedef Vertex_iterator Finite_vertices_iterator;
|
||||
typedef Vertex_iterator All_vertices_iterator;
|
||||
typedef Face_iterator All_faces_iterator;
|
||||
// \}
|
||||
|
||||
|
|
@ -381,10 +390,11 @@ public:
|
|||
/// Checks whether the triangulation is a valid simplicial complex in the one cover.
|
||||
bool is_triangulation_in_1_sheet() const;
|
||||
|
||||
/// Convert a 9 sheeted cover (used for sparse triangulations) to a single sheeted cover.
|
||||
/// Converts a 9 sheeted cover (used for sparse triangulations) to a single sheeted cover.
|
||||
/// \pre !is_1_cover();
|
||||
void convert_to_1_sheeted_covering();
|
||||
/// Convert a single sheeted cover (used for dense triangulations) to a 9 sheeted cover.
|
||||
|
||||
/// Converts a single sheeted cover (used for dense triangulations) to a 9 sheeted cover.
|
||||
/// \pre is_1_cover();
|
||||
void convert_to_9_sheeted_covering();
|
||||
// \}
|
||||
|
|
@ -676,6 +686,32 @@ public:
|
|||
Periodic_2_triangulation_2_internal::Domain_tester<Self>(this));
|
||||
}
|
||||
|
||||
Unique_edge_iterator unique_edges_begin() const
|
||||
{
|
||||
return CGAL::filter_iterator(edges_end(),
|
||||
Periodic_2_triangulation_2_internal::Domain_tester<Self>(this),
|
||||
edges_begin());
|
||||
}
|
||||
/// past-the-end iterator over the canonical edges
|
||||
Unique_edge_iterator unique_edges_end() const
|
||||
{
|
||||
return CGAL::filter_iterator(edges_end(),
|
||||
Periodic_2_triangulation_2_internal::Domain_tester<Self>(this));
|
||||
}
|
||||
|
||||
Unique_face_iterator unique_faces_begin() const
|
||||
{
|
||||
return CGAL::filter_iterator(faces_end(),
|
||||
Periodic_2_triangulation_2_internal::Domain_tester<Self>(this),
|
||||
faces_begin());
|
||||
}
|
||||
/// past-the-end iterator over the non-virtual vertices
|
||||
Unique_face_iterator unique_faces_end() const
|
||||
{
|
||||
return CGAL::filter_iterator(faces_end(),
|
||||
Periodic_2_triangulation_2_internal::Domain_tester<Self>(this));
|
||||
}
|
||||
|
||||
// \}
|
||||
/// \name Geometric iterators
|
||||
//\{
|
||||
|
|
@ -972,6 +1008,32 @@ public:
|
|||
return Offset();
|
||||
}
|
||||
|
||||
// Gets the canonicalized offsets of a face.
|
||||
void get_offsets(Face_handle fh,
|
||||
Offset& off0, Offset& off1, Offset& off2) const
|
||||
{
|
||||
Offset face_off0 = int_to_off(fh->offset(0));
|
||||
Offset face_off1 = int_to_off(fh->offset(1));
|
||||
Offset face_off2 = int_to_off(fh->offset(2));
|
||||
Offset diff_off((face_off0.x() == 1 && face_off1.x() == 1 && face_off2.x() == 1) ? -1 : 0,
|
||||
(face_off0.y() == 1 && face_off1.y() == 1 && face_off2.y() == 1) ? -1 : 0);
|
||||
off0 = combine_offsets(get_offset(fh, 0), diff_off);
|
||||
off1 = combine_offsets(get_offset(fh, 1), diff_off);
|
||||
off2 = combine_offsets(get_offset(fh, 2), diff_off);
|
||||
}
|
||||
|
||||
// Gets the canonicalized offsets of an edge.
|
||||
void get_offsets(const Edge& e,
|
||||
Offset& off0, Offset& off1) const
|
||||
{
|
||||
Offset edge_off0 = int_to_off(e.first->offset(cw(e.second)));
|
||||
Offset edge_off1 = int_to_off(e.first->offset(ccw(e.second)));
|
||||
Offset diff_off((edge_off0.x() == 1 && edge_off1.x() == 1) ? -1 : 0,
|
||||
(edge_off0.y() == 1 && edge_off1.y() == 1) ? -1 : 0);
|
||||
off0 = combine_offsets(get_offset(e.first, cw(e.second)), diff_off);
|
||||
off1 = combine_offsets(get_offset(e.first, ccw(e.second)), diff_off);
|
||||
}
|
||||
|
||||
/// Converts an offset to a bit pattern where bit1==offx and bit0==offy.
|
||||
int off_to_int(const Offset & off) const
|
||||
{
|
||||
|
|
@ -986,13 +1048,12 @@ public:
|
|||
return Offset((i >> 1) & 1, i & 1);
|
||||
}
|
||||
|
||||
// \}
|
||||
// Protected functions of Periodic_2_triangulation_2
|
||||
/// Const accessor to the virtual vertices reverse map,
|
||||
/// used to optimize point location for periodic copies.
|
||||
const Virtual_vertex_reverse_map &virtual_vertices_reverse() const
|
||||
/// Tests whether a vertex is a periodic copy of a vertex in the 3-cover.
|
||||
bool is_virtual(Vertex_handle v) const
|
||||
{
|
||||
return _virtual_vertices_reverse;
|
||||
if (is_1_cover())
|
||||
return false;
|
||||
return (_virtual_vertices.find(v) != _virtual_vertices.end());
|
||||
}
|
||||
|
||||
/// [Undoc] Returns the non-virtual copy of the vertex.
|
||||
|
|
@ -1007,15 +1068,6 @@ public:
|
|||
return vh;
|
||||
}
|
||||
|
||||
|
||||
/// Tests whether a vertex is a periodic copy of a vertex in the 3-cover.
|
||||
bool is_virtual(Vertex_handle v)
|
||||
{
|
||||
if (is_1_cover())
|
||||
return false;
|
||||
return (_virtual_vertices.find(v) != _virtual_vertices.end());
|
||||
}
|
||||
|
||||
const std::vector<Vertex_handle>& periodic_copies(const Vertex_handle v) const
|
||||
{
|
||||
CGAL_precondition(number_of_sheets() != make_array(1, 1) );
|
||||
|
|
@ -1024,6 +1076,77 @@ public:
|
|||
return _virtual_vertices_reverse.find(v)->second;
|
||||
}
|
||||
|
||||
// Protected functions of Periodic_2_triangulation_2
|
||||
/// Const accessor to the virtual vertices reverse map,
|
||||
/// used to optimize point location for periodic copies.
|
||||
const Virtual_vertex_reverse_map& virtual_vertices_reverse() const
|
||||
{
|
||||
return _virtual_vertices_reverse;
|
||||
}
|
||||
|
||||
// check whether pos points onto a unique edge or not.
|
||||
// If we are computing in 1-sheeted covering this should
|
||||
// always be true.
|
||||
bool is_canonical(Face_handle fh) const
|
||||
{
|
||||
if(is_1_cover())
|
||||
return true;
|
||||
|
||||
Offset off0, off1, off2;
|
||||
get_offsets(fh, off0, off1, off2);
|
||||
|
||||
// If there is one offset with entries larger than 1 then we are
|
||||
// talking about a vertex that is too far away from the original
|
||||
// domain to belong to a canonical triangle.
|
||||
if (off0.x() > 1) return false;
|
||||
if (off0.y() > 1) return false;
|
||||
if (off1.x() > 1) return false;
|
||||
if (off1.y() > 1) return false;
|
||||
if (off2.x() > 1) return false;
|
||||
if (off2.y() > 1) return false;
|
||||
|
||||
// If there is one direction of space for which all offsets are
|
||||
// non-zero then the edge is not canonical because we can
|
||||
// take the copy closer towards the origin in that direction.
|
||||
int offx = off0.x() & off1.x() & off2.x();
|
||||
int offy = off0.y() & off1.y() & off2.y();
|
||||
|
||||
return (offx == 0 && offy == 0);
|
||||
}
|
||||
|
||||
bool is_canonical(const Edge& e) const
|
||||
{
|
||||
if(is_1_cover())
|
||||
return true;
|
||||
|
||||
// fetch all offsets
|
||||
Offset off0, off1;
|
||||
get_offsets(e, off0, off1);
|
||||
|
||||
// If there is one offset with entries larger than 1 then we are
|
||||
// talking about a vertex that is too far away from the original
|
||||
// domain to belong to a canonical edge.
|
||||
if (off0.x() > 1) return false;
|
||||
if (off0.y() > 1) return false;
|
||||
if (off1.x() > 1) return false;
|
||||
if (off1.y() > 1) return false;
|
||||
|
||||
// If there is one direction of space for which all offsets are
|
||||
// non-zero then the edge is not canonical because we can
|
||||
// take the copy closer towards the origin in that direction.
|
||||
int offx = off0.x() & off1.x();
|
||||
int offy = off0.y() & off1.y();
|
||||
|
||||
return (offx == 0 && offy == 0);
|
||||
}
|
||||
|
||||
// checks whether pos points onto a vertex inside the original domain
|
||||
bool is_canonical(Vertex_handle vh) const
|
||||
{
|
||||
return !is_virtual(vh);
|
||||
}
|
||||
|
||||
public:
|
||||
template<class Stream>
|
||||
Stream& draw_triangulation(Stream& os) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -14,13 +14,11 @@
|
|||
|
||||
#include <CGAL/license/Periodic_2_triangulation_2.h>
|
||||
|
||||
|
||||
#include <CGAL/assertions.h>
|
||||
#include <CGAL/iterator.h>
|
||||
#include <CGAL/array.h>
|
||||
|
||||
namespace CGAL
|
||||
{
|
||||
namespace CGAL {
|
||||
|
||||
template < class T >
|
||||
class Periodic_2_triangulation_triangle_iterator_2
|
||||
|
|
@ -66,7 +64,7 @@ public:
|
|||
{
|
||||
if (_it == T::UNIQUE || _it == T::UNIQUE_COVER_DOMAIN)
|
||||
{
|
||||
while (pos != _t->faces_end() && !is_canonical() )
|
||||
while (pos != _t->faces_end() && !_t->is_canonical(pos) )
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
|
@ -88,7 +86,7 @@ public:
|
|||
{
|
||||
++pos;
|
||||
}
|
||||
while (pos != _t->faces_end() && !is_canonical());
|
||||
while (pos != _t->faces_end() && !_t->is_canonical(pos));
|
||||
break;
|
||||
case T::STORED_COVER_DOMAIN:
|
||||
case T::UNIQUE_COVER_DOMAIN:
|
||||
|
|
@ -112,7 +110,7 @@ public:
|
|||
{
|
||||
--pos;
|
||||
}
|
||||
while (pos != _t->faces_begin() && !is_canonical());
|
||||
while (pos != _t->faces_begin() && !_t->is_canonical(pos));
|
||||
break;
|
||||
case T::STORED_COVER_DOMAIN:
|
||||
case T::UNIQUE_COVER_DOMAIN:
|
||||
|
|
@ -172,37 +170,6 @@ private:
|
|||
mutable Periodic_triangle periodic_triangle; // current triangle.
|
||||
|
||||
private:
|
||||
// check whether pos points onto a unique edge or not.
|
||||
// If we are computing in 1-sheeted covering this should
|
||||
// always be true.
|
||||
bool is_canonical()
|
||||
{
|
||||
// fetch all offsets
|
||||
Offset off0, off1, off2;
|
||||
get_edge_offsets(off0, off1, off2);
|
||||
|
||||
if (_t->number_of_sheets() != make_array(1, 1))
|
||||
{
|
||||
// If there is one offset with entries larger than 1 then we are
|
||||
// talking about a vertex that is too far away from the original
|
||||
// domain to belong to a canonical triangle.
|
||||
if (off0.x() > 1) return false;
|
||||
if (off0.y() > 1) return false;
|
||||
if (off1.x() > 1) return false;
|
||||
if (off1.y() > 1) return false;
|
||||
if (off2.x() > 1) return false;
|
||||
if (off2.y() > 1) return false;
|
||||
}
|
||||
|
||||
// If there is one direction of space for which all offsets are
|
||||
// non-zero then the edge is not canonical because we can
|
||||
// take the copy closer towards the origin in that direction.
|
||||
int offx = off0.x() & off1.x() & off2.x();
|
||||
int offy = off0.y() & off1.y() & off2.y();
|
||||
|
||||
return (offx == 0 && offy == 0);
|
||||
}
|
||||
|
||||
// Artificial incrementation function that takes periodic
|
||||
// copies into account.
|
||||
void increment_domain()
|
||||
|
|
@ -217,7 +184,7 @@ private:
|
|||
++pos;
|
||||
}
|
||||
while (_it == T::UNIQUE_COVER_DOMAIN
|
||||
&& pos != _t->faces_end() && !is_canonical());
|
||||
&& pos != _t->faces_end() && !_t->is_canonical(pos));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -241,7 +208,7 @@ private:
|
|||
{
|
||||
--pos;
|
||||
}
|
||||
while (_it == T::UNIQUE_COVER_DOMAIN && !is_canonical());
|
||||
while (_it == T::UNIQUE_COVER_DOMAIN && !_t->is_canonical(pos));
|
||||
_off = get_drawing_offsets();
|
||||
}
|
||||
else
|
||||
|
|
@ -256,25 +223,6 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
// Get the canonicalized offsets of an edge.
|
||||
// This works in any cover that is encoded in _t->combine_offsets
|
||||
void get_edge_offsets(Offset &off0, Offset &off1,
|
||||
Offset &off2) const
|
||||
{
|
||||
Offset face_off0 = _t->int_to_off(pos->offset(0));
|
||||
Offset face_off1 = _t->int_to_off(pos->offset(1));
|
||||
Offset face_off2 = _t->int_to_off(pos->offset(2));
|
||||
Offset diff_off((face_off0.x() == 1
|
||||
&& face_off1.x() == 1
|
||||
&& face_off2.x() == 1) ? -1 : 0,
|
||||
(face_off0.y() == 1
|
||||
&& face_off1.y() == 1
|
||||
&& face_off2.y() == 1) ? -1 : 0);
|
||||
off0 = _t->combine_offsets(_t->get_offset(pos, 0), diff_off);
|
||||
off1 = _t->combine_offsets(_t->get_offset(pos, 1), diff_off);
|
||||
off2 = _t->combine_offsets(_t->get_offset(pos, 2), diff_off);
|
||||
}
|
||||
|
||||
// return an integer that encodes the translations which have to be
|
||||
// applied to the edge *pos
|
||||
int get_drawing_offsets()
|
||||
|
|
@ -284,10 +232,10 @@ private:
|
|||
// intersect the boundary of the periodic domain. In UNIQUE mode
|
||||
// this means that the offset with respect to drawing should
|
||||
// differ in some entries. Otherwise we consider the offsets
|
||||
// internally stored inside the cell telling us that this cell
|
||||
// internally stored inside the face telling us that this face
|
||||
// wraps around the domain.
|
||||
if (_it == T::UNIQUE_COVER_DOMAIN)
|
||||
get_edge_offsets(off0, off1, off2);
|
||||
_t->get_offsets(pos, off0, off1, off2);
|
||||
else
|
||||
{
|
||||
CGAL_assertion(_it == T::STORED_COVER_DOMAIN);
|
||||
|
|
@ -319,7 +267,7 @@ private:
|
|||
{
|
||||
CGAL_assertion(pos != typename T::Face_handle());
|
||||
Offset off0, off1, off2;
|
||||
get_edge_offsets(off0, off1, off2);
|
||||
_t->get_offsets(pos, off0, off1, off2);
|
||||
Offset transl_off = Offset((((_off >> 1) & 1) == 1 ? -1 : 0),
|
||||
(((_off ) & 1) == 1 ? -1 : 0));
|
||||
if (_it == T::STORED_COVER_DOMAIN)
|
||||
|
|
@ -385,7 +333,7 @@ public:
|
|||
{
|
||||
if (_it == T::UNIQUE || _it == T::UNIQUE_COVER_DOMAIN)
|
||||
{
|
||||
while (pos != _t->edges_end() && !is_canonical() )
|
||||
while (pos != _t->edges_end() && !_t->is_canonical(*pos) )
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
|
@ -407,7 +355,7 @@ public:
|
|||
{
|
||||
++pos;
|
||||
}
|
||||
while (pos != _t->edges_end() && !is_canonical());
|
||||
while (pos != _t->edges_end() && !_t->is_canonical(*pos));
|
||||
break;
|
||||
case T::STORED_COVER_DOMAIN:
|
||||
case T::UNIQUE_COVER_DOMAIN:
|
||||
|
|
@ -431,7 +379,7 @@ public:
|
|||
{
|
||||
--pos;
|
||||
}
|
||||
while (pos != _t->edges_begin() && !is_canonical());
|
||||
while (pos != _t->edges_begin() && !_t->is_canonical(*pos));
|
||||
break;
|
||||
case T::STORED_COVER_DOMAIN:
|
||||
case T::UNIQUE_COVER_DOMAIN:
|
||||
|
|
@ -490,35 +438,6 @@ private:
|
|||
mutable Periodic_segment periodic_segment; // current segment.
|
||||
|
||||
private:
|
||||
// check whether pos points onto a unique edge or not.
|
||||
// If we are computing in 1-sheeted covering this should
|
||||
// always be true.
|
||||
bool is_canonical()
|
||||
{
|
||||
// fetch all offsets
|
||||
Offset off0, off1;
|
||||
get_edge_offsets(off0, off1);
|
||||
|
||||
if (_t->number_of_sheets() != make_array(1, 1))
|
||||
{
|
||||
// If there is one offset with entries larger than 1 then we are
|
||||
// talking about a vertex that is too far away from the original
|
||||
// domain to belong to a canonical triangle.
|
||||
if (off0.x() > 1) return false;
|
||||
if (off0.y() > 1) return false;
|
||||
if (off1.x() > 1) return false;
|
||||
if (off1.y() > 1) return false;
|
||||
}
|
||||
|
||||
// If there is one direction of space for which all offsets are
|
||||
// non-zero then the edge is not canonical because we can
|
||||
// take the copy closer towards the origin in that direction.
|
||||
int offx = off0.x() & off1.x();
|
||||
int offy = off0.y() & off1.y();
|
||||
|
||||
return (offx == 0 && offy == 0);
|
||||
}
|
||||
|
||||
// Artificial incrementation function that takes periodic
|
||||
// copies into account.
|
||||
void increment_domain()
|
||||
|
|
@ -533,7 +452,7 @@ private:
|
|||
++pos;
|
||||
}
|
||||
while (_it == T::UNIQUE_COVER_DOMAIN
|
||||
&& pos != _t->edges_end() && !is_canonical());
|
||||
&& pos != _t->edges_end() && !_t->is_canonical(*pos));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -557,7 +476,7 @@ private:
|
|||
{
|
||||
--pos;
|
||||
}
|
||||
while (_it == T::UNIQUE_COVER_DOMAIN && !is_canonical());
|
||||
while (_it == T::UNIQUE_COVER_DOMAIN && !_t->is_canonical(*pos));
|
||||
_off = get_drawing_offsets();
|
||||
}
|
||||
else
|
||||
|
|
@ -572,20 +491,6 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
// Get the canonicalized offsets of an edge.
|
||||
// This works in any cover that is encoded in _t->combine_offsets
|
||||
void get_edge_offsets(Offset &off0, Offset &off1) const
|
||||
{
|
||||
Offset cell_off0 = _t->int_to_off(pos->first->offset(_t->cw(pos->second)));
|
||||
Offset cell_off1 = _t->int_to_off(pos->first->offset(_t->ccw(pos->second)));
|
||||
Offset diff_off((cell_off0.x() == 1 && cell_off1.x() == 1) ? -1 : 0,
|
||||
(cell_off0.y() == 1 && cell_off1.y() == 1) ? -1 : 0);
|
||||
off0 = _t->combine_offsets(_t->get_offset(pos->first, _t->cw(pos->second)),
|
||||
diff_off);
|
||||
off1 = _t->combine_offsets(_t->get_offset(pos->first, _t->ccw(pos->second)),
|
||||
diff_off);
|
||||
}
|
||||
|
||||
// return an integer that encodes the translations which have to be
|
||||
// applied to the edge *pos
|
||||
int get_drawing_offsets()
|
||||
|
|
@ -595,10 +500,10 @@ private:
|
|||
// intersect the boundary of the periodic domain. In UNIQUE mode
|
||||
// this means that the offset with respect to drawing should
|
||||
// differ in some entries. Otherwise we consider the offsets
|
||||
// internally stored inside the cell telling us that this cell
|
||||
// internally stored inside the face telling us that this face
|
||||
// wraps around the domain.
|
||||
if (_it == T::UNIQUE_COVER_DOMAIN)
|
||||
get_edge_offsets(off0, off1);
|
||||
_t->get_offsets(*pos, off0, off1);
|
||||
else
|
||||
{
|
||||
CGAL_assertion(_it == T::STORED_COVER_DOMAIN);
|
||||
|
|
@ -618,7 +523,7 @@ private:
|
|||
{
|
||||
CGAL_assertion(pos->first != typename T::Face_handle());
|
||||
Offset off0, off1;
|
||||
get_edge_offsets(off0, off1);
|
||||
_t->get_offsets(*pos, off0, off1);
|
||||
Offset transl_off = Offset((((_off >> 1) & 1) == 1 ? -1 : 0),
|
||||
(( _off & 1) == 1 ? -1 : 0));
|
||||
if (_it == T::STORED_COVER_DOMAIN)
|
||||
|
|
@ -681,7 +586,7 @@ public:
|
|||
{
|
||||
if (_it == T::UNIQUE || _it == T::UNIQUE_COVER_DOMAIN)
|
||||
{
|
||||
while (pos != _t->vertices_end() && !is_canonical() )
|
||||
while (pos != _t->vertices_end() && !_t->is_canonical(pos) )
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
|
@ -705,7 +610,7 @@ public:
|
|||
{
|
||||
++pos;
|
||||
}
|
||||
while (pos != _t->vertices_end() && !is_canonical());
|
||||
while (pos != _t->vertices_end() && !_t->is_canonical(pos));
|
||||
break;
|
||||
default:
|
||||
CGAL_assertion(false);
|
||||
|
|
@ -727,7 +632,7 @@ public:
|
|||
{
|
||||
--pos;
|
||||
}
|
||||
while (pos != _t->vertices_begin() && !is_canonical());
|
||||
while (pos != _t->vertices_begin() && !_t->is_canonical(pos));
|
||||
break;
|
||||
default:
|
||||
CGAL_assertion(false);
|
||||
|
|
@ -785,14 +690,6 @@ private:
|
|||
mutable Periodic_point periodic_point; // current point.
|
||||
|
||||
private:
|
||||
// check whether pos points onto a vertex inside the original
|
||||
// domain. If we are computing in 1-sheeted covering this should
|
||||
// always be true.
|
||||
bool is_canonical()
|
||||
{
|
||||
return (_t->get_offset(pos).is_null());
|
||||
}
|
||||
|
||||
Periodic_point construct_periodic_point() const
|
||||
{
|
||||
CGAL_assertion(pos != typename T::Vertex_handle());
|
||||
|
|
@ -801,23 +698,91 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
namespace Periodic_2_triangulation_2_internal
|
||||
{
|
||||
namespace Periodic_2_triangulation_2_internal {
|
||||
|
||||
// returns `true` if the simplex is not canonical, and has to be filtered out
|
||||
template <class T>
|
||||
class Domain_tester
|
||||
{
|
||||
const T *t;
|
||||
typedef typename T::Offset Offset;
|
||||
|
||||
public:
|
||||
Domain_tester() {}
|
||||
Domain_tester(const T *tr) : t(tr) {}
|
||||
const T *t;
|
||||
|
||||
bool operator()(const typename T::Vertex_iterator & v) const
|
||||
public:
|
||||
Domain_tester() {}
|
||||
Domain_tester(const T *tr) : t(tr) {}
|
||||
|
||||
bool operator()(const typename T::Vertex_iterator v) const
|
||||
{
|
||||
return !(t->get_offset(v).is_null());
|
||||
}
|
||||
|
||||
bool operator()(const typename T::Edge_iterator e) const
|
||||
{
|
||||
Offset eo_0 = t->int_to_off(e->first->offset(t->cw(e->second)));
|
||||
Offset eo_1 = t->int_to_off(e->first->offset(t->ccw(e->second)));
|
||||
|
||||
Offset diff_off((eo_0.x() == 1 && eo_1.x() == 1) ? -1 : 0,
|
||||
(eo_0.y() == 1 && eo_1.y() == 1) ? -1 : 0);
|
||||
Offset off0 = t->combine_offsets(t->get_offset(e->first, t->cw(e->second)), diff_off);
|
||||
Offset off1 = t->combine_offsets(t->get_offset(e->first, t->ccw(e->second)), diff_off);
|
||||
|
||||
if (t->number_of_sheets() != make_array(1, 1))
|
||||
{
|
||||
return (t->get_offset(v) != typename T::Offset(0, 0));
|
||||
// If there is one offset with entries larger than 1 then we are
|
||||
// talking about a vertex that is too far away from the original
|
||||
// domain to belong to a canonical edge.
|
||||
if (off0.x() > 1) return true;
|
||||
if (off0.y() > 1) return true;
|
||||
if (off1.x() > 1) return true;
|
||||
if (off1.y() > 1) return true;
|
||||
}
|
||||
|
||||
// If there is one direction of space for which all offsets are
|
||||
// non-zero then the edge is not canonical because we can
|
||||
// take the copy closer towards the origin in that direction.
|
||||
int offx = off0.x() & off1.x();
|
||||
int offy = off0.y() & off1.y();
|
||||
|
||||
return (offx != 0 || offy != 0);
|
||||
}
|
||||
|
||||
bool operator()(const typename T::Face_iterator f) const
|
||||
{
|
||||
Offset fo_0 = t->int_to_off(f->offset(0));
|
||||
Offset fo_1 = t->int_to_off(f->offset(1));
|
||||
Offset fo_2 = t->int_to_off(f->offset(2));
|
||||
|
||||
Offset diff_off((fo_0.x() == 1 && fo_1.x() == 1 && fo_2.x() == 1) ? -1 : 0,
|
||||
(fo_0.y() == 1 && fo_1.y() == 1 && fo_2.y() == 1) ? -1 : 0);
|
||||
Offset off0 = t->combine_offsets(t->get_offset(f, 0), diff_off);
|
||||
Offset off1 = t->combine_offsets(t->get_offset(f, 1), diff_off);
|
||||
Offset off2 = t->combine_offsets(t->get_offset(f, 2), diff_off);
|
||||
|
||||
if (t->number_of_sheets() != make_array(1, 1))
|
||||
{
|
||||
// If there is one offset with entries larger than 1 then we are
|
||||
// talking about a vertex that is too far away from the original
|
||||
// domain to belong to a canonical triangle.
|
||||
if (off0.x() > 1) return true;
|
||||
if (off0.y() > 1) return true;
|
||||
if (off1.x() > 1) return true;
|
||||
if (off1.y() > 1) return true;
|
||||
if (off2.x() > 1) return true;
|
||||
if (off2.y() > 1) return true;
|
||||
}
|
||||
|
||||
// If there is one direction of space for which all offsets are
|
||||
// non-zero then the edge is not canonical because we can
|
||||
// take the copy closer towards the origin in that direction.
|
||||
int offx = off0.x() & off1.x() & off2.x();
|
||||
int offy = off0.y() & off1.y() & off2.y();
|
||||
|
||||
return (offx != 0 || offy != 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} // Periodic_2_triangulation_2_internal
|
||||
|
||||
// Iterates over the vertices in a periodic triangulation that are
|
||||
// located inside the original cube.
|
||||
|
|
@ -830,7 +795,6 @@ template <class T>
|
|||
class Periodic_2_triangulation_unique_vertex_iterator_2
|
||||
: public Filter_iterator<typename T::Vertex_iterator, Periodic_2_triangulation_2_internal::Domain_tester<T> >
|
||||
{
|
||||
|
||||
typedef typename T::Vertex_handle Vertex_handle;
|
||||
typedef typename T::Vertex_iterator Vertex_iterator;
|
||||
|
||||
|
|
@ -838,8 +802,8 @@ class Periodic_2_triangulation_unique_vertex_iterator_2
|
|||
|
||||
typedef Filter_iterator<Vertex_iterator, Tester > Base;
|
||||
typedef Periodic_2_triangulation_unique_vertex_iterator_2 Self;
|
||||
public:
|
||||
|
||||
public:
|
||||
Periodic_2_triangulation_unique_vertex_iterator_2() : Base() {}
|
||||
Periodic_2_triangulation_unique_vertex_iterator_2(const Base &b) : Base(b) {}
|
||||
|
||||
|
|
@ -872,6 +836,108 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
} //namespace CGAL
|
||||
// Iterates over the canonical edges in a periodic triangulation.
|
||||
// Derives from Filter_iterator in order to add a conversion to handle
|
||||
//
|
||||
// Comments:
|
||||
// When computing in 1-sheeted covering, there will be no difference
|
||||
// between a normal Edge_iterator and this iterator
|
||||
template <class T>
|
||||
class Periodic_2_triangulation_unique_edge_iterator_2
|
||||
: public Filter_iterator<typename T::Edge_iterator, Periodic_2_triangulation_2_internal::Domain_tester<T> >
|
||||
{
|
||||
typedef typename T::Edge Edge;
|
||||
typedef typename T::Edge_iterator Edge_iterator;
|
||||
|
||||
typedef typename Periodic_2_triangulation_2_internal::Domain_tester<T> Tester;
|
||||
|
||||
typedef Filter_iterator<Edge_iterator, Tester > Base;
|
||||
typedef Periodic_2_triangulation_unique_edge_iterator_2 Self;
|
||||
|
||||
public:
|
||||
Periodic_2_triangulation_unique_edge_iterator_2() : Base() {}
|
||||
Periodic_2_triangulation_unique_edge_iterator_2(const Base &b) : Base(b) {}
|
||||
|
||||
Self & operator++()
|
||||
{
|
||||
Base::operator++();
|
||||
return *this;
|
||||
}
|
||||
Self & operator--()
|
||||
{
|
||||
Base::operator--();
|
||||
return *this;
|
||||
}
|
||||
Self operator++(int)
|
||||
{
|
||||
Self tmp(*this);
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
Self operator--(int)
|
||||
{
|
||||
Self tmp(*this);
|
||||
--(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
operator Edge() const
|
||||
{
|
||||
return Base::base();
|
||||
}
|
||||
};
|
||||
|
||||
// Iterates over the canonical faces in a periodic triangulation.
|
||||
// Derives from Filter_iterator in order to add a conversion to handle
|
||||
//
|
||||
// Comments:
|
||||
// When computing in 1-sheeted covering, there will be no difference
|
||||
// between a normal Face_iterator and this iterator
|
||||
template <class T>
|
||||
class Periodic_2_triangulation_unique_face_iterator_2
|
||||
: public Filter_iterator<typename T::Face_iterator, Periodic_2_triangulation_2_internal::Domain_tester<T> >
|
||||
{
|
||||
typedef typename T::Face_handle Face_handle;
|
||||
typedef typename T::Face_iterator Face_iterator;
|
||||
|
||||
typedef typename Periodic_2_triangulation_2_internal::Domain_tester<T> Tester;
|
||||
|
||||
typedef Filter_iterator<Face_iterator, Tester > Base;
|
||||
typedef Periodic_2_triangulation_unique_face_iterator_2 Self;
|
||||
|
||||
public:
|
||||
Periodic_2_triangulation_unique_face_iterator_2() : Base() {}
|
||||
Periodic_2_triangulation_unique_face_iterator_2(const Base &b) : Base(b) {}
|
||||
|
||||
Self & operator++()
|
||||
{
|
||||
Base::operator++();
|
||||
return *this;
|
||||
}
|
||||
Self & operator--()
|
||||
{
|
||||
Base::operator--();
|
||||
return *this;
|
||||
}
|
||||
Self operator++(int)
|
||||
{
|
||||
Self tmp(*this);
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
Self operator--(int)
|
||||
{
|
||||
Self tmp(*this);
|
||||
--(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
operator Face_handle() const
|
||||
{
|
||||
return Base::base();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_PERIODIC_2_TRIANGULATION_ITERATORS_2_H
|
||||
|
|
|
|||
|
|
@ -208,6 +208,8 @@ void test_iterators()
|
|||
Vertex_handle vh2 = t.insert(Point(0.7, 0.7));
|
||||
CGAL_USE(vh2);
|
||||
|
||||
std::cout << "Cover = " << t.number_of_sheets()[0] << " " << t.number_of_sheets()[1] << std::endl;
|
||||
|
||||
// vertices
|
||||
size_t size = 0;
|
||||
for (typename T::Vertex_iterator vit = t_const.vertices_begin();
|
||||
|
|
@ -217,19 +219,19 @@ void test_iterators()
|
|||
}
|
||||
assert(size == t_const.number_of_stored_vertices());
|
||||
size = 0;
|
||||
for (typename T::Vertex_iterator vit = t_const.all_vertices_begin();
|
||||
vit != t_const.all_vertices_end(); ++vit)
|
||||
{
|
||||
++size;
|
||||
}
|
||||
assert(size == t_const.number_of_stored_vertices());
|
||||
size = 0;
|
||||
for (typename T::Unique_vertex_iterator uvit = t_const.unique_vertices_begin();
|
||||
uvit != t_const.unique_vertices_end(); ++uvit)
|
||||
{
|
||||
++size;
|
||||
}
|
||||
assert(size == t_const.number_of_vertices());
|
||||
size = 0;
|
||||
for (typename T::Vertex_iterator vit = t_const.all_vertices_begin();
|
||||
vit != t_const.all_vertices_end(); ++vit)
|
||||
{
|
||||
++size;
|
||||
}
|
||||
assert(size == t_const.number_of_stored_vertices());
|
||||
|
||||
// edges
|
||||
size = 0;
|
||||
|
|
@ -246,6 +248,13 @@ void test_iterators()
|
|||
++size;
|
||||
}
|
||||
assert(size == t_const.number_of_stored_edges());
|
||||
size = 0;
|
||||
for (typename T::Unique_edge_iterator uvit = t_const.unique_edges_begin();
|
||||
uvit != t_const.unique_edges_end(); ++uvit)
|
||||
{
|
||||
++size;
|
||||
}
|
||||
assert(size == t_const.number_of_edges());
|
||||
|
||||
// faces
|
||||
size = 0;
|
||||
|
|
@ -262,6 +271,13 @@ void test_iterators()
|
|||
++size;
|
||||
}
|
||||
assert(size == t_const.number_of_stored_faces());
|
||||
size = 0;
|
||||
for (typename T::Unique_face_iterator uvit = t_const.unique_faces_begin();
|
||||
uvit != t_const.unique_faces_end(); ++uvit)
|
||||
{
|
||||
++size;
|
||||
}
|
||||
assert(size == t_const.number_of_faces());
|
||||
|
||||
/// Geometric iterators
|
||||
for (typename T::Periodic_point_iterator ppit = t_const.periodic_points_begin();
|
||||
|
|
|
|||
|
|
@ -169,6 +169,13 @@ public:
|
|||
typedef Facet_iterator All_facets_iterator;
|
||||
typedef Edge_iterator All_edges_iterator;
|
||||
typedef Vertex_iterator All_vertices_iterator;
|
||||
|
||||
typedef Periodic_3_triangulation_unique_cell_iterator_3<Self>
|
||||
Unique_cell_iterator;
|
||||
typedef Periodic_3_triangulation_unique_facet_iterator_3<Self>
|
||||
Unique_facet_iterator;
|
||||
typedef Periodic_3_triangulation_unique_edge_iterator_3<Self>
|
||||
Unique_edge_iterator;
|
||||
typedef Periodic_3_triangulation_unique_vertex_iterator_3<Self>
|
||||
Unique_vertex_iterator;
|
||||
|
||||
|
|
@ -397,26 +404,14 @@ public:
|
|||
}
|
||||
|
||||
const Covering_sheets& number_of_sheets() const { return _cover; }
|
||||
const std::pair<Vertex_handle, Offset> original_vertex(const Vertex_handle v) const
|
||||
{
|
||||
return (virtual_vertices.find(v) == virtual_vertices.end()) ?
|
||||
std::make_pair(v,Offset()) : virtual_vertices.find(v)->second;
|
||||
}
|
||||
const std::vector<Vertex_handle>& periodic_copies(const Vertex_handle v) const
|
||||
{
|
||||
CGAL_precondition(number_of_sheets() != CGAL::make_array(1,1,1));
|
||||
CGAL_precondition(virtual_vertices.find(v) == virtual_vertices.end());
|
||||
CGAL_assertion(
|
||||
virtual_vertices_reverse.find(v) != virtual_vertices_reverse.end());
|
||||
return virtual_vertices_reverse.find(v)->second;
|
||||
}
|
||||
|
||||
bool is_triangulation_in_1_sheet() const;
|
||||
|
||||
void convert_to_1_sheeted_covering();
|
||||
|
||||
virtual void update_cover_data_after_converting_to_27_sheeted_covering() { }
|
||||
void convert_to_27_sheeted_covering();
|
||||
|
||||
public:
|
||||
size_type number_of_cells() const {
|
||||
if(is_1_cover()) return _tds.number_of_cells();
|
||||
else return _tds.number_of_cells()/27;
|
||||
|
|
@ -460,14 +455,6 @@ public:
|
|||
_cover = cover;
|
||||
}
|
||||
|
||||
public:
|
||||
bool is_virtual(Vertex_handle v)
|
||||
{
|
||||
if(is_1_cover())
|
||||
return false;
|
||||
return (virtual_vertices.find(v) != virtual_vertices.end());
|
||||
}
|
||||
|
||||
public:
|
||||
// Offset converters
|
||||
int off_to_int(const Offset& off) const
|
||||
|
|
@ -549,6 +536,232 @@ public:
|
|||
c->set_offsets(o0i,o1i,o2i,o3i);
|
||||
}
|
||||
|
||||
public:
|
||||
// undocumented access functions
|
||||
Offset get_offset(Cell_handle ch, int i) const
|
||||
{
|
||||
if(is_1_cover())
|
||||
return int_to_off(ch->offset(i));
|
||||
|
||||
Virtual_vertex_map_it it = virtual_vertices.find(ch->vertex(i));
|
||||
if(it != virtual_vertices.end())
|
||||
return combine_offsets(it->second.second, int_to_off(ch->offset(i)));
|
||||
else
|
||||
return combine_offsets(Offset(), int_to_off(ch->offset(i)));
|
||||
}
|
||||
|
||||
Offset get_offset(Vertex_handle vh) const
|
||||
{
|
||||
if(is_1_cover())
|
||||
return Offset();
|
||||
|
||||
Virtual_vertex_map_it it = virtual_vertices.find(vh);
|
||||
if(it != virtual_vertices.end())
|
||||
return it->second.second;
|
||||
else
|
||||
return Offset();
|
||||
}
|
||||
|
||||
// Get the canonicalized offsets of a cell.
|
||||
void get_offsets(Cell_handle ch,
|
||||
Offset& off0, Offset& off1, Offset& off2, Offset& off3) const
|
||||
{
|
||||
Offset cell_off0 = int_to_off(ch->offset(0));
|
||||
Offset cell_off1 = int_to_off(ch->offset(1));
|
||||
Offset cell_off2 = int_to_off(ch->offset(2));
|
||||
Offset cell_off3 = int_to_off(ch->offset(3));
|
||||
Offset diff_off((cell_off0.x() == 1 && cell_off1.x() == 1 &&
|
||||
cell_off2.x() == 1 && cell_off3.x() == 1) ? -1 : 0,
|
||||
(cell_off0.y() == 1 && cell_off1.y() == 1 &&
|
||||
cell_off2.y() == 1 && cell_off3.y() == 1) ? -1 : 0,
|
||||
(cell_off0.z() == 1 && cell_off1.z() == 1 &&
|
||||
cell_off2.z() == 1 && cell_off3.z() == 1) ? -1 : 0);
|
||||
off0 = combine_offsets(get_offset(ch,0), diff_off);
|
||||
off1 = combine_offsets(get_offset(ch,1), diff_off);
|
||||
off2 = combine_offsets(get_offset(ch,2), diff_off);
|
||||
off3 = combine_offsets(get_offset(ch,3), diff_off);
|
||||
}
|
||||
|
||||
// Gets the canonicalized offsets of a face.
|
||||
void get_offsets(const Facet& f,
|
||||
Offset& off0, Offset& off1, Offset& off2) const
|
||||
{
|
||||
Offset cell_off0 = int_to_off(f.first->offset((f.second+1)&3));
|
||||
Offset cell_off1 = int_to_off(f.first->offset((f.second+2)&3));
|
||||
Offset cell_off2 = int_to_off(f.first->offset((f.second+3)&3));
|
||||
Offset diff_off((cell_off0.x() == 1 && cell_off1.x() == 1 && cell_off2.x() == 1) ? -1 : 0,
|
||||
(cell_off0.y() == 1 && cell_off1.y() == 1 && cell_off2.y() == 1) ? -1 : 0,
|
||||
(cell_off0.z() == 1 && cell_off1.z() == 1 && cell_off2.z() == 1) ? -1 : 0);
|
||||
off0 = combine_offsets(get_offset(f.first, (f.second+1)&3), diff_off);
|
||||
off1 = combine_offsets(get_offset(f.first, (f.second+2)&3), diff_off);
|
||||
off2 = combine_offsets(get_offset(f.first, (f.second+3)&3), diff_off);
|
||||
}
|
||||
|
||||
// Gets the canonicalized offsets of an edge.
|
||||
void get_offsets(const Edge& e,
|
||||
Offset& off0, Offset& off1) const
|
||||
{
|
||||
Offset cell_off0 = int_to_off(e.first->offset(e.second));
|
||||
Offset cell_off1 = int_to_off(e.first->offset(e.third));
|
||||
Offset diff_off((cell_off0.x()==1 && cell_off1.x()==1) ? -1 : 0,
|
||||
(cell_off0.y()==1 && cell_off1.y()==1) ? -1 : 0,
|
||||
(cell_off0.z()==1 && cell_off1.z()==1) ? -1 : 0);
|
||||
off0 = combine_offsets(get_offset(e.first, e.second), diff_off);
|
||||
off1 = combine_offsets(get_offset(e.first, e.third), diff_off);
|
||||
}
|
||||
|
||||
public:
|
||||
Offset combine_offsets(const Offset& o_c, const Offset& o_t) const
|
||||
{
|
||||
Offset o_ct(_cover[0]*o_t.x(), _cover[1]*o_t.y(), _cover[2]*o_t.z());
|
||||
return o_c + o_ct;
|
||||
}
|
||||
|
||||
public:
|
||||
Offset neighbor_offset(Cell_handle ch, int i, Cell_handle nb) const;
|
||||
|
||||
Offset neighbor_offset(Cell_handle ch, int i) const
|
||||
{
|
||||
return neighbor_offset(ch, i, ch->neighbor(i));
|
||||
}
|
||||
|
||||
public:
|
||||
/// Tests whether a vertex is a periodic copy of a vertex in the 3-cover.
|
||||
bool is_virtual(Vertex_handle vh) const
|
||||
{
|
||||
if(is_1_cover())
|
||||
return false;
|
||||
return (virtual_vertices.find(vh) != virtual_vertices.end());
|
||||
}
|
||||
|
||||
/// Returns the non-virtual (i.e. canonical) copy of the vertex.
|
||||
Vertex_handle get_original_vertex(Vertex_handle vh) const
|
||||
{
|
||||
if(is_1_cover())
|
||||
return vh;
|
||||
|
||||
Virtual_vertex_map_it it = virtual_vertices.find(vh);
|
||||
if(it != virtual_vertices.end())
|
||||
return it->second.first;
|
||||
else
|
||||
return vh;
|
||||
}
|
||||
|
||||
const std::pair<Vertex_handle, Offset> original_vertex(const Vertex_handle v) const
|
||||
{
|
||||
return (virtual_vertices.find(v) == virtual_vertices.end()) ?
|
||||
std::make_pair(v,Offset()) : virtual_vertices.find(v)->second;
|
||||
}
|
||||
|
||||
const std::vector<Vertex_handle>& periodic_copies(const Vertex_handle v) const
|
||||
{
|
||||
CGAL_precondition(number_of_sheets() != CGAL::make_array(1,1,1));
|
||||
CGAL_precondition(virtual_vertices.find(v) == virtual_vertices.end());
|
||||
CGAL_assertion(
|
||||
virtual_vertices_reverse.find(v) != virtual_vertices_reverse.end());
|
||||
return virtual_vertices_reverse.find(v)->second;
|
||||
}
|
||||
|
||||
public:
|
||||
bool is_canonical(Cell_handle ch) const
|
||||
{
|
||||
if(is_1_cover())
|
||||
return true;
|
||||
|
||||
Offset off0, off1, off2, off3;
|
||||
get_offsets(ch, off0, off1, off2, off3);
|
||||
|
||||
// If there is one offset with entries larger than 1 then we are
|
||||
// talking about a vertex that is too far away from the original
|
||||
// domain to belong to a canonical triangle.
|
||||
if (off0.x() > 1) return false;
|
||||
if (off0.y() > 1) return false;
|
||||
if (off0.z() > 1) return false;
|
||||
if (off1.x() > 1) return false;
|
||||
if (off1.y() > 1) return false;
|
||||
if (off1.z() > 1) return false;
|
||||
if (off2.x() > 1) return false;
|
||||
if (off2.y() > 1) return false;
|
||||
if (off2.z() > 1) return false;
|
||||
if (off3.x() > 1) return false;
|
||||
if (off3.y() > 1) return false;
|
||||
if (off3.z() > 1) return false;
|
||||
|
||||
// If there is one direction of space for which all offsets are
|
||||
// non-zero then the edge is not canonical because we can
|
||||
// take the copy closer towards the origin in that direction.
|
||||
int offx = off0.x() & off1.x() & off2.x() & off3.x();
|
||||
int offy = off0.y() & off1.y() & off2.y() & off3.y();
|
||||
int offz = off0.z() & off1.z() & off2.z() & off3.z();
|
||||
|
||||
return (offx == 0 && offy == 0 && offz == 0);
|
||||
}
|
||||
|
||||
bool is_canonical(const Edge& e) const
|
||||
{
|
||||
if(is_1_cover())
|
||||
return true;
|
||||
|
||||
Offset off0, off1;
|
||||
get_offsets(e, off0, off1);
|
||||
|
||||
// If there is one offset with entries larger than 1 then we are
|
||||
// talking about a vertex that is too far away from the original
|
||||
// domain to belong to a canonical edge.
|
||||
if (off0.x() > 1) return false;
|
||||
if (off0.y() > 1) return false;
|
||||
if (off0.z() > 1) return false;
|
||||
if (off1.x() > 1) return false;
|
||||
if (off1.y() > 1) return false;
|
||||
if (off1.z() > 1) return false;
|
||||
|
||||
// If there is one direction of space for which all offsets are
|
||||
// non-zero then the edge is not canonical because we can
|
||||
// take the copy closer towards the origin in that direction.
|
||||
int offx = off0.x() & off1.x();
|
||||
int offy = off0.y() & off1.y();
|
||||
int offz = off0.z() & off1.z();
|
||||
|
||||
return (offx == 0 && offy == 0 && offz == 0);
|
||||
}
|
||||
|
||||
bool is_canonical(const Facet& f) const
|
||||
{
|
||||
if(is_1_cover())
|
||||
return true;
|
||||
|
||||
Offset off0, off1, off2;
|
||||
get_offsets(f, off0, off1, off2);
|
||||
|
||||
// If there is one offset with entries larger than 1 then we are
|
||||
// talking about a vertex that is too far away from the original
|
||||
// domain to belong to a canonical triangle.
|
||||
if(off0.x() > 1) return false;
|
||||
if(off0.y() > 1) return false;
|
||||
if(off0.z() > 1) return false;
|
||||
if(off1.x() > 1) return false;
|
||||
if(off1.y() > 1) return false;
|
||||
if(off1.z() > 1) return false;
|
||||
if(off2.x() > 1) return false;
|
||||
if(off2.y() > 1) return false;
|
||||
if(off2.z() > 1) return false;
|
||||
|
||||
// If there is one direction of space for which all offsets are
|
||||
// non-zero then the facet is not canonical because we can
|
||||
// take the copy closer towards the origin in that direction.
|
||||
int offx = off0.x() & off1.x() & off2.x();
|
||||
int offy = off0.y() & off1.y() & off2.y();
|
||||
int offz = off0.z() & off1.z() & off2.z();
|
||||
|
||||
return (offx == 0 && offy == 0 && offz == 0);
|
||||
}
|
||||
|
||||
/// Tests whether a vertex belongs to the original (canonical) domain.
|
||||
bool is_canonical(Vertex_handle vh) const
|
||||
{
|
||||
return !is_virtual(vh);
|
||||
}
|
||||
|
||||
public:
|
||||
/** @name Wrapping the traits */
|
||||
// Note that calling functors with "construct_point(p), offset" and not
|
||||
|
|
@ -988,6 +1201,14 @@ public:
|
|||
// end of geometric functions
|
||||
|
||||
public:
|
||||
// These functions give the pair (vertex, offset) that corresponds to the
|
||||
// i-th vertex of cell ch or vertex vh, respectively.
|
||||
void get_vertex(Cell_handle ch, int i, Vertex_handle& vh, Offset& off) const;
|
||||
void get_vertex(Vertex_handle vh_i, Vertex_handle& vh, Offset& off) const;
|
||||
|
||||
// Auxiliary functions
|
||||
Cell_handle get_cell(const Vertex_handle* vh) const;
|
||||
|
||||
/** @name Queries */
|
||||
bool is_vertex(const Point& p, Vertex_handle& v) const;
|
||||
|
||||
|
|
@ -1305,6 +1526,14 @@ public:
|
|||
std::vector<Vertex_handle> insert_generic_dummy_points();
|
||||
|
||||
protected:
|
||||
template<class Conflict_tester>
|
||||
Offset get_location_offset(const Conflict_tester& tester,
|
||||
Cell_handle c) const;
|
||||
|
||||
template<class Conflict_tester>
|
||||
Offset get_location_offset(const Conflict_tester& tester,
|
||||
Cell_handle c, bool& found) const;
|
||||
|
||||
// this is needed for compatibility reasons
|
||||
template <class Conflict_test, class OutputIteratorBoundaryFacets,
|
||||
class OutputIteratorCells, class OutputIteratorInternalFacets>
|
||||
|
|
@ -1474,6 +1703,8 @@ public:
|
|||
return _tds.facets_end();
|
||||
}
|
||||
|
||||
// Finite iterators (= all iterators, for periodic triangulations)
|
||||
|
||||
Cell_iterator finite_cells_begin() const {
|
||||
return _tds.cells_begin();
|
||||
}
|
||||
|
|
@ -1502,6 +1733,8 @@ public:
|
|||
return _tds.facets_end();
|
||||
}
|
||||
|
||||
// All iterators (= finite, for periodic triangulations)
|
||||
|
||||
All_cells_iterator all_cells_begin() const {
|
||||
return _tds.cells_begin();
|
||||
}
|
||||
|
|
@ -1530,6 +1763,16 @@ public:
|
|||
return _tds.facets_end();
|
||||
}
|
||||
|
||||
// Unique iterators
|
||||
|
||||
Unique_cell_iterator unique_cells_begin() const {
|
||||
return CGAL::filter_iterator(cells_end(), Domain_tester<Self>(this),
|
||||
cells_begin());
|
||||
}
|
||||
Unique_cell_iterator unique_cells_end() const {
|
||||
return CGAL::filter_iterator(cells_end(), Domain_tester<Self>(this));
|
||||
}
|
||||
|
||||
Unique_vertex_iterator unique_vertices_begin() const {
|
||||
return CGAL::filter_iterator(vertices_end(), Domain_tester<Self>(this),
|
||||
vertices_begin());
|
||||
|
|
@ -1538,6 +1781,22 @@ public:
|
|||
return CGAL::filter_iterator(vertices_end(), Domain_tester<Self>(this));
|
||||
}
|
||||
|
||||
Unique_edge_iterator unique_edges_begin() const {
|
||||
return CGAL::filter_iterator(edges_end(), Domain_tester<Self>(this),
|
||||
edges_begin());
|
||||
}
|
||||
Unique_edge_iterator unique_edges_end() const {
|
||||
return CGAL::filter_iterator(edges_end(), Domain_tester<Self>(this));
|
||||
}
|
||||
|
||||
Unique_facet_iterator unique_facets_begin() const {
|
||||
return CGAL::filter_iterator(facets_end(), Domain_tester<Self>(this),
|
||||
facets_begin());
|
||||
}
|
||||
Unique_facet_iterator unique_facets_end() const {
|
||||
return CGAL::filter_iterator(facets_end(), Domain_tester<Self>(this));
|
||||
}
|
||||
|
||||
// Geometric iterators
|
||||
Periodic_tetrahedron_iterator periodic_tetrahedra_begin(
|
||||
Iterator_type it = STORED) const {
|
||||
|
|
@ -1576,6 +1835,7 @@ public:
|
|||
}
|
||||
|
||||
// Circulators
|
||||
|
||||
Cell_circulator incident_cells(const Edge& e) const {
|
||||
return _tds.incident_cells(e);
|
||||
}
|
||||
|
|
@ -1695,75 +1955,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
public:
|
||||
// undocumented access functions
|
||||
Offset get_offset(Cell_handle ch, int i) const
|
||||
{
|
||||
if(is_1_cover())
|
||||
return int_to_off(ch->offset(i));
|
||||
|
||||
Virtual_vertex_map_it it = virtual_vertices.find(ch->vertex(i));
|
||||
if(it != virtual_vertices.end())
|
||||
return combine_offsets(it->second.second, int_to_off(ch->offset(i)));
|
||||
else
|
||||
return combine_offsets(Offset(), int_to_off(ch->offset(i)));
|
||||
}
|
||||
|
||||
Offset get_offset(Vertex_handle vh) const
|
||||
{
|
||||
if(is_1_cover())
|
||||
return Offset();
|
||||
|
||||
Virtual_vertex_map_it it = virtual_vertices.find(vh);
|
||||
if(it != virtual_vertices.end())
|
||||
return it->second.second;
|
||||
else
|
||||
return Offset();
|
||||
}
|
||||
|
||||
Vertex_handle get_original_vertex(Vertex_handle vh) const
|
||||
{
|
||||
if(is_1_cover())
|
||||
return vh;
|
||||
|
||||
Virtual_vertex_map_it it = virtual_vertices.find(vh);
|
||||
if(it != virtual_vertices.end())
|
||||
return it->second.first;
|
||||
else
|
||||
return vh;
|
||||
}
|
||||
|
||||
Offset combine_offsets(const Offset& o_c, const Offset& o_t) const
|
||||
{
|
||||
Offset o_ct(_cover[0]*o_t.x(), _cover[1]*o_t.y(), _cover[2]*o_t.z());
|
||||
return o_c + o_ct;
|
||||
}
|
||||
|
||||
// These functions give the pair (vertex, offset) that corresponds to the
|
||||
// i-th vertex of cell ch or vertex vh, respectively.
|
||||
void get_vertex(Cell_handle ch, int i, Vertex_handle& vh, Offset& off) const;
|
||||
void get_vertex(Vertex_handle vh_i, Vertex_handle& vh, Offset& off) const;
|
||||
|
||||
protected:
|
||||
// Auxiliary functions
|
||||
Cell_handle get_cell(const Vertex_handle* vh) const;
|
||||
|
||||
template<class Conflict_tester>
|
||||
Offset get_location_offset(const Conflict_tester& tester,
|
||||
Cell_handle c) const;
|
||||
|
||||
template<class Conflict_tester>
|
||||
Offset get_location_offset(const Conflict_tester& tester,
|
||||
Cell_handle c, bool& found) const;
|
||||
|
||||
Offset neighbor_offset(Cell_handle ch, int i, Cell_handle nb) const;
|
||||
|
||||
public:
|
||||
Offset neighbor_offset(Cell_handle ch, int i) const
|
||||
{
|
||||
return neighbor_offset(ch, i, ch->neighbor(i));
|
||||
}
|
||||
|
||||
protected:
|
||||
/** @name Friends */
|
||||
friend std::istream& operator>> <>
|
||||
|
|
@ -1788,51 +1979,6 @@ protected:
|
|||
return construct_periodic_point(p);
|
||||
}
|
||||
|
||||
public:
|
||||
bool is_canonical(const Facet& f) const
|
||||
{
|
||||
if(number_of_sheets() == CGAL::make_array(1,1,1))
|
||||
return true;
|
||||
|
||||
Offset cell_off0 = int_to_off(f.first->offset((f.second+1)&3));
|
||||
Offset cell_off1 = int_to_off(f.first->offset((f.second+2)&3));
|
||||
Offset cell_off2 = int_to_off(f.first->offset((f.second+3)&3));
|
||||
Offset diff_off((cell_off0.x() == 1
|
||||
&& cell_off1.x() == 1
|
||||
&& cell_off2.x() == 1) ? -1 : 0,
|
||||
(cell_off0.y() == 1
|
||||
&& cell_off1.y() == 1
|
||||
&& cell_off2.y() == 1) ? -1 : 0,
|
||||
(cell_off0.z() == 1
|
||||
&& cell_off1.z() == 1
|
||||
&& cell_off2.z() == 1) ? -1 : 0);
|
||||
Offset off0 = combine_offsets(get_offset(f.first, (f.second+1)&3), diff_off);
|
||||
Offset off1 = combine_offsets(get_offset(f.first, (f.second+2)&3), diff_off);
|
||||
Offset off2 = combine_offsets(get_offset(f.first, (f.second+3)&3), diff_off);
|
||||
|
||||
// If there is one offset with entries larger than 1 then we are
|
||||
// talking about a vertex that is too far away from the original
|
||||
// domain to belong to a canonical triangle.
|
||||
if(off0.x() > 1) return false;
|
||||
if(off0.y() > 1) return false;
|
||||
if(off0.z() > 1) return false;
|
||||
if(off1.x() > 1) return false;
|
||||
if(off1.y() > 1) return false;
|
||||
if(off1.z() > 1) return false;
|
||||
if(off2.x() > 1) return false;
|
||||
if(off2.y() > 1) return false;
|
||||
if(off2.z() > 1) return false;
|
||||
|
||||
// If there is one direction of space for which all offsets are
|
||||
// non-zero then the edge is not canonical because we can
|
||||
// take the copy closer towards the origin in that direction.
|
||||
int offx = off0.x() & off1.x() & off2.x();
|
||||
int offy = off0.y() & off1.y() & off2.y();
|
||||
int offz = off0.z() & off1.z() & off2.z();
|
||||
|
||||
return (offx == 0 && offy == 0 && offz == 0);
|
||||
}
|
||||
|
||||
protected:
|
||||
template <class ConstructCircumcenter>
|
||||
bool canonical_dual_segment(Cell_handle c, int i, Periodic_segment_3& ps,
|
||||
|
|
@ -3310,7 +3456,7 @@ periodic_remove(Vertex_handle v,
|
|||
nr_vec.push_back(boost::make_tuple(o_ch,o_i,new_ch));
|
||||
nr_vec.push_back(boost::make_tuple(new_ch,i_i,o_ch));
|
||||
|
||||
// for the other faces check, if they can also be glued
|
||||
// for the other facets check, if they can also be glued
|
||||
for(unsigned int i = 0; i < 4; i++) {
|
||||
if(i != i_i) {
|
||||
Facet f = std::pair<Cell_handle,int>(new_ch,i);
|
||||
|
|
@ -3322,7 +3468,7 @@ periodic_remove(Vertex_handle v,
|
|||
std::swap(vt.second,vt.third);
|
||||
outer_map[vt]= f;
|
||||
} else {
|
||||
// glue the faces
|
||||
// glue the facets
|
||||
typename Vertex_triple_Facet_map::value_type o_vt_f_pair2 = *oit2;
|
||||
Cell_handle o_ch2 = o_vt_f_pair2.second.first;
|
||||
int o_i2 = o_vt_f_pair2.second.second;
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ public:
|
|||
Iterator_type it = T::STORED)
|
||||
: _t(t), pos(_t->cells_begin()), _it(it), _off(0) {
|
||||
if (_it == T::UNIQUE || _it == T::UNIQUE_COVER_DOMAIN) {
|
||||
while (pos != _t->cells_end() && !is_canonical() )
|
||||
while (pos != _t->cells_end() && !_t->is_canonical(pos) )
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
|
@ -79,7 +79,7 @@ public:
|
|||
++pos;
|
||||
break;
|
||||
case T::UNIQUE:
|
||||
do { ++pos; } while (pos != _t->cells_end() && !is_canonical());
|
||||
do { ++pos; } while (pos != _t->cells_end() && !_t->is_canonical(pos));
|
||||
break;
|
||||
case T::STORED_COVER_DOMAIN:
|
||||
case T::UNIQUE_COVER_DOMAIN:
|
||||
|
|
@ -97,7 +97,7 @@ public:
|
|||
--pos;
|
||||
break;
|
||||
case T::UNIQUE:
|
||||
do { --pos; } while (pos != _t->cells_begin() && !is_canonical());
|
||||
do { --pos; } while (pos != _t->cells_begin() && !_t->is_canonical(pos));
|
||||
break;
|
||||
case T::STORED_COVER_DOMAIN:
|
||||
case T::UNIQUE_COVER_DOMAIN:
|
||||
|
|
@ -156,42 +156,6 @@ private:
|
|||
mutable Periodic_tetrahedron periodic_tetrahedron; // current tetrahedron.
|
||||
|
||||
private:
|
||||
// check whether pos points onto a unique edge or not.
|
||||
// If we are computing in 1-sheeted covering this should
|
||||
// always be true.
|
||||
bool is_canonical() {
|
||||
// fetch all offsets
|
||||
Offset off0, off1, off2, off3;
|
||||
get_edge_offsets(off0, off1, off2, off3);
|
||||
|
||||
if (_t->number_of_sheets() != make_array(1,1,1)) {
|
||||
// If there is one offset with entries larger than 1 then we are
|
||||
// talking about a vertex that is too far away from the original
|
||||
// domain to belong to a canonical triangle.
|
||||
if (off0.x() > 1) return false;
|
||||
if (off0.y() > 1) return false;
|
||||
if (off0.z() > 1) return false;
|
||||
if (off1.x() > 1) return false;
|
||||
if (off1.y() > 1) return false;
|
||||
if (off1.z() > 1) return false;
|
||||
if (off2.x() > 1) return false;
|
||||
if (off2.y() > 1) return false;
|
||||
if (off2.z() > 1) return false;
|
||||
if (off3.x() > 1) return false;
|
||||
if (off3.y() > 1) return false;
|
||||
if (off3.z() > 1) return false;
|
||||
}
|
||||
|
||||
// If there is one direction of space for which all offsets are
|
||||
// non-zero then the edge is not canonical because we can
|
||||
// take the copy closer towards the origin in that direction.
|
||||
int offx = off0.x() & off1.x() & off2.x() & off3.x();
|
||||
int offy = off0.y() & off1.y() & off2.y() & off3.y();
|
||||
int offz = off0.z() & off1.z() & off2.z() & off3.z();
|
||||
|
||||
return (offx == 0 && offy == 0 && offz == 0);
|
||||
}
|
||||
|
||||
// Artificial incrementation function that takes periodic
|
||||
// copies into account.
|
||||
void increment_domain() {
|
||||
|
|
@ -200,7 +164,7 @@ private:
|
|||
if (_off == off) {
|
||||
_off = 0;
|
||||
do { ++pos; } while (_it == T::UNIQUE_COVER_DOMAIN
|
||||
&& pos != _t->cells_end() && !is_canonical());
|
||||
&& pos != _t->cells_end() && !_t->is_canonical(pos));
|
||||
} else {
|
||||
do {
|
||||
++_off;
|
||||
|
|
@ -214,7 +178,7 @@ private:
|
|||
void decrement_domain() {
|
||||
if (_off == 0) {
|
||||
if (pos == _t->cells_begin()) return;
|
||||
do { --pos; } while (_it == T::UNIQUE_COVER_DOMAIN && !is_canonical());
|
||||
do { --pos; } while (_it == T::UNIQUE_COVER_DOMAIN && !_t->is_canonical(pos));
|
||||
_off = get_drawing_offsets();
|
||||
} else {
|
||||
int off = get_drawing_offsets();
|
||||
|
|
@ -225,32 +189,6 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
// Get the canonicalized offsets of an edge.
|
||||
// This works in any cover that is encoded in _t->combine_offsets
|
||||
void get_edge_offsets(Offset &off0, Offset &off1,
|
||||
Offset &off2, Offset &off3) const {
|
||||
Offset cell_off0 = _t->int_to_off(pos->offset(0));
|
||||
Offset cell_off1 = _t->int_to_off(pos->offset(1));
|
||||
Offset cell_off2 = _t->int_to_off(pos->offset(2));
|
||||
Offset cell_off3 = _t->int_to_off(pos->offset(3));
|
||||
Offset diff_off((cell_off0.x() == 1
|
||||
&& cell_off1.x() == 1
|
||||
&& cell_off2.x() == 1
|
||||
&& cell_off3.x() == 1)?-1:0,
|
||||
(cell_off0.y() == 1
|
||||
&& cell_off1.y() == 1
|
||||
&& cell_off2.y() == 1
|
||||
&& cell_off3.y() == 1)?-1:0,
|
||||
(cell_off0.z() == 1
|
||||
&& cell_off1.z() == 1
|
||||
&& cell_off2.z() == 1
|
||||
&& cell_off3.z() == 1)?-1:0);
|
||||
off0 = _t->combine_offsets(_t->get_offset(pos,0), diff_off);
|
||||
off1 = _t->combine_offsets(_t->get_offset(pos,1), diff_off);
|
||||
off2 = _t->combine_offsets(_t->get_offset(pos,2), diff_off);
|
||||
off3 = _t->combine_offsets(_t->get_offset(pos,3), diff_off);
|
||||
}
|
||||
|
||||
// return an integer that encodes the translations which have to be
|
||||
// applied to the edge *pos
|
||||
int get_drawing_offsets() {
|
||||
|
|
@ -262,7 +200,7 @@ private:
|
|||
// internally stored inside the cell telling us that this cell
|
||||
// wraps around the domain.
|
||||
if (_it == T::UNIQUE_COVER_DOMAIN)
|
||||
get_edge_offsets(off0,off1,off2,off3);
|
||||
_t->get_offsets(pos, off0, off1, off2, off3);
|
||||
else {
|
||||
CGAL_assertion(_it == T::STORED_COVER_DOMAIN);
|
||||
off0 = _t->int_to_off(pos->offset(0));
|
||||
|
|
@ -303,7 +241,7 @@ private:
|
|||
Periodic_tetrahedron construct_periodic_tetrahedron() const {
|
||||
CGAL_assertion(pos != typename T::Cell_handle());
|
||||
Offset off0, off1, off2, off3;
|
||||
get_edge_offsets(off0, off1, off2, off3);
|
||||
_t->get_offsets(pos, off0, off1, off2, off3);
|
||||
Offset transl_off = Offset((((_off>>2)&1)==1 ? -1:0),
|
||||
(((_off>>1)&1)==1 ? -1:0),
|
||||
(( _off &1)==1 ? -1:0));
|
||||
|
|
@ -369,7 +307,7 @@ public:
|
|||
Iterator_type it = T::STORED)
|
||||
: _t(t), pos(_t->facets_begin()), _it(it), _off(0) {
|
||||
if (_it == T::UNIQUE || _it == T::UNIQUE_COVER_DOMAIN) {
|
||||
while (pos != _t->facets_end() && !is_canonical() )
|
||||
while (pos != _t->facets_end() && !_t->is_canonical(*pos) )
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
|
@ -385,7 +323,7 @@ public:
|
|||
++pos;
|
||||
break;
|
||||
case T::UNIQUE:
|
||||
do { ++pos; } while (pos != _t->facets_end() && !is_canonical());
|
||||
do { ++pos; } while (pos != _t->facets_end() && !_t->is_canonical(*pos));
|
||||
break;
|
||||
case T::STORED_COVER_DOMAIN:
|
||||
case T::UNIQUE_COVER_DOMAIN:
|
||||
|
|
@ -403,7 +341,7 @@ public:
|
|||
--pos;
|
||||
break;
|
||||
case T::UNIQUE:
|
||||
do { --pos; } while (pos != _t->facets_begin() && !is_canonical());
|
||||
do { --pos; } while (pos != _t->facets_begin() && !_t->is_canonical(*pos));
|
||||
break;
|
||||
case T::STORED_COVER_DOMAIN:
|
||||
case T::UNIQUE_COVER_DOMAIN:
|
||||
|
|
@ -462,39 +400,6 @@ private:
|
|||
mutable Periodic_triangle periodic_triangle; // current segment.
|
||||
|
||||
private:
|
||||
// check whether pos points onto a unique edge or not.
|
||||
// If we are computing in 1-sheeted covering this should
|
||||
// always be true.
|
||||
bool is_canonical() {
|
||||
// fetch all offsets
|
||||
Offset off0, off1, off2;
|
||||
get_edge_offsets(off0, off1, off2);
|
||||
|
||||
if (_t->number_of_sheets() != make_array(1,1,1)) {
|
||||
// If there is one offset with entries larger than 1 then we are
|
||||
// talking about a vertex that is too far away from the original
|
||||
// domain to belong to a canonical triangle.
|
||||
if (off0.x() > 1) return false;
|
||||
if (off0.y() > 1) return false;
|
||||
if (off0.z() > 1) return false;
|
||||
if (off1.x() > 1) return false;
|
||||
if (off1.y() > 1) return false;
|
||||
if (off1.z() > 1) return false;
|
||||
if (off2.x() > 1) return false;
|
||||
if (off2.y() > 1) return false;
|
||||
if (off2.z() > 1) return false;
|
||||
}
|
||||
|
||||
// If there is one direction of space for which all offsets are
|
||||
// non-zero then the edge is not canonical because we can
|
||||
// take the copy closer towards the origin in that direction.
|
||||
int offx = off0.x() & off1.x() & off2.x();
|
||||
int offy = off0.y() & off1.y() & off2.y();
|
||||
int offz = off0.z() & off1.z() & off2.z();
|
||||
|
||||
return (offx == 0 && offy == 0 && offz == 0);
|
||||
}
|
||||
|
||||
// Artificial incrementation function that takes periodic
|
||||
// copies into account.
|
||||
void increment_domain() {
|
||||
|
|
@ -503,7 +408,7 @@ private:
|
|||
if (_off == off) {
|
||||
_off = 0;
|
||||
do { ++pos; } while (_it == T::UNIQUE_COVER_DOMAIN
|
||||
&& pos != _t->facets_end() && !is_canonical());
|
||||
&& pos != _t->facets_end() && !_t->is_canonical(*pos));
|
||||
} else {
|
||||
do {
|
||||
++_off;
|
||||
|
|
@ -517,7 +422,7 @@ private:
|
|||
void decrement_domain() {
|
||||
if (_off == 0) {
|
||||
if (pos == _t->facets_begin()) return;
|
||||
do { --pos; } while (_it == T::UNIQUE_COVER_DOMAIN && !is_canonical());
|
||||
do { --pos; } while (_it == T::UNIQUE_COVER_DOMAIN && !_t->is_canonical(*pos));
|
||||
_off = get_drawing_offsets();
|
||||
} else {
|
||||
int off = get_drawing_offsets();
|
||||
|
|
@ -528,32 +433,6 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
// Get the canonicalized offsets of an edge.
|
||||
// This works in any cover that is encoded in _t->combine_offsets
|
||||
void get_edge_offsets(Offset &off0, Offset &off1, Offset &off2) const {
|
||||
Offset cell_off0 = _t->int_to_off(pos->first->offset((pos->second+1)&3));
|
||||
Offset cell_off1 = _t->int_to_off(pos->first->offset((pos->second+2)&3));
|
||||
Offset cell_off2 = _t->int_to_off(pos->first->offset((pos->second+3)&3));
|
||||
Offset diff_off((cell_off0.x() == 1
|
||||
&& cell_off1.x() == 1
|
||||
&& cell_off2.x() == 1)?-1:0,
|
||||
(cell_off0.y() == 1
|
||||
&& cell_off1.y() == 1
|
||||
&& cell_off2.y() == 1)?-1:0,
|
||||
(cell_off0.z() == 1
|
||||
&& cell_off1.z() == 1
|
||||
&& cell_off2.z() == 1)?-1:0);
|
||||
off0 = _t->combine_offsets(_t->get_offset(pos->first,
|
||||
(pos->second+1)&3),
|
||||
diff_off);
|
||||
off1 = _t->combine_offsets(_t->get_offset(pos->first,
|
||||
(pos->second+2)&3),
|
||||
diff_off);
|
||||
off2 = _t->combine_offsets(_t->get_offset(pos->first,
|
||||
(pos->second+3)&3),
|
||||
diff_off);
|
||||
}
|
||||
|
||||
// return an integer that encodes the translations which have to be
|
||||
// applied to the edge *pos
|
||||
int get_drawing_offsets() {
|
||||
|
|
@ -565,7 +444,7 @@ private:
|
|||
// internally stored inside the cell telling us that this cell
|
||||
// wraps around the domain.
|
||||
if (_it == T::UNIQUE_COVER_DOMAIN)
|
||||
get_edge_offsets(off0,off1,off2);
|
||||
_t->get_offsets(*pos, off0, off1, off2);
|
||||
else {
|
||||
CGAL_assertion(_it == T::STORED_COVER_DOMAIN);
|
||||
off0 = _t->int_to_off(pos->first->offset((pos->second+1)&3));
|
||||
|
|
@ -596,7 +475,7 @@ private:
|
|||
Periodic_triangle construct_periodic_triangle() const {
|
||||
CGAL_assertion(pos->first != typename T::Cell_handle());
|
||||
Offset off0, off1, off2;
|
||||
get_edge_offsets(off0, off1, off2);
|
||||
_t->get_offsets(*pos, off0, off1, off2);
|
||||
Offset transl_off = Offset((((_off>>2)&1)==1 ? -1:0),
|
||||
(((_off>>1)&1)==1 ? -1:0),
|
||||
(( _off &1)==1 ? -1:0));
|
||||
|
|
@ -659,7 +538,7 @@ public:
|
|||
Iterator_type it = T::STORED)
|
||||
: _t(t), pos(_t->edges_begin()), _it(it), _off(0) {
|
||||
if (_it == T::UNIQUE || _it == T::UNIQUE_COVER_DOMAIN) {
|
||||
while (pos != _t->edges_end() && !is_canonical() )
|
||||
while (pos != _t->edges_end() && !_t->is_canonical(*pos) )
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
|
@ -675,7 +554,7 @@ public:
|
|||
++pos;
|
||||
break;
|
||||
case T::UNIQUE:
|
||||
do { ++pos; } while (pos != _t->edges_end() && !is_canonical());
|
||||
do { ++pos; } while (pos != _t->edges_end() && !_t->is_canonical(*pos));
|
||||
break;
|
||||
case T::STORED_COVER_DOMAIN:
|
||||
case T::UNIQUE_COVER_DOMAIN:
|
||||
|
|
@ -693,7 +572,7 @@ public:
|
|||
--pos;
|
||||
break;
|
||||
case T::UNIQUE:
|
||||
do { --pos; } while (pos != _t->edges_begin() && !is_canonical());
|
||||
do { --pos; } while (pos != _t->edges_begin() && !_t->is_canonical(*pos));
|
||||
break;
|
||||
case T::STORED_COVER_DOMAIN:
|
||||
case T::UNIQUE_COVER_DOMAIN:
|
||||
|
|
@ -751,36 +630,6 @@ private:
|
|||
mutable Periodic_segment periodic_segment; // current segment.
|
||||
|
||||
private:
|
||||
// check whether pos points onto a unique edge or not.
|
||||
// If we are computing in 1-sheeted covering this should
|
||||
// always be true.
|
||||
bool is_canonical() {
|
||||
// fetch all offsets
|
||||
Offset off0, off1;
|
||||
get_edge_offsets(off0, off1);
|
||||
|
||||
if (_t->number_of_sheets() != make_array(1,1,1)) {
|
||||
// If there is one offset with entries larger than 1 then we are
|
||||
// talking about a vertex that is too far away from the original
|
||||
// domain to belong to a canonical triangle.
|
||||
if (off0.x() > 1) return false;
|
||||
if (off0.y() > 1) return false;
|
||||
if (off0.z() > 1) return false;
|
||||
if (off1.x() > 1) return false;
|
||||
if (off1.y() > 1) return false;
|
||||
if (off1.z() > 1) return false;
|
||||
}
|
||||
|
||||
// If there is one direction of space for which all offsets are
|
||||
// non-zero then the edge is not canonical because we can
|
||||
// take the copy closer towards the origin in that direction.
|
||||
int offx = off0.x() & off1.x();
|
||||
int offy = off0.y() & off1.y();
|
||||
int offz = off0.z() & off1.z();
|
||||
|
||||
return (offx == 0 && offy == 0 && offz == 0);
|
||||
}
|
||||
|
||||
// Artificial incrementation function that takes periodic
|
||||
// copies into account.
|
||||
void increment_domain() {
|
||||
|
|
@ -789,7 +638,7 @@ private:
|
|||
if (_off == off) {
|
||||
_off = 0;
|
||||
do { ++pos; } while (_it == T::UNIQUE_COVER_DOMAIN
|
||||
&& pos != _t->edges_end() && !is_canonical());
|
||||
&& pos != _t->edges_end() && !_t->is_canonical(*pos));
|
||||
} else {
|
||||
do {
|
||||
++_off;
|
||||
|
|
@ -803,7 +652,7 @@ private:
|
|||
void decrement_domain() {
|
||||
if (_off == 0) {
|
||||
if (pos == _t->edges_begin()) return;
|
||||
do { --pos; } while (_it == T::UNIQUE_COVER_DOMAIN && !is_canonical());
|
||||
do { --pos; } while (_it == T::UNIQUE_COVER_DOMAIN && !_t->is_canonical(*pos));
|
||||
_off = get_drawing_offsets();
|
||||
} else {
|
||||
int off = get_drawing_offsets();
|
||||
|
|
@ -814,20 +663,6 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
// Get the canonicalized offsets of an edge.
|
||||
// This works in any cover that is encoded in _t->combine_offsets
|
||||
void get_edge_offsets(Offset &off0, Offset &off1) const {
|
||||
Offset cell_off0 = _t->int_to_off(pos->first->offset(pos->second));
|
||||
Offset cell_off1 = _t->int_to_off(pos->first->offset(pos->third));
|
||||
Offset diff_off((cell_off0.x()==1 && cell_off1.x()==1)?-1:0,
|
||||
(cell_off0.y()==1 && cell_off1.y()==1)?-1:0,
|
||||
(cell_off0.z()==1 && cell_off1.z()==1)?-1:0);
|
||||
off0 = _t->combine_offsets(_t->get_offset(pos->first,pos->second),
|
||||
diff_off);
|
||||
off1 = _t->combine_offsets(_t->get_offset(pos->first,pos->third),
|
||||
diff_off);
|
||||
}
|
||||
|
||||
// return an integer that encodes the translations which have to be
|
||||
// applied to the edge *pos
|
||||
int get_drawing_offsets() {
|
||||
|
|
@ -839,7 +674,7 @@ private:
|
|||
// internally stored inside the cell telling us that this cell
|
||||
// wraps around the domain.
|
||||
if (_it == T::UNIQUE_COVER_DOMAIN)
|
||||
get_edge_offsets(off0,off1);
|
||||
_t->get_offsets(*pos, off0, off1);
|
||||
else {
|
||||
CGAL_assertion(_it == T::STORED_COVER_DOMAIN);
|
||||
off0 = _t->int_to_off(pos->first->offset(pos->second));
|
||||
|
|
@ -859,7 +694,7 @@ private:
|
|||
Periodic_segment construct_periodic_segment() const {
|
||||
CGAL_assertion(pos->first != typename T::Cell_handle());
|
||||
Offset off0, off1;
|
||||
get_edge_offsets(off0, off1);
|
||||
_t->get_offsets(*pos, off0, off1);
|
||||
Offset transl_off = Offset((((_off>>2)&1)==1 ? -1:0),
|
||||
(((_off>>1)&1)==1 ? -1:0),
|
||||
(( _off &1)==1 ? -1:0));
|
||||
|
|
@ -918,7 +753,7 @@ public:
|
|||
Iterator_type it = T::STORED)
|
||||
: _t(t), pos(_t->vertices_begin()), _it(it) {
|
||||
if (_it == T::UNIQUE || _it == T::UNIQUE_COVER_DOMAIN) {
|
||||
while (pos != _t->vertices_end() && !is_canonical() )
|
||||
while (pos != _t->vertices_end() && !_t->is_canonical(pos) )
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
|
@ -936,7 +771,7 @@ public:
|
|||
break;
|
||||
case T::UNIQUE:
|
||||
case T::UNIQUE_COVER_DOMAIN:
|
||||
do { ++pos; } while (pos != _t->vertices_end() && !is_canonical());
|
||||
do { ++pos; } while (pos != _t->vertices_end() && !_t->is_canonical(pos));
|
||||
break;
|
||||
default:
|
||||
CGAL_assertion(false);
|
||||
|
|
@ -952,7 +787,7 @@ public:
|
|||
break;
|
||||
case T::UNIQUE:
|
||||
case T::UNIQUE_COVER_DOMAIN:
|
||||
do { --pos; } while (pos != _t->vertices_begin() && !is_canonical());
|
||||
do { --pos; } while (pos != _t->vertices_begin() && !_t->is_canonical(pos));
|
||||
break;
|
||||
default:
|
||||
CGAL_assertion(false);
|
||||
|
|
@ -1009,13 +844,6 @@ private:
|
|||
mutable Periodic_point periodic_point; // current point.
|
||||
|
||||
private:
|
||||
// check whether pos points onto a vertex inside the original
|
||||
// domain. If we are computing in 1-sheeted covering this should
|
||||
// always be true.
|
||||
bool is_canonical() {
|
||||
return (_t->get_offset(pos) == Offset(0,0,0));
|
||||
}
|
||||
|
||||
Periodic_point construct_periodic_point() const {
|
||||
CGAL_assertion(pos != typename T::Vertex_handle());
|
||||
Offset off = _t->get_offset(pos);
|
||||
|
|
@ -1031,9 +859,54 @@ public:
|
|||
Domain_tester() {}
|
||||
Domain_tester(const T *tr) : t(tr) {}
|
||||
|
||||
bool operator()(const typename T::Vertex_iterator & v) const {
|
||||
return (t->get_offset(v) != typename T::Offset(0,0,0));
|
||||
bool operator()(const typename T::Cell_iterator c) const
|
||||
{
|
||||
return !t->is_canonical(c);
|
||||
}
|
||||
|
||||
bool operator()(const typename T::Facet_iterator f) const
|
||||
{
|
||||
return !t->is_canonical(*f);
|
||||
}
|
||||
|
||||
bool operator()(const typename T::Edge_iterator e) const
|
||||
{
|
||||
return !t->is_canonical(*e);
|
||||
}
|
||||
|
||||
bool operator()(const typename T::Vertex_iterator v) const
|
||||
{
|
||||
return !t->is_canonical(v);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Iterates over the canonical cells in a periodic triangulation.
|
||||
// Derives from Filter_iterator in order to add a conversion to handle
|
||||
//
|
||||
// Comments:
|
||||
// When computing in 1-sheeted covering, there will be no difference
|
||||
// between a normal Cell_iterator and this iterator
|
||||
template <class T>
|
||||
class Periodic_3_triangulation_unique_cell_iterator_3
|
||||
: public Filter_iterator<typename T::Cell_iterator, Domain_tester<T> >
|
||||
{
|
||||
typedef typename T::Cell_handle Cell_handle;
|
||||
typedef typename T::Cell_iterator Cell_iterator;
|
||||
|
||||
typedef Filter_iterator<Cell_iterator, Domain_tester<T> > Base;
|
||||
typedef Periodic_3_triangulation_unique_cell_iterator_3 Self;
|
||||
|
||||
public:
|
||||
Periodic_3_triangulation_unique_cell_iterator_3() : Base() {}
|
||||
Periodic_3_triangulation_unique_cell_iterator_3(const Base &b) : Base(b) {}
|
||||
|
||||
Self & operator++() { Base::operator++(); return *this; }
|
||||
Self & operator--() { Base::operator--(); return *this; }
|
||||
Self operator++(int) { Self tmp(*this); ++(*this); return tmp; }
|
||||
Self operator--(int) { Self tmp(*this); --(*this); return tmp; }
|
||||
|
||||
operator Cell_handle() const { return Base::base(); }
|
||||
};
|
||||
|
||||
// Iterates over the vertices in a periodic triangulation that are
|
||||
|
|
@ -1045,15 +918,15 @@ public:
|
|||
// between a normal Vertex_iterator and this iterator
|
||||
template <class T>
|
||||
class Periodic_3_triangulation_unique_vertex_iterator_3
|
||||
: public Filter_iterator<typename T::Vertex_iterator, Domain_tester<T> > {
|
||||
|
||||
: public Filter_iterator<typename T::Vertex_iterator, Domain_tester<T> >
|
||||
{
|
||||
typedef typename T::Vertex_handle Vertex_handle;
|
||||
typedef typename T::Vertex_iterator Vertex_iterator;
|
||||
|
||||
typedef Filter_iterator<Vertex_iterator, Domain_tester<T> > Base;
|
||||
typedef Periodic_3_triangulation_unique_vertex_iterator_3 Self;
|
||||
public:
|
||||
|
||||
public:
|
||||
Periodic_3_triangulation_unique_vertex_iterator_3() : Base() {}
|
||||
Periodic_3_triangulation_unique_vertex_iterator_3(const Base &b) : Base(b) {}
|
||||
|
||||
|
|
@ -1065,6 +938,62 @@ public:
|
|||
operator Vertex_handle() const { return Base::base(); }
|
||||
};
|
||||
|
||||
} //namespace CGAL
|
||||
// Iterates over the canonical edges in a periodic triangulation.
|
||||
// Derives from Filter_iterator in order to add a conversion to handle
|
||||
//
|
||||
// Comments:
|
||||
// When computing in 1-sheeted covering, there will be no difference
|
||||
// between a normal Edge_iterator and this iterator
|
||||
template <class T>
|
||||
class Periodic_3_triangulation_unique_edge_iterator_3
|
||||
: public Filter_iterator<typename T::Edge_iterator, Domain_tester<T> >
|
||||
{
|
||||
typedef typename T::Edge Edge;
|
||||
typedef typename T::Edge_iterator Edge_iterator;
|
||||
|
||||
typedef Filter_iterator<Edge_iterator, Domain_tester<T> > Base;
|
||||
typedef Periodic_3_triangulation_unique_edge_iterator_3 Self;
|
||||
|
||||
public:
|
||||
Periodic_3_triangulation_unique_edge_iterator_3() : Base() {}
|
||||
Periodic_3_triangulation_unique_edge_iterator_3(const Base &b) : Base(b) {}
|
||||
|
||||
Self & operator++() { Base::operator++(); return *this; }
|
||||
Self & operator--() { Base::operator--(); return *this; }
|
||||
Self operator++(int) { Self tmp(*this); ++(*this); return tmp; }
|
||||
Self operator--(int) { Self tmp(*this); --(*this); return tmp; }
|
||||
|
||||
operator Edge() const { return Base::base(); }
|
||||
};
|
||||
|
||||
// Iterates over the canonical facets in a periodic triangulation.
|
||||
// Derives from Filter_iterator in order to add a conversion to handle
|
||||
//
|
||||
// Comments:
|
||||
// When computing in 1-sheeted covering, there will be no difference
|
||||
// between a normal Facet_iterator and this iterator
|
||||
template <class T>
|
||||
class Periodic_3_triangulation_unique_facet_iterator_3
|
||||
: public Filter_iterator<typename T::Facet_iterator, Domain_tester<T> >
|
||||
{
|
||||
typedef typename T::Facet Facet;
|
||||
typedef typename T::Facet_iterator Facet_iterator;
|
||||
|
||||
typedef Filter_iterator<Facet_iterator, Domain_tester<T> > Base;
|
||||
typedef Periodic_3_triangulation_unique_facet_iterator_3 Self;
|
||||
public:
|
||||
|
||||
Periodic_3_triangulation_unique_facet_iterator_3() : Base() {}
|
||||
Periodic_3_triangulation_unique_facet_iterator_3(const Base &b) : Base(b) {}
|
||||
|
||||
Self & operator++() { Base::operator++(); return *this; }
|
||||
Self & operator--() { Base::operator--(); return *this; }
|
||||
Self operator++(int) { Self tmp(*this); ++(*this); return tmp; }
|
||||
Self operator--(int) { Self tmp(*this); --(*this); return tmp; }
|
||||
|
||||
operator Facet() const { return Base::base(); }
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_PERIODIC_3_TRIANGULATION_ITERATORS_3_H
|
||||
|
|
|
|||
|
|
@ -86,32 +86,158 @@ _test_unique_vertex_iterator( const Triangulation &T )
|
|||
size_type n = 0;
|
||||
|
||||
for (Unique_vertex_iterator ovit = T.unique_vertices_begin();
|
||||
ovit != T.unique_vertices_end(); ++ovit)
|
||||
{
|
||||
Vertex_handle vh = ovit; // Test the conversion.
|
||||
n++;
|
||||
const Vertex & v = *ovit; // Test operator*;
|
||||
Cell_handle c = ovit->cell(); // Test operator->;
|
||||
(void) vh;
|
||||
(void) v;
|
||||
(void) c;
|
||||
}
|
||||
ovit != T.unique_vertices_end(); ++ovit)
|
||||
{
|
||||
Vertex_handle vh = ovit; // Test the conversion.
|
||||
++n;
|
||||
const Vertex & v = *ovit; // Test operator*;
|
||||
Cell_handle c = ovit->cell(); // Test operator->;
|
||||
(void) vh;
|
||||
(void) v;
|
||||
(void) c;
|
||||
}
|
||||
assert( n == T.number_of_vertices() );
|
||||
|
||||
// Test Backward-ness of the iterators.
|
||||
n=0;
|
||||
n = 0;
|
||||
for (Unique_vertex_iterator ovit = T.unique_vertices_end();
|
||||
ovit != T.unique_vertices_begin(); --ovit)
|
||||
{
|
||||
Vertex_handle vh = ovit; // Test the conversion.
|
||||
(void) vh;
|
||||
n++;
|
||||
}
|
||||
ovit != T.unique_vertices_begin(); --ovit)
|
||||
{
|
||||
Vertex_handle vh = ovit; // Test the conversion.
|
||||
(void) vh;
|
||||
++n;
|
||||
}
|
||||
assert( n == T.number_of_vertices() );
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
template < class Triangulation >
|
||||
typename Triangulation::size_type
|
||||
_test_unique_edge_iterator( const Triangulation &T )
|
||||
{
|
||||
typedef typename Triangulation::size_type size_type;
|
||||
typedef typename Triangulation::Edge Edge;
|
||||
typedef typename Triangulation::Cell_handle Cell_handle;
|
||||
typedef typename Triangulation::Unique_edge_iterator
|
||||
Unique_edge_iterator;
|
||||
|
||||
size_type n = 0;
|
||||
|
||||
for (Unique_edge_iterator oeit = T.unique_edges_begin();
|
||||
oeit != T.unique_edges_end(); ++oeit)
|
||||
{
|
||||
++n;
|
||||
const Edge& e = *oeit; // Test operator*;
|
||||
Cell_handle c = oeit->first; // Test operator->;
|
||||
assert(c != Cell_handle());
|
||||
(void) e;
|
||||
(void) c;
|
||||
}
|
||||
assert( n == T.number_of_edges() );
|
||||
|
||||
// Test Backward-ness of the iterators.
|
||||
n = 0;
|
||||
for (Unique_edge_iterator oeit = T.unique_edges_end();
|
||||
oeit != T.unique_edges_begin(); --oeit)
|
||||
{
|
||||
++n;
|
||||
}
|
||||
assert( n == T.number_of_edges() );
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
template < class Triangulation >
|
||||
typename Triangulation::size_type
|
||||
_test_unique_facet_iterator( const Triangulation &T )
|
||||
{
|
||||
typedef typename Triangulation::size_type size_type;
|
||||
typedef typename Triangulation::Facet Facet;
|
||||
typedef typename Triangulation::Cell_handle Cell_handle;
|
||||
typedef typename Triangulation::Unique_facet_iterator
|
||||
Unique_facet_iterator;
|
||||
|
||||
size_type n = 0;
|
||||
|
||||
for (Unique_facet_iterator ofit = T.unique_facets_begin();
|
||||
ofit != T.unique_facets_end(); ++ofit)
|
||||
{
|
||||
++n;
|
||||
const Facet& f = *ofit; // Test operator*;
|
||||
Cell_handle c = ofit->first; // Test operator->;
|
||||
assert(c != Cell_handle());
|
||||
(void) f;
|
||||
(void) c;
|
||||
}
|
||||
assert( n == T.number_of_facets() );
|
||||
|
||||
// Test Backward-ness of the iterators.
|
||||
n = 0;
|
||||
for (Unique_facet_iterator ofit = T.unique_facets_end();
|
||||
ofit != T.unique_facets_begin(); --ofit)
|
||||
{
|
||||
++n;
|
||||
}
|
||||
assert( n == T.number_of_facets() );
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
template < class Triangulation >
|
||||
typename Triangulation::size_type
|
||||
_test_unique_cell_iterator( const Triangulation &T )
|
||||
{
|
||||
typedef typename Triangulation::size_type size_type;
|
||||
typedef typename Triangulation::Cell Cell;
|
||||
typedef typename Triangulation::Vertex_handle Vertex_handle;
|
||||
typedef typename Triangulation::Cell_handle Cell_handle;
|
||||
typedef typename Triangulation::Unique_cell_iterator
|
||||
Unique_cell_iterator;
|
||||
|
||||
size_type n = 0;
|
||||
|
||||
for (Unique_cell_iterator ocit = T.unique_cells_begin();
|
||||
ocit != T.unique_cells_end(); ++ocit)
|
||||
{
|
||||
Cell_handle ch = ocit; // Test the conversion.
|
||||
n++;
|
||||
const Cell& c = *ocit; // Test operator*;
|
||||
Vertex_handle vh = ocit->vertex(0); // Test operator->;
|
||||
(void) ch;
|
||||
(void) c;
|
||||
(void) vh;
|
||||
}
|
||||
assert( n == T.number_of_cells() );
|
||||
|
||||
// Test Backward-ness of the iterators.
|
||||
n=0;
|
||||
for (Unique_cell_iterator ocit = T.unique_cells_end();
|
||||
ocit != T.unique_cells_begin(); --ocit)
|
||||
{
|
||||
Cell_handle ch = ocit; // Test the conversion.
|
||||
(void) ch;
|
||||
++n;
|
||||
}
|
||||
assert( n == T.number_of_cells() );
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
template < class Triangulation >
|
||||
typename Triangulation::size_type
|
||||
_test_triangulation_unique_iterator( const Triangulation &T )
|
||||
{
|
||||
typedef typename Triangulation::size_type size_type;
|
||||
const size_type nc = _test_unique_cell_iterator(T);
|
||||
const size_type nf = _test_unique_facet_iterator(T);
|
||||
const size_type ne = _test_unique_edge_iterator(T);
|
||||
const size_type nv = _test_unique_vertex_iterator(T);
|
||||
assert((nv-ne+nf-nc) == 0);
|
||||
return nv-ne+nf-nc;
|
||||
}
|
||||
|
||||
template < class Triangulation >
|
||||
typename Triangulation::size_type
|
||||
_test_triangulation_iterator( const Triangulation &T )
|
||||
|
|
|
|||
|
|
@ -479,10 +479,10 @@ _test_cls_periodic_3_triangulation_3(const PeriodicTriangulation &,
|
|||
_test_vertex_iterator(PT3_deg);
|
||||
_test_vertex_iterator(PT1_deg);
|
||||
|
||||
_test_unique_vertex_iterator(PT3);
|
||||
_test_unique_vertex_iterator(PT1);
|
||||
_test_unique_vertex_iterator(PT3_deg);
|
||||
_test_unique_vertex_iterator(PT1_deg);
|
||||
_test_triangulation_unique_iterator(PT3);
|
||||
_test_triangulation_unique_iterator(PT1);
|
||||
_test_triangulation_unique_iterator(PT3_deg);
|
||||
_test_triangulation_unique_iterator(PT1_deg);
|
||||
|
||||
_test_triangulation_iterator(PT3);
|
||||
_test_triangulation_iterator(PT1);
|
||||
|
|
|
|||
|
|
@ -68,6 +68,9 @@ if(TARGET CGAL::Eigen3_support)
|
|||
|
||||
create_single_source_cgal_program("jet_pointer_as_property_map.cpp")
|
||||
target_link_libraries(jet_pointer_as_property_map PUBLIC CGAL::Eigen3_support)
|
||||
|
||||
create_single_source_cgal_program("psp_jet_includes.cpp")
|
||||
target_link_libraries(psp_jet_includes PUBLIC CGAL::Eigen3_support)
|
||||
else()
|
||||
message(STATUS "NOTICE: Some tests require Eigen 3.1 (or greater), and will not be compiled.")
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -2455,9 +2455,8 @@ bounded_error_squared_Hausdorff_distance_naive_impl(const TriangleMesh1& tm1,
|
|||
/**
|
||||
* \ingroup PMP_distance_grp
|
||||
*
|
||||
* returns an estimate on the Hausdorff distance between `tm1` and `tm2` that
|
||||
* is at most `error_bound` away from the actual Hausdorff distance between
|
||||
* the two given meshes.
|
||||
* returns an estimate on the Hausdorff distance from `tm1` to `tm2` that
|
||||
* is at most `error_bound` away from the actual Hausdorff distance from `tm1` to `tm2`.
|
||||
*
|
||||
* @tparam Concurrency_tag enables sequential versus parallel algorithm.
|
||||
* Possible values are `Sequential_tag` and `Parallel_tag`.
|
||||
|
|
|
|||
|
|
@ -3,13 +3,17 @@
|
|||
|
||||
#include <QColor>
|
||||
|
||||
inline QColor generate_color(double h, double s_min = 0.35)
|
||||
#include <stdlib.h>
|
||||
#include <iostream>
|
||||
|
||||
inline QColor generate_color(double h,
|
||||
double s_min = 0.35)
|
||||
{
|
||||
std::size_t s_max=255;
|
||||
if(h >0.8 && h < 0.95) //span of ugly pink, desaturates make it less garish IMO
|
||||
std::size_t s_max = 255;
|
||||
if(h > 0.8 && h < 0.95) // span of ugly pink, desaturates make it less garish IMO
|
||||
s_max = 160;
|
||||
std::size_t s = std::rand() % (s_max-static_cast<std::size_t>(s_min*255)) + static_cast<int>(s_min*255);
|
||||
return QColor::fromHsvF(h,s/255.0,1.0);
|
||||
return QColor::fromHsvF(h, s/255.0, 1.0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -22,19 +26,23 @@ compute_color_map(QColor base_color,
|
|||
qreal hue = base_color.hueF();
|
||||
const qreal step = (static_cast<qreal>(1)) / nb_of_colors;
|
||||
|
||||
qreal h = hue==-1 ? 0
|
||||
:hue;
|
||||
for(unsigned i = 0; i < nb_of_colors; ++i) {
|
||||
if (h!=-1) h += step;
|
||||
if ( h > 1 ) { h -= 1; }
|
||||
qreal h = (hue == -1) ? 0 : hue;
|
||||
for(std::size_t i=0; i<nb_of_colors; ++i)
|
||||
{
|
||||
if(h != -1)
|
||||
h += step;
|
||||
if(h > 1)
|
||||
h -= 1;
|
||||
*out++ = generate_color(h);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
inline QColor generate_random_color() {
|
||||
inline QColor generate_random_color()
|
||||
{
|
||||
std::size_t h = static_cast<std::size_t>(std::rand() % 360);
|
||||
return generate_color(h/359.0);
|
||||
return generate_color(h / 359.0);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // _COLOR_MAP_H
|
||||
|
|
|
|||
|
|
@ -1440,7 +1440,7 @@ QList<int> MainWindow::getSelectedSceneItemIndices() const
|
|||
void MainWindow::selectionChanged()
|
||||
{
|
||||
scene->setSelectedItemIndex(getSelectedSceneItemIndex());
|
||||
scene->setSelectedItemsList(getSelectedSceneItemIndices());
|
||||
scene->setSelectedItemIndices(getSelectedSceneItemIndices());
|
||||
CGAL::Three::Scene_item* item = scene->item(getSelectedSceneItemIndex());
|
||||
Q_FOREACH(CGAL::QGLViewer* vi, CGAL::QGLViewer::QGLViewerPool())
|
||||
{
|
||||
|
|
@ -2193,7 +2193,7 @@ void MainWindow::on_actionEraseAll_triggered()
|
|||
QList<int> all_ids;
|
||||
for(int i = 0; i < scene->numberOfEntries(); ++i)
|
||||
all_ids.push_back(i);
|
||||
scene->setSelectedItemsList(all_ids);
|
||||
scene->setSelectedItemIndices(all_ids);
|
||||
on_actionErase_triggered();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,16 @@
|
|||
include(polyhedron_demo_macros)
|
||||
|
||||
qt5_wrap_ui(display_propertyUI_FILES Display_property.ui)
|
||||
polyhedron_demo_plugin(display_property_plugin Display_property_plugin ${display_propertyUI_FILES} KEYWORDS Viewer)
|
||||
target_link_libraries(display_property_plugin PUBLIC scene_surface_mesh_item
|
||||
scene_points_with_normal_item
|
||||
scene_color_ramp)
|
||||
|
||||
if(TARGET CGAL::Eigen3_support)
|
||||
qt5_wrap_ui( display_propertyUI_FILES Display_property.ui )
|
||||
polyhedron_demo_plugin(display_property_plugin Display_property_plugin ${display_propertyUI_FILES} KEYWORDS Viewer)
|
||||
target_link_libraries(display_property_plugin
|
||||
PUBLIC
|
||||
scene_surface_mesh_item
|
||||
scene_points_with_normal_item
|
||||
scene_color_ramp
|
||||
CGAL::Eigen3_support)
|
||||
qt5_wrap_ui(heat_methodUI_FILES Heat_method.ui)
|
||||
polyhedron_demo_plugin(heat_method_plugin Heat_method_plugin ${heat_methodUI_FILES} KEYWORDS Viewer)
|
||||
target_link_libraries(heat_method_plugin PUBLIC scene_surface_mesh_item
|
||||
scene_selection_item
|
||||
scene_color_ramp
|
||||
CGAL::Eigen3_support)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -2,26 +2,202 @@
|
|||
<ui version="4.0">
|
||||
<class>DisplayPropertyWidget</class>
|
||||
<widget class="QDockWidget" name="DisplayPropertyWidget">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>292</width>
|
||||
<height>508</height>
|
||||
<width>514</width>
|
||||
<height>695</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>514</width>
|
||||
<height>695</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Property Displaying</string>
|
||||
<string>Property Display</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="0,0">
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="9" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="colorizeButton">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Cantarell</family>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Color Item</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="propertyGroup">
|
||||
<property name="title">
|
||||
<string>Property</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="propertyBox">
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Smallest Angle Per Face</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Scaled Jacobian</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Heat Intensity</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Heat Intensity (Intrinsic Delaunay)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QGridLayout" name="ColoringGroup" columnstretch="50,50">
|
||||
<item row="0" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="coloringChoiceGroup">
|
||||
<property name="title">
|
||||
<string>Color Visualization</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2" columnstretch="50,50">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="8" column="0">
|
||||
<widget class="QRadioButton" name="randomColorsRadioButton">
|
||||
<property name="text">
|
||||
<string>Random colors</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QPushButton" name="minColorButton">
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="initColorLabel">
|
||||
<property name="text">
|
||||
<string>First color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="maxColorLabel">
|
||||
<property name="text">
|
||||
<string>Max color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QRadioButton" name="colorRampRadioButton">
|
||||
<property name="text">
|
||||
<string>Color Ramp</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QPushButton" name="initColorButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QPushButton" name="maxColorButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="minColorLabel">
|
||||
<property name="text">
|
||||
<string>Min color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="1" rowspan="3">
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
|
|
@ -30,12 +206,12 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>127</width>
|
||||
<height>430</height>
|
||||
<width>236</width>
|
||||
<height>397</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="0" column="0" alignment="Qt::AlignHCenter">
|
||||
<widget class="QLabel" name="legendLabel">
|
||||
<property name="text">
|
||||
<string>RAMP DISPLAYING</string>
|
||||
|
|
@ -46,206 +222,70 @@
|
|||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QPushButton" name="colorizeButton">
|
||||
<property name="text">
|
||||
<string>Colorize</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QTabWidget" name="colorChoiceWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="ramp_tab">
|
||||
<attribute name="title">
|
||||
<string>Ramp</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Ramp Colors</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QPushButton" name="minColorButton">
|
||||
<property name="text">
|
||||
<string>Color Min...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="maxColorButton">
|
||||
<property name="text">
|
||||
<string>Color Max...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="map_tab">
|
||||
<attribute name="title">
|
||||
<string>Map</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QPushButton" name="initColorButton">
|
||||
<property name="text">
|
||||
<string>Initial Color...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QPushButton" name="sourcePointsButton">
|
||||
<property name="text">
|
||||
<string>Select Source Points</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Zoom </string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QPushButton" name="zoomToMinButton">
|
||||
<property name="text">
|
||||
<string>Zoom to min</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="zoomToMaxButton">
|
||||
<property name="text">
|
||||
<string>Zoom to max</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Ramp Extrema</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="DoubleEdit" name="minBox">
|
||||
<property name="text">
|
||||
<string>0.00</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="DoubleEdit" name="maxBox">
|
||||
<property name="text">
|
||||
<string>2.00</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QPushButton" name="deleteButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Delete Group</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="propertyBox">
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Smallest Angle Per Face</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Scaled Jacobian</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Heat Intensity</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Heat Intensity (Intrinsic Delaunay)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<item row="11" column="0">
|
||||
<widget class="QGroupBox" name="extremeValuesGroup">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
<property name="title">
|
||||
<string>Extreme Values</string>
|
||||
</property>
|
||||
</spacer>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="extremeValuesMinLabel">
|
||||
<property name="text">
|
||||
<string>Min Value</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="extremeValuesMaxLabel">
|
||||
<property name="text">
|
||||
<string>Max Value</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="DoubleEdit" name="maxBox">
|
||||
<property name="text">
|
||||
<string>2.00</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="zoomToMaxButton">
|
||||
<property name="text">
|
||||
<string>Zoom to max value</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="zoomToMinButton">
|
||||
<property name="text">
|
||||
<string>Zoom to min value</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="DoubleEdit" name="minBox">
|
||||
<property name="text">
|
||||
<string>0.00</string>
|
||||
</property>
|
||||
<property name="frame">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,294 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>HeatMethodWidget</class>
|
||||
<widget class="QDockWidget" name="HeatMethodWidget">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>365</width>
|
||||
<height>708</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>365</width>
|
||||
<height>708</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Heat Method</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="3" column="0">
|
||||
<layout class="QGridLayout" name="coloringGroup" columnstretch="50,50">
|
||||
<item row="2" column="0">
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="1" rowspan="3">
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>161</width>
|
||||
<height>371</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="0" column="0" alignment="Qt::AlignHCenter">
|
||||
<widget class="QLabel" name="legendLabel">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>RAMP DISPLAYING</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="coloringChoiceGroup">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Color Ramp</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2" columnstretch="50,50">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="minColorLabel">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Min color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="minColorButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="maxColorLabel">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Max color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QPushButton" name="maxColorButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="methodGroup">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Method</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="methodBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="0">
|
||||
<widget class="QGroupBox" name="extremeValueGroup">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Extreme Value</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="zoomToMaxButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Zoom to max value</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="extremeValueMaxLabel">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Max Value</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="DoubleEdit" name="maxBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="estimateDistancesButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Cantarell</family>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Estimate Geodesic Distances</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QGroupBox" name="sourcesGroup">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Source Vertices</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="createSourceVerticesButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string extracomment="Use 'Shift + Left Click'"/>
|
||||
</property>
|
||||
<property name="toolTipDuration">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Create Source Vertices Selection Item</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>DoubleEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>CGAL_double_edit.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
@ -0,0 +1,821 @@
|
|||
#include "ui_Heat_method.h"
|
||||
|
||||
#include "Color_ramp.h"
|
||||
#include "id_printing.h"
|
||||
#include "Messages_interface.h"
|
||||
#include "triangulate_primitive.h"
|
||||
|
||||
#include "Scene.h"
|
||||
#include "Scene_polyhedron_selection_item.h"
|
||||
#include "Scene_surface_mesh_item.h"
|
||||
|
||||
#include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
|
||||
#include <CGAL/Three/Polyhedron_demo_plugin_helper.h>
|
||||
#include <CGAL/Three/Three.h>
|
||||
#include <CGAL/Three/Triangle_container.h>
|
||||
#include <CGAL/Buffer_for_vao.h>
|
||||
|
||||
#include <CGAL/boost/bimap.hpp>
|
||||
#include <CGAL/boost/graph/helpers.h>
|
||||
#include <CGAL/Dynamic_property_map.h>
|
||||
#include <CGAL/Heat_method_3/Surface_mesh_geodesic_distances_3.h>
|
||||
|
||||
#include <QAbstractItemView>
|
||||
#include <QAction>
|
||||
#include <QApplication>
|
||||
#include <QColor>
|
||||
#include <QColorDialog>
|
||||
#include <QInputDialog>
|
||||
#include <QMainWindow>
|
||||
#include <QMessageBox>
|
||||
#include <QObject>
|
||||
#include <QPalette>
|
||||
#include <QStyleFactory>
|
||||
|
||||
// @fixme multiple selection items are broken, so don't create a selection item if there is already one
|
||||
|
||||
using namespace CGAL::Three;
|
||||
|
||||
Viewer_interface* (&getActiveViewer)() = Three::activeViewer;
|
||||
|
||||
class Scene_heat_item
|
||||
: public Scene_item_rendering_helper
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
Scene_surface_mesh_item* parent;
|
||||
SMesh* sm;
|
||||
|
||||
mutable std::vector<float> verts;
|
||||
mutable std::vector<float> normals;
|
||||
mutable std::vector<unsigned int> idx;
|
||||
mutable std::vector<float> colors;
|
||||
mutable std::vector<float> heat_values;
|
||||
mutable std::size_t nb_idx;
|
||||
|
||||
public:
|
||||
Scene_heat_item(Scene_surface_mesh_item* item)
|
||||
: parent(item), sm(item->face_graph())
|
||||
{
|
||||
CGAL_precondition(is_triangle_mesh(*sm));
|
||||
|
||||
setTriangleContainer(0, new Triangle_container(Viewer_interface::PROGRAM_HEAT_INTENSITY, true));
|
||||
setRenderingMode(Gouraud);
|
||||
}
|
||||
|
||||
~Scene_heat_item(){}
|
||||
|
||||
Scene_item* clone() const Q_DECL_OVERRIDE { return nullptr; }
|
||||
QString toolTip() const Q_DECL_OVERRIDE{ return QString(); }
|
||||
Scene_surface_mesh_item* getParent() { return parent; }
|
||||
bool isEmpty() const Q_DECL_OVERRIDE { return false; }
|
||||
|
||||
SMesh* face_graph() { return sm; }
|
||||
|
||||
void initializeBuffers(Viewer_interface *viewer) const Q_DECL_OVERRIDE
|
||||
{
|
||||
getTriangleContainer(0)->initializeBuffers(viewer);
|
||||
getTriangleContainer(0)->setIdxSize(nb_idx);
|
||||
|
||||
verts.resize(0);
|
||||
verts.shrink_to_fit();
|
||||
normals.resize(0);
|
||||
normals.shrink_to_fit();
|
||||
colors.resize(0);
|
||||
colors.shrink_to_fit();
|
||||
idx.clear();
|
||||
idx.shrink_to_fit();
|
||||
}
|
||||
|
||||
void draw(Viewer_interface *viewer) const Q_DECL_OVERRIDE
|
||||
{
|
||||
if(!visible())
|
||||
return;
|
||||
|
||||
if(!isInit(viewer))
|
||||
initGL(viewer);
|
||||
|
||||
if(getBuffersFilled() && !getBuffersInit(viewer))
|
||||
{
|
||||
initializeBuffers(viewer);
|
||||
setBuffersInit(viewer, true);
|
||||
}
|
||||
|
||||
if(!getBuffersFilled())
|
||||
{
|
||||
computeElements();
|
||||
initializeBuffers(viewer);
|
||||
}
|
||||
|
||||
getTriangleContainer(0)->setAlpha(1.0f);
|
||||
getTriangleContainer(0)->draw(viewer, false);
|
||||
}
|
||||
|
||||
void compute_bbox() const Q_DECL_OVERRIDE
|
||||
{
|
||||
setBbox(parent->bbox());
|
||||
}
|
||||
|
||||
virtual bool supportsRenderingMode(RenderingMode m) const Q_DECL_OVERRIDE
|
||||
{
|
||||
return (m == Gouraud);
|
||||
}
|
||||
|
||||
virtual void invalidateOpenGLBuffers() Q_DECL_OVERRIDE
|
||||
{
|
||||
setBuffersFilled(false);
|
||||
compute_bbox();
|
||||
getTriangleContainer(0)->reset_vbos(NOT_INSTANCED);
|
||||
}
|
||||
|
||||
void computeElements() const Q_DECL_OVERRIDE
|
||||
{
|
||||
typedef CGAL::Buffer_for_vao<float, unsigned int> CPF;
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
auto vpm = CGAL::get(CGAL::vertex_point, *sm);
|
||||
auto vnormals = sm->property_map<vertex_descriptor, EPICK::Vector_3>("v:normal").first;
|
||||
|
||||
auto [vcolors, vcolors_found] = sm->property_map<vertex_descriptor, CGAL::IO::Color>("v:color");
|
||||
CGAL_assertion(vcolors_found);
|
||||
auto [vdist, vdist_found] = sm->property_map<vertex_descriptor, double>("v:HM_Plugin_heat_intensity");
|
||||
CGAL_assertion(vdist_found);
|
||||
|
||||
verts.clear();
|
||||
normals.clear();
|
||||
idx.clear();
|
||||
colors.clear();
|
||||
|
||||
idx.reserve(3 * num_faces(*sm));
|
||||
for(face_descriptor fd : faces(*sm))
|
||||
{
|
||||
for(halfedge_descriptor hd : halfedges_around_face(halfedge(fd, *sm),*sm))
|
||||
idx.push_back(source(hd, *sm));
|
||||
}
|
||||
|
||||
const CGAL::qglviewer::Vec& o = static_cast<Viewer_interface*>(CGAL::QGLViewer::QGLViewerPool().first())->offset();
|
||||
EPICK::Vector_3 offset(o.x, o.y, o.z);
|
||||
|
||||
for(vertex_descriptor vd : vertices(*sm))
|
||||
{
|
||||
const CGAL::IO::Color& c = vcolors[vd];
|
||||
colors.push_back(float(c.red()) / 255);
|
||||
colors.push_back(float(c.green()) / 255);
|
||||
colors.push_back(float(c.blue()) / 255);
|
||||
|
||||
const EPICK::Point_3& p = get(vpm, vd) + offset;
|
||||
CPF::add_point_in_buffer(p, verts);
|
||||
|
||||
const EPICK::Vector_3& n = vnormals[vd];
|
||||
CPF::add_normal_in_buffer(n, normals);
|
||||
|
||||
heat_values.push_back(vdist[vd]);
|
||||
}
|
||||
|
||||
nb_idx = idx.size();
|
||||
getTriangleContainer(0)->allocate(Triangle_container::Vertex_indices, idx.data(),
|
||||
static_cast<int>(idx.size()*sizeof(unsigned int)));
|
||||
getTriangleContainer(0)->allocate(Triangle_container::Smooth_vertices, verts.data(),
|
||||
static_cast<int>(num_vertices(*sm)*3*sizeof(float)));
|
||||
getTriangleContainer(0)->allocate(Triangle_container::Smooth_normals, normals.data(),
|
||||
static_cast<int>(num_vertices(*sm)*3*sizeof(float)));
|
||||
getTriangleContainer(0)->allocate(Triangle_container::VColors, colors.data(),
|
||||
static_cast<int>(colors.size()*sizeof(float)));
|
||||
getTriangleContainer(0)->allocate(Triangle_container::Distances, heat_values.data(),
|
||||
static_cast<int>(heat_values.size()*sizeof(float)));
|
||||
|
||||
compute_bbox();
|
||||
setBuffersFilled(true);
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
}; // class Scene_heat_item
|
||||
|
||||
class DockWidget
|
||||
: public QDockWidget,
|
||||
public Ui::HeatMethodWidget
|
||||
{
|
||||
public:
|
||||
DockWidget(const QString& name, QWidget *parent)
|
||||
: QDockWidget(name, parent)
|
||||
{
|
||||
setupUi(this);
|
||||
}
|
||||
};
|
||||
|
||||
class Heat_method_plugin
|
||||
: public QObject,
|
||||
public Polyhedron_demo_plugin_helper
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
|
||||
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0")
|
||||
|
||||
using Vertex_distance_map = SMesh::Property_map<vertex_descriptor, double>;
|
||||
using Heat_method = CGAL::Heat_method_3::Surface_mesh_geodesic_distances_3<SMesh>;
|
||||
using Heat_method_idt = CGAL::Heat_method_3::Surface_mesh_geodesic_distances_3<SMesh, CGAL::Heat_method_3::Intrinsic_Delaunay>;
|
||||
|
||||
private:
|
||||
QAction* actionHeatMethod;
|
||||
|
||||
DockWidget* dock_widget;
|
||||
|
||||
// coloring choice and legend
|
||||
double rm = 1.;
|
||||
double gm = 0.;
|
||||
double bm = 0.;
|
||||
double rM = 0.;
|
||||
double gM = 1.;
|
||||
double bM = 0.;
|
||||
|
||||
Color_ramp color_ramp;
|
||||
QPixmap legend;
|
||||
|
||||
// tracking which scene items have which sources, and which heat method builders
|
||||
boost::bimap<boost::bimaps::set_of<Scene_surface_mesh_item*>,
|
||||
boost::bimaps::set_of<Scene_polyhedron_selection_item*> > item_source_vertices;
|
||||
|
||||
// the point of storing this is that in the Heat Method(s), a number of computations are only
|
||||
// dependent on the mesh, and not the sources, and such can be performed just once.
|
||||
std::unordered_map<Scene_surface_mesh_item*, Heat_method*> heat_methods;
|
||||
std::unordered_map<Scene_surface_mesh_item*, Heat_method_idt*> idt_heat_methods;
|
||||
|
||||
public:
|
||||
bool applicable(QAction*) const Q_DECL_OVERRIDE
|
||||
{
|
||||
// Single item => it must be a mesh and the selection item will be created through the plugin's button
|
||||
if(scene->selectionIndices().size() == 1)
|
||||
{
|
||||
Scene_item* item = scene->item(scene->mainSelectionIndex());
|
||||
return qobject_cast<Scene_surface_mesh_item*>(item);
|
||||
}
|
||||
// Two items => it must be a surface mesh and a selection item (in any order)
|
||||
else if(scene->selectionIndices().size() == 2)
|
||||
{
|
||||
Scene_item* item1 = scene->item(scene->selectionIndices().front());
|
||||
Scene_item* item2 = scene->item(scene->selectionIndices().back());
|
||||
return ((qobject_cast<Scene_surface_mesh_item*>(item1) &&
|
||||
qobject_cast<Scene_polyhedron_selection_item*>(item2)) ||
|
||||
(qobject_cast<Scene_polyhedron_selection_item*>(item1) &&
|
||||
qobject_cast<Scene_surface_mesh_item*>(item2)));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QList<QAction*> actions() const Q_DECL_OVERRIDE
|
||||
{
|
||||
return QList<QAction*>() << actionHeatMethod;
|
||||
}
|
||||
|
||||
void init(QMainWindow* mw,
|
||||
Scene_interface* sc,
|
||||
Messages_interface*) Q_DECL_OVERRIDE
|
||||
{
|
||||
this->scene = sc;
|
||||
this->mw = mw;
|
||||
|
||||
actionHeatMethod = new QAction(QString("Heat Method"), mw);
|
||||
actionHeatMethod->setProperty("submenuName", "Color");
|
||||
|
||||
connect(actionHeatMethod, SIGNAL(triggered()),
|
||||
this, SLOT(openDialog()));
|
||||
|
||||
Scene* scene_item = static_cast<Scene*>(scene);
|
||||
connect(scene_item, SIGNAL(itemIndicesSelected(QList<int>)),
|
||||
this, SLOT(onItemIndicesSelected(QList<int>)));
|
||||
|
||||
// Dock Widget
|
||||
dock_widget = new DockWidget("Heat Method", mw);
|
||||
addDockWidget(dock_widget);
|
||||
dock_widget->setVisible(false);
|
||||
|
||||
connect(dock_widget->methodBox, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(onNewMethodSelected(int)));
|
||||
|
||||
dock_widget->methodBox->addItems({"Heat Method",
|
||||
"Heat Method (Intrinsic Delaunay)"});
|
||||
|
||||
connect(dock_widget->createSourceVerticesButton, SIGNAL(clicked()),
|
||||
this, SLOT(createSourceVerticesSelectionItem()));
|
||||
|
||||
QPalette palette(Qt::red);
|
||||
dock_widget->minColorButton->setPalette(palette);
|
||||
dock_widget->minColorButton->setStyle(QStyleFactory::create("Fusion"));
|
||||
dock_widget->minColorButton->update();
|
||||
|
||||
palette = QPalette(Qt::green);
|
||||
dock_widget->maxColorButton->setPalette(palette);
|
||||
dock_widget->maxColorButton->setStyle(QStyleFactory::create("Fusion"));
|
||||
dock_widget->maxColorButton->update();
|
||||
|
||||
// lambda to generate the three connect(), for each color button (min, max, map)
|
||||
auto connect_color_buttons = [this](QPushButton* colorButton,
|
||||
double& r, double& g, double& b)
|
||||
{
|
||||
connect(colorButton, &QPushButton::pressed,
|
||||
this, [this, colorButton, &r, &g, &b]()
|
||||
{
|
||||
QColor color = QColorDialog::getColor();
|
||||
if(!color.isValid())
|
||||
return;
|
||||
|
||||
r = color.redF();
|
||||
g = color.greenF();
|
||||
b = color.blueF();
|
||||
|
||||
QPalette palette(color);
|
||||
colorButton->setPalette(palette);
|
||||
colorButton->update();
|
||||
|
||||
displayRampLegend();
|
||||
});
|
||||
};
|
||||
|
||||
connect_color_buttons(dock_widget->minColorButton, rm, gm, bm);
|
||||
connect_color_buttons(dock_widget->maxColorButton, rM, gM, bM);
|
||||
|
||||
// Main action connection
|
||||
connect(dock_widget->estimateDistancesButton, SIGNAL(clicked(bool)),
|
||||
this, SLOT(estimateDistances()));
|
||||
|
||||
// Post coloring connection
|
||||
connect(dock_widget->zoomToMaxButton, &QPushButton::pressed,
|
||||
this, &Heat_method_plugin::on_zoomToMaxButton_pressed);
|
||||
}
|
||||
|
||||
private Q_SLOTS:
|
||||
void openDialog()
|
||||
{
|
||||
if(!dock_widget->isVisible())
|
||||
dock_widget->show();
|
||||
dock_widget->raise();
|
||||
}
|
||||
|
||||
void closure() Q_DECL_OVERRIDE
|
||||
{
|
||||
dock_widget->hide();
|
||||
}
|
||||
|
||||
private:
|
||||
void disableExtremeValue()
|
||||
{
|
||||
dock_widget->extremeValueGroup->setEnabled(false);
|
||||
dock_widget->zoomToMaxButton->setEnabled(false);
|
||||
}
|
||||
|
||||
void enableExtremeValue()
|
||||
{
|
||||
dock_widget->extremeValueGroup->setEnabled(true);
|
||||
dock_widget->zoomToMaxButton->setEnabled(true);
|
||||
}
|
||||
|
||||
void resetExtremeValue()
|
||||
{
|
||||
dock_widget->maxBox->setRange(0, 99999999);
|
||||
dock_widget->maxBox->setValue(0);
|
||||
}
|
||||
|
||||
void displayRampLegend()
|
||||
{
|
||||
color_ramp = Color_ramp(rm, rM, gm, gM, bm, bM);
|
||||
|
||||
const int height = 256;
|
||||
const int width = 140;
|
||||
const int cell_width = width / 3;
|
||||
const int top_margin = 5;
|
||||
const int left_margin = 5;
|
||||
const int drawing_height = height - 2*top_margin;
|
||||
const int text_height = 20;
|
||||
|
||||
legend = QPixmap(width, height + text_height);
|
||||
legend.fill(QColor(200, 200, 200));
|
||||
|
||||
QPainter painter(&legend);
|
||||
painter.setPen(Qt::black);
|
||||
painter.setBrush(QColor(200, 200, 200));
|
||||
|
||||
const double min_value = 0;
|
||||
const double max_value = dock_widget->maxBox->value();
|
||||
|
||||
// Build legend data
|
||||
std::vector<double> graduations(100);
|
||||
for(int i=0; i<100; ++i)
|
||||
graduations[i] = i / 100.0;
|
||||
|
||||
int i = 0;
|
||||
for(std::vector<double>::iterator it = graduations.begin(), end = graduations.end(); it != end; ++it, i+=2)
|
||||
{
|
||||
QColor color(255 * color_ramp.r(*it),
|
||||
255 * color_ramp.g(*it),
|
||||
255 * color_ramp.b(*it));
|
||||
painter.fillRect(left_margin, drawing_height - top_margin - i, cell_width, 2, color);
|
||||
}
|
||||
|
||||
// draw right vertical line
|
||||
painter.setPen(Qt::blue);
|
||||
painter.drawLine(QPoint(left_margin + cell_width + 10,
|
||||
drawing_height - top_margin + 2),
|
||||
QPoint(left_margin + cell_width + 10,
|
||||
drawing_height - top_margin - static_cast<int>(graduations.size())*2 + 2));
|
||||
|
||||
// draw min value and max value
|
||||
painter.setPen(Qt::blue);
|
||||
QRect min_text_rect(left_margin + cell_width + 10,
|
||||
drawing_height - top_margin, 100, text_height);
|
||||
painter.drawText(min_text_rect, Qt::AlignCenter, QObject::tr("%1").arg(min_value, 0, 'f', 3));
|
||||
|
||||
QRect max_text_rect(left_margin + cell_width + 10,
|
||||
drawing_height - top_margin - 200, 100, text_height);
|
||||
painter.drawText(max_text_rect, Qt::AlignCenter, QObject::tr("%1").arg(max_value, 0, 'f', 3));
|
||||
|
||||
dock_widget->legendLabel->setPixmap(legend);
|
||||
}
|
||||
|
||||
private Q_SLOTS:
|
||||
// Called when new geometric objects are selected in the scene
|
||||
void onItemIndicesSelected(QList<int> selected_items)
|
||||
{
|
||||
resetExtremeValue();
|
||||
dock_widget->setEnabled(false);
|
||||
|
||||
Scene_surface_mesh_item* sm_item = nullptr;
|
||||
Scene_polyhedron_selection_item* source_vertices = nullptr;
|
||||
|
||||
if(selected_items.size() == 1)
|
||||
{
|
||||
Scene_item* item = scene->item(scene->mainSelectionIndex());
|
||||
source_vertices = qobject_cast<Scene_polyhedron_selection_item*>(item);
|
||||
if(source_vertices)
|
||||
{
|
||||
// While selecting a selection item, enable coloring if the selection item is linked to a sm_item
|
||||
if(item_source_vertices.right.count(source_vertices) == 0)
|
||||
return;
|
||||
|
||||
dock_widget->setEnabled(true);
|
||||
dock_widget->createSourceVerticesButton->setEnabled(false);
|
||||
dock_widget->estimateDistancesButton->setEnabled(true);
|
||||
disableExtremeValue();
|
||||
return;
|
||||
}
|
||||
else if(qobject_cast<Scene_heat_item*>(item))
|
||||
{
|
||||
dock_widget->setEnabled(true);
|
||||
dock_widget->createSourceVerticesButton->setEnabled(false);
|
||||
dock_widget->estimateDistancesButton->setEnabled(false);
|
||||
disableExtremeValue();
|
||||
return;
|
||||
}
|
||||
|
||||
sm_item = qobject_cast<Scene_surface_mesh_item*>(item);
|
||||
}
|
||||
else if(selected_items.size() == 2)
|
||||
{
|
||||
Scene_item* item1 = scene->item(selected_items.front());
|
||||
Scene_item* item2 = scene->item(selected_items.back());
|
||||
sm_item = qobject_cast<Scene_surface_mesh_item*>(item1);
|
||||
source_vertices = qobject_cast<Scene_polyhedron_selection_item*>(item2);
|
||||
if(!sm_item)
|
||||
{
|
||||
sm_item = qobject_cast<Scene_surface_mesh_item*>(item2);
|
||||
source_vertices = qobject_cast<Scene_polyhedron_selection_item*>(item1);
|
||||
}
|
||||
}
|
||||
|
||||
if(!sm_item)
|
||||
return;
|
||||
|
||||
dock_widget->setEnabled(true);
|
||||
const bool has_sources = (source_vertices || item_source_vertices.left.count(sm_item) != 0);
|
||||
dock_widget->estimateDistancesButton->setEnabled(has_sources);
|
||||
dock_widget->createSourceVerticesButton->setEnabled(!has_sources);
|
||||
disableExtremeValue();
|
||||
}
|
||||
|
||||
// This function is only called if the index actually changed (doesn't trigger
|
||||
// if you click again the item)
|
||||
void onNewMethodSelected(int method_index)
|
||||
{
|
||||
resetExtremeValue(); // reset extreme value before the legend to get the proper values
|
||||
displayRampLegend();
|
||||
|
||||
if(method_index >= 0 && method_index < dock_widget->methodBox->count()) // valid method
|
||||
{
|
||||
dock_widget->setEnabled(true);
|
||||
disableExtremeValue(); // only available after displaying geodesic distances
|
||||
}
|
||||
else // no or broken method?
|
||||
{
|
||||
dock_widget->setEnabled(false);
|
||||
dock_widget->methodBox->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool displayHeatIntensity(Scene_surface_mesh_item* sm_item,
|
||||
Scene_polyhedron_selection_item* source_vertices,
|
||||
const bool use_iDT = false)
|
||||
{
|
||||
SMesh& mesh = *sm_item->face_graph();
|
||||
|
||||
SMesh::Property_map<vertex_descriptor, double> heat_intensity =
|
||||
mesh.add_property_map<vertex_descriptor, double>("v:HM_Plugin_heat_intensity", 0).first;
|
||||
|
||||
auto initialize_hm_map = [this, sm_item, &mesh] (auto*& hm_ptr, auto& hm_map) -> void
|
||||
{
|
||||
using Method = std::decay_t<decltype(*hm_ptr)>;
|
||||
|
||||
auto it = hm_map.find(sm_item);
|
||||
if(it != hm_map.end()) // method already exists
|
||||
{
|
||||
hm_ptr = it->second;
|
||||
|
||||
for(vertex_descriptor v : vertices(mesh))
|
||||
hm_ptr->remove_source(v);
|
||||
}
|
||||
else
|
||||
{
|
||||
hm_ptr = new Method(mesh);
|
||||
hm_map[sm_item] = hm_ptr;
|
||||
}
|
||||
|
||||
connect(sm_item, &Scene_surface_mesh_item::aboutToBeDestroyed,
|
||||
this, [this, sm_item, &hm_map]()
|
||||
{
|
||||
item_source_vertices.left.erase(sm_item);
|
||||
|
||||
auto it = hm_map.find(sm_item);
|
||||
if(it == hm_map.end())
|
||||
return;
|
||||
delete it->second;
|
||||
hm_map.erase(it);
|
||||
});
|
||||
};
|
||||
|
||||
Heat_method* hm = nullptr;
|
||||
Heat_method_idt* hm_idt = nullptr;
|
||||
|
||||
if(use_iDT)
|
||||
initialize_hm_map(hm_idt, idt_heat_methods);
|
||||
else
|
||||
initialize_hm_map(hm, heat_methods);
|
||||
|
||||
for(auto v : source_vertices->selected_vertices)
|
||||
{
|
||||
if(use_iDT)
|
||||
hm_idt->add_source(v);
|
||||
else
|
||||
hm->add_source(v);
|
||||
}
|
||||
|
||||
if(use_iDT)
|
||||
hm_idt->estimate_geodesic_distances(heat_intensity);
|
||||
else
|
||||
hm->estimate_geodesic_distances(heat_intensity);
|
||||
|
||||
// Post treatment
|
||||
double max = 0;
|
||||
for(vertex_descriptor v : vertices(mesh))
|
||||
{
|
||||
double hi = heat_intensity[v];
|
||||
if(hi > max)
|
||||
max = hi;
|
||||
}
|
||||
|
||||
displayRampLegend();
|
||||
|
||||
auto [vcolors, vcolors_added] = mesh.add_property_map<vertex_descriptor, CGAL::IO::Color >("v:color", CGAL::IO::Color());
|
||||
for(vertex_descriptor v : vertices(mesh))
|
||||
{
|
||||
double h = heat_intensity[v] / max;
|
||||
CGAL::IO::Color color(255 * color_ramp.r(h),
|
||||
255 * color_ramp.g(h),
|
||||
255 * color_ramp.b(h));
|
||||
vcolors[v] = color;
|
||||
}
|
||||
|
||||
// Create the colored item
|
||||
Scene_heat_item* heat_item = new Scene_heat_item(sm_item);
|
||||
heat_item->setName(tr("%1 (distance isolines)").arg(sm_item->name()));
|
||||
heat_item->setVisible(false);
|
||||
|
||||
sm_item->invalidateOpenGLBuffers();
|
||||
sm_item->setRenderingMode(GouraudPlusEdges);
|
||||
sm_item->redraw();
|
||||
|
||||
scene->addItem(heat_item);
|
||||
scene->setSelectedItem(scene->item_id(sm_item));
|
||||
|
||||
// any change of sm_item destroys everything
|
||||
connect(sm_item, &Scene_surface_mesh_item::itemChanged,
|
||||
this, [this, sm_item, heat_item]()
|
||||
{
|
||||
sm_item->resetColors();
|
||||
removePluginProperties(sm_item);
|
||||
scene->erase(scene->item_id(heat_item));
|
||||
onItemIndicesSelected(scene->selectionIndices());
|
||||
});
|
||||
|
||||
connect(sm_item, &Scene_surface_mesh_item::aboutToBeDestroyed,
|
||||
this, [this, heat_item]()
|
||||
{
|
||||
scene->erase(scene->item_id(heat_item));
|
||||
onItemIndicesSelected(scene->selectionIndices());
|
||||
});
|
||||
|
||||
// here because if it's put above, the setSelectedItem() might reset the value
|
||||
dock_widget->maxBox->setValue(max);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private Q_SLOTS:
|
||||
void estimateDistances()
|
||||
{
|
||||
// Get the mesh and source vertices items
|
||||
Scene_surface_mesh_item* sm_item = nullptr;
|
||||
Scene_polyhedron_selection_item* source_vertices = nullptr;
|
||||
|
||||
if(scene->selectionIndices().size() == 1)
|
||||
{
|
||||
Scene_item* item = scene->item(scene->mainSelectionIndex());
|
||||
sm_item = qobject_cast<Scene_surface_mesh_item*>(item);
|
||||
if(sm_item)
|
||||
{
|
||||
// a surface mesh item is selected, an existing associated selection item must exist
|
||||
source_vertices = item_source_vertices.left.at(sm_item);
|
||||
}
|
||||
else
|
||||
{
|
||||
// a selection item is selected, an existing associated mesh item must exist
|
||||
source_vertices = qobject_cast<Scene_polyhedron_selection_item*>(item);
|
||||
if(source_vertices)
|
||||
sm_item = item_source_vertices.right.at(source_vertices);
|
||||
}
|
||||
}
|
||||
else if(scene->selectionIndices().size() == 2)
|
||||
{
|
||||
// two items, for (possibly unlinked) sm_item and its associated selection
|
||||
Scene_item* item1 = scene->item(scene->selectionIndices().front());
|
||||
Scene_item* item2 = scene->item(scene->selectionIndices().back());
|
||||
sm_item = qobject_cast<Scene_surface_mesh_item*>(item1);
|
||||
source_vertices = qobject_cast<Scene_polyhedron_selection_item*>(item2);
|
||||
if(!sm_item)
|
||||
{
|
||||
sm_item = qobject_cast<Scene_surface_mesh_item*>(item2);
|
||||
source_vertices = qobject_cast<Scene_polyhedron_selection_item*>(item1);
|
||||
}
|
||||
|
||||
link_mesh_and_selection(sm_item, source_vertices);
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(mw, "Error","Unsupported selection of items.");
|
||||
return;
|
||||
}
|
||||
|
||||
CGAL_assertion(sm_item && source_vertices);
|
||||
|
||||
if(!is_triangle_mesh(*sm_item->face_graph()))
|
||||
{
|
||||
QApplication::restoreOverrideCursor();
|
||||
QMessageBox::critical(mw, "Error","The mesh must be triangulated.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(source_vertices->selected_vertices.empty())
|
||||
{
|
||||
QApplication::restoreOverrideCursor();
|
||||
QMessageBox::critical(mw, "Error","At least one source vertex is required.");
|
||||
return;
|
||||
}
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
enableExtremeValue();
|
||||
|
||||
const std::string& method_name = dock_widget->methodBox->currentText().toStdString();
|
||||
if(method_name == "Heat Method")
|
||||
displayHeatIntensity(sm_item, source_vertices);
|
||||
else if(method_name == "Heat Method (Intrinsic Delaunay)")
|
||||
displayHeatIntensity(sm_item, source_vertices, true /*use IDT*/);
|
||||
|
||||
// @todo emit a new SIGNAL on successful coloring, something like "colorChanged()"
|
||||
// itemChanged is too strong and would conflict with the connection below
|
||||
sm_item->invalidateOpenGLBuffers();
|
||||
sm_item->redraw();
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
private:
|
||||
void removePluginProperty(Scene_item* item,
|
||||
const std::string& property_name)
|
||||
{
|
||||
Scene_surface_mesh_item* sm_item = qobject_cast<Scene_surface_mesh_item*>(item);
|
||||
if(!sm_item)
|
||||
return;
|
||||
|
||||
SMesh* sm = sm_item->face_graph();
|
||||
if(sm == nullptr)
|
||||
return;
|
||||
|
||||
// Here we only target the property maps added by this plugin, so 'double' is fine
|
||||
SMesh::Property_map<face_descriptor, double> property;
|
||||
bool found;
|
||||
std::tie(property, found) = sm->property_map<face_descriptor, double>(property_name);
|
||||
if(found)
|
||||
sm->remove_property_map(property);
|
||||
}
|
||||
|
||||
void removePluginProperties(Scene_item* item)
|
||||
{
|
||||
removePluginProperty(item, "v:HM_Plugin_heat_intensity");
|
||||
}
|
||||
|
||||
private Q_SLOTS:
|
||||
// deletion of the selection item removes the pair from the map
|
||||
void link_mesh_and_selection(Scene_surface_mesh_item* sm_item,
|
||||
Scene_polyhedron_selection_item* source_vertices)
|
||||
{
|
||||
item_source_vertices.left.insert(std::make_pair(sm_item, source_vertices));
|
||||
|
||||
connect(source_vertices, &Scene_polyhedron_selection_item::aboutToBeDestroyed,
|
||||
this, [this, sm_item]()
|
||||
{
|
||||
item_source_vertices.left.erase(sm_item);
|
||||
onItemIndicesSelected(scene->selectionIndices());
|
||||
});
|
||||
}
|
||||
|
||||
void createSourceVerticesSelectionItem()
|
||||
{
|
||||
Scene_item* item = scene->item(scene->mainSelectionIndex());
|
||||
Scene_surface_mesh_item* sm_item = qobject_cast<Scene_surface_mesh_item*>(item);
|
||||
if(!sm_item)
|
||||
{
|
||||
QMessageBox::warning(mw, "Warning", "Select a surface mesh to add source vertices");
|
||||
dock_widget->createSourceVerticesButton->setChecked(false);
|
||||
return;
|
||||
}
|
||||
|
||||
CGAL_assertion(item_source_vertices.left.count(sm_item) == 0);
|
||||
|
||||
Scene_polyhedron_selection_item* source_vertices = new Scene_polyhedron_selection_item(sm_item, mw);
|
||||
source_vertices->setName(tr("%1 (source vertices)").arg(sm_item->name()));
|
||||
scene->addItem(source_vertices);
|
||||
|
||||
link_mesh_and_selection(sm_item, source_vertices);
|
||||
|
||||
dock_widget->createSourceVerticesButton->setEnabled(false);
|
||||
dock_widget->estimateDistancesButton->setEnabled(true);
|
||||
}
|
||||
|
||||
private Q_SLOTS:
|
||||
void on_zoomToMaxButton_pressed()
|
||||
{
|
||||
Scene_surface_mesh_item* sm_item = nullptr;
|
||||
if(scene->selectionIndices().size() == 1)
|
||||
{
|
||||
Scene_item* item = scene->item(scene->mainSelectionIndex());
|
||||
sm_item = qobject_cast<Scene_surface_mesh_item*>(item);
|
||||
}
|
||||
else if(scene->selectionIndices().size() == 2)
|
||||
{
|
||||
Scene_item* item1 = scene->item(scene->selectionIndices().front());
|
||||
Scene_item* item2 = scene->item(scene->selectionIndices().back());
|
||||
sm_item = qobject_cast<Scene_surface_mesh_item*>(item1);
|
||||
if(!sm_item)
|
||||
sm_item = qobject_cast<Scene_surface_mesh_item*>(item2);
|
||||
}
|
||||
|
||||
const SMesh& mesh = *(sm_item->face_graph());
|
||||
|
||||
auto [heat_intensity, found] = mesh.property_map<vertex_descriptor, double>("v:HM_Plugin_heat_intensity");
|
||||
CGAL_assertion(found);
|
||||
|
||||
double max = 0;
|
||||
vertex_descriptor max_v = boost::graph_traits<SMesh>::null_vertex();
|
||||
for(vertex_descriptor v : vertices(mesh))
|
||||
{
|
||||
if(heat_intensity[v] > max)
|
||||
{
|
||||
max = heat_intensity[v];
|
||||
max_v = v;
|
||||
}
|
||||
}
|
||||
|
||||
CGAL_assertion(max_v != boost::graph_traits<SMesh>::null_vertex());
|
||||
|
||||
face_descriptor unused_fd;
|
||||
Point_3 unused_p;
|
||||
::zoomToId(mesh,
|
||||
QString("v%1").arg(max_v),
|
||||
getActiveViewer(),
|
||||
unused_fd, unused_p);
|
||||
}
|
||||
};
|
||||
|
||||
#include "Heat_method_plugin.moc"
|
||||
|
|
@ -217,7 +217,7 @@ void Polyhedron_demo_join_and_split_polyhedra_plugin::on_actionColorConnectedCom
|
|||
item->computeItemColorVectorAutomatically(true);
|
||||
item->invalidateOpenGLBuffers();
|
||||
item->setProperty("NbPatchIds", nb_patch_ids);
|
||||
scene->itemChanged(item);
|
||||
scene->itemChanged(item); // @todo emits
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,21 +7,20 @@
|
|||
#include <CGAL/boost/graph/properties.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK;
|
||||
typedef EPICK::Point_3 Point_3;
|
||||
|
||||
typedef CGAL::Surface_mesh<Point_3> SMesh;
|
||||
|
||||
typedef boost::graph_traits<SMesh>::face_descriptor face_descriptor;
|
||||
typedef boost::graph_traits<SMesh>::vertex_descriptor vertex_descriptor;
|
||||
typedef boost::graph_traits<SMesh>::halfedge_descriptor halfedge_descriptor;
|
||||
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <typename P>
|
||||
struct property_map<CGAL::Surface_mesh<P>, CGAL::vertex_selection_t>
|
||||
{
|
||||
|
||||
typedef typename boost::graph_traits<CGAL::Surface_mesh<P> >::vertex_descriptor vertex_descriptor;
|
||||
|
||||
typedef typename CGAL::Surface_mesh<P>::template Property_map<vertex_descriptor, int> type;
|
||||
|
|
@ -32,7 +31,6 @@ struct property_map<CGAL::Surface_mesh<P>, CGAL::vertex_selection_t>
|
|||
template <typename P>
|
||||
struct property_map<CGAL::Surface_mesh<P>, CGAL::face_selection_t>
|
||||
{
|
||||
|
||||
typedef typename boost::graph_traits<CGAL::Surface_mesh<P> >::face_descriptor face_descriptor;
|
||||
|
||||
typedef typename CGAL::Surface_mesh<P>::template Property_map<face_descriptor, int> type;
|
||||
|
|
@ -41,11 +39,11 @@ struct property_map<CGAL::Surface_mesh<P>, CGAL::face_selection_t>
|
|||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <typename P, typename Property_tag>
|
||||
struct Get_pmap_of_surface_mesh_ {
|
||||
struct Get_pmap_of_surface_mesh_
|
||||
{
|
||||
typedef typename boost::property_map<Surface_mesh<P>, Property_tag >::type type;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -172,20 +172,22 @@ Scene::replaceItem(Scene::Item_id index, CGAL::Three::Scene_item* item, bool emi
|
|||
Scene::Item_id
|
||||
Scene::erase(Scene::Item_id index)
|
||||
{
|
||||
if(index <0 || index >= numberOfEntries())
|
||||
if(index < 0 || index >= numberOfEntries())
|
||||
return -1;
|
||||
|
||||
CGAL::Three::Scene_item* item = m_entries[index];
|
||||
|
||||
if(qobject_cast<Scene_group_item*>(item))
|
||||
{
|
||||
setSelectedItemsList(QList<Scene_interface::Item_id>()<<item_id(item));
|
||||
setSelectedItemIndices(QList<Scene_interface::Item_id>() << item_id(item));
|
||||
return erase(selectionIndices());
|
||||
}
|
||||
|
||||
m_groups.removeAll(index);
|
||||
if(item->parentGroup()
|
||||
&& item->parentGroup()->isChildLocked(item))
|
||||
if(item->parentGroup() && item->parentGroup()->isChildLocked(item))
|
||||
return -1;
|
||||
//clears the Scene_view
|
||||
|
||||
// clears the Scene_view
|
||||
clear();
|
||||
index_map.clear();
|
||||
if(item->parentGroup())
|
||||
|
|
@ -286,12 +288,12 @@ Scene::erase(QList<int> indices)
|
|||
|
||||
void Scene::remove_item_from_groups(Scene_item* item)
|
||||
{
|
||||
CGAL::Three::Scene_group_item* group = item->parentGroup();
|
||||
if(group)
|
||||
{
|
||||
group->removeChild(item);
|
||||
children.push_back(item_id(item));
|
||||
}
|
||||
CGAL::Three::Scene_group_item* group = item->parentGroup();
|
||||
if(group)
|
||||
{
|
||||
group->removeChild(item);
|
||||
children.push_back(item_id(item));
|
||||
}
|
||||
}
|
||||
Scene::~Scene()
|
||||
{
|
||||
|
|
@ -315,19 +317,19 @@ Scene::~Scene()
|
|||
CGAL::Three::Scene_item*
|
||||
Scene::item(Item_id index) const
|
||||
{
|
||||
return m_entries.value(index); // QList::value checks bounds
|
||||
return m_entries.value(index); // QList::value checks bounds
|
||||
}
|
||||
|
||||
Scene::Item_id
|
||||
Scene::item_id(CGAL::Three::Scene_item* scene_item) const
|
||||
{
|
||||
return m_entries.indexOf(scene_item);
|
||||
return m_entries.indexOf(scene_item);
|
||||
}
|
||||
|
||||
int
|
||||
Scene::numberOfEntries() const
|
||||
{
|
||||
return m_entries.size();
|
||||
return m_entries.size();
|
||||
}
|
||||
|
||||
// Duplicate a scene item.
|
||||
|
|
@ -335,20 +337,23 @@ Scene::numberOfEntries() const
|
|||
Scene::Item_id
|
||||
Scene::duplicate(Item_id index)
|
||||
{
|
||||
if(index < 0 || index >= m_entries.size())
|
||||
return -1;
|
||||
if(index < 0 || index >= m_entries.size())
|
||||
return -1;
|
||||
|
||||
const CGAL::Three::Scene_item* item = m_entries[index];
|
||||
CGAL::Three::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 m_entries.size() - 1;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
const CGAL::Three::Scene_item* item = m_entries[index];
|
||||
CGAL::Three::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 m_entries.size() - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void Scene::initializeGL(CGAL::Three::Viewer_interface* viewer)
|
||||
|
|
@ -486,33 +491,33 @@ void Scene::initializeGL(CGAL::Three::Viewer_interface* viewer)
|
|||
|
||||
void Scene::s_itemAboutToBeDestroyed(CGAL::Three::Scene_item *rmv_itm)
|
||||
{
|
||||
Q_FOREACH(CGAL::Three::Scene_item* item, m_entries)
|
||||
{
|
||||
if(item == rmv_itm)
|
||||
item->itemAboutToBeDestroyed(item);
|
||||
}
|
||||
Q_FOREACH(CGAL::Three::Scene_item* item, m_entries)
|
||||
{
|
||||
if(item == rmv_itm)
|
||||
item->itemAboutToBeDestroyed(item);
|
||||
}
|
||||
}
|
||||
bool
|
||||
Scene::keyPressEvent(QKeyEvent* e){
|
||||
bool res=false;
|
||||
for (QList<int>::iterator it=selected_items_list.begin(),endit=selected_items_list.end();
|
||||
it!=endit;++it)
|
||||
{
|
||||
CGAL::Three::Scene_item* item=m_entries[*it];
|
||||
res |= item->keyPressEvent(e);
|
||||
}
|
||||
return res;
|
||||
Scene::keyPressEvent(QKeyEvent* e)
|
||||
{
|
||||
bool res = false;
|
||||
Q_FOREACH(int i, selected_items_list)
|
||||
{
|
||||
CGAL::Three::Scene_item* item = m_entries[i];
|
||||
res |= item->keyPressEvent(e);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
Scene::draw(CGAL::Three::Viewer_interface* viewer)
|
||||
{
|
||||
draw_aux(false, viewer);
|
||||
draw_aux(false, viewer);
|
||||
}
|
||||
void
|
||||
Scene::drawWithNames(CGAL::Three::Viewer_interface* viewer)
|
||||
{
|
||||
draw_aux(true, viewer);
|
||||
draw_aux(true, viewer);
|
||||
}
|
||||
|
||||
bool item_should_be_skipped_in_draw(Scene_item* item) {
|
||||
|
|
@ -615,12 +620,10 @@ void Scene::renderWireScene(const QList<Scene_interface::Item_id> &items,
|
|||
viewer->setGlPointSize(2.f);
|
||||
if(index == selected_item || selected_items_list.contains(index))
|
||||
{
|
||||
|
||||
item.selection_changed(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
item.selection_changed(false);
|
||||
}
|
||||
item.drawEdges(viewer);
|
||||
|
|
@ -1122,12 +1125,14 @@ bool Scene::dropMimeData(const QMimeData * /*data*/,
|
|||
if(group)
|
||||
{
|
||||
Q_FOREACH(int id, selected_items_list)
|
||||
{
|
||||
if(group->getChildren().contains(id))
|
||||
{
|
||||
one_contained = true;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
//if the drop item is not a group_item or if it already contains the item, then the drop action must be ignored
|
||||
if(!group ||one_contained)
|
||||
|
|
|
|||
|
|
@ -195,8 +195,10 @@ public Q_SLOTS:
|
|||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
//! Sets the target list of indices as the selected indices.
|
||||
QList<int> setSelectedItemsList(QList<int> l )
|
||||
const QList<int>& setSelectedItemIndices(QList<int> l,
|
||||
const bool do_emit = true)
|
||||
{
|
||||
Q_FOREACH(int i,l)
|
||||
{
|
||||
|
|
@ -206,13 +208,38 @@ public Q_SLOTS:
|
|||
{
|
||||
QList<int> list;
|
||||
Q_FOREACH(Item_id id, group->getChildrenForSelection())
|
||||
list<<id;
|
||||
l << setSelectedItemsList(list);
|
||||
list << id;
|
||||
l << setSelectedItemIndices(list, false /*do not emit*/);
|
||||
}
|
||||
|
||||
}
|
||||
selected_items_list = l;
|
||||
return l;
|
||||
if(do_emit)
|
||||
Q_EMIT itemIndicesSelected(selected_items_list);
|
||||
return selected_items_list;
|
||||
}
|
||||
|
||||
//! Sets the target list of indices as the selected indices.
|
||||
const QList<int>& setSelectedItemList(QList<int> l,
|
||||
const bool do_emit = true)
|
||||
{
|
||||
Q_FOREACH(int i,l)
|
||||
{
|
||||
CGAL::Three::Scene_group_item* group =
|
||||
qobject_cast<CGAL::Three::Scene_group_item*>(item(i));
|
||||
if(group)
|
||||
{
|
||||
QList<int> list;
|
||||
Q_FOREACH(Item_id id, group->getChildrenForSelection())
|
||||
list << id;
|
||||
l << setSelectedItemList(list, false /*do not emit*/);
|
||||
}
|
||||
}
|
||||
|
||||
selected_items_list = l;
|
||||
if(do_emit)
|
||||
Q_EMIT selectionChanged(selected_items_list);
|
||||
return selected_items_list;
|
||||
}
|
||||
|
||||
// Accessors (setters)
|
||||
|
|
@ -249,6 +276,8 @@ Q_SIGNALS:
|
|||
void selectionChanged(QList<int> is);
|
||||
//! Used when you don't want to update the selectedItem in the Geometric Objects view.
|
||||
void itemIndexSelected(int i);
|
||||
//! Used when you don't want to update the selectedItem in the Geometric Objects view.
|
||||
void itemIndicesSelected(QList<int> is);
|
||||
//! Emit this to reset the collapsed state of all groups after the Geometric Objects view has been redrawn.
|
||||
void restoreCollapsedState();
|
||||
//! Is emitted when draw() is finished.
|
||||
|
|
|
|||
|
|
@ -1175,11 +1175,11 @@ void* Scene_surface_mesh_item_priv::get_aabb_tree()
|
|||
|
||||
void
|
||||
Scene_surface_mesh_item::select(double orig_x,
|
||||
double orig_y,
|
||||
double orig_z,
|
||||
double dir_x,
|
||||
double dir_y,
|
||||
double dir_z)
|
||||
double orig_y,
|
||||
double orig_z,
|
||||
double dir_x,
|
||||
double dir_y,
|
||||
double dir_z)
|
||||
{
|
||||
SMesh *sm = d->smesh_;
|
||||
std::size_t vertex_to_emit = 0;
|
||||
|
|
@ -2005,7 +2005,7 @@ void Scene_surface_mesh_item::resetColors()
|
|||
d->has_feature_edges = false;
|
||||
}
|
||||
invalidate(COLORS);
|
||||
itemChanged();
|
||||
itemChanged(); // @fixme really shouldn't call something that strong
|
||||
}
|
||||
|
||||
QMenu* Scene_surface_mesh_item::contextMenu()
|
||||
|
|
@ -2387,7 +2387,6 @@ void Scene_surface_mesh_item::computeElements() const
|
|||
{
|
||||
d->compute_elements(ALL);
|
||||
setBuffersFilled(true);
|
||||
const_cast<Scene_surface_mesh_item*>(this)->itemChanged();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -1,79 +1,96 @@
|
|||
#ifndef ID_PRINTING_H
|
||||
#define ID_PRINTING_H
|
||||
#ifndef CGAL_POLYHEDRON_DEMO_ID_PRINTING_H
|
||||
#define CGAL_POLYHEDRON_DEMO_ID_PRINTING_H
|
||||
|
||||
#include <CGAL/boost/graph/selection.h>
|
||||
#include <CGAL/Kernel_traits.h>
|
||||
#include <CGAL/Kernel/global_functions.h>
|
||||
#include <CGAL/Polygon_mesh_processing/compute_normal.h>
|
||||
|
||||
#include <CGAL/Three/Viewer_interface.h>
|
||||
#include <CGAL/Three/TextRenderer.h>
|
||||
#include <CGAL/Three/Three.h>
|
||||
#include <CGAL/Kernel_traits.h>
|
||||
#include <CGAL/Polygon_mesh_processing/compute_normal.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#define POINT_SIZE 11
|
||||
|
||||
template<class Mesh>
|
||||
struct VKRingPMAP{
|
||||
typedef typename boost::graph_traits<Mesh>::vertex_descriptor key_type;
|
||||
typedef bool value_type;
|
||||
typedef value_type reference;
|
||||
typedef boost::read_write_property_map_tag category;
|
||||
typedef typename boost::property_map<Mesh, boost::vertex_index_t>::type IDmap;
|
||||
struct VKRingPMAP
|
||||
{
|
||||
using key_type = typename boost::graph_traits<Mesh>::vertex_descriptor;
|
||||
using value_type = bool;
|
||||
using reference = value_type;
|
||||
using category = boost::read_write_property_map_tag;
|
||||
|
||||
using IDmap = typename boost::property_map<Mesh, boost::vertex_index_t>::type;
|
||||
|
||||
std::vector<bool>* vec;
|
||||
Mesh* poly;
|
||||
IDmap idmap;
|
||||
|
||||
VKRingPMAP(std::vector<bool>* vec, Mesh* poly)
|
||||
:vec(vec), poly(poly)
|
||||
: vec(vec), poly(poly)
|
||||
{
|
||||
idmap = get(boost::vertex_index, *poly);
|
||||
}
|
||||
|
||||
friend value_type get(const VKRingPMAP<Mesh>& map, const key_type& v){
|
||||
friend value_type get(const VKRingPMAP<Mesh>& map, const key_type& v)
|
||||
{
|
||||
return (*map.vec)[get(map.idmap, v)];
|
||||
}
|
||||
friend void put(VKRingPMAP<Mesh>& map, const key_type& v, const value_type i){
|
||||
|
||||
friend void put(VKRingPMAP<Mesh>& map, const key_type& v, const value_type i)
|
||||
{
|
||||
(*map.vec)[get(map.idmap, v)] = i;
|
||||
}
|
||||
};
|
||||
|
||||
template<class Mesh>
|
||||
struct EdgeKRingPMAP{
|
||||
typedef typename boost::graph_traits<Mesh>::edge_descriptor key_type;
|
||||
typedef bool value_type;
|
||||
typedef value_type reference;
|
||||
typedef boost::read_write_property_map_tag category;
|
||||
typedef typename boost::property_map<Mesh, boost::halfedge_index_t>::type IDmap;
|
||||
struct EdgeKRingPMAP
|
||||
{
|
||||
using key_type = typename boost::graph_traits<Mesh>::edge_descriptor;
|
||||
using value_type = bool;
|
||||
using reference = value_type;
|
||||
using category = boost::read_write_property_map_tag;
|
||||
|
||||
using IDmap = typename boost::property_map<Mesh, boost::halfedge_index_t>::type;
|
||||
|
||||
std::vector<bool>* vec;
|
||||
Mesh* poly;
|
||||
IDmap idmap;
|
||||
|
||||
EdgeKRingPMAP(std::vector<bool>* vec, Mesh* poly)
|
||||
:vec(vec), poly(poly)
|
||||
: vec(vec), poly(poly)
|
||||
{
|
||||
idmap = get(boost::halfedge_index, *poly);
|
||||
}
|
||||
|
||||
friend value_type get(const EdgeKRingPMAP<Mesh>& map, const key_type& e){
|
||||
friend value_type get(const EdgeKRingPMAP<Mesh>& map, const key_type& e)
|
||||
{
|
||||
return (*map.vec)[get(map.idmap, halfedge(e, *map.poly))/2];
|
||||
}
|
||||
friend void put(EdgeKRingPMAP<Mesh>& map, const key_type& e, const value_type i){
|
||||
|
||||
friend void put(EdgeKRingPMAP<Mesh>& map, const key_type& e, const value_type i)
|
||||
{
|
||||
(*map.vec)[get(map.idmap, halfedge(e, *map.poly))/2] = i;
|
||||
}
|
||||
};
|
||||
template<class Mesh>
|
||||
struct FKRingPMAP{
|
||||
typedef typename boost::graph_traits<Mesh>::face_descriptor key_type;
|
||||
typedef bool value_type;
|
||||
typedef value_type reference;
|
||||
typedef boost::read_write_property_map_tag category;
|
||||
typedef typename boost::property_map<Mesh, boost::face_index_t>::type IDmap;
|
||||
struct FKRingPMAP
|
||||
{
|
||||
using key_type = typename boost::graph_traits<Mesh>::face_descriptor;
|
||||
using value_type = bool;
|
||||
using reference = value_type;
|
||||
using category = boost::read_write_property_map_tag;
|
||||
|
||||
using IDmap = typename boost::property_map<Mesh, boost::face_index_t>::type;
|
||||
|
||||
std::vector<bool>* vec;
|
||||
Mesh* poly;
|
||||
IDmap idmap;
|
||||
|
||||
FKRingPMAP(std::vector<bool>* vec, Mesh* poly)
|
||||
:vec(vec), poly(poly)
|
||||
: vec(vec), poly(poly)
|
||||
{
|
||||
idmap = get(boost::face_index, *poly);
|
||||
}
|
||||
|
|
@ -81,7 +98,9 @@ struct FKRingPMAP{
|
|||
friend value_type get(const FKRingPMAP<Mesh>& map, const key_type& f){
|
||||
return (*map.vec)[get(map.idmap, f)];
|
||||
}
|
||||
friend void put(FKRingPMAP<Mesh>& map, const key_type& f, const value_type i){
|
||||
|
||||
friend void put(FKRingPMAP<Mesh>& map, const key_type& f, const value_type i)
|
||||
{
|
||||
(*map.vec)[get(map.idmap, f)] = i;
|
||||
}
|
||||
};
|
||||
|
|
@ -91,26 +110,28 @@ void deleteIds(CGAL::Three::Viewer_interface* viewer,
|
|||
TextListItem* fitems,
|
||||
std::vector<TextItem*>* targeted_ids)
|
||||
{
|
||||
TextRenderer *renderer = viewer->textRenderer();
|
||||
TextRenderer* renderer = viewer->textRenderer();
|
||||
|
||||
for(TextItem* it : vitems->textList())
|
||||
delete it;
|
||||
delete it;
|
||||
for(TextItem* it : eitems->textList())
|
||||
delete it;
|
||||
delete it;
|
||||
for(TextItem* it : fitems->textList())
|
||||
delete it;
|
||||
delete it;
|
||||
|
||||
vitems->clear();
|
||||
renderer->removeTextList(vitems);
|
||||
|
||||
eitems->clear();
|
||||
renderer->removeTextList(eitems);
|
||||
|
||||
fitems->clear();
|
||||
renderer->removeTextList(fitems);
|
||||
|
||||
targeted_ids->clear();
|
||||
viewer->update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename Handle, typename Point, typename Tree>
|
||||
bool find_primitive_id(const QPoint& point,
|
||||
Tree* aabb_tree,
|
||||
|
|
@ -118,12 +139,13 @@ bool find_primitive_id(const QPoint& point,
|
|||
Handle& selected_fh,
|
||||
Point& pt_under)
|
||||
{
|
||||
typedef typename CGAL::Kernel_traits<Point>::Kernel Traits;
|
||||
using Traits = typename CGAL::Kernel_traits<Point>::Kernel;
|
||||
|
||||
bool found = false;
|
||||
CGAL::qglviewer::Vec point_under = viewer->camera()->pointUnderPixel(point,found);
|
||||
const CGAL::qglviewer::Vec offset = static_cast<CGAL::Three::Viewer_interface*>(CGAL::QGLViewer::QGLViewerPool().first())->offset();
|
||||
|
||||
//find clicked facet
|
||||
// find clicked facet
|
||||
CGAL::qglviewer::Vec dir;
|
||||
Point ray_origin;
|
||||
if(viewer->camera()->type() == CGAL::qglviewer::Camera::PERSPECTIVE)
|
||||
|
|
@ -151,38 +173,39 @@ bool find_primitive_id(const QPoint& point,
|
|||
|
||||
if(intersections.empty())
|
||||
return false;
|
||||
|
||||
typename Intersections::iterator closest = intersections.begin();
|
||||
const Point* closest_point =
|
||||
boost::get<Point>(&closest->first);
|
||||
for(typename Intersections::iterator
|
||||
it = std::next(intersections.begin()),
|
||||
end = intersections.end();
|
||||
it != end; ++it)
|
||||
const Point* closest_point = boost::get<Point>(&closest->first);
|
||||
for(typename Intersections::iterator it = std::next(intersections.begin()),
|
||||
end = intersections.end(); it != end; ++it)
|
||||
{
|
||||
if(! closest_point) {
|
||||
if(! closest_point)
|
||||
{
|
||||
closest = it;
|
||||
}
|
||||
else {
|
||||
const Point* it_point =
|
||||
boost::get<Point>(&it->first);
|
||||
if(it_point &&
|
||||
(ray_dir * (*it_point - *closest_point)) < 0)
|
||||
else
|
||||
{
|
||||
const Point* it_point = boost::get<Point>(&it->first);
|
||||
if(it_point && (ray_dir * (*it_point - *closest_point)) < 0)
|
||||
{
|
||||
closest = it;
|
||||
closest_point = it_point;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!closest_point)
|
||||
return false;
|
||||
|
||||
pt_under = Point(point_under.x, point_under.y, point_under.z);
|
||||
selected_fh = closest->second;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Mesh, typename Point >
|
||||
template<typename Mesh, typename Point>
|
||||
void compute_displayed_ids(Mesh& mesh,
|
||||
CGAL::Three::Viewer_interface *viewer,
|
||||
CGAL::Three::Viewer_interface* viewer,
|
||||
const typename boost::graph_traits<Mesh>::face_descriptor& selected_fh,
|
||||
const Point& pt_under,
|
||||
const CGAL::qglviewer::Vec& offset,
|
||||
|
|
@ -191,21 +214,21 @@ void compute_displayed_ids(Mesh& mesh,
|
|||
TextListItem* fitems,
|
||||
std::vector<TextItem*>* targeted_ids)
|
||||
{
|
||||
typedef typename boost::graph_traits<Mesh>::face_descriptor face_descriptor;
|
||||
typedef typename boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename boost::graph_traits<Mesh>::edge_descriptor edge_descriptor;
|
||||
typedef typename boost::graph_traits<Mesh>::halfedge_descriptor halfedge_descriptor;
|
||||
using vertex_descriptor = typename boost::graph_traits<Mesh>::vertex_descriptor;
|
||||
using halfedge_descriptor = typename boost::graph_traits<Mesh>::halfedge_descriptor;
|
||||
using edge_descriptor = typename boost::graph_traits<Mesh>::edge_descriptor;
|
||||
using face_descriptor = typename boost::graph_traits<Mesh>::face_descriptor;
|
||||
|
||||
typedef typename boost::property_map<Mesh, boost::vertex_point_t>::type Ppmap;
|
||||
using Ppmap = typename boost::property_map<Mesh, boost::vertex_point_t>::type;
|
||||
Ppmap ppmap = get(boost::vertex_point, mesh);
|
||||
|
||||
typedef typename boost::property_map<Mesh, boost::vertex_index_t>::type VIDmap;
|
||||
using VIDmap = typename boost::property_map<Mesh, boost::vertex_index_t>::type;
|
||||
VIDmap vidmap = get(boost::vertex_index, mesh);
|
||||
|
||||
typedef typename boost::property_map<Mesh, boost::halfedge_index_t>::type HIDmap;
|
||||
using HIDmap = typename boost::property_map<Mesh, boost::halfedge_index_t>::type;
|
||||
HIDmap hidmap = get(boost::halfedge_index, mesh);
|
||||
|
||||
typedef typename boost::property_map<Mesh, boost::face_index_t>::type FIDmap;
|
||||
using FIDmap = typename boost::property_map<Mesh, boost::face_index_t>::type;
|
||||
FIDmap fidmap = get(boost::face_index, mesh);
|
||||
|
||||
QFont font;
|
||||
|
|
@ -214,70 +237,77 @@ void compute_displayed_ids(Mesh& mesh,
|
|||
std::vector<vertex_descriptor> displayed_vertices;
|
||||
std::vector<edge_descriptor> displayed_edges;
|
||||
std::vector<face_descriptor> displayed_faces;
|
||||
//Test spots around facet to find the closest to point
|
||||
// Test spots around facet to find the closest to point
|
||||
|
||||
double min_dist = (std::numeric_limits<double>::max)();
|
||||
|
||||
// test the vertices of the closest face
|
||||
for(vertex_descriptor vh : vertices_around_face(halfedge(selected_fh, mesh), mesh))
|
||||
{
|
||||
Point test=Point(get(ppmap, vh).x()+offset.x,
|
||||
get(ppmap, vh).y()+offset.y,
|
||||
get(ppmap, vh).z()+offset.z);
|
||||
Point test=Point(get(ppmap, vh).x() + offset.x,
|
||||
get(ppmap, vh).y() + offset.y,
|
||||
get(ppmap, vh).z() + offset.z);
|
||||
double dist = CGAL::squared_distance(test, pt_under);
|
||||
if( dist < min_dist){
|
||||
if(dist < min_dist)
|
||||
{
|
||||
min_dist = dist;
|
||||
displayed_vertices.clear();
|
||||
displayed_vertices.push_back(vh);
|
||||
}
|
||||
}
|
||||
QVector3D point(
|
||||
float(get(ppmap, displayed_vertices[0]).x() + offset.x),
|
||||
float(get(ppmap, displayed_vertices[0]).y() + offset.y),
|
||||
float(get(ppmap, displayed_vertices[0]).z() + offset.z));
|
||||
|
||||
//test if we want to erase or not
|
||||
QVector3D point(float(get(ppmap, displayed_vertices[0]).x() + offset.x),
|
||||
float(get(ppmap, displayed_vertices[0]).y() + offset.y),
|
||||
float(get(ppmap, displayed_vertices[0]).z() + offset.z));
|
||||
|
||||
// test if we want to erase or not
|
||||
for(TextItem* text_item : *targeted_ids)
|
||||
{
|
||||
if(text_item->position() == point)
|
||||
{
|
||||
//hide and stop
|
||||
// hide and stop
|
||||
deleteIds(viewer, vitems, eitems, fitems, targeted_ids);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
deleteIds(viewer, vitems, eitems, fitems, targeted_ids);
|
||||
|
||||
// test the midpoint of edges of the closest face
|
||||
for(halfedge_descriptor e : halfedges_around_face(halfedge(selected_fh, mesh), mesh))
|
||||
{
|
||||
Point test=CGAL::midpoint(get(ppmap, source(e, mesh)),get(ppmap, target(e, mesh)));
|
||||
Point test = CGAL::midpoint(get(ppmap, source(e, mesh)),get(ppmap, target(e, mesh)));
|
||||
test = Point(test.x()+offset.x,
|
||||
test.y()+offset.y,
|
||||
test.z()+offset.z);
|
||||
double dist = CGAL::squared_distance(test, pt_under);
|
||||
if(dist < min_dist){
|
||||
if(dist < min_dist)
|
||||
{
|
||||
min_dist = dist;
|
||||
displayed_vertices.clear();
|
||||
displayed_edges.clear();
|
||||
displayed_edges.push_back(edge(e, mesh));
|
||||
}
|
||||
}
|
||||
|
||||
// test the centroid of the closest face
|
||||
double x(0), y(0), z(0);
|
||||
int total(0);
|
||||
for(vertex_descriptor vh : vertices_around_face(halfedge(selected_fh, mesh), mesh))
|
||||
{
|
||||
x+=get(ppmap, vh).x();
|
||||
y+=get(ppmap, vh).y();
|
||||
z+=get(ppmap, vh).z();
|
||||
x += get(ppmap, vh).x();
|
||||
y += get(ppmap, vh).y();
|
||||
z += get(ppmap, vh).z();
|
||||
++total;
|
||||
}
|
||||
|
||||
Point test(x/total+offset.x,
|
||||
y/total+offset.y,
|
||||
z/total+offset.z);
|
||||
Point test(x / total+offset.x,
|
||||
y / total+offset.y,
|
||||
z / total+offset.z);
|
||||
|
||||
double dist = CGAL::squared_distance(test, pt_under);
|
||||
if(dist < min_dist){
|
||||
if(dist < min_dist)
|
||||
{
|
||||
min_dist = dist;
|
||||
displayed_vertices.clear();
|
||||
displayed_edges.clear();
|
||||
|
|
@ -293,23 +323,21 @@ void compute_displayed_ids(Mesh& mesh,
|
|||
if(f != boost::graph_traits<Mesh>::null_face())
|
||||
displayed_faces.push_back(f);
|
||||
}
|
||||
|
||||
for(halfedge_descriptor h : CGAL::halfedges_around_target(halfedge(displayed_vertices[0], mesh), mesh))
|
||||
{
|
||||
displayed_edges.push_back(edge(h, mesh));
|
||||
}
|
||||
}
|
||||
else if(!displayed_edges.empty())
|
||||
{
|
||||
displayed_vertices.push_back(target(halfedge(displayed_edges[0], mesh), mesh));
|
||||
displayed_vertices.push_back(target(opposite(halfedge(displayed_edges[0], mesh), mesh),mesh));
|
||||
face_descriptor f1(face(halfedge(displayed_edges[0], mesh),mesh)),
|
||||
f2(face(opposite(halfedge(displayed_edges[0], mesh), mesh),mesh));
|
||||
f2(face(opposite(halfedge(displayed_edges[0], mesh), mesh),mesh));
|
||||
if(f1 != boost::graph_traits<Mesh>::null_face())
|
||||
displayed_faces.push_back(f1);
|
||||
if(f2 != boost::graph_traits<Mesh>::null_face())
|
||||
displayed_faces.push_back(f2);
|
||||
}
|
||||
|
||||
else if(!displayed_faces.empty())
|
||||
{
|
||||
for(halfedge_descriptor h : CGAL::halfedges_around_face(halfedge(displayed_faces[0], mesh), mesh))
|
||||
|
|
@ -318,7 +346,8 @@ void compute_displayed_ids(Mesh& mesh,
|
|||
displayed_vertices.push_back(target(h, mesh));
|
||||
}
|
||||
}
|
||||
//fill TextItems
|
||||
|
||||
// fill TextItems
|
||||
std::vector<bool> vertex_selection(false);
|
||||
vertex_selection.resize(num_vertices(mesh));
|
||||
VKRingPMAP<Mesh> vpmap(&vertex_selection, &mesh);
|
||||
|
|
@ -345,9 +374,7 @@ void compute_displayed_ids(Mesh& mesh,
|
|||
face_selection.resize(num_faces(mesh));
|
||||
FKRingPMAP<Mesh> fpmap(&face_selection, &mesh);
|
||||
for(face_descriptor f_h : displayed_faces)
|
||||
{
|
||||
put(fpmap, f_h, true);
|
||||
}
|
||||
put(fpmap, f_h, true);
|
||||
CGAL::expand_face_selection(displayed_faces,
|
||||
mesh,
|
||||
1,
|
||||
|
|
@ -356,9 +383,9 @@ void compute_displayed_ids(Mesh& mesh,
|
|||
|
||||
for(vertex_descriptor vh : displayed_vertices)
|
||||
{
|
||||
Point pos=Point(get(ppmap, vh).x()+offset.x,
|
||||
get(ppmap, vh).y()+offset.y,
|
||||
get(ppmap, vh).z()+offset.z);
|
||||
Point pos = Point(get(ppmap, vh).x() + offset.x,
|
||||
get(ppmap, vh).y() + offset.y,
|
||||
get(ppmap, vh).z() + offset.z);
|
||||
TextItem* text_item = new TextItem(float(pos.x()),
|
||||
float(pos.y()),
|
||||
float(pos.z()),
|
||||
|
|
@ -366,13 +393,14 @@ void compute_displayed_ids(Mesh& mesh,
|
|||
vitems->append(text_item);
|
||||
targeted_ids->push_back(text_item);
|
||||
}
|
||||
|
||||
for(edge_descriptor e : displayed_edges)
|
||||
{
|
||||
halfedge_descriptor h(halfedge(e, mesh));
|
||||
Point pos=CGAL::midpoint(get(ppmap, source(h, mesh)),get(ppmap, target(h, mesh)));
|
||||
pos = Point(pos.x()+offset.x,
|
||||
pos.y()+offset.y,
|
||||
pos.z()+offset.z);
|
||||
halfedge_descriptor h(halfedge(e, mesh));
|
||||
Point pos = CGAL::midpoint(get(ppmap, source(h, mesh)),get(ppmap, target(h, mesh)));
|
||||
pos = Point(pos.x() + offset.x,
|
||||
pos.y() + offset.y,
|
||||
pos.z() + offset.z);
|
||||
|
||||
TextItem* text_item = new TextItem(float(pos.x()),
|
||||
float(pos.y()),
|
||||
|
|
@ -387,15 +415,15 @@ void compute_displayed_ids(Mesh& mesh,
|
|||
int total(0);
|
||||
for(vertex_descriptor vh :vertices_around_face(halfedge(f, mesh), mesh))
|
||||
{
|
||||
x+=get(ppmap, vh).x();
|
||||
y+=get(ppmap, vh).y();
|
||||
z+=get(ppmap, vh).z();
|
||||
x += get(ppmap, vh).x();
|
||||
y += get(ppmap, vh).y();
|
||||
z += get(ppmap, vh).z();
|
||||
++total;
|
||||
}
|
||||
|
||||
Point pos(x/total+offset.x,
|
||||
y/total+offset.y,
|
||||
z/total+offset.z);
|
||||
Point pos(x/total + offset.x,
|
||||
y/total + offset.y,
|
||||
z/total + offset.z);
|
||||
TextItem* text_item = new TextItem(float(pos.x()),
|
||||
float(pos.y()),
|
||||
float(pos.z()),
|
||||
|
|
@ -408,18 +436,20 @@ template<class Mesh>
|
|||
bool printVertexIds(const Mesh& mesh,
|
||||
TextListItem* vitems)
|
||||
{
|
||||
typedef typename boost::property_map<Mesh, boost::vertex_point_t>::const_type Ppmap;
|
||||
typedef typename boost::property_traits<Ppmap>::value_type Point;
|
||||
typedef typename boost::property_map<Mesh, boost::vertex_index_t>::type IDmap;
|
||||
using Ppmap = typename boost::property_map<Mesh, boost::vertex_point_t>::const_type;
|
||||
using Point = typename boost::property_traits<Ppmap>::value_type;
|
||||
using IDmap = typename boost::property_map<Mesh, boost::vertex_index_t>::type;
|
||||
|
||||
Ppmap ppmap = get(boost::vertex_point, mesh);
|
||||
IDmap idmap = get(boost::vertex_index, mesh);
|
||||
|
||||
const CGAL::qglviewer::Vec offset = CGAL::Three::Three::mainViewer()->offset();
|
||||
|
||||
QFont font;
|
||||
font.setBold(true);
|
||||
font.setPointSize(POINT_SIZE);
|
||||
|
||||
//fills textItems
|
||||
// fills textItems
|
||||
for(typename boost::graph_traits<Mesh>::vertex_descriptor vh : vertices(mesh))
|
||||
{
|
||||
const Point& p = get(ppmap, vh);
|
||||
|
|
@ -429,7 +459,8 @@ bool printVertexIds(const Mesh& mesh,
|
|||
QString("%1").arg(get(idmap, vh)), true, font, Qt::red));
|
||||
|
||||
}
|
||||
//add the QList to the render's pool
|
||||
|
||||
// add the QList to the render's pool
|
||||
bool res = true;
|
||||
Q_FOREACH(CGAL::QGLViewer* v, CGAL::QGLViewer::QGLViewerPool())
|
||||
{
|
||||
|
|
@ -437,10 +468,9 @@ bool printVertexIds(const Mesh& mesh,
|
|||
renderer->addTextList(vitems);
|
||||
v->update();
|
||||
if(vitems->size() > static_cast<std::size_t>(renderer->getMax_textItems()))
|
||||
{
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -448,13 +478,15 @@ template<class Mesh>
|
|||
bool printEdgeIds(const Mesh& mesh,
|
||||
TextListItem* eitems)
|
||||
{
|
||||
typedef typename boost::property_map<Mesh, boost::vertex_point_t>::const_type Ppmap;
|
||||
typedef typename boost::property_traits<Ppmap>::value_type Point;
|
||||
typedef typename boost::property_map<Mesh, boost::halfedge_index_t>::type IDmap;
|
||||
using Ppmap = typename boost::property_map<Mesh, boost::vertex_point_t>::const_type;
|
||||
using Point = typename boost::property_traits<Ppmap>::value_type;
|
||||
using IDmap = typename boost::property_map<Mesh, boost::halfedge_index_t>::type;
|
||||
|
||||
Ppmap ppmap = get(boost::vertex_point, mesh);
|
||||
IDmap idmap = get(boost::halfedge_index, mesh);
|
||||
|
||||
const CGAL::qglviewer::Vec offset = CGAL::Three::Three::mainViewer()->offset();
|
||||
|
||||
QFont font;
|
||||
font.setBold(true);
|
||||
font.setPointSize(POINT_SIZE);
|
||||
|
|
@ -468,7 +500,8 @@ bool printEdgeIds(const Mesh& mesh,
|
|||
float((p1.z() + p2.z()) / 2 + offset.z),
|
||||
QString("%1").arg(get(idmap, halfedge(e, mesh)) / 2), true, font, Qt::green));
|
||||
}
|
||||
//add the QList to the render's pool
|
||||
|
||||
// add the QList to the render's pool
|
||||
bool res = true;
|
||||
Q_FOREACH(CGAL::QGLViewer* v, CGAL::QGLViewer::QGLViewerPool())
|
||||
{
|
||||
|
|
@ -476,10 +509,9 @@ bool printEdgeIds(const Mesh& mesh,
|
|||
renderer->addTextList(eitems);
|
||||
v->update();
|
||||
if(eitems->size() > static_cast<std::size_t>(renderer->getMax_textItems()))
|
||||
{
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -487,15 +519,18 @@ template<class Mesh>
|
|||
bool printFaceIds(const Mesh& mesh,
|
||||
TextListItem* fitems)
|
||||
{
|
||||
typedef typename boost::property_map<Mesh, boost::vertex_point_t>::const_type Ppmap;
|
||||
typedef typename boost::property_map<Mesh, boost::face_index_t>::type IDmap;
|
||||
using Ppmap = typename boost::property_map<Mesh, boost::vertex_point_t>::const_type;
|
||||
using IDmap = typename boost::property_map<Mesh, boost::face_index_t>::type;
|
||||
|
||||
Ppmap ppmap = get(boost::vertex_point, mesh);
|
||||
IDmap idmap = get(boost::face_index, mesh);
|
||||
|
||||
const CGAL::qglviewer::Vec offset = CGAL::Three::Three::mainViewer()->offset();
|
||||
|
||||
QFont font;
|
||||
font.setBold(true);
|
||||
font.setPointSize(POINT_SIZE);
|
||||
|
||||
for(typename boost::graph_traits<Mesh>::face_descriptor fh : faces(mesh))
|
||||
{
|
||||
double x(0), y(0), z(0);
|
||||
|
|
@ -513,7 +548,8 @@ bool printFaceIds(const Mesh& mesh,
|
|||
float(z / total + offset.z),
|
||||
QString("%1").arg(get(idmap, fh)), true, font, Qt::blue));
|
||||
}
|
||||
//add the QList to the render's pool
|
||||
|
||||
// add the QList to the render's pool
|
||||
bool res = true;
|
||||
Q_FOREACH(CGAL::QGLViewer* v, CGAL::QGLViewer::QGLViewerPool())
|
||||
{
|
||||
|
|
@ -521,9 +557,7 @@ bool printFaceIds(const Mesh& mesh,
|
|||
renderer->addTextList(fitems);
|
||||
v->update();
|
||||
if(fitems->size() > static_cast<std::size_t>(renderer->getMax_textItems()))
|
||||
{
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
@ -535,14 +569,15 @@ int zoomToId(const Mesh& mesh,
|
|||
typename boost::graph_traits<Mesh>::face_descriptor& selected_fh,
|
||||
Point& p)
|
||||
{
|
||||
typedef typename boost::graph_traits<Mesh>::face_descriptor face_descriptor;
|
||||
typedef typename boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename boost::property_map<Mesh, boost::vertex_point_t>::const_type Ppmap;
|
||||
typedef typename boost::property_map<Mesh, boost::vertex_index_t>::type VIDmap;
|
||||
typedef typename boost::property_map<Mesh, boost::halfedge_index_t>::type EIDmap;
|
||||
typedef typename boost::property_map<Mesh, boost::face_index_t>::type FIDmap;
|
||||
typedef typename CGAL::Kernel_traits<Point>::Kernel Traits;
|
||||
using vertex_descriptor = typename boost::graph_traits<Mesh>::vertex_descriptor;
|
||||
using face_descriptor = typename boost::graph_traits<Mesh>::face_descriptor;
|
||||
|
||||
using Ppmap = typename boost::property_map<Mesh, boost::vertex_point_t>::const_type;
|
||||
using VIDmap = typename boost::property_map<Mesh, boost::vertex_index_t>::type;
|
||||
using EIDmap = typename boost::property_map<Mesh, boost::halfedge_index_t>::type;
|
||||
using FIDmap = typename boost::property_map<Mesh, boost::face_index_t>::type;
|
||||
|
||||
using Traits = typename CGAL::Kernel_traits<Point>::Kernel;
|
||||
|
||||
Ppmap ppmap = get(boost::vertex_point, mesh);
|
||||
VIDmap vidmap = get(boost::vertex_index, mesh);
|
||||
|
|
@ -555,10 +590,11 @@ int zoomToId(const Mesh& mesh,
|
|||
if((first != QString("v") &&
|
||||
first != QString("e") &&
|
||||
first != QString("f")) ||
|
||||
!is_int)
|
||||
!is_int)
|
||||
{
|
||||
return 1; //("Input must be of the form [v/e/f][int]"
|
||||
}
|
||||
|
||||
const CGAL::qglviewer::Vec offset = viewer->offset();
|
||||
typename Traits::Vector_3 normal;
|
||||
if(first == QString("v"))
|
||||
|
|
@ -567,26 +603,25 @@ int zoomToId(const Mesh& mesh,
|
|||
for(vertex_descriptor vh : vertices(mesh))
|
||||
{
|
||||
std::size_t cur_id = get(vidmap, vh);
|
||||
if( cur_id == id)
|
||||
if(cur_id == id)
|
||||
{
|
||||
p = Point(get(ppmap, vh).x() + offset.x,
|
||||
get(ppmap, vh).y() + offset.y,
|
||||
get(ppmap, vh).z() + offset.z);
|
||||
|
||||
typename boost::graph_traits<Mesh>::halfedge_descriptor hf = halfedge(vh, mesh);
|
||||
if(CGAL::is_border(hf, mesh))
|
||||
{
|
||||
hf = opposite(hf, mesh);
|
||||
}
|
||||
|
||||
selected_fh = face(hf, mesh);
|
||||
normal = CGAL::Polygon_mesh_processing::compute_vertex_normal(vh, mesh);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!found)
|
||||
{
|
||||
return 2;//"No vertex with id %1").arg(id)
|
||||
}
|
||||
return 2; // "No vertex with id %1").arg(id)
|
||||
}
|
||||
else if(first == QString("e"))
|
||||
{
|
||||
|
|
@ -604,10 +639,10 @@ int zoomToId(const Mesh& mesh,
|
|||
typename Traits::Vector_3 normal1(0,0,0);
|
||||
if(!is_border(hf, mesh))
|
||||
{
|
||||
normal1= CGAL::Polygon_mesh_processing::compute_face_normal(face(hf,mesh),
|
||||
mesh);
|
||||
normal1 = CGAL::Polygon_mesh_processing::compute_face_normal(face(hf,mesh), mesh);
|
||||
selected_fh = face(hf, mesh);
|
||||
}
|
||||
|
||||
typename Traits::Vector_3 normal2(0,0,0);
|
||||
if(!is_border(opposite(hf, mesh), mesh))
|
||||
{
|
||||
|
|
@ -615,15 +650,15 @@ int zoomToId(const Mesh& mesh,
|
|||
mesh);
|
||||
selected_fh = face(hf, mesh);
|
||||
}
|
||||
normal = 0.5*normal1+0.5*normal2;
|
||||
|
||||
normal = 0.5*normal1 + 0.5*normal2;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!found)
|
||||
{
|
||||
return 3;//"No edge with id %1").arg(id)
|
||||
}
|
||||
return 3; // "No edge with id %1").arg(id)
|
||||
}
|
||||
else if(first == QString("f"))
|
||||
{
|
||||
|
|
@ -634,30 +669,30 @@ int zoomToId(const Mesh& mesh,
|
|||
{
|
||||
if(get(fidmap, fh) != id)
|
||||
continue;
|
||||
|
||||
for(vertex_descriptor vh : vertices_around_face(halfedge(fh, mesh), mesh))
|
||||
{
|
||||
x+=get(ppmap, vh).x();
|
||||
y+=get(ppmap, vh).y();
|
||||
z+=get(ppmap, vh).z();
|
||||
x += get(ppmap, vh).x();
|
||||
y += get(ppmap, vh).y();
|
||||
z += get(ppmap, vh).z();
|
||||
++total;
|
||||
}
|
||||
|
||||
p = Point(x/total + offset.x,
|
||||
y/total + offset.y,
|
||||
z/total + offset.z);
|
||||
normal = CGAL::Polygon_mesh_processing::compute_face_normal(
|
||||
fh,
|
||||
mesh);
|
||||
y/total + offset.y,
|
||||
z/total + offset.z);
|
||||
normal = CGAL::Polygon_mesh_processing::compute_face_normal(fh, mesh);
|
||||
selected_fh = fh;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!found)
|
||||
{
|
||||
return 4; //"No face with id %1").arg(id)
|
||||
}
|
||||
return 4; // "No face with id %1").arg(id)
|
||||
}
|
||||
|
||||
CGAL::qglviewer::Quaternion new_orientation(CGAL::qglviewer::Vec(0,0,-1),
|
||||
CGAL::qglviewer::Vec(-normal.x(), -normal.y(), -normal.z()));
|
||||
CGAL::qglviewer::Vec(-normal.x(), -normal.y(), -normal.z()));
|
||||
Point new_pos = p +
|
||||
0.25*CGAL::qglviewer::Vec(
|
||||
viewer->camera()->position().x - viewer->camera()->pivotPoint().x,
|
||||
|
|
@ -665,19 +700,69 @@ int zoomToId(const Mesh& mesh,
|
|||
viewer->camera()->position().z - viewer->camera()->pivotPoint().z)
|
||||
.norm() * normal ;
|
||||
|
||||
viewer->camera()->setPivotPoint(CGAL::qglviewer::Vec(p.x(),
|
||||
p.y(),
|
||||
p.z()));
|
||||
viewer->camera()->setPivotPoint(CGAL::qglviewer::Vec(p.x(), p.y(), p.z()));
|
||||
|
||||
viewer->moveCameraToCoordinates(QString("%1 %2 %3 %4 %5 %6 %7").arg(new_pos.x())
|
||||
.arg(new_pos.y())
|
||||
.arg(new_pos.z())
|
||||
.arg(new_orientation[0])
|
||||
.arg(new_orientation[1])
|
||||
.arg(new_orientation[2])
|
||||
.arg(new_orientation[3]));
|
||||
.arg(new_pos.y())
|
||||
.arg(new_pos.z())
|
||||
.arg(new_orientation[0])
|
||||
.arg(new_orientation[1])
|
||||
.arg(new_orientation[2])
|
||||
.arg(new_orientation[3]));
|
||||
viewer->update();
|
||||
return 0; //all clear;
|
||||
}
|
||||
#endif // ID_PRINTING_H
|
||||
|
||||
return 0; // all clear;
|
||||
}
|
||||
|
||||
template<class PointSet>
|
||||
int zoomToPoint(const PointSet& ps,
|
||||
const typename PointSet::Index& index,
|
||||
CGAL::Three::Viewer_interface* viewer,
|
||||
typename PointSet::Point_3& p)
|
||||
{
|
||||
const CGAL::qglviewer::Vec offset = viewer->offset();
|
||||
|
||||
using Point_3 = typename PointSet::Point_3;
|
||||
using Vector_3 = typename PointSet::Vector_3;
|
||||
|
||||
const Point_3& op = ps.point(index);
|
||||
|
||||
p = Point_3(op.x() + offset.x,
|
||||
op.y() + offset.y,
|
||||
op.z() + offset.z);
|
||||
|
||||
Vector_3 normal;
|
||||
if(ps.has_normal_map())
|
||||
normal = ps.normal(index);
|
||||
else
|
||||
normal = { viewer->camera()->position().x - viewer->camera()->pivotPoint().x,
|
||||
viewer->camera()->position().y - viewer->camera()->pivotPoint().y,
|
||||
viewer->camera()->position().z - viewer->camera()->pivotPoint().z };
|
||||
|
||||
Point_3 new_pos = p +
|
||||
0.25 * CGAL::qglviewer::Vec(
|
||||
viewer->camera()->position().x - viewer->camera()->pivotPoint().x,
|
||||
viewer->camera()->position().y - viewer->camera()->pivotPoint().y,
|
||||
viewer->camera()->position().z - viewer->camera()->pivotPoint().z)
|
||||
.norm() * normal ;
|
||||
|
||||
viewer->camera()->setPivotPoint(CGAL::qglviewer::Vec(p.x(), p.y(), p.z()));
|
||||
|
||||
CGAL::qglviewer::Quaternion new_orientation(CGAL::qglviewer::Vec(0,0,-1),
|
||||
CGAL::qglviewer::Vec(-normal.x(), -normal.y(), -normal.z()));
|
||||
|
||||
viewer->moveCameraToCoordinates(QString("%1 %2 %3 %4 %5 %6 %7").arg(new_pos.x())
|
||||
.arg(new_pos.y())
|
||||
.arg(new_pos.z())
|
||||
.arg(new_orientation[0])
|
||||
.arg(new_orientation[1])
|
||||
.arg(new_orientation[2])
|
||||
.arg(new_orientation[3]));
|
||||
|
||||
viewer->update();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // CGAL_POLYHEDRON_DEMO_ID_PRINTING_H
|
||||
|
||||
|
|
|
|||
|
|
@ -1,234 +1,246 @@
|
|||
#ifndef TRIANGULATE_PRIMITIVE
|
||||
#define TRIANGULATE_PRIMITIVE
|
||||
#ifndef CGAL_DEMO_TRIANGULATE_PRIMITIVE_H
|
||||
#define CGAL_DEMO_TRIANGULATE_PRIMITIVE_H
|
||||
|
||||
#include <CGAL/Three/Scene_item.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/Projection_traits_3.h>
|
||||
#include <CGAL/Three/Scene_item.h>
|
||||
#include <queue>
|
||||
|
||||
#include <QColor>
|
||||
|
||||
//Make sure all the facets are triangles
|
||||
#include <CGAL/boost/graph/properties.h>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
// Ensure that all the facets are triangles
|
||||
// @todo just use PMP::triangulate_face()...?
|
||||
// or at least mark_faces_in_domain()
|
||||
|
||||
template<class Mesh, typename Kernel, typename Index_type>
|
||||
class FacetTriangulator
|
||||
{
|
||||
typedef Kernel Traits;
|
||||
public:
|
||||
using Traits = Kernel;
|
||||
using Point = typename Kernel::Point_3;
|
||||
using Vector = typename Kernel::Vector_3;
|
||||
|
||||
typedef typename boost::graph_traits<Mesh>::halfedge_descriptor halfedge_descriptor;
|
||||
using P_traits = CGAL::Projection_traits_3<Traits>;
|
||||
|
||||
typedef typename Kernel::Vector_3 Vector;
|
||||
using halfedge_descriptor = typename boost::graph_traits<Mesh>::halfedge_descriptor;
|
||||
using face_descriptor = typename boost::graph_traits<Mesh>::face_descriptor;
|
||||
|
||||
struct Face_info
|
||||
{
|
||||
typename boost::graph_traits<Mesh>::halfedge_descriptor e[3];
|
||||
bool is_external;
|
||||
};
|
||||
|
||||
typedef CGAL::Projection_traits_3<Traits> P_traits;
|
||||
using Vb = CGAL::Triangulation_vertex_base_with_info_2<halfedge_descriptor, P_traits>;
|
||||
using Fbb = CGAL::Triangulation_face_base_with_info_2<Face_info, P_traits>;
|
||||
using Fb = CGAL::Constrained_triangulation_face_base_2<P_traits, Fbb>;
|
||||
using TDS = CGAL::Triangulation_data_structure_2<Vb, Fb>;
|
||||
using Itag = CGAL::Exact_predicates_tag;
|
||||
using CDT = CGAL::Constrained_Delaunay_triangulation_2<P_traits, TDS, Itag>;
|
||||
|
||||
typedef CGAL::Triangulation_vertex_base_with_info_2<halfedge_descriptor,
|
||||
P_traits> Vb;
|
||||
using Vertex_handle = typename CDT::Vertex_handle;
|
||||
using Face_handle = typename CDT::Face_handle;
|
||||
|
||||
struct Face_info {
|
||||
typename boost::graph_traits<Mesh>::halfedge_descriptor 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::Exact_predicates_tag Itag;
|
||||
struct PointAndId
|
||||
{
|
||||
Point point;
|
||||
Index_type id;
|
||||
PointAndId() = default;
|
||||
PointAndId(const Point& point, const Index_type id) : point(point), id(id) { }
|
||||
};
|
||||
|
||||
public:
|
||||
struct PointAndId {
|
||||
typename Kernel::Point_3 point;
|
||||
Index_type id;
|
||||
};
|
||||
CDT* cdt;
|
||||
CGAL::Unique_hash_map<Vertex_handle, Index_type> v2v;
|
||||
|
||||
typedef CGAL::Constrained_Delaunay_triangulation_2<P_traits,
|
||||
TDS,
|
||||
Itag> CDT;
|
||||
CDT *cdt;
|
||||
CGAL::Unique_hash_map<typename CDT::Vertex_handle, Index_type> v2v;
|
||||
|
||||
//Constructor
|
||||
FacetTriangulator(typename boost::graph_traits<Mesh>::face_descriptor fd,
|
||||
public:
|
||||
// Constructor
|
||||
FacetTriangulator(face_descriptor fd,
|
||||
const Vector& normal,
|
||||
Mesh *poly,
|
||||
Mesh* poly,
|
||||
Vector offset = Vector(0,0,0))
|
||||
{
|
||||
std::vector<PointAndId> idPoints;
|
||||
for(halfedge_descriptor he_circ : halfedges_around_face( halfedge(fd, *poly), *poly))
|
||||
{
|
||||
PointAndId idPoint;
|
||||
idPoint.point = get(boost::vertex_point,*poly,source(he_circ, *poly))+offset;
|
||||
idPoint.id = source(he_circ, *poly);
|
||||
idPoints.push_back(idPoint);
|
||||
for(halfedge_descriptor he_circ : halfedges_around_face(halfedge(fd, *poly), *poly))
|
||||
idPoints.emplace_back(get(CGAL::vertex_point, *poly, source(he_circ, *poly)) + offset,
|
||||
source(he_circ, *poly));
|
||||
|
||||
}
|
||||
if(!triangulate(idPoints, normal))
|
||||
std::cerr<<"Facet not displayed"<<std::endl;
|
||||
std::cerr << "Facet not displayed" << std::endl;
|
||||
}
|
||||
FacetTriangulator(typename boost::graph_traits<Mesh>::face_descriptor fd,
|
||||
const std::vector<typename Kernel::Point_3>& more_points,
|
||||
|
||||
FacetTriangulator(face_descriptor fd,
|
||||
const std::vector<Point>& more_points,
|
||||
const Vector& normal,
|
||||
Mesh *poly,
|
||||
Mesh* poly,
|
||||
Vector offset = Vector(0,0,0))
|
||||
{
|
||||
std::vector<PointAndId> idPoints;
|
||||
for(halfedge_descriptor he_circ : halfedges_around_face( halfedge(fd, *poly), *poly))
|
||||
{
|
||||
PointAndId idPoint;
|
||||
idPoint.point = get(boost::vertex_point,*poly,source(he_circ, *poly))+offset;
|
||||
idPoint.id = source(he_circ, *poly);
|
||||
idPoints.push_back(idPoint);
|
||||
std::vector<PointAndId> idPoints;
|
||||
for(halfedge_descriptor he_circ : halfedges_around_face(halfedge(fd, *poly), *poly))
|
||||
idPoints.emplace_back(get(CGAL::vertex_point, *poly, source(he_circ, *poly)) + offset,
|
||||
source(he_circ, *poly));
|
||||
|
||||
}
|
||||
if(!triangulate_with_points(idPoints,more_points, normal))
|
||||
std::cerr<<"Facet not displayed"<<std::endl;
|
||||
if(!triangulate_with_points(idPoints, more_points, normal))
|
||||
std::cerr << "Facet not displayed" << std::endl;
|
||||
}
|
||||
|
||||
FacetTriangulator(std::vector<PointAndId > &idPoints,
|
||||
const Vector& normal)
|
||||
{
|
||||
if(!triangulate(idPoints, normal))
|
||||
std::cerr<<"Facet not displayed"<<std::endl;
|
||||
}
|
||||
FacetTriangulator(std::vector<PointAndId > &idPoints,
|
||||
const std::vector<typename Kernel::Point_3>& more_points,
|
||||
FacetTriangulator(std::vector<PointAndId>& idPoints,
|
||||
const Vector& normal)
|
||||
{
|
||||
if(!triangulate_with_points(idPoints, more_points, normal))
|
||||
std::cerr<<"Facet not displayed"<<std::endl;
|
||||
|
||||
if(!triangulate(idPoints, normal))
|
||||
std::cerr << "Facet not displayed" << std::endl;
|
||||
}
|
||||
FacetTriangulator(std::vector<PointAndId>& idPoints,
|
||||
const std::vector<Point>& more_points,
|
||||
const Vector& normal)
|
||||
{
|
||||
if(!triangulate_with_points(idPoints, more_points, normal))
|
||||
std::cerr << "Facet not displayed" << std::endl;
|
||||
}
|
||||
|
||||
~FacetTriangulator()
|
||||
{
|
||||
if (cdt )
|
||||
delete cdt;
|
||||
if(cdt)
|
||||
delete cdt;
|
||||
}
|
||||
|
||||
private:
|
||||
bool triangulate( std::vector<PointAndId > &idPoints,
|
||||
const Vector& normal )
|
||||
bool triangulate(std::vector<PointAndId>& idPoints,
|
||||
const Vector& normal)
|
||||
{
|
||||
P_traits cdt_traits(normal);
|
||||
cdt = new CDT(cdt_traits);
|
||||
typename CDT::Vertex_handle previous, first, last_inserted;
|
||||
|
||||
Vertex_handle previous, first, last_inserted;
|
||||
|
||||
// Iterate the points of the facet and decide if they must be inserted in the CDT
|
||||
typename Kernel::FT x(0), y(0), z(0);
|
||||
|
||||
for(PointAndId idPoint : idPoints)
|
||||
for(const PointAndId& idPoint : idPoints)
|
||||
{
|
||||
|
||||
x += idPoint.point.x();
|
||||
y += idPoint.point.y();
|
||||
z += idPoint.point.z();
|
||||
typename CDT::Vertex_handle vh;
|
||||
//Always insert the first point, then only insert
|
||||
// if the distance with the previous is reasonable.
|
||||
if(first == typename CDT::Vertex_handle() || idPoint.point != previous->point())
|
||||
{
|
||||
vh = cdt->insert(idPoint.point);
|
||||
v2v[vh] = idPoint.id;
|
||||
if(first == typename CDT::Vertex_handle()) {
|
||||
first = vh;
|
||||
}
|
||||
if(previous != nullptr && previous != vh) {
|
||||
cdt->insert_constraint(previous, vh);
|
||||
last_inserted = previous;
|
||||
}
|
||||
previous = vh;
|
||||
}
|
||||
}
|
||||
if(last_inserted == typename CDT::Vertex_handle())
|
||||
return false;
|
||||
if(previous != first)
|
||||
cdt->insert_constraint(previous, first);
|
||||
// sets mark is_external
|
||||
for(typename CDT::All_faces_iterator
|
||||
fit2 = cdt->all_faces_begin(),
|
||||
end = cdt->all_faces_end();
|
||||
fit2 != end; ++fit2)
|
||||
{
|
||||
fit2->info().is_external = false;
|
||||
}
|
||||
//check if the facet is external or internal
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
y += idPoint.point.y();
|
||||
z += idPoint.point.z();
|
||||
|
||||
bool triangulate_with_points( std::vector<PointAndId > &idPoints,
|
||||
const std::vector<typename Kernel::Point_3>& more_points,
|
||||
const Vector& normal)
|
||||
{
|
||||
P_traits cdt_traits(normal);
|
||||
cdt = new CDT(cdt_traits);
|
||||
typename CDT::Vertex_handle previous, first, last_inserted;
|
||||
// Iterate the points of the facet and decide if they must be inserted in the CDT
|
||||
for(PointAndId idPoint : idPoints)
|
||||
{
|
||||
typename CDT::Vertex_handle vh;
|
||||
//Always insert the first point, then only insert
|
||||
// if the distance with the previous is reasonable.
|
||||
if(first == typename CDT::Vertex_handle() || idPoint.point != previous->point())
|
||||
Vertex_handle vh;
|
||||
// Always insert the first point, then only insert if the distance with the previous is reasonable.
|
||||
if(first == Vertex_handle() || idPoint.point != previous->point())
|
||||
{
|
||||
vh = cdt->insert(idPoint.point);
|
||||
v2v[vh] = idPoint.id;
|
||||
if(first == typename CDT::Vertex_handle()) {
|
||||
if(first == Vertex_handle())
|
||||
first = vh;
|
||||
}
|
||||
if(previous != nullptr && previous != vh) {
|
||||
|
||||
if(previous != nullptr && previous != vh)
|
||||
{
|
||||
cdt->insert_constraint(previous, vh);
|
||||
last_inserted = previous;
|
||||
}
|
||||
previous = vh;
|
||||
previous = vh;
|
||||
}
|
||||
}
|
||||
if(last_inserted == typename CDT::Vertex_handle())
|
||||
return false;
|
||||
cdt->insert_constraint(previous, first);
|
||||
for(typename Kernel::Point_3 point : more_points)
|
||||
{
|
||||
cdt->insert(point);
|
||||
}
|
||||
// sets mark is_external
|
||||
for(typename CDT::All_faces_iterator
|
||||
fit2 = cdt->all_faces_begin(),
|
||||
end = cdt->all_faces_end();
|
||||
fit2 != end; ++fit2)
|
||||
{
|
||||
fit2->info().is_external = false;
|
||||
}
|
||||
//check if the facet is external or internal
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if(last_inserted == Vertex_handle())
|
||||
return false;
|
||||
|
||||
if(previous != first)
|
||||
cdt->insert_constraint(previous, first);
|
||||
|
||||
// sets mark is_external
|
||||
for(Face_handle f2 : cdt->all_face_handles())
|
||||
f2->info().is_external = false;
|
||||
|
||||
// check if the facet is external or internal
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool triangulate_with_points(std::vector<PointAndId >& idPoints,
|
||||
const std::vector<Point>& more_points,
|
||||
const Vector& normal)
|
||||
{
|
||||
P_traits cdt_traits(normal);
|
||||
cdt = new CDT(cdt_traits);
|
||||
|
||||
// Iterate the points of the facet and decide if they must be inserted in the CDT
|
||||
Vertex_handle previous, first, last_inserted;
|
||||
for(const PointAndId& idPoint : idPoints)
|
||||
{
|
||||
Vertex_handle vh;
|
||||
// Always insert the first point, then only insert if the distance with the previous is reasonable.
|
||||
if(first == Vertex_handle() || idPoint.point != previous->point())
|
||||
{
|
||||
vh = cdt->insert(idPoint.point);
|
||||
v2v[vh] = idPoint.id;
|
||||
if(first == Vertex_handle())
|
||||
first = vh;
|
||||
|
||||
if(previous != nullptr && previous != vh)
|
||||
{
|
||||
cdt->insert_constraint(previous, vh);
|
||||
last_inserted = previous;
|
||||
}
|
||||
previous = vh;
|
||||
}
|
||||
}
|
||||
|
||||
if(last_inserted == Vertex_handle())
|
||||
return false;
|
||||
|
||||
cdt->insert_constraint(previous, first);
|
||||
for(const Point& point : more_points)
|
||||
cdt->insert(point);
|
||||
|
||||
// sets mark is_external
|
||||
for(Face_handle f2 : cdt->all_face_handles())
|
||||
f2->info().is_external = false;
|
||||
|
||||
// check if the facet is external or internal
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // TRIANGULATE_PRIMITIVE
|
||||
#endif // CGAL_DEMO_TRIANGULATE_PRIMITIVE_H
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,9 @@ create_single_source_cgal_program("test_Uncertain.cpp")
|
|||
create_single_source_cgal_program("test_vector.cpp")
|
||||
create_single_source_cgal_program("test_join_iterators.cpp")
|
||||
create_single_source_cgal_program("test_for_each.cpp")
|
||||
create_single_source_cgal_program("test_skiplist.cpp")
|
||||
create_single_source_cgal_program("test_leak.cpp")
|
||||
create_single_source_cgal_program("test_nth_element.cpp")
|
||||
if(TARGET CGAL::TBB_support)
|
||||
message(STATUS "Found TBB")
|
||||
target_link_libraries(test_for_each PUBLIC CGAL::TBB_support)
|
||||
|
|
|
|||
|
|
@ -12,18 +12,18 @@ int test() {
|
|||
CGAL::nth_element(nbs, nbs+pivot, nbs+sizeof(nbs) / sizeof(int), cmp);
|
||||
std::cerr << "After nth_element, nbs["<< pivot << "] = " << nbs[pivot] << std::endl;
|
||||
assert(nbs[pivot]==expected_value);
|
||||
for(int i = 0; i < sizeof(nbs) / sizeof(int); ++i) {
|
||||
for(std::size_t i = 0; i < sizeof(nbs) / sizeof(int); ++i) {
|
||||
std::cerr << " " << nbs[i];
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
for(pivot=0; pivot < 10; ++pivot)
|
||||
CGAL::nth_element(nbs, nbs+pivot, nbs+sizeof(nbs) / sizeof(int), cmp);
|
||||
std::cerr << "After sort:\n";
|
||||
for(int i = 0; i < sizeof(nbs) / sizeof(int); ++i) {
|
||||
for(std::size_t i = 0; i < sizeof(nbs) / sizeof(int); ++i) {
|
||||
std::cerr << " " << nbs[i];
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
for(int i = 1; i < sizeof(nbs) / sizeof(int); ++i) {
|
||||
for(std::size_t i = 1; i < sizeof(nbs) / sizeof(int); ++i) {
|
||||
assert(nbs[i]>=nbs[i-1]);
|
||||
}
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -50,8 +50,8 @@ BOOST_FIXTURE_TEST_CASE( test_insert, Fixture )
|
|||
|
||||
// clear and try again
|
||||
l.clear();
|
||||
BOOST_CHECK_EQUAL(l.all_size(), 0);
|
||||
BOOST_CHECK_EQUAL(l.skip_size(), 0);
|
||||
BOOST_CHECK_EQUAL(l.all_size(), std::size_t(0));
|
||||
BOOST_CHECK_EQUAL(l.skip_size(), std::size_t(0));
|
||||
l.insert(l.all_begin(), all.begin(), all.end());
|
||||
skips += 8, 9;
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(l.all_begin(), l.all_end(),
|
||||
|
|
@ -60,7 +60,6 @@ BOOST_FIXTURE_TEST_CASE( test_insert, Fixture )
|
|||
skips.begin(), skips.end());
|
||||
|
||||
// the same goes for inserting at an arbitrary position
|
||||
skip::all_iterator pos = std::next(l.all_begin(), 3);
|
||||
l.insert(std::next(l.all_begin(), 3)
|
||||
, 20);
|
||||
all.insert(std::next(all.begin(), 3)
|
||||
|
|
@ -124,7 +123,7 @@ BOOST_FIXTURE_TEST_CASE( skip_all_case, Fixture )
|
|||
l.skip(l.all_begin(), l.all_end());
|
||||
skips.clear();
|
||||
BOOST_CHECK_EQUAL(l.all_size(), all.size());
|
||||
BOOST_CHECK_EQUAL(l.skip_size(), 0);
|
||||
BOOST_CHECK_EQUAL(l.skip_size(), std::size_t(0));
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(l.skip_begin(), l.skip_end(),
|
||||
skips.begin(), skips.end());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -414,6 +414,13 @@ run_test_on_host()
|
|||
fi
|
||||
|
||||
for PLATFORM in ${PLATFORMS}; do
|
||||
|
||||
if [ "${CGAL_RELEASE_ID}" \> "CGAL-6.0" ]; then
|
||||
if [ "${PLATFORM}" = "MSVC2015-Release-64bits" ]; then
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
run_test_on_platform "${PLATFORM}"
|
||||
collect_demos_binaries "${PLATFORM}"
|
||||
publish_results "${PLATFORM}"
|
||||
|
|
|
|||
|
|
@ -92,6 +92,33 @@ for i in `ls -d ^build*/examples/*/ ^build*/test/*/ ^build*/demo/^(icons|resourc
|
|||
fi
|
||||
done
|
||||
|
||||
#check all tests/examples are tested
|
||||
echo '.. Checking if all .cpp files in examples/test are compiled...'
|
||||
CML_ERRORS=""
|
||||
for CML in `grep -L "GLOB cppfiles" */test/*/CMakeLists.txt */examples/*/CMakeLists.txt`; do
|
||||
DIR=`dirname $CML`
|
||||
|
||||
if [ "Arrangement_on_surface_2/test/Arrangement_on_surface_2" = $DIR ]; then
|
||||
continue
|
||||
fi
|
||||
if [ "Installation/test/Installation" = $DIR ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
for i in `ls ${DIR}/*.cpp`; do
|
||||
f=`basename $i .cpp`
|
||||
if ! grep -q $f ${CML}; then
|
||||
CML_ERRORS=`echo "${CML_ERRORS}\n$i is not tested!"`
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
|
||||
if [ -n "${CML_ERRORS}" ]; then
|
||||
echo -n "Some tests/examples are not tested:"
|
||||
echo ${CML_ERRORS}
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# check project in cmake scripts is correct
|
||||
echo '.. Checking if all CMakeLists.txt project names are correct...'
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ if(TARGET CGAL::OSQP_support)
|
|||
test_3_segments
|
||||
test_4_segments
|
||||
test_100_segments_angles
|
||||
test_100_segments_offsets)
|
||||
test_100_segments_offsets
|
||||
test_cgal_solver)
|
||||
|
||||
foreach(osqp_target ${osqp_targets})
|
||||
create_single_source_cgal_program("${osqp_target}.cpp")
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ void test_cgal_solver() {
|
|||
|
||||
using NQ = SR::Segments::Delaunay_neighbor_query_2<Traits, Segments>;
|
||||
using AR = SR::Segments::Angle_regularization_2<Traits, Segments>;
|
||||
using QP = CGAL::CGAL_quadratic_program_traits<FT>;
|
||||
using QP = CGAL::OSQP_quadratic_program_traits<FT>;
|
||||
|
||||
using QP_AR = SR::QP_regularization<Traits, Segments, NQ, AR, QP>;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ create_single_source_cgal_program("skin_surface_subdiv.cpp")
|
|||
create_single_source_cgal_program("skin_surface_subdiv_with_normals.cpp")
|
||||
create_single_source_cgal_program("union_of_balls_simple.cpp")
|
||||
create_single_source_cgal_program("union_of_balls_subdiv.cpp")
|
||||
create_single_source_cgal_program("skin_surface_retrieve_defining_weighted_points.cpp")
|
||||
|
||||
find_package(ESBTL QUIET)
|
||||
if(ESBTL_FOUND)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ create_single_source_cgal_program("searching_polyhedron_vertices_with_fuzzy_sphe
|
|||
create_single_source_cgal_program("user_defined_point_and_distance.cpp")
|
||||
create_single_source_cgal_program("using_fair_splitting_rule.cpp")
|
||||
create_single_source_cgal_program("weighted_Minkowski_distance.cpp")
|
||||
create_single_source_cgal_program("searching_sphere_orthogonally.cpp")
|
||||
create_single_source_cgal_program("splitter_worst_cases.cpp")
|
||||
|
||||
find_package(Eigen3 3.1.91 QUIET) #(requires 3.1.91 or greater)
|
||||
include(CGAL_Eigen3_support)
|
||||
|
|
|
|||
|
|
@ -58,7 +58,6 @@ namespace Three{
|
|||
* */
|
||||
class Scene_interface {
|
||||
public:
|
||||
|
||||
//!A bounding box is a box with each face corresponding to an extremum of its contents.
|
||||
|
||||
typedef CGAL::Bbox_3 Bbox;
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ public:
|
|||
PROGRAM_OLD_FLAT, /** Used to render flat shading without pre computing normals without geometry shader*/
|
||||
PROGRAM_SOLID_WIREFRAME, //! Used to render edges with width superior to 1.
|
||||
PROGRAM_NO_INTERPOLATION, //! Used to render faces without interpolating their color.
|
||||
PROGRAM_HEAT_INTENSITY, //! Used to render special item in Display_property_plugin
|
||||
PROGRAM_HEAT_INTENSITY, //! Used to render special item in Heat_method_plugin
|
||||
NB_OF_PROGRAMS //! Holds the number of different programs in this enum.
|
||||
};
|
||||
typedef CGAL::Bbox_3 Bbox;
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ public:
|
|||
PROGRAM_OLD_FLAT, /** Used to render flat shading without pre computing normals without geometry shader*/
|
||||
PROGRAM_SOLID_WIREFRAME, //! Used to render edges with width superior to 1.
|
||||
PROGRAM_NO_INTERPOLATION, //! Used to render faces without interpolating their color.
|
||||
PROGRAM_HEAT_INTENSITY, //! Used to render special item in Display_property_plugin
|
||||
PROGRAM_HEAT_INTENSITY, //! Used to render special item in Heat_method_plugin
|
||||
PROGRAM_TETRA_FILTERING, //! Used in Scene_tetrahedra_item with Tetrahedra_filtering_plugin
|
||||
NB_OF_PROGRAMS //! Holds the number of different programs in this enum.
|
||||
};
|
||||
|
|
|
|||
|
|
@ -347,8 +347,8 @@ ask the triangulation to construct the set of edges
|
|||
(\f$ 1\f$ dimensional faces) incident to the vertex at infinity. It is easy to see that
|
||||
these edges are in bijection with the vertices on the convex hull of the
|
||||
points. This gives us a handy way to count the convex hull vertices
|
||||
(include files <tt>triangulation1.cpp</tt> and
|
||||
<tt>triangulation2.cpp</tt> are given and commented below).
|
||||
(include files <tt>triangulation1.h</tt> and
|
||||
<tt>triangulation2.h</tt> are given and commented below).
|
||||
|
||||
\cgalExample{triangulation.cpp}
|
||||
|
||||
|
|
@ -368,14 +368,14 @@ there are (at least) two possibilities:
|
|||
The first is to iterate over the full cells of the triangulation and check if they
|
||||
are infinite or not:
|
||||
|
||||
\cgalExample{triangulation1.cpp}
|
||||
\cgalExample{triangulation1.h}
|
||||
|
||||
A second possibility is to ask the triangulation to gather all the full cells
|
||||
incident to the infinite vertex: they form precisely the set of infinite
|
||||
full cells:
|
||||
|
||||
|
||||
\cgalExample{triangulation2.cpp}
|
||||
\cgalExample{triangulation2.h}
|
||||
|
||||
One important difference between the two examples above is that the first uses
|
||||
<I>little</I> memory but traverses <I>all</I> the full cells, while the second
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
\example delaunay_triangulation.cpp
|
||||
\example regular_triangulation.cpp
|
||||
\example triangulation.cpp
|
||||
\example triangulation1.cpp
|
||||
\example triangulation2.cpp
|
||||
\example triangulation1.h
|
||||
\example triangulation2.h
|
||||
\example triangulation_data_structure_dynamic.cpp
|
||||
\example triangulation_data_structure_static.cpp
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ int main()
|
|||
std::cout << "There are " << edges.size()
|
||||
<< " vertices on the convex hull." << std::endl;
|
||||
|
||||
#include "triangulation1.cpp" // See below
|
||||
#include "triangulation2.cpp"
|
||||
#include "triangulation1.h" // See below
|
||||
#include "triangulation2.h"
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@ create_single_source_cgal_program("test_static_filters.cpp")
|
|||
create_single_source_cgal_program("test_triangulation_3.cpp")
|
||||
create_single_source_cgal_program("test_io_triangulation_3.cpp")
|
||||
create_single_source_cgal_program("test_triangulation_serialization_3.cpp")
|
||||
create_single_source_cgal_program("test_dt_deterministic_3.cpp")
|
||||
create_single_source_cgal_program("test_Triangulation_with_transform_iterator.cpp")
|
||||
create_single_source_cgal_program("test_Triangulation_with_zip_iterator.cpp")
|
||||
|
||||
if(TARGET CGAL::TBB_support)
|
||||
message(STATUS "Found TBB")
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@ int main()
|
|||
|
||||
std::stringstream buffer;
|
||||
buffer << dt3;
|
||||
//~ std::ofstream out ("test_dt_deterministic_3.in");
|
||||
//~ out << dt3;
|
||||
|
||||
//std::ofstream out ("test_dt_deterministic_3.in");
|
||||
//out << dt3;
|
||||
//out.close();
|
||||
|
||||
//reading the result from a file
|
||||
std::ifstream file ("test_dt_deterministic_3.in");
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue