Aller au contenu

Détection de collisions


Messages recommandés

Invité Patrick
Posté(e)

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.

Posté(e)

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)

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?

Posté(e)

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

Posté(e)

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

Posté(e)

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

Posté(e)

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.

Posté(e)

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

 

./__\.
(.°=°.)
Posté(e)

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

Posté(e)

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)

Merci pour vos réponses, je vais cogiter tout ça, le but sera dans mon cas une routine VBA.

Posté(e)

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

Posté(e)

Bonjour,

Il me semble que cela existe dans certains appli Autocad mais surtout cela existe dans INVENTOR ...

Passer à la 3D ;-)

Banzzzzaiiiiiii

 

Posté(e)

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

Posté(e)

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

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 compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant
×
×
  • 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é