ObjectARX/DBX, C++, .NET, RealDWG derniers sujetshttps://cadxp.com/forum/32-objectarxdbx-c-net-realdwg/ObjectARX/DBX, C++, .NET, RealDWG derniers sujetsfrQR Codehttps://cadxp.com/topic/62228-qr-code/ Ce n'est pas le premier plug-in pour créer des QR Code dans AutoCAD, mais celui-ci permet d'insérer un bloc (éventuellement anonyme, donc non modifiable via l'éditeur de blocs). Le bloc contient juste une hachure qui représente le QR Code sur fond blanc et, optionnellement un attribut constant avec le texte d'origine.

La commande QRCODEINSERT affiche une boite de dialogue pour définir les paramètres d'encodage et les propriétés du bloc inséré.

QR_Code_Block_DialogBox.png

Le code source, qui utilise la bibliothèque QRCoder, est disponible sur GitHub.

Télécharger InsertQRCodeBlockSetup.msi pour installer le plug-in (compatible avec toutes les version pleines ou verticales d'AutoCAD depuis 2013).

]]>
62228Tue, 15 Apr 2025 16:59:24 +0000
<![CDATA[Autocad <-> Python <-> L' infini et au-delà]]>https://cadxp.com/topic/61149-autocad-python-l-infini-et-au-del%C3%A0/ Bonjour,

Il est impossible d'être exhaustif au sujet des interactions Autocad/Python.

Des possibilités infini dans Autocad un peu comme VBA.

Au-delà d'Autocad, comme tout les langages de programmations avancés.

Si Python est devenu le langage le plus utilisé, ce n'est pas le cas pour les "Autocadiens".

Pourquoi ?

A vous de me répondre.

En attendant voici comment en profiter.

Prérequis

- Etre administrateur de son poste ou si vous pouvez prendre un ticket au près de votre service informatique qui vous configure votre poste.

- Windows 10 ou 11

- Un Autocad d'installé. (full 64 bit qu'importe la version, testé sur 2015 à 2024, non testé avec LT, CIVIL ou MAP à explorer)

- Un EDI comme Visual Studio Code

- Avoir des notions de base de Python. C'est peut être le langage le plus facile à apprendre. Je parle bien de la base, car c'est un langage modulaire et que l'utilisation de certain modules n'est pas si simple. Il y a des cours gratuit sur le net, il suffit de demander à votre moteur de recherche préféré. Si vous connaissez déjà un autre langage, l'apprentissage va très vite.

- Si vous connaissez l'Autolisp c'est le top, il communique très bien avec Python. De plus, comme Python est présenté comme multi- paradigme, vous pouvez coder en fonctionnel. Je dit bien présenté, car en fait, il est purement orienté objet. Si dans Autolisp tout est liste, tout est objet dans python, même une fonction ou une variable. 

 

Installation

- Télécharger la dernière version stable de Python 

- Installer Python. Normalement il n'y a rien à changer dans les options d'installation, mais vérifier quand même que Modifier PATH soit coché et que PIP (utilitaire de téléchargement des Modules) soit installé avec.

- Selon l'utilisation il y auras des modules à installer. Cela se fait en ligne de commande Windows avec l'utilitaire PIP.

   Pour le Module Pyautocad  qui permet d'agir dans le Domaine d'Autocad on tape ceci dans l'invite de commande Windows: pip install pyautocad

- Et c'est tout, rien à faire dans Autocad, il s'en fout totalement et l'ignore.

 

Voila, je reviendrais avec des exemples.

 

 

]]>
61149Wed, 14 Feb 2024 12:42:08 +0000
Désactiver les accrochages 2 (le retour)https://cadxp.com/topic/38718-d%C3%A9sactiver-les-accrochages-2-le-retour/ Salut,

 

Le dernier sujet sur le blog de Kean Walmsley m'a fait repenser à un vieux sujet.

Il s'avère que c'était mon cadeau de fin d'année il y deux ans.

 

Donc cette année le traditionnel cadeau sera le même qu'alors mais en mieux abouti.

 

Toujours deux commandes bascule pour activer/désactiver les accrochages aux objets sur les calques verrouillés (LOKO) ou les références externes (XROS).

Ces commandes peuvent être appelées de manière transparente ('LOKO ou 'XROS).

Les problèmes avec l'accrochage 'Intersection' sont résolus (merci Kean) mais je n'ai pas encore trouvé pour les composants des cotes sur un calque verrouillé.

Attention, la désactivation des accrochages sur de gros fichiers peut provoquer un ralentissement.

Cette nouvelle mouture semble stable sur AutoCAD 2012, 2013 et 2014, mais comme j'ai eu des plantages sévères avec AutoCAD 2011, elle sera réservé à ces versions

Ceci permet d'utiliser la technique Autoloader pour faciliter l'installation.

 

Mise à jour : support d'AutoCAD 2025 (et plus).

