215 lines
7.3 KiB
C
215 lines
7.3 KiB
C
|
// Copyright (c) 2011 CNRS and LIRIS' Establishments (France).
|
||
|
// All rights reserved.
|
||
|
//
|
||
|
// This file is part of CGAL (www.cgal.org)
|
||
|
//
|
||
|
// $URL: https://github.com/CGAL/cgal/blob/v5.1/Linear_cell_complex/include/CGAL/Linear_cell_complex_operations.h $
|
||
|
// $Id: Linear_cell_complex_operations.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot
|
||
|
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
|
||
|
//
|
||
|
// Author(s) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
|
||
|
//
|
||
|
#ifndef CGAL_LINEAR_CELL_COMPLEX_OPERATIONS_H
|
||
|
#define CGAL_LINEAR_CELL_COMPLEX_OPERATIONS_H 1
|
||
|
|
||
|
#include <CGAL/Cell_iterators.h>
|
||
|
#include <CGAL/Cell_const_iterators.h>
|
||
|
#include <CGAL/Origin.h>
|
||
|
|
||
|
namespace CGAL {
|
||
|
|
||
|
/** @file Linear_cell_complex_operations.h
|
||
|
* Basic operators on a linear cell complex.
|
||
|
*/
|
||
|
namespace internal {
|
||
|
template <class Point, class Vector>
|
||
|
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 <class LCC>
|
||
|
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 <class LCC>
|
||
|
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<i<=dimension
|
||
|
template<class LCC, unsigned int i, unsigned int dim=LCC::dimension>
|
||
|
struct Barycenter_functor
|
||
|
{
|
||
|
static typename LCC::Point run(const LCC& amap,
|
||
|
typename LCC::Dart_const_handle adart)
|
||
|
{
|
||
|
CGAL_static_assertion(0<i && i<=LCC::dimension);
|
||
|
CGAL_assertion(adart != LCC::null_handle);
|
||
|
|
||
|
typename LCC::Vector vec
|
||
|
(typename LCC::Traits::Construct_vector()(CGAL::ORIGIN,
|
||
|
amap.point(adart)));
|
||
|
unsigned int nb = 1;
|
||
|
|
||
|
typename LCC::template One_dart_per_incident_cell_range<0, i, i>::
|
||
|
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<class LCC, unsigned int dim>
|
||
|
struct Barycenter_functor<LCC, 1, dim>
|
||
|
{
|
||
|
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<class LCC, unsigned int dim>
|
||
|
struct Barycenter_functor<LCC, 2, dim>
|
||
|
{
|
||
|
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 //
|