/**
 * 
 */

package math.geom2d.domain;

import java.util.ArrayList;
import java.util.Iterator;

import math.geom2d.Box2D;
import math.geom2d.Point2D;
import math.geom2d.Shape2D;
import math.geom2d.UnboundedBox2DException;
import math.geom2d.curve.ContinuousCurve2D;
import math.geom2d.curve.Curve2D;
import math.geom2d.curve.Curves2D;
import math.geom2d.curve.CurveArray2D;
import math.geom2d.curve.CurveSet2D;
import math.geom2d.polygon.Polyline2D;

/**
 * Collects some useful methods for operating on boundary curves.
 * 
 * @author dlegland
 */
public abstract class Boundaries2D {

    /**
     * Clip a curve, and return a CurveSet2D. If the curve is totally outside
     * the box, return a CurveSet2D with 0 curves inside. If the curve is
     * totally inside the box, return a CurveSet2D with only one curve, which is
     * the original curve.
     */
    public final static CurveSet2D 
    clipContinuousOrientedCurve(ContinuousOrientedCurve2D curve, Box2D box) {

    	// create result array
    	CurveArray2D result = 
        	new CurveArray2D();
    	
    	// for each clipped curve, add its pieces
        for (ContinuousCurve2D cont : Curves2D.clipContinuousCurve(curve, box))
            if (cont instanceof ContinuousOrientedCurve2D)
                result.add((ContinuousOrientedCurve2D) cont);

        return result;

        // // create array of points
        // ArrayList points = new ArrayList();
        //
        // // add the intersections with edges of the box boundary
        // for(StraightObject2D edge : box.getEdges())
        // points.addAll(curve.getIntersections(edge));
        //		
        // // convert list to point array, sorted wrt to their position on the
        // curve
        // SortedSet set = new TreeSet();
        // for(Point2D p : points)
        // set.add(new java.lang.Double(curve.getPosition(p)));
        //				
        // // Create curveset for storing the result
        // CurveSet2D res =
        // new CurveSet2D();
        //				
        // // extract first point of the curve
        // Point2D point1 = curve.getFirstPoint();
        //		
        // // case of empty curve set, for example
        // if(point1==null)
        // return res;
        //
        // // if no intersection point, the curve is totally either inside or
        // outside the box
        // if(set.size()==0){
        // if(box.contains(point1))
        // res.addCurve(curve);
        // return res;
        // }
        //		
        // double pos1, pos2;
        // Iterator iter = set.iterator();
        //		
        // double pos0=0;
        //		
        // // different behavior depending if first point lies inside the box
        // if(box.contains(point1) && !box.getBoundary().contains(point1))
        // pos0 = iter.next().doubleValue();
        //		
        //		
        // // add the portions of curve between couples of intersections
        // while(iter.hasNext()){
        // pos1 = iter.next().doubleValue();
        // if(iter.hasNext())
        // pos2 = iter.next().doubleValue();
        // else
        // pos2 = pos0;
        // res.addCurve(curve.getSubCurve(pos1, pos2));
        // }
        //		
        // return res;
    }

