2012-06-05 42 views
9

Trong ứng dụng C# WinForms của tôi, tôi có một hình ảnh có 2 đường cong (Kết quả từ một phép đo điện áp/dòng). Trục X là điện áp và trục Y là dòng điện. Trục điện áp dao động từ -5 đến 5 nhưng trục hiện tại là một phạm vi nhỏ hơn nhiều dao động từ -10 uA đến 10 uA. Nhiệm vụ là để xem nếu đường cong thứ hai là trong vòng 10% của đường cong đầu tiên.Vẽ một phong bì xung quanh một đường cong

Để kiểm tra trực quan Tôi đang cố gắng vẽ một phong bì xung quanh đường cong đầu tiên (màu xanh lam). Đường cong chỉ là một mảng PointF. Tại thời điểm này vì tôi không có ý tưởng làm thế nào để vẽ một phong bì chính xác xung quanh đường cong màu xanh, tôi chỉ vẽ hai đường cong khác là kết quả của điểm X của đường cong thực tế được cộng và trừ đi 10% của đường cong ban đầu. Tất nhiên đây là một cách tiếp cận xấu, nhưng ít nhất cho phần của đường cong mà là đáng chú ý theo chiều dọc, nó hoạt động. Nhưng ngay sau khi các đường cong trên mặt đứng của nó không, thủ thuật này không làm việc nữa, như bạn có thể nhìn thấy trong hình dưới đây:

enter image description here

Đây là mã mà tôi đang sử dụng để vẽ phong bì :

public Bitmap DrawEnvelope(double[,] pinData, float vLimit, float iLimit) 
{ 
    g = Graphics.FromImage(box); 
    g.SmoothingMode = SmoothingMode.AntiAlias; 
    g.PixelOffsetMode = PixelOffsetMode.HighQuality; 

    PointF[] u = new PointF[pinData.GetLength(0)]; //Up line 
    PointF[] d = new PointF[pinData.GetLength(0)]; //Down Line 
    List<PointF> joinedCurves = new List<PointF>(); 

    float posX = xMaxValue * (vLimit/100); 
    float minX = posX * -1; 


    for (int i = 0; i < pinData.GetLength(0); i++) 
    { 
     u[i] = new PointF(400 * (1 + (((float)pinData[i, 0]) + minX)/(xMaxValue + vExpand)), 400 * (1 - ((float)pinData[i, 1] * GetInvers((yMaxValue + iExpand))))); 
    } 

    for (int i = 0; i < pinData.GetLength(0); i++) 
    { 
     d[i] = new PointF(400 * (1 + (((float)pinData[i, 0]) + posX)/(xMaxValue + vExpand)), 400 * (1 - ((float)pinData[i, 1] * GetInvers((yMaxValue + iExpand))))); 
    } 


    Pen pengraph = new Pen(Color.FromArgb(50, 0 ,0 ,200), 1F); 
    pengraph.Alignment = PenAlignment.Center; 

    joinedCurves.AddRange(u); 
    joinedCurves.AddRange(d.Reverse()); 

    PointF[] fillPoints = joinedCurves.ToArray(); 
    SolidBrush fillBrush = new SolidBrush(Color.FromArgb(40, 0, 0, 250)); 
    FillMode newFillMode = FillMode.Alternate; 

    g.FillClosedCurve(fillBrush, fillPoints, newFillMode, 0); 

    g.Dispose(); 
    return box; 
} 

các vòng tròn màu xanh lá cây được bổ sung bởi bản thân mình, và họ chỉ ra khu vực mà đường cong thứ hai (Red một) là có khả năng có một sự khác biệt lớn hơn 10% so với đường cong ban đầu.

Sẽ rất tuyệt nếu ai đó đưa tôi đi đúng hướng, tôi nên xem xét điều gì để đạt được phong bì đẹp quanh đường cong ban đầu?

CẬP NHẬT Bởi vì tôi đang rất Noob tôi không thể tìm thấy một cách để thực hiện các câu trả lời cho câu hỏi này cho đến bây giờ, Vì vậy, đặt một bounty để xem nếu somone vui lòng có thể cho tôi ít nhất một phương pháp mã hóa cho vấn đề này.

+2

