Aller au contenu

Overrule


Messages recommandés

Salut,

 

Juste pour le fun.

Les objets overrule permettent "d'outre-passer" l'affichage des entités AutoCAD, on peut, par exemple ajouter du texte à une polyligne* pour afficher dynamiquement les longueurs des segments, et ce, avec un code relativement concis.

 

* les textes font partie intégrante de la polyligne

 

La définition de l'overrule :

using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;

using AcDb = Autodesk.AutoCAD.DatabaseServices;

namespace LabelPolylineOverruleSample
{
   class LabelPolylineOverrule : DrawableOverrule
   {
       TextStyle textStyle;

       public LabelPolylineOverrule()
       {
           textStyle = new TextStyle() { FileName = "Arial", TextSize = 2.5 };
       }

       public override bool WorldDraw(Drawable drawable, WorldDraw wd)
       {
           var pline = (AcDb.Polyline)drawable;
           var nbSegments = pline.Closed ? pline.NumberOfVertices : pline.NumberOfVertices - 1;
           var point = default(Point3d);
           var direction = default(Vector3d);
           string text = null;
           for (int i = 0; i < nbSegments; i++)
           {
               if ((int)pline.GetSegmentType(i) < 2)
               {
                   switch (pline.GetSegmentType(i))
                   {
                       case AcDb.SegmentType.Line:
                           var line = pline.GetLineSegmentAt(i);
                           point = line.MidPoint;
                           direction = line.Direction;
                           text = line.Length.ToString("0.00");
                           wd.Geometry.WorldLine(line.StartPoint, line.EndPoint);
                           break;
                       case AcDb.SegmentType.Arc:
                           CircularArc3d arc = pline.GetArcSegmentAt(i);
                           var startParam = arc.GetParameterOf(arc.StartPoint);
                           var endParam = arc.GetParameterOf(arc.EndPoint);
                           point = arc.EvaluatePoint((startParam + endParam) / 2.0);
                           direction = arc.StartPoint.GetVectorTo(arc.EndPoint).GetNormal();
                           text = arc.GetLength(startParam, endParam, 0.0).ToString("0.00");
                           wd.Geometry.CircularArc(arc.StartPoint, point, arc.EndPoint, ArcType.ArcSimple);
                           break;
                       default:
                           break;
                   }
                   if (direction.X < 0) direction = direction.Negate();
                   var extents = textStyle.ExtentsBox(text, false, false, wd);
                   point -= direction * (extents.MaxPoint.X - extents.MinPoint.X) / 2.0;
                   point += direction.GetPerpendicularVector() * 1.25;
                   wd.Geometry.Text(point, pline.Normal, direction, text, false, textStyle);
               }
           }
           return true;
       }
   }
}

 

Une commande de test :

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

namespace LabelPolylineOverruleSample
{
   public class Commands
   {
       static LabelPolylineOverrule overrule;
       static string regAppName = "LABEL_POLYLINE";

       static Commands()
       {
           overrule = new LabelPolylineOverrule();
           Overrule.AddOverrule(RXObject.GetClass(typeof(Polyline)), overrule, false);
           overrule.SetXDataFilter(regAppName);
           Overrule.Overruling = true;
       }

       [CommandMethod("TEST")]
       public static void Test()
       {
           var doc = Application.DocumentManager.MdiActiveDocument;
           var db = doc.Database;
           var ed = doc.Editor;
           var options = new PromptEntityOptions("\nSelect polyline: ");
           options.SetRejectMessage("\nSelected object is not a polyline.");
           options.AddAllowedClass(typeof(Polyline), true);
           var result = ed.GetEntity(options);
           if (result.Status != PromptStatus.OK)
               return;
           using (var resBuf = new ResultBuffer(new TypedValue(1001, regAppName), new TypedValue(1000, "Dummy text")))
           {
               AddXdata(result.ObjectId, resBuf, db);
           }
       }

