geogebra.kernel.implicit.AlgoIntersectImplicitpolyParametric.java Source code

Java tutorial

Introduction

Here is the source code for geogebra.kernel.implicit.AlgoIntersectImplicitpolyParametric.java

Source

/* 
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.
    
*/

/*
 * AlgoSimpleRootsPolynomial.java
 *
 * Created on 28.07.2010, 13:20
 */
package geogebra.kernel.implicit;

import geogebra.common.euclidian.EuclidianConstants;
import geogebra.kernel.AlgoRoots;
import geogebra.kernel.AlgoSimpleRootsPolynomial;
import geogebra.kernel.Construction;
import geogebra.kernel.GeoFunction;
import geogebra.kernel.GeoLine;
import geogebra.kernel.GeoNumeric;
import geogebra.kernel.GeoPoint;
import geogebra.kernel.Kernel;
import geogebra.kernel.parser.ParseException;
import geogebra.main.MyError;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.math.analysis.polynomials.PolynomialFunction;

/**
 * Algorithm to intersect Implicit polynomials with either lines or polynomials
 */
public class AlgoIntersectImplicitpolyParametric extends AlgoSimpleRootsPolynomial {

    private PolynomialFunction tx;
    private PolynomialFunction ty;
    private GeoImplicitPoly p;
    private GeoLine l;
    private GeoFunction f;
    private GeoPoint[] tangentPoints;

    public AlgoIntersectImplicitpolyParametric(Construction c, GeoImplicitPoly p, GeoLine l) {
        this(c, null, false, p, l);
    }

    public AlgoIntersectImplicitpolyParametric(Construction c, GeoImplicitPoly p, GeoFunction f) {
        this(c, null, false, p, f);
    }

    public AlgoIntersectImplicitpolyParametric(Construction c, String[] labels, boolean setLabels,
            GeoImplicitPoly p, GeoLine l) {
        super(c, labels, setLabels, p, l);
        this.p = p;
        this.l = l;
        compute();
    }

    public AlgoIntersectImplicitpolyParametric(Construction c, String[] labels, boolean setLabels,
            GeoImplicitPoly p, GeoFunction f) {
        super(c, labels, setLabels, p, f);
        this.p = p;
        this.f = f;
        compute();
    }

    @Override
    protected double getYValue(double t) {
        return ty.value(t);
    }

    @Override
    protected double getXValue(double t) {
        return tx.value(t);
    }

    @Override
    protected void compute() {

        if (!p.isDefined()) {
            return;
        }

        double maxT;
        double minT;
        if (f != null) {
            if (!f.isDefined()) {
                return;
            }

            if (!f.isPolynomialFunction(false)) {

                Kernel ker = cons.getKernel();

                ker.setSilentMode(true);

                GeoFunction paramEquation = new GeoFunction(cons, p, null, f);

                AlgoRoots algo = new AlgoRoots(cons, paramEquation, new GeoNumeric(cons, f.getMinParameter()),
                        new GeoNumeric(cons, f.getMaxParameter()));

                GeoPoint[] points = algo.getRootPoints();
                List<double[]> valPairs = new ArrayList<double[]>();
                for (int i = 0; i < points.length; i++) {
                    double t = points[i].getX();
                    valPairs.add(new double[] { t, f.evaluate(t) });
                }

                ker.setSilentMode(false);
                setPoints(valPairs);
                return;
            }
            tx = new PolynomialFunction(new double[] { 0, 1 }); //x=t
            ty = new PolynomialFunction(f.getFunction().getNumericPolynomialDerivative(0).getCoeffs()); //y=f(t)
            maxT = f.getMaxParameter();
            minT = f.getMinParameter();
        } else if (l != null) {
            if (!l.isDefined()) {
                points.adjustOutputSize(0);
                return;
            }
            //get parametrisation of line
            double startP[] = new double[2];
            l.getInhomPointOnLine(startP);
            tx = new PolynomialFunction(new double[] { startP[0], l.getY() }); //x=p1+t*r1
            ty = new PolynomialFunction(new double[] { startP[1], -l.getX() }); //y=p2+t*r2
            maxT = l.getMaxParameter();
            minT = l.getMinParameter();

            if (l.getParentAlgorithm() instanceof AlgoTangentImplicitpoly) {
                tangentPoints = ((AlgoTangentImplicitpoly) l.getParentAlgorithm()).getTangentPoints();
            }
        } else {
            return;
        }
        PolynomialFunction sum = null;
        PolynomialFunction zs = null;
        //Insert x and y (univariat)polynomials via the Horner-scheme
        double[][] coeff = p.getCoeff();
        if (coeff != null)
            for (int i = coeff.length - 1; i >= 0; i--) {
                zs = new PolynomialFunction(new double[] { coeff[i][coeff[i].length - 1] });
                for (int j = coeff[i].length - 2; j >= 0; j--) {
                    zs = zs.multiply(ty).add(new PolynomialFunction(new double[] { coeff[i][j] }));//y*zs+coeff[i][j];
                }
                if (sum == null)
                    sum = zs;
                else
                    sum = sum.multiply(tx).add(zs);//sum*x+zs;
            }

        setRootsPolynomialWithinRange(sum, minT, maxT);
        mergeWithTangentPoints();
    }

    private void mergeWithTangentPoints() {

        if (tangentPoints == null || tangentPoints.length == 0)
            return;

        //assumption: tangent points are far apart from each other such that dist(tangent1,tangent2) > epsilon.
        boolean addTangent[] = new boolean[tangentPoints.length];
        int orgSize = points.size();
        while (!points.getElement(orgSize - 1).isDefined())
            --orgSize;

        int newSize = orgSize;
        double EPS2 = Kernel.EPSILON; //TODO: have a better guess of the error

        for (int i = 0; i < tangentPoints.length; ++i) {
            if (tangentPoints[i].getIncidenceList() != null && tangentPoints[i].getIncidenceList().contains(l)) {
                addTangent[i] = true;
                for (int j = 0; j < orgSize; ++j) {
                    if (points.getElement(j).distanceSqr(tangentPoints[i]) < EPS2) {
                        if (addTangent[i]) {
                            points.getElement(j).setUndefined();
                            --newSize;
                        } else {
                            addTangent[i] = false;
                            points.getElement(i).setCoords(tangentPoints[j]);
                        }

                    }
                }
                if (addTangent[i])
                    ++newSize;

            } else {
                addTangent[i] = false;
            }
        }

        int definedCount = 0;
        for (int i = 0; i < orgSize; ++i) {
            if (points.getElement(i).isDefined()) {
                if (definedCount != i)
                    points.getElement(definedCount).setCoords(points.getElement(i));
                ++definedCount;
            }
        }

        points.adjustOutputSize(newSize);

        for (int i = 0; i < tangentPoints.length; ++i) {
            if (addTangent[i]) {
                points.getElement(definedCount++).setCoords(tangentPoints[i]);
            }
        }

        if (setLabels)
            points.updateLabels();

    }

    public String getClassName() {
        return "AlgoIntersectImplicitpolyParametric";
    }

    public int getRelatedModeID() {
        return EuclidianConstants.MODE_INTERSECT;
    }

}