Modifier les points de FreeShape

Une interface graphique permet à un utilisateur de dessiner GraphicsPath sur mesure. Je l’ai créé à l’aide de la fonction GraphicsPath AddLine.

Maintenant, je veux implémenter ce que vous pouvez voir dans l’image Microsoft Word jointe – “Modifier les points”.

entrez la description de l'image ici

Je suis confronté à plusieurs problèmes:

  1. Mon chemin contient des centaines de “Lignes” -> chacune n’a qu’une taille de pixel. Je veux sélectionner uniquement les “points clés”. Comment je fais ça? C’est une sorte d’inversion de “Flatten”, impossible de trouver une telle fonction.

  2. Existe-t-il une fonction .Net existante pour dessiner les petits rectangles bleus et le petit cercle vert autour du tracé? et que dire des rectangles autour de chaque point sélectionné? entrez la description de l'image ici

Chaque aide, même partielle, serait appréciée.

Pour la première partie de votre question, jetez un coup d’œil à cet article , qui a une fonction de réduction pour une List . Notez que la collection GraphicsPath.PathPoints est en lecture seule. Vous devez donc recréer le chemin à partir de la liste de points réduits.

Quelques remarques sur la deuxième partie:

  • Il n’y a pas de routine intégrée pour créer les poignées. Ni pour leur faire faire quoi que ce soit. Donc, vous devez coder pour eux.

  • MoveLabel une simple classe MoveLabel qui peut être utilisée pour cela. Il peut être placé sur un contrôle ou ajouté à sa collection de Controls . Ensuite, vous pouvez le déplacer. J’ai ajouté une fonction de rappel MoveAction pour traiter le résultat lorsque la souris est relâchée.

Vous pouvez soit append un ..

 public delegate void Moved(MoveLabel sender); 

..pour la classe de formulaire ou, pour éviter la référence à Form1 , en dehors de la classe de formulaire mais dans l’étendue de MoveLabel .

Il peut être utilisé directement pour déplacer des points dans la liste de points:

Créez-le sur un panneau:

 var lab= new MoveLabel(Color.CadetBlue, 9, Point.Round(points[i]), i); lab.Parent = panel; lab.MoveAction = moved; 

Une fonction de traitement simple:

 void moved(MoveLabel sender) { points[sender.PointIndex] = new Point(sender.Left - sender.Width / 2, sender.Top - sender.Height / 2); panel.Invalidate(); } 

Notez que les GraphicsPath.PathPoints sont en lecture seule, nous devons donc recréer le chemin à partir de la nouvelle liste de points! En réalité, on peut modifier des PathPoints individuels dans le code, mais le résultat ne colle pas; il faut donc copier les PathPoints dans un PointF[] , les modifier et recréer le chemin. Pour les chemins complexes, utilisez au mieux cette surcharge .

Si vous souhaitez implémenter une rotation (ou d’autres transformations), vous pouvez utiliser la fonction GraphicsPath.Transform . Vous pouvez utiliser des étiquettes mobiles pour déterminer la rotation ou la mise à l’échelle des données. Voici ma classe minimale MoveLabel :

 public class MoveLabel : Label { public Form1.Moved MoveAction { get; set; } public int PointIndex { get; set; } private Point mDown = Point.Empty; public MoveLabel() { MouseDown += (ss, ee) => { mDown = ee.Location; }; MouseMove += (ss, ee) => { if (ee.Button.HasFlag(MouseButtons.Left)) { Location = new Point(Left + ee.X - Width / 2, Top + ee.Y - Height / 2); mDown = Location; } }; MouseUp += (ss, ee) => { if (MoveAction != null) MoveAction(this); }; } public MoveLabel(Color c, int size, Point location, int pointIndex) : this() { BackColor = Color.CadetBlue; Size = new Size(size, size); Location = location; PointIndex = pointIndex; } } 

Cela fonctionnera également très bien pour déplacer des points de courbes de Bézier. En ajoutant un appel à MoveAction(this); dans le code MouseMove vous pouvez obtenir des mises à jour en direct .. Assurez-vous que les Panels sont à double tampon pour cela 🙂

Exemple:

entrez la description de l'image ici


Btw: Je viens de découvrir ce billet qui montre à quel point la courbe ou tout autre dessin vectoriel GDI + peut être facilement enregistré au emf , tout en préservant la qualité vectorielle!