<?xml encoding=”UTF-8″>By Balaji Ramamoorthy
Exploding an AEC entity such as a Wall in AutoCAD results in a block reference and the block table record that it refers to contains faces. But when exploding the Wall entity in a RealDWG application results in a block reference and the block table record that it refers to contains lines.
In this blog post we will look into the reason for this difference and a way to workaround it. The workaround was provided by my colleagues Mikako Harada and Tony Zou. Many thanks to them.
While RealDWG can read a drawing created by any of the AutoCAD verticals, the object enablers specific to the verticals will still be needed for the host application to recognize the entities in that drawing. The object enabler defines the resulting entity set when the entity is exploded. As object enabler provides the explode functionality for its custom entities, they may also have other considerations.
For example, when an AEC drawing has its viewing direction set as Top View, a wall appears as a rectangle. When the viewing direction is any other view, the wall appears as a collection of faces.
Also, AEC drawings do not fully load into a side database when using the readDwgFile. This is a known behavior in AutoCAD Architecture and here is a blog post by my colleague Adam Nagy. For the database to get fully loaded in a side database it is required to call AecAppDbx::drawingPromoterAndIniter method.
Considering the above reasons, here are the C++ and .Net sample codes to explode a wall entity in a RealDWg application. The methods to have the database initialized and to set its viewing direction are invoked by accessing the exported methods from AecBase.dbx using their ordinal numbers. Please note that the ordinal numbers can change and are version specific. In the below code, the ordinal numbers for 2015 and 2016 releases are provided. For any other version, you may need to find them out using dumpbin on AecBase.lib from the Lib-x64 folder.
Here is the C# code snippet :
<span>using</span><span> System.Runtime.InteropServices;</span>
<span>using</span><span> Autodesk.AutoCAD.Runtime;</span>
<span>internal</span><span> <span>static</span><span> <span>class</span><span> <span>Workaround</span><span> </span></span></span></span>
<span>{</span>
[<span>StructLayout</span><span> (<span>LayoutKind</span><span> .Sequential)]</span></span>
<span>private</span><span> <span>struct</span><span> <span>AcGeVector3d</span><span> </span></span></span>
<span>{</span>
<span>public</span><span> <span>double</span><span> x;</span></span>
<span>public</span><span> <span>double</span><span> y;</span></span>
<span>public</span><span> <span>double</span><span> z;</span></span>
<span>}</span>
<span>// for 2016</span><span> </span>
<span>//[DllImport(@"C:\Program Files\Autodesk\RealDWG 2015\AecBase.dbx", </span><span> </span>
<span>// CallingConvention = CallingConvention.Cdecl, </span><span> </span>
<span>// EntryPoint = "#1202")]</span><span> </span>
<span>// for 2015</span><span> </span>
[<span>DllImport</span><span> (<span>@"C:\Program Files\Autodesk\RealDWG 2015\AecBase.dbx"</span><span> , </span></span>
CallingConvention = <span>CallingConvention</span><span> .Cdecl, </span>
EntryPoint = <span>"#1204"</span><span> )] </span>
<span>private</span><span> <span>extern</span><span> <span>static</span><span> <span>void</span><span> setLastViewDir(<span>ref</span><span> <span>AcGeVector3d</span><span> vDir);</span></span></span></span></span></span>
<span>public</span><span> <span>static</span><span> <span>void</span><span> SetLastViewDirection(Vector3d direction)</span></span></span>
<span>{</span>
<span>if</span><span> (! SystemObjects.ServiceDictionary.Contains(</span>
<span>"AecBaseServices"</span><span> ))</span>
<span>return</span><span> ;</span>
<span>AcGeVector3d</span><span> vec;</span>
vec.x = direction.X;
vec.y = direction.Y;
vec.z = direction.Z;
setLastViewDir(<span>ref</span><span> vec);</span>
<span>}</span>
<span>}</span>
<span>// No change in ordinals</span><span> </span>
<span>// For 2015 and 2016</span><span> </span>
[<span>DllImport</span><span> (<span>@"C:\Program Files\Autodesk\RealDWG 2015\AecBase.dbx"</span><span> , </span></span>
CallingConvention = <span>CallingConvention</span><span> .Cdecl, </span>
CharSet = <span>CharSet</span><span> .Unicode, EntryPoint = <span>"#897"</span><span> )] </span></span>
<span>public</span><span> <span>extern</span><span> <span>static</span><span> <span>void</span><span> drawingPromoterAndIniter</span></span></span></span>
(IntPtr db, <span>bool</span><span> sideDb);</span>
Database db = <span>new</span><span> Database(<span>false</span><span> , <span>true</span><span> );</span></span></span>
db.ReadDwgFile(
<span>@"D:\Temp\wall.dwg"</span><span> , </span>
System.IO.FileShare.None,
<span>false</span><span> , </span>
<span>""</span><span> );</span>
HostApplicationServices.WorkingDatabase = db;
drawingPromoterAndIniter(db.UnmanagedObject, <span>true</span><span> );</span>
Workaround.SetLastViewDirection(Vector3d.XAxis);
<span>//... Usual Explode of the entity</span>
Here is the C++ code snippet :
typedef <span>void</span><span> (*drawingPromoterAndIniter)</span>
(AcDbDatabase* pDb, <span>bool</span><span> bUseCurrentViewInfo);</span>
typedef <span>void</span><span> (*setLastViewDir)(AcGeVector3d direction);</span>
acdbSetHostApplicationServices(&gDumpDwgHostApp);
CString testFilePath = <span>"D:\\Temp\\wall.dwg"</span><span> ;</span>
<span>long</span><span> lcid = 0x00000409; <span>// English</span><span> </span></span>
acdbValidateSetup(lcid);
<span>bool</span><span> isLoaded = acrxLoadModule(</span>
_T(<span>"C:\\Program Files\\Autodesk\\RealDWG 2016\\AecBase.dbx"</span><span> ), 0);</span>
HMODULE hModule=GetModuleHandle(_T(<span>"AecBase.dbx"</span><span> ));</span>
<span>int</span><span> ordinal = 897;</span>
auto drawingPromoterFunc =
(drawingPromoterAndIniter)GetProcAddress(hModule, (LPCSTR) ordinal);
<span>if</span><span> (drawingPromoterFunc == nullptr) </span>
<span>{</span>
AfxMessageBox(_T(<span>"Error ! function not in AecBase.dbx !!"</span><span> ));</span>
<span>return</span><span> 1;</span>
<span>}</span>
ordinal = 1202; <span>// 2016</span><span> </span>
<span>//ordinal = 1204; //2015</span><span> </span>
auto setLastViewDirFunc =
(setLastViewDir)GetProcAddress(hModule, (LPCSTR) ordinal);
<span>if</span><span> (setLastViewDirFunc == nullptr) </span>
<span>{</span>
AfxMessageBox(_T(<span>"Error ! function not in AecBase.dbx !!"</span><span> ));</span>
<span>return</span><span> 1;</span>
<span>}</span>
AcDbDatabase *pDb = <span>new</span><span> AcDbDatabase(Adesk::kFalse);</span>
<span>if</span><span> (pDb == NULL)</span>
<span>return</span><span> 1;</span>
Acad::ErrorStatus es = Acad::eOk;
es = pDb->readDwgFile(testFilePath);
acdbHostApplicationServices()->setWorkingDatabase(pDb);
acdbResolveCurrentXRefs(pDb);
drawingPromoterFunc(pDb, <span>false</span><span> );</span>
setLastViewDirFunc(AcGeVector3d::kXAxis);
<span>//... Usual Explode of the entity</span>

Leave a Reply to WbmkCancel reply