public Split split()

in commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/AbstractConvexPolygon3D.java [296:382]


    public Split<PlaneConvexSubset> split(final Hyperplane<Vector3D> splitter) {
        final Plane splitterPlane = (Plane) splitter;
        final List<Vector3D> vertices = getVertices();

        final int size = vertices.size();

        int minusPlusTransitionIdx = -1;
        Vector3D minusPlusInsertVertex = null;

        int plusMinusTransitionIdx = -1;
        Vector3D plusMinusInsertVertex = null;

        int transitionCount = 0;

        Vector3D curVertex;
        HyperplaneLocation curLoc;

        int lastSideIdx = -1;
        Vector3D lastSideVertex = null;
        HyperplaneLocation lastSideLoc = null;

        int lastBoundaryIdx = -1;

        for (int i = 0; i <= size || transitionCount == 1; ++i) {

            curVertex = vertices.get(i % size);
            curLoc = splitter.classify(curVertex);

            if (lastSideLoc == HyperplaneLocation.MINUS && curLoc == HyperplaneLocation.PLUS) {
                // transitioned from minus side to plus side
                minusPlusTransitionIdx = Math.max(lastSideIdx, lastBoundaryIdx);
                ++transitionCount;

                if (lastBoundaryIdx < 0) {
                    // no shared boundary point; compute a new vertex
                    minusPlusInsertVertex = splitterPlane.intersection(
                            Lines3D.fromPoints(lastSideVertex, curVertex, splitterPlane.getPrecision()));
                }
            } else if (lastSideLoc == HyperplaneLocation.PLUS && curLoc == HyperplaneLocation.MINUS) {
                // transitioned from plus side to minus side
                plusMinusTransitionIdx = Math.max(lastSideIdx, lastBoundaryIdx);
                ++transitionCount;

                if (lastBoundaryIdx < 0) {
                    // no shared boundary point; compute a new vertex
                    plusMinusInsertVertex = splitterPlane.intersection(
                            Lines3D.fromPoints(lastSideVertex, curVertex, splitterPlane.getPrecision()));
                }
            }

            if (curLoc == HyperplaneLocation.ON) {
                lastBoundaryIdx = i;
            } else {
                lastBoundaryIdx = -1;

                lastSideIdx = i;
                lastSideVertex = curVertex;
                lastSideLoc = curLoc;
            }
        }

        if (minusPlusTransitionIdx > -1 && plusMinusTransitionIdx > -1) {
            // we've split; compute the vertex list for each side
            final List<Vector3D> minusVertices =  buildPolygonSplitVertexList(
                    plusMinusTransitionIdx, plusMinusInsertVertex,
                    minusPlusTransitionIdx, minusPlusInsertVertex, vertices);
            final List<Vector3D> plusVertices = buildPolygonSplitVertexList(
                    minusPlusTransitionIdx, minusPlusInsertVertex,
                    plusMinusTransitionIdx, plusMinusInsertVertex, vertices);

            // delegate back to the Planes factory methods to determine the concrete types
            // for each side of the split
            return new Split<>(
                    Planes.fromConvexPlanarVertices(plane, minusVertices),
                    Planes.fromConvexPlanarVertices(plane, plusVertices));

        } else if (lastSideLoc == HyperplaneLocation.PLUS) {
            // we lie entirely on the plus side of the splitter
            return new Split<>(null, this);
        } else if (lastSideLoc == HyperplaneLocation.MINUS) {
            // we lie entirely on the minus side of the splitter
            return new Split<>(this, null);
        }

        // we lie entirely on the splitter
        return new Split<>(null, null);
    }