package org.geogebra.common.geogebra3D.kernel3D.implicit3D;
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.AlgoElement;
import org.geogebra.common.kernel.algos.GetCommand;
import org.geogebra.common.kernel.arithmetic.Equation;
import org.geogebra.common.kernel.arithmetic.ExpressionNode;
import org.geogebra.common.kernel.arithmetic.FunctionVariable;
import org.geogebra.common.kernel.arithmetic.Traversing.VariableReplacer;
import org.geogebra.common.kernel.commands.Commands;
import org.geogebra.common.kernel.geos.GeoElement;
import org.geogebra.common.kernel.geos.GeoFunctionNVar;
import org.geogebra.common.kernel.kernelND.GeoPlaneND;
/**
* Finds intersection path of surface and plane
*
* @author zbynek
*
*/
public class AlgoIntersectFunctionNVarPlane extends AlgoElement {
private GeoFunctionNVar surface;
private GeoPlaneND plane;
private GeoImplicitCurve3D curve;
/**
* @param c
* construction
* @param surface
* surface
* @param plane
* plane
*/
public AlgoIntersectFunctionNVarPlane(Construction c,
GeoFunctionNVar surface, GeoPlaneND plane) {
super(c);
this.surface = surface;
this.plane = plane;
this.curve = new GeoImplicitCurve3D(c);
setInputOutput();
compute();
}
@Override
protected void setInputOutput() {
this.input = new GeoElement[] { (GeoElement) plane, surface };
setOnlyOutput(curve);
setDependencies();
}
@Override
public void compute() {
if (!plane.isDefined()) {
curve.setUndefined();
return;
}
if (!surface.isDefined()) {
curve.setUndefined();
return;
}
curve.setDefined();
curve.setFunctionExpression(surface.getFunction());
// a*x+b*y+c*z=d, z=d/c-a/c*x-b/c*y
Coords norm = plane.getCoordSys().getEquationVector();
curve.setPlaneEquation(norm);
FunctionVariable x = surface.getFunctionVariables()[0];
FunctionVariable y = surface.getFunctionVariables()[1];
ExpressionNode exp;
if (!Kernel.isZero(norm.getZ())) {
double a = norm.getX();
double b = norm.getY();
double c = norm.getZ();
double d = norm.getW();
exp = x.wrap().multiply(a / c)
.plus(y.wrap()
.multiply(b / c).plus(surface
.getFunctionExpression().deepCopy(kernel))
.plus(d / c));
curve.getTransformedCoordSys().setZequal(a, b, c, d);
} else {
VariableReplacer vr = VariableReplacer.getReplacer(kernel);
exp = surface.getFunctionExpression().getCopy(kernel);
if (!Kernel.isZero(norm.getY())) {
double a = norm.getX();
double b = norm.getY();
double d = norm.getW();
ExpressionNode substY = x.wrap().multiply(-a / b).plus(-d / b);
VariableReplacer.addVars("y", substY);
curve.getTransformedCoordSys().setYequal(a, b, d);
} else {
double v = -norm.getW() / norm.getX();
ExpressionNode substY = new ExpressionNode(kernel, v);
VariableReplacer.addVars("x", substY);
VariableReplacer.addVars("y",
new FunctionVariable(kernel, "x"));
// set transformed coord sys to x=value
curve.getTransformedCoordSys().setXequal(v);
}
exp = exp.traverse(vr).wrap()
.subtract(new FunctionVariable(kernel, "y"));
}
Equation eqn = new Equation(kernel, exp, new ExpressionNode(kernel, 0));
eqn.initEquation();
curve.fromEquation(eqn, null);
}
@Override
public GetCommand getClassName() {
return Commands.IntersectPath;
}
}