/*
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.geogebra3D.kernel3D.algos;
import org.geogebra.common.geogebra3D.kernel3D.geos.GeoLine3D;
import org.geogebra.common.geogebra3D.kernel3D.geos.GeoPoint3D;
import org.geogebra.common.kernel.Construction;
import org.geogebra.common.kernel.Kernel;
import org.geogebra.common.kernel.Matrix.Coords;
import org.geogebra.common.kernel.algos.AlgoTangentPointND;
import org.geogebra.common.kernel.geos.GeoLine;
import org.geogebra.common.kernel.kernelND.AlgoIntersectND;
import org.geogebra.common.kernel.kernelND.GeoConicND;
import org.geogebra.common.kernel.kernelND.GeoLineND;
import org.geogebra.common.kernel.kernelND.GeoPointND;
/**
* Two tangents through point P to conic section c
*/
public class AlgoTangentPoint3D extends AlgoTangentPointND {
public AlgoTangentPoint3D(Construction cons, String[] labels, GeoPointND P,
GeoConicND c) {
super(cons, labels, P, c);
}
@Override
protected void setPolar() {
polarCoords = new double[3];
// the tangents are computed by intersecting the
// polar line of P with c
polar = new GeoLine(cons);
// updatePolarLine();
algoIntersect = new AlgoIntersectLineIncludedConic3D(cons, polar, c);
// this is only an internal Algorithm that shouldn't be in the
// construction list
cons.removeFromConstructionList(algoIntersect);
tangentPoints = algoIntersect.getIntersectionPoints();
}
private double[] polarCoords;
private Coords polarOrigin, polarDirection;
@Override
protected void setTangentFromPolar(int i) {
if (i == 0) { // for second tangent, calculations are already done
polar.getCoords(polarCoords);
polarDirection = c.getCoordSys().getVector(-polarCoords[1],
polarCoords[0]);
if (Kernel.isZero(polarCoords[0])) {
polarOrigin = c.getCoordSys().getPoint(0,
-polarCoords[2] / polarCoords[1]);
} else {
polarOrigin = c.getCoordSys()
.getPoint(-polarCoords[2] / polarCoords[0], 0);
}
}
((GeoLine3D) tangents[i]).setCoord(polarOrigin, polarDirection);
}
@Override
protected void setTangents() {
tangents = new GeoLine3D[2];
tangents[0] = new GeoLine3D(cons);
tangents[1] = new GeoLine3D(cons);
((GeoLine3D) tangents[0]).setStartPoint(P);
((GeoLine3D) tangents[1]).setStartPoint(P);
}
@Override
protected boolean checkUndefined() {
if (super.checkUndefined()) {
return true;
}
coords2D = c.getCoordSys()
.getNormalProjection(P.getInhomCoordsInD3())[1];
if (!Kernel.isZero(coords2D.getZ())) {
return true;
}
// now it's a 2D point in coord sys
coords2D.setZ(1);
return false;
}
@Override
protected void updatePolarLine() {
c.polarLine(coords2D, polar);
}
private Coords coords2D;
@Override
protected boolean isIntersectionPointIncident() {
// Too low precision causes tangent not touching the conic GGB-1018
return c.isIntersectionPointIncident(coords2D,
Kernel.STANDARD_PRECISION); // ||
// P.getIncidenceList().contains(c);
}
@Override
protected void updateTangents() {
// calc tangents through tangentPoints
if (!tangentPoints[0].isDefined()) {
tangents[0].setUndefined();
} else {
((GeoLine3D) tangents[0]).setCoord(P, tangentPoints[0]);
}
if (!tangentPoints[1].isDefined()) {
tangents[1].setUndefined();
} else {
((GeoLine3D) tangents[1]).setCoord(P, tangentPoints[1]);
}
}
/**
* Inits the helping interesection algorithm to take the current position of
* the lines into account. This is important so the the tangent lines are
* not switched after loading a file
*/
@Override
public void initForNearToRelationship() {
// if first tangent point is not on first tangent,
// we switch the intersection points
initForNearToRelationship(tangentPoints, tangents[0], algoIntersect);
}
/**
* Inits the helping interesection algorithm to take the current position of
* the lines into account. This is important so the the tangent lines are
* not switched after loading a file
*
* @param tangentPoints
* tangent points
* @param tangent
* tangent line
* @param algoIntersect
* algo used
*/
public static final void initForNearToRelationship(
GeoPointND[] tangentPoints, GeoLineND tangent,
AlgoIntersectND algoIntersect) {
Coords firstTangentPoint = tangentPoints[0].getInhomCoordsInD3();
if (!((GeoLine3D) tangent).isOnFullLine(firstTangentPoint,
Kernel.MIN_PRECISION)) {
algoIntersect.initForNearToRelationship();
// first = second
algoIntersect.setIntersectionPoint(0, tangentPoints[1]);
// second = first
((GeoPoint3D) tangentPoints[1]).setCoords(firstTangentPoint);
algoIntersect.setIntersectionPoint(1, tangentPoints[1]);
}
}
}