Using .dgn Line Styles in a .dwg File (Part 2 of 4)

Andrew Markovich

January 03, 2019

This article is part of a series of articles about using DGN line styles in a .dwg file. For the previous article, see Part 1.

Internal line style component

The DGN file format supports eight internal components — hardcoded line styles that can’t be changed to have different behavior:

image1

Compared with custom line styles, internal line styles are always measured in pixels and can be recomputed after zoom operations. It is not recommended to use the AcDgnLS.tx module internal line style components for creating custom line styles, but this is possible.

To use the internal line style component, include the following header file:

#include "DgnLS/DbLSInternalComponent.h"

Now we can construct a new internal line style component, like the stroke pattern component in the first article but with some additional parameters:

// Create Internal LineStyle Component
OdDbLSInternalComponentPtr pComponent = OdDbLSInternalComponent::createObject();
pComponent->setComponentType(kLSInternalComponent);
pComponent->setComponentUID(dgnLS_UID);
pComponent->setHardwareStyle(lineCode); // Required for back Dgn import only.
pComponent->setIsHardwareStyle(false); // True for hardcoded internal Dgn styles.
pComponent->setLineCode(0x80000000 + lineCode);
// Append strokes
pComponent->insertStroke(0.008)->setDash();
pComponent->insertStroke(0.003)->setGap();
pComponent->insertStroke(0.002)->setDash();
pComponent->insertStroke(0.003)->setGap();

As with the stroke pattern component, we must set up strokes and gaps of the pattern. But internal pattern components can be rendered by hardware, and in this case appended strokes are ignored, and a hardcoded style is drawn instead. All hardcoded patterns were shown in the previous picture and they invoke codes in the 0-7 range. The following table describe these values:

Hardware Style Line Code (Hexadecimal) Pattern Description
0 0x80000000 Continuous.
1 0x80000001 Dot.
2 0x80000002 Dash.
3 0x80000003 Long dash.
4 0x80000004 Dash, dot.
5 0x80000005 Short dash.
6 0x80000006 Dot, dash, dot.
7 0x80000007 Long dash, short dash.

To avoid internal pattern components being rendered by hardware, set the hardware style to ‘false’:

pComponent->setIsHardwareStyle(false);

Also when using internal components, one additional call is needed to correctly set up the OdDbLSDefinition class related to our internal line style component:

pLSDef->setIsContinuous(true); // True for internal components.

After these changes we have the same picture of the linetype as shown for the stroke pattern component in the previous article:

Compared with the stroke pattern component, this linetype will be recomputed during graphics regeneration so it will have a similar length of dashes and gaps after zooming, which looks like the linetype is drawn in pixels on the screen plane.

Internal pattern component creation (full command source code

#include "DbLinetypeTable.h"
#include "DbLinetypeTableRecord.h"
#include "DbLine.h"
#include "DgnLS/DbLSDefinition.h"
#include "DgnLS/DbLSInternalComponent.h"
#include "DgnLS/DbLSMisc.h"

void _CreateDgnLineStyle_Internal_func(OdEdCommandContext* pCmdCtx)
{
  OdDbDatabasePtr pDb = pCmdCtx->baseDatabase();
  OdDbUserIOPtr pIO = pCmdCtx->userIO();

  ::odrxDynamicLinker()->loadModule(OdDgnLSModuleName);

  const OdUInt32 lineCode = 7; // We can utilize any code in 1-7 range.

  // We need GUID for DgnLS objects
  OdUInt8 dgnLS_UID[16];
  ::oddbDgnLSInitializeImportUID(dgnLS_UID);

  // Create Internal LineStyle Component
  OdDbLSInternalComponentPtr pComponent = OdDbLSInternalComponent::createObject();
  pComponent->setComponentType(kLSInternalComponent);
  pComponent->setComponentUID(dgnLS_UID);
  pComponent->setHardwareStyle(lineCode); // Required for back Dgn import only.
  pComponent->setIsHardwareStyle(false); // True for hardcoded internal Dgn styles.
  pComponent->setLineCode(0x80000000 + lineCode);
  // Append strokes
  pComponent->insertStroke(0.008)->setDash();
  pComponent->insertStroke(0.003)->setGap();
  pComponent->insertStroke(0.002)->setDash();
  pComponent->insertStroke(0.003)->setGap();
  // Add component into LineStyles dictionary
  OdDbDictionaryPtr pDict = ::oddbDgnLSGetComponentsDictionary(pDb, OdDb::kForWrite, true);
  pDict->setAt(OD_T("DemoDgnLineStyleInternalComponent"), pComponent);

  // Create LineStyle Definition
  OdDbLSDefinitionPtr pLSDef = OdDbLSDefinition::createObject();
  pLSDef->setIsContinuous(true); // True for internal components.
  pLSDef->setComponent(pComponent->objectId());
  pLSDef->setComponentUID(pComponent->componentUID());

  // Create Linetype Table Record
  OdDbLinetypeTableRecordPtr pLtpRec = OdDbLinetypeTableRecord::createObject();
  pLtpRec->setName(OD_T("DemoDgnLineStyleInternal"));
  pLtpRec->setComments(OD_T("Internal stroke 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 line for LineStyle testing
  OdDbLinePtr pLine = OdDbLine::createObject();
  pLine->setDatabaseDefaults(pDb);
  pLine->setLinetype(lsId);
  pLine->setEndPoint(OdGePoint3d(1.0, 0.0, 0.0));
  OdDbBlockTableRecord::cast(pDb->getActiveLayoutBTRId().safeOpenObject(OdDb::kForWrite))->appendOdDbEntity(pLine);
}

The next article in this series describes working with block (symbol) DGN line style components.