Author Topic: (FYI) Show nesting of xrefs  (Read 6183 times)

0 Members and 1 Guest are viewing this topic.

T.Willey

  • Needs a day job
  • Posts: 5251
(FYI) Show nesting of xrefs
« on: May 02, 2008, 02:55:41 PM »
So I knew there had to be a way to do it, but it just wasn't as simple as I thought it would be, but here you go.  It will show where each xref is, and which xrefs are within each.  No need to cycle through the block table record to see if an xref is nested within the definition.

Code: [Select]
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections;
using System.IO;
using System.Text;

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Windows;

using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;

[CommandMethod("TestXrefPrint")]
public void TestXrefPring() {
Document Doc = acadApp.DocumentManager.MdiActiveDocument;
Database Db = Doc.Database;
Editor Ed = Doc.Editor;
XrefGraph XrGraph = Db.GetHostDwgXrefGraph(false);
for (int i = 1; i < XrGraph.NumNodes; i++) {
XrefGraphNode XrNode = XrGraph.GetXrefNode(i);
Ed.WriteMessage("\n Name: {0}", XrNode.Name);
for (int j = 0; j < XrNode.NumIn; j++) {
int tempInt = IsXrNodeEqual(XrGraph, XrNode.In(j));
if ( tempInt.Equals(-1) )
continue;
Ed.WriteMessage("\n    Is In: {0}", XrGraph.GetXrefNode(tempInt).Name);
}
for (int j = 0; j < XrNode.NumOut; j++) {
int tempInt = IsXrNodeEqual(XrGraph, XrNode.Out(j));
if ( tempInt.Equals(-1) )
continue;
Ed.WriteMessage("\n    Has within: {0}", XrGraph.GetXrefNode(tempInt).Name);
}
Ed.WriteMessage("\n");
}
}
public int IsXrNodeEqual(XrefGraph xrGraph, GraphNode grNode) {
for (int i = 0; i < xrGraph.NumNodes; i++) {
if (grNode == xrGraph.GetXrefNode(i) as GraphNode)
return i;
}
return -1;
}

Sample output, where the drawing is named XrefIsIn2.dwg.
Quote
Command: testxrefprint

 Name: XrefMain
    Is In: XrefIsIn2
    Has within: Xref2
    Has within: Xref1

 Name: Xref2
    Is In: XrefMain
    Has within: Cube

 Name: Xref1
    Is In: XrefMain

 Name: Cube
    Is In: Xref2
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

jmaeding

  • Bull Frog
  • Posts: 304
  • I'm just here for the Shelties.
Re: (FYI) Show nesting of xrefs
« Reply #1 on: May 02, 2008, 05:15:11 PM »
one thing I ran accross before when resolving nested xrefs from files opened as dbx docs, you need to add this line for it to work.
db.ResolveXrefs(false, false);
before the line:
XrefGraph XrGraph = Db.GetHostDwgXrefGraph(false);

Otherwise I believe you can get the nested block names, but no other info on the nested items like the path.
It slows things down a lot too.
Now what I do, is dig through the top level of xrefs, then dig through those, and then their children until no more nesting.
Then I use that info to compile a tree for any file I want involving those xrefs.
Doing it that way is much faster if you are making a tool like your own etransmit, where say all 10 sheets you are gathering info on will have the same xrefs.  Simply skip xrefs you already dug into, this saving a lot of time.
Its probably not appropriate for single file investigation though.
I'm doing an app that catalogs the xref info, then shows me a tree of xrefs for any file in a project, then even rename an xref and fix the sheet paths for me.  I wonder if doc management systems do this type of thing well.  Any tool that investigated files, and let you change xref names and paths quickly would be so nice.
There are lots of xref repathers, but none that catalog xref trees for later retrieval.

thx
James Maeding

mcarson

  • Guest
Re: (FYI) Show nesting of xrefs
« Reply #2 on: May 06, 2008, 07:27:02 AM »
How about the following. I used some code from a number of posts and created a little generic method to return the paths for ALL xrefs.

