// Cohen–Sutherland clipping algorithm clips a line from // P0 = (x0, y0) to P1 = (x1, y1) against a rectangle with // diagonal from (xmin, ymin) to (xmax, ymax). bool Graph::Clip(Line &r) const { // compute outcodes for P0, P1, and whatever point lies outside the clip rectangle uint8_t ca = ComputeOutCode(r.a); uint8_t cb = ComputeOutCode(r.b); for (;;) { if (!(ca | cb)) { // Bitwise OR is 0. Trivially accept and get out of loop return true; } else if (ca & cb) { // Bitwise AND is not 0. Trivially reject and get out of loop return false; } else { // failed both tests, so calculate the line segment to clip // from an outside point to an intersection with clip edge // At least one endpoint is outside the clip rectangle; pick it. uint8_t c = ca ? ca : cb; // Now find the intersection point; // use formulas y = y0 + slope * (x - x0), x = x0 + (1 / slope) * (y - y0) Point p; if (c & TOP) { // point is above the clip rectangle p.x = r.a.x + (r.b.x - r.a.x) * (_view->b.y - r.a.y) / (r.b.y - r.a.y); p.y = _view->b.y; } else if (c & BOTTOM) { // point is below the clip rectangle p.x = r.a.x + (r.b.x - r.a.x) * (_view->a.y - r.a.y) / (r.b.y - r.a.y); p.y = _view->a.y; } else if (c & RIGHT) { // point is to the right of clip rectangle p.y = r.a.y + (r.b.y - r.a.y) * (_view->b.x - r.a.x) / (r.b.x - r.a.x); p.x = _view->b.x; } else { // point is to the left of clip rectangle p.y = r.a.y + (r.b.y - r.a.y) * (_view->a.x - r.a.x) / (r.b.x - r.a.x); p.x = _view->a.x; } // Now we move outside point to intersection point to clip // and get ready for next pass. if (c == ca) { r.a = p; ca = ComputeOutCode(r.a); } else { r.b = p; cb = ComputeOutCode(r.b); } } } }
// Cohen–Sutherland clipping algorithm clips a line from // P0 = (x0, y0) to P1 = (x1, y1) against a rectangle with // diagonal from (xmin, ymin) to (xmax, ymax). void drawline(rgbData data[][WIDTH], int x0, int y0, int x1, int y1, struct rgbData color) { // compute outcodes for P0, P1, and whatever point lies outside the clip rectangle OutCode outcode0 = ComputeOutCode(x0, y0); OutCode outcode1 = ComputeOutCode(x1, y1); bool accept = false; while (true) { if (!(outcode0 | outcode1)) { // Bitwise OR is 0. Trivially accept and get out of loop accept = true; break; } else if (outcode0 & outcode1) { // Bitwise AND is not 0. Trivially reject and get out of loop break; } else { // failed both tests, so calculate the line segment to clip // from an outside point to an intersection with clip edge double x, y; // At least one endpoint is outside the clip rectangle; pick it. OutCode outcodeOut = outcode0 ? outcode0 : outcode1; // Now find the intersection point; // use formulas y = y0 + slope * (x - x0), x = x0 + (1 / slope) * (y - y0) if (outcodeOut & TOP) { // point is above the clip rectangle x = x0 + (x1 - x0) * (HEIGHT - 1 - y0) / (double)(y1 - y0); y = HEIGHT - 1; } else if (outcodeOut & BOTTOM) { // point is below the clip rectangle x = x0 + (x1 - x0) * (0 - y0) / (double)(y1 - y0); y = 0; } else if (outcodeOut & RIGHT) { // point is to the right of clip rectangle y = y0 + (y1 - y0) * (WIDTH - 1 - x0) / (double)(x1 - x0); x = WIDTH - 1; } else if (outcodeOut & LEFT) { // point is to the left of clip rectangle y = y0 + (y1 - y0) * (0 - x0) / (double)(x1 - x0); x = 0; } // Now we move outside point to intersection point to clip // and get ready for next pass. if (outcodeOut == outcode0) { x0 = (int)x; y0 = (int)y; outcode0 = ComputeOutCode(x0, y0); } else { x1 = (int)x; y1 = (int)y; outcode1 = ComputeOutCode(x1, y1); } } } if (accept) drawlineUnsafe(data, x0, y0, x1, y1, color); }
// http://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland // Cohen–Sutherland clipping algorithm clips a line from // P0 = (x0, y0) to P1 = (x1, y1) against a rectangle with // diagonal from (xmin, ymin) to (xmax, ymax). //void CohenSutherlandLineClipAndDraw( void dDrawLine(unsigned char A[],double x0, double y0, double x1, double y1, int RayNumber, int color ) { // compute outcodes for P0, P1, and whatever point lies outside the clip rectangle int outcode0 = ComputeOutCode(x0, y0); int outcode1 = ComputeOutCode(x1, y1); int accept = 0; unsigned int ix0, iy0; // screen coordinate = indices of virtual 2D array unsigned int ix1, iy1; // screen coordinate = indices of virtual 2D array while (1) { if (!(outcode0 | outcode1)) { // Bitwise OR is 0. Trivially accept and get out of loop accept = 1; break; } else if (outcode0 & outcode1) { // Bitwise AND is not 0. Trivially reject and get out of loop break; } else { // failed both tests, so calculate the line segment to clip // from an outside point to an intersection with clip edge double x, y; // At least one endpoint is outside the clip rectangle; pick it. int outcodeOut = outcode0 ? outcode0 : outcode1; // Now find the intersection point; // use formulas y = y0 + slope * (x - x0), x = x0 + (1 / slope) * (y - y0) if (outcodeOut & TOP) { // point is above the clip rectangle x = x0 + (x1 - x0) * (ZyMax - y0) / (y1 - y0); y = ZyMax; } else if (outcodeOut & BOTTOM) { // point is below the clip rectangle x = x0 + (x1 - x0) * (ZyMin - y0) / (y1 - y0); y = ZyMin; } else if (outcodeOut & RIGHT) { // point is to the right of clip rectangle y = y0 + (y1 - y0) * (ZxMax - x0) / (x1 - x0); x = ZxMax; } else if (outcodeOut & LEFT) { // point is to the left of clip rectangle y = y0 + (y1 - y0) * (ZxMin - x0) / (x1 - x0); x = ZxMin; } // Now we move outside point to intersection point to clip // and get ready for next pass. if (outcodeOut == outcode0) { x0 = x; y0 = y; outcode0 = ComputeOutCode(x0, y0); } else { x1 = x; y1 = y; outcode1 = ComputeOutCode(x1, y1); } } } if (accept) { // draw line clipped to view window // SaveTurns(x0,y0,x1,y1,RayNumber); // all segment is inside a window ix0= (x0- ZxMin)/PixelWidth; iy0 = (ZyMax - y0)/PixelHeight; // inverse Y axis ix1= (x1- ZxMin)/PixelWidth; iy1= (ZyMax - y1)/PixelHeight; // inverse Y axis iDrawLine(A, ix0,iy0,ix1,iy1,RayNumber,color) ;} }
bool Graph::Clip(Point &p) const { uint8_t ca = ComputeOutCode(p); return ca == INSIDE; }
void oledc_drawLinePrimative(int x0, int y0, int x1, int y1, unsigned int color) { // check rotation, move pixel around if necessary switch (TFTROTATION) { case 1: gfx_swap(x0, y0); gfx_swap(x1, y1); x0 = TFTWIDTH - x0 - 1; x1 = TFTWIDTH - x1 - 1; //gfx_swap(x0, x1); break; case 2: gfx_swap(x0, x1); gfx_swap(y0, y1); x0 = TFTWIDTH - x0 - 1; y0 = TFTHEIGHT - y0 - 1; x1 = TFTWIDTH - x1 - 1; y1 = TFTHEIGHT - y1 - 1; break; case 3: gfx_swap(x0, y0); gfx_swap(x1, y1); y0 = TFTHEIGHT - y0 - 1; y1 = TFTHEIGHT - y1 - 1; //gfx_swap(y0, y1); break; } // Cohen–Sutherland clipping algorithm clips a line from // P0 = (x0, y0) to P1 = (x1, y1) against a rectangle with // diagonal from (xmin, ymin) to (xmax, ymax). // compute outcodes for P0, P1, and whatever point lies outside the clip rectangle OutCode outcode0 = ComputeOutCode(x0, y0); OutCode outcode1 = ComputeOutCode(x1, y1); char accept = 0; while (1) { if (!(outcode0 | outcode1)) { // Bitwise OR is 0. Trivially accept and get out of loop accept = 1; break; } else if (outcode0 & outcode1) { // Bitwise AND is not 0. Trivially reject and get out of loop break; } else { // failed both tests, so calculate the line segment to clip // from an outside point to an intersection with clip edge int x, y; // At least one endpoint is outside the clip rectangle; pick it. OutCode outcodeOut = outcode0 ? outcode0 : outcode1; // Now find the intersection point; // use formulas y = y0 + slope * (x - x0), x = x0 + (1 / slope) * (y - y0) if (outcodeOut & TOP) { // point is above the clip rectangle x = x0 + (x1 - x0) * (0 - y0) / (y1 - y0); y = 0; } else if (outcodeOut & BOTTOM) { // point is below the clip rectangle x = x0 + (x1 - x0) * (TFTHEIGHT - y0 - 1) / (y1 - y0); y = TFTHEIGHT - 1; } else if (outcodeOut & RIGHT) { // point is to the right of clip rectangle y = y0 + (y1 - y0) * (TFTWIDTH - x0 - 1) / (x1 - x0); x = TFTWIDTH - 1; } else if (outcodeOut & LEFT) { // point is to the left of clip rectangle y = y0 + (y1 - y0) * (0 - x0) / (x1 - x0); x = 0; } // Now we move outside point to intersection point to clip // and get ready for next pass. if (outcodeOut == outcode0) { x0 = x; y0 = y; outcode0 = ComputeOutCode(x0, y0); } else { x1 = x; y1 = y; outcode1 = ComputeOutCode(x1, y1); } } } if (accept) { oledc_writeCommand(SSD1331_CMD_DRAWLINE, 0); oledc_writeCommand(x0, 0); oledc_writeCommand(y0, 0); oledc_writeCommand(x1, 0); oledc_writeCommand(y1, 0); oledc_writeCommand((color >> 11) << 1, 0); oledc_writeCommand((color >> 5) & 0x3F, 0); oledc_writeCommand((color << 1) & 0x3F, 0); int _tMark = CNT + (CLKFREQ / 100000); while (_tMark > CNT); // Wait for system clock target } }
// Cohen–Sutherland clipping algorithm clips a line from // P0 = (x0, y0) to P1 = (x1, y1) against a rectangle with // diagonal from (xmin, ymin) to (xmax, ymax). bool clipLine(const pb_rect &bounds, int &x0, int &y0, int &x1, int &y1) { // compute outcodes for P0, P1, and whatever point lies outside the clip rectangle OutCode outcode0 = ComputeOutCode(bounds, x0, y0); OutCode outcode1 = ComputeOutCode(bounds, x1, y1); bool accept = false; double xmin = bounds.x; double xmax = bounds.x + bounds.width - 1; double ymin = bounds.y; double ymax = bounds.y + bounds.height - 1; while (true) { if (!(outcode0 | outcode1)) { // Bitwise OR is 0. Trivially accept and get out of loop accept = true; break; } else if (outcode0 & outcode1) { // Bitwise AND is not 0. Trivially reject and get out of loop break; } else { // failed both tests, so calculate the line segment to clip // from an outside point to an intersection with clip edge double x = 0; double y=0; // At least one endpoint is outside the clip rectangle; pick it. OutCode outcodeOut = outcode0 ? outcode0 : outcode1; // Now find the intersection point; // use formulas y = y0 + slope * (x - x0), x = x0 + (1 / slope) * (y - y0) if (outcodeOut & LN_TOP) { // point is above the clip rectangle x = x0 + (x1 - x0) * (ymax - y0) / (y1 - y0); y = ymax; } else if (outcodeOut & LN_BOTTOM) { // point is below the clip rectangle x = x0 + (x1 - x0) * (ymin - y0) / (y1 - y0); y = ymin; } else if (outcodeOut & LN_RIGHT) { // point is to the right of clip rectangle y = y0 + (y1 - y0) * (xmax - x0) / (x1 - x0); x = xmax; } else if (outcodeOut & LN_LEFT) { // point is to the left of clip rectangle y = y0 + (y1 - y0) * (xmin - x0) / (x1 - x0); x = xmin; } // Now we move outside point to intersection point to clip // and get ready for next pass. if (outcodeOut == outcode0) { x0 = x; y0 = y; outcode0 = ComputeOutCode(bounds, x0, y0); } else { x1 = x; y1 = y; outcode1 = ComputeOutCode(bounds, x1, y1); } } } return accept; }
void Segmenter:: compute_junctions(const Spot *spot, const Vertex &self, const Vertex &other, const Tracer *to) { const Coord klo = spot->klo; const Coord kup = spot->kup; const Vertex lo( X[klo.x], Y[klo.y]); const Vertex up( X[kup.x], Y[kup.y]); assert( INSIDE == ComputeOutCode(self,lo,up)); const OutCode other_code = ComputeOutCode(other, lo, up); if( other_code & LEFT) { assert( other.x < self.x); Segment &seg = Vert(klo.x); Junction *J = seg.append(); #if JUNCTION_TAG == 1 J->kind = Junction::Vert; J->tag = klo.x; #endif J->vertex.x = seg.value; J->alpha = ( J->vertex.x - self.x)/(other.x - self.x); J->vertex.y = self.y + (J->alpha)*(other.y - self.y); FinalizeJunction(J,spot->handle,to); } if( other_code & RIGHT) { assert( other.x > self.x); Segment &seg = Vert(kup.x); Junction *J = seg.append(); #if JUNCTION_TAG == 1 J->kind = Junction::Vert; J->tag = kup.x; #endif J->vertex.x = seg.value; J->alpha = ( J->vertex.x - self.x)/(other.x - self.x); J->vertex.y = self.y + (J->alpha)*(other.y - self.y); FinalizeJunction(J,spot->handle,to); } if( other_code & BOTTOM ) { assert( other.y < self.y ); Segment &seg = Horz(klo.y); Junction *J = seg.append(); #if JUNCTION_TAG == 1 J->kind = Junction::Horz; J->tag = klo.y; #endif J->vertex.y = seg.value; J->alpha = (J->vertex.y - self.y)/(other.y-self.y); J->vertex.x = self.x + (J->alpha)*(other.x-self.x); FinalizeJunction(J,spot->handle,to); } if( other_code & TOP ) { assert( other.y > self.y ); Segment &seg = Horz(kup.y); Junction *J = seg.append(); #if JUNCTION_TAG == 1 J->kind = Junction::Horz; J->tag = kup.y; #endif J->vertex.y = seg.value; J->alpha = (J->vertex.y - self.y)/(other.y-self.y); J->vertex.x = self.x + (J->alpha)*(other.x-self.x); FinalizeJunction(J,spot->handle,to); } }
// Cohen–Sutherland clipping algorithm clips a line from // P0 = (x0, y0) to P1 = (x1, y1) against a rectangle with // diagonal from (xmin, ymin) to (xmax, ymax). // Based on http://en.wikipedia.org/wiki/Cohen-Sutherland_algorithm // return false if line segment outside of bounding box bool GenGeomAlgs::ClipToBB(double& x0, double& y0, double& x1, double& y1, const double& xmin, const double& ymin, const double& xmax, const double& ymax) { // compute outcodes for P0, P1, // and whatever point lies outside the clip rectangle int outcode0 = ComputeOutCode(x0, y0, xmin, ymin, xmax, ymax); int outcode1 = ComputeOutCode(x1, y1, xmin, ymin, xmax, ymax); bool accept = false; while (true) { if (!(outcode0 | outcode1)) { // Bitwise OR is 0. Trivially accept and get out of loop accept = true; break; } else if (outcode0 & outcode1) { // Bitwise AND is not 0. Trivially reject and get out of loop break; } else { // failed both tests, so calculate the line segment to clip // from an outside point to an intersection with clip edge double x, y; // At least one endpoint is outside the clip rectangle; pick it. int outcodeOut = outcode0 ? outcode0 : outcode1; // Now find the intersection point; // use formulas y = y0 + slope * (x - x0), // x = x0 + (1 / slope) * (y - y0) if (outcodeOut & TOP) { // point is above the clip rectangle x = x0 + (x1 - x0) * (ymax - y0) / (y1 - y0); y = ymax; } else if (outcodeOut & BOTTOM) { // point is below the clip rectangle x = x0 + (x1 - x0) * (ymin - y0) / (y1 - y0); y = ymin; } else if (outcodeOut & RIGHT) { // point is to the right of clip rectangle y = y0 + (y1 - y0) * (xmax - x0) / (x1 - x0); x = xmax; } else if (outcodeOut & LEFT) { // point is to the left of clip rectangle y = y0 + (y1 - y0) * (xmin - x0) / (x1 - x0); x = xmin; } // Now we move outside point to intersection point to clip // and get ready for next pass. if (outcodeOut == outcode0) { x0 = x; y0 = y; outcode0 = ComputeOutCode(x0, y0, xmin, ymin, xmax, ymax); } else { x1 = x; y1 = y; outcode1 = ComputeOutCode(x1, y1, xmin, ymin, xmax, ymax); } } } return accept; }
static inline OutCode ComputeOutCode( const Vertex &r, const Vertex &lo, const Vertex &up) throw() { return ComputeOutCode(r.x, r.y, lo.x, up.x, lo.y, up.y); }
SDL_bool SDL_IntersectRectAndLine(const SDL_Rect * rect, int *X1, int *Y1, int *X2, int *Y2) { int x = 0; int y = 0; int x1, y1; int x2, y2; int rectx1; int recty1; int rectx2; int recty2; int outcode1, outcode2; if (!rect) { SDL_InvalidParamError("rect"); return SDL_FALSE; } if (!X1) { SDL_InvalidParamError("X1"); return SDL_FALSE; } if (!Y1) { SDL_InvalidParamError("Y1"); return SDL_FALSE; } if (!X2) { SDL_InvalidParamError("X2"); return SDL_FALSE; } if (!Y2) { SDL_InvalidParamError("Y2"); return SDL_FALSE; } /* Special case for empty rect */ if (SDL_RectEmpty(rect)) { return SDL_FALSE; } x1 = *X1; y1 = *Y1; x2 = *X2; y2 = *Y2; rectx1 = rect->x; recty1 = rect->y; rectx2 = rect->x + rect->w - 1; recty2 = rect->y + rect->h - 1; /* Check to see if entire line is inside rect */ if (x1 >= rectx1 && x1 <= rectx2 && x2 >= rectx1 && x2 <= rectx2 && y1 >= recty1 && y1 <= recty2 && y2 >= recty1 && y2 <= recty2) { return SDL_TRUE; } /* Check to see if entire line is to one side of rect */ if ((x1 < rectx1 && x2 < rectx1) || (x1 > rectx2 && x2 > rectx2) || (y1 < recty1 && y2 < recty1) || (y1 > recty2 && y2 > recty2)) { return SDL_FALSE; } if (y1 == y2) { /* Horizontal line, easy to clip */ if (x1 < rectx1) { *X1 = rectx1; } else if (x1 > rectx2) { *X1 = rectx2; } if (x2 < rectx1) { *X2 = rectx1; } else if (x2 > rectx2) { *X2 = rectx2; } return SDL_TRUE; } if (x1 == x2) { /* Vertical line, easy to clip */ if (y1 < recty1) { *Y1 = recty1; } else if (y1 > recty2) { *Y1 = recty2; } if (y2 < recty1) { *Y2 = recty1; } else if (y2 > recty2) { *Y2 = recty2; } return SDL_TRUE; } /* More complicated Cohen-Sutherland algorithm */ outcode1 = ComputeOutCode(rect, x1, y1); outcode2 = ComputeOutCode(rect, x2, y2); while (outcode1 || outcode2) { if (outcode1 & outcode2) { return SDL_FALSE; } if (outcode1) { if (outcode1 & CODE_TOP) { y = recty1; x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1); } else if (outcode1 & CODE_BOTTOM) { y = recty2; x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1); } else if (outcode1 & CODE_LEFT) { x = rectx1; y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1); } else if (outcode1 & CODE_RIGHT) { x = rectx2; y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1); } x1 = x; y1 = y; outcode1 = ComputeOutCode(rect, x, y); } else { if (outcode2 & CODE_TOP) { y = recty1; x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1); } else if (outcode2 & CODE_BOTTOM) { y = recty2; x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1); } else if (outcode2 & CODE_LEFT) { x = rectx1; y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1); } else if (outcode2 & CODE_RIGHT) { x = rectx2; y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1); } x2 = x; y2 = y; outcode2 = ComputeOutCode(rect, x, y); } } *X1 = x1; *Y1 = y1; *X2 = x2; *Y2 = y2; return SDL_TRUE; }
bool CohenSutherlandLineClipAndDraw(float &x0, float &y0, float &z0, float &x1, float &y1, float &z1) { // compute outcodes for P0, P1, and whatever point lies outside the clip rectangle OutCode outcode0 = ComputeOutCode(x0, y0,z0); OutCode outcode1 = ComputeOutCode(x1, y1,z1); while (true) { //std::cout<<x0<<" "<<y0<<" "<<z0<<" "<<std::endl; if (!(outcode0 | outcode1)) { // Bitwise OR is 0. Trivially accept and get out of loop // std::cout<<x0<<" "<<y0<<" "<<z0<<" "<<std::endl; // std::cout<<x1<<" "<<y1<<" "<<z1<<" "<<std::endl<<std::endl; return true; } else if (outcode0 & outcode1) { // Bitwise AND is not 0. Trivially reject and get out of loop return false; } else { // failed both tests, so calculate the line segment to clip // from an outside point to an intersection with clip edge float x, y, z; // At least one endpoint is outside the clip rectangle; pick it. OutCode outcodeOut = outcode0 ? outcode0 : outcode1; // Now find the intersection point; if (outcodeOut & TOP) { // point is above the clip rectangle x = x0 + (x1 - x0) * (YMAX - y0) / (y1 - y0); y = YMAX; z = z0 + (z1 - z0) * (YMAX - y0) / (y1 - y0); } else if (outcodeOut & BOTTOM) { // point is below the clip rectangle x = x0 + (x1 - x0) * (YMIN - y0) / (y1 - y0); y = YMIN; z = z0 + (z1 - z0) * (YMIN - y0) / (y1 - y0); } else if (outcodeOut & RIGHT) { // point is to the right of clip rectangle y = y0 + (y1 - y0) * (XMAX - x0) / (x1 - x0); x = XMAX; z = z0 + (z1 - z0) * (XMAX - x0) / (x1 - x0); } else if (outcodeOut & LEFT) { // point is to the left of clip rectangle y = y0 + (y1 - y0) * (XMIN - x0) / (x1 - x0); x = XMIN; z = z0 + (z1 - z0) * (XMIN - x0) / (x1 - x0); } else if (outcodeOut & BEHIND) { // point is to the left of clip rectangle y = y0 + (y1 - y0) * (ZMIN - z0) / (z1 - z0); x = x0 + (x1 - x0) * (ZMIN - z0) / (z1 - z0); z = ZMIN; } else if (outcodeOut & FRONT) { // point is to the left of clip rectangle y = y0 + (y1 - y0) * (ZMAX - z0) / (z1 - z0); x = x0 + (x1 - x0) * (ZMAX - z0) / (z1 - z0); z = ZMAX; } // Now we move outside point to intersection point to clip // and get ready for next pass. if (outcodeOut == outcode0) { x0 = x; y0 = y; z0 = z; outcode0 = ComputeOutCode(x0, y0, z0); } else { x1 = x; y1 = y; z1 = z; outcode1 = ComputeOutCode(x1, y1,z1); } } } }
void CohenSutherland(double x0, double y0, double x1, double y1) { outcode outcode0, outcode1, outcodeOut; bool accept=false, done=false; outcode0=ComputeOutCode(x0,y0); outcode1=ComputeOutCode(x1,y1); do { if(!(outcode0|outcode1)) { accept=true; done=true; } else if(outcode0&outcode1) done=true; else { double x, y; outcodeOut=outcode0?outcode0:outcode1; if(outcodeOut&TOP) { x=x0+(x1-x0)*(ymax-y0)/(y1-y0); y=ymax; } else if(outcodeOut&BOTTOM) { x=x0+(x1-x0)*(ymin-y0)/(y1-y0); y=ymin; } else if(outcodeOut&RIGHT) { y=y0+(y1-y0)*(xmax-x0)/(x1-x0); x=xmax; } else { y=y0+(y1-y0)*(xmin-x0)/(x1-x0); x=xmin; } if(outcodeOut==outcode0) { x0=x; y0=y; outcode0=ComputeOutCode(x0,y0); } else { x1=x; y1=y; outcode1=ComputeOutCode(x1,y1); } } }while(!done); if(accept) { double sx=(xvmax-xvmin)/(xmax-xmin); double sy=(yvmax-yvmin)/(ymax-ymin); double vx0=xvmin+(x0-xmin)*sx; double vy0=yvmin+(y0-ymin)*sy; double vx1=xvmin+(x1-xmin)*sx; double vy1=yvmin+(y1-ymin)*sy; glColor3f(1.0,0.0,0.0); glBegin(GL_LINE_LOOP); glVertex2f(xvmin, yvmin); glVertex2f(xvmax, yvmin); glVertex2f(xvmax, yvmax); glVertex2f(xvmin, yvmax); glEnd(); glColor3f(0.0,0.0,1.0); glBegin(GL_LINES); glVertex2d(vx0,vy0); glVertex2d(vx1,vy1); glEnd(); } }
/** Cohen-Sutherland clipping algorithm clips a line from P0 = (x0, y0) to P1 = (x1, y1) against a rectangle with diagonal from (xmin, ymin) to (xmax, ymax). **/ void cohen_sutherland_clip (int * x0, int * y0,int * x1, int * y1, int xmin, int ymin, int xmax, int ymax) { //Outcodes for P0, P1, and whatever point lies outside the clip rectangle outcode outcode0, outcode1, outcodeOut; bool accept = false, done = false; int tx0 = *x0, ty0 = *y0, tx1 = *x1, ty1 = *y1; //compute outcodes outcode0 = ComputeOutCode (tx0, ty0, xmin, ymin, xmax, ymax); outcode1 = ComputeOutCode (tx1, ty1, xmin, ymin, xmax, ymax); do{ if (!(outcode0 | outcode1)) //logical or is 0. Trivially accept and get out of loop { accept = true; done = true; } else if (outcode0 & outcode1) //logical and is not 0. Trivially reject and get out of loop done = true; else { //failed both tests, so calculate the line segment to clip //from an outside point to an intersection with clip edge double x, y; //At least one endpoint is outside the clip rectangle; pick it. outcodeOut = outcode0? outcode0: outcode1; //Now find the intersection point; //use formulas y = y0 + slope * (x - x0), x = x0 + (1/slope)* (y - y0) if (outcodeOut & TOP) //point is above the clip rectangle { x = tx0 + (tx1 - tx0) * (ymax - ty0)/(ty1 - ty0); y = ymax; } else if (outcodeOut & BOTTOM) //point is below the clip rectangle { x = tx0 + (tx1 - tx0) * (ymin - ty0)/(ty1 - ty0); y = ymin; } else if (outcodeOut & RIGHT) //point is to the right of clip rectangle { y = ty0 + (ty1 - ty0) * (xmax - tx0)/(tx1 - tx0); x = xmax; } else //point is to the left of clip rectangle { y = ty0 + (ty1 - ty0) * (xmin - tx0)/(tx1 - tx0); x = xmin; } //Now we move outside point to intersection point to clip //and get ready for next pass. if (outcodeOut == outcode0) { tx0 = x; ty0 = y; outcode0 = ComputeOutCode (tx0, ty0, xmin, ymin, xmax, ymax); } else { tx1 = x; ty1 = y; outcode1 = ComputeOutCode (tx1, ty1, xmin, ymin, xmax, ymax); } } }while (!done); if (accept) { *x0 = tx0; *x1 = tx1; *y0 = ty0; *y1 = ty1; } }