-
Compteur de contenus
12 247 -
Inscription
-
Dernière visite
-
Jours gagnés
209
Type de contenu
Profils
Forums
Calendrier
Blogs
Tout ce qui a été posté par (gile)
-
[Résolu] Comment décaler une polyligne ?
(gile) a répondu à un(e) sujet de DenisHen dans Débuter en LISP
vincentp010, J'ai quelques doutes quant à la méthode que tu utilises pour déterminer si une polyligne court en sens horaire ou en sens anti-horaire. En fait, c'est plus que des doutes j'ai fait un test avec un polyligne qui me donne le même résultat après avoir inversé le sens de la polyligne qu'avant de l'avoir fait... La méthode utilisée ci-dessous avec l'aire algébrique (signée) d'une polyligne est fiable même avec des segments en arc. Dans tous les cas, décaler "à l'intérieur" n'a de sens que si la polyligne fermée, comme décaler "à droite" n'a de sens que pour un polyligne ouverte. ;; PLINE-ALGEBRAIC-AREA (gile) ;; Returns the algebraic area of the polyline ;; the area is negative if the polyline is clockwise ;; ;; Argument: a polyline ename (defun Pline-Algebraic-Area (pl / elst lst tot cen p0 area cen) (setq elst (entget pl)) (while (setq elst (member (assoc 10 elst) elst)) (setq lst (cons (cons (cdar elst) (cdr (assoc 42 elst))) lst) elst (cdr elst) ) ) (setq lst (reverse lst) tot 0.0 p0 (caar lst) ) (if (/= 0 (cdar lst)) (setq tot (polyarc-algeb-area (cdar lst) p0 (caadr lst)) ) ) (setq lst (cdr lst)) (if (equal (car (last lst)) p0 1e-9) (setq lst (reverse (cdr (reverse lst)))) ) (while (cadr lst) (setq tot (+ (triangle-algeb-area p0 (caar lst) (caadr lst)) tot)) (if (/= 0 (cdar lst)) (setq tot (+ tot (polyarc-algeb-area (cdar lst) (caar lst) (caadr lst)))) ) (setq lst (cdr lst)) ) (if (/= 0 (cdar lst)) (setq tot (+ tot (polyarc-algeb-area (cdar lst) (caar lst) p0))) ) tot ) ;; TRIANGLE-ALGEB-AREA (gile) ;; Returns the algebraic area of the triangle defined by three 2d points ;; the area is negative if points are clockwise ;; ;; Arguments: three 2d points (defun triangle-algeb-area (p1 p2 p3) (/ (- (* (- (car p2) (car p1)) (- (cadr p3) (cadr p1)) ) (* (- (car p3) (car p1)) (- (cadr p2) (cadr p1)) ) ) 2.0 ) ) ;; POLYARC-ALGEB-AREA (gile) ;; Returns the algeraic area of a 'polyarc' ;; ;; Arguments ;; bu : polyarc bulge ;; p1 : start point ;; p2 : end point (defun polyarc-algeb-area (bu p1 p2 / ang rad) (setq ang (* 2 (atan bu)) rad (/ (distance p1 p2) (* 2 (sin ang)) ) ) (/ (* rad rad (- (* 2 ang) (sin (* 2 ang)))) 2.0) ) Exemple d'utilisation pour décaler vers l'intérieur une polyligne fermée. ;; OffsetInside (gile) ;; Offset inside a closed polyline ;; ;; Arguments ;; pl: a polyline (ename or vla-object) ;; dist: offset distance ;; ;; Returns a variant ;; (an array of the newly created objects resulting from the offset). (vl-load-com) (defun OffsetInside (pl dist / obj) (if (= (type pl) 'ENAME) (setq obj (vlax-ename->vla-object pl)) (setq obj pl pl (vlax-vla-object->ename obj) ) ) (vla-offset obj (if (minusp (Pline-Algebraic-Area pl)) dist (- dist) ) ) ) -
[Résolu] Comment décaler une polyligne ?
(gile) a répondu à un(e) sujet de DenisHen dans Débuter en LISP
Salut, Ce n'est pas la méthode la plus sûre, mais la plus "simple". (setq pts nil) (command "_.pline") (while (not (zerop (getvar "cmdactive"))) (command pause) (setq pts (cons (getvar 'lastpoint) pts)) ) (setq pts (reverse (cdr pts))) (command "_.offset" 5 (entlast) (polar (car pts) (- (angle (car pts) (cadr pts)) (/ pi 2)) 1 ) "" ) -
Salut, Tu peux ajouter des rangées à ton tableau d'extraction. Il faut déverrouiller ces nouvelles rangées pour pouvoir y mettre du contenu. Ensuite tu peux mettre des formules (comme dans Excel) dans certaines cellules des nouvelles rangées, ainsi quand tu mets à jour ton extraction, ces cellules se mettront aussi à jour. Tu peux aussi faire un tableau séparé pour les totaux avec des champs Formule.
-
Programmation fonctionnelle ou impérative
(gile) a répondu à un(e) sujet de (gile) dans Pour aller plus loin en LISP
Les deux paradigmes sont supportés, on peut donc faire les deux quand on a le choix, c'est une question de préférence. Ceci dit on n'a pas toujours le choix, on utilise généralement AutoLISP pour modifier l'état d'un dessin AutoCAD et ça c'est typiquement impératif. Toutes les fonctions qui retournent toujours nil comme command, prompt, etc. sont typiquement procédurales. D'un autre côté, pour traiter une structure en arborescence, la récursion est incontournable. En fait on a le choix dans le traitement des données, notamment des nombres et des listes. Le paradigme fonctionnel permet en général du code plus concis et parfois plus facile à lire (déclaratif) à condition de connaître les fonctions utilisées. Il permet aussi d'écrire du code plus robuste et facile à maintenir (même si ça s'applique moins à AutoLISP qu'à des langages plus "riches"). Après je pense qu'il s'agit vraiment de deux façons de penser/raisonner différentes (qui ne sont pas incompatibles) et j'ai pu noter que ceux qui étaient ou devenaient à l'aise avec le paradigme fonctionnel étaient du coup plus à l'aise avec AutoLISP en général. Autrement dit, la compréhension des fonctions d'ordre supérieur (mapcar), des fonctions anonymes (lambda) et de la récursivité est, à mon avis, une étape majeure dans l'apprentissage du LISP qui permet une compréhension plus intime du plus ancien langage fonctionnel. -
Salut, De ci de là on parle de paradigmes de programmation, j'ai donc pensé qu'il pouvait être intéressant de démarrer un sujet à propos des paradigmes de programmation supportés par AutoLISP / Visual LISP, à savoir la programmation fonctionnelle et la programmation impérative (procédurale). Ces deux paradigmes correspondent à deux façons de penser, deux approches différentes pour résoudre un problème. En gros, en programmation impérative, le code décrit en détail toutes les étapes de modifications des états des données nécessaires pour atteindre l'objectif. En programmation fonctionnelle, pour éviter les changements d'état, on fait appel à des applications de fonctions (comme en mathématique) imbriquées dans un code plus déclaratif (on décrit ce qu'on veut obtenir plutôt que la façon de l'obtenir). Je vais essayer d'illustrer ça avec un exemple simple : calculer la somme des carrés des nombres contenus dans une liste. En programmation impérative, on modifie l'état d'une variable en lui affectant une nouvelle valeur à chaque itération dans une boucle. L'algorithme décrit comment procéder : - initialiser sum à 0 - pour chaque élément de la liste (x), affecter à sum sa valeur additionnée du carré de x - renvoyer la valeur finale de sum (defun sumOfSquares (lst / sum) (setq sum 0) (foreach x lst (setq sum (+ sum (* x x))) ) sum ) Avec la liste : (2 3 4) initialisation : sum = 0 première itération, x = 2, sum = 0 + 2 * 2 = 4 seconde itération, x = 3, sum = 4 + 3 * 3 = 13 troisième itération, x = 4, sum = 13 + 4 * 4 = 29 En programmation fonctionnelle, on imbrique des appels de fonctions. Premier exemple avec l'utilisation d'une fonction récursive (très courant en programmation fonctionnelle). Un algorithme récursif tend à décrire l'intention plus que la méthode : - ajouter le carré du premier élément à la somme des carrés des éléments suivants ou à 0 si la liste est vide (defun sumOfSquares (lst) (if lst (+ (* (car lst) (car lst)) (sumOfSquares (cdr lst)) ) 0 ) ) Avec une fonction récursive, les appels récursifs construisent une imbrication d'appels de fonctions jusqu'à ce que la condition d'arrêt soit atteinte (empilement), l'évaluation peut alors avoir lieu (dépilement). Avec la liste (2 3 4) (sumOfSquares '(2 3 4) (+ 4 (sumOfSquares '(3 4))) (+ 4 (+ 9 (sumOfSquares '(4)))) (+ 4 (+ 9 (+ 16 (sumOfSquares '())))) (+ 4 (+ 9 (+ 16 0))) 29 Mais une des caractéristiques de la programmation fonctionnelle est de considérer les fonctions comme n'importe quelle autre type de donnée. On peut lier un symbole à une fonction avec setq : (setq f sqrt) et utiliser le symbole comme la fonction : (f 25)renvoie 5.0. Mais ça permet surtout d'utiliser une fonction comme argument d'une autre fonction dans ce qu'on appelle les fonctions d'ordre supérieur (apply, mapcar, vl-some, vl-remove-if, ...) Second exemple avec des fonctions d'ordre supérieur Ce type de fonction permet d'écrire du code de manière déclarative. L'algorithme se réduit une déclaration de ce que l'on souhaite obtenir: - faire la somme des nombres de la liste mis au carrés (defun sumOfSquares (lst) (apply '+ (mapcar '(lambda (x) (* x x)) lst)) ) La fonction apply applique la fonction qui lui est passé en premier argument (ici, +) aux arguments contenus dans la liste qui lui est passée en second argument (ici, la liste de nombres retournées par (mapcar ...)). La fonction mapcar retourne une liste qui est le résultat de l'application de la fonction qui lui est passée en premier argument à tous les éléments de la liste qui lui est passée en second argument. La fonction passée en argument à mapcar est une fonction lambda, encore une spécificité de la programmation fonctionnelle. (lambda (x) (* x x)) renvoie le carré du nombre qui lui est passé an argument Avec la liste (2 3 4) (mapcar '(lambda (x) (* x x)) '(2 3 4))renvoie (4 9 16) (apply '+ '(4 9 16)))renvoie le résultat de l'évaluation de (+ 4 9 16), soit 29 Autres exemples Supprimer tous les doublons d'une liste (1 2 1 3 2 3) => (1 2 3). Impératif : (defun distinct (lst / res) (while lst (setq res (cons (car lst) res) lst (vl-remove (car lst) lst) ) ) (reverse res) ) Fonctionnel (récursion) : (defun distinct (lst) (if lst (cons (car lst) (distinct (vl-remove (car lst) lst))) ) ) Transposer une matrice ((1 2 3) (4 5 6)) => ((1 4) (2 5) (3 6)) Impératif : (defun transpose (mat / i j row res) (repeat (setq i (length (car mat))) (setq i (1- i) row nil ) (repeat (setq j (length mat)) (setq j (1- j) row (cons (nth i (nth j mat)) row) ) ) (setq res (cons row res)) ) ) Fonctionnel (un joyaux du LISP à mon sens) : (defun transpose (mat) (apply 'mapcar (cons 'list mat)) )
-
Comment savoir si un Lisp existe avant de le charger ?
(gile) a répondu à un(e) sujet de DenisHen dans Débuter en LISP
Il me semble que eval est superfétatoire, (if c:cat (alert "Lisp CAT déjà chargé")) suffirait. Si on veut écrire quelque chose de plus explicite, la fonction boundp me semble plus indiquée : (if (boundp 'c:cat) (alert "Lisp CAT déjà chargé")) -
Je crains qu'il n'y ait là quelque confusion entre ce qu'on appelle les paradigmes des langages de programmation (orienté objet, fonctionnel, impératif/procédural) et leur syntaxe. La plupart des langages de programmations sont multi-paradigmes et tous (excepté certains langages purement fonctionnels) supportent la programmation impérative/procédurale : AutoLISP (dialecte du plus ancien langage fonctionnel) tout comme Java ou C# (langages typiquement orientés objet). Le fait d'écrire : objet.methode(arguments) ou : methode(objet, argument) ne définit en rien un paradigme de programmation, c'est uniquement une question de syntaxe (avec support de l'opérateur '.' ou pas). D'ailleurs la plupart des langages qui utilisent cet opérateur, supportent aussi l'autre syntaxe. Ce qui fait la particularité du LISP c'est : la notation préfixe (on écrit (+ 2 3) au lieu de 2 + 3) ainsi qu'une tendance culturelle intrinsèque à l'imbrication d'appels de fonction. Intrinsèque parce que LISP se définit récursivement : une expression LISP est : soit un atome ; soit une liste d'expressions LISP. Culturelle parce que, en programmation fonctionnelle, on a tendance à préférer utiliser des appels de fonction plutôt que des variables. Je pense que c'est à cette imbrication d'appels de fonctions et à leur évaluation depuis l'expression la plus imbriquée que ALEX-_-45 fait allusion quand il parle de lecture "à l'envers".
-
Comment faire une liste de paires pointés ?
(gile) a répondu à un(e) sujet de DenisHen dans Débuter en LISP
!!?? Essaye : (listbox "Test" "" (mapcar 'cons '("A" "B" "C") '("A" "B" "C")) 1) -
Comment faire une liste de paires pointés ?
(gile) a répondu à un(e) sujet de DenisHen dans Débuter en LISP
Mets des lunettes : -
Comment faire une liste de paires pointés ?
(gile) a répondu à un(e) sujet de DenisHen dans Débuter en LISP
Pour mémoire : (mapcar 'fun '(a b c))est équivalent à : (list (fun a) (fun B) (fun c)) et : (mapcar 'fun '(a b c) '(d e f))à : (list (fun a d) (fun b c) (fun c f)) où fun est une fonction qui peut être une fonction LISP prédéfinie, une fonction LISP définie avec (defun ...) ou une fonction lambda qui prend un seul argument dans le premier cas et deux dans le second. -
Comment faire une liste de paires pointés ?
(gile) a répondu à un(e) sujet de DenisHen dans Débuter en LISP
Je pense que tu veux plutôt parler de OptionBox ou ListBox. Toutes deux prennent en argument une liste de paires pointées (key . label). si je comprends bien, tu veux utiliser la même valeur comme clé et comme libellé à savoir le nom de la vue. Tu as donc une liste de type : '("A" "B" "C") et il te faut : '(("A" . "A") ("B" . "B") ("C" . "C"))autrement dit : (list (cons "A" "A") (cons "B" "B") (cons "C" "C"))et c'est exactement ce que fait : (mapcar 'cons '("A" "B" "C") '("A" "B" "C")) PS : un exemple est donné dans les commentaires de ListBox avec (layoutlist). -
[Résolu] Où se trouvent le nom des vues enregistrées ?
(gile) a répondu à un(e) sujet de DenisHen dans Débuter en LISP
On peut aussi faire une petite routine générique pour lister n'importe quelle table. (defun listTable (tblname / rec lst) (while (setq rec (tblnext tblname (not rec))) (setq lst (cons (cdr (assoc 2 rec)) lst)) ) (reverse lst) ) (listTable "view") retourne la liste des noms des vues enregistrées (listTable "block") la liste des blocs (listTable "appid") celle des application enregistrées etc. -
[Résolu] Où se trouvent le nom des vues enregistrées ?
(gile) a répondu à un(e) sujet de DenisHen dans Débuter en LISP
Salut, Petite astuce couramment utilisée avec tblnext pour démarrer au début de la collection (l'argument T) Si view est le nom de la variable qui prendra tour à tour chaque enregistrement contenu dans la table et que la variable view a bien été déclarée localement (comme il se doit), au lancement de la boucle (while ...), view vaut nil, donc (not view) renvoie T et après la première itération view ne vaudra plus nil et (not view) retournera nil. On peut donc faire : (defun c:CherchView (/ view LstView) (while (setq view (tblnext "VIEW" (not view))) (setq LstView (cons (cdr (assoc 2 view)) LstView))) (setq LstView (vl-sort LstView '<)) (princ LstView) (princ) ) -
Salut, Il est primordial de bien choisir la fonction getXXX en fonction du type de données qu'on souhaite obtenir. Utiliser getstring pour obtenir un nombre est possible (getstring accepte tout type d'entrée au clavier) mais ça suppose que le programme vérifie que l'utilisateur a bien entré un nombre. Avec getint, AutoLISP fera lui même ce contrôle à notre place, ce qui garantit que la valeur entrée sera bien un nombre entier (ou nil). En règle générale, on choisi la fonction getXXX la plus adaptée au type de donnée souhaitée : pour un entier: getint plutôt que getstring pour une option (mot clé) : getkword plutôt que getstring pour une distance : getdist plutôt que getreal et que getstring Si je comprends bien la demande, il faudrait inviter l'utilisateur à entrer un nombre entier en lui proposant une valeur par défaut. Dans AutoCAD, pour spécifier une valeur par défaut on fait Entrée au lieu se spécifier une valeur. Avec la fonction getint, quand on fait Entrée au lieu de spécifier un nombre la fonction getint renvoie nil. C'est ça qu'on va utiliser pour proposer une valeur par défaut. Voilà un exemple qui montre aussi l'utilisation de initget pour empêcher l'utilisateur d'entrer 0 ou un nombre négatif, et dans le premier cas, de faire Entrée. ;; Si numero_tube est nil (la variable n'a jamais été initialisée) (if (null numero_tube) ;; Alors, on invite l'utilisateur à entrer un nombre (progn (initget 7) ;_ <- force l'utilisateur à en entrer un nombre strictement positif (setq numero_tube (getint "\nEntrez le numéro du premier tube :")) ) ;; Sinon, on invite l'utilisateur à entrer un nombre ;; en lui proposant la valeur courante de numero_tube + 1 par défaut (progn (initget 6) ;_ <- le nombre doit être strictement positif, mais l'utilisateur peut faire Entrée ;; Si l'utilisateur entre un nombre (if (setq n_tube (getint (strcat "\nEntrer le numéro du premier tube <" (itoa (1+ numero_tube)) ">:" ) ) ) ;; Alors, on assigne à numero_tube la valeur spécifiée (setq numero_tube n_tube) ;; Sinon, on incrémente numero_tube (setq numero_tube (1+ numero_tube)) ) ) )
-
Un peu de théorie fondamentale Une expression LISP (ou appel de fonction) a la forme : (fonction [arguments ...]) Elle commence par une parenthèse ouvrante, immédiatement suivie par une fonction puis, optionnellement, un ou plusieurs arguments et enfin une parenthèse fermante. (+ 2 3)+ est la fonction 2 et 3 sont les arguments. La fonction, comme les arguments peuvent aussi être des appels de fonctions (d'où les imbrications et les nombreuses parenthèses typiques du LISP). nil est une expression particulière du LISP qui signifie à la fois rien, une liste vide ou faux (false). Dans le cas qui nous concerne (en reformatant le code pour qu'il soit plus lisible). ( (lambda (c s) (if s (command "_.chprop" s "" "_layer" c "") ) (setvar 'clayer c) ) "-EAS-Attente de validation" (cadr (ssgetfirst)) ) (lambda (c s) (if s (command "_.chprop" s "" "_layer" c "") ) (setvar 'clayer c) )est la fonction. Ici une fonction anonyme qu'on décortiquera plus bas. "-EAS-Attente de validation"et (cadr (ssgetfirst))sont les arguments. Le second est un appel de fonction. cadr est la fonction, (ssgetfirst) est l'argument, et c'est encore un appel de fonction (sans argument lui). ssgetfirst renvoie une liste dont le premier élément est toujours nil et le second élément est le jeu de sélection actif s'il y en a un ; sinon, nil. cadr renvoie le second élément d'une liste, donc ici, un jeu de sélection ou nil. Une fonction anonyme (ou expression lambda) est une définition de fonction qui utilise la fonction lambda suivie de la liste des arguments et variables locales puis des expressions à évaluer. Ici la liste des arguments (c s) définit deux arguments c et s qui seront utilisés dans les expressions de la fonction lambda en prenant respectivement les valeurs de "-EAS-Attente de validation" et du résultat de l'évaluation de (cadr (ssgetfirst)). En résumé, on va évaluer les expressions contenues dans le corps de l'expression lambda avec : c = "-EAS-Attente de validation" s = le jeu de sélection actif ou nil s'il n'y en a pas. Le corps de l'expression lambda ne contient que deux expressions : (if s (command "_.chprop" s "" "_layer" c "") )qui est une "expression conditionnelle" de la forme : (if condition then [else]) où condition, then et, optionnellement, else sont des expressions qui peuvent aussi être des appels de fonction. En LISP, toute condition est considérée comme vraie (true) si elle n'est pas nil. Dans notre cas, la condition est s qui sera considérée comme vraie s'il y a une sélection active. Si c'est le cas l'expression then sera exécutée, à savoir : (command "_.chprop" s "" "_layer" c "") qui est simplement un appel de la fonction command qui lance une commande AutoCAD et lui passe ses options dont le jeu de sélection s et le nom du calque c. Si ce n'est pas le cas, il n'y a pas ici d'expression then donc on ne fait rien. (setvar 'clayer c)sera exécutée dans tous les cas puisqu'elle est en dehors de l'expression (if ...). Cette expression rend le calque c courant.
-
AutoLISP est un langage de programmation embarqué dans AutoCAD, c'est à dire que AutoCAD intègre un interpréteur LISP et que cet interpréteur est accessible directement depuis ligne de commande. Si tu entres (+ 2 3) en ligne de commande, AutoCAD détecte une parenthèse et passe l'expression à l'interpréteur LISP. Celui-ci évalue l'expression et renvoie le résultat à AutoCAD : la ligne commande affiche 5. On peut donc utiliser des expressions LISP en ligne de commande pour répondre à des invites mais aussi dans les macros de commande et dans les scripts.
-
Salut, Si tu as une version pleine, c'est assez facile à faire en LISP (si c'est faisable en Diesel, je ne sais pas le faire). ^C^C((lambda (c s) (if s (command "_.chprop" s "" "_layer" c "")) (setvar 'clayer c)) "-EAS-Attente de validation" (cadr (ssgetfirst)))
-
Salut, C'est géré par la variable système CENTERLTYPE (et éventuellement CENTERLTYPEFILE). Il ne faut pas hésiter à consulter l'aide...
-
Salut, J'ai un peu modifié le LISP de Lee Mac. Deux commandes : - AUTOSAVEON : pour activer le réacteur - AUTOSAVEOFF : pour désactiver le réacteur Le réacteur ne prends en compte que l'évènement :vlr-commandEnded, c'est à dire les commandes qui ont abouti (inutile, à mon avis de comptabiliser les commandes qui ont échoué ou ont été annulées). L'utilisateur est averti si le dessin n'est pas enregistré. EDIT: Le fichier .bak est copié dans le même répertoire renommé avec la date et l'heure avec l'extension .dwg. J'ai évité toutes les variables globales. (vl-load-com) (defun c:AutoSaveOn () (if (not (vl-some '(lambda (rea) (equal '((:vlr-commandended . AUTOSAVE)) (vlr-reactions rea) ) ) (cdar (vlr-reactors :VLR-Command-Reactor)) ) ) (vlr-command-reactor 0 '((:vlr-commandended . AUTOSAVE))) ) (princ) ) (defun c:AutoSaveOff () (foreach rea (cdar (vlr-reactors :VLR-Command-Reactor)) (if (equal '((:vlr-commandEnded . AUTOSAVE)) (vlr-reactions rea) ) (vlr-remove rea) ) ) (princ) ) (defun autosave (rea lst / filename) (if (zerop (rem (vlr-data-set rea (1+ (vlr-data rea))) 20)) (if (= 1 (getvar 'dwgtitled)) (progn (vla-save (vla-get-ActiveDocument (vlax-get-acad-object))) (setq filename (strcat (getvar 'dwgprefix) (vl-filename-base (getvar 'dwgname)))) (vl-file-rename (strcat filename ".bak") (strcat filename "_" (rtos (getvar 'cdate) 2 6) ".dwg") ) ) (alert "\nLe dessin n'est pas enregistré") ) ) (princ) )
-
Salut, D'après ce que j'ai lu, BLADE fait parti de la mise à jour intermédiaire 18.2. L'as-tu installée ?
-
Salut, C'est normal, le triangle fait parti du jeu de sélection de l'action d'étirement, pas le cercle... Tu devrais utiliser deux états de visibilité plutôt qu'une inversion.
-
Au risque de paraître (encore) faire le pédant 'professeur', je préciserais que les goélands/gabians ne s'éloignent que très rarement de la mer. Ce sont plutôt les mouettes, qui chassées des bords de la grande bleue par les gabians, remontent le Rhône, la Durance et autres cours d'eaux jusque haut dans les alpes (j'en ai vu sur le lac Léman).
-
Il y en plein à Marseille, ici on les appelle "gabians", ils ont de plus en plus tendance à se nourrir dans les poubelles et mangent plus souvent des restes de poulet que du poisson (je retrouve régulièrement des os sur ma terrasse). Il y a trois ans un couple a réussi à nicher sur un pan du toit (faible pente) et à couver sans qu'on s'en rende compte jusqu'à ce qu'un petit éclose. Et là, tant que le petit n'a pas pris son envol, impossible de retourner sur la terrasse sans se faire sérieusement agresser par les parents, environ 1.50 m d'envergure et un bec de plus de 5 cm, c'est "Les oiseaux" d'Hitchcock en vrai ! Depuis, en cette saison, je dois monter régulièrement sur le toit pour empêcher toute velléité de nidification.
-
Le lien était mal fait, c'est réparé. CustomCurvesSetup.msi
-
Salut, Je te propose une autre façon avec la commande BALAYAGE (_SWEEP) avec l'option baSculement (_Twist). Pour le chemin du balayage, j'ai utilisé une courbe appelée chainette dessiné avec la routine donnée ici (tu peux aussi utiliser le LISP de la réponse suivante. Un petit screencast.
