在视图显示中,通常会有装饰屏幕或者临时绘制的需求。平台提供了多种方式屏幕装饰及临时绘制的方式供选择:

  • 如果在工具中,即继承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进行注销。