Code: [Select]
[Autodesk.AutoCAD.Runtime.CommandMethod("PrintAllXrefs")]
public List<string> GetDrawingReferences()
{
    List<string> result = new List<string>();
   
    //Get current document
    Autodesk.AutoCAD.ApplicationServices.Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
    //Get current database
    Database db = doc.Database;
    //Get current editor
    Editor ed = doc.Editor;
   
    //For debug print to editor only...
    string name = null;
    string fullname = null;
    bool isnested = false;
   
    //Get the first transaction to read the xref graph
    using (Transaction tr = doc.TransactionManager.StartTransaction()) {
        //Get the current document's xref graph
        XrefGraph DocDbXrGraph = db.GetHostDwgXrefGraph(false);
        //Loop through the nodes in the xref graph
        for (int i = 0; i <= DocDbXrGraph.NumNodes - 1; i++) {
            //Get the node
            XrefGraphNode XrGraphNode = DocDbXrGraph.GetXrefNode(i);
            //Only continue if the node contains items
            if (i != 0) {
                //Start another transaction to get extended information for the xref
                TransactionManager tm = db.TransactionManager;
                using (Transaction tr2 = tm.StartTransaction) {
                    //Get block table of the current document
                    BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                    //Get block table record for the xref
                    BlockTableRecord btr = (BlockTableRecord)tr.GetObject(XrGraphNode.BlockTableRecordId, OpenMode.ForRead);
                    //Add xref to the list for returning, regardless of nested status
                    result.Add(btr.PathName);
                    //debug only:
                    name = btr.Name;
                    fullname = btr.PathName;
                    isnested = XrGraphNode.IsNested;
                }
               
                //Uncomment the following lines for extended debug
                //With ed
                //.WriteMessage("" & Chr(10) & "--------------------")
                //.WriteMessage("" & Chr(10) & "Block Name: " + name)
                //.WriteMessage("" & Chr(10) & "Full Name: " + fullname)
                //.WriteMessage("" & Chr(10) & "Is Nested: " + isnested.ToString)
                //End With
               
            }
        }
    }
    return result;
}
The next thing to do, I suppose, is to ensure that the xrefs are up-to-date and current in the drawing

T.Willey

  • Needs a day job
  • Posts: 5251
Re: (FYI) Show nesting of xrefs
« Reply #3 on: May 06, 2008, 02:22:58 PM »
James,

  Thanks for the tip about 'db.ResolveXrefs(false, false)'.  I was just updating my utility program that gets all the xref information I want, and I had to do this before I could get the in's and out's of the xref nodes.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: (FYI) Show nesting of xrefs
« Reply #4 on: January 09, 2010, 01:34:31 PM »
Hi,

I was looking for a way to list all xrefs in a drawing (even nested), and searching some inspiration here and there and I found this one.

I tried to build one my own way and here's the result.
Thanks to T.Willey, mcarson, Glenn R and all others... for the the shared informations.

As I didn't find a way to convert a GraphNode (as returned by GraphNode.In) into an XrefGraphNode, I first 'copy' the XrefGraph in a GraphNodeCollection to be able to deal with index.

Any comments are welcome.

