Communauté
AutoCAD – tous produits - Français
Bienvenue sur les forums AutoCAD d’Autodesk. Partagez vos connaissances, posez des questions, et explorez les sujets AutoCAD populaires.
annuler
Affichage des résultats de 
Afficher  uniquement  | Rechercher plutôt 
Vouliez-vous dire : 

Création d'un lisp pour placer des points altimétriques

30 RÉPONSES 30
Répondre
Message 1 sur 31
Mélanie_
3276 Visites, 30 Réponses

Création d'un lisp pour placer des points altimétriques

Bonjour,

 

Je suis début en programmation lisp et pour mon projet de fin d'études il m'a été demandé de créer un programme lisp pour placer des points altimétriques , certains de ces points devront être lié entre eux. Une fois les points placés la donnée de leur valeur, qui sera mis dans un attribut, devra être enregistrer dans un excel. Et que je puisse directement changer les valeurs de ces points dans le excel ce qui entraînera une mise à jour automatique dans mon plan AutoCAD.

 

Voici le début de mon lisp :

 

(defun c:alti ()

;; Création de variable  

(setq cc (getvar "CLAYER"))  

(setq gg (getvar "SCU"))  

(setq os (getvar "OSMODE"))

 

;Ne pas afficher dans la barre de commande toutes les étapes de calcul    

 (setvar "cmdecho"0)

 

 (setvar "ATTDIA" 0)     

 

;;Mise à zéro des variables

 (setq ptbase 0)

 (setq pt1 0)

 (setq x1 0)  

 (setq y1 0)

 (setq pt2 0)  

 (setq pt3 0)

 (setq pt4 0)

 (setq pt5 0)

 (setq pt6 0)

 (setq pt7 0)

 (setq pt8 0)

 (setq valeur 0)

 

 ;Création du calque   

  (command "-calque" "E" "ICI-PT Alti" "co" "1" "ICI-PT Alti" "tl" "continuous" "ICI-PT Alti" "")

 

 ;Si le bloc "blocaltimel" n'est pas présent dans le dessin  

;Tblsearch, recherche du bloc "blocaltimel"

(if (not (tblsearch "BLOCK" "blocaltimel")) ;Si la condition est vraie  

(progn

  ;Accrochage objet par le point nodal    

(setvar "OSMODE" 😎

 

  ;Accrochage objet par l'objet le plus proche   

(setvar "OSMODE" 512)

 

 ;Point d'insertion du point de base

(setq ptbase (getpoint "\nSélectionner le point de départ :"))

 

 ;Création du point croix

(setq pt1 ( list  (+ (car ptbase) 5)      (+ (cadr ptbase) 5)    ) )

(setq pt2 ( list (- (car ptbase) 5)      (- (cadr ptbase) 5)    ) )

(command "_pline" pt1 pt2 "c" ) (setq ent (entlast))

 

(setq pt3 ( list  (- (car ptbase) 5)      (+ (cadr ptbase) 5)    ) )

(setq pt4 ( list (+ (car ptbase) 5)      (- (cadr ptbase) 5)    ) )

(command "_pline" pt3 pt4 "c" )  (setq ent1 (entlast))

 

 ;Création du cercle du point croix

(command "_circle" ptbase 2.5)

(setq ent2 (entlast))

 

(command "-scu" "3" ptbase (entlest "\nSélectionner la ligne :") ) (command "_erase" cir "")

 

 ;Valeur de l'attribut du bloc du 1er point

(setq valeur (getdist "\n Donner la valeur de départ :"))      

 

;Création de l'attribut "valeur"   

(command "_attdef" "R" "R" "" "VALEUR" "Valeur" "" pt1 5 0)   (setq ent3 (entlast))

 

  ;Création du bloc puis insertion de ce même bloc  

 (command "_block" "blocaltimel" ptbase ent ent1 ent2 ent3 "")  

 (command "_insert" "blocaltimel" ptbase 1 1 0 (rtos valeur 2 2) "")   

 );; End progn   

 

 ;Sinon  (progn

 ;Point d'insertion du point de base

(setq ptbase (getpoint "\n Point de départ :"))

 

 ;Valeur de l'attribut du bloc du 1er point

(setq valeur (getdist "\n Donner la valeur de départ :"))

 

 ;Insertion du premier bloc

(command "_insert" "blocaltimel" ptbase 1 1 0 (rtos valeur 2 2)"")

 

 );; End progn

);; End if

 

;Récupérer les cordonnées du point créer

(setq name (entlast))

 

; Orienter le SCU

(command "_circle" ptbase 5) (setq cir(entlast))

(command "-scu" "3" ptbase (entlest "\nSélectionner la ligne :") cir "" ) (command "_erase" cir "")

 

;Sélectionner le bloc précédent pour avoir son nom logique

(setq pt5(entget name)) (setq pt6 (cdr (assoc 10 pt5)))

 

;Prendre les coordonnées de l'origine du bloc

(setq x1 (car pt6)) ;Coordonné de x

(setq y1 (cadr pt6)) ;Coordonné de y

 

 ;Points suivant

(setq pt7 (getdist "\nPoint d'insertion :"))

(setq pt8 (list    x1    (+ y1 pt7)    ) )

 

 ;Valeur des nouveaux points

(setq valatt (+ valeur pt7))

 

;; Insertion du bloc aux points

(command "_insert" "blocaltimel" pt8 1 1 0 (rtos valatt 2 2) "")

 

(while T ; Tant que c'est vrai (T=true)

;Récupérer les cordonnées du point créer

(setq name2 (entlast))

 

;Sélectionner le bloc précédent pour avoir son nom logique

(setq pt5(entget name2)) (setq pt6 (cdr (assoc 10 pt5)))

 

;Prendre les coordonnées de l'origine du bloc

(setq x1 (car pt6)) ;Coordonné de x

(setq y1 (cadr pt6)) ;Coordonné de y

 

 ;Points suivant

(setq pt7 (getdist "\nPoint d'insertion :"))

(setq pt8 (list    x1    (+ y1 pt7)    ) )

 

 ;Valeur des nouveaux points

(setq valatt (+ valeur pt7))

 

;; Insertion du bloc aux points

(command "_insert" "blocaltimel" pt8 1 1 0 (rtos valatt 2 2) "")

 

);; End while

 

(setvar "CLAYER" cc)

(setvar "OSMODE" os)

(setvar "SCU" gg)

 

);; End defun

 

 

Mais avant de continuer à écrire mon lisp, je voudrais régler quelques petits problèmes.

Je voudrais savoir comment conserver le SCU pour le remettre à la fin, j'essaye avec (setq gg (getvar "SCU")) .... (setvar "SCU" gg) mais ça n'a pas l'air de fonctionner.

Le premier (zone en rouge) est que je n'arrive pas à changer le SCU, je voudrais que le X de mon SCU se place le long de la ligne que l'utilisateur sélectionnera et le point (qui donnera la direction) soit le point d'intersection entre le cercle créé précedemment et la ligne que l'on vient de sélectionner.

Pour le Y, il devra être perpendiculaire au X et être TOUJOURS positif.

Je voulais utiliser la comande : command "-scu" "3" "ptbase" ....; mais j'arrive pas à prendre l'intersection.

 

J'ai un autre problème c'est la valeur de mon attribut n'apparaît pas sur tous les AutoCAD, en moi et en cours il apparaît (version 2014) mais quand j'essaye de l'utiliser sur l'ordinateur de mon travail (version 2013) la valeur de l'attribut n'apparaît pas...

J'ai essayé avec ATTMODE mais cela ne change rien.

 

Et après je voudrais savoir comment mettre les données de mes points dans un excel et pouvoir faire une mise à jour automatique du excel vers AutoCAD comme je l'ai expliquée précedemment.

 

Il y a peut-être d'autres erreurs dans mon lisp que je n'ai pas vue.

Je ne sais pas si j'ai été assez claire, il faut que le lisp reste assez simple car après je dois être capable d'expliquer chaque lignes.

 

Merci d'avance

Cordialement

 

30 RÉPONSES 30
Message 21 sur 31
Mélanie_
en réponse à: _gile

Merci beaucoup, j'ai réussit à le faire fonctionner.

 

Pourrais-tu m'expliquer comment on fait la mise à jour automatique des attributs ? Car une fois que j'ai copier mes blocs j'aimerais modifier la valeur de l'attribut sans modifier les valeurs des premiers attributs

Message 22 sur 31
_gile
en réponse à: Mélanie_

Si tu as une version 2012 ou supérieure, tu peux utiliser les nouvelles fonctions GetPropertyValue et SetPropertyValue.

Pour récupérer la valeur de l'attribut dont l'étiquette est : "VALEUR" dans le bloc assigné à la variable 'bloc'

(GetPropertyValue bloc "VALEUR")

Pour attribuer la valeur "toto" à l'attribut dont l'étiquette est : "VALEUR" dans le bloc assigné à la variable 'bloc'

(SetPropertyValue bloc "VALEUR" "toto")

 

Si tu n'as pas 2012, ça va être plus compliqué, il va falloir récupérer l'entité attribut à l'intérieur de bloc avec entnext et traiter directement cette entité par ses propriétés DXF avec entmod.

entnext retourne le nom d'entité (ENAME) de l'entité créé juste après l'entité qui lui est passée en argument. Dans le cas de blocs avec attribut(s)

(entnext bloc) retourne le premier attribut dans le bloc (pour les attributs suiavnt, il faut faire une boucle avec while).

Tu as de la chance, ton bloc n'a qu'un attribut.

Donc pour récupérer l'attribut, on fait :

(setq att (entnext bloc))

 On obtient les propriétés DXF de l'entité en faisant :

(setq propList (entget att))

 La valeur de l'attribut correspond au code de groupe 1 dans la liste :

(setq val (cdr (assoc 1 propList)))

 Pour modifier une valeur d'attribut, il faut passer à entmod la liste de propriétés DXF modifiée. Pour modifier la liste, il faut substituer au groupe 1 existant (c'est une paire pointée du type : (1 . "laValeur")) un nouveau groupe 1 avec la fonction subst.

