在BIMBase中,对象的编辑有以下几种方法:
- 右键菜单及编辑菜单栏中的移动、复制、镜像、删除功能。对于用户自建对象,需用户代码实现移动、复制、镜像、删除功能;
- 夹点拖拽功能,用户自建对象需代码实现;
- 属性编辑功能,用户自建对象需代码实现;
3.2.1 移动
对于自建对象,需实现自己的复制功能,可通过重写IToolMove
类实现,IToolMove
类提供的接口如表3-1所示。
表3-1 IToolMove类接口
方法 | 描述 |
---|---|
ElementsSelected(vector |
过滤选择对象接口 |
Dynamic(vector |
动态预览接口 |
Move(vector |
实现移动效果接口 |
CacheDynamic() | 是否使用默认动态效果 |
class ToolCubeMoveDemo:public IToolMove
{
public:
ToolCubeMoveDemo();
~ToolCubeMoveDemo();
//选中需要移动的构件后响应
virtual void ElementsSelected(vector<BPEntityPtr> & refps) override;
//如果返回false则会调用自定义Dynamic函数,调自定义函数时最好不要是
//计算密集型操作
virtual bool CacheDynamic() override { return true; }
//动态移动物体时响应函数,需要CacheDynamic为false时函数启动
virtual void Dynamic(std::vector<BPEntityPtr> const & refps, GeTransformCR transform, BPRedrawEntitys& redrawElems) override;
//移动完构件点击布置时响应函数
virtual void Move(std::vector<BPEntityPtr> const & refps, GeTransformCR transform) override;
};
代码3-9:立方体移动(头文件)
#include "pch.h"
#include "ToolCubeMoveDemo.h"
#include "CubeDemo.h"
ToolCubeMoveDemo::ToolCubeMoveDemo()
{}
ToolCubeMoveDemo::~ToolCubeMoveDemo()
{}
void ToolCubeMoveDemo::Dynamic(std::vector<BPEntityPtr> const & refps, GeTransformCR transform, BPRedrawEntitys& redrawElems){}
void ToolCubeMoveDemo::Move(std::vector<BPEntityPtr> const & refps, GeTransformCR transform)
{
for (BPEntityPtr refP : refps)
{
if (refP.isNull())
continue;
//根据传入的BPEntity信息获取对象实例
BPDataPtr ptrData = BPDataUtil::getDataOnEntity(*refP);
if (!ptrData.isValid())
continue;
DemoObject::CubeDemo pbCube;
pbCube.initFromData(*ptrData);
//选中的墙乘以移动的转换矩阵,移动到点击的位置
pbCube.onTransform(transform);
//新位置的替换旧位置的
pbCube.replaceInProject(*refP->getBPProject());
}
}
void ToolCubeMoveDemo::ElementsSelected(std::vector<BPEntityPtr> & refps)
{}
//注册移动
class CubeMoveDemoFactory :public IToolInterfaceFactory
{
public:
virtual IToolInterface* CreateInterface() override
{
ToolCubeMoveDemo *p = new ToolCubeMoveDemo();
p->AddRef();
return p;
}
};
static CubeMoveDemoFactory s_CubeMoveDemoFactory;
AutoDoRegisterFunctionsBegin
PBBimToolsInterfaceManager::RegisterFactory("CubeDemo",IToolNameMove,&s_CubeMoveDemoFactory);
AutoDoRegisterFunctionsEnd
代码3-10:立方体移动(源文件)
示例代码3-9,3-10展示了Cube
移动实现的部分代码,主要通过重写Move
接口实现Cube
的移动。对象移动类采用工厂模式进行管理,需要将当前对象的移动工厂利用PBBimToolsInterfaceManager
类进行注册。
3.2.2 复制
复制功能同移动功能,可重写类IToolCopy
实现。
3.2.3 镜像
镜像功能同移动功能,可重写类IToolMirror
实现。
3.2.4 删除
删除功能同移动功能,可重写类IToolDelete
实现。
3.2.5 夹点
夹点功能可实现构件的自由拖拽,如图3-5所示,拖拽选中构件后显示的夹点,可自由编辑构件。

图3-5 CubeTest夹点
对于用户自建对象,可按需要实现夹点功能。实现夹点功能步骤如下:
- 在插件加载入口
DllMain
函数中注册对象的夹点,详见代码3-11; - 继承类
BPPointDragManipulator
并重写_onCreateControls
和_doDragControls
接口可实现增加夹点及夹点拖拽效果的实现,详见代码3-12,3-13; - 继承类
IBPDragManipulatorExtension
,注册夹点实现类,需重写_getIDragManipulator
接口,返回上一步骤实现的类,详见代码3-14。
//注册造型夹点
std::wstring classname = std::wstring(L"DemoSchema").append(L":").append(L"CubeDemo");
BPManipulatorExtensionManager::registerDragManipulatorExtension(classname.c_str(), new MyCubeDragManipulatorDemoExtension());
代码3-11:立方体夹点注册
class MyCubeDragManipulatorDemo : public BPPointDragManipulator
{
DefineSuper(BPPointDragManipulator)
public:
static MyCubeDragManipulatorDemo* Create();
protected:
MyCubeDragManipulatorDemo();
~MyCubeDragManipulatorDemo();
protected:
//增加夹点控制点
virtual bool _onCreateControls(::BIMBase::Core::BPEntityCR) override;
//实现拖拽夹点构件变化效果
virtual StatusInt _doDragControls(BPEntityR elHandle, BPBaseButtonEventCR ev, bool isDynamics) override;
};
代码3-12:立方体夹点实现(头文件)
#include "pch.h"
#include "MyCubeDragManipulatorDemo.h"
#include "CubeDemo.h"
using namespace DemoObject;
MyCubeDragManipulatorDemo::MyCubeDragManipulatorDemo()
{}
MyCubeDragManipulatorDemo::~MyCubeDragManipulatorDemo()
{}
bool MyCubeDragManipulatorDemo::_onCreateControls (::BIMBase::Core::BPEntityCR eh)
{
//根据传入的BPEntity信息获取对象实例
BIMBase::Core::BPDataPtr ptrData = BPDataUtil::getDataOnEntity(eh);
if (!ptrData.isValid())
return false;
//根据根据实例初始化
DemoObject::CubeDemo pbCube;
pbCube.initFromData(*ptrData);
GePoint3d startPt, endPt, midPt;
startPt = pbCube.getStartPoint();
endPt = pbCube.getEndPoint();
midPt = pbCube.getMiddlePoint();
// 基础数据
double height = pbCube.getHeight();
addControlPoint(startPt);
addControlPoint(endPt);
addControlPoint(midPt);
return true;
}
StatusInt MyCubeDragManipulatorDemo::_doDragControls(BPEntityR elHandle,BPBaseButtonEventCR ev, bool isDynamics)
{
//根据传入的BPEntity信息获取对象实例
BPDataPtr ptrData = BPDataUtil::getDataOnEntity(elHandle);
if (!ptrData.isValid())
return false;
//根据实例初始化
CubeDemo pbCube;
pbCube.initFromData(*ptrData);
//获取点击夹点后鼠标点
GePoint3d cursorPt = GePoint3d::create(0, 0, 0);
_getAdjustedPoint(cursorPt, ev);
//获取点击夹点的编号,编号根据加入夹点的顺序确定
GePoint3d m_orginPt;
SIZE_T index = -1;
for (SIZE_T i = 0; i < m_controls.m_locations.size(); i++)
{
if (CONTROL_STATE_Flashed == m_controls.m_locations[i]->m_state)
{
m_orginPt = m_controls.m_locations[i]->m_point;
index = i;
break;
}
}
if (index < 0)
return ERROR;
cursorPt.z = m_orginPt.z;
//长度方向中点设置为移动点,端点设置为拖拽点
if (index != 2)
{
//通过转换矩阵获取原点及坐标信息
GeTransform curTm = pbCube.getPlacement().toTransform();
GePoint3d ptOri;
GeVec3d vecX, vecY, vecZ;
curTm.getOriginAndVectors(ptOri, vecX, vecY, vecZ);
double dLenNew = pbCube.getLength();
GeVec3d vecXNew = vecX;
GePoint3d ptOriNew = ptOri;
if (index == 0)
{//起点
//根据新起点重新计算墙长度及坐标系
GePoint3d ptEnd = pbCube.getEndPoint();
dLenNew = cursorPt.distance(ptEnd);
vecXNew = GeVec3d::createByStartEndNormalize(cursorPt, ptEnd);
ptOriNew = cursorPt;
}
else
{//终点
//根据新的终点重新计算长度及坐标系
dLenNew = cursorPt.distance(ptOri);
vecXNew = GeVec3d::createByStartEndNormalize(ptOri, cursorPt);
}
GeVec3d vecYNew = vecZ^vecXNew;
//根据新计算的坐标及原点得到转换矩阵
GeTransform transNew = GeTransform::createByOriginAndVectors(ptOriNew, vecXNew, vecYNew, vecZ);
BPPlacement placNew;
placNew.fromTransform(transNew);
//墙设置新的转换矩阵,转换到新的位置
pbCube.setPlacement(placNew);
pbCube.setLength(dLenNew);
}
else
{
//根据鼠标移动点与原始点求转换矩阵
GePoint3d offset = { cursorPt.x - m_orginPt.x, cursorPt.y - m_orginPt.y, cursorPt.z - m_orginPt.z };
GeTransform tm = GeTransform::create(offset);
pbCube.onTransform(tm);
}
::BIMBase::PModelId curModelId = ev.getViewport()->getTargetModel()->getModelId();
BIMBase::Core::IBPProjectManagerP pProjectManager = BIMBase::Core::BPApplication::getInstance().getProjectManager();
if (pProjectManager == nullptr)
return ERROR;
BPProjectP pProject = pProjectManager->getMainProject();
if (pProject == nullptr)
return ERROR;
if (isDynamics)
{//动态显示
BPGraphicsPtr ptrGraphics= pbCube.createPhysicalGraphics(*pProject, curModelId, true);
GeTransform trans = pbCube.getPlacement().toTransform();
BPGraphicsUtils::transformPhysicalGraphics(*ptrGraphics, trans);
if (ptrGraphics.isValid())
{
elHandle = ptrGraphics->getEntityR();
}
}
else
{//最终点击后Replace
return pbCube.replaceInProject(*pProject);
}
return SUCCESS;
}
MyCubeDragManipulatorDemo* MyCubeDragManipulatorDemo::Create()
{
return new MyCubeDragManipulatorDemo();
}
代码3-13:立方体夹点实现(源文件)
class MyCubeDragManipulatorDemoExtension : public ::BIMBase::Data::IBPDragManipulatorExtension
{
protected:
virtual BPIDragManipulatorP _getIDragManipulator (::BIMBase::Core::BPEntityCR elHandle, ::BIMBase::Core::BPPickDataCP path) override
{
//返回自己的夹点类
return MyCubeDragManipulatorDemo::Create();
}
};
代码3-14:注册夹点实现类
需要指出,运行当前夹点功能,需要对CubeDemo文件进行修改,主要是对获取立方体的起点、中点、终点进行了封装,获取的是世界坐标系下的点。修改代码如下:
//获取起点
GePoint3d getStartPoint() const;
//获取中点
GePoint3d getMiddlePoint() const;
//获取终点
GePoint3d getEndPoint() const;
代码3-15:CubeDemo头文件补充
GePoint3d DemoObject::CubeDemo::getStartPoint() const
{
//通过转换矩阵获取原点
return getPlacement().getOrigin();
}
GePoint3d DemoObject::CubeDemo::getMiddlePoint() const
{
GePoint3d ptMiddle = GePoint3d::create(getLength() / 2.0, 0, 0);
//墙局部坐标系转到世界坐标系下
GeTransform trans = getPlacement().toTransform();
trans.multiply(ptMiddle);
return ptMiddle;
}
GePoint3d DemoObject::CubeDemo::getEndPoint() const
{
GePoint3d ptEnd = GePoint3d::create(getLength(), 0, 0);
//墙局部坐标系转到世界坐标系下
GeTransform trans = getPlacement().toTransform();
trans.multiply(ptEnd);
return ptEnd;
}
代码3-16:CubeDemo源文件补充
3.2.6 属性
对于自建对象,用户可通过重写IToolProperty
类实现自建对象的属性功能,如图3-6所示,在属性栏显示Cube的属性长度、宽度、高度,并可通过修改属性值驱动对象变化。

图3-6 CubeDemo属性展示
示例代码3-15,3-16展示了Cube属性实现的部分代码,其中OnPropertyGet
中实现从对象获取属性显示在属性栏的功能,OnPropertySet
实现在属性栏修改属性,驱动对象修改的功能。属性类采用工厂模式进行管理,需要将当前对象的属性工厂利用PBBimToolsInterfaceManager
类进行注册。
若属性代码实现后没有调出属性功能,可参见示例代码3-7对象的注册,查看是否对自己的构件实现了注册。
class MyCubePropertyDemo :public IToolProperty
{
enum CubePropName
{
Length, //长度
Height, //高度
Width, //宽度
CubePropCount
};
public:
MyCubePropertyDemo();
~MyCubePropertyDemo();
//获取属性并且在属性框显示
virtual void OnPropertyGet(std::vector<BPEntityP> const & refps, PBBimUIProperyList& lst) override;
//设置属性框中的值
virtual TIErrorStatus OnPropertySet(std::vector<BPEntityP> const & refps, int index, PBBimUIPropertyItem const & item) override;
};
代码3-17:立方体属性(头文件)
#include "pch.h"
#include "MyCubePropertyDemo.h"
#include "CubeDemo.h"
MyCubePropertyDemo::MyCubePropertyDemo()
{}
MyCubePropertyDemo::~MyCubePropertyDemo()
{}
void MyCubePropertyDemo::OnPropertyGet(std::vector<BPEntityP> const & refps, PBBimUIProperyList& lst)
{
//选择集中的对象的个数
if (refps.size() == 0)
return;
BPEntityId eleId;
std::vector<IBPObjectPtr> pbObjs;
BPProjectP pProject = nullptr;
for (auto elementRef : refps)
{
if (NULL == pProject)
{
pProject = elementRef->getBPProject();
if (pProject == NULL)
continue;
}
IBPObjectPtr ptrPbObj = BPObjectExtensionManager::getInstance().getBPObject(*elementRef);
if (!ptrPbObj.isValid())
continue;
pbObjs.push_back(ptrPbObj);
}
if (pbObjs.size() < 1)
return;
PBBimUIPropertyItem properties[CubePropName::CubePropCount];
for (int i = 0; i < pbObjs.size(); ++i)
{
IBPObjectPtr ptrObj= pbObjs.at(i);
DemoObject::CubeDemoP pCube = dynamic_cast< DemoObject::CubeDemoP>(ptrObj.get());
if (NULL == pCube)
continue;
// -----------------长度--------------------
{
int nLength = pCube->getLength();
if (0 == i)
{
PBBimUIPropertyItem item(L"长度", nLength);
properties[CubePropName::Length].swap(item);
}
else
{
PBBimUIPropertyItem *oldItem = &properties[CubePropName::Length];
if (!oldItem->multiValue())
{
PBBimUIPropertyItem::ListValue oldType;
int oldLength;
oldItem->getValue(oldLength);
if (oldLength != nLength)
properties[CubePropName::Length].setMultiValue(true);
}
}
}
}
lst.AppendGroup(L"构件属性");
for (int i = 0; i < CubePropName::CubePropCount; ++i)
{
lst.Append(i+1, properties[i]);
}
}
TIErrorStatus MyCubePropertyDemo::OnPropertySet(std::vector<BPEntityP> const & refps, int index, PBBimUIPropertyItem const & item)
{
BPProjectP pProject = NULL;
std::vector<IBPObjectPtr> pbObjs;
for (auto elementRef : refps)
{
if (NULL == pProject)
{
pProject = elementRef->getBPProject();
if (pProject == NULL)
continue;
}
IBPObjectPtr ptrObj = BPObjectExtensionManager::getInstance().getBPObject(*elementRef);
if (!ptrObj.isValid())
continue;
pbObjs.push_back(ptrObj);
}
if (pbObjs.size() < 1)
return TIErrorStatus::failed;
for (int indexGj = 0; indexGj < pbObjs.size(); ++indexGj)
{
IBPObjectPtr ptrObj= pbObjs.at(indexGj);
DemoObject::CubeDemoP pCube = dynamic_cast< DemoObject::CubeDemo*>(ptrObj.get());
if (pCube == nullptr)
continue;
switch (index-1)
{
case CubePropName::Length:
{
int nLen = 0;
item.getValue(nLen);
pCube->setLength(nLen);
}
break;
default:
break;
}
pCube->replaceInProject(*pProject);
}
return TIErrorStatus::succeed;
}
class CubePropertyFactoryDemo :public IToolInterfaceFactory
{
public:
virtual IToolInterface* CreateInterface() override
{
MyCubePropertyDemo *p = new MyCubePropertyDemo();
p->AddRef();
return p;
}
};
static CubePropertyFactoryDemo s_CubePropertyFactory;
AutoDoRegisterFunctionsBegin
PBBimToolsInterfaceManager::RegisterFactory("CubeDemo", IToolNameProperty,&s_CubePropertyFactory);
AutoDoRegisterFunctionsEnd
代码3-18:立方体属性(源文件部分代码)