TheSwamp
Code Red => .NET => Topic started by: Kerry on January 27, 2010, 03:31:12 AM
-
LIBRARY THREAD for AutoCAD XREFS
Members are encouraged to post any functions, methods, snips regarding
AutoCAD XREFS in .NET : C# , VB , F# , Python , etc
Feel free to include comments, descriptive notes, limitations, and images to document your post.
Please post questions in a regular thread.
-
Command line tools for xrefs:
AttachXrefs
BindXrefs
DetachXrefs
OpenXrefs
ReloadXrefs
ReloadAllXrefs
UnloadXrefs
using System;
using System.IO;
using System.Text;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Windows;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.ApplicationServices;
using ofdFlags = Autodesk.AutoCAD.Windows.OpenFileDialog.OpenFileDialogFlags;
[assembly: ExtensionApplication(typeof(cgabriel.XrefTools))]
[assembly: CommandClass(typeof(cgabriel.XrefTools))]
namespace cgabriel
{
public class XrefTools : IExtensionApplication
{
#region ExtensionAppImplementation
public void Initialize() { }
public void Terminate() { }
#endregion
#region Helpers
public delegate void ProcessSingleXref(BlockTableRecord btr);
public delegate void ProcessMultipleXrefs(ObjectIdCollection xrefIds);
public static void detachXref(BlockTableRecord btr)
{
Application.DocumentManager.MdiActiveDocument.Database.DetachXref(btr.ObjectId);
}
public static void openXref(BlockTableRecord btr)
{
string xrefPath = btr.PathName;
if (xrefPath.Contains(".\\"))
{
string hostPath =
Application.DocumentManager.MdiActiveDocument.Database.Filename;
Directory.SetCurrentDirectory(Path.GetDirectoryName(hostPath));
xrefPath = Path.GetFullPath(xrefPath);
}
if (!File.Exists(xrefPath)) return;
Document doc = Application.DocumentManager.Open(xrefPath, false);
if (doc.IsReadOnly)
{
System.Windows.Forms.MessageBox.Show(
doc.Name + " opened in read-only mode.",
"OpenXrefs",
System.Windows.Forms.MessageBoxButtons.OK,
System.Windows.Forms.MessageBoxIcon.Warning);
}
}
public static void bindXrefs(ObjectIdCollection xrefIds)
{
Application.DocumentManager.MdiActiveDocument.Database.BindXrefs(xrefIds, false);
}
public static void reloadXrefs(ObjectIdCollection xrefIds)
{
Application.DocumentManager.MdiActiveDocument.Database.ReloadXrefs(xrefIds);
}
public static void unloadXrefs(ObjectIdCollection xrefIds)
{
Application.DocumentManager.MdiActiveDocument.Database.UnloadXrefs(xrefIds);
}
public static void processXrefs(string promptMessage, ProcessSingleXref process)
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
TypedValue[] filterList = { new TypedValue(0, "INSERT") };
ed.WriteMessage(promptMessage);
PromptSelectionResult result = ed.GetSelection(new SelectionFilter(filterList));
if (result.Status != PromptStatus.OK) return;
ObjectId[] ids = result.Value.GetObjectIds();
Database db = Application.DocumentManager.MdiActiveDocument.Database;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
ObjectIdCollection xrefIds = new ObjectIdCollection();
foreach (ObjectId id in ids)
{
BlockReference blockRef = (BlockReference)tr.GetObject(id, OpenMode.ForRead, false, true);
ObjectId bId = blockRef.BlockTableRecord;
if (!xrefIds.Contains(bId))
{
xrefIds.Add(bId);
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bId, OpenMode.ForRead);
if (btr.IsFromExternalReference)
process(btr);
}
}
tr.Commit();
}
}
public static void processXrefs(string promptMessage, ProcessMultipleXrefs process)
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
TypedValue[] filterList = { new TypedValue(0, "INSERT") };
ed.WriteMessage(promptMessage);
PromptSelectionResult result = ed.GetSelection(new SelectionFilter(filterList));
if (result.Status != PromptStatus.OK) return;
ObjectId[] ids = result.Value.GetObjectIds();
Database db = Application.DocumentManager.MdiActiveDocument.Database;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
ObjectIdCollection blockIds = new ObjectIdCollection();
foreach (ObjectId id in ids)
{
BlockReference blockRef = (BlockReference)tr.GetObject(id, OpenMode.ForRead, false, true);
blockIds.Add(blockRef.BlockTableRecord);
}
ObjectIdCollection xrefIds = filterXrefIds(blockIds);
if (xrefIds.Count != 0)
process(xrefIds);
tr.Commit();
}
}
public static void attachXrefs(string[] fileNames)
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
Array.Sort(fileNames);
Database db = Application.DocumentManager.MdiActiveDocument.Database;
double dimScale = db.Dimscale;
foreach (string fileName in fileNames)
{
PromptPointOptions options = new PromptPointOptions("Pick insertion point for " + fileName + ": ");
options.AllowNone = false;
PromptPointResult pt = ed.GetPoint(options);
if (pt.Status != PromptStatus.OK) continue;
double xrefScale = getDwgScale(fileName);
double scaleFactor = dimScale / xrefScale;
using (Transaction tr = Application.DocumentManager.MdiActiveDocument.TransactionManager.StartTransaction())
{
ObjectId xrefId = db.AttachXref(fileName, Path.GetFileNameWithoutExtension(fileName));
BlockReference blockRef = new BlockReference(pt.Value, xrefId);
BlockTableRecord layoutBlock = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
blockRef.ScaleFactors = new Scale3d(scaleFactor, scaleFactor, scaleFactor);
blockRef.Layer = "0";
layoutBlock.AppendEntity(blockRef);
tr.AddNewlyCreatedDBObject(blockRef, true);
tr.Commit();
}
}
}
public static double getDwgScale(string fileName)
{
using (Database db = new Database(false, true))
{
db.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, false, string.Empty);
return db.Dimscale;
}
}
public static ObjectIdCollection filterXrefIds(ObjectIdCollection blockIds)
{
ObjectIdCollection xrefIds = new ObjectIdCollection();
foreach (ObjectId bId in blockIds)
{
if (!xrefIds.Contains(bId))
{
BlockTableRecord btr = (BlockTableRecord)bId.GetObject(OpenMode.ForRead);
if (btr.IsFromExternalReference)
xrefIds.Add(bId);
}
}
return xrefIds;
}
#endregion
#region Commands
[CommandMethod("XrefTools", "AttachXrefs", CommandFlags.Modal | CommandFlags.DocExclusiveLock)]
public static void XrefAttach()
{
string initFolder = Application.DocumentManager.MdiActiveDocument.Database.Filename.ToUpper();
if (initFolder.Contains("PLOT"))
{
initFolder = initFolder.Replace("-PLOT.DWG", "");
initFolder = initFolder.Replace("PLOT\\", "");
initFolder = initFolder.Replace("PLOTS\\", "");
if (!Directory.Exists(initFolder))
initFolder = Application.DocumentManager.MdiActiveDocument.Database.Filename;
}
ofdFlags flags = ofdFlags.DefaultIsFolder | ofdFlags.AllowMultiple;
OpenFileDialog dlg = new OpenFileDialog("Select Drawings to Attach", initFolder, "dwg", "Select Xrefs", flags);
if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
attachXrefs(dlg.GetFilenames());
}
[CommandMethod("XrefTools", "BindXrefs", CommandFlags.Modal | CommandFlags.DocExclusiveLock)]
public static void XrefBind()
{
processXrefs("\nSelect xrefs to bind: ", XrefTools.bindXrefs);
}
[CommandMethod("XrefTools", "DetachXrefs", CommandFlags.Modal | CommandFlags.DocExclusiveLock)]
public static void XrefDetach()
{
processXrefs("\nSelect xrefs to detach: ", XrefTools.detachXref);
}
[CommandMethod("XrefTools", "OpenXrefs", CommandFlags.Session)]
public static void XrefOpen()
{
processXrefs("\nSelect xrefs to open: ", XrefTools.openXref);
}
[CommandMethod("XrefTools", "ReloadXrefs", CommandFlags.Modal | CommandFlags.DocExclusiveLock)]
public static void XrefReload()
{
processXrefs("\nSelect xrefs to reload: ", XrefTools.reloadXrefs);
}
[CommandMethod("XrefTools", "ReloadAllXrefs", CommandFlags.Modal | CommandFlags.DocExclusiveLock)]
public static void XrefReloadAll()
{
Database db = Application.DocumentManager.MdiActiveDocument.Database;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable blockTbl = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
ObjectIdCollection blockIds = new ObjectIdCollection();
foreach (ObjectId bId in blockTbl)
blockIds.Add(bId);
ObjectIdCollection xrefIds = filterXrefIds(blockIds);
if (xrefIds.Count != 0)
db.ReloadXrefs(xrefIds);
tr.Commit();
}
}
[CommandMethod("XrefTools", "UnloadXrefs", CommandFlags.Modal | CommandFlags.DocExclusiveLock)]
public static void XrefUnload()
{
processXrefs("\nSelect xrefs to unload: ", XrefTools.unloadXrefs);
}
#endregion
}
}
-
Here is my code to batch repath/rename xrefs.
[ http://www.theswamp.org/index.php?topic=22517.0 ]
-
Here is my class that hold my xref information, that I use in other codes.
public class MyXrefInformation {
private string XrName;
private string XrPath;
private string XrFndAtPath = string.Empty;
private string NewXrName = "";
private string NewXrPath = "";
private string[] InsertedAt;
private string[] _OwnerNames = new string[0];
private string[] _ChildrenNames = new string[0];
private Autodesk.AutoCAD.DatabaseServices.XrefStatus XrStatus;
private string DwgPath;
private bool Overlay;
private bool Nested;
public MyXrefInformation() {}
public string Name {
get { return XrName; }
set { XrName = value; }
}
public string Path {
get { return XrPath; }
set { XrPath = value; }
}
public string FoundAtPath {
get { return XrFndAtPath; }
set { XrFndAtPath = value; }
}
public string[] InsertedWhere {
get { return InsertedAt; }
set { InsertedAt = value; }
}
public Autodesk.AutoCAD.DatabaseServices.XrefStatus Status {
get { return XrStatus; }
set { XrStatus = value; }
}
public string DrawingPath {
get { return DwgPath; }
set { DwgPath = value; }
}
public bool IsOverlay {
get { return Overlay; }
set { Overlay = value; }
}
public bool IsNested {
get { return Nested; }
set { Nested = value; }
}
public string NewName {
get { return NewXrName; }
set { NewXrName = value; }
}
public string NewPath {
get { return NewXrPath; }
set { NewXrPath = value; }
}
public string[] OwnerNames {
get { return _OwnerNames; }
set { _OwnerNames = value; }
}
public string[] ChildrenNames {
get { return _ChildrenNames; }
set { _ChildrenNames = value; }
}
}
Here is an example of how I use it.
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections;
using System.IO;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Geometry;
public static MyXrefInformation[] FindXrefs (Database db) {
MyXrefInformation[] XrefArray;
string[] tempStrArray;
int tempCnt;
using (Transaction Trans = db.TransactionManager.StartTransaction()) {
BlockTable BlkTbl = (BlockTable)Trans.GetObject(db.BlockTableId, OpenMode.ForRead);
db.ResolveXrefs(false, true);
XrefGraph XrGph = db.GetHostDwgXrefGraph(false);
XrefArray = new MyXrefInformation[XrGph.NumNodes - 1];
for (int i = 1; i < XrGph.NumNodes; ++i) {
XrefGraphNode XrNode = XrGph.GetXrefNode(i);
BlockTableRecord btr = (BlockTableRecord)Trans.GetObject(XrNode.BlockTableRecordId, OpenMode.ForRead);
MyXrefInformation XrInfo = new MyXrefInformation();
XrInfo.Name = XrNode.Name;
XrInfo.Path = btr.PathName;
XrInfo.DrawingPath = db.Filename;
string FoundAt = WillLoad(btr.PathName, db);
if (XrNode.XrefStatus == XrefStatus.Unresolved) {
if ( string.IsNullOrEmpty( FoundAt ) )
XrInfo.Status = XrefStatus.Unresolved;
else
XrInfo.Status = XrefStatus.Resolved;
}
else
XrInfo.Status = XrNode.XrefStatus;
if ( XrInfo.Status == XrefStatus.Resolved ) {
XrInfo.FoundAtPath = FoundAt;
}
XrInfo.IsNested = XrNode.IsNested;
XrInfo.IsOverlay = btr.IsFromOverlayReference;
ObjectIdCollection ObjIdCol = (ObjectIdCollection)btr.GetBlockReferenceIds(true, true);
string[] InsertedAtArray = new string[ObjIdCol.Count];
for (int j = 0; j < ObjIdCol.Count; ++j) {
ObjectId ObjId = ObjIdCol[j];
BlockReference BlkRef = (BlockReference)Trans.GetObject(ObjId, OpenMode.ForRead);
BlockTableRecord tempbtr = (BlockTableRecord)Trans.GetObject(BlkRef.OwnerId, OpenMode.ForRead);
if (tempbtr.IsLayout) {
Layout templo = (Layout)Trans.GetObject(tempbtr.LayoutId, OpenMode.ForRead);
InsertedAtArray[j] = "Layout: " + templo.LayoutName;
}
else InsertedAtArray[j] = "Block: " + tempbtr.Name;
}
XrInfo.InsertedWhere = InsertedAtArray;
if ( !XrNode.NumIn.Equals(0) ) {
tempStrArray = new string[XrNode.NumIn];
tempCnt = 0;
for (int j = 0; j < XrNode.NumIn; j++) {
int tempInt = FindGraphLocation( XrNode.In( j ) );
if ( tempInt.Equals( -1 ) )
continue;
tempStrArray[tempCnt] = XrGph.GetXrefNode( tempInt ).Name;
tempCnt++;
}
XrInfo.OwnerNames = tempStrArray;
}
if ( !XrNode.NumOut.Equals(0) ) {
tempStrArray = new string[XrNode.NumOut];
tempCnt = 0;
for (int j = 0; j < XrNode.NumOut; j++) {
int tempInt = FindGraphLocation( XrNode.Out( j ) );
if ( tempInt.Equals( -1 ) )
continue;
tempStrArray[tempCnt] = XrGph.GetXrefNode( tempInt ).Name;
tempCnt++;
}
XrInfo.ChildrenNames = tempStrArray;
}
XrefArray[i - 1] = XrInfo;
}
}
return XrefArray;
}
-
Function in VB.NET to insert a Raster Image (that is an external reference) in AutoCAD. It includes options to manager transparency and the layer.
Public Function Add_Raster(ByRef ThisDoc As Document, ByVal RasterFile As String, ByVal InsPoint As Geometry.Point3d, ByVal Scale As Double, ByVal ImageTransp As Boolean, ByVal ImageLayer As String) As RasterImage
Dim RasterEnt As RasterImage, RasterDef As RasterImageDef
Dim ImageDicID, ImageDefID As ObjectId, ImageDic As DBDictionary
Dim Matrix As Geometry.Matrix3d
Dim btr As BlockTableRecord
Dim RasterName As String = ""
RasterName = RasterFile.Substring(RasterFile.LastIndexOf("\") + 1)
RasterName = RasterName.Substring(0, RasterName.IndexOf("."))
Add_Raster = Nothing
If ThisDoc Is Nothing Then Exit Function
Try
Using Trans As Transaction = ThisDoc.TransactionManager.StartTransaction()
RasterEnt = New RasterImage
RasterEnt.Dispose() ' force loading of RasterImage.dbx module (needed for 2009 and earlier)
RasterDef = New RasterImageDef
RasterDef.SourceFileName = RasterFile
RasterDef.ActiveFileName = RasterFile
RasterDef.Load()
ImageDicID = RasterImageDef.GetImageDictionary(ThisDoc.Database)
If ImageDicID.IsNull Then
RasterImageDef.CreateImageDictionary(ThisDoc.Database)
ImageDicID = RasterImageDef.GetImageDictionary(ThisDoc.Database)
End If
If ImageDicID.IsNull Then
MsgBox("Could not create image dictionary", MsgBoxStyle.Critical, "Failed")
'Exit Try
End If
ImageDic = Trans.GetObject(ImageDicID, DatabaseServices.OpenMode.ForWrite)
If ImageDic Is Nothing Then
MsgBox("Could not open image dictionary", MsgBoxStyle.Critical, "Failed")
Else
If ImageDic.Contains(RasterName) Then
MsgBox("That image name is already in use", MsgBoxStyle.Critical, "Failed")
Else
ImageDic.UpgradeOpen()
ImageDefID = ImageDic.SetAt(RasterName, RasterDef)
Trans.AddNewlyCreatedDBObject(RasterDef, True)
RasterEnt = New RasterImage
RasterEnt.SetDatabaseDefaults(ThisDoc.Database)
Matrix = New Geometry.Matrix3d
Matrix = Geometry.Matrix3d.Scaling(Scale / RasterDef.Size.X, New Geometry.Point3d(0, 0, 0))
RasterEnt.TransformBy(Matrix)
Matrix = Geometry.Matrix3d.Displacement(New Geometry.Vector3d(InsPoint.X, InsPoint.Y, InsPoint.Z))
RasterEnt.TransformBy(Matrix)
RasterEnt.ImageDefId = ImageDefID
If ImageTransp = True Then
RasterEnt.ImageTransparency = True
End If
RasterEnt.Layer = ImageLayer
btr = Trans.GetObject(ThisDoc.Database.CurrentSpaceId, DatabaseServices.OpenMode.ForWrite)
btr.AppendEntity(RasterEnt)
Trans.AddNewlyCreatedDBObject(RasterEnt, True)
RasterEnt.AssociateRasterDef(RasterDef)
Trans.Commit()
End If
End If
End Using
Add_Raster = RasterEnt
Catch ex As Exception
MsgBox("Error inserting image " & RasterName, MsgBoxStyle.Critical, "Failed." & ex.ToString)
End Try
End Function
Original code from GTVic with a little addition. Original idea: Tony Tanzillo (who coded this in C#).
-
Has not been tested thoroughly and basic and simple
but did for someone else to insert a xref that is a closed drawing into a closed drawing
C#
[CommandMethod("AttachXref")]
public void AttachXref()
{
string xrefPath = "C:\\Test\\XrefTest.dwg";
string hostPath = "C:\\Test\\HostTest.dwg";
Database xrefDb = new Database(false, false);
xrefDb.ReadDwgFile(hostPath, FileShare.ReadWrite, false, "");
using (Transaction trx = xrefDb.TransactionManager.StartTransaction())
{
BlockTable xrefBt = xrefDb.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
BlockTableRecord btrMs = xrefBt[BlockTableRecord.ModelSpace].GetObject(OpenMode.ForWrite) as BlockTableRecord;
ObjectId xrefObjId = xrefDb.AttachXref(xrefPath, Path.GetFileNameWithoutExtension(xrefPath));
BlockReference bref = new BlockReference(Point3d.Origin, xrefObjId);
btrMs.AppendEntity(bref);
trx.AddNewlyCreatedDBObject(bref, true);
xrefDb.CloseInput(true);
xrefDb.SaveAs(hostPath, DwgVersion.Current);
trx.Commit();
}
}
VB
<CommandMethod("AttachXref")> _
Public Sub AttachXref()
Dim xrefPath As String = "C:\Test\XrefTest.dwg"
Dim hostPath As String = "C:\Test\HostTest.dwg"
Dim xrefDb As Database = New Database(False, False)
xrefDb.ReadDwgFile(hostPath, FileShare.ReadWrite, False, "")
Using trx As Transaction = xrefDb.TransactionManager.StartTransaction()
Dim xrefBt As BlockTable = xrefDb.BlockTableId.GetObject(OpenMode.ForRead)
Dim btrMs As BlockTableRecord = xrefBt(BlockTableRecord.ModelSpace).GetObject(OpenMode.ForWrite)
Dim xrefObjId As ObjectId = xrefDb.AttachXref(xrefPath, Path.GetFileNameWithoutExtension(xrefPath))
Dim bref As New BlockReference(Point3d.Origin, xrefObjId)
btrMs.AppendEntity(bref)
trx.AddNewlyCreatedDBObject(bref, True)
xrefDb.CloseInput(True)
xrefDb.SaveAs(hostPath, DwgVersion.Current)
trx.Commit()
End Using
End Sub
-
T.Willey wrote:
string FoundAt = WillLoad(btr.PathName, db);
int tempInt = FindGraphLocation( XrNode.Out( j ) );
Could you please explain what these functions do? :?
edit:
SOLVED!
For anyone with same problem, utility file is posted here by T.Willey http://www.theswamp.org/index.php?topic=24075.0 (http://www.theswamp.org/index.php?topic=24075.0)