Aller au contenu

de WCS vers SCU


bathepn

Messages recommandés

Bonjour

 

Je suis en train de programmer en .net pour autocad. J'ai un problème avec les SCU.

En effet j'ai besoin de placer du texte. Ce texte doit s'afficher horizontalement et au bon endroit.

 

Je calcul les coordonnées du texte en fonction de coordonnées d'une polyligne sauf qu'avec le SCU le NORD n'est pas au bon endroit ect. Quand je calcul mes coordonnées pour le point de départ de mon texte, il n'est alors pas au bon endroit et complètement décalé et retourné.

 

J'ai cherché sur le net et j'ai trouvé comment passé des coordonnées du SCU vers WCS mais jamais l'inverse or c'est ce dont j'ai besoin.

 

Merci d'avance pour vos réponses

Bathepn

Lien vers le commentaire
Partager sur d’autres sites

je suppose que ça n'a rien a voir avec l'autolisp et que TRANS ne peu rien pour toi?

mais ce serai incongru qu'il n'y ai pas d'équivalent dans l'API .net d'autocad...

 

à tout hasard j'ai tapé "TRANS .net autocad" dans google

 

je tombe la dessus

http://spiderinnet1....anetoworld.html

Lien vers le commentaire
Partager sur d’autres sites

Merci pour la réponse :)

 

En effet je ne fais rien au AutoLisp.

 

J'ai regardé le lien et il donne une transformation vers un plan en utilisant un point d'origine et un seul vecteur. Or les SCU en utilise 3.

 

voici ce que j'avais trouvé pour passé de SCU à WCS, je pense que l'inverse doit ressembler mais le calcul matriciel n'est pas commutatif ce qui rend la chose plus compliqué.

 

http://docs.autodesk.com/ACD/2013/ENU/index.html?url=files/GUID-096085E3-5AD5-4454-BF10-C9177FDB5979.htm,topicNumber=d30e730706

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Comme il t'a été répondu sur TheSwamp, la propriété Editor.CurrentCoordinateSytem retourne la matrice 3d correspondant à la transformation du SCU courant vers le SCG.

La méthode Matrix3d.Inverse() retourne la matrice inverse, donc Editor.CurrentCoordinateSytem.Inverse() retourne la matrice 3d correspondant à la transformation du SCG vers le SCU courant.

 

Si ceci ne fonctionne pas pour toi, c'est que ton problème n'est pas un problème de conversion entre le SCG et le SCU courant.

 

Je rappelle que l'API .NET d'AutoCAD utilise toujours le SCG sauf avec l'éditeur (appels de commande et retours de PromptResult).

en d'autres termes, si tu n'obtiens pas tes points avec Editor.GetPoint() et si tu ne les utilises pas dans une commande avec SendStringToExecute(), SendCommand() ou Command(), tu n'as pas à te préoccuper du SCU courant.

 

Peut-être devrais-tu préciser le contexte dans lequel tu obtiens et utilises ces points.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Je récupère les points d'une Polyligne comme ceci :

 

public static List<List<System.Drawing.PointF>> SelectionnerPolyligne(string question, double echelle)
       {
           if (transaction == null)
           {
               throw new ExceptionTransactionAutocadInvalide("Transaction non crée");
           }
           PromptSelectionResult selectionResult = editor.SelectImplied();
           List<ObjectId> listeId = new List<ObjectId>();

           if (selectionResult.Status == PromptStatus.Error)
           {
               PromptEntityResult per = editor.GetEntity("\n" + question);
               if (per.Status != PromptStatus.OK)
               {
                   return null;
               }
               listeId.Add(per.ObjectId);
           }
           else
           {
               editor.SetImpliedSelection(new ObjectId[0]);
               ObjectId[] objIds = selectionResult.Value.GetObjectIds();
               for (int i = 0; i < objIds.Length; i++) listeId.Add(objIds[i]);
           }
           var listeResultat = new List<List<System.Drawing.PointF>>();
           foreach (ObjectId id in listeId)
           {
               try
               {
                   listeResultat.Add(GetPolyligne(id, echelle));
               }
               catch (ExceptionMauvaisObjet ex)
               {
                   MonAutocad.EcrireDansLaConsole("Un objet détecté n'était pas une polyligne");
               }
           }
           MonAutocad.EcrireDansLaConsole(listeResultat.Count + " polyligne" + ((listeResultat.Count > 1) ? "s" : "") + " trouvée" + ((listeResultat.Count > 1) ? "s" : "") + ".");
           return listeResultat;
       }

 

