Loading DWG models


HOOPS Visualize is able to load DWG models using the RealDWG integration. You must be a RealDWG licensee in order to use the interface. DWG is only available on Windows platforms. See the release notes for platform-specific information. DXF files are also supported.

The Sprockets DWG module is used to read DWG and DXF files through the Autodesk's RealDWG API. Once the file has been imported, the integration creates a component tree with support for a model browser. The user is then able to query the model either through the component structure, the HPS scene graph, or directly through RealDWG. Data mapping is achieved through the HPS::DWG::Component class, which lets the user access the AcDbObjectId object associated with each component, which in turn can be used with the RealDWG API.

Prerequisites

RealDWG is initialized after the HPS::World constructor has been called, at which point you can make function calls to RealDWG. RealDWG becomes uninitialized during the Visualize shutdown procedure. After the shutdown begins, you can no longer make calls to RealDWG.

The steps for loading DWG/DXF models are delineated below:

Step 1: Get RealDWG

In order to use the RealDWG functionality, you must install the native RealDWG libraries. If you have licensed RealDWG through Tech Soft 3D, you may download the package from our Developer Zone. The supported version of the RealDWG SDK is noted in the release notes. The RealDWG DLLs must be distributed with your application.

Step 2: Include RealDWG header

To utilize the RealDWG importer, you need to include sprk_dwg.h in your source.

Step 3: Add RealDWG to your PATH

In order to use DWG, it's necessary to add the RealDWG directory to your machine's PATH. If you're using RealDWG Object Enablers (optional), then also make sure that the directory containing the DBX files for the Object Enablers is located in your PATH prior to initializing HPS.

Import example

To import RealDWG files, HOOPS Visualize uses the same basic framework as it does for other file types. The main difference is the use of functions from the HPS::DWG container class.

notifier.Wait();
// get the status of the import
HPS::IOResult result = notifier.Status();
if (result == HPS::IOResult::Success)
{
// file loading successfully
modelFile = notifier.GetCADModel();
myCanvas.AttachViewAsLayout(myView);
// alternatively, if you already have a View object, you can simply
// get the Model and attach it directly:
HPS::Model model = modelFile.GetModel();
myView.AttachModel(model);
}
// you can cancel the import by calling:
notifier.Cancel();
notifier.Wait();
// get the status of the import
HPS.IOResult result = notifier.Status();
if (result == HPS.IOResult.Success)
{
// file loading successfully
modelFile = notifier.GetCADModel();
modelFile.ActivateDefaultCapture();
myCanvas.AttachViewAsLayout(myView);
// alternatively, if you already have a View object, you can simply
// get the Model and attach it directly:
HPS.Model model = modelFile.GetModel();
myView.AttachModel(model);
}
// you can cancel the import by calling:
notifier.Cancel();



The DWG import options can have a significant effect on the load time of certain models:

  • SetMaxTessellationDeviation - This option specifies how finely to tessellate shells and meshes imported through DWG. Smaller numbers create more detailed and complex geometry.
  • SetUnreferencedRecords - This option specifies whether to import parts of the drawings which are present, but not referenced in the model. Turning this off can result in a faster import.

If your model contains textures, and those textures are stored in an unusual location, you can specify the texture directory in the import options kit using SetTextureDirectories.

DWG Components

The Sprocket DWG module builds a component structure as it imports a DWG file. DWG components can be one of the following types:

  1. DWGModelFile - The top of the hierarchy. Represents an AcDbDatabase object in RealDWG.
  2. DWGBlockTable - The block table. This is always found directly under the DWGModelFile. Represents an AcDbBlockTable object in RealDWG.
  3. DWGLayerTable - The layer table. This is always found directly under the DWGModelFile. Represents an AcDbLayerTable object in RealDWG.
  4. DWGLayout - A DWG Layout. Found under the DWGBlockTable. Represents an AcDbLayout object in RealDWG.
  5. DWGBlockTableRecord - A record inside the Block Table. Found under the DWGBlockTable. Represents an AcDbBlockTableRecord object in RealDWG.
  6. DWGLayer - A layer. Found under the DWGLayerTable. Represents an AcDbLayer object in RealDWG.
  7. DWGEntity - A geometric entity. Found under a DWGLayout or a DWGBlockTableRecord, or under another DWGEntity. Represents an AcDbEntity object in RealDWG.

You can ask a component what type it is by calling the Component::GetComponentType function. All DWG components have the DWGComponentMask set on them. Therefore, you can tell if a component is a DWGComponent because Component::HasComponentType(ComponentType::DWGComponentMask) will return true.

Working with layers

As an example of how to use the component type to operate on an object, we'll look at a code sample that deals with layers. Once you have identified that a component you are interested in is of type DWGLayer, you can build a DWG::Layer object with it. With a layer object, you can enable and disable visibility, or return the visibility status. Below is an example of doing this:

auto tables = modelFile.GetSubcomponents();
for (auto const & table : tables)
{
// access the layer table
if (table.GetComponentType() == HPS::Component::ComponentType::DWGLayerTable)
{
auto layers = table.GetSubcomponents();
for (auto const & one_layer : layers)
{
// find the correct layer by name
HPS::StringMetadata layer_name = one_layer.GetMetadata("Name");
if (layer_name.GetValue() == "0")
{
// toggle its visibility
HPS::DWG::Layer layer(one_layer);
if (layer.IsOn())
layer.TurnOff();
else
layer.TurnOn();
break;
}
}
}
}
Component[] tables = modelFile.GetSubcomponents();
for (int i = 0; i < tables.Length; i++)
{
// access the layer table
if (tables[i].GetComponentType() == HPS.Component.ComponentType.DWGLayerTable)
{
Component[] layers = tables[i].GetSubcomponents();
for (int j = 0; j < layers.Length; j++)
{
// find the correct layer by name
HPS.StringMetadata layer_name = new HPS.StringMetadata(layers[j].GetMetadata("Name"));
if (layer_name.GetValue() == "0")
{
// toggle its visibility
HPS.DWG.Layer layer = new HPS.DWG.Layer(layers[j]);
if (layer.IsOn())
layer.TurnOff();
else
layer.TurnOn();
break;
}
}
}
}



The DWG CAD Model

The HPS::DWG::CADModel class derives from HPS::CADModel. In addition to the functions available in HPS::CADModel, the HPS::DWG::CADModel class has access to these three extra functions:

  • ActivateDefaultLayout - This function activates the default Layout. It is equivalent to calling ActivateDefaultCapture.
  • GetDWGDatabase - Returns the DWGDatabase pointer. The user can request the database to use it in RealDWG calls. The user should NEVER delete a database pointer it gets from this function.
  • GetAllLayouts - Returns a list of layouts associated with this CAD model.

Here is an example of how to activate the default layout:

HPS::DWG::CADModel cadModel = (HPS::DWG::CADModel) modelFile;
myView = cadModel.ActivateDefaultLayout();
myCanvas = HPS::Factory::CreateCanvas(myWindowKey);
myCanvas.AttachViewAsLayout(myView);
HPS.DWG.CADModel cadModel = (HPS.DWG.CADModel) modelFile;
myView = cadModel.ActivateDefaultLayout();
myCanvas = HPS.Factory.CreateCanvas(myWindowKey);
myCanvas.AttachViewAsLayout(myView);



Getting an array of all layouts from the CAD model may be done in the following way:

HPS::DWG::LayoutArray layouts = cadModel.GetAllLayouts();
for (auto & layout : layouts)
{
HPS::StringMetadata name = layout.GetMetadata("Name");
if (name.GetValue() == HPS::UTF8("PDF"))
{
HPS::View new_view = layout.Activate();
myCanvas.AttachViewAsLayout(myView);
}
}
HPS.DWG.Layout[] layouts = cadModel.GetAllLayouts();
for (int i = 0; i < layouts.Length; i++)
{
HPS.StringMetadata name = new HPS.StringMetadata(layouts[i].GetMetadata("Name"));
if (name.GetValue().Equals("PDF"))
{
HPS.View new_view = layouts[i].Activate();
myCanvas.AttachViewAsLayout(myView);
}
}



Here is an example of how to get a DWGObjectID from the layout object, and using it with RealDWG:

// get the object id
HPS::DWG::Layout layout = cad_model.GetAllLayouts()[0];
DWGObjectID * object_id = layout.GetDWGObjectID();
AcDbObjectId * acdb_object_id = reinterpret_cast<AcDbObjectId *>(object_id);
// open the object
AcDbObject * object = nullptr;
acdbOpenObject(object, *acdb_object_id, AcDb::kForRead);
// ...
// do something with it
// ...
// cleanup
object->close();

Acquiring a reference to the DWG database

This is an example of getting and using the DWG database from a CAD model object:

//get the database pointer from the CAD Model
DWGDatabase * database = cad_model.GetDWGDatabase();
AcDbDatabase * acdb_database = reinterpret_cast<AcDbDatabase *>(database);
// Now you can use it to access RealDWG
ACHAR * dimension_block;
acdb_database->getDimblk(dimension_block);
acdbFree(dimension_block);

WARNING: You should never try to delete a RealDWG database pointer!

Metadata

Metadata is additional non-geometric information that is associated with an HPS::DWG::Component. Each piece of metadata is a name-value pair, and the values are always returned as HPS::StringMetadata.

You can ask for the following metadata by calling GetMetadata from any HPS::DWG::Component:

  • "Name" - Either returns the name of the component, or if the component has no name returns a string formatted as follows: <RealDWG Entity Type> <RealDWG Handle>. Example: AcDbPolyline 1AB45.
  • "Handle" - Returns the hexadecimal handle of the entity associated with the component.
  • "Layer" - Returns the name of the layer associated to this component, if any.
  • "Units" - Returns the units used in the drawing. Only available from the DWG CAD Model.

Limitations

Multiline text

When multiline text is encountered, RealDWG explodes it into fragments. These fragments are not guaranteed to match those produced by AutoCAD. (Example: in a two line multi-line text, the last word of the first line might actually appear as the first word of the second line).

Line patterns containing glyphs and shapes

Line patterns containing glyphs and SHX shapes are not supported.