bool line_intersects_rect(const vector2& l_s, const vector2& l_e, const vector2& r_s, const vector2& r_e) { // // I translated this from intersectsLine in // http://www.opensource.apple.com/source/gcc_os/ // gcc_os-1256/libjava/java/awt/geom/Rectangle2D.java // // Seeing as they're professionals, they might know what they're doing ;-) // enum { OUT_LEFT = 1, OUT_TOP = 2, OUT_RIGHT = 4, OUT_BOTTOM = 8 }; #define OUTCODE(x1, y1, x2, y2, w, h, v)\ do {\ if ((x1) < (x2)) {\ (v) |= OUT_LEFT;\ } else if ((x1) >= (x2) + (w)) {\ (v) |= OUT_RIGHT;\ }\ if ((y1) < (y2)) {\ (v) |= OUT_TOP;\ } else if ((y1) >= (y2) + (h)) {\ (v) |= OUT_BOTTOM;\ }\ } while (0) double r_w = r_e[0] - r_s[0], r_h = r_e[1] - r_s[1], r_x = r_s[0], r_y = r_s[1], x1 = l_s[0], y1 = l_s[1], x2 = l_e[0], y2 = l_e[1], mx = r_x, my = r_y, mx2 = r_w, my2 = r_h; int o1 = 0, o2 = 0; OUTCODE(x1, y1, r_x, r_y, r_w, r_h, o1); OUTCODE(x2, y2, r_x, r_y, r_w, r_h, o2); x1 -= mx; x2 -= mx; y1 -= my; y2 -= my; // Here we handle all lines that stay entirely on one side of the // rectangle. We also handle some lines that intersect the // rectangle. All vertical and horizontal lines are handled here. int x_or = o1 ^ o2; int o_r = o1 | o2; if ((x_or & (OUT_BOTTOM | OUT_TOP)) == 0) { if ((o_r & (OUT_BOTTOM | OUT_TOP)) != 0) { return false; } return ((o1 & (OUT_LEFT | OUT_RIGHT)) != 0 || (o2 & (OUT_LEFT | OUT_RIGHT)) != 0); } else if ((x_or & (OUT_LEFT | OUT_RIGHT)) == 0) { if ((o_r & (OUT_LEFT | OUT_RIGHT)) != 0) { return false; } return ((o1 & (OUT_BOTTOM | OUT_TOP)) != 0 || (o2 & (OUT_BOTTOM | OUT_TOP)) != 0); } double dx = x2 - x1, dy = y2 - y1, t1l = - x1 / dx, t1h = (mx2 - x1) / dx; if (t1l >= t1h) { return false; } double t2l = - y1 / dy, t2h = (my2 - y1) / dy; if (t2l >= t2h || t2l >= t1h || t2h < t1l) { return false; } return true; }
void DibBitmap::DrawLine(short x1, short y1, short x2, short y2, Color clr) { int xl = 0, yb = 0; int xr = m_siz.cx - 1; int yt = m_siz.cy - 1; int adx, ady, adx2, ady2, sx, sy; int out1, out2, type1, type2; int ca, cb, r, diff, xs, ys, n, alt; OUTCODE(x1, y1, out1, type1); OUTCODE(x2, y2, out2, type2); if (out1 & out2) return; if ((type1 != 0 && type2 == 0) || (type1 == 2 && type2 == 1)){ SWAP(out1, out2); SWAP(type1, type2); SWAP(x1, x2); SWAP(y1, y2); } xs = x1; ys = y1; sx = 1; adx = x2 - x1; if (adx < 0) { adx = -adx; sx = -1; } sy = 1; ady = y2 - y1; if (ady < 0) { ady = -ady; sy = -1; } adx2 = adx + adx; ady2 = ady + ady; if (adx >= ady) { /* * line is semi-horizontal */ r = ady2 - adx; CLIP(x1, x2, y1, adx, adx2, ady2, xs, ys, sx, sy, xl, LEFT, xr, RIGHT, yb, BOTTOM, yt, TOP); diff = ady2 - adx2; if (alt) { for (;; xs += sx) { /* alternate Bresenham */ plot(xs, ys); if (r >= 0 ) { if (--n < 0) break; r += diff; ys += sy; } else r += ady2; } } else{ for (;; xs += sx) { /* standard Bresenham */ plot(xs, ys); if (--n < 0) break; if (r >= 0 ) { r += diff; ys += sy; } else r += ady2; } } } else { /* * line is semi-vertical */ r = adx2 - ady; CLIP(y1, y2, x1, ady, ady2, adx2, ys, xs, sy, sx, yb, BOTTOM, yt, TOP, xl, LEFT, xr, RIGHT); diff = adx2 - ady2; if (alt) { for (;; ys += sy) { /* alternate Bresenham */ plot(xs, ys); if (r >= 0 ) { if (--n < 0) break; r += diff; xs += sx; } else r += adx2; } } else { for (;; ys += sy) { /* standard Bresenham */ plot(xs, ys); if (--n < 0) break; if (r >= 0 ) { r += diff; xs += sx; } else r += adx2; } } } }