Aller au contenu

[Résolu] SCU Objet


didier

Messages recommandés

Bonjour à Toutes et à Tous

En parallèle de mon apprentissage des bases du langage en application Console, ce qui explique mon absence partielle du site, je continue de faire des essais avec C# pour AutoCAD. Je refais des routines écrites en lisp et je suis dans un cas où je passe temporairement en SCU Objet

En fait c'est une entité TEXTE et j'ai besoin de connaître sa longueur, pas le nombre de caractères je parle de la distance entre le point d'insertion et la fin de la chaîne de caractère dessinée

Ma question est :

Comment mettre en SCU courant (sans le nommer pour autant) en choisissant une entité ?

Amicalement

Lien vers le commentaire
Partager sur d’autres sites

Salut Didier,

 

Alors j'y connais rien en C# mais en commande ça donne :

 

SCU -> choisir une face d'objet (3D) ou deux points ->donc F ou juste deux clics

_plan -> pour se mettre suivant le SCU courant -> C pour le courant.

 

Je sais pas sir ça peux aider mais sais t'on jamais.

"98% des soucis informatiques sont assis entre la chaise et le bureau !"

 

"C'est parce que la vitesse de la lumière est supérieure à celle du son que tant de gens paraissent brillants avant d'avoir l'air con."
Lien vers le commentaire
Partager sur d’autres sites

Coucou

 

Je te remercie d'avoir répondu mais en l’occurrence il se trouve qu'en ligne de commande je n'ai aucun souci, j'ai la faiblesse de le croire du moins !

Je cherche à trouver le moyen de faire un SCU dépendant d'un objet, comme en ligne de commande, mais en C#

Ensuite je pourrai faire toutes les transformations de coordonnées qui vont bien.

Lien vers le commentaire
Partager sur d’autres sites

Salut didier,

 

Comment le faisais-tu en LISP ? En appelant la commande SCU (_UCS) ou en construisant une matrice de transformation ?

 

Et bien c'est pareil en .NET...

 

En programmation, il est parfois plus simple de ne pas chercher à reproduire ce qu'on fait en ligne de commande à moins de l'utiliser (faire du script quoi).

Personnellement je n'ai plus jamais cherché à modifier le SCU du dessin depuis belle lurette parce que dès qu'on met le nez dans les matrices, autant les utiliser directement sur les objets.

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

Lien vers le commentaire
Partager sur d’autres sites

Re,

 

Reconstruire la matrice de transformation correspondant au SCU Objet est "relativement" facile pour un objet DBText qui a des propriétés Position, Rotation et Normal. Il en sera de même pour une référence de bloc par exemple, mais ça sera un petit peu plus compliqué pour une polyligne par exemple.

