diff --git a/vtm/src/org/oscim/layers/tile/vector/labeling/Debug.java b/vtm/src/org/oscim/layers/tile/vector/labeling/Debug.java index 165db5f3..8c0932b0 100644 --- a/vtm/src/org/oscim/layers/tile/vector/labeling/Debug.java +++ b/vtm/src/org/oscim/layers/tile/vector/labeling/Debug.java @@ -24,7 +24,7 @@ import org.oscim.theme.styles.Line; class Debug { - private final static float[] mDebugPoints = new float[4]; + private final static float[] mDebugPoints = new float[8]; static void addDebugBox(ElementLayers dbg, Label l, TextItem ti, int overlaps, boolean prev, float scale) { @@ -57,8 +57,9 @@ class Debug { points[3] = (l.y + height * scale); ll.addLine(points, 4, false); + System.arraycopy(l.bbox.vec, 2, points, 0, 8); if (l.bbox != null && overlaps != 3) { - ll.addLine(l.bbox.corner, 8, true); + ll.addLine(points, 8, true); } } diff --git a/vtm/src/org/oscim/utils/OBB2D.java b/vtm/src/org/oscim/utils/OBB2D.java index 0a2cb27e..927f6021 100644 --- a/vtm/src/org/oscim/utils/OBB2D.java +++ b/vtm/src/org/oscim/utils/OBB2D.java @@ -17,115 +17,129 @@ package org.oscim.utils; /** - * from http://www.flipcode.com/archives/2D_OBB_Intersection.shtml - * - * @author Morgan McGuire morgan@cs.brown.edu - * @author Hannes Janetzek + * ported from http://www.flipcode.com/archives/2D_OBB_Intersection.shtml */ public class OBB2D { + /** + * Vector math for one array + */ public static class Vec2 { public static void set(float[] v, int pos, float x, float y) { - v[(pos << 1) + 0] = x; - v[(pos << 1) + 1] = y; + v[pos + 0] = x; + v[pos + 1] = y; } - public static float dot(float[] a, int apos, float[] b, int bpos) { - return a[apos << 1] * b[bpos << 1] + a[(apos << 1) + 1] * b[(bpos << 1) + 1]; + public static float dot(float[] v, int a, int b) { + return v[a] * v[b] + v[a + 1] * v[b + 1]; } public final static float lengthSquared(float[] v, int pos) { - float x = v[(pos << 1) + 0]; - float y = v[(pos << 1) + 1]; + float x = v[pos + 0]; + float y = v[pos + 1]; return x * x + y * y; } public final static void normalizeSquared(float[] v, int pos) { - float x = v[(pos << 1) + 0]; - float y = v[(pos << 1) + 1]; + float x = v[pos + 0]; + float y = v[pos + 1]; float length = x * x + y * y; - v[(pos << 1) + 0] = x / length; - v[(pos << 1) + 1] = y / length; + v[pos + 0] = x / length; + v[pos + 1] = y / length; } public final static void normalize(float[] v, int pos) { - float x = v[(pos << 1) + 0]; - float y = v[(pos << 1) + 1]; + float x = v[pos + 0]; + float y = v[pos + 1]; double length = Math.sqrt(x * x + y * y); - v[(pos << 1) + 0] = (float) (x / length); - v[(pos << 1) + 1] = (float) (y / length); + v[pos + 0] = (float) (x / length); + v[pos + 1] = (float) (y / length); } public final static float length(float[] v, int pos) { - float x = v[(pos << 1) + 0]; - float y = v[(pos << 1) + 1]; + float x = v[pos + 0]; + float y = v[pos + 1]; return (float) Math.sqrt(x * x + y * y); } - public final static void add(float[] result, int rpos, float[] a, int apos, float[] b, - int bpos) { - result[(rpos << 1) + 0] = a[(apos << 1) + 0] + b[(bpos << 1) + 0]; - result[(rpos << 1) + 1] = a[(apos << 1) + 1] + b[(bpos << 1) + 1]; + public final static void add(float[] v, int r, int a, int b) { + v[r + 0] = v[a + 0] + v[b + 0]; + v[r + 1] = v[a + 1] + v[b + 1]; } - public final static void sub(float[] result, int rpos, float[] a, int apos, float[] b, - int bpos) { - result[(rpos << 1) + 0] = a[(apos << 1) + 0] - b[(bpos << 1) + 0]; - result[(rpos << 1) + 1] = a[(apos << 1) + 1] - b[(bpos << 1) + 1]; + public final static void sub(float[] v, int r, int a, int b) { + v[r + 0] = v[a + 0] - v[b + 0]; + v[r + 1] = v[a + 1] - v[b + 1]; } public final static void mul(float[] v, int pos, float a) { - v[(pos << 1) + 0] *= a; - v[(pos << 1) + 1] *= a; + v[pos + 0] *= a; + v[pos + 1] *= a; } } + float originX; + float originY; + + public final float[] vec = new float[4 * 2 + 2 * 2]; + // Corners of the box, where 0 is the lower left. - public final float[] corner = new float[4 * 2]; + //public final float[] corner = new float[ 4 * 2]; + private final static int CORNER_X = 0; + private final static int CORNER_Y = CORNER_X + 1; + private final static int CORNER_0 = CORNER_X; + private final static int CORNER_1 = CORNER_X + 2; + //private final static int CORNER_2 = CORNER_X + 4; + private final static int CORNER_3 = CORNER_X + 6; - // Two edges of the box extended away from corner[0]. - public final float[] axis = new float[2 * 2]; + // Two edges of the box extended away from origin[CORNER_X + 0]. + //public final float[] axis = new float[2 * 2]; + private final static int AXIS_X = 2 * 4; + private final static int AXIS_Y = AXIS_X + 1; - // origin[a] = corner[0].dot(axis[a]); - public final float[] origin = new float[2]; + private final static int AXIS_1 = AXIS_X; + private final static int AXIS_2 = AXIS_X + 2; // Returns true if other overlaps one dimension of this. private boolean overlaps1Way(OBB2D other) { - for (int a = 0; a < 2; a++) { - float ax = axis[a * 2]; - float ay = axis[a * 2 + 1]; + for (int a = 0; a <= 2; a += 2) { + float ax = vec[AXIS_X + a]; + float ay = vec[AXIS_Y + a]; // dot product - float t = ax * other.corner[0] + ay * other.corner[1]; + float t = ax * other.vec[CORNER_X] + ay * other.vec[CORNER_Y]; // Find the extent of box 2 on axis a float tMin = t; float tMax = t; - for (int c = 2; c < 8; c += 2) { - t = ax * other.corner[c] + ay * other.corner[c + 1]; + for (int c = CORNER_X + 2; c < 8; c += 2) { + t = ax * other.vec[c] + ay * other.vec[c + 1]; - if (t < tMin) { + if (t < tMin) tMin = t; - } else if (t > tMax) { + else if (t > tMax) tMax = t; - } } // We have to subtract off the origin // See if [tMin, tMax] intersects [0, 1] - if ((tMin > 1 + origin[a]) || (tMax < origin[a])) { - // There was no intersection along this dimension; - // the boxes cannot possibly overlap. - return false; + if (a == 0) { + if ((tMin > 1 + originX) || (tMax < originX)) + // There was no intersection along this dimension; + // the boxes cannot possibly overlap. + return false; + } else { + if ((tMin > 1 + originY) || (tMax < originY)) + return false; } } @@ -137,42 +151,42 @@ public class OBB2D { // Updates the axes after the corners move. Assumes the // corners actually form a rectangle. private void computeAxes() { - Vec2.sub(axis, 0, corner, 1, corner, 0); - Vec2.sub(axis, 1, corner, 3, corner, 0); + Vec2.sub(vec, AXIS_1, CORNER_1, CORNER_0); + Vec2.sub(vec, AXIS_2, CORNER_3, CORNER_0); // Make the length of each axis 1/edge length so we know any // dot product must be less than 1 to fall within the edge. - Vec2.normalizeSquared(axis, 0); - origin[0] = Vec2.dot(corner, 0, axis, 0); + Vec2.normalizeSquared(vec, AXIS_1); + originX = Vec2.dot(vec, CORNER_0, AXIS_1); - Vec2.normalizeSquared(axis, 1); - origin[1] = Vec2.dot(corner, 0, axis, 1); - } - - public OBB2D(float cx, float cy, float w, float h, float angle) { - float rcos = (float) Math.cos(angle); - float rsin = (float) Math.sin(angle); - - float[] tmp = new float[4 * 2]; - Vec2.set(tmp, 0, rcos, rsin); - Vec2.set(tmp, 1, -rsin, rcos); - - Vec2.mul(tmp, 0, w / 2); - Vec2.mul(tmp, 1, h / 2); - - Vec2.add(tmp, 2, tmp, 0, tmp, 1); - Vec2.sub(tmp, 3, tmp, 0, tmp, 1); - - Vec2.set(tmp, 0, cx, cy); - - Vec2.sub(corner, 0, tmp, 0, tmp, 3); - Vec2.add(corner, 1, tmp, 0, tmp, 3); - Vec2.add(corner, 2, tmp, 0, tmp, 2); - Vec2.sub(corner, 3, tmp, 0, tmp, 2); - - computeAxes(); + Vec2.normalizeSquared(vec, AXIS_2); + originY = Vec2.dot(vec, CORNER_0, AXIS_2); } + // public OBB2D(float cx, float cy, float w, float h, float angle) { + // float rcos = (float) Math.cos(angle); + // float rsin = (float) Math.sin(angle); + // + // float[] tmp = new float[4 * 2]; + // Vec2.set(tmp, 0, rcos, rsin); + // Vec2.set(tmp, 1, -rsin, rcos); + // + // Vec2.mul(tmp, 0, w / 2); + // Vec2.mul(tmp, 1, h / 2); + // + // Vec2.add(tmp, 2, tmp, 0, tmp, 1); + // Vec2.sub(tmp, 3, tmp, 0, tmp, 1); + // + // Vec2.set(tmp, 0, cx, cy); + // + // Vec2.sub(origin, CORNER_X + 0, tmp, 0, tmp, 3); + // Vec2.add(origin, CORNER_X + 2, tmp, 0, tmp, 3); + // Vec2.add(origin, CORNER_X + 4, tmp, 0, tmp, 2); + // Vec2.sub(origin, CORNER_X + 6, tmp, 0, tmp, 2); + // + // computeAxes(); + // } + // public OBB2D() { } @@ -185,17 +199,17 @@ public class OBB2D { float ux = (float) -asin * height / 2; float uy = (float) acos * height / 2; - corner[0] = cx + (vx - ux); - corner[1] = cy + (vy - uy); + vec[CORNER_X] = cx + (vx - ux); + vec[CORNER_Y] = cy + (vy - uy); - corner[2] = cx + (-vx - ux); - corner[3] = cy + (-vy - uy); + vec[CORNER_X + 2] = cx + (-vx - ux); + vec[CORNER_Y + 2] = cy + (-vy - uy); - corner[4] = cx + (-vx + ux); - corner[5] = cy + (-vy + uy); + vec[CORNER_X + 4] = cx + (-vx + ux); + vec[CORNER_Y + 4] = cy + (-vy + uy); - corner[6] = cx + (vx + ux); - corner[7] = cy + (vy + uy); + vec[CORNER_X + 6] = cx + (vx + ux); + vec[CORNER_Y + 6] = cy + (vy + uy); computeAxes(); } @@ -219,17 +233,17 @@ public class OBB2D { ux *= hh; uy *= hh; - corner[0] = cx - (vx - ux); - corner[1] = cy - (vy - uy); + vec[CORNER_X] = cx - (vx - ux); + vec[CORNER_Y] = cy - (vy - uy); - corner[2] = cx + (vx - ux); - corner[3] = cy + (vy - uy); + vec[CORNER_X + 2] = cx + (vx - ux); + vec[CORNER_Y + 2] = cy + (vy - uy); - corner[4] = cx + (vx + ux); - corner[5] = cy + (vy + uy); + vec[CORNER_X + 4] = cx + (vx + ux); + vec[CORNER_Y + 4] = cy + (vy + uy); - corner[6] = cx - (vx + ux); - corner[7] = cy - (vy + uy); + vec[CORNER_X + 6] = cx - (vx + ux); + vec[CORNER_Y + 6] = cy - (vy + uy); computeAxes(); } @@ -251,17 +265,17 @@ public class OBB2D { vx *= hw; vy *= hw; - corner[0] = cx - vx - ux; - corner[1] = cy - vy - uy; + vec[CORNER_X] = cx - vx - ux; + vec[CORNER_Y] = cy - vy - uy; - corner[2] = cx + vx - ux; - corner[3] = cy + vy - uy; + vec[CORNER_X + 2] = cx + vx - ux; + vec[CORNER_Y + 2] = cy + vy - uy; - corner[4] = cx + vx + ux; - corner[5] = cy + vy + uy; + vec[CORNER_X + 4] = cx + vx + ux; + vec[CORNER_Y + 4] = cy + vy + uy; - corner[6] = cx - vx + ux; - corner[7] = cy - vy + uy; + vec[CORNER_X + 6] = cx - vx + ux; + vec[CORNER_Y + 6] = cy - vy + uy; computeAxes(); } @@ -284,17 +298,17 @@ public class OBB2D { vx *= hw; vy *= hw; - corner[0] = cx - vx - ux; - corner[1] = cy - vy - uy; + vec[CORNER_X + 0] = cx - vx - ux; + vec[CORNER_Y + 0] = cy - vy - uy; - corner[2] = cx + vx - ux; - corner[3] = cy + vy - uy; + vec[CORNER_X + 2] = cx + vx - ux; + vec[CORNER_Y + 2] = cy + vy - uy; - corner[4] = cx + vx + ux; - corner[5] = cy + vy + uy; + vec[CORNER_X + 4] = cx + vx + ux; + vec[CORNER_Y + 4] = cy + vy + uy; - corner[6] = cx - vx + ux; - corner[7] = cy - vy + uy; + vec[CORNER_X + 6] = cx - vx + ux; + vec[CORNER_Y + 6] = cy - vy + uy; computeAxes(); } @@ -305,26 +319,26 @@ public class OBB2D { float hw = width / 2; float hh = height / 2; - corner[0] = cx - hw; - corner[1] = cy - hh; + vec[CORNER_X] = cx - hw; + vec[CORNER_Y] = cy - hh; - corner[2] = cx - hw; - corner[3] = cy + hh; + vec[CORNER_X + 2] = cx - hw; + vec[CORNER_Y + 2] = cy + hh; - corner[4] = cx + hw; - corner[5] = cy + hh; + vec[CORNER_X + 4] = cx + hw; + vec[CORNER_Y + 4] = cy + hh; - corner[6] = cx + hw; - corner[7] = cy - hh; + vec[CORNER_X + 6] = cx + hw; + vec[CORNER_Y + 6] = cy - hh; - axis[0] = 0; - axis[1] = 1 / height; + vec[AXIS_X + 0] = 0; + vec[AXIS_X + 1] = 1 / height; - axis[2] = 1 / width; - axis[3] = 0; + vec[AXIS_X + 2] = 1 / width; + vec[AXIS_X + 3] = 0; - origin[0] = corner[1] * axis[1]; - origin[1] = corner[2] * axis[2]; + vec[0] = vec[CORNER_Y] * vec[AXIS_Y]; + vec[1] = vec[CORNER_X + 2] * vec[AXIS_X + 2]; } // Returns true if the intersection of the boxes is non-empty. @@ -334,12 +348,12 @@ public class OBB2D { // // For testing purposes. // void moveTo(Vec2 center) { - // Vec2 centroid = (corner[0] + corner[1] + corner[2] + corner[3]) / 4; + // Vec2 centroid = (origin[CORNER_X + 0] + origin[CORNER_X + 1] + origin[CORNER_X + 2] + origin[CORNER_X + 3]) / 4; // // Vec2 translation = center - centroid; // // for (int c = 0; c < 4; ++c) { - // corner[c] += translation; + // origin[CORNER_X + c] += translation; // } // // computeAxes(); @@ -348,7 +362,7 @@ public class OBB2D { // void render() { // glBegin(GL_LINES); // for (int c = 0; c < 5; ++c) { - // glVertex2fv(corner[c & 3]); + // glVertex2fv(origin[CORNER_X + c & 3]); // } // glEnd(); // }