diff --git a/Intersections_3/include/CGAL/Intersections_3/internal/Line_3_Ray_3_do_intersect.h b/Intersections_3/include/CGAL/Intersections_3/internal/Line_3_Ray_3_do_intersect.h index f4aa1e8e37c..1cafde62ad3 100644 --- a/Intersections_3/include/CGAL/Intersections_3/internal/Line_3_Ray_3_do_intersect.h +++ b/Intersections_3/include/CGAL/Intersections_3/internal/Line_3_Ray_3_do_intersect.h @@ -38,11 +38,8 @@ do_intersect(const typename K::Line_3& l, if(p0p1s == COLLINEAR) return true; - CGAL::Orientation stp0 = pred(r.source(), r.second_point(), l.point(0)); - if(stp0 == COLLINEAR) - return Ray_3_has_on_collinear_Point_3(r,l.point(0),k); - - return (p0p1s != stp0); + typename K::Point_3 lst = l.point(0) + (r.point(1) - r.point(0)); + return (pred(l.point(0), l.point(1), r.point(0), lst) != CGAL::POSITIVE); } template diff --git a/Intersections_3/test/Intersections_3/test_intersections_Line_3.cpp b/Intersections_3/test/Intersections_3/test_intersections_Line_3.cpp index 6fe55a40654..936e077e018 100644 --- a/Intersections_3/test/Intersections_3/test_intersections_Line_3.cpp +++ b/Intersections_3/test/Intersections_3/test_intersections_Line_3.cpp @@ -232,6 +232,10 @@ struct Line_3_intersection_tester check_no_intersection(L(p(0,0,0),p(1,0,0)), R(p(3,0,1),p(6,0,1))); check_no_intersection(L(p(0,0,0),p(1,0,0)), R(p(0,2,0),p(0,4,0))); check_no_intersection(L(p(0,0,0),p(1,0,0)), R(p(6,2,0),p(5,4,0))); + check_no_intersection(L(p(0,0,0),p(0,1,0)), R(p(1,-1,0),p(1,0,0))); + check_no_intersection(L(p(0,-10,0),p(0,-9,0)), R(p(1,-1,0),p(2,0,0))); + check_no_intersection(L(p(0,-10,0),p(0,0,0)), R(p(1,-1,0),p(2,0,0))); + check_no_intersection(L(p(0,0,0),p(0,1,0)), R(p(1,-1,0),p(2,0,0))); // Point intersection check_intersection (L(p(0,0,0),p(1,0,0)), R(p(3,0,0),p(6,4,0)), diff --git a/Intersections_3/test/Intersections_3/test_intersections_Ray_3.cpp b/Intersections_3/test/Intersections_3/test_intersections_Ray_3.cpp index e1d603d4a5e..1ce4ab53642 100644 --- a/Intersections_3/test/Intersections_3/test_intersections_Ray_3.cpp +++ b/Intersections_3/test/Intersections_3/test_intersections_Ray_3.cpp @@ -74,6 +74,14 @@ struct Ray_3_intersection_tester check_no_intersection (R(p(0,0,0), p(1,0,0)), R(p(0,1,0), p(0,2,0))); check_no_intersection (R(p(0,0,0), p(1,0,0)), R(p(-1,0,0), p(-1,-1,0))); + check_no_intersection (R(p(1,-1,0), p(2,0,0)), R(p(2,-1,0), p(3,0,0))); + check_no_intersection (R(p(1,-1,0), p(2,0,0)), R(p(2,-1,0), p(3,-1,0))); + check_no_intersection (R(p(1,-1,0), p(2,0,0)), R(p(2,-1,0), p(3,-2,0))); + check_no_intersection (R(p(0,0,0), p(0,1,0)), R(p(0,-1,0), p(1,-1,0))); + check_no_intersection (R(p(0,0,0), p(0,1,0)), R(p(-1,-3,0),p(2,0,0))); + check_no_intersection (R(p(0,0,0), p(0,1,0)), R(p(-2,-4,0),p(-1,-3,0))); + check_no_intersection (R(p(0,0,0), p(0,1,0)), R(p(1,-1,0), p(2,0,0))); + // Point check_intersection (R(p(0,0,0), p(1,0,0)), R(p(0,0,0), p(-1,0,0)), p(0,0,0)); @@ -88,6 +96,10 @@ struct Ray_3_intersection_tester check_intersection (R(p(0,0,0), p(1,0,0)), R(p(1,-2,0), p(1,-1,0)), p(1,0,0)); + check_intersection (R(p(0,0,0), p(1,0,0)), R(p(1,-2,0), p(1,-1,0)), + p(1,0,0)); + + // Segment check_intersection (R(p(0,0,0), p(1,0,0)), R(p(2,0,0), p(-3,0,0)), S(p(0,0,0), p(2,0,0)), false); @@ -161,6 +173,8 @@ struct Ray_3_intersection_tester for(int i=0; i #include #include +#include #include @@ -81,6 +82,7 @@ struct Shell_polygons_visitor Vertex_index_map& vertex_indices; PolygonRange& polygons; bool triangulate_all_faces; + CGAL::Generic_handle_map Done; Shell_polygons_visitor(Vertex_index_map& vertex_indices, PolygonRange& polygons, @@ -88,6 +90,7 @@ struct Shell_polygons_visitor : vertex_indices( vertex_indices ) , polygons(polygons) , triangulate_all_faces(triangulate_all_faces) + , Done(false) {} std::size_t get_cycle_length( typename Nef_polyhedron::Halffacet_cycle_const_iterator hfc) const @@ -103,6 +106,14 @@ struct Shell_polygons_visitor void visit(typename Nef_polyhedron::Halffacet_const_handle opposite_facet) { + typename Nef_polyhedron::Halffacet_const_handle twin_facet = opposite_facet->twin(); + + // skip when we have to do with the unbounded volume and a surface with boundaries + if ((twin_facet->incident_volume() == opposite_facet->incident_volume()) && Done[twin_facet]) + return; + + Done[opposite_facet] = true; + bool is_marked=opposite_facet->incident_volume()->mark(); CGAL_assertion(Nef_polyhedron::Infi_box::is_standard(opposite_facet->plane())); @@ -351,18 +362,50 @@ void convert_nef_polyhedron_to_polygon_soup(const Nef_polyhedron& nef, typedef Cartesian_converter Converter; typename Nef_polyhedron::Volume_const_iterator vol_it = nef.volumes_begin(), vol_end = nef.volumes_end(); - if ( Nef_polyhedron::Infi_box::extended_kernel() ) ++vol_it; // skip Infi_box - CGAL_assertion ( vol_it != vol_end ); - ++vol_it; // skip unbounded volume + + if (Nef_polyhedron::Infi_box::extended_kernel()) ++vol_it; // skip Infi_box + + if ( vol_it == vol_end ) return; Converter to_output; + bool handling_unbounded_volume = true; + + auto shell_is_closed = [](typename Nef_polyhedron::Shell_entry_const_iterator sfh) + { + typename Nef_polyhedron::SFace_const_handle sf = sfh; + + typename Nef_polyhedron::SFace_cycle_const_iterator fc; + for(fc = sf->sface_cycles_begin(); fc != sf->sface_cycles_end(); ++fc) + { + if (fc.is_shalfedge() ) { + typename Nef_polyhedron::SHalfedge_const_handle e(fc); + typename Nef_polyhedron::SHalfedge_around_sface_const_circulator ec(e),ee(e); + CGAL_For_all(ec,ee) + { + typename Nef_polyhedron::Halffacet_const_handle f = ec->twin()->facet(); + if (f->incident_volume()==f->twin()->incident_volume()) + return false; + } + } + } + + return true; + }; + for (;vol_it!=vol_end;++vol_it) - nef_to_pm::collect_polygon_mesh_info(points, - polygons, - nef, - vol_it->shells_begin(), - to_output, - triangulate_all_faces); + { + for(auto sit = vol_it->shells_begin(); sit != vol_it->shells_end(); ++sit) + { + if ( (handling_unbounded_volume || sit!=vol_it->shells_begin()) && shell_is_closed(sit)) continue; + nef_to_pm::collect_polygon_mesh_info(points, + polygons, + nef, + sit, + to_output, + triangulate_all_faces); + } + handling_unbounded_volume = false; + } } template diff --git a/Nef_3/test/Nef_3/issue_6423.cpp b/Nef_3/test/Nef_3/issue_6423.cpp new file mode 100644 index 00000000000..441dd0b7939 --- /dev/null +++ b/Nef_3/test/Nef_3/issue_6423.cpp @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include +#include + +typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; +typedef Kernel::Point_3 Point_3; +typedef CGAL::Surface_mesh SurfaceMesh; +typedef CGAL::Nef_polyhedron_3 NefPolyhedron; + + +int main() +{ + SurfaceMesh surfaceMesh; + SurfaceMesh::Vertex_index v0 = surfaceMesh.add_vertex(Point_3(-1, 0, 0)); + SurfaceMesh::Vertex_index v1 = surfaceMesh.add_vertex(Point_3(1, 0, 0)); + SurfaceMesh::Vertex_index v2 = surfaceMesh.add_vertex(Point_3(0, 1, 0)); + + SurfaceMesh::Vertex_index v3 = surfaceMesh.add_vertex(Point_3(-1, 0, 1)); + SurfaceMesh::Vertex_index v4 = surfaceMesh.add_vertex(Point_3(1, 0, 1)); + SurfaceMesh::Vertex_index v5 = surfaceMesh.add_vertex(Point_3(0, 1, 1)); + + surfaceMesh.add_face(v0, v1, v2); + surfaceMesh.add_face(v3, v4, v5); + + make_tetrahedron(Point_3(-1, 0, 10), + Point_3(1, 0, 10), + Point_3(0, 1, 10), + Point_3(-1, 0, 11), + surfaceMesh); + + std::cout << "Before conversion, number_of_faces: " << surfaceMesh.number_of_faces() << std::endl; + + NefPolyhedron nefPoly(surfaceMesh); + std::cout << "NefPolyhedron, number_of_faces: " << nefPoly.number_of_facets() << std::endl; + SurfaceMesh convertedSurfaceMesh; + CGAL::convert_nef_polyhedron_to_polygon_mesh(nefPoly, convertedSurfaceMesh, true); + std::cout << "After conversion, number_of_faces: " << convertedSurfaceMesh.number_of_faces() << std::endl; + std::ofstream("out.off") << convertedSurfaceMesh; + assert(vertices(convertedSurfaceMesh).size()==10); + assert(faces(convertedSurfaceMesh).size()==6); + return EXIT_SUCCESS; +} diff --git a/Scripts/developer_scripts/run_doxygen_testsuite b/Scripts/developer_scripts/run_doxygen_testsuite index 470eb295d84..5aaab01d981 100755 --- a/Scripts/developer_scripts/run_doxygen_testsuite +++ b/Scripts/developer_scripts/run_doxygen_testsuite @@ -6,7 +6,7 @@ cd /home/cgal-testsuite # Rotate log files on one month: the logfile name contains the number of # the day -LOGFILE=$PWD/doxygen_testsuite-`date '+%d'`.log +LOGFILE=$PWD/doxygen_testsuite-$(date '+%d').log exec > "$LOGFILE" @@ -39,8 +39,8 @@ if [ -r "${CGAL_DOC_BUILD}" ]; then rm -rf "${CGAL_DOC_BUILD}" fi -mkdir ${CGAL_DOC_BUILD} -cd ${CGAL_DOC_BUILD} +mkdir "${CGAL_DOC_BUILD}" +cd "${CGAL_DOC_BUILD}" if [ -r "LATEST" ]; then rm -rf LATEST @@ -52,12 +52,12 @@ if [ ! -f "LATEST" ]; then error "COULD NOT DOWNLOAD LATEST!" fi -for i in `cat LATEST` +for i in $(cat LATEST) do CGAL_LOCATION="${CGAL_URL}/${i}"; CGAL_ZIPFILE="${i}"; done -CGAL_RELEASE_ID=`echo $CGAL_ZIPFILE | sed "s/.tar.gz//"` +CGAL_RELEASE_ID=$(echo "$CGAL_ZIPFILE" | sed "s/.tar.gz//") curl ${CURL_OPTS} "${CGAL_LOCATION}" tar xvzf "${CGAL_ZIPFILE}" && rm "${CGAL_ZIPFILE}" @@ -68,11 +68,16 @@ cd "${CGAL_RELEASE_ID}" PATH=/home/cgal-testsuite/local/bin:$PATH export PATH -cd "$PWD/doc/scripts" +cd "${PWD}/doc/scripts" bash -$- ./process_doc.sh /home/cgal-testsuite/bin/doxygen_1_8_13 /home/cgal-testsuite/bin/doxygen_1_9_6 /srv/CGAL/www/Members/Manual_doxygen_test if head -2 ../../.scm-branch | grep -q cgal/master; then rsync -a --delete "/srv/CGAL/www/Members/Manual_doxygen_test/${CGAL_RELEASE_ID}/output2/" /srv/CGAL/www/doc/master/ fi +if sestatus &>/dev/null && [ -d "/srv/CGAL/www/doc/master/" ] && [ -d "/srv/CGAL/www/Members/Manual_doxygen_test/${CGAL_RELEASE_ID}" ]; then + restorecon -R /srv/CGAL/www/doc/master/ /srv/CGAL/www/Members/Manual_doxygen_test/${CGAL_RELEASE_ID} || error "restorecon command failed" +else + error "SELinux is not enabled or the paths do not exist" +fi rm -rf "${CGAL_DOC_BUILD}" # Then gzip the log file, to save space exec