AGX Dynamics 2.41.2.0
Loading...
Searching...
No Matches
WireUtils.h
Go to the documentation of this file.
1/*
2Copyright 2007-2025. Algoryx Simulation AB.
3
4All AGX source code, intellectual property, documentation, sample code,
5tutorials, scene files and technical white papers, are copyrighted, proprietary
6and confidential material of Algoryx Simulation AB. You may not download, read,
7store, distribute, publish, copy or otherwise disseminate, use or expose this
8material unless having a written signed agreement with Algoryx Simulation AB, or having been
9advised so by Algoryx Simulation AB for a time limited evaluation, or having purchased a
10valid commercial license from Algoryx Simulation AB.
11
12Algoryx Simulation AB disclaims all responsibilities for loss or damage caused
13from using this software, unless otherwise stated in written agreements with
14Algoryx Simulation AB.
15*/
16
17#pragma once
18
20#include <agx/Math.h>
21#include <agxCollide/Mesh.h>
22#include <agxCollide/Contacts.h>
26
27namespace agxWire
28{
29 class WireDistanceCompositeConstraint;
30
31#define shape_to_world_transform( geom ) \
32 ((*geom->getShapes().begin())->getLocalTransform() * geom->getTransform())
33
34#define world_to_shape_transform( geom ) \
35 (shape_to_world_transform( geom ).inverse())
36
37 // Temporary: I don't like this.
38
46 {
47 agxAssert( g && g->getShapes().size() == 1 && v.isValid() );
48 return g ? world_to_shape_transform( g ).transform3x3( v ) : v;
49 }
50
58 {
59 agxAssert( g && g->getShapes().size() == 1 && v.isValid() );
60 return g ? shape_to_world_transform( g ).transform3x3( v ) : v;
61 }
62
70 {
71 agxAssert( g && g->getShapes().size() == 1 && p.isValid() );
72 return g? (p * world_to_shape_transform( g )) : p;
73 }
74
82 {
83 agxAssert( g && g->getShapes().size() == 1 && p.isValid() );
84 return g ? (p * shape_to_world_transform( g )) : p;
85 }
86
87#undef shape_to_world_transform
88#undef world_to_shape_transform
89
91
92 static inline bool overlappingRange( agx::Real range1Start,agx::Real range1End,agx::Real range2Start,agx::Real range2End )
93 {
94 return ( agx::leq(range1Start, range2End ) && agx::geq(range1End, range2Start ) );
95 }
96
98
99
100
106 template < typename IteratorCompatibleContainer >
107 typename IteratorCompatibleContainer::const_iterator findBeginIterator( const IteratorCompatibleContainer& container, int nodeMask )
108 {
109 if ( container.empty() )
110 return container.end();
111
112 typename IteratorCompatibleContainer::const_iterator i = container.begin();
113 while ( i != container.end() && ((*i)->getType() & nodeMask) == 0 )
114 ++i;
115 return i;
116 }
117
124 template < typename IteratorCompatibleContainer >
125 typename IteratorCompatibleContainer::const_iterator findEndIterator( const IteratorCompatibleContainer& container, int nodeMask )
126 {
127 // Empty, begin == end.
128 if ( container.empty() )
129 return container.end();
130
131 typename IteratorCompatibleContainer::const_iterator i = container.end();
132 --i;
133 while ( i != container.begin() && ((*i)->getType() & nodeMask) == 0 )
134 --i;
135 return i;
136 }
137
149 template < typename IteratorCompatibleContainer >
150 agx::Real findDistanceFromStartGivenPoint( agx::Real pulledInBegin, const IteratorCompatibleContainer& container, const agx::Vec3& point, typename IteratorCompatibleContainer::const_iterator beginIt, typename IteratorCompatibleContainer::const_iterator endIt, agx::Real& shortestDistanceSquared )
151 {
152 agx::Real bestDistance = 0;
153 agx::Real currentDistance = 0;
154 shortestDistanceSquared = agx::Infinity;
155
156 // Container is empty, undefined.
157 if ( container.empty() || beginIt == endIt )
158 return 0;
159
160 typename IteratorCompatibleContainer::const_iterator i = beginIt;
161 agxAssert( i != container.end() );
162 typename IteratorCompatibleContainer::const_iterator end = endIt;
163 agxAssert( end != container.begin() );
164
165 agx::Vec3 startPoint = (*i)->getFrame()->getWorldPosition();
166 agx::Vec3 endPoint, direction;
167 ++i;
168 for ( ; i != end; ++i ) {
169 endPoint = (*i)->getFrame()->getWorldPosition();
170
171 direction = endPoint - startPoint;
172 agx::Real t;
173 if (agx::equalsZero(direction.length2()))
174 t = 0;
175 else {
176 t = (( point - startPoint ) * direction) / direction.length2();
177 t = agx::clamp( t, agx::Real( 0 ), agx::Real( 1 ) );
178 }
179
180 startPoint += direction * t;
181 agx::Real d2 = ( startPoint - point ).length2();
182 agx::Real dl = direction.length();
183
184 if ( d2 < shortestDistanceSquared ) {
185 shortestDistanceSquared = d2;
186 bestDistance = currentDistance + t * dl;
187 }
188 currentDistance += dl;
189 startPoint = endPoint;
190 }
191
192 return bestDistance + pulledInBegin;
193 }
194
203 template < typename IteratorCompatibleContainer >
204 agx::Real findDistanceFromStartGivenPoint( agx::Real pulledInBegin, const IteratorCompatibleContainer& container, const agx::Vec3& point )
205 {
206 agx::Real dummySquaredDistance = 0;
207 return findDistanceFromStartGivenPoint( pulledInBegin, container, point, container.begin(), container.end(),dummySquaredDistance );
208 }
209
219 template < typename IteratorCompatibleContainer >
220 agx::Vec3 findPointOnWire( const IteratorCompatibleContainer& container, const agx::Vec3& point, typename IteratorCompatibleContainer::const_iterator beginIt, typename IteratorCompatibleContainer::const_iterator endIt, agx::Real& shortestDistanceSquared )
221 {
222 if ( container.empty() )
223 return agx::Vec3();
224
225 // Find the distance along the wire.
226 agx::Real distanceAlongWire = findDistanceFromStartGivenPoint( 0, container, point, beginIt, endIt, shortestDistanceSquared );
227
228 // If the distance is equal to the pulled in length the first point is the correct one.
229 if ( agx::equalsZero( distanceAlongWire ) ) {
230 return beginIt->get()->getFrame()->getWorldPosition();
231 }
232
233 typename IteratorCompatibleContainer::const_iterator i = beginIt;
234 typename IteratorCompatibleContainer::const_iterator end = endIt;
235 agxAssert( i != container.end() && end != container.begin() );
236
237 agx::Vec3 currPos = (*i)->getFrame()->getWorldPosition();
238 ++i;
239 agx::Real currDistanceAlongWire = 0;
240 for ( ; i != end; ++i ) {
241 agx::Vec3 nextPos = (*i)->getFrame()->getWorldPosition();
242 agx::Vec3 dir = nextPos - currPos;
243 agx::Real length = dir.normalize();
244 // If we're about pass distanceAlongWire, calculate the difference and the point wanted:
245 // point_wanted = current_position_on_line + dir_to_next_node * ( distance_from_start_to_previous_node + distance_to_next_node - total_distance_to_wanted_point )
246 if ( currDistanceAlongWire + length > distanceAlongWire || agx::equivalent( currDistanceAlongWire + length, distanceAlongWire, agx::RealEpsilon ) ) {
247 agx::Real d = distanceAlongWire - currDistanceAlongWire;
248 return currPos + dir * d;
249 }
250 currDistanceAlongWire += length;
251 currPos = nextPos;
252 }
253 // Last position is the one wanted.
254 return currPos;
255 }
256
257 template < typename IteratorCompatibleContainer >
258 agx::Vec3 findPointOnWire( const IteratorCompatibleContainer& container, const agx::Vec3& point, typename IteratorCompatibleContainer::const_iterator beginIt, typename IteratorCompatibleContainer::const_iterator endIt, const agx::Vec3 n, agx::Real& shortestDistanceSquared )
259 {
260 shortestDistanceSquared = agx::RealMax;
261 agx::Vec3 currentBest;
262
263 agx::Vec3 normal;
264 agx::Vec4 plane;
265
266 // pp = p in plane
267 // w1 & w2, two line node points in world coords
268 // p1 & p2, same two line node points, but projected onto plane
269 // pd = plane direction (p2-p1)
270 agx::Vec3 pp, p1,p2, w1,w2, pd;
271
272 agx::Real t, dist;
273
274 normal = n;
275 normal.normalize();
276
277 plane = agx::Vec4( normal, 0 );
278
279#define planeProject( pnt ) pnt - ( normal * ( plane * pnt ) )
280
281 pp = planeProject(point);
282
283 if ( container.empty() ) return agx::Vec3();
284 // Collect the first node position from the first segments' node list
285 w1 = (*(++container.begin()))->getFrame()->getWorldPosition(); //c->m_nodes.front()->getNodeFrame().getWorldPosition();
286 p1 = planeProject( w1 );
287
288 typename IteratorCompatibleContainer::const_iterator nodeIter = beginIt;
289 typename IteratorCompatibleContainer::const_iterator end = endIt;
290
291 for ( ; nodeIter != end; ++nodeIter ) {
292 const Node* currentNode = static_cast< const Node* >( (*nodeIter).get() );
293 w2 = currentNode->getFrame()->getWorldPosition();
294
295 p2 = planeProject( w2 );
296
297 pd = p2 - p1;
298
299 t = (( pp - p1 ) * pd ) / pd.length2();
300 t = agx::clamp( t, agx::Real(0.0), agx::Real(1.0) );
301
302 // calculate closest point on this part of the line composite ... and distance to point
303 p1 += pd * t;
304
305 dist = (p1-pp).length2();
306
307 if ( dist < shortestDistanceSquared )
308 {
309 shortestDistanceSquared = dist;
310 currentBest = w1 + (w2-w1) * t;
311 }
312
313 p1 = p2;
314 w1 = w2;
315 }
316
317
318
319#undef planeProject
320
321 return currentBest;
322 }
323
330 template < typename IteratorCompatibleContainer >
331 agx::Vec3 findPointOnWire( const IteratorCompatibleContainer& container, const agx::Vec3& point )
332 {
333 agx::Real dummySquaredDistance = 0;
334 return findPointOnWire( container, point, container.begin(), container.end(), dummySquaredDistance );
335 }
336
344 template < typename IteratorCompatibleContainer >
345 agx::Vec3 findPointOnWire( const IteratorCompatibleContainer& container, const agx::Vec3& point, const agx::Vec3 n )
346 {
347 agx::Real dummySquaredDistance = 0;
348 return findPointOnWire( container, point, container.begin(), container.end(), n , dummySquaredDistance );
349 }
350
358 template < typename It >
359 It getNodeIterator( agx::Real distanceFromStart, It begin, It end, It containerEnd )
360 {
361 if ( begin == end || begin == containerEnd )
362 return containerEnd;
363
364 if ( agx::leq( distanceFromStart, agx::Real( 0 ) ) )
365 return begin;
366
367 It next = begin;
368 It curr = next++;
369 if ( next == containerEnd || next == end )
370 return curr;
371
372 agx::Real length = 0;
373 while ( next != containerEnd && next != end ) {
374 length += ( (*next)->getFrame()->getWorldPosition() - (*curr)->getFrame()->getWorldPosition() ).length();
375 if ( length > distanceFromStart )
376 return curr;
377
378 curr = next;
379 ++next;
380 }
381
382 return end;
383 }
384
391 template < typename IteratorCompatibleContainer >
392 const Node* getNode( const IteratorCompatibleContainer& container, agx::Real distanceFromStart )
393 {
394 if ( container.empty() )
395 return nullptr;
396
397 typename IteratorCompatibleContainer::const_iterator i = getNodeIterator( distanceFromStart, container.begin(), container.end(), container.end() );
398 if ( i != container.end() )
399 return *i;
400 return nullptr;
401 }
402
409 template < typename IteratorCompatibleContainer >
410 Node* getNode( IteratorCompatibleContainer& container, agx::Real distanceFromStart )
411 {
412 if ( container.empty() )
413 return nullptr;
414
415 typename IteratorCompatibleContainer::iterator i = getNodeIterator( distanceFromStart, container.begin(), container.end(), container.end() );
416 if ( i != container.end() )
417 return *i;
418 return nullptr;
419 }
420
422
423 //return -1 if non was passed. otherwise 0,1 or 2 (index if edge passed first)
424 int AGXPHYSICS_EXPORT validateEdgePassings( const agxCollide::Geometry* meshGeometry,const agxCollide::Mesh* mesh,const size_t triangleIndex, const agx::RigidBody* rb, const agx::Vec3 lineGeometryBegin, const agx::Vec3 lineGeometryEnd, const agx::Vec3 lineGeometryBeginLastNTimeSteps, const agx::Vec3 lineGeometryEndLastNTimeSteps, agx::Vec3 /*contactPointW*/,agx::Real timeStep,agx::Real wireRadius,const agx::Real numTimeStepsBackToEvaluateFrom = 2);
425
426 int closestEdgeToContact(const agxCollide::Mesh* mesh,const size_t triangleIndex,const agx::Vec3 pointInTriangle);
427
428
429 template <typename T>
430 static inline bool findMeshTriangleAndEdge( const agx::Vec3 lineGeometryBegin, const agx::Vec3 lineGeometryEnd,
431 const agx::Vec3 lineGeometryBeginLastNTimeSteps, const agx::Vec3 lineGeometryEndLastNTimeSteps ,
432 size_t& triangleIndex,size_t& edgeIndex, T* /* geometryContact */,
433 const typename T::PointType& contactPoint, const agxCollide::Mesh* meshShape,
434 agxCollide::Geometry* geometryMesh, const agx::Real timeStep,
435 const agx::Real wireRadius,const agx::Real numTimeStepsBackToEvaluateFrom = 2 )
436 {
437 agx::UInt32 faceIndex;
438 agx::UInt8 faceFeature;
439 if (meshShape->getEntity() == contactPoint.shape1()) {
440 faceIndex = contactPoint.faceIndex1();
441 faceFeature = contactPoint.faceFeature1();
442 }
443 else {
444 agxAssert(meshShape->getEntity() == contactPoint.shape2());
445 faceIndex = contactPoint.faceIndex2();
446 faceFeature = contactPoint.faceFeature2();
447 }
448
449
450 triangleIndex = faceIndex;
452
453 if ( triangleIndex == meshShape->getNumTriangles() )
454 return false;
455
456 if ( edgeIndexTVR == agxCollide::TriangleVoronoiRegion::EDGE )
457 edgeIndex = faceFeature - 3;
458 else if ( edgeIndexTVR == agxCollide::TriangleVoronoiRegion::FACE )
459 {
460 int closestEdgeIndex = validateEdgePassings(geometryMesh,meshShape,triangleIndex,geometryMesh->getRigidBody(),lineGeometryBegin,lineGeometryEnd,lineGeometryBeginLastNTimeSteps,lineGeometryEndLastNTimeSteps,contactPoint.point(),timeStep,wireRadius,numTimeStepsBackToEvaluateFrom );
461
462 if ( closestEdgeIndex < 0 )
463 {
464 // Find if the wire segment points are on different sides of the face.
465 // If they are NOT, we cant accept that the face contact to create an edge contact.
466 agx::Vec3 triangleNormalWorld = transformVectorToWorld( meshShape->getTriangle(triangleIndex).getNormal(), geometryMesh );
467 agx::Vec3 pointInTriangle = contactPoint.point() + agx::Vec3( contactPoint.normal() ) * contactPoint.depth() * agx::Real(0.5);
468 agx::Vec3 toLineBegin = lineGeometryBegin - pointInTriangle;
469 agx::Vec3 toLineEnd = lineGeometryEnd - pointInTriangle;
470
471 //Both segment points are on the same side of the plane
472 agx::Real distToPlaneFromBegin = (toLineBegin * triangleNormalWorld );
473 agx::Real distToPlaneFromEnd = (toLineEnd * triangleNormalWorld );
474 if ( distToPlaneFromBegin * distToPlaneFromEnd > 0 )
475 return false;
476
477 // The two points seem to be on the same side
478 // Find which edge that is closest
479 agx::Vec3 pointInTriangleLocal = transformPointToShape( pointInTriangle, geometryMesh );
480 if ( !agx::equivalent( meshShape->getTriangle(triangleIndex).getNormal() * (pointInTriangleLocal - meshShape->getTriangle(triangleIndex).getVertex(0)),agx::Real(0) ) )
481 {// point followed the wrong direction of the normal
482 pointInTriangle = contactPoint.point() - agx::Vec3( contactPoint.normal() ) * contactPoint.depth() * agx::Real(0.5);
483 pointInTriangleLocal = transformPointToShape( pointInTriangle, geometryMesh );
484 }
485 closestEdgeIndex = closestEdgeToContact( meshShape, triangleIndex, pointInTriangleLocal );
486
487 // Now find if the path through the closest point of the edge is
488 // increasing the wire length more than the distance to the plane
489 // for any of the two wire segment points.
490 // if the distance HAS increased more, then we assume that
491 // the wire segment is more or less resting on the surface.
492 // If the distance has increased less than the min distance to the plane,
493 // we assume that the contact is valid, since then it is not near resting on the plane.
494 // Distance from line nodes to edge must also be greater than the wire radius for the face contact to be interesting.
495 agx::Vec3 edgeStart = transformPointToWorld(meshShape->getTriangle(triangleIndex).getVertex((uint_fast8_t)closestEdgeIndex),geometryMesh);
496 agx::Vec3 edgeEnd = transformPointToWorld(meshShape->getTriangle(triangleIndex).getVertex( uint_fast8_t(closestEdgeIndex+1)%3),geometryMesh);
497 agxCollide::ClosestPointsSolution solution;
498 agxCollide::ClosestPointsSolution parallelSolution;
499 bool isParallel = false;
501 closestPointsSegmentSegment(edgeStart, edgeEnd, lineGeometryBegin, lineGeometryEnd, solution, isParallel, parallelSolution, epsilon );
502 agx::Real spDistanceBegin = solution.pointOn1.distance(lineGeometryBegin);
503 agx::Real spDistanceEnd = solution.pointOn1.distance(lineGeometryEnd);
504 // Find if the distance to the edge close point is less than radius
505 if ( spDistanceBegin < wireRadius || spDistanceEnd < wireRadius )
506 closestEdgeIndex = -1;
507 else
508 {
509 agx::Real distanceDiff = spDistanceBegin + spDistanceEnd - lineGeometryEnd.distance(lineGeometryBegin);
510
511 if ( std::min( std::abs(distToPlaneFromBegin), std::abs(distToPlaneFromEnd) ) < distanceDiff )
512 closestEdgeIndex = -1;
513 }
514
515 }
516
517 if ( closestEdgeIndex < 0 )
518 return false;
519
520 edgeIndex = (size_t)closestEdgeIndex;
521
522 }
523 else
524 return false;
525
526 if ( meshShape->getTriangle( triangleIndex ).isValid() && meshShape->getTriangle(triangleIndex).hasHalfEdgePartner((uint8_t)edgeIndex) )
527 {
528 agx::Vec3 n1 = meshShape->getTriangle(triangleIndex ).getNormal();
529 agx::Vec3 n2 = meshShape->getTriangle(triangleIndex).getHalfEdgePartner((uint8_t)edgeIndex).getNormal();
530
531 if ( agx::geq(n1*n2,agx::Real(1) ) )
532 return false;
533 }
534 else
535 return false;
536
537 return true;
538 }
539
540 //Adjust edge given line radius
541 static inline void calculateContactPoint( const agxCollide::Mesh* mesh, size_t triangleIndex, size_t edgeIndex, const agx::Vec3& localContactPoint, agx::Vec3& retLocalCorrectedContactPoint, agx::Vec3& retEdge, agx::Vec3& retEdgeStart, agx::Vec3& retEdgeEnd, const agx::Real /*radius*/ )
542 {
543 const agxCollide::Mesh::Triangle& triangle = mesh->getTriangle( triangleIndex );
544
545 agx::Vec3 edgeStart = triangle.getEdgeStartVertex( ( uint8_t ) edgeIndex );
546 agx::Vec3 edgeEnd = triangle.getEdgeEndVertex( ( uint8_t ) edgeIndex );
547
548 retEdge = edgeEnd - edgeStart;
549 agx::Real edgeL = retEdge.normalize();
550
551 agx::Vec3 pRelStart = localContactPoint - edgeStart;
552 pRelStart = retEdge*( pRelStart*retEdge );
553 retLocalCorrectedContactPoint = edgeStart + pRelStart;
554
555 retEdgeStart = edgeEnd - retEdge*( edgeL /*+ radius*/ );
556 retEdgeEnd = edgeStart + retEdge*( edgeL /*+ radius*/ );
557 }
558
559
560 AGXPHYSICS_EXPORT agx::Real calculateNormalForceMagnitude( const agxWire::WireDistanceCompositeConstraint* wireConstraint, agxWire::NodeConstIterator nIt );
561
562 AGXPHYSICS_EXPORT agx::Vec3 getMovementRangeDirection( agx::Vec3 contactNormal, agx::Vec3 wireDir );
563
564 AGXPHYSICS_EXPORT agx::Vec3 getContactNormal( agx::Vec3 wireDir, agx::Vec3 movementRangeDir );
565
567
568 AGXPHYSICS_EXPORT agx::Real getAngleAroundMovementRange( const agx::Vec3& p1, const agx::Vec3& p2, const agx::Vec3& p3, const agx::Vec3& contactNormal, const agx::Vec3& movementDir );
569
570 AGXPHYSICS_EXPORT agx::Real getAngleAroundMovementRange( agxWire::NodeConstIterator nIt );
571
573
574}
#define world_to_shape_transform(geom)
Definition: WireUtils.h:34
#define planeProject(pnt)
#define shape_to_world_transform(geom)
Definition: WireUtils.h:31
#define AGXPHYSICS_EXPORT
The geometry representation used by the collision detection engine.
Definition: Geometry.h:92
const ShapeRefVector & getShapes() const
Class for more intuitive access to the Mesh's mesh data.
Definition: Mesh.h:79
agx::Vec3 getEdgeEndVertex(uint_fast8_t localEdgeIndex) const
Definition: Mesh.h:678
agx::Vec3 getEdgeStartVertex(uint_fast8_t localEdgeIndex) const
Definition: Mesh.h:672
Mesh is a common base class for triangle meshes, such as Mesh or HeightField.
Definition: Mesh.h:70
const Triangle getTriangle(size_t triangleIndex) const
Definition: Mesh.h:731
static Type calculateType(unsigned index)
const agx::Vec3 & getWorldPosition() const
Class defining a node that is part of a wire.
Definition: agxWire/Node.h:512
NodeFrame * getFrame()
size_t size() const
Definition: Container.h:134
Real normalize()
Normalize the vector so that it has length unity.
Definition: Vec3Template.h:701
Real length() const
Length of the vector = sqrt( vec .
Definition: Vec3Template.h:683
bool isValid() const
Definition: Vec3Template.h:529
Real length2() const
Length squared of the vector = vec .
Definition: Vec3Template.h:689
A class holding 4 dimensional vectors and providing basic arithmetic.
Definition: Vec4Template.h:35
#define agxAssert(expr)
Definition: debug.h:143
#define DOXYGEN_END_INTERNAL_BLOCK()
Definition: macros.h:89
#define DOXYGEN_START_INTERNAL_BLOCK()
Definition: macros.h:88
This namespace consists of a set of classes for handling geometric intersection tests including boole...
Implements a Wire model with adaptive resolution.
Definition: MergedBody.h:40
NodeContainer::const_iterator NodeConstIterator
Definition: agxWire/Node.h:57
static agx::Vec3 transformPointToWorld(const agx::Vec3 &p, const agxCollide::Geometry *g)
Transforms a point given in shape coordinates to world given geometry g.
Definition: WireUtils.h:81
IteratorCompatibleContainer::const_iterator findBeginIterator(const IteratorCompatibleContainer &container, int nodeMask)
Primitive function to find begin iterator for utility functions below.
Definition: WireUtils.h:107
static agx::Vec3 transformVectorToWorld(const agx::Vec3 &v, const agxCollide::Geometry *g)
Transforms a vector given in shape coordinates to world coordinates given geometry g.
Definition: WireUtils.h:57
const Node * getNode(const IteratorCompatibleContainer &container, agx::Real distanceFromStart)
Finds the wire node given current distance from the start of the wire (wire defined to be iterator co...
Definition: WireUtils.h:392
agx::Real findDistanceFromStartGivenPoint(agx::Real pulledInBegin, const IteratorCompatibleContainer &container, const agx::Vec3 &point, typename IteratorCompatibleContainer::const_iterator beginIt, typename IteratorCompatibleContainer::const_iterator endIt, agx::Real &shortestDistanceSquared)
Search vector/list container defining a wire for the 3D point -> 1D wire projection.
Definition: WireUtils.h:150
static agx::Vec3 transformPointToShape(const agx::Vec3 &p, const agxCollide::Geometry *g)
Transforms a point given in world coordinates to shape coordinates of geometry g.
Definition: WireUtils.h:69
static agx::Vec3 transformVectorToShape(const agx::Vec3 &v, const agxCollide::Geometry *g)
Transforms a vector given in world coordinates to shape coordinates of geometry g.
Definition: WireUtils.h:45
It getNodeIterator(agx::Real distanceFromStart, It begin, It end, It containerEnd)
This function is used by getNode, but can be used of some nodes in the beginning or end of the wire s...
Definition: WireUtils.h:359
agx::Vec3 findPointOnWire(const IteratorCompatibleContainer &container, const agx::Vec3 &point, typename IteratorCompatibleContainer::const_iterator beginIt, typename IteratorCompatibleContainer::const_iterator endIt, agx::Real &shortestDistanceSquared)
Projects any 3D point onto wire.
Definition: WireUtils.h:220
IteratorCompatibleContainer::const_iterator findEndIterator(const IteratorCompatibleContainer &container, int nodeMask)
Primitive function to find end iterator for utility functions below.
Definition: WireUtils.h:125
The agx namespace contains the dynamics/math part of the AGX Dynamics API.
uint32_t UInt32
Definition: Integer.h:32
Vec3T< Real > Vec3
The object holding 3 dimensional vectors and providing basic arithmetic.
Definition: agx/Vec3.h:36
AGXCORE_EXPORT const Real RealMax
bool geq(double a, double b, double eps=(double) AGX_EQUIVALENT_EPSILON)
Definition: Math.h:381
T1 clamp(T1 v, T2 minimum, T3 maximum)
Definition: Math.h:318
AGXCORE_EXPORT const Real RealEpsilon
AGXPHYSICS_EXPORT agx::Bool equalsZero(const agx::AddedMassInteraction::Matrix6x6 &matrix, agx::Real eps=agx::RealEpsilon)
double Real
Definition: Real.h:42
uint8_t UInt8
Definition: Integer.h:30
Vec4T< Real > Vec4
Definition: Vec4.h:25
bool leq(double a, double b, double eps=(double) AGX_EQUIVALENT_EPSILON)
Definition: Math.h:369
const Real Infinity
Definition: Math.h:72
static constexpr Real AGX_EQUIVALENT_EPSILON
Definition: Math.h:57
AGXPHYSICS_EXPORT agx::Bool equivalent(const agx::AddedMassInteraction::Matrix6x6 &lhs, const agx::AddedMassInteraction::Matrix6x6 &rhs, agx::Real eps=agx::RealEpsilon)