2009-04-07 29 views
21

Chúng tôi đang sử dụng wpf để phát triển một ứng dụng như cad nơi bản vẽ được đặt trên canvas bằng cách sử dụng đối tượng Đường dẫn. Tôi chỉ gặp một vấn đề nhỏ khi i scale/zoom canvas của tôi, tất cả các phần tử trong canvas được thu nhỏ và đây là hành vi tôi muốn nhưng điều này cũng làm tăng độ dày nét của Path.Độ dày đột biến bất thường của đường dẫn bất kể quy mô

Có cách nào để tôi tăng/thu phóng/thu phóng đối tượng nhưng tôi vẫn duy trì độ dày nét vẽ tương tự của đường dẫn.

Bất kỳ trợ giúp nào về vấn đề này sẽ rất hữu ích đối với tôi.

Trả lời

6

Cuối cùng tôi nhận giải pháp cho giải pháp trên. Tôi đã làm điều đó bằng cách đặt số StrokeThickness của số Path tương ứng với tỷ lệ của số Canvas.

Như thế này:

// scale = scaling factor applied to the canvas 
path.StrokeThickness = 1.0/scale; 

này chỉ hoạt động nếu ScaleXScaleY là thống nhất.

+13

Điều này là tốt nếu quy mô x và y của bạn là đồng nhất, nhưng không hoạt động nếu tỷ lệ không giống nhau. – Klay

13

Một giải pháp tốt hơn sẽ được sử dụng một hoặc đối tượng System.Windows.Media.Geometry hơn để lưu trữ đường dẫn của bạn, chỉ, vv

hình học này có thể được rút ra với Pen, vì vậy bạn thực sự có thể thay đổi đột quỵ độ dày khi bạn phóng to, nhưng linh hoạt hơn là sử dụng thuộc tính Biến đổi.

Sử dụng phép biến đổi, bạn có thể "thu phóng" tọa độ thực tế của đại diện hình học chứ không phải trực quan hóa - vì vậy khi bạn vẽ nó, bạn không cần phải fiddle với biến đổi kết xuất.

Để tính toán biến đổi, tôi sử dụng đoạn mã sau như:

public static Matrix TransformShape(Rect fromPosition, Rect toPosition, bool flipVertical) { 
    Matrix translateThenScale = Matrix.Identity; 
    //we first translate to origin since that's just easier 
    translateThenScale.Translate(-fromPosition.X, -fromPosition.Y); 
    //now we scale the graph to the appropriate dimensions 
    translateThenScale.Scale(toPosition.Width/fromPosition.Width, toPosition.Height/fromPosition.Height); 
    //then we flip the graph vertically around the viewport middle since in our graph positive is up, not down. 
    if (flipVertical) 
     translateThenScale.ScaleAt(1.0, -1.0, 0.0, toPosition.Height/2.0); 
    //now we push the graph to the right spot, which will usually simply be 0,0. 
    translateThenScale.Translate(toPosition.X, toPosition.Y); 

    return translateThenScale; 
} 

nơi fromPosition Rect nên chứa các giới hạn untransformed, và toPosition Rect nên chứa các giới hạn biến đổi. Điều này cũng trivially cho phép mở rộng X và Y một cách riêng biệt, mà thường là cần thiết cho âm mưu.

Thật dễ dàng để tính toán giới hạn của hình học của bạn:

Geometry graphGeom; 
//[...] 
//the bounds are modified by the transform, so we want no transform!  
graphGeom.Transform = Transform.Identity; 
Rect graphBounds = graphGeom.Bounds; 
//then set the transform again 

//or, if the transform is axis-aligned, the following _should_ work: 
Rect graphBoundsAlt = graphGeom.Transform.Inverse.TransformBounds(graphGeom.Bounds); 

Và tất nhiên WPF có thể cho bạn biết tiếp giáp bạn cần phải làm vào, mà cần thiết. Đưa nó lại với nhau, bạn có thể làm một cái gì đó giống như

public void RecomputeTransform(Rect targetRect, bool flipVertical) { 
    graphGeom.Transform = Transform.Identity; 
    Rect graphBounds = graphGeom.Bounds; 
    Matrix transMat = TransformShape(graphBounds,targetRect,flipVertical); 
    graphGeom.Transform = new MatrixTransform(transMat); 
} 

Ưu điểm của việc sử dụng giải pháp này là bạn không cần phải gây rối với RenderTransforms, bạn đang miễn phí để sử dụng biến mà cắt và/hoặc quy mô X và Y một cách độc lập mà không bị biến dạng lạ trong đường kẻ của bạn, và bạn có thể coi Bút là đối tượng mờ đục (tức là dễ dàng hơn để tùy chỉnh từ giao diện người dùng - nếu bạn chọn Chiều rộng bút hoặc không có gì, không cần sửa thêm nữa).

+0

Tôi giả định rằng việc sử dụng giải pháp này sẽ yêu cầu các phần của bản vẽ mà bạn không muốn chia tỷ lệ để tách biệt với canvas chính có thể mở rộng. Ví dụ sẽ là một ứng dụng vẽ vector, nơi bản vẽ chính nó quy mô nhưng hình ảnh điểm neo và quy mô như vậy vị trí nhưng không xa như độ dày của họ và như vậy. Tôi có đúng trong giả định này không? – jpierson

+0

Tôi xin lỗi, tôi không * khá hiểu câu hỏi của bạn ... Thực tế đây là điều bạn muốn làm trong một kịch bản vẽ vector, nơi bạn quan tâm đến một đường hoặc điểm lý tưởng hóa chứ không phải về độ dày của chúng. Cách tiếp cận này sẽ mở rộng (hoặc biến đổi tuyến tính) một bản vẽ đường thẳng mà không cần phải chuyển đổi chiều rộng đường kẻ. Tức là, bạn đang chuyển đổi hình học lý tưởng và chỉ * sau đó * chuyển đổi thành hình dạng "thực" mà tất nhiên có các đường có chiều rộng khác 0. Nếu bạn đã biến đổi 'Bản vẽ', bạn cũng sẽ biến đổi các chi tiết như các đường thẳng và đường nối vv. Điều đó làm rõ nó? –

+0

Tôi nghĩ rằng, giả định của tôi là ứng dụng vẽ sẽ có một số phần mở rộng mọi thứ như bản vẽ và một số phần giống như trang trí không mở rộng về độ dày nhưng vẫn được định vị tương đối với bản vẽ được chia tỷ lệ. Chẳng hạn như các ứng dụng vẽ vector như Inkscape nơi các đường vẽ được thu nhỏ về độ dày nhưng các điểm neo được hiển thị cho đối tượng đã chọn không được thu nhỏ theo cách tương tự. Vì vậy, giả định của tôi là để thực hiện điều này trong .NET bạn sẽ vẫn cần phải có những phần này trong hai bảng phân chia được thu nhỏ một cách độc lập. – jpierson

0

Tôi đã trở lại đây nhiều lần, nhưng ý tưởng này chỉ xảy ra với tôi, làm thế nào về việc chỉ gói nó trong Viewbox?

Bạn có thể thử điều này: gây rối với Chiều cao/Chiều rộng không được thay đổi tỷ lệ độ dày thành kích thước. Có lẽ nó làm những điều xấu khác mà tôi chưa phát hiện ra ...

<Viewbox Height="50" Width="50"> 
    <Path Stroke="Black" Fill="Black" StrokeThickness="0.8" Stretch="Uniform" 
       Data="M0,0 20,20" /> 
</Viewbox> 
Các vấn đề liên quan