public GeoElement[] processFunction(ExpressionNode funNode, Function fun) { fun.initFunction(); String label = fun.getLabel(); GeoFunction f; GeoElement[] ret = new GeoElement[1]; GeoElement[] vars = fun.getGeoElementVariables(); boolean isIndependent = (vars == null || vars.length == 0); // check for interval ExpressionNode en = fun.getExpression(); if (en.operation.equals(Operation.AND)) { ExpressionValue left = en.left; ExpressionValue right = en.right; if (left.isExpressionNode() && right.isExpressionNode()) { ExpressionNode enLeft = (ExpressionNode) left; ExpressionNode enRight = (ExpressionNode) right; Operation opLeft = enLeft.operation; Operation opRight = enRight.operation; ExpressionValue leftLeft = enLeft.left; ExpressionValue leftRight = enLeft.right; ExpressionValue rightLeft = enRight.left; ExpressionValue rightRight = enRight.right; // directions of inequalities, need one + and one - for an interval int leftDir = 0; int rightDir = 0; if ((opLeft.equals(Operation.LESS) || opLeft.equals(Operation.LESS_EQUAL))) { if (leftLeft instanceof FunctionVariable && leftRight.isNumberValue()) leftDir = -1; else if (leftRight instanceof FunctionVariable && leftLeft.isNumberValue()) leftDir = +1; } else if ((opLeft.equals(Operation.GREATER) || opLeft.equals(Operation.GREATER_EQUAL))) { if (leftLeft instanceof FunctionVariable && leftRight.isNumberValue()) leftDir = +1; else if (leftRight instanceof FunctionVariable && leftLeft.isNumberValue()) leftDir = -1; } if ((opRight.equals(Operation.LESS) || opRight.equals(Operation.LESS_EQUAL))) { if (rightLeft instanceof FunctionVariable && rightRight.isNumberValue()) rightDir = -1; else if (rightRight instanceof FunctionVariable && rightLeft.isNumberValue()) rightDir = +1; } else if ((opRight.equals(Operation.GREATER) || opRight.equals(Operation.GREATER_EQUAL))) { if (rightLeft instanceof FunctionVariable && rightRight.isNumberValue()) rightDir = +1; else if (rightRight instanceof FunctionVariable && rightLeft.isNumberValue()) rightDir = -1; } // Application.debug(leftDir+" "+rightDir); // Application.debug(leftLeft.getClass()+" "+leftRight.getClass()); // Application.debug(rightLeft.getClass()+" "+rightRight.getClass()); // opposite directions -> OK if (leftDir * rightDir < 0) { if (isIndependent) { f = kernel.Interval(label, fun); } else { f = kernel.DependentInterval(label, fun); } ret[0] = f; return ret; } // Application.debug(enLeft.operation+""); // Application.debug(enLeft.left.getClass()+""); // Application.debug(enLeft.right.getClass()+""); } // Application.debug(left.getClass()+""); // Application.debug(right.getClass()+""); // Application.debug(""); } else if (en.operation.equals(Operation.FUNCTION)) { ExpressionValue left = en.left; ExpressionValue right = en.right; if (left.isLeaf() && left.isGeoElement() && right.isLeaf() && right.isNumberValue() && !isIndependent) { f = (GeoFunction) kernel.DependentGeoCopy(label, (GeoElement) left); ret[0] = f; return ret; } } if (isIndependent) { f = kernel.Function(label, fun); } else { f = kernel.DependentFunction(label, fun); } ret[0] = f; return ret; }
public GeoElement[] processEquation(Equation equ) throws MyError { // Application.debug("EQUATION: " + equ); // Application.debug("NORMALFORM POLYNOMIAL: " + equ.getNormalForm()); try { equ.initEquation(); // Application.debug("EQUATION: " + equ.getNormalForm()); // check no terms in z checkNoTermsInZ(equ); if (equ.isFunctionDependent()) { return processImplicitPoly(equ); } // consider algebraic degree of equation // check not equation of eg plane switch (equ.degree()) { // linear equation -> LINE case 1: return processLine(equ, false); // quadratic equation -> CONIC case 2: return processConic(equ); default: // test for "y= <rhs>" here as well if (equ.getLHS().toString().trim().equals("y")) { Function fun = new Function(equ.getRHS()); // try to use label of equation fun.setLabel(equ.getLabel()); return processFunction(null, fun); } return processImplicitPoly(equ); } } catch (MyError eqnError) { eqnError.printStackTrace(); // invalid equation: maybe a function of form "y = <rhs>"? String lhsStr = equ.getLHS().toString().trim(); if (lhsStr.equals("y")) { try { // try to create function from right hand side Function fun = new Function(equ.getRHS()); // try to use label of equation fun.setLabel(equ.getLabel()); return processFunction(null, fun); } catch (MyError funError) { funError.printStackTrace(); } } // throw invalid equation error if we get here if (eqnError.getMessage() == "InvalidEquation") throw eqnError; else { String[] errors = {"InvalidEquation", eqnError.getLocalizedMessage()}; throw new MyError(app, errors); } } }
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; }