puis je calcul le centre de la Polyligne pour écriredu texte centré comme ceci :


private System.Drawing.PointF centre(List<System.Drawing.PointF> liste, string texte = "", double echelle = 1)
       {
           float nord = liste[0].Y;
           float sud = liste[0].Y;
           float est = liste[0].X;
           float ouest = liste[0].X;

           foreach (var point in liste)
           {
               if (point.Y < sud) sud = point.Y;
               if (point.Y > nord) nord = point.Y;
               if (point.X > est) est = point.X;
               if (point.X < ouest) ouest = point.X;
           }
           var pt = new System.Drawing.PointF((est + ouest) / 2 - (float)(texte.Length * CONSTANTES.VUE.LARGEUR_LETTRE * echelle / 2), nord - (nord - sud) / 2);
           return pt; 
       }

 

et enfin je place mon texte comme ceci :

private static ObjectId ajouterObjet(Entity entity)
       {
           if (transaction == null)
           {
               throw new ExceptionTransactionAutocadInvalide("Transaction non crée");
           }
           ObjectId id = blockTableRecord.AppendEntity(entity);
           ajouterObjetALaTransaction(entity);
           return id;
       }

public static ObjectId AjouterTexte(System.Drawing.PointF origine, string contenu, double echelle, System.Drawing.Color couleur, Hauteur hauteur = Hauteur.NORMAL)
       {
           bool creationDuGroupe = !existeUnGroupeCree();
           if (creationDuGroupe)
           {
               blockTableRecord = (BlockTableRecord)transaction.GetObject(blockTable[blockTableRecord.ModelSpace], OpenMode.ForWrite);
           }
           MText texte = new MText();
           texte.Contents = contenu;



           texte.Location = new Point3d(origine.X / echelle, origine.Y / echelle, 0);
           texte.Color = Color.FromColor(couleur);
           ObjectId id = ajouterObjet(texte);
           texte.TextHeight *= (int)hauteur;
           if (creationDuGroupe)
           {
               blockTableRecord = null;
           }
           return id;
       }


 

 

 

Le problème est que le texte s'affiche bien dans le SCU nomé "Général" il s'affiche au centre et bien alligné. mais dans les autre SCU il s'afiche penché et plus au centre car pour calculer le centre il prend les coordonnées WCS et non SCU et du coup j'ajoute mon texte aussi avec des coordonnée WCS, il faudrait donc une fonction qui converti de WCS à SCU et une qui fait l'opposé. Concernant l'inverse j'ai essayé ceci :

 

Matrix3d ucs = Application.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem;
           CoordinateSystem3d cs = ucs.CoordinateSystem3d;

           Matrix3d newMatrix2 = Matrix3d.AlignCoordinateSystem(Point3d.Origin,
                                                      Vector3d.XAxis,
                                                      Vector3d.YAxis,
                                                      Vector3d.ZAxis,
                                                      cs.Origin,
                                                      cs.Xaxis,
                                                      cs.Yaxis,
                                                      cs.Zaxis

                                                     );

 

Après je crée un point 3d avec les coordonnée WCS et j'ai essayer de faire TransformBy avec ma matrice et toutes les possibilité plus haut et rien n'a marché.

Lien vers le commentaire
Partager sur d’autres sites

Sans aller plus loin, pourquoi utilises-tu des objets de type : System.Drawing.PointF ?

Et comment les définis-tu ? (on ne voit pas la fonction GetPolyligne(id, echelle)).

 

L'espace de nom Autodesk.AutoCAD.Geometry fournit, entre autres, la structure Point3d qui est prévue pour fonctionner avec d'autres structures du même espace de nom (Vector3d, Matrix3d) et avec les entités et système de coordonnées AutoCAD.

 

La classe Polyline fournit les méthodes NumberOfVertices() et GetPoint3dAt() qui permettent de récupérer facilement les sommets de la polyligne directement sous la forme d'instances de Point3d (sans tenir compte du SCU courant). Tu peux ensuite calculer ton centre et le passer directement à la propriété Location du MText.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Sans aller plus loin, pourquoi utilises-tu des objets de type : System.Drawing.PointF ?

