2013-08-20 47 views
6

Trên ứng dụng của tôi, tôi cần vẽ trên TCanvas một "điểm đánh dấu", như dấu Google Maps (xem hình ảnh).Vẽ một điểm đánh dấu như bản đồ google với TCanvas trên Delphi

google marker

Tôi muốn sử dụng là tham số thì bán kính, chiều cao và nguồn gốc:

marker parameters

Tôi không có ý tưởng về thuật toán để sử dụng. Tôi có thể sử dụng một vòng cung để vẽ phía trên, nhưng làm thế nào tôi có thể vẽ đáy? Lưu ý: Tôi cần vẽ cả hai bằng GDI và GDI + để mọi giải pháp đều được chào đón.

+2

Tôi không muốn trở thành thô lỗ, nhưng tôi không nghĩ rằng đây có bất cứ điều gì để làm với Delphi hoặc GDI đặc biệt. Nó giống như tìm kiếm một thuật toán có ba tham số và kết quả đầu ra giống như ở trên. –

+0

@ GünthertheBeautiful nó có thể nhưng tôi cần phải làm điều đó với Delphi bằng cách sử dụng GDI và GDI + – Martin

+1

Vấn đề là khi bạn có mô tả toán học, bạn có thể vẽ nó bằng bất kỳ ngôn ngữ nào bạn ưa thích. Nó không phải là một câu hỏi delphi. FWIW Tôi đặt cược Google sử dụng hình ảnh raster. –

Trả lời

10

Dưới đây là ví dụ nhanh sử dụng 200x200 PaintBox - ít nhất nó sẽ cung cấp cho bạn ý tưởng về thuật toán. Tôi tin rằng bạn có thể vẽ chấm đen ở giữa. Đọc trên Bezier Curves; PolyBezier định nghĩa cubic Bezier curves. (link)

bezier

Bốn điểm xác định một đường cong Bezier khối - bắt đầu, kết thúc, và hai điểm kiểm soát. Các điểm điều khiển xác định độ cong của đường cong khi đường di chuyển từ đầu đến cuối.

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; 

Để đáp ứng các điểm mà bạn có thể làm điều này với một Bút chì:

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

Không cần phải điền vào bài đăng 'FloodFill' cũ. Ngoài ra, bạn có thể mô tả toàn bộ hình dạng điểm đánh dấu bằng các đường cong bezier (và vẽ nó bằng một cuộc gọi 'PolyBezier' duy nhất). – TLama

+2

@TLama - vâng, bạn có thể làm điều đó với một bezier. Tôi đã làm điều đó một cách nhanh chóng và không muốn xác định thêm bốn điểm kiểm soát nữa - nó có nghĩa là giáo khoa, không phải là sản xuất hoàn chỉnh. Arc nhanh hơn để mã hóa, không nhất thiết phải tốt hơn. Rõ ràng là một giải pháp GDI sẽ sử dụng các đường dẫn (xác định Beziers theo cùng một cách) và với các đường dẫn, việc điền thông tin là không cần thiết, một cách tự nhiên. Một lần nữa, đó là một cách làm việc vui vẻ hơn, không cố gắng làm công việc của OP cho anh ta. –

+1

Vâng, điều đó tốt hơn :-) Và bạn nói đúng. Với GDI + bạn có thể tạo một đường dẫn và điền vào đường dẫn. Nó dễ dàng hơn ở đó. [+1] – TLama