Invité Patrick Posté(e) le 13 juin 2006 Posté(e) le 13 juin 2006 Existe-t-il un programme LISP ou VBA permettant de détecter et donc de signaler des collisions entre blocs 2D? Par collision, j'entend la supperposition partielle ou totale d'un bloc 2D avec soit un autre bloc, soit une autre instance du même bloc. Cette demande part d'un besoin réel. Je réalise par programmation VBA des plans de calepinage et j'ai besoin de m'assurer que deux blocs ne se chevaucheront pas. L'idée n'est pas d'empêcher ces collisions ni de dessiner un plan de calepinage ne comportant pas de collisions, mais de simplement les signaler avec une marque quelconque sur le plan. Je me doute que cette application, si elle existe est complexe, et le but de ce message est plus de lancer le débat sur la faisabilité de cela, de tracer les grandes lignes d'un futur algorytme, plutôt que de trouver une solution.
LUDWIG Posté(e) le 13 juin 2006 Posté(e) le 13 juin 2006 moi je vois un truc du style (si j'ai bien compris) : - sélection des instances de blocs (ou tous ou filtre etc)- bounding box de chaque instance --> récupération des 4 points (car 2D) de la bounding box de chaque instance (définissant 4 lignes)- pour chaque lignes de chaque instances : calculs des intersections avec les lignes des autres intances- si intersections --> cercles rouges C'est facile à dire, mais je ne m'aventurerais pas là dedans !! Autocad 2021 - Revit 2022 - Windows 10
Invité Patrick Posté(e) le 13 juin 2006 Posté(e) le 13 juin 2006 Oui, les blocs en question ne sont pas forcément de forme rectangulaire, je suppose que la méthode de la "bounding box" ne nous aidera pas, de plus ces blocs peuvent être pivotés, donc même si les blocs étaient rectangulaires, la bounding box ne représenterait pas leur surface. Il m'est venu une idée: détecter le contour des blocs en utilisant la commande Contour (ou une fonction de hachurage?), hachurer SOLID ces contours et faire des opérations booléennes de soustraction entre surfaces trouvées, si le résultat de la soustraction est nul, les blocs ne se touchent pas... mais cela suppose une méthode de détermination du contour d'un bloc, dans ce cas là la "bounding box" pourrait nous aider, l'idée est de hachurer la bounding box d'un bloc sans hachurer l'intérieur du bloc puis d'inverser la zone hachurée... C'est une piste, mais peut être y a-t-il une solution "miracle" avant de se lancer dans un tel développement?
(gile) Posté(e) le 13 juin 2006 Posté(e) le 13 juin 2006 En Vlisp (vlax-safearray>list (vlax-variant-value (vla-IntersectWith bloc1 bloc2 acExtendNone))) retourne la liste des coordonnées des entre les deux objets points d'intersection. Je crois qu'en VBA c'est IntersectWith Method. À partir une liste de tous les blocs insérés, je ferais une boucle pour tester le premier de la liste successivement avec tous les autres, marquerais les points d'intersection, puis le supprimerais de la liste et recommencerais avec le suivant, et anisi de suite jusquà la fin de la liste. C'est peut-être un peu "lispien" cette façon de faire avec les listes, je ne connais pas le VBA. Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
nazemrap Posté(e) le 13 juin 2006 Posté(e) le 13 juin 2006 Bonjour. J'avais pensé aussi à la méthode "intersectwith", mais elle semble fonctionner sur le principe de la "boundingbox".Je viens de tester la réponse est faussée.Il me semble qu'en copiant le bloc puis en l explosant, et pour chaque objet le constituant vérifier par "intersectwith".Un peu long m'enfin.. nazemrap
(gile) Posté(e) le 13 juin 2006 Posté(e) le 13 juin 2006 Et non, les points retournés par IntersectWith correspondent à l'intersection des "bounding box" des blocs, pas à l'intersection des entités qi les composent. C'était et non, pour gile, mais c'est et oui, pour nazemrap qui m'a coiffé au poteau ;) [Edité le 13/6/2006 par (gile)] Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
nazemrap Posté(e) le 13 juin 2006 Posté(e) le 13 juin 2006 Par contre il semble que ça marche en décomposant le bloc.Il faut donc travailler sur des copies des blocs, pour les exploser sans les perdre.Mais il faut le faire avant de boucler puisque la commande "copie" ne fonctionne pas dans dans une itération.
Tramber Posté(e) le 13 juin 2006 Posté(e) le 13 juin 2006 Je ne suis pas d'accord avec vous. L'intersectwith est valable pour des objets simples seulement( remarquez, ca peut peut-être aller). J'ai développé des programmes avec detection de collisions par les régions. Si l'intersect a une superficie (>0), il y a collision. Faut se taper des régions, mais c'est comme ça ! Mais en Vlisp, c'est facile (si le contour est bien fermé), ici un contour en 4 objets : (setq regio(vla-addRegion spac(vlax-make-variant(vlax-safearray-fill(vlax-make-safearray 9(cons 0(1-(length(list obj2 obj3 l1 l2)))))(list obj2 obj3 l1 l2))))) spac étant le Modelespace et la liste d'objets des objets créant strictement une région. Bureau d'études dessin. Spécialiste Escaliers Développement - Formation ./__\. (.°=°.)
(gile) Posté(e) le 13 juin 2006 Posté(e) le 13 juin 2006 Une petite idée avec le booléennes, à faire au fur et à mesure de l'insertion (premier et deuxième puis deuxième et troisième ...) Je la donne en vlisp : Transformer les blocs en régions (il faut qu'ils ne soient composés que de lignes, arcs circulaires ou elliptiques, lwpolylignes, splines) : (setq reg1 (car (vlax-safearray->list (vlax-variant-value (vla-addRegion (vla-get-ModelSpace (vla-get-ActiveDocument (vlax-get-acad-object)) ) (vla-explode bloc1) ) ) ) ))(setq reg2 (car (vlax-safearray->list (vlax-variant-value (vla-addRegion (vla-get-ModelSpace (vla-get-ActiveDocument (vlax-get-acad-object)) ) (vla-explode bloc2) ) ) ) )) Et on récupère l'intersection, si elle existe, par la booléenne intersection : (vla-boolean reg1 acIntersection reg2) Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
(gile) Posté(e) le 13 juin 2006 Posté(e) le 13 juin 2006 Un LISP qui semble marcher. Il crée une région (rouge, mais on peut changer) aux intersections de tous les blocs insérés dans le dessin (on peut aussi ajouter des filtres pour les blocs) (defun inters_reg (bloc1 bloc2 / ModSp reg1 reg2 ent1 ent2) (setq ModSp (vla-get-ModelSpace AcDoc)) (setq reg1 (car (vlax-safearray->list (vlax-variant-value (vla-addRegion ModSp (setq ent1 (vla-explode bloc1)) ) ) ) ) ) (mapcar 'vla-delete (vlax-safearray->list (vlax-variant-value ent1) ) ) (setq reg2 (car (vlax-safearray->list (vlax-variant-value (vla-addRegion ModSp (setq ent2 (vla-explode bloc2)) ) ) ) ) ) (mapcar 'vla-delete (vlax-safearray->list (vlax-variant-value ent2) ) ) (vla-boolean reg2 acIntersection reg1) (vla-put-color (vlax-ename->vla-object (entlast)) 1) ) (defun c:inters_bloc (/ AcDoc ss lst n) (vl-load-com) (setq AcDoc (vla-get-ActiveDocument (vlax-get-acad-object))) (vla-StartUndoMark AcDoc) (setq ss (ssget "_X" '((0 . "INSERT")))) (if ss (repeat (setq n (sslength ss)) (setq lst (cons (vlax-ename->vla-object (ssname ss (setq n (1- n)))) lst ) ) ) ) (while (cadr lst) (repeat (setq n (1- (length lst))) (inters_reg (car lst) (nth n lst)) (setq n (1- n)) ) (setq lst (cdr lst)) ) (princ) ) Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
Invité Patrick Posté(e) le 13 juin 2006 Posté(e) le 13 juin 2006 Merci pour vos réponses, je vais cogiter tout ça, le but sera dans mon cas une routine VBA.
(gile) Posté(e) le 13 juin 2006 Posté(e) le 13 juin 2006 Comme il s'agit de suggestions et que çà m'amusait j'ai un peu plus abouti la routine donnée ci-dessus. L'utilisateur choisit la couleur pour les interférences, des sélectionner certains blocs à l'écran ou tous (Enter, clic droit). Si plusieurs régions sont génèrées par la décomposition du bloc elles sont unies en une seule. ;;; INTERFERE_BLOC -Gilles Chanteau- 17/06/06 ;;; Crée une région de la couleur choisie sur les interférences des blocs sélectionnés ;; Création de la région d'intersection entre deux blocs (defun inters_reg (lst / ModSp) (setq ModSp (vla-get-ModelSpace AcDoc)) ;; Transforme la liste (bloc1 bloc2) ;; en liste ((composants1 . region1) (composants2 . region2)) (setq lst (mapcar '(lambda (x / ent reg) ;; création de la (ou des) région(s) (setq ent (vla-explode x) ;_ composants du bloc reg (vl-catch-all-apply 'vla-addRegion (list ModSp ent) ) ) (if (vl-catch-all-error-p reg) (cons ent "err") (progn (setq reg (vlax-safearray->list ;_ liste des régions créées (vlax-variant-value reg ) ) ) ;; union des régions (while (cadr reg) (vla-boolean (car reg) acUnion (cadr reg) ) (setq reg (cons (car reg) (cddr reg))) ) ;; paire pointée (composants . region) (cons ent (car reg)) ) ) ) lst ) ) ;; suppression des composants des blocs décomposés (mapcar '(lambda (x) (mapcar 'vla-delete (vlax-safearray->list (vlax-variant-value x) ) ) ) (mapcar 'car lst) ) ;; intersection des deux régions et mise en couleur (cond ((and (/= (cdar lst) "err") (/= (cdadr lst) "err")) (vla-boolean (cdar lst) acIntersection (cdadr lst)) (vla-put-color (cdar lst) col) ) ;; suppression des régions "solitaires" ((/= (cdar lst) "err") (vla-delete (cdar lst))) ((/= (cdadr lst) "err") (vla-delete (cdadr lst))) ) ) ;; Fonction principale (defun c:interfere_bloc (/ AcDoc col ss lst n) (vl-load-com) (setq AcDoc (vla-get-ActiveDocument (vlax-get-acad-object))) (vla-StartUndoMark AcDoc) ;; Choix de la couleur (prompt "\nSélectionnez la couleur pour les interférences.") (while (not (setq col (acad_colordlg (cond ((= (getvar "CECOLOR") "BYLAYER") 256) ((= (getvar "CECOLOR") "BYBLOCK") 0) (T (getvar "CECOLOR")) ) ) ) ) ) ;; Sélection des blocs (prompt "\nSélectionnez les blocs à traiter ou : ") (if (not (setq ss (ssget '((0 . "INSERT"))))) (setq ss (ssget "_X" '((0 . "INSERT")))) ) ;; liste des blocs sélectionnés (if ss (repeat (setq n (sslength ss)) (setq lst (cons (vlax-ename->vla-object (ssname ss (setq n (1- n)))) lst ) ) ) ) ;; Boucle pour rechercher les intersections entre chacun des blocs ;; et chaque bloc placé après lui dans la liste (while (cadr lst) (repeat (setq n (1- (length lst))) (inters_reg (list (car lst) (nth n lst))) (setq n (1- n)) ) (setq lst (cdr lst)) ) (vla-EndUndoMark AcDoc) (princ) )[Edité le 15/6/2006 par (gile)] [Edité le 17/6/2006 par (gile)] Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
Banzai Posté(e) le 14 juin 2006 Posté(e) le 14 juin 2006 Bonjour,Il me semble que cela existe dans certains appli Autocad mais surtout cela existe dans INVENTOR ...Passer à la 3D ;-)Banzzzzaiiiiiii
(gile) Posté(e) le 14 juin 2006 Posté(e) le 14 juin 2006 Salut Banzai, la commande _interfere d'AutoCAD ne fonctionne qu'avec des solides 3D,et dans le cas qui nous préoccupe ici il s'agit de blocs 2D. Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
(gile) Posté(e) le 15 juin 2006 Posté(e) le 15 juin 2006 J'ai un petit peu amélioré le LISP ci-dessus, ajout de commentaires et réparation d'une erreur dans l'union des régions créées à partir des composants d'un bloc. Toutefois, çà ne fonctionne pas si les entités qui composent le(s) contour(s) du bloc ne sont pas jointives par leurs extrémités (de même avec la commande _region). http://img512.imageshack.us/img512/4849/inters5wi.png http://img45.imageshack.us/img45/5420/inters24oh.png [Edité le 15/6/2006 par (gile)] Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
(gile) Posté(e) le 17 juin 2006 Posté(e) le 17 juin 2006 En essayant de répondre à une demande un peu similaire, mais concernant les polylignes ici, j'ai un peu creusé la question. J'ai trouvé une faille concernant les blocs dont les composants ne peuvent générer de région (et le moyen d'y remédier). Je corrige le LISP. Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
Messages recommandés
Créer un compte ou se connecter pour commenter
Vous devez être membre afin de pouvoir déposer un commentaire
Créer un compte
Créez un compte sur notre communauté. C’est facile !
Créer un nouveau compteSe connecter
Vous avez déjà un compte ? Connectez-vous ici.
Connectez-vous maintenant