// Copyright (c) 2011 CNRS and LIRIS' Establishments (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 3 of the License, // or (at your option) any later version. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // SPDX-License-Identifier: LGPL-3.0+ // // Author(s) : Guillaume Damiand // #ifndef CGAL_LINEAR_CELL_COMPLEX_OPERATIONS_H #define CGAL_LINEAR_CELL_COMPLEX_OPERATIONS_H 1 #include #include #include namespace CGAL { /** @file Linear_cell_complex_operations.h * Basic operators on a linear cell complex. */ namespace internal { template void newell_single_step_3_for_lcc(const Point& p, const Point& q, Vector& n) { // Compute normal of the face by using Newell's method: for each edge PQ // Nx += (Py - Qy) * (Pz + Qz); // Ny += (Pz - Qz) * (Px + Qx); // Nz += (Px - Qx) * (Py + Qy); n = Vector(n.x()+((p.y()-q.y())*(p.z()+q.z())), n.y()+((p.z()-q.z())*(p.x()+q.x())), n.z()+((p.x()-q.x())*(p.y()+q.y()))); // Dot product formula /*n=Vector(n.x()+((p.y()*q.z())-(p.z()*q.y())), n.y()+((p.x()*q.z())-(p.z()*q.x())), n.z()+((p.x()*q.y())-(p.y()*q.x())));*/ } } // End namespace internal /** Compute the normal of the given facet. * @param amap the used linear cell complex. * @param adart a dart incident to the facet. * @return the normal of the facet. */ template typename LCC::Vector compute_normal_of_cell_2 (const LCC& amap, typename LCC::Dart_const_handle adart) { typedef typename LCC::Point Point; typedef typename LCC::Vector Vector; typename LCC::Dart_const_handle start=adart; Vector normal(CGAL::NULL_VECTOR); // We go to the beginning of the face (first dart) while ( amap.is_previous_exist(start) && amap.previous(start)!=adart ) start = amap.previous(start); // Now we advance to process each edge unsigned int nb = 0; const Point* curr = &amap.point(start); adart=start; do { if (amap.other_extremity(adart)==LCC::null_handle) adart=start; // To leave the loop, because we know that adart has no next dart else { const Point* next = &amap.point(amap.other_extremity(adart)); internal::newell_single_step_3_for_lcc(*curr, *next, normal); ++nb; curr = next; if (amap.is_next_exist(adart) && amap.next(adart)!=start) adart=amap.next(adart); else adart=start; } } while(adart!=start); assert(nb>0); return (typename LCC::Traits::Construct_scaled_vector()(normal, 1.0/nb)); // return normal / std::sqrt(normal * normal); } /** Compute the normal of the given vertex. * @param amap the used linear cell complex. * @param adart a dart incident to the vertex. * @return the normal of the vertex. */ template typename LCC::Vector compute_normal_of_cell_0 (const LCC& amap, typename LCC::Dart_const_handle adart) { typedef typename LCC::Vector Vector; Vector normal(CGAL::NULL_VECTOR); unsigned int nb = 0; for ( typename LCC::template One_dart_per_incident_cell_range<2,0>:: const_iterator it(amap, adart); it.cont(); ++it ) { normal = typename LCC::Traits::Construct_sum_of_vectors() (normal, CGAL::compute_normal_of_cell_2(amap,it)); ++nb; } if ( nb<2 ) return normal; return (typename LCC::Traits::Construct_scaled_vector()(normal, 1.0/nb)); } // Compute the barycenter of a given i-cell // General case, 1 struct Barycenter_functor { static typename LCC::Point run(const LCC& amap, typename LCC::Dart_const_handle adart) { CGAL_static_assertion(0:: const_iterator it(amap, adart); for ( ++it; it.cont(); ++it) { vec = typename LCC::Traits::Construct_sum_of_vectors() (vec, typename LCC::Traits::Construct_vector()(CGAL::ORIGIN, amap.point(it) )); ++nb; } return typename LCC::Traits::Construct_translated_point() (CGAL::ORIGIN, typename LCC::Traits::Construct_scaled_vector() (vec, 1.0/nb)); } }; // Compute the barycenter of a given 1-cell template struct Barycenter_functor { static typename LCC::Point run(const LCC& amap, typename LCC::Dart_const_handle adart) { CGAL_static_assertion(1<=LCC::dimension); CGAL_assertion(adart != LCC::null_handle); typename LCC::Dart_const_handle d2=amap.other_extremity(adart); if (d2==amap.null_handle) return amap.point(adart); return typename LCC::Traits::Construct_midpoint() (amap.point(adart), amap.point(d2)); } }; // Compute the barycenter of a given 2-cell template struct Barycenter_functor { static typename LCC::Point run(const LCC& amap, typename LCC::Dart_const_handle adart) { CGAL_static_assertion(2<=LCC::dimension); CGAL_assertion(adart != LCC::null_handle); // We go to the beginning of the face (first dart, case of open face) typename LCC::Dart_const_handle start=adart; while ( amap.is_previous_exist(start) && amap.previous(start)!=adart ) start = amap.previous(start); typename LCC::Vector vec (typename LCC::Traits::Construct_vector()(CGAL::ORIGIN, amap.point(start))); if ((!amap.is_previous_exist(adart) && !amap.is_next_exist(adart)) || amap.next(adart)==adart) return typename LCC::Traits::Construct_translated_point() (CGAL::ORIGIN, vec); // case of face with only one edge unsigned int nb = 1; // Now we advance to process each edge adart=amap.next(start); // Because the first vertex was already sum up do { vec = typename LCC::Traits::Construct_sum_of_vectors() (vec, typename LCC::Traits::Construct_vector()(CGAL::ORIGIN, amap.point(adart))); ++nb; if (amap.is_next_exist(adart) && amap.next(adart)!=start) adart=amap.next(adart); else adart=start; } while(adart!=start); assert(nb>1); return typename LCC::Traits::Construct_translated_point() (CGAL::ORIGIN, typename LCC::Traits::Construct_scaled_vector() (vec, 1.0/nb)); } }; } // namespace CGAL #endif // CGAL_LINEAR_CELL_COMPLEX_OPERATIONS_H // // EOF //