剖切出图是实际工程的常用需求,BIMBase SDK的剖切接口简单易用,能快速实现不同的剖切需求。

[BPExternalCommandAttribute(name = "CuttingDemo")]
public class CuttingToolDemo : IBPPointCommand
{
    int mcount = 0;
    GeTransform mSectionBox = GeTransform.createIdentityMatrix();
    GePlane3d mplane;
    public CuttingToolDemo()
    {
    }
    public override void onPostInstall()
    {
        mcount = 0;
        BPMessageCenter.sendMessage("当前默认剖切平面为xy平面");
        BPMessageCenter.sendMessage("按shift 键切换剖切平面");
        BPMessageCenter.sendMessage("左键进行剖切");
    }
    public override bool onLeftClick(BPCommandContext context)
    {
        BPDocument doc = BPApplication.singleton().activeDocument;
        BPModel model = doc.modelManager.activeModel;
        //获取剖切的对象
        List<BPGraphics> gras = BPGraphicUtil.getGraphicsOfModel(doc,
        model);
        //确定剖切范围,范例所用剖切范围为所有对象的包围盒
        GeRange3d range = GeRange3d.createByNull();
        foreach (var gra in gras)
        {
            range.extendRange(gra.range);
        }
        GeTransform tm = createCuttingBoxAndPlane(range);
        //进行剖切
        BPHideLineEntity data = new BPHideLineEntity(gras, mplane, mSectionBox);
        Dictionary < int, BPClassifyHideLineData> res = data.getClassifyHideLineResult();
        //展示剖切结果,剖切线为实线,投影线为虚线
        BPModelId modelId = new BPModelId();
        doc.modelManager.createNewModel(modelId,"剖切结果",BPModelType.enSheet);
        doc.viewManager.displayModelOnViewPort(modelId, doc.viewManager.getActiveIndex());
        BPModel newModel = doc.modelManager.getModelById(modelId);
        BPGraphics graphic = new BPGraphics(newModel);
        BPGeSymbology symb = new BPGeSymbology { color = System.Drawing.Color.Black, style = 2, weight = 1 };
        foreach (var lineData in res.Values)
        {
            foreach (var listCurve in lineData.sliceCurve)
            {
                foreach (var curve in listCurve)
                {
                    GeCurveArray cur = curve.curve; cur.setByTransform(tm);
                    graphic.addCurveVector(cur);
                }
            }
            foreach (var curve in lineData.projectCurve)
            {
                GeCurveArray cur = curve.curve; cur.setByTransform(tm);
                graphic.addCurveVector(cur,symb, 0);
            }
        }
        graphic.save();
        return true;
    }
    public override bool onRightClick(BPCommandContext context)
    {
        callExitTool();
        return true;
    }
    public override bool onKeyDown(BPVirtualKey key,bool shiftIsDown, bool ctrlIsDown)
    {
        if (key == BPVirtualKey.enShift)
        {
            mcount++;
            if (mcount > 2)
            {
                mcount = mcount - 3;
            }
            if (mcount == 0)
            {
                BPMessageCenter.sendMessage("当前剖切平面为xy 平面");
            }
            else if (mcount == 1)
            {
                BPMessageCenter.sendMessage("当前剖切平面为yz平面");
            }
            else
            {
                BPMessageCenter.sendMessage("当前剖切平面为xz平面");
            }
            BPMessageCenter.sendMessage("左键进行剖切");
        }
        return true;
    }
    public GeTransform createCuttingBoxAndPlane(GeRange3d range)
    {
        GeTransform tm = GeTransform.createIdentityMatrix();
        BPPlacement placement = new BPPlacement();
        if (mcount == 0)//将xy 平面作为剖切面
        {
            GeVec3d dirX = GeVec3d.createByStartEnd(range.high,new GePoint3d(range.low.x,range.high.y,range.high.z));
            GeVec3d dirY = GeVec3d.createByStartEnd(range.high, new GePoint3d(range.high.x,range.low.y,range.high.z));
            GeVec3d dirZ = GeVec3d.createByStartEnd(range.high, new GePoint3d(range.high.x,range.high.y,range.low.z));
            GeVec3d dir = GeVec3d.createByStartEndNormalize(range.high, new GePoint3d(range.high.x,range.high.y,range.low.z));
            mplane = new GePlane3d(range.high - new GePoint3d(0,0,200), dir);
            mSectionBox = GeTransform.createByOriginAndVectors(range.high, dirX, dirY, dirZ);
        }
        else if (mcount == 1)//将yz平面作为部切面
        {
            //yz 平面的部切面
            GePoint3d ypt = new GePoint3d(0,(range.high.y - range.low.y),0);
            GePoint3d zpt = new GePoint3d(0, 0, (range.high.z - range.low.z));
            GeVec3d y = ypt.asVector();
            GeVec3d z = zpt.asVector();
            //yz平面,要遵守右手法则,当平面法向量为正时,把 yz 平面的y要作为构造剖切盒子的x,z要作为构造剖切盒子的y,然后剖切盒子的z要和平面的法向同向
            //当平面法向量为负时,把 yz 平面的z要作为构造剖切盒子的x,y要作为构造剖切盒子的y,这里以法向为正为例
            GeVec3d yzdirX = y;
            GeVec3d yzdirY = z;
            GeVec3d yzdir = GeVec3d.createByStartEndNormalize(range.low, new GePoint3d(range.high.x, range.low.y,range.low.z));
            GeVec3d yzdirZ = GeVec3d.createByStartEnd(range.low, new GePoint3d(range.high.x,range.low.y,range.low.z));
            mplane = new GePlane3d(range.low,yzdir);
            mSectionBox = GeTransform.createByOriginAndVectors(range.low, yzdirX, yzdirY, yzdirZ);
            yzdirZ.negate();//如果是yz 平面,求逆方向
            GePoint3d pt = new GePoint3d(0, 0, 0);
            placement.setPlacement(pt, yzdirZ.point3d(), 0);
            tm = placement.toTransform();
            tm.setByInverse(tm);
        }
        else//将xz平面作为剖切面
        {
            //xz平面的剖切面
            GePoint3d xpt1 = new GePoint3d((range.high.x - range.low.x), 0, 0);
            GePoint3d zpt1 = new GePoint3d( 0, 0,(range.high.z - range.low.z));
            GeVec3d x1 = xpt1.asVector(); GeVec3d z1 = zpt1.asVector();
            //xz平面,要遵守右手法则,当平面法向量为正时,把xz平面的要作为构造剖切盒子的x,x要作为构造剖切盒子的y,然后剖切盒子的z要私平面的法向同向
            //当平面法向量为负时,把xz平面的x要作为构造剖切盒子的x,z要作为构造剖切盒子的y,这里以法向为正为例
            GeVec3d xzdirX = z1; 
            GeVec3d xzdirY = x1;
            GeVec3d xzdir = GeVec3d.createByStartEndNormalize(range.low, new GePoint3d(range.low.x, range.high.y, range.low.z));
            GeVec3d xzdirZ = GeVec3d.createByStartEnd(range.low, new GePoint3d(range.low.x,range.high.y,range.low.z));
            mplane = new GePlane3d(range.low, xzdir); mSectionBox =
    GeTransform.createByOriginAndVectors(range.low, xzdirX, xzdirY,xzdirZ);
            xzdirZ.negate();//如果是xz平面,求逆方向
            GePoint3d pt = new GePoint3d(0,0,0);
            placement.setPlacement(pt, xzdirZ.point3d(), 0);
            tm = placement.toTransform();
            tm.setByInverse(tm);
        }
        return tm;
    }
}

代码9-6 剖切范例代码

示例代码9-6为剖切范例代码。首先拿到当前模型中所有的构件,然后确定所有构件的包围盒为剖切范围,以所有模型的range为剖切盒子。图9-4为剖切盒子在Z方向的顶面为剖切面进行剖切的效果图。

图9-4 剖切效果图