package org.geogebra.common.kernel.advanced; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoConic3D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoCurveCartesian3D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoPoint3D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoVector3D; import org.geogebra.common.kernel.CircularDefinitionException; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.algos.AlgoElement; import org.geogebra.common.kernel.cas.AlgoDerivative; import org.geogebra.common.kernel.commands.Commands; import org.geogebra.common.kernel.commands.EvalInfo; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoVec3D; import org.geogebra.common.kernel.kernelND.GeoConicNDConstants; import org.geogebra.common.kernel.kernelND.GeoPointND; /** * @author Michael * * http://en.wikipedia.org/w/index.php?title=Curvature§ion=8# * Local_expressions_2 Calculate Curvature Vector for curve: c(t) = * ((a'(t)b''(t)-a''(t)b'(t))/T^4) * (-b'(t),a'(t)) T = * sqrt(a'(t)^2+b'(t)^2) */ public class AlgoCurvatureVectorCurve3D extends AlgoElement { private GeoPointND A; // input private GeoCurveCartesian3D f, f1, f2; // f = f(x), f1 is f'(x), f2 is // f''(x) private GeoVector3D v; // output private double f1eval[] = new double[3]; private double f2eval[] = new double[3]; private AlgoDerivative algoCAS, algoCAS2; private GeoConic3D gc; public AlgoCurvatureVectorCurve3D(Construction cons, String label, GeoPoint3D arg, GeoCurveCartesian3D arg2) { this(cons, arg, arg2); if (label != null) { v.setLabel(label); } else { // if we don't have a label we could try c v.setLabel("cv"); } } AlgoCurvatureVectorCurve3D(Construction cons, GeoPointND A, GeoCurveCartesian3D f) { super(cons); this.A = A; this.f = f; // create new vector v = new GeoVector3D(cons); try { v.setStartPoint(A); } catch (CircularDefinitionException e) { } cas(); setInputOutput(); compute(); } public AlgoCurvatureVectorCurve3D(Construction cons, GeoPoint3D arg, GeoConic3D geoConic3D) { super(cons); this.gc = geoConic3D; this.A = arg; // create new vector v = new GeoVector3D(cons); try { v.setStartPoint(A); } catch (CircularDefinitionException e) { } f = new GeoCurveCartesian3D(cons); gc.toGeoCurveCartesian(f); cas(); setInputOutput(); compute(); } private void cas() { EvalInfo info = new EvalInfo(false); // First derivative of curve f algoCAS = new AlgoDerivative(cons, f, true, info); cons.removeFromConstructionList(algoCAS); this.f1 = (GeoCurveCartesian3D) algoCAS.getResult(); // Second derivative of curve f algoCAS2 = new AlgoDerivative(cons, f1, true, info); cons.removeFromConstructionList(algoCAS2); this.f2 = (GeoCurveCartesian3D) algoCAS2.getResult(); } /* * AlgoCurvatureVectorCurve3D(Construction cons, String label, GeoPoint a2, * GeoConic geoConic) { this(cons, a2, geoConic); if (label != null) { * v.setLabel(label); } else { v.setLabel("cv"); } } */ /* * public AlgoCurvatureVectorCurve3D(Construction cons, GeoPoint A, GeoConic * geoConic) { super(cons); this.A = A; this.gc = geoConic; f = new * GeoCurveCartesian3D(cons); gc.toGeoCurveCartesian(f); // create new * vector v = new GeoVector3D(cons); try { v.setStartPoint(A); } catch * (CircularDefinitionException e) { } * * cas(); * * setInputOutput(); compute(); } */ @Override public Commands getClassName() { return Commands.CurvatureVector; } // for AlgoElement @Override protected void setInputOutput() { input = new GeoElement[2]; input[0] = (GeoElement) A; if (gc != null) { input[1] = gc; } else { input[1] = f; } super.setOutputLength(1); super.setOutput(0, v); setDependencies(); // done by AlgoElement } // Return the resultant vector public GeoVector3D getVector() { return v; } @Override public final void compute() { try { double tvalue; double curvature; if (gc != null && gc.getType() == GeoConicNDConstants.CONIC_PARABOLA) { tvalue = gc.getClosestParameterForParabola(A); gc.evaluateFirstDerivativeForParabola(tvalue, f1eval); gc.evaluateSecondDerivativeForParabola(tvalue, f2eval); curvature = gc.evaluateCurvatureForParabola(tvalue); } else { if (gc != null) { gc.toGeoCurveCartesian(f); f.updateDistanceFunction(); cas(); } tvalue = f.getClosestParameterForCurvature(A, f.getMinParameter()); f1.evaluateCurve(tvalue, f1eval); f2.evaluateCurve(tvalue, f2eval); curvature = f.evaluateCurvature(tvalue); } double[] w = new double[3]; double[] w2 = new double[3]; double[] w3 = new double[4]; // CurvatureVector = curvature.((f'xf'')xf')/|(f'xf'')xf'| GeoVec3D.cross(f1eval, f2eval, w); GeoVec3D.cross(w, f1eval, w2); // normalize double d = Math.sqrt(w2[0] * w2[0] + w2[1] * w2[1] + w2[2] * w2[2]); w2[0] /= d; w2[1] /= d; w2[2] /= d; w3[0] = w2[0] * curvature; w3[1] = w2[1] * curvature; w3[2] = w2[2] * curvature; w3[3] = 0; v.setCoords(w3); } catch (Exception e) { // in case something went wrong, e.g. derivatives not defined v.setUndefined(); } } @Override public void remove() { if (removed) { return; } super.remove(); ((GeoElement) A).removeAlgorithm(algoCAS); f.removeAlgorithm(algoCAS); ((GeoElement) A).removeAlgorithm(algoCAS2); f.removeAlgorithm(algoCAS2); } }