2785 lines
64 KiB
Java
2785 lines
64 KiB
Java
/*
|
|
|
|
Copyright 2006 Rene Grothmann, modified by Eric Hakenholz
|
|
|
|
This file is part of C.a.R. software.
|
|
|
|
C.a.R. is a 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, version 3 of the License.
|
|
|
|
C.a.R. is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
package rene.zirkel.expression;
|
|
|
|
import java.util.Enumeration;
|
|
|
|
import rene.util.MyVector;
|
|
import rene.gui.Global;
|
|
import rene.zirkel.construction.Construction;
|
|
import rene.zirkel.construction.ConstructionException;
|
|
import rene.zirkel.construction.DepList;
|
|
import rene.zirkel.objects.AngleObject;
|
|
import rene.zirkel.objects.ConstructionObject;
|
|
import rene.zirkel.objects.EquationXYObject;
|
|
import rene.zirkel.objects.Evaluator;
|
|
import rene.zirkel.objects.FunctionObject;
|
|
import rene.zirkel.objects.InsideObject;
|
|
import rene.zirkel.objects.PointObject;
|
|
import rene.zirkel.objects.PrimitiveLineObject;
|
|
import rene.zirkel.objects.SimulationObject;
|
|
import rene.zirkel.objects.TrackObject;
|
|
import rene.zirkel.objects.UserFunctionObject;
|
|
import rene.zirkel.objects.VectorObject;
|
|
|
|
/*
|
|
This file contains classes for computing arithmetic expression. Those
|
|
classes might be useful elsewhere. However, variables evaluate to sizes of
|
|
construction objects or values of expressions here.
|
|
*/
|
|
/**
|
|
* This class holds information abut the current position in the scanned text.
|
|
*/
|
|
class ExpressionText {
|
|
|
|
char A[];
|
|
int N;
|
|
Construction C;
|
|
ConstructionObject O;
|
|
DepList DL;
|
|
String Var[];
|
|
boolean NoCircles;
|
|
|
|
|
|
public ExpressionText(final String S, final Construction c,
|
|
final ConstructionObject o, final DepList dl,
|
|
final boolean nocircles) {
|
|
A = S.toCharArray();
|
|
N = 0;
|
|
C = c;
|
|
O = o;
|
|
DL = dl;
|
|
NoCircles = nocircles;
|
|
}
|
|
|
|
public void setVar(final String t[]) {
|
|
Var = t;
|
|
}
|
|
|
|
public boolean isVar(final String var) {
|
|
if (Var == null) {
|
|
return false;
|
|
}
|
|
for (final String element : Var) {
|
|
if (element.equals(var)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public char next(final boolean quotes) {
|
|
if (!quotes) {
|
|
skipblanks();
|
|
}
|
|
if (N < A.length) {
|
|
return A[N];
|
|
} else {
|
|
return (char) 0;
|
|
}
|
|
}
|
|
|
|
public char next() {
|
|
return next(false);
|
|
}
|
|
|
|
public char nextnext() {
|
|
skipblanks();
|
|
if (N + 1 < A.length) {
|
|
return A[N + 1];
|
|
} else {
|
|
return (char) 0;
|
|
}
|
|
}
|
|
|
|
public void advance(final boolean quotes) {
|
|
if (!quotes) {
|
|
skipblanks();
|
|
}
|
|
N++;
|
|
}
|
|
|
|
public void advance() {
|
|
advance(false);
|
|
}
|
|
|
|
public Construction getConstruction() {
|
|
return C;
|
|
}
|
|
|
|
public ConstructionObject getObject() {
|
|
return O;
|
|
}
|
|
|
|
public DepList getDepList() {
|
|
return DL;
|
|
}
|
|
|
|
public void skipblanks() {
|
|
while (N < A.length && A[N] == ' ') {
|
|
N++;
|
|
}
|
|
}
|
|
|
|
public boolean nocircles() {
|
|
return NoCircles;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* basic = (sum) basic = elementary
|
|
*/
|
|
class BasicExpression {
|
|
|
|
BasicExpression E;
|
|
static final int MINUS = -1, PLUS = 1;
|
|
|
|
public static BasicExpression scan(final ExpressionText t)
|
|
throws ConstructionException {
|
|
if (t.next() == '-') {
|
|
t.advance();
|
|
return scan(t, MINUS);
|
|
}
|
|
if (t.next() == '+') {
|
|
t.advance();
|
|
return scan(t, PLUS);
|
|
}
|
|
if (t.next() == '(') {
|
|
return new BracketExpression(scanBracket(t));
|
|
}
|
|
return ElementaryExpression.scan(t);
|
|
}
|
|
|
|
public static BasicExpression scan(final ExpressionText t, final int sign)
|
|
throws ConstructionException {
|
|
if (sign == MINUS) {
|
|
if (t.next() == '(') {
|
|
return new MinusExpression(scanBracket(t));
|
|
}
|
|
return new MinusExpression(ElementaryExpression.scan(t));
|
|
}
|
|
if (t.next() == '(') {
|
|
return scanBracket(t);
|
|
}
|
|
return ElementaryExpression.scan(t);
|
|
}
|
|
|
|
public static BasicExpression scanBracket(final ExpressionText t)
|
|
throws ConstructionException {
|
|
t.advance();
|
|
final BasicExpression E = TopExpression.scan(t);
|
|
if (t.next() == ')') {
|
|
t.advance();
|
|
} else {
|
|
throw new ConstructionException(Global.name("exception.bracket"));
|
|
}
|
|
return E;
|
|
}
|
|
|
|
public double getValue() throws ConstructionException {
|
|
throw new ConstructionException("");
|
|
}
|
|
|
|
public void translate() {
|
|
}
|
|
|
|
public boolean isNumber() {
|
|
return false;
|
|
}
|
|
|
|
public void reset() {
|
|
}
|
|
|
|
public boolean isLogical() {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* double = 34.45879 double = +34.45879 double = -34.45879
|
|
*/
|
|
class DoubleExpression extends BasicExpression {
|
|
|
|
double X;
|
|
|
|
public DoubleExpression(final double x) {
|
|
X = x;
|
|
}
|
|
|
|
public static BasicExpression scan(final ExpressionText t)
|
|
throws ConstructionException {
|
|
boolean Punkt = false, Digit = false, Expo = false;
|
|
String num = "";
|
|
char c = t.next();
|
|
if ((c == '+') || (c == '-')) {
|
|
num += c;
|
|
t.advance();
|
|
}
|
|
|
|
while (true) {
|
|
c = t.next();
|
|
if (c >= '0' && c <= '9') {
|
|
num += c;
|
|
t.advance();
|
|
Digit = true;
|
|
} else if (c == '.') {
|
|
if (Punkt) {
|
|
throw new ConstructionException(Global.name("exception.dot"));
|
|
}
|
|
Punkt = true;
|
|
num += c;
|
|
t.advance();
|
|
} else if ((Digit) && (c == 'E')) {
|
|
if (Expo) {
|
|
throw new ConstructionException(
|
|
"Exponential notation error");
|
|
}
|
|
Expo = true;
|
|
num += c;
|
|
t.advance();
|
|
c = t.next();
|
|
if ((c == '+') || (c == '-')) {
|
|
num += c;
|
|
t.advance();
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!Digit) {
|
|
throw new ConstructionException(Global.name("exception.nodigit"));
|
|
}
|
|
|
|
return new DoubleExpression(Double.valueOf(num).doubleValue());
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
return X;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
String s = "" + X;
|
|
if (s.endsWith(".0")) {
|
|
s = s.substring(0, s.length() - 2);
|
|
}
|
|
return s;
|
|
}
|
|
|
|
@Override
|
|
public void translate() {
|
|
}
|
|
|
|
@Override
|
|
public boolean isNumber() {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* object = @name object = @"name"
|
|
*/
|
|
class FindObjectExpression extends ObjectExpression implements Translator {
|
|
|
|
String Name;
|
|
String Var = null;
|
|
Construction C;
|
|
ConstructionObject O = null; // found object
|
|
|
|
public FindObjectExpression(final String name, final Construction c) {
|
|
super(null);
|
|
Name = name;
|
|
C = c;
|
|
}
|
|
|
|
@Override
|
|
public ConstructionObject getObject() {
|
|
if (C == null) {
|
|
return null;
|
|
}
|
|
if (O != null && O.getConstruction() == C && O.isInConstruction()
|
|
&& O.getName().equals(Name)) {
|
|
return O;
|
|
}
|
|
return O = C.find(Name);
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
if (C == null) {
|
|
throw new InvalidException("");
|
|
}
|
|
if (O != null && O.getConstruction() == C && O.isInConstruction()
|
|
&& O.getName().equals(Name)) {
|
|
return O.getValue();
|
|
}
|
|
O = C.find(Name);
|
|
if (O == null) {
|
|
throw new InvalidException("");
|
|
}
|
|
return O.getValue();
|
|
}
|
|
|
|
public static BasicExpression scan(final ExpressionText t,
|
|
final boolean quotes) throws ConstructionException {
|
|
if (!quotes && t.next() == '\"') {
|
|
t.advance();
|
|
final BasicExpression E = scan(t, true);
|
|
if (t.next() != '\"') {
|
|
throw new ConstructionException(Global.name("exception.quotes"));
|
|
}
|
|
t.advance();
|
|
return E;
|
|
}
|
|
final StringBuffer b = new StringBuffer();
|
|
while (true) {
|
|
final char c = t.next(quotes);
|
|
if (!(Character.isLetterOrDigit(c) || c == '\\' || c == '\''
|
|
|| (quotes && c != '\"' && c != 0) || (quotes && c == ' '))) {
|
|
break;
|
|
}
|
|
b.append(c);
|
|
t.advance(quotes);
|
|
}
|
|
if (!quotes && t.next() == '(') {
|
|
return FunctionExpression.scan(t, b.toString());
|
|
}
|
|
final String s = b.toString();
|
|
return new FindObjectExpression(s, t.getConstruction());
|
|
}
|
|
|
|
public static BasicExpression scan(final ExpressionText t)
|
|
throws ConstructionException {
|
|
return scan(t, false);
|
|
}
|
|
|
|
@Override
|
|
public void translate() {
|
|
C = C.getTranslation();
|
|
C.addTranslator(this);
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
if (Var != null) {
|
|
return Var;
|
|
}
|
|
return "@" + ObjectExpression.quote(Name);
|
|
}
|
|
|
|
/**
|
|
* Used to translate expressions with @P in macros
|
|
*/
|
|
@Override
|
|
public void laterTranslate(final Construction from) {
|
|
if (C == null) {
|
|
return;
|
|
}
|
|
final ConstructionObject o = from.find(Name);
|
|
if (o == null || o.getTranslation() == null) {
|
|
from.addError(ConstructionObject.text1(Global.name("warning.macrodefinition"), Name));
|
|
return;
|
|
}
|
|
Name = o.getTranslation().getName();
|
|
O = null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* object = name object = "name"
|
|
*/
|
|
class ObjectExpression extends BasicExpression {
|
|
|
|
ConstructionObject O;
|
|
String Var = null;
|
|
|
|
public ObjectExpression(final ConstructionObject o) {
|
|
O = o;
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
if (!O.valid()) {
|
|
throw new InvalidException("");
|
|
}
|
|
if (Var != null && (O instanceof FunctionObject)) {
|
|
return ((FunctionObject) O).getValue(Var);
|
|
}
|
|
if (Var != null && (O instanceof UserFunctionObject)) {
|
|
return ((UserFunctionObject) O).getValue(Var);
|
|
}
|
|
if (Var != null && (O instanceof EquationXYObject)) {
|
|
return ((EquationXYObject) O).getValue(Var);
|
|
}
|
|
return O.getValue();
|
|
}
|
|
|
|
public ConstructionObject getObject() {
|
|
return O;
|
|
}
|
|
|
|
public static BasicExpression scan(final ExpressionText t,
|
|
final boolean quotes) throws ConstructionException {
|
|
if (!quotes && t.next() == '\"') {
|
|
t.advance();
|
|
final BasicExpression E = scan(t, true);
|
|
if (t.next() != '\"') {
|
|
throw new ConstructionException(Global.name("exception.quotes"));
|
|
}
|
|
t.advance();
|
|
return E;
|
|
}
|
|
final StringBuffer b = new StringBuffer();
|
|
while (true) {
|
|
final char c = t.next(quotes);
|
|
if (!(Character.isLetterOrDigit(c) || c == '\\' || c == '\''
|
|
|| (quotes && c != '\"' && c != 0) || (quotes && c == ' '))) {
|
|
break;
|
|
}
|
|
b.append(c);
|
|
t.advance(quotes);
|
|
}
|
|
if (!quotes && t.next() == '(') {
|
|
return FunctionExpression.scan(t, b.toString());
|
|
}
|
|
final String s = b.toString();
|
|
if (s.equals("pi")) {
|
|
return new ConstantExpression("pi", Math.PI);
|
|
}
|
|
if (s.equals("valid")) {
|
|
return new ValidExpression(true);
|
|
}
|
|
if (s.equals("invalid")) {
|
|
return new ValidExpression(false);
|
|
}
|
|
if (s.equals("this")) {
|
|
t.getDepList().add(t.getObject());
|
|
return new ObjectExpression(t.getObject());
|
|
}
|
|
if (s.equals("windoww")) {
|
|
return new ConstructionExpression(t.getConstruction(),
|
|
ConstructionExpression.WIDTH);
|
|
}
|
|
if (s.equals("windowh")) {
|
|
return new ConstructionExpression(t.getConstruction(),
|
|
ConstructionExpression.HEIGHT);
|
|
}
|
|
if (s.equals("windowcx")) {
|
|
return new ConstructionExpression(t.getConstruction(),
|
|
ConstructionExpression.CENTERX);
|
|
}
|
|
if (s.equals("windowcy")) {
|
|
return new ConstructionExpression(t.getConstruction(),
|
|
ConstructionExpression.CENTERY);
|
|
}
|
|
if (s.equals("pixel")) {
|
|
return new ConstructionExpression(t.getConstruction(),
|
|
ConstructionExpression.PIXEL);
|
|
}
|
|
if (t.isVar(s)) {
|
|
final ObjectExpression oe = new ObjectExpression(t.getObject());
|
|
oe.Var = s;
|
|
return oe;
|
|
}
|
|
ConstructionObject o = t.getConstruction().findInclusive(s,
|
|
t.getObject());
|
|
if (o == null) {
|
|
o = t.getConstruction().find(s);
|
|
if (o == null) {
|
|
if (t.getConstruction().loading()) {
|
|
return new FindObjectExpression(s, t.getConstruction());
|
|
} else {
|
|
throw new ConstructionException(Global.name("exception.notfound")
|
|
+ " (" + s + ")");
|
|
}
|
|
}
|
|
// System.out.println("---");
|
|
// System.out.println(o.getName()+" "+t.getObject().getName());
|
|
// System.out.println(t.getConstruction().dependsOn(o,t.getObject()));
|
|
if (t.getConstruction().dependsOn(o, t.getObject())) {
|
|
if (t.nocircles()) {
|
|
throw new ConstructionException(ConstructionObject.text1(
|
|
Global.name("exception.depends"), s));
|
|
}
|
|
return new FindObjectExpression(s, t.getConstruction());
|
|
}
|
|
t.getConstruction().needsOrdering();
|
|
}
|
|
t.getDepList().add(o);
|
|
return new ObjectExpression(o);
|
|
}
|
|
|
|
public static BasicExpression scan(final ExpressionText t)
|
|
throws ConstructionException {
|
|
if (t.next() == '@') {
|
|
t.advance();
|
|
return FindObjectExpression.scan(t);
|
|
}
|
|
return scan(t, false);
|
|
}
|
|
|
|
@Override
|
|
public void translate() {
|
|
O = O.getTranslation();
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
if (Var != null) {
|
|
return Var;
|
|
}
|
|
return quote(O.getName());
|
|
}
|
|
|
|
static public String quote(final String name) {
|
|
boolean quotes = false;
|
|
for (int i = 0; i < name.length(); i++) {
|
|
if (!Character.isLetterOrDigit(name.charAt(i))) {
|
|
quotes = true;
|
|
break;
|
|
}
|
|
}
|
|
if (quotes) {
|
|
return "\"" + name + "\"";
|
|
} else {
|
|
return name;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @author Rene
|
|
*
|
|
* Evaluates a user funktion (a FunctionObject). The Y-expression of
|
|
* this function is used.
|
|
*
|
|
*/
|
|
class UserFunctionExpression extends BasicExpression {
|
|
|
|
ConstructionObject F;
|
|
BasicExpression E[];
|
|
double X[];
|
|
|
|
public UserFunctionExpression(final ConstructionObject f,
|
|
final BasicExpression e[]) {
|
|
F = f;
|
|
E = e;
|
|
X = new double[E.length];
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
for (int i = 0; i < E.length; i++) {
|
|
X[i] = E[i].getValue();
|
|
}
|
|
if (F instanceof FunctionObject) {
|
|
return ((FunctionObject) F).evaluateF(X);
|
|
}
|
|
return ((UserFunctionObject) F).evaluateF(X);
|
|
}
|
|
|
|
@Override
|
|
public void translate() {
|
|
for (final BasicExpression element : E) {
|
|
element.translate();
|
|
}
|
|
if (F instanceof FunctionObject) {
|
|
F = (FunctionObject) F.getTranslation();
|
|
} else {
|
|
F = (UserFunctionObject) F.getTranslation();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void reset() {
|
|
for (final BasicExpression element : E) {
|
|
element.reset();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
String ex = E[0].toString();
|
|
for (int i = 1; i < E.length; i++) {
|
|
ex = ex + "," + E[i].toString();
|
|
}
|
|
return F.getName() + "(" + ex + ")";
|
|
}
|
|
}
|
|
|
|
class SimulationExpression extends BasicExpression {
|
|
|
|
ConstructionObject SO;
|
|
ConstructionObject Container, F;
|
|
BasicExpression E;
|
|
Construction C;
|
|
|
|
public SimulationExpression(final ConstructionObject so,
|
|
final ConstructionObject c, final BasicExpression e,
|
|
final ConstructionObject f) {
|
|
SO = so;
|
|
Container = c;
|
|
E = e;
|
|
F = f;
|
|
C = c.getConstruction();
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
if (C.BlockSimulation) {
|
|
throw new ConstructionException(Global.name("exception.simmulation.block"));
|
|
}
|
|
try {
|
|
final double aa = E.getValue();
|
|
C.BlockSimulation = true;
|
|
((SimulationObject) SO).setSimulationValue(aa);
|
|
F.getConstruction().validate(F, SO);
|
|
final double res = F.getValue();
|
|
((SimulationObject) SO).resetSimulationValue();
|
|
F.getConstruction().validate(F, SO);
|
|
C.BlockSimulation = false;
|
|
return res;
|
|
} catch (final Exception e) {
|
|
C.BlockSimulation = false;
|
|
throw new ConstructionException("");
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void translate() {
|
|
E.translate();
|
|
SO = SO.getTranslation();
|
|
Container = Container.getTranslation();
|
|
F = F.getTranslation();
|
|
}
|
|
|
|
@Override
|
|
public void reset() {
|
|
E.reset();
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "simulate(" + SO.getName() + "," + E.toString() + ","
|
|
+ F.getName() + ")";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* function = sin(parameter) etc. function = x(point) function = y(point)
|
|
*/
|
|
class FunctionExpression extends BasicExpression {
|
|
|
|
int F;
|
|
BasicExpression E[];
|
|
int NParams;
|
|
|
|
public FunctionExpression(final int f, final BasicExpression e) {
|
|
F = f;
|
|
E = new BasicExpression[1];
|
|
E[0] = e;
|
|
NParams = 1;
|
|
}
|
|
|
|
public FunctionExpression(final int f, final BasicExpression e,
|
|
final BasicExpression ee) {
|
|
F = f;
|
|
E = new BasicExpression[2];
|
|
E[0] = e;
|
|
E[1] = ee;
|
|
NParams = 2;
|
|
}
|
|
|
|
public FunctionExpression(final int f, final BasicExpression e,
|
|
final BasicExpression ee, final BasicExpression eee) {
|
|
F = f;
|
|
E = new BasicExpression[3];
|
|
E[0] = e;
|
|
E[1] = ee;
|
|
E[2] = eee;
|
|
NParams = 3;
|
|
}
|
|
|
|
/**
|
|
* @author Vincent Robert, 2nde SI 3, LPO Roland-Garros
|
|
* pgcd de deux nombres
|
|
* @param x entier premier nombre
|
|
* @param y entier second nombre
|
|
* @return le pgcd
|
|
*/
|
|
public int pgcd(int x, int y){
|
|
int a=Math.abs(x);
|
|
int b=Math.abs(y);
|
|
int c;
|
|
while(b>0){
|
|
c=a%b;
|
|
a=b;
|
|
b=c;
|
|
}
|
|
return a;
|
|
}
|
|
|
|
final static String Functions[] = { "sin", "cos", "tan", "arcsin",
|
|
"arccos", "arctan", "sqrt", "exp", "log", "round", "x", "y",
|
|
"floor", "ceil", "d", "a", "angle180", "angle360", "abs", "scale",
|
|
"sign", "d", "sum", "if", "deg", "rad", "integrate", "zero",
|
|
"diff", "min", "max", "length", "rsin", "rcos", "rtan", "rarcsin",
|
|
"rarccos", "rarctan", "sinhyp", "coshyp", "z", "simulate",
|
|
"inside", "random", "old", "ratan2", "atan2", "tanhyp", "Argsinh",
|
|
"Argcosh", "Argtanh", "div","mod", "gcd", "lcm", "x3D", "y3D", "z3D", "d3D"};
|
|
final static int NX = 10, NY = 11, ND = 14, NA = 15, NS = 19, NSUM = 22,
|
|
NIF = 23, NINT = 26, NZERO = 27, NDIFF = 28, NMIN = 29, NMAX = 30,
|
|
NLENGTH = 31, NZ = 40, NSIM = 41, NINSIDE = 42, NRANDOM = 43,
|
|
NOLD = 44, NRATAN2=45, NATAN2=46, NDIV=51, NMOD=52, NGCD=53, NLCM=54, NX3D=55, NY3D=56, NZ3D= 57, ND3D=58 ;
|
|
|
|
public static BasicExpression scan(final ExpressionText t, final String name)
|
|
throws ConstructionException {
|
|
int f = -1;
|
|
for (int i = 0; i < Functions.length; i++) {
|
|
if (name.equals(Functions[i])) {
|
|
f = i;
|
|
break;
|
|
}
|
|
}
|
|
if (f < 0) {
|
|
boolean forward = false;
|
|
ConstructionObject o = t.getConstruction()
|
|
.find(name, t.getObject());
|
|
if (o == null) {
|
|
o = t.getConstruction().find(name);
|
|
forward = true;
|
|
}
|
|
if (o != null
|
|
&& (o instanceof FunctionObject || o instanceof UserFunctionObject)
|
|
&& !(o == t.getObject())
|
|
&& !t.getConstruction().dependsOn(o, t.getObject())) {
|
|
if (t.next() != '(') {
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
t.advance();
|
|
final MyVector ex = new MyVector();
|
|
while (true) {
|
|
final BasicExpression e = TopExpression.scan(t);
|
|
ex.addElement(e);
|
|
if (t.next() == ')') {
|
|
break;
|
|
}
|
|
if (t.next() != ',') {
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
t.advance();
|
|
}
|
|
t.advance();
|
|
t.getDepList().add(o);
|
|
if (forward) {
|
|
t.getConstruction().needsOrdering();
|
|
}
|
|
final BasicExpression exp[] = new BasicExpression[ex.size()];
|
|
ex.copyInto(exp);
|
|
return new UserFunctionExpression(o, exp);
|
|
}
|
|
throw new ConstructionException(Global.name("exception.function")
|
|
+ " (" + name + ")");
|
|
}
|
|
if (t.next() != '(') {
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
t.advance();
|
|
BasicExpression e = TopExpression.scan(t);
|
|
if (f == NX || f == NY || f == NZ) {
|
|
if (e instanceof FindObjectExpression) {
|
|
e = new FunctionExpression(f, e);
|
|
} else if (e instanceof ObjectExpression
|
|
&& ((ObjectExpression) e).getObject() instanceof PointObject) {
|
|
e = new FunctionExpression(f, e);
|
|
} else if (e instanceof ObjectExpression
|
|
&& ((ObjectExpression) e).getObject() instanceof PrimitiveLineObject) {
|
|
e = new FunctionExpression(f, e);
|
|
} else {
|
|
|
|
throw new ConstructionException(Global.name("exception.parameter")
|
|
+ " (" + Functions[f] + ")");
|
|
}
|
|
}
|
|
else if (f == NX3D || f == NY3D || f == NZ3D) {
|
|
if (e instanceof FindObjectExpression) {
|
|
e = new FunctionExpression(f, e);
|
|
} else if (e instanceof ObjectExpression
|
|
&& ((ObjectExpression) e).getObject() instanceof PointObject) {
|
|
e = new FunctionExpression(f, e);
|
|
} else if (e instanceof ObjectExpression
|
|
&& ((ObjectExpression) e).getObject() instanceof PrimitiveLineObject) {
|
|
e = new FunctionExpression(f, e);
|
|
} else {
|
|
|
|
throw new ConstructionException(Global.name("exception.parameter")
|
|
+ " (" + Functions[f] + ")");
|
|
}
|
|
}
|
|
else if (f == ND) {
|
|
if (t.next() != ',') {
|
|
e = new DExpression(e);
|
|
} else {
|
|
t.advance();
|
|
final BasicExpression ee = TopExpression.scan(t);
|
|
if (((e instanceof ObjectExpression && ((ObjectExpression) e)
|
|
.getObject() instanceof PointObject) || e instanceof FindObjectExpression)
|
|
&& ((ee instanceof ObjectExpression && ((ObjectExpression) ee)
|
|
.getObject() instanceof PointObject) || ee instanceof FindObjectExpression)) {
|
|
e = new FunctionExpression(f, e, ee);
|
|
} else {
|
|
throw new ConstructionException(Global.name("exception.parameter")
|
|
+ " (" + Functions[f] + ")");
|
|
}
|
|
}
|
|
}
|
|
else if (f == ND3D) {
|
|
if (t.next() != ',') {
|
|
e = new D3DExpression(e);
|
|
} else {
|
|
t.advance();
|
|
final BasicExpression ee = TopExpression.scan(t);
|
|
if (((e instanceof ObjectExpression && ((ObjectExpression) e)
|
|
.getObject() instanceof PointObject) || e instanceof FindObjectExpression)
|
|
&& ((ee instanceof ObjectExpression && ((ObjectExpression) ee)
|
|
.getObject() instanceof PointObject) || ee instanceof FindObjectExpression)) {
|
|
e = new FunctionExpression(f, e, ee);
|
|
} else {
|
|
throw new ConstructionException(Global.name("exception.parameter")
|
|
+ " (" + Functions[f] + ")");
|
|
}
|
|
}
|
|
}
|
|
else if (f == NOLD) {
|
|
if (t.next() != ',') {
|
|
e = new OldExpression(e);
|
|
} else {
|
|
t.advance();
|
|
final BasicExpression ee = TopExpression.scan(t);
|
|
e = new OldExpression(e, ee);
|
|
}
|
|
} else if (f == NA) {
|
|
if (t.next() != ',') {
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
t.advance();
|
|
final BasicExpression ee = TopExpression.scan(t);
|
|
if (t.next() != ',') {
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
t.advance();
|
|
final BasicExpression eee = TopExpression.scan(t);
|
|
if (((e instanceof ObjectExpression && ((ObjectExpression) e)
|
|
.getObject() instanceof PointObject) || e instanceof FindObjectExpression)
|
|
&& ((ee instanceof ObjectExpression && ((ObjectExpression) ee)
|
|
.getObject() instanceof PointObject) || ee instanceof FindObjectExpression)
|
|
&& ((eee instanceof ObjectExpression && ((ObjectExpression) eee)
|
|
.getObject() instanceof PointObject) || eee instanceof FindObjectExpression)) {
|
|
e = new FunctionExpression(f, e, ee, eee);
|
|
} else {
|
|
throw new ConstructionException(Global.name("exception.parameter")
|
|
+ " (" + Functions[f] + ")");
|
|
}
|
|
|
|
} else if (f == NS) {
|
|
if (t.next() != ',') {
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
t.advance();
|
|
final BasicExpression ee = TopExpression.scan(t);
|
|
if (t.next() != ',') {
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
t.advance();
|
|
final BasicExpression eee = TopExpression.scan(t);
|
|
e = new FunctionExpression(f, e, ee, eee);
|
|
} else if (f == NSUM) {
|
|
if (t.next() != ',') {
|
|
e = new CumSumExpression(e);
|
|
} else {
|
|
t.advance();
|
|
final BasicExpression ee = TopExpression.scan(t);
|
|
e = new CumSumExpression(e, ee);
|
|
}
|
|
} else if (f == NRANDOM) {
|
|
if (t.next() != ',') {
|
|
e = new RandomExpression(e);
|
|
} else {
|
|
t.advance();
|
|
final BasicExpression ee = TopExpression.scan(t);
|
|
e = new RandomExpression(e, ee);
|
|
}
|
|
} else if (f == NIF) {
|
|
if (t.next() != ',') {
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
t.advance();
|
|
final BasicExpression ee = TopExpression.scan(t);
|
|
if (t.next() != ',') {
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
t.advance();
|
|
final BasicExpression eee = TopExpression.scan(t);
|
|
e = new IfExpression(e, ee, eee);
|
|
} else if (f == NINT || f == NZERO || f == NMIN || f == NMAX
|
|
|| f == NLENGTH || f==NRATAN2 || f==NATAN2
|
|
|| f == NDIV || f== NMOD || f == NGCD || f == NLCM) {
|
|
if (!(e instanceof ObjectExpression)||t.isVar(e.toString())) {
|
|
if (f == NMAX || f == NMIN || f==NRATAN2 || f==NATAN2
|
|
|| f == NDIV || f == NMOD || f == NGCD || f == NLCM) {
|
|
if (t.next() != ',') {
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
t.advance();
|
|
final BasicExpression ee = TopExpression.scan(t);
|
|
e = new FunctionExpression(f, e, ee);
|
|
} else {
|
|
throw new ConstructionException(Global.name("exception.parameter")
|
|
+ " (" + Functions[f] + ")");
|
|
}
|
|
} else {
|
|
final boolean function = ((ObjectExpression) e).getObject() instanceof Evaluator
|
|
|| ((ObjectExpression) e).getObject() instanceof TrackObject;
|
|
if ((f == NINT || f == NLENGTH) && t.next() == ')') {
|
|
if (!function) {
|
|
throw new ConstructionException(Global.name("exception.parameter")
|
|
+ " (" + Functions[f] + ")");
|
|
}
|
|
e = new FunctionExpression(f, e);
|
|
} else if (f == NLENGTH) {
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
} else {
|
|
if (t.next() != ',') {
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
t.advance();
|
|
final BasicExpression ee = TopExpression.scan(t);
|
|
if (function) {
|
|
if (t.next() != ',') {
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
t.advance();
|
|
final BasicExpression eee = TopExpression.scan(t);
|
|
e = new FunctionExpression(f, e, ee, eee);
|
|
} else if (f == NMIN || f == NMAX || f == NATAN2
|
|
|| f == NRATAN2 || f == NDIV || f == NMOD
|
|
|| f == NGCD || f == NLCM) {
|
|
e = new FunctionExpression(f, e, ee);
|
|
} else {
|
|
throw new ConstructionException(Global.name("exception.parameter")
|
|
+ " (" + Functions[f] + ")");
|
|
}
|
|
}
|
|
}
|
|
} else if (f == NDIFF) {
|
|
if (!(e instanceof ObjectExpression)
|
|
|| !(((ObjectExpression) e).getObject() instanceof Evaluator)) {
|
|
throw new ConstructionException(Global.name("exception.parameter")
|
|
+ " (" + Functions[f] + ")");
|
|
}
|
|
if (t.next() != ',') {
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
t.advance();
|
|
final BasicExpression ee = TopExpression.scan(t);
|
|
e = new FunctionExpression(f, e, ee);
|
|
} else if (f == NSIM) {
|
|
if (t.next() != ',') {
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
t.advance();
|
|
final BasicExpression ee = TopExpression.scan(t);
|
|
if (t.next() != ',') {
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
t.advance();
|
|
final BasicExpression eee = TopExpression.scan(t);
|
|
if ((e instanceof ObjectExpression && ((ObjectExpression) e)
|
|
.getObject() instanceof SimulationObject)
|
|
|| !(eee instanceof ObjectExpression)) {
|
|
final ConstructionObject SO = ((ObjectExpression) e)
|
|
.getObject();
|
|
if (t.getConstruction().dependsOn(SO, t.getObject())) {
|
|
throw new ConstructionException(Global.name("exception.parameter")
|
|
+ " (" + Functions[f] + ")");
|
|
}
|
|
e = new SimulationExpression(
|
|
((ObjectExpression) e).getObject(), t.getObject(), ee,
|
|
((ObjectExpression) eee).getObject());
|
|
} else {
|
|
throw new ConstructionException(Global.name("exception.parameter")
|
|
+ " (" + Functions[f] + ")");
|
|
}
|
|
|
|
} else if (f == NINSIDE) {
|
|
if (t.next() != ',') {
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
t.advance();
|
|
final BasicExpression ee = TopExpression.scan(t);
|
|
if (((e instanceof ObjectExpression && ((ObjectExpression) e)
|
|
.getObject() instanceof PointObject) || e instanceof FindObjectExpression)
|
|
&& ((ee instanceof ObjectExpression && ((ObjectExpression) ee)
|
|
.getObject() instanceof InsideObject) || ee instanceof FindObjectExpression)) {
|
|
e = new FunctionExpression(f, e, ee);
|
|
} else {
|
|
throw new ConstructionException(Global.name("exception.parameter")
|
|
+ " (" + Functions[f] + ")");
|
|
}
|
|
} else {
|
|
e = new FunctionExpression(f, e);
|
|
}
|
|
if (t.next() != ')') {
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
t.advance();
|
|
return e;
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
PointObject P, PP, PPP;
|
|
double cc;
|
|
switch (F) {
|
|
case NX:
|
|
cc = getPointLineX(0);
|
|
return cc;
|
|
case NY:
|
|
cc = getPointLineY(0);
|
|
return cc;
|
|
case NX3D:
|
|
cc = getPointLineX3D(0);
|
|
return cc;
|
|
case NY3D:
|
|
cc = getPointLineY3D(0);
|
|
return cc;
|
|
case NZ3D:
|
|
cc = getPointLineZ3D(0);
|
|
return cc;
|
|
case NZ:
|
|
P = getPoint(0);
|
|
if (!P.valid()) {
|
|
throw new InvalidException(Global.name("exception.invalid"));
|
|
}
|
|
return P.getZ();
|
|
case ND:
|
|
P = getPoint(0);
|
|
PP = getPoint(1);
|
|
if (!P.valid() || !PP.valid()) {
|
|
throw new InvalidException(Global.name("exception.invalid"));
|
|
}
|
|
double dx = P.getX() - PP.getX();
|
|
double dy = P.getY() - PP.getY();
|
|
return Math.sqrt(dx * dx + dy * dy);
|
|
case ND3D:
|
|
P = getPoint(0);
|
|
PP = getPoint(1);
|
|
if (!P.valid() || !PP.valid()) {
|
|
throw new InvalidException(Global.name("exception.invalid"));
|
|
}
|
|
double dx3D = P.getX3D() - PP.getX3D();
|
|
double dy3D = P.getY3D() - PP.getY3D();
|
|
double dz3D = P.getZ3D() - PP.getZ3D();
|
|
return Math.sqrt(dx3D * dx3D + dy3D * dy3D + dz3D * dz3D);
|
|
case NA:
|
|
P = getPoint(0);
|
|
PP = getPoint(1);
|
|
PPP = getPoint(2);
|
|
if (!P.valid() || !PP.valid() || !PPP.valid()) {
|
|
throw new InvalidException(Global.name("exception.invalid"));
|
|
}
|
|
dx = P.getX() - PP.getX();
|
|
dy = P.getY() - PP.getY();
|
|
final double dx1 = PPP.getX() - PP.getX();
|
|
final double dy1 = PPP.getY() - PP.getY();
|
|
double a = Math.atan2(dx, dy) - Math.atan2(dx1, dy1);
|
|
a = a / Math.PI * 180;
|
|
if (a < 0) {
|
|
a += 360;
|
|
}
|
|
if (a > 360) {
|
|
a -= 360;
|
|
}
|
|
return a;
|
|
case NS:
|
|
final double x = E[0].getValue(),
|
|
xa = E[1].getValue(),
|
|
xb = E[2].getValue();
|
|
if (x < xa || x >= xb || xb <= xa) {
|
|
throw new InvalidException(Global.name("exception.invalid"));
|
|
}
|
|
return (x - xa) / (xb - xa);
|
|
case NINT:
|
|
if (((ObjectExpression) E[0]).getObject() instanceof Evaluator) {
|
|
final Evaluator F = (Evaluator) (((ObjectExpression) E[0])
|
|
.getObject());
|
|
|
|
if (E.length > 1) {
|
|
final double aa = E[1].getValue(), bb = E[2].getValue();
|
|
return Romberg.compute(F, aa, bb, 10, 1e-10, 10);
|
|
} else if (F instanceof FunctionObject) {
|
|
return ((FunctionObject) F).getIntegral();
|
|
}
|
|
} else {
|
|
final TrackObject TO = (TrackObject) (((ObjectExpression) E[0])
|
|
.getObject());
|
|
if (E.length > 1) {
|
|
final double aa = E[1].getValue(), bb = E[2].getValue();
|
|
return TO.getSum(aa, bb);
|
|
} else {
|
|
return TO.getSum();
|
|
}
|
|
}
|
|
case NLENGTH:
|
|
if (((ObjectExpression) E[0]).getObject() instanceof FunctionObject) {
|
|
final FunctionObject F = (FunctionObject) (((ObjectExpression) E[0])
|
|
.getObject());
|
|
return F.getLength();
|
|
} else {
|
|
final TrackObject TO = (TrackObject) (((ObjectExpression) E[0])
|
|
.getObject());
|
|
return TO.getLength();
|
|
}
|
|
case NZERO:
|
|
Evaluator F = (Evaluator) (((ObjectExpression) E[0]).getObject());
|
|
double aa = E[1].getValue(),
|
|
bb = E[2].getValue();
|
|
return Secant.compute(F, aa, bb, 1e-10);
|
|
case NDIFF:
|
|
F = (Evaluator) (((ObjectExpression) E[0]).getObject());
|
|
aa = E[1].getValue();
|
|
return (F.evaluateF(aa + 1e-7) - F.evaluateF(aa - 1e-7)) / 2e-7;
|
|
case NMIN:
|
|
if (NParams == 2) {
|
|
return Math.min(E[0].getValue(), E[1].getValue());
|
|
} else {
|
|
F = (Evaluator) (((ObjectExpression) E[0]).getObject());
|
|
aa = E[1].getValue();
|
|
bb = E[2].getValue();
|
|
return ConvexMin.computeMin(F, aa, bb, 1e-10);
|
|
}
|
|
case NMAX:
|
|
if (NParams == 2) {
|
|
return Math.max(E[0].getValue(), E[1].getValue());
|
|
} else {
|
|
F = (Evaluator) (((ObjectExpression) E[0]).getObject());
|
|
aa = E[1].getValue();
|
|
bb = E[2].getValue();
|
|
return ConvexMin.computeMax(F, aa, bb, 1e-10);
|
|
}
|
|
case NINSIDE:
|
|
P = getPoint(0);
|
|
final InsideObject IO = (InsideObject) (((ObjectExpression) E[1])
|
|
.getObject());
|
|
return IO.containsInside(P);
|
|
}
|
|
double x = E[0].getValue();
|
|
switch (F) {
|
|
case 0:
|
|
return Math.sin(x / 180 * Math.PI);
|
|
case 1:
|
|
return Math.cos(x / 180 * Math.PI);
|
|
case 2:
|
|
return Math.tan(x / 180 * Math.PI);
|
|
case 3:
|
|
return Math.asin(x) / Math.PI * 180;
|
|
case 4:
|
|
return Math.acos(x) / Math.PI * 180;
|
|
case 5:
|
|
return Math.atan(x) / Math.PI * 180;
|
|
case 6:
|
|
return Math.sqrt(x);
|
|
case 7:
|
|
return Math.exp(x);
|
|
case 8:
|
|
return Math.log(x);
|
|
case 9:
|
|
return Math.round(x);
|
|
case 12:
|
|
return Math.floor(x);
|
|
case 13:
|
|
return Math.ceil(x);
|
|
case 16:
|
|
x = x / 360;
|
|
x -= Math.floor(x);
|
|
x = x * 360;
|
|
if (x < 180) {
|
|
return x;
|
|
} else {
|
|
return (x - 360);
|
|
}
|
|
case 17:
|
|
x /= 360;
|
|
x -= Math.floor(x);
|
|
return x * 360;
|
|
case 18:
|
|
return Math.abs(x);
|
|
case 20:
|
|
if (x > 0) {
|
|
return 1;
|
|
} else if (x == 0) {
|
|
return 0;
|
|
} else {
|
|
return -1;
|
|
}
|
|
case 24:
|
|
return (x / Math.PI * 180);
|
|
case 25:
|
|
return (x / 180 * Math.PI);
|
|
case 32:
|
|
return Math.sin(x);
|
|
case 33:
|
|
return Math.cos(x);
|
|
case 34:
|
|
return Math.tan(x);
|
|
case 35:
|
|
return Math.asin(x);
|
|
case 36:
|
|
return Math.acos(x);
|
|
case 37:
|
|
return Math.atan(x);
|
|
case 38:
|
|
return (Math.exp(x) - Math.exp(-x)) / 2;
|
|
case 39:
|
|
return (Math.exp(x) + Math.exp(-x)) / 2;
|
|
case 47:
|
|
return (Math.exp(x) - Math.exp(-x))/(Math.exp(x) + Math.exp(-x));
|
|
case 48:
|
|
return Math.log(x+Math.sqrt(x*x+1));
|
|
case 49:
|
|
return Math.log(x+Math.sqrt(x*x-1));
|
|
case 50:
|
|
return Math.log((1+x)/(1-x))/2.0;
|
|
case 45://these two functions by S. Reyrolle
|
|
if(NParams==2){
|
|
return Math.atan2(x,E[1].getValue());
|
|
} else{
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
case 46:
|
|
if(NParams==2){
|
|
return Math.atan2(x,E[1].getValue())/ Math.PI * 180;
|
|
}else{
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
case NDIV:
|
|
if(NParams==2){
|
|
return Math.floor(x/E[1].getValue());
|
|
}else{
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
case NMOD:
|
|
if(NParams==2){
|
|
return x%(E[1].getValue());
|
|
} else {
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
case NGCD:
|
|
if(NParams==2){
|
|
return pgcd((int) x,(int) E[1].getValue());
|
|
} else {
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
case NLCM:
|
|
if(NParams==2){
|
|
return x*E[1].getValue()/pgcd((int) x,(int) E[1].getValue());
|
|
|
|
} else {
|
|
throw new ConstructionException(Global.name("exception.parameter"));
|
|
}
|
|
}
|
|
throw new ConstructionException("");
|
|
}
|
|
|
|
public double getPointLineX(final int n) throws ConstructionException {
|
|
PointObject p;
|
|
PrimitiveLineObject l;
|
|
VectorObject s;
|
|
try {
|
|
p = (PointObject) ((ObjectExpression) E[n]).getObject();
|
|
if (!p.valid()) {
|
|
throw new ConstructionException("exception.invalid");
|
|
}
|
|
return p.getX();
|
|
} catch (final Exception e) {
|
|
try{
|
|
s=(VectorObject) ((ObjectExpression) E[n]).getObject();
|
|
if (!s.valid()){
|
|
throw new ConstructionException("exception.invalid");
|
|
}
|
|
return s.getDeltaX();
|
|
|
|
} catch (final Exception eee) {
|
|
}
|
|
try {
|
|
l = (PrimitiveLineObject) ((ObjectExpression) E[n]).getObject();
|
|
if (!l.valid()) {
|
|
throw new ConstructionException("exception.invalid");
|
|
}
|
|
return l.getDX();
|
|
} catch (final Exception ee) {
|
|
throw new ConstructionException("exception.notfound");
|
|
}
|
|
}
|
|
}
|
|
|
|
public double getPointLineY(final int n) throws ConstructionException {
|
|
PointObject p;
|
|
PrimitiveLineObject l;
|
|
VectorObject s;
|
|
try {
|
|
p = (PointObject) ((ObjectExpression) E[n]).getObject();
|
|
if (!p.valid()) {
|
|
throw new ConstructionException("exception.invalid");
|
|
}
|
|
return p.getY();
|
|
} catch (final Exception e) {
|
|
try{
|
|
s=(VectorObject) ((ObjectExpression) E[n]).getObject();
|
|
if (!s.valid()){
|
|
throw new ConstructionException("exception.invalid");
|
|
}
|
|
return s.getDeltaY();
|
|
|
|
} catch (final Exception eee) {
|
|
}
|
|
try {
|
|
l = (PrimitiveLineObject) ((ObjectExpression) E[n]).getObject();
|
|
if (!l.valid()) {
|
|
throw new ConstructionException("exception.invalid");
|
|
}
|
|
return l.getDY();
|
|
} catch (final Exception ee) {
|
|
throw new ConstructionException("exception.notfound");
|
|
}
|
|
}
|
|
}
|
|
|
|
public double getPointLineX3D(final int n) throws ConstructionException {
|
|
PointObject p;
|
|
PrimitiveLineObject l;
|
|
VectorObject s;
|
|
try {
|
|
p = (PointObject) ((ObjectExpression) E[n]).getObject();
|
|
if (!p.valid()) {
|
|
throw new ConstructionException("exception.invalid");
|
|
}
|
|
return p.getX3D();
|
|
} catch (final Exception e) {
|
|
try{
|
|
s=(VectorObject) ((ObjectExpression) E[n]).getObject();
|
|
if (!s.valid()){
|
|
throw new ConstructionException("exception.invalid");
|
|
}
|
|
return s.getDeltaX3D();
|
|
|
|
} catch (final Exception eee) {
|
|
}
|
|
try {
|
|
l = (PrimitiveLineObject) ((ObjectExpression) E[n]).getObject();
|
|
if (!l.valid()) {
|
|
throw new ConstructionException("exception.invalid");
|
|
}
|
|
return l.getDX3D();
|
|
} catch (final Exception ee) {
|
|
throw new ConstructionException("exception.notfound");
|
|
}
|
|
}
|
|
}
|
|
|
|
public double getPointLineY3D(final int n) throws ConstructionException {
|
|
PointObject p;
|
|
PrimitiveLineObject l;
|
|
VectorObject s;
|
|
try {
|
|
p = (PointObject) ((ObjectExpression) E[n]).getObject();
|
|
if (!p.valid()) {
|
|
throw new ConstructionException("exception.invalid");
|
|
}
|
|
return p.getY3D();
|
|
} catch (final Exception e) {
|
|
try{
|
|
s=(VectorObject) ((ObjectExpression) E[n]).getObject();
|
|
if (!s.valid()){
|
|
throw new ConstructionException("exception.invalid");
|
|
}
|
|
return s.getDeltaY3D();
|
|
|
|
} catch (final Exception eee) {
|
|
}
|
|
try {
|
|
l = (PrimitiveLineObject) ((ObjectExpression) E[n]).getObject();
|
|
if (!l.valid()) {
|
|
throw new ConstructionException("exception.invalid");
|
|
}
|
|
return l.getDY3D();
|
|
} catch (final Exception ee) {
|
|
throw new ConstructionException("exception.notfound");
|
|
}
|
|
}
|
|
}
|
|
|
|
public double getPointLineZ3D(final int n) throws ConstructionException {
|
|
PointObject p;
|
|
PrimitiveLineObject l;
|
|
VectorObject s;
|
|
try {
|
|
p = (PointObject) ((ObjectExpression) E[n]).getObject();
|
|
if (!p.valid()) {
|
|
throw new ConstructionException("exception.invalid");
|
|
}
|
|
return p.getZ3D();
|
|
} catch (final Exception e) {
|
|
try{
|
|
s=(VectorObject) ((ObjectExpression) E[n]).getObject();
|
|
if (!s.valid()){
|
|
throw new ConstructionException("exception.invalid");
|
|
}
|
|
return s.getDeltaZ3D();
|
|
|
|
} catch (final Exception eee) {
|
|
}
|
|
try {
|
|
l = (PrimitiveLineObject) ((ObjectExpression) E[n]).getObject();
|
|
if (!l.valid()) {
|
|
throw new ConstructionException("exception.invalid");
|
|
}
|
|
return l.getDZ3D();
|
|
} catch (final Exception ee) {
|
|
throw new ConstructionException("exception.notfound");
|
|
}
|
|
}
|
|
}
|
|
|
|
public PointObject getPoint(final int n) throws ConstructionException {
|
|
PointObject p;
|
|
try {
|
|
p = (PointObject) ((ObjectExpression) E[n]).getObject();
|
|
} catch (final Exception e) {
|
|
throw new ConstructionException("exception.notfound");
|
|
}
|
|
if (!p.valid()) {
|
|
throw new ConstructionException("exception.invalid");
|
|
}
|
|
return p;
|
|
}
|
|
|
|
@Override
|
|
public void translate() {
|
|
for (int i = 0; i < NParams; i++) {
|
|
E[i].translate();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void reset() {
|
|
for (int i = 0; i < NParams; i++) {
|
|
E[i].reset();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
String s = Functions[F] + "(";
|
|
for (int i = 0; i < NParams; i++) {
|
|
if (i > 0) {
|
|
s = s + ",";
|
|
}
|
|
s = s + E[i];
|
|
}
|
|
return s + ")";
|
|
}
|
|
}
|
|
|
|
class OldExpression extends FunctionExpression {
|
|
|
|
double oldvalue1 = Double.NaN, oldvalue2 = Double.NaN;
|
|
|
|
public OldExpression(final BasicExpression e) {
|
|
super(NOLD, e);
|
|
}
|
|
|
|
public OldExpression(final BasicExpression e, final BasicExpression ee) {
|
|
super(NOLD, e, ee);
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
final double x = E[0].getValue();
|
|
final double p = (NParams > 1) ? E[1].getValue() : 0;
|
|
if (Double.isNaN(oldvalue1)) {
|
|
oldvalue1 = x;
|
|
}
|
|
if (Double.isNaN(oldvalue2)) {
|
|
oldvalue2 = x;
|
|
}
|
|
if (p == 1) {
|
|
oldvalue1 = oldvalue2;
|
|
oldvalue2 = x;
|
|
} else {
|
|
if (x != oldvalue2) {
|
|
oldvalue1 = oldvalue2;
|
|
oldvalue2 = x;
|
|
}
|
|
}
|
|
return oldvalue1;
|
|
}
|
|
|
|
@Override
|
|
public void reset() {
|
|
super.reset();
|
|
}
|
|
}
|
|
|
|
class DExpression extends FunctionExpression {
|
|
|
|
double Old = 0;
|
|
double Old1 = 0;
|
|
boolean start = false;
|
|
|
|
public DExpression(final BasicExpression e) {
|
|
super(21, e);
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
if (E[0] instanceof ObjectExpression) {
|
|
final ConstructionObject o = ((ObjectExpression) E[0]).getObject();
|
|
if (o instanceof PointObject) {
|
|
final PointObject p = (PointObject) o;
|
|
if (p.dontUpdate()) {
|
|
return 0;
|
|
}
|
|
final double x = p.getX(), y = p.getY();
|
|
if (start) {
|
|
final double res = (x - Old) * (x - Old) + (y - Old1)
|
|
* (y - Old1);
|
|
Old = x;
|
|
Old1 = y;
|
|
return Math.sqrt(res);
|
|
}
|
|
Old = x;
|
|
Old1 = y;
|
|
start = true;
|
|
return 0;
|
|
} else if (o instanceof AngleObject) {
|
|
final AngleObject a = (AngleObject) o;
|
|
final double x = a.getValue();
|
|
if (start) {
|
|
double res = x - Old;
|
|
if (res < -180) {
|
|
res += 180;
|
|
}
|
|
if (res > 180) {
|
|
res -= 180;
|
|
}
|
|
Old = x;
|
|
return res;
|
|
}
|
|
Old = x;
|
|
start = true;
|
|
return 0;
|
|
}
|
|
}
|
|
final double x = E[0].getValue();
|
|
double res;
|
|
if (start) {
|
|
res = x - Old;
|
|
} else {
|
|
res = 0;
|
|
start = true;
|
|
}
|
|
Old = x;
|
|
return res;
|
|
}
|
|
|
|
@Override
|
|
public void reset() {
|
|
start = false;
|
|
super.reset();
|
|
}
|
|
}
|
|
|
|
class D3DExpression extends FunctionExpression {
|
|
|
|
double Old = 0;
|
|
double Old1 = 0;
|
|
double Old2 = 0;
|
|
boolean start = false;
|
|
|
|
public D3DExpression(final BasicExpression e) {
|
|
super(58, e);
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
if (E[0] instanceof ObjectExpression) {
|
|
final ConstructionObject o = ((ObjectExpression) E[0]).getObject();
|
|
if (o instanceof PointObject) {
|
|
final PointObject p = (PointObject) o;
|
|
if (p.dontUpdate()) {
|
|
return 0;
|
|
}
|
|
final double x3D = p.getX3D(), y3D = p.getY3D(), z3D = p.getZ3D();
|
|
if (start) {
|
|
final double res = (x3D - Old) * (x3D - Old) + (y3D - Old1) * (y3D - Old1) + (z3D - Old2) * (z3D - Old2);
|
|
Old = x3D;
|
|
Old1 = y3D;
|
|
Old2 = y3D;
|
|
return Math.sqrt(res);
|
|
}
|
|
Old = x3D;
|
|
Old1 = y3D;
|
|
Old2 = z3D;
|
|
start = true;
|
|
return 0;
|
|
} else if (o instanceof AngleObject) {
|
|
final AngleObject a = (AngleObject) o;
|
|
final double x = a.getValue();
|
|
if (start) {
|
|
double res = x - Old;
|
|
if (res < -180) {
|
|
res += 180;
|
|
}
|
|
if (res > 180) {
|
|
res -= 180;
|
|
}
|
|
Old = x;
|
|
return res;
|
|
}
|
|
Old = x;
|
|
start = true;
|
|
return 0;
|
|
}
|
|
}
|
|
final double x = E[0].getValue();
|
|
double res;
|
|
if (start) {
|
|
res = x - Old;
|
|
} else {
|
|
res = 0;
|
|
start = true;
|
|
}
|
|
Old = x;
|
|
return res;
|
|
}
|
|
|
|
@Override
|
|
public void reset() {
|
|
start = false;
|
|
super.reset();
|
|
}
|
|
}
|
|
|
|
class CumSumExpression extends FunctionExpression {
|
|
|
|
double sum = 0;
|
|
|
|
public CumSumExpression(final BasicExpression e, final BasicExpression ee) {
|
|
super(22, e, ee);
|
|
}
|
|
|
|
public CumSumExpression(final BasicExpression e) {
|
|
super(22, e);
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
if (NParams > 1) {
|
|
try {
|
|
final double x = E[1].getValue();
|
|
if (x < 0) {
|
|
reset();
|
|
return sum;
|
|
}
|
|
} catch (final Exception e) {
|
|
sum = 0;
|
|
return sum;
|
|
}
|
|
}
|
|
sum += E[0].getValue();
|
|
return sum;
|
|
}
|
|
|
|
@Override
|
|
public void reset() {
|
|
sum = 0;
|
|
super.reset();
|
|
}
|
|
}
|
|
|
|
class RandomExpression extends FunctionExpression {
|
|
|
|
double rand = Double.NaN;
|
|
|
|
public RandomExpression(final BasicExpression e, final BasicExpression ee) {
|
|
super(NRANDOM, e, ee);
|
|
}
|
|
|
|
public RandomExpression(final BasicExpression e) {
|
|
super(NRANDOM, e);
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
if (NParams > 1) {
|
|
try {
|
|
final double r = E[0].getValue();
|
|
final double p = E[1].getValue();
|
|
|
|
if ((p == 1) || (Double.isNaN(rand))) {
|
|
rand = r * Math.random();
|
|
}
|
|
} catch (final Exception e) {
|
|
rand = 0;
|
|
return rand;
|
|
}
|
|
} else {
|
|
final double r = E[0].getValue();
|
|
rand = r * Math.random();
|
|
}
|
|
return rand;
|
|
}
|
|
|
|
@Override
|
|
public void reset() {
|
|
rand = 0;
|
|
super.reset();
|
|
}
|
|
}
|
|
|
|
class IfExpression extends FunctionExpression {
|
|
|
|
public IfExpression(final BasicExpression e, final BasicExpression ee,
|
|
final BasicExpression eee) {
|
|
super(23, e, ee, eee);
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
double v = 0;
|
|
try {
|
|
v = E[0].getValue();
|
|
} catch (final NoValueException e) {
|
|
if (e.isValid()) {
|
|
return E[1].getValue();
|
|
} else {
|
|
return E[2].getValue();
|
|
}
|
|
} catch (final ConstructionException e) {
|
|
return E[2].getValue();
|
|
}
|
|
if (E[0].isLogical()) {
|
|
if (v == 0) {
|
|
return E[2].getValue();
|
|
} else {
|
|
return E[1].getValue();
|
|
}
|
|
}
|
|
return E[1].getValue();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* constant = pi
|
|
*/
|
|
class ConstantExpression extends BasicExpression {
|
|
|
|
double X;
|
|
String S;
|
|
|
|
public ConstantExpression(final String s, final double x) {
|
|
X = x;
|
|
S = s;
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
return X;
|
|
}
|
|
|
|
@Override
|
|
public void translate() {
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return S;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* constant depending on construction
|
|
*/
|
|
class ConstructionExpression extends BasicExpression {
|
|
|
|
int Type;
|
|
Construction C;
|
|
final static int CENTERX = 0, CENTERY = 1, WIDTH = 2, HEIGHT = 3,
|
|
PIXEL = 4;
|
|
|
|
public ConstructionExpression(final Construction c, final int type) {
|
|
Type = type;
|
|
C = c;
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
if (C == null) {
|
|
return 0;
|
|
}
|
|
switch (Type) {
|
|
case WIDTH:
|
|
return C.getW();
|
|
case CENTERX:
|
|
return C.getX();
|
|
case CENTERY:
|
|
return C.getY();
|
|
case HEIGHT:
|
|
return C.getH();
|
|
case PIXEL:
|
|
return C.getPixel();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public void translate() {
|
|
C = C.getTranslation();
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
switch (Type) {
|
|
case WIDTH:
|
|
return "windoww";
|
|
case CENTERX:
|
|
return "windowcx";
|
|
case CENTERY:
|
|
return "windowcy";
|
|
case HEIGHT:
|
|
return "windowh";
|
|
case PIXEL:
|
|
return "pixel";
|
|
}
|
|
return "";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* constant = valid,invalid
|
|
*/
|
|
class ValidExpression extends BasicExpression {
|
|
|
|
boolean V;
|
|
|
|
public ValidExpression(final boolean valid) {
|
|
V = valid;
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
if (V) {
|
|
return 0;
|
|
} else {
|
|
throw new ConstructionException("");
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void translate() {
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
if (V) {
|
|
return "valid";
|
|
} else {
|
|
return "invalid";
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Bracket = (Basic)
|
|
*/
|
|
class BracketExpression extends ElementaryExpression {
|
|
|
|
BasicExpression E;
|
|
|
|
public BracketExpression(final BasicExpression e) {
|
|
E = e;
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
return E.getValue();
|
|
}
|
|
|
|
@Override
|
|
public void translate() {
|
|
E.translate();
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "(" + E.toString() + ")";
|
|
}
|
|
|
|
@Override
|
|
public boolean isNumber() {
|
|
return E.isNumber();
|
|
}
|
|
|
|
@Override
|
|
public void reset() {
|
|
E.reset();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* element = double element = object (with value)
|
|
*/
|
|
abstract class ElementaryExpression extends BasicExpression {
|
|
|
|
public static BasicExpression scan(final ExpressionText t)
|
|
throws ConstructionException {
|
|
try {
|
|
final BasicExpression E = DoubleExpression.scan(t);
|
|
return E;
|
|
} catch (final Exception e) {
|
|
}
|
|
try {
|
|
final BasicExpression E = ObjectExpression.scan(t);
|
|
return E;
|
|
} catch (final ConstructionException e) {
|
|
throw e;
|
|
} catch (final Exception e) {
|
|
}
|
|
throw new ConstructionException(Global.name("exception.elementary"));
|
|
}
|
|
|
|
@Override
|
|
abstract public boolean isNumber();
|
|
|
|
@Override
|
|
abstract public double getValue() throws ConstructionException;
|
|
}
|
|
|
|
/**
|
|
* E^E
|
|
*/
|
|
class PotenzExpression extends BasicExpression {
|
|
|
|
BasicExpression E1, E2;
|
|
|
|
public PotenzExpression(final BasicExpression e1, final BasicExpression e2) {
|
|
E1 = e1;
|
|
E2 = e2;
|
|
}
|
|
|
|
public static BasicExpression scan(final ExpressionText t)
|
|
throws ConstructionException {
|
|
final BasicExpression E1 = BasicExpression.scan(t);
|
|
if (t.next() == '^' || (t.next() == '*' && t.nextnext() == '*')) {
|
|
if (t.next() == '*') {
|
|
t.advance();
|
|
}
|
|
t.advance();
|
|
return scan(t, E1);
|
|
}
|
|
return E1;
|
|
}
|
|
|
|
public static BasicExpression scan(final ExpressionText t,
|
|
final BasicExpression E) throws ConstructionException {
|
|
final BasicExpression E1 = BasicExpression.scan(t);
|
|
if (t.next() == '^' || (t.next() == '*' && t.nextnext() == '*')) {
|
|
if (t.next() == '*') {
|
|
t.advance();
|
|
}
|
|
t.advance();
|
|
return scan(t, new PotenzExpression(E, E1));
|
|
}
|
|
return new PotenzExpression(E, E1);
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
return Math.pow(E1.getValue(), E2.getValue());
|
|
}
|
|
|
|
@Override
|
|
public void translate() {
|
|
E1.translate();
|
|
E2.translate();
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return E1 + "^" + E2;
|
|
}
|
|
|
|
@Override
|
|
public void reset() {
|
|
E1.reset();
|
|
E2.reset();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* -E
|
|
*/
|
|
class MinusExpression extends ElementaryExpression {
|
|
|
|
BasicExpression E;
|
|
|
|
public MinusExpression(final BasicExpression e) {
|
|
E = e;
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
return -E.getValue();
|
|
}
|
|
|
|
public static BasicExpression scan(final ExpressionText t)
|
|
throws ConstructionException {
|
|
if (t.next() != '-') {
|
|
return PotenzExpression.scan(t);
|
|
}
|
|
t.advance();
|
|
final BasicExpression E1 = PotenzExpression.scan(t);
|
|
return new MinusExpression(E1);
|
|
}
|
|
|
|
@Override
|
|
public void translate() {
|
|
E.translate();
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "-" + E.toString();
|
|
}
|
|
|
|
@Override
|
|
public boolean isNumber() {
|
|
return E.isNumber();
|
|
}
|
|
|
|
@Override
|
|
public void reset() {
|
|
E.reset();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* E/E
|
|
*/
|
|
class QuotientExpression extends BasicExpression {
|
|
|
|
BasicExpression E1, E2;
|
|
|
|
public QuotientExpression(final BasicExpression e1, final BasicExpression e2) {
|
|
E1 = e1;
|
|
E2 = e2;
|
|
}
|
|
|
|
public static BasicExpression scan(final ExpressionText t,
|
|
final BasicExpression E) throws ConstructionException {
|
|
final BasicExpression E1 = MinusExpression.scan(t);
|
|
if (t.next() == '/') {
|
|
t.advance();
|
|
return scan(t, new QuotientExpression(E, E1));
|
|
} else if (t.next() == '*' && t.nextnext() != '*') {
|
|
t.advance();
|
|
return ProductExpression.scan(t, new QuotientExpression(E, E1));
|
|
}
|
|
return new QuotientExpression(E, E1);
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
return E1.getValue() / E2.getValue();
|
|
}
|
|
|
|
@Override
|
|
public void translate() {
|
|
E1.translate();
|
|
E2.translate();
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return E1 + "/" + E2;
|
|
}
|
|
|
|
@Override
|
|
public void reset() {
|
|
E1.reset();
|
|
E2.reset();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* E*E
|
|
*/
|
|
class ProductExpression extends BasicExpression {
|
|
|
|
BasicExpression E1, E2;
|
|
|
|
public ProductExpression(final BasicExpression e1, final BasicExpression e2) {
|
|
E1 = e1;
|
|
E2 = e2;
|
|
}
|
|
|
|
public static BasicExpression scan(final ExpressionText t)
|
|
throws ConstructionException {
|
|
final BasicExpression E1 = MinusExpression.scan(t);
|
|
if (t.next() == '*') {
|
|
t.advance();
|
|
return scan(t, E1);
|
|
} else if (t.next() == '/') {
|
|
t.advance();
|
|
return QuotientExpression.scan(t, E1);
|
|
}
|
|
return E1;
|
|
}
|
|
|
|
public static BasicExpression scan(final ExpressionText t,
|
|
final BasicExpression E) throws ConstructionException {
|
|
final BasicExpression E1 = MinusExpression.scan(t);
|
|
if (t.next() == '*' && t.nextnext() != '*') {
|
|
t.advance();
|
|
return scan(t, new ProductExpression(E, E1));
|
|
} else if (t.next() == '/') {
|
|
t.advance();
|
|
return QuotientExpression.scan(t, new ProductExpression(E, E1));
|
|
}
|
|
return new ProductExpression(E, E1);
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
return E1.getValue() * E2.getValue();
|
|
}
|
|
|
|
@Override
|
|
public void translate() {
|
|
E1.translate();
|
|
E2.translate();
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return E1 + "*" + E2;
|
|
}
|
|
|
|
@Override
|
|
public void reset() {
|
|
E1.reset();
|
|
E2.reset();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* E-E
|
|
*/
|
|
class DifferenceExpression extends BasicExpression {
|
|
|
|
BasicExpression E1, E2;
|
|
|
|
public DifferenceExpression(final BasicExpression e1,
|
|
final BasicExpression e2) {
|
|
E1 = e1;
|
|
E2 = e2;
|
|
}
|
|
|
|
public static BasicExpression scan(final ExpressionText t,
|
|
final BasicExpression E) throws ConstructionException {
|
|
final BasicExpression E1 = ProductExpression.scan(t);
|
|
if (t.next() == '+') {
|
|
t.advance();
|
|
return SumExpression.scan(t, new DifferenceExpression(E, E1));
|
|
} else if (t.next() == '-') {
|
|
t.advance();
|
|
return scan(t, new DifferenceExpression(E, E1));
|
|
}
|
|
return new DifferenceExpression(E, E1);
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
return E1.getValue() - E2.getValue();
|
|
}
|
|
|
|
@Override
|
|
public void translate() {
|
|
E1.translate();
|
|
E2.translate();
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return E1 + "-" + E2;
|
|
}
|
|
|
|
@Override
|
|
public void reset() {
|
|
E1.reset();
|
|
E2.reset();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* E+E
|
|
*/
|
|
class SumExpression extends BasicExpression {
|
|
|
|
BasicExpression E1, E2;
|
|
|
|
public SumExpression(final BasicExpression e1, final BasicExpression e2) {
|
|
E1 = e1;
|
|
E2 = e2;
|
|
}
|
|
|
|
public static BasicExpression scan(final ExpressionText t)
|
|
throws ConstructionException {
|
|
final BasicExpression E1 = ProductExpression.scan(t);
|
|
if (t.next() == '+') {
|
|
t.advance();
|
|
return scan(t, E1);
|
|
} else if (t.next() == '-') {
|
|
t.advance();
|
|
return DifferenceExpression.scan(t, E1);
|
|
}
|
|
return E1;
|
|
}
|
|
|
|
public static BasicExpression scan(final ExpressionText t,
|
|
final BasicExpression E) throws ConstructionException {
|
|
final BasicExpression E1 = ProductExpression.scan(t);
|
|
if (t.next() == '+') {
|
|
t.advance();
|
|
return scan(t, new SumExpression(E, E1));
|
|
} else if (t.next() == '-') {
|
|
t.advance();
|
|
return DifferenceExpression.scan(t, new SumExpression(E, E1));
|
|
}
|
|
return new SumExpression(E, E1);
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
return E1.getValue() + E2.getValue();
|
|
}
|
|
|
|
@Override
|
|
public void translate() {
|
|
E1.translate();
|
|
E2.translate();
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return E1 + "+" + E2;
|
|
}
|
|
|
|
@Override
|
|
public void reset() {
|
|
E1.reset();
|
|
E2.reset();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Diverse Vegleiche.
|
|
*/
|
|
class CompareExpression extends BasicExpression {
|
|
|
|
BasicExpression E1, E2;
|
|
int Operator;
|
|
final static int LESS = 1, LESSEQUAL = 2, GREATER = 3, GREATEREQUAL = 4,
|
|
EQUAL = 5, ABOUTEQUAL = 6;
|
|
|
|
public CompareExpression(final BasicExpression e1,
|
|
final BasicExpression e2, final int op) {
|
|
E1 = e1;
|
|
E2 = e2;
|
|
Operator = op;
|
|
}
|
|
|
|
public static BasicExpression scan(final ExpressionText t)
|
|
throws ConstructionException {
|
|
final BasicExpression E1 = SumExpression.scan(t);
|
|
final char c = t.next();
|
|
int op = 0;
|
|
if (c == '<') {
|
|
t.advance();
|
|
if (t.next(true) == '=') {
|
|
op = LESSEQUAL;
|
|
t.advance();
|
|
} else {
|
|
op = LESS;
|
|
}
|
|
} else if (c == '>') {
|
|
t.advance();
|
|
if (t.next(true) == '=') {
|
|
op = GREATEREQUAL;
|
|
t.advance();
|
|
} else {
|
|
op = GREATER;
|
|
}
|
|
} else if (c == '=') {
|
|
t.advance();
|
|
if (t.next(true) == '=') {
|
|
t.advance();
|
|
}
|
|
op = EQUAL;
|
|
} else if (c == '~') {
|
|
t.advance();
|
|
if (t.next(true) == '=') {
|
|
t.advance();
|
|
}
|
|
op = ABOUTEQUAL;
|
|
} else {
|
|
return E1;
|
|
}
|
|
final BasicExpression E2 = SumExpression.scan(t);
|
|
return new CompareExpression(E1, E2, op);
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
switch (Operator) {
|
|
case LESS:
|
|
return logical(E1.getValue() < E2.getValue());
|
|
case LESSEQUAL:
|
|
return logical(E1.getValue() <= E2.getValue());
|
|
case GREATER:
|
|
return logical(E1.getValue() > E2.getValue());
|
|
case GREATEREQUAL:
|
|
return logical(E1.getValue() >= E2.getValue());
|
|
case EQUAL:
|
|
// return logical(E1.getValue()==E2.getValue());
|
|
return logical(Math.abs(E1.getValue() - E2.getValue()) < 1e-14);
|
|
case ABOUTEQUAL:
|
|
return logical(Math.abs(E1.getValue() - E2.getValue()) < 1e-10);
|
|
}
|
|
return 0.0;
|
|
}
|
|
|
|
public double logical(final boolean flag) {
|
|
if (flag) {
|
|
return 1.0;
|
|
} else {
|
|
return 0.0;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void translate() {
|
|
E1.translate();
|
|
E2.translate();
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
switch (Operator) {
|
|
case LESS:
|
|
return E1 + "<" + E2;
|
|
case LESSEQUAL:
|
|
return E1 + "<=" + E2;
|
|
case GREATER:
|
|
return E1 + ">" + E2;
|
|
case GREATEREQUAL:
|
|
return E1 + ">=" + E2;
|
|
case EQUAL:
|
|
return E1 + "==" + E2;
|
|
case ABOUTEQUAL:
|
|
return E1 + "~=" + E2;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
@Override
|
|
public void reset() {
|
|
E1.reset();
|
|
E2.reset();
|
|
}
|
|
|
|
@Override
|
|
public boolean isLogical() {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ! CE
|
|
*/
|
|
class NotExpression extends BasicExpression {
|
|
|
|
BasicExpression E1;
|
|
|
|
public NotExpression(final BasicExpression e1) {
|
|
E1 = e1;
|
|
}
|
|
|
|
public static BasicExpression scan(final ExpressionText t)
|
|
throws ConstructionException {
|
|
if (t.next() != '!') {
|
|
return CompareExpression.scan(t);
|
|
}
|
|
t.advance();
|
|
final BasicExpression E1 = CompareExpression.scan(t);
|
|
return new NotExpression(E1);
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
if (E1.getValue() == 0.0) {
|
|
return 1.0;
|
|
} else {
|
|
return 0.0;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void translate() {
|
|
E1.translate();
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "!" + E1;
|
|
}
|
|
|
|
@Override
|
|
public void reset() {
|
|
E1.reset();
|
|
}
|
|
|
|
@Override
|
|
public boolean isLogical() {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* /* E & E
|
|
*/
|
|
class AndExpression extends BasicExpression {
|
|
|
|
BasicExpression E1, E2;
|
|
|
|
public AndExpression(final BasicExpression e1, final BasicExpression e2) {
|
|
E1 = e1;
|
|
E2 = e2;
|
|
}
|
|
|
|
public static BasicExpression scan(final ExpressionText t)
|
|
throws ConstructionException {
|
|
final BasicExpression E1 = NotExpression.scan(t);
|
|
if (t.next() == '&') {
|
|
t.advance();
|
|
if (t.next(true) == '&') {
|
|
t.advance();
|
|
}
|
|
return scan(t, E1);
|
|
}
|
|
return E1;
|
|
}
|
|
|
|
public static BasicExpression scan(final ExpressionText t,
|
|
final BasicExpression E) throws ConstructionException {
|
|
final BasicExpression E1 = NotExpression.scan(t);
|
|
if (t.next() == '&') {
|
|
t.advance();
|
|
return scan(t, new AndExpression(E, E1));
|
|
}
|
|
return new AndExpression(E, E1);
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
if (E1.getValue() != 0.0 && E2.getValue() != 0.0) {
|
|
return 1.0;
|
|
} else {
|
|
return 0.0;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void translate() {
|
|
E1.translate();
|
|
E2.translate();
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return E1 + "&&" + E2;
|
|
}
|
|
|
|
@Override
|
|
public void reset() {
|
|
E1.reset();
|
|
E2.reset();
|
|
}
|
|
|
|
@Override
|
|
public boolean isLogical() {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* E | E
|
|
*/
|
|
class OrExpression extends BasicExpression {
|
|
|
|
BasicExpression E1, E2;
|
|
|
|
public OrExpression(final BasicExpression e1, final BasicExpression e2) {
|
|
E1 = e1;
|
|
E2 = e2;
|
|
}
|
|
|
|
public static BasicExpression scan(final ExpressionText t)
|
|
throws ConstructionException {
|
|
final BasicExpression E1 = AndExpression.scan(t);
|
|
if (t.next() == '|') {
|
|
t.advance();
|
|
if (t.next(true) == '|') {
|
|
t.advance();
|
|
}
|
|
return scan(t, E1);
|
|
}
|
|
return E1;
|
|
}
|
|
|
|
public static BasicExpression scan(final ExpressionText t,
|
|
final BasicExpression E) throws ConstructionException {
|
|
final BasicExpression E1 = AndExpression.scan(t);
|
|
if (t.next() == '|') {
|
|
t.advance();
|
|
if (t.next(true) == '|') {
|
|
t.advance();
|
|
}
|
|
return scan(t, new OrExpression(E, E1));
|
|
}
|
|
return new OrExpression(E, E1);
|
|
}
|
|
|
|
@Override
|
|
//suppression de l'évaluation paresseuse par Patrice pour un ExecuteMacro Expression-compatible
|
|
public double getValue() throws ConstructionException {
|
|
try {
|
|
if (E1.getValue() == 1.0) return 1.0;
|
|
} catch (Exception e) {}
|
|
try {
|
|
if (E2.getValue() == 1.0) return 1.0;
|
|
} catch (Exception e) {}
|
|
if (E1.getValue() != 1.0 && E2.getValue() != 1.0) {return 0.0;} else {return 1.0;}
|
|
|
|
}
|
|
|
|
@Override
|
|
public void translate() {
|
|
E1.translate();
|
|
E2.translate();
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return E1 + "||" + E2;
|
|
}
|
|
|
|
@Override
|
|
public void reset() {
|
|
E1.reset();
|
|
E2.reset();
|
|
}
|
|
|
|
@Override
|
|
public boolean isLogical() {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
class TopExpression extends BasicExpression {
|
|
|
|
public static BasicExpression scan(final ExpressionText t)
|
|
throws ConstructionException {
|
|
return OrExpression.scan(t);
|
|
}
|
|
}
|
|
|
|
public class Expression {
|
|
|
|
String S;
|
|
BasicExpression E;
|
|
boolean Valid;
|
|
String ErrorText;
|
|
DepList DL;
|
|
double Value;
|
|
boolean HasDoubleValue = false;
|
|
boolean ForcePlus = false;
|
|
|
|
/**
|
|
* Create a new expression
|
|
*
|
|
* @param s
|
|
* expression string
|
|
* @param c
|
|
* construction to search for objects
|
|
* @param o
|
|
* "this" object
|
|
* @param var
|
|
* variable names used in the referring object
|
|
* @param nocircles
|
|
* prevent circular exressions
|
|
*/
|
|
public Expression(String s, final Construction c,
|
|
final ConstructionObject o, final String var[],
|
|
final boolean nocircles) {
|
|
if (s.startsWith("+")) {
|
|
ForcePlus = true;
|
|
s = s.substring(1);
|
|
}
|
|
S = s;
|
|
DL = new DepList();
|
|
try {
|
|
final ExpressionText t = new ExpressionText(s, c, o, DL, nocircles);
|
|
t.setVar(var);
|
|
E = TopExpression.scan(t);
|
|
if (t.next() != 0) {
|
|
throw new ConstructionException(Global.name("exception.superfluous"));
|
|
}
|
|
Valid = true;
|
|
} catch (final Exception e) {
|
|
Valid = false;
|
|
ErrorText = (e.toString());
|
|
// e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
public Expression(final String s, final Construction c,
|
|
final ConstructionObject o, final String var[]) {
|
|
this(s, c, o, var, false);
|
|
}
|
|
|
|
public Expression(final String s, final Construction c,
|
|
final ConstructionObject o) {
|
|
this(s, c, o, null, false);
|
|
}
|
|
|
|
public boolean isValid() {
|
|
return Valid;
|
|
}
|
|
|
|
public String getErrorText() {
|
|
return ErrorText;
|
|
}
|
|
|
|
public double getValue() throws ConstructionException {
|
|
if (HasDoubleValue) {
|
|
return Value;
|
|
}
|
|
if (!Valid) {
|
|
throw new ConstructionException(Global.name("exception.expression"));
|
|
}
|
|
final double x = E.getValue();
|
|
if (Double.isNaN(x) || Double.isInfinite(x)) {
|
|
throw new ConstructionException(Global.name("exception.value"));
|
|
}
|
|
return x;
|
|
}
|
|
|
|
public void setValue(final double x) {
|
|
HasDoubleValue = true;
|
|
ForcePlus = false;
|
|
DL = new DepList();
|
|
Value = x;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
if (HasDoubleValue) {
|
|
return "" + Value;
|
|
}
|
|
if (Valid) {
|
|
return E.toString();
|
|
} else {
|
|
return S;
|
|
}
|
|
}
|
|
|
|
public DepList getDepList() {
|
|
return DL;
|
|
}
|
|
|
|
public void translate() {
|
|
E.translate();
|
|
DL.translate();
|
|
}
|
|
|
|
public boolean isNumber() {
|
|
return HasDoubleValue || E.isNumber();
|
|
}
|
|
|
|
public void reset() {
|
|
if (E != null && Valid) {
|
|
E.reset();
|
|
}
|
|
}
|
|
|
|
public boolean isForcePlus() {
|
|
return ForcePlus;
|
|
}
|
|
|
|
public void setForcePlus(final boolean flag) {
|
|
ForcePlus = flag;
|
|
}
|
|
|
|
public ConstructionObject getObject() {
|
|
if (E instanceof ObjectExpression) {
|
|
return ((ObjectExpression) E).getObject();
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add the objects this expression depends on to the static dependency list
|
|
* of the current object.
|
|
*/
|
|
public void addDep(final ConstructionObject o) {
|
|
final Enumeration e = getDepList().elements();
|
|
while (e.hasMoreElements()) {
|
|
ConstructionObject.DL.add((ConstructionObject) e.nextElement());
|
|
}
|
|
}
|
|
}
|