    /**
     * Clips a boundary and closes the result curve. Returns an instance of
     * ContourArray2D.
     */
    public final static ContourArray2D clipBoundary(
            Boundary2D boundary, Box2D box) {

    	// basic check-up
        if (!box.isBounded())
            throw new UnboundedBox2DException(box);

        // iteration variable
        ContinuousOrientedCurve2D curve;

        // The set of boundary curves. Each curve of this set is either a
        // curve of the original boundary, or a composition of a portion of
        // original boundary with a portion of the box.
		ContourArray2D res = new ContourArray2D();

        // to store result of curve clipping
        CurveSet2D clipped;

        // to store set of all clipped curves
        CurveArray2D curveSet = 
        	new CurveArray2D();

        // Iterate on contours: clip each contour with box, 
        // and add clipped curves to the array 'curveSet'
        for (Contour2D contour : boundary.continuousCurves()) {
            clipped = Boundaries2D.clipContinuousOrientedCurve(contour, box);

            for (ContinuousOrientedCurve2D clip : clipped)
                curveSet.add(clip);
        }

        // array of position on the box for first and last point of each curve
        int nc = curveSet.size();
        double[] startPositions = new double[nc];
        double[] endPositions = new double[nc];

        // Flag indicating if the curve intersects the boundary of the box
        boolean intersect = false;

        // also create array of curves
        ContinuousOrientedCurve2D[] curves = new ContinuousOrientedCurve2D[nc];

        // boundary of the box
        Curve2D boxBoundary = box.boundary();

        // compute position on the box for first and last point of each curve
        Iterator iter = curveSet.curves().iterator();

        for (int i = 0; i < nc; i++) {
            // save current curve
            curve = iter.next();
            curves[i] = curve;

            if (curve.isClosed()) {
                startPositions[i] = java.lang.Double.NaN;
                endPositions[i] = java.lang.Double.NaN;
                continue;
            }

            // compute positions of first point and last point on box boundary
            startPositions[i] = boxBoundary.position(curve.firstPoint());
            endPositions[i] = boxBoundary.position(curve.lastPoint());

            // set up the flag
            intersect = true;
        }

        // theoretical number of boundary curves. Set to the number of clipped
        // curves, but total number can be reduced if several clipped curves
        // belong to the same boundary curve.
        int nb = nc;

        // current index of curve
        int c = 0;

		// iterate while there are boundary curve to build
		while (c < nb) {
			int ind = c;
			// find the current curve (used curves are removed from array)
			while (curves[ind] == null)
				ind++;

            // current curve
            curve = curves[ind];

            // if curve is closed, we can switch to next curve
            if (curve.isClosed()) {
                // Add current boundary to the set of boundary curves
                if (curve instanceof Contour2D) {
                    res.add((Contour2D) curve);
                } else {
                    BoundaryPolyCurve2D bnd = 
                    	new BoundaryPolyCurve2D();
                    bnd.add(curve);
                    res.add(bnd);
                }
                curves[ind] = null;

                // switch to next curve
                c++;
                continue;
            }

            // create a new Boundary curve
            BoundaryPolyCurve2D boundary0 = 
            	new BoundaryPolyCurve2D();

            // add current curve to boundary curve
            boundary0.add(curve);

            // get last points (to add a line with next curve)
            Point2D p0 = curve.firstPoint();
            Point2D p1 = curve.lastPoint();

            // index of first curve, used as a stop flag
            int ind0 = ind;

            // store indices of curves, to remove them later
            ArrayList indices = new ArrayList();
            indices.add(new Integer(ind));

            // position of last point of current curve on box boundary
            ind = findNextCurveIndex(startPositions, endPositions[ind0]);

            // iterate while we don't come back to first point
            while (ind != ind0) {
                // find the curve whose first point is just after last point
                // of current curve on box boundary
                curve = curves[ind];

                // add a link between previous curve and current curve
                Point2D p0i = curve.firstPoint();
				boundary0.add(getBoundaryPortion(box, p1, p0i));

                // add to current boundary
                boundary0.add(curve);

                indices.add(new Integer(ind));

                // find index and position of next curve
                ind = findNextCurveIndex(startPositions, endPositions[ind]);

                // get last points
                p1 = curve.lastPoint();

                // decrease total number of boundary curves
                nb--;
            }

            // add a line from last point to first point
            boundary0.add(getBoundaryPortion(box, p1, p0));

            // Add current boundary to the set of boundary curves
            res.add(boundary0);

            // remove curves from array
            Iterator iter2 = indices.iterator();
            while (iter2.hasNext())
                curves[iter2.next().intValue()] = null;

            // next curve !
            c++;
        }

        // Add processing when the box boundary does not intersect the curve.
        // In this case add the boundary of the box to the resulting boundary
        // set.
        if (!intersect) {
            Point2D vertex = box.vertices().iterator().next();
            if (boundary.isInside(vertex))
                res.add(box.asRectangle().boundary().firstCurve());
        }

        // return the result
        return res;
    }

    public final static int findNextCurveIndex(double[] positions, double pos) {
        int ind = -1;
        double posMin = java.lang.Double.MAX_VALUE;
        for (int i = 0; i vertices = new ArrayList(6);

        // add the first point.
        vertices.add(p0);

		// compute index of first box boundary edge
		int ind = (ind0 + 1) % 4;

		// add all vertices segments between the 2 end points
		while (ind != ind1) {
			vertices.add(boundary.point(ind));
			ind = (ind + 1) % 4;
		}
        vertices.add(boundary.point(ind));

        // add the last line segment
        vertices.add(p1);

        return new Polyline2D(vertices);
    }
}

 

Ads help maintain this website.