2009-11-19 34 views
7

Tôi đang cố gắng tạo công cụ 'cọ vẽ' trong AS3 (thuần túy, không phải Flex) mô phỏng chữ viết tay, làm cho nét được mịn thay vì bị dồn vào chân. Sau đó, dấu vết phải được giảm xuống các đường cong bezier khối có thể được kéo và biến dạng, ảnh hưởng đến đường dẫn được vẽ trước đó (như công cụ bút vẽ của họa sĩ minh họa).Tạo một đường đi trơn tru từ số x, y không đều để mô phỏng chữ viết tay

Tôi đang theo dõi chuyển động của chuột để có được một tập hợp các điểm để vẽ đường dẫn. Theo như tôi biết, tôi cần phải làm một con đường B-Spline bằng cách sử dụng tập hợp các điểm đó. Sau đó, tôi nên giảm nó thành các đường cong khối bezier (thêm chức năng 'công cụ bút' vào đường dẫn).

Tôi đã phát triển công cụ bút, sử dụng thuật toán làm giảm Beziers khối thành Beziers bậc hai (và sau đó sử dụng hàm curveTo Flash). Nhưng tôi không có ý tưởng làm thế nào để tạo ra một B-Spline (hoặc đơn giản hóa khác), sau đó giảm nó để Bezier đường cong.

Bạn có biết cách nào để thực hiện việc này không?

+0

Tôi đang tìm kiếm điều tương tự nhưng javascript, bạn có biết không? – igor

Trả lời

7

jhotdraw là dự án mã nguồn mở trong Java để vẽ. Nó chuyển đổi các bản vẽ tay miễn phí thành các đường cong khối bezier. Nguồn có sẵn - tải xuống và dịch. Đừng sợ hãi ở kích thước của dự án: bạn chỉ cần một vài lớp học cụ thể là:

org.jhotdraw.geom.Bezier 
org.jhotdraw.geom.BezierPath 
org.jhotdraw.geom.Geom 

Trong khi dịch bắt đầu bằng cách thay đổi tất cả các tờ khai bộ sưu tập để Mảng (vectơ sử dụng nếu bạn đang nhắm mục tiêu chỉ những người dùng FP10) . Tôi có một số regexes mà bạn có thể thấy hữu ích trong chuyển đổi - Tôi có thể đăng chúng nếu bạn muốn.


Dưới đây là danh sách các regex mà bạn có thể thấy hữu ích. Trong mỗi cặp, dán cái đầu tiên vào vùng văn bản tìm kiếm và thứ hai vào vùng thay thế, chọn hộp kiểm regex và sử dụng nút Tìm và Thay thế. Không sử dụngReplace All- không cách nào trong số này được đảm bảo là đơn giản.

Thay thế tất cả int/double name tờ khai với var name:Number

\b(double|int)\s+(\w+)\b 

var $2:Number 

Thay thế tất cả Point2D.Double name tờ khai với var name:Point

\bPoint2D\.Double\s+(\w+)\b 

var $1:Point 

Thay thế tất cả int/double name tờ khai trong chữ ký chức năng với name:Number

\(([^)]*)\b(?:double|int)\s+(\w+)\b([^)]*?)\) 

($1$2:Number$3) 

Thay thế tất cả Point2D.Double name tờ khai trong chữ ký chức năng với name:Point

\(([^)]*)\b(?:Point2D\.Double)\s+(\w+)\b([^)]*?)\) 

($1$2:Point$3) 

Trước khi thay đổi chữ ký phương pháp, chắc chắn rằng tất cả các phương pháp tĩnh:

(public|private)\s+(?!static) 

Thay thế chữ ký phương pháp để AS dạng

(public|private)\s+static\s+(\w+)\s+(\w+)\s*\(([^)]*)\) 

$1 static function $3($4):$2 

Thay thế ArrayList.get (index) bằng mảng [index] // Cảnh báo: thất bại cho list.get (danh sách.size() - 1)

(\w+)\.get\(([^)]+)\) 

$1[$2] 

//avoid the() failure 

(\w+)\.get\(([^)]*(?:\([^)]*\))[^)]*)\) 

