/*
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.GeoQuadric3DLimited;
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.geos.GeoElement;
import org.geogebra.common.kernel.kernelND.GeoQuadricNDConstants;
/**
* Compute one end of a limited quadric
*
* @author Mathieu
*/
public abstract class AlgoQuadricEnd extends AlgoElement3D {
private GeoQuadric3DLimited quadric; // input
private GeoConic3D section; // output
private CoordSys coordsys;
// private GeoPoint3D help;
/**
*
* @param cons
* construction
* @param quadric
* quadric
*/
public AlgoQuadricEnd(Construction cons, GeoQuadric3DLimited quadric) {
this(cons, quadric, false);
}
public AlgoQuadricEnd(Construction cons, GeoQuadric3DLimited quadric,
boolean helper) {
super(cons, !helper);
this.quadric = quadric;
section = new GeoConic3D(cons);
coordsys = new CoordSys(2);
section.setCoordSys(coordsys);
section.setIsEndOfQuadric(true);
if (!helper) {
setInputOutput(new GeoElement[] { quadric },
new GeoElement[] { section });
}
compute();
}
/**
*
* @param cons
* construction
* @param label
* label
* @param quadric
* quadric
*/
public AlgoQuadricEnd(Construction cons, String label,
GeoQuadric3DLimited quadric) {
this(cons, quadric);
section.setLabel(label);
}
/**
*
* @return section
*/
public GeoConic3D getSection() {
return section;
}
private CoordMatrix pm = new CoordMatrix(4, 3);
private CoordMatrix pmt = new CoordMatrix(3, 4);
@Override
public final void compute() {
if (!quadric.isDefined()) {
section.setUndefined();
return;
}
section.setDefined();
if (quadric
.getType() == GeoQuadricNDConstants.QUADRIC_PARABOLIC_CYLINDER) {
CoordMatrix qm = quadric.getSymetricMatrix();
Coords d = quadric.getEigenvec3D(1).normalize();
Coords o1 = quadric.getMidpoint3D().copy().addInsideMul(d,
quadric.getBottomParameter());
Coords o2 = quadric.getMidpoint3D().copy().addInsideMul(d,
quadric.getTopParameter());
pm.setOrigin(getOrigin(o1, o2));
Coords[] v = new Coords[3];// d.completeOrthonormal();
v[2] = quadric.getEigenvec3D(2).normalize();
v[0] = quadric.getEigenvec3D(0).normalize();
v[1] = d;
pm.setVx(v[0]);
pm.setVy(v[2]);
/*
* Coords[] v = d.completeOrthonormal();
*/
pm.transposeCopy(pmt);
// sets the conic matrix from plane and quadric matrix
CoordMatrix cm = pmt.mul(qm).mul(pm);
// Application.debug("pm=\n"+pm+"\nqm=\n"+qm+"\ncm=\n"+cm);
coordsys.resetCoordSys();
coordsys.addPoint(getOrigin(o1, o2));
coordsys.addVector(v[0]);
coordsys.addVector(getV1(v[2]));
coordsys.makeOrthoMatrix(false, false);
section.setMatrix(cm);
} else {
CoordMatrix qm = quadric.getSymetricMatrix();
Coords d = quadric.getEigenvec3D(2);
Coords o1 = quadric.getMidpoint3D().copy().addInsideMul(d,
quadric.getBottomParameter());
Coords o2 = quadric.getMidpoint3D().copy().addInsideMul(d,
quadric.getTopParameter());
if (quadric.getType() == GeoQuadricNDConstants.QUADRIC_CYLINDER
|| quadric
.getType() == GeoQuadricNDConstants.QUADRIC_CONE) {
// cylinder or cone equal to a segment
if (Kernel.isZero(quadric.getHalfAxis(0))
&& (Double.isNaN(quadric.getHalfAxis(1))
|| Kernel.isZero(quadric.getHalfAxis(1)))) {
section.setSinglePoint(getOrigin(o1, o2));
return;
}
}
pm.setOrigin(getOrigin(o1, o2));
Coords[] v = new Coords[3];// d.completeOrthonormal();
v[2] = d;
v[0] = quadric.getEigenvec3D(0).normalize();
v[1] = quadric.getEigenvec3D(1).normalize();
pm.setVx(v[0]);
pm.setVy(v[1]);
/*
* Coords[] v = d.completeOrthonormal();
*/
pm.transposeCopy(pmt);
// sets the conic matrix from plane and quadric matrix
CoordMatrix cm = pmt.mul(qm).mul(pm);
// Application.debug("pm=\n"+pm+"\nqm=\n"+qm+"\ncm=\n"+cm);
coordsys.resetCoordSys();
coordsys.addPoint(getOrigin(o1, o2));
coordsys.addVector(v[0]);
coordsys.addVector(getV1(v[1]));
coordsys.makeOrthoMatrix(false, false);
section.setMatrix(cm);
}
// areas
// section.calcArea();
}
private boolean isHelperAlgo = false;
/**
* says that it's an helper algo for quadric limites (cone/cylinder)
*/
public void setIsHelperAlgo() {
isHelperAlgo = true;
}
@Override
public void remove() {
if (removed) {
return;
}
super.remove();
// if is helper algo for a quadric, remove it
if (isHelperAlgo) {
quadric.remove();
}
}
/**
* @param o1
* bottom origin
* @param o2
* top origin
* @return origin of given end
*/
abstract protected Coords getOrigin(Coords o1, Coords o2);
/**
*
* @param v1
* orientation out of the quadric
* @return orientation out of the end
*/
abstract protected Coords getV1(Coords v1);
}