Android Open Source - Thrift-box Approximator






From Project

Back to project page Thrift-box.

License

The source code is released under:

GNU General Public License

If you think the Android project Thrift-box listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.github.mikephil.charting.data.filter;
/*from   w ww . j  a  v  a2 s .c o m*/
import com.github.mikephil.charting.data.Entry;

import java.util.ArrayList;

/**
 * Implemented according to Wiki-Pseudocode {@link}
 * http://en.wikipedia.org/wiki/Ramer?Douglas?Peucker_algorithm
 * 
 * @author Philipp Baldauf & Phliipp Jahoda
 */
public class Approximator {

    /** the type of filtering algorithm to use */
    private ApproximatorType mType = ApproximatorType.DOUGLAS_PEUCKER;

    /** the tolerance to be filtered with */
    private double mTolerance = 0;

    private float mScaleRatio = 1f;
    private float mDeltaRatio = 1f;

    /**
     * array that contains "true" on all indices that will be kept after
     * filtering
     */
    private boolean[] keep;

    /** enums for the different types of filtering algorithms */
    public enum ApproximatorType {
        NONE, DOUGLAS_PEUCKER
    }

    /**
     * Initializes the approximator with type NONE
     */
    public Approximator() {
        this.mType = ApproximatorType.NONE;
    }

    /**
     * Initializes the approximator with the given type and tolerance. If
     * toleranec <= 0, no filtering will be done.
     * 
     * @param type
     */
    public Approximator(ApproximatorType type, double tolerance) {
        setup(type, tolerance);
    }

    /**
     * sets type and tolerance, if tolerance <= 0, no filtering will be done
     * 
     * @param type
     * @param tolerance
     */
    public void setup(ApproximatorType type, double tolerance) {
        mType = type;
        mTolerance = tolerance;
    }

    /**
     * sets the tolerance for the Approximator. When using the
     * Douglas-Peucker-Algorithm, the tolerance is an angle in degrees, that
     * will trigger the filtering.
     */
    public void setTolerance(double tolerance) {
        mTolerance = tolerance;
    }

    /**
     * Sets the filtering algorithm that should be used.
     * 
     * @param type
     */
    public void setType(ApproximatorType type) {
        this.mType = type;
    }

    /**
     * Sets the ratios for x- and y-axis, as well as the ratio of the scale
     * levels
     * 
     * @param deltaRatio
     * @param scaleRatio
     */
    public void setRatios(float deltaRatio, float scaleRatio) {
        mDeltaRatio = deltaRatio;
        mScaleRatio = scaleRatio;
    }

    /**
     * Filters according to type. Uses the pre set set tolerance
     * 
     * @param points the points to filter
     * @return
     */
    public ArrayList<Entry> filter(ArrayList<Entry> points) {
        return filter(points, mTolerance);
    }

    /**
     * Filters according to type.
     * 
     * @param points the points to filter
     * @param tolerance the angle in degrees that will trigger the filtering
     * @return
     */
    public ArrayList<Entry> filter(ArrayList<Entry> points, double tolerance) {

        if (tolerance <= 0)
            return points;

        keep = new boolean[points.size()];

        switch (mType) {
            case DOUGLAS_PEUCKER:
                return reduceWithDouglasPeuker(points, tolerance);
            case NONE:
                return points;
            default:
                return points;
        }
    }

    /**
     * uses the douglas peuker algorithm to reduce the given arraylist of
     * entries
     * 
     * @param entries
     * @param epsilon
     * @return
     */
    private ArrayList<Entry> reduceWithDouglasPeuker(ArrayList<Entry> entries, double epsilon) {
        // if a shape has 2 or less points it cannot be reduced
        if (epsilon <= 0 || entries.size() < 3) {
            return entries;
        }

        // first and last always stay
        keep[0] = true;
        keep[entries.size() - 1] = true;

        // first and last entry are entry point to recursion
        algorithmDouglasPeucker(entries, epsilon, 0, entries.size() - 1);

        // create a new array with series, only take the kept ones
        ArrayList<Entry> reducedEntries = new ArrayList<Entry>();
        for (int i = 0; i < entries.size(); i++) {
            if (keep[i]) {
                Entry curEntry = entries.get(i);
                reducedEntries.add(new Entry(curEntry.getVal(), curEntry.getXIndex()));
            }
        }
        return reducedEntries;
    }

