add btFileUtils::toLower to convert a string (char*) to lower case
URDF import demo: add COLLADA .dae file support add FiniteElementMethod demo, extracted from the OpenTissue library (under the zlib license) don't crash if loading an invalid STL file add comparison with Assimp for COLLADA file loading (disabled by default, to avoid library dependency) Gwen: disable some flags that make the build incompatible
This commit is contained in:
@@ -0,0 +1,368 @@
|
||||
#ifndef OPENTISSUE_CORE_GEOMETRY_GEOMETRY_AABB_H
|
||||
#define OPENTISSUE_CORE_GEOMETRY_GEOMETRY_AABB_H
|
||||
//
|
||||
// OpenTissue Template Library
|
||||
// - A generic toolbox for physics-based modeling and simulation.
|
||||
// Copyright (C) 2008 Department of Computer Science, University of Copenhagen.
|
||||
//
|
||||
// OTTL is licensed under zlib: http://opensource.org/licenses/zlib-license.php
|
||||
//
|
||||
#include <OpenTissue/configuration.h>
|
||||
|
||||
#include <OpenTissue/core/geometry/geometry_volume_shape.h>
|
||||
#include <OpenTissue/utility/utility_class_id.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
namespace OpenTissue
|
||||
{
|
||||
|
||||
namespace geometry
|
||||
{
|
||||
|
||||
/**
|
||||
* Axed Aligned Bounding Box (AABB).
|
||||
*/
|
||||
template< typename math_types_ >
|
||||
class AABB
|
||||
: public VolumeShape< math_types_ >
|
||||
, public OpenTissue::utility::ClassID< AABB<math_types_> >
|
||||
{
|
||||
public:
|
||||
|
||||
typedef math_types_ math_types;
|
||||
typedef typename math_types::value_traits value_traits;
|
||||
typedef typename math_types::real_type real_type;
|
||||
typedef typename math_types::vector3_type vector3_type;
|
||||
typedef typename math_types::matrix3x3_type matrix3x3_type;
|
||||
typedef typename math_types::quaternion_type quaternion_type;
|
||||
|
||||
public:
|
||||
|
||||
vector3_type m_min; ///< Coordinates of minimum corner.
|
||||
vector3_type m_max; ///< Coordinates of maximum corner.
|
||||
|
||||
public:
|
||||
|
||||
size_t const class_id() const { return OpenTissue::utility::ClassID<OpenTissue::geometry::AABB<math_types_> >::class_id(); }
|
||||
|
||||
AABB()
|
||||
{
|
||||
m_min.clear();
|
||||
m_max.clear();
|
||||
}
|
||||
|
||||
explicit AABB(
|
||||
real_type const & xmin
|
||||
, real_type const & ymin
|
||||
, real_type const & zmin
|
||||
, real_type const & xmax
|
||||
, real_type const & ymax
|
||||
, real_type const & zmax
|
||||
)
|
||||
{
|
||||
set(xmin,ymin,zmin,xmax,ymax,zmax);
|
||||
}
|
||||
|
||||
explicit AABB( vector3_type const & pmin_v, vector3_type const & pmax_v) { set(pmin_v,pmax_v); }
|
||||
|
||||
virtual ~AABB() {}
|
||||
|
||||
public:
|
||||
|
||||
void compute_surface_points(std::vector<vector3_type> & points) const
|
||||
{
|
||||
vector3_type dia;
|
||||
dia = m_max - m_min;
|
||||
|
||||
vector3_type p000 = m_min;
|
||||
vector3_type p001 = m_min + vector3_type( dia[0], value_traits::zero(), value_traits::zero());
|
||||
vector3_type p010 = m_min + vector3_type(value_traits::zero(), dia[1], value_traits::zero());
|
||||
vector3_type p011 = m_min + vector3_type( dia[0], dia[1], value_traits::zero());
|
||||
vector3_type p100 = m_min + vector3_type(value_traits::zero(), value_traits::zero(), dia[2]);
|
||||
vector3_type p101 = m_min + vector3_type( dia[0], value_traits::zero(), dia[2]);
|
||||
vector3_type p110 = m_min + vector3_type(value_traits::zero(), dia[1], dia[2]);
|
||||
vector3_type p111 = m_min + vector3_type( dia[0], dia[1], dia[2]);
|
||||
|
||||
points.push_back(p000);
|
||||
points.push_back(p001);
|
||||
points.push_back(p010);
|
||||
points.push_back(p011);
|
||||
points.push_back(p100);
|
||||
points.push_back(p101);
|
||||
points.push_back(p110);
|
||||
points.push_back(p111);
|
||||
}
|
||||
|
||||
vector3_type center() const { return vector3_type( (m_max+m_min)/value_traits::two() ); }
|
||||
|
||||
public:
|
||||
/**
|
||||
* Assingment Method.
|
||||
* Assigns the size of the specified AABB to this AABB.
|
||||
*
|
||||
* @param other_aabb Another AABB
|
||||
*/
|
||||
void set(AABB const & other_aabb)
|
||||
{
|
||||
this->m_min = other_aabb.m_min;
|
||||
this->m_max = other_aabb.m_max;
|
||||
}
|
||||
|
||||
void set( vector3_type const & pmin_v, vector3_type const & pmax_v)
|
||||
{
|
||||
assert(pmin_v[0] <= pmax_v[0] || !"AABB.set(): minimum must be less than or equal to maximum");
|
||||
assert(pmin_v[1] <= pmax_v[1] || !"AABB.set(): minimum must be less than or equal to maximum");
|
||||
assert(pmin_v[2] <= pmax_v[2] || !"AABB.set(): minimum must be less than or equal to maximum");
|
||||
m_min = pmin_v;
|
||||
m_max = pmax_v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set AABB box.
|
||||
*
|
||||
* @param xmin
|
||||
* @param ymin
|
||||
* @param zmin
|
||||
* @param xmax
|
||||
* @param ymax
|
||||
* @param zmax
|
||||
*/
|
||||
void set(
|
||||
real_type const & xmin
|
||||
, real_type const & ymin
|
||||
, real_type const & zmin
|
||||
, real_type const & xmax
|
||||
, real_type const & ymax
|
||||
, real_type const & zmax
|
||||
)
|
||||
{
|
||||
assert(xmin<=xmax || !"AABB.set(): minimum must be less than or equal to maximum");
|
||||
assert(ymin<=ymax || !"AABB.set(): minimum must be less than or equal to maximum");
|
||||
assert(zmin<=zmax || !"AABB.set(): minimum must be less than or equal to maximum");
|
||||
m_min = vector3_type(xmin,ymin,zmin);
|
||||
m_max = vector3_type(xmax,ymax,zmax);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set AABB box.
|
||||
*
|
||||
* @param xmin
|
||||
* @param ymin
|
||||
* @param zmin
|
||||
* @param width
|
||||
* @param height
|
||||
* @param depth
|
||||
*/
|
||||
void extent(
|
||||
real_type const & xmin
|
||||
, real_type const & ymin
|
||||
, real_type const & zmin
|
||||
, real_type const & width
|
||||
, real_type const & height
|
||||
, real_type const & depth
|
||||
)
|
||||
{
|
||||
assert(width>=0 || !"AABB.extent(): width must be non-negative");
|
||||
assert(height>=0 || !"AABB.extent(): height must be non-negative");
|
||||
assert(depth>=0 || !"AABB.extent(): depth must be non-negative");
|
||||
m_min = vector3_type(xmin,ymin,zmin);
|
||||
m_max = vector3_type(xmin+width,ymin+height,zmin+depth);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
real_type const & x() const { return m_min[0]; }
|
||||
real_type const & y() const { return m_min[1]; }
|
||||
real_type const & z() const { return m_min[2]; }
|
||||
real_type w() const { return m_max[0] - m_min[0]; }
|
||||
real_type h() const { return m_max[1] - m_min[1]; }
|
||||
real_type d() const { return m_max[2] - m_min[2]; }
|
||||
|
||||
vector3_type & min() { return m_min; }
|
||||
vector3_type & max() { return m_max; }
|
||||
vector3_type const & min() const { return m_min; }
|
||||
vector3_type const & max() const { return m_max; }
|
||||
|
||||
/**
|
||||
* Update Bounding Box
|
||||
* This method updates the size of the AABB such that it encloses the
|
||||
* given nodes.
|
||||
*
|
||||
* @param n0
|
||||
* @param n1
|
||||
* @param n2
|
||||
*/
|
||||
void update(vector3_type const & n0,vector3_type const & n1, vector3_type const & n2)
|
||||
{
|
||||
using std::min;
|
||||
using std::max;
|
||||
|
||||
m_min[0] = min(n2[0],min(n1[0],n0[0]));
|
||||
m_min[1] = min(n2[1],min(n1[1],n0[1]));
|
||||
m_min[2] = min(n2[2],min(n1[2],n0[2]));
|
||||
m_max[0] = max(n2[0],max(n1[0],n0[0]));
|
||||
m_max[1] = max(n2[1],max(n1[1],n0[1]));
|
||||
m_max[2] = max(n2[2],max(n1[2],n0[2]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Bounding Box
|
||||
* This method updates the size of the AABB such that it encloses the
|
||||
* given nodes.
|
||||
*
|
||||
* @param n0
|
||||
* @param n1
|
||||
* @param n2
|
||||
* @param n3
|
||||
*/
|
||||
void update(vector3_type const & n0,vector3_type const & n1,vector3_type const & n2, vector3_type const & n3)
|
||||
{
|
||||
using std::min;
|
||||
using std::max;
|
||||
|
||||
m_min[0] = min(n3[0],min(n2[0],min(n1[0],n0[0])));
|
||||
m_min[1] = min(n3[1],min(n2[1],min(n1[1],n0[1])));
|
||||
m_min[2] = min(n3[2],min(n2[2],min(n1[2],n0[2])));
|
||||
m_max[0] = max(n3[0],max(n2[0],max(n1[0],n0[0])));
|
||||
m_max[1] = max(n3[1],max(n2[1],max(n1[1],n0[1])));
|
||||
m_max[2] = max(n3[2],max(n2[2],max(n1[2],n0[2])));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Box.
|
||||
* This method updates the size of the AABB such that it encloses
|
||||
* the given AABBs.
|
||||
*
|
||||
* @param A
|
||||
* @param B
|
||||
*/
|
||||
void update(AABB const & A,AABB const & B)
|
||||
{
|
||||
using std::min;
|
||||
using std::max;
|
||||
|
||||
m_min[0] = min(A.m_min[0],B.m_min[0]);
|
||||
m_min[1] = min(A.m_min[1],B.m_min[1]);
|
||||
m_min[2] = min(A.m_min[2],B.m_min[2]);
|
||||
m_max[0] = max(A.m_max[0],B.m_max[0]);
|
||||
m_max[1] = max(A.m_max[1],B.m_max[1]);
|
||||
m_max[2] = max(A.m_max[2],B.m_max[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Volume.
|
||||
*
|
||||
* @return The current value of the volume of the AABB.
|
||||
*/
|
||||
real_type volume() const
|
||||
{
|
||||
vector3_type vd = m_max-m_min;
|
||||
return vd[0]*vd[1]*vd[2];
|
||||
}
|
||||
|
||||
real_type area() const
|
||||
{
|
||||
vector3_type vd = m_max-m_min;
|
||||
return 2*vd[0]*vd[1] + 2*vd[0]*vd[2] + 2*vd[2]*vd[1];
|
||||
}
|
||||
|
||||
real_type diameter() const
|
||||
{
|
||||
vector3_type vd = m_max-m_min;
|
||||
return length(vd);
|
||||
}
|
||||
|
||||
void translate(vector3_type const & T)
|
||||
{
|
||||
m_max += T;
|
||||
m_min += T;
|
||||
}
|
||||
|
||||
void rotate(matrix3x3_type const & /*R*/) { }
|
||||
|
||||
void scale(real_type const & s)
|
||||
{
|
||||
assert(s>=value_traits::zero() || !"AABB::scale: s must be non-negative");
|
||||
vector3_type c = center();
|
||||
m_min -= c;
|
||||
m_max -= c;
|
||||
m_min *= s;
|
||||
m_max *= s;
|
||||
m_min += c;
|
||||
m_max += c;
|
||||
}
|
||||
|
||||
vector3_type get_support_point(vector3_type const & v) const
|
||||
{
|
||||
vector3_type dir = unit(v);
|
||||
vector3_type ext = (m_max - m_min)/2.;
|
||||
vector3_type c = center();
|
||||
vector3_type p(0,0,0);
|
||||
|
||||
real_type sign = value_traits::zero();
|
||||
real_type tst = ext[0] * dir[0];
|
||||
if(tst>0)
|
||||
sign = value_traits::one();
|
||||
else if(tst<0)
|
||||
sign = -value_traits::one();
|
||||
else //(tst==0)
|
||||
sign = value_traits::zero();
|
||||
p[0] += sign * ext[0];
|
||||
|
||||
tst = ext[1] * dir[1];
|
||||
if(tst>0)
|
||||
sign = value_traits::one();
|
||||
else if(tst<0)
|
||||
sign = -value_traits::one();
|
||||
else //(tst==0)
|
||||
sign = value_traits::zero();
|
||||
p[1] += sign * ext[1];
|
||||
|
||||
tst = ext[2] * dir[2];
|
||||
if(tst>0)
|
||||
sign = value_traits::one();
|
||||
else if(tst<0)
|
||||
sign = -value_traits::one();
|
||||
else //(tst==0)
|
||||
sign = value_traits::zero();
|
||||
p[2] += sign * ext[2];
|
||||
p += c;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Compute Bounding Box.
|
||||
* This method computes an axis aligned bounding
|
||||
* box (AABB) that encloses the geometry.
|
||||
*
|
||||
* @param r The position of the model frame (i.e the coordinate frame the geometry lives in).
|
||||
* @param R The orientation of the model frame (i.e the coordinate frame the geometry lives in).
|
||||
* @param min_coord Upon return holds the minimum corner of the box.
|
||||
* @param max_coord Upon return holds the maximum corner of the box.
|
||||
*
|
||||
*/
|
||||
void compute_collision_aabb(
|
||||
vector3_type const & r
|
||||
, matrix3x3_type const & /*R*/
|
||||
, vector3_type & min_coord
|
||||
, vector3_type & max_coord
|
||||
) const
|
||||
{
|
||||
min_coord = r + this->min();
|
||||
max_coord = r + this->max();
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
|
||||
} // namespace OpenTissue
|
||||
|
||||
//OPENTISSUE_CORE_GEOMETRY_GEOMETRY_AABB_H
|
||||
#endif
|
||||
@@ -0,0 +1,394 @@
|
||||
#ifndef OPENTISSUE_CORE_GEOMETRY_BARYCENTRIC_H
|
||||
#define OPENTISSUE_CORE_GEOMETRY_BARYCENTRIC_H
|
||||
//
|
||||
// OpenTissue Template Library
|
||||
// - A generic toolbox for physics-based modeling and simulation.
|
||||
// Copyright (C) 2008 Department of Computer Science, University of Copenhagen.
|
||||
//
|
||||
// OTTL is licensed under zlib: http://opensource.org/licenses/zlib-license.php
|
||||
//
|
||||
#include <OpenTissue/configuration.h>
|
||||
|
||||
#include <OpenTissue/core/math/math_is_number.h>
|
||||
#include <OpenTissue/core/math/math_value_traits.h>
|
||||
#include <OpenTissue/core/math/math_matrix3x3.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
|
||||
namespace OpenTissue
|
||||
{
|
||||
namespace geometry
|
||||
{
|
||||
|
||||
/*
|
||||
* Compute Barycentric Coordinates.
|
||||
* This method computes the barycentric coodinates for a point x3 of an edge
|
||||
* given by the points x1 and x2.
|
||||
*
|
||||
* The barycentric coordinates w1 and w2 are defined such
|
||||
* that x3' = w1*x1 + w2*x2, is the point on the line closest to x3.
|
||||
*
|
||||
* if 0 <= w1,w2 <= 1 then the point lies inside or on the perimeter of the triangle.
|
||||
*
|
||||
* @warning This method uses a geometric approach to compute the barycentric coordinates.
|
||||
*
|
||||
* @param x1 The first point of the edge.
|
||||
* @param x2 The second point of the edge.
|
||||
* @param x3 The point for which the barycentric coordinates should be computed.
|
||||
* @param w1 Upon return this parameter contains the value of the first barycentric coordinate.
|
||||
* @param w2 Upon return this parameter contains the value of the second barycentric coordinate.
|
||||
*/
|
||||
template<typename V>
|
||||
inline void barycentric_geometric(
|
||||
V const & x1
|
||||
, V const & x2
|
||||
, V const & x3
|
||||
, typename V::value_type & w1
|
||||
, typename V::value_type & w2
|
||||
)
|
||||
{
|
||||
using std::sqrt;
|
||||
|
||||
typedef typename V::value_type T;
|
||||
typedef typename V::value_traits value_traits;
|
||||
|
||||
V const u = x2-x1;
|
||||
T const uu = dot(u,u);
|
||||
|
||||
assert( is_number(uu) || !"barycentric_geometric(): NaN encountered");
|
||||
assert( uu > value_traits::zero() || !"barycentric_geometric(): Degenerate edge encountered");
|
||||
|
||||
// Project x3 onto edge running from x1 to x2.
|
||||
V const q = (dot(u, x3-x1)/ uu )*u + x1;
|
||||
V const a = q - x2;
|
||||
//V const b = q-x1;
|
||||
T const aa = dot(a,a);
|
||||
|
||||
assert( is_number(aa) || !"barycentric_geometric(): NaN encountered");
|
||||
|
||||
//T const bb = dot(b,b);
|
||||
w1 = sqrt( aa / uu );
|
||||
w2 = value_traits::one() - w1; // sqrt( bb / uu );
|
||||
|
||||
assert( is_number(w1) || !"barycentric_geometric(): NaN encountered");
|
||||
assert( is_number(w2) || !"barycentric_geometric(): NaN encountered");
|
||||
|
||||
assert( w1 >= value_traits::zero() || !"barycentric_geometric(): Illegal coordinate encountered");
|
||||
assert( w1 <= value_traits::one() || !"barycentric_geometric(): Illegal coordinate encountered");
|
||||
assert( w2 >= value_traits::zero() || !"barycentric_geometric(): Illegal coordinate encountered");
|
||||
assert( w2 <= value_traits::one() || !"barycentric_geometric(): Illegal coordinate encountered");
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute Barycentric Coordinates.
|
||||
* This method computes the barycentric coodinates for a point x4 of a triangle
|
||||
* given by the points x1,x2, and x3 (in counter clockwise order).
|
||||
*
|
||||
* The barycentric coordinates w1,w2, and w3 are defined such
|
||||
* that x4' = w1*x1 + w2*x2 + w3*x3, is the point in plane of the
|
||||
* triangle closest to x4.
|
||||
*
|
||||
* if 0 <= w1,w2,w3 <= 1 then the point lies inside or on the perimeter of the triangle.
|
||||
*
|
||||
* @warning This method uses a geometric approach to compute the barycentric coordinates.
|
||||
*
|
||||
* @param x1 The first point of the triangle.
|
||||
* @param x2 The second point of the triangle.
|
||||
* @param x3 The third point of the triangle.
|
||||
* @param x4 The point for which the barycentric coordinates should be computed.
|
||||
* @param w1 Upon return this parameter contains the value of the first barycentric coordinate.
|
||||
* @param w2 Upon return this parameter contains the value of the second barycentric coordinate.
|
||||
* @param w3 Upon return this parameter contains the value of the third barycentric coordinate.
|
||||
*/
|
||||
template<typename V>
|
||||
inline void barycentric_geometric(
|
||||
V const & x1
|
||||
, V const & x2
|
||||
, V const & x3
|
||||
, V const & x4
|
||||
, typename V::value_type & w1
|
||||
, typename V::value_type & w2
|
||||
, typename V::value_type & w3
|
||||
)
|
||||
{
|
||||
using std::sqrt;
|
||||
|
||||
typedef typename V::value_type T;
|
||||
typedef typename V::value_traits value_traits;
|
||||
|
||||
V const n = cross( x1-x3, x2-x3);
|
||||
T const nn = dot(n,n);
|
||||
|
||||
assert( is_number(nn) || !"barycentric_geometric(): NaN encountered");
|
||||
assert( nn > value_traits::zero() || !"barycentric_geometric(): Degenerate triangle encountered");
|
||||
|
||||
V const q = x4 - ( dot(n, x4 - x1)*n / nn );
|
||||
V const a = cross( x2-q, x3-q);
|
||||
V const b = cross( x1-q, x3-q);
|
||||
//V const c = cross( x1-q, x2-q);
|
||||
|
||||
T const aa = dot(a,a);
|
||||
T const bb = dot(b,b);
|
||||
//T const cc = dot(c,c);
|
||||
|
||||
assert( is_number(aa) || !"barycentric_geometric(): NaN encountered");
|
||||
assert( is_number(bb) || !"barycentric_geometric(): NaN encountered");
|
||||
//assert( is_number(cc) || !"barycentric_geometric(): NaN encountered");
|
||||
|
||||
w1 = sqrt( aa / nn );
|
||||
w2 = sqrt( bb / nn );
|
||||
w3 = value_traits::one() - w1 - w2; // sqrt( cc / nn );
|
||||
|
||||
assert( is_number(w1) || !"barycentric_geometric(): NaN encountered");
|
||||
assert( is_number(w2) || !"barycentric_geometric(): NaN encountered");
|
||||
assert( is_number(w3) || !"barycentric_geometric(): NaN encountered");
|
||||
|
||||
assert( w1 >= value_traits::zero() || !"barycentric_geometric(): Illegal coordinate encountered");
|
||||
assert( w1 <= value_traits::one() || !"barycentric_geometric(): Illegal coordinate encountered");
|
||||
assert( w2 >= value_traits::zero() || !"barycentric_geometric(): Illegal coordinate encountered");
|
||||
assert( w2 <= value_traits::one() || !"barycentric_geometric(): Illegal coordinate encountered");
|
||||
assert( w3 >= value_traits::zero() || !"barycentric_geometric(): Illegal coordinate encountered");
|
||||
assert( w3 <= value_traits::one() || !"barycentric_geometric(): Illegal coordinate encountered");
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute Barycentric Coordinates.
|
||||
* This method computes the barycentric coodinates for a point p of a tetrahedron
|
||||
* given by the points x1,x2,x3, x4 (in right-hand order).
|
||||
*
|
||||
* @warning This method uses a geometric approach to compute the barycentric coordinates.
|
||||
*
|
||||
* @param x1 The first point of the triangle.
|
||||
* @param x2 The second point of the triangle.
|
||||
* @param x3 The third point of the triangle.
|
||||
* @param x4 The fourth point of the triangle.
|
||||
* @param p The point for which the barycentric coordinates should be computed.
|
||||
* @param w1 Upon return this parameter contains the value of the first barycentric coordinate.
|
||||
* @param w2 Upon return this parameter contains the value of the second barycentric coordinate.
|
||||
* @param w3 Upon return this parameter contains the value of the third barycentric coordinate.
|
||||
* @param w4 Upon return this parameter contains the value of the fourth barycentric coordinate.
|
||||
*/
|
||||
template<typename V>
|
||||
inline void barycentric_geometric(
|
||||
V const & x1
|
||||
, V const & x2
|
||||
, V const & x3
|
||||
, V const & x4
|
||||
, V const & p
|
||||
, typename V::value_type & w1
|
||||
, typename V::value_type & w2
|
||||
, typename V::value_type & w3
|
||||
, typename V::value_type & w4
|
||||
)
|
||||
{
|
||||
using std::fabs;
|
||||
|
||||
typedef typename V::value_type T;
|
||||
typedef typename V::value_traits value_traits;
|
||||
|
||||
T const V6 = fabs( dot( (x1-x4), cross( x2-x4, x3-x4 ) ) );
|
||||
|
||||
assert( is_number(V6) || !"barycentric_geometric(): NaN encountered");
|
||||
assert( V6 > value_traits::zero() || !"barycentric_geometric(): Degenerate tetrahedron encountered");
|
||||
|
||||
w1 = fabs( dot( (x2-p), cross( (x3-p), (x4-p) ) ) ) / V6;
|
||||
w2 = fabs( dot( (x1-p), cross( (x3-p), (x4-p) ) ) ) / V6;
|
||||
w3 = fabs( dot( (x1-p), cross( (x2-p), (x4-p) ) ) ) / V6;
|
||||
//w4 = fabs( dot( (x1-p), cross( (x2-p), (x3-p) ) ) );
|
||||
w4 = value_traits::one() - w1 -w2 - w3;
|
||||
|
||||
assert( is_number(w1) || !"barycentric_geometric(): NaN encountered");
|
||||
assert( is_number(w2) || !"barycentric_geometric(): NaN encountered");
|
||||
assert( is_number(w3) || !"barycentric_geometric(): NaN encountered");
|
||||
assert( is_number(w4) || !"barycentric_geometric(): NaN encountered");
|
||||
|
||||
assert( w1 >= value_traits::zero() || !"barycentric_geometric(): Illegal coordinate encountered");
|
||||
assert( w1 <= value_traits::one() || !"barycentric_geometric(): Illegal coordinate encountered");
|
||||
assert( w2 >= value_traits::zero() || !"barycentric_geometric(): Illegal coordinate encountered");
|
||||
assert( w2 <= value_traits::one() || !"barycentric_geometric(): Illegal coordinate encountered");
|
||||
assert( w3 >= value_traits::zero() || !"barycentric_geometric(): Illegal coordinate encountered");
|
||||
assert( w3 <= value_traits::one() || !"barycentric_geometric(): Illegal coordinate encountered");
|
||||
assert( w4 >= value_traits::zero() || !"barycentric_geometric(): Illegal coordinate encountered");
|
||||
assert( w4 <= value_traits::one() || !"barycentric_geometric(): Illegal coordinate encountered");
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute Barycentric Coordinates.
|
||||
* This method computes the barycentric coodinates for a point p of a triangle
|
||||
* given by the points x1,x2, and x3 (in counter clockwise order).
|
||||
*
|
||||
* The barycentric coordinates w1, w2, and w3 are defined such
|
||||
* that p' = w1*x1 + w2*x2 + w3*x3, is the point in plane of the
|
||||
* triangle closest to p.
|
||||
*
|
||||
* if 0 <= w1,w2,w3 <= 1 then the point lies inside or on the perimeter of the triangle.
|
||||
*
|
||||
* @warning This method uses a algebraic approach to compute the barycentric coordinates.
|
||||
*
|
||||
* @param x1 The first point of the triangle.
|
||||
* @param x2 The second point of the triangle.
|
||||
* @param x3 The third point of the triangle.
|
||||
* @param p The point for which the barycentric coordinates should be computed.
|
||||
* @param w1 Upon return this parameter contains the value of the first barycentric coordinate.
|
||||
* @param w2 Upon return this parameter contains the value of the second barycentric coordinate.
|
||||
* @param w3 Upon return this parameter contains the value of the third barycentric coordinate.
|
||||
*/
|
||||
template<typename V>
|
||||
inline void barycentric_algebraic(
|
||||
V const & x1
|
||||
, V const & x2
|
||||
, V const & x3
|
||||
, V const & p
|
||||
, typename V::value_type & w1
|
||||
, typename V::value_type & w2
|
||||
, typename V::value_type & w3
|
||||
)
|
||||
{
|
||||
typedef typename V::value_type T;
|
||||
typedef math::ValueTraits<T> value_traits;
|
||||
|
||||
//--- We compute barycentric coordinates, w1,w2,w3, of p, that is we solve the linear system
|
||||
//---
|
||||
//--- |(x1-x3).(x1-x3) (x1-x3).(x2-x3)| |w1| |(x1-x3).(p-x3)|
|
||||
//--- |(x1-x3).(x2-x3) (x2-x3).(x2-x3)| |w2| = |(x2-x3).(p-x3)|
|
||||
//--- w1 + w2 + w3 = 1
|
||||
//---
|
||||
V x13 = x1-x3;
|
||||
V x23 = x2-x3;
|
||||
V x43 = p-x3;
|
||||
|
||||
//---
|
||||
//--- We introduce the shorthand notation
|
||||
//---
|
||||
//--- |a11 a12| |w1| |b1|
|
||||
//--- |a12 a22| |w2| = |b2|
|
||||
//---
|
||||
//--- Isolating w2 from the second equation yields
|
||||
//---
|
||||
//--- w2 = (b2 - a12 w1)/a22
|
||||
//--- = b2/a22 - (a12/a22)w1
|
||||
//---
|
||||
//--- And substituting into the first gives
|
||||
//---
|
||||
//--- a11 w1 + a12 ((b2 - a12 w1)/a22) = b1
|
||||
//--- a11 w1 + (a12/a22)*b2 - a12*(a12/a22)*w1 = b1
|
||||
//--- (a11 - a12*(a12/a22))*w1 = b1 - (a12/a22)*b2
|
||||
//---
|
||||
//--- Letting f = a12/a22 (to minimize computations by collecting common subterms) and
|
||||
//---
|
||||
//--- m = (a11 - a12*f)
|
||||
//--- n = b1 - f*b2
|
||||
//---
|
||||
//--- we have
|
||||
//---
|
||||
//--- w1 = n/m
|
||||
//--- w2 = b2/a22 - f*w1
|
||||
//--- w3 = 1 - w1 - w2
|
||||
//---
|
||||
//--- Since we always have a11>0 and a22>0 a solution will always exist
|
||||
//--- regardless of the value of a12,b1 and b2
|
||||
//---
|
||||
|
||||
T a11 = dot(x13 , x13);
|
||||
T a12 = dot(x13 , x23);
|
||||
T a22 = dot(x23 , x23);
|
||||
T b1 = dot(x13 , x43);
|
||||
T b2 = dot(x23 , x43);
|
||||
|
||||
assert( is_number(a11) || !"barycentric_algebraic(): NaN encountered");
|
||||
assert( is_number(a12) || !"barycentric_algebraic(): NaN encountered");
|
||||
assert( is_number(a22) || !"barycentric_algebraic(): NaN encountered");
|
||||
assert( is_number(b1) || !"barycentric_algebraic(): NaN encountered");
|
||||
assert( is_number(b2) || !"barycentric_algebraic(): NaN encountered");
|
||||
|
||||
assert( a22 < value_traits::zero() || a22>value_traits::zero() || !"barycentric_algebraic(): Degenerate triangle encountered");
|
||||
|
||||
T f = a12/a22;
|
||||
T m = (a11 - a12*f);
|
||||
T n = b1-(b2*f);
|
||||
|
||||
assert( is_number(f) || !"barycentric_algebraic(): NaN encountered");
|
||||
assert( is_number(m) || !"barycentric_algebraic(): NaN encountered");
|
||||
assert( is_number(n) || !"barycentric_algebraic(): NaN encountered");
|
||||
|
||||
assert( m < value_traits::zero() || m > value_traits::zero() || !"barycentric_algebraic(): potential division by zero");
|
||||
|
||||
w1 = n/m;
|
||||
w2 = b2/a22 - f*w1;
|
||||
w3 = value_traits::one() - w1 - w2;
|
||||
|
||||
assert( is_number(w1) || !"barycentric_algebraic(): NaN encountered");
|
||||
assert( is_number(w2) || !"barycentric_algebraic(): NaN encountered");
|
||||
assert( is_number(w3) || !"barycentric_algebraic(): NaN encountered");
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute Barycentric Coordinates.
|
||||
* This method computes the barycentric coodinates for a point p of a tetrahedron
|
||||
* given by the points x1,x2,x3, p (in right-hand order).
|
||||
*
|
||||
* @warning This method uses a algebraic approach to compute the barycentric coordinates.
|
||||
*
|
||||
* @param x1 The first point of the triangle.
|
||||
* @param x2 The second point of the triangle.
|
||||
* @param x3 The third point of the triangle.
|
||||
* @param x4 The fourth point of the triangle.
|
||||
* @param p The point for which the barycentric coordinates should be computed.
|
||||
* @param w1 Upon return this parameter contains the value of the first barycentric coordinate.
|
||||
* @param w2 Upon return this parameter contains the value of the second barycentric coordinate.
|
||||
* @param w3 Upon return this parameter contains the value of the third barycentric coordinate.
|
||||
* @param w4 Upon return this parameter contains the value of the fourth barycentric coordinate.
|
||||
*/
|
||||
template<typename V>
|
||||
inline void barycentric_algebraic(
|
||||
V const & x1
|
||||
, V const & x2
|
||||
, V const & x3
|
||||
, V const & x4
|
||||
, V const & p
|
||||
, typename V::value_type & w1
|
||||
, typename V::value_type & w2
|
||||
, typename V::value_type & w3
|
||||
, typename V::value_type & w4
|
||||
)
|
||||
{
|
||||
typedef typename V::value_type T;
|
||||
typedef math::ValueTraits<T> value_traits;
|
||||
typedef math::Matrix3x3<T> M; // 2008-08-01 kenny: This is rather bad, it makes this function hardwired to our own matrix3x3 type!
|
||||
|
||||
M P;
|
||||
|
||||
P(0,0) = x1(0) - x4(0);
|
||||
P(1,0) = x1(1) - x4(1);
|
||||
P(2,0) = x1(2) - x4(2);
|
||||
|
||||
P(0,1) = x2(0) - x4(0);
|
||||
P(1,1) = x2(1) - x4(1);
|
||||
P(2,1) = x2(2) - x4(2);
|
||||
|
||||
P(0,2) = x3(0) - x4(0);
|
||||
P(1,2) = x3(1) - x4(1);
|
||||
P(2,2) = x3(2) - x4(2);
|
||||
|
||||
P = math::inverse(P); // 2008-08-01 kenny: This is very specific for our OT library, it should probably be a policy?
|
||||
|
||||
V w = P * V(p-x4);
|
||||
|
||||
w1 = w(0);
|
||||
w2 = w(1);
|
||||
w3 = w(2);
|
||||
w4 = value_traits::one() - w1 - w2 - w3;
|
||||
|
||||
assert( is_number(w1) || !"barycentric_algebraic(): NaN encountered");
|
||||
assert( is_number(w2) || !"barycentric_algebraic(): NaN encountered");
|
||||
assert( is_number(w3) || !"barycentric_algebraic(): NaN encountered");
|
||||
assert( is_number(w4) || !"barycentric_algebraic(): NaN encountered");
|
||||
|
||||
}
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace OpenTissue
|
||||
|
||||
// OPENTISSUE_CORE_GEOMETRY_BARYCENTRIC_H
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
#ifndef OPENTISSUE_CORE_GEOMETRY_GEOMETRY_BASE_SHAPE_H
|
||||
#define OPENTISSUE_CORE_GEOMETRY_GEOMETRY_BASE_SHAPE_H
|
||||
//
|
||||
// OpenTissue Template Library
|
||||
// - A generic toolbox for physics-based modeling and simulation.
|
||||
// Copyright (C) 2008 Department of Computer Science, University of Copenhagen.
|
||||
//
|
||||
// OTTL is licensed under zlib: http://opensource.org/licenses/zlib-license.php
|
||||
//
|
||||
#include <OpenTissue/configuration.h>
|
||||
|
||||
#include <OpenTissue/collision/collision_geometry_interface.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace OpenTissue
|
||||
{
|
||||
|
||||
namespace geometry
|
||||
{
|
||||
|
||||
/**
|
||||
* BaseShape Template Class
|
||||
* If you implement a new geometry type then you should derive your geometry class from the BaseShape class
|
||||
*
|
||||
* @tparam math_types standard math types containing at least the real, vector3 and matrix3x3 types.
|
||||
**/
|
||||
template< typename math_types >
|
||||
class BaseShape
|
||||
: public OpenTissue::collision::GeometryInterface< math_types >
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~BaseShape() {}
|
||||
|
||||
public:
|
||||
|
||||
typedef typename math_types::real_type real_type;
|
||||
typedef typename math_types::vector3_type vector3_type;
|
||||
typedef typename math_types::matrix3x3_type matrix3x3_type;
|
||||
|
||||
|
||||
// 2007-07-24 kenny: generic design problem with compute_surface_points
|
||||
// 2007-09-11 micky: I agree, it's not possible to have a pure abstract interface and letting the user decide his choice of point container.
|
||||
// 2007-09-11 micky: compute_surface_points and get_support_point should be removed from this interface. Both functions belong to some collision interface.
|
||||
// 2007-09-18 kenny: I partial agree... get_support_point is used by GJK (exclusively as I recall?) However, compute_surface_points is used by some of the geometry utils. Fitting tools and such.
|
||||
|
||||
// TODO 2007-02-06 kenny: Yikes what if end-user wants to use std::list or some homebrewed container type? It is a bit ugly that the container type is hardwired into the abstract base class:-( Could we make something like a pure virtual template class?
|
||||
virtual void compute_surface_points( std::vector<vector3_type> & points) const = 0;
|
||||
virtual vector3_type get_support_point(vector3_type const & v) const = 0;
|
||||
|
||||
virtual void translate(vector3_type const & T) = 0;
|
||||
virtual void rotate(matrix3x3_type const & R) = 0;
|
||||
virtual void scale(real_type const & s) = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
|
||||
} // namespace OpenTissue
|
||||
|
||||
//OPENTISSUE_CORE_GEOMETRY_GEOMETRY_BASE_SHAPE_H
|
||||
#endif
|
||||
@@ -0,0 +1,103 @@
|
||||
#ifndef OPENTISSUE_CORE_GEOMETRY_GEOMETRY_COMPUTE_TETRAHEDRON_AABB_H
|
||||
#define OPENTISSUE_CORE_GEOMETRY_GEOMETRY_COMPUTE_TETRAHEDRON_AABB_H
|
||||
//
|
||||
// OpenTissue Template Library
|
||||
// - A generic toolbox for physics-based modeling and simulation.
|
||||
// Copyright (C) 2008 Department of Computer Science, University of Copenhagen.
|
||||
//
|
||||
// OTTL is licensed under zlib: http://opensource.org/licenses/zlib-license.php
|
||||
//
|
||||
#include <OpenTissue/configuration.h>
|
||||
|
||||
#include <OpenTissue/core/geometry/geometry_aabb.h>
|
||||
|
||||
namespace OpenTissue
|
||||
{
|
||||
namespace geometry
|
||||
{
|
||||
/**
|
||||
* Compute AABB of Tetrahedron.
|
||||
*
|
||||
*
|
||||
* @param p0 The position of a corner of the tetrahedron.
|
||||
* @param p1 The position of a corner of the tetrahedron.
|
||||
* @param p2 The position of a corner of the tetrahedron.
|
||||
* @param p3 The position of a corner of the tetrahedron.
|
||||
* @param min_coord Upon return holds the minimum coordinate corner of the AABB.
|
||||
* @param max_coord Upon return holds the maximum coordinate corner of the AABB.
|
||||
*/
|
||||
template<typename vector3_type>
|
||||
void compute_tetrahedron_aabb(
|
||||
vector3_type const & p0
|
||||
, vector3_type const & p1
|
||||
, vector3_type const & p2
|
||||
, vector3_type const & p3
|
||||
, vector3_type & min_coord
|
||||
, vector3_type & max_coord
|
||||
)
|
||||
{
|
||||
using std::min;
|
||||
|
||||
min_coord = min(p0, p1);
|
||||
min_coord = min(min_coord, p2);
|
||||
min_coord = min(min_coord, p3);
|
||||
|
||||
max_coord = max(p0, p1);
|
||||
max_coord = max(max_coord, p2);
|
||||
max_coord = max(max_coord, p3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute Tetrahedron AABB.
|
||||
*
|
||||
* This function computes a tight fitting axis aligned bounding box around the specified tetrahedron.
|
||||
*
|
||||
* @param tetrahedron The specified tetrahedron.
|
||||
* @param min_coord Upon return holds the minimum coordinate corner of the AABB.
|
||||
* @param max_coord Upon return holds the maximum coordinate corner of the AABB.
|
||||
*/
|
||||
template<typename tetrahedron_type,typename vector3_type>
|
||||
void compute_tetrahedron_aabb(
|
||||
tetrahedron_type const & tetrahedron
|
||||
, vector3_type & min_coord
|
||||
, vector3_type & max_coord
|
||||
)
|
||||
{
|
||||
compute_tetrahedron_aabb(tetrahedron.p0(),tetrahedron.p1(),tetrahedron.p2(),tetrahedron.p3(),min_coord,max_coord);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute Tetrahedron AABB.
|
||||
*
|
||||
* This function computes a tight fitting axis aligned bounding box around the specified tetrahedron.
|
||||
*
|
||||
* @param tetrahedron The specified tetrahedron.
|
||||
* @param aabb Upon return holds the computed AABB.
|
||||
*/
|
||||
template<typename tetrahedron_type,typename aabb_type>
|
||||
void compute_tetrahedron_aabb(tetrahedron_type const & tetrahedron,aabb_type & aabb)
|
||||
{
|
||||
compute_tetrahedron_aabb(tetrahedron.p0(),tetrahedron.p1(),tetrahedron.p2(),tetrahedron.p3(),aabb.min(),aabb.max());
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute Tetrahedron AABB.
|
||||
*
|
||||
* This function computes a tight fitting axis aligned bounding box around the specified tetrahedron.
|
||||
*
|
||||
* @param tetrahedron The specified tetrahedron.
|
||||
* @return The computed AABB.
|
||||
*/
|
||||
template<typename tetrahedron_type>
|
||||
geometry::AABB<typename tetrahedron_type::math_types> compute_tetrahedron_aabb(tetrahedron_type const & tetrahedron)
|
||||
{
|
||||
geometry::AABB<typename tetrahedron_type::math_types> aabb;
|
||||
compute_tetrahedron_aabb(tetrahedron,aabb);
|
||||
return aabb;
|
||||
}
|
||||
|
||||
} //End of namespace geometry
|
||||
} //End of namespace OpenTissue
|
||||
|
||||
// OPENTISSUE_CORE_GEOMETRY_GEOMETRY_COMPUTE_TETRAHEDRON_AABB_H
|
||||
#endif
|
||||
@@ -0,0 +1,272 @@
|
||||
#ifndef OPENTISSUE_CORE_GEOMETRY_GEOMETRY_TETRAHEDRON_H
|
||||
#define OPENTISSUE_CORE_GEOMETRY_GEOMETRY_TETRAHEDRON_H
|
||||
//
|
||||
// OpenTissue Template Library
|
||||
// - A generic toolbox for physics-based modeling and simulation.
|
||||
// Copyright (C) 2008 Department of Computer Science, University of Copenhagen.
|
||||
//
|
||||
// OTTL is licensed under zlib: http://opensource.org/licenses/zlib-license.php
|
||||
//
|
||||
#include <OpenTissue/configuration.h>
|
||||
|
||||
#include <OpenTissue/core/geometry/geometry_volume_shape.h>
|
||||
#include <OpenTissue/core/geometry/geometry_compute_tetrahedron_aabb.h>
|
||||
|
||||
#include <OpenTissue/utility/utility_class_id.h>
|
||||
#include <OpenTissue/core/math/math_constants.h>
|
||||
#include <OpenTissue/core/geometry/geometry_barycentric.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <float.h>
|
||||
|
||||
|
||||
namespace OpenTissue
|
||||
{
|
||||
|
||||
namespace geometry
|
||||
{
|
||||
|
||||
template< typename math_types_ >
|
||||
class Tetrahedron
|
||||
: public VolumeShape< math_types_ >
|
||||
, public OpenTissue::utility::ClassID< OpenTissue::geometry::Tetrahedron<math_types_> >
|
||||
{
|
||||
public:
|
||||
|
||||
typedef math_types_ math_types;
|
||||
typedef typename math_types::value_traits value_traits;
|
||||
typedef typename math_types::real_type real_type;
|
||||
typedef typename math_types::vector3_type vector3_type;
|
||||
typedef typename math_types::matrix3x3_type matrix3x3_type;
|
||||
typedef typename math_types::quaternion_type quaternion_type;
|
||||
|
||||
protected:
|
||||
|
||||
vector3_type m_p0; ///< Tetrahedron vertex number 1
|
||||
vector3_type m_p1; ///< Tetrahedron vertex number 2
|
||||
vector3_type m_p2; ///< Tetrahedron vertex number 3
|
||||
vector3_type m_p3; ///< Tetrahedron vertex number 4
|
||||
|
||||
public:
|
||||
|
||||
size_t const class_id() const { return OpenTissue::utility::ClassID<OpenTissue::geometry::Tetrahedron<math_types_> >::class_id(); }
|
||||
|
||||
Tetrahedron()
|
||||
{
|
||||
m_p0.clear();
|
||||
m_p1.clear();
|
||||
m_p2.clear();
|
||||
m_p3.clear();
|
||||
}
|
||||
|
||||
virtual ~Tetrahedron() {}
|
||||
|
||||
Tetrahedron(Tetrahedron const & tetrahedron_) { set(tetrahedron_); }
|
||||
|
||||
Tetrahedron( vector3_type const & p0, vector3_type const & p1, vector3_type const & p2, vector3_type const & p3)
|
||||
{
|
||||
set(p0,p1,p2,p3);
|
||||
}
|
||||
|
||||
Tetrahedron const & operator=(Tetrahedron const & tetrahedron_)
|
||||
{
|
||||
set(tetrahedron_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void set(Tetrahedron const & t)
|
||||
{
|
||||
m_p0 = t.m_p0;
|
||||
m_p1 = t.m_p1;
|
||||
m_p2 = t.m_p2;
|
||||
m_p3 = t.m_p3;
|
||||
}
|
||||
|
||||
void set(vector3_type const & p0, vector3_type const & p1, vector3_type const & p2, vector3_type const & p3)
|
||||
{
|
||||
m_p0 = p0;
|
||||
m_p1 = p1;
|
||||
m_p2 = p2;
|
||||
m_p3 = p3;
|
||||
}
|
||||
|
||||
real_type area() const
|
||||
{
|
||||
vector3_type u,v,uXv;
|
||||
real_type A = value_traits::zero();
|
||||
|
||||
u = m_p1-m_p0;
|
||||
v = m_p2-m_p0;
|
||||
uXv = (u % v);
|
||||
A += length(uXv);
|
||||
|
||||
u = m_p0-m_p3;
|
||||
v = m_p1-m_p3;
|
||||
uXv = (u % v);
|
||||
A += length(uXv);
|
||||
|
||||
u = m_p1-m_p3;
|
||||
v = m_p2-m_p3;
|
||||
uXv = (u % v);
|
||||
A += length(uXv);
|
||||
|
||||
u = m_p2-m_p3;
|
||||
v = m_p0-m_p3;
|
||||
uXv = (u % v);
|
||||
A += length(uXv);
|
||||
|
||||
return A/value_traits::two();
|
||||
}
|
||||
|
||||
void compute_surface_points(std::vector<vector3_type> & points) const
|
||||
{
|
||||
points.push_back(m_p0);
|
||||
points.push_back(m_p1);
|
||||
points.push_back(m_p2);
|
||||
points.push_back(m_p3);
|
||||
}
|
||||
|
||||
vector3_type & p0() { return m_p0; };
|
||||
vector3_type & p1() { return m_p1; };
|
||||
vector3_type & p2() { return m_p2; };
|
||||
vector3_type & p3() { return m_p3; };
|
||||
vector3_type const & p0() const { return m_p0; };
|
||||
vector3_type const & p1() const { return m_p1; };
|
||||
vector3_type const & p2() const { return m_p2; };
|
||||
vector3_type const & p3() const { return m_p3; };
|
||||
|
||||
vector3_type center() const { return vector3_type( (m_p0+m_p1+m_p2+m_p3)/4. ); };
|
||||
|
||||
/**
|
||||
* Compute Barycentric Coordinates.
|
||||
*
|
||||
* @param p The point for which the barycentric coordinates should be computed.
|
||||
* @param w1 Upon return this parameter contains the value of the first barycentric coordinate.
|
||||
* @param w2 Upon return this parameter contains the value of the second barycentric coordinate.
|
||||
* @param w3 Upon return this parameter contains the value of the third barycentric coordinate.
|
||||
* @param w4 Upon return this parameter contains the value of the fourth barycentric coordinate.
|
||||
*/
|
||||
void barycentric(vector3_type const & p,real_type & w1,real_type & w2,real_type & w3,real_type & w4) const
|
||||
{
|
||||
OpenTissue::geometry::barycentric_algebraic(m_p0,m_p1,m_p2,m_p3,p,w1,w2,w3,w4);
|
||||
}
|
||||
|
||||
real_type diameter() const
|
||||
{
|
||||
using std::max;
|
||||
using std::sqrt;
|
||||
|
||||
vector3_type x30 = m_p3 - m_p0;
|
||||
vector3_type x20 = m_p2 - m_p0;
|
||||
vector3_type x10 = m_p1 - m_p0;
|
||||
real_type d = max( max(x30*x30, x20*x20), x10*x10);
|
||||
return sqrt(d);
|
||||
}
|
||||
|
||||
vector3_type get_support_point(vector3_type const & v) const
|
||||
{
|
||||
vector3_type p;
|
||||
real_type tst = -FLT_MAX;//math::detail::lowest<real_type>();
|
||||
real_type tmp = v * m_p0;
|
||||
if (tmp>tst)
|
||||
{
|
||||
tst = tmp;
|
||||
p = m_p0;
|
||||
}
|
||||
tmp = v * m_p1;
|
||||
if (tmp>tst)
|
||||
{
|
||||
tst = tmp;
|
||||
p = m_p1;
|
||||
}
|
||||
tmp = v *m_p2;
|
||||
if (tmp>tst)
|
||||
{
|
||||
tst = tmp;
|
||||
p = m_p2;
|
||||
}
|
||||
tmp = v * m_p3;
|
||||
if (tmp>tst)
|
||||
{
|
||||
tst = tmp;
|
||||
p = m_p3;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void translate(vector3_type const & T)
|
||||
{
|
||||
m_p0 += T;
|
||||
m_p1 += T;
|
||||
m_p2 += T;
|
||||
m_p3 += T;
|
||||
}
|
||||
|
||||
void rotate(matrix3x3_type const & R)
|
||||
{
|
||||
vector3_type c = center();
|
||||
m_p0 = (R*(m_p0 - c)) + c;
|
||||
m_p1 = (R*(m_p1 - c)) + c;
|
||||
m_p2 = (R*(m_p2 - c)) + c;
|
||||
m_p3 = (R*(m_p3 - c)) + c;
|
||||
}
|
||||
|
||||
void scale(real_type const & s)
|
||||
{
|
||||
vector3_type c = center();
|
||||
m_p0 = s*(m_p0 - c) + c;
|
||||
m_p1 = s*(m_p1 - c) + c;
|
||||
m_p2 = s*(m_p2 - c) + c;
|
||||
m_p3 = s*(m_p3 - c) + c;
|
||||
}
|
||||
|
||||
real_type volume() const
|
||||
{
|
||||
/*
|
||||
** From Zienkiewicz & Taylor p.637
|
||||
** V = 1/6*det( 1 x0 y0 z0; 1 x1 y1 z1; 1 x2 y2 z2; 1 x3 y3 z3)
|
||||
** where x0 = n0->i; y0 = n0[1]; ...
|
||||
** Calculated by Mathematica ;-)
|
||||
*/
|
||||
return (m_p0[2]*m_p1[1]*m_p2[0] - m_p0[1]*m_p1[2]*m_p2[0] - m_p0[2]*m_p1[0]*m_p2[1]
|
||||
+ m_p0[0]*m_p1[2]*m_p2[1] + m_p0[1]*m_p1[0]*m_p2[2] - m_p0[0]*m_p1[1]*m_p2[2]
|
||||
- m_p0[2]*m_p1[1]*m_p3[0] + m_p0[1]*m_p1[2]*m_p3[0] + m_p0[2]*m_p2[1]*m_p3[0]
|
||||
- m_p1[2]*m_p2[1]*m_p3[0] - m_p0[1]*m_p2[2]*m_p3[0] + m_p1[1]*m_p2[2]*m_p3[0]
|
||||
+ m_p0[2]*m_p1[0]*m_p3[1] - m_p0[0]*m_p1[2]*m_p3[1] - m_p0[2]*m_p2[0]*m_p3[1]
|
||||
+ m_p1[2]*m_p2[0]*m_p3[1] + m_p0[0]*m_p2[2]*m_p3[1] - m_p1[0]*m_p2[2]*m_p3[1]
|
||||
- m_p0[1]*m_p1[0]*m_p3[2] + m_p0[0]*m_p1[1]*m_p3[2] + m_p0[1]*m_p2[0]*m_p3[2]
|
||||
- m_p1[1]*m_p2[0]*m_p3[2] - m_p0[0]*m_p2[1]*m_p3[2] + m_p1[0]*m_p2[1]*m_p3[2])/6.;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compute Bounding Box.
|
||||
* This method computes an axis aligned bounding
|
||||
* box (AABB) that encloses the geometry.
|
||||
*
|
||||
* @param r The position of the model frame (i.e the coordinate frame the geometry lives in).
|
||||
* @param R The orientation of the model frame (i.e the coordinate frame the geometry lives in).
|
||||
* @param min_coord Upon return holds the minimum corner of the box.
|
||||
* @param max_coord Upon return holds the maximum corner of the box.
|
||||
*
|
||||
*/
|
||||
void compute_collision_aabb(
|
||||
vector3_type const & r
|
||||
, matrix3x3_type const & R
|
||||
, vector3_type & min_coord
|
||||
, vector3_type & max_coord
|
||||
) const
|
||||
{
|
||||
compute_tetrahedron_aabb( *this, min_coord, max_coord );
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
|
||||
} // namespace OpenTissue
|
||||
|
||||
// OPENTISSUE_CORE_GEOMETRY_GEOMETRY_TETRAHEDRON_H
|
||||
#endif
|
||||
@@ -0,0 +1,157 @@
|
||||
#ifndef OPENTISSUE_CORE_GEOMETRY_GEOMETRY_TETRAHEDRON_SLICER_H
|
||||
#define OPENTISSUE_CORE_GEOMETRY_GEOMETRY_TETRAHEDRON_SLICER_H
|
||||
//
|
||||
// OpenTissue Template Library
|
||||
// - A generic toolbox for physics-based modeling and simulation.
|
||||
// Copyright (C) 2008 Department of Computer Science, University of Copenhagen.
|
||||
//
|
||||
// OTTL is licensed under zlib: http://opensource.org/licenses/zlib-license.php
|
||||
//
|
||||
#include <OpenTissue/configuration.h>
|
||||
|
||||
|
||||
namespace OpenTissue
|
||||
{
|
||||
namespace geometry
|
||||
{
|
||||
|
||||
|
||||
template<typename vector3_type_>
|
||||
class TetrahedronSlicer
|
||||
{
|
||||
public:
|
||||
|
||||
typedef vector3_type_ vector3_type;
|
||||
typedef typename vector3_type::value_type real_type;
|
||||
|
||||
|
||||
vector3_type m_nodes[4]; ///< Nodes of tetrahedron
|
||||
int m_edges[6][2]; ///< Edge topology of tetrahedron
|
||||
///< m_edges[i][0] index of the first node of the i'th edge
|
||||
///< m_edges[i][1] index of the second node of the i'th edge
|
||||
|
||||
vector3_type m_intersections[4]; ///< Intersection points of slice and tetrahedron.
|
||||
vector3_type m_triangle1[3]; ///< Vertices of first triangle in slice.
|
||||
vector3_type m_triangle2[3]; ///< Vertices of second trinagle in slice.
|
||||
|
||||
public:
|
||||
|
||||
TetrahedronSlicer(
|
||||
vector3_type const & p0
|
||||
, vector3_type const & p1
|
||||
, vector3_type const & p2
|
||||
, vector3_type const & p3
|
||||
)
|
||||
{
|
||||
m_nodes[0] = p0;
|
||||
m_nodes[1] = p1;
|
||||
m_nodes[2] = p2;
|
||||
m_nodes[3] = p3;
|
||||
|
||||
//
|
||||
// Node indices and edge labels:
|
||||
//
|
||||
// 3
|
||||
// +
|
||||
// / \
|
||||
// / \
|
||||
// / . \
|
||||
// / \
|
||||
// / \
|
||||
// / . \
|
||||
// / \
|
||||
// / \
|
||||
// / . \
|
||||
// C F E
|
||||
// / \
|
||||
// / . \
|
||||
// / \
|
||||
// / . \
|
||||
// / 2+ \
|
||||
// / . . \
|
||||
// / . B D. \
|
||||
// / . . \
|
||||
// +------------------A------------------+
|
||||
//0 1
|
||||
//
|
||||
//
|
||||
m_edges[ 0 ][ 0 ] = 0; // A
|
||||
m_edges[ 0 ][ 1 ] = 1;
|
||||
m_edges[ 1 ][ 0 ] = 0; // B
|
||||
m_edges[ 1 ][ 1 ] = 2;
|
||||
m_edges[ 2 ][ 0 ] = 0; // C
|
||||
m_edges[ 2 ][ 1 ] = 3;
|
||||
m_edges[ 3 ][ 0 ] = 1; // D
|
||||
m_edges[ 3 ][ 1 ] = 2;
|
||||
m_edges[ 4 ][ 0 ] = 1; // E
|
||||
m_edges[ 4 ][ 1 ] = 3;
|
||||
m_edges[ 5 ][ 0 ] = 2; // F
|
||||
m_edges[ 5 ][ 1 ] = 3;
|
||||
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
template<typename plane_type>
|
||||
void compute_slice(plane_type const & plane)
|
||||
{
|
||||
//--- Loop over all edges and find those that cross the plane
|
||||
int count = 0;
|
||||
for(int i=0;i<6;++i)
|
||||
{
|
||||
vector3_type & a = m_nodes[m_edges[i][0]];
|
||||
vector3_type & b = m_nodes[m_edges[i][1]];
|
||||
real_type dst_a = plane.signed_distance(a);
|
||||
real_type dst_b = plane.signed_distance(b);
|
||||
if ( (dst_a*dst_b<0) || (dst_a==0 && dst_b>0) || (dst_b==0 && dst_a>0))
|
||||
{
|
||||
//--- Compute coordinates of the plane intersections
|
||||
vector3_type & a = m_nodes[m_edges[ i ][0]];
|
||||
vector3_type & b = m_nodes[m_edges[ i ][1]];
|
||||
m_intersections[count++] = plane.get_intersection(a,b);
|
||||
}
|
||||
}
|
||||
assert(count==3 || count==4); //--no other possibilities?
|
||||
|
||||
//--- Order plane intersections to a a CCW polygon (as seen from positive side of plane)
|
||||
vector3_type & n = plane.n();
|
||||
vector3_type e10 = m_intersections[1] - m_intersections[0];
|
||||
vector3_type e21 = m_intersections[2] - m_intersections[1];
|
||||
if(n*(e10%e20)<0)
|
||||
{
|
||||
m_triangle1[0] = m_intersections[0];
|
||||
m_triangle1[1] = m_intersections[2];
|
||||
m_triangle1[2] = m_intersections[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_triangle1[0] = m_intersections[0];
|
||||
m_triangle1[1] = m_intersections[1];
|
||||
m_triangle1[2] = m_intersections[2];
|
||||
}
|
||||
if ( count == 4 )
|
||||
{
|
||||
for(int i=0;i<3;++i)
|
||||
{
|
||||
int next = (i+1)%3;
|
||||
int prev = i;
|
||||
vector3_type e = m_triangle1[next] - m_triangle1[prev];
|
||||
vector3_type h = m_intersections[4] - m_triangle1[prev];
|
||||
if(n*(h%e)>0)
|
||||
{
|
||||
m_triangle2[0] = m_triangle1[prev];
|
||||
m_triangle2[1] = m_intersections[4];
|
||||
m_triangle2[2] = m_triangle1[next];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace OpenTissue
|
||||
|
||||
//OPENTISSUE_CORE_GEOMETRY_GEOMETRY_TETRAHEDRON_SLICER_H
|
||||
#endif
|
||||
@@ -0,0 +1,165 @@
|
||||
#ifndef OPENTISSUE_CORE_GEOMETRY_GEOMETRY_TETRAHEDRON_Z_SLICER_H
|
||||
#define OPENTISSUE_CORE_GEOMETRY_GEOMETRY_TETRAHEDRON_Z_SLICER_H
|
||||
//
|
||||
// OpenTissue Template Library
|
||||
// - A generic toolbox for physics-based modeling and simulation.
|
||||
// Copyright (C) 2008 Department of Computer Science, University of Copenhagen.
|
||||
//
|
||||
// OTTL is licensed under zlib: http://opensource.org/licenses/zlib-license.php
|
||||
//
|
||||
#include <OpenTissue/configuration.h>
|
||||
|
||||
namespace OpenTissue
|
||||
{
|
||||
namespace geometry
|
||||
{
|
||||
/**
|
||||
* Specialized Tetrahedron Slicer.
|
||||
* Cut a tetrahedron with a specified z-plane and returns the
|
||||
* sliced tetrahedron.
|
||||
*
|
||||
* This code was originally implemented by Andreas Bæentzen, IMM (jab@imm.dtu.dk).
|
||||
*
|
||||
*/
|
||||
template<typename vector3_type_>
|
||||
class ZTetrahedronSlicer
|
||||
{
|
||||
public:
|
||||
|
||||
typedef vector3_type_ vector3_type;
|
||||
typedef typename vector3_type::value_type real_type;
|
||||
|
||||
protected:
|
||||
|
||||
vector3_type m_p[4]; ///< Nodes of tetrahedron.
|
||||
|
||||
public:
|
||||
|
||||
ZTetrahedronSlicer(
|
||||
vector3_type const & p0
|
||||
, vector3_type const & p1
|
||||
, vector3_type const & p2
|
||||
, vector3_type const & p3
|
||||
)
|
||||
{
|
||||
m_p[0] = p0;
|
||||
m_p[1] = p1;
|
||||
m_p[2] = p2;
|
||||
m_p[3] = p3;
|
||||
|
||||
//--- Primitive bubble sort - ensures that tetrahedron vertices
|
||||
//--- are sorted according to z value.
|
||||
while(swap(0,1)||swap(1,2)||swap(2,3));
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Swap the order of two nodes if their z-value allows it.
|
||||
*
|
||||
* @param i A node index.
|
||||
* @param j A node index.
|
||||
*
|
||||
* @return true if swapped otherwise false.
|
||||
*/
|
||||
bool swap(int i,int j)
|
||||
{
|
||||
if(m_p[j](2)< m_p[i](2))
|
||||
{
|
||||
vector3_type tmp = m_p[j];
|
||||
m_p[j] = m_p[i];
|
||||
m_p[i] = tmp;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Computes intersection point of edge going from node i towards node j
|
||||
*
|
||||
* @param z The z value, indicating the z-plane aginst which the edge is tested.
|
||||
* @param i The node index of the starting node (got lowest z-value).
|
||||
* @param j The node index of the ending node (got highest z-value).
|
||||
* @param p Upon return this argument holds the intersection point.
|
||||
*/
|
||||
void intersect(real_type const & z, int i, int j, vector3_type & p) const
|
||||
{
|
||||
p = m_p[i];
|
||||
vector3_type dir = m_p[j] - m_p[i];
|
||||
real_type s = (z-m_p[i](2))/(m_p[j](2)-m_p[i](2));
|
||||
p += s * dir;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Compute Intersection Slice of Tetrahedron and Z-plane.
|
||||
*
|
||||
* @param z The z-plane to slice against.
|
||||
* @param slice Upon return holds the intersection points of the sliced tetrahedron.
|
||||
*
|
||||
* @return The number of vertices in the sliced tetrahedron.
|
||||
*/
|
||||
unsigned int intersect(real_type const & z, vector3_type slice[4]) const
|
||||
{
|
||||
if( z < m_p[0](2) || z > m_p[3](2) )
|
||||
return 0;
|
||||
if( z<m_p[1](2) )
|
||||
{
|
||||
intersect(z,0,3, slice[0]);
|
||||
intersect(z,0,1, slice[1]);
|
||||
intersect(z,0,2, slice[2]);
|
||||
return 3;
|
||||
}
|
||||
else if( z<m_p[2](2) )
|
||||
{
|
||||
intersect(z,0,3, slice[0]);
|
||||
intersect(z,1,3, slice[1]);
|
||||
intersect(z,1,2, slice[2]);
|
||||
intersect(z,0,2, slice[3]);
|
||||
return 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
intersect(z,0,3, slice[0]);
|
||||
intersect(z,1,3, slice[1]);
|
||||
intersect(z,2,3, slice[2]);
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
// unsigned int intersect(real_type const & z, vector3_type slice[4]) const
|
||||
// {
|
||||
// unsigned int cnt=0;
|
||||
// if(z > m_p[0](2))
|
||||
// {
|
||||
// if(z < m_p[3](2))
|
||||
// {
|
||||
// intersect(z,0,3,slice[cnt++]);
|
||||
// if(z<m_p[1](2))
|
||||
// intersect(z,0,1,slice[cnt++]);
|
||||
// else
|
||||
// {
|
||||
// intersect(z,1,3,slice[cnt++]);
|
||||
//
|
||||
// if(z<m_p[2](2))
|
||||
// intersect(z,1,2,slice[cnt++]);
|
||||
// }
|
||||
// if(z<m_p[2](2))
|
||||
// intersect(z,0,2, slice[cnt++]);
|
||||
// else
|
||||
// intersect(z,2,3,slice[cnt++]);
|
||||
// return cnt;
|
||||
// }
|
||||
// else return 0;
|
||||
// }
|
||||
// else
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace OpenTissue
|
||||
|
||||
//OPENTISSUE_CORE_GEOMETRY_GEOMETRY_TETRAHEDRON_Z_SLICER_H
|
||||
#endif
|
||||
@@ -0,0 +1,77 @@
|
||||
#ifndef OPENTISSUE_CORE_GEOMETRY_GEOMETRY_VOLUME_SHAPE_H
|
||||
#define OPENTISSUE_CORE_GEOMETRY_GEOMETRY_VOLUME_SHAPE_H
|
||||
//
|
||||
// OpenTissue Template Library
|
||||
// - A generic toolbox for physics-based modeling and simulation.
|
||||
// Copyright (C) 2008 Department of Computer Science, University of Copenhagen.
|
||||
//
|
||||
// OTTL is licensed under zlib: http://opensource.org/licenses/zlib-license.php
|
||||
//
|
||||
#include <OpenTissue/configuration.h>
|
||||
|
||||
#include <OpenTissue/core/geometry/geometry_base_shape.h>
|
||||
|
||||
|
||||
namespace OpenTissue
|
||||
{
|
||||
namespace geometry
|
||||
{
|
||||
/**
|
||||
* VolumeShape Template Class.
|
||||
* If you implement a new volumetric geometry then you should derive your new class from the VolumeShape class .
|
||||
*
|
||||
* @tparam math_types standard math types containing at least the real, vector3 and matrix3x3 types.
|
||||
**/
|
||||
template<typename math_types >
|
||||
class VolumeShape
|
||||
: public BaseShape< math_types >
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~VolumeShape() {}
|
||||
|
||||
public:
|
||||
|
||||
typedef typename math_types::real_type real_type;
|
||||
typedef typename math_types::vector3_type vector3_type;
|
||||
typedef typename math_types::matrix3x3_type matrix3x3_type;
|
||||
|
||||
/**
|
||||
* Get Center Position.
|
||||
*
|
||||
* @return The center point of the volume shape, in most cases this would be the mean point.
|
||||
*/
|
||||
virtual vector3_type center() const = 0;
|
||||
|
||||
/**
|
||||
* Get Volume.
|
||||
*
|
||||
* @return The actual volume of the shape.
|
||||
*/
|
||||
virtual real_type volume() const = 0;
|
||||
|
||||
/**
|
||||
* Get Area.
|
||||
*
|
||||
* @return The actual surface area of the volume.
|
||||
*/
|
||||
virtual real_type area() const = 0;
|
||||
|
||||
/**
|
||||
* Get Diameter.
|
||||
*
|
||||
*
|
||||
* @return A measure of the diameter of the shape. Not all shapes have a well-defined
|
||||
* diameter in such cases the measure would simply be a measure of the longst
|
||||
* extent of the shape.
|
||||
*/
|
||||
virtual real_type diameter() const = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
|
||||
} // namespace OpenTissue
|
||||
|
||||
//OPENTISSUE_CORE_GEOMETRY_GEOMETRY_VOLUME_SHAPE_H
|
||||
#endif
|
||||
Reference in New Issue
Block a user