Installation :

  • Télecharger LockOsnap.zip.
  • Débloquer le zip (clic droit -> Propriétés -> onglet Général -> Débloquer
  • Lancer l'installeur LockOsnapSetup.msi (Un dossier LockOsnap.bundle est créé dans : %appdata%\Autodesk\ApplicationPlugins

 

Désinstallation :

Désinstaller via le Panneau de configuration.

 

Le code:

// (C) Copyright 2012 by Gilles Chanteau 
//
using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;

[assembly: CommandClass(typeof(Gile.LockOsnap.CommandMethods))]

namespace Gile.LockOsnap
{
   public class CommandMethods
   {
       private OSOverrule lokoOSOverrule, xrosOSOverrule;
       private IntOverrule lokoIntOverrule, xrosIntOverrule;

       [CommandMethod("LOKO", CommandFlags.Modal | CommandFlags.Transparent)]
       public void LockOsnapCmd()
       {
           ToggleOsnaps(ref lokoOSOverrule, ref lokoIntOverrule, lokoPromptingForPoint, LockedUpdate, "calques verrouillés");
       }

       [CommandMethod("XROS", CommandFlags.Modal | CommandFlags.Transparent)]
       public void XrefOsnapCmd()
       {
           ToggleOsnaps(ref xrosOSOverrule, ref xrosIntOverrule, xrosPromptingForPoint, XrefUpdate, "références externes");
       }

       void lokoPromptingForPoint(object sender, PromptPointOptionsEventArgs e)
       {
           LockedUpdate();
       }

       void xrosPromptingForPoint(object sender, PromptPointOptionsEventArgs e)
       {
           XrefUpdate();
       }

       private void ToggleOsnaps(
           ref OSOverrule osOverrule,
           ref IntOverrule intOverrule,
           PromptPointOptionsEventHandler handler, 
           Action update, 
           string msg)
       {
           Editor ed = AcAp.DocumentManager.MdiActiveDocument.Editor;
           RXClass entityClass = RXClass.GetClass(typeof(Entity));
           if (osOverrule == null)
           {
               ed.PromptingForPoint += handler;
               osOverrule = new OSOverrule();
               Overrule.AddOverrule(entityClass, osOverrule, false);
               intOverrule = new IntOverrule();
               Overrule.AddOverrule(entityClass, intOverrule, false);
               ed.WriteMessage(string.Format("\nAccrochages sur les {0} désactivés.", msg));
               update();
               Overrule.Overruling = true;
           }
           else
           {
               ed.PromptingForPoint -= xrosPromptingForPoint;
               Overrule.RemoveOverrule(entityClass, osOverrule);
               osOverrule = null;
               Overrule.RemoveOverrule(entityClass, intOverrule);
               intOverrule = null;
               ed.WriteMessage(string.Format("\nAccrochages sur les {0} activés.", msg));
           }
       }

       private void LockedUpdate()
       {
           if (lokoOSOverrule != null)
           {
               Database db = HostApplicationServices.WorkingDatabase;
               using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
               {
                   HashSet<string> layers = new HashSet<string>(
                       ((LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead))
                       .Cast<ObjectId>()
                       .Select(id => (LayerTableRecord)tr.GetObject(id, OpenMode.ForRead))
                       .Where(ltr => ltr.IsLocked)
                       .Select(ltr => ltr.Name));
                   ObjectId[] onLocked = ((BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForRead))
                       .Cast<ObjectId>()
                       .Where(id => layers.Contains(((Entity)tr.GetObject(id, OpenMode.ForRead)).Layer))
                       .ToArray();
                   lokoOSOverrule.SetIdFilter(onLocked);
                   lokoIntOverrule.SetIdFilter(onLocked);
                   tr.Commit();
               }
           }
       }

       private void XrefUpdate()
       {
           if (xrosOSOverrule != null)
           {
               Database db = HostApplicationServices.WorkingDatabase;
               using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
               {
                   ObjectId[] xrIds = ((BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead))
                       .Cast<ObjectId>()
                       .Select(id => (BlockTableRecord)tr.GetObject(id, OpenMode.ForRead))
                       .Where(btr => btr.IsFromExternalReference)
                       .SelectMany(btr => btr.GetBlockReferenceIds(true, false).Cast<ObjectId>())
                       .ToArray();
                   xrosOSOverrule.SetIdFilter(xrIds);
                   xrosIntOverrule.SetIdFilter(xrIds);
                   tr.Commit();
               }
           }
       }

       class OSOverrule : OsnapOverrule
       {
           public override void GetObjectSnapPoints(
             Entity ent,
             ObjectSnapModes mode,
             IntPtr gsm,
             Point3d pick,
             Point3d last,
             Matrix3d view,
             Point3dCollection snap,
             IntegerCollection geomIds) { }

           public override void GetObjectSnapPoints(
             Entity ent,
             ObjectSnapModes mode,
             IntPtr gsm,
             Point3d pick,
             Point3d last,
             Matrix3d view,
             Point3dCollection snaps,
             IntegerCollection geomIds,
             Matrix3d insertion) { }

           public override bool IsContentSnappable(Entity entity)
           {
               return false;
           }
       }

       class IntOverrule : GeometryOverrule
       {
           public override void IntersectWith(
             Entity ent1,
             Entity ent2,
             Intersect intType,
             Plane proj,
             Point3dCollection points,
             IntPtr thisGsm,
             IntPtr otherGsm) { }

           public override void IntersectWith(
             Entity ent1,
             Entity ent2,
             Intersect intType,
             Point3dCollection points,
             IntPtr thisGsm,
             IntPtr otherGsm) { }
       }
   }
}
 
]]>
38718Wed, 18 Dec 2013 13:52:41 +0000
Import/Export d\'attributs avec Excelhttps://cadxp.com/topic/32142-importexport-dattributs-avec-excel/ Salut,

Un petit programme qui permet d'extraire des attributs et de ré-importer les valeurs modifiées un peu comme les commandes ATTIN et ATTOUT des Express Tools à ceci près qu'il utilise directement Excel plutôt qu'un fichier .txt et que les attributs des blocs dynamiques apparaissent sous le nom du bloc d'origine.

La classe Commands définit les commandes : EATT pour l'extraction et IATT pour l'importation. D'après mes tests elles fonctionnent sans encombres avec Excel 2003 et 2010.

Ces commandes utilisent trois classes qui peuvent être utilisées par ailleurs. ExcelReader et ExcelWriter définissent des méthodes pour lire et écrire dans une feuille Excel un peu à la manière des StreamReader et StreamWriter avec les fichiers texte. Par ailleurs des propriétés sont aussi définies dans ces classes pour accéder au fichier.

Pour assurer une compatibilité avec toutes les versions d'Excel, ces classes utilisent la "liaison tardive" (late binding).

Une autre classe : LateBindings définit des méthodes pour rendre la syntaxe des expressions de liaison tardive plus concises et explicites.

Les codes source.

Nouvelle version 2010-2012 ExcelAttribute.zip

Version 2013-? ExcelAttribute_19.zip

Extraire les deux DLLs correspondant à la version d'AutoCAD ciblée dans le même répertoire.

Charger dans AutoCAD avec NETLOAD ExcelAttribute.dll ou ExcelAttribute_19.dll suivant la version d'autoCAD (ExcelLateBinding.dll ou ExcelDynamic.dll sont des DLLs de ressources).

Nouvelle version : on peut désormais télécharger ExcelAttributeSetup.exe, pour installer ExcelAttribute sur toute version d'AutoCAD depuis 2013 (il faut probablement Débloquer le fichier téléchargé).

]]>
32142Wed, 01 Jun 2011 16:08:59 +0000
Question de couleurshttps://cadxp.com/topic/36499-question-de-couleurs/bonjour à tous

Comment remplir un combobox en utilisant la panoplie de couleurs

d'AutoCAD afin de pouvoir modifier facilement la couleur d'un texte (par exemple).

En VB net bien sûr.

Merci d'avance

Phil

]]>
36499Wed, 07 Nov 2012 07:45:18 +0000
AutoCAD 2025 et .NET Core 8https://cadxp.com/topic/61281-autocad-2025-et-net-core-8/ AutoCAD 2025 supporte .NET Core 8.0 en place de .NET Framework.

Il s'agit d'une rupture de compatibilité pour les développements .NET qui doivent être mis à jour pour fonctionner avec AutoCAD 2025 (et versions ultérieures).

J'ai d'ores et déjà migré les applications sur Autodesk App Store et les dépôts sur GitHub:

