Added the 800lb gorilla: Area, and its myriad helper classes.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,291 @@
|
||||
//
|
||||
// Pythagoras - a collection of geometry classes
|
||||
// http://github.com/samskivert/pythagoras
|
||||
|
||||
package pythagoras.f;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An internal class used to compute crossings.
|
||||
*/
|
||||
class CrossingHelper
|
||||
{
|
||||
private float[][] coords;
|
||||
private int[] sizes;
|
||||
private List<IntersectPoint> isectPoints = new ArrayList<IntersectPoint>();
|
||||
|
||||
public CrossingHelper (float[][] coords, int[] sizes) {
|
||||
this.coords = coords;
|
||||
this.sizes = sizes;
|
||||
}
|
||||
|
||||
public IntersectPoint[] findCrossing () {
|
||||
int pointCount1 = sizes[0] / 2;
|
||||
int pointCount2 = sizes[1] / 2;
|
||||
int[] indices = new int[pointCount1 + pointCount2];
|
||||
for (int i = 0; i < pointCount1 + pointCount2; i++) {
|
||||
indices[i] = i;
|
||||
}
|
||||
|
||||
sort(coords[0], pointCount1, coords[1], pointCount2, indices);
|
||||
// the set for the shapes edges storing
|
||||
List<Edge> edges = new ArrayList<Edge>();
|
||||
Edge edge;
|
||||
int begIndex, endIndex;
|
||||
int areaNumber;
|
||||
|
||||
for (int i = 0; i < indices.length; i++) {
|
||||
if (indices[i] < pointCount1) {
|
||||
begIndex = indices[i];
|
||||
endIndex = indices[i] - 1;
|
||||
if (endIndex < 0) {
|
||||
endIndex = pointCount1 - 1;
|
||||
}
|
||||
areaNumber = 0;
|
||||
|
||||
} else if (indices[i] < pointCount1 + pointCount2) {
|
||||
begIndex = indices[i] - pointCount1;
|
||||
endIndex = indices[i] - 1 - pointCount1;
|
||||
if (endIndex < 0) {
|
||||
endIndex = pointCount2 - 1;
|
||||
}
|
||||
areaNumber = 1;
|
||||
|
||||
} else {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
if (!removeEdge(edges, begIndex, endIndex)) {
|
||||
edge = new Edge(begIndex, endIndex, areaNumber);
|
||||
intersectShape(edges, coords[0], pointCount1, coords[1], pointCount2, edge);
|
||||
edges.add(edge);
|
||||
}
|
||||
|
||||
begIndex = indices[i];
|
||||
endIndex = indices[i] + 1;
|
||||
|
||||
if ((begIndex < pointCount1) && (endIndex == pointCount1)) {
|
||||
endIndex = 0;
|
||||
} else if ((begIndex >= pointCount1) && (endIndex == (pointCount2 + pointCount1))) {
|
||||
endIndex = pointCount1;
|
||||
}
|
||||
|
||||
if (endIndex < pointCount1) {
|
||||
areaNumber = 0;
|
||||
} else {
|
||||
areaNumber = 1;
|
||||
endIndex -= pointCount1;
|
||||
begIndex -= pointCount1;
|
||||
}
|
||||
|
||||
if (!removeEdge(edges, begIndex, endIndex)) {
|
||||
edge = new Edge(begIndex, endIndex, areaNumber);
|
||||
intersectShape(edges, coords[0], pointCount1, coords[1], pointCount2, edge);
|
||||
edges.add(edge);
|
||||
}
|
||||
}
|
||||
|
||||
return isectPoints.toArray(new IntersectPoint[isectPoints.size()]);
|
||||
}
|
||||
|
||||
private boolean removeEdge (List<Edge> edges, int begIndex, int endIndex) {
|
||||
for (Edge edge : edges) {
|
||||
if (edge.reverseCompare(begIndex, endIndex)) {
|
||||
edges.remove(edge);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// return the quantity of intersect points
|
||||
private void intersectShape (List<Edge> edges, float[] coords1, int length1,
|
||||
float[] coords2, int length2, Edge initEdge) {
|
||||
int areaOfEdge1, areaOfEdge2;
|
||||
int initBegin, initEnd;
|
||||
int addBegin, addEnd;
|
||||
float x1, y1, x2, y2, x3, y3, x4, y4;
|
||||
float[] point = new float[2];
|
||||
Edge edge;
|
||||
|
||||
if (initEdge.areaNumber == 0) {
|
||||
x1 = coords1[2 * initEdge.begIndex];
|
||||
y1 = coords1[2 * initEdge.begIndex + 1];
|
||||
x2 = coords1[2 * initEdge.endIndex];
|
||||
y2 = coords1[2 * initEdge.endIndex + 1];
|
||||
areaOfEdge1 = 0;
|
||||
} else {
|
||||
x1 = coords2[2 * initEdge.begIndex];
|
||||
y1 = coords2[2 * initEdge.begIndex + 1];
|
||||
x2 = coords2[2 * initEdge.endIndex];
|
||||
y2 = coords2[2 * initEdge.endIndex + 1];
|
||||
areaOfEdge1 = 1;
|
||||
}
|
||||
|
||||
for (Iterator<Edge> iter = edges.iterator(); iter.hasNext();) {
|
||||
edge = iter.next();
|
||||
|
||||
if (edge.areaNumber == 0) {
|
||||
x3 = coords1[2 * edge.begIndex];
|
||||
y3 = coords1[2 * edge.begIndex + 1];
|
||||
x4 = coords1[2 * edge.endIndex];
|
||||
y4 = coords1[2 * edge.endIndex + 1];
|
||||
areaOfEdge2 = 0;
|
||||
} else {
|
||||
x3 = coords2[2 * edge.begIndex];
|
||||
y3 = coords2[2 * edge.begIndex + 1];
|
||||
x4 = coords2[2 * edge.endIndex];
|
||||
y4 = coords2[2 * edge.endIndex + 1];
|
||||
areaOfEdge2 = 1;
|
||||
}
|
||||
|
||||
if ((areaOfEdge1 != areaOfEdge2) &&
|
||||
(GeometryUtil.intersectLines(x1, y1, x2, y2, x3, y3, x4, y4, point) == 1) &&
|
||||
(!containsPoint(point))) {
|
||||
|
||||
if (initEdge.areaNumber == 0) {
|
||||
initBegin = initEdge.begIndex;
|
||||
initEnd = initEdge.endIndex;
|
||||
addBegin = edge.begIndex;
|
||||
addEnd = edge.endIndex;
|
||||
} else {
|
||||
initBegin = edge.begIndex;
|
||||
initEnd = edge.endIndex;
|
||||
addBegin = initEdge.begIndex;
|
||||
addEnd = initEdge.endIndex;
|
||||
}
|
||||
|
||||
if (((initEnd == length1 - 1) && (initBegin == 0 && initEnd > initBegin)) ||
|
||||
(((initEnd != length1 - 1) || (initBegin != 0)) &&
|
||||
((initBegin != length1 - 1) || (initEnd != 0)) && (initBegin > initEnd))) {
|
||||
int temp = initBegin;
|
||||
initBegin = initEnd;
|
||||
initEnd = temp;
|
||||
}
|
||||
|
||||
if (((addEnd == length2 - 1) && (addBegin == 0) && (addEnd > addBegin)) ||
|
||||
(((addEnd != length2 - 1) || (addBegin != 0)) &&
|
||||
((addBegin != length2 - 1) || (addEnd != 0)) && (addBegin > addEnd))) {
|
||||
int temp = addBegin;
|
||||
addBegin = addEnd;
|
||||
addEnd = temp;
|
||||
}
|
||||
|
||||
IntersectPoint ip;
|
||||
for (Iterator<IntersectPoint> i = isectPoints.iterator(); i.hasNext();) {
|
||||
ip = i.next();
|
||||
if ((initBegin == ip.getBegIndex(true)) && (initEnd == ip.getEndIndex(true))) {
|
||||
if (compare(ip.getX(), ip.getY(), point[0], point[1]) > 0) {
|
||||
initEnd = -(isectPoints.indexOf(ip) + 1);
|
||||
ip.setBegIndex1(-(isectPoints.size() + 1));
|
||||
} else {
|
||||
initBegin = -(isectPoints.indexOf(ip) + 1);
|
||||
ip.setEndIndex1(-(isectPoints.size() + 1));
|
||||
}
|
||||
}
|
||||
|
||||
if ((addBegin == ip.getBegIndex(false)) && (addEnd == ip.getEndIndex(false))) {
|
||||
if (compare(ip.getX(), ip.getY(), point[0], point[1]) > 0) {
|
||||
addEnd = -(isectPoints.indexOf(ip) + 1);
|
||||
ip.setBegIndex2(-(isectPoints.size() + 1));
|
||||
} else {
|
||||
addBegin = -(isectPoints.indexOf(ip) + 1);
|
||||
ip.setEndIndex2(-(isectPoints.size() + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isectPoints.add(new IntersectPoint(initBegin, initEnd, addBegin, addEnd,
|
||||
point[0], point[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the array sorting
|
||||
private static void sort (float[] coords1, int length1,
|
||||
float[] coords2, int length2, int[] array) {
|
||||
int temp;
|
||||
int length = length1 + length2;
|
||||
float x1, y1, x2, y2;
|
||||
|
||||
for (int i = 1; i < length; i++) {
|
||||
if (array[i - 1] < length1) {
|
||||
x1 = coords1[2 * array[i - 1]];
|
||||
y1 = coords1[2 * array[i - 1] + 1];
|
||||
} else {
|
||||
x1 = coords2[2 * (array[i - 1] - length1)];
|
||||
y1 = coords2[2 * (array[i - 1] - length1) + 1];
|
||||
}
|
||||
if (array[i] < length1) {
|
||||
x2 = coords1[2 * array[i]];
|
||||
y2 = coords1[2 * array[i] + 1];
|
||||
} else {
|
||||
x2 = coords2[2 * (array[i] - length1)];
|
||||
y2 = coords2[2 * (array[i] - length1) + 1];
|
||||
}
|
||||
int j = i;
|
||||
while (j > 0 && compare(x1, y1, x2, y2) <= 0) {
|
||||
temp = array[j];
|
||||
array[j] = array[j - 1];
|
||||
array[j - 1] = temp;
|
||||
j--;
|
||||
if (j > 0) {
|
||||
if (array[j - 1] < length1) {
|
||||
x1 = coords1[2 * array[j - 1]];
|
||||
y1 = coords1[2 * array[j - 1] + 1];
|
||||
} else {
|
||||
x1 = coords2[2 * (array[j - 1] - length1)];
|
||||
y1 = coords2[2 * (array[j - 1] - length1) + 1];
|
||||
}
|
||||
if (array[j] < length1) {
|
||||
x2 = coords1[2 * array[j]];
|
||||
y2 = coords1[2 * array[j] + 1];
|
||||
} else {
|
||||
x2 = coords2[2 * (array[j] - length1)];
|
||||
y2 = coords2[2 * (array[j] - length1) + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containsPoint (float[] point) {
|
||||
IntersectPoint ipoint;
|
||||
for (Iterator<IntersectPoint> i = isectPoints.iterator(); i.hasNext();) {
|
||||
ipoint = i.next();
|
||||
if (ipoint.getX() == point[0] && ipoint.getY() == point[1]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int compare (float x1, float y1, float x2, float y2) {
|
||||
if ((x1 < x2) || (x1 == x2 && y1 < y2)) {
|
||||
return 1;
|
||||
} else if (x1 == x2 && y1 == y2) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static final class Edge
|
||||
{
|
||||
final int begIndex;
|
||||
final int endIndex;
|
||||
final int areaNumber;
|
||||
|
||||
Edge (int begIndex, int endIndex, int areaNumber) {
|
||||
this.begIndex = begIndex;
|
||||
this.endIndex = endIndex;
|
||||
this.areaNumber = areaNumber;
|
||||
}
|
||||
|
||||
boolean reverseCompare (int begIndex, int endIndex) {
|
||||
return this.begIndex == endIndex && this.endIndex == begIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
//
|
||||
// Pythagoras - a collection of geometry classes
|
||||
// http://github.com/samskivert/pythagoras
|
||||
|
||||
package pythagoras.f;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* An internal class used to compute crossings.
|
||||
*/
|
||||
class CurveCrossingHelper
|
||||
{
|
||||
private float[][] coords;
|
||||
private int[][] rules;
|
||||
private int[] sizes;
|
||||
private int[] rulesSizes;
|
||||
private int[][] offsets;
|
||||
private List<IntersectPoint> isectPoints = new ArrayList<IntersectPoint>();
|
||||
|
||||
public CurveCrossingHelper (float[][] coords, int[] sizes,
|
||||
int[][] rules, int[] rulesSizes, int[][] offsets) {
|
||||
this.coords = coords;
|
||||
this.rules = rules;
|
||||
this.sizes = sizes;
|
||||
this.rulesSizes = rulesSizes;
|
||||
this.offsets = offsets;
|
||||
}
|
||||
|
||||
public IntersectPoint[] findCrossing () {
|
||||
float[] edge1 = new float[8];
|
||||
float[] edge2 = new float[8];
|
||||
float[] points = new float[6];
|
||||
float[] params = new float[6];
|
||||
float[] mp1 = new float[2];
|
||||
float[] cp1 = new float[2];
|
||||
float[] mp2 = new float[2];
|
||||
float[] cp2 = new float[2];
|
||||
int rule1, rule2, endIndex1, endIndex2;
|
||||
int ipCount = 0;
|
||||
|
||||
for (int i = 0; i < rulesSizes[0]; i++) {
|
||||
rule1 = rules[0][i];
|
||||
endIndex1 = getCurrentEdge(0, i, edge1, mp1, cp1);
|
||||
for (int j = 0; j < rulesSizes[1]; j++) {
|
||||
ipCount = 0;
|
||||
rule2 = rules[1][j];
|
||||
endIndex2 = getCurrentEdge(1, j, edge2, mp2, cp2);
|
||||
if (((rule1 == PathIterator.SEG_LINETO) || (rule1 == PathIterator.SEG_CLOSE)) &&
|
||||
((rule2 == PathIterator.SEG_LINETO) || (rule2 == PathIterator.SEG_CLOSE))) {
|
||||
ipCount = GeometryUtil.intersectLinesWithParams(
|
||||
edge1[0], edge1[1], edge1[2], edge1[3],
|
||||
edge2[0], edge2[1], edge2[2], edge2[3], params);
|
||||
|
||||
if (ipCount != 0) {
|
||||
points[0] = GeometryUtil.line(params[0], edge1[0], edge1[2]);
|
||||
points[1] = GeometryUtil.line(params[0], edge1[1], edge1[3]);
|
||||
}
|
||||
|
||||
} else if (((rule1 == PathIterator.SEG_LINETO) ||
|
||||
(rule1 == PathIterator.SEG_CLOSE)) &&
|
||||
(rule2 == PathIterator.SEG_QUADTO)) {
|
||||
ipCount = GeometryUtil.intersectLineAndQuad(
|
||||
edge1[0], edge1[1], edge1[2], edge1[3],
|
||||
edge2[0], edge2[1], edge2[2], edge2[3], edge2[4], edge2[5], params);
|
||||
for (int k = 0; k < ipCount; k++) {
|
||||
points[2 * k] = GeometryUtil.line(params[2 * k], edge1[0], edge1[2]);
|
||||
points[2 * k + 1] = GeometryUtil.line(params[2 * k], edge1[1], edge1[3]);
|
||||
}
|
||||
|
||||
} else if (rule1 == PathIterator.SEG_QUADTO &&
|
||||
(rule2 == PathIterator.SEG_LINETO || rule2 == PathIterator.SEG_CLOSE)) {
|
||||
ipCount = GeometryUtil.intersectLineAndQuad(
|
||||
edge2[0], edge2[1], edge2[2], edge2[3],
|
||||
edge1[0], edge1[1], edge1[2], edge1[3], edge1[4], edge1[5], params);
|
||||
for (int k = 0; k < ipCount; k++) {
|
||||
points[2 * k] = GeometryUtil.line(params[2 * k + 1], edge2[0], edge2[2]);
|
||||
points[2 * k + 1] = GeometryUtil.line(
|
||||
params[2 * k + 1], edge2[1], edge2[3]);
|
||||
}
|
||||
|
||||
} else if ((rule1 == PathIterator.SEG_CUBICTO) &&
|
||||
((rule2 == PathIterator.SEG_LINETO) ||
|
||||
(rule2 == PathIterator.SEG_CLOSE))) {
|
||||
ipCount = GeometryUtil.intersectLineAndCubic(
|
||||
edge1[0], edge1[1], edge1[2], edge1[3], edge1[4], edge1[5], edge1[6],
|
||||
edge1[7], edge2[0], edge2[1], edge2[2], edge2[3], params);
|
||||
for (int k = 0; k < ipCount; k++) {
|
||||
points[2 * k] = GeometryUtil.line(params[2 * k + 1], edge2[0], edge2[2]);
|
||||
points[2 * k + 1] = GeometryUtil.line(
|
||||
params[2 * k + 1], edge2[1], edge2[3]);
|
||||
}
|
||||
|
||||
} else if (((rule1 == PathIterator.SEG_LINETO) ||
|
||||
(rule1 == PathIterator.SEG_CLOSE)) &&
|
||||
(rule2 == PathIterator.SEG_CUBICTO)) {
|
||||
ipCount = GeometryUtil.intersectLineAndCubic(
|
||||
edge1[0], edge1[1], edge1[2], edge1[3], edge2[0], edge2[1],
|
||||
edge2[2], edge2[3], edge2[4], edge2[5], edge2[6], edge2[7], params);
|
||||
for (int k = 0; k < ipCount; k++) {
|
||||
points[2 * k] = GeometryUtil.line(params[2 * k], edge1[0], edge1[2]);
|
||||
points[2 * k + 1] = GeometryUtil.line(params[2 * k], edge1[1], edge1[3]);
|
||||
}
|
||||
|
||||
} else if ((rule1 == PathIterator.SEG_QUADTO) &&
|
||||
(rule2 == PathIterator.SEG_QUADTO)) {
|
||||
ipCount = GeometryUtil.intersectQuads(
|
||||
edge1[0], edge1[1], edge1[2], edge1[3], edge1[4], edge1[5],
|
||||
edge2[0], edge2[1], edge2[2], edge2[3], edge2[4], edge2[5], params);
|
||||
for (int k = 0; k < ipCount; k++) {
|
||||
points[2 * k] = GeometryUtil.quad(
|
||||
params[2 * k], edge1[0], edge1[2], edge1[4]);
|
||||
points[2 * k + 1] = GeometryUtil.quad(
|
||||
params[2 * k], edge1[1], edge1[3], edge1[5]);
|
||||
}
|
||||
|
||||
} else if ((rule1 == PathIterator.SEG_QUADTO) &&
|
||||
(rule2 == PathIterator.SEG_CUBICTO)) {
|
||||
ipCount = GeometryUtil.intersectQuadAndCubic(
|
||||
edge1[0], edge1[1], edge1[2], edge1[3], edge1[4], edge1[5],
|
||||
edge2[0], edge2[1], edge2[2], edge2[3], edge2[4], edge2[5],
|
||||
edge2[6], edge2[7], params);
|
||||
for (int k = 0; k < ipCount; k++) {
|
||||
points[2 * k] = GeometryUtil.quad(
|
||||
params[2 * k], edge1[0], edge1[2], edge1[4]);
|
||||
points[2 * k + 1] = GeometryUtil.quad(
|
||||
params[2 * k], edge1[1], edge1[3], edge1[5]);
|
||||
}
|
||||
|
||||
} else if ((rule1 == PathIterator.SEG_CUBICTO) &&
|
||||
(rule2 == PathIterator.SEG_QUADTO)) {
|
||||
ipCount = GeometryUtil.intersectQuadAndCubic(
|
||||
edge2[0], edge2[1], edge2[2], edge2[3], edge2[4], edge2[5],
|
||||
edge1[0], edge1[1], edge1[2], edge1[3], edge1[4], edge1[5],
|
||||
edge2[6], edge2[7], params);
|
||||
for (int k = 0; k < ipCount; k++) {
|
||||
points[2 * k] = GeometryUtil.quad(
|
||||
params[2 * k + 1], edge2[0], edge2[2], edge2[4]);
|
||||
points[2 * k + 1] = GeometryUtil.quad(
|
||||
params[2 * k + 1], edge2[1], edge2[3], edge2[5]);
|
||||
}
|
||||
|
||||
} else if ((rule1 == PathIterator.SEG_CUBICTO) &&
|
||||
(rule2 == PathIterator.SEG_CUBICTO)) {
|
||||
ipCount = GeometryUtil.intersectCubics(
|
||||
edge1[0], edge1[1], edge1[2], edge1[3], edge1[4], edge1[5], edge1[6],
|
||||
edge1[7], edge2[0], edge2[1], edge2[2], edge2[3], edge2[4], edge2[5],
|
||||
edge2[6], edge2[7], params);
|
||||
for (int k = 0; k < ipCount; k++) {
|
||||
points[2 * k] = GeometryUtil.cubic(
|
||||
params[2 * k], edge1[0], edge1[2], edge1[4], edge1[6]);
|
||||
points[2 * k + 1] = GeometryUtil.cubic(
|
||||
params[2 * k], edge1[1], edge1[3], edge1[5], edge1[7]);
|
||||
}
|
||||
}
|
||||
|
||||
endIndex1 = i;
|
||||
endIndex2 = j;
|
||||
int begIndex1 = i - 1;
|
||||
int begIndex2 = j - 1;
|
||||
|
||||
for (int k = 0; k < ipCount; k++) {
|
||||
IntersectPoint ip = null;
|
||||
if (!containsPoint(points[2 * k], points[2 * k + 1])) {
|
||||
for (Iterator<IntersectPoint> iter = isectPoints.iterator();
|
||||
iter.hasNext();) {
|
||||
ip = iter.next();
|
||||
if ((begIndex1 == ip.getBegIndex(true)) &&
|
||||
(endIndex1 == ip.getEndIndex(true))) {
|
||||
if (ip.getParam(true) > params[2 * k]) {
|
||||
endIndex1 = -(isectPoints.indexOf(ip) + 1);
|
||||
ip.setBegIndex1(-(isectPoints.size() + 1));
|
||||
} else {
|
||||
begIndex1 = -(isectPoints.indexOf(ip) + 1);
|
||||
ip.setEndIndex1(-(isectPoints.size() + 1));
|
||||
}
|
||||
}
|
||||
|
||||
if ((begIndex2 == ip.getBegIndex(false)) &&
|
||||
(endIndex2 == ip.getEndIndex(false))) {
|
||||
if (ip.getParam(false) > params[2 * k + 1]) {
|
||||
endIndex2 = -(isectPoints.indexOf(ip) + 1);
|
||||
ip.setBegIndex2(-(isectPoints.size() + 1));
|
||||
} else {
|
||||
begIndex2 = -(isectPoints.indexOf(ip) + 1);
|
||||
ip.setEndIndex2(-(isectPoints.size() + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rule1 == PathIterator.SEG_CLOSE) {
|
||||
rule1 = PathIterator.SEG_LINETO;
|
||||
}
|
||||
|
||||
if (rule2 == PathIterator.SEG_CLOSE) {
|
||||
rule2 = PathIterator.SEG_LINETO;
|
||||
}
|
||||
|
||||
isectPoints.add(new IntersectPoint(
|
||||
begIndex1, endIndex1, rule1, i, begIndex2, endIndex2,
|
||||
rule2, j, points[2 * k], points[2 * k + 1],
|
||||
params[2 * k], params[2 * k + 1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return isectPoints.toArray(new IntersectPoint[isectPoints.size()]);
|
||||
}
|
||||
|
||||
private int getCurrentEdge (int areaIndex, int index, float[] c, float[] mp, float[] cp) {
|
||||
int endIndex = 0;
|
||||
|
||||
switch (rules[areaIndex][index]) {
|
||||
case PathIterator.SEG_MOVETO:
|
||||
cp[0] = mp[0] = coords[areaIndex][offsets[areaIndex][index]];
|
||||
cp[1] = mp[1] = coords[areaIndex][offsets[areaIndex][index] + 1];
|
||||
break;
|
||||
case PathIterator.SEG_LINETO:
|
||||
c[0] = cp[0];
|
||||
c[1] = cp[1];
|
||||
cp[0] = c[2] = coords[areaIndex][offsets[areaIndex][index]];
|
||||
cp[1] = c[3] = coords[areaIndex][offsets[areaIndex][index] + 1];
|
||||
endIndex = 0;
|
||||
break;
|
||||
case PathIterator.SEG_QUADTO:
|
||||
c[0] = cp[0];
|
||||
c[1] = cp[1];
|
||||
c[2] = coords[areaIndex][offsets[areaIndex][index]];
|
||||
c[3] = coords[areaIndex][offsets[areaIndex][index] + 1];
|
||||
cp[0] = c[4] = coords[areaIndex][offsets[areaIndex][index] + 2];
|
||||
cp[1] = c[5] = coords[areaIndex][offsets[areaIndex][index] + 3];
|
||||
endIndex = 2;
|
||||
break;
|
||||
case PathIterator.SEG_CUBICTO:
|
||||
c[0] = cp[0];
|
||||
c[1] = cp[1];
|
||||
c[2] = coords[areaIndex][offsets[areaIndex][index]];
|
||||
c[3] = coords[areaIndex][offsets[areaIndex][index] + 1];
|
||||
c[4] = coords[areaIndex][offsets[areaIndex][index] + 2];
|
||||
c[5] = coords[areaIndex][offsets[areaIndex][index] + 3];
|
||||
cp[0] = c[6] = coords[areaIndex][offsets[areaIndex][index] + 4];
|
||||
cp[1] = c[7] = coords[areaIndex][offsets[areaIndex][index] + 5];
|
||||
endIndex = 4;
|
||||
break;
|
||||
case PathIterator.SEG_CLOSE:
|
||||
c[0] = cp[0];
|
||||
c[1] = cp[1];
|
||||
cp[0] = c[2] = mp[0];
|
||||
cp[1] = c[3] = mp[1];
|
||||
if (offsets[areaIndex][index] >= sizes[areaIndex]) {
|
||||
endIndex = -sizes[areaIndex];
|
||||
} else {
|
||||
endIndex = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return offsets[areaIndex][index] + endIndex;
|
||||
}
|
||||
|
||||
private boolean containsPoint (float x, float y) {
|
||||
IntersectPoint ipoint;
|
||||
for (Iterator<IntersectPoint> i = isectPoints.iterator(); i.hasNext();) {
|
||||
ipoint = i.next();
|
||||
if ((Math.abs(ipoint.getX() - x) < Math.pow(10, -6)) &&
|
||||
(Math.abs(ipoint.getY() - y) < Math.pow(10, -6))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,481 @@
|
||||
//
|
||||
// Pythagoras - a collection of geometry classes
|
||||
// http://github.com/samskivert/pythagoras
|
||||
|
||||
package pythagoras.f;
|
||||
|
||||
/**
|
||||
* Various geometry utility methods.
|
||||
*/
|
||||
public class GeometryUtil
|
||||
{
|
||||
public static final float EPSILON = (float)Math.pow(10, -14);
|
||||
|
||||
public static int intersectLinesWithParams (float x1, float y1, float x2, float y2,
|
||||
float x3, float y3, float x4, float y4,
|
||||
float[] params) {
|
||||
float dx = x4 - x3;
|
||||
float dy = y4 - y3;
|
||||
float d = dx * (y2 - y1) - dy * (x2 - x1);
|
||||
// float comparison
|
||||
if (Math.abs(d) < EPSILON) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
params[0] = (-dx * (y1 - y3) + dy * (x1 - x3)) / d;
|
||||
|
||||
if (dx != 0) {
|
||||
params[1] = (line(params[0], x1, x2) - x3) / dx;
|
||||
} else if (dy != 0) {
|
||||
params[1] = (line(params[0], y1, y2) - y3) / dy;
|
||||
} else {
|
||||
params[1] = 0f;
|
||||
}
|
||||
|
||||
if (params[0] >= 0 && params[0] <= 1 && params[1] >= 0 && params[1] <= 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether line (x1, y1) - (x2, y2) and line (x3, y3) - (x4, y4) intersect. If lines
|
||||
* intersect then the result parameters are saved to point array. The size of {@code point}
|
||||
* must be at least 2.
|
||||
*
|
||||
* @return 1 if two lines intersect in the defined interval, otherwise 0.
|
||||
*/
|
||||
public static int intersectLines (float x1, float y1, float x2, float y2, float x3, float y3,
|
||||
float x4, float y4, float[] point) {
|
||||
float A1 = -(y2 - y1);
|
||||
float B1 = (x2 - x1);
|
||||
float C1 = x1 * y2 - x2 * y1;
|
||||
float A2 = -(y4 - y3);
|
||||
float B2 = (x4 - x3);
|
||||
float C2 = x3 * y4 - x4 * y3;
|
||||
float coefParallel = A1 * B2 - A2 * B1;
|
||||
// float comparison
|
||||
if (x3 == x4 && y3 == y4 && (A1 * x3 + B1 * y3 + C1 == 0) && (x3 >= Math.min(x1, x2)) &&
|
||||
(x3 <= Math.max(x1, x2)) && (y3 >= Math.min(y1, y2)) && (y3 <= Math.max(y1, y2))) {
|
||||
return 1;
|
||||
}
|
||||
if (Math.abs(coefParallel) < EPSILON) {
|
||||
return 0;
|
||||
}
|
||||
point[0] = (B1 * C2 - B2 * C1) / coefParallel;
|
||||
point[1] = (A2 * C1 - A1 * C2) / coefParallel;
|
||||
if (point[0] >= Math.min(x1, x2) && point[0] >= Math.min(x3, x4) &&
|
||||
point[0] <= Math.max(x1, x2) && point[0] <= Math.max(x3, x4) &&
|
||||
point[1] >= Math.min(y1, y2) && point[1] >= Math.min(y3, y4) &&
|
||||
point[1] <= Math.max(y1, y2) && point[1] <= Math.max(y3, y4)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether there is intersection of the line (x1, y1) - (x2, y2) and the quad curve
|
||||
* (qx1, qy1) - (qx2, qy2) - (qx3, qy3). The parameters of the intersection area saved to
|
||||
* {@code params}. Therefore {@code params} must be of length at least 4.
|
||||
*
|
||||
* @return the number of roots that lie in the defined interval.
|
||||
*/
|
||||
public static int intersectLineAndQuad (float x1, float y1, float x2, float y2,
|
||||
float qx1, float qy1, float qx2, float qy2,
|
||||
float qx3, float qy3, float[] params) {
|
||||
float[] eqn = new float[3];
|
||||
float[] t = new float[2];
|
||||
float[] s = new float[2];
|
||||
float dy = y2 - y1;
|
||||
float dx = x2 - x1;
|
||||
int quantity = 0;
|
||||
int count = 0;
|
||||
|
||||
eqn[0] = dy * (qx1 - x1) - dx * (qy1 - y1);
|
||||
eqn[1] = 2 * dy * (qx2 - qx1) - 2 * dx * (qy2 - qy1);
|
||||
eqn[2] = dy * (qx1 - 2 * qx2 + qx3) - dx * (qy1 - 2 * qy2 + qy3);
|
||||
|
||||
if ((count = Crossing.solveQuad(eqn, t)) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (dx != 0) {
|
||||
s[i] = (quad(t[i], qx1, qx2, qx3) - x1) / dx;
|
||||
} else if (dy != 0) {
|
||||
s[i] = (quad(t[i], qy1, qy2, qy3) - y1) / dy;
|
||||
} else {
|
||||
s[i] = 0f;
|
||||
}
|
||||
if (t[i] >= 0 && t[i] <= 1 && s[i] >= 0 && s[i] <= 1) {
|
||||
params[2 * quantity] = t[i];
|
||||
params[2 * quantity + 1] = s[i];
|
||||
++quantity;
|
||||
}
|
||||
}
|
||||
|
||||
return quantity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the line (x1, y1) - (x2, y2) and the cubic curve (cx1, cy1) - (cx2, cy2) -
|
||||
* (cx3, cy3) - (cx4, cy4) intersect. The points of intersection are saved to {@code points}.
|
||||
* Therefore {@code points} must be of length at least 6.
|
||||
*
|
||||
* @return the numbers of roots that lie in the defined interval.
|
||||
*/
|
||||
public static int intersectLineAndCubic (float x1, float y1, float x2, float y2,
|
||||
float cx1, float cy1, float cx2, float cy2,
|
||||
float cx3, float cy3, float cx4, float cy4,
|
||||
float[] params) {
|
||||
float[] eqn = new float[4];
|
||||
float[] t = new float[3];
|
||||
float[] s = new float[3];
|
||||
float dy = y2 - y1;
|
||||
float dx = x2 - x1;
|
||||
int quantity = 0;
|
||||
int count = 0;
|
||||
|
||||
eqn[0] = (cy1 - y1) * dx + (x1 - cx1) * dy;
|
||||
eqn[1] = -3 * (cy1 - cy2) * dx + 3 * (cx1 - cx2) * dy;
|
||||
eqn[2] = (3 * cy1 - 6 * cy2 + 3 * cy3) * dx - (3 * cx1 - 6 * cx2 + 3 * cx3) * dy;
|
||||
eqn[3] = (-3 * cy1 + 3 * cy2 - 3 * cy3 + cy4) * dx +
|
||||
(3 * cx1 - 3 * cx2 + 3 * cx3 - cx4) * dy;
|
||||
|
||||
if ((count = Crossing.solveCubic(eqn, t)) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (dx != 0) {
|
||||
s[i] = (cubic(t[i], cx1, cx2, cx3, cx4) - x1) / dx;
|
||||
} else if (dy != 0) {
|
||||
s[i] = (cubic(t[i], cy1, cy2, cy3, cy4) - y1) / dy;
|
||||
} else {
|
||||
s[i] = 0f;
|
||||
}
|
||||
if (t[i] >= 0 && t[i] <= 1 && s[i] >= 0 && s[i] <= 1) {
|
||||
params[2 * quantity] = t[i];
|
||||
params[2 * quantity + 1] = s[i];
|
||||
++quantity;
|
||||
}
|
||||
}
|
||||
|
||||
return quantity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether two quads (x1, y1) - (x2, y2) - (x3, y3) and (qx1, qy1) - (qx2, qy2) - (qx3,
|
||||
* qy3) intersect. The result is saved to {@code params}. Thus {@code params} must be of length
|
||||
* at least 4.
|
||||
*
|
||||
* @return the number of roots that lie in the interval.
|
||||
*/
|
||||
public static int intersectQuads (float x1, float y1, float x2, float y2, float x3, float y3,
|
||||
float qx1, float qy1, float qx2, float qy2, float qx3,
|
||||
float qy3, float[] params) {
|
||||
float[] initParams = new float[2];
|
||||
float[] xCoefs1 = new float[3];
|
||||
float[] yCoefs1 = new float[3];
|
||||
float[] xCoefs2 = new float[3];
|
||||
float[] yCoefs2 = new float[3];
|
||||
int quantity = 0;
|
||||
|
||||
xCoefs1[0] = x1 - 2 * x2 + x3;
|
||||
xCoefs1[1] = -2 * x1 + 2 * x2;
|
||||
xCoefs1[2] = x1;
|
||||
|
||||
yCoefs1[0] = y1 - 2 * y2 + y3;
|
||||
yCoefs1[1] = -2 * y1 + 2 * y2;
|
||||
yCoefs1[2] = y1;
|
||||
|
||||
xCoefs2[0] = qx1 - 2 * qx2 + qx3;
|
||||
xCoefs2[1] = -2 * qx1 + 2 * qx2;
|
||||
xCoefs2[2] = qx1;
|
||||
|
||||
yCoefs2[0] = qy1 - 2 * qy2 + qy3;
|
||||
yCoefs2[1] = -2 * qy1 + 2 * qy2;
|
||||
yCoefs2[2] = qy1;
|
||||
|
||||
// initialize params[0] and params[1]
|
||||
params[0] = params[1] = 0.25f;
|
||||
quadNewton(xCoefs1, yCoefs1, xCoefs2, yCoefs2, initParams);
|
||||
if (initParams[0] <= 1 && initParams[0] >= 0 && initParams[1] >= 0 && initParams[1] <= 1) {
|
||||
params[2 * quantity] = initParams[0];
|
||||
params[2 * quantity + 1] = initParams[1];
|
||||
++quantity;
|
||||
}
|
||||
// initialize params
|
||||
params[0] = params[1] = 0.75f;
|
||||
quadNewton(xCoefs1, yCoefs1, xCoefs2, yCoefs2, params);
|
||||
if (initParams[0] <= 1 && initParams[0] >= 0 && initParams[1] >= 0 && initParams[1] <= 1) {
|
||||
params[2 * quantity] = initParams[0];
|
||||
params[2 * quantity + 1] = initParams[1];
|
||||
++quantity;
|
||||
}
|
||||
|
||||
return quantity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the quad (x1, y1) - (x2, y2) - (x3, y3) and the cubic (cx1, cy1) - (cx2, cy2)
|
||||
* - (cx3, cy3) - (cx4, cy4) curves intersect. The points of the intersection are saved to
|
||||
* {@code params}. Thus {@code params} must be of length at least 6.
|
||||
*
|
||||
* @return the number of intersection points that lie in the interval.
|
||||
*/
|
||||
public static int intersectQuadAndCubic (float qx1, float qy1, float qx2, float qy2,
|
||||
float qx3, float qy3, float cx1, float cy1,
|
||||
float cx2, float cy2, float cx3, float cy3,
|
||||
float cx4, float cy4, float[] params) {
|
||||
int quantity = 0;
|
||||
float[] initParams = new float[3];
|
||||
float[] xCoefs1 = new float[3];
|
||||
float[] yCoefs1 = new float[3];
|
||||
float[] xCoefs2 = new float[4];
|
||||
float[] yCoefs2 = new float[4];
|
||||
xCoefs1[0] = qx1 - 2 * qx2 + qx3;
|
||||
xCoefs1[1] = 2 * qx2 - 2 * qx1;
|
||||
xCoefs1[2] = qx1;
|
||||
|
||||
yCoefs1[0] = qy1 - 2 * qy2 + qy3;
|
||||
yCoefs1[1] = 2 * qy2 - 2 * qy1;
|
||||
yCoefs1[2] = qy1;
|
||||
|
||||
xCoefs2[0] = -cx1 + 3 * cx2 - 3 * cx3 + cx4;
|
||||
xCoefs2[1] = 3 * cx1 - 6 * cx2 + 3 * cx3;
|
||||
xCoefs2[2] = -3 * cx1 + 3 * cx2;
|
||||
xCoefs2[3] = cx1;
|
||||
|
||||
yCoefs2[0] = -cy1 + 3 * cy2 - 3 * cy3 + cy4;
|
||||
yCoefs2[1] = 3 * cy1 - 6 * cy2 + 3 * cy3;
|
||||
yCoefs2[2] = -3 * cy1 + 3 * cy2;
|
||||
yCoefs2[3] = cy1;
|
||||
|
||||
// initialize params[0] and params[1]
|
||||
params[0] = params[1] = 0.25f;
|
||||
quadAndCubicNewton(xCoefs1, yCoefs1, xCoefs2, yCoefs2, initParams);
|
||||
if (initParams[0] <= 1 && initParams[0] >= 0 && initParams[1] >= 0 && initParams[1] <= 1) {
|
||||
params[2 * quantity] = initParams[0];
|
||||
params[2 * quantity + 1] = initParams[1];
|
||||
++quantity;
|
||||
}
|
||||
// initialize params
|
||||
params[0] = params[1] = 0.5f;
|
||||
quadAndCubicNewton(xCoefs1, yCoefs1, xCoefs2, yCoefs2, params);
|
||||
if (initParams[0] <= 1 && initParams[0] >= 0 && initParams[1] >= 0 && initParams[1] <= 1) {
|
||||
params[2 * quantity] = initParams[0];
|
||||
params[2 * quantity + 1] = initParams[1];
|
||||
++quantity;
|
||||
}
|
||||
|
||||
params[0] = params[1] = 0.75f;
|
||||
quadAndCubicNewton(xCoefs1, yCoefs1, xCoefs2, yCoefs2, params);
|
||||
if (initParams[0] <= 1 && initParams[0] >= 0 && initParams[1] >= 0 && initParams[1] <= 1) {
|
||||
params[2 * quantity] = initParams[0];
|
||||
params[2 * quantity + 1] = initParams[1];
|
||||
++quantity;
|
||||
}
|
||||
return quantity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether two cubic curves (x1, y1) - (x2, y2) - (x3, y3) - (x4, y4) and (cx1, cy1) -
|
||||
* (cx2, cy2) - (cx3, cy3) - (cx4, cy4) intersect. The result is saved to {@code params}. Thus
|
||||
* {@code params} must be of length at least 6.
|
||||
*
|
||||
* @return the number of intersection points that lie in the interval.
|
||||
*/
|
||||
public static int intersectCubics (float x1, float y1, float x2, float y2, float x3, float y3,
|
||||
float x4, float y4, float cx1, float cy1,
|
||||
float cx2, float cy2, float cx3, float cy3,
|
||||
float cx4, float cy4, float[] params) {
|
||||
int quantity = 0;
|
||||
float[] initParams = new float[3];
|
||||
float[] xCoefs1 = new float[4];
|
||||
float[] yCoefs1 = new float[4];
|
||||
float[] xCoefs2 = new float[4];
|
||||
float[] yCoefs2 = new float[4];
|
||||
xCoefs1[0] = -x1 + 3 * x2 - 3 * x3 + x4;
|
||||
xCoefs1[1] = 3 * x1 - 6 * x2 + 3 * x3;
|
||||
xCoefs1[2] = -3 * x1 + 3 * x2;
|
||||
xCoefs1[3] = x1;
|
||||
|
||||
yCoefs1[0] = -y1 + 3 * y2 - 3 * y3 + y4;
|
||||
yCoefs1[1] = 3 * y1 - 6 * y2 + 3 * y3;
|
||||
yCoefs1[2] = -3 * y1 + 3 * y2;
|
||||
yCoefs1[3] = y1;
|
||||
|
||||
xCoefs2[0] = -cx1 + 3 * cx2 - 3 * cx3 + cx4;
|
||||
xCoefs2[1] = 3 * cx1 - 6 * cx2 + 3 * cx3;
|
||||
xCoefs2[2] = -3 * cx1 + 3 * cx2;
|
||||
xCoefs2[3] = cx1;
|
||||
|
||||
yCoefs2[0] = -cy1 + 3 * cy2 - 3 * cy3 + cy4;
|
||||
yCoefs2[1] = 3 * cy1 - 6 * cy2 + 3 * cy3;
|
||||
yCoefs2[2] = -3 * cy1 + 3 * cy2;
|
||||
yCoefs2[3] = cy1;
|
||||
|
||||
// TODO
|
||||
params[0] = params[1] = 0.25f;
|
||||
cubicNewton(xCoefs1, yCoefs1, xCoefs2, yCoefs2, initParams);
|
||||
if (initParams[0] <= 1 && initParams[0] >= 0 && initParams[1] >= 0 && initParams[1] <= 1) {
|
||||
params[2 * quantity] = initParams[0];
|
||||
params[2 * quantity + 1] = initParams[1];
|
||||
++quantity;
|
||||
}
|
||||
|
||||
params[0] = params[1] = 0.5f;
|
||||
cubicNewton(xCoefs1, yCoefs1, xCoefs2, yCoefs2, params);
|
||||
if (initParams[0] <= 1 && initParams[0] >= 0 && initParams[1] >= 0 && initParams[1] <= 1) {
|
||||
params[2 * quantity] = initParams[0];
|
||||
params[2 * quantity + 1] = initParams[1];
|
||||
++quantity;
|
||||
}
|
||||
|
||||
params[0] = params[1] = 0.75f;
|
||||
cubicNewton(xCoefs1, yCoefs1, xCoefs2, yCoefs2, params);
|
||||
if (initParams[0] <= 1 && initParams[0] >= 0 && initParams[1] >= 0 && initParams[1] <= 1) {
|
||||
params[2 * quantity] = initParams[0];
|
||||
params[2 * quantity + 1] = initParams[1];
|
||||
++quantity;
|
||||
}
|
||||
return quantity;
|
||||
}
|
||||
|
||||
public static float line (float t, float x1, float x2) {
|
||||
return x1 * (1f - t) + x2 * t;
|
||||
}
|
||||
|
||||
public static float quad (float t, float x1, float x2, float x3) {
|
||||
return x1 * (1f - t) * (1f - t) + 2f * x2 * t * (1f - t) + x3 * t * t;
|
||||
}
|
||||
|
||||
public static float cubic (float t, float x1, float x2, float x3, float x4) {
|
||||
return x1 * (1f - t) * (1f - t) * (1f - t) + 3f * x2 * (1f - t) * (1f - t) * t + 3f * x3 *
|
||||
(1f - t) * t * t + x4 * t * t * t;
|
||||
}
|
||||
|
||||
// x, y - the coordinates of new vertex
|
||||
// t0 - ?
|
||||
public static void subQuad (float[] coef, float t0, boolean left) {
|
||||
if (left) {
|
||||
coef[2] = (1 - t0) * coef[0] + t0 * coef[2];
|
||||
coef[3] = (1 - t0) * coef[1] + t0 * coef[3];
|
||||
} else {
|
||||
coef[2] = (1 - t0) * coef[2] + t0 * coef[4];
|
||||
coef[3] = (1 - t0) * coef[3] + t0 * coef[5];
|
||||
}
|
||||
}
|
||||
|
||||
public static void subCubic (float[] coef, float t0, boolean left) {
|
||||
if (left) {
|
||||
coef[2] = (1 - t0) * coef[0] + t0 * coef[2];
|
||||
coef[3] = (1 - t0) * coef[1] + t0 * coef[3];
|
||||
} else {
|
||||
coef[4] = (1 - t0) * coef[4] + t0 * coef[6];
|
||||
coef[5] = (1 - t0) * coef[5] + t0 * coef[7];
|
||||
}
|
||||
}
|
||||
|
||||
private static void cubicNewton (float[] xCoefs1, float[] yCoefs1,
|
||||
float[] xCoefs2, float[] yCoefs2, float[] params) {
|
||||
float t = 0f, s = 0f;
|
||||
float t1 = params[0];
|
||||
float s1 = params[1];
|
||||
float d, dt, ds;
|
||||
|
||||
while (Math.sqrt((t - t1) * (t - t1) + (s - s1) * (s - s1)) > EPSILON) {
|
||||
d = -(3 * t * t * xCoefs1[0] + 2 * t * xCoefs1[1] + xCoefs1[2]) *
|
||||
(3 * s * s * yCoefs2[0] + 2 * s * yCoefs2[1] + yCoefs2[2]) +
|
||||
(3 * t * t * yCoefs1[0] + 2 * t * yCoefs1[1] + yCoefs1[2]) *
|
||||
(3 * s * s * xCoefs2[0] + 2 * s * xCoefs2[1] + xCoefs2[2]);
|
||||
|
||||
dt = (t * t * t * xCoefs1[0] + t * t * xCoefs1[1] + t * xCoefs1[2] + xCoefs1[3] -
|
||||
s * s * s * xCoefs2[0] - s * s * xCoefs2[1] - s * xCoefs2[2] - xCoefs2[3]) *
|
||||
(-3 * s * s * yCoefs2[0] - 2 * s * yCoefs2[1] - yCoefs2[2]) +
|
||||
(t * t * t * yCoefs1[0] + t * t * yCoefs1[1] + t * yCoefs1[2] + yCoefs1[3] -
|
||||
s * s * s * yCoefs2[0] - s * s * yCoefs2[1] - s * yCoefs2[2] - yCoefs2[3]) *
|
||||
(3 * s * s * xCoefs2[0] + 2 * s * xCoefs2[1] + xCoefs2[2]);
|
||||
|
||||
ds = (3 * t * t * xCoefs1[0] + 2 * t * xCoefs1[1] + xCoefs1[2]) *
|
||||
(t * t * t * yCoefs1[0] + t * t * yCoefs1[1] + t * yCoefs1[2] + yCoefs1[3] -
|
||||
s * s * s * yCoefs2[0] - s * s * yCoefs2[1] - s * yCoefs2[2] - yCoefs2[3]) -
|
||||
(3 * t * t * yCoefs1[0] + 2 * t * yCoefs1[1] + yCoefs1[2]) *
|
||||
(t * t * t * xCoefs1[0] + t * t * xCoefs1[1] + t * xCoefs1[2] + xCoefs1[3] -
|
||||
s * s * s * xCoefs2[0] - s * s * xCoefs2[1] - s * xCoefs2[2] - xCoefs2[3]);
|
||||
|
||||
t1 = t - dt / d;
|
||||
s1 = s - ds / d;
|
||||
}
|
||||
params[0] = t1;
|
||||
params[1] = s1;
|
||||
}
|
||||
|
||||
private static void quadAndCubicNewton (float xCoefs1[], float yCoefs1[],
|
||||
float xCoefs2[], float yCoefs2[], float[] params) {
|
||||
float t = 0f, s = 0f;
|
||||
float t1 = params[0];
|
||||
float s1 = params[1];
|
||||
float d, dt, ds;
|
||||
|
||||
while (Math.sqrt((t - t1) * (t - t1) + (s - s1) * (s - s1)) > EPSILON) {
|
||||
d = -(2 * t * xCoefs1[0] + xCoefs1[1]) *
|
||||
(3 * s * s * yCoefs2[0] + 2 * s * yCoefs2[1] + yCoefs2[2]) +
|
||||
(2 * t * yCoefs1[0] + yCoefs1[1]) *
|
||||
(3 * s * s * xCoefs2[0] + 2 * s * xCoefs2[1] + xCoefs2[2]);
|
||||
|
||||
dt = (t * t * xCoefs1[0] + t * xCoefs1[1] + xCoefs1[2] + -s * s * s * xCoefs2[0] -
|
||||
s * s * xCoefs2[1] - s * xCoefs2[2] - xCoefs2[3]) *
|
||||
(-3 * s * s * yCoefs2[0] - 2 * s * yCoefs2[1] - yCoefs2[2]) +
|
||||
(t * t * yCoefs1[0] + t * yCoefs1[1] + yCoefs1[2] - s * s * s * yCoefs2[0] -
|
||||
s * s * yCoefs2[1] - s * yCoefs2[2] - yCoefs2[3]) *
|
||||
(3 * s * s * xCoefs2[0] + 2 * s * xCoefs2[1] + xCoefs2[2]);
|
||||
|
||||
ds = (2 * t * xCoefs1[0] + xCoefs1[1]) *
|
||||
(t * t * yCoefs1[0] + t * yCoefs1[1] + yCoefs1[2] - s * s * s * yCoefs2[0] -
|
||||
s * s * yCoefs2[1] - s * yCoefs2[2] - yCoefs2[3]) -
|
||||
(2 * t * yCoefs1[0] + yCoefs1[1]) *
|
||||
(t * t * xCoefs1[0] + t * xCoefs1[1] + xCoefs1[2] - s * s * s * xCoefs2[0] -
|
||||
s * s * xCoefs2[1] - s * xCoefs2[2] - xCoefs2[3]);
|
||||
|
||||
t1 = t - dt / d;
|
||||
s1 = s - ds / d;
|
||||
}
|
||||
params[0] = t1;
|
||||
params[1] = s1;
|
||||
}
|
||||
|
||||
private static void quadNewton (float xCoefs1[], float yCoefs1[],
|
||||
float xCoefs2[], float yCoefs2[], float params[]) {
|
||||
float t = 0f, s = 0f;
|
||||
float t1 = params[0];
|
||||
float s1 = params[1];
|
||||
float d, dt, ds;
|
||||
|
||||
while (Math.sqrt((t - t1) * (t - t1) + (s - s1) * (s - s1)) > EPSILON) {
|
||||
t = t1;
|
||||
s = s1;
|
||||
d = -(2 * t * xCoefs1[0] + xCoefs1[1]) * (2 * s * yCoefs2[0] + yCoefs2[1]) +
|
||||
(2 * s * xCoefs2[0] + xCoefs2[1]) * (2 * t * yCoefs1[0] + yCoefs1[1]);
|
||||
|
||||
dt = -(t * t * xCoefs1[0] + t * xCoefs1[1] + xCoefs1[1] - s * s * xCoefs2[0] -
|
||||
s * xCoefs2[1] - xCoefs2[2]) * (2 * s * yCoefs2[0] + yCoefs2[1]) +
|
||||
(2 * s * xCoefs2[0] + xCoefs2[1]) *
|
||||
(t * t * yCoefs1[0] + t * yCoefs1[1] + yCoefs1[2] - s * s * yCoefs2[0] -
|
||||
s * yCoefs2[1] - yCoefs2[2]);
|
||||
|
||||
ds = (2 * t * xCoefs1[0] + xCoefs1[1]) *
|
||||
(t * t * yCoefs1[0] + t * yCoefs1[1] + yCoefs1[2] - s * s * yCoefs2[0] -
|
||||
s * yCoefs2[1] - yCoefs2[2]) - (2 * t * yCoefs1[0] + yCoefs1[1]) *
|
||||
(t * t * xCoefs1[0] + t * xCoefs1[1] + xCoefs1[2] - s * s * xCoefs2[0] -
|
||||
s * xCoefs2[1] - xCoefs2[2]);
|
||||
|
||||
t1 = t - dt / d;
|
||||
s1 = s - ds / d;
|
||||
}
|
||||
params[0] = t1;
|
||||
params[1] = s1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
//
|
||||
// Pythagoras - a collection of geometry classes
|
||||
// http://github.com/samskivert/pythagoras
|
||||
|
||||
package pythagoras.f;
|
||||
|
||||
/**
|
||||
* An internal helper class that represents the intersection point of two edges.
|
||||
*/
|
||||
class IntersectPoint
|
||||
{
|
||||
public IntersectPoint (int begIndex1, int endIndex1, int begIndex2, int endIndex2,
|
||||
float x, float y) {
|
||||
this.begIndex1 = begIndex1;
|
||||
this.endIndex1 = endIndex1;
|
||||
this.begIndex2 = begIndex2;
|
||||
this.endIndex2 = endIndex2;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public IntersectPoint (int begIndex1, int endIndex1, int rule1, int ruleIndex1,
|
||||
int begIndex2, int endIndex2, int rule2, int ruleIndex2,
|
||||
float x, float y, float param1, float param2) {
|
||||
this.begIndex1 = begIndex1;
|
||||
this.endIndex1 = endIndex1;
|
||||
this.rule1 = rule1;
|
||||
this.ruleIndex1 = ruleIndex1;
|
||||
this.param1 = param1;
|
||||
this.begIndex2 = begIndex2;
|
||||
this.endIndex2 = endIndex2;
|
||||
this.rule2 = rule2;
|
||||
this.ruleIndex2 = ruleIndex2;
|
||||
this.param2 = param2;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public int getBegIndex (boolean isCurrentArea) {
|
||||
return isCurrentArea ? begIndex1 : begIndex2;
|
||||
}
|
||||
|
||||
public int getEndIndex (boolean isCurrentArea) {
|
||||
return isCurrentArea ? endIndex1 : endIndex2;
|
||||
}
|
||||
|
||||
public int getRuleIndex (boolean isCurrentArea) {
|
||||
return isCurrentArea ? ruleIndex1 : ruleIndex2;
|
||||
}
|
||||
|
||||
public float getParam (boolean isCurrentArea) {
|
||||
return isCurrentArea ? param1 : param2;
|
||||
}
|
||||
|
||||
public int getRule (boolean isCurrentArea) {
|
||||
return isCurrentArea ? rule1 : rule2;
|
||||
}
|
||||
|
||||
public float getX () {
|
||||
return x;
|
||||
}
|
||||
|
||||
public float getY () {
|
||||
return y;
|
||||
}
|
||||
|
||||
public void setBegIndex1 (int begIndex) {
|
||||
this.begIndex1 = begIndex;
|
||||
}
|
||||
|
||||
public void setEndIndex1 (int endIndex) {
|
||||
this.endIndex1 = endIndex;
|
||||
}
|
||||
|
||||
public void setBegIndex2 (int begIndex) {
|
||||
this.begIndex2 = begIndex;
|
||||
}
|
||||
|
||||
public void setEndIndex2 (int endIndex) {
|
||||
this.endIndex2 = endIndex;
|
||||
}
|
||||
|
||||
// the edge begin number of first line
|
||||
private int begIndex1;
|
||||
// the edge end number of first line
|
||||
private int endIndex1;
|
||||
// the edge rule of first figure
|
||||
private int rule1;
|
||||
// the index of the first figure rules array
|
||||
private int ruleIndex1;
|
||||
// the parameter value of edge1
|
||||
private float param1;
|
||||
// the edge begin number of second line
|
||||
private int begIndex2;
|
||||
// the edge end number of second line
|
||||
private int endIndex2;
|
||||
// the edge rule of second figure
|
||||
private int rule2;
|
||||
// the index of the second figure rules array
|
||||
private int ruleIndex2;
|
||||
// the absciss coordinate of the point
|
||||
private final float x;
|
||||
// the ordinate coordinate of the point
|
||||
private final float y;
|
||||
// the parameter value of edge2
|
||||
private float param2;
|
||||
}
|
||||
Reference in New Issue
Block a user