I have written generic Point classes, line/line intersection algorithms and Layer administration code more times than I can remember. I don't like menial programming, so this is effectively my code library. But you can use it too!
The language used is Processing, which is a mostly-Java-syntax language. I hardly ever use Java-specific ninja code, so rewriting any of these snippets to your favourite language is less than a minute's worth of work, typically.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | /**
* Verify whether some line across an image mask
* actually registers as touching the mask or not.
* We use Bresenham's line algorithm, with a
* safety conditional to prevent infinite loops.
*
* INPUTS a mask image with non-transparent pixels
* for its mask area, {sx,sy,ex,ey} representing
* the line across the image, and {ox,oy}
* representing the image offset with respect
* to the world's (0,0), used to turn points
* on the line {S,E} into points in the image mask.
*
* RETURNS boolean representing whether or not mask
* overlap occurred. This method may also fail
* if the line segment covers more than 65,535
* pixels, due to the iteration safety value.
*/
boolean isSpriteMasked(PImage mask, float sx, float sy, float ex, float ey, float ox, float oy) {
int x0 = (int) round(sx), // start coordinate
y0 = (int) round(sy),
x1 = (int) round(ex), // end coordinate
y1 = (int) round(ey),
dx = (int) abs(x1-x0), // distance to travel
dy = (int) abs(y1-y0),
ax = (x0<x1) ? 1 : -1, // x and y stepping values
ay = (y0<y1) ? 1 : -1,
err = dx-dy,
// Normally you rely on "while(true)", but no one
// should ever do that. Safety first: add a cutoff.
safety = 0;
while(safety++ < 0xFFFF) {
// The intersection is valid if we find a
// pixel in the mask that is not transparent.
if(alpha(mask.get(x0-(int)ox, y0-(int)oy)) > 0) {
return true;
}
// We must stop when we've reached the end coordinate
else if(x0==x1 && y0==y1) {
return false;
}
// continue: move to the next pixel.
int e2 = err << 1;
if(e2 > -dy) { err -= dy; x0 += ax; }
if(e2 < dx) { err += dx; y0 += ay; }
}
// this code is unreachable, but ONLY in isolated theory.
// if you have a typo when you call this method, and ex or
// ey is really high, you want this loop to fail instead
// of running a few million times, eating up all your cycles.
return false;
} |
Written and maintained by Mike "Pomax" Kamermans. All code snippets on this site are "do whatever you want with it" licensed.