Merci de me signaler si je dois le faire pour d'autres programmes .NET publiés sur CADxp.

Je peux aussi essayer de faire un petit tuto sur la migration de projets existants si besoin.

]]>
61281Wed, 27 Mar 2024 07:09:21 +0000
Chargement automatique des DLLs .NEThttps://cadxp.com/topic/38595-chargement-automatique-des-dlls-net/Salut,

 

Je vais essayer de faire ici la synthèse de ce que j'ai pu dire ici ou là pour automatiser le chargement des DLLs .NET pour AutoCAD.

 

 

Préambule

 

Dans tous les cas (excepté l'utilisation de la technique AutoLoader), si la DLL n'est pas placée dans un répertoire des chemins de support il est nécessaire de spécifier le chemin complet.

Dans les exemples suivants, on considèrera que le fichier : "SuperApplication.DLL" est dans un répertoire des chemins de support.

 

Pour AutoCAD 2014 (et plus probablement), il faut aussi ajouter le chemin du répertoire dans les Emplacements approuvés (commande Options... > Fichiers ou variable TRUSTEDPATHS). Si le chemin du dossier se termine par "\...", tous ses sous-dossiers sont également approuvé. Le dossier d'installation AutoCAD et les dossiers de plug-ins (voir Autoloader plus bas), ainsi que tous leurs sous-dossiers, sont toujours implicitement approuvés.

 

Les applications .NET n'ont pas besoin d'être chargées pour chaque document (comme les applications AutoLISP).

 

 

Utilisation du fichier "acad.lsp"

 

Un fichier nommé "acad.lsp" (à créer s'il n'existe pas) placé dans les chemins de support est automatiquement chargé et exécuté au démarrage d'AutoCAD.

Il suffit donc d'ajouter à ce fichier une expression LISP qui charge la DLL avec la commande NETLOAD :

 

(command "netload" "SuperApplication.dll")

 

 

Utilisation de la base de registre

 

Il est possible d'automatiser le chargement d'une DLL .NET en créant quelques clés dans la base de registre.

Cette méthode permet une exécution plus rapide et plus silencieuse du chargement et aussi de pouvoir ne charger l'application qu'au premier appel d'une commande qui y est définie (un peu comme la fonction LISP autoload).

Dans les deux cas, si les clés sont créées dans HKEY_CURRENT_USER le chargement ne se fera que pour l'utilisateur, si elles sont créées dans HKEY_LOCAL_MACHINE (droit d'administrateur requis) le chargement se fera pour tous les utilisateurs.

 

Pour charger l'application systématiquement au démarrage.

  • Créer une clé dans : "HKEY_CURRENT_USER\Software\Autodesk\AutoCAD\\\Applications" avec le nom de l'application (SuperApplication, par exemple).
  • Ajouter 4 valeurs das cette clé :
    • DESCRIPTION (valeur chaîne) : une description de l'application
    • LOADCTRLS (valeur DWORD) : 2 dans ce cas
    • LOADER (valeur chaîne) : le nom du fichier (éventuellement le chemin complet)
    • MANAGED (valeur DWORD) : toujours 1 pour les applications .NET

NetAutoLoad_1.png

 

On peut utiliser la routine LISP suivante pour créer la clé dans HKEY_CURRENT_USER

;;; NetStartupAutoLoad
;;; Inscrit une application .NET dans la base de registre pour
;;; un chargement automatique au démarrage
;;;
;;; Arguments
;;; key       : la clé de l'application (string)
;;; descr     : une description (string)
;;; filename  : le chemin complet de la dll ou le nom du fichier avec l'extension .dll
;;;             si le fichier est dans un chemin de recherche (string)

(defun NetStartupAutoLoad (key descr filename / fullpath)
 (vl-load-com)
 (if (setq fullpath (findfile filename))
   (mapcar
     '(lambda (k v)
        (vl-registry-write
          (strcat "HKEY_CURRENT_USER\\"
                  (vlax-product-key)
                  "\\Applications\\"
                  key
          )
          k
          v
        )
      )
     '("DESCRIPTION" "LOADCTRLS" "LOADER" "MANAGED")
     (list descr 2 fullpath 1)
   )
   (princ (strcat "\nLe fichier \"" filename "\"  est introuvable"))
 )
)

Exemple :

(NetStartupAutoLoad "SuperApplication"
                   "Fait plein de supers trucs dans AutoCAD"
                   "SuperApplication.dll"
)

 

 

Utilisation du mécanisme Autoloader

 

Depuis AutoCAD 2012, il est possible d'utiliser une nouvelle technique de chargement automatique des applications .NET (mais aussi LISP ou ObjectARX). Cette technique facilite grandement le déploiement d'applications elle est recommandée par Autodesk qui l'utilise pour les applications d'Exchange Apps Store.

 

La variable système APPAUTOLOAD gère la manière dont les plug-ins sont chargés. Elle doit avoir le code binaire 2 actif pour que les plug-ins soient chargés au démarrage (défaut 14 = 8 + 4 +2).

 

Il s'agit d'un dossier avec l'extension : .bundle qui doit être placé dans un des répertoires suivant (les chemins sont spécifié avec les variables d'environnement Windows, il suffit de les copier dans la barre d'adresse de l'explorer quel que soit l'OS -XP, 7 ou 8-).

Pour désinstaller l'application, il suffit de supprimer le dossier.bundle.

 


  • Pour l'utilisateur courant :
    • %appdata%\Autodesk\ApplicationPlugins\

    [*]Pour tous les utilisateurs :

    • %allusersprofile%\Autodesk\ApplicationPlugins\
    • %programdata%\Autodesk\ApplicationPlugins\ (Windows 7 ou 8)
    • %programfiles%\Autodesk\ApplicationPlugins\

Le dossier .bundle doit contenir un fichier PackageContents.xml et tous les fichiers nécessaires à l'application (ceux-ci peuvent être répartis dans différents sous-dossiers).

Le fichier PackageContents.xml est un fichier XML qui désigne les différents composants de l'application et décrit comment l'application est chargée.

Ce fichier doit contenir les nœuds suivants :

  • ApplicationPackage
    • CompanyDetails (facultatif)
    • Components
      • RuntimeRequirements
      • ComponentEntry (un noeud par composant)

 

Exemple pour un dossier .bundle de base :

Le dossier SuperApplication.bundle contient

  • le fichier PackageContents.xml
  • le sous-dossier Contents qui contient le fichier SuperApplication.dll
  • le sous-dossier Help qui contient un fichier d'aide SuperApplicationHelp.html

 

Le fichier PackageContents.xml