    /**
     * apply the Douglas-Peucker-Reduction to an ArrayList of Entry with a given
     * epsilon (tolerance)
     * 
     * @param entries
     * @param epsilon as y-value
     * @param start
     * @param end
     */
    private void algorithmDouglasPeucker(ArrayList<Entry> entries, double epsilon, int start,
            int end) {
        if (end <= start + 1) {
            // recursion finished
            return;
        }

        // find the greatest distance between start and endpoint
        int maxDistIndex = 0;
        double distMax = 0;

        Entry firstEntry = entries.get(start);
        Entry lastEntry = entries.get(end);

        for (int i = start + 1; i < end; i++) {
            double dist = calcAngleBetweenLines(firstEntry, lastEntry, firstEntry, entries.get(i));

            // keep the point with the greatest distance
            if (dist > distMax) {
                distMax = dist;
                maxDistIndex = i;
            }
        }

        // Log.i("maxangle", "" + distMax);

        if (distMax > epsilon) {
            // keep max dist point
            keep[maxDistIndex] = true;

            // recursive call
            algorithmDouglasPeucker(entries, epsilon, start, maxDistIndex);
            algorithmDouglasPeucker(entries, epsilon, maxDistIndex, end);
        } // else don't keep the point...
    }

    /**
     * calculate the distance between a line between two entries and an entry
     * (point)
     * 
     * @param startEntry line startpoint
     * @param endEntry line endpoint
     * @param entryPoint the point to which the distance is measured from the
     *            line
     * @return
     */
    public double calcPointToLineDistance(Entry startEntry, Entry endEntry, Entry entryPoint) {

        float xDiffEndStart = (float) endEntry.getXIndex() - (float) startEntry.getXIndex();
        float xDiffEntryStart = (float) entryPoint.getXIndex() - (float) startEntry.getXIndex();

        double normalLength = Math.sqrt((xDiffEndStart)
                * (xDiffEndStart)
                + (endEntry.getVal() - startEntry.getVal())
                * (endEntry.getVal() - startEntry.getVal()));
        return Math.abs((xDiffEntryStart)
                * (endEntry.getVal() - startEntry.getVal())
                - (entryPoint.getVal() - startEntry.getVal())
                * (xDiffEndStart))
                / normalLength;
    }

    /**
     * Calculates the angle between two given lines. The provided Entry objects
     * mark the starting and end points of the lines.
     * 
     * @param start1
     * @param end1
     * @param start2
     * @param end2
     * @return
     */
    public double calcAngleBetweenLines(Entry start1, Entry end1, Entry start2, Entry end2) {

        double angle1 = calcAngleWithRatios(start1, end1);
        double angle2 = calcAngleWithRatios(start2, end2);

        return Math.abs(angle1 - angle2);
    }

    /**
     * calculates the angle between two Entries (points) in the chart taking
     * ratios into consideration
     * 
     * @param p1
     * @param p2
     * @return
     */
    public double calcAngleWithRatios(Entry p1, Entry p2) {

        float dx = p2.getXIndex() * mDeltaRatio - p1.getXIndex() * mDeltaRatio;
        float dy = p2.getVal() * mScaleRatio - p1.getVal() * mScaleRatio;
        double angle = Math.atan2(dy, dx) * 180.0 / Math.PI;

        return angle;
    }

