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.
HPS::DWG::ImportNotifier notifier = HPS::DWG::File::Import(filename, HPS::DWG::ImportOptionsKit());
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();
HPS.DWG.ImportNotifier notifier = HPS.DWG.File.Import(filename, new HPS.DWG.ImportOptionsKit());
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:
DWGModelFile
- The top of the hierarchy. Represents anAcDbDatabase
object in RealDWG.DWGBlockTable
- The block table. This is always found directly under theDWGModelFile
. Represents anAcDbBlockTable
object in RealDWG.DWGLayerTable
- The layer table. This is always found directly under theDWGModelFile
. Represents anAcDbLayerTable
object in RealDWG.DWGLayout
- A DWG Layout. Found under theDWGBlockTable
. Represents anAcDbLayout
object in RealDWG.DWGBlockTableRecord
- A record inside the Block Table. Found under theDWGBlockTable
. Represents anAcDbBlockTableRecord
object in RealDWG.DWGLayer
- A layer. Found under theDWGLayerTable
. Represents anAcDbLayer
object in RealDWG.DWGEntity
- A geometric entity. Found under aDWGLayout
or aDWGBlockTableRecord
, or under anotherDWGEntity
. Represents anAcDbEntity
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 callingActivateDefaultCapture
.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.