This is the second article in a series about using compound DGN line styles in a .dwg file. For the previous article, see Part 1.
Creating line style modifiers
An additional feature of DGN line styles is the ability to modify their behavior for selected entities. If we require a small modification of line style behavior to a single entity (or more entities), we don’t have to create a separate line style; we can attach a simple line style modifier to this entity instead.
To enhance our compound line style demonstration, we create an additional OdDbCircle entity:
// Create circle for LineStyle testing
OdDbCirclePtr pCircle = OdDbCircle::createObject();
pCircle->setDatabaseDefaults(pDb);
pCircle->setLinetype(lsId);
pCircle->setCenter(OdGePoint3d(1.15, -0.07, 0.0));
pCircle->setRadius(0.02);
OdDbBlockTableRecord::cast(pDb->getActiveLayoutBTRId().safeOpenObject(OdDb::kForWrite))->appendOdDbEntity(pCircle);
And use the following simple code to attach a line style modifier for a second line entity and for the created circle entity:
// Set up LineStyle modifier for 2nd line and circle
OdGiDgLinetypeModifiers lsModifiers;
lsModifiers.setWidth(0.002); // Width override value
lsModifiers.setWidthFlag(true); // Enable width override
::oddbDgnLSWriteEntityXData(OdDbEntity::cast(lineIds[1].openObject(OdDb::kForWrite)), lsModifiers, 1.0);
::oddbDgnLSWriteEntityXData(pCircle, lsModifiers, 1.0);
The OdGiDgLinetypeModifiers structure provides a set of parameters that can be customized in existing line styles during selected entity vectorization. Here, for example, we have enabled a width override using the OdGiDgLinetypeModifiers::setWidth() and OdGiDgLinetypeModifiers::setWidthFlag() methods. The first one sets the width override value, and the second one is used to enable this override. Take into account that a single width value means constant width for line style dashes, i. e. usage of similar width values for start and end dash points. To enable different widths for start and end dash points, the OdGiDgLinetypeModifiers::setEndWidth() and OdGiDgLinetypeModifiers::setEndWidthFlag() methods can be used.
The ::oddbDgnLSWriteEntityXData() function in this example is used to attach specified modifiers to selected entities. To invoke it, include an additional header file:
#include "DgnLS/DbLSXData.h"
After applying the line style modifier, we have different compound line style behavior for the middle line:
Look at the modified line style closely:
The only difference from the original compound line style is the width of the dash in the stroke pattern component. And this is how our final modified line style looks on the circle entity:
Compound component creation (full command source code)
#include "DbLinetypeTable.h"
#include "DbLinetypeTableRecord.h"
#include "DbLine.h"
#include "DbCircle.h"
#include "Gi/GiDgLinetype.h"
#include "DgnLS/DbLSDefinition.h"
#include "DgnLS/DbLSCompoundComponent.h"
#include "DgnLS/DbLSXData.h"
#include "DgnLS/DbLSMisc.h"
// Declare commands from previous articles.
void _CreateDgnLineStyle_Stroke_func(OdEdCommandContext* pCmdCtx);
void _CreateDgnLineStyle_Internal_func(OdEdCommandContext* pCmdCtx);
void _CreateDgnLineStyle_Point_func(OdEdCommandContext* pCmdCtx);
void _CreateDgnLineStyle_Compound_func(OdEdCommandContext* pCmdCtx)
{
OdDbDatabasePtr pDb = pCmdCtx->baseDatabase();
OdDbUserIOPtr pIO = pCmdCtx->userIO();
::odrxDynamicLinker()->loadModule(OdDgnLSModuleName);
// Create stroke, internal and point components
_CreateDgnLineStyle_Stroke_func(pCmdCtx);
_CreateDgnLineStyle_Internal_func(pCmdCtx);
_CreateDgnLineStyle_Point_func(pCmdCtx);
OdDbDictionaryPtr pLsDict = ::oddbDgnLSGetComponentsDictionary(pDb, OdDb::kForRead);
OdDbObjectId strokeCompId = pLsDict->getAt(OD_T("DemoDgnLineStyleStrokeComponent"));
OdDbObjectId internalCompId = pLsDict->getAt(OD_T("DemoDgnLineStyleInternalComponent"));
OdDbObjectId pointCompId = pLsDict->getAt(OD_T("DemoDgnPointComponent"));
OdDbObjectId pointStrokeCompId = pLsDict->getAt(OD_T("DemoDgnLineStyleStrokeComponentForPointComponent"));
// We need GUID for DgnLS objects
OdUInt8 dgnLS_UID[16];
::oddbDgnLSInitializeImportUID(dgnLS_UID);
// Create Compound LineStyle Component
OdDbLSCompoundComponentPtr pCompComponent = OdDbLSCompoundComponent::createObject();
pCompComponent->setComponentType(kLSCompoundComponent);
pCompComponent->setComponentUID(dgnLS_UID);
// Append compound component sub-components
pCompComponent->appendComponent(pointStrokeCompId);
pCompComponent->appendComponent(pointCompId);
pCompComponent->appendComponent(strokeCompId, -0.005);
pCompComponent->appendComponent(internalCompId, 0.005);
// Add component into LineStyles dictionary
pLsDict->upgradeOpen();
pLsDict->setAt(OD_T("DemoDgnLineStyleCompoundComponent"), pCompComponent);
// Create LineStyle Definition
OdDbLSDefinitionPtr pLSDef = OdDbLSDefinition::createObject();
pLSDef->setComponent(pCompComponent->objectId());
pLSDef->setComponentUID(pCompComponent->componentUID());
// Create Linetype Table Record
OdDbLinetypeTableRecordPtr pLtpRec = OdDbLinetypeTableRecord::createObject();
pLtpRec->setName(OD_T("DemoDgnLineStyleCompound"));
pLtpRec->setComments(OD_T("Compound component"));
OdDbObjectId lsId = OdDbLinetypeTable::cast(pDb->getLinetypeTableId().safeOpenObject(OdDb::kForWrite))->add(pLtpRec);
// Attach LineStyle Definition to Linetype Table Record
pLtpRec->createExtensionDictionary();
OdDbDictionaryPtr pLtpDict = OdDbDictionary::cast(pLtpRec->extensionDictionary().openObject(OdDb::kForWrite));
pLtpDict->setAt(::oddbDgnLSGetDefinitionKeyName(), pLSDef);
// Create three lines for LineStyle testing
OdDbObjectId lineIds[3];
for (int nLine = 0; nLine < 3; nLine++)
{
OdDbLinePtr pLine = OdDbLine::createObject();
pLine->setDatabaseDefaults(pDb);
pLine->setLinetype(lsId);
pLine->setStartPoint(OdGePoint3d(1.1, 0.03 - 0.03 * nLine, 0.0));
pLine->setEndPoint(OdGePoint3d(1.2, 0.03 - 0.03 * nLine, 0.0));
lineIds[nLine] = OdDbBlockTableRecord::cast(pDb->getActiveLayoutBTRId().safeOpenObject(OdDb::kForWrite))->appendOdDbEntity(pLine);
}
// Create circle for LineStyle testing
OdDbCirclePtr pCircle = OdDbCircle::createObject();
pCircle->setDatabaseDefaults(pDb);
pCircle->setLinetype(lsId);
pCircle->setCenter(OdGePoint3d(1.15, -0.07, 0.0));
pCircle->setRadius(0.02);
OdDbBlockTableRecord::cast(pDb->getActiveLayoutBTRId().safeOpenObject(OdDb::kForWrite))->appendOdDbEntity(pCircle);
// Set up LineStyle modifier for 2nd line and circle
OdGiDgLinetypeModifiers lsModifiers;
lsModifiers.setWidth(0.002); // Width override value
lsModifiers.setWidthFlag(true); // Enable width override
::oddbDgnLSWriteEntityXData(OdDbEntity::cast(lineIds[1].openObject(OdDb::kForWrite)), lsModifiers, 1.0);
::oddbDgnLSWriteEntityXData(pCircle, lsModifiers, 1.0);
}
Here is the final picture that is generated from the command execution:
Conclusion
In these articles we examined DGN line style possibilities while embedding them into a .dwg database. We didn’t look at the details for each line style feature, but after reading these introductory topics you will be able to continue experimenting with DGN line styles independently.
The DGN line style feature is a powerful tool that signficantly extends .dwg linetype functionality and can be used to create Autodesk® AutoCAD® compatible drawings. It is simple to use and doesn’t require special knowledge about internal vectorization processes, the API is simple, and so there should be no limitations to invoke this functionality in advanced CAD editors. ODA Visualize SDK invokes the same code base to display DGN line styles for all kinds of databases, so this guarantees compatibility of line style behavior in different products. The DGN line styles vectorization code base is well established and has full compatibility with Bentley® MicroStation®. This is a good example of how functionality can be effectively shared between different products and file formats.