/*
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.
*/
/*
* AlgoDependentNumber.java
*
* Created on 30. August 2001, 21:37
*/
package org.geogebra.common.geogebra3D.kernel3D.algos;
import org.geogebra.common.geogebra3D.kernel3D.geos.GeoSurfaceCartesian3D;
import org.geogebra.common.kernel.Construction;
import org.geogebra.common.kernel.StringTemplate;
import org.geogebra.common.kernel.algos.AlgoDependentFunction;
import org.geogebra.common.kernel.algos.AlgoElement;
import org.geogebra.common.kernel.arithmetic.ExpressionNode;
import org.geogebra.common.kernel.arithmetic.Function;
import org.geogebra.common.kernel.arithmetic.FunctionNVar;
import org.geogebra.common.kernel.arithmetic.FunctionVariable;
import org.geogebra.common.kernel.commands.Commands;
import org.geogebra.common.kernel.geos.GeoElement;
import org.geogebra.common.kernel.geos.GeoNumberValue;
import org.geogebra.common.kernel.geos.GeoNumeric;
import org.geogebra.common.kernel.kernelND.GeoSurfaceCartesianND;
/**
* Cartesian curve: Curve[ x-expression in var, y-expression in var, var, from,
* to]
*
* @author Markus Hohenwarter
*/
public class AlgoSurfaceCartesian3D extends AlgoElement {
private GeoNumberValue[] coords; // input
private GeoNumberValue[] from, to; // input
private GeoNumeric[] localVar; // input
private GeoSurfaceCartesianND surface; // output
/**
* Creates new algo for Surface
*
* @param cons
* construction
* @param label
* output label
* @param point
* point expression
* @param coords
* coordinate functions
* @param localVar
* variables
* @param from
* range min
* @param to
* range max
*/
public AlgoSurfaceCartesian3D(Construction cons, String label,
ExpressionNode point, GeoNumberValue[] coords,
GeoNumeric[] localVar, GeoNumberValue[] from, GeoNumberValue[] to) {
super(cons);
this.coords = coords;
this.from = from;
this.to = to;
this.localVar = localVar;
// we need to create Function objects for the coord NumberValues,
// so let's get the expressions of xcoord and ycoord and replace
// the localVar by a functionVar
FunctionVariable[] funVar = new FunctionVariable[localVar.length];
for (int i = 0; i < localVar.length; i++) {
funVar[i] = new FunctionVariable(kernel);
funVar[i].setVarString(
localVar[i].getLabel(StringTemplate.defaultTemplate));
}
ExpressionNode[] exp = new ExpressionNode[coords.length];
FunctionNVar[] fun = new FunctionNVar[coords.length];
for (int i = 0; i < coords.length; i++) {
exp[i] = kernel.convertNumberValueToExpressionNode(
coords[i].toGeoElement());
for (int j = 0; j < localVar.length; j++) {
exp[i] = exp[i].replace(localVar[j], funVar[j]).wrap();
}
fun[i] = new FunctionNVar(exp[i], funVar);
}
// create the curve
surface = createCurve(cons, point, fun);
setInputOutput(); // for AlgoElement
// compute value of dependent number
compute();
surface.setLabel(label);
}
/**
* creates a curve
*
* @param cons
* @param fun
* @return a curve
*/
protected GeoSurfaceCartesianND createCurve(Construction cons,
ExpressionNode point, FunctionNVar[] fun) {
return new GeoSurfaceCartesian3D(cons, point, fun);
}
@Override
public Commands getClassName() {
return Commands.Surface;
}
// for AlgoElement
@Override
protected void setInputOutput() {
int offset = coords.length;
if (surface.getPointExpression() != null) {
input = new GeoElement[1 + 3 * localVar.length];
offset = 1;
input[0] = new AlgoDependentFunction(cons,
new Function(surface.getPointExpression(),
new FunctionVariable(kernel)),
false).getFunction();
for (int i = 0; i < offset; i++) {
coords[i].toGeoElement().addAlgorithm(this);
}
} else {
input = new GeoElement[coords.length + 3 * localVar.length];
for (int i = 0; i < coords.length; i++) {
input[i] = coords[i].toGeoElement();
}
}
for (int i = 0; i < localVar.length; i++) {
input[offset + 3 * i] = localVar[i];
input[offset + 3 * i + 1] = from[i].toGeoElement();
input[offset + 3 * i + 2] = to[i].toGeoElement();
}
setOnlyOutput(surface);
setDependencies(); // done by AlgoElement
}
public GeoSurfaceCartesianND getSurface() {
return surface;
}
@Override
public final void compute() {
double[] min = new double[from.length];
double[] max = new double[to.length];
// set min, max, and localVar (to avoid false undefined)
for (int i = 0; i < 2; i++) {
min[i] = from[i].getDouble();
max[i] = to[i].getDouble();
localVar[i].setValue(min[i]);
}
// take care to set the surface undefined
// if its predecessors are undefined
for (int i = 0; i < 3; i++) {
AlgoElement algo = null;
if (coords[i].toGeoElement() != null) {
algo = (coords[i].toGeoElement()).getParentAlgorithm();
}
if (algo != null) {
for (GeoElement geo : algo.getInput()) {
if (!geo.isDefined()) {
surface.setUndefined();
return;
}
}
}
// if (containsFunctions[i]) {
// ExpressionValue ev = null;
// try { // needed for eg f(x)=floor(x) f'(x)
//
// // boolean internationalizeDigits =
// // Kernel.internationalizeDigits;
// // Kernel.internationalizeDigits = false;
// // TODO: seems that we never read internationalize digits
// // flag
// // here ...
// ev = AlgoDependentFunction
// .expandFunctionDerivativeNodes(exp[i]
// .deepCopy(kernel));
//
// // Kernel.internationalizeDigits = internationalizeDigits;
//
// } catch (Exception e) {
// e.printStackTrace();
// Log.debug("derivative failed");
// }
// if (ev == null) {
// curve.setUndefined();
// return;
// }
// ExpressionNode node;
// if (ev.isExpressionNode())
// node = (ExpressionNode) ev;
// else
// node = new ExpressionNode(kernel, ev);
//
// // expandedFun.setExpression(node);
//
// curve.getFun(i).setExpression(node);
// }
}
// the coord-functions don't have to be updated,
// so we only set the interval
surface.setIntervals(min, max);
}
}