2009-05-11 11 views
3

J'écris une fonction pour dessiner des poignées d'interface utilisateur (rotation, redimensionnement, etc.) dans ma zone cliente dans une application Windows Forms. La fonction est appelée lorsqu'un objet est sélectionné. L'appelant m'envoie un objet graphique correctement pivoté, mis à l'échelle et traduit pour tenir dans le schéma plus large (l'objet sélectionné a sa propre rotation/translation/échelle et le handle de l'interface utilisateur a une translation et une rotation relatives par rapport au objet). Maintenant, je veux que mes poignées d'interface utilisateur aient la même taille, quelle que soit l'échelle du parent (objet sélectionné). Comment éliminer/réinitialiser le facteur d'échelle dans la matrice de transformation?Réinitialiser l'échelle dans une matrice de transformation GDI +

Comment éliminer/réinitialiser le facteur d'échelle dans la matrice de transformation? Comment réinitialiser à une échelle de 1 tout en conservant les précieuses valeurs de translation et de rotation?

Répondre

1

Anti-Grain Geometry utilise une méthode de base pour déterminer la mise à l'échelle d'une transformation (implémentation trouvée dans agg_trans_affine.cpp). Il le fait en:

  1. Calcul de la rotation de la transformation
  2. Duplication la transformation et l'application de la rotation opposée
  3. Transformer deux points connus et le calcul de l'échelle à partir du résultat

traduit à C#, cela ressemble à:

Matrix transform = (Matrix)graphics.Transform.Clone(); 

PointF[] rotationPoints = new PointF[] { new PointF(0, 0), new PointF(1, 0) }; 
transform.TransformPoints(rotationPoints); 

double rotationRadians = Math.Atan2(rotationPoints[1].Y - rotationPoints[0].Y, rotationPoints[1].X - rotationPoints[0].X); 
transform.Rotate((float)(-rotationRadians * (180.0/Math.PI))); 

PointF[] scalePoints = new PointF[] { new PointF(0, 0), new PointF(1, 1) }; 
transform.TransformPoints(scalePoints); 

float xScale = scalePoints[1].X - scalePoints[0].X; 
float yScale = scalePoints[1].Y - scalePoints[0].Y; 

Le code AGG contient également un avertissement qu'il existe des cas dégénérés où cela ne fonctionnera pas correctement, mais cela peut être utile pour votre situation.

+0

Bonne idée. Mais cela semble cher. –

+0

Acceptée comme seule réponse possible. –

1

Vous devez être conscient que l'ordre des transformations est important. Par conséquent, le simple fait de supprimer l'échelle peut changer la "signification" des traductions suivantes (offset par exemple). Peut-être juste garder un enregistrement de l'échelle appliquée jusqu'à présent (appelons cela currentscale) et ajouter une échelle de 1/currentscale à vos transformations.

+0

Acceptée provisoirement. C'est ce que j'ai toujours soupçonné. N'existe-t-il pas un moyen de récupérer la composante de mise à l'échelle de la matrice de transformation? J'ai essayé mais cela affecte la rotation. –

+0

Non, pas que je sache, du moins pas de manière générique. Si seulement une échelle était effectuée, cela devrait être facile, mais si la matrice effectue des opérations plus complexes, les choses ne sont plus aussi faciles. – Lucero