CadXP: Lister des blocs par le nom d'attributs - CadXP

Aller au contenu

Page 1 sur 1
  • Vous ne pouvez pas commencer un sujet
  • Vous ne pouvez pas répondre à ce sujet

Lister des blocs par le nom d'attributs chercher la liste des numéros de points pour trouver le dernier

#1 L'utilisateur est hors-ligne   jujugeometre 

  • Member
  • PipPip
  • Groupe : Membres
  • Messages : 19
  • Inscrit(e) : 06-décembre 20

Posté 07 janvier 2021 - 23:11

Bonsoir,

Je voudrais rechercher tous les blocs ayant un attribut nommé MAT pour dresser une liste de points afin de connaitre le dernier matricule à utiliser, sans forcément connaitre les noms de blocs, je pensais utiliser un jeu de sélection :

(setq entl  (ssget "_X" '((0 . "ATTRIB") (2 . "MAT"))))


mais si je poste une question c'est que ça ne marche pas.

j'avais essayé des entget sur des blocs mais je n'arrive pas à comprendre l'enchassement des entités les unes dans les autres. Bref, je suis bloqué, si quelqu'un a une idée, j'ai trainé sur des blogs mais les routines de manipulation de blocs font souvent appel à du visual et je ne connais pas ces fonctions. Merci d'avance.
Geometre - Autocad 2016 - Covadis v17.0
0

#2 L'utilisateur est hors-ligne   (gile) 

  • ceinture rouge et blanche 8em dan
  • Groupe : Moderateurs
  • Messages : 11 451
  • Inscrit(e) : 02-septembre 05

Posté 08 janvier 2021 - 07:49

Salut,
On ne peut filtrer directement avec les attributs. Il faut traiter la sélection a posteriori.
;; sélectionner tous les blocs avec attribut
(setq s (ssget "_X" '((0 . "INSERT") (66 . 1))))
;; parcourir le jeu de sélection pour écarter le blocs n'ayant pas d'attribut "MAT
(repeat	(setq i (sslength s))
  (setq b (ssname s (setq i (1- i))))
  (if (vl-catch-all-error-p
	(vl-catch-all-apply 'getpropertyvalue (list b "MAT"))
      )
    (ssdel b s)
  )
)

Gilles Chanteau - gileCAD -
Développements sur mesure pour AutoCAD
Image IPB
0

#3 L'utilisateur est hors-ligne   jujugeometre 

  • Member
  • PipPip
  • Groupe : Membres
  • Messages : 19
  • Inscrit(e) : 06-décembre 20

Posté 15 janvier 2021 - 22:47

Bonsoir,

Merci pour la routine, ca marche nickel, du coup j'ai ajouté une seconde boucle derrière pour rechercher le max des attributs et ça roule, ça m'a permis de découvrir le "getpropertyvalue" qui est terrible pour récupérer des infos.


;j'ai un jeu de sélection s avec tous les blocs dont l'attribut est MAT
 
;je dois rechercher les valeurs de ces attributs puis en chercher le max
(setq	i	0
  	maxlist	0)
(repeat (sslength 	s)
  	(setq		matr 	(atoi (getpropertyvalue (ssname s i) "MAT"));je récupère les valeurs des matricules
			i	(1+	i)
	  		listmat	(cons	matr	listmat) ;je construis la liste des tous les matricules
	)
  	(if	(> matr maxlist);je recherche la valeur max des attributs
	  (setq	maxlist	matr)
	  );if
);repeat





Voir le message(gile), le 08 janvier 2021 - 07:49 , dit :

Salut,
On ne peut filtrer directement avec les attributs. Il faut traiter la sélection a posteriori.
;; sélectionner tous les blocs avec attribut
(setq s (ssget "_X" '((0 . "INSERT") (66 . 1))))
;; parcourir le jeu de sélection pour écarter le blocs n'ayant pas d'attribut "MAT
(repeat	(setq i (sslength s))
  (setq b (ssname s (setq i (1- i))))
  (if (vl-catch-all-error-p
	(vl-catch-all-apply 'getpropertyvalue (list b "MAT"))
      )
    (ssdel b s)
  )
)


Geometre - Autocad 2016 - Covadis v17.0
0

#4 L'utilisateur est hors-ligne   jujugeometre 

  • Member
  • PipPip
  • Groupe : Membres
  • Messages : 19
  • Inscrit(e) : 06-décembre 20

Posté 19 janvier 2021 - 21:14

Bonsoir,

je reviens avec ma liste de points en fonction des attributs, une fois que j'ai la sélection des blocs avec un attribut MAT, je souhaite insérer un point sur chaque sommet mais avant je souhaite vérifier qu'il n'y a pas déja de points sur les sommets, donc à partir de la sélection s des points avec un attribut MAT, je la parcours pour vérifier que les sommets de la polyligne "listpts" n'existent pas et je veux supprimer ces points de "lispts" pour ensuite insérer les points uniquement sur les sommets restants.

je comprends pas ce qui bug dans mon traitement :

(repeat (sslength s)
  	(setq	coordbloc 	(list	(getpropertyvalue (ssname s ind1) "Position/X")	(getpropertyvalue (ssname s ind1) "Position/Y") ) ) ;je parcours les points avec MAT pour construire leurs coordonnées
  	(setq	ind1	(1+	ind1) )
	(vl-remove	coordbloc	listpts )		;je supprime l'entité de la liste des sommets
);repeat

Geometre - Autocad 2016 - Covadis v17.0
0

#5 L'utilisateur est hors-ligne   Luna 

  • ceinture bleue
  • Groupe : Membres
  • Messages : 190
  • Inscrit(e) : 27-février 20

Posté 20 janvier 2021 - 08:49

Coucou,

Premièrement, plutôt que de passer par (getpropertyvalue) pour récupérer les coordonnées X et Y du point d'insertion du bloc, je pense qu'il suffit de passer par un (cdr (assoc 10 (entget (ssname s ind1)))).
Ensuite, serait-il possible d'avoir un aperçu de la valeur de tes variables, listpts notamment. A quel endroit précisément as-tu une erreur ? Est-ce lors de la suppression des coordbloc de ta listpts ?

Bon après si je comprend bien, tu possèdes un plan topo avec les blocs TCPOINT (un point, un attribut ALT et un attribut MAT) et tu souhaites être en mesure de placer automatiquement ces blocs sur des polylignes existantes (issues d'un relevé) en incrémentant le matricule par rapport à la dernière valeur de matricule insérée et en plaçant ces blocs sur tous les sommets de polylignes (sauf s'il y a déjà un bloc à cet emplacement), c'est bien chat ?
Si c'est bien cela, alors comment définis-tu l'altitude (attribut ALT) lors de l'insertion ? S'agit-il de polylignes "LWPOLYLINE" ou bien "POLYLINE" 3D ?

Car en fonction du type de polyligne à lire, les sommets ne sont pas récupérables de la même manière..

Bisous,
Luna
0

#6 L'utilisateur est hors-ligne   jujugeometre 

  • Member
  • PipPip
  • Groupe : Membres
  • Messages : 19
  • Inscrit(e) : 06-décembre 20

Posté 20 janvier 2021 - 21:13

Bonjour,

Pour la routine c'est cela :

Citation

tu souhaites être en mesure de placer automatiquement ces blocs sur des polylignes existantes (issues d'un relevé) en incrémentant le matricule par rapport à la dernière valeur de matricule insérée et en plaçant ces blocs sur tous les sommets de polylignes (sauf s'il y a déjà un bloc à cet emplacement), c'est bien chat ?


sauf que la polyligne je la crée puisque c'est une reconstitution de contour et sur ce contour je veux insérer un bloc POINT à chaque sommet, sauf s'il en existe déjà un.

Pour l'attribut ALT, je ne m'en occupe pas, je travaille en 2D.

Je réalise la sélection de tous les blocs ayant un attribut MAT avec la routine de GILE

(setq 	s 	(ssget "_X" '((0 . "INSERT") (66 . 1))))
(repeat (setq i (sslength s))
  		(setq b (ssname s (setq i (1- i))))
  	(if 	(vl-catch-all-error-p
        	(vl-catch-all-apply 'getpropertyvalue (list b "MAT"))
      		)
    	(ssdel b s)
  	);if
	);repeat


puis je liste les sommets de la polyligne sur lesquels je souhaite ajouter des blocs :



(setq 	ptinser		(getpoint "\nCliquez dans le contour à immatriculer:"))
(command-s	"-contour"	ptinser	"")
(setq nompoly		(cdr (assoc -1 (entget (entlast)))))

(setq	liste-sommets '()
        ent-liste (entget nompoly)
        n 0)
(repeat (length ent-liste)
   	(if (= 10 (car (nth n ent-liste)))
      	(setq liste-sommets (cons (cdr (nth n ent-liste)) liste-sommets))
    	);if 
 	(setq n (1+ n))
 );repeat
(setq liste-sommets (reverse liste-sommets))




et je veux ensuite réaliser ma routine de suppression de "liste-sommets" en enlevant les points du jeu de sélection "s" s'ils existent dans les deux.
"s" est un jeu de sélection de blocs

"liste-sommets" est une liste de type:
Commande: !liste-sommets
((935.077 180.848) (905.821 188.627) (888.46 170.264) (904.042 159.066) (924.398 148.397))

la polyligne est bien LWPOLYLINE

Espérant avoir été assez clair, peux tu m'expliquer s'il y a une différence à parcourir la liste DXF ou à utiliser "getpropertyvalue"?
Geometre - Autocad 2016 - Covadis v17.0
0

#7 L'utilisateur est hors-ligne   Olivier Eckmann 

  • ceinture noire 3em dan
  • Groupe : Membres
  • Messages : 1 537
  • Inscrit(e) : 29-décembre 11
  • LocationLongjumeau (91)

Posté 22 janvier 2021 - 08:50

Bonjour,

Gilles a écrit un tas de routine pour manipuler les listes (dernière ligne du 1er message) ICI
dont une fonction "exclusive" qui devrait faire le boulot

;; EXCLUSIVE
;; Retourne une liste contenant les éléments appartenant exclusivement à l1

(defun exclusive (l1 l2)
  (if l1
    (if	(member (car l1) l2)
      (exclusive (cdr l1) l2)
      (cons (car l1) (exclusive (cdr l1) l2))
    )
  )
)



Olivier
0

#8 L'utilisateur est hors-ligne   Luna 

  • ceinture bleue
  • Groupe : Membres
  • Messages : 190
  • Inscrit(e) : 27-février 20

Posté 22 janvier 2021 - 09:38

Coucou,

Je me demande si...la raison ne vient pas plutôt du fait que l'on compare deux points (possédant chacun des coordonnées) et j'avais déjà eu un soucis similaire à cause notamment au géoréférencement de mes plans mais aussi parfois sur des écarts de précision...

J'avais essayé de solutionner le problème avec cette fonction mais je ne sais pas si cela te sera utile :
(defun pt-member (pt pt-list fuzz / d)

	(setq d (strlen (substr (vl-princ-to-string fuzz) (1+ (cond ((= (type fuzz) 'REAL) (vl-string-position (ascii ".") (vl-princ-to-string fuzz))) (t 0))))))
	(if (> (length pt) (length (car pt-list)))
		 (setq pt (reverse (cdr (reverse pt))))
	)
	(while (and pt-list
		    (not (equal (mapcar '(lambda (x) (rtos x 2 d)) pt) (mapcar '(lambda (x) (rtos x 2 d)) (car pt-list)) fuzz))
	       )
		(setq pt-list (cdr pt-list))
	)
	pt-list

)

L'idée ici c'est de vérifier si oui ou non, un point appartient à une liste de point, avec pt le point à comparer, pt-list la liste de point à comparer et fuzz le degré de précision. Plus le fuzz est précis (ex : 0.001) et plus tu veux t'assurer de la position exacte du point. Le retour est similaire à la fonction (member) qui retourne la liste restante à partir du point correspondant à la recherche.
C'était une idée comme une autre, développé en peu de temps donc probablement pas parfaite mais cela avait corrigé mon souci à l'époque.

Il serait également possible de comparer les points via (distance), bref un tas d'améliorations ^^

Petite remarque, tu n'as pas besoin d'écrire
(setq nompoly (cdr (assoc -1 (entget (entlast)))))
étant donné que (entlast) te renvoie déjà le même résultat donc petit raccourci avec
(setq nompoly (entlast))

et un autre raccourci, c'est la fonction (member) pour récupérer la liste des sommets d'une polyligne, car tu ne t'intéresse qu'au code DXF 10 donc boucler un (member) en tronquant à chaque passage dans la boucle la liste obtenue via (member), c'est plus rapide à l'exécution.

Bisous,
Luna
0

#9 L'utilisateur est hors-ligne   Luna 

  • ceinture bleue
  • Groupe : Membres
  • Messages : 190
  • Inscrit(e) : 27-février 20

Posté 22 janvier 2021 - 09:38

sumimasen double post.. >w<
0

#10 L'utilisateur est hors-ligne   jujugeometre 

  • Member
  • PipPip
  • Groupe : Membres
  • Messages : 19
  • Inscrit(e) : 06-décembre 20

Posté 27 janvier 2021 - 08:00

Bonjour,

Je n'ai pas réussi à utiliser ta routine, j'ai retravaillé de mon côté en construisant la liste des positions dans la liste que je parcours des points que je recherche en fonction d'une distance fixe, puis à partir de cette liste de positions je reconstruis ma liste de points en ayant exclu ceux qui sont à moins de 0.02m des existants. ca a l'air plus bourrin mais ca fonctionne, je te mets la routine :



;il faut que je compare la liste 's' des blocs dans le calque PIP-90 et la liste-sommets de la polyligne listpts
  (setq 	s 	(ssget "_X" '((0 . "INSERT") (8 . "PIP-90")))
	ind1	0
	entl	'()
	listpt	'()
	)

  (if	(/= nil s)
    (progn
  	(repeat	(sslength s)
		(setq	coordbloc	(list (car (cdr (assoc 10 (entget (ssname s ind1 ))))) (cadr (cdr (assoc 10 (entget (ssname s ind1))))))
			ind1	(1+ ind1)
			ind2	0
			);setq
		(repeat	(length	listpts)
			(if	(< (distance 	coordbloc 	(nth	ind2 	listpts) ) 	0.02) 	;je veux rechercher les points qui sont à moins de 2 cm des 'coordbloc' existants
		   		(setq	entl	(cons	ind2	entl))					;je construis la liste des indices de points communs pour ensuite les supprimer dans 'listpts'
			  );if
			(setq   ind2	(1+ ind2) )
		  );repeat
 	);repeat
	(setq	i	0
		n	0
		)
    	(repeat	(- (length	 listpts) 1 )
		;je veux construire la liste 'listpt' en insérant chacun des éléments de 'listpts' sauf ceux qui sont dans la liste 'entl'
		(if ( /= i (nth n entl) )
			 (setq listpt (cons (nth i listpts) listpt )
			      i	(1+ i)
			      ) )
		
		 (if ( = i (nth n entl))	
			(setq n	(1+ n)
			      i	(1+ i)
			      ) )
	  );repeat
	(setq listpts (reverse listpt ) )
      );progn	
	
    );if 



Je ne suis pas trop sur de la seconde boucle 'repeat' avec les deux 'if' qui se succèdent, j'avais essayé avec mapcar qui me semblait adapté mais je n'ai pas réussi à écrire quelquechose qui tourne.
Geometre - Autocad 2016 - Covadis v17.0
0

#11 L'utilisateur est hors-ligne   Olivier Eckmann 

  • ceinture noire 3em dan
  • Groupe : Membres
  • Messages : 1 537
  • Inscrit(e) : 29-décembre 11
  • LocationLongjumeau (91)

Posté 27 janvier 2021 - 09:22

Bonjour,

A partir des 2 fonctions de Giles : EXCLUSIVE et MEMBER-FUZZ on peut créer EXCLUSIVE-FUZZ qui permet de renvoyer une liste exclusive avec une tolérance
J'en ai profité pour mettre une fonction POINT2D qui renvoie un point 2D à partir d'un point 3D
;; MEMBER-FUZZ
;; Comme MEMBER avec une tolérance dans la comparaison

(defun member-fuzz (expr lst fuzz)
  (while (and lst (not (equal (car lst) expr fuzz)))
    (setq lst (cdr lst))
  )
  lst
)

;; EXCLUSIVE
;; Retourne une liste contenant les éléments appartenant exclusivement à l1

(defun exclusive (l1 l2)
  (if l1
    (if (member (car l1) l2)
      (exclusive (cdr l1) l2)
      (cons (car l1) (exclusive (cdr l1) l2))
    )
  )
)

;; EXCLUSIVE-FUZZ
;; Retourne une liste contenant les éléments appartenant exclusivement à l1 avec une tolérance de comparaison

(defun exclusive-fuzz (l1 l2 fuzz)
  (if l1
    (if (member-fuzz (car l1) l2 fuzz)
      (exclusive-fuzz (cdr l1) l2 fuzz)
      (cons (car l1) (exclusive-fuzz (cdr l1) l2 fuzz))
    )
  )
)

;; retourne un point 2D à partir d'une liste de 2 ou 3 coordonnées
(defun Point2D (pt)
  (list (car PT) (cadr PT))
)




A partir de là ta routine se simplifie pas mal


  ;il faut que je compare la liste 's' des blocs dans le calque PIP-90 et la liste-sommets de la polyligne listpts
  (setq s   	(ssget "_X" '((0 . "INSERT") (8 . "PIP-90")))
        ind1    0
        listpt  '()
	dTolr   0.02
        )

  (if   s
    (progn
      (repeat (sslength s)
        (setq coordbloc (Point2D (cdr (assoc 10 (entget (ssname s ind1 )))))
              ind1      (1+ ind1)
        );setq
  	
   	(setq listpt (append (listpt (list coordbloc))))
      
      );repeat

      ;renvoie les éléments de listpts qui ne sont pas dans listpt à la tolérance près
      (setq listpts-restante (exclusive-fuzz listpts listpt dTolr))
      
    );progn   
        
  );if 




Je l'ai écrite à l'arrache sans tester donc code à vérifier

Olivier
0

#12 L'utilisateur est hors-ligne   jujugeometre 

  • Member
  • PipPip
  • Groupe : Membres
  • Messages : 19
  • Inscrit(e) : 06-décembre 20

Posté 27 janvier 2021 - 09:33

Voir le messageOlivier Eckmann, le 27 janvier 2021 - 09:22 , dit :




;; EXCLUSIVE-FUZZ
;; Retourne une liste contenant les éléments appartenant exclusivement à l1 avec une tolérance de comparaison

(defun exclusive-fuzz (l1 l2 fuzz)
  (if l1
    (if (member-fuzz (car l1) l2 fuzz)
      (exclusive-fuzz (cdr l1) l2 fuzz)
      (cons (car l1) (exclusive-fuzz (cdr l1) l2 fuzz))
    )
  )
)




Je l'ai écrite à l'arrache sans tester donc code à vérifier

Olivier


Bonjour,

Je te remercie pour ce retour, je vais tester ca, ca simplifie énormément, je débute, je patauge un peu.

Il y a un point que je ne comprends pas dans les fonctions et j'avais vu ca dans pas mal d'exemples de routines, quand tu définis la fonction entre des bornes 'defun', comment tu peux utiliser cette fonction 'dans elle même' en quelque sorte?
Geometre - Autocad 2016 - Covadis v17.0
0

#13 L'utilisateur est hors-ligne   Luna 

  • ceinture bleue
  • Groupe : Membres
  • Messages : 190
  • Inscrit(e) : 27-février 20

Posté 27 janvier 2021 - 09:35

Coucou,

Concernant le (mapcar) pour la seconde boucle je pense que ceci correspond à ce que tu cherches à faire :
(setq listpt (vl-remove-if '(lambda (x) (member x entl)) listpts))


Bisous,
Luna
0

#14 L'utilisateur est hors-ligne   Olivier Eckmann 

  • ceinture noire 3em dan
  • Groupe : Membres
  • Messages : 1 537
  • Inscrit(e) : 29-décembre 11
  • LocationLongjumeau (91)

Posté 27 janvier 2021 - 12:22

Voir le messagejujugeometre, le 27 janvier 2021 - 09:33 , dit :

Bonjour,

Je te remercie pour ce retour, je vais tester ca, ca simplifie énormément, je débute, je patauge un peu.

Il y a un point que je ne comprends pas dans les fonctions et j'avais vu ca dans pas mal d'exemples de routines, quand tu définis la fonction entre des bornes 'defun', comment tu peux utiliser cette fonction 'dans elle même' en quelque sorte?


Ca s'appelle la récursivité et ça ne pose pas de souci au niveau du langage (mais du cerveau oui!).
Il suffit d'une condition pour sortir de la boucle de récursivité.

l'exemple le plus couramment utilisé pour présenter ce concept de récursivité, c'est la fonction factorielle
n! = n * (n-1)! et 0! = 1 (condition de sortie pour arrêter l'empilage)

Olivier
0

#15 L'utilisateur est hors-ligne   (gile) 

  • ceinture rouge et blanche 8em dan
  • Groupe : Moderateurs
  • Messages : 11 451
  • Inscrit(e) : 02-septembre 05

Posté 27 janvier 2021 - 19:49

Salut,

Pour le fonctions récursives, tu peux voir la section 13.3 de Introduction à AutoLISP téléchargeable sur cette page.
Gilles Chanteau - gileCAD -
Développements sur mesure pour AutoCAD
Image IPB
0

#16 L'utilisateur est hors-ligne   jujugeometre 

  • Member
  • PipPip
  • Groupe : Membres
  • Messages : 19
  • Inscrit(e) : 06-décembre 20

Posté 28 janvier 2021 - 08:00

Voir le message(gile), le 27 janvier 2021 - 19:49 , dit :

Salut,

Pour le fonctions récursives, tu peux voir la section 13.3 de Introduction à AutoLISP téléchargeable sur cette page.


Merci pour cet envoi, je vais regarder cela, tout un monde de fonctions qui s'ouvre à moi, la compréhension du fonctionnement n'est pas aisée pour un novice, le factoriel c'est tellement simple que ca en est un peu trivial alors que l'application aux autres fonctions est pas évidente.
Geometre - Autocad 2016 - Covadis v17.0
0

Partager ce sujet :


Page 1 sur 1
  • Vous ne pouvez pas commencer un sujet
  • Vous ne pouvez pas répondre à ce sujet

1 utilisateur(s) en train de lire ce sujet
0 membre(s), 1 invité(s), 0 utilisateur(s) anonyme(s)