领域对象(BPObject)在BIMBase里边分为图形对象(BPGraphicElement)和非图形数据(BPNonGraphicElement),图形对象尤其重要,用户能够看见的对象基本都是图形对象,比如墙、标高、轴网等。对象是可序列化的,即是可被保存到p3d工程文件中。

3.1.1 相关类图

  • 领域对象类图
    图3-1为领域对象类图,基类BPObject定义了对象的一些通用行为,例如addToProjectdeleteFromProject等。基于BPOBject衍生出来两类对象,一类是图形对象(BPGraphicElement),一类是非图形数据(BPNonGraphicElement)。图形对象主要包括两个主要的内容,一个是图形BPEntity,由model进行管理,一个是数据BPData,由project进行管理。非图形数据只包括数据BPData
    BPGraphic是几何数据的集合,可通过各种几何元素进行构造(线段、弧、曲线集、实体等等),是一种内存数据形式。BPEntity是物理实体,由几何数据生成的一种可持久化的内存数据。


    图3-1 BPObject相关类图
  • 三维图形对象
    三维图形对象类图见图3-2,列出的是一些常用的图形对象,墙、梁、板、柱、房间等。


图3-2 三维图形对象类图
  • 二维对象
    二维对象常用于绘制标注等内容,类图见图3-3。

    图3-3 二维对象类图

注意:本书并没有列出所有的类,而是一些重要的基础类,其它类请参考BIMBase C++ API说明文档.chm。

3.1.2 如何获取对象

BIMBase中的对象都有一个BPDataKey,我们可以通过BPDataKeyBPProject中获取这个元素。一般可通过其它接口获取相应的BPDataKey,然后获取对象。

  • 获取选择的对象
    使用选择集管理类BPSelectionSetManager用户可以获得被选中的元素。
for (int i = 0; i < BPSelectionSetManager::getInstance().getCount(); i++)
{
    BPEntityPtr ptrEntity = BPSelectionSetManager::getInstance().
    getEntityByIndex(i);
    if (ptrEntity.isNull())
        continue;
    BPDataKey key = BPDataUtil::getDataKeyOnEntity(*ptrEntity);
}

代码3-1:通过BPSelectionSetManager获取对象(代码片段)

  • 通过class获取对象
    BIMBase API提供接口通过class获取某个类型的所有对象,具体代码如下所示。
BPProjectP pProject = BPApplication::getInstance().
getProjectManager()->getMainProject();
if (pProject == nullptr)
    return;
pset<BPEntityId> entitySet;
BPEntityUtil::getEntitiesByClass(entitySet, *pProject, L"schemaName", L"className");
for (auto entityId : entitySet)
{
    BPEntity entity(entityId);
    BPDataKey key = BPDataUtil::getDataKeyOnEntity(entity);
}

代码3-2:通过class获取对象(代码片段)

  • 获取某个模型空间的所有对象
    BIMBase API提供接口获取某个模型空间的所有对象,具体代码如下所示。
BPProjectP pProject = BPApplication::getInstance().getProjectManager()->getMainProject();
if (pProject == nullptr)
    return;
pset<BPEntityId> entitySet;
BPEntityUtil::getEntitiesOfModel(entitySet,*pProject,pProject->getActiveModel()->getModelId());
for (auto entityId : entitySet)
{
    BPEntity entity(entityId);
    BPDataKey key = BPDataUtil::getDataKeyOnEntity(entity);
}

代码3-3:获取活动模型空间的所有对象(代码片段)

3.1.3 获取和修改元素参数

  • 获取参数
    元素都有参数,用户可以通过文档查找对象的所有参数条目,然后通过BPObjectgetValue接口获取到元素的参数。
  • 修改参数
    用户可以用BPObjectsetValue接口修改元素的参数。

3.1.4 重要的方法

  • 对象的位置
    通过BPGraphicElementsetPlacement方法,可设置对象的位置,对象的位置包含对象的偏移和旋转信息。
  • 获取对象的图素信息
    通过BPGraphicElementcreatePhysicalGraphics方法,可创建对象的图素信息,用于几何解析和动态绘制。

3.1.5 领域对象的创建

  • 内建对象的创建
    BIMBase图形对象的创建一般使用对象的构造函数,对象构造出来以后,调用addToProject接口将对象添加到相应的工程及模型空间。
BPProjectP pProject = BPApplication::getInstance().
getProjectManager()->getMainProject();
if (pProject == nullptr)
    return;
BPModelBaseP pModel = pProject->getActiveModel();
if (pModel == nullptr)
    return;
//创建线对象
BPModelLine line(GePoint3d::create(3000, 3000, 0), GePoint3d::create(4000, 4000, 0));
//将对象保存到model
::p3d::P3DStatus status = line.addToProject(*pProject, pModel->getModelId());

代码3-4:内建对象的创建(代码片段)

  • 自建对象的创建

当BIMBase中已有对象不能满足用户需求时,用户可通过实现一个继承自BPGraphicElement的类,构造自己的对象,主要分为以下三步:

  1. 创建对象的数据表(schema),用于在工程中保存对象,具体步骤见附录二;
  2. 实现继承自BPGraphicElement的类,见示例代码3-5,3-6;
  3. 注册构件,一般在插件加载时进行注册,例如在插件的dllMain函数中加载。示例代码见3-7;
    示例代码3-8为该自建对象cube的自测函数,类似1.1节的HelloBIMBase命令的注册,打开BIMBase在命令行输入已经注册的命令“CubeDemo”,即可在BIMBase中调出自己所创建的对象(无需写出工具再来调用对象)。

注意:

  • 具体schema文件生成过程请查看附录二
  • schema字段说明见附录三
#pragma once
namespace DemoObject
{
    class CubeDemo;
    typedef CubeDemo const&          CubeDemoCR;
    typedef CubeDemo&                CubeDemoR;
    typedef CubeDemo*                CubeDemoP;
    typedef RefCountedPtr<CubeDemo>  CubeDemoPtr;

    class CubeDemo : public BIMBase::Data::BPGraphicElement
    {
        DefineSuper(BPGraphicElement)
    public:
        CubeDemo();
        ~CubeDemo();
        int    getWidth() const;
        void   setWidth(int nWidth);
        int    getLength() const;
        void   setLength(int nLength);
        int    getHeight() const;
        void   setHeight(int nHeight);
    protected:
        virtual Utf8String _getSchemaName() const override { return PBM_SCHEMA_Demo; };
        virtual Utf8String _getClassName() const override { return PBM_CLASS_CUBE_Demo; };
        //往数据库中写数据
        virtual P3DStatus _copyToData(BPDataR instance, BPProject& project) const override;
        //从数据库中读数据
        virtual P3DStatus _initFromData(BPDataCR instance) override;
        //创建几何造型
        virtual BPGraphicsPtr _createPhysicalGraphics(BPProjectR project,PModelIdCR modelId, bool isDynamics) override;
    private:
        int m_nWidth;
        int m_nHeight;
        int m_nLenght;
        Demo_CREATE(CubeDemo);
    };
    Demo_EXTENSION(CubeDemo);
}

代码3-5:实现自己的构件对象(头文件)

#include "pch.h"
#include "CubeDemo.h"

#define Property_Lenght                          "Length"
#define Property_Width                           "Width"
#define Property_Height                          "Height"

using namespace DemoObject;

CubeDemo::CubeDemo()
{
    m_nLenght = 1000;
    m_nWidth = 200;
    m_nHeight = 3000;
}

CubeDemo::~CubeDemo()
{}
int CubeDemo::getWidth() const {
    return m_nWidth;
}
void CubeDemo::setWidth(int nWidth) {
    m_nWidth = nWidth;
}
int CubeDemo::getLength() const {
    return m_nLenght;
}
void CubeDemo::setLength(int nLength) {
    m_nLenght = nLength;
}
int CubeDemo::getHeight() const {
    return m_nHeight;
}
void CubeDemo::setHeight(int nHeight) {
    m_nHeight = nHeight;
}

::p3d::P3DStatus CubeDemo::_copyToData(BIMBase::Core::BPDataR instance, BIMBase::Core::BPProject& project) const
{
    if (T_Super::_copyToData(instance, project) != P3DStatus::SUCCESS)
        return ERROR;

    P3DStatus status;
    status = instance.setValue(Property_Lenght, BPValue(this->getLength()));
    if (P3DStatus::SUCCESS != status)
        return ERROR;

    status = instance.setValue(Property_Width, BPValue(this->getWidth()));
    if (P3DStatus::SUCCESS != status)
        return ERROR;

    status = instance.setValue(Property_Height, BPValue(this->getHeight()));
    if (P3DStatus::SUCCESS != status)
        return ERROR;

    return SUCCESS;
}

::p3d::P3DStatus CubeDemo::_initFromData(BIMBase::Core::BPDataCR instance)
{
    if (T_Super::_initFromData(instance) != P3DStatus::SUCCESS)
        return ERROR;

    BPValue value;
    P3DStatus status;

    status = instance.getValue(value, Property_Lenght);
    if (P3DStatus::SUCCESS != status)
        return ERROR;
    setLength(value.getInteger());

    status = instance.getValue(value, Property_Width);
    if (P3DStatus::SUCCESS != status)
        return ERROR;
    setWidth(value.getInteger());

    status = instance.getValue(value, Property_Height);
    if (P3DStatus::SUCCESS != status)
        return ERROR;
    setHeight(value.getInteger());

    return SUCCESS;
}

BPGraphicsPtr CubeDemo::_createPhysicalGraphics(BPProjectR project, PModelIdCR modelId, bool isDynamics)
{
    BPModelPtr ptrModel = project.getModelById(modelId);
    if (ptrModel.isNull())
        return nullptr;

    BPGraphicsPtr ptrGraphic = ptrModel->createPhysicalGraphics();
    if (ptrGraphic.isNull())
        return nullptr;

    int nWidth = getWidth();
    int nLength = getLength();
    int nHeight = getHeight();

    //绘制底部外轮廓
    pvector<GePoint3d> pts;
    pts.push_back(GePoint3d::create(0, -nWidth / 2, 0));
    pts.push_back(GePoint3d::create(nLength, -nWidth / 2, 0));
    pts.push_back(GePoint3d::create(nLength, nWidth / 2, 0));
    pts.push_back(GePoint3d::create(0, nWidth / 2, 0));
    pts.push_back(GePoint3d::create(0, -nWidth / 2, 0));
    GeCurveArrayPtr ptrOutLines = GeCurveArray::createLinestringArray(pts, GeCurveArray::BOUNDARY_TYPE_Outer);

    //向Z方向拉伸
    GeVec3d vec = GeVec3d::create(0, 0, nHeight);
    GeExtrusionInfo extrData(ptrOutLines, vec, true);
    IGeSolidBasePtr ptrExtrusion = IGeSolidBase::createGeExtrusion(extrData);
    ptrGraphic->addGeSolidBase(*ptrExtrusion);
    return ptrGraphic;
}


代码3-6:实现自己的构件对象(源文件)

//注册运行时类型判断
BPObjectExtensionManager::getInstance().registerBPObjectExtension(PBM_SCHEMA_DEMO,PBM_CLASS_CUBE_DEMO, new CubeDemoExtension());

代码3-7:注册自己的构建对象

void CubeDemoFun()
{
    BPProjectP pProject = BPApplication::getInstance().getProjectManager()->getMainProject();
    if (pProject == nullptr)        
        return;
    BPModelBaseP pModel = pProject->getActiveModel();
    if (pModel == nullptr)        
        return;    
    PModelId modelId = pModel->getModelId();
    DemoObject::CubeDemo pcube;    
    pcube.setWidth(2000);    
    pcube.setLength(3000);    
    pcube.setHeight(800);    
    pcube.addToProject(*pProject, modelId);    
    BPViewportP pViewPort = BPViewManager::getInstance().getActivedViewport();    
    if (NULL == pViewPort) 
        return ;    
    if (pViewPort)    
    {        
        pViewPort->updateView();    
    }
}
AutoDoRegisterFunctionsBegin
BPToolsManager::registerFun(_T("CubeDemo"), &CubeDemoFun);
AutoDoRegisterFunctionsEnd

代码3-8:立方体造型自测函数

示例代码3-4,3-5,3-6实现了一个自定义的立方体构件,如图3-4所示,通过立方体的长、宽、高进行构造。
注意:代码3-6中的Length、Width与Height需要在schema中Class属性定义,否则代码无法运行。
示例代码3-7对象的注册是必不可少的,主要用于在BPObjectExtensionManager中获取自己的构件,如实现对象属性中需要用到,对象的注册需要在工程启动时就进行。


图3-4 立方体构件

示例代码3-5,3-6实现继承自BPGraphicElement的类CubeDemoCubeDemo类中主要完成了如下几个工作:

  • 定义长、宽、高三个属性及其getset接口。
  • copyToData中实现保存属性值到数据,在initFromData中实现从数据中初始化属性值。
  • 重写BPGraphicElement中的_createPhysicalGraphics接口,根据CubeDemo的Length、Width、Height构造立方体图形。

至此,自建对象CubeDemo构造完毕,可同内建对象一样通过addToProject接口保存到工程中。