//generate the cyclical list of vertices in the polygon
for (int i = 0; i < shapeVerts.getNumPoints(); i++)
polygonVertices.addLast(new Vertex(shapeVerts.getCoordinateN(i), i));
//generate the cyclical list of vertices in the hole
CyclicalList holePolygon = new CyclicalList();
for (int i = 0; i < holeVerts.getNumPoints(); i++)
holePolygon.add(new Vertex(holeVerts.getCoordinateN(i), i + polygonVertices.size()));
// calc list of convex and reflex vertices
findConvexAndReflexVertices();
//find the hole vertex with the largest X value
Vertex rightMostHoleVertex = (Vertex)holePolygon.get(0);
for(int count=0;count<holePolygon.size();count++) {
Vertex v=(Vertex)holePolygon.get(count);
if (v.getPosition().x > rightMostHoleVertex.getPosition().x)
rightMostHoleVertex = v;
}
//construct a list of all line segments where at least one vertex
//is to the right of the rightmost hole vertex with one vertex
//above the hole vertex and one below
ArrayList segmentsToTest = new ArrayList();
for (int i = 0; i < polygonVertices.size(); i++)
{
Vertex a = (Vertex)polygonVertices.get(i);
Vertex b = (Vertex)polygonVertices.get(i + 1);
if ((a.getPosition().x > rightMostHoleVertex.getPosition().x || b.getPosition().x > rightMostHoleVertex.getPosition().x) &&
((a.getPosition().y >= rightMostHoleVertex.getPosition().y && b.getPosition().y <= rightMostHoleVertex.getPosition().y) ||
(a.getPosition().y <= rightMostHoleVertex.getPosition().y && b.getPosition().y >= rightMostHoleVertex.getPosition().y)))
segmentsToTest.add(new LineSegment(a, b));
}
//now we try to find the closest intersection point heading to the right from
//our hole vertex.
Float closestPoint = null;
LineSegment closestSegment = new LineSegment();
for (int count=0;count<segmentsToTest.size();count++)
{
LineSegment segment=(LineSegment)segmentsToTest.get(count);
Float intersection = segment.intersectsWithRay(rightMostHoleVertex.getPosition(), new Coordinate(1.0,0.0));
if (intersection != null)
{
if (closestPoint == null || closestPoint.floatValue()> intersection.floatValue())
{
closestPoint = intersection;
closestSegment = segment;
}
}
}
//if closestPoint is null, there were no collisions (likely from improper input data),
//but we'll just return without doing anything else
if (closestPoint == null)
return shapeVerts;
//otherwise we can find our mutually visible vertex to split the polygon
Coordinate I = rightMostHoleVertex.getPosition();
GVector i=new GVector(new double[] {I.x,I.y});
i.add(new GVector(new double[] {closestPoint.floatValue(),0.0}));
Vertex P = (closestSegment.A.getPosition().x > closestSegment.B.getPosition().x)
? closestSegment.A
: closestSegment.B;
//construct triangle MIP
Triangle mip = new Triangle(rightMostHoleVertex, new Vertex(I, 1), P);
//see if any of the reflex vertices lie inside of the MIP triangle
ArrayList interiorReflexVertices = new ArrayList();
for (int count=0;count<reflexVertices.size();count++) {
Vertex v=(Vertex)reflexVertices.get(count);
if (mip.ContainsPoint(v))
interiorReflexVertices.add(v);
}
//if there are any interior reflex vertices, find the one that, when connected
//to our rightMostHoleVertex, forms the line closest to Vector2.UnitX
if (interiorReflexVertices.size() > 0)
{
float closestDot = -1f;
for (int count=0;count<interiorReflexVertices.size();count++)
{
Vertex v=(Vertex)interiorReflexVertices.get(count);
GVector n=new GVector(new double[] {v.getPosition().x,v.getPosition().y});
n.sub(new GVector(new double[] {rightMostHoleVertex.getPosition().x,rightMostHoleVertex.getPosition().y}));
n.normalize();
GVector m=new GVector(new double[] {1.0,0.0});
float dot=(float)m.dot(n);
//if this line is the closest we've found
if (dot > closestDot)
{
//save the value and save the vertex as P
closestDot = dot;
P = v;
}
}
}
//now we just form our output array by injecting the hole vertices into place
//we know we have to inject the hole into the main array after point P going from
//rightMostHoleVertex around and then back to P.
int mIndex = holePolygon.indexOf(rightMostHoleVertex);
int injectPoint = polygonVertices.indexOf(P)+1;
for (int count = mIndex; count <= mIndex + holePolygon.size(); count++)
{
polygonVertices.add(injectPoint++, holePolygon.get(count));
}
polygonVertices.add(injectPoint, P);
Coordinate[] newShapeVerts = new Coordinate[polygonVertices.size()];