Drawings SDK allows you to insert external references to drawings. This topic describes how to load and manage an external reference in a drawing. An example of adding an external reference can be found in the OdWriteEx sample application.
Xref (short for eXternal REFerence) is, as the name suggests, a reference to an external .dwg file. External references are often used to split big files into a smaller ones; the smaller files are referenced by one "host" file. The smaller files can be processed by different engineers independently and simultaneously. External references are also used to make block libraries and underlays. All changes made in referenced files will take effect in the host drawing after opening or reloading a reference.
In the host database, an xref is represented as a block with a name corresponding to the name of the referenced file (without a .dwg file extension). An xref block does not contain entities from the xref database; instead it returns an iterator to the xref's model space using the OdDbBlockTableRecord::newIterator() method.
During an export of a .dwg file, all objects of the external references are exported with the host database.
Xref management methods are bundled in two namespaces: OdDbXRefMan and OdDbXRefManExt. The most important method is OdDbXRefMan::load(). It loads the external reference to the current drawing if it wasn't already loaded. It has three definitions:
OdResult load(OdDbBlockTableRecord* pBTR); // pBTR is a pointer to the Block Table Record
// of the Xref to load
OdResult load(OdDbDatabase* pHostDb, const OdString& xrefBlockname); // pHostDb is a pointer to the host database
// xrefBlockname is an xref block name to load
OdResult load(OdDbObjectIdArray& xrefBTRids); // xrefBTRids is an array of the object IDs
// of the Block Table Records of the Xrefs to load.
The loading process is rather complicated. First, the saved xref path (OdDbBlockTableRecord::pathName()) is passed to OdDbHostAppServices::findFile() with a hint FindFileHint::kXRefDrawing findFile() that should return a resolved path, which will be passed to OdDbHostAppServices::readFile(). If the file was not found, the block xrefStatus() is set to kXrfUnresolved. If the file was found, xref symbol tables are merged into the host database as follows:
ID mapping created while cloning is saved in the xref database, and the cloned objects get the "redirected" status, so that opening an object ID of the cloned object (e.g., a layer), will return the corresponding layer from the host database. To get an original object, use the OdDbObjectId::convertToRedirectedId() or OdDbObjectId::getNonForwardedHandle() method. The reason for this redirection is to make the xref block look more native in the host database (also for list scripts). This way, when asking for a layer of an entity from the xref block you get a layer from the host database, which is what is usually expected.
The xref database also keeps a reference to the host xref block, accessible via the OdDbDatabase::xrefBlockId() method.
To temporarily restore an xref database to its original state (e.g., in REFEDIT-like scenarios), use the OdDbDatabase::restoreOriginalXrefSymbols() method. OdDbDatabase::restoreForwardingXrefSymbols() method does the opposite.
When referencing a database that in turn references other files (nested xrefs), you have an option to skip these nested files using the "overlay" xref status by using the OdDbXRefMan::setOverlaid() method, which requires a pointer to an object of the OdDbBlockTableRecord class to define a pointer to the Block Table Record of the Xref to detach.
The OdDbGraph::findCycles() method is used while loading to detect circular references of the nested xrefs, which requires a pointer to an object of the OdDbGraphNode class to define a pointer to the starting node from which the search will be started. Use the OdDbXrefGraph::getFrom() method to inspect the nested xref graph structure. It requires two parameters: pointer to the object of the OdDbDatabase class to specify the xref database and a reference to an object of the OdDbXrefGraph class to receive the xref tree.
To create a new xref block, use the OdDbXRefManExt::addNewXRefDefBlock() method. It requires six parameters: pointer to an object of the OdDbDatabase class to define a host database, OdString value to define a path and filename of the xref block (path can be absolute or relative), OdString value to define a name of the xref block, bool value that should be "true" for an xref overlay or "false" for an xref attachment, object of the OdPassword class to define a file password, and object of the OdDbHandle class to define the handle for the xref block. After that, either explicitly load it via OdDbXRefMan::load() or it will automatically be loaded when the block insert is rendered (xref block should also be inserted, just as a normal block). For example:
// Create a BlockTableRecord
OdDbBlockTableRecordPtr pXRef = OdDbXRefManExt::addNewXRefDefBlock(pDb, OD_T("test.dwg"), OD_T("XRefBlock"), false);
OdDbObjectId brefId;
// Add the block reference to the BlockTableRecord
OdDbBlockReferencePtr pBlkRef = OdDbBlockReference::createObject();
pBlkRef->setDatabaseDefaults(bBTR->database());
brefId = bBTR->appendOdDbEntity(pBlkRef);
//Set some properties
pBlkRef->setBlockTableRecord(pXRef->objectId());
pBlkRef->setBlockTransform(OdGeMatrix3d::kIdentity);
// Open it for writing
OdDbBlockReferencePtr pXRefIns = brefId.safeOpenObject(OdDb::kForWrite);
// Set parameters
...
After saving, the path to an xref file is saved in an OdDbBlockBegin object in the xref block. Layers and other cloned symbols are saved with the host database if the "VISRETAIN" database system variable is true. Blocks and symbols copied without cloning are, of course, never saved with the host.
The external reference is one of the dependencies maintained by the OdFileDependencyManager.
Other useful methods for working with external references are listed below.
Method | Description |
---|---|
OdDbBlockTableRecord class (block records inside the OdDbBlockTable) |
|
bool isFromExternalReference() | Returns true if the block is an xref. |
bool isFromOverlayReference() | Returns true if the block is an overlaid xref. |
bool isUnloaded() | Returns true if the xref is unloaded. |
OdString pathName() | Returns the path and filename of the xref drawing. |
void setIsUnloaded(bool isUnloaded) | Sets the unloaded status for the xref. |
void setPathName(const OdString& pathName) | Sets the path and filename for the xref drawing. |
OdDbDatabase* xrefDatabase(bool includeUnresolved = false) | Returns the database that defines this xref. |
OdDb::XrefStatus xrefStatus() | Returns the xref status of the block:
|
OdDbSymbolTableRecord class (named record object, which is the base class for all record objects in the database) |
|
OdString getName() | Returns the name of the record object. |
void setName(const OdString& sName) | Sets the name for the record object. |
bool isDependent() | Returns true if the record object is xref-dependent. |
bool isResolved() | Returns true if the record object is xref-dependent and resolved. |
OdDbXrefGraph class (xref tree of a database) |
|
OdDbXrefGraphNode* hostDwg() | Returns the XrefGraphNode associated with the host drawing of the XrefGraph object. |
void getFrom(OdDbDatabase* pDb, OdDbXrefGraph& xrefGraph, bool includeGhosts = false); | Populates the specified XrefGraph object with the xref tree of the specified database. |
OdDbXrefGraphNode* xrefNode(const OdDbDatabase* pDb) | Returns the XrefGraphNode object corresponding to the specified database. |
OdDbXrefGraphNode class (xref database) |
|
bool isNested() | Returns true if the XrefGraphNode represents an xref that is not directly referenced by the host drawing. |
OdDbXRefMan class (manages xrefs in an OdDbDatabase object) |
|
OdResult detach(OdDbBlockTableRecord* pBTR) | Detaches the specified xref (erases all traces of the xref from the host). |
OdResult bind(OdDbBlockTableRecord* pBTR, bool insertBind = false) | Merges the xref into the host, cloning all the missing data (model space contents) and changing symbols to "xref$n$name" from the usual "xref|name". It converts the xref block to a normal block and releases the xref database. Bind is like OdDbXRefMan::detach() followed by OdDbDatabase::insert(). Bind is irreversible; you won't be able to detach the bound drawing because it is not "attached" anymore. |
OdResult loadAll(OdDbDatabase* pHostDb, bool verify = false) | Loads all xrefs not currently loaded from the host database. |
void unload(OdDbBlockTableRecord* pBTR) | Unloads the specified xref. |
void unloadAll(OdDbDatabase* pHostDb) | Unloads all loaded xrefs from the host database. |
The following system variables can affect external references:
Copyright © 2002 – 2021. Open Design Alliance. All rights reserved.
|