/*
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.
*/
/*
* AlgoIntersectLines.java
*
* Created on 30. August 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.Kernel;
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.GeoLine;
import org.geogebra.common.kernel.geos.GeoPoint;
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.prover.NoSymbolicParametersException;
import org.geogebra.common.kernel.prover.polynomial.PPolynomial;
import org.geogebra.common.kernel.prover.polynomial.PVariable;
/**
*
* @author Markus
*/
public class AlgoIntersectLines extends AlgoIntersectAbstract
implements SymbolicParametersAlgo, SymbolicParametersBotanaAlgo {
private GeoLine g, h; // input
private GeoPoint S; // output
private PPolynomial[] polynomials;
private PPolynomial[] botanaPolynomials;
private PVariable[] botanaVars;
/** Creates new AlgoJoinPoints */
public AlgoIntersectLines(Construction cons, String label, GeoLine g,
GeoLine h) {
super(cons);
this.g = g;
this.h = h;
S = new GeoPoint(cons);
setInputOutput(); // for AlgoElement
// compute line through P, Q
compute();
S.setLabel(label);
addIncidence();
}
/**
* @author Tam
*
* for special cases of e.g. AlgoIntersectLineConic
*/
private void addIncidence() {
S.addIncidence(g, false);
S.addIncidence(h, false);
}
@Override
public Commands getClassName() {
return Commands.Intersect;
}
@Override
public int getRelatedModeID() {
return EuclidianConstants.MODE_INTERSECT;
}
// for AlgoElement
@Override
protected void setInputOutput() {
input = new GeoElement[2];
input[0] = g;
input[1] = h;
super.setOutputLength(1);
super.setOutput(0, S);
setDependencies(); // done by AlgoElement
}
public GeoPoint getPoint() {
return S;
}
// Made public for LocusEqu
public GeoLine geth() {
return g;
}
// Made public for LocusEqu
public GeoLine getg() {
return h;
}
// calc intersection S of lines g, h
@Override
public final void compute() {
GeoVec3D.cross(g, h, S);
// test the intersection point
// this is needed for the intersection of segments
if (S.isDefined()) {
if (!(g.isIntersectionPointIncident(S, Kernel.MIN_PRECISION)
&& h.isIntersectionPointIncident(S, Kernel.MIN_PRECISION))) {
S.setUndefined();
}
}
}
@Override
final public String toString(StringTemplate tpl) {
// Michael Borcherds 2008-03-30
// simplified to allow better Chinese translation
return getLoc().getPlain("IntersectionPointOfAB", g.getLabel(tpl),
h.getLabel(tpl));
}
@Override
public SymbolicParameters getSymbolicParameters() {
return new SymbolicParameters(this);
}
@Override
public void getFreeVariables(HashSet<PVariable> variables)
throws NoSymbolicParametersException {
if ((g instanceof GeoSegment) || (h instanceof GeoSegment)) {
throw new NoSymbolicParametersException();
}
if (g != null && h != null) {
g.getFreeVariables(variables);
h.getFreeVariables(variables);
return;
}
throw new NoSymbolicParametersException();
}
@Override
public int[] getDegrees() throws NoSymbolicParametersException {
if ((g instanceof GeoSegment) || (h instanceof GeoSegment)) {
throw new NoSymbolicParametersException();
}
if (g != null && h != null) {
int[] degree1 = g.getDegrees();
int[] degree2 = h.getDegrees();
return SymbolicParameters.crossDegree(degree1, degree2);
}
throw new NoSymbolicParametersException();
}
@Override
public BigInteger[] getExactCoordinates(
final HashMap<PVariable, BigInteger> values)
throws NoSymbolicParametersException {
if ((g instanceof GeoSegment) || (h instanceof GeoSegment)) {
throw new NoSymbolicParametersException();
}
if (g != null && h != null) {
BigInteger[] coords1 = g.getExactCoordinates(values);
BigInteger[] coords2 = h.getExactCoordinates(values);
return SymbolicParameters.crossProduct(coords1, coords2);
}
throw new NoSymbolicParametersException();
}
@Override
public PPolynomial[] getPolynomials() throws NoSymbolicParametersException {
if (polynomials != null) {
return polynomials;
}
if ((g instanceof GeoSegment) || (h instanceof GeoSegment)) {
throw new NoSymbolicParametersException();
}
if (g != null && h != null) {
PPolynomial[] coords1 = g.getPolynomials();
PPolynomial[] coords2 = h.getPolynomials();
polynomials = PPolynomial.crossProduct(coords1, coords2);
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;
}
/*
* In fact we cannot decide a statement properly if any of the inputs is
* a segment, at least not algebraically (without using cylindrical
* algebraic decomposition or such). But since we are doing constructive
* geometry, it's better to assume that segment intersection is not a
* real problem. TODO: Consider adding an NDG somehow in this case (but
* maybe not really important and useful).
*
* See also AlgoIntersectLineConic.
*/
if (g != null
&& h != null /* && !g.isGeoSegment() && !h.isGeoSegment() */) {
if (botanaVars == null) {
botanaVars = new PVariable[2];
botanaVars[0] = new PVariable(kernel);
botanaVars[1] = new PVariable(kernel);
}
PVariable[] fv = g.getBotanaVars(g);
botanaPolynomials = new PPolynomial[2];
botanaPolynomials[0] = PPolynomial.collinear(fv[0], fv[1], fv[2],
fv[3], botanaVars[0], botanaVars[1]);
fv = h.getBotanaVars(h);
botanaPolynomials[1] = PPolynomial.collinear(fv[0], fv[1], fv[2],
fv[3], botanaVars[0], botanaVars[1]);
return botanaPolynomials;
}
throw new NoSymbolicParametersException();
}
}