/*
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.
*/
/*
* AlgoJoinPointsSegment
*
* Created on 21. August 2003
*/
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.GeoPolygon;
import org.geogebra.common.kernel.geos.GeoSegment;
import org.geogebra.common.kernel.geos.GeoVec3D;
import org.geogebra.common.kernel.kernelND.GeoElementND;
import org.geogebra.common.kernel.kernelND.GeoPointND;
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 AlgoJoinPointsSegment extends AlgoElement
implements AlgoJoinPointsSegmentInterface, SymbolicParametersBotanaAlgo,
SymbolicParametersAlgo {
private GeoPoint P, Q; // input
private GeoSegment s; // output: GeoSegment subclasses GeoLine
private GeoPolygon poly; // for polygons
private PVariable[] botanaVars;
private PPolynomial[] polynomials;
/** Creates new AlgoJoinPoints */
public AlgoJoinPointsSegment(Construction cons, String label, GeoPoint P,
GeoPoint Q) {
this(cons, P, Q, null, true);
s.setLabel(label);
}
public AlgoJoinPointsSegment(Construction cons, GeoPoint P, GeoPoint Q,
GeoPolygon poly, boolean addToConstructionList) {
super(cons, addToConstructionList);
// make sure that this helper algorithm is updated right after its
// parent polygon
if (poly != null) {
setUpdateAfterAlgo(poly.getParentAlgorithm());
setProtectedInput(true);
}
this.poly = poly;
this.P = P;
this.Q = Q;
s = new GeoSegment(cons, P, Q);
s.setFromMeta(poly);
setInputOutput(); // for AlgoElement
// compute line through P, Q
compute();
setIncidence();
}
private void setIncidence() {
P.addIncidence(s, true);
Q.addIncidence(s, true);
}
@Override
public Commands getClassName() {
return Commands.Segment;
}
@Override
public int getRelatedModeID() {
return EuclidianConstants.MODE_SEGMENT;
}
// for AlgoElement
@Override
protected void setInputOutput() {
GeoElement[] efficientInput = new GeoElement[2];
efficientInput[0] = P;
efficientInput[1] = Q;
if (poly == null) {
input = efficientInput;
} else {
input = new GeoElement[3];
input[0] = P;
input[1] = Q;
input[2] = poly;
// input = new GeoElement[2];
// input[0] = P;
// input[1] = Q;
}
super.setOutputLength(1);
super.setOutput(0, s);
// setDependencies();
setEfficientDependencies(input, efficientInput);
}
@Override
public void modifyInputPoints(GeoPointND A, GeoPointND B) {
// same points : return
if ((P == A && Q == B) || (Q == A && P == B)) {
return;
}
for (int i = 0; i < input.length; i++) {
input[i].removeAlgorithm(this);
}
P = (GeoPoint) A;
Q = (GeoPoint) B;
s.setPoints(P, Q);
setInputOutput();
compute();
}
public GeoSegment getSegment() {
return s;
}
// Made public for LocusEqu
public GeoPoint getP() {
return P;
}
// Made public for LocusEqu
public GeoPoint getQ() {
return Q;
}
@Override
public GeoPolygon getPoly() {// protected
return poly;
}
// calc the line g through P and Q
@Override
public final void compute() {
// g = P v Q <=> g_n : n = P x Q
// g = cross(P, Q)
GeoVec3D.lineThroughPoints(P, Q, s);
s.calcLength();
}
@Override
public void remove() {
if (removed) {
return;
}
super.remove();
if (poly != null) {
poly.remove();
}
}
/**
* Only removes this segment and does not remove parent polygon (if poly !=
* null)
*/
public void removeSegmentOnly() {
super.remove();
}
@Override
public int getConstructionIndex() {
if (poly != null) {
return poly.getConstructionIndex();
}
return super.getConstructionIndex();
}
@Override
final public String toString(StringTemplate tpl) {
// Michael Borcherds 2008-03-30
// simplified to allow better Chinese translation
if (poly != null) {
return getLoc().getPlain("SegmentABofC", P.getLabel(tpl),
Q.getLabel(tpl), poly.getNameDescription());
}
return getLoc().getPlain("SegmentAB", P.getLabel(tpl), Q.getLabel(tpl));
}
@Override
public PVariable[] getBotanaVars(GeoElementND geo)
throws NoSymbolicParametersException {
if (botanaVars == null) {
botanaVars = SymbolicParameters.addBotanaVarsJoinPoints(input);
}
return botanaVars;
}
@Override
public PPolynomial[] getBotanaPolynomials(GeoElementND geo)
throws NoSymbolicParametersException {
// It's OK, polynomials for lines/segments are only created when a third
// point is lying on them, too:
return null;
}
@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[] degree1 = P.getDegrees();
int[] degree2 = Q.getDegrees();
return SymbolicParameters.crossDegree(degree1, degree2);
}
throw new NoSymbolicParametersException();
}
@Override
public BigInteger[] getExactCoordinates(
final HashMap<PVariable, BigInteger> values)
throws NoSymbolicParametersException {
if (P != null && Q != null) {
BigInteger[] coords1 = P.getExactCoordinates(values);
BigInteger[] coords2 = Q.getExactCoordinates(values);
if (coords1 != null && coords2 != null) {
return SymbolicParameters.crossProduct(coords1, coords2);
}
}
throw new NoSymbolicParametersException();
}
@Override
public PPolynomial[] getPolynomials() throws NoSymbolicParametersException {
if (polynomials != null) {
return polynomials;
}
if (P != null && Q != null) {
PPolynomial[] coords1 = P.getPolynomials();
PPolynomial[] coords2 = Q.getPolynomials();
if (coords1 != null && coords2 != null) {
polynomials = PPolynomial.crossProduct(coords1, coords2);
return polynomials;
}
}
throw new NoSymbolicParametersException();
}
}