CADarome Posté(e) le 31 mai 2007 Posté(e) le 31 mai 2007 Bonjour,... Je cherche le moyen de trouver le centre d'un polyline fermé. des suggestions ? Sky is the limit.....Mon oeuil !!
Tramber Posté(e) le 31 mai 2007 Posté(e) le 31 mai 2007 Le centroide, terme exact. Vois ici. Bureau d'études dessin. Spécialiste Escaliers Développement - Formation ./__\. (.°=°.)
Didier-AD Posté(e) le 31 mai 2007 Posté(e) le 31 mai 2007 voici. (defun C:CDGPOL ( / pol cdg) (setq pol (car (entsel "\n pointez une polyligne"))) (if (setq cdg (cdgpol pol)) (alert (strcat "centre de gravité : " (rtos (car cdg) 2 3) " , " (rtos (cadr cdg) 2 3))) ) ) (defun cdgpol (pol / ent lp) (if (and pol (= "LWPOLYLINE" (cdr (assoc 0 (setq ent (entget pol)))))) (setq lp (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= 10 (car x))) ent))) (print "pas une polyligne !!! ") ) (if lp (List (/ (apply '+ (mapcar 'car lp)) (length lp)) (/ (apply '+ (mapcar 'cadr lp)) (length lp)) ) ) ) Attention, la routine ne vérifie pas si la polyligne est fermée et ne tient pas compte des arcs éventuels; si çà ne te suffit pas, dis le, on peut faire mieux.
(gile) Posté(e) le 31 mai 2007 Posté(e) le 31 mai 2007 Dans le lien donné par Tramber, je donnais une routine en "pur Visual LISP" pour les VBistes. Il est indispensable de passer par VisualLISP pour récupérer le centroïd d'une région ou d'un solide, mais on peut écrire la même chose de manière un peu plus "lisible" pour des lispeurs. (defun c:pt-cen (/ AcDoc Space SelSet Region) ;; Pointeur sur le document actif (setq AcDoc (vla-get-ActiveDocument (vlax-get-acad-object))) ;; Pointeur sur l'espace actif (objet ou papier) (if (= (getvar "CVPORT") 1) (setq Space (vla-get-PaperSpace AcDoc)) (setq Space (vla-get-ModelSpace AcDoc)) ) (if (setq SelSet (ssget '((0 . "LWPOLYLINE") (-4 . "&") (70 . 1)))) ;; Pour tous les objets contenus dans le jeu de sélection (vlax-for obj (vla-get-activeSelectionSet AcDoc) ;; Création d'une région (setq Region (vlax-invoke Space 'addRegion (list obj))) ;; Création d'un point au centre de gravité (vlax-invoke Space 'addPoint (trans (vlax-get (car Region) 'Centroid) 1 0) ) ;; Supression de la région (vla-delete (car Region)) ) ;_ fin de vlax-for ) ;_ fin de if (princ) ) ;_ fin de defun Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
(gile) Posté(e) le 31 mai 2007 Posté(e) le 31 mai 2007 Je vais encore "chipoter", mais la routine donnée par didier-AD retourne le barycentre (plus exactement l'équibarycentre) d'un polygone. Ceci ne correspond au centre de gravité (centroïd) que dans le cas de triangles queconques ou de polygones réguliers ou particuliers (rectangles, losanges, parallélogrames) à 4 côtés ou plus.Voir ici [Edité le 31/5/2007 par (gile)] Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
lecrabe Posté(e) le 1 juin 2007 Posté(e) le 1 juin 2007 Hello Dans un genre un peu différent, j'aurais plutôt besoin d'une routine qui à partir de la sélection de 1 ou N (si possibles) Polylignes 2D (ou Régions) fermées donne le barycentre ou centre de gravité (Cela m'importe peu) MAIS avec donc un point à l'intérieur du polygone IMPERATIVEMENT ! Comment faire avec les contours complexes (concavités) et pas si complexesque ça en forme du L ou de U par exemple ! Application: obtenir un point graphique (en fait un bloc avec N attributs: No, Surface, Périmètre par exemple) TOUJOURS DANS le polygone des parcelles en cadastre ... Le Decapode "chiant" PS: C quoi la différence entre le CDG et le Barycentre "simplement" ? Autodesk Expert Elite Team
(gile) Posté(e) le 1 juin 2007 Posté(e) le 1 juin 2007 Salut lecrabe, Une routine vite fait qui place un point à l'intérieur des polylignes sélectionnées. Le point est placé sur le barycentre des premier, deuxième, et le premier sommet suivant qui permet de remplir la condition "est à l'intérieur de la polyligne". Cette condition est évaluée avec la routine SelByObj (donc fonctionne aussi avec des polylignes contenant des arcs). ;;; SelByObj -Gilles Chanteau- 06/10/06 ;;; Crée un jeu de sélection avec tous les objets contenus ou ;;; capturés, dans la vue courante, par l'objet sélectionné ;;; (cercle, ellipse, polyligne fermée). ;;; Arguments : ;;; - un nom d'entité (ename) ;;; - un mode de sélection (Cp ou Wp) ;;; - un filtre de sélection ou nil (defun SelByObj (ent opt fltr / obj dist n lst prec dist p_lst) (vl-load-com) (if (= (type ent) 'ENAME) (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 ) ) ) ) ((= (cdr (assoc 0 (entget ent))) "LWPOLYLINE") (setq p_lst (vl-remove-if-not '(lambda (x) (or (= (car x) 10) (= (car x) 42) ) ) (entget ent) ) ) (while p_lst (setq lst (cons (trans (append (cdr (assoc 10 p_lst)) (list (cdr (assoc 38 (entget ent)))) ) ent 1 ) lst ) ) (if (/= 0 (cdadr p_lst)) (progn (setq prec (1+ (fix (* 25 (sqrt (abs (cdadr p_lst)))))) dist (/ (- (if (cdaddr p_lst) (vlax-curve-getDistAtPoint obj (trans (cdaddr p_lst) ent 0) ) (vlax-curve-getDistAtParam obj (vlax-curve-getEndParam obj) ) ) (vlax-curve-getDistAtPoint obj (trans (cdar p_lst) ent 0) ) ) prec ) n 0 ) (repeat (1- prec) (setq lst (cons (trans (vlax-curve-getPointAtDist obj (+ (vlax-curve-getDistAtPoint obj (trans (cdar p_lst) ent 0) ) (* dist (setq n (1+ n))) ) ) 0 1 ) lst ) ) ) ) ) (setq p_lst (cddr p_lst)) ) ) ) (ssget (strcat "_" opt) lst fltr) ) ;;=========================================;; ;; Place un point à l'intérieur des polylignes fermées sélectionnées (defun c:pt-int (/ g3 ss cnt ent plst n pt loop ssp) (defun g3 (p1 p2 p3) (mapcar '(lambda (x1 x2 x3) (/ (+ x1 x2 x3) 3)) p1 p2 p3) ) (if (setq ss (ssget '((0 . "LWPOLYLINE") (-4 . "&") (70 . 1)))) (repeat (setq cnt (sslength ss)) (setq ent (ssname ss (setq cnt (1- cnt)))) (setq plst (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget ent) ) ) ) (setq n 2 pt (trans (g3 (car plst) (cadr plst) (caddr plst)) ent 0) ) (entmake (list '(0 . "LINE") (cons 10 pt) (cons 11 pt))) (setq pt (entlast) loop T ) (redraw) (while (and ( (setq ssp (SelByObj ent "WP" '((0 . "LINE")))) (if (and ssp (member pt (vl-remove-if 'listp (mapcar 'cadr (ssnamex ssp))) ) ) (progn (entmake (list '(0 . "POINT") (assoc 10 (entget pt)))) (entdel pt) (setq loop nil) ) (progn (entdel pt) (setq n (1+ n) pt (trans (g3 (car plst) (cadr plst) (nth n plst)) ent 0) ) (entmake (list '(0 . "LINE") (cons 10 pt) (cons 11 pt))) (setq pt (entlast)) ) ) ) ) ) (princ) ) PS : pour lecrabe, la routine pour mettre les sommets des polylignes fermées dans le sens trigo te convient-elle ? [Edité le 1/6/2007 par (gile)] Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
lecrabe Posté(e) le 2 juin 2007 Posté(e) le 2 juin 2007 Hello Gilles Comme d'habitude ça marche super ! je suis ébloui par ta rapidité !! Par contre cela ne focntionne PAS sur les polylignes Splinées ou Lissées ! Sniff !? J'en profite pour suggérer une petite (grosse) amélioration : Plutôt que d'insérer un point, il serait TIP-TOP d'insérer un bloc avec quelques attributs (un peu comme la routine faite pour JALNA) 1er attribut : reporter le code de maintien (handle) de la polyligne(Pour jointure / identification ultérieure)2eme / 3eme attribut : surface et périmètre de la polyligne4eme attribut : Z départ de la polyligne5eme attribut : une valeur numerique entière qui s'incrémente de UN en UN à partir de la dernière valeur utilisée ou d'une valeur demandée préalablement Le Decapode "chiant" Autodesk Expert Elite Team
(gile) Posté(e) le 3 juin 2007 Posté(e) le 3 juin 2007 C quoi la différence entre le CDG et le Barycentre "simplement" ? Je vais essayer de faire "simplement", mais c'est pas si simple. Le barycentre (centre des poids) est un point qui est la moyenne de plusieurs points pondérés.Si les pondérations des différents points sont égales on parle d'équibarycentre. Le centre de gravité d'un solide (ou d'une surface) c'est son "point d'équilibre", le point qui est à la verticale du point de suspension quelque soit celui-ci. http://img516.imageshack.us/img516/9384/cdg1re1.png De plus, le centre de gravité d'une structure composée de plusieurs éléments est le barycentre des points aux centres de gravité de chacun des éléments pondérés par leurs poids (ou leurs surfaces en 2d). Excepté pour certaines figure planes (tous le triangles, les carrés, rectangles, parallélogrames, losanges et les polygones réguliers) et certains solides (prisme dont la section est une des surfaces citées et polyèdres réguliers) le centre de gravité est différent de l'équibarycentre des sommets. Exemple avec un trapèze isocèle de coordonnées (0 0) (4 4) (8 4) (12 0).L'équibarycentre est le point (6 2). http://img523.imageshack.us/img523/1025/cdg2nf6.png Si on décompose le trapèze en figures plus simples (un carré et deux triangles rectangles isocèles), il est aisé de placer le centre de gravité sur chacune des figures. Le "poids" de chaque figure est proportionnel à sa surface (16 unités² pour le carré, 8 unités² pour chaque triangle, soit la moitié). http://img299.imageshack.us/img299/6867/cdg3ao7.png Pour trouver le centre de gravité du trapèze, on peut, dans un premier temps, chercher celui du trapèze composé du triangle de gauche et du carré.Il s'agit de trouver le barycentre de leurs centre de gravités respectifs pondérés par leurs surface.Le centre de gravité de ce trapèze se situe donc sur la ligne entre les deux centres et au 2/3 de la distance entre ces points. le "poids" de ce trapèze est de 18 + 8 = 24 soit trois fois plus que celui du triangle. http://img115.imageshack.us/img115/472/cdg4nr6.png On procède de la même manière pour trouver le centre de gravité de la figure complète. http://img504.imageshack.us/img504/4039/cdg5ki0.png Le centre de gravité du trapèze (6.0 1.66667) est différent de son équibarycentre. http://img47.imageshack.us/img47/4245/cdg6qu8.png Une autre méthode est montrée ici. [Edité le 3/6/2007 par (gile)] [Edité le 6/2/2008 par (gile)] Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
(gile) Posté(e) le 3 juin 2007 Posté(e) le 3 juin 2007 Voilà un LISP (Parcelle) qui place le bloc "Parcelle" à l'intérieur des polylignes fermées fermées sélectionnées. Le bloc doit avoir 5 attributs, dans l'ordre, le maintient (handle) de la polyligne, son périmètre, son aire, son élévation et un numéro automatiquement incrémenté. Si plusieurs polylignes sont sélectionnées en même temps, le numéro est incrémenté dans l'ordre de création des objets.Le périmètre et la surface sont des champs dynamiques, pour le formatage des champs se reporter aux sujets sur Pline_block. ;;; SelByObj -Gilles Chanteau- 06/10/06 ;;; Crée un jeu de sélection avec tous les objets contenus ou ;;; capturés, dans la vue courante, par l'objet sélectionné ;;; (cercle, ellipse, polyligne fermée). ;;; Arguments : ;;; - un nom d'entité (ename) ;;; - un mode de sélection (Cp ou Wp) ;;; - un filtre de sélection ou nil (defun SelByObj (ent opt fltr / obj dist n lst prec dist p_lst) (vl-load-com) (if (= (type ent) 'ENAME) (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 ) ) ) ) ((= (cdr (assoc 0 (entget ent))) "LWPOLYLINE") (setq p_lst (vl-remove-if-not '(lambda (x) (or (= (car x) 10) (= (car x) 42) ) ) (entget ent) ) ) (while p_lst (setq lst (cons (trans (append (cdr (assoc 10 p_lst)) (list (cdr (assoc 38 (entget ent)))) ) ent 1 ) lst ) ) (if (/= 0 (cdadr p_lst)) (progn (setq prec (1+ (fix (* 25 (sqrt (abs (cdadr p_lst)))))) dist (/ (- (if (cdaddr p_lst) (vlax-curve-getDistAtPoint obj (trans (cdaddr p_lst) ent 0) ) (vlax-curve-getDistAtParam obj (vlax-curve-getEndParam obj) ) ) (vlax-curve-getDistAtPoint obj (trans (cdar p_lst) ent 0) ) ) prec ) n 0 ) (repeat (1- prec) (setq lst (cons (trans (vlax-curve-getPointAtDist obj (+ (vlax-curve-getDistAtPoint obj (trans (cdar p_lst) ent 0) ) (* dist (setq n (1+ n))) ) ) 0 1 ) lst ) ) ) ) ) (setq p_lst (cddr p_lst)) ) ) ) (ssget (strcat "_" opt) lst fltr) ) ;;; 2d-coord->pt-lst Convertit une liste de coordonnées 2D en liste de points ;;; (2d-coord->pt-lst '(1.0 2.0 3.0 4.0)) -> ((1.0 2.0 0.0) (3.0 4.0 0.0)) (defun 2d-coord->pt-lst (lst) (if lst (cons (list (car lst) (cadr lst) 0.0) (2d-coord->pt-lst (cddr lst)) ) ) ) ;;================================================================;; ;; Place le bloc "parcelle" à l'intérieur des polylignes fermées sélectionnées (defun c:parcelle (/ g3 bloc AcDoc Space ss ent plst n pt l0 loop ech cnt ssp id long aire ) (vl-load-com) (defun g3 (p1 p2 p3) (mapcar '(lambda (x1 x2 x3) (/ (+ x1 x2 x3) 3)) p1 p2 p3) ) (if (or (tblsearch "BLOCK" (setq bloc "Parcelle")) (findfile (setq bloc "Parcelle.dwg")) ) (progn (setq AcDoc (vla-get-activedocument (vlax-get-acad-object)) Space (if (= (getvar "CVPORT") 1) (vla-get-PaperSpace acDoc) (vla-get-ModelSpace acDoc) ) ) (vla-StartUndoMark AcDoc) (if (setq ss (ssget '((0 . "LWPOLYLINE") (-4 . "&") (70 . 1)))) (progn (if (not (vlax-ldata-get "Parcelle" "ech")) (vlax-ldata-put "Parcelle" "ech" 1) ) (if (not (setq ech (getreal (strcat "\nEntrez le facteur d'échelle (rtos (vlax-ldata-get "Parcelle" "ech")) ">: " ) ) ) ) (setq ech (vlax-ldata-get "Parcelle" "ech")) (vlax-ldata-put "Parcelle" "ech" ech) ) (if (not (vlax-ldata-get "Parcelle" "inc")) (progn (initget 1) (vlax-ldata-put "Parcelle" "inc" (getint "\nNuméro de départ: ") ) ) ) (repeat (setq cnt (sslength ss)) (setq ent (vlax-ename->vla-object (ssname ss (setq cnt (1- cnt))) ) plst (2d-coord->pt-lst (vlax-get ent 'Coordinates)) nor (vlax-get ent 'Normal) n 2 pt (trans (g3 (car plst) (cadr plst) (caddr plst)) nor 0) ) (entmake (list '(0 . "LINE") (cons 10 pt) (cons 11 pt))) (setq l0 (entlast) loop T ) (while (and ( (setq ssp (SelByObj (vlax-vla-object->ename ent) "WP" '((0 . "LINE")) ) ) (if (and ssp (member l0 (vl-remove-if 'listp (mapcar 'cadr (ssnamex ssp))) ) ) (progn (setq id (vla-get-ObjectID ent) ;; Attribut périmètre (mm -> m) long (strcat "% (itoa id) ">%).Length \\f \"%lu2%pr2%\">%" ) ;; Attribut surface (mm² -> m²) aire (strcat "% (itoa id) ">%).Area \\f \"%lu2%pr2%\">%" ) ) (setq ref (vla-InsertBlock Space (vlax-3d-point pt) bloc ech ech 1 0.0 ) ) ;; attribution de leur valeur aux attributs (mapcar '(lambda (x y) (vla-put-TextString x y)) (vlax-invoke ref 'GetAttributes) (list (vla-get-Handle ent) long aire (vla-get-Elevation ent) (vlax-ldata-get "Parcelle" "inc") ) ) (vlax-ldata-put "Parcelle" "inc" (1+ (vlax-ldata-get "Parcelle" "inc")) ) (vla-regen AcDoc acActiveViewport) (entdel l0) (setq loop nil) ) (progn (entdel l0) (setq n (1+ n) pt (trans (g3 (car plst) (cadr plst) (nth n plst)) nor 0 ) ) (entmake (list '(0 . "LINE") (cons 10 pt) (cons 11 pt)) ) (setq l0 (entlast)) ) ) ) ) ) ) ) (prompt "\nLe bloc " Parcelle " est introuvable.") ) (vla-EndUndoMark AcDoc) (princ) ) en prime, le bloc Parcelle avec lequel j'ai fait les tests. Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
lecrabe Posté(e) le 4 juin 2007 Posté(e) le 4 juin 2007 Hello Gilles Merci mais qq questions: Pourquoi ton bloc comprend 10 attributs et non pas 5 ? Pourquoi son système d'unité en MM et non pas en M ?Est ce important ? Moultes révérences oh Grand Seigneur de la Programmation, Le Decapode Autodesk Expert Elite Team
(gile) Posté(e) le 4 juin 2007 Posté(e) le 4 juin 2007 Salut le crabe, 5 des attributs sont des attributs constants (j'aurais pu mettre des textes). Mais ce n'est qu'un exemple, tu peux faire to bloc "Parcelle" comme tu veux. Pour les unités, c'est un copié/collé de pline_block, le commentaire dit conversion des mm en m (ou m²) mais j'ai supprimé le facteur de conversion dans le formatage des champs (pensant que tu travaillais en mètre) 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