/*
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.
*/
/*
* AlgoIntersectPolynomialConic.java
*
* Created on 14.07.2010, 14:28
*/
package org.geogebra.common.kernel.algos;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.math3.analysis.polynomials.PolynomialFunction;
import org.geogebra.common.euclidian.EuclidianConstants;
import org.geogebra.common.kernel.Construction;
import org.geogebra.common.kernel.Kernel;
import org.geogebra.common.kernel.Matrix.Coords;
import org.geogebra.common.kernel.arithmetic.PolyFunction;
import org.geogebra.common.kernel.commands.Commands;
import org.geogebra.common.kernel.geos.GeoConic;
import org.geogebra.common.kernel.geos.GeoFunction;
import org.geogebra.common.kernel.geos.GeoNumeric;
import org.geogebra.common.kernel.geos.GeoPoint;
import org.geogebra.common.kernel.implicit.GeoImplicit;
import org.geogebra.common.kernel.kernelND.GeoConicNDConstants;
/**
* Intersect polynomial function with a conic
*/
public class AlgoIntersectPolynomialConic extends AlgoSimpleRootsPolynomial {
private GeoFunction h; // input
private GeoConic c;
/**
*
* @param cons
* construction
* @param h
* polynomial function
* @param c
* conic
*/
public AlgoIntersectPolynomialConic(Construction cons, GeoFunction h,
GeoConic c) {
super(cons, h, c);
this.h = h;
this.c = c;
// initForNearToRelationship();
// TODO set incidence
compute();
}
@Override
public void compute() {
double[] A = c.getFlatMatrix();
PolyFunction pf = null;
if (h.isPolynomialFunction(false)) {
pf = h.getFunction().getNumericPolynomialDerivative(0, false);
}
if (pf != null) {
PolynomialFunction y = new PolynomialFunction(pf.getCoeffs());
PolynomialFunction r = new PolynomialFunction(
new double[] { A[2], 2 * A[4], A[0] });
r = r.add(y.multiply(new PolynomialFunction(
new double[] { 2 * A[5], 2 * A[3] })));
r = r.add(y.multiply(
y.multiply(new PolynomialFunction(new double[] { A[1] }))));
// Application.debug("r = "+r.toString());
setRootsPolynomial(r);
} else {
Kernel ker = cons.getKernel();
boolean oldSilentMode = ker.isSilentMode();
ker.setSilentMode(true);
GeoImplicit iPoly = kernel.newImplicitPoly(cons);
iPoly.preventPathCreation();
c.toGeoImplicitCurve(iPoly);
GeoFunction paramEquation = new GeoFunction(cons, iPoly, null, h);
// int nroots = 0;
// double res[] = new double[2];
// bounds of the ellipse:
// axx+byy+c+2dxy+2ex+2fy = b yy + (2dx + 2f)+(axx+2ex+c) has
// exactly one root wrt y if
// 0=(2dx +2f)^2-4*b(axx+2ex+c)=4*((d^2-ab)xx+(2df-2eb)x+(f^2-bc))
// nroots = kernel.getEquationSolver().solveQuadratic(
// new double[] { -A[5] * A[5] + A[1] * A[2],
// 2 * (A[1] * A[4] - A[3] * A[5]),
// A[0] * A[1] - A[3] * A[3] }, res,
// Kernel.STANDARD_PRECISION);
Coords midPoint = null;
double[] halfAxes = null;
double ellipseCirlcleFactor = 1.05;
double hyperParaBolaFactor = 0.5;
// bounds of the ellipse:
// axx+byy+c+2dxy+2ex+2fy = b yy + (2dx + 2f)+(axx+2ex+c) has
// exactly one root wrt y if
// 0=(2dx +2f)^2-4*b(axx+2ex+c)=4*((d^2-ab)xx+(2df-2eb)x+(f^2-bc))
if (c.getType() == GeoConicNDConstants.CONIC_CIRCLE
|| c.getType() == GeoConicNDConstants.CONIC_ELLIPSE) {
midPoint = c.getMidpoint();
halfAxes = c.getHalfAxes();
}
AlgoRoots algo = null;
if (midPoint != null && halfAxes != null) {
algo = new AlgoRoots(cons, paramEquation,
new GeoNumeric(cons,
midPoint.getX() - ellipseCirlcleFactor
* Math.max(halfAxes[0], halfAxes[1])),
new GeoNumeric(cons,
midPoint.getX() + ellipseCirlcleFactor
* Math.max(halfAxes[0], halfAxes[1])));
// Log.debug("interval(ellipse/circle): "
// + (midPoint.getX() - ellipseCirlcleFactor
// * Math.max(halfAxes[0], halfAxes[1]))
// + ", "
// + (midPoint.getX() + ellipseCirlcleFactor
// * Math.max(halfAxes[0], halfAxes[1])));
} else {
algo = new AlgoRoots(cons, paramEquation,
new GeoNumeric(cons,
h.getMinParameter() - hyperParaBolaFactor
* Math.abs(h.getMinParameter())),
new GeoNumeric(cons,
h.getMaxParameter() + hyperParaBolaFactor
* Math.abs(h.getMaxParameter())));
// Log.debug("interval(hyperbola/parabola): "
// + (h.getMinParameter() - Math.abs(h.getMinParameter()
// * hyperParaBolaFactor))
// + ", "
// + (h.getMaxParameter() + Math.abs(h.getMaxParameter()
// * hyperParaBolaFactor)));
}
GeoPoint[] rootPoints = algo.getRootPoints();
List<double[]> valPairs = new ArrayList<double[]>();
for (int i = 0; i < rootPoints.length; i++) {
double t = rootPoints[i].getX();
valPairs.add(new double[] { t, h.value(t) });
}
ker.setSilentMode(oldSilentMode);
setPoints(valPairs);
return;
}
}
@Override
public Commands getClassName() {
return Commands.Intersect;
}
@Override
public int getRelatedModeID() {
return EuclidianConstants.MODE_INTERSECT;
}
@Override
protected double getYValue(double x) {
return h.value(x);
}
}