【Revit二次开发】RevitAPI布尔运算错误及解决方法

 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原版布尔运算容易报错的问题,希望也能解决大家的难点。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值