Eyeshot provides two different collision detection classes:
- CollisionDetection2D for the 2D version in which all the input entities have to lay on Plane.XY (it supports BlockReference, Region, and ICurve);
- CollisionDetection for the 3D version with input entities in any position and orientation of the 3D space (it supports BlockReference and all entities implementing IFace).
Both classes can be setup with some properties and constructor parameters.
Parameters
CheckMethod (default collisionCheckType.OB)
The accuracy of the check performed. It can be set with the following types:
- collisionCheckType.OB is the fastest but also the most approximate check, because it checks just the entities oriented bounding (OrientedBoundingBox for 3D, OrientedBoundingRect for 2D);
Difference between AABB and OB/OBB
- collisionCheckType.SubdivisionTree is the best choice for Mesh/Solid (defined by triangles) since it creates a subdivision tree (Octree for 3D, QuadTree for 2D) of the triangles of each entity (of type IFace). It uses the tessellation data of each entity and exploits the spatial tree subdivision to perform an optimized triangle-triangle accurate check. For curved entities (e.g. Brep, Surface, ICurve) the accuracy of the check depends on the refinement tolerance used to regenerate those entities. Also, the performance depends on the number of triangles involved during the build and check of the tree;
QuadTree of Bunny shape
- collisionCheckType.OBBWithSubdivisionTree combines the OB check (as the first check used among BlockReferences) with the subdivision tree check (at the end between two leaves IFace entities). It's more useful than collisionCheckType.SubdivisionTreewith deep assembly;
- collisionCheckType.Accurate is the heaviest but most accurate check for curved entities (e.g. Brep, Surface, ICurve) performing geometrical checks. It uses OB as a threshold check;
Warning
Avoid using Accurate type with Mesh/Solid entities or a miscellaneous list containing also Mesh/Solid entities. Use SubdivisionTree or OBBSubdivisionTree instead.
Difference between SubdivisionTree (affected by refinement tolerance) and Accurate (using geometrical data)
FirstOnly (default true)
With this flag, you can choose to stop collision detection at the first tuple of intersecting entities or find all the intersecting entities.
CoincidenceAsCollision (default true)
With this flag, you can choose to change the default behavior and discard as collisions the touching but not intersecting entities (like coplanar surfaces). Setting this to false requires CollisionDetection to perform additional computations to find the "touching" collisions.
nodeMaxItemCount (default = total number of items/100)
It defines the maximum number of elements (triangles for 3D/ segments+triangles for 2D) admitted into a leaf voxel of each entity subdivision tree. The fewer triangles there are for each voxel, the quicker the collision check between two voxels. At the same time, the fewer triangles, the bigger the complexity of the tree and the total amount of voxels to check. The choice is a trade-off depending on the context and the tessellation type of the objects (an isotropic mesh will have a better-balanced tree and so better performance).
maxEdgeLength (default = disabled) Fem edition only
The maximum length that a tessellated triangle edge could have. It is used during the SubdivisionTree check method for curved entities like Brep and Surface in order to build an isotropic tesselation that will result in a more balanced octree.
If the parameter is not specified, the already preexisting tessellation will be used during the build of the octree, otherwise, a new regeneration will be forced to create an isotropic tessellation with the parameter as maxLength data. This regen will slow down the first pre-computation call (see below). The choice is a trade-off depending on the size of the objects to check and the desired accuracy (an isotropic mesh will have a better-balanced tree and hence better performance).
Entities to check
You can choose between all-vs-all collision check (by specifying a unique entity list), to check the reciprocal collisions among all the entities, or a first-vs-second check (by specifying two different entity lists), in order to avoid a collision check among entities belonging to the same list (e.g. you won't need to check if the components of a robot arm intersect to their-selves).
Remarks: Input entities should already be regenerated before starting collision detection.
Result
With CollisionResult[] type, each CollisionResult contains all the collision data found between two intersecting entities.
public struct CollisionResult
{
public Tuple<CollisionData, CollisionData> CollidedEntities;
public Entity[] CollisionItems;
}
Each CollisionData type defines the following properties:
- Transformation β the accumulated parent transformations from the input root to the leaf intersecting entity (for the entities already at root level it will be null);
- ParentName β a string containing the Block name of the first parent of the leaf entity (it will be null if the entity is at root level);
- Parents β the stack of BlockReferences from the root given in input to CollisionDetection to the leaf hit entity (it will be null if the entity is at root level);
- Entity β the reference to the leaf entity found intersecting with the entity saved into its adjacent CollisionItem;
CollisionItems will be filled with:
- points and/or intersection curves found during the DoWork() computation if it required to check collision;
- volumes/surfaces found as collision volumes after the ComputeIntersectionVolume() method call.
In detail, it will contain:
CollisionDetection2D
collisionCheckType.SubdivisionTree/OBBWithSubdivisionTree |
||
|
Region |
ICurve |
Region |
Collision Area (Region) |
Intersection Points among tessellated segments (Point) |
ICurve |
Intersection Points among tessellated segments (Point) |
Intersection Points among tessellated segments (Point) |
collisionCheckType.Accurate |
||
|
Region |
ICurve |
Region |
Collision Area (Region) |
Intersection Points among geometrical curve (Point) |
ICurve |
Intersection Points among geometrical curve (Point) |
Intersection Points among geometrical curve (Point) |
CollisionDetection (3D)
collisionCheckType.SubdivisionTree/OBBWithSubdivisionTree |
|
|
Entity (all internally converted to Mesh during Octree computation) |
Entity |
CollisionVolumes (Solid) |
collisionCheckType.Accurate |
|||||
|
Mesh (+ Bar, Joint, Triangle, Quad) |
Solid |
Brep |
Surface |
Region |
Mesh (+ Bar, Joint, Triangle, Quad) |
see <Solid,Solid> |
see <Solid,Solid> |
see <Solid,Solid> |
see <Solid,Solid> |
see <Solid,Solid> |
Solid |
see <Solid,Solid> |
CollisionVolumes (Solid) |
see <Solid,Solid> |
see <Solid,Solid> |
see <Solid,Solid> |
Brep |
see <Solid,Solid> |
see <Solid,Solid> |
CollisionVolumes (Brep) |
see <Surface,Surface> |
see <Surface,Surface> |
Surface |
see <Solid,Solid> |
see <Solid,Solid> |
see <Surface,Surface> |
Intersection Curves (ICurve) |
see <Surface,Surface> |
Region |
see <Solid,Solid> |
see <Solid,Solid> |
see <Brep,Brep> |
see <Surface,Surface> |
CollisionVolumes (Solid) |
Workflow
Collision detection (CD) derives from WorkUnit, so it could be called synchronously with CD.DoWork() or asynchronously with design1.StartWork(CD). When asynchronously, you can call more different CDs at a time but during the collision checks the entities' data must remain constant, so no transformations are allowed during that time. For this reason, if you want to perform the asynchronous check with the same entities (in different positions) you have to clone (and transform them after that) the relevant entities used inside the CD.
The workflow is the following:
- Precomputation of the needed data during collision checks (like Octree/QuadTree, OBR/OBB) only for the entities that don't already have them. The method PrepareDataForCollision() performs this computation and it can be called separately from the DoWork() call. After this first computation, the entities will keep their data until:
- The Entity.RegenMode won't be anymore NotNeeded (for Octree/Quadtree);
- A non-uniform scale is applied to the entity (for OBR/OBB);
- Check for collisions by exploiting the data previously computed depending on the CheckMethod chosen. The collision check won't check entities that belong to the same Block/BlockReferences input hierarchy anyway (see Block/BlockReference entity documentation to find details on how the scene graph works). It will check recursively all the entities (until the leaves) contained in each assembly (see sample below for details). If at least an intersecting tuple of entities is found then the result list won't be empty;
- [optional] Calling the ComputeIntersectionVolume() method to compute and fill the CollisionResult.CollisionItems into Result list with the volumes for each colliding tuple.
Note: Always register to the WorkFailed event when using the asynchronous approach!
Example:
Block b1 = new Block("b1");
b1.Entities.Add(entity1);
Block b2 = new Block("b2");
b2.Entities.Add(entity2);
BlockReference br1 = new BlockReference("b1");
b2.Entities.Add(br1);
Block b3 = new Block("b3");
b3.Entities.Add(entity3);
BlockKeyedCollection blocksCollection = new BlockKeyedCollection();
blocksCollection.Add(b1);
blocksCollection.Add(b2);
blocksCollection.Add(b3);
BlockReference br2 = new BlockReference("b2");
BlockReference br3 = new BlockReference("b3");
List<Entity> listToCheck = new List<Entity>();
listToCheck.Add(br2);
listToCheck.Add(br3);
CollisionDetection cd = new CollisionDetection(listToCheck, blocksCollection);
cd.DoWork();
CD won't check collisions among entity1 and entity2, neither entity2 and br1 because they belong to the same assembly (with br2 as root).
Collisions checks could be instead between:
- br3 and br2;
- br3 and entity2;
- br3 and br1;
- br3 and entity1;
- entity3 and br2;
- entity3 and entity2;
- entity3 and br1;
- entity3 and entity1;
Have a look at the CollisionDetection code sample for a good starting point.
Comments
Article is closed for comments.