       private static void AddXdata(ObjectId id, ResultBuffer resBuf, Database db)
       {
           using (Transaction tr = db.TransactionManager.StartTransaction())
           {
               var regAppTable = (RegAppTable)tr.GetObject(db.RegAppTableId, OpenMode.ForRead);
               if (!regAppTable.Has(regAppName))
               {
                   var regApp = new RegAppTableRecord() { Name = regAppName };
                   regAppTable.UpgradeOpen();
                   regAppTable.Add(regApp);
                   tr.AddNewlyCreatedDBObject(regApp, true);
               }
               var pline = (Polyline)tr.GetObject(id, OpenMode.ForWrite);
               pline.XData = resBuf;
               tr.Commit();
           }
       }
   }
}

 

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

Lien vers le commentaire
Partager sur d’autres sites

Hello Gilles

 

1) MAGNIFIQUE & IMPRESSIONNANT !

 

2) Multiples Suggestions (Il est super penible Le Decapode !) :

 

- Si 3 Vertex (ou plus) afficher simultanement la surface au Centroid

 

- Traiter aussi les 3DPolys

Sans la Surface ou alors si 3 Vertex (ou +) la Surface projetee au sol

 

- Ca marche aussi sur les 2D/3D Polys (courbees , splinees) ?!

 

- Option pour ecrire reellement les textes

Au fait les textes seraient bien sur "pilotes" par des reacteurs ?!

 

Bon WE, MERCI, Bye, lecrabe

Autodesk Expert Elite Team

Lien vers le commentaire
Partager sur d’autres sites

Invité Patrick

Salut Gille, c'est super! Peut-on considérer que c'est un mécanisme similaire aux réacteurs persistants en VLISP ? Autrement dit est-ce que l'affichage des longueurs de segments persisterait dans un dessin que je transmettrais à quelqu'un ?

Lien vers le commentaire
Partager sur d’autres sites

Salut Gille, c'est super! Peut-on considérer que c'est un mécanisme similaire aux réacteurs persistants en VLISP ? Autrement dit est-ce que l'affichage des longueurs de segments persisterait dans un dessin que je transmettrais à quelqu'un ?

Non, ça n'est pas persistant, il faut que l'application qui définit l'objet Overrule soit chargée. Et c'est plus proche d'un objet personnalisé (comme on peut en faire avec ObjectARX) que d'un réacteur (ou un gestionnaire d'évènement). Si elle n'est pas chargée, la polyligne est affichée "normalement".

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

Lien vers le commentaire
Partager sur d’autres sites

Bonjour,

 

toujours aussi impressionné par tes réalisations Gilles, même si pour toi c'est juste pour le fun !biggrin.gif

 

Petite question : comment fait-on pour installer cette merveille sur Autocad (2013) et s'en servir ?

 

Encore merci pour tes partages.

COME

 

La vie sans musique est tout simplement une erreur, une fatigue, un exil. »

Friedrich Nietzsche

Lien vers le commentaire
Partager sur d’autres sites

Merci.

 

C'était juste un exemple, pas vraiment suffisamment abouti pour être publié.

 

Ah d'accord ! Dans le cas présent on n'a pas la même définition de "pas vraiment suffisamment abouti"tongue.gif

 

 

En tout cas BRAVO pour cette démo !

 

 

 

PS : Aleck les majuscules sont volontaireswink.gif

COME

 

La vie sans musique est tout simplement une erreur, une fatigue, un exil. »

Friedrich Nietzsche

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

merci beaucoup pour le partage, c'est génial !

J'allais justement faire une demande à l'occasion, j'ai un client qui demande des projets de réseaux électriques aériens que sur autocad, et c'est particulièrement pénible de placer les longueurs manuellement entre 2 poteaux ! ;)

 

Me reste plus qu'à comprendre comment installer cette petite merveille !

Lien vers le commentaire
Partager sur d’autres sites

Hello Mr hey_bapt

 

1) Pour Gilles : j'espere que tu m'en voudras de "polluer" ton superbe sujet

avec une routine VLisp de Gilles pour Mr hey_bapt !?

 

2) Donc si tu as des Polylignes qui relient des Blocs/Symboles (Poteau, Regard, etc)

la merveilleuse routine "POLYLENGTH" de Gilles sera d'un grand secours !

Elle genere des Champs dynamiques qui indiquent la longueur totale de la Polyligne ...

 

3) Chargement par APPLOAD et execution en tapant au clavier : POLYLENGTH

 

MERCI Gilles, Bye, lecrabe

 


