Aller au contenu

Messages recommandés

Posté(e)

Bonjour,

 

Tout d'abord bonne année à tous. Je vous souhaite : santé, amour, argent, boulot. Le bonheur, tout simplement.

 

Mais l'activité reprend et je me remet sur mon dev "nettoyage automatique des dessins".

 

Le réacheminement des XRefs introuvables est réussi et clos.

 

Je m'attaque maintenant aux autres objets gérés pas la même commande XRef : PDF, DWF, DGN, RasterImage. Je pensais à priori qu'il étaient gérés de la même façon. Déçu.

 

Je crois savoir qu'il ne sont pas considérés comme de blocks et j'ai besoin d'y accéder.

 

Auriez-vous, sous le coude, un bout de code qui me mettrait sur la piste ?

 

Par avance, merci.[Edité le 10/1/2010 par PhilOctet]

 

[Edité le 10/1/2010 par PhilOctet]

Posté(e)

Salut,

 

Les images, dwf et pdf sont stockées dans des dictionnaires (entrées du NamedObjectDictionary) :

ACAD_DWFDEFINITIONS

ACAD_IMAGE_DICT

ACAD_PDFDEFINITIONS

On peut supposer que les dgn seront dans ACAD_DGNDEFINITIONS, mais je ne saurais l'affirmer.

 

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Bonjour,

 

Merci (Gile) pour ton soutient.

 

Voici où j'en suis avec ma routine :

 

=====

'' accès aux définition d'objets des dictionnaires

Public Sub ScanDefinition()

 

Dim acDb As Database = HostApplicationServices.WorkingDatabase

Dim acTrans As Transaction = acDb.TransactionManager.StartTransaction()

Dim acDbDict As DBDictionary = acTrans.GetObject(acDb.NamedObjectsDictionaryId, OpenMode.ForRead)

 

Try

' Ne pas supprimer : fourni la liste des dictionnaires utilisés

'For Each Obj As DBDictionaryEntry In acDbDict

' Debug.Print("=>" & Obj.Key)

'Next

 

' dictionnaires et définitions utilisés

' Est-ce le que le dictionnaire existe ?

If acDbDict.Contains("ACAD_DWFDEFINITIONS") Then

 

' Saisi le dictionnaire

Dim acDict As DBDictionary

Dim acDictId As ObjectId = acDbDict.GetAt("ACAD_DWFDEFINITIONS")

acDict = acTrans.GetObject(acDictId, OpenMode.ForWrite)

 

' Traite chaque élément du dictionnaire

For Each acDictEnt As DBDictionaryEntry In acDict

Dim MyDef As DwfDefinition = acTrans.GetObject(acDictEnt.m_value, OpenMode.ForWrite)

MyDef.SourceFileName = "..\..\Cercle2-Model.dwf"

Next

 

End If

=====

 

Voici ma question:

Je sais passer une variable dans une sub.

Donc pour le ACAD_DWFDEFINITIONS pas de problème.

Mais j'aurais aimé passer le type d'objet DwfDefinition du dernier bloc ci-dessus en variable.

Est-ce possible en VB(.net) ? et comment ?

 

J'y arrive en C, en Lisp, avec Delphi mais pas en VB.

 

Merci de votre aide, Au plaisir de vous lire

Posté(e)

Salut,

 

Je ne comprends pas bien la question.

