2008-10-30 8 views
12

Ayant des données de géométrie et une transformation, comment la transformation peut-elle être appliquée à la géométrie pour obtenir une nouvelle géométrie avec ses données transformées?WPF: Comment appliquer une propriété GeneralTransform à une donnée géométrique et renvoyer la nouvelle géométrie?

Ex: J'ai un objet de chemin qui a son Path.Data réglé sur un objet PathGeometry, je veux Tranform points de l'objet PathGeometry en place en utilisant une transformation, et ne pas appliquer une transformation à la PathGeometry qui sera utilisé au moment du rendu.

P.S. Je sais que la classe Transform a une méthode Point Transform.Transform(Point p) qui peut être utilisée pour transformer un Point mais ... y a-t-il un moyen de transformer une géométrie arbitraire à la fois?

Edit: Voir mon repply pour le moment trouvé solution

+0

Si vous trouvez en fait une façon de le faire ... Je l'utilise aussi. Heh heh. – cplotts

Répondre

9

Vous pouvez essayer d'utiliser Geometry.Combine. Il applique une transformation pendant la moissonneuse-batteuse. Une capture est que Combine ne fonctionne que si votre géométrie a une zone, donc les lignes simples ne fonctionneront pas.

Voici un exemple qui a fonctionné pour moi.

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

Excellente idée et réponse. – cplotts

+0

Le seul problème est que la géométrie combinée n'est pas la même que la géométrie d'origine. Les différences ne sont pas grandes mais peuvent être importantes. – Goran

-1

Il y a deux choses que vous devez considérer:

  1. Géométrie hérite de Freezable, vous ne pouvez pas modifier l'objet de la géométrie en place si c'est gelé.
  2. Vous pouvez analyser la liste PathGeometry de figures et de segments et transformer tous les points en eux, mais certains types, comme ArcSegment comprend des tailles et des angles, vous ne pouvez pas les transformer.
+0

vous pouvez tout transformer, même les tailles et les angles, d'ailleurs, je sais que vous pouvez transformer des points individuellement, et aussi ma géométrie n'est pas gelée. Je voulais savoir s'il existait un moyen d'appliquer des transformations à un objet géométrique dans son ensemble. –

0

Malheureusement, je ne pense pas qu'il existe une méthode ou une propriété pour faire ce que vous demandez. Au moins, je ne peux pas en trouver un. (Grande question!)

Il semble que vous auriez à le faire manuellement (comme vous le suggérez) ... c'est appeler Point Transform.Transform (Point p) pour chaque point de votre PathGeometry ... créer une nouvelle PathGeometry dans le processus.

Probablement n'est pas la réponse que vous voulez. (Rueful Grin)

+0

Je ne sais pas pourquoi cela a été voté car il semble que la seule bonne réponse. – Goran

11

que j'ai trouvé une solution avec laquelle Tranform arbitraire peut être appliqué à une géométrie de chemin, grâce à la réponse de Todd White:

Fondamentalement Geometry.Combine est utilisé pour combiner la géométrie désirée avec la géométrie. Vide en utilisant Union, et la transformation souhaitée est donnée. La géométrie résultante est transformée avec la transformation donnée.

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

J'ai eu le même problème ET j'ai besoin de lignes (pas seulement des géométries avec zone).

Je suis seulement en utilisant PathGeometry, donc ce ne peut pas être la solution générale que vous recherchez, mais cela a fonctionné pour moi:

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

Obtenez-vous réellement la géométrie transformée? L'application CreateFromGeometry sur un PathGeometry renvoie la même géométrie (mêmes points). Vous ne transformez pas la géométrie mais ajoutez simplement la propriété transform. – Goran

1

Je ne pas utiliser réponse acceptée depuis sa géométrie de retour en format différent de l'original, donc je ceci:

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

A travaillé comme un charme, merci! – Craig

5

ce que j'ai trouvé que vous pouvez faire pour obtenir une géométrie transformée avec toutes les informations de la figure intacte:

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

Aucune des solutions rapides basées sur Geometry.Combine ne fonctionne dans le cas d'un chemin d'un seul LineElement. Je résolu le problème à la dure, comme celui-ci (mais je suis aussi limité à 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; 
} 
} 
Questions connexes