;; 
;; PolyLength par GC - 03/03/2018 
;; 
;; Micro-Modif par Patrice B.
;; 
;; ------------------------------------------------------
;; SVP changer TEXTSIZE AVANT d'executer la Routine ... 
;; Car la routine utilise la valeur de TEXTSIZE comme Hauteur de MTEXT
;; ------------------------------------------------------ 
;; 
;; J'ai revu les codes, le probleme venait de la methode utilisee 
;; pour placer le texte/champ sur le barycentre de la polyligne. 
;; Cette methode ne fonctionnait qu'avec des polylignes.
;; 
;; J'ai change cela. Le texte est desormais place au centre de la boundingbox de l'entite. 
;; J'ai aussi revu les filtres de selection 
;; qui ne devraient pas etre tout à fait les memes pour l'aire et la longueur. 
;; 
;; Pour l'aire, je te laisse choisir entre uniquement les objets fermes, ou pas.
;; 
;; Pour les longueurs, les champs sont differents pour les cercles (Circumference), 
;; les regions et mpolygons (Perimeter) 
;; et n'existent pas pour les ELLIPSEs et SPLINEs, 
;; 
;; ---- ATTENTION ---- ELLIPSEs et SPLINEs ---- NON TRAITEES ---- 
;; 
;; %<\AcObjProp Object(%<\_ObjId 1181647088>%).Area \f "%lu2">%
;; %<\AcObjProp Object(%<\_ObjId 1181647088>%).Length \f "%lu2">%
;; %<\AcObjProp Object(%<\_ObjId 1181647088>%).Perimeter \f "%lu2">%
;; %<\AcObjProp Object(%<\_ObjId 1181647088>%).Circumference \f "%lu2">%
;; 
;; Liste sur ELLIPSE --> Aire & Circonference ?? 
;; Liste sur SPLINE  --> Aire & Circonference ??
;; 

