use of maspack.geometry.BVNode in project artisynth_core by artisynth.
the class SurfaceMeshContourIxer method findContours.
/*
* Main interface for collision -- called by CollisionPair. Returns a
* ContactInfo populated with the results of the collision analysis. Returns
* null if there is no collision. mesh0, mesh1 are the candidate colliding
* surface meshes, which can be the same mesh.
*
* isRigidBodyRigidBody should be specified as true only if mesh0 and mesh1
* both represent rigid bodies. This controls the type of data returned in
* ContactInfo.
*/
public boolean findContours(PolygonalMesh mesh0, PolygonalMesh mesh1) {
if (mesh0 != mesh1) {
if (mesh0.canSelfIntersect)
if (findContours(mesh0, mesh0))
throw new RuntimeException("self-intersecting mesh");
if (mesh1.canSelfIntersect)
if (findContours(mesh1, mesh1))
throw new RuntimeException("self-intersecting mesh");
}
this.mesh0 = mesh0;
this.mesh1 = mesh1;
double maxRadius = Math.max(RenderableUtils.getRadius(mesh0), RenderableUtils.getRadius(mesh1));
myMaxLength = 2 * maxRadius;
mesh0.updateFaceNormals();
mesh1.updateFaceNormals();
if (!mesh0.isTriangular() | !mesh1.isTriangular())
throw new IllegalArgumentException("collision with non-triangular mesh");
ArrayList<IntersectionPoint> allMips = new ArrayList<IntersectionPoint>();
// Try getting allMips continuously until no DegenerateCases are caught
boolean intersected;
int exceptCntr = 0;
while (true) {
// Clear old saved results
mySavedEdgeFaceResults.clear();
myContours.clear();
allMips.clear();
BVTree bvh0 = mesh0.getBVTree();
BVTree bvh1 = mesh1.getBVTree();
ArrayList<BVNode> nodes0 = new ArrayList<BVNode>();
ArrayList<BVNode> nodes1 = new ArrayList<BVNode>();
bvh0.intersectTree(nodes0, nodes1, bvh1);
try {
getAllMIPs(allMips, nodes0, nodes1);
if (allMips.size() > 0) {
buildContours(myContours, allMips);
intersected = true;
} else {
intersected = false;
}
return intersected;
// break;
} catch (DegeneratePairCaseException e) {
System.out.println("Caught a DegeneratePairCaseException, points perturbed and retrying");
mesh0.notifyVertexPositionsModified();
mesh1.notifyVertexPositionsModified();
} catch (DegenerateLoopCaseException e) {
if (exceptCntr > 5) {
System.out.println("SurfaceMeshContourIxer failed! Giving up after 5 tries");
break;
}
System.out.println("Caught a DegenerateLoopCaseException, points perturbed and retrying");
System.out.println(e.getMessage());
perturbVertices(mesh0);
perturbVertices(mesh1);
mesh0.notifyVertexPositionsModified();
mesh1.notifyVertexPositionsModified();
exceptCntr++;
continue;
}
}
return false;
}
use of maspack.geometry.BVNode in project artisynth_core by artisynth.
the class FemModel3d method findContainingElement.
/**
* Returns the element within an FEM that contains a specified
* point, or <code>null</code> if there is no such element.
*
* @param pnt Point for which containing element is desired.
* @return containing element, or null.
*/
public FemElement3d findContainingElement(Point3d pnt) {
BVTree bvtree = getBVTree();
ArrayList<BVNode> nodes = new ArrayList<BVNode>(16);
bvtree.intersectPoint(nodes, pnt);
// System.out.println ("num nodes " + nodes.size());
if (nodes.size() == 0) {
return null;
}
for (BVNode n : nodes) {
Boundable[] elements = n.getElements();
for (int i = 0; i < elements.length; i++) {
if (((FemElement3d) elements[i]).isInside(pnt)) {
return (FemElement3d) elements[i];
}
}
}
return null;
}
use of maspack.geometry.BVNode in project artisynth_core by artisynth.
the class FemModel3d method findNearestNode.
/**
* Finds the nearest node to a specified point that is within
* a specified maximum distance. If no node is within the
* specified maximum distance, <code>null</code> is returned.
*
* @param pnt Point for which the nearest node should be located
* @param maxDist Maximum distance that the node must be from the
* point. If <code>maxDist</code> < 0, then <code>null</code>
* will be returned.
* @return Nearest point within the prescribed distance, or <code>null</code>
* if there is no such point
*/
public FemNode3d findNearestNode(Point3d pnt, double maxDist) {
if (maxDist < 0) {
return null;
}
BVTree bvtree = getBVTree();
ArrayList<BVNode> nodes = new ArrayList<BVNode>();
bvtree.intersectSphere(nodes, pnt, maxDist);
FemNode3d nearest = null;
double dist = 1 + 2 * maxDist;
for (BVNode n : nodes) {
Boundable[] elements = n.getElements();
for (int i = 0; i < elements.length; i++) {
FemElement3d e = (FemElement3d) elements[i];
for (int k = 0; k < e.numNodes(); k++) {
double d = e.myNodes[k].getPosition().distance(pnt);
if (d < dist && d <= maxDist) {
dist = d;
nearest = e.myNodes[k];
}
}
}
}
return nearest;
}
use of maspack.geometry.BVNode in project artisynth_core by artisynth.
the class FemMuscleModel method computeAverageFiberDirection.
/**
* Computes the average fiber direction in the vicinity of a point based on
* the line segments contained in a PolylineMesh. Returns the number of
* supporting line segments used for the calculation. If no segments were
* found, the method returns 0 and the direction is undefined.
*
* @param dir returns the normalized direction
* @param pos position at which direction should be computed
* @param rad radius of influence within which polyline mesh segments are
* considerd
* @param mesh mesh containing line segments used to determine the direction
* @return number of supporting line segment
*/
public static int computeAverageFiberDirection(Vector3d dir, Point3d pos, double rad, PolylineMesh mesh) {
BVTree bvh = mesh.getBVTree();
ArrayList<BVNode> nodes = new ArrayList<BVNode>();
Matrix3d cov = new Matrix3d();
SVDecomposition3d svd = new SVDecomposition3d();
Vector3d tmp = new Vector3d();
Matrix3d tmp2 = new Matrix3d();
bvh.intersectSphere(nodes, pos, rad);
dir.setZero();
int nsegs = 0;
// for computing sign of direction vector
Vector3d segmentSum = new Vector3d();
// System.out.println("p=[");
for (BVNode n : nodes) {
Boundable[] elements = n.getElements();
for (int i = 0; i < elements.length; i++) {
LineSegment seg = (LineSegment) elements[i];
seg = getSegmentInsideSphere(seg, pos, rad);
if (seg != null) {
tmp.sub(seg.myVtx1.pnt, seg.myVtx0.pnt);
if (tmp.norm() >= 1e-8 * rad) {
// System.out.println(seg.myVtx0.getPosition() + " " +
// seg.myVtx1.getPosition());
nsegs++;
// prepare to average directions using SVD
computeCov(tmp2, tmp);
cov.add(tmp2);
segmentSum.add(tmp);
}
}
}
}
if (nsegs > 0) {
// we are technically including both +/- directions, so
// we have twice the number of points
cov.scale(2.0 / (2.0 * nsegs - 1));
try {
svd.factor(cov);
} catch (Exception e) {
// System.err.println(e.getMessage());
}
// principal components
tmp2 = svd.getU();
tmp2.getColumn(0, dir);
dir.normalize();
// most line segments
if (dir.dot(segmentSum) < 0) {
dir.scale(-1);
}
return nsegs;
} else {
return 0;
}
}
use of maspack.geometry.BVNode in project artisynth_core by artisynth.
the class FemIntersector method intersectPlane.
/**
* Intersects a FEM 3d model with a plane, returning a Polygonal mesh
* on the plane corresponding to inside the FEM
* @param fem model to intersect with the plane
* @param plane plane to intersect with
* @return intersection mesh
*/
public PolygonalMesh intersectPlane(FemModel3d fem, Plane plane) {
AABBTree aabb = new AABBTree();
FemElement3d[] elements = fem.getElements().toArray(new FemElement3d[fem.numElements()]);
aabb.build(elements, fem.numElements());
ArrayList<BVNode> nodes = new ArrayList<BVNode>();
aabb.intersectPlane(nodes, plane);
DirectedGraph<Point3d, Vector3d> nodeGraph = new DirectedGraph<Point3d, Vector3d>();
TriangleIntersector ti = new TriangleIntersector();
ti.setEpsilon(epsilon);
for (BVNode node : nodes) {
Boundable[] elems = node.getElements();
for (int i = 0; i < node.getNumElements(); i++) {
FemElement3d elem = (FemElement3d) elems[i];
FaceNodes3d[] faceNodes = elem.getFaces();
for (FaceNodes3d fn : faceNodes) {
FemNode3d[][] faces = fn.triangulate();
for (FemNode3d[] face : faces) {
addIfUnique(ti.intersectTrianglePlane(face[0].getPosition(), face[1].getPosition(), face[2].getPosition(), plane), nodeGraph, epsilon);
}
// end loop through faces
}
// end loop through "face nodes"
}
// end looping through elements
}
// end looping through BVNodes
// reduceGraph(nodeGraph, tol);
fixOverlaps(nodeGraph, epsilon);
PolygonalMesh mesh = buildMesh(nodeGraph, plane.normal);
removeBackFaces(mesh, plane.normal);
nonConvexTriangulate(mesh, plane.normal, epsilon);
return mesh;
}
Aggregations