在 .dwg 文件中使用 .dgn 线型(第 4 部分,共 4 部分)

本文是关于在 .dwg 文件中使用 DGN 线型系列文章的一部分。有关上一篇文章,请参阅第 3 部分

创建点线型组件

点线型组件能够为每个笔划图案虚线(或间隙)或曲线起点/终点设置要矢量化的符号组件。它还能够为每个多段线顶点设置要矢量化的符号组件。要为笔划图案虚线(和间隙)设置符号,首先创建笔划图案组件。在此示例中,我们使用上一篇文章中的简单笔划图案组件:

// Create Stroke LineStyle Component
OdDbLSStrokePatternComponentPtr pLsComponent = OdDbLSStrokePatternComponent::createObject();
pLsComponent->setComponentType(kLSStrokePatternComponent);
pLsComponent->setComponentUID(dgnLS_UID);

// Append strokes
pLsComponent->insertStroke(0.008)->setDash();
pLsComponent->insertStroke(0.003)->setGap();
pLsComponent->insertStroke(0.002)->setDash();
pLsComponent->insertStroke(0.003)->setGap();

// Add component into LineStyles dictionary
OdDbDictionaryPtr pDict = ::oddbDgnLSGetComponentsDictionary(pDb, OdDb::kForWrite, true);
pDict->setAt(OD_T("DemoDgnLineStyleStrokeComponentForPointComponent"), pLsComponent);

这组笔画和间隙生成以下线型:

image0

现在我们可以创建一个新的点组件(此代码是创建所有 DGN 线型组件的典型代码),并将现有的笔画模式组件附加到它:

// Create Point Component
OdDbLSPointComponentPtr pPtComponent = OdDbLSPointComponent::createObject();
pPtComponent->setComponentType(kLSPointComponent);
::oddbDgnLSIncrementUID(dgnLS_UID);
pPtComponent->setComponentUID(dgnLS_UID);

// Set up stroke component for point component
pPtComponent->setStrokeComponent(pLsComponent->objectId());

注意:当附加到点组件时,底层笔画模式组件的虚线不会被矢量化。要将笔画模式组件与点组件符号一起矢量化,需要创建复合组件。复合组件将在未来的博客文章中讨论。

要使用点组件,请在程序源代码中添加一个额外的包含文件:

#include "DgnLS/DbLSPointComponent.h"

现在,例如,将现有符号组件连接到描边图案组件中的第二个段(这是描边图案中的第一个间隙):

// Set symbol for stroke component gaps
OdDbLSSymbolReference lsRef;
lsRef.setSymbolComponent(pSymComponent->objectId());
lsRef.setJustify(OdDbLSSymbolReference::kLSJustifyCenter);
pPtComponent->insertSymbolForStroke(&lsRef, 1);

此代码中的 OdDbLSSymbolReference 结构表示一组符号参数,例如旋转、偏移、对齐方式和一些附加标志。在此示例中,使用 OdDbLSSymbolReference::setSymbolComponent 方法将符号组件 ID 附加到 OdDbLSSymbolReference 结构。此外,设置对齐方式以在描边图案间隙的中心显示符号。必须设置对齐参数才能为描边附加符号。最后,调用 OdDbLSPointComponent::insertSymbolForStroke 方法将符号附加到点组件。

并将第二个符号组件附加到曲线末端进行矢量化:

// Set symbol for line end
lsRef.setSymbolComponent(pSymComponent->objectId());
lsRef.setJustify(OdDbLSSymbolReference::kLSNoJustify);
pPtComponent->insertSymbolForVertex(&lsRef, OdDbLSSymbolReference::kLSAtEnd);

最后,将我们的点组件附加到 DGN 线型组件字典:

// Add component into LineStyles dictionary
pDict->setAt(OD_T("DemoDgnPointComponent"), pPtComponent);

所有以下代码都在上一篇文章中详细介绍过,用于创建线型定义组件,将其附加到 OdDbLinetypeTableRecord 并创建线实体以测试线型可视化。这里我们再次使用它,但有一个小区别:将新的点线型组件附加到线型定义,而不是描边图案组件。