$1[$2] 

Thay ArrayList.set(index, element) với array[index] = element // Cảnh báo: không cho list.set (i, list.size())

(\w+)\.set\(([^,]+)\s*,\s*([^)]+)\) 

$1[$2] = $3 


/*the above regex successfully made the following replacement*/ 

cleaned.set(cleaned.size() - 1, digitizedPoints[digitizedPoints.size() - 1]) 

cleaned[cleaned.size() - 1] = digitizedPoints[digitizedPoints.size() - 1] 

Thay arraylist.add(object) với array.push(object)

//would fail if object contains ')' 
//add(index, object) should be done with splice 

(\w+)\.add\(([^)]+)\) 

$1.push($2) 

//too many failures - fail safe version - 
//still fails for nested parenthesis list.add(new Point(a.first(), a.last())) 
//- only three such cases - the effort to match parenthesis wouldn't be worth it 
//works for list.add(new Point(3, 4)) - there were many similar cases 

(\w+)\.add\(([^)]*(?:\([^)]*\))[^)]*)\) 

$1.push($2) 

Thay thế chữ ký của phương thức thành định dạng AS (phương pháp không tĩnh)

(public|private)\s+(?!function)(\w+)\s+(\w+)\s*\(([^)]*)\) 

$1 function $3($4):$2 

Thay thế tất cả int/double/point/boolean name tờ khai trong chữ ký chức năng với name:type

\(([^)]*)\b(\w+)\s+(\w+)\b([^)]*?)\) 

($1$3:$2$4) 

Thay thế tất cả các khai báo biến trong một dòng riêng với một = AS dạng

^(\s+)(\w+)\s+(\w+)\s*=\s*(.+?)\s*;(\s*)$ 

$1var $3:$2 = $4;$5 

đặt thay đổi niềng răng.

^(\t)(\s*)([^\n]+)\{\s*(\n)\s+ 

$1$2$3$4$1$2{$4$1$2 

thay đổi } else vào } \n else

^([ \t]+)}[ \t]*else\b([^\n]*)(\n) 

$1}$3$1else$2$3 

Thay 4 khai báo biến trong một đường duy nhất để AS trong dòng khác nhau

^(\t+)(\w+)\s+(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*;[ \t]*(\n) 

$1var $3:$2;$7$1var $4:$2;$7$1var $5:$2;$7$1var $6:$2;$7 

tờ khai mảng Thay

^(\s+)\w+\[\]\s*(\w+)\b 

$1 var $2:Array 

Remove() đúc - AS biên dịch không thích chúng

(?:\(\w+\)\s*)([^ ,*+;/)><=\-]) 

$1 

Thay max vv vào Math.max - AS không có hàng nhập khẩu tĩnh

