package org.geogebra.common.geogebra3D.kernel3D.arithmetic; import org.geogebra.common.geogebra3D.kernel3D.geos.Geo3DVec; import org.geogebra.common.kernel.Kernel; import org.geogebra.common.kernel.StringTemplate; import org.geogebra.common.kernel.arithmetic.ExpressionNodeEvaluator; import org.geogebra.common.kernel.arithmetic.ExpressionValue; import org.geogebra.common.kernel.arithmetic.MyDouble; import org.geogebra.common.kernel.arithmetic.MyList; import org.geogebra.common.kernel.arithmetic.NumberValue; import org.geogebra.common.kernel.arithmetic.VectorNDValue; import org.geogebra.common.kernel.arithmetic.VectorValue; import org.geogebra.common.kernel.arithmetic3D.Vector3DValue; import org.geogebra.common.kernel.geos.GeoVec2D; import org.geogebra.common.main.Localization; import org.geogebra.common.plugin.Operation; /** * @author ggb3D * * Evaluator for ExpressionNode (used in ExpressionNode.evaluate()) in * 3D mode * */ public class ExpressionNodeEvaluator3D extends ExpressionNodeEvaluator { /** * @param l10n * localization for errors * @param kernel * kernel */ public ExpressionNodeEvaluator3D(Localization l10n, Kernel kernel) { super(l10n, kernel); } @Override public ExpressionValue handleOp(Operation op, ExpressionValue lt, ExpressionValue rt, ExpressionValue left, ExpressionValue right, StringTemplate tpl, boolean holdsLaTeX) { // right tree MyDouble num; switch (op) { /* * ARITHMETIC operations */ case PLUS: // 3D vector + 3D vector if (lt instanceof Vector3DValue) { if (rt instanceof Vector3DValue) { Geo3DVec vec3D = (Geo3DVec) ((Vector3DValue) lt) .getVector(); Geo3DVec.add(vec3D, (Geo3DVec) ((Vector3DValue) rt).getVector(), vec3D); return vec3D; } else if (rt instanceof VectorValue) { Geo3DVec vec3D = (Geo3DVec) ((Vector3DValue) lt) .getVector(); Geo3DVec.add(vec3D, ((VectorValue) rt).getVector(), vec3D); return vec3D; } } else if (lt instanceof VectorValue && rt instanceof Vector3DValue) { Geo3DVec vec3D = (Geo3DVec) ((Vector3DValue) rt).getVector(); Geo3DVec.add(vec3D, ((VectorValue) lt).getVector(), vec3D); return vec3D; } break; case MINUS: // 3D vector - 3D vector if (lt instanceof Vector3DValue) { if (rt instanceof Vector3DValue) { Geo3DVec vec3D = (Geo3DVec) ((Vector3DValue) lt) .getVector(); Geo3DVec.sub(vec3D, (Geo3DVec) ((Vector3DValue) rt).getVector(), vec3D); return vec3D; } else if (rt instanceof VectorValue) { Geo3DVec vec3D = (Geo3DVec) ((Vector3DValue) lt) .getVector(); Geo3DVec.sub(vec3D, ((VectorValue) rt).getVector(), vec3D); return vec3D; } } else if (lt instanceof VectorValue && rt instanceof Vector3DValue) { Geo3DVec vec3D = (Geo3DVec) ((Vector3DValue) rt).getVector(); Geo3DVec.sub(((VectorValue) lt).getVector(), vec3D, vec3D); return vec3D; } break; case DIVIDE: if (rt instanceof NumberValue) { // number * 3D vector if (lt instanceof Vector3DValue) { Geo3DVec vec3D = (Geo3DVec) ((Vector3DValue) lt) .getVector(); Geo3DVec.div(vec3D, ((NumberValue) rt).getDouble(), vec3D); return vec3D; } } break; case POWER: if (lt instanceof Vector3DValue && rt instanceof NumberValue) { num = ((NumberValue) rt).getNumber(); Geo3DVec vec3D = (Geo3DVec) ((Vector3DValue) lt).getVector(); if (num.getDouble() == 2.0) { Geo3DVec.inner(vec3D, vec3D, num); } else { num.set(Double.NaN); } return num; } break; } return super.handleOp(op, lt, rt, left, right, tpl, holdsLaTeX); } @Override protected ExpressionValue multiply(NumberValue en, VectorNDValue ev) { if (ev instanceof Vector3DValue) { Geo3DVec vec3D = (Geo3DVec) ((Vector3DValue) ev).getVector(); Geo3DVec.mult(vec3D, en.getDouble(), vec3D); return vec3D; } return super.multiply(en, ev); } @Override protected ExpressionValue innerProduct(VectorNDValue ev1, VectorNDValue ev2, Kernel kernel1) { if (ev1 instanceof Vector3DValue || ev2 instanceof Vector3DValue) { MyDouble num = new MyDouble(kernel1); Geo3DVec.inner(ev1.getVector(), ev2.getVector(), num); return num; } // 2D vec * 2D vec return super.innerProduct(ev1, ev2, kernel1); } @Override protected ExpressionValue complexMult(VectorNDValue ev1, VectorNDValue ev2, Kernel kernel1) { if (ev1 instanceof Vector3DValue || ev2 instanceof Vector3DValue) { GeoVec2D vec = new GeoVec2D(kernel1); Geo3DVec.complexMultiply(ev1.getVector(), ev2.getVector(), vec); return vec; } // 2D vec * 2D vec return super.complexMult(ev1, ev2, kernel1); } @Override protected ExpressionValue vectorProduct(VectorNDValue v1, VectorNDValue v2) { if (v1.getMode() == Kernel.COORD_CARTESIAN_3D || v1.getMode() == Kernel.COORD_SPHERICAL || v2.getMode() == Kernel.COORD_CARTESIAN_3D || v2.getMode() == Kernel.COORD_SPHERICAL) { // 3D vector product Geo3DVec vec3D = new Geo3DVec(this.kernel); Geo3DVec.vectorProduct(v1.getVector(), v2.getVector(), vec3D); return vec3D; } // 2D vector product (number) return super.vectorProduct(v1, v2); } @Override protected ExpressionValue multiply(MyList myList, VectorNDValue rt) { if (!myList.isMatrix()) { return null; } int rows = myList.getMatrixRows(); int cols = myList.getMatrixCols(); // 2D coords if (rt.getMode() != Kernel.COORD_CARTESIAN_3D && rt.getMode() != Kernel.COORD_SPHERICAL) { if (rows == 3 && cols == 2) { // creates 3D vector from 2D coords Geo3DVec myVec = new Geo3DVec(this.kernel); // 3x2 matrix * 3D vector / point myVec.multiplyMatrix3x2(myList, rt); return myVec; } if (rt instanceof VectorValue) { // 2D vector / point return multiply2D(myList, rows, cols, (VectorValue) rt); } // 3D vector / point GeoVec2D myVec = new GeoVec2D(this.kernel); return multiply2D(myList, rows, cols, rt, myVec); } // 3D coords if (cols == 3) { if (rows == 3) { // creates 3D vector/point Geo3DVec myVec = new Geo3DVec(this.kernel); // 3x3 matrix * 3D vector / point myVec.multiplyMatrix3x3(myList, rt); return myVec; } if (rows == 2) { // creates 2D vector/point GeoVec2D myVec = new GeoVec2D(this.kernel); // 2x3 matrix * 3D vector / point Geo3DVec.multiplyMatrix(myList, rt, myVec); return myVec; } } else if (cols == 4) { if (rows == 4) { // affine multiplication Geo3DVec myVec = new Geo3DVec(this.kernel); // 3x3 matrix * 3D vector / point myVec.multiplyMatrix4x4(myList, rt); return myVec; } } return null; } }