剖切出图是实际工程的常用需求,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 剖切效果图