2009-08-03 47 views
23

Tôi hiện đang sử dụng thuật toán của Bresenham để vẽ các đường nhưng chúng (tất nhiên) có độ dày một pixel. Câu hỏi của tôi là cách hiệu quả nhất để vẽ các đường có độ dày tùy ý là gì?Làm thế nào để tôi tạo ra một đường dày tùy ý bằng cách sử dụng Bresenham?

Các ngôn ngữ tôi đang sử dụng là C.

+1

Được gắn thẻ lại "ngôn ngữ không thuyết phục" vì ngôn ngữ triển khai thực sự không liên quan. –

+0

đây là câu hỏi SO có liên quan: http://stackoverflow.com/questions/101718/drawing-a-variable-width-line-in-opengl-no-gllinewidth –

+0

@banister: bạn có một số bản demo để chia sẻ với chúng tôi? – sdkie

Trả lời

10

Tôi nghĩ rằng cách tốt nhất là để vẽ một hình chữ nhật chứ không phải là một dòng từ một phù hợp với chiều rộng là một đối tượng hai chiều. Tring để vẽ một tập hợp các đường song song để tránh quá tải (để giảm băng thông ghi) và rút tiền (thiếu pixel) sẽ khá phức tạp. Nó không phải là quá khó để tính toán các điểm góc của hình chữ nhật từ điểm bắt đầu và kết thúc và chiều rộng.

+2

Tôi không có giải pháp của bạn. Bạn có thể xây dựng được không. – sdkie

9

Đây là một paper and Delphi implementation của phiên bản sửa đổi thuật toán của Bresenham để vẽ các đường dày.

Bạn cũng có thể xem Anti-Grain Geometry, thư viện cho phần mềm chất lượng cao và hiệu suất cao hiển thị đồ họa 2D. Hãy xem demo page để có ý tưởng về những gì nó có thể làm.

4

Một số tuyến đường đơn giản để sử dụng:

  1. cho bất kỳ chiều rộng n trong đó n là số lẻ. đối với bất kỳ điểm p nào cũng vẽ đồ thị các điểm trên/dưới nó cho n/2 (nếu dòng> góc nghiêng 45 độ sang bên).
    • không thực sự là một dòng thích hợp của độ dày phù hợp, giống như bút nghiêng, nhưng rất nhanh.
  2. cho điểm bắt đầu p (x, y) chọn các điểm t0 và b sao cho chúng nằm ở vị trí cách nhau cách nhau p nhưng n pixel. cho điểm cuối làm tương tự với t1 b1. Vẽ các đường từ t0 -> t1, t1-> b1, b1 -> t0, b0 -> t1. Điền vào hình chữ nhật kết quả.
    • Bí quyết ở đây là chọn các điểm sao cho chúng xuất hiện trực giao theo hướng của đường dẫn.
  3. cho mỗi điểm p trên đường thay vì vẽ một điểm vẽ một vòng tròn.
    • Điều này có lợi thế là làm cho điểm kết thúc 'sạch' bất kể định hướng là gì.
    • không cần phải hiển thị bất kỳ vòng kết nối nào ở dạng rắn ngoại trừ vòng kết nối đầu tiên.
    • hơi chậm
2

Tôi giả định rằng bạn sẽ rút ra nhịp ngang từ một dòng bounding khác, và tính x-giá trị của mỗi dòng bằng phương pháp Bresenham như bạn đi (trong một đơn vòng lặp).

Chưa thử.

Điểm kết thúc có thể cần một số sự chú ý, vì sợ rằng họ trông kỳ lạ bị cắt.

+0

vâng, đây là chiến lược mà tôi đã nghĩ đến và tôi đồng ý rằng các điểm kết thúc sẽ cần một số suy nghĩ. – horseyguy

0

Đối với ứng dụng máy in nhiệt nhúng của tôi, sử dụng thuật toán của Bresenham, dòng này quá mỏng. Tôi không có GL hoặc bất cứ điều gì ưa thích. Tôi đã kết thúc chỉ đơn giản là giảm giá trị Y và vẽ nhiều dòng hơn dưới giá trị đầu tiên. Mỗi số độ dày thêm một dòng khác. Rất nhanh chóng để thực hiện và thực hiện cho các kết quả mong muốn in từ bitmap đơn sắc đến nhiệt.

+0

Tôi thích ý tưởng của bạn, làm cách nào bạn kiểm tra/tính toán khoảng cách mong muốn giữa các đường để bạn bắt chước độ dày? là nó bằng thử và sai? –

+0

Mỗi chấm có dấu chấm khác bên dưới nó ... không tính toán; dòng rõ ràng hơn. Tôi đã kết thúc bằng cách sử dụng 3 dòng, mỗi dòng có giá trị Y nhỏ hơn trước đó. Bất kỳ y nào nhỏ hơn y tối thiểu được đổi thành Y tối thiểu. –

