labels on contours

labels on contours

marie-laurence.pollet
Contributor Contributor
683 Views
16 Replies
Message 1 of 17

labels on contours

marie-laurence.pollet
Contributor
Contributor

Hello, 

I need to label polylines regarding the elevation. I have Civil 3d but I am not happy with the way it labels the contours. So I have now polylines with elevation and I want a label on interval, so I made lots of searches and ask to ChatGPT. Now I have a lisp that works but it is impossible to have labels parallel to the polylines; I have made several modifications but they are always perpendicular.

Can someone have a look and tell me what is wrong with the lisp?

thank you!!!

 

(defun c:AlignTextOnPolyline (/ *dist* dist height ss count ent obj chainage len point1 angle)
(vl-load-com)

;; Variable globale pour la distance par défaut
(setq *dist* 100.0)

;; Fonction pour créer un texte aligné sur la polyligne
(defun _text (p angle height content)
(entmake
(list
'(0 . "TEXT") ; Utiliser "TEXT" pour plus de simplicité
'(100 . "AcDbEntity")
'(8 . "C-CTRL_TXT") ; Calque pour les textes
(cons 10 p) ; Point d'insertion
(cons 40 height) ; Hauteur du texte
(cons 1 content) ; Contenu du texte
(cons 50 angle) ; Angle de rotation (aligné sur la polyligne)
(cons 7 (getvar "textstyle")) ; Style de texte courant
)
)
)

;; Fonction pour calculer l'angle de la tangente à la polyligne
(defun _tangent-angle (obj dist)
(angle (vlax-curve-getPointAtDist obj (- dist 0.001)) (vlax-curve-getPointAtDist obj dist))
)

;; Demander l'intervalle et la hauteur du texte
(initget 6)
(setq dist (getdist (strcat "\nIntervalle de texte <" (rtos *dist*) ">: ")))
(setq *dist* (if dist dist *dist*)) ; Utiliser la valeur par défaut si l'utilisateur n'entre rien

(setq height (getdist "\nHauteur du texte : "))

;; Sélectionner les polylignes
(setq ss (ssget '((0 . "LWPOLYLINE")))) ; Sélectionner uniquement des polylignes légères

(if ss
(progn
(setq count 0)
(repeat (sslength ss)
(setq ent (ssname ss count)
obj (vlax-ename->vla-object ent)
chainage *dist*) ; Commencer à l'intervalle spécifié

;; Obtenir la longueur totale de la polyligne
(setq len (vlax-curve-getDistAtParam obj (vlax-curve-getEndParam obj)))

;; Placer les textes à intervalles réguliers le long de la polyligne
(while (<= chainage len)
(setq point1 (vlax-curve-getPointAtDist obj chainage))
(if point1
(progn
;; Créer le texte aligné sur la polyligne (angle parallèle)
(setq angle (_tangent-angle obj chainage)) ; Calcul de l'angle parallèle à la polyligne
(_text point1 angle height (rtos chainage 2 2))
(setq chainage (+ chainage *dist*)) ; Passer à l'intervalle suivant
)
)
)
(setq count (1+ count))
)
)
(princ "\nAucune polyligne sélectionnée.")
)
(princ)
)

0 Likes
Accepted solutions (2)
684 Views
16 Replies
Replies (16)
Message 2 of 17

Kent1Cooper
Consultant
Consultant

I have something called LabelElevMask.lsp, >here<.  It requires you to pick at each location on an object, and does not do the at-intervals part of what you're looking for, but it could be modified to do so.  [I find that automated spacings or linetypes with linetype generation enabled often land labels right at bends or other awkward locations, so for the purpose at the time, I made it to have the location(s) selected.]

Kent Cooper, AIA
0 Likes
Message 3 of 17

ВeekeeCZ
Consultant
Consultant

Try this one.

The issue is that you (or gpt) used angle as name of variable. But that cannot be because it is built-in function which you also use..

 

(defun c:AlignTextOnPolyline (/ *dist* dist height ss count ent obj chainage len point1 angle_)
  (vl-load-com)
  
  ;; Variable globale pour la distance par défaut
  (setq *dist* 100.0)
  
  ;; Fonction pour créer un texte aligné sur la polyligne
  (defun _text (p angle_ height content)
    (entmake
      (list
	'(0 . "TEXT") ; Utiliser "TEXT" pour plus de simplicité
	'(100 . "AcDbEntity")
	'(8 . "C-CTRL_TXT") ; Calque pour les textes
	(cons 10 p) ; Point d'insertion
	(cons 40 height) ; Hauteur du texte
	(cons 1 content) ; Contenu du texte
	(cons 50 angle_) ; Angle de rotation (aligné sur la polyligne)
	(cons 7 (getvar "textstyle")) ; Style de texte courant
	)
      )
    )
  
  ;; Fonction pour calculer l'angle de la tangente a la polyligne
  (defun _tangent-angle (obj dist)
    (angle (vlax-curve-getPointAtDist obj (- dist 0.001)) (vlax-curve-getPointAtDist obj dist))
    )
  
  ;; Demander l'intervalle et la hauteur du texte
  (initget 6)
  (setq dist (getdist (strcat "\nIntervalle de texte <" (rtos *dist*) ">: ")))
  (setq *dist* (if dist dist *dist*)) ; Utiliser la valeur par défaut si l'utilisateur n'entre rien
  
  (setq height (getdist "\nHauteur du texte : "))
  
  ;; Sélectionner les polylignes
  (setq ss (ssget '((0 . "LWPOLYLINE")))) ; Sélectionner uniquement des polylignes légeres
  
  (if ss
    (progn
      (setq count 0)
      (repeat (sslength ss)
	(setq ent (ssname ss count)
	      obj (vlax-ename->vla-object ent)
	      chainage *dist*) ; Commencer a l'intervalle spécifié
	
	;; Obtenir la longueur totale de la polyligne
	(setq len (vlax-curve-getDistAtParam obj (vlax-curve-getEndParam obj)))
	
	;; Placer les textes a intervalles réguliers le long de la polyligne
	(while (<= chainage len)
	  (setq point1 (vlax-curve-getPointAtDist obj chainage))
	  (if point1
	    (progn
	      ;; Créer le texte aligné sur la polyligne (angle parallele)
	      (setq angle_ (_tangent-angle obj chainage)) ; Calcul de l'angle parallele a la polyligne
	      (_text point1 angle_ height (rtos chainage 2 2))
	      (setq chainage (+ chainage *dist*)) ; Passer a l'intervalle suivant
	      )
	    )
	  )
	(setq count (1+ count))
	)
      )
    (princ "\nAucune polyligne sélectionnée.")
    )
  (princ)
  )

 

0 Likes
Message 4 of 17

marie-laurence.pollet
Contributor
Contributor

Thank you , but it doesn't seem to work with polylines? it says bad argument type: numberp: nil

0 Likes
Message 5 of 17

marie-laurence.pollet
Contributor
Contributor

Thank you Beekeeper CZ! unfortunately the labels are still perpendicular... Can't we try to apply a 90° rotation on each label in the lisp?

0 Likes
Message 6 of 17

marie-laurence.pollet
Contributor
Contributor
Accepted solution

OK my mistake, it seems to work now thanks! 

 

0 Likes
Message 7 of 17

ВeekeeCZ
Consultant
Consultant

Well, this is what I am seeing and I would call it 'tangent', not 'perpendicular'

 

eekeeCZ_0-1741352622652.png

 

Anyways, if you want to adjust the angle, just locate this line

(cons 50 angle_)

and add something to it, like pi/2.

(cons 50 (+ (/ pi 2) angle_))

 

0 Likes
Message 8 of 17

marie-laurence.pollet
Contributor
Contributor

thank you, now my lisp works well, but I saw it doesn't put text on the lines with length smaller than the distance chosen between labels.

I just want there to be texts on the lines whose length is between the requested minimum and the requested interval. I have to add a condition to check if the length of each segment is less than or equal to the chosen interval, but greater than the minimum length, but it doesn't work.

Have you an idea?

thank you very much!

0 Likes
Message 9 of 17

ВeekeeCZ
Consultant
Consultant

You have all wrapped into

(while (<= chainage len) ...)

where initial value of chainage is *dist*, not min-length

 

But.. also this line does not seem right

(setq segment-length (vlax-curve-getDistAtParam obj (vlax-curve-getParamAtDist obj chainage)))  ... you can remove both... you would set chainage to segment-length 

...some sample drawing would help to understand of what you mean by 'segment' -- where you want to have text and where not.

0 Likes
Message 10 of 17

marie-laurence.pollet
Contributor
Contributor

I can send you my test dwg file.

I want labels of the elevation aligned on the polylines (parallel) but always readable (rotation between -90° and 90°), and in the layer of the polyline. I wan to be able to decide the height of the text

I want also label on all polylines when length> x, with an interval=y, but also on polylines withe x<length<y.

ChatGPT and I worked a lot, but now I am stuck with the last request...

Thank you if you have time to have a look!

 

0 Likes
Message 11 of 17

Kent1Cooper
Consultant
Consultant

It works for me, on both heavy and lightweight Polylines.  Did you follow the instruction at the top, and find all the <--EDIT lines in the code, and set them according to your needs?  Read their descriptions -- for example, the Style creation line needs a different number of Enters built in depending on whether you're using a .SHX or .TTF font. 

Kent Cooper, AIA
0 Likes
Message 12 of 17

ВeekeeCZ
Consultant
Consultant

First of all, programming is about consistency. If I give you advice and even mark! bad variable names, then you really need to fix all of them!!

Edit: Now I can see that even I did not fix all of them... but you should ;).

 

Second, make your live easy. Don't try to put all contentions into one loop. Make a simple if before the loop....

 

 

(defun c:AlignTextOnPolyline (/ *dist* dist height ss count ent obj chainage len point1 tangent-angle elevation layer min-length)
  (vl-load-com)
  
  ;; Variable globale pour la distance par défaut
  (setq *dist* 100.0)
  
  ;; Demander la longueur minimale de ligne pour le texte
  (setq min-length (getdist "\nLongueur minimale de ligne pour ajouter le texte (en mčtres) : "))
  
  ;; Fonction pour créer un texte aligné
  (defun _text (p tangent-angle height content layer)
    (entmake
      (list
	'(0 . "TEXT") ; Utiliser "TEXT" pour plus de simplicité
	'(100 . "AcDbEntity")
	(cons 8 layer) ; Calque de la polyligne
	(cons 10 p) ; Point d'insertion
	(cons 40 height) ; Hauteur du texte
	(cons 1 content) ; Contenu du texte
	(cons 50 tangent-angle) ; Angle de rotation (aligné sur la polyligne)
	(cons 7 (getvar "textstyle")) ; Style de texte courant
	)
      )
    )
  
  ;; Fonction pour calculer l'angle de la tangente ŕ la polyligne
  (defun _tangent-angle (obj dist)
    (angle '(0 0 0) (vlax-curve-getFirstDeriv obj (vlax-curve-getParamAtDist obj dist)))
    )
  
  ;; Fonction pour ajuster l'angle entre -90° et 90° (-p/2 et p/2)
  (defun _adjust-angle (angle)
    (cond
      ((> angle (/ pi 2)) (- angle pi)) ; Si l'angle est supérieur ŕ 90°, on soustrait 180°
      ((< angle (- (/ pi 2))) (+ angle pi)) ; Si l'angle est inférieur ŕ -90°, on ajoute 180°
      (t angle) ; Sinon, on conserve l'angle tel quel
      )
    )
  
  ;; Demander l'intervalle et la hauteur du texte
  (initget 6)
  (setq dist (getdist (strcat "\nIntervalle de texte <" (rtos *dist*) ">: ")))
  (setq *dist* (if dist dist *dist*)) ; Utiliser la valeur par défaut si l'utilisateur n'entre rien
  
  (setq height (getdist "\nHauteur du texte : "))
  
  ;; Sélectionner les polylignes
  (setq ss (ssget '((0 . "LWPOLYLINE")))) ; Sélectionner uniquement des polylignes légčres
  
  (if ss
    (progn
      (setq count 0)
      (repeat (sslength ss)
	(setq ent (ssname ss count)
	      obj (vlax-ename->vla-object ent)
	      chainage *dist*) ; Commencer ŕ l'intervalle spécifié
	
	;; Obtenir la longueur totale de la polyligne
	(setq len (vlax-curve-getDistAtParam obj (vlax-curve-getEndParam obj)))
	
	;; Extraire le calque de la polyligne
	(setq layer (cdr (assoc 8 (entget ent))))
	


	(if (< min-length len *dist*)

	  (progn

	    (setq chainage (/ len 2))

	    (setq point1 (vlax-curve-getPointAtDist obj chainage))
	    
	    ;; Calculer l'angle de la tangente (parallčle ŕ la polyligne)
	    (setq tangent-angle (_tangent-angle obj chainage))
	    
	    ;; Ajuster l'angle pour qu'il soit toujours entre -90° et 90°
	    (setq tangent-angle (_adjust-angle tangent-angle))
	    
	    ;; Extraire l'élévation (coordonnée Z) du point
	    (setq elevation (caddr point1))
	    
	    ;; Créer le texte aligné sur la polyligne avec l'élévation comme contenu
	    (_text point1 tangent-angle height (rtos elevation 2 2) layer)
	    )
	  
	  
	  ;; Placer les textes ŕ intervalles réguliers le long de la polyligne
	  (while (<= chainage len)
	    (setq point1 (vlax-curve-getPointAtDist obj chainage))
	    (if point1
	      (progn
		;; Vérifier la longueur du segment
		(setq segment-length (vlax-curve-getDistAtParam obj (vlax-curve-getParamAtDist obj chainage)))
		(if (>= segment-length min-length) ; Vérifier si la longueur du segment est suffisante
		  (progn
		    ;; Calculer l'angle de la tangente (parallčle ŕ la polyligne)
		    (setq tangent-angle (_tangent-angle obj chainage))
		    
		    ;; Ajuster l'angle pour qu'il soit toujours entre -90° et 90°
		    (setq tangent-angle (_adjust-angle tangent-angle))
		    
		    ;; Extraire l'élévation (coordonnée Z) du point
		    (setq elevation (caddr point1))
		    
		    ;; Créer le texte aligné sur la polyligne avec l'élévation comme contenu
		    (_text point1 tangent-angle height (rtos elevation 2 2) layer)
		    )
		  )
		;; Passer ŕ l'intervalle suivant
		(setq chainage (+ chainage *dist*))
		)
	      )
	    )
	  )
	(setq count (1+ count))
	)
      )
    (princ "\nAucune polyligne sélectionnée.")
    )
  (princ)
  )

 

0 Likes
Message 13 of 17

marie-laurence.pollet
Contributor
Contributor

ok , thank you very much, but I still have a part of texts upside-down?

I realize that I overestimated ChatGPT on this one...

0 Likes
Message 14 of 17

-didier-
Advisor
Advisor

Bonjour @marie-laurence.pollet 

 

I realize that I overestimated ChatGPT on this one...

In other words: It’s a real false good idea.

 

Amicalement

Éternel débutant.. my site for learning : Programmer dans AutoCAD

DA

EESignature

0 Likes
Message 15 of 17

ВeekeeCZ
Consultant
Consultant
Accepted solution

It's a simple math... IF (90 < alfa <= 270) THEN alfa+180. It does not mind alfa>=360.... but you can always add IF alfa>=360 THEN alfa-360.

And yes, it must be in radians.

 

  ;; Fonction pour ajuster l'angle entre -90° et 90° (-p/2 et p/2)
  (defun _adjust-angle (angle_)
    (if (and (> angle_ (* pi 0.5))
	     (<= angle_ (* pi 1.5)))
      (+ angle_ pi)
      angle_))

 

0 Likes
Message 16 of 17

marie-laurence.pollet
Contributor
Contributor

great, thanks a lot!

Do you know if this kind of command could be created in Dynamo? I don't know much about programming so I started to study Dynamo, and I wonder if it's actually easier or not.

Anyway thank you again for your time

0 Likes
Message 17 of 17

ВeekeeCZ
Consultant
Consultant

Well, I don't use Dynamo. But from what I've seen, it must be possible and it seems that this task is simple enough to be a good learning case.

And since Dynamo is designed "to be easy", so it should be easier. But... still, it's programming as any other and that is about logical thinking...