-
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)
-
La méthode que j'ai donné avec TranslateCoordinates est fausse (je suis allé un peu trop vite en besogne), celle avec la calcul vectoriel (dotProduct) est "juste" (si j'ai bien compris la demande).
-
Une autre méthode en utilisant TranslateCoordinates comme suggéré par @didier dans sa première réponse. On convertit le point P du SCG vers le SCO du plan du triangle, puis on met sa coordonnées Z à 0.0 dans ce système de coordonnées, et enfin on re-convertit le point P dans le SCG pour récupérer sa coordonnée Z. Function CoordZ(pt1 As Variant, pt2 As Variant, pt3 As Variant, pt As Variant) As Double Dim norm(0 To 2) As double norm = CrossProduct(vect(pt1, pt2), vect(pt1, pt3)) pt = ThisDrawing.Utility.TranslateCoordinates(pt, acWorld, acOcs, False, norm) pt(2) = 0.0 pt = ThisDrawing.Utility.TranslateCoordinates(pt, acOcs, acWorld, False, norm) CoordZ = pt(2) End Function EDIT : cette méthode ne fonctionne pas.
-
À ta guise, mais le jour où tu auras à nouveau besoin de définir des vecteurs ou de calculer un produit vectoriel ou scalaire, tu devras tout refaire... Personnellement, si je faisait du VBA (qui sans être réellement 'orienté objet' est quand même 'basé objet') j'aurais des classes Point3d, Vector3d et Matrix3d avec des propriétés et des méthodes pour les calculs géométriques qui permettraient d'écrire du code directement explicite (CF le code VB .NET plus haut).
-
En VBA, ça devrait être quelque chose comme ça: Function Vector(pt1 As Variant, pt2 As Variant) As Variant Dim result(0 To 2) As Double result(0) = pt2(0) - pt1(0) result(1) = pt2(1) - pt1(1) result(2) = pt2(2) - pt1(2) Vector = result End Function Function DotProduct(v1 As Variant, v2 As Variant) As Double DotProduct = v1(0) * v2(0) + v1(1) * v2(1) + v1(2) * v2(2) End Function Function CrossProduct(v1 As Variant, v2 As Variant) As Variant Dim result(0 To 2) As Double result(0) = v1(1) * v2(2) - v1(2) * v2(1) result(1) = v1(2) * v2(0) - v1(0) * v2(2) result(2) = v1(0) * v2(1) - v1(1) * v2(0) CrossProduct = result End Function Function CoordZ(pt1 As Variant, pt2 As Variant, pt3 As Variant, pt As Variant) As Double Dim norm(0 To 2) As double norm = CrossProduct(vect(pt1, pt2), vect(pt1, pt3)) Dim zAxis(0 To 2) As Double zAxis(2) = 1.0 CoordZ = DotProduct(norm, Vector(pt, pt1) / DotProduct(norm, zAxis) End Function
-
Je pense que j'ai (enfin) compris. Il s'agirait de la coordonnée Z de la projection verticale du point P sur le plan. Si c'est bien ça, il te faut calculer le vecteur normal du plan, autrement dit le produit vectoriel (cross product) du vecteur de p1 à p2 et du vecteur de p1 à p3. Ensuite, la division du produit scalaire (dot product) du vecteur normal et du vecteur de p à p1 par le produit scalaire du vecteur normal et du vecteur (0, 0, 1) devrait te renvoyer la coordonnée Z. Pseudo code : normal = CrossProduct(Vector(p1, p2), Vector(p1, p3)) Z = DotProduct(normal, Vector(p, p1)) / DotProduct(normal, (0, 0, 1)) En VB.NET, ça donnerait ça : Dim normal As Vector3d = p1.GetVectorTo(p2).CrossProduct(p1.GetVectorTo(p3)) Dim z As Double = normal.DotProduct(p.GetVectorTo(p1)) / normal.DotProduct(New Vector3d(0.0, 0.0, 1.0)) En VBA, il va falloir créer une classe Vector3d avec les méthodes CrossProduct et DotProduct ou faire des équivalents avec des Variants (three-element array of doubles). C'est en partie pour ça que je n'aime pas le VBA AutoCAD, il ne fournit ni objets de type point et vecteur comme on a en .NET, ni de fonctions de traitement des Variants (three-element array of doubles) utilisés pour les points comme on a des fonctions de traitement des listes en LISP. Ce qui me semble une grosse lacune pour un logiciel de DAO.
-
Désolé, je ne comprends toujours pas. Si on connait les distances de P à chacun de ces points (d1, d2 et d3), il n'y a que deux points P possibles (un de chaque côté du plan défini par 1, 2 et 3) ou un seul si P appartient au plan. Ces points sont les intersections des 3 sphères de centres 1, 2 et 3 et respectivement de rayons d1, d2 et d3. Je ne vois pas ce que les coordonnées X et Y de P ont à voir là dedans ni comment elles peuvent être connues si Z est inconnue. Peut-être que si tu fournissais un petit dessin...
-
Bravo à tous ceux qui avancent des réponses ! Personnellement je n'ai pas compris l’énoncé. Le Z du point P, c'est par rapport au plan défini par les points 1, 2 et 3 (qui appartiennent au plan XY du SCG) ? ou c'est le Z de P dans le SCG les points 1, 2 et 3 étant des points 3D quelconques ? Comment connait-on les coordonnées X et Y de P ?
-
Suppresion du dynamisme d'un block
(gile) a répondu à un(e) sujet de benoitlacroix dans AutoCAD 2020-2024
Salut, (vl-load-com) (or *acad* (setq *acad* (vlax-get-acad-object))) (or *acdoc* (setq *acdoc* (vla-get-ActiveDocument *acad*))) (or *blocks* (setq *blocks* (vla-get-Blocks *acdoc*))) ;; GetItem (gile) ;; Retourne le vla-object de l'item s'il est présent dans la collection (ou nil) ;; ;; Arguments ;; col : la collection (vla-object) ;; name : le nom de l'objet (string) ou son indice (entier) (defun gc:GetItem (col name / obj) (vl-catch-all-apply (function (lambda () (setq obj (vla-Item col name)))) ) obj ) ;; DYN2STAT ;; Converti les blocs dynamiques sélectionnés en blocs statiques (defun c:DYN2STAT (/ s) (if (ssget '((0 . "INSERT"))) (progn (vla-StartUndoMark *acdoc*) (setq s (vla-get-ActiveSelectionSet *acdoc*)) (vl-catch-all-apply (function (lambda (/ i n) (vlax-for b s (if (= (vla-get-IsDynamicBlock b) :vlax-true) (progn (setq i 1) (while (gc:GetItem *blocks* (setq n (strcat (vla-get-EffectiveName b) "_" (itoa i)))) (setq i (1+ i)) ) (Vla-ConvertToStaticBlock b n) ) ) ) ) ) ) (vla-Delete s) (vla-EndUndoMark *acdoc*) ) ) (princ) ) -
Pour ceux que ça intéresse(s'il y en a), le code C#. using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.GraphicsInterface; using Autodesk.AutoCAD.Runtime; using System.Collections.Generic; using System.Linq; using AcAp = Autodesk.AutoCAD.ApplicationServices.Core.Application; [assembly: CommandClass(typeof(Gile.AutoCAD.DynamicGrid.Commands))] namespace Gile.AutoCAD.DynamicGrid { public class Commands { static int nH = 3, nV = 3; [CommandMethod("DYNGRID")] public static void DynamicGrid() { var doc = AcAp.DocumentManager.MdiActiveDocument; var db = doc.Database; var ed = doc.Editor; var pio = new PromptIntegerOptions("\nNombre de lignes horizontales: "); pio.LowerLimit = 2; pio.DefaultValue = nH; pio.UseDefaultValue = true; var pir = ed.GetInteger(pio); if (pir.Status != PromptStatus.OK) return; nH = pir.Value; pio.Message = "\nNombre de lignes verticales: "; pio.DefaultValue = nV; pir = ed.GetInteger(pio); if (pir.Status != PromptStatus.OK) return; nV = pir.Value; var ppo = new PromptPointOptions("\nSpécifiez le premier coin: "); var ppr = ed.GetPoint(ppo); if (ppr.Status != PromptStatus.OK) return; var ucs = ed.CurrentUserCoordinateSystem; var basePt = ppr.Value.TransformBy(ucs); var jig = new GridJig(basePt, ucs, nH, nV); var pr = ed.Drag(jig); if (pr.Status == PromptStatus.OK) { using (var tr = db.TransactionManager.StartTransaction()) { var btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite); foreach (var line in LineSegment.ComputeGrid(basePt, jig.VectorX, jig.VectorY, nH, nV) .Select(l => l.ToLine())) { btr.AppendEntity(line); tr.AddNewlyCreatedDBObject(line, true); } tr.Commit(); } } } struct LineSegment { public Point3d StartPoint { get; } public Point3d EndPoint { get; } public LineSegment(Point3d startPoint, Point3d endPoint) { StartPoint = startPoint; EndPoint = endPoint; } public Line ToLine() => new Line(StartPoint, EndPoint); public static List<LineSegment> ComputeGrid(Point3d pt, Vector3d u, Vector3d v, int nU, int nV) { var lines = new List<LineSegment>(); double d = nU - 1.0; for (int i = 0; i < nU; i++) { var p = pt + v * i / d; lines.Add(new LineSegment(p, p + u)); } d = nV - 1.0; for (int i = 0; i < nV; i++) { var p = pt + u * i / d; lines.Add(new LineSegment(p, p + v)); } return lines; } } class GridJig : DrawJig { Point3d basePt, dragPt; Matrix3d ucs, wcs; int nH, nV; public Vector3d VectorX { get; private set; } public Vector3d VectorY { get; private set; } public GridJig(Point3d basePt, Matrix3d ucs, int nH, int nV) { this.basePt = basePt; this.ucs = ucs; wcs = ucs.Inverse(); this.nH = nH; this.nV = nV; } protected override SamplerStatus Sampler(JigPrompts prompts) { var options = new JigPromptPointOptions("\nSpécifiez le coin opposé: "); options.BasePoint = basePt; options.UseBasePoint = true; options.UserInputControls = UserInputControls.Accept3dCoordinates | UserInputControls.UseBasePointElevation; var result = prompts.AcquirePoint(options); if (result.Value.IsEqualTo(dragPt)) return SamplerStatus.NoChange; dragPt = result.Value; var vector = basePt.GetVectorTo(dragPt).TransformBy(wcs); VectorX = new Vector3d(vector.X, 0.0, 0.0).TransformBy(ucs); VectorY = new Vector3d(0.0, vector.Y, 0.0).TransformBy(ucs); return SamplerStatus.OK; } protected override bool WorldDraw(WorldDraw draw) { var geo = draw.Geometry; foreach (var line in LineSegment.ComputeGrid(basePt, VectorX, VectorY, nH, nV)) { geo.WorldLine(line.StartPoint, line.EndPoint); } return true; } } } }
- 9 réponses
-
- bloc dynamique
- grille
-
(et 1 en plus)
Étiqueté avec :
-
Salut, Il me semble avoir déjà fait quelque chose en LISP, mais le refaire avec .NET m'a amusé. Télécharger DynamicGrid.zip Débloquer l'archive Extraire et lancer DynamicGrid_setup.msi Lancer la commande DYNGRID dans AutoCAD. Un screencast.
- 9 réponses
-
- bloc dynamique
- grille
-
(et 1 en plus)
Étiqueté avec :
-
Pour essayer de comprendre, tu simplifies le problème avec deux jeux de sélection seulement contenant chacun une seule entité et tu entres les expressions LISP une par une en ligne de commande en contrôlant le résultat à chaque expression. En règle générale, on essaye toujours de décomposer un problème en plusieurs problèmes plus simple pour les tester séparément.
-
Salut, C:\Program Files\Autodesk\AutoCAD 20XX\Support\fr-fr\acad20XXdoc.lsp
-
Salut, Les commandes ne fonctionnent pas toujours de la même façon quand elle sont appelées depuis LISP. Par exemple la commande JOINDRE (_JOIN) appelée depuis un LISP n'accepte pas un jeu de sélection. Dans ton cas la commande PEDIT devrait faire l'affaire. Quand on appelle cette commande depuis LISP il faut faire attention à la valeur de la variable système PEDITACCEPT. Avec les fonction ai_sysvar et vl-catch-all-apply on est certain que les variables système reprendront leur valeur initiale même en cas d'erreur. (defun c:blocs_to_joindre (/ s i e) (ai_sysvar '(("cmdecho" . 0) ("peditaccept" . 1))) (vl-catch-all-apply '(lambda () (and (setq s (ssget '((0 . "INSERT")))) (setq i -1 ) (while (setq e (ssname s (setq i (1+ i)))) (command-s "_.explode" e "") (setq ss (ssget "P")) (command-s "_.pedit" "_multiple" ss "" "_join" "" "") ) ) ) ) (ai_sysvar nil) (princ) )
-
Petit problème de lecture et de tri...
(gile) a répondu à un(e) sujet de DenisHen dans Débuter en LISP
Et quand je lis par ailleurs que tu veux te mettre au .NET, je suis absolument convaincu qu'il s'agit d'une fuite en avant qui va immanquablement te mener à l'échec. Il est plus "complexe" de comprendre commet insérer un bloc avec attributs en .NET que de comprendre l'utilisation des dictionnaires en LISP ou VBA (je parle bien de comprendre et pas de copier/coller des extraits de code, ce qui, en .NET mène directement à la catastrophe). Si j'ai un conseil à te donner, c'est de continuer à apprendre à programmer AutoCAD avec des langages de très haut niveau avec un IDE intégré à AutoCAD pour pouvoir tester plus facilement ton code (c'est comme ça qu'on apprend) et de ne te poser la question d'aborder un environnement de programmation plus puissant mais beaucoup plus complexe que quand tu auras le sentiment d'avoir épuiser les possibilités du LISP et du VBA. -
Essaye comme ça : (defun c:test (/ putBack) (defun putBack (layer / s) (if (setq s (ssget "_X" (list (cons 8 layer)))) (command-s "_.draworder" s "" "_back") ) ) (foreach l '("*(Hach)" "*(Trame)" "*(Image)") (putBack l)) (princ) )
-
Je ne vois pas ce qui ne fonctionne pas chez toi. J'ai fait quelques tests et ça marche chez moi. Encore une fois, teste dans un dessin significatif avec d'abord une seule expression (command-s "_draworder" ...) pour voir le résultat. Le principal avantage d'AutoLISP est cette possibilité de pouvoir tester aussi facilement n'importe quelle expression LISP. command-s est une variation de command qui s'exécute théoriquement deux fois plus vite. Seule restriction avec command-s : on ne peut pas utilise de pause ou autre expression (get* ...) dans ses arguments (voir l'aide). Dans ton cas, on peut utiliser indifféremment l'un ou l'autre.
-
Salut, Première question : est-ce que les sélections fonctionnent ? Dans un dessin test significatif (avec des entités sur les différents calques superposées dans le mauvais ordre), tu exécutes l'expression (depuis la ligne de commande ou l'éditeur VisualLISP) : (setq Select (ssget "_A" '((8 . "*(Hach)")))) Est-ce que ça renvoie nil ou pas ? Si c'est nil, c'est que ton filtre n'est pas bon. Si tu as bien un jeu de sélection, tu testes l'expression suivante : (command-s "ordretrace" Select "" "AR") Et tu regardes si ça a eu un effet dans AutoCAD, etc...
-
Salut, La variable système LISPSYS à 0 permet de définir le VLIDE comme éditeur par défaut (redémarrage d'AutoCAD nécessaire). Voir ce sujet. Pour l'indentation dans le VLIDE, tu peux la paramétrer depuis le menu Outils > Options d'environnement > Options de formatage VisualLISP...
-
Petit problème de lecture et de tri...
(gile) a répondu à un(e) sujet de DenisHen dans Débuter en LISP
OK, je comprends mieux. En fait tu ne communiques pas entre LISP et VBA via les ldata, mais plutôt via SendCommand pour entrer des expressions LISP. Cette méthode a un inconvénient majeur : on ne peut utiliser que des chaînes de caractères avec SendCommand. Il serait plus simple d'utiliser directement les variables système USERS1-5, USERI1-5 et USERR1-5 qui sont accessibles directement en lecture et écriture par les deux environnements et qui permettent de passer aussi des données de type nombre entier ou réel. Sinon, pour des données conservées dans le dessin entre deux sessions, plutôt que d'utiliser les ldata, préférer des dictionnaires et xrecords standards qui sont directement accessibles en lecture et écriture depuis LISP comme depuis VBA et peuvent contenir tout type de donnée AutoCAD (chaînes, nombres, entités, etc.). -
Petit problème de lecture et de tri...
(gile) a répondu à un(e) sujet de DenisHen dans Débuter en LISP
Tu arrives à accéder aux ldata depuis VBA ?! Ça m'intéresse, j'étais persuadé que les ldata (LISP data) n'étaient accessibles qu'en LISP. -
Salut @didier Les vidéos passent bien chez moi avec Firefox en ADSL (la fibre a du mal à arriver dans certains quartiers de Marseille). Par contre, je trouve que la circulation entre le pages n'est pas très ergonomique. On aurait aimé, à la fin d'une page, un lien vers la page suivante en plus de "Retour au menu VBA" (les pages Variable 1, Variable 2 et Dessiner n'ont même pas ce lien, et celui de UserForm renvoie au début de la page, pas au menu).
-
@Curlygoth ton message ci-dessus est absolument mystérieux, si ce n'est incompréhensible (en tout cas pour moi). De quoi parles-tu, qu'est-ce qui ne compte pas ? À ma connaissance les UserForms VBA s'affichent par défaut en modal. en tout cas, dans la vidéo, @didier ne change pas la propriété ShowModal qui est à True. De manière générale, s'il te plait, essaye de penser que tu t'adresses à des personnes qui ne savent pas ce que tu as en tête quand tu postes un message. Alors si tu veux être compris, tache d'être clair dans tes réponses.
-
; erreur: no function definition: EDIT_COMMAND
(gile) a répondu à un(e) sujet de Ernest dans Débuter en LISP
Salut, Un fichier dwg ne peut pas contenir un LISP. La seule possibilité avec le LISP c'est qu'il y ait un réacteur persistant défini avec une fonction callback nommée edit_command. Dans ce cas,tu peux essayer d'entrer l'expression LISP : (vlr-remove-all) en ligne de commande, ça devrait supprimer tous les réacteurs. -
Une idée farfelue...
(gile) a répondu à un(e) sujet de Olivier Eckmann dans ObjectARX/DBX, C++, .NET, RealDWG
Tu es tout seul dans le bureau ? 😉 -
Pas un LISP, une commande native EXTRACTDONNEES (_DATAEXTRACTION). Le tableau n'est pas dynamique, mais il suffit de le sélectionner > clic droit > Mettre à jour les liaisons de données de la table
