2008-10-30 10 views
12

Teniendo algunos datos de Geometría y una Transformación, ¿cómo se puede aplicar la transformación a la Geometría para obtener una nueva Geometría con sus datos transformados?WPF: ¿Cómo aplicar una GeneralTransform a los datos de Geometría y devolver la nueva geometría?

Ex: Tengo un objeto de trazado que tiene su Path.Data establecerse en un objeto PathGeometry, quiero tranform los puntos del objeto PathGeometry en su lugar usando una transformación, y no aplicar una transformación para el PathGeometry que se usará en el momento del renderizado.

P.S. Sé que la clase Transform tiene un método Point Transform.Transform(Point p) que se puede usar para transformar un punto pero ... ¿hay alguna manera de transformar una geometría arbitraria a la vez?

Editar: Ver mi repply de que actualmente se encuentran solution

+0

Si realmente encontrar una manera de hacer esto ... lo estoy usando también. Je je. – cplotts

Respuesta

9

Puede probar y usar Geometry.Combine. Aplica una transformación durante la cosechadora. Una pega es que Combine solo funciona si tu Geometry tiene área, por lo que las líneas individuales no funcionarán.

Aquí hay una muestra que funcionó para mí.

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); 
+0

Excelente idea y respuesta. – cplotts

+0

El único problema es que la geometría combinada no es la misma que la geometría original. Las diferencias no son grandes, pero podrían ser importantes. – Goran

-1

hay dos cosas que hay que considerar:

  1. Geometría hereda de Freezable, no se puede modificar el objeto de geometría en el lugar si está congelado
  2. Puede explorar la lista PathGeometry de figuras y segmentos y transformar todos los puntos en ellos, pero algunos tipos, como ArcSegment incluye tamaños y ángulos, no puede transformarlos.
+0

puede transformar cualquier cosa, incluso tamaños y ángulos, además, sé que puede transformar puntos individualmente, y también mi geometría no está congelada. Quería saber si hay una forma de marco para aplicar transformaciones a un objeto de geometría como un todo. –

0

Desafortunadamente, no creo que haya un método o propiedad para hacer lo que está pidiendo. Al menos, no puedo encontrar uno. (¡Buena pregunta!)

Parece que tendrías que hacerlo manualmente (como te propones) ... eso es llamar Point Transform.Transform (Punto p) para cada punto en tu PathGeometry ... creando una nueva PathGeometry en el proceso.

Probablemente no sea la respuesta que desea. (Rueful Grin)

+0

No estoy seguro de por qué este voto fue rechazado ya que parece ser la única respuesta correcta. – Goran

11

he encontrado una solución con la que TRANFORM arbitraria se puede aplicar a una geometría camino, gracias a Todd White 's respuesta:

Básicamente Geometry.Combine se utiliza para combinar la geometría deseada con la geometría. Vacío usando Union, y se da la transformación deseada. La geometría resultante se transforma con la transformación dada.

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

He tenido el mismo problema Y necesito líneas también (no solo las geometrías con área).

estoy usando sólo PathGeometry, por lo que este puede no ser la solución general que busca, pero esta trabajado para mí:

pathgeometry.Transform = transform; 
PathGeometry transformed = PathGeometry.CreateFromGeometry(pathgeometry); 
+1

¿De verdad obtienes la geometría transformada? La aplicación de CreateFromGeometry en PathGeometry devuelve la misma geometría (mismos puntos). No está transformando la geometría sino simplemente agregando la propiedad de transformación. – Goran

1

que no utilizaron respuesta aceptada, ya que regresaba de la geometría formato diferente de la original, por lo que utiliza esto:

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(); 
+0

¡Funcionó como un amuleto, gracias! – Craig

5

esto es lo que he encontrado que puede hacer para obtener una geometría transformada con toda la información figura intacta:

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); 
2

Ninguna de las soluciones rápidas basadas en Geometry.Combine funciona en el caso de una ruta hecha de un solo LineElement. Así que resolvió el problema de la manera difícil, como esto (pero también estoy limitado a 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; 
} 
} 
Cuestiones relacionadas