/* 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.commands; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoPlane3D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoQuadric3D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoVec4D; import org.geogebra.common.geogebra3D.kernel3D.implicit3D.AlgoDependentImplicitSurface; import org.geogebra.common.geogebra3D.kernel3D.implicit3D.GeoImplicitSurface; import org.geogebra.common.kernel.Kernel; import org.geogebra.common.kernel.algos.AlgoElement; import org.geogebra.common.kernel.arithmetic.Equation; import org.geogebra.common.kernel.arithmetic.ExpressionNode; import org.geogebra.common.kernel.arithmetic.ExpressionValue; import org.geogebra.common.kernel.arithmetic.MyVecNDNode; import org.geogebra.common.kernel.arithmetic.Polynomial; import org.geogebra.common.kernel.arithmetic3D.Vector3DValue; import org.geogebra.common.kernel.commands.AlgebraProcessor; import org.geogebra.common.kernel.commands.CommandDispatcher; import org.geogebra.common.kernel.commands.ParametricProcessor; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.main.Feature; /** * 3D expression processor * */ public class AlgebraProcessor3D extends AlgebraProcessor { /** * @param kernel * kernel * @param cd * commands dispatcher */ public AlgebraProcessor3D(Kernel kernel, CommandDispatcher cd) { super(kernel, cd); } /** * creates 3D point or 3D vector * * @param n * point expression * @param evaluate * evaluated expression * @return 3D point or 3D vector */ @Override protected GeoElement[] processPointVector3D(ExpressionNode n, ExpressionValue evaluate) { String label = n.getLabel(); double[] p = ((Vector3DValue) evaluate).getPointAsDouble(); int mode = ((Vector3DValue) evaluate).getMode(); if (evaluate instanceof MyVecNDNode) { // force vector for CAS vectors GGB-1492 if (((MyVecNDNode) evaluate).isCASVector()) { n.setForceVector(); } } GeoElement[] ret = new GeoElement[1]; boolean isIndependent = n.isConstant(); // make vector, if label begins with lowercase character if (label != null) { if (!(n.isForcedPoint() || n.isForcedVector())) { // may be set by // MyXMLHandler if (Character.isLowerCase(label.charAt(0))) { n.setForceVector(); } else { n.setForcePoint(); } } } boolean isVector = n.shouldEvaluateToGeoVector(); if (isIndependent) { // get coords double x = p[0]; double y = p[1]; double z = p[2]; if (isVector) { ret[0] = kernel.getManager3D().Vector3D(x, y, z); } else { ret[0] = kernel.getManager3D().Point3D(x, y, z, false) .toGeoElement(); } ret[0].setDefinition(n); } else { if (isVector) { ret[0] = kernel.getManager3D().DependentVector3D(n); } else { ret[0] = kernel.getManager3D().DependentPoint3D(n, true) .toGeoElement(); } } if (mode == Kernel.COORD_SPHERICAL) { ((GeoVec4D) ret[0]).setMode(Kernel.COORD_SPHERICAL); } ret[0].setLabel(label); return ret; } @Override protected void checkNoTermsInZ(Equation equ) { if (equ.containsZ()) { switch (equ.degree()) { case 1: equ.setForcePlane(); break; case 2: equ.setForceQuadric(); break; default: equ.setForceSurface(); break; } } } @Override protected GeoElement[] processLine(Equation equ, ExpressionNode def) { if (equ.isForcedLine()) { return super.processLine(equ, def); } // check if the equ is forced plane or if the 3D view has the focus if (equ.isForcedPlane() || kernel.isParsingFor3D()) { return processPlane(equ, def); } return super.processLine(equ, def); } @Override public GeoElement[] processConic(Equation equ, ExpressionNode def) { if (equ.isForcedConic()) { return super.processConic(equ, def); } // check if the equ is forced plane or if the 3D view has the focus if (equ.isForcedQuadric() || kernel.getApplication() .getActiveEuclidianView().isEuclidianView3D()) { return processQuadric(equ, def); } return super.processConic(equ, def); } private GeoElement[] processQuadric(Equation equ, ExpressionNode def) { double xx = 0, yy = 0, zz = 0, xy = 0, xz = 0, yz = 0, x = 0, y = 0, z = 0, c = 0; GeoElement[] ret = new GeoElement[1]; GeoQuadric3D quadric; String label = equ.getLabel(); Polynomial lhs = equ.getNormalForm(); boolean isIndependent = lhs.isConstant(); if (isIndependent) { xx = lhs.getCoeffValue("xx"); yy = lhs.getCoeffValue("yy"); zz = lhs.getCoeffValue("zz"); c = lhs.getCoeffValue(""); xy = lhs.getCoeffValue("xy") / 2; xz = lhs.getCoeffValue("xz") / 2; yz = lhs.getCoeffValue("yz") / 2; x = lhs.getCoeffValue("x") / 2; y = lhs.getCoeffValue("y") / 2; z = lhs.getCoeffValue("z") / 2; double[] coeffs = { xx, yy, zz, c, xy, xz, yz, x, y, z }; quadric = new GeoQuadric3D(cons, coeffs); } else { quadric = (GeoQuadric3D) kernel.getManager3D() .DependentQuadric3D(equ); } quadric.setDefinition(def); quadric.showUndefinedInAlgebraView(true); quadric.setLabel(label); ret[0] = quadric; return ret; } /** * @param equ * equation to process * @return resulting plane */ private GeoElement[] processPlane(Equation equ, ExpressionNode def) { double a = 0, b = 0, c = 0, d = 0; GeoPlane3D plane = null; GeoElement[] ret = new GeoElement[1]; String label = equ.getLabel(); Polynomial lhs = equ.getNormalForm(); boolean isIndependent = lhs.isConstant(); if (isIndependent) { // get coefficients a = lhs.getCoeffValue("x"); b = lhs.getCoeffValue("y"); c = lhs.getCoeffValue("z"); d = lhs.getCoeffValue(""); plane = (GeoPlane3D) kernel.getManager3D().Plane3D(a, b, c, d); plane.setDefinition(def); } else { plane = (GeoPlane3D) kernel.getManager3D().DependentPlane3D(equ); } plane.showUndefinedInAlgebraView(true); plane.setLabel(label); ret[0] = plane; return ret; } @Override public ParametricProcessor getParamProcessor() { if (this.paramProcessor == null) { paramProcessor = new ParametricProcessor3D(kernel, this); } return paramProcessor; } @Override public GeoElement[] processImplicitPoly(Equation equ, ExpressionNode definition) { if (app.has(Feature.IMPLICIT_SURFACES)) { Polynomial lhs = equ.getNormalForm(); boolean isIndependent = !equ.isFunctionDependent() && lhs.isConstant() && !equ.hasVariableDegree(); if (kernel.getApplication().getActiveEuclidianView() .isEuclidianView3D() || equ.isForcedSurface() || equ.isForcedPlane() || equ.isForcedQuadric()) { GeoElement geo = null; if (isIndependent) { geo = new GeoImplicitSurface(cons, equ); } else { AlgoElement surfaceAlgo = new AlgoDependentImplicitSurface( cons, equ); geo = surfaceAlgo.getOutput(0); } geo.setDefinition(definition); geo.setLabel(equ.getLabel()); return new GeoElement[] { geo }; } } return super.processImplicitPoly(equ, definition); } }