Android examples for java.lang:Math Geometry
Removes unnecessary vertices from a line strip.
/******************************************************************************* * 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); } }