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.