Aller au contenu

Lisp extraction de données a l'intérieur d'une polyligne fermée (bloc, att, texte et multitexte)


Messages recommandés

Posté(e)

Bonjour à toute et à tous, je suis débutant encore dans la création du lis et je souhaiterais créer un LISP permettant d'extraire les données présentes dans une polyligne.
Pour expliquer le but, c'est que je travaille dans une boîte d'exécution et nous recevons des DCE misérable et pouvons exploitable. Donc nous sommes contraints de recommencer le travail.
Pour cela je voudrais en désignant une polyligne fermée autour d'un local par exemple extrait les noms et attributs de tous les blocs présents dans la polyligne mais également le texte présent dans le Xref ou bloc de bloc dans xref ou juste les texte présent dans l'aire de la polyligne. Le tout regrouper dans un tableau autocad pour plus tard faire une extraction vers excel.  
Voici mon code sur lequel je suis partis mais rien ne fonctionne.
Merci infiniment de votre attention et de votre aide en avance. 

Le code : 

(defun C:ANALYSER ()
  (setq pline (car (entsel "\nSélectionnez la polyligne fermée : ")))
  (if (not (null pline))
    (progn
      (setq data '()) ; Initialisation de la liste de données
      (setq detectorCount 0) ; Initialisation du compteur de détecteurs
      
      ; Récupération des sommets de la polyligne
      (setq vertices (vlax-get-property (vlax-ename->vla-object pline) 'Coordinates))
      
      ; Fonction pour vérifier si un point est à l'intérieur d'une polyligne fermée
      (defun is-point-inside-polyline (pt vertices)
        (setq oddNodes 0)
        (setq j (length vertices) i 0)
        (while (< i (length vertices))
          (setq vi (nth i vertices))
          (setq vj (nth j vertices))
          (if (and (< (cadr pt) (cadr vj))
                   (or (and (<= (cadr vi) (cadr pt))
                            (< (cadr pt) (cadr vj)))
                       (and (<= (cadr vj) (cadr pt))
                            (< (cadr pt) (cadr vi)))))
              (if (< (car pt)
                     (+ (/ (- (car vj) (car vi)) (- (cadr vj) (cadr vi))) (car vi)))
                  (setq oddNodes (1+ oddNodes))
              )
          )
          (setq j i)
          (setq i (1+ i))
        )
        (/= 0 (% oddNodes 2))
      )
      
      ; Boucle à travers tous les blocs dans le dessin
      (setq ss (ssget "X" '((0 . "INSERT"))))
      (setq i 0)
      (while (< i (sslength ss))
        (setq block (ssname ss i))
        (setq insertion-point (cdr (assoc 10 (entget block))))
        
        ; Vérification si le point d'insertion est à l'intérieur de la polyligne
        (if (is-point-inside-polyline insertion-point vertices)
          (progn
            ; Incrémentation du compteur de détecteurs
            (setq detectorCount (1+ detectorCount))
            ; Récupération des attributs du bloc
            (setq attlist '())
            (setq attents (entget block))
            (foreach x attents
              (if (= (car x) 1) ; Code 1 représente le texte de l'attribut
                (setq attlist (cons (cdr x) attlist))))
            
            ; Ajout des données du bloc à la liste
            (setq data (cons (list (cdr (assoc 2 (tblsearch "BLOCK" (cdr (assoc -2 attents))))) ; Nom du bloc
                                   insertion-point ; Point d'insertion du bloc
                                   attlist) ; Liste des attributs du bloc
                             data))
        ))
        (setq i (1+ i))
      )
      
      ; Affichage des données récupérées
      (setq table (vla-add acadDoc '(-4 . 1) (vlax-3D-point 0 0 0) 1 (1+ detectorCount) 3))
      (vla-put-name table "ANALYSE")
      (vla-put-columns table 3)
      
      ; Remplissage du tableau avec les données récupérées
      (setq row 1)
      (foreach item data
        (vla-setText table row 0 (car item)) ; Nom du bloc
        (vla-setText table row 1 (rtos (vlax-safearray->list (vlax-variant-value (cadr item))) 2 2)) ; Point d'insertion du bloc
        (vla-setText table row 2 (apply 'strcat (caddr item))) ; Attributs du bloc
        (setq row (1+ row))
      )
      
      (prompt "\nAnalyse terminée. Tableau créé avec les données.")
    )
    (prompt "\nAucune polyligne sélectionnée.")
  )
  (princ)
)
 

Posté(e)

Coucou,

Je remarque ici que tu as opté pour l'option de sélectionner l'ensemble des objets (en l’occurrence ici les "INSERT") du dessin pour ensuite vérifier si leur point d'insertion est situé dans ta polyligne. Je pense que tu gagneras fortement en efficacité en complexifiant un peu ta fonction de sélection (ssget). En effet, cette fonction possède de très nombreuse possibilités et notamment les mots clés. Tu as écrit (si tu n'oublies pas l'underscore évidemment) :

(ssget "_X" '((0 . "INSERT")))

ce qui se traduit par "sélectionner tout les objets 'INSERT' de la base de donnée du dessin". Or dans ton cas, il serait plus judicieux d'utiliser

(ssget "_CP" pt_list '((0 . "INSERT"))) ;; "_CP" = Crossing Polygon (capture polygonale donc un polygone de sélection vert)
;;ou bien
(ssget "_WP" pt_list '((0 . "INSERT"))) ;; "_CP" = Window Polygon (fenêtre polygonale donc un polygone de sélection bleu)

où 'pt_list' correspond à une liste de coordonnées de points 2D comme ceci par exemple

((23.45 93.01) (-1.00 4.79) (11.15 -13.405))

Autrement dit, fais bien attention au contenu de ta variable 'vertices' et plus exactement à son format ! Car certes c'est une méthode qui semble simple pour récupérer les coordonnées mais en réalité, cela requiert un peu de traitement selon les autres fonctions utilisant ces coordonnées... Normalement tu auras un format comme ceci :

(23.45 93.01 -1.00 4.79 11.15 -13.405)

Ce qui, comme tu peux le voir, ne correspond pas vraiment à une liste de coordonnées de points 2D. Il existe de nombreuses manières pour récupérer la liste des coordonnées d'une polyligne donc je suis sûre que tu trouveras une solution (car après tout tu sembles être surtout là pour apprendre et non pour recopier).

Ainsi, en passant par ces options de sélection ("_CP" ou bien "_WP" selon ton besoin réel) tu peux directement filtrer ta sélection d'objets sur une zone précise de ton dessin, permettant ainsi de ne pas avoir besoin d'étudier les potentiels 10 000 références de blocs contenues dans ton dessin mais de juste se concentrer sur la zone de travail souhaitée (ce qui est beaucoup plus rapide à l'exécution !). Du coup ta fonction (is-point-inside-polyline) n'est plus nécessaire.

Ensuite pour la récupération des attributs d'un bloc, je te conseille les fonctions de LeeMac qui sont vraiment simple d'utilisation et assez simple à comprendre (donc pas besoin de réécrire une fonction par toi-même, des fois on peut se servir de ce qui existe déjà et qui fonctionne très bien ;p) : http://www.lee-mac.com/attributefunctions.html

Ensuite un conseil, si tu débutes en LISP, peut-être qu'avant d'insérer tes résultats dans un tableau AutoCAD (qui sont des entités complexes à maîtriser) tu devrais essayer de trouver une méthode plus simple pour toi en temps que programmeur. Tu peux facilement créer un fichier .csv par exemple (utilisable par Excel). Ou bien trouver d'autres alternatives.
Si tu as besoin de plus de précisions, ou bien d'exemples de programmation plus concrets n'hésites pas à demander ! C'est pour chat qu'on est là, et chat fait toujours plaisir d'aider quelqu'un qui désire apprendre 😜

Bisous,
Luna

  • Upvote 1
Invité
Répondre à ce sujet…

×   Collé en tant que texte enrichi.   Coller en tant que texte brut à la place

  Seulement 75 émoticônes maximum sont autorisées.

×   Votre lien a été automatiquement intégré.   Afficher plutôt comme un lien

×   Votre contenu précédent a été rétabli.   Vider l’éditeur

×   Vous ne pouvez pas directement coller des images. Envoyez-les depuis votre ordinateur ou insérez-les depuis une URL.

×
×
  • 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é