Esempio n. 1
0
    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;
    }
Esempio n. 2
0
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;
			}
		}
	}
}