use of maspack.geometry.HalfEdge in project artisynth_core by artisynth.
the class IntersectionPoint method getTriangleEdge.
/**
* If this intersection is degenerate and associated with one of the
* triangle edges (but not a vertex), return that edge. Otherwise, return
* <code>null</code>.
*
* @return degenerate triangle edge or <code>null</code>
*/
public HalfEdge getTriangleEdge() {
int tedges = (intersectionCode & TRIANGLE_EDGE_MASK);
if (tedges != 0) {
HalfEdge he = face.firstHalfEdge();
if (tedges == RobustPreds.E01_ON_SEGMENT) {
return he;
}
he = he.getNext();
if (tedges == RobustPreds.E12_ON_SEGMENT) {
return he;
}
he = he.getNext();
if (tedges == RobustPreds.E20_ON_SEGMENT) {
return he;
}
}
return null;
}
use of maspack.geometry.HalfEdge in project artisynth_core by artisynth.
the class IntersectionPoint method getCommonEdge.
/**
* If this point and the specified intersection point <code>p1</code>
* are degenerate such that they both lie on a common triangle edge,
* return that edge. Otherwise, return null. If both points lie on
* a vertex, this method will return null as well.
*
* @param p1 point to query for common edge
* @return common edge, if any
*/
public HalfEdge getCommonEdge(IntersectionPoint p1) {
int tedges = (intersectionCode & TRIANGLE_EDGE_MASK);
tedges &= (p1.intersectionCode & TRIANGLE_EDGE_MASK);
HalfEdge he = face.firstHalfEdge();
if (tedges == RobustPreds.E01_ON_SEGMENT) {
return he;
}
he = he.getNext();
if (tedges == RobustPreds.E12_ON_SEGMENT) {
return he;
}
he = he.getNext();
if (tedges == RobustPreds.E20_ON_SEGMENT) {
return he;
}
return null;
}
use of maspack.geometry.HalfEdge in project artisynth_core by artisynth.
the class ContactPlane method edgeEdgeContact.
/*
* Handle the case where there are insufficient contact points in the contour
* to define a plane. and there are no penetrating vertices in either region.
*/
boolean edgeEdgeContact(PenetrationRegion region0, PenetrationRegion region1, PolygonalMesh mesh0) {
HashSet<HalfEdge> edges = new HashSet<HalfEdge>();
for (IntersectionPoint mip : contour) edges.add(mip.edge);
if (edges.size() != 2) {
/*
* This can happen if a penetrating vertex goes right through the other
* object and out the other side, or if an edge is co-planar with a
* face.
*/
System.out.println("unknown contact type: edge-edge with " + edges.size() + " edges");
// with "+edges.size()+" edges");
return false;
}
HalfEdge edge0, edge1;
Iterator<HalfEdge> itr = edges.iterator();
edge0 = itr.next();
edge1 = itr.next();
Vector3d vedge0 = new Vector3d(), vedge1 = new Vector3d();
vedge0.sub(edge0.getHead().getWorldPoint(), edge0.getTail().getWorldPoint());
vedge1.sub(edge1.getHead().getWorldPoint(), edge1.getTail().getWorldPoint());
normal.cross(vedge0, vedge1);
normal.normalize();
/* Compute depth=perpendicular distance between the two edges. */
Vector3d c = new Vector3d();
c.sub(edge1.getTail().getWorldPoint(), edge0.getTail().getWorldPoint());
vedge0.cross(vedge0, vedge1);
depth = Math.abs(c.dot(vedge0)) / vedge0.norm();
minProjectedDistance = maxProjectedDistance = 0;
checkNormalDirection(region0.getFaces(), region1.getFaces(), mesh0);
return true;
}
use of maspack.geometry.HalfEdge in project artisynth_core by artisynth.
the class SurfaceMeshCollider method findEdgeEdgeContacts.
/*
* Create an edge-edge contact for each unique pair of HalfEdges where - the
* edges are from opposite regions, - both edges are in need of edge-edge
* correction - the geometry is suitable (see EdgeEdgeContact.calculate())
*/
public ArrayList<EdgeEdgeContact> findEdgeEdgeContacts(ContactInfo cinfo) {
/* First scan the contours for interlocking triangles, */
HashMap<Vertex3d, PenetratingPoint> vertexCpps = new HashMap<Vertex3d, PenetratingPoint>();
for (PenetratingPoint cpp : cinfo.getPenetratingPoints(0)) {
vertexCpps.put(cpp.vertex, cpp);
}
for (PenetratingPoint cpp : cinfo.getPenetratingPoints(1)) {
vertexCpps.put(cpp.vertex, cpp);
}
ArrayList<EdgeEdgeContact> contacts = new ArrayList<EdgeEdgeContact>();
HashMap<PenetrationRegion, PenetrationRegion> opposingRegions = cinfo.findMatchingRegions();
for (PenetrationRegion r0 : opposingRegions.keySet()) {
PenetrationRegion r1 = opposingRegions.get(r0);
for (HalfEdge edge0 : r0.myEdges) {
if (needsEdgeEdgeCorrection(edge0, vertexCpps)) {
for (HalfEdge edge1 : r1.myEdges) {
if (needsEdgeEdgeCorrection(edge1, vertexCpps)) {
EdgeEdgeContact eec = new EdgeEdgeContact();
if (eec.calculate(this, edge0, edge1)) {
// Test the geometry to see if it is a valid edge-edge
// contact.
eec.region = r0;
contacts.add(eec);
}
}
}
}
}
}
return contacts;
}
use of maspack.geometry.HalfEdge in project artisynth_core by artisynth.
the class SurfaceMeshContourIxer method getOneContour.
/**
* From an non-empty list of MIPs, create a new MeshIntersectionContour and
* return it. It might be open or closed. MIPs are removed from mips as they
* are used.
*
* @param mips List of possible MeshIntersectionPoints to check. This method
* deletes MIPs in mips as it goes along.
* @return new MeshIntersectionContour, or <code>null</code>
* if <code>mips</code> is empty
*/
protected IntersectionContour getOneContour(ArrayList<IntersectionPoint> mips) throws DegenerateLoopCaseException {
if (mips.size() == 0) {
return null;
}
IntersectionContour contour = new IntersectionContour();
contour.setClosed(true);
IntersectionPoint firstMip = mips.get(0);
IntersectionPoint mip = firstMip;
IntersectionPoint nextMip = null;
// Start the contour
contour.add(mip);
Face fPrev = null;
while (nextMip != contour.get(0) || contour.size() < 2) {
nextMip = null;
// First search this edge's face's edges for intersection with mip.face
Face thisEdgesFace;
if (mip.edge.getFace() == fPrev) {
if (mip.edge.opposite == null) {
thisEdgesFace = null;
} else {
thisEdgesFace = mip.edge.opposite.getFace();
}
} else {
thisEdgesFace = mip.edge.getFace();
}
/*
* We have found the edge of an open mesh. This contour is
* definitely open. Continue from contour.get(0) and go in
* opposite direction. If we already did that, then we're finished.
*/
if (thisEdgesFace == null) {
if (!contour.isClosed()) {
// We're finished, since we already did this
break;
}
contour.setClosed(false);
nextMip = firstMip;
contour.reverse();
mip = nextMip;
mips.remove(mip);
// mip.edge.getFace was already checked in first pass,
// so we should use this as previous to switch directions.
fPrev = mip.edge.getFace();
continue;
}
/*
* Now the meat of the algorithm. Search this edge's faces edges
* for another match. If found, this is the next mip in the contour
*/
for (int i = 0; i < 3; i++) {
HalfEdge candEdge = thisEdgesFace.getEdge(i).getPrimary();
if (candEdge == mip.edge.getPrimary()) {
// We already know about this edge
continue;
}
EdgeFacePair testPair = new EdgeFacePair(candEdge, mip.face);
nextMip = mySavedEdgeFaceResults.get(testPair);
if (nextMip == null) {
continue;
} else {
fPrev = thisEdgesFace;
break;
}
}
/*
* if nextMip is still null, the next mip must be on the other mesh's face
*/
if (nextMip == null) {
for (int i = 0; i < 3; i++) {
HalfEdge candEdge = mip.face.getEdge(i).getPrimary();
EdgeFacePair testPair = new EdgeFacePair(candEdge, thisEdgesFace);
nextMip = mySavedEdgeFaceResults.get(testPair);
if (nextMip == null) {
continue;
} else {
fPrev = mip.face;
break;
}
}
}
/*
* If we still haven't found the next MIP at this point,
* we're basically screwed. We should probably give up or something
*/
if (nextMip == null) {
System.out.println("mips.size(): " + mips.size());
System.out.println("contour.size(): " + contour.size());
throw new DegenerateLoopCaseException("Couldn't find next intersection point!");
}
mip = nextMip;
contour.add(mip);
if (!mips.remove(mip)) {
// This shouldn't happen
System.out.println("mips.size(): " + mips.size());
System.out.println("contour.size(): " + contour.size());
if (!contour.isClosed()) {
System.out.println("Open contour");
}
throw new DegenerateLoopCaseException("Warning! nextMip wasn't in mips!!! aborting");
}
}
return contour;
}
Aggregations