Phong bì có nghĩa là vùng + - 10% không? Nếu có, thì tôi nghĩ điều đầu tiên bạn cần là rõ ràng hơn về những gì thực sự có nghĩa là "trong vòng 10%". Hiện tại trong vòng 10% ở mỗi điện áp? Điện áp trong vòng 10% ở mỗi dòng? Một số điều khác? Nếu điều này xuất phát từ một bài tập ở trường/đại học, thì từ ngữ thực sự là gì? Nếu đó là điều bạn đang làm vì lý do kinh doanh, các yêu cầu cơ bản là gì? Một khi điều đó rõ ràng, nó có thể sẽ rõ ràng hơn những gì "phong bì" của bạn nên trông như thế nào. –

+2

Bạn có thể không chỉ vẽ đường cong ban đầu của bạn một lần nữa, làm cho độ dày dòng rất lớn và độ mờ đục thấp? – Dan

+0

@Tôi đã cố gắng tạo ra đường cong ban đầu với một chiếc bút lớn hơn về kích thước, nhưng đó là một ý tưởng tồi vì kết quả sẽ tồi tệ hơn những gì tôi đang làm bây giờ. –

Trả lời

1

Đặt cược tốt nhất của bạn là lặp lại mảng điểm và tính toán vectơ vuông góc với hai điểm liên tiếp mỗi lần (xem Calculating a 2D Vector's Cross Product để biết các đầu mối triển khai). Dự án theo hai hướng dọc theo các vectơ vuông góc này để tạo ra hai mảng điểm của phong bì của bạn.

Chức năng này tạo cho họ khoảng sử dụng trung điểm đoạn (miễn là số điểm cao và bù đắp của bạn không phải là quá nhỏ nó nên nhìn ok khi vẽ):

private void GetEnvelope(PointF[] curve, out PointF[] left, out PointF[] right, float offset) 
     { 
      left = new PointF[curve.Length - 1]; 
      right = new PointF[curve.Length - 1]; 

      for (int i = 1; i < curve.Length; i++) 
      { 
       PointF normal = new PointF(curve[i].Y - curve[i - 1].Y, curve[i - 1].X - curve[i].X); 
       float length = (float)Math.Sqrt(normal.X * normal.X + normal.Y * normal.Y); 
       normal.X /= length; 
       normal.Y /= length; 

       PointF midpoint = new PointF((curve[i - 1].X + curve[i].X)/2F, (curve[i - 1].Y + curve[i].Y)/2F); 
       left[i - 1] = new PointF(midpoint.X - (normal.X * offset), midpoint.Y - (normal.Y * offset)); 
       right[i - 1] = new PointF(midpoint.X + (normal.X * offset), midpoint.Y + (normal.Y * offset)); 
      } 
     } 
+0

Cảm ơn, đây là một chút gần với những gì tôi muốn. –

3

Bạn có thể thử tìm độ dốc giữa mỗi cặp điểm và tính hai điểm ở hai bên nằm trên trực giao đi qua điểm giữa.

Sau đó, bạn sẽ có thêm hai dòng được xác định là tập hợp các điểm mà bạn có thể sử dụng để vẽ phong bì.

+0

Bạn có thể vui lòng cung cấp một chút mã để tôi có thể thấy được không? –

1

Tất cả phụ thuộc vào cách bạn muốn phong bì có kích thước.

Bạn có thể tính toán/đánh giá độ dốc của đường cong tại mỗi điểm bằng cách tính độ dốc cho điểm tiếp theo và độ dốc đến điểm trước đó, trung bình và sau đó tính toán vectơ vuông góc với độ dốc.

Thêm vectơ này vào điểm của đường cong; điều này mang lại cho bạn cạnh bên phải của phong bì.

Trừ vector này khỏi điểm của đường cong; điều này mang lại cho bạn cạnh bên trái của phong bì.

Phương pháp này sẽ thất bại nếu các điểm quá xa nhau hoặc thay đổi đột ngột về điểm xuất hiện.

+0

Hmmm ... Tôi vừa để ý rằng Nicholas cũng nghĩ như vậy. –

+0

@Cảm ơn mẹo ... mọi cơ hội để xem mã trông như thế nào? ít nhất cho một số điểm dữ liệu? –

+0

Tôi cần biết bạn muốn bao bọc phong bì như thế nào. –

0

Đây có lẽ là một gợi ý câm. Có lẽ thay vì vẽ phong bì cho mình, có lẽ bạn có thể cho phép winforms làm điều đó cho bạn. Hãy thử vẽ phong bì như một dòng với một cây bút có chiều rộng lớn hơn. Có lẽ nó có thể hoạt động.

Nếu bạn xem ví dụ msdn này về việc thay đổi độ rộng của bút, bạn có thể thấy ý tôi.

http://msdn.microsoft.com/en-us/library/3bssbs7z.aspx

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