001/**
002 * Return intersections between an arbitrary (often OBLique) plane and various geometric
003 * objects.
004 *
005 * @method GeomList OBL(GeomList geom, GeomPlane plane, Parameter tol)
006 * @method PointString OBL(Curve crv, GeomPlane plane, double eps)
007 * @method GeomList OBL(Surface srf, GeomPlane plane, Parameter tol)
008 */
009package geomss.app.GeomSSCommands.utils;
010
011import bsh.*;
012import geomss.geom.*;
013import jahuwaldt.js.param.Parameter;
014import java.util.Collections;
015import java.util.List;
016import javax.measure.quantity.Dimensionless;
017import javolution.context.ConcurrentContext;
018
019public class OBL {
020
021    public static String usage() {
022        return "usage: OBL(geom, plane, tol);";
023    }
024
025    /**
026     * Return the intersection between an arbitrary plane and the specified list of
027     * geometry. Only intersections with curves and surfaces are considered. Intersections
028     * with curves result in PointString objects being added to the output GeomList that
029     * contain any intersection SubrangePoint objects. Intersections with surfaces result
030     * in GeomList objects being added to the output GeomList that contain any
031     * intersection SubrangeCurves on the surface.
032     *
033     * @param geom  The list of geometry to be intersected with the plane.
034     * @param plane The arbitrary plane to use for intersection.
035     * @param tol   The desired tolerance for the intersection.
036     * @return The list of all the intersections between the specified plane and the input
037     *         list of geometry.
038     * @throws bsh.EvalError
039     */
040    public static GeomList invoke(Interpreter env, CallStack callstack,
041            GeometryList geom, GeomPlane plane, Parameter tol) throws EvalError {
042
043        if (geom instanceof LoftedSurface) {
044            //  Do the intersection directly.
045            GeomList output = ((LoftedSurface)geom).intersect(plane, tol);
046
047            return output;
048        }
049        
050        GeomList output = GeomList.newInstance();
051        List syncLst = Collections.synchronizedList(output);
052        
053        //  Use a ConcurrentContext to run each intersection in parallel.
054        ConcurrentContext.enter();
055        try {
056            int size = geom.size();
057            for (int i=0; i < size; ++i) {
058                GeomElement elem = (GeomElement)geom.get(i);
059                
060                //  Run each intersection concurrently on its own processor.
061                Runnable runner = new InternsectionRunner(elem, plane, tol, syncLst);
062                ConcurrentContext.execute(runner);
063                
064            }
065        } finally {
066            ConcurrentContext.exit();
067        }
068
069        return output;
070    }
071
072    /**
073     * Return the intersection between an arbitrary plane and the specified curve. A
074     * PointString object is returned that contains any intersection SubrangePoint
075     * objects.
076     *
077     * @param crv   The curve to be intersected with the plane.
078     * @param plane The arbitrary plane to use for intersection.
079     * @param eps   The desired fractional tolerance in parameter space for the
080     *              intersection.
081     * @return The list of all the intersections points between the specified plane and
082     *         the input curve.
083     * @throws bsh.EvalError
084     */
085    public static PointString invoke(Interpreter env, CallStack callstack,
086            Curve crv, GeomPlane plane, double eps) throws EvalError {
087
088        //  Do the intersection.
089        PointString output = crv.intersect(plane, eps);
090
091        return output;
092    }
093
094    /**
095     * Return the intersection between an arbitrary plane and the specified surface. A
096     * GeomList object is returned that contains any intersection SubrangeCurve objects.
097     *
098     * @param srf   The surface to be intersected with the plane.
099     * @param plane The arbitrary plane to use for intersection.
100     * @param tol   The desired tolerance for the intersection.
101     * @return The list of all the intersections curves between the specified plane and
102     *         the input surface.
103     */
104    public static GeomList invoke(Interpreter env, CallStack callstack,
105            Surface srf, GeomPlane plane, Parameter tol) throws EvalError {
106        //  Do the intersection.
107        GeomList output = srf.intersect(plane, tol);
108
109        return output;
110    }
111    
112    /**
113     * A Runnable for use with computing intersections in a ConcurrentContext.
114     */
115    private static class InternsectionRunner implements Runnable {
116
117        private final GeomElement elem;
118        private final GeomPlane plane;
119        private final Parameter tol;
120        private final List output;
121
122        public InternsectionRunner(GeomElement elem, GeomPlane plane, Parameter tol, List outputLst) {
123            this.elem = elem;
124            this.plane = plane;
125            this.tol = tol;
126            this.output = outputLst;
127        }
128
129        @Override
130        public void run() {
131            if (elem instanceof Curve) {
132                Curve crv = (Curve)elem;
133                Parameter len = crv.getArcLength(1e-3);
134                double eps = 1e-9;
135                if (!len.isLessThan(tol))
136                    eps = tol.divide(len).doubleValue(Dimensionless.UNIT);
137                PointString ints = crv.intersect(plane, eps);
138                if (ints != null && ints.size() > 0)
139                    output.addAll(ints);
140
141            } else if (elem instanceof Surface) {
142                Surface srf = (Surface)elem;
143                GeomList ints = srf.intersect(plane, tol);
144                if (ints != null && ints.size() > 0)
145                    output.addAll(ints);
146            }
147        }
148    }
149
150}