/* 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. */ /* * AlgoMidPoint.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.Construction; import org.geogebra.common.kernel.StringTemplate; 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.GeoSegment; import org.geogebra.common.kernel.kernelND.GeoElementND; 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 */ public class AlgoMidpointSegment extends AlgoElement implements SymbolicParametersAlgo, SymbolicParametersBotanaAlgo { private GeoSegment segment; // input private GeoPoint M; // output private GeoPoint P, Q; // endpoints of segment private PPolynomial[] polynomials; private PVariable[] botanaVars; private PPolynomial[] botanaPolynomials; /** * Creates new AlgoMidpointSegment * * @param cons * construction * @param segment * segment */ AlgoMidpointSegment(Construction cons, GeoSegment segment) { super(cons); this.segment = segment; // create new Point M = new GeoPoint(cons); setInputOutput(); // compute M = (P + Q)/2 compute(); } @Override public Commands getClassName() { return Commands.Midpoint; } @Override public int getRelatedModeID() { return EuclidianConstants.MODE_MIDPOINT; } // for AlgoElement @Override protected void setInputOutput() { input = new GeoElement[1]; input[0] = segment; super.setOutputLength(1); super.setOutput(0, M); setDependencies(); // done by AlgoElement } /** * Created for LocusEqu * * @return startpoint */ public GeoPoint getP() { return P; } /** * Created for LocusEqu * * @return endpoint */ public GeoPoint getQ() { return Q; } /** * @return midpoint */ public GeoPoint getPoint() { return M; } // calc midpoint @Override public final void compute() { if (!segment.isDefined()) { M.setUndefined(); return; } P = segment.getStartPoint(); Q = segment.getEndPoint(); boolean pInf = P.isInfinite(); boolean qInf = Q.isInfinite(); if (!pInf && !qInf) { // M = (P + Q) / 2 M.setCoords((P.inhomX + Q.inhomX) / 2.0d, (P.inhomY + Q.inhomY) / 2.0d, 1.0); } else if (pInf && qInf) { M.setUndefined(); } else if (pInf) { M.setCoords(P); } else { // qInf M.setCoords(Q); } } @Override final public String toString(StringTemplate tpl) { // Michael Borcherds 2008-03-30 // simplified to allow better Chinese translation return getLoc().getPlain("MidpointOfA", segment.getLabel(tpl)); } @Override public SymbolicParameters getSymbolicParameters() { return new SymbolicParameters(this); } @Override public void getFreeVariables(HashSet<PVariable> variables) throws NoSymbolicParametersException { if (P != null && Q != null) { P.getFreeVariables(variables); Q.getFreeVariables(variables); return; } throw new NoSymbolicParametersException(); } @Override public int[] getDegrees() throws NoSymbolicParametersException { if (P != null && Q != null) { int[] degreeP = P.getDegrees(); int[] degreeQ = Q.getDegrees(); int[] result = new int[3]; result[0] = Math.max(degreeP[0] + degreeQ[2], degreeQ[0] + degreeP[2]); result[1] = Math.max(degreeP[1] + degreeQ[2], degreeQ[1] + degreeP[2]); result[2] = degreeP[2] + degreeQ[2]; return result; } throw new NoSymbolicParametersException(); } @Override public BigInteger[] getExactCoordinates( HashMap<PVariable, BigInteger> values) throws NoSymbolicParametersException { if (P != null && Q != null) { BigInteger[] pP = P.getExactCoordinates(values); BigInteger[] pQ = Q.getExactCoordinates(values); BigInteger[] coords = new BigInteger[3]; coords[0] = pP[0].multiply(pQ[2]).add(pQ[0].multiply(pP[2])); coords[1] = pP[1].multiply(pQ[2]).add(pQ[1].multiply(pP[2])); coords[2] = pP[2].multiply(pQ[2]).multiply(BigInteger.valueOf(2)); return coords; } throw new NoSymbolicParametersException(); } @Override public PPolynomial[] getPolynomials() throws NoSymbolicParametersException { if (polynomials != null) { return polynomials; } if (P != null && Q != null) { PPolynomial[] pP = P.getPolynomials(); PPolynomial[] pQ = Q.getPolynomials(); polynomials = new PPolynomial[3]; polynomials[0] = pP[0].multiply(pQ[2]).add(pQ[0].multiply(pP[2])); polynomials[1] = pP[1].multiply(pQ[2]).add(pQ[1].multiply(pP[2])); polynomials[2] = pP[2].multiply(pQ[2]).multiply(new PPolynomial(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; } if (P == null || Q == null) { throw new NoSymbolicParametersException(); } if (botanaVars == null) { botanaVars = new PVariable[2]; botanaVars[0] = new PVariable(kernel); botanaVars[1] = new PVariable(kernel); } botanaPolynomials = SymbolicParameters.botanaPolynomialsMidpoint(P, Q, botanaVars); return botanaPolynomials; } }