- dans le nœud ApplicationPackage, l'attribut ProductCode doit être un GUID unique (il y a un générateur de GUID dans les outils de Visual Studio et de nombreux autres sur le net)

- dans le nœud RuntimeRequirement, l'attribut SupportPath permet d'ajouter le dossier .\Help\ aux chemins de recherche.

<?xml version="1.0" encoding="utf-8" ?>
<ApplicationPackage
   SchemaVersion="1.0"
   AppVersion="1.0"
   Author="SuperMan"
   ProductCode="{Ajouter un GUID unique ici}"
   Name="Super Application"
>
 <CompanyDetails
   Name="SuperMan, Inc."
 />
 <Components>
   <RuntimeRequirements SupportPath="./Help"/>
   <ComponentEntry
     AppName="SuperApplication"
     ModuleName="./Contents/SuperApplication.dll"
   />
 </Components>
</ApplicationPackage>

 

Pour plus de renseignements sur le mécanisme Autoloader, voir l'aide :

A2012 : Guide de personnalisation > Introduction aux interfaces de programmation > Installer et désinstaller des applications plug-in

A2013/2014 (et tant qu'on ne retrouvera pas de table des matières dans l'aide...) Rechercher : ApplicationPlugins

]]>
38595Fri, 22 Nov 2013 14:25:35 +0000
Process.Start .Net Corehttps://cadxp.com/topic/61626-processstart-net-core/ Bonjour,

 

Juste une petite info pour un problème que j'ai rencontré en portant un de mes plug-in sous 2025 et .Net Core 8

Pour ouvrir un fichier PDF par ex, j'utilisais ce code

      string sFileName = @"C:\TEST.pdf";
      Process.Start(sFileName);

qui fonctionnait très bien en .Net Framework mais qui ne fonctionne plus en .Net Core avec un message d'erreur indiquant un exécutable non compatible avec l'OS.

La raison est un changement de la valeur par défaut de la propriété UseShellExecute du processus qui est définie à true en .Net Framework et à false en .Net Core, comme indiqué dans la doc 

Cette propriété indique au système s'il faut ouvrir le fichier transmis avec l'application associée, ou bien le considérer comme un exécutable. Il faut donc initialiser cette valeur à true pour 2025, puisque fonctionnant le .Net Core. Le code pourrait devenir

      string sFileName = @"C:\test.pdf";
      ProcessStartInfo psi = new ProcessStartInfo(sFileName);
      psi.UseShellExecute = true;
      Process.Start(psi);

ou bien 

      string sFileName = @"C:\TEST.pdf";
      using (Process proc = new Process())
      {
        proc.StartInfo.FileName = sFileName;
        proc.StartInfo.UseShellExecute = true;
        proc.Start();
      }

Ce n'était pas très compliqué à trouver la solution, mais ça pourra éventuellement servir à quelqu'un qui rencontrerait le problème.

 

Olivier Eckmann

]]>
61626Mon, 19 Aug 2024 12:11:52 +0000
<![CDATA[[<= 2013] Rendre les calques verrouillés non sélectionnables (3, le retour)]]>https://cadxp.com/topic/41941--/Salut,

 

Suite à ce sujet (et aux précedentes réponses) et à certain problèmes d'installation, j'ai fait une mise à jour pour utiliser le mécanisme de chargement automatique (Autoloader/bundle)

 

Cette version est compatible avec AutoCAD (et verticaux) à partir de 2013.

 

LAYLOCKSEL est une véritable variable système (stockée par utilisateur dans la base de registre) qui permet de rendre les objets sur les calques verrouillés non sélectionnables.

Valeurs :

- 0 (Inactif) : les objets sur les calques verrouillés sont sélectionnables (défaut).

- 1 (Actif) : les objets sur les calques verrouillés ne sont pas sélectionnables.

La variable est accessible et modifiable en entrant son nom en ligne de commande ou en LISP avec les fonctions getvar et setvar.

 

Installation :

- télécharger et lancer LayLockSelSetup.msi

 

Désinstallation :

- relancer LayLockSelSetup.msi ou désinstaller LayerLockSelection via le panneau de configuration.

]]>
41941Sun, 25 Oct 2015 11:11:21 +0000
.NET (C#) équivalents des commandes Lisp UCS / DVIEW / PLANhttps://cadxp.com/topic/61249-net-c-%C3%A9quivalents-des-commandes-lisp-ucs-dview-plan/ Bonjour, 

Novice en developpement C# pour AutoCad, j'essaie porter des scripts en Lisp en C#. Je suis confronté à la transcription de certaines commandes (ne trouvant pas les classes ou les objets pour le faire ). 

Par exemple des commandes Lisp ci-dessous

  • (command "_UCS" "_WORLD")
  • (command "_UCS" "_3P" point1 point2 "")
  • (command "_PLAN" "")
  • (command "_UCS" "_R" nomscu)
  • (command "_UCS" "_X" -100.00)
  • (command "_DVIEW" "" "_PO" pt-target pt-camera "_CL" "_B" (* -1 section_half_depth) "_CL" "_F" section_half_depth "")
     

Merci d'avance de votre aide.

 

]]>
61249Sun, 17 Mar 2024 17:08:45 +0000
[PYTHON] Conversion .las en .dwghttps://cadxp.com/topic/60331-python-conversion-las-en-dwg/ Bonjour,

Cela fait déjà quelques années que les Lidar nous livrent leurs nuages.

Nous ne sommes pas tous équipés pour recevoir ce type de données en entrée.

Surtout en logiciels, si on ne dispose que d'AutoCAD on ne peut pas faire grand chose avec.

Heureusement, il existe CloudCompare, qui reste l'une des meilleurs solutions actuelles.

Mais un part un, et en dxf qu'il faut convertir en dwg.

Et mettre un coup de Flatten si on veut de la 2D (pas trouvé comment faire dans CloudCompare).

Au bout 50 las, je ne vous raconte pas l'état de la RAM.

L'écriture d'un script est devenu une urgence. (30km de las ...)

Python, avec ses modules pyautocad et laspy, permet d'en réaliser.

J'espère qu'en partageant mon expérience, je puisse donner envie de programmer en Python dans Autocad, car je me sens très seul dans ce domaine.

J'ai dépose mon code sur Github.

traceAreaLas

qui trace l'emprise des .las sélectionnés dans un dwg. (plan de repérage)

tracePtLas

tracePtLas2D et tracePtLas3D, qui récupère les points dans un dwg.

Par contre je n'ai pas pu tester les .exe sur un autre poste.

Un testeur serait le bienvenu.

Merci

 

]]>
60331Tue, 28 Feb 2023 16:00:36 +0000
IDEE DE DEVELOPPEMENThttps://cadxp.com/topic/60979-idee-de-developpement/ Bonjour

