/*
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;
}
}