const
  CKWW=80;
  SecWW=30;
  
var
  vs:Real;  
  a:Word;
begin
    a:=10; //a=0~59
    vs :=a/60.0*2*Pi;
    with PaintBox1 do
     begin
      Brush.Style:=bsClear;
      Pen.Width:=2;  //2
      Pen.Color:=clRed;
      MoveTo(Round(CKWW div 2),Round(CKWW div 2));
      LineTo(Round(CKWW div 2)+Round(SecWW*Sin(vs)),Round(CKWW div 2)-
         Round(SecWW*Cos(vs)));
     end;
end;问题:如果直线旋转到垂直或水平位置时,直线形状正常,其他位置则出现波浪或锯齿变形,如何解决?

解决方案 »

  1.   

    draw an anti-aliased line? {
     This code draws an anti-aliased line on a bitmap
     This means that the line is not jagged like the
     lines drawn using the LineTo() function
    }uses
      Graphics, Windows;type
      TRGBTripleArray = array[0..1000] of TRGBTriple;
      PRGBTripleArray = ^TRGBTripleArray;// anti-aliased line
    procedure WuLine(ABitmap : TBitmap ; Point1, Point2 : TPoint ; AColor : TColor);
    var
      deltax, deltay, loop, start, finish : integer;
      dx, dy, dydx : single; // fractional parts
      LR, LG, LB : byte;
      x1, x2, y1, y2 : integer;
    begin
      x1 := Point1.X; y1 := Point1.Y;
      x2 := Point2.X; y2 := Point2.Y;
      deltax := abs(x2 - x1); // Calculate deltax and deltay for initialisation
      deltay := abs(y2 - y1);
      if (deltax = 0) or (deltay = 0) then begin // straight lines
        ABitmap.Canvas.Pen.Color := AColor;
        ABitmap.Canvas.MoveTo(x1, y1);
        ABitmap.Canvas.LineTo(x2, y2);
        exit;
      end;
      LR := (AColor and $000000FF);
      LG := (AColor and $0000FF00) shr 8;
      LB := (AColor and $00FF0000) shr 16;
      if deltax > deltay then
      begin // horizontal or vertical
        if y2 > y1 then // determine rise and run
          dydx := -(deltay / deltax)
        else
          dydx := deltay / deltax;
        if x2 < x1 then
        begin
          start := x2; // right to left
          finish := x1;
          dy := y2;
        end else
        begin
          start := x1; // left to right
          finish := x2;
          dy := y1;
          dydx := -dydx; // inverse slope
        end;
        for loop := start to finish do
        begin
          AlphaBlendPixel(ABitmap, loop, trunc(dy), LR, LG, LB, 1 - frac(dy));
          AlphaBlendPixel(ABitmap, loop, trunc(dy) + 1, LR, LG, LB, frac(dy));
          dy := dy + dydx; // next point
        end;
      end else
      begin
        if x2 > x1 then // determine rise and run
          dydx := -(deltax / deltay)
        else
          dydx := deltax / deltay;
        if y2 < y1 then
        begin
          start := y2; // right to left
          finish := y1;
          dx := x2;
        end else
        begin
          start := y1; // left to right
          finish := y2;
          dx := x1;
          dydx := -dydx; // inverse slope
        end;
        for loop := start to finish do
        begin
          AlphaBlendPixel(ABitmap, trunc(dx), loop, LR, LG, LB, 1 - frac(dx));
          AlphaBlendPixel(ABitmap, trunc(dx) + 1, loop, LR, LG, LB, frac(dx));
          dx := dx + dydx; // next point
        end;
      end;
    end;// blend a pixel with the current colour
    procedure AlphaBlendPixel(ABitmap : TBitmap ; X, Y : integer ; R, G, B : byte ; ARatio : Real);
    Var
      LBack, LNew : TRGBTriple;
      LMinusRatio : Real;
      LScan : PRGBTripleArray;
    begin
      if (X < 0) or (X > ABitmap.Width - 1) or (Y < 0) or (Y > ABitmap.Height - 1) then
        Exit; // clipping
      LScan := ABitmap.Scanline[Y];
      LMinusRatio := 1 - ARatio;
      LBack := LScan[X];
      LNew.rgbtBlue := round(B*ARatio + LBack.rgbtBlue*LMinusRatio);
      LNew.rgbtGreen := round(G*ARatio + LBack.rgbtGreen*LMinusRatio);
      LNew.rgbtRed := round(R*ARatio + LBack.rgbtRed*LMinusRatio);
      LScan[X] := LNew;
    end;
      

  2.   

    To: aiirii我是这样调用你给出的代码的,但在界面上却看不到绘制出的图形来,为什么?procedure TForm1.Button1Click(Sender: TObject);
    var
        Tmp_Bitmap: TBitmap;
        Pnt1, Pnt2: TPoint;
    begin
        Tmp_Bitmap := TBitmap.Create;    Pnt1.X := 0;
        Pnt1.Y := 0;
        Pnt2.X := Self.Width;
        Pnt2.Y := Self.Height;    WuLine(Tmp_Bitmap, Pnt1, Pnt2, clBlack);
        Self.Canvas.Draw(0, 0, Tmp_Bitmap);
        Tmp_Bitmap.Free;end;能帮助看一下吗?
      

  3.   

    我也同bookbull一样,没有看见绘出的直线。
      

  4.   

    算法找到了,矢量线条——
        
    http://www.mt86.com/graphic/ui/200506/graphic_20050611140718.shtml
      

  5.   

    (*   Description: Draw an anti-aliased line using the Wu algorithm.
       Uses fixed point arithmetic.   Original code by:  Peter Bone
                          http://www.geocities.com/peter_bone_uk/engine3d.html   Adapted to use Scanline pointers.*)type
      TRGB = record
        r : byte;
        g : byte;
        b : byte;
      end;
      TRGBArray = array[0..32767] of TRGB;
      pRGBArray = ^TRGBArray;procedure WuLine(Bmp: TBitmap; x1, y1, x2, y2: integer ; R, G, B : byte);
    var
      deltax, deltay, X, Y, start, finish : integer;
      LM, LR : integer;
      dxi, dyi, dydxi : integer;  W, H : integer;
      ScanLines : pRGBArray;
      ScanLine0,
      ScanlinePtr : PByte;
      ScanlineIncrement : integer;
    begin
      Bmp.PixelFormat := pf24bit;
      W := Bmp.Width;
      H := Bmp.Height;  deltax := abs(x2 - x1); // Calculate deltax and deltay for initialisation
      deltay := abs(y2 - y1);  if (deltax = 0) or (deltay = 0) then begin
        Bmp.Canvas.Pen.Color := (B shl 16) + (G shl 8) + R;
        Bmp.Canvas.MoveTo(x1, y1);
        Bmp.Canvas.LineTo(x2, y2);    exit;
      end;  //use pointers instead of scanline (faster than accessing scanline)
      ScanLine0   := Bmp.Scanline[0];
      ScanlinePtr := Bmp.Scanline[0];
      ScanlineIncrement := integer(Bmp.Scanline[1]) - integer(ScanlinePtr);  if deltax > deltay then begin // horizontal or vertical
        if y2 > y1 then // determine rise and run
          dydxi := -deltay shl 16 div deltax
        else
          dydxi := deltay shl 16 div deltax;    if x2 < x1 then begin
          start := x2; // right to left
          finish := x1;
          dyi := y2 shl 16;
        end else begin
          start := x1; // left to right
          finish := x2;
          dyi := y1 shl 16;
          dydxi := -dydxi; // inverse slope
        end;    if finish >= W then
          finish := W - 1;    for X := start to finish do begin
          Y := dyi shr 16;
          if (X < 0) or (Y < 0) or (Y > H-2) then begin
            Inc(dyi, dydxi);
            Continue;
          end;      LM := dyi - Y shl 16; // fractional part of dyi - in fixed-point
          LR := 65536 - LM;      ScanlinePtr := ScanLine0;
          Inc(ScanlinePtr, ScanlineIncrement *Y);
          ScanLines := pRGBArray(ScanLinePtr);      Scanlines[X].B := (B*LR + Scanlines[X].B*LM) shr 16;
          Scanlines[X].G := (G*LR + Scanlines[X].G*LM) shr 16;
          Scanlines[X].R := (R*LR + Scanlines[X].R*LM) shr 16;      Inc(ScanlinePtr, ScanlineIncrement);
          ScanLines := pRGBArray(ScanLinePtr);      Scanlines[X].B := (B*LM + Scanlines[X].B*LR) shr 16;
          Scanlines[X].G := (G*LM + Scanlines[X].G*LR) shr 16;
          Scanlines[X].R := (R*LM + Scanlines[X].R*LR) shr 16;      Inc(dyi, dydxi); // next point
        end;
      end else begin
        if x2 > x1 then // determine rise and run
          dydxi := -deltax shl 16 div deltay
        else
          dydxi := deltax shl 16 div deltay;    if y2 < y1 then begin
          start := y2; // right to left
          finish := y1;
          dxi := x2 shl 16;
        end else begin
          start := y1; // left to right
          finish := y2;
          dxi := x1 shl 16;
          dydxi := -dydxi; // inverse slope
        end;    if finish >= H then
          finish := H - 1;    for Y := start to finish do begin
          X := dxi shr 16;      if (Y < 0) or (X < 0) or (X > W-2) then begin
            Inc(dxi, dydxi);
            Continue;
          end;      LM := dxi - X shl 16;
          LR := 65536 - LM;      ScanlinePtr := ScanLine0;
          Inc(ScanlinePtr, ScanlineIncrement *Y);
          ScanLines := pRGBArray(ScanLinePtr);      Scanlines[X].B := (B*LR + Scanlines[X].B*LM) shr 16;
          Scanlines[X].G := (G*LR + Scanlines[X].G*LM) shr 16;
          Scanlines[X].R := (R*LR + Scanlines[X].R*LM) shr 16;      Inc(X);      Scanlines[X].B := (B*LM + Scanlines[X].B*LR) shr 16;
          Scanlines[X].G := (G*LM + Scanlines[X].G*LR) shr 16;
          Scanlines[X].R := (R*LM + Scanlines[X].R*LR) shr 16;      Inc(dxi, dydxi); // next point
        end;
      end;
    end;
      

  6.   

    (*
        Just to confuse things, here's another version that is slightly slower
        but draws better lines. This gives the same result as drawing the same
        line twice (one on top of the other) which reduces the effect of
        alternating light and dark patches.
    *)
    procedure WuLine2(Bmp: TBitmap; x1, y1, x2, y2 : integer ; R, G, B : byte);
    var
      deltax, deltay, X, Y, start, finish : integer;
      LM, LR, LMR, LMM, LRR : integer;
      dxi, dyi, dydxi : integer;  ScanLines : pRGBArray;
      ScanLine0,
      ScanlinePtr : PByte;
      ScanlineIncrement : integer;
    begin
      Bmp.PixelFormat := pf24bit;  deltax := abs(x2 - x1); // Calculate deltax and deltay for initialisation
      deltay := abs(y2 - y1);
      if (deltax = 0) or (deltay = 0) then begin
        Bmp.Canvas.Pen.Color := (B shl 16) + (G shl 8) + R;
        Bmp.Canvas.MoveTo(x1, y1);
        Bmp.Canvas.LineTo(x2, y2);
        exit;
      end;  //use pointers instead of scanline (faster than accessing scanline)
      ScanLine0   := Bmp.Scanline[0];
      ScanlinePtr := Bmp.Scanline[0];
      ScanlineIncrement := integer(Bmp.Scanline[1]) - integer(ScanlinePtr);  if deltax > deltay then begin // horizontal or vertical
        if y2 > y1 then // determine rise and run
          dydxi := -deltay shl 11 div deltax
        else
          dydxi := deltay shl 11 div deltax;
        if x2 < x1 then begin
          start := x2; // right to left
          finish := x1;
          dyi := y2 shl 11;
        end else begin
          start := x1; // left to right
          finish := x2;
          dyi := y1 shl 11;
          dydxi := -dydxi; // inverse slope
        end;    if finish >= Bmp.Width then finish := Bmp.Width - 1;    for X := start to finish do begin
          Y := dyi shr 11;
          if (X < 0) or (Y < 0) or (Y > Bmp.Height-2) then begin
            Inc(dyi, dydxi);
            Continue;
          end;
          LM := dyi - Y shl 11; // fractional part of dyi - in fixed-point
          LR := 2048 - LM;
          LMR := LM * LR;
          LMM := LM * LM;
          LRR := LR * LR;      ScanlinePtr := ScanLine0;
          Inc(ScanlinePtr, ScanlineIncrement *Y);
          ScanLines := pRGBArray(ScanLinePtr);      Scanlines[X].B := B*LR shr 11 + (B*LMR + Scanlines[X].B*LMM) shr 22;
          Scanlines[X].G := G*LR shr 11 + (G*LMR + Scanlines[X].G*LMM) shr 22;
          Scanlines[X].R := R*LR shr 11 + (R*LMR + Scanlines[X].R*LMM) shr 22;      Inc(ScanlinePtr, ScanlineIncrement);
          ScanLines := pRGBArray(ScanLinePtr);      Scanlines[X].B := B*LM shr 11 + (B*LMR + Scanlines[X].B*LRR) shr 22;
          Scanlines[X].G := G*LM shr 11 + (G*LMR + Scanlines[X].G*LRR) shr 22;
          Scanlines[X].R := R*LM shr 11 + (R*LMR + Scanlines[X].R*LRR) shr 22;
          Inc(dyi, dydxi); // next point
        end;
      end else begin
        if x2 > x1 then // determine rise and run
          dydxi := -deltax shl 11 div deltay
        else
          dydxi := deltax shl 11 div deltay;
        if y2 < y1 then begin
          start := y2; // right to left
          finish := y1;
          dxi := x2 shl 11;
        end else begin
          start := y1; // left to right
          finish := y2;
          dxi := x1 shl 11;
          dydxi := -dydxi; // inverse slope
        end;
        if finish >= Bmp.Height then finish := Bmp.Height - 1;
        for Y := start to finish do begin
          X := dxi shr 11;
          if (Y < 0) or (X < 0) or (X > Bmp.Width-2) then begin
            Inc(dxi, dydxi);
            Continue;
          end;
          LM := dxi - X shl 11;
          LR := 2048 - LM;
          LMR := LM * LR;
          LMM := LM * LM;
          LRR := LR * LR;      ScanlinePtr := ScanLine0;
          Inc(ScanlinePtr, ScanlineIncrement *Y);
          ScanLines := pRGBArray(ScanLinePtr);      Scanlines[X].B := B*LR shr 11 + (B*LMR + Scanlines[X].B*LMM) shr 22;
          Scanlines[X].G := G*LR shr 11 + (G*LMR + Scanlines[X].G*LMM) shr 22;
          Scanlines[X].R := R*LR shr 11 + (R*LMR + Scanlines[X].R*LMM) shr 22;
          Inc(X);
          Scanlines[X].B := B*LM shr 11 + (B*LMR + Scanlines[X].B*LRR) shr 22;
          Scanlines[X].G := G*LM shr 11 + (G*LMR + Scanlines[X].G*LRR) shr 22;
          Scanlines[X].R := R*LM shr 11 + (R*LMR + Scanlines[X].R*LRR) shr 22;
          Inc(dxi, dydxi); // next point
        end;
      end;
    end;
      

  7.   

    ARI的代码是可以的,原因是你没有设置Tmp_Bitmapprocedure TForm1.Button1Click(Sender: TObject);
    var
        Tmp_Bitmap: TBitmap;
        Pnt1, Pnt2: TPoint;
    begin
        Tmp_Bitmap := TBitmap.Create;
        Tmp_Bitmap.Width:=200;    
        Tmp_Bitmap.Height:=200;    
         
            
        Pnt1.X := 0;
        Pnt1.Y := 0;
        Pnt2.X := Self.Width;
        Pnt2.Y := Self.Height;    WuLine(Tmp_Bitmap, Pnt1, Pnt2, clBlack);
        Self.Canvas.Draw(0, 0, Tmp_Bitmap);
        Tmp_Bitmap.Free;end;
      

  8.   

    使用GDI+进行绘图,使用GDI+中的Graphis对象中的SetSmoothingMode方法,便可以达到反锯齿效果
    fgraphics.SetSmoothingMode(SmoothingModeAntiAlias);
    ///
    GDI+ Delphi 开发包下载
    http://www.2ccc.com/article.asp?articleid=3131