La classe Matrix3d fournit de nombreuses méthodes qui facilitent cette tâche (en AutoLISP, à part trans, il n'y a aucune fonction native pour construire, combiner et appliquer des matrices de transformation).

 

Exemple pour un texte :

        public void ScuTexte()
       {
           Document doc = Application.DocumentManager.MdiActiveDocument;
           Database db = doc.Database;
           Editor ed = doc.Editor;

           var entOpts = new PromptEntityOptions("\nChoix d'un texte correspondant au SCU: ");
           entOpts.SetRejectMessage("\nL'objet séléctionné n'est pas un texte.");
           entOpts.AddAllowedClass(typeof(DBText), true);
           var entRes = ed.GetEntity(entOpts);
           if (entRes.Status != PromptStatus.OK)
               return;

           using (Transaction tr = db.TransactionManager.StartTransaction())
           {
               var text = (DBText)tr.GetObject(entRes.ObjectId, OpenMode.ForWrite);
               var plane = new Plane(Point3d.Origin, text.Normal);

               ed.CurrentUserCoordinateSystem =
                   Matrix3d.Rotation(text.Rotation, text.Normal, text.Position) *
                   Matrix3d.Displacement(text.Position.GetAsVector()) *
                   Matrix3d.PlaneToWorld(plane);

               tr.Commit();
           }
       }

 

Mais comme je disais ci-dessus, je ne comprends l'intérêt de définir et rendre courant un SCU par programmation si ce n'est pour l'utiliser dans des appels de commande.

 

Depuis la version 2015, la classe Editor fournit une méthode Command() efficiente qui prend comme argument des objets typés (string, int, double, Point3d, ObjectId, SelectionSet, ...) un peu comme la fonction LISP command.

Donc quitte à appeler des commandes, on peut aussi appeler la commande native _UCS avec l'option OBject et lui passer l'ObjectId d'une entité sélectionnée (qui n'a plus besoin d'être un texte).

        [CommandMethod("CMD2")]
       public void ScuObjet()
       {
           var ed = Application.DocumentManager.MdiActiveDocument.Editor;

           var entRes = ed.GetEntity("\nChoix d'un objet correspondant au SCU: ");
           if (entRes.Status != PromptStatus.OK)
               return;

           try { ed.Command("_ucs", "_object", entRes.ObjectId); }
           catch { }
       }

 

On pourrait même encore simplifier le code en utilisant CommandAsync() et une pause pour l'utilisateur, mais dans ce cas, on n'a plus d'identifiant pour l'objet sélectionné.

        [CommandMethod("CMD3")]
       public async void ScuObjetAsync()
       {
           var ed = Application.DocumentManager.MdiActiveDocument.Editor;

           try { await ed.CommandAsync("_ucs", "_object", Editor.PauseToken); }
           catch { }
       }

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

Lien vers le commentaire
Partager sur d’autres sites

Coucou

 

Pardon pour le retard de la réponse, ce n'est pas un manque d'intérêt mais j'ai une femme, j'ai un jardin et la première veut me faire travailler dans le deuxième, tu vois le dilemme ? je blague mais il y a pire comme torture car j'aime les deux.

 

Depuis hier soir (et cette nuit) je relis ta littérature que tu as déposé sur divers sites au sujet des matrices

Je ne suis pas familier de ce sujet mais il semble que si je veux progresser je dois en passer par là.

En effet en lisp quand je devais changer de SCU je passais (par fainéantise) par Command

Ce genre de "programmation" tient du script je le reconnais et n'en tire pas de fierté (plutôt l'inverse)

 

Je cherche à faire un encadrement d'une entité texte (pas MTEXT), je suis toujours dans le simple et l'efficace pour apprentissage).

 