Je ne vois pas où est le problème pour passer un DwfDefinition (ou un quelconque autre type d'objet) comme paramètre d'une méthode.

 

un exemple (C#)

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace CsMgd1
{
   public class Class1
   {
       private Document doc = acadApp.DocumentManager.MdiActiveDocument;

       [CommandMethod("Test")]
       public void Test()
       {
           Database db = doc.Database;
           using (Transaction tr = db.TransactionManager.StartTransaction())
           {
               DBDictionary NOD = (DBDictionary)tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead);
               if (!NOD.Contains("ACAD_DWFDEFINITIONS"))
                   return;
               DBDictionary dwfDict = (DBDictionary)tr.GetObject(NOD.GetAt("ACAD_DWFDEFINITIONS"), OpenMode.ForRead);
               foreach (DBDictionaryEntry ent in dwfDict)
               {
                   DwfDefinition dwf = (DwfDefinition)tr.GetObject(ent.Value, OpenMode.ForRead);
                   GetProps(dwf);
               }
               tr.Commit();
           }
       }

       private void GetProps(DwfDefinition dwf)
       {
           Editor ed = doc.Editor;
           ed.WriteMessage(
               "\nChemin enregistré: {0}\nEmplacement: {1}\nChargé: {2}",
               dwf.SourceFileName,
               dwf.ActiveFileName,
               dwf.Loaded ? "Oui" : "Non");
       }
   }
}

 

la traduction (automatique) en VB

Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Runtime
Imports acadApp = Autodesk.AutoCAD.ApplicationServices.Application

Namespace CsMgd1
   Public Class Class1
       Private doc As Document = acadApp.DocumentManager.MdiActiveDocument
       
        _
       Public Sub Test()
           Dim db As Database = doc.Database
           Using tr As Transaction = db.TransactionManager.StartTransaction()
               Dim NOD As DBDictionary = DirectCast(tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead), DBDictionary)
               If Not NOD.Contains("ACAD_DWFDEFINITIONS") Then
                   Exit Sub
               End If
               Dim dwfDict As DBDictionary = DirectCast(tr.GetObject(NOD.GetAt("ACAD_DWFDEFINITIONS"), OpenMode.ForRead), DBDictionary)
               For Each ent As DBDictionaryEntry In dwfDict
                   Dim dwf As DwfDefinition = DirectCast(tr.GetObject(ent.Value, OpenMode.ForRead), DwfDefinition)
                   GetProps(dwf)
               Next
               tr.Commit()
           End Using
       End Sub
       
       Private Sub GetProps(ByVal dwf As DwfDefinition)
           Dim ed As Editor = doc.Editor
           ed.WriteMessage(vbLf & "Chemin enregistré: {0}" & vbLf & "Emplacement: {1}" & vbLf & "Chargé: {2}", dwf.SourceFileName, dwf.ActiveFileName, If(dwf.Loaded, "Oui", "Non"))
       End Sub
   End Class
End Namespace

 

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Bonsoir,

 

La routine que j'ai écrite fonctionne avec un objet DwfDefinition.

 

J'aimerais aussi l'effectuer avec un PdfDefinition, DwgDefinition, RasterImage, etc.

 

Donc je cherche à savoir comment passer un argument qui serait le choix du type d'objet et d'utiliser une seule et même routine pour tous les objets du dictionnaire.

 

appel de la fonction :

ScanDict("DWF") ou Scan(DwfDefinition) de la même façon que ScanDict("PDF") ou Scan(PdfDefinition).

 

et que la fonction appelé soit

Public Sub ScanDict(ByRef TypeDObjetDict as Object) par exemple.

 

et que la ligne concernée ressemble à

Dim MyDef As TypeDObjetDict = acTrans.GetObject(acDictEnt.m_value, OpenMode.ForWrite)

 

Donc je passe un type d'objet à ScanDict et celle-ci, avec le même code, traite aussi bien les Pdf, Dwf, Dgn, et ainsi de suite.

 

Ce qui m'éviterais de faire un "select case" avec un "case" pour chaque type d'objet.

 

Merci de votre aide

Posté(e)

Salut, tout dépend de ce que tu dois faire dans ta fonction.

 

Si tu passes un argument de type Object, tu seras certainement obligé de faire un TryCast pour utiliser certaines méthodes.

Les classes RasterImage, PdfDefinition, DwfDefinition, DgnDefinition dérivent toutes de la classe UnderlayDefinition. Si cette classe fournit les méthodes et propriétés dont tu as besoin, tu n'auras pas de Cast à faire.

 

Public Sub ScanDict(ByRef TypeDObjetDict as UnderlayDefinition)

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Bonsoir,

 