// Create LineStyle Definition
OdDbLSDefinitionPtr pLSDef = OdDbLSDefinition::createObject();
pLSDef->setComponent(pPtComponent->objectId());
pLSDef->setComponentUID(pPtComponent->componentUID());

// Create Linetype Table Record
OdDbLinetypeTableRecordPtr pLtpRec = OdDbLinetypeTableRecord::createObject();
pLtpRec->setName(OD_T("DemoDgnLineStylePoint"));
pLtpRec->setComments(OD_T("Point 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);

执行代码后生成的线型如下图所示(在不同的缩放级别下):

image1 image2 image3 image4

包含四个螺旋的块显示在每个线型(描边)图案重复处,包含折线箭头的块显示在 OdDbLine 实体的终点处。

点组件创建(完整命令源代码)

#include "DbLinetypeTable.h"
#include "DbLinetypeTableRecord.h"
#include "DbLine.h"
#include "DbHelix.h"
#include "DbPolyline.h"
#include "DbBlockTable.h"
#include "DgnLS/DbLSDefinition.h"
#include "DgnLS/DbLSStrokePatternComponent.h"
#include "DgnLS/DbLSPointComponent.h"
#include "DgnLS/DbLSSymbolComponent.h"
#include "DgnLS/DbLSMisc.h"

static OdDbHelixPtr createHelix(OdGePoint3d location, double radius)
{
  OdDbHelixPtr helPtr = OdDbHelix::createObject();
  helPtr->setStartPoint(location - OdGeVector3d::kZAxis);
  helPtr->setConstrain(OdDbHelix::kTurns);
  helPtr->setBaseRadius(radius);
  helPtr->setTopRadius(radius / 5);
  helPtr->setTurns(4.0);
  helPtr->setAxisVector(OdGeVector3d::kZAxis);
  helPtr->createHelix();
  return helPtr;
}

static OdDbBlockTableRecordPtr createSegmentBlock()
{ const double fBlockScale = 1.0 / 1000.0;
  OdDbBlockTableRecordPtr btrPtr = OdDbBlockTableRecord::createObject();
  btrPtr->appendOdDbEntity(createHelix(OdGePoint3d(-fBlockScale, -fBlockScale, 0.0), fBlockScale));
  btrPtr->appendOdDbEntity(createHelix(OdGePoint3d( fBlockScale, -fBlockScale, 0.0), fBlockScale));
  btrPtr->appendOdDbEntity(createHelix(OdGePoint3d(-fBlockScale,  fBlockScale, 0.0), fBlockScale));
  btrPtr->appendOdDbEntity(createHelix(OdGePoint3d( fBlockScale,  fBlockScale, 0.0), fBlockScale));
  btrPtr->setName(OD_T("4helix"));
  return btrPtr;
}

static OdDbBlockTableRecordPtr createArrowBlock()
{
  const double fBlockScale = 1.0 / 1000.0;
  OdDbPolylinePtr pPl = OdDbPolyline::createObject();
  pPl->addVertexAt(0, OdGePoint2d(-fBlockScale, -fBlockScale));
  pPl->addVertexAt(1, OdGePoint2d(-fBlockScale,  fBlockScale));
  pPl->addVertexAt(2, OdGePoint2d( fBlockScale,  0.0));
  pPl->setClosed(true);
  OdDbBlockTableRecordPtr btrPtr = OdDbBlockTableRecord::createObject();
  btrPtr->appendOdDbEntity(pPl);
  btrPtr->setName(OD_T("arrow"));
  return btrPtr;
}

static OdDbObjectId appendBlock(OdDbDatabase *pDb, OdDbBlockTableRecordPtr btrPtr)
{
  return OdDbBlockTable::cast(pDb->getBlockTableId().openObject(OdDb::kForWrite))->add(btrPtr);
}

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

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

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

  // Create Stroke LineStyle Component
  OdDbLSStrokePatternComponentPtr pLsComponent = OdDbLSStrokePatternComponent::createObject();
  pLsComponent->setComponentType(kLSStrokePatternComponent);
  pLsComponent->setComponentUID(dgnLS_UID);

  // Append strokes
  pLsComponent->insertStroke(0.008)->setDash();
  pLsComponent->insertStroke(0.003)->setGap();
  pLsComponent->insertStroke(0.002)->setDash();
  pLsComponent->insertStroke(0.003)->setGap();

  // Add component into LineStyles dictionary
  OdDbDictionaryPtr pDict = ::oddbDgnLSGetComponentsDictionary(pDb, OdDb::kForWrite, true);
  pDict->setAt(OD_T("DemoDgnLineStyleStrokeComponentForPointComponent"), pLsComponent);

  // Create symbol component for first block
  OdDbLSSymbolComponentPtr pSymComponent = OdDbLSSymbolComponent::createObject();
  pSymComponent->setComponentType(kLSSymbolComponent);
  pSymComponent->setDescription(OD_T("DemoDgnSymbol1"));
  ::oddbDgnLSIncrementUID(dgnLS_UID);
  pSymComponent->setComponentUID(dgnLS_UID);

  // Attach block to symbol component
  pSymComponent->setBlockTableRecord(::appendBlock(pDb, ::createSegmentBlock()));

  // Add component into LineStyles dictionary
  pDict->setAt(OD_T("DemoDgnSymbolForSegment"), pSymComponent);

  // Create Point Component
  OdDbLSPointComponentPtr pPtComponent = OdDbLSPointComponent::createObject();
  pPtComponent->setComponentType(kLSPointComponent);
  ::oddbDgnLSIncrementUID(dgnLS_UID);
  pPtComponent->setComponentUID(dgnLS_UID);

  // Set up stroke component for point component
  pPtComponent->setStrokeComponent(pLsComponent->objectId());

  // Set symbol for stroke component gaps
  OdDbLSSymbolReference lsRef;
  lsRef.setSymbolComponent(pSymComponent->objectId());
  lsRef.setJustify(OdDbLSSymbolReference::kLSJustifyCenter);
  pPtComponent->insertSymbolForStroke(&lsRef, 1);

  // Create symbol component for second block
  pSymComponent = OdDbLSSymbolComponent::createObject();
  pSymComponent->setComponentType(kLSSymbolComponent);
  pSymComponent->setDescription(OD_T("DemoDgnSymbol2"));
  ::oddbDgnLSIncrementUID(dgnLS_UID);
  pSymComponent->setComponentUID(dgnLS_UID);

  // Attach block to symbol component
  pSymComponent->setBlockTableRecord(::appendBlock(pDb, ::createArrowBlock()));

  // Add component into LineStyles dictionary
  pDict->setAt(OD_T("DemoDgnSymbolForLineEnd"), pSymComponent);

  // Set symbol for line end
  lsRef.setSymbolComponent(pSymComponent->objectId());
  lsRef.setJustify(OdDbLSSymbolReference::kLSNoJustify);
  pPtComponent->insertSymbolForVertex(&lsRef, OdDbLSSymbolReference::kLSAtEnd);

  // Add component into LineStyles dictionary
  pDict->setAt(OD_T("DemoDgnPointComponent"), pPtComponent);

  // Create LineStyle Definition
  OdDbLSDefinitionPtr pLSDef = OdDbLSDefinition::createObject();
  pLSDef->setComponent(pPtComponent->objectId());
  pLSDef->setComponentUID(pPtComponent->componentUID());

  // Create Linetype Table Record
  OdDbLinetypeTableRecordPtr pLtpRec = OdDbLinetypeTableRecord::createObject();
  pLtpRec->setName(OD_T("DemoDgnLineStylePoint"));
  pLtpRec->setComments(OD_T("Point 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);
}

今天就开始行动

免费试用 ODA 软件 60 天。
无风险,无需信用卡。

免费试用