package net.sourceforge.jmicropolygon; /** * Geometry utilities in support of polygon graphics in J2ME * * @author <a href="mailto:simonturner@users.sourceforge.net">Simon Turner</a> * @version $Id: GeomUtils.java,v 1.4 2006/02/26 17:21:44 simonturner Exp $ */ public abstract class GeomUtils { /** * Is the point represented by px and py within the triangle * represented by ax,ay,bx,by,cx,cy? * * @param px The x of the point to test * @param py The y of the point to test * @param ax The x of the 1st point of the triangle * @param ay The y of the 1st point of the triangle * @param bx The x of the 2nd point of the triangle * @param by The y of the 2nd point of the triangle * @param cx The x of the 3rd point of the triangle * @param cy The y of the 3rd point of the triangle * @return true if the point is inside the triangle */ public static boolean withinBounds(int px, int py, int ax, int ay, int bx, int by, int cx, int cy) { if ( px < min(ax, bx, cx) || px > max(ax, bx, cx) || py < min(ay, by, cy) || py > max(ay, by, cy) ) { return false; } boolean sameabc = sameSide(px, py, ax, ay, bx, by, cx, cy); boolean samebac = sameSide(px, py, bx, by, ax, ay, cx, cy); boolean samecab = sameSide(px, py, cx, cy, ax, ay, bx, by); return sameabc && samebac && samecab; } /** * Split a polygon into two, divided by the diagonal between the point * at aIndex and the point at bIndex. Nb: assumes that the line between * the two points is completely within the polygon. * * @param xPoints The x-points of the polygon * @param yPoints The y-points of the polygon * @param aIndex The index within the polygon of the first point * of the internal line * @param bIndex The index within the polygon of the second point * of the internal line * @return A 3D array of ints, where the 2 top-level arrays * represent 2 new polygons; each polygon consists of a * 2D array of ints, where the 1st sub-array represents * xPoints and the second sub-array represents yPoints, * eg: [[[ax1,ax2,ax3][ay1,ay2,ay3]],[[bx1,bx2][by1,by2]]] */ static int[][][] split(int[] xPoints, int[] yPoints, int aIndex, int bIndex) { int firstLen, secondLen; if (bIndex < aIndex) { firstLen = (xPoints.length - aIndex) + bIndex + 1; } else { firstLen = (bIndex - aIndex) + 1; } secondLen = (xPoints.length - firstLen) + 2; int[][] first = new int[2][firstLen]; int[][] second = new int[2][secondLen]; for (int i=0; i<firstLen; i++) { int index = (aIndex + i) % xPoints.length; first[0][i] = xPoints[index]; first[1][i] = yPoints[index]; } for (int i=0; i<secondLen; i++) { int index = (bIndex + i) % xPoints.length; second[0][i] = xPoints[index]; second[1][i] = yPoints[index]; } int[][][] result = new int[2][][]; result[0] = first; result[1] = second; return result; } /** * Trim an "ear" off a polygon * * @param xPoints The x-points of the polygon * @param yPoints The y-points of the polygon * @param earIndex The index of the point to remove * @return The supplied polygon, without the point at earIndex */ static int[][] trimEar(int[] xPoints, int[] yPoints, int earIndex) { int[] newXPoints = new int[xPoints.length - 1]; int[] newYPoints = new int[yPoints.length - 1]; int[][] newPoly = new int[2][]; newPoly[0] = newXPoints; newPoly[1] = newYPoints; int p = 0; for (int i=0; i<xPoints.length; i++) { if (i != earIndex) { newXPoints[p] = xPoints[i]; newYPoints[p] = yPoints[i]; p++; } } return newPoly; } /** * Get the index of the lowest value in the array * * @param elements The values from which the lowest is to be found * @return The index of the lowest value in the array */ static int indexOfLeast(int[] elements) { int index = 0; int least = elements[0]; for (int i=1; i<elements.length; i++) { if (elements[i] < least) { index = i; least = elements[i]; } } return index; } static int indexOfBiggest(int[] elements){ int index = 0; int biggest = elements[0]; for (int i=1; i<elements.length; i++){ if (elements[i] > biggest){ index = i; biggest = elements[i]; } } return index; } // internal helpers /** * @return true if the line p1 and p2 are both on the same side of * the line between l1 and l2. If one of the points is actually * on the line that is still considered the same side. */ private static boolean sameSide (int p1x, int p1y, int p2x, int p2y, int l1x, int l1y, int l2x, int l2y) { long lhs = ((p1x - l1x) * (l2y - l1y) - (l2x - l1x) * (p1y - l1y)); long rhs = ((p2x - l1x) * (l2y - l1y) - (l2x - l1x) * (p2y - l1y)); long product = lhs * rhs; boolean result = product >= 0; return result; } /** * @return The smallest of three numbers */ public static int min(int a, int b, int c) { return Math.min(Math.min(a,b),c); } /** * @return The biggest of three numbers */ public static int max(int a, int b, int c) { return Math.max(Math.max(a,b),c); } }