// Copyright (c) 2019 Max-Planck-Institute Saarbruecken (Germany). // All rights reserved. // // This file is part of CGAL (www.cgal.org). // // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Jasmeet Singh // Mostafa Ashraf #ifndef DRAW_NEF_3_H #define DRAW_NEF_3_H #include #include #include #include #include #include #include #include #include #include namespace CGAL { namespace draw_function_for_nef_polyhedron { typedef CGAL::Exact_predicates_inexact_constructions_kernel Local_kernel; typedef Local_kernel::Vector_3 Local_vector; template Local_vector get_face_normal(typename Nef_Polyhedron::SHalfedge_const_handle she) { typename Nef_Polyhedron::SHalfedge_around_facet_const_circulator he(she), end(he); Local_vector normal=CGAL::NULL_VECTOR; unsigned int nb=0; using GU=internal::Geom_utils::Kernel, Local_kernel>; CGAL_For_all(he, end) { internal::newell_single_step_3(GU::get_local_point(he->next()->source()-> center_vertex()->point()), GU::get_local_point(he->source()->center_vertex()-> point()), normal); ++nb; } CGAL_assertion(nb > 0); return (typename Local_kernel::Construct_scaled_vector_3()(normal, 1.0/nb)); } template Local_vector get_vertex_normal(typename Nef_Polyhedron::Vertex_const_handle vh) { typename Nef_Polyhedron::SHalfedge_const_iterator it=vh->shalfedges_begin(); typename Nef_Polyhedron::SHalfedge_const_handle end=it; Local_vector normal=CGAL::NULL_VECTOR; do { Local_vector n=get_face_normal(it); normal=typename Local_kernel::Construct_sum_of_vectors_3()(normal, n); it=it->snext(); } while(it!=end); if (!typename Local_kernel::Equal_3()(normal, CGAL::NULL_VECTOR)) { normal=(typename Local_kernel::Construct_scaled_vector_3() (normal, 1.0/CGAL::sqrt(normal.squared_length()))); } return normal; } // Visitor class to iterate through shell objects template class Nef_Visitor { typedef typename Nef_Polyhedron::Halfedge_const_handle Halfedge_const_handle; typedef typename Nef_Polyhedron::Halffacet_const_handle Halffacet_const_handle; typedef typename Nef_Polyhedron::SHalfedge_const_handle SHalfedge_const_handle; typedef typename Nef_Polyhedron::SHalfedge_around_facet_const_circulator SHalfedge_around_facet_const_circulator; typedef typename Nef_Polyhedron::Vertex_const_handle Vertex_const_handle; typedef typename Nef_Polyhedron::SFace_const_handle SFace_const_handle; typedef typename Nef_Polyhedron::SHalfloop_const_handle SHalfloop_const_handle; typedef typename Nef_Polyhedron::Halffacet_cycle_const_iterator Halffacet_cycle_const_iterator; public: Nef_Visitor(const Nef_Polyhedron&_nef, CGAL::Graphics_scene& _graphics_scene, const GSOptions&_gs_options) : n_faces(0), n_edges(0), graphics_scene(_graphics_scene), gs_options(_gs_options), nef(_nef) {} void visit(Vertex_const_handle vh) { if (!gs_options.are_vertices_enabled() || !gs_options.draw_vertex(nef, vh)) { return; } if(gs_options.colored_vertex(nef, vh)) { graphics_scene.add_point(vh->point(), gs_options.vertex_color(nef, vh)); } else { graphics_scene.add_point(vh->point()); } } void visit(Halffacet_const_handle opposite_facet) { if (!gs_options.are_faces_enabled() || !gs_options.draw_face(nef, opposite_facet)) { return; } Halffacet_const_handle f=opposite_facet->twin(); if (facets_done.find(f)!=facets_done.end() || facets_done.find(opposite_facet)!=facets_done.end()) { return; } SHalfedge_const_handle se; Halffacet_cycle_const_iterator fc = f->facet_cycles_begin(); se = SHalfedge_const_handle(fc); // non-zero if shalfedge is returned if(se==0) { return; } //return if not-shalfedge if(gs_options.colored_face(nef, f)) { graphics_scene.face_begin(gs_options.face_color(nef, f)); } else { graphics_scene.face_begin(); } SHalfedge_around_facet_const_circulator hc_start(se); SHalfedge_around_facet_const_circulator hc_end(hc_start); Vertex_const_handle lastvh; CGAL_For_all(hc_start, hc_end) { Vertex_const_handle vh=hc_start->source()->center_vertex(); lastvh=vh; graphics_scene.add_point_in_face(vh->point(), get_vertex_normal(vh)); } // Now iterate through holes of the face ++fc; while(fc!=f->facet_cycles_end()) { if(fc.is_shalfedge()) { se = SHalfedge_const_handle(fc); hc_start=se; hc_end=hc_start; CGAL_For_all(hc_start, hc_end) { Vertex_const_handle vh=hc_start->source()->center_vertex(); graphics_scene.add_point_in_face(vh->point(), get_vertex_normal(vh)); } graphics_scene.add_point_in_face(hc_start->source()->center_vertex()->point(), get_vertex_normal (hc_start->source()->center_vertex())); graphics_scene.add_point_in_face(lastvh->point(), get_vertex_normal(lastvh)); } ++fc; } graphics_scene.face_end(); facets_done[f]=true; ++n_faces; } void visit(Halfedge_const_handle he) { if (!gs_options.are_edges_enabled() || !gs_options.draw_edge(nef, he)) { return; } Halfedge_const_handle twin=he->twin(); if (edges_done.find(he)!=edges_done.end() || edges_done.find(twin)!=edges_done.end()) { return; } // Edge already added if(gs_options.colored_edge(nef, he)) { graphics_scene.add_segment(he->source()->point(), he->target()->point(), gs_options.edge_color(nef, he)); } else { graphics_scene.add_segment(he->source()->point(), he->target()->point()); } edges_done[he]=true; ++n_edges; } void visit(SHalfedge_const_handle ) {} void visit(SHalfloop_const_handle ) {} void visit(SFace_const_handle ) {} int n_faces; int n_edges; protected: std::unordered_map facets_done; std::unordered_map edges_done; CGAL::Graphics_scene& graphics_scene; const GSOptions& gs_options; const Nef_Polyhedron& nef; }; template void compute_elements(const Nef_Polyhedron &nef, CGAL::Graphics_scene &graphics_scene, const GSOptions &gs_options) { typedef typename Nef_Polyhedron::Volume_const_iterator Volume_const_iterator; typedef typename Nef_Polyhedron::Shell_entry_const_iterator Shell_entry_const_iterator; typedef typename Nef_Polyhedron::SFace_const_handle SFace_const_handle; Volume_const_iterator c; Nef_Visitor V(nef, graphics_scene, gs_options); CGAL_forall_volumes(c, nef) { Shell_entry_const_iterator it; CGAL_forall_shells_of(it, c) { nef.visit_shell_objects(SFace_const_handle(it), V); } } graphics_scene.reverse_all_normals(); } } // namespace draw_function_for_nef_polyhedron #define CGAL_NEF3_TYPE Nef_polyhedron_3 // add_to_graphics_scene template void add_to_graphics_scene(const CGAL_NEF3_TYPE &anef, CGAL::Graphics_scene &graphics_scene, const GSOptions &gs_options) { draw_function_for_nef_polyhedron::compute_elements(anef, graphics_scene, gs_options); } template void add_to_graphics_scene(const CGAL_NEF3_TYPE &anef, CGAL::Graphics_scene &graphics_scene) { // Default graphics view options. Graphics_scene_options gs_options; gs_options.colored_face=[](const CGAL_NEF3_TYPE&, typename CGAL_NEF3_TYPE::Halffacet_const_handle) -> bool { return true; }; gs_options.face_color=[](const CGAL_NEF3_TYPE&, typename CGAL_NEF3_TYPE::Halffacet_const_handle fh) -> CGAL::IO::Color { if (fh==nullptr) // use to get the mono color { return CGAL::IO::Color(100, 125, 200); } CGAL::Random random((unsigned int)(std::size_t)(&(*fh))); return get_random_color(random); }; add_to_graphics_scene(anef, graphics_scene, gs_options); } #ifdef CGAL_USE_BASIC_VIEWER // Specialization of draw function template void draw(const CGAL_NEF3_TYPE &anef, const GSOptions &gs_options, const char *title="Nef Polyhedron Viewer") { CGAL::Graphics_scene buffer; add_to_graphics_scene(anef, buffer, gs_options); draw_graphics_scene(buffer, title); } template void draw(const CGAL_NEF3_TYPE &anef, const char *title="Nef Polyhedron Viewer") { CGAL::Graphics_scene buffer; add_to_graphics_scene(anef, buffer); draw_graphics_scene(buffer, title); } #endif // CGAL_USE_BASIC_VIEWER #undef CGAL_NEF3_TYPE } // End namespace CGAL #endif // DRAW_NEF_3_H