Les polylignes chapitre 1
Les polylignes sont un peu plus que des lignes liées par leurs extrémités. Mais si vous dessinez sur Autocad, vous le savez déjà. On va regarder comment les manipuler par la programmation. On va dans un 1ere temps regarder les codes dxf d'une polyligne 2d.
((-1 . <Nom d'entité: 7ffff7a24f0>) (0 . LWPOLYLINE) (330 . <Nom d'entité: 7ffff798f00>) (5 . 1187) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . 0) (100 . AcDbPolyline) (90 . 7) (70 . 0) (43 . 0.0) (38 . 0.0) (39 . 0.0) (10 0.0 0.0) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (10 1.0 0.0) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (10 1.0 1.0) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (10 2.0 1.0) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (10 2.0 2.0) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (10 3.0 2.0) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (10 3.0 3.0) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (210 0.0 0.0 1.0))
Après les entête d'usage, (code -1 0 5 8...) dont je vous invite à regarder la définition dans les références DXF communes à tous les objets, on trouve une succession de codes 10, 40, 41, 42, 91. Le 10 comme souvent est le code pour les coordonnées d'un point, nous voila donc avec les coordonnées successive de tous les points de la polyligne. 40, 41, sont les valeurs de largeur du segment. Le 42 sert pour les arcs. Avec ce qu'on sais déjà faire, parcourir et jouer avec cette liste ne sera pas trop compliqué.
Au fil de l'eau.
Dans mon boulot, je dois régulièrement coté l'altimétrie de réseaux gravitaires. Généralement, le z du point d'arrivée est imposé ou du point de départ, et la pente est connue. |
On le voie, il y a matière à réflexion... ça commence à etre un vrai programme et plus une fonction bricolée... pour ne pas vous décourager, ou vous faire pousser des ailes si vous vous en sortez mieux, j'ai ai passé pas mal de temps, tout dilettante que je suis le bricole en parallèle ces pages et le programme qui va avec environ une à 2h par jour... j'y suis depuis presque une semaine... Ben oui, je suis débutant aussi donc ne vous découragez pas si vous vous en sortez pas en 10mn... La persévérence c'est la clef... après tout le couillon, c'est l'ordi, et c'est à nous d'être plus mailn !
Le bloc
Il y a peu, on a vu comment lire et modifier des attributs. On à donc 2 fonctions sous la main pour faire cette partie du problème. On peu créer un bloc avec 2 attributs R et fe. On verra dans un 2eme temps les blocs dynamique car les sélections demandent un peu de recherches.. le dwg avec une poly et des blocs est ici
on peut du reste repartir sur la trame de ascu0.lsp il n'y aura qu'à réécrire la fonction principale.
Insérer le bloc
Il y aurai peut être, un moyen d'insérer le bloc avec (entmake, mais bon, la commande insérer fera l'affaire Il faudra se méfier des SCU avec un (trans bien placé.
observons...
On lance la commande -INSERER. (le - devant le nom de la commande appelle la version "en ligne") On retrouve à devoir rentrer en ligne de commande les paramètres c'est ceux qu'il va falloir faire passer dans le lisp à (command ...
Commande: -INSERER
Entrez le nom du bloc ou [?]: re-fe
Unités: Mètres Conversion: 1.000
Spécifiez le point d'insertion ou [Pointdebase/Echelle/X/Y/Z/Rotation]: 0
Spécifiez le facteur d'échelle ou [Coin/XYZ] <1>: 1
Entrez le facteur d'échelle en Y <utiliser le facteur d'échelle en X>: 1
Spécifiez l'angle de rotation <0>: 0
Entrez la valeur des attributs.
R <1>: 1
fe <0.00>: 1
Pour passer des paramètre à (command "-_insert" supporte une syntaxe DIESEL mais on peu s'en sortir en passant entre guillemets ce qu'on ferai au clavier et si on respecte les unités informatiques on peu passer des variables par exemple (rappel ne "_non" annule momentanément l'accrochage)
(command "_.-insert" "re-fe" "_non" pt ech ech ang (itoa nr) (rtos fe 2 2))
Bien sur angle doit être en radian et pas en chaîne de caractères
Reste à calculer les valeurs.
(à noter qu'il est préférable d'utiliser la version internationale des commandes)
Description du fonctionnement
On va annoncer que qu'on fait et rappeler que le bloc "re-fe" doit etre présent dans le dessin, puis demander un point sur la polyligne ou "Entrer" pour changer les paramètres qu'on rappelle (échelle, n° de départ, Alti de départ, angle, calque la pente)
Les blocs doivent être positionnés aux sommets de la polyligne avec l'attribut R un entier incrémenté , l’attribut Fe un réel calculé en fonction de la distance au point précédent multiplié parla pente.
Problèmes pts de départ
Demander 1 points peu se faire par un (getpoint mais la polyligne doit être sélectionnée aussi (on doit pouvoir faire mieux, mais faut avancer..) En suite, il faut déterminer si le point cliqué est bien un des sommets de la polyligne. Reste à se méfier de l'ordre dans la liste de ces pts si le 1er point cliqué est à la fin, il faudra inverser la liste des points
Mise à jour
Il serait intéressant de pouvoir mettre à joue un bloc s'il existe plutôt que de le recréer. Cela peut nous permettre si on à d'autres attributs de ne pas les écraser. De toute façon il aurai fallu détruire le bloc si on ne veut pas avoir de superpositions ce qui est pas forcément plus simple. On va donc sélectionner tous les blocs "re-fe" et vérifier si leur point d'insertion correspond à un point de la polyligne, faire une liste de ces blocs
Pour cela, on va faire un ssget filtré sur les blocs "re-fe"
Flirtes ssget
Il est temps de regarder ces filtres (ssget . On va commencer par relire la page 39
Le "_X" sélectionne l'ensemble de la base, il faut trier les blocs dont le nom est "re-fe"
Dans la liste dxf de notre bloc on repère vite (0 . INSERT) et (2 . re-fe)
ça peut donner cette forme.
(ssget "_X" (list '(0 . "INSERT") '(2 . "re-fe") ) )
Il faudra trier cette liste des blocs "re-fe" insérés, pour créer notre liste de bloc qui correspondent aux sommets de la polyligne en faisant une liste avec le point d'insertion et le handle.
Variables globales
On en avait parlé, les effets de bords, que peuvent générer les variables globales sont à éviter.
Mais cela serai intéressant de conserver la valeur du dernier fil d'eau, pour enchaîner les segments. Et aussi pour conserver les valeurs par défaut au cours d'une sécession de dessin. Il va falloir chercher si elles sont affectées avant de les initialiser et leur donner un nom bien typique.
Essayez donc de dessiner le logigramme pour voir voila la trame de Ascu il suffit de la modifier...Si on se complique pas la vie, il y a moyen de s'en sortir à moindre frai... mais je vais nous la compliquer...
Algorithme, morceaux choisis
Je ne vais pas détailler tout l'algorithme en correction, simplement qqs morceaux car je vais commencer à vous faire voir des trucs un peu tordu
Les entrées de paramètres
Pour qu'un programme soit utile, il faut qu'il soit facile à utiliser. Si c'est trop contraignant, ce n'est souvent pas rentable. Je vais m'inspirer de la structure d'entrée sortie du lisp CT.lsp de (gile) qui est de toute beauté et agréable à l'utilisation.
La subtilité consiste à afficher les variables à modifier tout en demandant un point. Si l'utilisateur répond espace (ou entrée) On fait une demande de paramètre puis on re affiche les variables tout en re demandant un point. Tant que l'utilisateur ne clique pas de point il peu donc refaire tous les paramètres.
Pour inclure l'affichage à la boucle, la condition de sortie du while est un ET d'un print et de la non sélection du point. Le print retournant toujours vrai seule la sélection d'un point peu faire sortir de la boucle. Placer le print à cet endroit est plutôt original, mais super efficace.
Dans la boucle on trouve un cond pour choisir le paramètre à modifier.
On demande une nouvelle valeur mais on se sert de (strcat dans la question pour afficher le paramètre actuel, et si on ne fait que valider ce paramètre est conservé. C'est plutôt bien fichu non?
Liste des points de la polyligne
On a déjà vu comment parcourir une liste et en extraire des données, on pourrait parcourir la liste dxf de la polyligne en testant le 1er élément avec un (car puis en la réduisant dans une boucle avec des (cdr... On l'a déjà fait... on le fera encore..
J'ai trouvé beaucoup plus joli ici
(setq lst-pts (mapcar 'cdr (vl-remove-if-not ' (lambda (x) (= (car x) 10)) (entget poly) ) ) )
Il faut reconnaître que la construction est des plus élégantes. Mais un peu énigmatique...
Il faut une fois de plus écouter religieusement les explications de (gile) un peu plus bas
C'est très bien adaptée pour extraire les valeurs successives commençant par (10 XY)
C'est la 1ere fois qu'on parle de (mapcar et de (lambda, mais ce ne sera sûrement pas la dernière.
Mise à jour ou nouveau bloc ?
On dispose d'une liste de point, et d'une liste de bloc. Il faut faire une boucle qui parcours la liste de points avec imbriqué une boucle qui teste si le point testé correspond à un bloc ou non. S'il y a un bloc, on le met à jour, s'il n'y en a pas, on en insère un.
les scu
Il y a 2 endroits qu'il faudra gérer, le (getpoint qui va répondre avec des coordonnées scu, et la commande insérer à la quelle in faut passer des coordonnées scu. tout le reste des calculs peut se faire avec des coordonnée scg.
Une solution
Ca devrait commencer à être plus clair non?
Voici ma solution... je dis bien ma solution car il y en a sans doute pas mal d'autres l'essentiel c'est que ça marche. Des forts en code trouveront sans doute plus économe, des tout débutants plus laborieux.. mais je suis moi même très laborieux :)
C'est pas mal, mais pour la lisibilité d'un dessin, il est préférable de pouvoir déplacer les repères. Donc on peu faire des blocs dynamiques. Voila un autre fichier dwg avec une version orientable et déplacable du bloc re-fr. Il serait perfectible mais ça fera l'affaire.
Ce qui change...
J'ai bien essayer de faire un filtre de sélection sur des blocs dynamiques, et franchement..., c'est compliqué. Et c'est même pas moi qui le dit, c'est Maxence DELANNOY, autre pensionnaire émérite de CadXp, il à fait l'expérience sur son site ici, et pour avoir tout bien lu son code, j'en arrive à la même conclusion que lui, c'est compliqué. On va donc utiliser la même technique chelou d'avec ascu. En faisant une sélection de tous les blocs du dessin, puis en triant dans ce sélection set les blocs qui nous intéressent suivant leur effective name VBA. On passe donc d'un sélection set à une liste et il faudra adapter la boucle de parcours (ssname n'étant pas utilisable sur une liste.
Une autre micro modif dans Vb-Mod-att car on avait écrit cette fonction pour modifier le 1er attribut ( le (nth 0 ) Il faudra rajouter un compteur pour modifier le bon.
Si vous avez compris la version pour blocs normal et les mécanismes utilisé dans ascu, la version pour blocs dynamique ne pose pas de pb...
Voila ma solution...