Code: [Select]
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace XrefSample
{
    public static class ListXref
    {
        [CommandMethod("XRLST")]
        public static void GetXrefList()
        {
            Document doc = acadApp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            XrefGraph xrg = db.GetHostDwgXrefGraph(true);
            GraphNodeCollection gnc = new GraphNodeCollection();
            for (int i = 0; i < xrg.NumNodes; i++)
            {
                gnc.Add(xrg.GetXrefNode(i));
            }
            for (int i = 1; i < xrg.NumNodes; i++)
            {
                XrefGraphNode xrgn = xrg.GetXrefNode(i);
                if (xrgn.IsNested)
                {
                    for (int j = 0; j < xrgn.NumIn; j++)
                    {
                        XrefGraphNode parent = xrg.GetXrefNode(gnc.IndexOf(gnc[i].In(j)));
                        ed.WriteMessage("\n{0}|{1} : {2}", parent.Name, xrgn.Name, getStatus(xrgn));
                    }
                }
                else
                {
                    ed.WriteMessage("\n{0} : {1}", xrgn.Name, getStatus(xrgn));
                }
            }
        }

        private static string getStatus(XrefGraphNode xrgn)
        {
            string result = string.Empty;
            switch (xrgn.XrefStatus)
            {
                case XrefStatus.FileNotFound:
                    result = "File not found";
                    break;
                case XrefStatus.Resolved:
                    result = "Resolved";
                    break;
                case XrefStatus.Unloaded:
                    result = "Unloaded";
                    break;
                case XrefStatus.Unreferenced:
                    result = "Unreferenced";
                    break;
                case XrefStatus.Unresolved:
                    result = "Unresolved";
                    break;
            }
            return result;
        }
    }
}

Result for a sample drawing:
Theatre
    | Equipement
        | Perches
        | Passerelles
    | Plateau
Rotonde
    | Mobilier
Detail
    | Passerelles

Quote
Theatre : Resolved
Rotonde : Resolved
Rotonde|Mobilier : Resolved
Theatre|Plateau : Resolved
Theatre|Equipement : Unloaded
Equipement|Perches : Unreferenced
Equipement|Passerelles : Resolved
Detail|Passerelles : Resolved
Detail : Resolved
« Last Edit: January 10, 2010, 04:14:26 AM by gile »
Speaking English as a French Frog

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: (FYI) Show nesting of xrefs
« Reply #5 on: January 10, 2010, 05:14:41 AM »
Another way (classical recursive process).

Code: [Select]
        [CommandMethod("XRTREE")]
        public static void XrefTree()
        {
            Document doc = acadApp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            try
            {
                getNestedXref(db, ed, string.Empty);
            }
            catch (System.Exception ex)
            {
                ed.WriteMessage("\nErreur: " + ex.Message);
            }
        }

        private static void getNestedXref(Database db, Editor ed, string parent)
        {
            XrefGraph xrg = db.GetHostDwgXrefGraph(true);
            for (int i = 1; i < xrg.NumNodes; i++)
            {
                XrefGraphNode xrgn = xrg.GetXrefNode(i);
                if (!xrgn.IsNested)
                {
                    ed.WriteMessage("\n{0}{1} ({2})", parent, xrgn.Name, getStatus(xrgn));
                    if (xrgn.XrefStatus == XrefStatus.Resolved)
                        getNestedXref(xrgn.Database, ed, parent + xrgn.Name + "|");
                }
            }
        }

Quote
Théâtre (Resolved)
Théâtre|Plateau (Resolved)
Théâtre|Equipement (Resolved)
Théâtre|Equipement|Perches (Resolved)
Théâtre|Equipement|Passerelles (Resolved)
Rotonde (Resolved)
Rotonde|Mobilier (Resolved)
Detail (Resolved)
Detail|Passerelles (Resolved)
« Last Edit: January 10, 2010, 06:36:22 AM by gile »
Speaking English as a French Frog

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: (FYI) Show nesting of xrefs
« Reply #6 on: January 10, 2010, 12:48:03 PM »
Again...

The recursive way allows to get the tree structure but using XrefGraphNode.Database doesn't allows to get an unresolved node children .
So I mixed the two previous ways, and write the result in an Xml file.