Je passe par des objet Tampon générique afin que ma classe de gestion d'autocad soit complètement indépendante du reste de l'application.

 

Et comment les définis-tu ? (on ne voit pas la fonction GetPolyligne(id, echelle)).

En effet j'ai oublié une fonction.

public static List<System.Drawing.PointF> GetPolyligne(ObjectId id, double echelle)
       {
           if (transaction == null)
           {
               throw new ExceptionTransactionAutocadInvalide("Transaction non crée");
           }
           Matrix3d xform = Matrix3d.Scaling(echelle, Point3d.Origin);
           List<System.Drawing.PointF> listeDePoints = new List<System.Drawing.PointF>();
           try
           {
               var sol = transaction.GetObject(id, OpenMode.ForRead) as Autodesk.AutoCAD.DatabaseServices.Polyline;
               for (int i = 0; true; i++)
               {
                   try
                   {
                       Point3d tmp = sol.GetPoint3dAt(i).TransformBy(xform);
                       listeDePoints.Add(new System.Drawing.PointF((float)tmp.X, (float)tmp.Y));
                   }
                   catch (System.Exception ex) { break; }
               }
               if (sol.Closed)
               {
                   listeDePoints.Add(new System.Drawing.PointF(listeDePoints[0].X, listeDePoints[0].Y));
               }
           }
           catch (System.Exception ex)
           {
               throw new ExceptionMauvaisObjet("Ce n'est pas une polyligne");
           }
           if (listeDePoints.Count == 0)
           {
               throw new ExceptionMauvaisObjet("Ce n'est pas une polyligne");
           }
           return listeDePoints;
       }

 

Pour les exception ce sont des exceptions maisons qui héritent de la classe Exception :)

 

La classe Polyline fournit les méthodes NumberOfVertices()

En effet je ne savais pas je ferais la modification dans ma fonction :)

 

et GetPoint3dAt() qui permettent de récupérer facilement les sommets de la polyligne directement sous la forme d'instances de Point3d (sans tenir compte du SCU courant). Tu peux ensuite calculer ton centre et le passer directement à la propriété Location du MText.

 

C'est ce que je fais sauf que le texte n'est pas affiché comme il faut.

Quand je calcul mon centre c'est avec le repère WCS donc le nord calculé est peutêtre l'est en vrai dnas le scu courant donc la position de mon point est pas bonne.

Deplus le texte est horizontal dans le SCU Général donc quand on passe dans un autre ou dnas le Courant il ne l'est plus.

 

J'ai bien essayé un

texte.rotation = 0; 

mais le point de rotation es en haut à gauche du texte et non au centre donc ça tourne pas bien.

Lien vers le commentaire
Partager sur d’autres sites

Je passe par des objet Tampon générique afin que ma classe de gestion d'autocad soit complètement indépendante du reste de l'application.

Je ne suis pas sûr du tout de l'intérêt de cette façon de faire, c'est très certainement inefficient du point de vue des performances et ça n'apporte rien, à mon avis, en terme de lisibilité ou de maintenabilité du code surtout que tu y utilises déjà les bibliothèques d'AutoCAD...

De plus, je pense que si tu as un problème de positionnement du texte, c'est à cause de ça.

 

Il me semble que tu as tendance à compliquer inutilement des choses simples.

 

Si j'ai bien compris, tu souhaites placer le mtexte au centre de l'emprise de la polyligne et que ce texte soit toujours parallèle à l'axe X du SCU courant.

 

Pour le placement du texte, la propriété GeometricExtents de toutes les entités retourne un objet Extents3d qui contient les points inférieur gauche (MinPoint) et supérieur droit (MaxPoint) de la "boite englobante" de l'entité.

Ces points sont définis dans le SCG (WCS) leur moyenne correspond donc au centre de l'emprise de la polyligne (toujours dans le SCG/WCS).

La propriété Location du mtexte est toujours définie dans le SCG. Elle sera donc toujours la même quel que soit le SCU courant.

Concernant l'orientation maintenant, si tu veux que le texte soit toujours parallèle à l'axe X du SCU courant, il suffit de lui faire subir une rotation autour de son point d'insertion d'un angle correspondant à l'angle entre l'axe X du SCG et l'axe X du SCU.

 