je m'avance peut etre mais quand on fait une fenêtre dans une présentation , la régénération de celle ci prend en compte toutes les entités de l'espace objet dont les couches ne sont pas gelées.

donc si on zoom dans la fenêtre sur 500 entités par exemple, et que l'on régénère, autocad va redessiner les 100 000 entités que l'on ne voit pas en fait dans cette fenêtre.

et ca peut prendre du temps

surtout quand on a plusieurs fenêtres par présentations.

une idée qui me vient pour accélérer AUTOCAD.

 

pourrait on associer a une fenêtre de l'espace papier, une polyligne dans l'espace objet qui pourrait etre un peu plus grande ( on défini le décalage par rapport a la fenêtre ).

et que quand on régénère  la fenêtre, de ne s'occuper que des entités qui traverse cette polyligne.

ca permettrait de régénérer que ce qui en vaux la peine, et d'aller plus vite.

 

c'est possible ou c'est une idée saugrenue ?

 

Phil

 

]]>
60979Mon, 11 Dec 2023 17:51:40 +0000
Epaisseur Polyligne 3Dhttps://cadxp.com/topic/60774-epaisseur-polyligne-3d/ Bonjour, je cherche un moyen de créer une polyligne 3d avec plusieurs segments tout en imposant une épaisseur et une couleur. (en c# bien sur).

Merci d'avance.

Phil.

]]>
60774Wed, 04 Oct 2023 09:16:25 +0000
Affichage asynchrone de graphisme dans un dialogue non modalhttps://cadxp.com/topic/60444-affichage-asynchrone-de-graphisme-dans-un-dialogue-non-modal/ Bonjour,

 

Pour situer le contexte, j'essaie d'afficher une coupe de nuage de point dans un dialogue non modal pendant un Jig. 

Je n'utilise pas le RCP car l'affichage en mode Filaire (non 2D) est pénalisant et je n'ai pas toutes les options souhaitées.

J'ai redéveloppé une structure en mémoire pour charger mes points et je souhaite afficher dans une picturebox (Graphics.FillRectangle et Graphics.DrawLine) les points de ma coupe, pendant que je suis dans un Jig qui dessine une polyligne. Comme le temps de calcul (et surtout de dessin) des points/pixel est long (1s environ pour calculer et afficher 20 000 pts-pixel), ce n'est pas réaliste de faire la mise à jour en temps réel suivant le déplacement de mon curseur, sinon j'aurais un déplacement hyper saccadé.

Je voulais savoir s'il était possible de désynchroniser le dessin dans ma picturebox. C'est à dire que je bouge mon curseur et ça commence à dessiner, mais si je bouge à nouveau, ça efface et ça recommence à dessiner la nouvelle coupe sans bloquer.

L'idée c'est d'avoir un dessin en continu qui s'arrête et reprend dès que je bouge et qui finit de se dessiner si je ne bouge plus.

Un peu comme ces logiciels  qui chargent et affichent les données au fur et à mesure, mais sans bloquer le déplacement (ou le pan, ou l'orbite)

 

Merci d'avance pour les éventuelles pistes.

 

Olivier

]]>
60444Fri, 21 Apr 2023 09:00:22 +0000
Création d'une DLL en Visual Studio 2022.https://cadxp.com/topic/60179-cr%C3%A9ation-dune-dll-en-visual-studio-2022/ Bonjour à la communauté. Comment vas-tu ?
Dans ma nouvelle entreprise, on m'a demandé de faire différentes macros pour AutoCAD (compatibles avec 2011 ou 2012 jusqu'à 2023 voir plus) et d'adapter quelques-unes existantes (les miennes comme les siennes).
Elle voudrait être "propriétaire" de ses codes. J'en ai donc adapté un en VBA (car il y a beaucoup de fenêtres) avec mot de passe. Mais on m'a démontré qu'en moins d'une minute, ce code était accessible à tous (le mot de passe a résisté quelques secondes). Ce que ma direction souhaite éviter.
Je ne suis pas capable de tout faire en Lisp pour les compiler en VLX.

En discutant avec mes nouveaux collègues, il s'avère que seule une DLL remplirait "le contrat" (sauf si vous avez d'autres solutions). Elle seront chargées automatiquement dans AutoCAD avec un NETLOAD.

J'avais pensé qu'en faisant du Lisp (pour le code) qui appèleraient du VBA (pour les fenêtres) serait une autre solution. Mais je pense que ça va être une grosse galère à développer.
J'ai un poste avec Visual Studio 2022 et AutoCAD 2023.

J'ai déjà commencé à faire évoluer mes petites connaissances en VB6 et VBA vers le VB.NET (je sais, C# serait plus judicieux), mais je patoge un peu pour l'intéraction dans AutoCAD et  aussi pour la compilation en DLL d'un projet VS.
J'ai cherché beaucoup sur internet des tutos, des PDF (qui m'ont déjà bien dépoussiéré le truc)... Mais je n'ai rien trouvé de probant pour la création de DLL sous VS2022 pour les charger dans AutoCAD.

On me dira que j'essai de courrir avant de savoir marcher, mais je répondrais que je sais déjà me tenir debout 😉.

Ma question est donc toute simple, à part une formation (pour laquelle je me renseigne en ce moment), existe-t-il un site, un livre ou autrechose qui pourrait me venir en aide ?
Bien à toi, la communauté.
Denis...

]]>
60179Mon, 02 Jan 2023 12:17:55 +0000
Coupe sur nuage de point dans une palettehttps://cadxp.com/topic/59818-coupe-sur-nuage-de-point-dans-une-palette/ Bonjour,

 

J'envisage de créer une coupe sur un nuage de point.

Ce que j'aimerais, c'est extraire une coupe verticale d'un nuage et pouvoir l'afficher dans une palette sans influer le dessin courant qui lui peut rester avec son nuage et sa coupe horizontale par exemple.

En .net on dispose de l'extension PointCloudEx pour afficher/masquer une partie d'un nuage RCP. Ca fonctionne bien. Mais à priori, seule l'API C++ autorise l'extraction de points. Je n'ai rien trouvé d'exposer en C#.

Je me posais donc la question s'il était possible d'afficher dans une palette une portion d'une autre database avec laquelle je puisse interagir. J'avais envisagé de cloner mon RCP dans une autre database dont je n'affiche que la coupe spécifique.

Dans un produit comme Civil3D, on a une telle palette pour la partie Visualisation 3D, mais je n'ai pas trouvé d'exemple .Net pour ça et visiblement on peut visualiser un objet (zoom/orbit...), mais pas d'autre interaction possible/programmée/programmable?

Est-ce que vous auriez une idée si c'est possible?