(?<!Math\.)\b(max|min|abs|sqrt|PI|cos|sin|atan2)\(

Math.$1(
+0

Tôi đã kiểm tra thư viện và có vẻ tuyệt vời. Ứng dụng vẽ mẫu thực hiện chính xác những gì tôi muốn. Cảm ơn bạn đã tham khảo. – yizzreel

+0

Đây là các regex tôi đã nói đến. – Amarghosh

+0

Thật là một công việc tuyệt vời !! Tôi đã bắt đầu chuyển mã Java sang AS3, nó dường như không phải là một nhiệm vụ khó khăn, nhưng điều này sẽ đẩy nhanh quá trình này rất nhiều. Cảm ơn rất nhiều. – yizzreel

1

tôi đã sử dụng chức năng này một lúc.

 

    public function multicurve(g: Graphics, args: Array, closed: Boolean): void {   
      var mid: Array = args.slice(); //make dublicate 
      var i: uint; 
      var point: Point; 
      var nextPoint: Point; 
      var numPoints: uint = mid.length; 

      if (numPoints == 2) { 
       g.moveTo(mid[0].x, mid[0].y); 
       g.lineTo(mid[1].x, mid[1].y); 
       return; 
      } 

      var Xpoint: Array = new Array(); 
      var Ypoint: Array = new Array(); 
      for (i = 1; i < numPoints - 2; i++) { 
       point = mid[i]; 
       nextPoint = mid[i+1]; 
       Xpoint[i] = 0.5*(nextPoint.x + point.x); 
       Ypoint[i] = 0.5*(nextPoint.y + point.y); 
      } 
      if (closed) { 
       Xpoint[0] = 0.5*(mid[1].x + mid[0].x); 
       Ypoint[0] = 0.5*(mid[1].y + mid[0].y); 
       Xpoint[i] = 0.5*(mid[i+1].x + mid[i].x); 
       Ypoint[i] = 0.5*(mid[i+1].y + mid[i].y); 
       Xpoint[i+1] = 0.5*(mid[i+1].x + mid[0].x); 
       Ypoint[i+1] = 0.5*(mid[i+1].y + mid[0].y); 
       mid.push(new Point(mid[0].x, mid[0].y)); 
       Xpoint[i+2] = Xpoint[0]; 
       Ypoint[i+2] = Ypoint[0]; 
      } else { 
       Xpoint[0] = mid[0].x; 
       Ypoint[0] = mid[0].y; 
       Xpoint[i] = mid[i+1].x; 
       Ypoint[i] = mid[i+1].y; 
       mid.pop(); 
       numPoints--; 
      } 
      g.moveTo(Xpoint[0], Ypoint[0]); 
      for (i = 1; i < numPoints; i++) { 
       point = mid[i]; 
       g.curveTo(point.x, point.y, Xpoint[i], Ypoint[i]); 
      } 
      if (closed) { 
       g.curveTo(mid[0].x, mid[0].y, Xpoint[i], Ypoint[i]); 
      } 
     } 

 
1

Có một thuật toán trong thư viện ac mà những gì bạn đang hỏi: http://tog.acm.org/resources/GraphicsGems/gems/FitCurves.c

Đây là một thuật toán khá phức tạp giúp đơn giản hóa hình học của bạn bằng cách chuyển đổi danh sách nhiều điểm thành danh sách một số đường cong bezier gần, chuyển bản vẽ thành đường cong rất trơn tru. Nó có một số lượng có thể điều chỉnh của slack, và hoạt động bằng cách tìm số tiền ít nhất của đường cong bezier phù hợp với tập hợp các điểm của bạn trong một slack nhất định. Vì vậy, bạn càng đặt độ trễ của thuật toán, văn bản của bạn càng mượt mà hơn (nhưng có khả năng kém chính xác hơn).

+0

Hey! Cảm ơn! điều này có vẻ tốt đẹp !. Tôi đã sử dụng thuật toán jHotDraw (được đơn giản hóa) và nó hoạt động khá giống với mã bạn đã liên kết với tôi. Tuy nhiên, tôi cũng sẽ xem xét kỹ phần này. Và có vẻ như có nhiều nguồn hơn trong trang web có tệp. Cảm ơn một lần nữa để tham khảo! – yizzreel

+0

Cập nhật nhanh: thư viện FitCurves đã hoạt động, nhưng nếu tôi đã giải quyết vấn đề này một lần nữa, tôi sẽ tiếp cận nó một cách khác nhau. Trước hết tôi phải chỉnh sửa thư viện để xử lý chữ viết tay nhanh - chữ viết tay nhanh có vẻ là một cách tốt để kiểm tra căng thẳng như một thuật toán. Quan trọng hơn mặc dù, tôi sẽ làm cho một thuật toán thời gian thực tính toán một đường cong tại một thời điểm khi bạn vẽ. Tôi sẽ giữ phần cốt lõi của FitCurves, một thuật toán trả về một đường cong duy nhất phù hợp nhất với một tập hợp các điểm và tùy chỉnh phần còn lại. –

+0

Liên kết giờ đã chết. Đã lưu trữ tại đây: https://web.archive.org/web/20090805204502/http://tog.acm.org/resources/GraphicsGems/gems/FitCurves.c và dường như liên kết chính thức mới: https://github.com/erich666/GraphicsGems/blob/master/gems/FitCurves.c /* Thuật toán để tự động lắp các đường cong được số hóa bởi Philip J. Schneider từ "Gems đồ họa", Báo chí học thuật, 1990 * / – murkle

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