Merci, je n'y vais pas penser. Mais cela ne fonctionne pas avec tous les types d'objets des dictionnaires ?

 

Et d'une façon plus générale, est-ce que cela est possible en VB.net ou C# ? Comme ca l'est en C ou Lisp.

Posté(e)

J'ai été un peu vite en besogne, RatserImage ne dérive pas de UnderlayDefinition.

par conte tous héritent de DBObbject, mais cette classe fournit peu de méthodes pour ce que tu veux faire.

Je crains que si tu veux faire une méthode unique tu ne sois obligé, dans ta méthode, de retrouver le type d'origine de chaque objet, pour lui appliquer les méthode dont tu as besoin.

 

Il faut bien comprendre les relations d'héritage : tous les types qui héritent d'une classe héritent de toutes les méthodes et propriété de cette classe.

 

Par exemple Line et Arc héritent de Entity, la propriété Color de la classe Entity est utilisable avec les deux, par contre, la propriété Radius n'est utilisable qu'avec Arc.

Toutes les classes .NET héritent de la classe Object mais cette classe ne fournit que les méthodes Equals, GetHashCode, GetType, MemeberWiseClone, ReferenceEquals et ToString.

 

PS : je ne comprends pas ta comparaison avec C (que je ne connais pas) et LISP (que je connais assez bien)

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Effectivement, je comprend bien ce que tu veux dire. Je me doutai bien qu'en fonction du type d'objet que je passe en paramètre je ne puisse pas accéder à toutes les propriétés comme le rayon d'une ligne ou la surface d'une ligne, etc.

 

En C ou en Lisp, il est possible de passer une fonction par un paramètre et ainsi pour "l'exécuter" par la commande (eval foo). foo étant la fonction passée en paramètre.

 

En Lisp, la notion d'objet n'existe pas, mais on peut les simuler par les listes comme les extractions AutoCAD de type (entget (car (entsel))). Le langage LeLispou XLisp permet de faire la même chose.

 

Bonne soirée,

 

J'essaie ce que tu m'a conseillé et si cela fonctionne, je t'en tiendrai informer.

 

Comment puis-je partager le code du deveoppement que je suis entrain de réaliser? Il n'est pas un très bonne exemple de programmation mais permer de montrer quelqiues exemples de codes. En toute modestie.

Posté(e)

Je n'avais pas compris la question, si tu veux passer une fonction comme paramètre, il faut utiliser un 'delegate', mais je n'en voit pas l'utilité...

Je te laisse chercher dans ta doc ou sur MSDN...

 

Pour traiter ces 4 dictionnaires, je ferais un truc deu style :

private Document doc = acadApp.DocumentManager.MdiActiveDocument;

private void ScanDict()
{
   Database db = doc.Database;
   string[] dicts = new string[3] { "ACAD_DWFDEFINITIONS", "ACAD_DNGDEFINITIONS", "ACAD_PDFDEFINITIONS" };
   using (Transaction tr = db.TransactionManager.StartTransaction())
   {
       DBDictionary NOD = (DBDictionary)tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead);
       foreach (string str in dicts)
       {
           if (NOD.Contains(str))
               ScanDef(tr, NOD.GetAt(str));
       }
       if (NOD.Contains("ACAD_IMAGE_DICT"))
           ScanImg(tr, NOD.GetAt("ACAD_IMAGE_DICT"));
       tr.Commit();
   }
}

private void ScanImg(Transaction tr, ObjectId dictId)
{
   Editor ed = doc.Editor;
   DBDictionary dict = (DBDictionary)tr.GetObject(dictId, OpenMode.ForRead);
   foreach (DBDictionaryEntry entry in dict)
   {
       RasterImageDef img = (RasterImageDef)tr.GetObject(entry.Value, OpenMode.ForRead);
       ed.WriteMessage(
           "\nChemin enregistré: {0}\nEmplacement: {1}",
           img.SourceFileName,
           img.ActiveFileName);  
   }
}

