Revit二次开发中经常会用到布尔运算,RevitAPI自带的BooleanOperationsUtils的Union(合并)、intersect(相交)、difference(相减)是其中的主要函数。
但是自Revit2017起,大量开发工程师都反馈这个布尔运算非常容易出错,只要处理的几何体出现一点细微问题,就会报错,导致程序崩溃。如下提示:

根据提示只能知道这是由于几何不精确引起的,但是没有进一步说明,也没有提示出问题的位置,令开发人员非常困惑。
笔者经过反复研究与测试,发现了一套方法可以解决此类问题,并提升了系统布尔运算的适用性。现将方法列出来供同样有需求的开发人员一起使用。
首先是这类错误的原因。错误提示中说得非常模糊,但是实际操作下来发现,基本都是由于进行布尔运算的两个实体存在着局部的点、线、面出现“伪重叠”。所谓“伪重叠”也就是看上去是在同一个位置,但是实际上在空间中存在着微小的距离。这个微小的距离,导致了布尔运算后形成的实体存在极小尺度的边线,而Revit不允许有小于0.7mm的线段,从而出错。
要解决这一问题,目前查阅大量资料没发现直接有效的解决方法。笔者目前发现了一种简单易行,略微影响精确度但是对于大部分场景都可以接受的方法。具体思路如下:
(1)两个几何体存在“伪重叠”,需要进行调整以消除伪重叠;
(2)修正几何体形状难度很大,很多几何体都有几十、几百个面,上千线条,要进行“伪重叠”部位分析并修正几乎不可能。所以笔者采用了微移动的方法,即整体旋转、平移或者两者结合的方法,对其中一个实体进行调整;
(3)调整后的结合体再进行布尔运算;
(4)如果出错,再重复第(2)步内容;
(5)输出处理后实体。
下面列举其中一种代码实现方式:
(1)修正布尔运算-并集
/// <summary>
/// 修正版布尔运算-并集
/// </summary>
/// <param name="solid1"></param>
/// <param name="solid2"></param>
/// <returns></returns>
public static Solid CorrectUnion(Solid solid1, Solid solid2)
{
if (solid2 == null)
{
return solid1;
}
else if (solid1 == null)
{
return solid2;
}
double interationCount = 0;
Solid solidTF = SolidUtils.Clone(solid2);
while (interationCount <= 10)
{
try
{
if (interationCount==0)
{
return BooleanOperationsUtils.ExecuteBooleanOperation(solid1, solid2, BooleanOperationsType.Union);
}
else
{
Transform tf = Transform.CreateTranslation(new XYZ(0, 0, 10 * interationCount.toImperial()));
solidTF = SolidUtils.CreateTransformed(solidTF, tf);
return BooleanOperationsUtils.ExecuteBooleanOperation(solid1, solidTF, BooleanOperationsType.Union);
}
}
catch (Exception)
{
interationCount++;
continue;
}
}
return null;
}
(2)修正布尔运算-交集
/// <summary>
/// 修正版布尔运算-交集
/// </summary>
/// <param name="solid1"></param>
/// <param name="solid2"></param>
/// <returns></returns>
public static Solid CorrectIntersect(Solid solid1, Solid solid2)
{
if (solid1==null||solid2==null)
{
return null;
}
double interationCount = 0;
Solid solidTF = SolidUtils.Clone(solid2);
while (interationCount <= 10)
{
try
{
if (interationCount == 0)
{
return BooleanOperationsUtils.ExecuteBooleanOperation(solid1, solid2, BooleanOperationsType.Intersect);
}
else
{
Transform tf = Transform.CreateTranslation(new XYZ(0, 0, 10 * interationCount.toImperial()));
solidTF = SolidUtils.CreateTransformed(solidTF, tf);
return BooleanOperationsUtils.ExecuteBooleanOperation(solid1, solidTF, BooleanOperationsType.Intersect);
}
}
catch (Exception)
{
interationCount++;
continue;
}
}
return null;
}
(3)修正布尔运算-差集
/// <summary>
/// 修正版布尔运算-差集
/// </summary>
/// <param name="solid1"></param>
/// <param name="solid2"></param>
/// <returns></returns>
public static Solid CorrectDifference(Solid solid1, Solid solid2)
{
if (solid2==null)
{
return solid1;
}
else if (solid1==null)
{
return null;
}
double interationCount = 0;
Solid solidTF = SolidUtils.Clone(solid2);
while (interationCount<=10)
{
try
{
if (interationCount == 0)
{
return BooleanOperationsUtils.ExecuteBooleanOperation(solid1, solid2, BooleanOperationsType.Difference);
}
else
{
Transform tf = Transform.CreateTranslation(new XYZ(0, 0, 10 * interationCount.toImperial()));
solidTF = SolidUtils.CreateTransformed(solidTF, tf);
return BooleanOperationsUtils.ExecuteBooleanOperation(solid1, solidTF, BooleanOperationsType.Difference);
}
}
catch (Exception)
{
interationCount++;
continue;
}
}
return null;
}
目前笔者在项目中使用修正版的布尔运算,效果比较好,基本解决了API原版布尔运算容易报错的问题,希望也能解决大家的难点。
449

被折叠的 条评论
为什么被折叠?



