/* GeoGebra - Dynamic Mathematics for Everyone http://www.geogebra.org This file is part of GeoGebra. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. */ /* * AlgoVector.java * * Created on 24. September 2001, 21:37 */ package org.geogebra.common.kernel.algos; import java.math.BigInteger; import java.util.HashMap; import java.util.HashSet; import org.geogebra.common.euclidian.EuclidianConstants; import org.geogebra.common.kernel.CircularDefinitionException; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.commands.Commands; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoPoint; import org.geogebra.common.kernel.geos.GeoVector; import org.geogebra.common.kernel.kernelND.GeoElementND; import org.geogebra.common.kernel.kernelND.GeoPointND; import org.geogebra.common.kernel.kernelND.GeoVectorND; import org.geogebra.common.kernel.prover.NoSymbolicParametersException; import org.geogebra.common.kernel.prover.polynomial.PPolynomial; import org.geogebra.common.kernel.prover.polynomial.PVariable; /** * Vector between two points P and Q. * * @author Markus */ public class AlgoVector extends AlgoElement implements SymbolicParametersAlgo, SymbolicParametersBotanaAlgo { private GeoPointND P, Q; // input private GeoVectorND v; // output private PPolynomial[] polynomials; private PPolynomial[] botanaPolynomials; private PVariable[] botanaVars; /** * Creates new AlgoVector * * @param cons * construction * @param label * label for output * @param P * start point * @param Q * end point */ public AlgoVector(Construction cons, String label, GeoPointND P, GeoPointND Q) { super(cons); this.P = P; this.Q = Q; // create new vector v = createNewVector(); // v = new GeoVector(cons); // set dependencies now to make sure the vector v is // not added to the locatable list of P // see #2462 setInputOutput(); // set startpoint of vector try { if (P.isLabelSet()) { v.setStartPoint(P); } else { GeoPointND startPoint = newStartPoint(); // GeoPoint startPoint = new GeoPoint(P); startPoint.set(P); v.setStartPoint(startPoint); } } catch (CircularDefinitionException e) { // just formal; v is new, so can't really cause this } // compute vector PQ compute(); v.setLabel(label); } /** * @return new vector (overriden in 3D) */ protected GeoVectorND createNewVector() { return new GeoVector(cons); } /** * @return copy of P (overriden in 3D) */ protected GeoPointND newStartPoint() { return new GeoPoint((GeoPoint) P); } @Override public Commands getClassName() { return Commands.Vector; } @Override public int getRelatedModeID() { return EuclidianConstants.MODE_VECTOR; } // for AlgoElement @Override public void setInputOutput() { input = new GeoElement[2]; input[0] = (GeoElement) P; input[1] = (GeoElement) Q; super.setOutputLength(1); super.setOutput(0, (GeoElement) v); setDependencies(); // done by AlgoElement } /** * @return output vector */ public GeoVectorND getVector() { return v; } /** * @return input start point */ public GeoPointND getP() { return P; } /** * @return input end point */ public GeoPointND getQ() { return Q; } // calc the vector between P and Q @Override public final void compute() { if (P.isFinite() && Q.isFinite()) { setCoords(); // update position of unlabeled startpoint GeoPointND startPoint = v.getStartPoint(); if (startPoint != null) { if (!startPoint.isLabelSet()) { startPoint.set(P); } } } else { v.setUndefined(); } } /** * Updates coords of v using the strtpoint and endpoint */ protected void setCoords() { v.setCoords(P.vectorTo(Q)); } @Override public SymbolicParameters getSymbolicParameters() { return new SymbolicParameters(this); } @Override public void getFreeVariables(HashSet<PVariable> variables) throws NoSymbolicParametersException { if (P != null && Q != null && P instanceof SymbolicParametersAlgo && Q instanceof SymbolicParametersAlgo) { ((SymbolicParametersAlgo) P).getFreeVariables(variables); ((SymbolicParametersAlgo) Q).getFreeVariables(variables); return; } throw new NoSymbolicParametersException(); } @Override public int[] getDegrees() throws NoSymbolicParametersException { if (P != null && Q != null && P instanceof SymbolicParametersAlgo && Q instanceof SymbolicParametersAlgo) { int[] degree1 = ((SymbolicParametersAlgo) P).getDegrees(); int[] degree2 = ((SymbolicParametersAlgo) Q).getDegrees(); int[] result = new int[3]; result[0] = Math.max(degree1[0] + degree2[2], degree2[0] + degree1[2]); result[1] = Math.max(degree1[1] + degree2[2], degree2[1] + degree1[2]); result[2] = degree2[2] + degree1[2]; return result; } throw new NoSymbolicParametersException(); } @Override public BigInteger[] getExactCoordinates( final HashMap<PVariable, BigInteger> values) throws NoSymbolicParametersException { if (P != null && Q != null && P instanceof SymbolicParametersAlgo && Q instanceof SymbolicParametersAlgo) { BigInteger[] coords1 = ((SymbolicParametersAlgo) P) .getExactCoordinates(values); BigInteger[] coords2 = ((SymbolicParametersAlgo) Q) .getExactCoordinates(values); BigInteger[] result = new BigInteger[3]; result[0] = coords2[0].multiply(coords1[2]) .subtract(coords1[0].multiply(coords2[2])); result[1] = coords2[1].multiply(coords1[2]) .subtract(coords1[1].multiply(coords2[2])); result[2] = coords1[2].multiply(coords2[2]); return SymbolicParameters.reduce(result); } return null; } @Override public PPolynomial[] getPolynomials() throws NoSymbolicParametersException { if (polynomials != null) { return polynomials; } if (P != null && Q != null && P instanceof SymbolicParametersAlgo && Q instanceof SymbolicParametersAlgo) { PPolynomial[] coords1 = ((SymbolicParametersAlgo) P) .getPolynomials(); PPolynomial[] coords2 = ((SymbolicParametersAlgo) Q) .getPolynomials(); polynomials = new PPolynomial[3]; polynomials[0] = coords2[0].multiply(coords1[2]) .subtract(coords1[0].multiply(coords2[2])); polynomials[1] = coords2[1].multiply(coords1[2]) .subtract(coords1[1].multiply(coords2[2])); polynomials[2] = coords1[2].multiply(coords2[2]); return polynomials; } throw new NoSymbolicParametersException(); } @Override public PVariable[] getBotanaVars(GeoElementND geo) { return botanaVars; } @Override public PPolynomial[] getBotanaPolynomials(GeoElementND geo) throws NoSymbolicParametersException { if (botanaPolynomials != null) { return botanaPolynomials; } GeoPoint A = (GeoPoint) P; GeoPoint B = (GeoPoint) Q; if (P != null && Q != null) { PVariable[] vP = A.getBotanaVars(A); PVariable[] vQ = B.getBotanaVars(B); if (botanaVars == null) { botanaVars = new PVariable[6]; // vector u botanaVars[0] = new PVariable(kernel); botanaVars[1] = new PVariable(kernel); // P botanaVars[2] = vP[0]; botanaVars[3] = vP[1]; // Q botanaVars[4] = vQ[0]; botanaVars[5] = vQ[1]; } botanaPolynomials = new PPolynomial[2]; PPolynomial p1 = new PPolynomial(vP[0]); PPolynomial p2 = new PPolynomial(vP[1]); PPolynomial q1 = new PPolynomial(vQ[0]); PPolynomial q2 = new PPolynomial(vQ[1]); PPolynomial u1 = new PPolynomial(botanaVars[0]); PPolynomial u2 = new PPolynomial(botanaVars[1]); botanaPolynomials[0] = u1.subtract(q1).add(p1); botanaPolynomials[1] = u2.subtract(q2).add(p2); return botanaPolynomials; } throw new NoSymbolicParametersException(); } }