image.png.8ba0236805302026aefc19fdc4341a66.png  image.png.bd3f5f8ca7be3938aa3f71bf19825c5b.png

Merci

 

Olivier

 

PS : j'ai aussi posté sur le forum US : https://forums.autodesk.com/t5/net/view-slice-of-pointcloud-in-a-palette/m-p/11512363#M74588

]]>
59818Thu, 27 Oct 2022 10:29:06 +0000
Overrulehttps://cadxp.com/topic/46582-overrule/Salut,

 

Juste pour le fun.

Les objets overrule permettent "d'outre-passer" l'affichage des entités AutoCAD, on peut, par exemple ajouter du texte à une polyligne* pour afficher dynamiquement les longueurs des segments, et ce, avec un code relativement concis.

 

* les textes font partie intégrante de la polyligne

 

La définition de l'overrule :

using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;

using AcDb = Autodesk.AutoCAD.DatabaseServices;

namespace LabelPolylineOverruleSample
{
   class LabelPolylineOverrule : DrawableOverrule
   {
       TextStyle textStyle;

       public LabelPolylineOverrule()
       {
           textStyle = new TextStyle() { FileName = "Arial", TextSize = 2.5 };
       }

       public override bool WorldDraw(Drawable drawable, WorldDraw wd)
       {
           var pline = (AcDb.Polyline)drawable;
           var nbSegments = pline.Closed ? pline.NumberOfVertices : pline.NumberOfVertices - 1;
           var point = default(Point3d);
           var direction = default(Vector3d);
           string text = null;
           for (int i = 0; i < nbSegments; i++)
           {
               if ((int)pline.GetSegmentType(i) < 2)
               {
                   switch (pline.GetSegmentType(i))
                   {
                       case AcDb.SegmentType.Line:
                           var line = pline.GetLineSegmentAt(i);
                           point = line.MidPoint;
                           direction = line.Direction;
                           text = line.Length.ToString("0.00");
                           wd.Geometry.WorldLine(line.StartPoint, line.EndPoint);
                           break;
                       case AcDb.SegmentType.Arc:
                           CircularArc3d arc = pline.GetArcSegmentAt(i);
                           var startParam = arc.GetParameterOf(arc.StartPoint);
                           var endParam = arc.GetParameterOf(arc.EndPoint);
                           point = arc.EvaluatePoint((startParam + endParam) / 2.0);
                           direction = arc.StartPoint.GetVectorTo(arc.EndPoint).GetNormal();
                           text = arc.GetLength(startParam, endParam, 0.0).ToString("0.00");
                           wd.Geometry.CircularArc(arc.StartPoint, point, arc.EndPoint, ArcType.ArcSimple);
                           break;
                       default:
                           break;
                   }
                   if (direction.X < 0) direction = direction.Negate();
                   var extents = textStyle.ExtentsBox(text, false, false, wd);
                   point -= direction * (extents.MaxPoint.X - extents.MinPoint.X) / 2.0;
                   point += direction.GetPerpendicularVector() * 1.25;
                   wd.Geometry.Text(point, pline.Normal, direction, text, false, textStyle);
               }
           }
           return true;
       }
   }
}

 

Une commande de test :

using Autodesk.AutoCAD.ApplicationServices.Core;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

namespace LabelPolylineOverruleSample
{
   public class Commands
   {
       static LabelPolylineOverrule overrule;
       static string regAppName = "LABEL_POLYLINE";

       static Commands()
       {
           overrule = new LabelPolylineOverrule();
           Overrule.AddOverrule(RXObject.GetClass(typeof(Polyline)), overrule, false);
           overrule.SetXDataFilter(regAppName);
           Overrule.Overruling = true;
       }

       [CommandMethod("TEST")]
       public static void Test()
       {
           var doc = Application.DocumentManager.MdiActiveDocument;
           var db = doc.Database;
           var ed = doc.Editor;
           var options = new PromptEntityOptions("\nSelect polyline: ");
           options.SetRejectMessage("\nSelected object is not a polyline.");
           options.AddAllowedClass(typeof(Polyline), true);
           var result = ed.GetEntity(options);
           if (result.Status != PromptStatus.OK)
               return;
           using (var resBuf = new ResultBuffer(new TypedValue(1001, regAppName), new TypedValue(1000, "Dummy text")))
           {
               AddXdata(result.ObjectId, resBuf, db);
           }
       }

       private static void AddXdata(ObjectId id, ResultBuffer resBuf, Database db)
       {
           using (Transaction tr = db.TransactionManager.StartTransaction())
           {
               var regAppTable = (RegAppTable)tr.GetObject(db.RegAppTableId, OpenMode.ForRead);
               if (!regAppTable.Has(regAppName))
               {
                   var regApp = new RegAppTableRecord() { Name = regAppName };
                   regAppTable.UpgradeOpen();
                   regAppTable.Add(regApp);
                   tr.AddNewlyCreatedDBObject(regApp, true);
               }
               var pline = (Polyline)tr.GetObject(id, OpenMode.ForWrite);
               pline.XData = resBuf;
               tr.Commit();
           }
       }
   }
}

 

]]>
46582Fri, 22 Mar 2019 22:15:29 +0000
Visual Studio 2022https://cadxp.com/topic/56005-visual-studio-2022/ Bonjour,

 

Je viens de recevoir une notif sur la fin du support de VS2019 et une proposition pour installer VS 2022.

Est-ce qu'il y aurait une contre-indication? Je développe (C#) pour AutoCAD 2013 et au delà.

 

Merci

 

Olivier

]]>
56005Fri, 15 Apr 2022 13:14:59 +0000
Inspectorhttps://cadxp.com/topic/55339-inspector/ Salut,

MgdDbg, publié il y a quelques années par Autodesk,est un outil puissant d'inspection pour l'API .NET mais je le trouve plutôt lourd et il faut le mettre à jour pour chaque version (compilation + débogage).
Comme je n'utilise quasiment que les commandes d'inspection de la base de donnée et des entités, j'ai voulu faire un outil plus léger avec uniquement ces fonctionnalités. Il utilise essentiellement Reflection ce qui le rend beaucoup moins dépendant des versions, il est compatible avec toutes les versions depuis 2016 et devrait l'être avec les prochaines..

C'est mon cadeau de fin début d'année.

  • Télécharger InspectorSetup.zip.
  • Débloquer le ZIP
  • Extraire et lancer l'installeur InspectorSetup.msi

Les commandes sont accessibles depuis le menu contextuel par défaut (Inspector). Les propriétés des objets sont affichées dans une boite de dialogue. Celles en gras peuvent être sélectionnées pour être inspectées. Ces outils peuvent aussi intéresser ceux qui bien que ne programmant pas en .NET voudraient connaitre les dessous de la base données AutoCAD.

