/* 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.GeoConic3D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoQuadric3DLimitedOrPart; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.Kernel; import org.geogebra.common.kernel.Matrix.CoordMatrix; import org.geogebra.common.kernel.Matrix.CoordSys; import org.geogebra.common.kernel.Matrix.Coords; import org.geogebra.common.kernel.commands.Commands; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.kernelND.GeoQuadricND; import org.geogebra.common.kernel.kernelND.GeoQuadricNDConstants; /** * Compute the ends of a limited quadric * * @author mathieu */ public class AlgoQuadricEnds extends AlgoElement3D { private GeoQuadricND quadric; // input private GeoConic3D[] sections; // output private CoordSys coordsys1, coordsys2; /** * * @param labels * labels * @param cons * construction * @param quadric * quadric */ public AlgoQuadricEnds(Construction cons, String[] labels, GeoQuadricND quadric) { this(cons, quadric); if (labels == null) { sections[0].setLabel(null); sections[1].setLabel(null); } else if (labels.length == 1) { GeoElement.setLabels(labels[0], sections); } else { GeoElement.setLabels(labels, sections); } } /** * * @param cons * construction * @param quadric * quadric */ public AlgoQuadricEnds(Construction cons, GeoQuadricND quadric) { this(cons, quadric, false); } /** * * @param cons * construction * @param quadric * quadric * @param helper * whether this is just a helper */ public AlgoQuadricEnds(Construction cons, GeoQuadricND quadric, boolean helper) { super(cons, !helper); // set origin w coord pm.set(4, 3, 1); this.quadric = quadric; sections = new GeoConic3D[2]; sections[0] = new GeoConic3D(cons); coordsys1 = new CoordSys(2); sections[0].setCoordSys(coordsys1); sections[0].setIsEndOfQuadric(true); sections[1] = new GeoConic3D(cons); coordsys2 = new CoordSys(2); sections[1].setCoordSys(coordsys2); sections[1].setIsEndOfQuadric(true); // if helper, will be updated by caller if (!helper) { setInputOutput(new GeoElement[] { quadric }, sections); } compute(); } public GeoConic3D getSection1() { return sections[0]; } public GeoConic3D getSection2() { return sections[1]; } public GeoConic3D[] getSections() { return sections; } private CoordMatrix pm = new CoordMatrix(4, 3); private CoordMatrix pmt = new CoordMatrix(3, 4); private Coords o1 = new Coords(3), o2 = new Coords(3), v = new Coords(3), vn1 = new Coords(3), vn2 = new Coords(3); @Override public final void compute() { if (!quadric.isDefined()) { sections[0].setUndefined(); sections[1].setUndefined(); return; } sections[0].setDefined(); sections[1].setDefined(); o1.setAdd3(quadric.getMidpoint3D(), o1.setMul3(quadric.getEigenvec3D(2), ((GeoQuadric3DLimitedOrPart) quadric).getBottomParameter())); o2.setAdd3(quadric.getMidpoint3D(), o2.setMul3(quadric.getEigenvec3D(2), ((GeoQuadric3DLimitedOrPart) quadric).getTopParameter())); if (quadric.getType() == GeoQuadricNDConstants.QUADRIC_CYLINDER || quadric.getType() == GeoQuadricNDConstants.QUADRIC_CONE) { if (Kernel.isZero(quadric.getHalfAxis(0)) && (Double.isNaN(quadric.getHalfAxis(1)) || Kernel.isZero(quadric.getHalfAxis(1)))) { // cylinder or cone equal to a segment sections[0].setSinglePoint(o1); sections[1].setSinglePoint(o2); return; } } CoordMatrix qm = quadric.getSymetricMatrix(); pm.setOrigin(o1); v.setSub3(o2, o1); v.completeOrthonormal3(vn1, vn2); pm.setVx(vn1); pm.setVy(vn2); pm.transposeCopy(pmt); // sets the conic matrix from plane and quadric matrix CoordMatrix cm = pmt.mul(qm).mul(pm); // Log.debug("pm=\n" + pm + "\nqm=\n" + qm + "\ncm=\n" + cm); coordsys1.resetCoordSys(); coordsys1.addPoint(o1); coordsys1.addVector(vn1); coordsys1.addVector(v.setMul3(vn2, -1)); // orientation out of the // quadric coordsys1.makeOrthoMatrix(false, false); sections[0].setMatrix(cm); // section2 pm.setOrigin(o2); pm.transposeCopy(pmt); cm = pmt.mul(qm).mul(pm); coordsys2.resetCoordSys(); coordsys2.addPoint(o2); coordsys2.addVector(vn1); coordsys2.addVector(vn2); coordsys2.makeOrthoMatrix(false, false); sections[1].setMatrix(cm); } @Override public Commands getClassName() { return Commands.Ends; } @Override public void remove() { if (removed) { return; } super.remove(); quadric.remove(); } /* * final public String toString() { return * loc.getPlain("EndsOfABetweenBC",((GeoElement) * quadric).getLabel(),point.getLabel(),pointThrough.getLabel()); } */ }