Home > User Guide > Applications of ACIS Assembly Modeling
Converting ACIS Assembly Models into Customer Assemblies
Some ACIS customers will wish to develop their own assembly modeling systems rather than use the assembly modeling functionality provided with ACIS. One of the goals of ACIS Assembly Modeling is to provide, through ASAT, a standard format which can be used by the ACIS customers to exchange assembly models with other such customers, with customers who are using ACIS’ assembly modeling functionality, and (through the use of Spatial’s InterOp translators) with other modeling formats.
This section describes, and illustrates with corresponding example code, what such customers should do in order to take advantage of the ASAT format.
Reading and Writing an Assembly
The general strategy for such a customer to write an assembly that is stored in memory in the customer’s format as an ASAT file is to first create an equivalent, temporary ACIS Assembly Modeling assembly in memory, then to use asmi_save_model_list() to write the ACIS Assembly Modeling assembly into an ASAT (or ASAB) file.
The strategy for reading ASAT into the customer's application is the inverse; first the customer should call asmi_restore_model_list() to read the ASAT file into memory in ACIS Assembly Modeling format then the customer should construct a customer assembly by querying the structure of the ACIS Assembly Modeling assembly.
Assembly Transcription
The ACIS Assembly Modeling system was designed to avoid imposing artificial limitations on the way that customers might wish to organize their assembly models. Because of this generality, the ASAT format may admit model structures that are more general than those of the customer system; the goal is that no customer should have to change the structure of their assemblies when writing their models out as ASAT and then restoring them. This means that the elements of a customer assembly being transcribed into an ACIS Assembly Modeling assembly (for writing to ASAT) should generally be one-to-one with the corresponding elements of the ACIS Assembly Modeling assembly. Thus, the structure of the assembly will not need to be changed for a typical customer assembly modeling system.
When transcribing from an ACIS Assembly Modeling assembly (read in from ASAT) into a customer assembly, however, elements of the ACIS Assembly Modeling assembly might not have corresponding constructs in the customer's assembly modeling system. In such cases, the customer will need to construct an equivalent assembly in the customer's system; this equivalent assembly will in general have more components. Some examples of constructs present in ACIS Assembly Modeling that might need to be emulated by less general customer constructs are given below. Note that in the discussion, we refer to the customer equivalent of an asm_model object as a "node", and the customer equivalent of an asm_model_ref object as an "instance".
Multiple Primary Models Per File
Customers should not assume that an ASAT file has only one primary model.
Note: A primary model is a model that is explicitly specified when the ASAT file is written.
An ASAT file will contain by value (monolithic mode) or by reference (atomic mode) all primary models and all their sub-models. When a customer reads a file that has multiple primary models, the customer can simply make each primary model the root model of its own assembly. Note that a primary model can be instanced within another primary model in a file (that is, a primary model can be a sub-model of another primary model in the same file). Hence, it can share sub-models with other primary models, or it can be the root model of a completely separate model tree.
Assembly-level Entities
An ACIS Assembly Modeling assembly model (that is, an asm_model object which has an assembly, as opposed to an ACIS Assembly Modeling part model, which does not have an assembly) can also contain B-Rep entities, specifically, bodies. This functionality is provided to allow customers to represent assembly level-features between instances, for example, a "weld". If the customer system requires that all B-Rep data be owned by part nodes, then the customer will need to represent an asm_model object which has both an assembly and B-Rep entities by two customer nodes; an assembly node containing instances corresponding to the asm_model's model references and an instance of a part node containing the B-Rep data.
Component Properties vs Instance Properties
Most assembly modeling systems allow properties (such as color, suppression, and naming) to be applied to instances. The limitation of this scheme is that it does not admit applying a property to an instance of an instance. For example, if one has a simple cart model with front and rear instances of an axle assembly, then with instance decoration one can color both left wheels red by applying a "red" property to the left-wheel instance in the axle assembly. In order to color only the front-left wheel red, however, one would need two different axle assembly models: one with "red" applied to the left-wheel instance (for the front axle assembly instance) and one without properties applied (for the rear axle assembly instance).
An ACIS Assembly Modeling assembly has a construct which allows component properties (for example, "red" applied to the front-left wheel) to be specified without requiring that new asm_model objects be created. The basic strategy for a customer whose assembly modeling system does not support component properties will be described below, along with a sample C++ implementation.
Examples for Converting Customer Assemblies and ACIS Modeling Assembly Assemblies
We provide four example implementations for converting between customer assemblies and ACIS Assembly Modeling assemblies: reading and writing examples for customer systems which do and do not support component decoration. These four examples are used to implement the scheme extensions (asm-example:import) and (asm-example:export); the import and export extensions each have two "conversion types", which determine whether or not the customer's system being emulated admits component properties.
All four examples assume that the ASAT file is monolithic, that is, it does not depend on models contained in other files. The example code is contained in the file asm_example_scm.cpp.
Note: The example code is segregated between "ACIS" code and "Customer" code. The "Customer Code" functions are intended to be operations in the customer's assembly modeling system using customer objects. Even though the functions are implemented using ACIS Assembly Modeling calls, the interface between "ACIS Code" and "Customer Code" treats these objects as void* pointers to indicate that they are actually customer objects. The "Customer Code" sections of the example are indicated by "Customer Implementation Begin" and "Customer Implementation End" text markers.
Example 1: Reading an ASAT File into a Customer Format Supporting Component Decoration
The example code is implemented as type "1" in the function import_asat_to_customer_assembly(). The basic strategy in this conversion routine is to directly transcribe the "folded" assembly tree (that is, model-ref/instance view) from ACIS into the customer system and then apply component properties.
Step 1
Open the ASAT file, in the same way you would open a SAT file.
Step 2
Ensure that a default_entity_mgr_factory is set as the global entity manager factory. If the ACIS Part Management library, SPAPart.lib, is not linked into your application, then the global factory should already be set to a default_entity_mgr_factory and you do not need to do anything in this step. If you use SPAPart in your application, however, then you should either create a default_entity_mgr_factory on the heap (using ACIS_NEW) and reset the global factory using asmi_set_entity_mgr_factory(), or create a default_entity_mgr_factory and make an asm_restore_options object which points to it (using asm_restore_options::set_entity_mgr_factory()). Note that, in the latter case, the default_entity_mgr_factory object can be instantiated on the stack; there is no need to put it on the heap.
An entity manager is an ACIS Assembly Modeling wrapper for the "customer" object which manages the entities associated with an asm_model object (that is, a node of the assembly model). Every asm_model object owns a single entity manager object, and uses that object to pass messages to and from the customer's part modeling system. Spatial provides a rudimentary default entity manager class for customers who need to read ASAT files but have their own assembly modeling systems (and hence do not need to set up communications between their "part" objects and ACIS Assembly Modeling).
This default_entity_mgr class is essentially a wrapper for an entity list (and a pointer to the associated history stream), and is intended only for the purposes of reading and writing of ASAT files by customers who have not derived their own entity manager class. The default_entity_mgr_factory will create a new default_entity_mgr for each model in the file. By default, a new history stream is created for every default_entity_mgr instantiated, and the default_entity_mgr owns both the history stream and the B-Rep entities that it contains. These defaults were chosen to avoid memory leaks; a default_entity_mgr owns its contents unless it or the factory are explicitly configured otherwise.Step 3
Change the ownership setting on the entity manager factory to FALSE for the mgr_owns_history and mgr_owns_ents data members (if you are using the global factory, you can call asmi_get_entity_mgr_factory() to obtain a pointer to it). This will result in the creation of default_entity_mgr objects which do not own their history streams or B-Rep entities. This step is based on the assumption that you want each node to have a different history stream associated with it, and that you will transfer ownership of the history stream and B-Rep entities associated with an asm_model/default_entity_mgr directly to the corresponding node in your application. If you are not going to take ownership of the B-Rep entities, for example, because you will be using deep-copy on the entities rather than merely taking ownership of their pointers, then you should leave the ownership setting on the factory untouched.
Note that a default_entity_mgr object always keeps ownership of its assembly and model-ref entities. This is because the entities will never be directly transferred to you, rather you will create equivalent constructs in your application using your own assembly modeling system.Step 4
Call asm_restore_model_list(), passing in the asm_restore_options object which has pointers to the factory, if necessary. This results in an asm_model_list object containing the primary entities in the file.
Step 5
Call asm_get_sub_models with a request type of ASM_ALL, and accumulate the result in a new model list. This new model list will be the list of all asm_model objects contained in the file.
Note: Steps 2 through 5 above are performed in the functions load_acis_assembly_from_asat() and import_asat_to_customer_assembly() in asm_example_scm.cpp. The remaining steps below can be found in the function convert_acis_assembly_to_folded_tree_with_component_properties.
Step 6
For each model, create a corresponding node in the customer’s system. If the customer’s system does not admit assembly-level entities, then two nodes may need to be created if the asm_model contains both an assembly and B-Rep entities. The reason for creating nodes corresponding to all models at this stage is to obviate the need for recursion when creating instances; any node which will be instanced will have already been created during this step.
- While creating the corresponding nodes, the customer should keep a mapping between the ACIS model and its corresponding node. In the example code, this is done by storing the models in an asm_model_list and the nodes in a VOID_LIST in the same order so that the index values in the two lists match for a model/node pair. Also, the customer should keep track of models that required the creation of two nodes and the map of these models to the new part nodes.
- As each customer node is created, the customer should transfer ownership of the corresponding model’s history stream and entities to the customer node. The history stream pointer can be found by calling model->mgr()->get_history(), where model is a pointer to the asm_model. The top-level entities can be obtained by calling asmi_model_get_entities() or model->mgr()->get_top_level_entities(), which returns the list of top-level entities for the entities owned by the entity manager, with the assembly entity excluded from the list.
Note: If there are no top-level entities in the model (for example, an assembly model with no B-Rep data), then you might not want to transfer ownership of the history stream to your application. In that case, you should use default_entity_mgr::set_owns_stream(TRUE) to notify the particular entity manager that it should delete its stream when it is destructed. In general, the history stream should be transferred to the same node in your application to which the entities were transferred. A default_entity_mgr pointer can by obtained from the manager pointer by calling asm_model_entity_mgr::default_cast().Step 7
Perform the following steps for each model:
- Call asm_model_get_model_refs(). This will be the set of model references owned by this model's assembly (assuming there is one) which for which the customer will need to create corresponding instance objects.
- Create an instance object corresponding to each model-ref. To do this, you should call asm_model_ref_get_model() and asm_model_ref_get_transform(), which get the model being referenced and the transform which is applied to it, respectively. This, along with the mapping between ACIS models and customer nodes should be enough information for you to create an instance of the node corresponding to the model-ref.
- While creating corresponding instance objects, you should keep a mapping between the ACIS model-refs and the instance objects.
Step 8
At this point, the customer’s assembly structure will represent the undecorated ACIS assembly (that is, the assembly without properties attached). The next steps transcribe the property decorations from the ACIS Assembly Modeling model into the customer format.
Step 9
An applied property in ACIS Assembly Modeling has these characteristics:
- The property itself; this is represented by an ACIS attribute
- The component which the property modifies
- The owning model of the property, that is, the model in which it is applied. Any sub-models of the owning model, when viewed as independent assembly trees, are un-affected by the property, even if they contain the component being modified.
Step 10
Perform the following steps for each model:
- Find all properties which are owned by that model. This is done by calling the function api_asm_model_get_owned_property_owners(), which returns an ENTITY_LIST containing ATTRIB_COMPONENT_PROP_OWNER objects. Each ATTRIB_COMPONENT_PROP_OWNER object corresponds to a component which has had a property applied in the model (that is, owned by the model); the attributes attached to the object represent the properties themselves.
- For each ATTRIB_COMPONENT_PROP_OWNER in the list, search for attributes which are recognized by your application. Because there are several types of attributes which can represent color in ACIS, it is suggested that the api_rh_get_rgb() function be used to determine the color property that was applied.
- For each property found, apply a corresponding property in your application.
Note: Care needs to be taken to be working in the correct history stream during this process. Because they work with entities, Steps 1 and 2 immediately above should be performed in a MODEL_BEGIN/MODEL_END(ASM_NO_CHANGE) block, while Step 3 should be performed in the appropriate history stream in your application.Step 11
CAUTION: One of the complexities of properties in assembly modeling is determining which property (for example, color) is dominant when more than one applied properties affect a particular component.
The rules used by ACIS Assembly Modeling are as follows:
- A property applied higher in the assembly tree is always dominant over a property applied lower in the tree (where the root model is at the "top" of the tree).
- For properties applied in the same model, a property applied to a component whose root (or start) model is higher in the tree is dominant over a property applied to a component with a lower root.
- For properties applied in the model to components having the same root, a property applied to a component with a lower end model is dominant over a property applied to a component with a higher end model.
If your application uses a different set of rules for determining property dominance, then you will not be able to transcribe the ACIS component properties directly into properties in your application; you will need to work out a set of transcription rules which result in an equivalent set of properties being applied to your assembly.
Step 12
At this point, your assembly model should be equivalent to the ACIS assembly model that was read in, and your application should own the history stream and entities for each node. The only remaining thing to do is clean up the remaining ACIS Assembly Modeling objects. To do this, the customer should call asmi_model_cleanup_tree() on the list of primary models that was read in, with a force_clear flag of TRUE. This will release the asm_model objects, causing them to be deleted when their use count falls to zero.
CAUTION: After a model has been force-cleared, you should not attempt to use it.
Example 2: Reading an ASAT File into a Customer Format That Does Not Support Component Decoration
In this example, the import process is the same as in Example 1, except that the ASAT file is read into a customer format which does not support component decoration. The example code is implemented as type "2" in the function import_asat_to_customer_assembly().
The basic strategy in this conversion routine is to query the ACIS model for its unfolded assembly tree (that is, component view) and then re-create the instancing structure for (that is, re-share the models among) components which share the same model information, including properties. The sample implementation presented below assumes that instance decorations that are applied higher in the assembly tree are dominant over decorations that are applied lower in the tree. Note that this conversion method will result in a customer assembly which omits suppressed components, rather than including them with a "suppressed" property.
Step 1
Refer to Step 1 in Example 1.
Step 2
Refer to Step 2 in Example 1.
Step 3
Refer to Step 3 in Example 1.
Step 4
Refer to Step 4 in Example 1.
Step 5
Refer to Step 5 in Example 1.
Step 6
Refer to Step 6 in Example 1.
Step 7
Find the immediate sub-components of each model using asmi_model_get_components(ASM_IMMEDIATE) and accumulate the result in an asm_component_handle list. Note that instances will be created in Step 10 below.
Step 8
Check each component in the accumulated list to see whether it refers to a model with child modifications. A component's model has a child modification if there is a property which modifies a sub-component of the component, that is, if there is a property affecting a sub-component of the component which can only be represented as an instance property if the component’s model is changed. If that is the case, then you need to make a duplicate model in which the instance property is applied (that is, a duplicate model which will be changed in the necessary way).
To perform this check, you should call asmi_component_is_model_modified() . If the result is TRUE, then you should check for child modifications by calling an asmi_component_has_XXX_modifications() routine (for example, asmi_component_has_color_modifications() and asmi_component_has_property_modifications()) for each of the property types understood by your application (that is, those property types you will be transcribing).
Notes
- Immediate sub-components which do not have child modifications can be treated (and thought of) as model-refs and transcribed by creating instance objects of existing nodes in your application (described below).
- Immediate sub-components which have child modifications will require you to create duplicate nodes in your assembly structure and to create instances of these duplicate nodes (described below).
Step 9
Make a copy of the node corresponding to the component’s model (obtained by calling asmi_component_get_unmodified_model() ) for every component in the list which has child modifications. You should maintain a mapping between the duplicate node and the modified component. In addition, you should add all immediate sub-components of the component to the cumulative component list. These subcomponents can be found by calling asmi_component_get_sub_components(ASM_IMMEDIATE).
Notes
- Any "part" entities (obtained by calling asmi_model_get_entities()) belonging to a node being duplicated will need to be deep-copied into the duplicate node. This will only occur if there are assembly-level entities in the ASAT model, because part models can never have child modifications (and, hence, their corresponding nodes will never be duplicated).
- If the node being duplicated corresponds to a model from Step 6 which required the creation of an assembly-only node and a part-only node, then the customer should add an instance of the part-only node to the duplicated assembly-only node. Any properties affecting the part-only node should be applied at this time.
- Properties affecting the part-only node are not properly transferred in the C++ code example.
Step 9
At this point, you should have a node for every ACIS model and a duplicate node for every ACIS component with child modifications. The next step is to add instances (and their properties) to your application nodes.
- For each customer node, get the immediate sub-components of the corresponding ACIS object.
- For "original" nodes (corresponding to ACIS models), call asmi_model_get_components(ASM_IMMEDIATE) on the corresponding model. The parent component (used below) for these sub-components is obtained by calling asmi_model_get_component_handle() on the model.
- For duplicate nodes (corresponding to ACIS components), call asmi_component_get_sub_components(ASM_IMMEDIATE) on the corresponding component, which is the parent component used below.
- For each ACIS sub-component found, create a corresponding instance of a customer node and add appropriate properties.
- Determine the node to be instanced.
- If the sub-component corresponds to a duplicate node, then you should instance that node.
- If the sub-component does not correspond to a duplicate node, then use asmi_component_get_unmodified_model() to find the component’s model; you should instance the corresponding (original) node.
- Determine the instance's transform by calling asmi_component_get_relative_transform() between the sub-component and its parent (determined above).
- Create the instance in your application.
- Check for direct modifications to the component (in the same manner described above for child modifications) and apply the modifying properties to the newly created instance in your application.
Step 10
Cleanup the model as described in Step 12 of Example 1.
Example 3: Reading an ASAT File into a Customer Format That Uses Component Properties
This examples discusses the export process in the case where the customer assembly modeling system uses component properties. The example code is implemented as type "1" in the function export_customer_assembly_to_asat(). The strategy is simply to create an ACIS model for every customer node and add corresponding model references and properties.
Step 1
Accumulate a list of all customer nodes, both primary and sub-nodes.
Step 2
Create an ACIS model object (asm_model) for each customer node in the list by performing the following steps:
Note: These steps are illustrated in the create_export_model function example code.
- Make an ENTITY_LIST containing pointers to all top-level "part" (non-assembly) entities belonging to the node.
- Make an asm_model_info object and set the data members to appropriate values for the node, including the "has_asm" flag.
- Call asmi_model_create_for_export(), passing in the entity list and model info objects.
- asmi_model_create_for_export() creates a model which owns a default_entity_mgr. This default_entity_mgr is created in a state where it owns neither its history stream nor its entities, and is bound to the history stream which owns the first entity in the input list (or the default history stream, if there is no such stream). These three choices can overridden by optional parameters. The defaults are chosen so that the ACIS Assembly Modeling structure will point to entities and history streams owned by your application, but not take ownership of them.
- CAUTION: It is important that you not note a delta state in any stream which will be associated with an asm_model object containing an assembly between this point and the call to asmi_model_cleanup_tree() below. This is because the clear_vf() method of default_entity_mgr (which is called during forced clear) prunes history at delta states which contain assembly bulletins. If no delta states are noted between creation of the assembly and its destruction during force-clear, then the assembly bulletins are deleted without requiring that history be pruned; noting a delta will break this mechanism and force all delta states to be pruned from the history stream in which the assembly was created.
If this problem arises in your application, you can fix it by noting a delta state on each of your history streams before beginning the export process (this is, before Step 1) and rolling all streams back to their original states just before the call to asmi_model_cleanup_tree() (that is, immediately before Step 6). This will place any assembly bulletins which survive on an inactive branch of history and prevent pruning of your main history branch.
- Maintain a mapping between customer nodes their corresponding ACIS model objects.
Step 3
For each node in the list, add ACIS model-refs which correspond to the instances owned by its assembly.
- For each node:
- get the instances owned by its assembly.
- get the corresponding ACIS model.
- For each instance owned by the node:
- find the ACIS model corresponding to the node being instanced.
- get the instance's transform.
- create an ACIS model-ref by calling asmi_model_add_model_ref().
Step 4
For each node in the list, add ACIS properties corresponding to properties in your application which have been applied in the node.
- Find the path through the instance tree corresponding to the component being decorated with a property.
- Make an entity_handle_list of handles for the corresponding model-refs.
- Call asmi_model_get_component_handle to determine the ACIS component corresponding to the component in your application.
Note: If the property is applied to an instance, rather than to a component, asmi_model_get_component_handle() can be called directly on the entity_handle of the corresponding model-ref object.- Call asmi_component_set_color() to set the color property.
- Call api_asm_component_add_property() inside a MODEL_BEGIN/MODEL_END block to set other properties.
- MODEL_BEGIN and MODEL_END are needed to ensure that the correct default stream is set; MODEL_BEGIN should be called before the attribute corresponding to the property is created.
- The model used for MODEL_BEGIN should be the owning model of the property, that is, the model in which the property is applied.
- The MODEL_END macro takes an event type which specifies, in this case, whether the attribute changed the physical properties of the model (for example, suppression), the rendering properties (for example, color), or other properties (for example, name) of the model.
Step 5
At this point, you have built an ACIS assembly model hierarchy corresponding to the assembly tree in your application's assembly modeling system. You can now simply write out the ACIS hierarchy into an ASAT file:
- Create an asm_model_list containing ACIS model objects corresponding to the primary nodes in your application.
- Open an ASAT file for writing.
- Call asmi_save_model_list on the list of primary models.
Step 6
Clean up the ACIS Assembly Modeling structure using asmi_model_cleanup_tree() on the list of ACIS models with a force_clear flag of TRUE.
Example 4: Reading an ASAT File into a Customer Assembly Modeling System That Uses Only Instances Properties
The final code example is of the export process in the case where your assembly modeling application only uses instances properties. The example code is implemented as type "2" in the function export_customer_assembly_to_asat(). The discussion is identical to Example 3, except for the following two points:
- Add the following to Step 3.2:
Query the instance for decorations and then apply corresponding properties to an ACIS component that corresponds to the instance.- Omit Step 4.
Related topics:
HOOPS/ACIS Bridge and ACIS Assemblies
[Top]
© 1989-2007 Spatial Corp., a Dassault Systèmes company. All rights reserved.