(defun c:PolyLength (/ *error* filter ss acSpace minPt maxPt pt id str txt)
 (vl-load-com)
 (or *acdoc* (setq *acdoc* (vla-get-ActiveDocument (vlax-get-acad-object))))
 (or *util* (setq *util* (vla-get-Utility *acdoc*)))
 (defun *error* (msg)
   (and msg
 (/= msg "Fonction annulée")
 (/= msg "Function cancelled")
 (princ (strcat "Erreur: " msg))
   )
   (vla-EndUndomark *acdoc*)
   (princ)
 )

 (setq	filter (list
	 '(-4 . "<OR") 

;;		 '(0 . "ARC,CIRCLE,LINE,LWPOLYLINE,MPOLYGON,REGION,SPLINE,ELLIPSE") 
	 '(0 . "ARC,CIRCLE,LINE,LWPOLYLINE,MPOLYGON,REGION") 

	 '(-4 . "<AND") 
	 '(0 . "POLYLINE")
	 '(-4 . "<NOT")
	 '(-4 . "&")
	 '(70 . 112)
	 '(-4 . "NOT>")
	 '(-4 . "AND>")
	 '(-4 . "OR>"))
 ) 

 (prompt "Hauteur courante de MTEXT - Voir la Variable System TEXTSIZE ... \n"  ) 
 (prompt "---- ATTENTION ---- ELLIPSEs et SPLINEs ---- NON TRAITEES ---- \n") 

 (prompt "POLYLENGTH traite: ARC,CIRCLE,POLYLINE 2D/3D,MPOLYGON,REGION \nSelectionnez les objets ou Entree pour tous ") 

 (if (or (ssget filter)
  (ssget "_X" (cons (cons 410 (getvar 'ctab)) filter))
     )
   (progn
     (vla-StartUndomark *acdoc*)
     (setq acSpace (vla-get-Block (vla-get-ActiveLayout *acdoc*)))
     (vlax-for	obj (setq ss (vla-get-ActiveSelectionSet *acdoc*))
(vla-GetBoundingBox obj 'minPt 'maxPt)
(setq pt  (mapcar '(lambda (x1 x2) (/ (+ x1 x2) 2.))
		  (vlax-safearray->list minPt)
		  (vlax-safearray->list maxPt)
	  )
      id  (vla-GetObjectIdString *util* obj :vlax-false)
      str (cond
	    ((member (vla-get-ObjectName obj) '("AcDbEllipse" "AcDbSpline"))
	      (rtos (strcat (vlax-curve-getDistAtParam obj (vlax-curve-getEndParam obj)) 2 1) "m")
	    )
	    ((= (vla-get-ObjectName obj) "AcDbCircle")
	     (strcat
	       "%<\\AcObjProp Object(%<\\_ObjId "
	       id
	       ">%).Circumference \\f \"%lu2%pr1%ps[,m]%\">%"
	     )
	    )
	    ((member (vla-get-ObjectName obj) '("AcDbRegion" "AcDbMPolygon"))
	     (strcat
	       "%<\\AcObjProp Object(%<\\_ObjId "
	       id
	       ">%).Perimeter \\f \"%lu2%pr1%ps[,m]%\">%"
	     )
	    )
	    (T
	     (strcat
	       "%<\\AcObjProp Object(%<\\_ObjId "
	       id
	       ">%).Length \\f \"%lu2%pr1%ps[,m]%\">%"
	     )
	    )
	  )
      txt (vla-addMText acSpace (vlax-3d-point pt) 0. str)
)
(vla-put-AttachmentPoint txt acAttachmentPointMiddleCenter)
(vla-put-insertionPoint txt (vlax-3d-point pt))
     )
     (vla-Delete ss)
   )
 )
 (*error* nil)
) 

Autodesk Expert Elite Team

Lien vers le commentaire
Partager sur d’autres sites

Je rappelle juste ce que je répondais à Patrick réponse #5 : les textes ne sont affichés que si l'extension (DLL) est chargée, sinon, la polyligne s'affiche normalement. Donc transmettre un fichier suppose de transmettre aussi l'extension et de l'installer.

Il existe de nombreux LISPs qui le font en ajoutant des entités texte (CF SegLen) ce qui simplifie l'échange de fichiers.

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

Lien vers le commentaire
Partager sur d’autres sites

Hello Gilles

 

Etant donne que l'on ne dispose pas de la propriete LONGUEUR (ou PERIMETRE ou CIRCONFERENCE)

sur les ELLIPSEs et SPLINEs ,

j'imagine qu'il est impossible d'avoir un champ dynamique "refletant" la longueur !?

 

Merci d'avance, Bye, lecrabe

Autodesk Expert Elite Team

Lien vers le commentaire
Partager sur d’autres sites

Pour les amateurs, vous pouvez télécharger et installer PolylineOverruleSetup.msi.

Le plugin est compatible à partir de AutoCAD 2013.

Deux commandes SEGLEN_OVERRULE_ON et SEGLEN_OVERRULE_OFF pour respectivement activer ou désactiver l'overrule sur les polylignes sélectionnées.

Les commandes sont accessibles depuis le menu contextuel quand seulement des polylignes sont sélectionnées :

Polyligne overrule
   > Actif
   > inactif
 

La hauteur de texte et le nombre de décimales affichées sont tirés des valeurs de TEXTSIZE et LUPREC au moment de la création du lancement de SEGLEN_OVERRULE_ON (on peut modifier ces valeurs a posteriori et relancer la commande).

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

Lien vers le commentaire
Partager sur d’autres sites

Pour les amateurs, vous pouvez télécharger et installer PolylineOverruleSetup.msi.

Le plugin est compatible de AutoCAD 2013 à AutoCAD 2020.

Deux commandes SEGLEN_OVERRULE_ON et SEGLEN_OVERRULE_OFF pour respectivement activer ou désactiver l'overrule sur les polylignes sélectionnées.

Les commandes sont accessibles depuis le menu contextuel quand seulement des polylignes sont sélectionnées :

Polyligne overrule
   > Actif
   > inactif

La hauteur de texte et le nombre de décimales affichées sont tirés des valeurs de TEXTSIZE et LUPREC au moment de la création du lancement de SEGLEN_OVERRULE_ON (on peut modifier ces valeurs a posteriori et relancer la commande).

Salut,

 

Waouh !

 

Merci, merci beaucoup pour ce très beau partage.

COME

 

La vie sans musique est tout simplement une erreur, une fatigue, un exil. »

Friedrich Nietzsche

Lien vers le commentaire
Partager sur d’autres sites

  • 3 ans après...

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é