Aller au contenu

Sélection de polylignes fermées


Messages recommandés

Posté(e)

Bonsoir à tous,

 

je cherche une routine (lisp ou vba) qui me permette de selectionner une polyligne fermée quand je clique à l'intérieur.

 

Est-ce possible ?

Si oui, comment ?

 

Merci d'avance.

 

PS: je ne sais pas si je poste dans le bon forum, mais je m'y perd un peu.

Il n'y a pas de courage sans peur

Posté(e)

Salut,

 

Voici un LISP pas très élégant (il y a peut-être plus simple mais je n'ai pas trouvé).

Il ne fonctionne sous certaines conditions :

- La polyligne doit être entièrement visible à l'écran

- Le point de sélection ne doit pas être spécifié à l'intérieur d'un arc

 

Nouvelle nouvelle version

 

(defun c:selpline (/ pt size fenc inc loop point pmode ss ent test)
 (initget 1)
 (setq	pt   (getpoint
       "\nSpécifiez un point à l'intérieur de la polyligne: "
     )
size (getvar "viewsize")
fenc  (/ size 100)
inc fenc
loop T
 )
 (entmake
   (list '(0 . "LINE")
  (cons 10 (trans pt 1 0))
  (cons 11 (trans pt 1 0))
   )
 )
 (setq point (entlast))
 (while loop
   (if	(      (setq loop nil)
   )
   (if
     (and (setq
     ss	(ssget
	  "_F"
	  (list
	    pt
	    (mapcar '+ pt (list 0 fenc 0))
	  )
	  '((0 . "LWPOLYLINE") (-4 . "&") (70 . 1))
	)
   )
   (setq ent (ssname ss (1- (sslength ss))))
   (setq test (ssget "_CP"
		     (mapcar
		       '(lambda	(pt)
			  (trans pt ent 1)
			)
		       (mapcar
			 'cdr
			 (vl-remove-if-not
			   '(lambda (x) (= (car x) 10))
			   (entget ent)
			 )
		       )
		     )
		     (list '(0 . "LINE")
			   (assoc 10 (entget point))
		     )
	      )
   )
     )
      (setq loop nil)
      (setq ent nil)
   )
   (setq fenc (+ fenc inc))
 )
 (entdel point)
 (if ent
   (sssetfirst nil (ssadd ent))
 )
 (princ)
) 

[Edité le 1/10/2006 par (gile)][Edité le 1/10/2006 par (gile)]

 

[Edité le 1/10/2006 par (gile)]

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

 

hello (gile)

 

Je suis nul en Lisp mais j'ai l'impression que tu fais une sélection en mode _WP ?

"Fenêtre normale Non capturante" pour tenter de "chopper" la polyligne ?

 

Ai je compris ?

 

Le Decapode "admiratif"

 

Autodesk Expert Elite Team

Posté(e)

Salut lecrabe,

 

En fait, dans une boucle, je fais d'abord une sélection en mode _Fence (Trajet) depuis le point spécifié en augmentant le trajet de 1/1000 de la taille de la vue active à chaque boucle jusqu'à ce que je trouve un polyligne fermée. Si une poly est trouvée je fais une selection en mode _WP avec les sommet de la dernière poly trouvée pour être sûr que le point spécifié est bien à l'intérieur, s'il n'y est pas on continue à boucler pour trouver une autre poly. Si aucune poly n'est trouvée la boucle s'arrête quand le trajet est égal à la hauteur de la vue (VIEWSIZE).

 

PS : J'ai modifié le LISP, le trajet pour la sélection se faisait sur l'axe des X, je l'ai passé sur les Y puisque la limite est la hauteur de la vue.

 

[Edité le 1/10/2006 par (gile)]

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

 

Hello

 

Un seul mot : Waouhh = la Classe ! :) :D :cool:

 

Comment as tu eu l'dée "démoniaque" de cet algorithme ?

 

Le Decapode "abasourdi par (gile)"

 

Autodesk Expert Elite Team

Posté(e)

Je ne l'ai pas fait en un seul coup, j'ai d'abord pensé au mode de sélection par un trajet qui augmente depuis le point spécifié, puis en faisant des essais j'ai imaginé que ce trajet pouvait rencontrer une autre polyligne fermée qui ne "contenait" pas ce point, alors j'ai imaginé un moyen pour écarter ce type de polyligne de la sélection.

 

Je crois que le plus difficile en programmation est d'imaginer tout ce qui peut mettre en echec le programme, alors quand une routine semble fonctionner je fais des test pour essayer de la faire échouer.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

J'ai un peu modifier le LISP :

- changement de l'incrémentation de la longueur du trajet de sélection (1/100 de la hauteur de la fenêtre au lieu de 1/1000) pour plus de rapidité d'exécution.

- Changement de la variable PDMODE pour le point temporaire, et restauration de la valeur initiale.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Que n'y avais-je pensé plus tôt !

 

Mieux que le changement de PDMODE : mode de sélection _CP (crossing polygon) et une ligne de longueur 0 pour remplacer le point temporaire.

 

Le point peut être spécifié à l'intérieur de la polyligne ou sur la polyligne (avec les accrochages aux objets)

 

Je re-modifie le LISP

 

[Edité le 1/10/2006 par (gile)]

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Je reponds au sujet par ces deux petites routines que j'ai créé.

;-----------------------------------------------------------------

(defun c:FERMEES ( / js-text)

(setvar "cmdecho" 0)

(setq FERMEES (ssget (list (cons 0 "LWPOLYLINE") (cons 70 1))))

(sssetfirst FERMEES FERMEES)

);fin

;-----------------------------------------------------------------

(defun c:NON-FERMEES ( / js-text)

(setvar "cmdecho" 0)

(setq NON-FERMEES (ssget (list (cons 0 "LWPOLYLINE") (cons 70 0))))

(sssetfirst NON-FERMEES NON-FERMEES)

);fin

;-----------------------------------------------------------------

 

A tester....

 

[Edité le 2/10/2006 par fabcad]

Posté(e)

Bonjour à vous,

 

J'ai pensé couplé cela avec pline_block mais je ne savais pas à quelle ligne l'insérer, ou quelle lignes remplacer...

 

Il faut sans doute remplacer celles-là :

 

  ;; Sélection d'une entité
(while (not (setq ent (car (entsel)))))

 

Confirmation ?

 

 

Merci !

"La ligne droite est le plus court chemin entre deux points, à condition que les deux points soient bien en face l'un de l'autre" P. Desproges.

Posté(e)

J'ai apporté quelques améliorations au premier LISP, notamment en utilisant SelByObj, une routine qui permet de faire un jeu de sélection à partir d'un objet (polyligne cercle ellipse).

 

La nouvelle version cherche une polyligne fermée par Capture avec des cercles concentriques autour du point spécifié.

Chaque polyligne sélectionnée est testée toujours avec SelByObj pour vérifier si elle contient le point spécifié (les arcs des polylignes sont donc maintenant pris en compte).

Si le point est contenu dans plusieurs polylignes c'est la plus proche du point qui est sélectionnée.

 

Le LISP ne fonctionne que si la vue est parallèle au SCU courant et la polyligne contenue dans la vue.

 

Le LISP est décomposé en une routine pour pouvoir l'utiliser dans d'autres LISP et une fonction d'appel.

 

Nouvelle version (04/10/06)

 

;;; SELPLINE -Gilles Chanteau- 04/10/06
;;; Sélection d'une polyligne par un point à l'intérieur
;;; Retourne un nom d'entité (ename) ou un message d'erreur

(defun SelPlineByPoint
      (pt / size inc rad norm loop pick circle ss ent x_lst)
 (if
   (equal '(0 0)
   (reverse (cdr (reverse (getvar "VIEWDIR"))))
   1e-9
   )
    (progn
      (setq size (getvar "viewsize")
     inc  (/ size 200)
     rad  inc
     norm (trans '(0 0 1) 1 0 T)
     loop T
      )
      (entmake
 (list '(0 . "LINE")
       (cons 10 (trans pt 1 0))
       (cons 11 (trans pt 1 0))
 )
      )
      (setq pick (entlast))
      (while loop
 (if (	   (setq loop nil)
 )
 (entmake (list	'(0 . "CIRCLE")
		(cons 10 (trans pt 1 norm))
		(cons 40 rad)
		(cons 210 norm)
	  )
 )
 (setq circle (entlast))
 (if (setq
       ss
	(SelByObj circle
		  "Cp"
		  '((0 . "LWPOLYLINE") (-4 . "&") (70 . 1))
	)
     )
   (progn
     (repeat (setq n (sslength ss))
       (setq ent (ssname ss (setq n (1- n))))
       (if (member ent x_lst)
	 (ssdel ent ss)
       )
     )
     (if
       (setq ent (ssname ss 0))
	(if
	  (SelByObj ent
		    "Wp"
		    (list '(0 . "LINE")
			  (cons 10 (trans pt 1 0))
			  (cons 11 (trans pt 1 0))
		    )
	  )
	   (setq loop nil)
	   (setq x_lst (cons ent x_lst))
	)
     )
   )
 )
 (entdel circle)
 (setq rad (+ rad inc))
      )
      (entdel pick)
      ent
    )
    (alert "La vue doit être dans le plan du SCU courant")
 )
)

;;; Fonction d'appel

(defun c:selpline (/ pt)
 (sssetfirst nil nil)
 (initget 1)
 (setq	pt (getpoint
     "\nSpécifiez un point à l'intérieur de la polyligne: "
   )
 )
 (if (setq ent (SelPlineByPoint pt))
   (sssetfirst nil (ssadd ent))
   (princ "\nPas polyligne trouvée.")
 )
 (princ)
)

 

Et SelByObj qui doit être chargée aussi :

version corrigée (04/10/06)

 

 

;;; SelByObj -Gilles Chanteau- 04/10/06
;;; Crée un jeu de sélection avec tous les objets contenus ou 
;;; capturés par le polygone créé à partir de l'objet sélectionné
;;; Les courbes (cercles, ellipses, arcs de polylignes) sont segmentés
;;; Arguments :
;;; - un nom d'entité (ename) -cercle, ellipse, polyligne fermée-
;;; - un mode de sélection (Cp ou Wp)
;;; - un filtre de sélection

(defun SelByObj	(ent opt fltr / obj dist n lst prec dist p_lst)
 (vl-load-com)
 (setq obj (vlax-ename->vla-object ent))
 (cond
   ((member (cdr (assoc 0 (entget ent))) '("CIRCLE" "ELLIPSE"))
    (setq dist	(/ (vlax-curve-getDistAtParam
	     obj
	     (vlax-curve-getEndParam obj)
	   )
	   50
	)
   n	0
    )
    (repeat 50
      (setq
 lst
  (cons
    (trans
      (vlax-curve-getPointAtDist obj (* dist (setq n (1+ n))))
      0
      1
    )
    lst
  )
      )
    )
   )
   (T
    (setq p_lst (vl-remove-if-not
	   '(lambda (x)
	      (or (= (car x) 10)
		  (= (car x) 42)
	      )
	    )
	   (entget ent)
	 )
    )
    (while p_lst
      (setq lst (append lst (list (cdr (assoc 10 p_lst)))))
      (if (/= 0 (cdadr p_lst))
 (progn
   (setq prec (fix (* 50 (abs (cdadr p_lst))))
	 dist (/ (- (if	(cdaddr p_lst)
		      (vlax-curve-getDistAtPoint
			obj
			(cdaddr p_lst)
		      )
		      (vlax-curve-getDistAtParam
			obj
			(vlax-curve-getEndParam obj)
		      )
		    )
		    (vlax-curve-getDistAtPoint
		      obj
		      (cdar p_lst)
		    )
		 )
		 prec
	      )
	 n    0
   )
   (repeat (1- prec)
     (setq
       lst (append
	     lst
	     (list
	       (trans
		 (vlax-curve-getPointAtDist
		   obj
		   (+ (vlax-curve-getDistAtPoint
			obj
			(cdar p_lst)
		      )
		      (* dist (setq n (1+ n)))
		   )
		 )
		 0
		 1
	       )
	     )
	   )
     )
   )
 )
      )
      (setq p_lst (cddr p_lst))
    )
    (setq lst (mapcar '(lambda (x) (trans x 0 1)) lst))
   )
 )
 (ssget (strcat "_" opt) lst fltr)
)

 

 

Sinon, bien vu phil, pour utiliser SelPline dans Pline_Block, il faut remplacer :

(while (not (setq ent (car (entsel)))))
(if (= (cdr (assoc 0 (entget ent))) "LWPOLYLINE")

par :

(if (= (type (setq ent
		  (selpline
		    (getpoint
		      "\nSpécifiez un point à l'intérieur de la polyligne: "
		    )
		  )
	   )
     )
     'ENAME
  )

en utilisant la dernière version de SelPline.[Edité le 3/10/2006 par (gile)][Edité le 3/10/2006 par (gile)]

 

[Edité le 4/10/2006 par (gile)]

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

J'ai corrigé un petit bug quand le "cercle de sélection" rencontrait certaine polylignes fermées ne conteneant pas le point spécifié.

 

Il semble que ça fonctionne bien maintenant...

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Des tests plus approfondis ont fait apparaître un dysfonctionnement dans des SCU différents du SCG.

 

SelPline et SelByObj ont été corrigés en conséquence.

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é