protected final void compute() { size = inputList.size(); if (!inputList.isDefined()) { outputList.setUndefined(); return; } outputList.setDefined(true); outputList.clear(); if (size == 0) return; // <Zbynek Konecny 2010-05-13> /* * If val is not numeric, we use the underlying Expression of the function and * plug the list element as variable. * Deep copy is needed so that we can plug the value repeatedly. */ FunctionVariable var = boolFun.getFunction().getFunctionVariable(); for (int i = 0; i < size; i++) { GeoElement geo = inputList.get(i); if (geo.isGeoNumeric()) { if (boolFun.evaluateBoolean(((GeoNumeric) geo).getValue())) outputList.add(geo.copyInternal(cons)); ; } else { ExpressionNode ex = (ExpressionNode) boolFun.getFunction().getExpression().deepCopy(kernel); ex.replaceAndWrap(var, geo.evaluate()); if (((MyBoolean) ex.evaluate()).getBoolean()) outputList.add(geo.copyInternal(cons)); ; } } // </Zbynek> }
private GeoElement[] processBoolean(ExpressionNode n, ExpressionValue evaluate) { GeoElement[] ret = new GeoElement[1]; String label = n.getLabel(); boolean isIndependent = n.isConstant(); if (isIndependent) { ret[0] = kernel.Boolean(label, ((BooleanValue) evaluate).getBoolean()); } else ret[0] = kernel.DependentBoolean(label, n); return ret; }
protected final void compute() { // Sum[{x^2,x^3}] int n = truncate == null ? geoList.size() : (int) truncate.getDouble(); if (n == 0 || n > geoList.size()) { resultFun.setUndefined(); return; } else if (n == 1) { if (!geoList.get(0).isGeoFunctionable()) { resultFun.setUndefined(); return; } GeoFunction fun1 = ((GeoFunctionable) geoList.get(0)).getGeoFunction(); FunctionVariable x1 = fun1.getFunction().getFunctionVariable(); FunctionVariable x = new FunctionVariable(kernel); ExpressionNode left = fun1.getFunctionExpression().getCopy(fun1.getKernel()); Function f = new Function(left.replace(x1, x), x); resultFun.setFunction(f); resultFun.setDefined(true); return; } if (!geoList.get(0).isGeoFunctionable() || !geoList.get(1).isGeoFunctionable()) { resultFun.setUndefined(); return; } // add first two: resultFun = GeoFunction.add( resultFun, ((GeoFunctionable) geoList.get(0)).getGeoFunction(), ((GeoFunctionable) geoList.get(1)).getGeoFunction()); if (n == 2) return; for (int i = 2; i < n; i++) { if (!geoList.get(i).isGeoFunctionable()) { resultFun.setUndefined(); return; } resultFun = GeoFunction.add( resultFun, resultFun, ((GeoFunctionable) geoList.get(i)).getGeoFunction()); } }
/** * for AlgebraView changes in the tree selection and redefine dialog * * @return changed geo */ public GeoElement changeGeoElementNoExceptionHandling( GeoElement geo, ValidExpression newValue, boolean redefineIndependent, boolean storeUndoInfo) throws Exception { String oldLabel, newLabel; GeoElement[] result; try { oldLabel = geo.getLabel(); newLabel = newValue.getLabel(); if (newLabel == null) { newLabel = oldLabel; newValue.setLabel(newLabel); } // make sure that points stay points and vectors stay vectors if (newValue instanceof ExpressionNode) { ExpressionNode n = (ExpressionNode) newValue; if (geo.isGeoPoint()) n.setForcePoint(); else if (geo.isGeoVector()) n.setForceVector(); else if (geo.isGeoFunction()) n.setForceFunction(); } if (newLabel.equals(oldLabel)) { // try to overwrite result = processValidExpression(newValue, redefineIndependent); if (result != null && storeUndoInfo) app.storeUndoInfo(); return result[0]; } else if (cons.isFreeLabel(newLabel)) { newValue.setLabel(oldLabel); // rename to oldLabel to enable overwriting result = processValidExpression(newValue, redefineIndependent); result[0].setLabel(newLabel); // now we rename if (storeUndoInfo) app.storeUndoInfo(); return result[0]; } else { String str[] = {"NameUsed", newLabel}; throw new MyError(app, str); } } catch (CircularDefinitionException e) { Application.debug("CircularDefinition"); throw e; } catch (Exception e) { e.printStackTrace(); throw new Exception(app.getError("InvalidInput") + ":\n" + newValue); } catch (MyError e) { e.printStackTrace(); throw new Exception(e.getLocalizedMessage()); } catch (Error e) { e.printStackTrace(); throw new Exception(app.getError("InvalidInput") + ":\n" + newValue); } }
private GeoElement[] processText(ExpressionNode n, ExpressionValue evaluate) { GeoElement[] ret = new GeoElement[1]; String label = n.getLabel(); boolean isIndependent = n.isConstant(); if (isIndependent) { MyStringBuffer eval = ((TextValue) evaluate).getText(); ret[0] = kernel.Text(label, eval.toValueString()); } else ret[0] = kernel.DependentText(label, n); return ret; }
private GeoElement[] processParametric(Parametric par) throws CircularDefinitionException { /* ExpressionValue temp = P.evaluate(); if (!temp.isVectorValue()) { String [] str = { "VectorExpected", temp.toString() }; throw new MyParseError(kernel.getApplication(), str); } v.resolveVariables(); temp = v.evaluate(); if (!(temp instanceof VectorValue)) { String [] str = { "VectorExpected", temp.toString() }; throw new MyParseError(kernel.getApplication(), str); } */ // point and vector are created silently boolean oldMacroMode = cons.isSuppressLabelsActive(); cons.setSuppressLabelCreation(true); // get point ExpressionNode node = par.getP(); node.setForcePoint(); GeoElement[] temp = processExpressionNode(node); GeoPoint P = (GeoPoint) temp[0]; // get vector node = par.getv(); node.setForceVector(); temp = processExpressionNode(node); GeoVector v = (GeoVector) temp[0]; // switch back to old mode cons.setSuppressLabelCreation(oldMacroMode); // Line through P with direction v GeoLine line; // independent line if (P.isConstant() && v.isConstant()) { line = new GeoLine(cons); line.setCoords(-v.y, v.x, v.y * P.inhomX - v.x * P.inhomY); } // dependent line else { line = kernel.Line(par.getLabel(), P, v); } line.setToParametric(par.getParameter()); line.updateRepaint(); GeoElement[] ret = {line}; return ret; }
// for AlgoElement protected void setInputOutput() { input = root.getGeoElementVariables(); setOutputLength(1); setOutput(0, list); setDependencies(); // done by AlgoElement }
private GeoElement[] processList(ExpressionNode n, MyList evalList) { String label = n.getLabel(); GeoElement[] ret = new GeoElement[1]; // no operations or no variables are present, e.g. // { a, b, 7 } or { 2, 3, 5 } + {1, 2, 4} if (!n.hasOperations() || n.isConstant()) { // PROCESS list items to generate a list of geoElements ArrayList<GeoElement> geoElements = new ArrayList<GeoElement>(); boolean isIndependent = true; // make sure we don't create any labels for the list elements boolean oldMacroMode = cons.isSuppressLabelsActive(); cons.setSuppressLabelCreation(true); int size = evalList.size(); for (int i = 0; i < size; i++) { ExpressionNode en = (ExpressionNode) evalList.getListElement(i); // we only take one resulting object GeoElement[] results = processExpressionNode(en); GeoElement geo = results[0]; // add to list geoElements.add(geo); if (geo.isLabelSet() || !geo.isIndependent()) isIndependent = false; } cons.setSuppressLabelCreation(oldMacroMode); // Create GeoList object ret[0] = kernel.List(label, geoElements, isIndependent); } // operations and variables are present // e.g. {3, 2, 1} + {a, b, 2} else { ret[0] = kernel.ListExpression(label, n); } return ret; }
/** * Parses given String str and tries to evaluate it to a GeoPoint. Returns null if something went * wrong. */ public GeoPointND evaluateToPoint(String str, boolean showErrors) { boolean oldMacroMode = cons.isSuppressLabelsActive(); cons.setSuppressLabelCreation(true); GeoPointND p = null; GeoElement[] temp = null; ; try { ValidExpression ve = parser.parseGeoGebraExpression(str); if (ve instanceof ExpressionNode) { ExpressionNode en = (ExpressionNode) ve; en.setForcePoint(); } temp = processValidExpression(ve); p = (GeoPointND) temp[0]; } catch (CircularDefinitionException e) { if (showErrors) { Application.debug("CircularDefinition"); app.showError("CircularDefinition"); } } catch (Exception e) { if (showErrors) { e.printStackTrace(); app.showError("InvalidInput", str); } } catch (MyError e) { if (showErrors) { e.printStackTrace(); app.showError(e); } } catch (Error e) { if (showErrors) { e.printStackTrace(); app.showError("InvalidInput", str); } } cons.setSuppressLabelCreation(oldMacroMode); return p; }
/** * Parses given String str and tries to evaluate it to a double. Returns Double.NaN if something * went wrong. */ public double evaluateToDouble(String str, boolean suppressErrors) { try { ValidExpression ve = parser.parseExpression(str); ExpressionNode en = (ExpressionNode) ve; en.resolveVariables(); NumberValue nv = (NumberValue) en.evaluate(); return nv.getDouble(); } catch (Exception e) { e.printStackTrace(); if (!suppressErrors) app.showError("InvalidInput", str); return Double.NaN; } catch (MyError e) { e.printStackTrace(); if (!suppressErrors) app.showError(e); return Double.NaN; } catch (Error e) { e.printStackTrace(); if (!suppressErrors) app.showError("InvalidInput", str); return Double.NaN; } }
private GeoElement[] processNumber(ExpressionNode n, ExpressionValue evaluate) { GeoElement[] ret = new GeoElement[1]; String label = n.getLabel(); boolean isIndependent = n.isConstant(); MyDouble eval = ((NumberValue) evaluate).getNumber(); boolean isAngle = eval.isAngle(); double value = eval.getDouble(); if (isIndependent) { if (isAngle) ret[0] = new GeoAngle(cons, label, value); else ret[0] = new GeoNumeric(cons, label, value); } else { ret[0] = kernel.DependentNumber(label, n, isAngle); } if (n.isForcedFunction()) { ret[0] = ((GeoFunctionable) (ret[0])).getGeoFunction(); } return ret; }
private GeoElement[] processPointVector(ExpressionNode n, ExpressionValue evaluate) { String label = n.getLabel(); GeoVec2D p = (GeoVec2D) ((VectorValue) evaluate).getVector(); boolean polar = p.getMode() == Kernel.COORD_POLAR; // we want z = 3 + i to give a (complex) GeoPoint not a GeoVector boolean complex = p.getMode() == Kernel.COORD_COMPLEX; GeoVec3D[] ret = new GeoVec3D[1]; boolean isIndependent = n.isConstant(); // make point if complex parts are present, e.g. 3 + i if (complex) { n.setForcePoint(); } // make vector, if label begins with lowercase character else if (label != null) { if (!(n.isForcedPoint() || n.isForcedVector())) { // may be set by MyXMLHandler if (Character.isLowerCase(label.charAt(0))) n.setForceVector(); else n.setForcePoint(); } } boolean isVector = n.isVectorValue(); if (isIndependent) { // get coords double x = p.getX(); double y = p.getY(); if (isVector) ret[0] = kernel.Vector(label, x, y); else ret[0] = kernel.Point(label, x, y, complex); } else { if (isVector) ret[0] = kernel.DependentVector(label, n); else ret[0] = kernel.DependentPoint(label, n, complex); } if (polar) { ret[0].setMode(Kernel.COORD_POLAR); ret[0].updateRepaint(); } else if (complex) { ret[0].setMode(Kernel.COORD_COMPLEX); ret[0].updateRepaint(); } return ret; }
// evaluate the current value of the arithmetic tree protected final void compute() { // get resulting list of ExpressionNodes ExpressionValue evlist = root.evaluate(); MyList myList = (evlist instanceof MyList) ? (MyList) evlist : ((GeoList) evlist).getMyList(); int evalListSize = myList.size(); int cachedListSize = list.getCacheSize(); list.clear(); for (int i = 0; i < evalListSize; i++) { ExpressionValue element = myList.getListElement(i).evaluate(); GeoElement geo = null; // number result if (element.isNumberValue()) { double val = ((NumberValue) element).getDouble(); // try to use cached element of same type if (i < cachedListSize) { GeoElement cachedGeo = list.getCached(i); // the cached element is a number: set value if (cachedGeo.isGeoNumeric()) { ((GeoNumeric) cachedGeo).setValue(val); geo = cachedGeo; } } // no cached number: create new one if (geo == null) { geo = new GeoNumeric(cons, val); } // add number to list list.add(geo); } // point else if (element.isVectorValue()) { GeoVec2D vec = ((VectorValue) element).getVector(); // try to use cached element of same type if (i < cachedListSize) { GeoElement cachedGeo = list.getCached(i); // the cached element is a point: set value if (cachedGeo.isGeoPoint()) { ((GeoPoint) cachedGeo).setCoords(vec); geo = cachedGeo; } } // no cached point: create new one if (geo == null) { GeoPoint point = new GeoPoint(cons); point.setCoords(vec); geo = point; } // add point to list list.add(geo); } // needed for matrix multiplication // eg {{1,3,5},{2,4,6}}*{{11,14},{12,15},{13,a}} else if (element instanceof MyList) { MyList myList2 = (MyList) element; GeoList list2 = new GeoList(cons); list2.clear(); /* removed Michael Borcherds 20080602 * bug: 9PointCubic.ggb (matrix multiplication) // try to use cached element of type GeoList GeoList list2 = null; if (i < cachedListSize) { GeoElement cachedGeo = list.getCached(i); // the cached element is a number: set value if (cachedGeo.isGeoList()) { list2 = (GeoList) cachedGeo; } } if (list2 == null) { list2 = new GeoList(cons); } */ for (int j = 0; j < myList2.size(); j++) { ExpressionValue en = myList2.getListElement(j); ExpressionValue ev = en.evaluate(); if (ev instanceof MyDouble) { GeoNumeric geo2 = new GeoNumeric(cons); geo2.setValue(((NumberValue) ev).getDouble()); list2.add(geo2); } } list.add(list2); } else if (element instanceof MyStringBuffer) { MyStringBuffer str = (MyStringBuffer) element; // try to use cached element of same type if (i < cachedListSize) { GeoElement cachedGeo = list.getCached(i); // the cached element is a point: set value if (cachedGeo.isGeoText()) { ((GeoText) cachedGeo).setTextString(str.toValueString()); geo = cachedGeo; } } // no cached point: create new one if (geo == null) { GeoText text = new GeoText(cons); text.setTextString(str.toValueString()); geo = text; } // add point to list list.add(geo); } else if (element instanceof MyBoolean) { MyBoolean bool = (MyBoolean) element; // try to use cached element of same type if (i < cachedListSize) { GeoElement cachedGeo = list.getCached(i); // the cached element is a point: set value if (cachedGeo.isGeoBoolean()) { ((GeoBoolean) cachedGeo).setValue(bool.getBoolean()); geo = cachedGeo; } } // no cached point: create new one if (geo == null) { GeoBoolean geoBool = new GeoBoolean(cons); geoBool.setValue(bool.getBoolean()); geo = geoBool; } // add point to list list.add(geo); } else if (element instanceof GeoFunction) { GeoFunction fun = (GeoFunction) element; if (i < cachedListSize) { GeoElement cachedGeo = list.getCached(i); // the cached element is a point: set value if (cachedGeo.isGeoFunction()) { ((GeoFunction) cachedGeo).set(fun); geo = cachedGeo; } } // no cached point: create new one if (geo == null) { GeoFunction geoFun = new GeoFunction(cons); geoFun.set(fun); geo = geoFun; } list.add(geo); } else { Application.debug("unsupported list addition: " + element.getClass() + ""); } } }
public final String toRealString() { // was defined as e.g. L = 3 * {a, b, c} return root.toRealString(); }
public GeoElement[] processExpressionNode(ExpressionNode n) throws MyError { // command is leaf: process command if (n.isLeaf()) { ExpressionValue leaf = n.getLeft(); if (leaf instanceof Command) { Command c = (Command) leaf; c.setLabels(n.getLabels()); return cmdDispatcher.processCommand(c, true); } else if (leaf instanceof Equation) { Equation eqn = (Equation) leaf; eqn.setLabels(n.getLabels()); return processEquation(eqn); } else if (leaf instanceof Function) { Function fun = (Function) leaf; fun.setLabels(n.getLabels()); return processFunction(n, fun); } else if (leaf instanceof FunctionNVar) { FunctionNVar fun = (FunctionNVar) leaf; fun.setLabels(n.getLabels()); return processFunctionNVar(n, fun); } } // ELSE: resolve variables and evaluate expressionnode n.resolveVariables(); eval = n.evaluate(); boolean dollarLabelFound = false; ExpressionNode myNode = n; if (myNode.isLeaf()) myNode = myNode.getLeftTree(); // leaf (no new label specified): just return the existing GeoElement if (eval.isGeoElement() && n.getLabel() == null && !(n.operation.equals(Operation.ELEMENT_OF))) { // take care of spreadsheet $ names: don't loose the wrapper ExpressionNode here // check if we have a Variable switch (myNode.getOperation()) { case $VAR_COL: case $VAR_ROW: case $VAR_ROW_COL: // don't do anything here: we need to keep the wrapper ExpressionNode // and must not return the GeoElement here dollarLabelFound = true; break; default: // return the GeoElement GeoElement[] ret = {(GeoElement) eval}; return ret; } } if (eval.isBooleanValue()) return processBoolean(n, eval); else if (eval.isNumberValue()) return processNumber(n, eval); else if (eval.isVectorValue()) return processPointVector(n, eval); else if (eval.isVector3DValue()) return processPointVector3D(n, eval); else if (eval.isTextValue()) return processText(n, eval); else if (eval instanceof MyList) { return processList(n, (MyList) eval); } else if (eval instanceof Function) { return processFunction(n, (Function) eval); } else if (eval instanceof FunctionNVar) { return processFunctionNVar(n, (FunctionNVar) eval); } // we have to process list in case list=matrix1(1), but not when list=list2 else if (eval instanceof GeoList && myNode.hasOperations()) { Application.debug("should work"); return processList(n, ((GeoList) eval).getMyList()); } else if (eval.isGeoElement()) { // e.g. B1 = A1 where A1 is a GeoElement and B1 does not exist yet // create a copy of A1 if (n.getLabel() != null || dollarLabelFound) { return processGeoCopy(n.getLabel(), n); } } // REMOVED due to issue 131: http://code.google.com/p/geogebra/issues/detail?id=131 // // expressions like 2 a (where a:x + y = 1) // // A1=b doesn't work for these objects // else if (eval instanceof GeoLine) { // if (((GeoLine)eval).getParentAlgorithm() instanceof AlgoDependentLine) { // GeoElement[] ret = {(GeoElement) eval }; // return ret; // } // // } // if we get here, nothing worked Application.debug("Unhandled ExpressionNode: " + eval + ", " + eval.getClass()); return null; }