/*
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.implicit;
import org.geogebra.common.euclidian.EuclidianConstants;
import org.geogebra.common.kernel.Construction;
import org.geogebra.common.kernel.algos.AlgoElement;
import org.geogebra.common.kernel.algos.AlgoIntersect;
import org.geogebra.common.kernel.algos.AlgoPointOnPath;
import org.geogebra.common.kernel.algos.TangentAlgo;
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.kernelND.GeoLineND;
import org.geogebra.common.kernel.kernelND.GeoPointND;
/**
* Algorithm to calculate all tangents to the implicit polynomial equation
* either going threw a given point or parallel to given line.
*/
public class AlgoTangentImplicitpoly extends AlgoElement
implements TangentAlgo {
private GeoImplicit p;
private GeoPoint[] ip; // tangent points.
private OutputHandler<GeoLine> tangents;
private AlgoIntersect algoIntersect;
private String[] labels;
private AlgoTangentHelper algoTangentPoly;
/**
* @param c
* construction
* @param labels
* labels for output
* @param p
* implicit polynomial
*/
protected AlgoTangentImplicitpoly(Construction c, String[] labels,
GeoImplicit p) {
super(c);
this.labels = labels;
this.p = p;
}
/**
* To compute tangents to poly through given point
*
* @param c
* construction
* @param labels
* labels for output
* @param p
* implicit polynomial
* @param R
* point on tangent
*/
public AlgoTangentImplicitpoly(Construction c, String[] labels,
GeoImplicit p, GeoPointND R) {
this(c, labels, p);
boolean pointOnPath = false;
if (R.getParentAlgorithm() != null) {
if (R.getParentAlgorithm() instanceof AlgoPointOnPath) {
AlgoPointOnPath a = (AlgoPointOnPath) R.getParentAlgorithm();
if (a.getPath() == p) {
pointOnPath = true; // AlgoPointOnPath (on this curve)
}
}
}
this.algoTangentPoly = new AlgoImplicitPolyTangentCurve(c, p, R,
pointOnPath);
if (!pointOnPath) {
GeoImplicit tangentCurve = algoTangentPoly.getTangentCurve();
algoIntersect = new AlgoIntersectImplicitpolys(cons, p,
tangentCurve);
cons.removeFromConstructionList(algoIntersect);
ip = algoIntersect.getIntersectionPoints();
}
setInputOutput();
}
/**
* To compute tangents to poly in given direction
*
* @param c
* construction
*
* @param labels
* labels for output
*
* @param p
* implicit polynomial
*
* @param g
* line
*
*
* not working #4380
*/
public AlgoTangentImplicitpoly(Construction c, String[] labels,
GeoImplicit p, GeoLineND g) {
this(c, labels, p);
this.algoTangentPoly = new AlgoImplicitPolyTangentLine(
c, p, g);
GeoImplicit tangentCurve = algoTangentPoly.getTangentCurve();
algoIntersect = new AlgoIntersectImplicitpolys(cons, p, tangentCurve);
cons.removeFromConstructionList(algoIntersect);
ip = algoIntersect.getIntersectionPoints();
setInputOutput();
}
@Override
protected void setInputOutput() {
input = new GeoElement[2];
input[1] = p.toGeoElement();
input[0] = algoTangentPoly.getVec();
tangents = new OutputHandler<GeoLine>(new elementFactory<GeoLine>() {
@Override
public GeoLine newElement() {
GeoLine g1 = new GeoLine(getConstruction());
g1.setParentAlgorithm(AlgoTangentImplicitpoly.this);
return g1;
}
});
tangents.setLabels(labels);
setDependencies();
}
@Override
public void compute() {
// idea: find intersection points between given curve and
// tangent curve
// and construct lines through (x_p, y_p) and intersection points,
// where (x_p, y_p) is given point.
if (!algoTangentPoly.vecDefined()) {
tangents.adjustOutputSize(0);
return;
}
tangents.adjustOutputSize(0);
ip = algoIntersect == null ? null : algoIntersect
.getIntersectionPoints();
this.algoTangentPoly.getTangents(ip, tangents);
}
@Override
public Commands getClassName() {
return Commands.Tangent;
}
@Override
public int getRelatedModeID() {
return EuclidianConstants.MODE_TANGENTS;
}
/**
* @return resulting tangents
*/
public GeoLine[] getTangents() {
return tangents.getOutput(new GeoLine[tangents.size()]);
}
/**
* @param labels
* set labels of tangents
*/
public void setLabels(String[] labels) {
tangents.setLabels(labels);
update();
}
/**
* @return tangent points
*/
public GeoPoint[] getTangentPoints() {
return ip;
}
@Override
public GeoPointND getTangentPoint(GeoElement geo, GeoLine line) {
return this.algoTangentPoly.getTangentPoint(geo, line);
}
}