package org.geogebra.common.geogebra3D.kernel3D.algos; import org.geogebra.common.euclidian.EuclidianViewInterfaceCommon; import org.geogebra.common.geogebra3D.kernel3D.commands.CommandProcessor3D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoVector3D; import org.geogebra.common.geogebra3D.kernel3D.implicit3D.AlgoIntersectImplicitSurface; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.Kernel; import org.geogebra.common.kernel.Manager3DInterface; import org.geogebra.common.kernel.Path; import org.geogebra.common.kernel.Region; import org.geogebra.common.kernel.Matrix.CoordSys; import org.geogebra.common.kernel.Matrix.Coords; import org.geogebra.common.kernel.algos.AlgoClosestPoint; import org.geogebra.common.kernel.algos.AlgoDispatcher; import org.geogebra.common.kernel.algos.AlgoPolygon; import org.geogebra.common.kernel.algos.AlgoVertexPolygon; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoList; import org.geogebra.common.kernel.geos.GeoNumberValue; import org.geogebra.common.kernel.geos.GeoNumeric; import org.geogebra.common.kernel.geos.GeoPoly; import org.geogebra.common.kernel.kernelND.GeoConicND; import org.geogebra.common.kernel.kernelND.GeoCoordSys2D; import org.geogebra.common.kernel.kernelND.GeoDirectionND; import org.geogebra.common.kernel.kernelND.GeoElementND; import org.geogebra.common.kernel.kernelND.GeoImplicitSurfaceND; import org.geogebra.common.kernel.kernelND.GeoLineND; import org.geogebra.common.kernel.kernelND.GeoPointND; import org.geogebra.common.kernel.kernelND.GeoVectorND; import org.geogebra.common.plugin.GeoClass; /** * extending 2D AlgoDispatcher * * @author mathieu * */ public class AlgoDispatcher3D extends AlgoDispatcher { /** * Constructor * * @param cons * Construction */ public AlgoDispatcher3D(Construction cons) { super(cons); } @Override public AlgoClosestPoint getNewAlgoClosestPoint(Construction cons2, Path path, GeoPointND point) { if (((GeoElement) path).isGeoElement3D() || point.isGeoElement3D()) { return new AlgoClosestPoint3D(cons2, path, point); } return super.getNewAlgoClosestPoint(cons2, path, point); } @Override public GeoNumeric Distance(String label, GeoLineND g, GeoLineND h) { if (g.isGeoElement3D() || h.isGeoElement3D()) { AlgoDistanceLines3D algo = new AlgoDistanceLines3D(cons, label, g, h); return algo.getDistance(); } return super.Distance(label, g, h); } @Override public GeoPointND IntersectLines(String label, GeoLineND g, GeoLineND h) { if (((GeoElement) g).isGeoElement3D() || ((GeoElement) h).isGeoElement3D()) { return (GeoPointND) getManager3D().Intersect(label, g, h); } return super.IntersectLines(label, g, h); } @Override protected GeoVectorND createVector(String label, GeoPointND P) { if (P.isGeoElement3D()) { AlgoVectorPoint3D algo = new AlgoVectorPoint3D(cons, label, P); return algo.getVector(); } return super.createVector(label, P); } @Override public GeoPointND[] IntersectConics(String[] labels, GeoConicND a, GeoConicND b) { if (((GeoElement) a).isGeoElement3D() || ((GeoElement) b).isGeoElement3D()) { return getManager3D().IntersectConics(labels, a, b); } return super.IntersectConics(labels, a, b); } @Override public GeoPointND[] IntersectLineConic(String[] labels, GeoLineND g, GeoConicND c) { if (((GeoElement) g).isGeoElement3D() || ((GeoElement) c).isGeoElement3D()) { return getManager3D().IntersectLineConic(null, g, c); } return super.IntersectLineConic(labels, g, c); } private Manager3DInterface getManager3D() { return cons.getKernel().getManager3D(); } @Override public AlgoVertexPolygon newAlgoVertexPolygon(Construction cons1, String[] labels, GeoPoly p) { if (p.isGeoElement3D()) { return new AlgoVertexPolygon3D(cons1, labels, p); } return super.newAlgoVertexPolygon(cons1, labels, p); } @Override protected GeoElement[] SegmentFixed(String pointLabel, String segmentLabel, GeoPointND A, GeoNumberValue n) { Kernel kernel = cons.getKernel(); GeoDirectionND orientation = CommandProcessor3D .getCurrentViewOrientation(kernel, cons.getApplication()); if (orientation == kernel.getSpace()) { // create a sphere return SegmentFixedSphere(pointLabel, segmentLabel, A, n); } if (A.isGeoElement3D()) { if (orientation == null) { // create a sphere return SegmentFixedSphere(pointLabel, segmentLabel, A, n); } // create a circle around A with radius n AlgoCircle3DPointRadiusDirection algoCircle = new AlgoCircle3DPointRadiusDirection( cons, A, n, orientation); cons.removeFromConstructionList(algoCircle); // place the new point on the circle Coords coords = A.getInhomCoordsInD3(); if (orientation instanceof GeoCoordSys2D) { CoordSys cs = ((GeoCoordSys2D) orientation).getCoordSys(); Coords project = cs.getNormalProjection(coords)[1]; coords = cs.getPoint(project.getX() + n.getDouble(), project.getY()); } else { coords = coords.copyVector(); coords.setX(coords.getX() + n.getDouble()); } AlgoPoint3DOnPath algoPoint = new AlgoPoint3DOnPath(cons, algoCircle.getCircle(), coords.getX(), coords.getY(), coords.getZ()); algoPoint.getP().setLabel(pointLabel); // return segment and new point GeoElement[] ret = { (GeoElement) getManager3D() .Segment3D(segmentLabel, A, algoPoint.getP()), (GeoElement) algoPoint.getP() }; return ret; } return super.SegmentFixed(pointLabel, segmentLabel, A, n); } private Coords tmpCoords; private GeoElement[] SegmentFixedSphere(String pointLabel, String segmentLabel, GeoPointND A, GeoNumberValue n) { // create a sphere around A with radius n AlgoSpherePointRadius algoSphere = new AlgoSpherePointRadius(cons, A, n); cons.removeFromConstructionList(algoSphere); // place the new point on the circle Coords coords = A.getInhomCoordsInD3(); if (tmpCoords == null) { tmpCoords = Coords.createInhomCoorsInD3(); } else { tmpCoords.setW(1.0); } tmpCoords.setX(coords.getX() + n.getDouble()); tmpCoords.setY(coords.getY()); tmpCoords.setZ(coords.getZ()); AlgoPoint3DInRegion algoPoint = new AlgoPoint3DInRegion(cons, pointLabel, algoSphere.getSphere(), tmpCoords); // return segment and new point GeoElement[] ret = { (GeoElement) getManager3D().Segment3D(segmentLabel, A, algoPoint.getP()), algoPoint.getP() }; return ret; } @Override final public GeoElement[] Polygon(String[] labels, GeoPointND[] P) { for (int i = 0; i < P.length; i++) { if (P[i].isGeoElement3D()) { return getManager3D().Polygon3D(labels, P); } } return super.Polygon(labels, P); } @Override final public GeoConicND Circle(String label, GeoPointND M, GeoNumberValue r) { if (M.isGeoElement3D()) { return getManager3D().Circle3D(label, M, r); } return super.Circle(label, M, r); } @Override public GeoPointND PointIn(String label, Region region, Coords coords, boolean addToConstruction, boolean complex, boolean coords2D) { if (region.isRegion3D()) { return getManager3D().Point3DIn(label, region, coords, addToConstruction, coords2D); } return super.PointIn(label, region, coords, addToConstruction, complex, coords2D); } @Override public GeoPointND Point(String label, Path path, Coords coords, boolean addToConstruction, boolean complex, boolean coords2D) { if (path.isGeoElement3D()) { return getManager3D().Point3D(label, path, coords.getX(), coords.getY(), coords.getZ(), addToConstruction, coords2D); } return super.Point(label, path, coords, addToConstruction, complex, coords2D); } @Override protected GeoPointND copyFreePoint(GeoPointND point, EuclidianViewInterfaceCommon view) { if (point.isGeoElement3D()) { double xOffset = 0, yOffset = 0; if (!view.isEuclidianView3D()) { xOffset = DETACH_OFFSET * view.getInvXscale(); yOffset = DETACH_OFFSET * view.getInvYscale(); } return (GeoPointND) getManager3D().Point3D(null, point.getInhomX() + xOffset, point.getInhomY() + yOffset, point.getInhomZ(), point.getMode() == Kernel.COORD_CARTESIAN); } return super.copyFreePoint(point, view); } public GeoVectorND Vector3D(String label) { GeoVectorND ret = (GeoVectorND) getManager3D().Vector3D(0, 0, 0); ret.setLabel(label); return ret; } public GeoVectorND Vector3D() { GeoVector3D v = new GeoVector3D(cons); v.setCoords(0, 0, 0, 0); v.setMode(Kernel.COORD_CARTESIAN_3D); return v; } @Override public GeoElement[] TranslateND(String label, GeoElementND geoTrans, GeoVectorND v) { return getManager3D().Translate3D(label, geoTrans, v); } @Override protected GeoElement LocusNoCheck(String label, GeoPointND Q, GeoNumeric P) { if (Q.isGeoElement3D()) { return getManager3D().Locus3D(label, Q, P); } return super.LocusNoCheck(label, Q, P); } @Override public GeoElement[] IntersectImplicitSurfaceLine(String[] labels, GeoImplicitSurfaceND surf, GeoLineND line) { AlgoIntersectImplicitSurface algo = new AlgoIntersectImplicitSurface( cons, labels, surf, line); GeoElement[] out = algo.getIntersectionPoints(); algo.setLabels(labels); return out; } @Override final public GeoElement[] Polygon(String[] labels, GeoList pointList) { AlgoPolygon algo; if (pointList.getElementType() == GeoClass.POINT3D) { algo = new AlgoPolygon3D(cons, labels, null, pointList); } else { algo = new AlgoPolygon(cons, labels, pointList); } return algo.getOutput(); } }