package org.geogebra.common.kernel.algos; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.arithmetic.ExpressionNode; import org.geogebra.common.kernel.arithmetic.FunctionVariable; import org.geogebra.common.kernel.arithmetic.PolyFunction; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoFunction; import org.geogebra.common.kernel.kernelND.GeoCurveCartesianND; import org.geogebra.common.kernel.kernelND.GeoPointND; /** * Intersect plane and curve * */ public abstract class AlgoIntersectCoordSysCurve extends AlgoIntersectAbstract { /** curve */ protected GeoCurveCartesianND curve; /** * * @param c * construction */ public AlgoIntersectCoordSysCurve(Construction c) { super(c); } /** * @param enx * eqution of the corrd sys with x,y,z replaced by corresponding * curve expressions * @param fv * function variable */ protected void findIntersections(ExpressionNode enx, FunctionVariable fv) { // wrap in a function GeoFunction geoFun = enx.buildFunction(fv); double[] roots = null; int outputSize = -1; ArrayList<Double> polyRoots = new ArrayList<Double>(); if (geoFun.isPolynomialFunction(true)) { // AbstractApplication.debug("trying polynomial"); LinkedList<PolyFunction> factorList = geoFun.getFunction() .getPolynomialFactors(false, false); if (factorList != null) { // compute the roots of every single factor Iterator<PolyFunction> it = factorList.iterator(); while (it.hasNext()) { PolyFunction polyFun = it.next(); if (polyFun.updateCoeffValues()) { // now let's compute the roots of this factor // compute all roots of polynomial polyFun roots = polyFun.getCoeffsCopy(); int n = cons.getKernel().getEquationSolver() .polynomialRoots(roots, true); for (int i = 0; i < n; i++) { polyRoots.add(roots[i]); } } else { outputSize = -1; break; } } } } if (polyRoots.size() > 0) { outputSize = polyRoots.size(); roots = new double[outputSize]; for (int i = 0; i < outputSize; i++) { roots[i] = polyRoots.get(i); } } else { // polynomial method hasn't worked // AbstractApplication.debug("trying non-polynomial"); // solve a x(t) + b y(t) + c = 0 (for t) roots = AlgoRoots.findRoots(geoFun, curve.getMinParameter(), curve.getMaxParameter(), 100); outputSize = roots == null || roots.length == 0 ? 1 : roots.length; } // update and/or create points getOutputPoints().adjustOutputSize(outputSize); // affect new computed points int index = 0; if (roots != null && roots.length > 0) { for (index = 0; index < outputSize; index++) { double paramVal = roots[index]; GeoPointND point = (GeoPointND) getOutputPoints() .getElement(index); if (paramVal < curve.getMinParameter() || paramVal > curve.getMaxParameter()) { // intersection is not on the curve point.setUndefined(); } else { // substitute parameter back into curve to get cartesian // coords updatePoint(point, paramVal, fv); // test the intersection point // this is needed for the intersection of Segments, Rays if (!inCoordSys(point)) { point.setUndefined(); } } // AbstractApplication.debug(xFun.evaluateDouble()+","+ // yFun.evaluateDouble()); } } // other points are undefined for (; index < getOutputPoints().size(); index++) { // AbstractApplication.debug("setting undefined "+index); getOutputPoints().getElement(index).setUndefined(); } } /** * @return output handler */ protected abstract OutputHandler<GeoElement> getOutputPoints(); /** * * @param point * output point * @param param * curve parameter * @param fv * function variable */ protected abstract void updatePoint(GeoPointND point, double param, FunctionVariable fv); /** * @param point * point * @return check it's really on the coord sys element */ protected abstract boolean inCoordSys(GeoPointND point); }