Removes unnecessary vertices from a line strip. - Android java.lang

Android examples for java.lang:Math Geometry

Description

Removes unnecessary vertices from a line strip.

Demo Code

/*******************************************************************************
 * Copyright (c) 2011 MadRobot.// w  ww.ja  v  a  2 s.co  m
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License v2.1
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *  Elton Kent - initial API and implementation
 ******************************************************************************/
//package com.java2s;
import java.util.Arrays;
import android.graphics.PointF;

public class Main {
    /**
     * Removes unnecessary vertices from a line strip. Uses the
     * Ramer?Douglas?Peucker algorithm
     * 
     * @param input
     *            in x,y,x,y format
     * @param maxD
     *            The maximum distance a point from the input set will
     *            be from the output shape
     * @param loop
     *            <code>true</code> for a line loop rather than a strip
     * @return a decimated vertex array, in x,y,x,y... format
     */
    public static float[] decimate(final float[] input, final float maxD,
            final boolean loop) {
        boolean[] marked = new boolean[input.length / 2];
        Arrays.fill(marked, false);

        int end = loop ? marked.length : marked.length - 1;

        rdp(input, marked, maxD, 0, end);

        // build output list
        int count = 0;
        for (int i = 0; i < marked.length; i++) {
            if (marked[i]) {
                count++;
            }
        }

        float[] output = new float[count * 2];
        int index = 0;
        for (int i = 0; i < marked.length; i++) {
            if (marked[i]) {
                output[index++] = input[2 * i];
                output[index++] = input[2 * i + 1];
            }
        }
        return output;
    }

    /**
     * Recursive step. Finds the point furthest from the start-end
     * segment, divide and conquer on that vertex if it is outside the
     * tolerance value
     * 
     * @param verts
     * @param marked
     * @param maxD
     * @param start
     * @param end
     */
    private static void rdp(final float[] verts, final boolean[] marked,
            final float maxD, final int start, final int end) {
        marked[start % marked.length] = true;
        marked[end % marked.length] = true;

        // find furthest from line
        float maxDistance = -1;
        int maxIndex = -1;

        float ax = verts[2 * start % verts.length];
        float ay = verts[(2 * start + 1) % verts.length];
        float bx = verts[2 * end % verts.length];
        float by = verts[(2 * end + 1) % verts.length];

        for (int i = start + 1; i < end; i++) {
            float px = verts[2 * i % verts.length];
            float py = verts[(2 * i + 1) % verts.length];

            float d = distanceToSegment(ax, ay, bx, by, px, py);

            if ((d > maxD) && (d > maxDistance)) {
                maxDistance = d;
                maxIndex = i;
            }
        }

        if (maxIndex != -1) {
            // recurse
            rdp(verts, marked, maxD, start, maxIndex);
            rdp(verts, marked, maxD, maxIndex, end);
        }
    }

    /**
     * @param ax
     * @param ay
     * @param bx
     * @param by
     * @param px
     * @param py
     * @return The distance from p to the line segment a-b
     */
    public static float distanceToSegment(float ax, float ay, float bx,
            float by, float px, float py) {
        float vx = bx - ax;
        float vy = by - ay;
        float wx = px - ax;
        float wy = py - ay;

        double c1 = wx * vx + wy * vy;
        double c2 = vx * vx + vy * vy;

        if (c1 <= 0) {
            return (float) Math.hypot((ax - px), (ay - py));
        }
        if (c1 >= c2) {
            return (float) Math.hypot(bx - px, (by - py));
        }

        double b = c1 / c2;
        vx *= b;
        vy *= b;

        vx += ax;
        vy += ay;

        return (float) Math.hypot((vx - px), (vy - py));
    }

    public static float distanceToSegment(PointF pointStart,
            PointF pointEnd, PointF point) {
        return distanceToSegment(pointStart.x, pointStart.y, pointEnd.x,
                pointEnd.y, point.x, point.y);

    }
}

Related Tutorials