Aller au contenu

Déterminer si un bloc se trouve à gauche ou à droite d'une polyligne


Messages recommandés

Posté(e)

Pour un futur projet je me pose la question s'il est possible de savoir si un bloc est à gauche ou à droite d'une polyligne.

Graphique:

           [B1]__
          _______|______
         /    |         \
        /     |__[B2]    \_____ (A')
 (Z')__/
           [B3]__
          _______|______
         /    |         \
        /     |__[B4]    \_____ (Z)
 (A) __/
 

Chemin (à base de polyligne) dans un bloc avec attribut (A/Z ou Z'/A') pour le sens de circulation (il y a le sens de la polyligne mais en fait je veux pas en tenir compte).
Les attributs (A/Z ou Z'/A') pour indiquer le "début" et la "fin" du chemin (saisie par l'utilisateur).
Pour les blocs (B1 à B4), qui ne contiennent pas la barre verticale, je pense me focaliser sur la rotation du bloc par rapport à la polyligne pour ainsi savoir si le bloc [B1] est dans le sens normal (réponse oui) de circulation, avec d'autres champs automatiques comme le nom du bloc chemin ...
L'idée est de demander à l'utilisateur de sélectionner [B1] puis de demander à quel bloc chemin il appartient (en l'occurence (A'/Z')).

Je ne demande pas un programme tout fait, mais plutôt de savoir si ce que j'envisage est possible ou non.
Merci.

 

PS: En vue éclatée (car j'ai pas réussi à mettre de la couleur sur le graphique au-dessus) :

Bloc Chemin (A') à (Z')
          ______________
         /              \
        /                \_____ (A')
 (Z')__/

Bloc Chemin (A) à (Z)
          ______________
         /              \
        /                \_____ (Z)
 (A) __/

Blocs de signalisation :
[B1]__

__[B2]

[B3]__

__[B4]

 

Posté(e)

Coucou,

Alors je pense ne pas avoir compris parfaitement le problème... Tu n'as que des blocs dans ton histoire, aucune ligne ou polyligne ? Car tu as tes blocs de signalisation, qui sont donc des blocs et on veut savoir de quel côté ils se trouvent et tu as le bloc chemin, qui du coup est aussi un bloc...

Pourquoi faut-il un bloc pour le chemin au lieu d'une polyligne basique...? Dans le cas d'un chemin à base d'une polyligne je prendrais ceci :

((lambda (/ crv blk ptb ptc prm i pta ptz ang bng)
  (setq
    crv (car (entsel "\nSelect polyline : "))
    blk (car (entsel "\nSelect block : "))
    ptb (cdr (assoc 10 (entget blk)))
    ptc (vlax-curve-getClosestPointTo crv ptb)
    prm (vlax-curve-getParamAtPoint crv ptc)
    i (fix prm)
    pta (vlax-curve-getPointAtParam crv i)
    ptz (vlax-curve-getPointAtParam crv (1+ i))
    ang (angle pta ptz)
    bng (angle ptc ptb)
  )
  (cond
    ((equal (- bng ang) (/ pi 2.) 1e-15) "left")
    ((equal (- bng ang) (/ (* 3.0 pi) 2.) 1e-15) "right")
  )
))

Évidemment on peut simplifier l'écriture, etc mais c'est juste à titre d'exemple, je ferais quelque chose comme cela perso. Si je devais traduire mathématiquement parlant, je dirais qu'il suffit de calculer l'angle entre la normale induite par le bloc projeté sur ta courbe et l'angle de ton segment. Pour être encore plus dans le vrai, il ne faudrait pas utiliser le PointAtParam mais plutôt la FirstDeriv pour pouvoir également gérer les courbes d'une polyligne/spline.

Bisous,
Luna

Posté(e)

Merci @Luna

Pour répondre à la question d'un bloc à la place d'une polyligne classique, c'est que le bloc je peux lui donner un nom contrairement à une polyligne, du style "section 1 voie 1" ou "raccord n°XX" ou "truc mumuche" ...

Donc en fait "il suffirait" de remplacer "Select polyline" par la sélection du bloc chemin qui irait automatiquement rechercher la polyligne qui s'y trouve.

L'idée est donc de créer un lien entre le bloc de signalisation et le bloc chemin, afin de permettre au bloc de signalisation d'aller récupérer en mode champ automatique toutes les infos nécessaires dans le bloc chemin. Une sorte de mini-Revit 🤪 afin de limiter les saisies de l'utilisateur (qui sont longues et fastidieuses 😣).

Posté(e)

Si c'est juste une histoire de nom, regarde plutôt du côté des données étendues et/ou gestion de dictionnaires, c'est bien plus pratique !!
Je n'ai personnellement pas encore eut le temps d'étudier ce domaine de la programmation mais je comprends son fonctionnement donc cela devrait être la solution que tu recherches pour te simplifier la vie en temps que développeur ET d'utilisateur 😉

Bisous,
Luna

Posté(e)

J'ai une autre méthode :

0°) Sélection du bloc

1°) Je sélectionne la polyligne et j'en extrait le point de sélection (utile pour valider le segment à vérifier)

2°) Je recherche sur quel segment de ma polyligne est mon point de sélection et j'en définis la fonction affine avec les deux points.

3°) je peux donc définir avec ça si le bloc est au dessus ou en dessous de la polyligne 😉

https://moonbooks.org/Articles/Créer-un-algorithme-pour-vérifier-si-un-point-et-au-dessus-ou-au-dessous-dune-droite/

 

Posté(e)

Merci @Curlygoth, à tester aussi.

@Luna, chat à l'air intéressant, mais chat à l'air un poil complexe ton affaire 😅

Le plus dur avant de se lancer tête baissée, c'est de bien définir la structure, et là y'a du boulot car pour l'instant je n'ai seulement que 2/3 idées, je n'ai pas encore la vision globale du projet.

En fait, le projet existe déjà, mais j'ai envie que l'utilisateur fasse moins de saisies manuelles, et qu'il y ait plus de nouvelles informations comme le sens d'orientation du bloc signalisation (actuellement y'a pas, mais ça deviendra un plus pour un autre programme qui est déjà en cours).

Posté(e)

@JPhil,

En vrai les données étendues c'est simple ! 😉

Citation

vlax-ldata-put (vlax-ldata-put dict key data [private])

Stocke une donnée LISP dans un dictionnaire ou une entité. Le dictionnaire est créé s'il n'existe pas.

Retourne la valeur de data ou nil.

dict : une entité AutoCAD (ename ou vla-object) ou un nom (clé primaire)

key : la clé (secondaire) pour récupérer la donnée.

data : tout type de donnée LISP

private : (optionnel) si vlax-ldata-put est exécuté depuis un VLX dans un espace de nom séparé et que cet argument est spécifié et non nil, la donnée ne sera récupérable que par ce VLX.

 

 

;; créer une donnée LISP
(vlax-ldata-put "VL_DICO" "data1" "test")
(vlax-ldata-put "VL_DICO" "data2" '(1 2 3))
 

 

 

vlax-ldata-get (vlax-ldata-get dict key [default-data] [private])

Récupère une donnée LISP dans un dictionnaire ou une entité.

Retourne la donnée si elle est existe sinon la valeur de default-data si elle a été spécifiée, sinon nil.

dict : une entité AutoCAD (ename ou vla-object) ou un nom (clé primaire)

key : la clé (secondaire) pour récupérer la donnée.

default-data : (optionnel) la donnée à retourner si la clé n'est pas trouvée

private : (optionnel, default-data doit être spécifié) si vlax-ldata-get est exécuté depuis un VLX dans un espace de nom séparé et que cet argument est spécifié et non nil, vlax-ldata-get récupère la donnée.

Autrement dit tu peux simplement faire :

((lambda (key value / crv val)
  (setq crv (car (entsel "\nSelect polyline : ")))
  (if (null (setq val (vlax-ldata-get crv key)))
    (setq val (vlax-ldata-put crv key value))
    val
  )
))

Donc pour ton exemple tu peux définir la 'key' avec un string du genre "Nom" et 'value' tu définis "section 1 voie 1", "raccord n°XX" ou "truc mumuche" 😉
Ya pas plus simple pour ajouter une donnée étendue ou choper sa valeur existante. Et du coup c'est directement liée à l'objet sélectionné et c'est enregistré dans la liste DXF de l'objet donc si tu fermes/ré-ouvres le dessin, les données sont conservées (si je ne dis pas de bêtises).

Convaincu ou il faut encore que je donne un autre exemple pour éviter l'utilisation de blocs à référence unique dans le seul et unique but de "nommer" une polyligne ? xD

Bisous,
Luna

Posté(e)
Citation

...utilisateur fasse moins de saisies manuelles...

 

Je fonctionne beaucoup avec des listes intelligentes ou base de données (l'idée c'est que dès qu'il y a un éléments supplémentaires que le programme ne connais pas

l'utilisateur paramètre "la données/ l'objet" et est enregistrée, une fois que tu reviens (pour une autre dessin)  mes collègues vont pouvoir chosir une données préalablement entrée et modifier les paramètres si besoin pour eux... (une base par défault / une base par utilisateur)

c'est long à mettre en place, la base n'est jamais terminée, mais au moins elle est alimentée continuellement 😉 et surtout pas de doublons !

 

@Luna

Citation

Convaincu ou il faut encore que je donne un autre exemple pour éviter l'utilisation de blocs à référence unique dans le seul et unique but de "nommer" une polyligne ? xD

et du coup c'est enregistrer dans le dessin ? (j'aimerais effectivement nommer ou mettre une/des donnée sur des polylignes)

(histoire de connecter des polylignes entre elle)

Posté(e)

Bonjour @JPhil

 

Je reviens au premier énoncé, car je m'apprêtais à répondre, mais quelque chose est bloquant.

Il est écrit : (il y a le sens de la polyligne mais en fait je veux pas en tenir compte).

Quand je dis que c'est bloquant, c'est que sans tenir compte du sens de construction de la poyligne il n'est pas possible de définir la droite de la gauche pour la position du bloc.
Pour répondre Gauche ou droite, c'est quelques lignes de code, mais c'est toujours en tenant compte du sens de construction…

On peut en savoir plus sur cette vue de l'esprit ?

Amicalement

Éternel débutant…
Mon site perso : Programmer dans AutoCAD

 

 

Posté(e) (modifié)

@Curlygoth,

Je n'ai pas encore vraiment pris le temps pour comprendre parfaitement l'utilisation des données étendues et des dictionnaires, donc rien de ce que je dis sur ce sujet est une certitude pour le moment. Disons que les quelques lignes que j'ai pu comprendre et sur le fonctionnement supposée (modification de la liste DXF d'un objet), cela me semble cohérent que les données soient enregistrées dans le dessin vui. Je sais qu'il y a une différence entre les données étendues et les dictionnaires mais je ne sais pas exactement quoi...

Edit: Bon du coup j'ai testé vite fait et vui les données étendues ajoutées via (vlax-ldata-put (car (entsel)) ...) sont enregistrées dans le dessin donc à partir du moment où on a ajouté une donnée étendue à un objet, on peut y accéder quand on veut ce qui permet de lier tout type de donnée à un objet (strings, bit-integer, valeur numériques, Entity name, ...). L'utilisateur n'a pas vraiment moyen d'accéder à ces données (sauf avec les ExpressTools : Tools > Attach Xdata / List Object Xdata), par contre pour la programmation cela permet de créer des applications plus évoluées et intelligentes.

 

@didier, de ce que j'ai cru comprendre de sa démarche à ce niveau là, il préfère définir un sens non pas vis-à-vis du sens de construction de la polyligne mais plutôt du sens que l'utilisateur aura défini par la position des attributs A et Z. Autrement dit, même si géométriquement le point de départ de la polyligne est située au niveau de l'attribut Z, il faudra considérer que le sens de construction de la polyligne est inversé.

Pour être honnête, j'ai un peu du mal avec ce principe, surtout lorsqu'on connaît l'existence de la fonction INVERSER (sélection d'UNE polyligne, clic droit > Polyligne > INVERSER) permettant de permuter l'ordre des sommets dans la liste DXF et donc le sens de construction de la polyligne. C'est pour cela que j'essaye de corriger plutôt l'utilisation d'un bloc de polyligne afin de ne plus utiliser ces attributs et privilégier naturellement le sens de la polyligne.

Bisous,
Luna

Modifié par Luna
Posté(e)
il y a 15 minutes, didier a dit :

Bonjour @JPhil

 

Je reviens au premier énoncé, car je m'apprêtais à répondre, mais quelque chose est bloquant.

Il est écrit : (il y a le sens de la polyligne mais en fait je veux pas en tenir compte).

Quand je dis que c'est bloquant, c'est que sans tenir compte du sens de construction de la poyligne il n'est pas possible de définir la droite de la gauche pour la position du bloc.
Pour répondre Gauche ou droite, c'est quelques lignes de code, mais c'est toujours en tenant compte du sens de construction…

On peut en savoir plus sur cette vue de l'esprit ?

Amicalement

Merci @didier.

En effet, je comprends totalement ta remarque qui est totalement légitime et plus simple, mais vu le plan source actuel je voulais éviter les mauvaises surprises, c'est le pourquoi j'avais en tête 2 attributs pour dire toi t'es au début et toi t'es à la fin. En plus j'ai des bouts de chemins à double sens de circulation mais généralement il y a un sens prioritaire.

Bref, comme tu peux le voir il y a plusieurs solutions, reste à savoir quelle décision prendre pour être à la fois souple pour l'utilisateur, et souple pour une évolution future (nouveaux chemins...).

Si je prends l'exemple de mon graphique, potentiellement tu peux avoir un chemin (ou liaison) entre le point (A) et (Z'), ça c'est plutôt simple, mais tu peux avoir un nouveau chemin (en plus de celui qui relie (A) et (Z')) qui part du point (C) se situant entre les points (A) et (Z') vers un nouveau point.

Pour imager, c'est comme si tu devais redéfinir (structurer ?) le réseau routier afin d'avoir des feux de signalisation plus "intelligents" (d'où le mini-Revit).

Il y a eu un travail de fait (plutôt excellent), mais l'outils est arrivé à limitation, d'où mon questionnement pour faire quelque chose d'encore plus fou (d'un point de vue dev) mais surtout plus souple (d'un point de vue utilisateur) et permettant par la suite d'être utilisé pour faire des études ou vérifications d'études.

Posté(e)

Bonjour @JPhil

 

Je ne comprends pas le but à atteindre, désolé.

C'est possible d'avoir un dessin DWG avec des cas de figure, car je ne "visualise" pas les schémas avec des tiretés.
Question : faut-il interroger un bloc et qu'il réponde droite ou gauche ou faut-il insérer tel bloc si c'est à gauche et tel autre bloc si c'est à droite ?

Amicalement

Éternel débutant…
Mon site perso : Programmer dans AutoCAD

 

 

Posté(e)
il y a une heure, Luna a dit :

@Curlygoth,

Je n'ai pas encore vraiment pris le temps pour comprendre parfaitement l'utilisation des données étendues et des dictionnaires, donc rien de ce que je dis sur ce sujet est une certitude pour le moment. Disons que les quelques lignes que j'ai pu comprendre et sur le fonctionnement supposée (modification de la liste DXF d'un objet), cela me semble cohérent que les données soient enregistrées dans le dessin vui. Je sais qu'il y a une différence entre les données étendues et les dictionnaires mais je ne sais pas exactement quoi...

Edit: Bon du coup j'ai testé vite fait et vui les données étendues ajoutées via (vlax-ldata-put (car (entsel)) ...) sont enregistrées dans le dessin donc à partir du moment où on a ajouté une donnée étendue à un objet, on peut y accéder quand on veut ce qui permet de lier tout type de donnée à un objet (strings, bit-integer, valeur numériques, Entity name, ...). L'utilisateur n'a pas vraiment moyen d'accéder à ces données (sauf avec les ExpressTools : Tools > Attach Xdata / List Object Xdata), par contre pour la programmation cela permet de créer des applications plus évoluées et intelligentes.

 

Bonjour à tous,

Une petite précision pour les ldata (qui sont effectivement trés simple d'utilisation)qui ne devrait pas arranger @Curlygoth, car elles sont accessible seulement en Lisp et ObjectArx. 

Un lien de (gile) qui résume cela sur le forum 

A+ Bruno

Apprendre => Prendre => Rendre

Posté(e)

@didier,

Actuellement, il y a deux blocs qui visuellement sont les mêmes, juste le nom du bloc qui change et la rotation.
Donc forcément dans certains coins, il y a le "mauvais" bloc et comme il y a des données qui sont liés avec une base de données externes, c'est difficile de faire un ménage rapide sans mettre le foutoir.
Hors, un seul bloc aurait suffit en appliquant la rotation à l'endroit où il faut, avec une gestion de l'évolution plus souple.
N'étant pas là au début de ce projet (pas loin de 10 ans), je vois des erreurs de choix qui fait que le besoin en interne a évolué mais pas le programme qui lui n'est plus assez souple pour encaisser tout ça.

Donc oui, seulement un seul bloc, l'interroger afin qu'il nous donne sa position.
J'ai conscience que sur le papier c'est super facile, mais à structurer c'est une autre paire de manche. Un joli challenge en fait.


@Luna,

Si je reprends ton exemple de donnée étendue.
J'applique ceci sur une polyligne (dont je peux inverser le sens à tout moment parce que ça me fait plaisir) :

((lambda (key value / crv val)
  (setq crv (car (entsel "\nSelect polyline : ")))
  (if (null (setq val (vlax-ldata-get crv key)))
    (setq val (vlax-ldata-put crv key value))
    val
  )
))

Avec 'key' dont la valeur serait "Nom", et 'value' dont la valeur serait "section 1 voie 1".

J'applique la même procédure sur un bloc de signalisation :

((lambda (key / crvb value val)
  (setq crv (car (entsel "\nSelect bloc de signalisation : ")))
  (setq value (car (entsel "\nSelect polyline de liaison : ")))
  (if (null (setq val (vlax-ldata-get crv key)))
    (setq val (vlax-ldata-put crv key value))
    val
  )
))

Avec 'key' dont la valeur serait "Chemin", et 'value' dont la valeur serait le nom de l'entité polyligne afin de permettre de créer une liaison.

Donc si j'ai bien compris, même si je renomme "section 1 voie 1" en "truc mumuche", le bloc signalisation sera lié à la polyligne à la condition bien évidement de ne pas supprimer cette dernière.

J'ai bon ?

Posté(e)

Vui bien sûr tu peux lier des objets entre eux (enfin juste créer une relation de l'un vers l'autre). Donc vui tu peux mettre un nom à ta polyligne via (vlax-ldata-put) et pour chaque bloc qui doivent être "lier" à cette polyligne tu ajoutes l'EntityName de ta polyligne via (vlax-ldata-put). Comme chat tu peux, même depuis un bloc basique, récupérer le nom (vlax-ldata-get) de la polyligne via son EntityName.

C'est pas clair mes explications, mon dieu...!

Tu pourrais très bien par exemple utiliser ce principe pour faire de la post-sélection en sélectionnant tous les blocs et tu regardes lesquels sont liés à la Polyligne nommée "section 1 voie 1" par exemple. C'est pour cela que je pense sincèrement que cette méthode sera la plus simple sur le long terme car tu auras une fonction/commande qui va créer ces liaisons entre objets ou les mettre à jour, et une fois la première passe faite, tu pourras tout gérer sans aucune intervention utilisateur. Tout ce qu'il faut c'est prévoir les fonctions/commandes pour associer l'ancien au nouveau.

En effet, dans ce principe de données étendues il est logique de créer les objets directement depuis une commande pour créer en auto les liaisons de données étendues sans que l'utilisateur soit au courant. Mais il faut aussi prendre en compte l'existant qui nécessite de demander à l'utilisateur de créer les liaisons de données sur les objets déjà crées sans liaisons. Mais après une fois que le principe est en place, cela facilite grandement les lectures de fichier et traitement d'objets.

Bisous,
Luna

Posté(e)

J'ai pas encore fait l'essai mais que se passe-t-il lorsqu'on duplique une polyligne ou bloc de signalisation qui possèdent une donnée étendue ? 

Ces nouveaux objets auront-ils ces données étendues ou au contraire vierges ? Dans le cas d'une polyligne ça peut être intéressant mais pas dans le cas d'un bloc de signalisation.

Bref, à creuser en attendant que je fasse un schéma fonctionnel.

Merci ;) 

Posté(e)

J'ai testé vite fait, et vui les données étendues sont copiées avec l'entité. Cela est cohérent en soit. Pour esquiver cela, les dictionnaires peuvent probablement palier à ce soucis mais encore une fois, je m'avance dans un domaine inconnu pour moi (pour le moment 🙂 ).

Bisous,
Luna

  • 3 semaines après...
Posté(e)

Le schéma fonctionnel est bien avancé mais pas encore fini.
Je viens de comprendre à l'instant comment ils ont faits (je parle du programme Lisp actuel).
Ben c'est tout simple, ils ont utilisés la technique des données étendues 🥳.
Et là le programme Lisp devient clair ... enfin presque 😅.
Je vais pouvoir dormir sur mes deux oreilles.

Bref, merci à tou(te)s

[Edit]
La zone dans le Lisp qui m'a aidée à la compréhension :

  ;; Lecture des objets
  (setq j (ssget "X" '((-3 . (("Toto"))))))

C'est le -3 qui m'a poussé à regarder >>> ici <<<

Group code // Description
-5 // APP: persistent reactor chain
-4 // APP: conditional operator (used only with ssget)
-3 // APP: extended data (XDATA) sentinel (fixed)
-2 // APP: entity name reference (fixed)
-1 // APP: entity name. The name changes each time a drawing is opened. It is never saved (fixed)

 

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é