Bonjour,
J'ai un fichier avec des blocs (semblant être des lignes horizontales et verticales) et qui forment donc un cadrillage inégal. Je voudrais sélectionner toutes les intersections entre ces blocs et ajouter un bloc par dessus (une croix par exemple) et un morceau de texte (du style A1, A2 ... B1, B2...) sachant que les blocs n'ont pas tous la même longueur et donc pas tous le même nombre d'intersections.
J'ai trouvé deux trois choses sur les interesctions de lignes mais rien sur les blocs. Quant à mon niveau de LISP, je suis un débutant total, je n'avais jamais utilisé un tel langage auparavant.
Si donc, vous pouvez faire simple/clair dans vos réponse, je vous en serai gré =).
Merci d'avance pour vos lumières et vos conseils.
Résolu ! Accéder à la solution.
Résolu par _gile. Accéder à la solution.
Résolu par _gile. Accéder à la solution.
Hello
+1 avec Gilles
Ce que j'ai compris : Desires tu une detection des Intersections entre les "Bounding Box" (Rectangles englobants) de tous les Blocs de la selection classique AutoCAD avec Insertion automatique d'un nouveau Bloc specifique au centre (Centroid des N Bounding Box en Intersections) !?
Ce nouveau Bloc dispose d'un attribut qui va s'incrementer automatiquement ...
Apres on traite en Manuel (si necessaire) ... en voyant OU sont ces nouveaux Blocs "de detection" ...
Regards, Patrice
Patrice BRAUD
Merci beaucoup pour vos réponses,
pour clarifier mes propos, voici comment j'imaginais les choses:
- On démarre d'en haut à gauche, on commence par descendre pour capter la première colonne de noeuds
- Detection de l'intersection des deux blocs
- On nomme le noeud A1 (A est la colonne, 1 le numéro de l'intersection), on met un bloc avec une croix sur l'intersection et "A1"
- On descend, on en trouve un autre, il se nomme alors A2 etc...
...
- La seconde colonne commence par BX avec X correspondant au numéro de la colonne A à sa gauche.
Ce qui pourrait donc donner par exemple:
A1 C1
A2 B2 C2
A3 B3 C3
>Est-ce que cela vous semble plus clair ? (et faisable ?)
NB: J'ai attaché un fichier comme demandé. Vous verrez qu'il y a des emplacement sans croisement de blocs.
Merci d'avance pour vos réponses et votre expertise.
Salut,
La problématique dépasse le niveau débutant en LISP, ne serait-ce que pour récupérer les coordonnées de la ligne contenue dan le bloc.
Comme je trouvais le problème rigolo, j'ai essayé de faire un truc.
Le LISP fonctionne avec un bloc nommé "INTERS" qui a un attribut. Tu peux utiliser le dwg attaché. Tu peux aussi te faire ton propre bloc et au besoin renommer le bloc cans le LISP.
(defun c:BLKINTERS (/ ss n blk line vert horiz dia req echo pt) (if (setq ss (ssget "_X" '((0 . "INSERT") (2 . "`*U*,bande_6inchs_centered") (410 . "Model")))) (progn (repeat (setq n (sslength ss)) (setq blk (ssname ss (setq n (1- n)))) (if (= (getpropertyvalue (getpropertyvalue blk "BlockTableRecord") "Name") "bande_6inchs_centered" ) (progn (setq line (list (getpropertyvalue blk "Position") (polar (getpropertyvalue blk "Position") (- (getpropertyvalue blk "Rotation") (* pi 0.5)) (getpropertyvalue blk "AcDbDynBlockPropertyDistance1") ) ) ) (if (equal (caar line) (caadr line) 1e-8) (setq horiz (cons line horiz)) (setq vert (cons line vert)) ) ) ) ) ) (setq ih 64 iv 0 horiz (mapcar '(lambda (l) (cons (chr (setq ih (1+ ih))) l)) (vl-sort horiz '(lambda (p1 p2) (< (caar p1) (caar p2)))) ) vert (mapcar '(lambda (l) (cons (itoa (setq iv (1+ iv))) l)) (vl-sort vert '(lambda (p1 p2) (> (cadar p1) (cadar p2)))) ) dia (getvar 'attdia) req (getvar 'attreq) echo (getvar 'cmdecho) ) (setvar 'attdia 0) (setvar 'attreq 1) (setvar 'cmdecho 0) (vl-catch-all-apply '(lambda () (command "_.undo" "_begin") (foreach h horiz (foreach v vert (if (setq pt (inters (cadr h) (caddr h) (cadr v) (caddr v) T)) (command "_.insert" "inters" pt 1.0 1.0 0.0 (strcat (car h) (car v))) ; changer le nom du bloc ) ) ) ) ) (command "_.undo" "_end") (setvar 'attdia dia) (setvar 'attreq req) (setvar 'cmdecho echo) ) (princ) )
Le LISP ci dessus présente des dysfonctionnements dans l'affecttion des indices de colonne et rangée.
Utilise celui-ci qui comporte aussi quelques optimisations et des commentaires
(defun c:BLKINTERS (/ *error* dia req echo os ss n blk line vert horiz ih iv hy vx pt) ;; substitution locale de la fonction *error* (defun *error* (msg) (and msg (/= msg "Fonction annulée") (princ (strcat "erreur: " msg)) ) (command-s "_.undo" "_end") ;; restauration des valeurs initiales (setvar 'attdia dia) (setvar 'attreq req) (setvar 'osmode os) (setvar 'cmdecho echo) (princ) ) ;; valeurs initiales des variables système (setq dia (getvar 'attdia) req (getvar 'attreq) echo (getvar 'cmdecho) os (getvar 'osmode) ) ;; sélection des blocs "bande_6inchs_centered" et des blocs anonymes (if (setq ss (ssget "_X" '((0 . "INSERT") (2 . "`*U*,bande_6inchs_centered") (410 . "Model")))) (progn ;; traitement de la sélection (repeat (setq n (sslength ss)) (setq blk (ssname ss (setq n (1- n)))) ;; contrôle du nom du bloc (blocs anonymes) (if (= (getpropertyvalue (getpropertyvalue blk "BlockTableRecord") "Name") "bande_6inchs_centered" ) (progn ;; constitution d'une liste avec les points de départ et de fin de la ligne (setq line (list (getpropertyvalue blk "Position") (polar (getpropertyvalue blk "Position") (- (getpropertyvalue blk "Rotation") (* pi 0.5)) (getpropertyvalue blk "AcDbDynBlockPropertyDistance1") ) ) ) ;; ajout de la sous-liste à la liste des lignes horizontales ou verticales (if (equal (caar line) (caadr line) 1e-6) (setq vert (cons line vert)) (setq horiz (cons line horiz)) ) ) ) ) ;; tri de la liste des lignes horizontales par Y décroissant ;; et de la liste des lignes vetrticales par X croissant (setq horiz (vl-sort horiz '(lambda (p1 p2) (> (cadar p1) (cadar p2)))) vert (vl-sort vert '(lambda (p1 p2) (< (caar p1) (caar p2)))) iv 65 ; index de départ des colonnes (ascii "A") ih 1 ; index de départ des rangées hy (cadaar horiz) ; Y maximum vx (caaar vert) ; X minimum ;; ajout de l'index aux lignes horizontales horiz (mapcar '(lambda (l) (cons (if (equal hy (setq hy (cadar l)) 1e-6) (itoa ih) (itoa (setq ih (1+ ih))) ) l ) ) horiz ) ;; ajout de l'index aux lignes verticales vert (mapcar '(lambda (l) (cons (if (equal vx (setq vx (caar l)) 1e-6) (chr iv) (chr (setq iv (1+ iv))) ) l ) ) vert ) ) (command-s "_.undo" "_begin") ;; affectation des variables système (setvar 'cmdecho 0) (setvar 'osmode 0) (setvar 'attdia 0) (setvar 'attreq 1) ;; pour chaque ligne verticale (foreach v vert ;; pour chaque ligne horizontale (foreach h horiz ;; insertion du bloc s'il y a intersection ;; affectation de la valeur de l'attribut avec les indices des lignes (if (setq pt (inters (cadr h) (caddr h) (cadr v) (caddr v) T)) (command-s "_.insert" "inters" pt 1.0 1.0 0.0 (strcat (car v) (car h))) ) ) ) ) ) (*error* nil) )
Bonjour Gilles,
Merci beaucoup pour ce code (!), effectivement un débutant comme moi n'en aurait pas été capable...pour un début ça aurait été un peu sec...
J'ai donc testé cela avec le schéma que j'avais posté et il s'avère que les blocs se collent parfaitement à leur place, donc aux intersections de blocs. Cependant, j'ai dû raté une étape car aucun attribut (A1, A2, ... ) ne s'affiche à côté des blcos fraichement créés. Comment rectifier cela ?
Je pense que le nom de l'attribut se définit à travers:
(strcat (car v) (car h))
mais je ne le retrouve nul part sur le dessin.
D'avance merci pour vos bons conseils,
NB: en pièce jointe, les deux fichiers employés pour le test.
Bonjour Gilles,
Merci pour votre réponse, j'ai repris votre fichier, j'ai relancé mais rien n'a changé. Je suis alors allé modifier le bloc inters afin de supprimer l'attribut nommé coordonnées. cela n'a rien changé non plus.
La réaction est toujours la même, les croix se mettent parfaitement en place mais aucun attribut de "coordonnées" (A1, B1....) n'est visible.
NB: Merci pour le point de base 😃
Bonjour Gilles,
Merci beaucoup de votre réponse, j'ai pu effectivement mettre le script en application et il fonctionne très bien !
J'ai tenté d'y apporter une légère modification, à savoir afficher,( en plus de A1, A2...), un numéro qui s'incrémente sur chaque bloc ajouté, j'ai donc ajouté un attribut commençant à 1. J'ai ensuite créer une variable "num" puis j'ai essayé d'incrémenter dans chaque boucle. Cependant, le nombre ne bouge pas...
Pourriez-vous m'expliquer la démarche pas à pas ?
La problématique semble récurrente chez les débutants, le maniement des variables et leur incrémentation ne semble pas aussi clair/facile que dans les langages communs tels que C ou PHP... Je suis donc un peu perdu à ce niveau.
Merci encore de votre aide,
Cordialement,
Bonjour Gilles, merci de votre rapide réponse,
Il ne plante pas car j'ai retiré la partie pour afficher ma variable "num", j'ai modifié inters afin d'avoir un second attribut mais celui ci est demandé manuellement par Autocad pour chaque pose de inters... preuve que mon script n'est pas au point. Je pense que num s'incrémente, mais je n'ai aucune certitude.
J'ai mis en gras le peu que j'ai rajouté et qui ne fait pas tout planter.
Mon réel souci se situe dans l'affichage de num, je ne vois pas comment faire. Mon code est le suivant:
(defun c:BLKINTERS (/ *error* dia req echo os ss n blk line vert horiz ih iv hy vx pt) ;; substitution locale de la fonction *error* (defun *error* (msg) (and msg (/= msg "Fonction annulée") (princ (strcat "erreur: " msg)) ) (command-s "_.undo" "_end") ;; restauration des valeurs initiales (setvar 'attdia dia) (setvar 'attreq req) (setvar 'osmode os) (setvar 'cmdecho echo) (princ) ) ;; valeurs initiales des variables système (setq dia (getvar 'attdia) req (getvar 'attreq) echo (getvar 'cmdecho) os (getvar 'osmode) ) (setq num 1) ;; nombre a incrementer ;; sélection des blocs "bande_6inchs_centered" et des blocs anonymes (if (setq ss (ssget "_X" '((0 . "INSERT") (2 . "`*U*,bande_6inchs_centered") (410 . "Model")))) (progn ;; traitement de la sélection (repeat (setq n (sslength ss)) (setq blk (ssname ss (setq n (1- n)))) ;; contrôle du nom du bloc (blocs anonymes) (if (= (getpropertyvalue (getpropertyvalue blk "BlockTableRecord") "Name") "bande_6inchs_centered" ) (progn ;; constitution d'une liste avec les points de départ et de fin de la ligne (setq line (list (getpropertyvalue blk "Position") (polar (getpropertyvalue blk "Position") (- (getpropertyvalue blk "Rotation") (* pi 0.5)) (getpropertyvalue blk "AcDbDynBlockPropertyDistance1") ) ) ) ;; ajout de la sous-liste à la liste des lignes horizontales ou verticales (if (equal (caar line) (caadr line) 1e-6) (setq vert (cons line vert)) (setq horiz (cons line horiz)) ) ) ) ) ;; tri de la liste des lignes horizontales par Y décroissant ;; et de la liste des lignes vetrticales par X croissant (setq horiz (vl-sort horiz '(lambda (p1 p2) (> (cadar p1) (cadar p2)))) vert (vl-sort vert '(lambda (p1 p2) (< (caar p1) (caar p2)))) iv 65 ; index de départ des colonnes (ascii "A") ih 1 ; index de départ des rangées hy (cadaar horiz) ; Y maximum vx (caaar vert) ; X minimum ;; ajout de l'index aux lignes horizontales horiz (mapcar '(lambda (l) (cons (if (equal hy (setq hy (cadar l)) 1e-6) (itoa ih) (itoa (setq ih (1+ ih))) ) l ) ) horiz ) ;; ajout de l'index aux lignes verticales vert (mapcar '(lambda (l) (cons (if (equal vx (setq vx (caar l)) 1e-6) (chr iv) (chr (setq iv (1+ iv))) ) l ) ) vert ) ) (command-s "_.undo" "_begin") ;; affectation des variables système (setvar 'cmdecho 0) (setvar 'osmode 0) (setvar 'attdia 0) (setvar 'attreq 1) ;; pour chaque ligne verticale (foreach v vert ;; pour chaque ligne horizontale (foreach h horiz ;; insertion du bloc s'il y a intersection ;; affectation de la valeur de l'attribut avec les indices des lignes (if (setq pt (inters (cadr h) (caddr h) (cadr v) (caddr v) T)) (command-s "_.insert" "inters" pt 1.0 1.0 0.0 (strcat (car v) (car h))) (setq num (+ num 1)) ) ) ) ) ) (*error* nil) )
Je vous joins le fichier inters modifié avec son nouvel attribut.
Pas testé mais ça devrait marcher (j'ai ajouté quelques commentaires)
(defun c:BLKINTERS (/ *error* dia req echo os ss n blk line vert horiz ih iv hy vx pt num ) ;; substitution locale de la fonction *error* (defun *error* (msg) (and msg (/= msg "Fonction annulée") (princ (strcat "erreur: " msg)) ) (command-s "_.undo" "_end") ;; restauration des valeurs initiales (setvar 'attdia dia) (setvar 'attreq req) (setvar 'osmode os) (setvar 'cmdecho echo) (princ) ) ;; valeurs initiales des variables système (setq dia (getvar 'attdia) req (getvar 'attreq) echo (getvar 'cmdecho) os (getvar 'osmode) ) (setq num 1) ; nombre a incrémenter ;; sélection des blocs "bande_6inchs_centered" et des blocs anonymes (if (setq ss (ssget "_X" '((0 . "INSERT") (2 . "`*U*,bande_6inchs_centered") (410 . "Model") ) ) ) (progn ;; traitement de la sélection (repeat (setq n (sslength ss)) (setq blk (ssname ss (setq n (1- n)))) ;; contrôle du nom du bloc (blocs anonymes) (if (= (getpropertyvalue (getpropertyvalue blk "BlockTableRecord") "Name" ) "bande_6inchs_centered" ) (progn ;; constitution d'une liste avec les points de départ et de fin de la ligne (setq line (list (getpropertyvalue blk "Position") (polar (getpropertyvalue blk "Position") (- (getpropertyvalue blk "Rotation") (* pi 0.5)) (getpropertyvalue blk "AcDbDynBlockPropertyDistance1" ) ) ) ) ;; ajout de la sous-liste à la liste des lignes horizontales ou verticales (if (equal (caar line) (caadr line) 1e-6) (setq vert (cons line vert)) (setq horiz (cons line horiz)) ) ) ) ) ;; tri de la liste des lignes horizontales par Y décroissant ;; et de la liste des lignes vetrticales par X croissant (setq horiz (vl-sort horiz '(lambda (p1 p2) (> (cadar p1) (cadar p2))) ) vert (vl-sort vert '(lambda (p1 p2) (< (caar p1) (caar p2)))) iv 65 ; index de départ des colonnes (ascii "A") ih 1 ; index de départ des rangées hy (cadaar horiz) ; Y maximum vx (caaar vert) ; X minimum ;; ajout de l'index aux lignes horizontales horiz (mapcar '(lambda (l) (cons (if (equal hy (setq hy (cadar l)) 1e-6) (itoa ih) (itoa (setq ih (1+ ih))) ) l ) ) horiz ) ;; ajout de l'index aux lignes verticales vert (mapcar '(lambda (l) (cons (if (equal vx (setq vx (caar l)) 1e-6) (chr iv) (chr (setq iv (1+ iv))) ) l ) ) vert ) ) (command-s "_.undo" "_begin") ;; affectation des variables système (setvar 'cmdecho 0) (setvar 'osmode 0) (setvar 'attdia 0) (setvar 'attreq 1) ;; pour chaque ligne verticale (foreach v vert ;; pour chaque ligne horizontale (foreach h horiz ;; insertion du bloc s'il y a intersection ;; affectation de la valeur de l'attribut avec les indices des lignes (if (setq pt (inters (cadr h) (caddr h) (cadr v) (caddr v) T)) (progn (command-s "_.insert" "inters" ; nom du bloc pt ; point d'insertion 1.0 ; échelle X 1.0 ; échelle Y 0.0 ; rotation (strcat (car v) (car h)) ; premier attribut (itoa num) ; second attribut ) (setq num (1+ num)) ; incrémentation de l'attribut ) ) ) ) ) ) (*error* nil) )
Bonjour Gilles,
Merci beaucoup pour ce nouveau coup de pouce et surtout ces précisions pas à pas qui me permettent de mieux comprendre le code et la manière dont il est pensé.
Il fonctionne mais il y a un bug que je ne saurais résoudre. En effet, mes lignes sont parfois en deux morceaux, et donc cela créé une double croix et engendre un décalage sur tout le reste du fichier.
Je suppose qu'il faudrait vérifier si chaque entrée n'existe pas déjà dans la liste des coordonnées: si le point (X,Y) n'est pas déjà enregistré alors on l'ajoute à la liste.
Pourrait-on imaginer se servir de last afin de comparer si le point N et N+1 sont les même ? Très théoriquement, je voyais les choses ainsi:
(foreach v vert ;; pour chaque ligne horizontale (foreach h horiz ;; insertion du bloc s'il y a intersection ;; affectation de la valeur de l'attribut avec les indices des lignes ;;Ici il faudrait excepter le premier point car la comparaison ne peut pas avoir lieu ?? pt n'existe pas encore (if ( (=(inters (cadr h) (caddr h) (cadr v) (caddr v) T)) pt) ( (if (setq pt (inters (cadr h) (caddr h) (cadr v) (caddr v) T)) (progn (command-s "_.insert" "inters" ; nom du bloc pt ; point d'insertion 1.0 ; échelle X 1.0 ; échelle Y 0.0 ; rotation (strcat (car v) (car h)) ; premier attribut (itoa num) ; second attribut ) (setq num (1+ num)) ; incrémentation de l'attribut ) ) ) ) )
Merci d'avance de ton aide.
NB: En PJ, le bug illustré.
Bonjour,
Si une des réponses à votre question résout votre problème, ou contribue significativement à sa résolution, voulez vous avoir l'amabilité de cliquer sur le bouton "Accepter comme solution" en bas de la réponse? Merci.
Bonjour Patrick,
Je n'ai pas encore de solution à proprement parler, d'où mon non clic. Mais c'est en effet la dernière étape à mon sens pour une solution bien adaptée. Dès lors que ce sera résolu, je cliquerais bien entendu sur le lien approprié.
zminWZ7PT a écrit :
Bonjour Patrick,
Je n'ai pas encore de solution à proprement parler, d'où mon non clic. Mais c'est en effet la dernière étape à mon sens pour une solution bien adaptée. Dès lors que ce sera résolu, je cliquerais bien entendu sur le lien approprié.
Exigeant avec ça...
Ils me semblent que les solutions que je t'ai gracieusement fournies répondaient à chaque fois à ce que tu avais demandé mais tu as, à chaque fois, ajouté une nouvelle requête.
Je te réponds une dernière fois et tant pis si tu ne trouve pas cette solution suffisamment adaptée...
(defun c:BLKINTERS (/ *error* dia req echo os ss n blk line vert horiz ih iv hy vx pt num pts) ;; substitution locale de la fonction *error* (defun *error* (msg) (and msg (/= msg "Fonction annulée") (princ (strcat "erreur: " msg)) ) (command-s "_.undo" "_end") ;; restauration des valeurs initiales (setvar 'attdia dia) (setvar 'attreq req) (setvar 'osmode os) (setvar 'cmdecho echo) (princ) ) ;; valeurs initiales des variables système (setq dia (getvar 'attdia) req (getvar 'attreq) echo (getvar 'cmdecho) os (getvar 'osmode) ) (setq num 1) ; nombre a incrémenter ;; sélection des blocs "bande_6inchs_centered" et des blocs anonymes (if (setq ss (ssget "_X" '((0 . "INSERT") (2 . "`*U*,bande_6inchs_centered") (410 . "Model") ) ) ) (progn ;; traitement de la sélection (repeat (setq n (sslength ss)) (setq blk (ssname ss (setq n (1- n)))) ;; contrôle du nom du bloc (blocs anonymes) (if (= (getpropertyvalue (getpropertyvalue blk "BlockTableRecord") "Name" ) "bande_6inchs_centered" ) (progn ;; constitution d'une liste avec les points de départ et de fin de la ligne (setq line (list (getpropertyvalue blk "Position") (polar (getpropertyvalue blk "Position") (- (getpropertyvalue blk "Rotation") (* pi 0.5)) (getpropertyvalue blk "AcDbDynBlockPropertyDistance1" ) ) ) ) ;; ajout de la sous-liste à la liste des lignes horizontales ou verticales (if (equal (caar line) (caadr line) 1e-6) (setq vert (cons line vert)) (setq horiz (cons line horiz)) ) ) ) ) ;; tri de la liste des lignes horizontales par Y décroissant ;; et de la liste des lignes verticales par X croissant (setq horiz (vl-sort horiz '(lambda (p1 p2) (> (cadar p1) (cadar p2))) ) vert (vl-sort vert '(lambda (p1 p2) (< (caar p1) (caar p2)))) iv 65 ; index de départ des colonnes (ascii "A") ih 1 ; index de départ des rangées hy (cadaar horiz) ; Y maximum vx (caaar vert) ; X minimum ;; ajout de l'index aux lignes horizontales horiz (mapcar '(lambda (l) (cons (if (equal hy (setq hy (cadar l)) 1e-6) (itoa ih) (itoa (setq ih (1+ ih))) ) l ) ) horiz ) ;; ajout de l'index aux lignes verticales vert (mapcar '(lambda (l) (cons (if (equal vx (setq vx (caar l)) 1e-6) (chr iv) (chr (setq iv (1+ iv))) ) l ) ) vert ) ) (command-s "_.undo" "_begin") ;; affectation des variables système (setvar 'cmdecho 0) (setvar 'osmode 0) (setvar 'attdia 0) (setvar 'attreq 1) ;; pour chaque ligne verticale (foreach v vert ;; pour chaque ligne horizontale (foreach h horiz ;; insertion du bloc s'il y a intersection ;; affectation de la valeur de l'attribut avec les indices des lignes (if (and (setq pt (inters (cadr h) (caddr h) (cadr v) (caddr v) T)) (not (vl-member-if '(lambda (p) (equal pt p 1e-8)) pts)) ) (progn (command-s "_.insert" "inters" ; nom du bloc pt ; point d'insertion 1.0 ; échelle X 1.0 ; échelle Y 0.0 ; rotation (strcat (car v) (car h)) ; premier attribut (itoa num) ; second attribut ) (setq num (1+ num) ; incrémentation de l'attribut pts (cons pt pts) ; ajout du point à la liste ) ) ) ) ) ) ) (*error* nil) )
Je vous prie de m'excuser pour toutes ces requêtes ajoutées en effet. Je n'osais cliquer car sur beaucoup de forums, cliquer sur "sujet résolu", entraîne l'enterrement du topic.
Désolé encore d'avoir abusé de votre patience et de votre gentillesse.
Bonjour, non, marquer une réponse comme solution acceptée n'entraine pas le blocage des réponses, comme c'est le cas, vous avez raison, sur d'autres forums. La clôture d'un sujet et donc le blocage des réponses résulte d'une action manuelle d'un administrateur.
Vous n'avez pas trouvé ce que vous recherchiez ? Posez une question à la communauté ou partagez vos connaissances.