(setq porpList (subst (cons 1 "nouvelleValeur") (asso 1 propList) propList))
(entmod propList)

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 23 sur 31
Mélanie_
en réponse à: Mélanie_

  J'ai une version 2014, du coup j'ai essayer GetPropertyValue et SetPropertyValue. Vue que GetPropertyValue permet de prendre la valeur de l'attribut, dans SetPropertyValue on pourrait remplacer la nouvelle par celle de l'ancien + 10 par exemple, non ?

 

	;On le sélectionne le point où seront placés des nouveaux blocs parallèle aux anciens
	(setq pt8 (getpoint "\nSélectionner le point suivant à l'axe :"))
(setq dis (getdist "\nDonner l'écart par rapport au point de base :")) ;Si (if ;Blocs n'est pas vide (/= blocs nil) ;Alors (progn (foreach bloc blocs ;On copie les blocs qui sont dans la liste "Blocs" (command "_copy" bloc "" ptbase pt8 "") (setq lst (entlast)) (setq val (GetPropertyValue lst "VALEUR")) (setq nvval (+ val dis)) (SetPropertyValue lst "VALEUR" nvval) );End foreach );end progn nil );End if

 Car je voudrais que toute les nouvelles valeurs ne deviennent pas que 10 ou "toto".


  Dès que j'enlève les guillemets à la nouvelle valeur pour mettre un nombre cela me met une erreur.

Message 24 sur 31
_gile
en réponse à: Mélanie_

Encore un fois (et je risque de finir par me lasser) choisis des noms de variables qui correspondent à ce que contient la variable : pt, pt1, pt2 pour des points, lst, lst1, lst2, pour des listes, ptLst pour une liste de points, mais pas :

(setq lst (entlast))

(entlast) retourne un nom d'entité (type ENAME) donc fait plutôt :

(setq ent (entlast))

ou

(setq bloc (entlast))

ton code sera ainsi beaucoup plus lisible et compréhensible, même pour toi.

 

Une valeur d'attribut est toujours une chaîne de caratère (type STR)

L'expression :

(GetPropertyValue lst "VALEUR")

retourne donc un chaîne de caractère qu'il va falloir convertir en nombre (réel ou entier) pour pouvoir lui ajouter 10, puis convertir le résultat en chaîne pour pouvoir le passer en argument à SetPropertyValue.

 

Regarde l'aide pour les fonctions de conversion de chaîne en nombre : atoi et atof  et pour les conversion de nombre en chaîne itoa et rtos (que tu as déjà utilisé).

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 25 sur 31
Mélanie_
en réponse à: Mélanie_

Merci beaucoup Gile pour ton aide, mon lisp fonctionne bien.

Maintenant je vais essayer de l'améliorer.

Je voulais savoir comment on fait si un jour on veut modifier d'un seul coup toutes les valeurs d'attribut, juste en modifiant la valeur du premier attribut à la main et que du coup les autres changent automatiquement.

Par exemple 3 jours après avoir fait mon plan avec ma fonction alti, je veux changer les valeurs de mes attributs car elles sont toutes augmentées de 5.

Il y a-t-il une possibilité de faire ceci ?

Message 26 sur 31
_gile
en réponse à: Mélanie_

Ce que tu demandes est possible en utilisant les réacteurs. Mais la manipulation des réacteurs demande une maitrise du LISP (et des fonctions Visual LISP) qui dépasse, à mon avis, largement le niveau que tu semble avoir.

 

Par contre, tu peux essayer de faire un commande qui demande à l'utilisateur la valeur à ajouter (elle peut être négative) puis, le programme sélectionne tous les blocs et modifie leurs attributs en conséquence.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 27 sur 31
Mélanie_
en réponse à: _gile

Désolée de répondre que maintenant mais j'ai été assez occuper dernièrement.

Si je comprend mieux en créant une nouvelle fonction qui utiliserai le même principe que :

(GetPropertyValue bloc "VALEUR")
(SetPropertyValue bloc "VALEUR" "toto")

 Il va forcément retrouver les bons blocs ?

Ou il faut que je rappelle à un moment le nom de mon bloc ?

Et que si on reprend le nom de la liste cré dans l'autre fonction cela marche ?

 

Car j'ai commencé à essayer mais apparemment il ne trouve pas les blocs qui sont sur mon dessin

 

Merci d'avance 

Message 28 sur 31
Mélanie_
en réponse à: Mélanie_

Bonjour, 

Cela fait plusieurs jours que j'essaye de faire un lips pour mettre à jour automatiquement les attributs de mes blocs, en vain...

Je n'arrive pas à utiliser correctement les DXF, je me mélange un peu...

 

Est-ce quelqu'un pourrait aider au moins pour le début ?

 

Merci d'avance

Message 29 sur 31
_gile
en réponse à: Mélanie_

Salut,

 

Essaye d'expliquer le plus clairement possible ce que tu souhaites faire. Décrire une procédure de manière logique est la première étape incontournable du développement. Il ne faut jamais perdre de vur que programmer c'est s'adresser à une machine qui, quoi que dotée d'une grande puissance de calcul, est parfaitement dénuée d'intelligence et ne fera que ce qu'on lui demande à condition de lui fournir tous les éléments nécessaire pour le faire.

 

Et poste ce que tu as déjà écrit comme code en essayant de faire en sorte que le code soit propre et lisible par ceux qui seraient susceptibles de t'aider.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 30 sur 31
_gile
en réponse à: _gile

Je n'ai pas le temps de faire plus que de te donner un code tout fait avec des commentaires.

 

(defun c:MajVal	(/ add jeuSel index bloc valAtt valNum) ; déclaration des variables locales

  ;; on demande à l'utilisateur de spécifier la valeur à ajouter (ou soustraire)
  ;; et le programme ne continue que si l'utilisateur donne une réponse
  (if (setq add (getreal "\nEntrez la valeur à ajouter à tous les attributs: "))
    (progn

      ;; sélection automatique de tous les blocs "blocaltimel" de l'espace objet
      (setq jeuSel (ssget
		     "X"		      ; option "X" pour tout sélectionner
		     (list		      ; filtre de sélection :
		       (cons 0 "INSERT")      ; référence de bloc
		       (cons 2 "blocaltimel") ; nom du bloc
		       (cons 410 "Model")     ; espace objet
		     )
		   )
      )

      ;; on vérifie que des blocs "blocaltimel" ont été sélectionnés
      (if jeuSel

	;; alors...
	(progn
	  ;; initialisation de l'index
	  (setq index 0)

	  ;; tant que le jeu de sélection contient une entité à l'index spécifié
	  (while (setq bloc (ssname jeuSel index))

	    ;; on récupère la valeur de l'attribut "VALEUR"
	    (setq valAtt (getPropertyValue bloc "VALEUR"))

	    ;; si la valeur représente bien une valeur numérique...
	    (if	(setq valNum (distof valAtt))
	      ;; ...on modifie la valeur de l'attibut
	      (setPropertyValue bloc "VALEUR" (rtos (+ valNum add)))
	    )

	    ;; on incrémente l'index pour passer au bloc suivant
	    (setq index (1+ index))
	  )
	)

	;; sinon...
	(prompt "\nAucun bloc 'blocaltimel' dans le dessin.")
      )
    )
  )
  (princ) ;_ sortie silencieuse
)

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 31 sur 31
Mélanie_
en réponse à: _gile

Merci beaucoup, c'est vraiment très gentil

Vous n'avez pas trouvé ce que vous recherchiez ? Posez une question à la communauté ou partagez vos connaissances.

Publier dans les forums