private void ScanDef(Transaction tr, ObjectId dictId)
{
   Editor ed = doc.Editor;
   DBDictionary dict = (DBDictionary)tr.GetObject(dictId, OpenMode.ForRead);
   foreach (DBDictionaryEntry entry in dict)
   {
       UnderlayDefinition def = (UnderlayDefinition)tr.GetObject(entry.Value, OpenMode.ForRead);
       ed.WriteMessage(
           "\nChemin enregistré: {0}\nEmplacement: {1}",
           def.SourceFileName,
           def.ActiveFileName);
   }
}

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Bonjour (Gile),

 

L'ensemble de tes réponses me conviennent.

 

Dans ta sub "ScanImg(Transaction tr, ObjectId dictId)" à la ligne "RasterImageDef img = (RasterImageDef)tr.GetObject(entry.Value, OpenMode.ForRead);"

 

et dans ta sub "ScanDef(Transaction tr, ObjectId dictId)" à la ligne "UnderlayDefinition def = (UnderlayDefinition)tr.GetObject(entry.Value, OpenMode.ForRead);"

 

On constate qu'à un mot prêt, c'est la même chose. Ce mot est un type d'objet. Plutôt que de faire deux routines, existe-t-il un moyen de passer ce mot (ou type d'objet) en paramètre ?

 

Et si il est possible de passer un type d'objet en paramètre, est-il possible de faire la même chose avec une fonction ?

 

Je te remercie pour les efforts consentis,

Posté(e)

