代码之家  ›  专栏  ›  技术社区  ›  Pop Catalin

WPF:如何对几何数据应用常规转换并返回新几何?

  •  12
  • Pop Catalin  · 技术社区  · 16 年前

    有了一些几何数据和转换,如何将转换应用于几何,以获得一个新的几何数据转换?

    例:我有一个路径对象有它的路径。数据设置为一个路径几何对象,我想转换 要点 PathGeometry对象的 就位 使用转换,而不将转换应用于将在渲染时使用的路径几何体。

    P.S.我知道Transform类有一个方法 Point Transform.Transform(Point p) 它可以用来变换一个点,但是…有没有一种方法可以同时变换一个任意的几何图形?

    编辑: 查看我的repply以获取当前找到的 solution

    8 回复  |  直到 10 年前
        1
  •  9
  •   Todd White    16 年前

    您可以尝试使用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);
    
        2
  •  11
  •   Community rcollyer    7 年前

    我已经找到了一种解决方案,可以将任意变换应用于路径几何体,这要归功于 Todd White 答案是:

    基本上是几何学。combine用于将所需的几何学与几何学结合起来。使用union清空,并给出所需的转换。生成的几何图形将使用给定的转换进行转换。

    PathGeometry geometryTransformed = Geometry.Combine(Geometry.Empty, geometry, GeometryCombineMode.Union, transform);
    
        3
  •  6
  •   Curtis    12 年前

    这是我发现你可以做的,以得到一个转换的几何图形,所有的图形信息都是完整的:

    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); 
    
        4
  •  3
  •   Snowbear NicoRiff    13 年前

    我没有使用接受的答案,因为它返回的几何图形格式与原始的不同,所以我使用了这个:

    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();
    
        5
  •  2
  •   Pop Catalin    10 年前

    没有基于几何的快速解决方案。Combine适用于由单个LineElement构成的路径。 所以我很难解决这个问题,像这样(但我也局限于路径几何):

    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;
    }
    }
    
        6
  •  0
  •   cplotts    16 年前

    不幸的是,我认为没有方法或属性可以满足您的要求。至少,我找不到。(问得好!)

    似乎你必须手动操作(正如你自己建议的那样)。那就是呼叫 点变换。变换(点P) 对于路径几何中的每个点…在进程中创建新的PathGeometry。

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

        7
  •  0
  •   Brian J    10 年前

    我也有同样的问题,需要线条(不仅仅是面积的几何图形)。

    我只使用PathGeometry,因此这可能不是您要寻找的一般解决方案,但这对我很有用:

    pathgeometry.Transform = transform;
    PathGeometry transformed =  PathGeometry.CreateFromGeometry(pathgeometry);
    
        8
  •  -1
  •   Nir    16 年前

    有两件事你必须考虑:

    1. 几何体继承自Freezable,如果几何体对象被冻结,则不能在原地修改它。
    2. 您可以扫描图形和段的路径几何列表,并转换其中的所有点,但某些类型(如ArcSegment)包括大小和角度,您不能转换它们。