2.1 画直线算法:
//DDA算法 void drawAlgorithmDialog::drawLineDDA( int x0,int y0,int x1,int y1, QPainter* ppainter ) { //QPainter painter(this); int dx, dy, n, k; float xinc, yinc, x, y; dx = x1 - x0; dy = y1 - y0; if( qAbs(dx) > qAbs(dy) ) { n = abs(dx); } else { n = abs(dy); } xinc = (float)dx / n; yinc = (float)dy / n; x = (float)x0; y = (float)y0; for( k = 1; k <= n; k++ ) { ppainter->drawPoint( int(x + 0.5), int(y+0.5) ); x+=xinc; y+=yinc; } return; } //中点画线 void drawAlgorithmDialog::drawLineMidPoint(int x0, int y0, int x1, int y1, QPainter *ppainter) { int a, b, d1, d2, d, x, y; a = y0-y1; b = x1 - x0; d = 2 * a + b; d1 = 2 * a; d2 = 2 * ( a + b ); x=x0; y=y0; ppainter->drawPoint( x, y ); while( x < x1 ) { if( d < 0 ) { x++, y++, d+=d2; } else { x++, d += d1; } ppainter->drawPoint( x, y ); //drawpixel (x, y, color); } return; } // BresenHam画线 void drawAlgorithmDialog::drawLineBresenHam(int x1, int y1, int x2, int y2, QPainter *ppainter ) { int dx = x2 - x1;//△x int dy = y2 - y1;//△y int p = (2*dy) - dx ; //P = 2△y - △x int dobDy = 2* dy ; // 2 △y int dobD = 2*(dy - dx) ; // 2(△y - △x) int PointX,PointY; //设置两个临时用来显示位置的变量 if( x1 > x2) { //判断线段的方向 PointX = x2;//起始坐标X PointY = y2;////起始坐标Y x2 = x1; } else { PointX = x1;//起始坐标X PointY = y1;//起始坐标Y } //达因第一个起始点 //cout<<"Point: X:"<<PointX<<" Y:"<<PointY<<endl; ppainter->drawPoint( PointX, PointY ); while( PointX < x2) { PointX++; if(p < 0) { p += dobDy; } else { PointY++; p += dobD; } //cout<<"Point: X:"<<PointX<<" Y:"<<PointY<<endl; ppainter->drawPoint( PointX, PointY ); } return; }
// 中点画圆 void drawAlgorithmDialog::MidPointCircle( int x1, int y1, int R, QPainter* ppainter ) { int x = 0; int y = R; double d = 1.25 - R; ppainter->drawPoint( x1,y1 ); //绘制圆心 while( x < y )\ { ppainter->drawPoint( x+x1,y+y1 ); ppainter->drawPoint( y+x1,x+y1 ); ppainter->drawPoint( -x+x1,y+y1 ); ppainter->drawPoint( -y+x1,x+y1 ); ppainter->drawPoint( -x+x1,-y+y1 ); ppainter->drawPoint( -y+x1,-x+y1 ); ppainter->drawPoint( x+x1,-y+y1 ); ppainter->drawPoint( y+x1,-x+y1 ); if( d < 0 ) { d += 2 * x + 3; x++; } else { d += 2 * ( x - y ) + 5; x++; y--; } //ppainter->drawPoint( x, y ); } return; } // Bresenham画圆 void drawAlgorithmDialog::BresenhamDrawCircle(int x1, int y1, int R, QPainter *ppainter) { int x = 0; int y = R; int p = 3 - 2 * R; ppainter->drawPoint( x1,y1 ); //绘制圆心 for( ; x <= y; x++ ) { ppainter->drawPoint( x+x1,y+y1 ); ppainter->drawPoint( y+x1,x+y1 ); ppainter->drawPoint( -x+x1,y+y1 ); ppainter->drawPoint( -y+x1,x+y1 ); ppainter->drawPoint( -x+x1,-y+y1 ); ppainter->drawPoint( -y+x1,-x+y1 ); ppainter->drawPoint( x+x1,-y+y1 ); ppainter->drawPoint( y+x1,-x+y1 ); if( p >= 0 ) { p += 4 * ( x - y ) + 10; y--; } else { p += 4 * x + 6; } } return; } // 中点画椭圆 void drawAlgorithmDialog::MidPointEllise( int xcenter, int ycenter, int a, int b, QPainter *ppainter) //中点画椭圆法 { int x = 0; int y = b; double d1 = 0; double d2 = 0; d1 = b * b + a * a * ( -b + 0.25 ); ppainter->drawPoint( xcenter + x,ycenter + y); ppainter->drawPoint( xcenter - x,ycenter + y); ppainter->drawPoint( xcenter + x,ycenter - y); ppainter->drawPoint( xcenter - x,ycenter - y); while( b*b*(x+1) < a*a*(y-0.5) ) { if( d1 < 0 ) { d1 += b*b*(2*x+3); x++; } else { d1 += ( b*b*(2*x+3) + a*a*(-2*y+2 ) ); x++; y--; } ppainter->drawPoint( xcenter + x,ycenter + y); ppainter->drawPoint( xcenter - x,ycenter + y); ppainter->drawPoint( xcenter + x,ycenter - y); ppainter->drawPoint( xcenter - x,ycenter - y); } d2 = b*b*(x+0.5)*(x+0.5) + a*a*(y-1)*(y-1)-a*a*b*b; while( y > 0 ) { if( d2 < 0 ) { d2 += b*b*(2*x+2) + a*a*(-2*y+3); x++; y--; } else { d2 += a*a*(-2*y+3); y--; } ppainter->drawPoint( xcenter + x,ycenter + y); ppainter->drawPoint( xcenter - x,ycenter + y); ppainter->drawPoint( xcenter + x,ycenter - y); ppainter->drawPoint( xcenter - x,ycenter - y); } return; }
// 二维直线裁剪-区域编码法裁剪算法: void LineTrimDialog::makecode(double x, double y, int &c) { c = 0; if( x < xl ) { c = 1; } else if( x > xr ) { c = 2; } if( y < yb ) { c += 4; } else if( y > yt ) { c += 8; } return; } //xl 窗口左边x坐标 //xr 窗口右边x坐标 //yb 窗口底部y坐标 //yt 窗口顶部y坐标 //由于坐标原点默认在左上角,故,xr, xl, yt, tb应该为: // xl = vertexPoint[0].x(); // xr = vertexPoint[1].x(); // yb = vertexPoint[0].y(); // yt = vertexPoint[1].y(); // vertexPoint[0]为裁剪窗口左上角坐标 // vertexPoint[1]为裁剪窗口右下角坐标 // 区域编码法裁剪 void LineTrimDialog::Cohen_Sutherland( double x0, double y0, double x2, double y2, QPainter *pPainter, int i ) { // pPainter->drawLine( 100, 100, 300, 300 ); // QMessageBox::warning(this,tr("Warning"),"cohen",QMessageBox::Yes); // update(); int c = 0; int c1 = 0; int c2 = 0; double x = 0; double y = 0; makecode( x0, y0, c1 ); makecode( x2, y2, c2 ); while( c1 != 0 || c2 != 0 ) { if( c1&c2 == 1 ) { return; } c = c1; if( c == 0 ) { c = c2; } if( c&1 == 1 ) { y = y0 + ( y2 - y0 ) * ( xl - x0 ) / ( x2 - x0 ); x = xl; } else if( c&2 ) { y = y0 + ( y2 - y0 ) * ( xr - x0 ) / ( x2 - x0 ); x = xr; } else if( c&4 ) { x = x0 + ( x2 - x0 ) * ( yb - y0 ) / ( y2 - y0 ); y = yb; } else if( c&8 ) { x = x0 + ( x2 - x0 ) * ( yt - y0 ) / ( y2 - y0 ); y = yt; } if( c == c1 ) { x0 = x; y0 = y; makecode( x, y, c1 ); } else { x2 = x; y2 = y; makecode( x, y, c2 ); } } /* if( x0 - (int)(x0) > 0.5 ) //防止double转int丢失较大精度 { x0++; } if( y0 - (int)(y0) > 0.5 ) { y0++; } if( x2 - (int)(x2) > 0.5 ) { x2++; } if( y2 - (int)(y2) > 0.5 ) { y2++; }*/ // QMessageBox::warning(this,tr("Warning"),"t344st",QMessageBox::Yes); // LinePointArray[i] = QPoint( x0, y0 ); //会把x0,y0,x2,y2转换为int,会丢失精度 // LinePointArray[i+1] = QPoint( x2, y2 ); //在这里直接绘制,可以避免由double转换为int时丢失的精度 pPainter->drawLine( x0, y0, x2, y2 ); //向上偏移一下,方便看到裁剪后的直线 update(); return; } // 二维直线裁剪-梁友栋-Barsky算法: bool LineTrimDialog::cansee(double q, double d, double &t0, double &t1) { double r; if( q < 0 ) { r = d / q; if( r > t1 ) { return false; } else if( r > t0 ) { t0 = r; } } else if( q > 0 ) { r = d / q; if( r < t0 ) { return false; } else if( r < t1 ) { t1 = r; } else if( d < 0 ) { return false; } } return true; } void LineTrimDialog::L_Barsky(double x0, double y0, double x2, double y2, QPainter *pPainter, int i ) { //QMessageBox::warning(this,tr("Warning"),"barsky",QMessageBox::Yes); double t0, t1, deltax, deltay; t0 = 0.0; t1 = 1.0; deltax = x2 - x0; if( !cansee( -deltax, x0 - xl, t0, t1 ) ) { return; } if( !cansee( deltax, xr - x0, t0, t1 ) ) { return; } deltay = y2 - y0; if( !cansee( -deltay, y0 - yb, t0, t1 ) ) { return; } if( !cansee( deltay, yt - y0, t0, t1 ) ) { return; } x2 = x0 + t1 * deltax; y2 = y0 + t1 * deltay; x0 = x0 + t0 * deltax; y0 = y0 + t0 * deltay; // LinePointArray1.push_back( DPoint( x0, y0 ) ); // LinePointArray1.push_back( DPoint( x2, y2 ) ); pPainter->drawLine( x0, y0, x2, y2 ); update(); /* if( x0 - (int)(x0) > 0.5 ) //防止double转int丢失较大精度 { x0++; } if( y0 - (int)(y0) > 0.5 ) { y0++; } if( x2 - (int)(x2) > 0.5 ) { x2++; } if( y2 - (int)(y2) > 0.5 ) { y2++; }*/ //pPainter->drawLine( x0, y0, x2, y2 ); //LinePointArray[i] = QPoint( x0, y0 ); //LinePointArray[i+1] = QPoint( x2, y2 ); return; }
2.4 种子扫描填充算法
// 种子扫描填充算法 (x,y)为种子点 void CZhztchView::boundaryfill4(int x, int y, int boundarycolor, int newcolor) { /* int color; CClientDC dc(this); //获取客户区设备描述表 color=dc.GetPixel(x,y); if(color!=newcolor&&color!=boundarycolor) { dc.SetPixel(x,y,newcolor); boundaryfill4(x,y+1,boundarycolor,newcolor); boundaryfill4(x,y-1,boundarycolor,newcolor); boundaryfill4(x-1,y,boundarycolor,newcolor); boundaryfill4(x+1,y,boundarycolor,newcolor); } */ int color; //color=dc.GetPixel(x,y); CClientDC dc(this); //获取客户区设备描述表 using namespace std; int x0 = 0; int xl = 0; int xr = 0; int y0 = 0; int xid = 0; bool flag = false; int count = 0; stack<Point> s; Point p; s.push( Point( x, y ) ); while( !s.empty() ) //判断栈是否为空 { p = s.top(); s.pop(); x = p.x; y = p.y; dc.SetPixel(x,y,newcolor); //painter->drawPoint( x, y ); // SetPixel( hdc, x, y, 16711935 ); // repaint(); x0 = x + 1; while( dc.GetPixel( x0, y ) != boundarycolor && dc.GetPixel( x0, y ) != newcolor )// 填充种子右方像素 { //painter->drawPoint( x0, y ); dc.SetPixel(x,y,newcolor); //SetPixel( hdc, x, y, 16711935 ); // repaint(); x0++; //repaint(); } xr = x0 - 1; //最右边像素位置 x0 = x - 1; while( dc.GetPixel( x0, y ) != boundarycolor && dc.GetPixel( x0, y ) != newcolor ) //填充种子左边像素 { //painter->drawPoint( x0, y ); dc.SetPixel(x,y,newcolor); //SetPixel( hdc, x, y, 16711935 ); // repaint(); x0--; } xl = x0 + 1; //最左边像素位置 y0 = y; for( int i = 1; i >= -1; i -= 2 ) { x0 = xr; y = y0 + i; while( x0 >= xl ) { flag = false; while( ( dc.GetPixel( x0, y ) != boundarycolor ) && ( dc.GetPixel( x0, y ) != newcolor ) && ( x0 >= xl ) ) { if( !flag ) { flag = true; xid = x0; } x0--; } if(flag) { s.push( Point( xid, y ) ); flag = false; } while( ( dc.GetPixel( x0, y ) == boundarycolor ) || ( dc.GetPixel( x0, y ) == newcolor ) && ( x0 >= xl ) ) { x0--; } } } } }