/* GeoGebra - Dynamic Mathematics for Everyone http://www.geogebra.org This file is part of GeoGebra. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. */ package org.geogebra.common.geogebra3D.kernel3D; import java.util.LinkedHashMap; import java.util.TreeSet; import org.geogebra.common.geogebra3D.io.MyXMLHandler3D; import org.geogebra.common.geogebra3D.kernel3D.algos.AlgoDispatcher3D; import org.geogebra.common.geogebra3D.kernel3D.algos.AlgoElement3D; import org.geogebra.common.geogebra3D.kernel3D.algos.AlgoPointVector3D; import org.geogebra.common.geogebra3D.kernel3D.algos.AlgoVectorPoint3D; import org.geogebra.common.geogebra3D.kernel3D.algos.Manager3D; import org.geogebra.common.geogebra3D.kernel3D.arithmetic.ExpressionNodeEvaluator3D; import org.geogebra.common.geogebra3D.kernel3D.commands.AlgebraProcessor3D; import org.geogebra.common.geogebra3D.kernel3D.commands.CommandDispatcher3D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoAxis3D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoConic3D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoCoords4D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoElement3D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoLine3D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoPlane3D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoPlane3DConstant; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoPoint3D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoSpace; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoVector3D; import org.geogebra.common.io.MyXMLHandler; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.ConstructionCompanion; import org.geogebra.common.kernel.EVProperty; import org.geogebra.common.kernel.GeoFactory; import org.geogebra.common.kernel.Kernel; import org.geogebra.common.kernel.Manager3DInterface; import org.geogebra.common.kernel.Matrix.CoordSys; import org.geogebra.common.kernel.Matrix.Coords; import org.geogebra.common.kernel.algos.AlgoDispatcher; import org.geogebra.common.kernel.algos.AlgoPointVector; import org.geogebra.common.kernel.algos.AlgoVectorPoint; import org.geogebra.common.kernel.arithmetic.ExpressionNodeEvaluator; import org.geogebra.common.kernel.commands.AlgebraProcessor; import org.geogebra.common.kernel.commands.CommandDispatcher; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoPoint; import org.geogebra.common.kernel.kernelND.GeoAxisND; import org.geogebra.common.kernel.kernelND.GeoConicND; import org.geogebra.common.kernel.kernelND.GeoPointND; import org.geogebra.common.kernel.kernelND.GeoRayND; import org.geogebra.common.kernel.kernelND.GeoSegmentND; import org.geogebra.common.kernel.kernelND.GeoVectorND; import org.geogebra.common.main.App; import org.geogebra.common.plugin.GeoClass; /** * * Class used for (3D) calculations * * <h3>How to add a method for creating a {@link GeoElement3D}</h3> * * <ul> * <li>simply call the element's constructor * <p> * <code> final public GeoNew3D New3D(String label, ???) { <br>    GeoNew3D ret = new GeoNew3D(cons, ???); <br>    // stuff <br>    ret.setLabel(label); <br>    return ret; <br> } </code></li> * <li>use an {@link AlgoElement3D} * <p> * <code> final public GeoNew3D New3D(String label, ???) { <br>    AlgoNew3D algo = new AlgoNew3D(cons, label, ???); <br>    return algo.getGeo(); <br> } </code></li> * </ul> * * * @author ggb3D * */ public class Kernel3D extends Kernel { /** * @param app * application * @param factory * factory for geos */ public Kernel3D(App app, GeoFactory factory) { super(app, factory); } @Override public GeoAxisND getXAxis3D() { return cons.getXAxis(); } @Override public GeoAxisND getYAxis3D() { return cons.getYAxis(); } @Override public GeoAxis3D getZAxis3D() { return (GeoAxis3D) cons.getZAxis(); } @Override public GeoPlane3DConstant getXOYPlane() { return (GeoPlane3DConstant) cons.getXOYPlane(); } @Override public GeoSpace getSpace() { return (GeoSpace) cons.getSpace(); } /* * ******************************************* Methods for 3D manager * ******************************************* */ @Override public Manager3DInterface newManager3D(Kernel kernel) { return new Manager3D(kernel); } /** * Returns whether the variable name "z" may be used. Note that the 3D * kernel does not allow this as it uses "z" in plane equations like 3x + 2y * + z = 5. * * @return whether z may be used as a variable name */ @Override public boolean isZvarAllowed() { return false; } /* * ******************************************* Methods for MyXMLHandler * ******************************************* */ /** * creates the 3D construction cons */ @Override protected void newConstruction() { cons = new Construction(this); } @Override public MyXMLHandler newMyXMLHandler(Kernel kernel, Construction construction) { return new MyXMLHandler3D(kernel, construction); } @Override public ExpressionNodeEvaluator newExpressionNodeEvaluator(Kernel kernel) { return new ExpressionNodeEvaluator3D(app.getLocalization(), kernel); } /** * @param kernel * kernel * @return a new algebra processor (used for 3D) */ @Override public AlgebraProcessor newAlgebraProcessor(Kernel kernel) { CommandDispatcher cd = new CommandDispatcher3D(kernel); return new AlgebraProcessor3D(kernel, cd); } /** return all points of the current construction */ @Override public TreeSet<GeoElement> getPointSet() { TreeSet<GeoElement> t3d = getConstruction() .getGeoSetLabelOrder(GeoClass.POINT3D); TreeSet<GeoElement> t = super.getPointSet(); t.addAll(t3d); // TODO add super.getPointSet() return t; } /* * ******************************************* Methods for MyXMLHandler * ******************************************* */ @Override public boolean handleCoords(GeoElement geo, LinkedHashMap<String, String> attrs) { if (geo instanceof GeoLine3D) { try { // origin double ox = Double.parseDouble(attrs.get("ox")); double oy = Double.parseDouble(attrs.get("oy")); double oz = Double.parseDouble(attrs.get("oz")); double ow = Double.parseDouble(attrs.get("ow")); // direction double vx = Double.parseDouble(attrs.get("vx")); double vy = Double.parseDouble(attrs.get("vy")); double vz = Double.parseDouble(attrs.get("vz")); double vw = Double.parseDouble(attrs.get("vw")); ((GeoLine3D) geo).setCoord(new Coords(ox, oy, oz, ow), new Coords(vx, vy, vz, vw)); return true; } catch (Exception e) { return false; } } if (geo instanceof GeoConic3D && geo.isIndependent()) { try { double ox = Double.parseDouble(attrs.get("ox")); double oy = Double.parseDouble(attrs.get("oy")); double oz = Double.parseDouble(attrs.get("oz")); double ow = Double.parseDouble(attrs.get("ow")); // direction double vx = Double.parseDouble(attrs.get("vx")); double vy = Double.parseDouble(attrs.get("vy")); double vz = Double.parseDouble(attrs.get("vz")); double wx = Double.parseDouble(attrs.get("wx")); double wy = Double.parseDouble(attrs.get("wy")); double wz = Double.parseDouble(attrs.get("wz")); CoordSys cs = ((GeoConic3D) geo).getCoordSys(); if (cs == null) { cs = new CoordSys(2); } cs.addPoint(new Coords(ox, oy, oz, ow)); cs.addVector(new Coords(vx, vy, vz)); cs.addVector(new Coords(wx, wy, wz)); cs.makeOrthoMatrix(false, false); // cs.makeOrthoMatrix(true, true); ((GeoConic3D) geo).setCoordSys(cs); return true; } catch (Exception e) { return false; } } if (!(geo instanceof GeoCoords4D)) { return super.handleCoords(geo, attrs); } try { double x = Double.parseDouble(attrs.get("x")); double y = Double.parseDouble(attrs.get("y")); double z = Double.parseDouble(attrs.get("z")); double w = Double.parseDouble(attrs.get("w")); ((GeoCoords4D) geo).setCoords(x, y, z, w); // Application.debug(geo.getLabel()+": x="+x+", y="+y+", z="+z+", // w="+w); return true; } catch (Exception e) { // Application.debug("erreur : "+e); return false; } } @Override public GeoPlane3D getDefaultPlane() { return getXOYPlane(); } // ////////////////////////////////// // 2D FACTORY EXTENSION // ////////////////////////////////// @Override final public GeoRayND rayND(String label, GeoPointND P, GeoPointND Q) { if (((GeoElement) P).isGeoElement3D() || ((GeoElement) Q).isGeoElement3D()) { return getManager3D().Ray3D(label, P, Q); } return super.ray(label, (GeoPoint) P, (GeoPoint) Q); } @Override final public GeoSegmentND segmentND(String label, GeoPointND P, GeoPointND Q) { if (((GeoElement) P).isGeoElement3D() || ((GeoElement) Q).isGeoElement3D()) { return getManager3D().Segment3D(label, P, Q); } return super.segment(label, (GeoPoint) P, (GeoPoint) Q); } @Override final public GeoElement[] polygonND(String[] labels, GeoPointND[] P) { boolean is3D = false; for (int i = 0; i < P.length && !is3D; i++) { if (((GeoElement) P[i]).isGeoElement3D()) { is3D = true; } } if (is3D) { return getManager3D().Polygon3D(labels, P); } return super.polygon(labels, P); } @Override public GeoElement[] polyLineND(String label, GeoPointND[] P) { boolean is3D = false; for (int i = 0; i < P.length && !is3D; i++) { if (((GeoElement) P[i]).isGeoElement3D()) { is3D = true; } } if (is3D) { return getManager3D().PolyLine3D(label, P); } return super.polyLine(label, P, false); } @Override protected AlgoDispatcher newAlgoDispatcher(Construction cons1) { return new AlgoDispatcher3D(cons1); } @Override public double getZmax(int i) { if (i == 2) { return zmax3; } return super.getZmax(i); } @Override public double getZmin(int i) { if (i == 2) { return zmin3; } return super.getZmin(i); } @Override public double getZscale(int i) { if (i == 2) { return zscale3; } return super.getZscale(i); } private double zmin3, zmax3, zscale3; /** * Tells this kernel about the bounds and the scales for x-Axis and y-Axis * used in EudlidianView. The scale is the number of pixels per unit. * (useful for some algorithms like findminimum). All * * @param view * view * @param xmin * left x-coord * @param xmax * right x-coord * @param ymin * bottom y-coord * @param ymax * top y-coord * @param zmin * min z * @param zmax * max z * @param xscale * x scale (pixels per unit) * @param yscale * y scale (pixels per unit) * @param zscale * z scale */ final public void setEuclidianView3DBounds(int view, double xmin, double xmax, double ymin, double ymax, double zmin, double zmax, double xscale, double yscale, double zscale) { if (3 > this.xmin.length) { this.xmin = prolong(this.xmin, 3); this.xmax = prolong(this.xmin, 3); this.ymin = prolong(this.ymin, 3); this.ymax = prolong(this.ymax, 3); this.xscale = prolong(this.xscale, 3); this.yscale = prolong(this.yscale, 3); } this.xmin[2] = xmin; this.xmax[2] = xmax; this.ymin[2] = ymin; this.ymax[2] = ymax; this.zmin3 = zmin; this.zmax3 = zmax; this.xscale[2] = xscale; this.yscale[2] = yscale; this.zscale3 = zscale; notifyEuclidianViewCE(EVProperty.ZOOM); } @Override protected GeoPointND rigidPolygonPointOnCircle(GeoConicND circle, GeoPointND point1) { if (circle.isGeoElement3D()) { return getManager3D().Point3D(null, circle, point1.getInhomX(), point1.getInhomY(), point1.getInhomZ(), false, true); } return super.rigidPolygonPointOnCircle(circle, point1); } @Override protected void rigidPolygonAddEndOfCommand(StringBuilder sb, boolean is3D) { if (is3D) { sb.append("],xOyPlane]"); } else { super.rigidPolygonAddEndOfCommand(sb, is3D); } } @Override public GeoElement wrapInVector(GeoPointND pt) { if (pt instanceof GeoPoint3D) { AlgoVectorPoint3D algo = new AlgoVectorPoint3D(cons, pt); cons.removeFromConstructionList(algo); return (GeoElement) algo.getVector(); } AlgoVectorPoint algo = new AlgoVectorPoint(cons, pt); cons.removeFromConstructionList(algo); return (GeoElement) algo.getVector(); } /** * * @param vec * vector * @return Point[vector] */ @Override public GeoPointND wrapInPoint(GeoVectorND vec) { if (vec instanceof GeoVector3D) { AlgoPointVector3D algo = new AlgoPointVector3D(cons, cons.getOrigin(), vec); cons.removeFromConstructionList(algo); return algo.getQ(); } AlgoPointVector algo = new AlgoPointVector(cons, cons.getOrigin(), vec); cons.removeFromConstructionList(algo); return algo.getQ(); } @Override public ConstructionCompanion createConstructionCompanion( Construction cons1) { return new ConstructionCompanion3D(cons1); } }