38 #include <geogram/mesh/mesh.h> 40 #include <geogram/numerics/predicates.h> 53 bool is_almost_zero(
double value )
55 return value < global_epsilon && value > -global_epsilon;
63 return dot( v0,
vec2( v1.y, -v1.x ) );
69 const vec3& triangle_normal )
71 double area{ GEO::Geom::triangle_area( p0, p1, p2 ) };
72 vec3 area_normal{ cross( p0 - p2, p1 - p2 ) };
73 if( dot( triangle_normal, area_normal ) < 0 )
82 return u.x == v.x && u.y == v.y && u.z == v.z;
87 return u.x != v.x || u.y != v.y || u.z != v.z;
97 double total_volume{ GEO::Geom::tetra_signed_volume( p0, p1, p2, p3 ) };
98 if( std::fabs( total_volume ) < global_epsilon_3 )
100 std::array< double, 4 > lambdas{ { 0., 0., 0., 0. } };
101 return std::make_tuple(
false, lambdas );
103 double volume0{ GEO::Geom::tetra_signed_volume( p1, p3, p2, p ) };
104 double volume1{ GEO::Geom::tetra_signed_volume( p0, p2, p3, p ) };
105 double volume2{ GEO::Geom::tetra_signed_volume( p0, p3, p1, p ) };
106 double volume3{ GEO::Geom::tetra_signed_volume( p0, p1, p2, p ) };
108 double lambda0{ volume0 / total_volume };
109 double lambda1{ volume1 / total_volume };
110 double lambda2{ volume2 / total_volume };
111 double lambda3{ volume3 / total_volume };
112 std::array< double, 4 > lambdas{ { lambda0, lambda1, lambda2,
114 return std::make_tuple(
true, lambdas );
117 std::tuple< bool, std::array< double, 3 > >
121 double total_area{ GEO::Geom::triangle_area( p0, p1, p2 ) };
122 if( std::fabs( total_area ) < global_epsilon_sq )
124 std::array< double, 3 > lambdas{ { 0., 0., 0. } };
125 return std::make_tuple(
false, lambdas );
127 vec3 triangle_normal{ cross( p2 - p0, p1 - p0 ) };
132 double lambda0{ area0 / total_area };
133 double lambda1{ area1 / total_area };
134 double lambda2{ area2 / total_area };
135 std::array< double, 3 > lambdas{ { lambda0, lambda1, lambda2 } };
136 return std::make_tuple(
true, lambdas );
139 std::tuple< bool, std::array< double, 3 > >
144 if( std::fabs( total_area ) < global_epsilon_sq )
146 std::array< double, 3 > lambdas{ { 0., 0., 0. } };
147 return std::make_tuple(
false, lambdas );
153 double lambda0{ area0 / total_area };
154 double lambda1{ area1 / total_area };
155 double lambda2{ area2 / total_area };
156 std::array< double, 3 > lambdas{ { lambda0, lambda1, lambda2 } };
157 return std::make_tuple(
true, lambdas );
160 template < index_t DIMENSION >
169 double extent{ 0.5 * edge.length() };
170 edge = normalize( edge );
171 double d{ dot( edge, diff ) };
173 if( std::fabs( d ) <= extent )
176 return std::make_tuple(
true, new_p );
179 return std::make_tuple(
false, empty_point );
185 bool is_point_segment_projection_possible;
187 std::tie( is_point_segment_projection_possible, nearest_p ) =
189 if( is_point_segment_projection_possible )
191 return std::make_tuple( length( nearest_p - p ), nearest_p );
193 double p0_distance_sq{ length2( p0 - p ) };
194 double p1_distance_sq{ length2( p1 - p ) };
195 if( p0_distance_sq < p1_distance_sq )
197 return std::make_tuple( std::sqrt( p0_distance_sq ), p0 );
199 return std::make_tuple( std::sqrt( p1_distance_sq ), p1 );
203 const vec3& origin,
const vec3& axis,
double theta,
bool degrees )
210 theta = theta * M_PI / 180.;
213 double axis_length{ axis.length() };
215 double x1{ origin[0] };
216 double y1{ origin[1] };
217 double z1{ origin[2] };
218 double a{ axis[0] / axis_length };
219 double b{ axis[1] / axis_length };
220 double c{ axis[2] / axis_length };
221 double d{ std::sqrt( b * b + c * c ) };
222 double cos_angle{ std::cos( theta ) };
223 double sin_angle{ std::sin( theta ) };
225 GEO::Matrix< 4, double > T;
243 GEO::Matrix< 4, double > inv_T;
261 #ifdef RINGMESH_DEBUG 262 GEO::Matrix< 4, double > computed_inv_T = T.inverse();
282 GEO::Matrix< 4, double > Rx;
310 GEO::Matrix< 4, double > inv_Rx;
332 inv_Rx( 1, 1 ) = c / d;
333 inv_Rx( 1, 2 ) = b / d;
334 inv_Rx( 2, 1 ) = -b / d;
335 inv_Rx( 2, 2 ) = c / d;
338 #ifdef RINGMESH_DEBUG 339 GEO::Matrix< 4, double > computed_inv_Rx = Rx.inverse();
358 GEO::Matrix< 4, double > Ry;
376 GEO::Matrix< 4, double > inv_Ry;
394 #ifdef RINGMESH_DEBUG 395 GEO::Matrix< 4, double > computed_inv_Ry = Ry.inverse();
414 GEO::Matrix< 4, double > Rz;
415 Rz( 0, 0 ) = cos_angle;
416 Rz( 0, 1 ) = -sin_angle;
419 Rz( 1, 0 ) = sin_angle;
420 Rz( 1, 1 ) = cos_angle;
432 return inv_T * inv_Rx * inv_Ry * Rz * Ry * Rx * T;
435 template std::tuple< bool, vecn< 2 > >
439 template std::tuple< bool, vecn< 3 > >
std::tuple< bool, vecn< DIMENSION > > point_segment_projection(const vecn< DIMENSION > &p, const vecn< DIMENSION > &p0, const vecn< DIMENSION > &p1)
std::tuple< double, vec3 > point_segment_distance(const vec3 &p, const vec3 &p0, const vec3 &p1)
GEO::vecng< DIMENSION, double > vecn
double RINGMESH_API triangle_signed_area(const vec3 &p0, const vec3 &p1, const vec3 &p2, const vec3 &triangle_normal)
double RINGMESH_API dot_perp(const vec2 &v0, const vec2 &v1)
std::tuple< bool, std::array< double, 4 > > RINGMESH_API tetra_barycentric_coordinates(const vec3 &p, const vec3 &p0, const vec3 &p1, const vec3 &p2, const vec3 &p3)
bool operator==(const vecn< DIMENSION > &u, const vecn< DIMENSION > &v)
bool operator!=(const vecn< DIMENSION > &u, const vecn< DIMENSION > &v)
std::tuple< bool, std::array< double, 3 > > RINGMESH_API triangle_barycentric_coordinates(const vec3 &p, const vec3 &p0, const vec3 &p1, const vec3 &p2)
GEO::Matrix< 4, double > RINGMESH_API rotation_matrix_about_arbitrary_axis(const vec3 &origin, const vec3 &axis, double theta, bool degrees)
Builds a rotational matrix about an arbitrary axis.
#define ringmesh_assert(x)
Classes to build GeoModel from various inputs.