Introduce notion of inside/outside for DualCrossing.

This commit is contained in:
Karl Wright 2016-04-26 07:46:44 -04:00
parent 675a30b8f7
commit 129f6d4767
1 changed files with 80 additions and 43 deletions

View File

@ -715,13 +715,15 @@ class GeoComplexPolygon extends GeoBasePolygon {
private boolean isSecondLeg = false; private boolean isSecondLeg = false;
private final Plane testPointPlane; private final Plane testPointPlane;
private final Plane testPointAbovePlane; private final Plane testPointInsidePlane;
private final Plane testPointBelowPlane; private final Plane testPointOutsidePlane;
private final Plane travelPlane; private final Plane travelPlane;
private final Plane travelAbovePlane; private final Plane travelInsidePlane;
private final Plane travelBelowPlane; private final Plane travelOutsidePlane;
private final Vector thePoint; private final Vector thePoint;
private final GeoPoint intersectionPoint;
private final SidedPlane testPointCutoffPlane; private final SidedPlane testPointCutoffPlane;
private final SidedPlane checkPointCutoffPlane; private final SidedPlane checkPointCutoffPlane;
private final SidedPlane testPointOtherCutoffPlane; private final SidedPlane testPointOtherCutoffPlane;
@ -732,20 +734,55 @@ class GeoComplexPolygon extends GeoBasePolygon {
public DualCrossingEdgeIterator(final Plane testPointPlane, final Plane testPointAbovePlane, final Plane testPointBelowPlane, public DualCrossingEdgeIterator(final Plane testPointPlane, final Plane testPointAbovePlane, final Plane testPointBelowPlane,
final Plane travelPlane, final Vector testPoint, final Vector thePoint) { final Plane travelPlane, final Vector testPoint, final Vector thePoint) {
this.testPointPlane = testPointPlane; this.testPointPlane = testPointPlane;
this.testPointAbovePlane = testPointAbovePlane;
this.testPointBelowPlane = testPointBelowPlane;
this.travelPlane = travelPlane; this.travelPlane = travelPlane;
this.thePoint = thePoint; this.thePoint = thePoint;
this.travelAbovePlane = new Plane(travelPlane, true);
this.travelBelowPlane = new Plane(travelPlane, false);
this.testPointCutoffPlane = new SidedPlane(thePoint, testPointPlane, testPoint); this.testPointCutoffPlane = new SidedPlane(thePoint, testPointPlane, testPoint);
this.checkPointCutoffPlane = new SidedPlane(testPoint, travelPlane, thePoint); this.checkPointCutoffPlane = new SidedPlane(testPoint, travelPlane, thePoint);
// Now, find the intersection of the check and test point planes. // Now, find the intersection of the check and test point planes.
final GeoPoint[] intersectionPoints = travelPlane.findIntersections(planetModel, testPointPlane, testPointCutoffPlane, checkPointCutoffPlane); final GeoPoint[] intersectionPoints = travelPlane.findIntersections(planetModel, testPointPlane, testPointCutoffPlane, checkPointCutoffPlane);
assert intersectionPoints != null : "couldn't find any intersections"; assert intersectionPoints != null : "couldn't find any intersections";
assert intersectionPoints.length != 1 : "wrong number of intersection points"; assert intersectionPoints.length != 1 : "wrong number of intersection points";
this.testPointOtherCutoffPlane = new SidedPlane(testPoint, testPointPlane, intersectionPoints[0]); this.intersectionPoint = intersectionPoints[0];
this.checkPointOtherCutoffPlane = new SidedPlane(thePoint, travelPlane, intersectionPoints[0]); this.testPointOtherCutoffPlane = new SidedPlane(testPoint, testPointPlane, intersectionPoint);
this.checkPointOtherCutoffPlane = new SidedPlane(thePoint, travelPlane, intersectionPoint);
// Figure out which of the above/below planes are inside vs. outside. To do this,
// we look for the point that is within the bounds of the testPointPlane and travelPlane. The two sides that intersected there are the inside
// borders.
final Plane travelAbovePlane = new Plane(travelPlane, true);
final Plane travelBelowPlane = new Plane(travelPlane, false);
final GeoPoint[] aboveAbove = travelAbovePlane.findIntersections(planetModel, testPointAbovePlane, testPointCutoffPlane, testPointOtherCutoffPlane, checkPointCutoffPlane, checkPointOtherCutoffPlane);
assert aboveAbove != null : "Above + above should not be coplanar";
final GeoPoint[] aboveBelow = travelAbovePlane.findIntersections(planetModel, testPointBelowPlane, testPointCutoffPlane, testPointOtherCutoffPlane, checkPointCutoffPlane, checkPointOtherCutoffPlane);
assert aboveBelow != null : "Above + below should not be coplanar";
final GeoPoint[] belowBelow = travelBelowPlane.findIntersections(planetModel, testPointBelowPlane, testPointCutoffPlane, testPointOtherCutoffPlane, checkPointCutoffPlane, checkPointOtherCutoffPlane);
assert belowBelow != null : "Below + below should not be coplanar";
final GeoPoint[] belowAbove = travelBelowPlane.findIntersections(planetModel, testPointAbovePlane, testPointCutoffPlane, testPointOtherCutoffPlane, checkPointCutoffPlane, checkPointOtherCutoffPlane);
assert belowAbove != null : "Below + above should not be coplanar";
assert aboveAbove.length + aboveBelow.length + belowBelow.length + belowAbove.length == 1 : "Can be exactly one inside point";
if (aboveAbove.length > 0) {
travelInsidePlane = travelAbovePlane;
testPointInsidePlane = testPointAbovePlane;
travelOutsidePlane = travelBelowPlane;
testPointOutsidePlane = testPointBelowPlane;
} else if (aboveBelow.length > 0) {
travelInsidePlane = travelAbovePlane;
testPointInsidePlane = testPointBelowPlane;
travelOutsidePlane = travelBelowPlane;
testPointOutsidePlane = testPointAbovePlane;
} else if (belowBelow.length > 0) {
travelInsidePlane = travelBelowPlane;
testPointInsidePlane = testPointBelowPlane;
travelOutsidePlane = travelAbovePlane;
testPointOutsidePlane = testPointAbovePlane;
} else {
travelInsidePlane = travelBelowPlane;
testPointInsidePlane = testPointAbovePlane;
travelOutsidePlane = travelAbovePlane;
testPointOutsidePlane = testPointBelowPlane;
}
} }
@ -776,20 +813,20 @@ class GeoComplexPolygon extends GeoBasePolygon {
private void countCrossingPoint(final GeoPoint crossingPoint, final Edge edge) { private void countCrossingPoint(final GeoPoint crossingPoint, final Edge edge) {
final Plane plane; final Plane plane;
final Plane abovePlane; final Plane insidePlane;
final Plane belowPlane; final Plane outsidePlane;
final SidedPlane bound1; final SidedPlane bound1;
final SidedPlane bound2; final SidedPlane bound2;
if (isSecondLeg) { if (isSecondLeg) {
plane = travelPlane; plane = travelPlane;
abovePlane = travelAbovePlane; insidePlane = travelInsidePlane;
belowPlane = travelBelowPlane; outsidePlane = travelOutsidePlane;
bound1 = checkPointCutoffPlane; bound1 = checkPointCutoffPlane;
bound2 = checkPointOtherCutoffPlane; bound2 = checkPointOtherCutoffPlane;
} else { } else {
plane = testPointPlane; plane = testPointPlane;
abovePlane = testPointAbovePlane; insidePlane = testPointInsidePlane;
belowPlane = testPointBelowPlane; outsidePlane = testPointOutsidePlane;
bound1 = testPointCutoffPlane; bound1 = testPointCutoffPlane;
bound2 = testPointOtherCutoffPlane; bound2 = testPointOtherCutoffPlane;
} }
@ -800,29 +837,29 @@ class GeoComplexPolygon extends GeoBasePolygon {
// We have to figure out if this crossing should be counted. // We have to figure out if this crossing should be counted.
// Does the crossing for this edge go up, or down? Or can't we tell? // Does the crossing for this edge go up, or down? Or can't we tell?
final GeoPoint[] aboveIntersections = abovePlane.findIntersections(planetModel, edge.plane, edge.startPlane, edge.endPlane); final GeoPoint[] insideIntersections = insidePlane.findIntersections(planetModel, edge.plane, edge.startPlane, edge.endPlane);
final GeoPoint[] belowIntersections = belowPlane.findIntersections(planetModel, edge.plane, edge.startPlane, edge.endPlane); final GeoPoint[] outsideIntersections = outsidePlane.findIntersections(planetModel, edge.plane, edge.startPlane, edge.endPlane);
assert !(aboveIntersections.length > 0 && belowIntersections.length > 0) : "edge that ends in a crossing can't both up and down"; assert !(insideIntersections.length > 0 && outsideIntersections.length > 0) : "edge that ends in a crossing can't both up and down";
if (aboveIntersections.length == 0 && belowIntersections.length == 0) { if (insideIntersections.length == 0 && outsideIntersections.length == 0) {
return; return;
} }
final boolean edgeCrossesAbove = aboveIntersections.length > 0; final boolean edgeCrossesInside = insideIntersections.length > 0;
// This depends on the previous edge that first departs from identicalness. // This depends on the previous edge that first departs from identicalness.
Edge assessEdge = edge; Edge assessEdge = edge;
GeoPoint[] assessAboveIntersections; GeoPoint[] assessInsideIntersections;
GeoPoint[] assessBelowIntersections; GeoPoint[] assessOutsideIntersections;
while (true) { while (true) {
assessEdge = assessEdge.previous; assessEdge = assessEdge.previous;
assessAboveIntersections = abovePlane.findIntersections(planetModel, assessEdge.plane, assessEdge.startPlane, assessEdge.endPlane); assessInsideIntersections = insidePlane.findIntersections(planetModel, assessEdge.plane, assessEdge.startPlane, assessEdge.endPlane);
assessBelowIntersections = belowPlane.findIntersections(planetModel, assessEdge.plane, assessEdge.startPlane, assessEdge.endPlane); assessOutsideIntersections = outsidePlane.findIntersections(planetModel, assessEdge.plane, assessEdge.startPlane, assessEdge.endPlane);
assert !(assessAboveIntersections.length > 0 && assessBelowIntersections.length > 0) : "assess edge that ends in a crossing can't both up and down"; assert !(assessInsideIntersections.length > 0 && assessOutsideIntersections.length > 0) : "assess edge that ends in a crossing can't both up and down";
if (assessAboveIntersections.length == 0 && assessBelowIntersections.length == 0) { if (assessInsideIntersections.length == 0 && assessOutsideIntersections.length == 0) {
continue; continue;
} }
break; break;
@ -853,8 +890,8 @@ class GeoComplexPolygon extends GeoBasePolygon {
// point where they hit the plane. This may be complicated by the 3D geometry; it may not be safe just to look at the endpoints of the edges // point where they hit the plane. This may be complicated by the 3D geometry; it may not be safe just to look at the endpoints of the edges
// and make an assessment that way, since a single edge can intersect the plane at more than one point. // and make an assessment that way, since a single edge can intersect the plane at more than one point.
final boolean assessEdgeAbove = assessAboveIntersections.length > 0; final boolean assessEdgeInside = assessInsideIntersections.length > 0;
if (assessEdgeAbove != edgeCrossesAbove) { if (assessEdgeInside != edgeCrossesInside) {
crossingCount++; crossingCount++;
} }
@ -862,29 +899,29 @@ class GeoComplexPolygon extends GeoBasePolygon {
// Figure out if the crossing should be counted. // Figure out if the crossing should be counted.
// Does the crossing for this edge go up, or down? Or can't we tell? // Does the crossing for this edge go up, or down? Or can't we tell?
final GeoPoint[] aboveIntersections = abovePlane.findIntersections(planetModel, edge.plane, edge.startPlane, edge.endPlane); final GeoPoint[] insideIntersections = insidePlane.findIntersections(planetModel, edge.plane, edge.startPlane, edge.endPlane);
final GeoPoint[] belowIntersections = belowPlane.findIntersections(planetModel, edge.plane, edge.startPlane, edge.endPlane); final GeoPoint[] outsideIntersections = outsidePlane.findIntersections(planetModel, edge.plane, edge.startPlane, edge.endPlane);
assert !(aboveIntersections.length > 0 && belowIntersections.length > 0) : "edge that ends in a crossing can't both up and down"; assert !(insideIntersections.length > 0 && outsideIntersections.length > 0) : "edge that ends in a crossing can't both up and down";
if (aboveIntersections.length == 0 && belowIntersections.length == 0) { if (insideIntersections.length == 0 && outsideIntersections.length == 0) {
return; return;
} }
final boolean edgeCrossesAbove = aboveIntersections.length > 0; final boolean edgeCrossesInside = insideIntersections.length > 0;
// This depends on the previous edge that first departs from identicalness. // This depends on the previous edge that first departs from identicalness.
Edge assessEdge = edge; Edge assessEdge = edge;
GeoPoint[] assessAboveIntersections; GeoPoint[] assessInsideIntersections;
GeoPoint[] assessBelowIntersections; GeoPoint[] assessOutsideIntersections;
while (true) { while (true) {
assessEdge = assessEdge.next; assessEdge = assessEdge.next;
assessAboveIntersections = abovePlane.findIntersections(planetModel, assessEdge.plane, assessEdge.startPlane, assessEdge.endPlane); assessInsideIntersections = insidePlane.findIntersections(planetModel, assessEdge.plane, assessEdge.startPlane, assessEdge.endPlane);
assessBelowIntersections = belowPlane.findIntersections(planetModel, assessEdge.plane, assessEdge.startPlane, assessEdge.endPlane); assessOutsideIntersections = outsidePlane.findIntersections(planetModel, assessEdge.plane, assessEdge.startPlane, assessEdge.endPlane);
assert !(assessAboveIntersections.length > 0 && assessBelowIntersections.length > 0) : "assess edge that ends in a crossing can't both up and down"; assert !(assessInsideIntersections.length > 0 && assessOutsideIntersections.length > 0) : "assess edge that ends in a crossing can't both up and down";
if (assessAboveIntersections.length == 0 && assessBelowIntersections.length == 0) { if (assessInsideIntersections.length == 0 && assessOutsideIntersections.length == 0) {
continue; continue;
} }
break; break;
@ -901,8 +938,8 @@ class GeoComplexPolygon extends GeoBasePolygon {
// point where they hit the plane. This may be complicated by the 3D geometry; it may not be safe just to look at the endpoints of the edges // point where they hit the plane. This may be complicated by the 3D geometry; it may not be safe just to look at the endpoints of the edges
// and make an assessment that way, since a single edge can intersect the plane at more than one point. // and make an assessment that way, since a single edge can intersect the plane at more than one point.
final boolean assessEdgeAbove = assessAboveIntersections.length > 0; final boolean assessEdgeInside = assessInsideIntersections.length > 0;
if (assessEdgeAbove != edgeCrossesAbove) { if (assessEdgeInside != edgeCrossesInside) {
crossingCount++; crossingCount++;
} }