/* 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. */ /* * AlgoCirclePointRadius.java * * Created on 15. November 2001, 21:37 */ package org.geogebra.common.kernel.algos; import org.geogebra.common.euclidian.EuclidianConstants; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.StringTemplate; import org.geogebra.common.kernel.commands.Commands; import org.geogebra.common.kernel.geos.GeoConic; import org.geogebra.common.kernel.geos.GeoNumberValue; import org.geogebra.common.kernel.geos.GeoNumeric; import org.geogebra.common.kernel.geos.GeoPoint; import org.geogebra.common.kernel.geos.GeoSegment; import org.geogebra.common.kernel.kernelND.GeoElementND; import org.geogebra.common.kernel.kernelND.GeoQuadricND; import org.geogebra.common.kernel.prover.NoSymbolicParametersException; import org.geogebra.common.kernel.prover.polynomial.PPolynomial; import org.geogebra.common.kernel.prover.polynomial.PVariable; /** * * @author Markus added TYPE_SEGMENT Michael Borcherds 2008-03-14 */ public class AlgoCirclePointRadius extends AlgoSphereNDPointRadius implements AlgoCirclePointRadiusInterface, SymbolicParametersBotanaAlgo { private PVariable[] botanaVars; private PPolynomial[] botanaPolynomials; public AlgoCirclePointRadius(Construction cons, GeoPoint M, GeoNumberValue r) { super(cons, M, r); } AlgoCirclePointRadius(Construction cons, GeoPoint M, GeoSegment rgeo) { super(cons, M, rgeo); } @Override protected GeoQuadricND createSphereND(Construction cons1) { return new GeoConic(cons1); } @Override public Commands getClassName() { return Commands.Circle; } @Override public int getRelatedModeID() { switch (super.getType()) { case AlgoSphereNDPointRadius.TYPE_RADIUS: return EuclidianConstants.MODE_CIRCLE_POINT_RADIUS; default: return EuclidianConstants.MODE_COMPASSES; } } public GeoConic getCircle() { return (GeoConic) getSphereND(); } @Override final public String toString(StringTemplate tpl) { // Michael Borcherds 2008-03-30 // simplified to allow better Chinese translation return getLoc().getPlain("CircleWithCenterAandRadiusB", getM().getLabel(tpl), getRGeo().getLabel(tpl)); } @Override public PVariable[] getBotanaVars(GeoElementND geo) { return botanaVars; } @Override public PPolynomial[] getBotanaPolynomials(GeoElementND geo) throws NoSymbolicParametersException { if (botanaPolynomials != null) { return botanaPolynomials; } GeoPoint P = (GeoPoint) this.getInput(0); /* SPECIAL CASE 1: radius is a segment */ if (this.getInput(1) instanceof GeoSegment) { /* * Here we do the full work for this segment. It would be nicer to * put this code into GeoSegment but we need to use the square of * the length of the segment in this special case. */ GeoSegment s = (GeoSegment) this.getInput(1); if (botanaVars == null) { PVariable[] centerBotanaVars = P.getBotanaVars(P); botanaVars = new PVariable[4]; // center P botanaVars[0] = centerBotanaVars[0]; botanaVars[1] = centerBotanaVars[1]; // point C on the circle botanaVars[2] = new PVariable(kernel); botanaVars[3] = new PVariable(kernel); } GeoPoint A = s.getStartPoint(); GeoPoint B = s.getEndPoint(); PVariable[] ABotanaVars = A.getBotanaVars(A); PVariable[] BBotanaVars = B.getBotanaVars(B); botanaPolynomials = new PPolynomial[2]; // C-P == B-A <=> C-P-B+A == 0 botanaPolynomials[0] = new PPolynomial(botanaVars[2]) .subtract(new PPolynomial(botanaVars[0])) .subtract(new PPolynomial(BBotanaVars[0])) .add(new PPolynomial(ABotanaVars[0])); botanaPolynomials[1] = new PPolynomial(botanaVars[3]) .subtract(new PPolynomial(botanaVars[1])) .subtract(new PPolynomial(BBotanaVars[1])) .add(new PPolynomial(ABotanaVars[1])); // done for both coordinates! return botanaPolynomials; } /* SPECIAL CASE 2: radius is an expression */ GeoNumeric num = null; if (this.getInput(1) instanceof GeoNumeric) { num = (GeoNumeric) this.getInput(1); } if (P == null || num == null) { throw new NoSymbolicParametersException(); } if (botanaVars == null) { PVariable[] centerBotanaVars = P.getBotanaVars(P); botanaVars = new PVariable[5]; // center botanaVars[0] = centerBotanaVars[0]; botanaVars[1] = centerBotanaVars[1]; // point on circle botanaVars[2] = new PVariable(kernel); botanaVars[3] = new PVariable(kernel); // radius botanaVars[4] = new PVariable(kernel); } PPolynomial[] extraPolys = null; if (num.getParentAlgorithm() instanceof AlgoDependentNumber) { extraPolys = num.getBotanaPolynomials(num); botanaPolynomials = new PPolynomial[extraPolys.length + 1]; } else { botanaPolynomials = new PPolynomial[1]; } /* * Note that we read the Botana variables just after reading the Botana * polynomials since the variables are set after the polys are set. */ PVariable[] radiusBotanaVars = num.getBotanaVars(num); int k = 0; // r^2 PPolynomial sqrR = PPolynomial.sqr(new PPolynomial(radiusBotanaVars[0])); // define radius if (extraPolys != null) { botanaPolynomials = new PPolynomial[extraPolys.length + 1]; for (k = 0; k < extraPolys.length; k++) { botanaPolynomials[k] = extraPolys[k]; } } // define circle botanaPolynomials[k] = PPolynomial.sqrDistance(botanaVars[0], botanaVars[1], botanaVars[2], botanaVars[3]).subtract(sqrR); return botanaPolynomials; } }