// Copyright (c) 2018 CNRS and LIRIS' Establishments (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org) // // $URL$ // $Id$ // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // // Author(s) : Guillaume Damiand // Mostafa Ashraf #ifndef CGAL_DRAW_LCC_H #define CGAL_DRAW_LCC_H #include #include #include #include #include #include namespace CGAL { namespace draw_function_for_lcc { typedef CGAL::Exact_predicates_inexact_constructions_kernel Local_kernel; typedef Local_kernel::Point_3 Local_point; typedef Local_kernel::Vector_3 Local_vector; template struct LCC_geom_utils; template struct LCC_geom_utils { static typename Local_kernel::Vector_3 get_vertex_normal(const LCC& lcc, typename LCC::Dart_const_descriptor dh) { typename Local_kernel::Vector_3 n = internal::Geom_utils:: get_local_vector(CGAL::compute_normal_of_cell_0(lcc, dh)); n = n / (CGAL::sqrt(n * n)); return n; } }; template struct LCC_geom_utils { static typename Local_kernel::Vector_3 get_vertex_normal(const LCC&, typename LCC::Dart_const_descriptor) { typename Local_kernel::Vector_3 n=CGAL::NULL_VECTOR; return n; } }; template void compute_face(const LCC& lcc, typename LCC::Dart_const_handle dh, typename LCC::Dart_const_handle voldh, CGAL::Graphic_storage& graphic_buffer, const DrawingFunctorLCC& drawing_functor) { if (!drawing_functor.are_faces_enabled() || !drawing_functor.draw_face(lcc, dh)) { return; } // We fill only closed faces. typename LCC::Dart_const_handle cur=dh; do { if (!lcc.is_next_exist(cur)) { return; } // open face=>not filled cur = lcc.next(cur); } while (cur!=dh); if (drawing_functor.colored_volume(lcc, voldh)) { graphic_buffer.face_begin(drawing_functor.volume_color(lcc, voldh)); } else if (drawing_functor.colored_face(lcc, dh)) { graphic_buffer.face_begin(drawing_functor.face_color(lcc, dh)); } else { graphic_buffer.face_begin(); } cur=dh; do { graphic_buffer.add_point_in_face (lcc.point(cur), LCC_geom_utils::get_vertex_normal(lcc, cur)); cur=lcc.next(cur); } while (cur!=dh); graphic_buffer.face_end(); } template void compute_edge(const LCC& lcc, typename LCC::Dart_const_handle dh, CGAL::Graphic_storage& graphic_buffer, const DrawingFunctor& drawing_functor) { if (!drawing_functor.are_edges_enabled() || !drawing_functor.draw_edge(lcc, dh)) { return; } const typename LCC::Point& p1=lcc.point(dh); typename LCC::Dart_const_handle d2=lcc.other_extremity(dh); if (d2!=LCC::null_descriptor) { if (drawing_functor.colored_edge(lcc, dh)) { graphic_buffer.add_segment(p1, lcc.point(d2), drawing_functor.edge_color(lcc, dh)); } else { graphic_buffer.add_segment(p1, lcc.point(d2)); } } } template void compute_vertex(const LCC& lcc, typename LCC::Dart_const_handle dh, CGAL::Graphic_storage& graphic_buffer, const DrawingFunctorLCC& drawing_functor) { if (!drawing_functor.are_vertices_enabled() || !drawing_functor.draw_vertex(lcc, dh)) { return; } if (drawing_functor.colored_vertex(lcc, dh)) { graphic_buffer.add_point(lcc.point(dh), drawing_functor.vertex_color(lcc, dh)); } else { graphic_buffer.add_point(lcc.point(dh)); } } template void compute_elements(const LCC& lcc, CGAL::Graphic_storage& graphic_buffer, const DrawingFunctor& drawing_functor) { typename LCC::size_type markvolumes = lcc.get_new_mark(); typename LCC::size_type markfaces = lcc.get_new_mark(); typename LCC::size_type markedges = lcc.get_new_mark(); typename LCC::size_type markvertices = lcc.get_new_mark(); typename LCC::size_type oriented_mark = lcc.get_new_mark(); lcc.orient(oriented_mark); for(typename LCC::Dart_range::const_iterator it=lcc.darts().begin(), itend=lcc.darts().end(); it!=itend; ++it) { if (!lcc.is_marked(it, markvolumes) && drawing_functor.draw_volume(lcc, it)) { for(typename LCC::template Dart_of_cell_basic_range<3>::const_iterator itv=lcc.template darts_of_cell_basic<3>(it, markvolumes).begin(), itvend=lcc.template darts_of_cell_basic<3>(it, markvolumes).end(); itv!=itvend; ++itv) { lcc.mark(itv, markvolumes); if (!lcc.is_marked(itv, markfaces) && lcc.is_marked(itv, oriented_mark) && drawing_functor.draw_face(lcc, itv)) { if ((!drawing_functor.volume_wireframe(lcc, itv) || (!lcc.template is_free<3>(itv) && !drawing_functor.volume_wireframe(lcc, lcc.template opposite<3>(itv)))) && !drawing_functor.face_wireframe(lcc, itv)) { compute_face(lcc, itv, it, graphic_buffer, drawing_functor); } for(typename LCC::template Dart_of_cell_basic_range<2>::const_iterator itf=lcc.template darts_of_cell_basic<2>(itv, markfaces).begin(), itfend=lcc.template darts_of_cell_basic<2>(itv, markfaces).end(); itf!=itfend; ++itf) { lcc.mark(itf, markfaces); if (!lcc.is_marked(itf, markedges) && drawing_functor.draw_edge(lcc, itf)) { compute_edge(lcc, itf, graphic_buffer, drawing_functor); for(typename LCC::template Dart_of_cell_basic_range<1>::const_iterator ite=lcc.template darts_of_cell_basic<1>(itf, markedges).begin(), iteend=lcc.template darts_of_cell_basic<1>(itf, markedges).end(); ite!=iteend; ++ite) { lcc.mark(ite, markedges); if (!lcc.is_marked(ite, markvertices) && drawing_functor.draw_vertex(lcc, ite)) { compute_vertex(lcc, ite, graphic_buffer, drawing_functor); CGAL::mark_cell(lcc, ite, markvertices); } } } } } } } } for (typename LCC::Dart_range::const_iterator it = lcc.darts().begin(), itend = lcc.darts().end(); it != itend; ++it) { lcc.unmark(it, markvertices); lcc.unmark(it, markedges); lcc.unmark(it, markfaces); lcc.unmark(it, markvolumes); lcc.unmark(it, oriented_mark); } lcc.free_mark(markvolumes); lcc.free_mark(markfaces); lcc.free_mark(markedges); lcc.free_mark(markvertices); lcc.free_mark(oriented_mark); } } // namespace draw_function_for_lcc #define CGAL_LCC_TYPE \ CGAL::Linear_cell_complex_base // add_in_graphic_buffer: to add a LCC in the given graphic buffer, with a // drawing functor. template class Map, class Refs, class Storage_, typename BufferType=float, class DrawingFunctor> void add_in_graphic_buffer(const CGAL_LCC_TYPE& alcc, CGAL::Graphic_storage& graphic_buffer, const DrawingFunctor& drawing_functor) { draw_function_for_lcc::compute_elements(static_cast(alcc), graphic_buffer, drawing_functor); } // add_in_graphic_buffer: to add a LCC in the given graphic buffer, without a // drawing functor. Use default drawing values. template class Map, class Refs, class Storage_, typename BufferType=float> void add_in_graphic_buffer(const CGAL_LCC_TYPE& alcc, CGAL::Graphic_storage& graphic_buffer) { CGAL::Drawing_functor_with_volume drawing_functor_with_volume; drawing_functor_with_volume.colored_volume = [](const CGAL_LCC_TYPE&, typename CGAL_LCC_TYPE::Dart_const_handle) -> bool { return true; }; drawing_functor_with_volume.volume_color = [] (const CGAL_LCC_TYPE& alcc, typename CGAL_LCC_TYPE::Dart_const_handle dh) -> CGAL::IO::Color { CGAL::Random random((unsigned int)(alcc.darts().index(dh))); return get_random_color(random); }; add_in_graphic_buffer(alcc, graphic_buffer, drawing_functor_with_volume); } #ifdef CGAL_USE_BASIC_VIEWER // Specialization of draw function for a LCC, with a drawing functor. template class Map, class Refs, class Storage_, class DrawingFunctor> void draw(const CGAL_LCC_TYPE& alcc, const DrawingFunctor& drawing_functor, const char *title="LCC Basic Viewer") { CGAL::Graphic_storage buffer; add_in_graphic_buffer(alcc, buffer, drawing_functor); draw_buffer(buffer, title); } // Specialization of draw function for a LCC, without a drawing functor. template class Map, class Refs, class Storage_> void draw(const CGAL_LCC_TYPE& alcc, const char *title="LCC Basic Viewer") { CGAL::Graphic_storage buffer; add_in_graphic_buffer(alcc, buffer); draw_buffer(buffer, title); } #endif // CGAL_USE_BASIC_VIEWER #undef CGAL_LCC_TYPE } // End namespace CGAL #endif // CGAL_DRAW_LCC_H