6

在我的应用程序中,我需要在 TCanvas 上绘制一个“标记”,例如 Google 地图标记(见图)。

谷歌标记

我想将半径、高度和原点用作参数:

标记参数

我不知道要使用的算法。我可以使用圆弧来绘制顶部,但如何绘制底部?注意:我需要用 GDI 和 GDI+ 来绘制它,所以欢迎任何解决方案。

4

1 回答 1

10

这是一个使用 200x200 的快速示例PaintBox- 它至少应该让您对算法有所了解。我相信你可以画出中间的黑点。阅读贝塞尔曲线PolyBezier定义三次贝塞尔曲线。(关联)

贝塞尔曲线

四个点定义了一条三次贝塞尔曲线 - 起点、终点和两个控制点。控制点定义线从开始到结束移动时的曲率强度。

var origin, innerL, midL, midR, lft, tp, rgt, innerR : TPoint;
    radius, hgt : integer;
begin    
  radius := 25;
  hgt := 90;    
  origin.X := 100;
  origin.Y := 180;
  //control points
  innerL.X := origin.X;
  innerL.Y := origin.Y - (hgt - radius) div 3;
  midL.X := origin.X - radius;
  midL.Y := origin.Y - 2*((hgt - radius) div 3);
  //top circle
  lft.X := origin.X - radius;
  lft.Y := origin.Y - (hgt - radius);
  tp.X := origin.X;
  tp.Y := origin.Y - hgt;
  rgt.X := origin.X + radius;
  rgt.Y := lft.Y;
  //control points
  midR.X := origin.X + radius;
  midR.Y := midL.Y;
  innerR.X := origin.X;
  innerR.Y := innerL.Y;

  PaintBox1.Canvas.Pen.Width := 2;
  PaintBox1.Canvas.PolyBezier([origin, innerL, midL, lft]);
  PaintBox1.Canvas.Arc(lft.X, tp.Y, rgt.X, rgt.Y + radius, rgt.X, rgt.Y, lft.X, lft.Y);
  PaintBox1.Canvas.PolyBezier([rgt, midR, innerR, origin]);
  //fill
  PaintBox1.Canvas.Brush.Color := clYellow;
  PaintBox1.Canvas.FloodFill(origin.X, origin.Y - radius,
                             Canvas.Pen.Color, TFillStyle.fsBorder);    
end;

为了满足你可以用一个贝塞尔曲线做到这一点:

  // add four more control TPoints
  cornerL.X := lft.X;
  cornerL.Y := tp.Y + radius div 2;
  cL2.X := lft.X + radius div 2;
  cL2.Y := tp.Y;
  cR2.X := rgt.X - radius div 2;
  cR2.Y := tp.Y;
  cornerR.X := rgt.X;
  cornerR.Y := cornerL.Y;


  PaintBox1.Canvas.PolyBezier([origin, innerL, midL, lft,
                               cornerL, cL2, tp, cR2, cornerR, rgt,
                               midR, innerR, origin]);
于 2013-08-20T17:42:53.813 回答