SAT Save and Restore
ACIS provides API functions for saving model data to and retrieving model data from standard stream files. In addition, ACIS provides API functions that allow applications to target media other than stream files. ACIS allows model data to be saved and restored with or without history information. (History information allows models to be rolled to a previous state.)
The standard ACIS save/restore process supports two types of stream file formats: Standard ACIS Text (file extension .sat) and Standard ACIS Binary (file extension .sab). The only difference between these files is that the data is stored as ASCII text in a .sat file and in binary form in a .sab file. The organization of the model data is identical in both formats. The term "SAT file" is often used generically to refer to both types.
Text file saves have the advantages of being human-readable. Binary saves are not human-readable, but writing records in binary is roughly twice as fast as writing in text and the files are 10% to 20% smaller. ACIS can read and write any format of binary file on any platform. The default format for writing a binary file is the native format of the machine on which it is being written.
Save and Restore Details
The four API functions for saving a list of ENTITYs are:
api_save_entity_list Writes a list of ENTITYs to a FILE*. api_save_entity_list_file Writes a list of ENTITYs to a custom output target. api_save_entity_list_with_history Writes a list of ENTITYs and their history records to a FILE*. api_save_entity_list_with_history_file Writes a list of ENTITYs and their history records to a custom output target.
The most commonly used API function for saving ENTITYs is api_save_entity_list. This API function accepts an open stream pointer (FILE*), a logical indicating whether to save in binary or text format, and an ENTITY_LIST containing the list of entities to be saved. The save process, which is used by the four API functions listed above and which writes the records one by one to the current position in the output stream, can be broken down into the following series of steps:
- Writing the header record
- Writing the FileInfo record
- Writing the ENTITY records
- Writing HISTORY_STREAM records (when saving with history)
- Writing history ENTITY records (when saving with history)
- Writing the end of data token
The header record consists of four numbers which represent: the version of the data (save version), the number of entities in the data block (saved entities), the number of entities originally supplied to the save process (top-level entities), and a bit-field, mainly used internally, that indicates whether history records are available in the data block. An example of a header record is shown below.
2000 0 1 0
In this example the save version is 20.0, the value for saved entities is 0, the value for top-level entities is 1, and the final value, 0, indicates history records have not been saved in the file.
The save version is simply the ACIS version to which the model data is formatted. This is typically the current version of ACIS but can be modified, with api_save_version, to target an earlier version of ACIS. This is useful when exchanging model data with applications based on older versions of ACIS, but has several drawbacks that are discussed in the topic Backward Compatibility. The save version is a portmanteau value created by multiplying the major version by 100 and adding the minor version.
Note: Later versions of ACIS data cannot be restored by earlier versions of ACIS. In other words, model data is not backwards compatible. An ACIS R20 file cannot be read by an ACIS R16 application. The only way to make model data consumable by older versions of ACIS is to specifically target these versions with the save version value. An ACIS R20 application can generate an ACIS R16 formatted save file.
The saved entities value is now obsolete and only has value in very old versions of ACIS data (prior to version 1). This value reflected the number of ENTITY records actually saved to the stream. The difficulty of maintaining this value is mainly caused by the need to change the writing position of the stream (to record the number of records actually written), which is made problematic by different interpretations of end-of-line formatting characters. Changing the data output position may also be difficult or even impossible when the media does not support random access, such as tape. The modern format solves this problem with and end-of-data token, discussed later in this section. We may choose to use the saved entities value for other purposes in the future.
The top-level entities value represents the number of entities supplied to the save process in the ENTITY_LIST argument. These are the seed entities used to discover all other supporting entities that must also be saved in order to maintain the complete topological and geometric structure of the model. These are usually BODY entities and are the first records saved to the stream. The supporting entities, written to the stream after the top-level entities, are all entities that can be reached by scanning both up and down the topological hierarchy. These entities, when restored, duplicate the state of the model when it was saved.
The final value in the header record is a bit field. The first bit is used when saving with history. The remaining bits are reserved for internal use and should be ignored.
All of the header data, with the exception of the save version, is calculated by the save process and cannot be modified in any way. This data simplifies the restore process.
The FileInfo record is saved next. This record is unique to each ACIS-based application because it contains a product identifier, a unit specifier, and the tolerance values of the application. The FileInfo record must be setup correctly by calling the api_set_file_info function before model data can be saved. The save process fails if this record is not correctly initialized. This is not only used to track the creator of the data, but also helps assure the correct representation of the data in the application model space, with respect to units and tolerances.
Important: The product ID and units must be set correctly in the FileInfo record before SAT files can be saved. Refer to api_set_file_info for more information.
An example of a FileInfo record is shown below.
23 ACIS/Scheme AIDE - 20.0 12 ACIS 20.0 NT 24 Wed Oct 14 15:32:26 2009 1 9.9999999999999995e-007 1e-010
This record was extracted from a SAT file generated by Scheme AIDE. The record contains six fields. The first field is a variable length string containing the name of the application. The string has 23 characters and is "ACIS/Scheme AIDE - 20.0". The second field is a variable length string specifying the version of ACIS used to produce the file. This string has 12 characters and is "ACIS 20.0 NT". Note that the version of ACIS used to generate the file may be different than the save file version recorded in the header. The third field is a variable length string specifying the date the file was created. This string is 24 characters long and is "Wed Oct 14 15:32:26 2009". The fourth fields is a numerical value specifying the units of the model, in millimeters per unit. The fifth field is a numerical value specifying the positional tolerance value, SPAresabs. The sixth field is a numerical value specifying the angular tolerance value, SPAresnor.
The ENTITY records are saved next, beginning with the entities of the supplied ENTITY_LIST. These are followed by the supporting entities in no particular order. The HISTORY_STREAM records, including DELTA_STATE, BULLETIN_BOARD, and BULLETIN records, as well as the history entities, which are simply snapshots of entities at particular states, follow next if saving with history. A couple of examples of ENTITY records are presented in the section on Sequence Numbers. (The format for each type of ENTITY is different and may change from version to version.)
The terminator token for a block of ACIS model data is the string End-of-ACIS-data.
Multiple and Embedded Model Data Blocks
Each ACIS model data block consists of a header record, followed by a FileInfo record, followed by active entity records, then history stream records and history entity records (when saving with history), and finally the end of ACIS data terminator token.
Each ACIS model data block is an atomic unit and should not be modified or broken up in any way. However, more than one ACIS model data block can be saved to a file, and applications can surround the blocks with custom data. We call the later compound files and urge you to change the extension of these files and to provide a process to extract ACIS model data blocks so that they can be restored by any ACIS-based application.
The four API functions for restoring a set of ENTITYs are:
api_restore_entity_list Restores ENTITYs from a FILE*. api_restore_entity_list_file Restores ENTITYs from a custom input source. api_restore_entity_list_with_history Restores ENTITYs and their history records from a FILE*. api_restore_entity_list_with_history_file Restores ENTITYs and their history records from a custom input source.
The most commonly used function to restore model data is api_restore_entity_list. This API function accepts an open stream pointer (FILE*), a logical indicating whether to restore in binary or text format, and an ENTITY_LIST to receive the entities that are restored, as arguments. The restore process, which reads the records one by one from the current read position in the stream, is analogous to the steps of the save process. The header record is restored first, followed by the FileInfo record, the ENTITY records, the history records and ENTITYs if applicable, ending with the terminator record.
The header record can be restored individually with the read_header function. This may be useful when applications need version information before calling standard restore functions. Care must be taken to reset the current read position so that standard restore can successfully re-read the header. Also, note that the binary format of the data block, in the case of an SAB file, is determined during the header read process.
The FileInfo record can also be restored, after the header record is restored, by calling the restore method on a FileInfo object. This may be useful when applications need creator or unit information from the model data before calling the standard restore functions. The FileInfo record can also be evaluated after the restore process by getting the last one restored with the api_get_file_info function.
The ENTITY records are restored next, beginning with the top-level entities, which are added to the supplied ENTITY_LIST. The entities returned by the restore process are the same ones supplied to the save process. The HISTORY_STREAM records, including DELTA_STATE, BULLETIN_BOARD, and BULLETIN records, as well as the history ENTITYs, are restored next if restoring with history.
The restore process ends after the End-of-ACIS-data terminator token is restored from the file.
Applications are responsible for opening and closing the stream files, and for making sure that the file pointers are positioned correctly when the standard save and restore functions are called. Each function expects that the file is open and positioned at the byte where the save or restore is to begin. When the function finishes, the stream file is positioned after the last byte of the end of ACIS data terminator token.
Additional Restore Details
The restoration of ENTITYs is performed in two stages:
- Read the save file record and construct the new object, leaving pointers to other restored entities in symbolic form (as indices into an array), and entering the address into the array.
- After all new objects have been constructed, visit each to convert the symbolic ENTITY pointers into genuine ones.
Restore Stage 1
The restore_entity_from_file function reads the ID string from the start of each save file record, and searches its tables for the ID components, starting with the last (base) one, and proceeding towards the leaf. It then calls the restore function for the leaf-most class found. That function constructs an object of the appropriate derived type, and then calls its restore_common member function. That function in turn calls its parent's restore_common member function, and then reads data specific to the derived class. Finally, restore_entity_from_file reads any more data in the save file record, and constructs an unknown_entity_text record to contain it, together with any unrecognized ID strings.
Restore Stage 2
The fix_pointers member function for each ENTITY in the array is called, with the array as argument. This calls fix_common, which calls its parent's fix_common, and then corrects any pointers in the derived class. In practice, there is never anything special for fix_pointers to do, but it is retained for consistency and compatibility.
The indexing of the entity records depends on the active ACIS options when the model was saved. If they are indexed, the indexing is sequential starting at 0. All top-level entities must appear before any other entities. Thereafter, the record order is not significant.
The optional sequence number represents the index assigned to a record and is intended to improve readability and simplify editing of ACIS save files. The option sequence_save_files controls whether ACIS writes sequence numbers to the save file.
-0 body $1 $2 $-1 $-1 # . . . -25 point $-1 10 0 25 #
In the example above from a SAT file, "-0" and "-25" are sequence numbers. In the first line, "$1 $2" happen to be pointers to records (not shown) with sequence numbers "-1" and "-2", respectively.
This sequence number itself can be turned on or off for the entity records in the save file. Even when the sequence number is not written to the file, it is implied by the order of the records in the file. Pointers to other records correspond to these implied sequence numbers. If sequence numbers are turned off, a record cannot be simply moved or removed from the save file, because this creates invalid index referencing when the file is restored.
If sequence numbers are turned on, an entity may be deleted by simply removing its record from the save file. Any references to the removed record's index become NULL pointers when the file is restored by ACIS. With sequence numbers on, records may also be rearranged within the file.
A mixture of records with sequence numbers and records without sequence numbers is permitted within the save file. Any record having a sequence number is given an index one greater than the previous entry in the file. Specified sequence numbers can be in any order. However, care must be taken that no sequence number repeat itself, either through manual specification of sequence numbers or the implied incrementing of other, non-specified, sequence numbers.
Regardless of what sequence numbers they contain, the entities represented by the first records are assumed to be the top-level entities. Top-level entities are part of the ACIS topology. Also, if the total entity count was written in the header and the last record's sequence number is not one less than that count, a dummy record with a sequence number equal to the count must be added at the end of the file.
The ACIS version number for subsequent save operations is set using the function api_save_version, which takes two arguments, a major version and a minor version. Throughout the system all functions for saving ENTITYs and construction geometry take into account the save version number. This is the global value, save_version_number, which gives the version of save file format being written. This can be used to produce a save file in a previous version's format.
Objects can be modified to be compatible with an earlier version. This may or may not result in loss of information. If the modification involves loss of information or a possible error in the resulting save file, the system generates a warning, but still produces the save file. When saving to a previous version of 7.0 or later, the system may attempt to use tolerant modeling to remove gap errors in such modified models.
When restoring objects with shared subtypes, such as int_cur or spl_sur, from a save file in which they are not shared, the default is to share identical sub-objects rather than to leave them unshared.
Note: The restore of pre-Release 1.6 save files causes the coedges in the entity restored to be ordered counterclockwise about their edge.
The save version number is normally the current version, but the version may be set backwards to simulate save files generated by previous versions. If api_save_version is called with a major version 0 and a minor version of -1, the save version will be set to the current ACIS version.
Decimal Point Representation
Some applications using earlier versions of ACIS were written using "internationalization" concepts and have written save files that contain representations of double precision numbers containing commas for decimal points. This occurs if the application writing the save file had made a call to the C standard library function setlocale to change the locale properties from the default C settings. Consequently, other applications not using this "internationalization" feature could not read these files.
Beginning with version 2.1, ACIS always writes a save file using the "C" locale, which uses the period representation for decimal points. ACIS makes a call to the "C" library function setlocale to change the environment to the "C" locale before writing a save file. The locale is reset to its original value after the file is written.
The option restore_locale enables applications to read pre-ACIS 2.1 save files that were written with other locales. Before restoring the file, the option should be set to a string representing the locale in effect when the file was written. The option may be set with the function api_set_str_option, or with the Scheme extension option:set. When a file is restored, ACIS makes a call to the function setlocale to set the environment to the value (string) specified by the option.
The test_share option checks for shared geometry when restoring SAT files. As entities are read into ACIS, int_cur and spl_sur types are compared with those that have already been restored to determine if they are identical to a previously restored int_cur or spl_sur. They can then be restored simply by incrementing a use count instead of restoring the entire object. This option significantly reduces the size of retrieved bodies and aids subsequent operations, but it can be expensive and can become noticeable when restoring large parts.
The option can be turned off to speed up the restore process. However, the amount of memory required to restore a model is larger, because sharing of geometry is not taking place. Also, evaluations of geometry during modeling operations may take longer because the test for coincidence takes place each time the objects are evaluated. This may cause the test to happen many times instead of once when the model is loaded.
If you are confident that your models contain little shared data or that the data has already been shared via modeling operations in ACIS, then turning the test_share option off may lead to faster load times.
Functionality has been added to the SAT/SAB restore process that can be used to generate an entity record sanity log file when ACIS data cannot be restored because of errors. This log file contains a character-by-character copy of the loading file with error information, if any, inserted directly after the field of the entity record that did not meet the criteria of the restore logic. The information in this log file can be used to identify corrupt fields in entity records so that successful restores can be possible.
A simple example of the structure of the log file and the information it contains is presented below. The first block contains the first few lines of a good SAT file. The second contains a few modifications to the same SAT file. The third shows the contents of the log file that result from loading the modified file.
1100 0 1 0 24 ACIS Scheme AIDE - 11.0 12 ACIS 11.0 NT 24 Wed Jun 18 14:50:34 2003 1 9.9999999999999995e-007 1e-010 body $-1 -1 -1 $-1 $1 $-1 $-1 F # lump $-1 -1 -1 $-1 $-1 $2 $0 F # shell $-1 -1 -1 $-1 $-1 $-1 $3 $-1 $1 F # face $-1 -1 -1 $-1 $4 $5 $2 $-1 $6 '''forward''' single F F # ...
1100 0 1 0 24 ACIS Scheme AIDE - 11.0 12 ACIS 11.0 NT 24 Wed Jun 18 14:50:34 2003 1 9.9999999999999995e-007 1e-010 body -1 -1 -1 $-1 $1 $-1 $-1 F # lump $-1 -1 a $-1 $-1 $2 $0 F # shell $-1 -1 -1 $-1 $-1 $-1 $3 $-1 $1 F # face $-1 -1 -1 $-1 $4 $5 $2 $-1 $6 '''forw''' single F F # ...
1100 0 1 0 24 ACIS Scheme AIDE - 11.0 12 ACIS 11.0 NT 24 Wed Jun 18 14:50:34 2003 1 9.9999999999999995e-007 1e-010 body -1 ERROR reading pointer: expected token '$' found '-'. -1 -1 $-1 $1 $-1 $-1 F # lump $-1 -1 a ERROR reading number: expected number found 'a'. $-1 $-1 $2 $0 F # shell $-1 -1 -1 $-1 $-1 $-1 $3 $-1 $1 F # face $-1 -1 -1 $-1 $4 $5 $2 $-1 $6 forw ERROR reading bool: expected 'reversed' or 'forward' found 'forw'. single F F # ...
The restore logging functionality can be enabled by setting the restore_log option to TRUE and disabled by setting the option to FALSE. It is set to FALSE by default. The output log file is by default named restore.log and is created in the current working directory, in overwrite mode. Setting the restore_file string option to the desired file name will change the name and location of the output log file.
The following lines demonstrate how the options can be changed in the ACIS Scheme AIDE example application:
(option:set "restore_log" #t) (option:set "restore_file" "/ACISR12/my_restore.log")
A parse error can and often will cause cascading errors in the same entity record. When the restore_log option is enabled, the logic generates default values for missing or erroneous fields, which do not meet the field requirements, in order to allow the process to continue. When the parser encounters a character string where a number is expected, it simply returns the number zero instead of the string. An entity record containing multiple errors will be skipped and the restore logging will continue with the next entity.
Hence, the best strategy to repair the SAT file is to fix the first field error of a given entity and to then repeat the restore. This approach eventually eliminates the cascading errors and allows a successful restore.
Dealing with SAB files is different because these files are in binary form and are therefore not readily editable. When the restore_log option is enabled, the logic generates a one-to-one SAT representation of the SAB data in the log file. This file can then be edited and evaluated with the SAT restore logging capabilities.