在Delphi上用TCanvas绘制一个像google地图的标记 [英] Draw a marker like google maps with TCanvas on Delphi

查看:587
本文介绍了在Delphi上用TCanvas绘制一个像google地图的标记的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用程序中,我需要在TCanvas上绘制一个标记,如Google Maps标记(参见图像)。





我想使用半径,高度和起点的参数:





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

解决方案

例如使用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;
//控制点
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);
//顶圈
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;
//控制点
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);
结束

要满足您可以使用一个贝塞尔语:

  //添加另外四个控件TPoint 
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 ,来源]);


On my application I need draw on TCanvas a "marker", like Google Maps marker (see the image).

I'd like use as parameters the radius, the height and the origin:

I don't have idea about algorithm to use. I can use an arc to draw the top, but how can I draw the bottom? Note: I need draw it both with GDI and GDI+ so any solution is welcome.

解决方案

Here is a quick example using a 200x200 PaintBox - it should at least give you an idea for the algorithm. I trust you can draw the black dot in the middle. Read up on Bezier Curves; PolyBezier defines cubic Bezier curves. (link)

Four points define a cubic Bezier curve - start, end, and two control points. Control points define the strength of curvature as the line moves from start to end.

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;

To satisfy the point that you can do this with one bezier :

  // 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]);

这篇关于在Delphi上用TCanvas绘制一个像google地图的标记的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