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 53 54 55 56 57 58 59 60 | // REQUIRES: LinePairRotation.pde // REQUIRES: LineLineIntersection.pde /** * Line-through-box intersection algorithm. * * INPUT x1,y1,x2,y2 constitute a line segment S1 * minx,miny,maxx,maxy constitute a world-aligned rectangular box * colinearity is a boolean indicating whether or not lines that are * colinear with one of the box edges count as intersecting. * * Note that the follow assumptions are made: minx<maxx, miny<maxy * * RETURNS ArrayList<float[2/3]> representing all found intersections {x, y} * with an optional third element [2] that * indicates whether the intersections are on edges, * or (when the line segment is full contained * by the bounding box) somewhere inside the box. * * Note that we do not return null when no intersections are found, but * instead return an empty list. There's no point in checking the size * of the list every time this function is called. */ ArrayList<float[]> getLineRectIntersection(float x1, float y1, float x2, float y2, float minx, float miny, float maxx, float maxy, boolean colinearity) { ArrayList<float[]> intersections = new ArrayList<float[]>(); // It's possible that the line segment is fully contained // by the bounding box. This is easily, and quickly, checked // for. Note that even though the conditional is four AND // clauses, boolean AND evaluation stops the moment any of them // is false, so we're doing at most four checks. if (minx<min(x1,x2) && max(x1,x2)<maxx && miny<min(y1,y2) && max(y1,y2)<maxy) { // full containment makes the end points "intersections" intersections.add(new float[]{x1,y1,0}); intersections.add(new float[]{x2,y2,0}); } // If we get here, the line is not fully contained else { // form the four edges float[][] edges = {{minx, miny, maxx, miny}, {maxx, miny, maxx, maxy}, {minx, maxy, maxx, maxy}, {minx, miny, minx, maxy}}; // perform line/line intersection detection for each edge for (float[] edge: edges) { float[] intersection = getLineLineIntersection(x1, y1, x2, y2, edge[0], edge[1], edge[2], edge[3], colinearity); if (intersection!=null) { intersections.add(intersection); // As we can't have more than two intersections, // stop iterating when we have found two of them. if(intersections.size()==2) { break; } } } } // At this point intersections is guaranteed // to contain all intersections. Return it. return intersections; } |
Written and maintained by Mike "Pomax" Kamermans. All code snippets on this site are "do whatever you want with it" licensed.