All Downloads are FREE. Search and download functionalities are using the official Maven repository.

pythagoras.f.CrossingHelper Maven / Gradle / Ivy

//
// 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 isectPoints = new ArrayList();

    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 edges = new ArrayList();
        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 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 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 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 i = isectPoints.iterator(); i.hasNext();) {
                    ip = i.next();
                    if ((initBegin == ip.begIndex(true)) && (initEnd == ip.endIndex(true))) {
                        if (compare(ip.x(), ip.y(), 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.begIndex(false)) && (addEnd == ip.endIndex(false))) {
                        if (compare(ip.x(), ip.y(), 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 i = isectPoints.iterator(); i.hasNext();) {
            ipoint = i.next();
            if (ipoint.x() == point[0] && ipoint.y() == 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;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy