本文是关于在 .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);
这组笔画和间隙生成以下线型:
现在我们可以创建一个新的点组件(此代码是创建所有 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);
执行代码后生成的线型如下图所示(在不同的缩放级别下):
包含四个螺旋的块显示在每个线型(描边)图案重复处,包含折线箭头的块显示在 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);
}