package org.geogebra.common.geogebra3D.kernel3D.algos; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoPoint3D; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.Kernel; import org.geogebra.common.kernel.Matrix.Coords; import org.geogebra.common.kernel.algos.AlgoIntersectCoordSysCurve; import org.geogebra.common.kernel.arithmetic.ExpressionNode; import org.geogebra.common.kernel.arithmetic.FunctionVariable; import org.geogebra.common.kernel.arithmetic.MyDouble; import org.geogebra.common.kernel.commands.Commands; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.kernelND.GeoCoordSys2D; import org.geogebra.common.kernel.kernelND.GeoCurveCartesianND; import org.geogebra.common.kernel.kernelND.GeoPointND; import org.geogebra.common.plugin.Operation; public class AlgoIntersectPlaneCurve extends AlgoIntersectCoordSysCurve { protected OutputHandler<GeoElement> outputPoints; private GeoCoordSys2D plane; public AlgoIntersectPlaneCurve(Construction cons, GeoCoordSys2D plane, GeoCurveCartesianND c, String[] labels) { super(cons); outputPoints = createOutputPoints(); this.plane = plane; this.curve = c; compute(); setInputOutput(); // for AlgoElement outputPoints.setLabelsMulti(labels); update(); } @Override public void compute() { Coords coeffs = plane.getCoordSys().getEquationVector(); FunctionVariable fv = curve.getFun(0).getFunctionVariable(); // substitute x = x(t), y=y(t), z=z(t) into // ax + by + cz = d ExpressionNode enx; if (Kernel.isZero(coeffs.getW())) { enx = new ExpressionNode(kernel, 0); for (int i = 0; i < curve.getDimension(); i++) { enx = enx.plus(new ExpressionNode(kernel, new MyDouble(kernel, coeffs.get(i + 1)), Operation.MULTIPLY, curve.getFun(i).getExpression())); } } else { // Normalizing to (a/c)x + (b/c)y + 1 seems to work better enx = new ExpressionNode(kernel, 1); for (int i = 0; i < curve.getDimension(); i++) { enx = enx.plus(new ExpressionNode(kernel, new MyDouble(kernel, coeffs.get(i + 1) / coeffs.getW()), Operation.MULTIPLY, curve.getFun(i).getExpression())); } } findIntersections(enx, fv); } @Override public Commands getClassName() { return Commands.Intersect; } @Override protected void setInputOutput() { input = new GeoElement[2]; input[0] = plane.toGeoElement(); input[1] = curve; setDependencies(); } /** * * @return handler for output points */ protected OutputHandler<GeoElement> createOutputPoints() { return new OutputHandler<GeoElement>(new elementFactory<GeoElement>() { @Override public GeoPoint3D newElement() { GeoPoint3D p = new GeoPoint3D(cons); p.setCoords(0, 0, 1); p.setParentAlgorithm(AlgoIntersectPlaneCurve.this); return p; } }); } @Override protected OutputHandler<GeoElement> getOutputPoints() { return outputPoints; } @Override protected void updatePoint(GeoPointND point, double param, FunctionVariable fv) { ExpressionNode xFun = curve.getFun(0).getExpression(); ExpressionNode yFun = curve.getFun(1).getExpression(); double z = 0; fv.set(param); if (curve.getDimension() > 2) { z = curve.getFun(2).getExpression().evaluateDouble(); } point.setCoords(xFun.evaluateDouble(), yFun.evaluateDouble(), z, 1.0); } @Override protected boolean inCoordSys(GeoPointND point) { return true; } }