Code: [Select]
using System.Text;
using System.Xml;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace XrefSample
{
    public class XrefToXml
    {
        [CommandMethod("XR2XML")]
        public static void XrefListToXml()
        {
            Document doc = acadApp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            XrefGraph xrg = db.GetHostDwgXrefGraph(true);
            using (GraphNodeCollection gnc = new GraphNodeCollection())
            {
                for (int i = 0; i < xrg.NumNodes; i++)
                {
                    gnc.Add(xrg.GetXrefNode(i));
                }
                string dwgName = doc.Name;
                string xmlName = dwgName.Substring(0, dwgName.LastIndexOf('.')) + ".xml";
                XmlTextWriter writer = new XmlTextWriter(xmlName, Encoding.UTF8);
                try
                {
                    writer.Formatting = Formatting.Indented;
                    writer.WriteStartDocument();
                    writer.WriteStartElement("host");
                    writer.WriteAttributeString("path", dwgName);
                    using (Transaction tr = db.TransactionManager.StartTransaction())
                    {
                        for (int i = 1; i < xrg.NumNodes; i++)
                        {
                            XrefGraphNode xrgn = xrg.GetXrefNode(i);
                            if (!xrgn.IsNested)
                                writeXmlElement(tr, writer, xrgn, xrg, gnc);
                        }
                    }
                    writer.WriteEndElement();
                    writer.WriteEndDocument();
                    writer.Flush();
                }
                catch (Autodesk.AutoCAD.Runtime.Exception ex)
                {
                    ed.WriteMessage("\nAutoCAD error: " + ex.Message + "\n" + ex.StackTrace);
                }
                catch (System.Exception ex)
                {
                    ed.WriteMessage("\nSystem error: " + ex.Message + "\n" + ex.StackTrace);
                }
                finally
                {
                    writer.Close();
                }
            }
        }

        private static void writeXmlElement(Transaction tr, XmlTextWriter writer, XrefGraphNode xrgn, XrefGraph xrg, GraphNodeCollection gnc)
        {
            BlockTableRecord btr = (BlockTableRecord)tr.GetObject(xrgn.BlockTableRecordId, OpenMode.ForRead);
            writer.WriteStartElement("xref");
            writer.WriteAttributeString("path", btr.PathName);
            writer.WriteAttributeString("status", getStatus(btr));
            for (int i = 0; i < xrgn.NumOut; i++)
            {
                writeXmlElement(tr, writer, xrg.GetXrefNode(gnc.IndexOf(xrgn.Out(i))), xrg, gnc);
            }
            writer.WriteEndElement();
        }

        private static string getStatus(BlockTableRecord btr)
        {
            switch (btr.XrefStatus)
            {
                case XrefStatus.FileNotFound:
                    return  "File not found";
                case XrefStatus.Resolved:
                    return  "Resolved";
                case XrefStatus.Unloaded:
                    return  "Unloaded";
                case XrefStatus.Unreferenced:
                    return "Unreferenced";
                default:
                    return "Unresolved";
            }
        }
    }
}

Code: [Select]
<?xml version="1.0" encoding="utf-8"?>
<host path="F:\DAO\Dessins\Theatre\Plan.dwg">
  <xref path="F:\DAO\Dessins\Theatre\Rotonde.dwg" status="Resolved">
    <xref path="F:\DAO\Dessins\Theatre\Mobilier.dwg" status="Resolved" />
  </xref>
  <xref path="F:\DAO\Dessins\Theatre\Theatre.DWG" status="Resolved">
    <xref path="F:\DAO\Dessins\Theatre\Plateau.dwg" status="Resolved" />
    <xref path="F:\DAO\Dessins\Theatre\Equipement.dwg" status="Unloaded">
      <xref path="F:\DAO\Dessins\Theatre\Perches.dwg" status="Unreferenced" />
      <xref path="F:\DAO\Dessins\Theatre\Passerelles.dwg" status="Resolved" />
    </xref>
  </xref>
  <xref path="F:\DAO\Dessins\Theatre\Detail.dwg" status="Resolved">
    <xref path="F:\DAO\Dessins\Theatre\Passerelles.dwg" status="Resolved" />
  </xref>
</host>
« Last Edit: January 10, 2010, 03:58:07 PM by gile »
Speaking English as a French Frog