    /**
     * calculates the angle between two Entries (points) in the chart
     * 
     * @param p1
     * @param p2
     * @return
     */
    public double calcAngle(Entry p1, Entry p2) {

        float dx = p2.getXIndex() - p1.getXIndex();
        float dy = p2.getVal() - p1.getVal();
        double angle = Math.atan2(dy, dx) * 180.0 / Math.PI;

        return angle;
    }
}




Java Source Code List

android.support.v4.preference.PreferenceFragment.java
android.support.v4.preference.PreferenceManagerCompat.java
android.widget_fixed.CursorFilter.java
android.widget_fixed.CursorTreeAdapter.java
com.github.mikephil.charting.charts.Chart.java
com.github.mikephil.charting.charts.PieChart.java
com.github.mikephil.charting.charts.PieRadarChartBase.java
com.github.mikephil.charting.data.ChartData.java
com.github.mikephil.charting.data.DataSet.java
com.github.mikephil.charting.data.Entry.java
com.github.mikephil.charting.data.PieDataSet.java
com.github.mikephil.charting.data.PieData.java
com.github.mikephil.charting.data.filter.Approximator.java
com.github.mikephil.charting.exception.DrawingDataSetNotCreatedException.java
com.github.mikephil.charting.interfaces.ChartInterface.java
com.github.mikephil.charting.interfaces.OnChartGestureListener.java
com.github.mikephil.charting.interfaces.OnChartValueSelectedListener.java
com.github.mikephil.charting.interfaces.OnDrawLineChartTouchListener.java
com.github.mikephil.charting.interfaces.OnDrawListener.java
com.github.mikephil.charting.listener.PieRadarChartTouchListener.java
com.github.mikephil.charting.matrix.Vector3.java
com.github.mikephil.charting.renderer.Transformer.java
com.github.mikephil.charting.utils.ColorFormatter.java
com.github.mikephil.charting.utils.ColorTemplate.java
com.github.mikephil.charting.utils.Highlight.java
com.github.mikephil.charting.utils.LabelBase.java
com.github.mikephil.charting.utils.LargeValueFormatter.java
com.github.mikephil.charting.utils.Legend.java
com.github.mikephil.charting.utils.LimitLine.java
com.github.mikephil.charting.utils.MarkerView.java
com.github.mikephil.charting.utils.PointD.java
com.github.mikephil.charting.utils.SelInfo.java
com.github.mikephil.charting.utils.Utils.java
com.github.mikephil.charting.utils.ValueFormatter.java
com.github.mikephil.charting.utils.XLabels.java
com.github.mikephil.charting.utils.YLabels.java
net.margaritov.preference.colorpicker.AlphaPatternDrawable.java
net.margaritov.preference.colorpicker.ColorPickerDialog.java
net.margaritov.preference.colorpicker.ColorPickerPanelView.java
net.margaritov.preference.colorpicker.ColorPickerPreference.java
net.margaritov.preference.colorpicker.ColorPickerView.java
ru.sash0k.thriftbox.AdapterExpenses.java
ru.sash0k.thriftbox.MainActivity.java
ru.sash0k.thriftbox.TypefaceSpan2.java
ru.sash0k.thriftbox.Utils.java
ru.sash0k.thriftbox.Widget.java
ru.sash0k.thriftbox.categories.Categories.java
ru.sash0k.thriftbox.categories.InterceptingHorizontalScrollView.java
ru.sash0k.thriftbox.database.DBProvider.java
ru.sash0k.thriftbox.database.DB.java
ru.sash0k.thriftbox.fragments.CommentDialog.java
ru.sash0k.thriftbox.fragments.DeleteConfirmDialog.java
ru.sash0k.thriftbox.fragments.ExpandableListFragment.java
ru.sash0k.thriftbox.fragments.ExpensesFragment.java
ru.sash0k.thriftbox.fragments.InputFragment.java
ru.sash0k.thriftbox.fragments.PieChartFragment.java
ru.sash0k.thriftbox.fragments.SettingsFragment.java