+0

Xin lỗi, tôi đã nhầm lẫn về việc kiểm soát độ dày và kiểm soát độ rộng của đường kẻ. –

15

Thực hiện một vòng lặp Bresenham khác và sử dụng nó để sửa đổi vị trí bắt đầu và kết thúc của dòng ban đầu theo hướng hình chữ nhật. Vấn đề là tìm hiệu quả điểm xuất phát phù hợp và không vẽ bất kỳ pixel nào hai lần (hoặc bỏ qua pixel) trong khi vẽ đường tiếp theo.

Làm việc và kiểm tra mã C có sẵn từ Github C code.

Đây là trang thử nghiệm bao gồm một số dòng mẫu được tạo bởi mã này. Các pixel đen là điểm bắt đầu cho thuật toán.

Test page with bresenham lines with different thickness

+2

Nếu tôi có thể, tôi sẽ upvote câu trả lời này nhiều hơn, bởi vì nó là người duy nhất chỉ đạo người đọc đến một thực hiện sạch sẽ, làm việc trong C - cũng giống như OP yêu cầu. – msteiger

+0

Điều đó thật thông minh! – hexaflexagonal

1

http://members.chello.at/~easyfilter/bresenham.html

Ví dụ ở dưới cùng của liên kết này là javascript, nhưng phải đủ dễ dàng để thích ứng với C. Đó là một thuật toán khử răng cưa khá đơn giản để vẽ dòng có độ dày khác nhau.

7

Để có độ chính xác tốt nhất và cũng có hiệu suất tốt cho các đường đặc biệt, bạn có thể vẽ đường như đa giác. Một số mã giả:

draw_line(x1,y1,x2,y2,thickness) 
    Point p[4]; 
    angle = atan2(y2-y1,x2-x1); 
    p[0].x = x1 + thickness*cos(angle+PI/2); 
    p[0].y = y1 + thickness*sin(angle+PI/2); 
    p[1].x = x1 + thickness*cos(angle-PI/2); 
    p[1].y = y1 + thickness*sin(angle-PI/2); 
    p[2].x = x2 + thickness*cos(angle-PI/2); 
    p[2].y = y2 + thickness*sin(angle-PI/2); 
    p[3].x = x2 + thickness*cos(angle+PI/2); 
    p[3].y = y2 + thickness*sin(angle+PI/2); 
    draw_polygon(p,4) 

Và tùy chọn một vòng tròn có thể được vẽ ở mỗi điểm cuối.

+0

Theo cách này, việc giảm vấn đề trở thành vấn đề phức tạp hơn. Để làm cho nó hoạt động (bằng Python), tôi phải điều chỉnh mọi thứ, mặc dù: a) trao đổi tội lỗi và cos. b) thay vì nhân với độ dày, nhân với độ dày/2.0. – Ant6n

+0

@ Ant6n Tôi nghĩ rằng đó là * góc * sai. Điều này sẽ là 'atan2 (y2-y1, x2-x1)'. – colinta

+0

@colina Đã sửa lỗi. – Fabel

0

Tôi đã đối mặt với cùng một vấn đề một thời gian trước đây. Dựa trên số paper này, tôi đã tạo một triển khai tham chiếu Matlab mà tôi muốn chia sẻ trên GitHub.

1

Tôi làm điều này khá thường xuyên để tạo ra hình ảnh của sợi và hình cầu cho mô phỏng phương tiện truyền thông xốp. Tôi có một cách đơn giản tốt đẹp làm điều này bằng cách sử dụng một kỹ thuật phân tích hình ảnh rất chuẩn được biết đến như là 'biến đổi khoảng cách'. Điều này đòi hỏi phải có quyền truy cập vào một số gói phân tích hình ảnh. Tôi sử dụng Python với Scipy, vì vậy đây không phải là vấn đề. Đây là một bản demo để chuyển đổi các điểm phân phối ngẫu nhiên vào các lĩnh vực:

import scipy as sp 
import scipy.ndimage as spim 

im1 = sp.rand(100, 100) < 0.995 # Create random points in space 
dt = spim.distance_transform_edt(im1) 
im2 = dt < 5 # To create sphere with a radius of 5 

random seeds, distance map, final spheres

Và đó là nó! Việc chuyển đổi khoảng cách có thể chậm đối với những hình ảnh rất lớn, nhưng có phiên bản hiệu quả trên mạng. Ví dụ, ImageJ có một song song. Rõ ràng, để tạo các sợi dày bạn chỉ cần tạo ra hình ảnh của bạn mỏng, sau đó áp dụng các bước 2 và 3 ở trên.

Các vấn đề liên quan