/*
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.kernel.algos;
import org.geogebra.common.kernel.Construction;
import org.geogebra.common.kernel.arithmetic.ExpressionNode;
import org.geogebra.common.kernel.arithmetic.ExpressionValue;
import org.geogebra.common.kernel.arithmetic.Function;
import org.geogebra.common.kernel.arithmetic.FunctionVariable;
import org.geogebra.common.kernel.commands.Commands;
import org.geogebra.common.kernel.geos.GeoCurveCartesian;
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.GeoCurveCartesianND;
import org.geogebra.common.util.debug.Log;
/**
* Cartesian curve: Curve[ x-expression in var, y-expression in var, var, from,
* to]
*
* @author Markus Hohenwarter
*/
public class AlgoCurveCartesian extends AlgoElement {
private GeoNumberValue[] coords; // input
private GeoNumberValue from, to; // input
private GeoNumeric localVar; // input
private GeoCurveCartesianND curve; // output
private boolean[] containsFunctions;
private ExpressionNode[] exp;
/**
* Creates new AlgoJoinPoints
*
* @param cons
* construction
* @param point
* point expression (null when defined per coord)
* @param coords
* coordinate expressions
* @param localVar
* variable
* @param from
* min parameter
* @param to
* max parameter
*/
public AlgoCurveCartesian(Construction cons, 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(kernel);
funVar.setVarString(localVar.getLabelSimple());
exp = new ExpressionNode[coords.length];
Function[] fun = new Function[coords.length];
containsFunctions = new boolean[coords.length];
for (int i = 0; i < coords.length; i++) {
exp[i] = kernel.convertNumberValueToExpressionNode(
coords[i].toGeoElement());
exp[i] = exp[i].replace(localVar, funVar).wrap();
fun[i] = new Function(exp[i], funVar);
containsFunctions[i] = AlgoDependentFunction
.containsFunctions(exp[i]);
}
// create the curve
curve = createCurve(cons, fun, point);
setInputOutput(); // for AlgoElement
// compute value of dependent number
compute();
}
/**
* creates a curve
*
* @param cons1
* construction
* @param fun
* functions
* @param point
* point expression
* @return a curve
*/
protected GeoCurveCartesianND createCurve(Construction cons1,
Function[] fun, ExpressionNode point) {
return new GeoCurveCartesian(cons1, fun[0], fun[1], point);
}
@Override
public Commands getClassName() {
return Commands.CurveCartesian;
}
// for AlgoElement
@Override
protected void setInputOutput() {
int offset = coords.length;
if (curve.getPointExpression() != null) {
input = new GeoElement[4];
offset = 1;
input[0] = new AlgoDependentFunction(cons,
new Function(curve.getPointExpression(),
new FunctionVariable(kernel)),
false).getFunction();
for (int i = 0; i < offset; i++) {
coords[i].toGeoElement().addAlgorithm(this);
}
} else {
input = new GeoElement[offset + 3];
for (int i = 0; i < offset; i++) {
input[i] = coords[i].toGeoElement();
}
}
input[offset] = localVar;
input[offset + 1] = from.toGeoElement();
input[offset + 2] = to.toGeoElement();
super.setOutputLength(1);
super.setOutput(0, curve);
setDependencies(); // done by AlgoElement
}
/**
* @return resulting curve
*/
public GeoCurveCartesianND getCurve() {
return curve;
}
@Override
public final void compute() {
// take care to set the curve undefined
// if its predecessors are undefined
for (int i = 0; i <= 1; i++) {
AlgoElement algo = null;
if (coords[i].toGeoElement() != null) {
algo = (coords[i].toGeoElement()).getParentAlgorithm();
}
if (algo != null && algo.isUndefined()) {
curve.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), false);
// 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);
}
}
curve.setDefined(true);
// the coord-functions don't have to be updated,
// so we only set the interval
curve.setInterval(from.getDouble(), to.getDouble());
}
}