(gile) Posté(e) le 1 août 2007 Partager Posté(e) le 1 août 2007 La question revenant souvent, j'ai essayé d'aboutir une routine pour évaluer si un point est à l'intérieur d'une polyligne fermée.J'ai repris la méthode de _zebulon (ici) consistant à consistant à compter le nomre d'intersections entre une ligne partant du point spécifié et la polyligne : si le nombre est impair, le point est à l'intérieur de la polyligne.Pour parer à toute éventualité, les points d'intersection correspondant à un sommet ou un point tangent à un arc sont écartés. La routine fonctione quelque soient le SCU courant et le SCO de la polyligne. EDIT : Les polylignes croisées (auto-intersection) posant encore des problèmes, j'ai supprimé les parties de code qui tentaient de les traiter. ;; INSIDE-P (gile) -version 2.1- ;; Evalue si le point est à l'intérieur d'une polyligne fermée ;; ;;Arguments ;; pt : le point (coordonnées SCG) ;; pl : la polyligne fermée (ename ou vla-object) ;; ;; Retour ;; T si le point est à l'intérieur de la polyligne ;; nil si le point est à l'extérieur ou sur la polyligne (defun inside-p (pt pl / space norm line int self) (vl-load-com) (or (= (type pl) 'VLA-OBJECT) (setq pl (vlax-ename->vla-object pl)) ) (setq space (if (= (getvar "CVPORT") 1) (vla-get-PaperSpace (vla-get-activedocument (vlax-get-acad-object)) ) (vla-get-ModelSpace (vla-get-activedocument (vlax-get-acad-object)) ) ) norm (vlax-get pl 'Normal) line (vla-addLine space (vlax-3d-point pt) (vlax-3d-point (mapcar '+ pt (trans (list (vla-get-Length pl) 0.0 0.0) norm 0) ) ) ) int (3d-coord->pt-lst (vlax-invoke pl 'IntersectWith line acExtendNone) ) ) (vla-delete line) (and int (not (vlax-curve-getParamAtPoint pl pt)) (= 1 (rem (length (vl-remove-if '(lambda (x / pa p0 p- p+ s1 s2) (setq pa (vlax-curve-getParamAtPoint pl x)) (or (and (equal (round pa) pa 1e-9) (setq p- (cond ((setq p- (vlax-curve-getPointAtParam pl (- pa 1e-8)) ) (trans p- 0 norm) ) (T (trans (vlax-curve-getPointAtParam pl (- (vlax-curve-getEndParam pl) 1e-8) ) 0 norm ) ) ) p+ (trans (vlax-curve-getPointAtParam pl (+ pa 1e-8)) 0 norm ) p0 (trans pt 0 norm) s1 (sin (angle p0 p-)) s2 (sin (angle p0 p+)) ) (or (and ( ) (and (/= 0.0 (vla-getBulge pl (fix pa))) (equal '(0.0 0.0) (cdr (trans (vlax-curve-getFirstDeriv pl pa) 0 norm)) 1e-9 ) ) ) ) int ) ) 2 ) ) ) ) ;;; 3d-coord->pt-lst Convertit une liste de coordonnées 3D en liste de points ;;; (3d-coord->pt-lst '(1.0 2.0 3.0 4.0 5.0 6.0)) -> ((1.0 2.0 3.0) (4.0 5.0 6.0)) (defun 3d-coord->pt-lst (lst) (if lst (cons (list (car lst) (cadr lst) (caddr lst)) (3d-coord->pt-lst (cdddr lst)) ) ) ) ;;; ROUND Arrondit à l'entier le plus proche (defun round (num) (fix ((if (minusp num) - +) num 0.5)) ) [Edité le 2/8/2007 par (gile)][Edité le 2/8/2007 par (gile)] [Edité le 4/8/2007 par (gile)] Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD Lien vers le commentaire Partager sur d’autres sites More sharing options...
(gile) Posté(e) le 2 août 2007 Auteur Partager Posté(e) le 2 août 2007 J'ai modifié/amélioré le code ci-dessus.Je pense avoir maintenant cerné tous les cas de figure particuliers. Pour ceux qui voudraient tester : (defun c:test () (and (setq ent (car (entsel "\nSélectionnez une polyligne: "))) (setq ent (vlax-ename->vla-object ent)) (= (vla-get-ObjectName ent) "AcDbPolyline") (= (vla-get-Closed ent) :vlax-true) (setq pt (trans (getpoint "\nSpécifiez un point: ") 1 0)) (if (inside-p pt ent) (alert "Dedans") (alert "Dehors") ) ) (princ) ) [Edité le 2/8/2007 par (gile)] Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD Lien vers le commentaire Partager sur d’autres sites More sharing options...
lecrabe Posté(e) le 2 août 2007 Partager Posté(e) le 2 août 2007 Bonjour Je tiens tout particulièrement à remercier tous ceux comme (Gile), Patrick_35, Bred, etc et bien d'autres ... pour leur "dévouement" et aussi la qualité des programmes qu'ils écrivent à partir des demandes des différents membres de Cadxp :) :D :cool: Longue vie et bonne santé à tous ces vaillants développeurs ! Le Decapode "reconnaissant" Autodesk Expert Elite Team Lien vers le commentaire Partager sur d’autres sites More sharing options...
(gile) Posté(e) le 2 août 2007 Auteur Partager Posté(e) le 2 août 2007 Merci lecrabe, mais la publication de codes n'est pas que "désintéressée", ce faisant, de vaillants testeurs apportent leur aide débusquant les dysfonctionnements et en proposant des améliorations. ;) Trouver toutes les situations qui peuvent faire échouer une routine est souvent le plus difficile.Dans le cas présent, je continue à trouver des situations, peu probables mais éventuelles. Je vais essayer d'expliquer un peu mieux comment fonctionne la routine. À partir du point spécifié, un ligne parallèle à l'axe des X du système de coordonnées de l'objet est dessinée et le nombre de points d'intersection entre la ligne et la polyligne, selon qu'il est pair ou impair, indique si le point est à l'intérieur de la polyligne http://img390.imageshack.us/img390/6286/inside1qe0.png Ensuite, il s'agit de trouver tous les cas qui pourraient fausser le résultat, et écarter ces points du comptage.Présentement, sont écartés :1 - la ligne passe par un sommet saillant de la polyligne2 - la ligne tangente avec un arc de la polyligne3 - la ligne se confond avec un segment (un des sommets est écarté)4 - la ligne passe par un point "d'auto-intersection" de la polyligne http://img470.imageshack.us/img470/2460/inside2ea0.png Si certains envisagaient d'autres cas de figure, merci d'avance de les signaler. Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD Lien vers le commentaire Partager sur d’autres sites More sharing options...
bazoul Posté(e) le 7 août 2007 Partager Posté(e) le 7 août 2007 Très bien la routine!Grand merciBon j'avoue avec un peu de mal a comprends son fonctionnement vu qu'elle est truffé de vla,et c'est pour ça que je vais poser la question suivante:Peut elle etre modifié pour savoir un objet est a l'intérieur d'un autre(ployligne bien sur) a la place d'un point? Lien vers le commentaire Partager sur d’autres sites More sharing options...
(gile) Posté(e) le 7 août 2007 Auteur Partager Posté(e) le 7 août 2007 Salut, Peut elle etre modifié pour savoir un objet est a l'intérieur d'un autre(ployligne bien sur) Pour ça, il me semble plus rationnel d'utiliser la routine SelByObj (ou encore sur cette page dans Spécial Sélections), qui crée un jeu de sélection (Fenêtre ou capture) à partir d'un objet (polyligne, cercle ou ellipse). un exemple d'expression ou rech est le nom d'entité (ename) de l'objet recherché et selobj celui de l'objet utilisé pour la sélection qui retourne T si l'objet est complètement à l'intérieur, nil sinon. (= 'ENAME (type (ssmemb (car (entsel)) (selbyobj (car (entsel)) "WP" nil)))) NOTA : en vue 3d, SelByObj fonctionne en fonction de la vue courante. [Edité le 7/8/2007 par (gile)] Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD Lien vers le commentaire Partager sur d’autres sites More sharing options...
zebulon_ Posté(e) le 13 août 2007 Partager Posté(e) le 13 août 2007 J'ai repris la méthode de _zebulon Tiens, on parle de moi ? Je tiens à préciser que ma petite tête n'est pas assez intelligente pour inventer une telle méthode. Je la dois à mon premier maitre lisp (martin, si tu te reconnais...) qui, lui aussi, la doit sans doute à quelqu'un...J'ai seulement tenté de répondre aux cas qui font échouer la méthode, en me basant sur une méthode faisant appel à la chance. (Gile) est plus mathématique dans sa démarche. AmicalementZebulon_ C'est au pied du mur que l'on reconnaît le maçon ! (Anonyme) C’est en restant au pied du mur qu’on ne voit que le mur (Anonyme aussi) Lien vers le commentaire Partager sur d’autres sites More sharing options...
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