转动的椭圆,看起来像原子符号。如果是三个的话是以前央视标志

Rotated EllipsesDecember 2005
There is no native Windows function to draw ellipses at rotated angles, so every programmer has to do the drawing themselves. It took me a while to find some decent code on the internet. However, I did find this excellent C++ code which I've used as the basis of my Delphi code below. The codeguru site linked to above also has a good summary of other ways to draw ellipses so I wont repeat here what was said there.

The rotated ellipse is constructed by a series of 4 bezier curves. Although not demonstrated in the code below, a reasonable approximation of bounding rectangle of the ellipse (aligned with the x-y axis) can be derived by finding both the minimum and maximum values for x and y from the 13 points used to define the bezier curves.

Anyhow, here's my Delphi function to draw rotated ellipses. The calling function Button1Click() also demonstrates how to assign a record constant, something newcomers to Delphi may not be aware is possible.

Code snippet ...
uses Math;

procedure RotatePts(var pts: array of TPoint;
  origin: TPoint; radians: single);
var
  i,x,y: integer;
  cosAng, sinAng: single;
begin
  cosAng := cos(radians);
  sinAng := sin(radians);
  for i := low(pts) to high(pts) do
  begin
    x := pts[i].X - origin.X;
    y := pts[i].Y - origin.Y;
    pts[i].X := round((x * cosAng) - (y * sinAng)) + origin.X;
    pts[i].Y := round((x * sinAng) + (y * cosAng)) + origin.Y;
  end;
end;
//--------------------------------------------------------------

//see - http://www.codeguru.com/Cpp/G-M/gdi/article.php/c131

procedure DrawRotatedEllipse(canvas: TCanvas;
  rec: TRect; degrees: integer);
const
  //Magic constant = 2/3*(sqrt(2)-1)
  offset: single = 0.27614237;
var
  midx, midy, offx, offy: integer;
  pts: array [0..12] of TPoint;
  radians: single;
begin
  degrees := degrees mod 360;
  if degrees < 0 then inc(degrees, 360);
  radians := degrees *pi / 180;

  //if there's no rotation, use the standard Windows function
  if radians = 0 then
    canvas.Ellipse(rec)
  else
  begin
    with rec do
    begin
      dec(right); dec(bottom); //empirically this seems better
      midx := (right + left) div 2;
      midy := (bottom + top) div 2;
      offx := round((right - left) * offset);
      offy := round((bottom - top) * offset);
      pts[0]  := Point(left, midy);
      pts[1]  := Point(left, midy - offy);
      pts[2]  := Point(midx - offx, top);
      pts[3]  := Point(midx, top);
      pts[4]  := Point(midx + offx, top);
      pts[5]  := Point(right, midy - offy);
      pts[6]  := Point(right, midy);
      pts[7]  := Point(right, midy + offy);
      pts[8]  := Point(midx + offx, bottom);
      pts[9]  := Point(midx, bottom);
      pts[10] := Point(midx - offx, bottom);
      pts[11] := Point(left, midy + offy);
      pts[12] := pts[0];
      //rotate all points about the ellipse center ...
      RotatePts(pts, Point(midx,midy), radians);
    end;
    with canvas do
    begin
      beginPath(Handle);
      canvas.PolyBezier(pts);
      EndPath(Handle);
      if canvas.Brush.Style = bsClear then
        StrokePath(Handle) else
        StrokeAndFillPath(Handle);
    end;
  end;
end;
//--------------------------------------------------------------

procedure TForm1.Button1Click(Sender: TObject);
const
  rec: TRect = (left:100; top:100; right:300; bottom:200);
begin
  canvas.Pen.Width := 2;

  canvas.Brush.Color := clWhite;
  DrawRotatedEllipse(Canvas, rec, 0);
  //now overlay the same sized ellipse,
  //but rotated at several angles ...
  canvas.Brush.Style := bsClear;
  DrawRotatedEllipse(Canvas, rec, -45);
  DrawRotatedEllipse(Canvas, rec, 45);
  DrawRotatedEllipse(Canvas, rec, 90);
end;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值