C'est un travail en progrès, j'ajouterais probablement des possibilités d'inspection plus profondes.

]]>
55339Sun, 16 Jan 2022 23:41:28 +0000
Aide aux développeurshttps://cadxp.com/topic/54385-aide-aux-d%C3%A9veloppeurs/ Depuis AutoCAD 2018, l'aide aux développeurs tous environnements confondus (AutoLISP, ActiveX/VBA, Managed .NET, ObjectARX, JavaScript) est accessible depuis la même page web :
https://help.autodesk.com/view/OARX/2018/ENU/

NB : on peut remplacer 2018 par une version ultérieure dans l'URL

]]>
54385Wed, 01 Dec 2021 17:56:28 +0000
généré des plans automatiquement à partir d'un plan d'ensemble et avec un layout plan bien définihttps://cadxp.com/topic/54254-g%C3%A9n%C3%A9r%C3%A9-des-plans-automatiquement-%C3%A0-partir-dun-plan-densemble-et-avec-un-layout-plan-bien-d%C3%A9fini/ bonjour 

J'ai un lots avec 1000 parcelles et je veux généré des plans de situation automatiquement se basant sur un module de plan .

Merci d'avance

]]>
54254Thu, 18 Nov 2021 01:09:15 +0000
Lancer AutoCAD depuis un exehttps://cadxp.com/topic/52868-lancer-autocad-depuis-un-exe/ Bonjour je cherche comment ouvrir un dessin autocad dans un nouveau process si celui ci n'est pas ouvert ou dans l'autocad Déja ouvert....

 

Ci dessous m'ouvre un autocad à chaque appel ....

///////////////////////////////////////////////

ConfigExe.FichierExeAutocad = ""C:\\Program Files\\Autodesk\\AutoCAD 2021\\acad.exe"

 file.FullName = "D:\\Dossier Plans\\xxx.dwg"

 System.Diagnostics.Process process = new System.Diagnostics.Process();
 process.StartInfo = new System.Diagnostics.ProcessStartInfo(ConfigExe.FichierExeAutocad, "\"" + file.FullName + "\"");
 process.Start();

//////////////////////////////////////////////////

]]>
52868Thu, 28 Oct 2021 08:02:19 +0000
Programmation VB.nethttps://cadxp.com/topic/52262-programmation-vbnet/ Bonjour à tous

Je débute en VB.net et je suis à la recherche de bonne information pour essayer de créer un petit projet pour communiquer avec Autocad.

J'ai réussi à programmer avec Excel et VBA une mini appli qui me permet de naviguer d'une présentation à l'autre via un formulaire Excel mais se qui me gêne avec celle-ci c'est qu'il faut laisser Excel ouvert en arrière plan.

Alors je ne suis dit pourquoi pas le faire en Vb.net.

Auriez-vous un bout de code qui me permet la communication avec Autocad ou des bon tuto.

 

Merci d'avance à tous

 

Bonne soirée

]]>
52262Wed, 29 Sep 2021 16:36:42 +0000
Mise à jour Attributs Blocshttps://cadxp.com/topic/50508-mise-%C3%A0-jour-attributs-blocs/ Bonjour, Dans un dwg, j'ai un bloc avec uniquement des attributs et je cherche à le redéfinir par un autre bloc, avec que des attributs lui aussi, tout en conservant les valeurs d'attributs en commun...

Est-ce possible en langage C# ?

Merci d'avance.

Phil.

]]>
50508Fri, 06 Aug 2021 08:26:59 +0000
Trapezehttps://cadxp.com/topic/44505-trapeze/ Salut,

 

C'était mon premier message sur CADxp.

Cette routine LISP a été écrite pour dessiner les triangulations ou contreventements dont la construction peut parfois être un peu fastidieuse (CF le screencast). Elle peut en fait servir à dessiner tout contour trapézoïdal à partir d'une hauteur (la largeur du contreventement), d'un point à chacune des extrémités (situés sur la même base ou non) et de l'angle depuis chacun de ces points, soit 4 clics une fois la hauteur paramétrée. Pratiquement, pour dessiner tout profil dont les coupes aux extrémités peuvent être de fausse équerre.

 

J'ai repris cette routine en .NET pour en faire un plugin (AutoCAD 2013 et plus) que je propose ici en test.

Télécharger et exécuter TrapezeSetup.msi pour installer le plugin sur toutes les versions d'AutoCAD (et verticaux) de 2013 à 2018.
Télécharger Trapezoid.zip depuis cette page, débloquer puis extraire et exécuter TrapezeSetup.msi pour installer le plugin sur toutes les versions d'AutoCAD (et verticaux) depuis 2013.

Lancer la commande TRZ.

La hauteur est enregistrée avec le dessin.

 

 

Le code :

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using static System.Math;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;

[assembly: CommandClass(typeof(Trapeze.Commands))]

namespace Trapeze
{
   public class Commands
   {
       Document doc;
       Database db;
       Editor ed;
       double height;

       public Commands()
       {
           doc = AcAp.DocumentManager.MdiActiveDocument;
           db = doc.Database;
           ed = doc.Editor;
           height = GetHeight();
           db.BeginSave += (s, e) => SaveHeight();
       }