Plutôt que de faire deux routines, existe-t-il un moyen de passer ce mot (ou type d'objet) en paramètre ?

 

Oui, mais je ne vois pas vraiment l'intérêt, il faudra de toutes façon traiter les RasterImageDef et les UnderlayDefinition séparément.

 

Appels de fonction :

Scan(tr, NOD.GetAt(str), typeof(UnderlayDefinition));

ou

Scan(tr, NOD.GetAt("ACAD_IMAGE_DICT"), typeof(RasterImageDef));

 

Fonction Scan() :

private void Scan(Transaction tr, ObjectId dictId, System.Type type)
{
   Editor ed = doc.Editor;
   DBDictionary dict = (DBDictionary)tr.GetObject(dictId, OpenMode.ForRead);
   foreach (DBDictionaryEntry entry in dict)
   {
       if (type.Equals(typeof(UnderlayDefinition)))
       {
           UnderlayDefinition def = (UnderlayDefinition)tr.GetObject(entry.Value, OpenMode.ForRead);
           ed.WriteMessage(
               "\nChemin enregistré: {0}\nEmplacement: {1}",
               def.SourceFileName,
               def.ActiveFileName);
       }
       else
       {
           RasterImageDef img = (RasterImageDef)tr.GetObject(entry.Value, OpenMode.ForRead);
           ed.WriteMessage(
               "\nChemin enregistré: {0}\nEmplacement: {1}",
               img.SourceFileName,
               img.ActiveFileName);
       }
   }
}

 

Pour passer une fonction en paramètre, comme je disais plus haut, il faut utiliser un delegate.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Un exemple très simple d'utilisation d'un délégué pour passer une fonction comme argument à une autre fonction

 

using System;

namespace ConsoleApplication1
{
   class Program
   {
       // Procédure de test
       // Appelle la méthode MyFunction en lui passant 
       // la méthode Mult2 ou Mult3 comme paramètre
       static void Main(string[] args)
       {
           MyFunction(7, Mult2);
           MyFunction(12, Mult2);
           MyFunction(7, Mult3);
           MyFunction(12, Mult3);
           Console.ReadLine();
       }

       // Déclaration du délégué (définit la signature de la méthode requise)
       public delegate void Multiple(int num);

       // Méthodes pouvant servir de référence à une instance de Multiple
       // (même signature que le délégué)
       public static void Mult2(int num)
       {
           Console.WriteLine("est {0}", (num & 1) == 0 ? "pair" : "impair");
       }

       public static void Mult3(int num)
       {
           Console.WriteLine("{0} multiple de 3", (num & 3) == 0 ? "est" : "n'est pas");
       }

       // Méthode acceptant une méthode (délégué de type Multiple) comme paramètre
       public static void MyFunction(int num, Multiple deleg)
       {
           Console.Write("{0} ", num);
           deleg(num);
       }
   }
}

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Bonsoir,

 

Je suis coincé avec mon dev.

 

Je cherche à passer en adressage relatif les différents chemins contenus dans la fenêtre XRef (AutoCAD 2010) dans laquelle on y trouve les xrefs, pdfs, dgns, dwfs et les images.

 

C'était la raison pour laquelle je voulais passer le type d'objet en paramètre.

4 cas sur 5, la propriété SourceFileName est commune au 4 types d'objet.

 

Toutefois, même de façon isolée, mes routines relatives aux images et xrefs fonctionnent très bien. Par contre, les trois autres ( pdfs, dgns, dwfs ) ne fonctionnent pas.

 

Les chemins sont bien mis à jour dans la fenêtre XRef mais dès que je veux fermer en enregistrant le dessin, AutoCAD se bloque définitivement.

 

Est-ce quelqu'un peut m'aider ?

 

Voici la routine, '' Traitement des Références DWF

Public Sub ScanDwf()

 

Dim acDb As Database = HostApplicationServices.WorkingDatabase

Dim acTrans As Transaction = acDb.TransactionManager.StartTransaction()

Dim acDbDict As DBDictionary = acTrans.GetObject(acDb.NamedObjectsDictionaryId, OpenMode.ForRead)

 

' récupère le chemin du dessin courant

Dim DWGPath As String = Application.GetSystemVariable("DwgPrefix")

Dim DWGName As String = Application.GetSystemVariable("DwgName")

Dim DWG = AF_ScanLAN.strLanPath(DWGPath & DWGName)

 

Try

Dim acDict As DBDictionary

 

' Ne pas supprimer : fourni la liste des dictionnaires utilisés

For Each Obj As DBDictionaryEntry In acDbDict

Debug.Print("=>" & Obj.Key)

Next

 

' dictionnaires et définitions utilisés

' Est-ce le que le dictionnaire existe ?

If acDbDict.Contains("ACAD_DWFDEFINITIONS") Then

 

' Saisi le dictionnaire

Dim acDictId As ObjectId = acDbDict.GetAt("ACAD_DWFDEFINITIONS")

acDict = acTrans.GetObject(acDictId, OpenMode.ForWrite)

 

' Traite chaque élément du dictionnaire

For Each acDictEnt As DBDictionaryEntry In acDict

Dim MyDwf As DwfDefinition = acTrans.GetObject(acDictEnt.m_value, OpenMode.ForWrite)

 

' adressage relatif de chemin équivalent du favori réseau

Dim MyDefPath = Abs2Rel(AF_ScanLAN.strLanPath(MyDwf.SourceFileName), DWG)

 

MyDwf.UpgradeOpen()

MyDwf.SourceFileName = MyDefPath

'MyDwf.Load("Yes")

Next

 

End If

 

Catch ex As System.Exception

MsgBox("Erreur dans le scanne des réferences externes")

Finally

'

End Try

 

acTrans.Commit()

acTrans.Dispose()

 

End Sub

 

Les 2 autres routines (ScanPdf(), ScanDgn() sont quasiment les mêmes.

 

 

merci de votre aide et au plaisir de vous lire.

Posté(e)

Salut,

 

Je ne connais pas bien VB et en plus le code posté comme ça sans indentations est plutôt pénible à lire.

 

Et pour localiser une erreur tu es le mieux placé :

Quel est le message d'erreur s'il y en a un ?

À quel endroit est-ce que ça plante ? As tu essayé un "pas à pas" en mode débogage ?

 

Toutefois, il y a quelques truc qui me paraissent curieux :

Dim MyDefPath = Abs2Rel(AF_ScanLAN.strLanPath(MyDwf.SourceFileName), DWG)

Il manquerait pas un As String, par hasard ?

 

MyDwf.UpgradeOpen()

est inutile YourDwf est déjà ouvert en écriture.

 

acTrans.Commit() devrait être dans le bloc Try (ou Finaly)

 

acTrans.Dispose() doit absolument être dans le bloc Finaly (à moins d'utiliser un bloc Using pour la transaction).

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Bonsoir,

 

J'appelle au secours. Je n'y arrive pas. Je cherche à modifier les chemins absolus en chemin relatifs des Xrefs : dwg, dwf, dwfx, pdf, dgn, images. Tous les objets qui sont gérés par la commande Xref d'AutoCAD 2010.

 

Cela fonctionne avec les Xrefs (type dwg) ou avec seulement l'un des 5 autres. Dès que je veux en traiter un autre type en plus, je ne peux plus fermer AutoCAD sans le bloquer.

 

J'ai fouillé sur différents sites à la recherche de code et je n'ai rien trouvé sur les manipulations de "UnderlayDefinition".

 

Est-ce quelqu'un ou toi (Gile) ne pourrait m'offrir une routine qui soulagerait tous mes énervements de ces derniers temps ?

 

Par avance, merci.

Posté(e)

Salut,

 

Un exemple de commande pour donner à toutes les xrefs, image et calques sous-jacents un chemin relatif.

 

using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace RelativePath
{
   public class Class1
   {
       [CommandMethod("Test")]
       public void Test()
       {
           Document doc = acadApp.DocumentManager.MdiActiveDocument;
           Database db = doc.Database;
           Editor ed = doc.Editor;
           string folder = (string)acadApp.GetSystemVariable("DWGPREFIX");
           folder = folder.Trim(new char[] { '\\' });
           using (Transaction tr = db.TransactionManager.StartTransaction())
           {
               // Traitement des xrefs
               XrefGraph xrg = db.GetHostDwgXrefGraph(true);
               GraphNodeCollection gnc = new GraphNodeCollection();
               for (int i = 0; i                 {
                   gnc.Add(xrg.GetXrefNode(i));
               }
               try
               {
                   for (int i = 1; i                     {
                       XrefGraphNode xrgn = xrg.GetXrefNode(i);
                       if ((!xrgn.IsNested) && (xrgn.XrefStatus != XrefStatus.FileNotFound))
                           SetXrefRelativePath(xrgn, xrg, gnc, tr, folder);
                   }
               }
               catch (System.Exception ex)
               {
                   ed.WriteMessage("\nErreur: " + ex.Message);
               }

               DBDictionary NOD =
                   (DBDictionary)tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead);

               // Traitement des objets sous-jacents
               string[] dicts = new string[3] { 
                   "ACAD_DWFDEFINITIONS", 
                   "ACAD_DNGDEFINITIONS", 
                   "ACAD_PDFDEFINITIONS" };
               foreach (string str in dicts)
               {
                   if (NOD.Contains(str))
                   {
                       try
                       {
                           SetUnderlayRelativePath(tr, NOD.GetAt(str), folder);
                       }
                       catch (System.Exception ex)
                       {
                           ed.WriteMessage("\nErreur: " + ex.Message);
                       }
                   }
               }

               // Traitement des images
               if (NOD.Contains("ACAD_IMAGE_DICT"))
               {
                   try
                   {
                       SetImageRelativePath(tr, NOD.GetAt("ACAD_IMAGE_DICT"), folder);
                   }
                   catch (System.Exception ex)
                   {
                       ed.WriteMessage("\nErreur: " + ex.Message);
                   }
               }
               tr.Commit();
           }
       }

       // Attribue un chemin relatif aux images raster
       private void SetImageRelativePath(Transaction tr, ObjectId dictId, string folder)
       {
           DBDictionary dict =
               (DBDictionary)tr.GetObject(dictId, OpenMode.ForRead);
           foreach (DBDictionaryEntry entry in dict)
           {
               RasterImageDef img = 
                   (RasterImageDef)tr.GetObject(entry.Value, OpenMode.ForWrite);
               img.SourceFileName = GetRelativePath(folder, img.SourceFileName);
               img.Load();
           }
       }

       // attribue un chemein relatif aux objets sous-jacents
       private void SetUnderlayRelativePath(Transaction tr, ObjectId dictId, string folder)
       {
           DBDictionary dict =
               (DBDictionary)tr.GetObject(dictId, OpenMode.ForRead);
           foreach (DBDictionaryEntry entry in dict)
           {
               UnderlayDefinition uDef =
                   (UnderlayDefinition)tr.GetObject(entry.Value, OpenMode.ForWrite);
               uDef.SourceFileName = GetRelativePath(folder, uDef.SourceFileName);
           }
       }

       // procédure récursive : attribue un chemin relatif aux enfants du fichier
       // et appelle la procédure pour ceux ci
       private void SetXrefRelativePath
           (XrefGraphNode xrgn, XrefGraph xrg, GraphNodeCollection gnc, Transaction tr, string folder)
       {
           BlockTableRecord btr =
               (BlockTableRecord)tr.GetObject(xrgn.BlockTableRecordId, OpenMode.ForWrite);
           string childFolder = btr.PathName.Substring(0, btr.PathName.LastIndexOf('\\'));
           btr.PathName = GetRelativePath(folder, btr.PathName);
           for (int i = 0; i             {
               XrefGraphNode child = xrg.GetXrefNode(gnc.IndexOf(xrgn.Out(i)));
               if (xrgn.XrefStatus == XrefStatus.FileNotFound)
                   continue;
               SetXrefRelativePath(child, xrg, gnc, tr, childFolder);
           }
       }

       // retourne le chemin relatif de fichier par rapport au dossier
       private string GetRelativePath(string folder, string filename)
       {
           if (folder.StartsWith(filename.Substring(1, 2)))
               return filename;
           char[] chr = new char[1] { '\\' };
           string[] foldArray = folder.Trim(chr).Split(chr);
           string[] fileArray = filename.Split(chr);
           int foldLength = foldArray.Length;
           int fileLength = fileArray.Length;
           int l = (foldLength             int i = 0;
           for (; i             {
               if (!foldArray[i].Equals(fileArray[i], StringComparison.CurrentCultureIgnoreCase))
                   break;
           }
           string result = fileArray[i];
           for (int j = i + 1; j             {
               result += "\\" + fileArray[j];
           }
           if (i == foldArray.Length)
               return ".\\" + result;
           for (; i             {
               result = "..\\" + result;
           }
           return result;
       }
   }
}

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Ouauou !

 

Je ne m'attendais pas à une aussi rapide.

 

Soit tu travailles avec un décalage horaire conséquent soit tu lis une grande dévotion à ton activité soit les deux.

 

Je n'ai pas encore le code mais je ne vais pas tarder à le faire.

 

Encore sincèrement merci.

Posté(e)

Je viens de faire quelques test un peu plus poussés (A2010), j'ai effectivement un problème avec les PDF (avec les DNG je peux pas tester). Ça plante systématiquement (Erreur fatale).

 

Par contre pour les xrefs, images raster, et dwf ça semble rouler comme il faut.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Bonjour,

 

Où est-ce que cela plante ? avec AutoCAD ou avec la routine ?

 

Si c'est AutoCAD et le DGN, je peux te fournir les fichiers par l'intermédiaire d'un zip.

 

Si c'est la routine, je ne sais pas quoi te dire parce que c'est justement l'un des endroits où j'éprouve des difficultés.

 

Il me semble que la transaction n'est pas ou mal terminé. Parce que si tu lance un acDoc.CloseAndSave(NomduDWG), le système te dit que le document est encore ouvert !

Et comme tu termines ton code de la même façon que moi, tu dois avoir le même problème.

 

Où trouver de la doc sans être ADN ? A part l'"AutoCAD 2010 .Net getstart".

 

Chez moi, là où çà plante, c'est lorsque je lance dgn après dwf, ou pdf après dwf. Bref, lorsque je lance l'un des quatres après l'un des quatres autre. C'est pas claire. Lorsque je lance un underlay après un autre underlay.

 

J'ai étudié ton code. Il est différent du mien. Bien plus dense et donc plus claire. Mais je ne suis pas et loin de là une référence.

 

Comme dans ton code, j'avais aussi créer une fonction récursive pour les xrefs imbriqués.

 

Au plaisir de te lire

Posté(e)

AutoCAD plante systématiquement après l'exécution de la routine si un PDF est attaché au dessin.

La routine aboutit (la transaction est bien terminée).

Je pense à un problème d'implémentation de la classe UnderlayDefinition pour les PDF.

 

Je vais soumettre le problème au support ADN.

 

Si tu veux m'envoyer un ou deux DNG :

string.Format("{0}@{1}", "chanteau.gilles", "orange.fr");

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

L'aide (ObjectARX 2010) est quelque peu équivoque :casstet:

 

Il y est dit qu'il ne faut pas modifier la chaîne retournée par UnderlayDefinition.SourceFileName, mais cette propriété est marquée Read / Write.

 

Et puis, ça fonctionne bien avec les DWF...

 

http://img294.imageshack.us/img294/6534/underlay.png

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Ce qui me surprend est que cela fonctionne si je n'en prend qu'un en charge. Mais dès que j'essai avec un autre cela plante AutoCAD.

 

Et quand je dis que cela fonctionne avec un, c'est avec n'importe lequel des 4 : dwf, pdf, dgn, dwfx.

 

Donc si j'en modifie un type, que je sauvegarde, que j'en prend un autre type et que je sauvegarde à nouveau et ainsi de suite, cela fonctionne. Pourquoi ? Je suppose que tu n'as pas non plus la réponse.

 

L'extrait "copie d'écran" vient de l'aide fourni avec l'ObjectARX ?

Posté(e)

Ce qui est curieux c'est qu'il semble que le comportement soit différent chez moi.

 

Je n'ai aucun problème avec les DWF, je peux en avoir plusieurs attachés et lancer la commande, en rajouter et relancer la commande sans problème.

 

C'est uniquement avec les PDF (pas testé les DGN). Il suffit qu'il y en ait un (il ne peut y avoir que lui dans le dessin). La routine s'exécute correctement, je peux lire les changement dans la palette des xrefs (ouverte auparavant). C'est quand je reprends la main dans le dessin, pour faire un zoom ou tenter un Ctrl+S qu'AutoCAD plante.

 

L'extrait "copie d'écran" vient de l'aide fourni avec l'ObjectARX ?

Oui ObjectARX 2010.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Bonsoir (Gile),

 

J'ai pas mal étudier ton code. Je ne connaissais pas cette façon d'extraire les Xrefs. Je n'ai pas encore tous compris mais je vais forcer quelques neurones défaillantes.

 

Tu dis que cela fonctionne avec les dwf. Je te rassure en te disant que cela fonctionne avec tous les dictionaires de type Underlay.

 

Sauf qu'il faut les utiliser un à un parce que les deuxièmes choix déstabilisent tous le système.

 

Voici les testes que j'ai fait :

 

' Traitement des objets sous-jacents

Dim NOD As DBDictionary = tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead)

'Dim dicts As String() = New String(0) {"ACAD_DWFDEFINITIONS"}

'Dim dicts As String() = New String(0) {"ACAD_PDFDEFINITIONS"}

Dim dicts As String() = New String(0) {"ACAD_DGNDEFINITIONS"}

'=>Dim dicts As String() = New String(1) {"ACAD_DWFDEFINITIONS", "ACAD_PDFDEFINITIONS"}

'Dim dicts As String() = New String(2) {"ACAD_DWFDEFINITIONS", "ACAD_PDFDEFINITIONS", "ACAD_DGNDEFINITIONS"}

 

Dès la ligne précédée d'un =>, ça plante et quelque soit l'ordre.

 

Questions annexes :

Comment puis-je te joindre un e-transmit ?

Pourquoi reçois-je 7 messages de notification de réponse sur ma messagerie ?

 

A bientôt ...

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é