c# - WPF:如何將GeneralTransform應用於Geometry數據並返回新的幾何?



.net (6)

不幸的是,我不認為有一種方法或財產去做你所要求的。 至少,我找不到一個。 (好問題!)

看起來你必須手動完成它(就像你自己所建議的那樣)...就是你的PathGeometry中的每個點調用Point Transform.Transform(Point p) ...在這個過程中創建一個新的PathGeometry。

可能不是你想要的答案。 (Rueful Grin)

有一些幾何數據和一個變換如何將變換應用到幾何來獲得一個新的幾何與它的數據轉換?

例如:我有一個將Path.Data設置為PathGeometry對象的Path對象,我想通過轉換來轉換PathGeometry對象的點 ,而不是將轉換應用於將在渲染時使用的PathGeometry 。

PS我知道,轉換類有一個方法Point Transform.Transform(Point p) ,可以用來轉換一個點,但...有沒有辦法一次轉換任意幾何?

編輯:請參閱我的重新應用當前找到的解決方案


Answer #1

你可以嘗試使用Geometry.Combine。 它在組合過程中應用了一個變換。 一個問題是,只有當你的幾何體有面積時,組合才有效,所以單行不行。

這是一個為我工作的樣本。

PathGeometry geometry = new PathGeometry();
geometry.Figures.Add(new PathFigure(new Point(10, 10), new PathSegment[] { new LineSegment(new Point(10, 20), true), new LineSegment(new Point(20, 20), true) }, true));
ScaleTransform transform = new ScaleTransform(2, 2);
PathGeometry geometryTransformed = Geometry.Combine(geometry, geometry, GeometryCombineMode.Intersect, transform);

Answer #2

我沒有使用接受的答案,因為它返回的格式與原始格式不同,所以我使用了這個:

Geometry inputGeometry = new PathGeometry();
var inputGeometryClone = inputGeometry.Clone(); // we need a clone since in order to
                                                // apply a Transform and geometry might be readonly
inputGeometryClone.Transform = new TranslateTransform(); // applying some transform to it
var result = inputGeometryClone.GetFlattenedPathGeometry();

Answer #3

這是我發現你可以做一個轉換的幾何圖形的所有數字信息:

var geometry = new PathGeometry();
geometry.Figures.Add(new PathFigure(new Point(10, 10), new PathSegment[] { new LineSegment(new Point(10, 20), true), new LineSegment(new Point(20, 20), true) }, true));
geometry.Transform = new ScaleTransform(2, 2);

var transformedGeometry = new PathGeometry ();
// this copies the transformed figures one by one into the new geometry
transformedGeometry.AddGeometry (geometry); 

Answer #4

基於Geometry.Combine的快速解決方案都不適用於由單個LineElement組成的路徑。 所以我解決了這個難題,像這樣(但我也限制在PathGeometry中):

public static class GeometryHelper
{
public static PointCollection TransformPoints(PointCollection pc, Transform t)
{
  PointCollection tp = new PointCollection(pc.Count);
  foreach (Point p in pc)
    tp.Add(t.Transform(p));
  return tp;
}
public static PathGeometry TransformedGeometry(PathGeometry g, Transform t)
{
  Matrix m = t.Value;
  double scaleX = Math.Sqrt(m.M11 * m.M11 + m.M21 * m.M21);
  double scaleY = (m.M11 * m.M22 - m.M12 * m.M21) / scaleX;
  PathGeometry ng = g.Clone();
  foreach (PathFigure f in ng.Figures)
  {
    f.StartPoint = t.Transform(f.StartPoint);
    foreach (PathSegment s in f.Segments)
    {
      if (s is LineSegment)
        (s as LineSegment).Point = t.Transform((s as LineSegment).Point);
      else if (s is PolyLineSegment)
        (s as PolyLineSegment).Points = TransformPoints((s as PolyLineSegment).Points, t);
      else if (s is BezierSegment)
      {
        (s as BezierSegment).Point1 = t.Transform((s as BezierSegment).Point1);
        (s as BezierSegment).Point2 = t.Transform((s as BezierSegment).Point2);
        (s as BezierSegment).Point3 = t.Transform((s as BezierSegment).Point3);
      }
      else if (s is PolyBezierSegment)
        (s as PolyBezierSegment).Points = TransformPoints((s as PolyBezierSegment).Points, t);
      else if (s is QuadraticBezierSegment)
      {
        (s as QuadraticBezierSegment).Point1 = t.Transform((s as QuadraticBezierSegment).Point1);
        (s as QuadraticBezierSegment).Point2 = t.Transform((s as QuadraticBezierSegment).Point2);
      }
      else if (s is PolyQuadraticBezierSegment)
        (s as PolyQuadraticBezierSegment).Points = TransformPoints((s as PolyQuadraticBezierSegment).Points, t);
      else if (s is ArcSegment)
      {
        ArcSegment a = s as ArcSegment;
        a.Point = t.Transform(a.Point);
        a.Size = new Size(a.Size.Width * scaleX, a.Size.Height * scaleY); // NEVER TRIED
      }
    }
  }
  return ng;
}
}

Answer #5

我發現了一個解決方案,可以將任意變換應用到路徑幾何上,這要歸功於Todd White的答案:

基本上Geometry.Combine是用來結合所需的幾何與Geometry.Empty使用聯合,並給出所需的變換。 由此產生的幾何變換與給定的變換。

PathGeometry geometryTransformed = Geometry.Combine(Geometry.Empty, geometry, GeometryCombineMode.Union, transform);




transform