/* 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. */ /* * AlgoCommonTangents.java, dsun48 [6/26/2011] * */ 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.CoordSys; import org.geogebra.common.kernel.Matrix.Coords; import org.geogebra.common.kernel.algos.AlgoCommonTangentsND; 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.GeoPointND; /** * Two tangents through point P to conic section c */ public class AlgoCommonTangents3D extends AlgoCommonTangentsND { public AlgoCommonTangents3D(Construction cons, String[] labels, GeoConicND c, GeoConicND c2) { super(cons, labels, c, c2); } @Override protected void createPoints(Construction cons1) { P = new GeoPoint3D[2]; P[0] = new GeoPoint3D(cons1); P[1] = new GeoPoint3D(cons1); coords2D = new Coords[2]; coords2D[0] = new Coords(3); coords2D[1] = new Coords(3); midpointProjected = new Coords[2][]; midpointProjected[0] = new Coords[2]; midpointProjected[1] = new Coords[2]; } @Override protected void setCoordsAsPoint(int index, double x, double y) { coords2D[index].setX(x); coords2D[index].setY(y); coords2D[index].setZ(1); ((GeoPoint3D) P[index]) .setCoords(c[index].getCoordSys().getPoint(x, y)); } @Override protected void setCoordsAsVector(int index, double x, double y) { coords2D[index].setX(x); coords2D[index].setY(y); coords2D[index].setZ(0); ((GeoPoint3D) P[index]) .setCoords(c[index].getCoordSys().getVector(x, y)); } @Override protected void initTangents() { tangents = new GeoLine3D[2 + 2]; tangents[0] = new GeoLine3D(cons); tangents[1] = new GeoLine3D(cons); ((GeoLine3D) tangents[0]).setStartPoint(P[0]); ((GeoLine3D) tangents[1]).setStartPoint(P[0]); tangents[0 + 2] = new GeoLine3D(cons); tangents[1 + 2] = new GeoLine3D(cons); ((GeoLine3D) tangents[0 + 2]).setStartPoint(P[1]); ((GeoLine3D) tangents[1 + 2]).setStartPoint(P[1]); } @Override protected AlgoIntersectND createAlgo(Construction cons1, GeoPointND p, GeoLine line, GeoConicND conic) { return new AlgoIntersectLineIncludedConic3D(cons1, line, conic); } /** * 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() { AlgoTangentPoint3D.initForNearToRelationship(tangentPoints, tangents[0], algoIntersect); AlgoTangentPoint3D.initForNearToRelationship(tangentPoints2, tangents[2], algoIntersect2); } @Override protected void updatePolarLines() { c[0].polarLine(coords2D[0], polar); c[1].polarLine(coords2D[1], polar2); } private Coords[] coords2D; @Override protected boolean isIntersectionPointIncident(int index, GeoConicND conic) { return conic.isIntersectionPointIncident(coords2D[index], Kernel.MIN_PRECISION); } @Override protected void updateTangents(GeoPointND[] tangentPts, int index) { // calc tangents through tangentPoints if (!tangentPts[0].isDefined()) { tangents[0 + 2 * index].setUndefined(); } else { // if (P[index].isInfinite()){ // App.error("\ntP:\n"+tangentPoints[0].getCoords()+"\nP:\n"+P[index].getCoords()); // ((GeoLine3D) // tangents[0+2*index]).setCoord(tangentPoints[0].getCoords(), // P[index].getCoords()); // }else{ ((GeoLine3D) tangents[0 + 2 * index]).setCoord(P[index], tangentPts[0]); // } } if (!tangentPts[1].isDefined()) { tangents[1 + 2 * index].setUndefined(); } else { // if (P[index].isInfinite()){ // App.error("\ntP:\n"+tangentPoints[1].getCoords()+"\nP:\n"+P[index].getCoords()); // ((GeoLine3D) // tangents[1+2*index]).setCoord(tangentPoints[1].getCoords(), // P[index].getCoords()); // }else{ ((GeoLine3D) tangents[1 + 2 * index]).setCoord(P[index], tangentPts[1]); // } } } private double[] polarCoords = new double[3]; private Coords polarOrigin, polarDirection; @Override protected void setTangentFromPolar(int i, GeoLine line) { if (i == 0 || i == 2) { // for second tangent, calculations are already // done CoordSys cs = c[i / 2].getCoordSys(); line.getCoords(polarCoords); polarDirection = cs.getVector(-polarCoords[1], polarCoords[0]); if (Kernel.isZero(polarCoords[0])) { polarOrigin = cs.getPoint(0, -polarCoords[2] / polarCoords[1]); } else { polarOrigin = cs.getPoint(-polarCoords[2] / polarCoords[0], 0); } } ((GeoLine3D) tangents[i]).setCoord(polarOrigin, polarDirection); } private Coords[][] midpointProjected; @Override protected boolean checkUndefined() { if (super.checkUndefined()) { return true; } // check normals are lin. dep. Coords n0 = c[0].getMainDirection(); Coords n1 = c[1].getMainDirection(); if (!n0.crossProduct(n1).isZero()) { return true; } // project each others midpoints and check z == 0 for (int csIndex = 0; csIndex < 2; csIndex++) { int mpIndex = 1 - csIndex; midpointProjected[csIndex][mpIndex] = c[csIndex].getCoordSys() .getNormalProjection(c[mpIndex].getMidpoint3D())[1]; if (!Kernel.isZero(midpointProjected[csIndex][mpIndex].getZ())) { return true; } } // project own midpoints for (int csIndex = 0; csIndex < 2; csIndex++) { midpointProjected[csIndex][csIndex] = c[csIndex].getCoordSys() .getNormalProjection(c[csIndex].getMidpoint3D())[1]; } return false; } @Override protected double getMidpointX(int csIndex, int mpIndex) { return midpointProjected[csIndex][mpIndex].getX(); } @Override protected double getMidpointY(int csIndex, int mpIndex) { return midpointProjected[csIndex][mpIndex].getY(); } } // Local Variables: // indent-tabs-mode: nil // c-basic-offset: 4 // tab-width: 4 // End: // vim: set expandtab shiftwidth=4 softtabstop=4 tabstop=4