PhilOctet Posté(e) le 10 janvier 2010 Posté(e) le 10 janvier 2010 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]
(gile) Posté(e) le 10 janvier 2010 Posté(e) le 10 janvier 2010 Salut, Les images, dwf et pdf sont stockées dans des dictionnaires (entrées du NamedObjectDictionary) :ACAD_DWFDEFINITIONSACAD_IMAGE_DICTACAD_PDFDEFINITIONSOn 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
PhilOctet Posté(e) le 15 janvier 2010 Auteur Posté(e) le 15 janvier 2010 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.WorkingDatabaseDim 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 dictionnaireDim acDict As DBDictionaryDim acDictId As ObjectId = acDbDict.GetAt("ACAD_DWFDEFINITIONS")acDict = acTrans.GetObject(acDictId, OpenMode.ForWrite) ' Traite chaque élément du dictionnaireFor Each acDictEnt As DBDictionaryEntry In acDictDim 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
(gile) Posté(e) le 15 janvier 2010 Posté(e) le 15 janvier 2010 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 VBImports 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
PhilOctet Posté(e) le 15 janvier 2010 Auteur Posté(e) le 15 janvier 2010 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
(gile) Posté(e) le 15 janvier 2010 Posté(e) le 15 janvier 2010 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
PhilOctet Posté(e) le 15 janvier 2010 Auteur Posté(e) le 15 janvier 2010 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.
(gile) Posté(e) le 15 janvier 2010 Posté(e) le 15 janvier 2010 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
PhilOctet Posté(e) le 15 janvier 2010 Auteur Posté(e) le 15 janvier 2010 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.
(gile) Posté(e) le 15 janvier 2010 Posté(e) le 15 janvier 2010 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
PhilOctet Posté(e) le 16 janvier 2010 Auteur Posté(e) le 16 janvier 2010 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,
(gile) Posté(e) le 16 janvier 2010 Posté(e) le 16 janvier 2010 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));ouScan(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
(gile) Posté(e) le 16 janvier 2010 Posté(e) le 16 janvier 2010 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
PhilOctet Posté(e) le 19 janvier 2010 Auteur Posté(e) le 19 janvier 2010 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 DWFPublic 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.
(gile) Posté(e) le 19 janvier 2010 Posté(e) le 19 janvier 2010 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
PhilOctet Posté(e) le 23 janvier 2010 Auteur Posté(e) le 23 janvier 2010 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.
(gile) Posté(e) le 24 janvier 2010 Posté(e) le 24 janvier 2010 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
PhilOctet Posté(e) le 24 janvier 2010 Auteur Posté(e) le 24 janvier 2010 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.
(gile) Posté(e) le 24 janvier 2010 Posté(e) le 24 janvier 2010 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
PhilOctet Posté(e) le 24 janvier 2010 Auteur Posté(e) le 24 janvier 2010 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
(gile) Posté(e) le 24 janvier 2010 Posté(e) le 24 janvier 2010 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
(gile) Posté(e) le 24 janvier 2010 Posté(e) le 24 janvier 2010 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
PhilOctet Posté(e) le 24 janvier 2010 Auteur Posté(e) le 24 janvier 2010 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 ?
(gile) Posté(e) le 24 janvier 2010 Posté(e) le 24 janvier 2010 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
PhilOctet Posté(e) le 24 janvier 2010 Auteur Posté(e) le 24 janvier 2010 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-jacentsDim 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 ...
Messages recommandés
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 compteSe connecter
Vous avez déjà un compte ? Connectez-vous ici.
Connectez-vous maintenant