package org.geogebra.common.geogebra3D.kernel3D.commands; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoPlane3D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoPolyhedron; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoQuadric3DLimited; import org.geogebra.common.geogebra3D.kernel3D.implicit3D.AlgoIntersectFunctionNVarPlane; import org.geogebra.common.geogebra3D.kernel3D.implicit3D.GeoImplicitSurface; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.Kernel; import org.geogebra.common.kernel.advanced.CmdIntersectPath; import org.geogebra.common.kernel.arithmetic.Command; import org.geogebra.common.kernel.arithmetic.Equation; import org.geogebra.common.kernel.arithmetic.ExpressionValue; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoFunctionNVar; import org.geogebra.common.kernel.geos.GeoLine; import org.geogebra.common.kernel.geos.GeoPolygon; import org.geogebra.common.kernel.kernelND.GeoLineND; import org.geogebra.common.kernel.kernelND.GeoPlaneND; import org.geogebra.common.kernel.kernelND.GeoQuadricND; import org.geogebra.common.main.MyError; /** * Processor forIntersectPath command * */ public class CmdIntersectPath3D extends CmdIntersectPath { /** * @param kernel * kernel */ public CmdIntersectPath3D(Kernel kernel) { super(kernel); } @Override public GeoElement[] process(Command c) throws MyError { int n = c.getArgumentNumber(); boolean[] ok = new boolean[n]; GeoElement[] arg; switch (n) { case 2: arg = resArgs(c); if (!arg[0].isGeoElement3D() && !arg[1].isGeoElement3D()) { return super.process(c); } // Line - Polygon(as region) in 2D/3D if ((ok[0] = (arg[0].isGeoLine())) && (ok[1] = (arg[1].isGeoPolygon()))) { GeoElement[] ret = kernelA.getManager3D().IntersectPath( c.getLabels(), (GeoLineND) arg[0], (GeoPolygon) arg[1]); return ret; } else if ((ok[0] = (arg[0].isGeoPolygon())) && (ok[1] = (arg[1].isGeoLine()))) { GeoElement[] ret = kernelA.getManager3D().IntersectPath( c.getLabels(), (GeoLineND) arg[1], (GeoPolygon) arg[0]); return ret; } // Plane - Polygon if ((ok[0] = (arg[0].isGeoPlane())) && (ok[1] = (arg[1].isGeoPolygon()))) { return kernelA.getManager3D().IntersectPath(c.getLabels(), (GeoPlane3D) arg[0], (GeoPolygon) arg[1]); } else if ((ok[1] = (arg[1].isGeoPlane())) && (ok[0] = (arg[0].isGeoPolygon()))) { return kernelA.getManager3D().IntersectPath(c.getLabels(), (GeoPlane3D) arg[1], (GeoPolygon) arg[0]); } // Plane - Polyhedron if ((ok[0] = (arg[0].isGeoPlane())) && (ok[1] = (arg[1].isGeoPolyhedron()))) { return kernelA.getManager3D().IntersectRegion(c.getLabels(), (GeoPlane3D) arg[0], (GeoPolyhedron) arg[1], c.getOutputSizes()); } else if ((ok[1] = (arg[1].isGeoPlane())) && (ok[0] = (arg[0].isGeoPolyhedron()))) { return kernelA.getManager3D().IntersectRegion(c.getLabels(), (GeoPlane3D) arg[1], (GeoPolyhedron) arg[0], c.getOutputSizes()); } // intersection 3D polygons if ((ok[0] = (arg[0].isGeoPolygon())) && (ok[1] = (arg[1].isGeoPolygon()))) { GeoElement[] result = kernelA.getManager3D().IntersectPolygons( c.getLabels(), (GeoPolygon) arg[0], (GeoPolygon) arg[1]); return result; } // argument x=0 should be a plane, not line for (int i = 0; i < 2; i++) { if (arg[i] instanceof GeoLine && arg[i].isIndependent() && !arg[i].isLabelSet()) { arg[i] = lineToPlane(arg[i]); } } // intersection plane/plane if ((ok[0] = (arg[0].isGeoPlane())) && (ok[0] = (arg[1].isGeoPlane()))) { GeoElement[] ret = { kernelA.getManager3D().IntersectPlanes(c.getLabel(), (GeoPlaneND) arg[0], (GeoPlaneND) arg[1]) }; return ret; } GeoElement ret = processPlaneSurface(kernelA, arg, ok, c.getLabel()); if (ret != null) { return new GeoElement[] { ret }; } // intersection plane/quadric ret = processQuadricPlane(kernelA, c, arg, ok); if (ret != null) { return new GeoElement[] { ret }; } throw argErr(app, c, getBadArg(ok, arg)); default: return super.process(c); } } private GeoElement lineToPlane(GeoElement geoElement) { GeoLine line = (GeoLine) geoElement; GeoPlane3D plane = new GeoPlane3D(cons, line.getX(), line.getY(), 0, line.getZ()); if (line.getDefinition() != null) { ExpressionValue eq = geoElement.getDefinition().unwrap(); if (eq instanceof Equation) { plane.setDefinition(eq.wrap()); } } return plane; } /** * @param kernel * kernel * @param arg * arguments * @param ok * feedback array for type check * @param label * label for output * @return path */ public static GeoElement processPlaneSurface(Kernel kernel, GeoElement[] arg, boolean[] ok, String label) { Construction cons = kernel.getConstruction(); GeoElement result = null; if ((ok[0] = (arg[0].isGeoPlane())) && (ok[1] = (arg[1].isGeoImplicitSurface()))) { result = kernel.getManager3D().IntersectPlaneImplicitSurface( (GeoPlaneND) arg[0], (GeoImplicitSurface) arg[1])[0]; } else if ((ok[1] = (arg[1].isGeoPlane())) && (ok[0] = (arg[0].isGeoImplicitSurface()))) { result = kernel.getManager3D().IntersectPlaneImplicitSurface( (GeoPlaneND) arg[1], (GeoImplicitSurface) arg[0])[0]; } else if ((ok[0] = (arg[0].isGeoPlane())) && (ok[1] = (arg[1].isGeoFunctionNVar()))) { result = new AlgoIntersectFunctionNVarPlane(cons, (GeoFunctionNVar) arg[1], (GeoPlaneND) arg[0]) .getOutput()[0]; } else if ((ok[1] = (arg[1].isGeoPlane())) && (ok[0] = (arg[0].isGeoFunctionNVar()))) { result = new AlgoIntersectFunctionNVarPlane(cons, (GeoFunctionNVar) arg[0], (GeoPlaneND) arg[1]) .getOutput()[0]; } if (result != null) { result.setLabel(label); } return result; } /** * (try to) process for plane / quadric (or limited quadric) * * @param kernelA * kernel * @param c * command * @param arg * arguments * @param ok * check * @return intersection */ static public final GeoElement processQuadricPlane(Kernel kernelA, Command c, GeoElement[] arg, boolean[] ok) { // intersection plane/limited quadric if ((ok[0] = (arg[0] instanceof GeoPlaneND)) && (ok[0] = (arg[1] instanceof GeoQuadric3DLimited))) { return intersectPlaneQuadricLimited(kernelA, c.getLabel(), (GeoPlaneND) arg[0], (GeoQuadric3DLimited) arg[1]); } else if ((ok[0] = (arg[0] instanceof GeoQuadric3DLimited)) && (ok[0] = (arg[1] instanceof GeoPlaneND))) { return intersectPlaneQuadricLimited(kernelA, c.getLabel(), (GeoPlaneND) arg[1], (GeoQuadric3DLimited) arg[0]); } // intersection plane/quadric if ((ok[0] = (arg[0] instanceof GeoPlaneND)) && (ok[1] = (arg[1] instanceof GeoQuadricND))) { GeoElement ret = kernelA.getManager3D().Intersect(c.getLabel(), (GeoPlaneND) arg[0], (GeoQuadricND) arg[1]); return ret; } else if ((arg[0] instanceof GeoQuadricND) && (arg[1] instanceof GeoPlaneND)) { GeoElement ret = kernelA.getManager3D().Intersect(c.getLabel(), (GeoPlaneND) arg[1], (GeoQuadricND) arg[0]); return ret; } return null; } static private final GeoElement intersectPlaneQuadricLimited(Kernel kernelA, String label, GeoPlaneND plane, GeoQuadric3DLimited quadric) { return kernelA.getManager3D().IntersectQuadricLimited(label, plane, quadric); } }