package org.ripple.power.ui.graphics; import java.awt.Point; import org.ripple.power.ui.graphics.geom.RectBox; public abstract class LGraphicsMath { private static final int[] SHIFT = { 0, 1144, 2289, 3435, 4583, 5734, 6888, 8047, 9210, 10380, 11556, 12739, 13930, 15130, 16340, 17560, 18792, 20036, 21294, 22566, 23853, 25157, 26478, 27818, 29179, 30560, 31964, 33392, 34846, 36327, 37837, 39378, 40951, 42560, 44205, 45889, 47615, 49385, 51202, 53070, 54991, 56970, 59009, 61113, 63287, 65536 }; public final static int round(int div1, int div2) { final int remainder = div1 % div2; if (Math.abs(remainder) * 2 <= Math.abs(div2)) { return div1 / div2; } else if (div1 * div2 < 0) { return div1 / div2 - 1; } else { return div1 / div2 + 1; } } public final static long round(long div1, long div2) { final long remainder = div1 % div2; if (Math.abs(remainder) * 2 <= Math.abs(div2)) { return div1 / div2; } else if (div1 * div2 < 0) { return div1 / div2 - 1; } else { return div1 / div2 + 1; } } public final static int toShift(int angle) { if (angle <= 45) { return SHIFT[angle]; } else if (angle >= 315) { return -SHIFT[360 - angle]; } else if (angle >= 135 && angle <= 180) { return -SHIFT[180 - angle]; } else if (angle >= 180 && angle <= 225) { return SHIFT[angle - 180]; } else if (angle >= 45 && angle <= 90) { return SHIFT[90 - angle]; } else if (angle >= 90 && angle <= 135) { return -SHIFT[angle - 90]; } else if (angle >= 225 && angle <= 270) { return SHIFT[270 - angle]; } else { return -SHIFT[angle - 270]; } } public final static Point getBoundingPointAtAngle(int boundingX, int boundingY, int boundingWidth, int boundingHeight, int angle) { if (angle >= 315 || angle <= 45) { return new Point(boundingX + boundingWidth, boundingY + (boundingHeight * (65536 - toShift(angle)) >>> 17)); } else if (angle > 45 && angle < 135) { return new Point(boundingX + (boundingWidth * (65536 + toShift(angle)) >>> 17), boundingY); } else if (angle >= 135 && angle <= 225) { return new Point(boundingX, boundingY + (boundingHeight * (65536 + toShift(angle)) >>> 17)); } else { return new Point(boundingX + (boundingWidth * (65536 - toShift(angle)) >>> 17), boundingY + boundingHeight); } } public final static RectBox getBoundingBox(int xpoints[], int ypoints[], int npoints) { int boundsMinX = Integer.MAX_VALUE; int boundsMinY = Integer.MAX_VALUE; int boundsMaxX = Integer.MIN_VALUE; int boundsMaxY = Integer.MIN_VALUE; for (int i = 0; i < npoints; i++) { int x = xpoints[i]; boundsMinX = Math.min(boundsMinX, x); boundsMaxX = Math.max(boundsMaxX, x); int y = ypoints[i]; boundsMinY = Math.min(boundsMinY, y); boundsMaxY = Math.max(boundsMaxY, y); } return new RectBox(boundsMinX, boundsMinY, boundsMaxX - boundsMinX, boundsMaxY - boundsMinY); } public final static int getBoundingShape(int xPoints[], int yPoints[], int startAngle, int arcAngle, int centerX, int centerY, int boundingX, int boundingY, int boundingWidth, int boundingHeight) { xPoints[0] = centerX; yPoints[0] = centerY; Point startPoint = getBoundingPointAtAngle(boundingX, boundingY, boundingWidth, boundingHeight, startAngle); xPoints[1] = startPoint.x; yPoints[1] = startPoint.y; int i = 2; for (int angle = 0; angle < arcAngle; i++, angle += 90) { if (angle + 90 > arcAngle && ((startAngle + angle - 45) % 360) / 90 == ((startAngle + arcAngle + 45) % 360) / 90) { break; } int modAngle = (startAngle + angle) % 360; if (modAngle > 315 || modAngle <= 45) { xPoints[i] = boundingX + boundingWidth; yPoints[i] = boundingY; } else if (modAngle > 135 && modAngle <= 225) { xPoints[i] = boundingX; yPoints[i] = boundingY + boundingHeight; } else if (modAngle > 45 && modAngle <= 135) { xPoints[i] = boundingX; yPoints[i] = boundingY; } else { xPoints[i] = boundingX + boundingWidth; yPoints[i] = boundingY + boundingHeight; } } Point endPoint = getBoundingPointAtAngle(boundingX, boundingY, boundingWidth, boundingHeight, (startAngle + arcAngle) % 360); if (xPoints[i - 1] != endPoint.x || yPoints[i - 1] != endPoint.y) { xPoints[i] = endPoint.x; yPoints[i++] = endPoint.y; } return i; } public final static boolean contains(int xPoints[], int yPoints[], int nPoints, RectBox bounds, int x, int y) { if ((bounds != null && bounds.inside(x, y)) || (bounds == null && getBoundingBox(xPoints, yPoints, nPoints) .inside(x, y))) { int hits = 0; int ySave = 0; int i = 0; while (i < nPoints && yPoints[i] == y) { i++; } for (int n = 0; n < nPoints; n++) { int j = (i + 1) % nPoints; int dx = xPoints[j] - xPoints[i]; int dy = yPoints[j] - yPoints[i]; if (dy != 0) { int rx = x - xPoints[i]; int ry = y - yPoints[i]; if (yPoints[j] == y && xPoints[j] >= x) { ySave = yPoints[i]; } if (yPoints[i] == y && xPoints[i] >= x) { if ((ySave > y) != (yPoints[j] > y)) { hits--; } } if (ry * dy >= 0 && (ry <= dy && ry >= 0 || ry >= dy && ry <= 0) && round(dx * ry, dy) >= rx) { hits++; } } i = j; } return (hits % 2) != 0; } return false; } }