       [CommandMethod("TRZ")]
       public void Trapeze()
       {
           PromptPointOptions ppo;
           PromptPointResult ppr;
           Point3d pt1;
           while (true)
           {
               ppo = new PromptPointOptions($@"
Hauteur courante = {height}
Spécifiez le premier coin ou [Hauteur du trapeze]: ", "Hauteur");
               ppo.Keywords.Default = "Hauteur";
               ppr = ed.GetPoint(ppo);
               if (ppr.Status == PromptStatus.Keyword)
               {
                   var pdo = new PromptDistanceOptions("\nSpécifiez la hauteur: ");
                   pdo.DefaultValue = height;
                   pdo.UseDefaultValue = true;
                   var pdr = ed.GetDistance(pdo);
                   if (pdr.Status != PromptStatus.OK)
                       return;
                   height = pdr.Value;
               }
               else
               {
                   if (ppr.Status != PromptStatus.OK)
                       return;
                   pt1 = ppr.Value;
                   break;
               }
           }

           ppo.Message = "\nSpécifiez un point dans la direction de ce côté: ";
           ppo.AppendKeywordsToMessage = false;
           ppo.BasePoint = pt1;
           ppo.UseBasePoint = true;
           ppr = ed.GetPoint(ppo);
           if (ppr.Status != PromptStatus.OK)
               return;
           var pt2 = ppr.Value;

           ppo.Message = "\nSpécifiez l'autre extémité de la base ou de la diagonale: ";
           ppr = ed.GetPoint(ppo);
           if (ppr.Status != PromptStatus.OK)
               return;
           var pt3 = ppr.Value;

           using (var tr = db.TransactionManager.StartTransaction())
           using (var pline = new Polyline(4))
           {
               pline.AddVertexAt(0, new Point2d(pt1.X, pt1.Y), 0.0, 0.0, 0.0);
               pline.AddVertexAt(1, new Point2d(pt1.X, pt1.Y), 0.0, 0.0, 0.0);
               pline.AddVertexAt(2, new Point2d(pt3.X, pt3.Y), 0.0, 0.0, 0.0);
               pline.AddVertexAt(3, new Point2d(pt3.X, pt3.Y), 0.0, 0.0, 0.0);
               pline.Closed = true;
               pline.Elevation = pt1.Z;
               var ucs = ed.CurrentUserCoordinateSystem;
               pline.TransformBy(ucs);
               var jig = new TrapezeJig(pline, height, pt1.TransformBy(ucs), pt2.TransformBy(ucs), pt3.TransformBy(ucs));
               var pr = ed.Drag(jig);
               if (pr.Status == PromptStatus.OK)
               {
                   var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                   curSpace.AppendEntity(pline);
                   tr.AddNewlyCreatedDBObject(pline, true);
               }
               tr.Commit();
           }
       }

       private void SaveHeight()
       {
           using (var tr = db.TransactionManager.StartOpenCloseTransaction())
           {
               var NOD = (DBDictionary)tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead);
               DBDictionary dict;
               if (NOD.Contains("GILE_TRAPEZE"))
               {
                   dict = (DBDictionary)tr.GetObject(NOD.GetAt("GILE_TRAPEZE"), OpenMode.ForRead);
               }
               else
               {
                   NOD.UpgradeOpen();
                   dict = new DBDictionary();
                   NOD.SetAt("GILE_TRAPEZE", dict);
                   tr.AddNewlyCreatedDBObject(dict, true);
               }
               Xrecord xrec;
               if (dict.Contains("TrapezeHeight"))
               {
                   xrec = (Xrecord)tr.GetObject(dict.GetAt("TrapezeHeight"), OpenMode.ForWrite);
               }
               else
               {
                   xrec = new Xrecord();
                   dict.SetAt("TrapezeHeight", xrec);
                   tr.AddNewlyCreatedDBObject(xrec, true);
               }
               xrec.Data = new ResultBuffer(new TypedValue(40, height));

               tr.Commit();
           }
       }

       private double GetHeight()
       {
           using (var tr = db.TransactionManager.StartOpenCloseTransaction())
           {
               var NOD = (DBDictionary)tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead);
               if (NOD.Contains("GILE_TRAPEZE"))
               {
                   var dict = (DBDictionary)tr.GetObject(NOD.GetAt("GILE_TRAPEZE"), OpenMode.ForRead);
                   if (dict.Contains("TrapezeHeight"))
                   {
                       var xrec = (Xrecord)tr.GetObject(dict.GetAt("TrapezeHeight"), OpenMode.ForWrite);
                       return (double)xrec.Data.AsArray()[0].Value;
                   }
               }
               return 10.0;
           }
       }

       class TrapezeJig : EntityJig
       {
           Polyline pline;
           Plane plane;
           Point3d dragPt, basePt;
           Point2d p1, p2, p3;
           Vector2d v1, v2, v3;
           double width, a1;

           public TrapezeJig(Polyline pline, double width, Point3d pt1, Point3d pt2, Point3d pt3) : base(pline)
           {
               this.pline = pline;
               this.width = width;
               plane = new Plane(Point3d.Origin, pline.Normal);
               basePt = pline.GetPoint3dAt(2);
               p1 = pt1.Convert2d(plane);
               p2 = pt2.Convert2d(plane);
               p3 = pt3.Convert2d(plane);
               v1 = p1.GetVectorTo(p3);
               v2 = p1.GetVectorTo(p2).GetNormal();
               a1 = v2.Angle - v1.Angle;
           }

           protected override SamplerStatus Sampler(JigPrompts prompts)
           {
               var options = new JigPromptPointOptions("\nSpécifiez un point dans la direction de ce côté: ");
               options.UseBasePoint = true;
               options.BasePoint = basePt;
               options.Cursor = CursorType.RubberBand;
               options.UserInputControls =
                   UserInputControls.Accept3dCoordinates |
                   UserInputControls.UseBasePointElevation;
               var result = prompts.AcquirePoint(options);
               if (result.Value.IsEqualTo(dragPt))
                   return SamplerStatus.NoChange;
               dragPt = result.Value;
               return SamplerStatus.OK;
           }

           protected override bool Update()
           {
               v3 = p3.GetVectorTo(dragPt.Convert2d(plane)).GetNormal();
               double a2 = v3.Angle - v1.Angle;
               Point2d pt1, pt2, pt3, pt4;
               if (Sign(Sin(a1)) == Sign(Sin(a2)))
               {
                   double d1 = Abs(width / Sin(a1));
                   double d2 = Abs(width / Sin(a2));
                   pt1 = p1 + v2 * d1;
                   pt2 = p3 + v3 * d2;
                   pt3 = p3;
                   pt4 = p1;
               }
               else
               {
                   double a0 = Acos(width / v1.Length);
                   double d1, d2;
                   if (Sin(a1) < 0)
                   {
                       d1 = Abs(width / Cos(a0 + a1));
                       d2 = Abs(width / Cos(a0 + a2));
                   }
                   else
                   {
                       d1 = Abs(width / Cos(a0 - a1));
                       d2 = Abs(width / Cos(a0 - a2));
                   }
                   pt1 = p1;
                   pt2 = p1 + v2 * d1;
                   pt3 = p3;
                   pt4 = p3 + v3 * d2;
               }
               if (IsConvex(pt1, pt2, pt3, pt4))
               {
                   pline.SetPointAt(0, pt1);
                   pline.SetPointAt(1, pt2);
                   pline.SetPointAt(2, pt3);
                   pline.SetPointAt(3, pt4);
               }
               return true;
           }

           private bool IsConvex(Point2d pt1, Point2d pt2, Point2d pt3, Point2d pt4)
           {
               var a1 = (pt2 - pt1).Angle;
               var a2 = (pt3 - pt2).Angle;
               var a3 = (pt4 - pt3).Angle;
               var a4 = (pt1 - pt4).Angle;
               var sign = Sign(Sin(a1 - a2));
               return Sign(Sin(a2 - a3)) == sign && Sign(Sin(a3 - a4)) == sign;
           }
       }
   }
}
 
]]>
44505Thu, 25 May 2017 15:37:56 +0000