/*
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.
*/
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.GeoConicPart;
import org.geogebra.common.kernel.geos.GeoElement;
import org.geogebra.common.kernel.geos.GeoPoint;
import org.geogebra.common.kernel.kernelND.GeoConicNDConstants;
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;
/**
* Semicircle defined by two points A and B (start and end point).
*/
public class AlgoSemicircle extends AlgoElement
implements SymbolicParametersBotanaAlgo {
private GeoPoint A, B; // input
private GeoConicPart conicPart; // output
private GeoPoint M; // midpoint of AB
private GeoConic conic;
private PPolynomial[] botanaPolynomials;
private PVariable[] botanaVars;
/**
* Creates new semicircle algoritm
*
* @param cons
* construction
* @param label
* label for the semicircle
* @param A
* first endpoint
* @param B
* second endpoint
*/
public AlgoSemicircle(Construction cons, String label, GeoPoint A,
GeoPoint B) {
this(cons, A, B);
conicPart.setLabel(label);
}
/**
* Creates new unlabeled semicircle algoritm
*
* @param cons
* construction
* @param A
* first endpoint
* @param B
* second endpoint
*/
public AlgoSemicircle(Construction cons, GeoPoint A, GeoPoint B) {
super(cons);
this.A = A;
this.B = B;
// helper algo to get midpoint
AlgoMidpoint algom = new AlgoMidpoint(cons, A, B);
cons.removeFromConstructionList(algom);
M = algom.getPoint();
// helper algo to get circle
AlgoCircleTwoPoints algo = new AlgoCircleTwoPoints(cons, M, B);
cons.removeFromConstructionList(algo);
conic = algo.getCircle();
conicPart = new GeoConicPart(cons, GeoConicNDConstants.CONIC_PART_ARC);
conicPart.addPointOnConic(A);
conicPart.addPointOnConic(B);
setInputOutput(); // for AlgoElement
compute();
}
@Override
public Commands getClassName() {
return Commands.Semicircle;
}
@Override
public int getRelatedModeID() {
return EuclidianConstants.MODE_SEMICIRCLE;
}
// for AlgoElement
@Override
protected void setInputOutput() {
input = new GeoElement[2];
input[0] = A;
input[1] = B;
setOutputLength(1);
setOutput(0, conicPart);
setDependencies();
}
/**
* Returns the semicercle
*
* @return the semicircle
*/
public GeoConicPart getSemicircle() {
return conicPart;
}
/**
* Returns first endpoint
*
* @return first endpoint
*/
public GeoPoint getA() {
return A;
}
/**
* Returns second endpoint
*
* @return second endpoint
*/
public GeoPoint getB() {
return B;
}
/**
* Returns the full circle
*
* @return full circle
*/
public GeoConic getConic() {
return conic;
}
@Override
public void compute() {
if (!conic.isDefined()) {
conicPart.setUndefined();
return;
}
double alpha = Math.atan2(B.inhomY - A.inhomY, B.inhomX - A.inhomX);
double beta = alpha + Math.PI;
conicPart.set(conic);
conicPart.setParameters(alpha, beta, true);
}
// ///////////////////////////////
// TRICKS FOR XOY PLANE
// ///////////////////////////////
@Override
protected int getInputLengthForXML() {
return getInputLengthForXMLMayNeedXOYPlane();
}
@Override
protected int getInputLengthForCommandDescription() {
return getInputLengthForCommandDescriptionMayNeedXOYPlane();
}
@Override
public GeoElementND getInput(int i) {
return getInputMaybeXOYPlane(i);
}
@Override
public String toString(StringTemplate tpl) {
return getLoc().getPlain("SemicircleThroughAandB", A.getLabel(tpl),
B.getLabel(tpl));
}
@Override
public PVariable[] getBotanaVars(GeoElementND geo) {
return botanaVars;
}
@Override
public PPolynomial[] getBotanaPolynomials(GeoElementND geo)
throws NoSymbolicParametersException {
if (botanaPolynomials != null) {
return botanaPolynomials;
}
if (botanaVars == null) {
PVariable[] circle1vars;
PVariable[] centerVars = new PVariable[2];
circle1vars = ((SymbolicParametersBotanaAlgo) A).getBotanaVars(A);
centerVars[0] = new PVariable(kernel);
centerVars[1] = new PVariable(kernel);
botanaVars = new PVariable[4];
// Center:
botanaVars[0] = centerVars[0];
botanaVars[1] = centerVars[1];
// Point on the circle:
botanaVars[2] = circle1vars[0];
botanaVars[3] = circle1vars[1];
botanaPolynomials = SymbolicParameters.botanaPolynomialsMidpoint(A,
B, centerVars);
return botanaPolynomials;
}
// this should not happen:
throw new NoSymbolicParametersException();
}
}