Un exemple de commande qui illustre cet algorithme :

 

        [CommandMethod("CMD1")]
       public void Cmd1()
       {
           Document doc = Application.DocumentManager.MdiActiveDocument;
           Database db = doc.Database;
           Editor ed = doc.Editor;

           // sélectionner une polyligne
           PromptEntityOptions peo = new PromptEntityOptions("\nSélectionnez une polyligne: ");
           peo.SetRejectMessage("Objet non valide.");
           peo.AddAllowedClass(typeof(Polyline), true);
           PromptEntityResult per = ed.GetEntity(peo);
           if (per.Status != PromptStatus.OK) return;

           using (Transaction tr = db.TransactionManager.StartTransaction())
           {
               // ouvrir la polyligne
               Polyline pline = (Polyline)tr.GetObject(per.ObjectId, OpenMode.ForRead);

               // calculer le centre de l'emprise de la polyligne
               Extents3d extents = pline.GeometricExtents;
               Point3d center = extents.MinPoint + (extents.MaxPoint - extents.MinPoint) / 2.0;

               // ajouter le texte multiligne au centre de la polyligne
               using (MText mtext = new MText())
               {
                   mtext.SetDatabaseDefaults();
                   mtext.Location = center;
                   mtext.Contents = "Ceci est un test";
                   BlockTableRecord curSpace =
                       (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                   curSpace.AppendEntity(mtext);
                   tr.AddNewlyCreatedDBObject(mtext, true);

                   // appliquer une rotation au texte
                   Vector3d xdir = (Point3d)Application.GetSystemVariable("UCSXDIR") - Point3d.Origin;
                   double ucsRotation = Vector3d.XAxis.GetAngleTo(xdir, Vector3d.ZAxis);
                   mtext.TransformBy(Matrix3d.Rotation(ucsRotation, Vector3d.ZAxis, center));
               }
               tr.Commit();
           }
       }

 

 

On peut aussi utiliser la matrice de transformation du SCU courant et son inverse (ce n'est pas forcément plus facile à comprendre quand on n'a pas une certaine habitude des matrices et des systèmes de coordonnées).

Vu ce qui a été dit plus haut, le "centre de la polyligne" est calculé dans le SCG, il va donc falloir le convertir dans le SCU courant avant de l'utiliser comme point d'insertion du mtexte de façon à ce que la transformation de l'objet mtexte du SCU vers le SCG replace celui-ci au centre de la polyligne tout en lui affectant l'orientation du SCU.

 

        [CommandMethod("CMD2")]
       public void Cmd2()
       {
           Document doc = Application.DocumentManager.MdiActiveDocument;
           Database db = doc.Database;
           Editor ed = doc.Editor;

           // sélectionner une polyligne
           PromptEntityOptions peo = new PromptEntityOptions("\nSélectionnez une polyligne: ");
           peo.SetRejectMessage("Objet non valide.");
           peo.AddAllowedClass(typeof(Polyline), true);
           PromptEntityResult per = ed.GetEntity(peo);
           if (per.Status != PromptStatus.OK) return;

           Matrix3d UCS2WCS = ed.CurrentUserCoordinateSystem;
           Matrix3d WCS2UCS = UCS2WCS.Inverse();

           using (Transaction tr = db.TransactionManager.StartTransaction())
           {
               // ouvrir la polyligne
               Polyline pline = (Polyline)tr.GetObject(per.ObjectId, OpenMode.ForRead);

               // calculer le centre de l'emprise de la polyligne
               Extents3d extents = pline.GeometricExtents;
               Point3d center = extents.MinPoint + (extents.MaxPoint - extents.MinPoint) / 2.0;

               // convertir les coordonnées du point en coordonnées SCU
               center = center.TransformBy(WCS2UCS);

               // ajouter le texte multiligne
               using (MText mtext = new MText())
               {
                   mtext.Location = center;
                   mtext.Contents = "Ceci est un test";
                   BlockTableRecord curSpace = 
                       (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                   curSpace.AppendEntity(mtext);
                   tr.AddNewlyCreatedDBObject(mtext, true);

                   // appliquer au mtexte une transformation du SCU vers le SCG
                   mtext.TransformBy(UCS2WCS);
               }
               tr.Commit();
           }
       }

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !

Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant
×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer. Politique de confidentialité