在视图显示中,通常会有装饰屏幕或者临时绘制的需求。平台提供了多种方式屏幕装饰及临时绘制的方式供选择:
- 如果在工具中,即继承
BPPrimitiveTool
或者BPEntitySelectSetTool
工具基类,可重写基类方法_decorateScreen(BPViewport)
来实现屏幕装饰,屏幕装饰的内容通常不能选中及捕捉。 - 基于
BPViewDecoration
的派生类,通过registerViewDecoration
来注册绘制装饰类,这样获得时机绘制屏幕装饰,此装饰类仅是显示层面的绘制,没有数据,不支持捕捉、选择、高亮。 - 基于
BPViewTransition
的派生类,通过registerViewTransient
来注册动态绘制,这样获得在视图中临时绘制的机会,此动态绘制可以达到屏幕装饰的效果。但是动态绘制类是有数据的,这个数据不会持久化存储到文件,可以支持捕捉、选择、高亮这些交互操作。
代码5-3展示了通过派生BPViewDecoration
类实现视图装饰的过程。
bool ViewDecorationDemo::_drawDecoration(BPViewportR viewport)
{
int nView = viewport.GetViewNumber();
BPViewDrawP pOutput = viewport.getIViewDraw();
if (pOutput == nullptr)
return false;
//随着屏幕缩放可改变--------------------改变大小及位置
GePoint3d ptOri = GePoint3d::create(0, 0, 0);
GeVec3d vec = GeVec3d::create(1, 1, 0);
GePoint3d ptEnd = ptOri + vec * 2000;
IGeCurveBasePtr ptrLine = IGeCurveBase::createSegment(GeSegment3d::create(ptOri, ptEnd));
if (ptrLine.isNull())
return false;
GeCurveArrayPtr ptrCurve = GeCurveArray::create(GeCurveArray::BOUNDARY_TYPE_Outer, ptrLine);
if (ptrCurve.isNull())
return false;
pOutput->setSymbology(RGB(255, 0, 0), RGB(255, 0, 0), 2, 0);
pOutput->drawGeCurveArray(*ptrCurve, true);
//不随屏幕缩放而改变------------------------固定大小及位置
p3d::GeRect rect;
viewport.getViewRect(rect);
//获取线条位置
GePoint3d ptPlaceStart = viewport.viewToWorld(GePoint3d::create(rect.left() + (rect.right() - rect.left()) / 2, rect.bottom() - (rect.bottom() - rect.top()) / 20
, 0));
GePoint3d ptPlaceEnd = viewport.viewToWorld(GePoint3d::create(rect.left(), rect.bottom()(rect.bottom() - rect.top()) / 20, 0));
IGeCurveBasePtr ptrLine3 = IGeCurveBase::createSegment(GeSegment3d::create(ptPlaceStart,
ptPlaceEnd));
if (Line3.isNull())
return false;
GeCurveArrayPtr ptrCurve3 = GeCurveArray::create(GeCurveArray::BOUNDARY_TYPE_Outer, ptrLine3 );
if (ptrCurve3.isNull())
return false;
output->setSymbology(RGB(0, 255, 0), RGB(0, 255, 0), 2, 0);
output->drawGeCurveArray(*ptrCurve3, true);
//不随屏幕缩放而改变------------------------固定大小
//获取旋转矩阵
GeRotMatrix rotMatrix = viewport.getRotation();
GeVec3d vtX, vtY;
rotMatrix.getRow(vtX, 0);
rotMatrix.getRow(vtY, 1);
GePoint3d ptOri2 = GePoint3d::create(0, 500, 0);
GePoint3d ptOri2View = viewport.worldToView(ptOri2);
GePoint3d ptEnd2View = ptOri2View - vtY * 50 + vtX*50;
GePoint3d ptEnd2 = viewport.viewToWorld(ptEnd2View);
IGeCurveBasePtr ptrLine2 = IGeCurveBase::createSegment(GeSegment3d::create(ptOri2, ptrLine2));
if (ptrLine2.isNull())
return false;
GeCurveArrayPtr ptrCurve2 = GeCurveArray::create(GeCurveArray::BOUNDARY_TYPE_Outer, ptrLine2);
if (ptrCurve2.isNull())
return false;
output->setSymbology(RGB(0, 0, 255), RGB(0, 0, 255), 2, 0);
output->drawGeCurveArray(*ptrCurve2, true);
return true;
}
代码5-3:视图装饰
在上述示例代码中,实现了三种形式的屏幕装饰,第一种就是绘制的装饰线条可以随着缩放改变大小及位置。第二种是绘制的装饰线条不能改变大小及位置,直接固定在屏幕中的。第三种是绘制的装饰线条可以改变线条的位置,但是不能改变线条的大小。实现这三种形式主要借助的是视图坐标与世界坐标的转换,根据相应的比例,对坐标值进行相应的变换
这段代码只是实现了需要绘制的内容,如果要启动这个绘制内容,需要对编写的派生类进行注册,注册的时机由自己确定,一旦进行注册,drawDecoration
函数会一直进入,如果不想再进行屏幕装饰,使用unregisterViewDecoration
进行注销。