Ce qui me tracasse dans le cas présent, c'est que je dois extraire des coordonnées depuis un objectid et les coordonnées que j'obtiens sont dans le SCU général, du moins j'ai le point d'insertion (pour l'instant je ne gère que le bas gauche),j'ai aussi l'angle de rotation par rapport à l'axe des X (les radians ne me tracassent pas)

 

Si je veux savoir combien elle mesure (l'entité texte), je dois pouvoir utiliser les coordonnées de la boite englobante

cette boite est définie par ses angles que j'extrais de Bound.Value mais cette boîte définit l'encombrement maximum dans le scu général parallèlement à l'axe des X et ses coordonnées ne me sont utiles (pour la longueur) que si le texte est parallèle à l'axe des X ce qui n'est pas le cas de mon texte.

Une fois que j'ai cette longueur j'aurai tout ce dont j'ai besoin pour appliquer les formules de trigonométrie qui me donneront les angles qui dessineront la ligne rouge de l'image

 

Ne me donne pas la solution s'il te plaît, je DOIS trouver, tu m'as déjà guidé, toutefois si je ne trouve toujours pas je reviendrai te questionner

 

Dis-moi simplement (oui ou non) si je peux m'en sortir en "jouant" avec les matrices

 

Merci de ta disponibilité

Lien vers le commentaire
Partager sur d’autres sites

Re,

 

S'il s'agit simplement de trouver la largeur d'un texte, tu peux utiliser la méthode :

Autodesk.AutoCAD.Internal.Utils.GetTextExtents()

qui prend comme arguments l'objectId d'un style de texte, uns chaîne de caractère et une hauteur donc aucun argument qui ne dépende de la position, de la rotation ou du plan dans lequel est inséré le texte.

Cette méthode est un peu l'équivalent de la fonction LISP textbox.

 

Avec un objet DBText (text) :

Point2d textExtents = Autodesk.AutoCAD.Internal.Utils.GetTextExtents(text.TextStyleId, text.TextString, text.Height);
double width = textExtents.X * text.WidthFactor;

  • Upvote 1

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

Lien vers le commentaire
Partager sur d’autres sites

Re,

 

Sans livrer plus de code que je ne l'ai déjà fait.

Si tu veux utiliser la boite englobante, objet de type Extents3d qu'on obtient avec la propriété Bounds ou, plus simplement, avec GeometricExtents, il faut comprendre que cet objet est toujours calculé par rapport au SCG.

 

Une astuce serait donc de :

  • "transformer" le texte pour le remettre dans le SCG avec TransformBy() et la matrice inverse de celle calculée dans la réponse #5 ;
  • récupérer la boite englobante du texte dans le SCG avec sa propriété GeometricExtents du texte ;
  • utiliser cet objet Extents3d pour créer le cadre ;
  • "transformer" le texte et le cadre avec la matrice (sans l'inverser cette fois) pour restaurer sa position initiale au texte et faire suive le cadre.

 

C'est la méthode utilisée dans le LISP bbox sur cette page.

 

PS : Bon jardinage, et profite de la lumière du jour...

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

Lien vers le commentaire
Partager sur d’autres sites

Coucou

 

Bon !, deux nouvelles, une bonne et une bonne,

  1. Un copain m'a prêté un scarificateur et je vais pouvoir enlever la mousse de la pelouse sans trop d'efforts
  2. J'ai travaillé cette nuit sur ma routine d'encadrement des textes en C# et ... j'y suis arrivé

J'y suis arrivé grâce à (gile) encore une fois, pas à cause des matrices que je vais regarder plus tard, promis ! mais parce qu'il m'a initié à une "propriété" une "option" je ne connais pas le nom exact, je parle de textExtents, avec ça je connais la longueur du texte le reste n'est que trigonométrie de base.

Ça donne ça :

16-10-16 18-04-13.png

 

Je vais y apporter quelques modifications pour l'améliorer mais la version de base est pliée.

Je continue mon apprentissage ...

 

Amicalement

Lien vers le commentaire
Partager sur d’autres sites

Coucou

 

J'ai oublié de demander :

 

Où est-il possible d'avoir une liste des différentes possibilités comme cette fameuse :

Autodesk.AutoCAD.Internal.Utils.GetTextExtents(text.TextStyleId, text.TextString, text.Height);

 

Ça sort d'où ?

J'ai cherché dans l'aide que j'ai et j'ai pas trouvé

D'ailleurs l'aide AutoCAD pour C# c'est où ?

 

Merci

 

 

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

D'abord, bravo. Je suis content que tu aies réussi.

L'avantage de l'utilisation des matrices (telles que celle dans l'exemple de création de SCU objet) c'est de pouvoir gérer, en plus de la rotation sur l'axe Z, les entités sur des plans différents du plan XY.

 

D'ailleurs l'aide AutoCAD pour C# c'est où ?

Là tu mets le doigt là où ça fait mal...

L'aide la plus "exhaustive" concernant les classes de l'API AutoCAD .NET (avec leurs méthodes, propriétés et évènements) se trouve dans ObjectARX 2015\docs\arxmgd.chm, mais comme parfois la description, plus que laconique, se limite à quelque chose du genre : "This .NET method wraps the xxxx ObjectARX method." il ne faut pas hésiter à aller aussi voir dans arxref.chm.

 

Mais certaines classes ne sont pas dans dans cette documentation comme par exemple toutes celles de l'espace de nom Autodesk.AutoCAD.Internal (a priori réservé à une usage interne, mais finalement exposé aux développeurs). Dans ce cas, on peut utiliser l'explorateur d'objets de Visual Studio (Ctrl+Alt+J) pour inspecter le contenu des DLLs AutoCAD.

Par exemple, dans AcMgd.dll on trouvera l'espace de nom Autodesk.AutoCAD.Internal et sa classe Utils qui contient nombre de méthodes effectivement utiles. Mais là, pas de description, il faut déduire ce que fait la méthode ou la propriété d'après son nom et ses arguments (avoir fait du LISP aide), puis faire des tests...

 

Personnellement j'utilise aussi beaucoup la touche F12 après avoir sélectionné un nom de classe, de méthode ou de propriété dans Visual Studio ce qui permet d'atteindre sa définition.

 

Il y a aussi, pour AutoCAD 2015 et plus des fichiers XML à télécharger sur cette page, dans la section Managed .NET (à la fin, juste avant la section ActiveX API), et à coller dans le dossier ObjectARX 201X\inc pour avoir quelques commentaires dans la définition de la classe (F12) et avec l'intellisense quand on laisse le curseur sur une classe, méthode ou propriété AutoCAD.

 

Sans oublier l'incontournable Managed .NET Developer's Guide.

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

Lien vers le commentaire
Partager sur d’autres sites

Coucou

 

Merci des ces indications

Je me sens effectivement un peu perdu dans ce nouveau langage sans aide aussi précise que le lisp mais si je me souviens bien à mes débuts l'aide ne me semblait pas aussi efficace que maintenant où elle sert plus d'aide-mémoire, avec le C# ça devrait faire pareil dans quelques temps j'en rirai.

J'ai le temps comme allié, je ne fais pas ça comme gagne-pain et ça fait la différence, ce qui n'est pas solutionné aujourd'hui le sera demain ou après-demain.

 

Les améliorations que je prévois sont :

Gérer le contenu du texte à encadrer car il faut tenir compte de la présence de j p y q g en minuscules à cause de leurs jambages inférieurs qui ne sont pas pris en compte dans la hauteur du texte (qui me sert à définir le côté de mon encadrement), idem s'il n'y a pas de majuscules et pas de lettres avec jambages supérieurs, m n x ... il faudra réduire la hauteur d'autant.

17-10-16 11-15-45.png

Je vais me débrouiller tout seul ce n'est pas une demande de solution, merci

 

 

Un grand merci encore pour ta disponibilité, cher Gilles.

 

Amicalement

Lien vers le commentaire
Partager sur d’autres sites

Coucou

 

Je ferai sans doute appel à tes services.

Pour l'instant j'ai fait un truc "qui fonctionne" avec ce que j'ai compris et je vais le peaufiner pour gérer les cas particuliers dont j'ai parlé (jambages inférieurs)car le détail fait la perfection.

 

Je regarderai les matrices tout seul dans mon coin et viendrai comparer nos solutions et certainement je vais rougir devant la tienne parce que Toi aussi tu n'as pas la réputation de négliger les détails.

 

Je persiste mais je ne signe pas encore.

 

Amicalement

Lien vers le commentaire
Partager sur d’autres sites

Coucou

 

voila c'est fini ! du moins voila ma version finie

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;

/// <summary>
/// Didier AVELINE
/// version 1.1 2016_10_19
/// cette routine fait une polyligne d'encadrement des entités TEXTE
/// la polyligne fait plus qu'un rectangle avec une fausse perspective
/// il faut sélectionner un TEXTE
/// le nom de la commande est entoure_texte
/// /// </summary>


namespace entoure_texte
{
public class Class1
{


   	[CommandMethod("entoure_texte")]
   	static public void EntoureTexte()
   	{
       	Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
       	Database db = HostApplicationServices.WorkingDatabase;
       	Editor ed = doc.Editor;
       	Transaction tr = db.TransactionManager.StartTransaction();


       	using (tr)
       	{
           	var entOpts = new PromptEntityOptions("\nChoix du Texte à encadrer : ");
           	entOpts.SetRejectMessage("\nL'objet choisi n'est pas un texte.");
           	entOpts.AddAllowedClass(typeof(DBText), true);
           	var entRes = ed.GetEntity(entOpts);
           	if (entRes.Status != PromptStatus.OK)
               	return;

           	BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
           	{

               	DBText txtobj = (DBText)tr.GetObject(entRes.ObjectId, OpenMode.ForWrite);

               	string contenu = txtobj.TextString;
               	double ht = txtobj.Height;
               	double dec = ht * 0.2;
               	double dec_bas = 0;


               	///  test qui vérifie la présence de lettres avec jambage inférieur dans le texte
               	///  si oui la variable dec_bas prend une valeur en fonction de la variable dec
               	///  dès que je rencontre une lettre qui ne correspond pas au test je sors
               	for (int index = 0; index < contenu.Length; index++)
               	{
                   	var test = contenu[index];
                   	if (contenu[index] == 'g' || contenu[index] == 'j' || contenu[index] == 'p' || contenu[index] == 'q' || contenu[index] == 'y' ||
                       	contenu[index] == '(' || contenu[index] == ')' || contenu[index] == '[' || contenu[index] == ']' || contenu[index] == '{' || contenu[index] == '}')
                   	{
                       	dec_bas = dec * 0.9;
                       	break;
                   	}

               	}
               	/// fin du test

               	///  test qui vérifie la présence de lettres simples sans jambage dans le texte
               	///  dès que je rencontre une lettre qui ne correspond pas au test je sors
               	bool minus = false;
               	for (int index = 0; index < contenu.Length; index++)
               	{
                   	var test = contenu[index];
                   	if (contenu[index] == 'a' || contenu[index] == 'z' || contenu[index] == 'e' || contenu[index] == 'r' || contenu[index] == 'u'||
                       	contenu[index] == 'o' || contenu[index] == 's' || contenu[index] == 'm' || contenu[index] == 'w'||
                       	contenu[index] == 'x' || contenu[index] == 'c' || contenu[index] == 'v' || contenu[index] == 'n')

                       	minus = true;
                   	else
                   	{
                       	minus = false;
                       	break;
                   	}
                       	
               	}

               	if (minus == true)
                   	ht = ht * 0.72;

               	double ang = txtobj.Rotation;
               	Point3d Pt_Ins = txtobj.Position;
               	Point2d TextExtents = Autodesk.AutoCAD.Internal.Utils.GetTextExtents(txtobj.TextStyleId, txtobj.TextString, txtobj.Height);
               	double long_texte = TextExtents.X * txtobj.WidthFactor;//longueur du texte



               	Point3d pttemp = new Point3d(Pt_Ins.X + ((Math.Cos(ang + Math.PI)) * dec), Pt_Ins.Y + ((Math.Sin(ang + Math.PI)) * dec), 0);
               	Point2d pt1 = new Point2d((pttemp.X + ((Math.Cos(ang - (Math.PI / 2))) * (dec + dec_bas))), (pttemp.Y + ((Math.Sin(ang - (Math.PI / 2))) * (dec + dec_bas))));
               	Point2d pt2 = new Point2d((pt1.X + (Math.Cos(ang) * (long_texte + (dec * 2)))), (pt1.Y + (Math.Sin(ang) * (long_texte + (dec * 2)))));
               	Point2d pt3 = new Point2d((pt2.X + ((Math.Cos(ang + (Math.PI / 2))) * (ht + dec + dec + dec_bas))), (pt2.Y + ((Math.Sin(ang + (Math.PI / 2))) * (ht + dec + dec + dec_bas))));
               	Point2d pt4 = new Point2d((pt3.X + ((Math.Cos(ang + Math.PI) * (long_texte + (dec * 2))))), (pt3.Y + ((Math.Sin(ang + Math.PI) * (long_texte + (dec * 2))))));
               	Point2d pt5 = new Point2d((pt2.X + ((Math.Cos(ang + (Math.PI / 4))) * (dec * 1.5))), (pt2.Y + ((Math.Sin(ang + (Math.PI / 4))) * (dec * 1.5))));
               	Point2d pt6 = new Point2d((pt5.X + ((Math.Cos(ang + (Math.PI / 2))) * (ht + dec + dec + dec_bas))), (pt5.Y + ((Math.Sin(ang + (Math.PI / 2))) * (ht + dec + dec + dec_bas))));
               	Point2d pt7 = new Point2d((pt6.X + ((Math.Cos(ang + Math.PI)) * (long_texte + (dec * 2)))), (pt6.Y + ((Math.Sin(ang + Math.PI)) * (long_texte + (dec * 2)))));




               	Polyline acPoly = new Polyline(10);
               	acPoly.SetDatabaseDefaults();
               	acPoly.AddVertexAt(0, pt2, 0, 0, 0);
               	acPoly.AddVertexAt(1, pt1, 0, 0, 0);
               	acPoly.AddVertexAt(2, pt4, 0, 0, 0);
               	acPoly.AddVertexAt(3, pt3, 0, 0, 0);
               	acPoly.AddVertexAt(4, pt2, 0, 0, 0);
               	acPoly.AddVertexAt(5, pt5, 0, 0, 0);
               	acPoly.AddVertexAt(6, pt6, 0, 0, 0);
               	acPoly.AddVertexAt(7, pt3, 0, 0, 0);
               	acPoly.AddVertexAt(8, pt6, 0, 0, 0);
               	acPoly.AddVertexAt(9, pt7, 0, 0, 0);
               	acPoly.AddVertexAt(10, pt4, 0, 0, 0);
               	acPoly.ColorIndex = 1; //passe la polyligne en rouge pour le fun              	
               	btr.AppendEntity(acPoly);//ajout de la polyligne dans la base
               	tr.AddNewlyCreatedDBObject(acPoly, true);

               	tr.Commit();
           	}
       	}
   	}
}
}

 

toujours à l'écoute de critiques pour devenir moins petit

 

amicalement

Lien vers le commentaire
Partager sur d’autres sites

Bravo ! ;)

 

Comme promis, une version qui utilise la matrice de transformation du "SCU objet" du texte sélectionné.

Cette matrice est la combinaison des matrices de changement de plan, de déplacement et de rotation du texte.

En transformant le texte avec la matrice inverse on le ramène dans le plan du SCG, à l'origine, avec une rotation nulle.

On peut alors récupérer son emprise (BoundingBox) pour dessiner le cadre.

Puis on applique la matrice au cadre et au texte pour les ramener à la position initiale du texte.

 

using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

using AcAp = Autodesk.AutoCAD.ApplicationServices.Core.Application;

namespace Matrices
{
   public class Commands
   {
       [CommandMethod("TEXTFRAME")]
       public void TextFrame()
       {
           var doc = AcAp.DocumentManager.MdiActiveDocument;
           var db = doc.Database;
           var ed = doc.Editor;

           // sélection du texte
           var entOpts = new PromptEntityOptions("\nSélectionnez un texte: ");
           entOpts.SetRejectMessage("\nL'objet sélectionné n'est pas un texte.");
           entOpts.AddAllowedClass(typeof(DBText), true);
           var entRes = ed.GetEntity(entOpts);
           if (entRes.Status != PromptStatus.OK)
               return;

           using (Transaction tr = db.TransactionManager.StartTransaction())
           {
               // calcul de la matrice du "SCU Object" du texte
               var text = (DBText)tr.GetObject(entRes.ObjectId, OpenMode.ForWrite);
               var plane = new Plane(Point3d.Origin, text.Normal);
               var xform =
                   Matrix3d.Rotation(text.Rotation, text.Normal, text.Position) *
                   Matrix3d.Displacement(text.Position.GetAsVector()) *
                   Matrix3d.PlaneToWorld(plane);

               // transformation inverse du texte (retour à l'origine dans le plan du SCG)
               text.TransformBy(xform.Inverse());

               // calcul des coordonnées des sommets du cadre
               var extents = text.GeometricExtents;
               double
                   offsetDist = text.Height * 0.2,
                   minX = extents.MinPoint.X - offsetDist,
                   minY = extents.MinPoint.Y - offsetDist,
                   maxX = extents.MaxPoint.X + offsetDist,
                   maxY = extents.MaxPoint.Y + offsetDist;

               // dessin du cadre dans le SCG puis transformation dans le "SCU object" du texte 
               using (var pline = new Polyline())
               {
                   pline.AddVertexAt(0, new Point2d(minX, minY), 0.0, 0.0, 0.0);
                   pline.AddVertexAt(1, new Point2d(maxX, minY), 0.0, 0.0, 0.0);
                   pline.AddVertexAt(2, new Point2d(maxX, maxY), 0.0, 0.0, 0.0);
                   pline.AddVertexAt(3, new Point2d(minX, maxY), 0.0, 0.0, 0.0);
                   pline.Closed = true;
                   var space = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                   space.AppendEntity(pline);
                   tr.AddNewlyCreatedDBObject(pline, true);
                   pline.TransformBy(xform);
               }

               // re-transformation du texte dans son "SCU Objet"
               text.TransformBy(xform);
               tr.Commit();
           }
       }
   }
}

 

 

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

Lien vers le commentaire
Partager sur d’autres sites

Coucou

 

Merci de tes encouragements mais aussi de ton explication qui me fait te questionner toutefois :

J'ai compris du moins je le crois :

Tu transformes le texte dans le SCG (mais on ne le voit pas faire graphiquement)

C'est ça ?

 

Allez ! je retourne me coucher ! marre de ces insomnies !!!

Lien vers le commentaire
Partager sur d’autres sites

C'est ça.

 

Pour voir les différentes étapes, tu peux essayer le code ci-dessous qui décompose le processus. Il faut faire Entrée (ou Espace, ou clic droit) pour passer à l'étape suivante.

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

using AcAp = Autodesk.AutoCAD.ApplicationServices.Core.Application;

namespace Matrices
{
   public class Commands
   {
       [CommandMethod("TEXTFRAME")]
       public void TextFrame()
       {
           var doc = AcAp.DocumentManager.MdiActiveDocument;
           var db = doc.Database;
           var ed = doc.Editor;

           // sélection du texte
           var entOpts = new PromptEntityOptions("\nSélectionnez un texte: ");
           entOpts.SetRejectMessage("\nL'objet séléctionné n'est pas un texte.");
           entOpts.AddAllowedClass(typeof(DBText), true);
           var entRes = ed.GetEntity(entOpts);
           if (entRes.Status != PromptStatus.OK)
               return;

           Matrix3d xform;

           using (Transaction tr = db.TransactionManager.StartTransaction())
           {
               // calcul de la matrice du "SCU Object" du texte
               var text = (DBText)tr.GetObject(entRes.ObjectId, OpenMode.ForWrite);
               var plane = new Plane(Point3d.Origin, text.Normal);
               xform =
                   Matrix3d.Rotation(text.Rotation, text.Normal, text.Position) *
                   Matrix3d.Displacement(text.Position.GetAsVector()) *
                   Matrix3d.PlaneToWorld(plane);

               // transformation inverse du texte (retour à l'origine dans le plan du SCG)
               text.TransformBy(xform.Inverse());

               // pause
               if (!PromptForEnter(doc)) return;

               // calcul des points du cadre
               var extents = text.GeometricExtents;
               double
                   offsetDist = text.Height * 0.2,
                   minX = extents.MinPoint.X - offsetDist,
                   minY = extents.MinPoint.Y - offsetDist,
                   maxX = extents.MaxPoint.X + offsetDist,
                   maxY = extents.MaxPoint.Y + offsetDist;

               // dessin du cadre dans le SCG puis transformation dans le "SCU object" du texte 
               using (var pline = new Polyline())
               {
                   pline.AddVertexAt(0, new Point2d(minX, minY), 0.0, 0.0, 0.0);
                   pline.AddVertexAt(1, new Point2d(maxX, minY), 0.0, 0.0, 0.0);
                   pline.AddVertexAt(2, new Point2d(maxX, maxY), 0.0, 0.0, 0.0);
                   pline.AddVertexAt(3, new Point2d(minX, maxY), 0.0, 0.0, 0.0);
                   pline.Closed = true;
                   var space = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                   space.AppendEntity(pline);
                   tr.AddNewlyCreatedDBObject(pline, true);

                   // pause
                   if (!PromptForEnter(doc)) return;

                   pline.TransformBy(xform);

                   // pause
                   if (!PromptForEnter(doc)) return;
               }
               // re-transformation du texte dans son "SCU Objet"
               text.TransformBy(xform);
               tr.Commit();
           }
       }

       private bool PromptForEnter(Document doc)
       {
           doc.TransactionManager.QueueForGraphicsFlush();
           var opts = new PromptKeywordOptions("\nPressez Entrée pour continuer: ");
           opts.AllowNone = true;
           return doc.Editor.GetKeywords(opts).Status != PromptStatus.Cancel;
       }
   }
}

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

Lien vers le commentaire
Partager sur d’autres sites

Coucou

 

Encore un grand merci pour ta pédagogie.

C'est bien comme ça que je sentais les choses

Dans une première version j'avais fait quelque chose qui créait une entité au point 0 dans le SCG dont j’extrayais les coordonnées

Déjà que je ne tire pas une fierté particulière de ma façon de programmer qui a plutôt un ascendant bourrin.

Je me disais en sus que créer une entité (et l'effacer plus tard) pour ces besoins était honteux

Mais pour être honnête sans ton GetTextExtents présent en réponse #9 j'aurais tourné en rond autour de cette solution.

 

Amicalement

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é