2012-11-06 35 views
6

Tôi tự hỏi liệu có ai đó đã quản lý để ghi đè hành vi mặc định của kết xuất hình dạng WPF khi áp dụng một scaletransform cho hình dạng. Hành vi mặc định biến đổi toàn bộ bản vẽ hình dạng, bao gồm các nét, nhưng tôi chỉ muốn chia tỷ lệ hình học. Khó khăn là các hình dạng của tôi nằm trong một hệ thống phân cấp trực quan với các biến đổi render được áp dụng trên các cấp độ khác nhau (giống như một đồ thị cảnh 2D nhưng một cây thị giác WPF), điều này tôi không thể thay đổi (!). Tôi đã đọc ở những nơi khác nhau mà nó có thể có thể tạo ra một hình dạng tùy chỉnh để hủy bỏ biến đổi cho biến đổi render và đặt nó vào hình học thay thế. Tại thời điểm này, tôi có một số thông tin như:Hình dạng hình học tỷ lệ WPF mà không ảnh hưởng đến nét nét

public sealed class MyPath : Shape 
{ 
    // This class has a Data property of type Geometry just like the normal Path class 

    protected override Geometry DefiningGeometry 
    { 
     get 
     { 
      Geometry data = Data; 

      if (data == null) 
      { 
       data = Geometry.Empty; 
      } 

      return data; 
     } 
    } 

    protected override void OnRender(DrawingContext drawingContext) 
    { 
     Transform tr = RenderedGeometry.Transform; 
     Geometry geomToDraw = RenderedGeometry.Clone(); 
     geomToDraw.Transform = new MatrixTransform(tr.Value * tr.Value); 
     Matrix trInv = tr.Value; trInv.Invert(); 
     drawingContext.PushTransform(new MatrixTransform(trInv)); 
     drawingContext.DrawGeometry(Brushes.Transparent, new Pen() { Brush = Brushes.Black, Thickness = 1 }, geomToDraw); 
    } 
} 

Rõ ràng là tôi khá mới với mã này và có thể hoàn toàn sai lầm. Tôi đã cố gắng để chuyển ma trận vào hình học mà không thay đổi biến đổi hình học kết quả cuối cùng, do đó tr.Value * tr.Value và trInv. Nhưng nó không hoạt động như tôi muốn. Tôi biết kỹ thuật chuyển đổi này hoạt động theo lý thuyết bởi vì tôi đã thử nó với các phép biến đổi liên tục (thử nghiệm để đặt Geometry.Transform để scale x với 4 và đẩy một biến đổi thành scale x với 0.25 làm việc tốt nhưng bản vẽ hình kết quả dường như không áp dụng stretch = fill, mà tôi dựa vào). Vì vậy, phải có một cái gì đó mà tôi đang thiếu với các biến đổi render.

Kịch bản thử nghiệm không hoạt động là thế này:

  • tôi áp dụng một render quy mô biến đổi với scaleX = 4 và scaleY = 1 trong XAML.
  • Lớp Path được xây dựng trong quy mô toàn bộ bản vẽ để nét rộng gấp 4 lần theo hướng x so với hướng y.
  • Tôi muốn MyPath chỉ co giãn hình học chứ không phải nét vẽ. < - NÀY KHÔNG LÀM VIỆC!
    • Điều gì xảy ra là: Hình học được chia tỷ lệ chính xác, các nét được chia tỷ lệ theo 4 theo hướng x và nhỏ hơn 4 theo hướng y. Chuyện gì thế? Tôi có cảm giác rằng tôi không nên làm việc chỉ với RenderedGeometry.Transform nhưng tôi nên sử dụng cái gì? Tôi cần phải kết hợp các biến đổi render và stretch = điền vào hình dạng. Phân cấp kết xuất biến đổi của tôi có thể chứa kết hợp các tỷ lệ, phép quay và bản dịch để giải pháp phải đủ chung để xử lý bất kỳ biến đổi nào, không chỉ là chia tỷ lệ trục.

Lưu ý: Tôi biết nó là xấu để tạo ra các hình học trong OnRender nhưng tôi muốn có được nó làm việc trước khi dành nhiều thời gian làm sạch nó lên.

Bằng cách này, tôi đọc bài này:

Invariant stroke thickness of Path regardless of the scale

Vấn đề như đã nêu trước là tôi phải đi làm biến đổi thành xem xét, tôi không chắc chắn làm thế nào để thích nghi rằng giải pháp cho làm việc với họ.

Trả lời

3

Nếu tôi hiểu chính xác câu hỏi bạn muốn hủy bỏ hiệu quả của phép biến đổi hiển thị trên bút chứ không phải trên hình.

Điều này có thể được thực hiện bằng cách chuyển đổi điều khiển liên quan đến mục mà bạn muốn hủy chuyển đổi bằng cách sử dụng nghịch đảo của nó để hủy hiệu ứng trên bút. (ví dụ, nếu bạn có hệ thống phân cấp P1/P2/P3/UrShape, và P1, P2, P3 tất cả đều biến đổi chúng và bạn muốn tất cả chúng không ảnh hưởng đến bút của bạn, bạn sẽ cần phải có được biến đổi của P1 tương đối đến UrShape).Sau đó, bạn có thể áp dụng lại biến đổi để chỉ hình dạng của bạn.

var brush = new SolidColorBrush(Colors.Red); 
var pen = new Pen(brush, 5); 
//Instead of the direct parent you could walk up the visual tree to the root from where you want to cancel the transform 

var rootTransform = (MatrixTransform)this.TransformToAncestor((Visual)this.Parent); 

var inverserRootTransform = (MatrixTransform)rootTransform.Inverse; 

//We cancel out the transformation from the parent 
drawingContext.PushTransform(inverserRootTransform); 

var renderGeometry = this.Geometry.Clone(); 
// We apply the parent transform to the shape only, and group it with the original transform that was present on the shape 
// we do this to honor any transformation that was set on the shape. 
renderGeometry.Transform = new TransformGroup() 
{ 
    Children = 
    { 
     rootTransform, 
     this.Geometry.Transform 
    } 
}; 

//We draw the shape, the pen size will have the correct size since we canceled out the transform from the parent 
// but the shape now has the transformation directly on it. 
drawingContext.DrawGeometry(brush, pen, renderGeometry); 
drawingContext.Pop(); 
Các vấn đề liên quan