Parasolid
The Visualize-Parasolid bridge supports a connection between Parasolid entities and their corresponding representation in the Visualize scene graph. This interface facilitates visualization of Parasolid models, as well as creation and editing of Parasolid entities. If you haven’t done so already, you should read through the Programming Guide page on the component hierarchy, as the Parasolid interface is based on it.
All Parasolid-related classes are members of the HPS::Parasolid
container class. Supported platforms are listed in the release notes compatibility table. Developers can choose to work with either C++ or C# (C# is Windows-only).
Convergent Modeling is available in the Visualize-Parasolid bridge, supporting both solid B-rep operations and faceted geometry operations in a single modelling component. It is available with Parasolid version 28.1 or higher.
NOTE: HOOPS Visualize automatically initializes Parasolid if it detects that the Parasolid integration is present. It will also shut down Parasolid at the end of the application, and restart it as needed. Your application should not initialize or shutdown Parasolid if it is using the Parasolid integration. If you need to use Parasolid after Visualize is finished, you need to restart the session.
Prerequisites
Steps for loading Parasolid models are delineated below:
Step 1: Set Up Parasolid
In order to use the HPS::Parasolid
functionality, you must download the Parasolid package from its developer and include it in your environment path. The supported version of Parasolid is noted in the release notes. The Parasolid runtime library file must be distributed with your application.
Platform |
Required file |
---|---|
Linux |
libpskernel.so |
OS X |
libpskernel.dylib |
Windows |
pskernel.dll - pskernel_net.dll also required for C# apps |
Step 2: Include Parasolid Header
To utilize the Parasolid importer, you need to include sprk_parasolid.h in your source.
Step 3: Set Schema Directory Location
Many Parasolid files depend on a schema. If a schema is required but the importer cannot find the schema directory, the import will fail. Visualize will check the following locations, in order, for the schema directory:
The schema directory set by your application (see code snippet below)
The
P_SCHEMA
environment variableThe ./schema directory
The schema directory is set on the HPS::World
object. World objects are discussed in this section.
world.SetParasolidSchemaDirectory("path/to/directory");
world.SetParasolidSchemaDirectory("path/to/directory");
Step 4: Link Against Parasolid (Optional)
If you are only planning to use the HPS::Parasolid
classes, then you can skip this step. However, if you have a need to connect to the Parasolid API directly, you also need to set your compiler to link against the Parasolid library and include the Parasolid header files in your source.
Importing
Visualize’s support for importing of Parasolid files is consistent with other supported file types. The main difference is the use of functions from the HPS::Parasolid
container class. Like other file I/O operations, Parasolid models are loaded asynchronously, so be sure to call ImportNotifier::Wait
before operating on your model.
HPS::Parasolid::ImportOptionsKit iok = Parasolid::ImportOptionsKit::GetDefault();
iok.SetFormat(HPS::Parasolid::Format::Text);
HPS::Parasolid::ImportNotifier notifier = HPS::Parasolid::File::Import(filename, iok);
notifier.Wait(); // wait for this model to finish loading
HPS.Parasolid.ImportOptionsKit iok = HPS.Parasolid.ImportOptionsKit.GetDefault();
iok.SetFormat(HPS.Parasolid.Format.Text);
HPS.Parasolid.ImportNotifier notifier = HPS.Parasolid.File.Import(filename, iok);
notifier.Wait(); // wait for this model to finish loading
After HPS::ImportNotifier::Wait
returns, the model is fully loaded. Note that setting the file format is mandatory and Visualize will likely throw an exception if this field is set incorrectly. By convention, Parasolid text files will have a .X_T extension, whereas binary files have a .X_B extension.
Import Options
Various import options are available when loading Parasolid models. These options enable you to set the file type, tessellation options, behavior directives, and whether user fields are imported. All options are set on the import options kit. Note that the tessellation fields require options kits of their own.
// setting up the facet tessellation kit
HPS::Parasolid::FacetTessellationKit ftk;
ftk.SetNormals(true);
ftk.SetFacetSize(1.0, 3.0, 10);
// setting up the line tessellation kit
HPS::Parasolid::LineTessellationKit ltk;
ltk.SetEdges(true, true);
ltk.SetIgnoreCriteria(false);
// setting the tessellation kits on the import options kit
HPS::Parasolid::ImportOptionsKit iok;
iok.SetCompoundBodyBehavior(Parasolid::CompoundBodyBehavior::Split);
iok.SetFacetTessellation(ftk);
iok.SetLineTessellation(ltk);
iok.SetFormat(Parasolid::Format::Text);
// setting up the facet tessellation kit
HPS.Parasolid.FacetTessellationKit ftk = new HPS.Parasolid.FacetTessellationKit();
ftk.SetNormals(true);
ftk.SetFacetSize(1.0, 3.0, 10);
// setting up the line tessellation kit
HPS.Parasolid.LineTessellationKit ltk = new HPS.Parasolid.LineTessellationKit();
ltk.SetEdges(true, true);
ltk.SetIgnoreCriteria(false);
// setting the tessellation kits on the import options kit
HPS.Parasolid.ImportOptionsKit iok = Parasolid.ImportOptionsKit.GetDefault();
iok.SetCompoundBodyBehavior(HPS.Parasolid.CompoundBodyBehavior.Split);
iok.SetFacetTessellation(ftk);
iok.SetLineTessellation(ltk);
iok.SetFormat(HPS.Parasolid.Format.Text);
The options kits in the code snippet above take numerical values for their tessellation parameters. These values are expected to be in the model’s units. While this gives you fine control over how the model is tessellated, it requires you to make some precalculations to determine the size of the model and what makes sense for values. Using arbitrary values could result in very long load times as Visualize tries to create precise tessellation.
For this reason, there is an alternative way to specify tessellation. The SetTessellationLevel
function will accept an enum value ranging from “extra low” to “extra high”, which instructs Visualize to automatically calculate an appropriate tessellation value based on the model’s extents. When this method is used, any other tolerance option set on the facet kit gets ignored (these are the options set through SetChordTolerance
, SetSurfacePlaneTolerance
, SetFacetPlaneTolerance
). This method is only available for facet tessellation.
ftk.SetTessellationLevel(HPS::Parasolid::TessellationLevel::Medium);
ftk.SetTessellationLevel(HPS.Parasolid.TessellationLevel.Medium);
Importing Other File Formats Into a Parasolid Session
If you are a HOOPS Exchange licensee, you may also import models from other file formats into an active Parasolid session using the HPS::ExchangeParasolid
importer. This importer will load the geometry into Parasolid and use it to tessellate the model. It will also preserve PMI and capture information which Parasolid doesn’t support natively. The importer creates HPS::Exchange::Component
objects for the PMI and captures. Everything else will be translated to Parasolid entities behind the scenes, which will be represented as HPS::Parasolid::Component
objects. You can reference both object types through the normal component interface. This includes accessing the underlying native data. For example, you can access Parasolid data directly through the Parasolid components and you can access HOOPS Exchange data (B-rep, PMI, etc.) directly through the Exchange components.
Loading the file in this way is done similarly to loading other file types:
HPS::Exchange::ImportOptionsKit iok = Exchange::ImportOptionsKit::GetDefault();
HPS::ExchangeParasolid::ImportNotifier notifier =
HPS::ExchangeParasolid::File::Import(filename,
iok,
HPS::Exchange::TranslationOptionsKit::GetDefault(),
HPS::Parasolid::FacetTessellationKit::GetDefault(),
HPS::Parasolid::LineTessellationKit::GetDefault());
notifier.Wait(); // wait for this model to finish loading
// get the CAD model object
HPS::CADModel cad_model = notifier.GetCADModel();
// get Exchange components
HPS::ComponentArray pmis = cad_model.GetAllSubcomponents(HPS::Component::ComponentType::ExchangePMIMask);
HPS::Exchange::Component pmi_component(pmis[0]);
A3DEntity* exchange_pmi_entity = pmi_component.GetExchangeEntity();
// get Parasolid components
HPS::ComponentArray faces = cad_model.GetAllSubcomponents(HPS::Component::ComponentType::ParasolidTopoFace);
HPS::Parasolid::Component face_component(faces[0]);
PK_ENTITY_t parasolid_face_entity = face_component.GetParasolidEntity();
HPS.Exchange.ImportOptionsKit iok = Exchange.ImportOptionsKit.GetDefault();
HPS.ExchangeParasolid.ImportNotifier notifier = HPS.ExchangeParasolid.File.Import(filename, iok,
HPS.Exchange.TranslationOptionsKit.GetDefault(),
HPS.Parasolid.FacetTessellationKit.GetDefault(),
HPS.Parasolid.LineTessellationKit.GetDefault());
notifier.Wait(); // wait for this model to finish loading
// get the CAD model object
HPS.Exchange.CADModel cad_model = notifier.GetCADModel();
// get Exchange components
HPS.Component[] pmis = cad_model.GetAllSubcomponents(HPS.Component.ComponentType.ExchangePMIMask);
HPS.Exchange.Component pmi_component = new HPS.Exchange.Component(pmis[0]);
IntPtr exchange_pmi_entity = pmi_component.GetExchangeEntity();
// get Parasolid components
HPS.Component[] faces = cad_model.GetAllSubcomponents(HPS.Component.ComponentType.ParasolidTopoFace);
HPS.Parasolid.Component face_component = new HPS.Parasolid.Component(faces[0]);
int parasolid_face_entity = face_component.GetParasolidEntity();
Getting a Reference to Subcomponents
The Parasolid importer uses the same component hierarchy structure used by other Visualize model importers. It is very important to understand the component hierarchy before continuing. The HPS::CADModel
object is the root of the component structure and is available from the import notifier. The subcomponents are then available from the CAD model object.
HPS::Parasolid::ImportNotifier notifier = HPS::Parasolid::File::Import(filename, iok);
notifier.Wait(); // wait for this model to finish loading
// get the CAD model object
HPS::Parasolid::CADModel cadModel = notifier.GetCADModel();
// get the top-level assemblies
HPS::ComponentArray assemblies = cadModel.GetSubcomponents();
HPS.Parasolid.ImportOptionsKit iok = HPS.Parasolid.ImportOptionsKit.GetDefault();
iok.SetFormat(HPS.Parasolid.Format.Text);
HPS.Parasolid.ImportNotifier notifier = HPS.Parasolid.File.Import(filename, iok);
notifier.Wait(); // wait for this model to finish loading
// get the CAD model object
HPS.Parasolid.CADModel cadModel = notifier.GetCADModel();
// get the top-level assemblies
HPS.Component[] assemblies = cadModel.GetSubcomponents();
Tessellating
When Visualize reads a Parasolid model into memory, the model is tessellated and the definition is retained in the component hierarchy structure. Because the definition is retained, Visualize is able to retessellate the model at a later time using different tessellation parameters and without rereading the file. To retessellate, simply set up new tessellation kits and call Tessellate
on the target component:
HPS::Parasolid::FacetTessellationKit ftk;
ftk.SetFacetPlaneTolerance(0, 1.3).SetChordTolerance(0, 0, 1.3);
HPS::Parasolid::LineTessellationKit ltk;
ltk = Parasolid::LineTessellationKit::GetDefault();
ltk.SetChordTolerance(0, 0, 1.3);
component.Tessellate(ftk, ltk);
// the next update yields a retessellated model
myCanvas.Update();
HPS.Parasolid.FacetTessellationKit ftk = new HPS.Parasolid.FacetTessellationKit();
ftk.SetFacetPlaneTolerance(7.3, 1.0).SetChordTolerance(5.0, 5.3, 1.0);
HPS.Parasolid.LineTessellationKit ltk = new HPS.Parasolid.LineTessellationKit();
ltk = Parasolid.LineTessellationKit.GetDefault();
ltk.SetChordTolerance(0, 0, 1.3);
component.Tessellate(ftk, ltk);
// the next update yields a retessellated model
myCanvas.Update();
Retessellating a component will also retessellate all subcomponents. Note that Tessellate
can only be called on either an assembly or body entity. If you need to retessellate the entire model, you can either reload the model or call HPS::CADModel::GetSubcomponents
and retessellate each component individually.
IMPORTANT: If you make modifications to a model using the Parasolid API you must call Tessellate
in order for Visualize to receive the updated model.
Attaching the Parasolid Model to Your Scene Graph
In order to attach the imported Parasolid model to the Visualize scene graph, you must use a view hierarchy. The HPS::CADModel
provides a default view which you obtain in the following way:
HPS::Canvas myCanvas = HPS::Factory::CreateCanvas(myWindowKey);
// ...
// get a reference to the model view
HPS::View view = notifier.GetCADModel().ActivateDefaultCapture();
// attach the view to the canvas
myCanvas.AttachViewAsLayout(view);
HPS.Canvas myCanvas = HPS.Factory.CreateCanvas(myWindowKey);
// ...
// get a reference to the model view
HPS.View view = notifier.GetCADModel().ActivateDefaultCapture();
// attach the view to the canvas
myCanvas.AttachViewAsLayout(view);
When calling HPS::CADModel::ActivateDefaultCapture
, a FitWorld
is automatically performed, which centralizes the model in the window.
Once you call HPS::Canvas::AttachViewAsLayout
, the model becomes part of the main scene graph and will be rendered at the next update.
Handling Metadata
Metadata is additional non-geometric information that is associated with a HPS::Parasolid::Component
. Each piece of metadata is a name-value pair, and the values can be strings, integers, doubles, or booleans. Any HPS::Parasolid::Component
can have metadata associated with it, although some types of metadata are only available on certain types of components. A list of metadata is as follows:
Name |
|
The name of the Parasolid entity associated with the component. If the entity does not have a name, a default name will be generated. The default name is in the form of |
Identifier |
|
Returns whether the Parasolid entity associated with the component is a void region. This is only valid if the component is of type |
IsRegionVoid |
|
Returns the identifier of the Parasolid entity associated with the component. |
Filename |
|
Name of the file imported. This is only valid from the |
FileFormat |
|
Format of the file imported. This is only valid from the |
ImportTime |
``DoubleMetadata |
Time taken to import the Parasolid file into memory, in milliseconds. This is only valid from the |
ParseTime |
|
Time taken to parse the Parasolid information into a scene graph, in milliseconds. This is only valid from the |
While metadata with any name can be set in a Parasolid model, Visualize is only able to retrieve metadata with names that are in the table above. If you need to retrieve other metadata, you need to use the Parasolid API.
Metadata can be embedded with any HPS::Parasolid::Component
. The following example demonstrates how to get metadata associated with a component:
Metadata metadata = cadModel.GetMetadata("Filename");
// "Filename" is always returned as a string, so we use a StringMetadata object
StringMetadata stringMetadata(metadata);
// getting the value of the "Filename" metadata
UTF8 filename_value = stringMetadata.GetValue();
HPS.Metadata metadata = cadModel.GetMetadata("Filename");
// "Filename" is always returned as a string, so we use a StringMetadata object
HPS.StringMetadata stringMetadata = new HPS.StringMetadata(metadata);
// getting the value of the "Filename" metadata
String filename_value = stringMetadata.GetValue();
Data Mapping
As mentioned on the component hierarchy page, Visualize associates each Parasolid Component object with native Parasolid entities. You can retrieve the underlying Parasolid entity with a call to GetParasolidEntity
. A ParasolidEntity
is equal to a PK_ENTITY_t
.
The code snippet below demonstrates how to get an entity’s Parasolid ID from a Visualize key:
// get Visualize-Parasolid component interface object for corresponding Visualize key
HPS::Component myComponent = modelFile.GetComponentFromKey(hpsKey);
// 'parasolidEntity' == PK_ENTITY_t
ParasolidEntity parasolidEntity = myComponent.GetParasolidEntity();
// test if the object type is a Parasolid assembly
// [see Component reference manual page for other Parasolid types]
if (component.GetComponentType() == HPS::Component::ComponentType::ParasolidAssembly)
{
// do something with this object
}
// gets the Visualize keys associated with the Component
KeyArray keys = component.GetKeys();
// at this point, you can use the returned entity to directly query model information from the Parasolid API
// get Visualize-Parasolid component interface object for corresponding Visualize key
HPS.Component myComponent = modelFile.GetComponentFromKey(hpsKey);
// 'parasolidEntity' == PK_ENTITY_t
ParasolidEntity parasolidEntity = myComponent.GetParasolidEntity();
// test if the object type is a Parasolid assembly
// [see Component reference manual page for other Parasolid types]
if (component.GetComponentType() == HPS.Component.ComponentType.ParasolidAssembly)
{
// do something with this object
}
// gets the keys associated with the Component
KeyArray keys = component.GetKeys();
// at this point, you can use the returned entity to directly query model information from the Parasolid API
See the HPS::Component
reference manual entry for a list of all the component enums.
Manipulating Entities at Runtime
Entity Creation
While Parasolid models may sometimes be loaded from a file, it is of course common for modeling operations to create entities dynamically. If you have a need to start from scratch (an empty model), you need to create all entities beginning with the CAD model. The HPS::Parasolid::CADModel
object is created using a factory method:
HPS::Parasolid::CADModel cadModel = HPS::Parasolid::Factory::CreateCADModel();
HPS.Parasolid.CADModel cadModel = HPS.Parasolid.Factory.CreateCADModel();
After you have the HPS::Parasolid::CADModel
object, new Parasolid kernel entities would be created using the Parasolid API, then attached to the model post-creation. The following example demonstrates how you would add a solid block to a model’s root entity at runtime, and then access the keys of the corresponding Visualize scene-graph entities which provide the visual representation:
PK_BODY_t solid_body = PK_ENTITY_null;
PK_BODY_create_solid_block(0.05, 0.05, 0.05, nullptr, &solid_body);
// add solid block to root entity
HPS::Parasolid::Component myNewComponent = cadModel.AddEntity(
solid_body, HPS::Parasolid::FacetTessellationKit::GetDefault(), HPS::Parasolid::LineTessellationKit::GetDefault());
// check to make sure it was inserted correctly
if (myNewComponent.GetComponentType() != HPS::Component::ComponentType::ParasolidTopoBody)
std::cout << "if you get here, something went wrong";
// get the underlying Visualize keys which represent this component
KeyArray componentKeys = myNewComponent.GetKeys();
PK.BODY_t solid_body = PK.ENTITY_t.@null;
PK.BODY.create_solid_block(0.05, 0.05, 0.05, null, &solid_body);
// add solid block to root entity
HPS.Component myNewComponent =
cadModel.AddEntity(solid_body, HPS.Parasolid.FacetTessellationKit.GetDefault(),
HPS.Parasolid.LineTessellationKit.GetDefault());
// check to make sure it was inserted correctly
if (myNewComponent.GetComponentType() != HPS.Component.ComponentType.ParasolidTopoBody)
{
// if you get here, something went wrong
}
// get the underlying Visualize keys which represent this component
Key[] componentKeys = myNewComponent.GetKeys();
The new solid block is ready to be rendered during the next update.
Entity Modification
A typical flow for entity modification would begin with the user selecting on a Visualize scene-graph object. Given a Visualize key, you would obtain the HPS::Component
object and the Parasolid entity ID as previously demonstrated. After modifying the entity using the Parasolid API, call HPS::Parasolid::Component::Tessellate
to update the Visualize scene-graph representation.
Entity Deletion
To delete a component, call HPS::Component::Delete
. Deleting a component will also delete any subcomponents, along with all associated Visualize scene-graph segments and graphical primitives. The HPS::Component::Delete
function will also delete the underlying Parasolid entity.
Exporting
Exporting files with the Visualize-Parasolid interface is possible if the associated HPS::Parasolid::CADModel
was obtained through a Parasolid import. The export process is synchronous and follows a pattern similar to other file exporters.
The HPS::Parasolid::ExportOptionsKit
has two options:
File format - you can choose between binary, neutral binary, or text
User data - this is a flag indicating whether or not user data should be included in the export
HPS::Parasolid::ExportOptionsKit export_options = HPS::Parasolid::ExportOptionsKit::GetDefault();
export_options.SetFormat(HPS::Parasolid::Format::Text).SetUserFields(true);
HPS::Parasolid::File::Export(cadModel, outfile, export_options);
HPS.Parasolid.ExportOptionsKit export_options = HPS.Parasolid.ExportOptionsKit.GetDefault();
export_options.SetFormat(HPS.Parasolid.Format.Text).SetUserFields(true);
HPS.Parasolid.File.Export(cadModel, outfile, export_options);
Warnings and Exceptions
The importer will issue a warning or throw an exception if it detects a condition that doesn’t make sense or cannot recover from. For example, if you specify a maximum value that is smaller than a minimum value, a warning is issued. Or, if you specify the file type to be text, but the imported file is actually a binary file, Visualize will throw an HPS::IOException
. Your code should be prepared to handle these occurrences so that it can take steps to recover.