【Revit API】梁构件支座检查算法

来源:互联网 发布:java混淆工具下载 编辑:程序博客网 时间:2024/04/27 19:54

一、前言

        应该是第二次写关于Revit API的博文了。虽然在BIM企业中工作,从事桌面BIM软件开发,但是我是不怎么喜欢写Revit API相关的代码。平时更多的是在写界面展示,架构维护,授权验证这块。为什么不喜欢Revit API呢?其实Autodesk封装的这套API是不错的(我在之后的工作中用起来挺舒服的),可能还是人比较懒吧,老查英文的API手册有点烦,而且这手册界面让我想起了上学时帮导师写ObjectARX的痛苦经历。。。

        吐槽完之后,开始上干货。为什么需要去判断梁构件是否有支座?原因有以下几个点:

        1. 提醒BIM建模设计师其设计的梁构件是否正确,说白点就是:你丫画对了没?!

            a. 如果有支座,支座与梁的位置是否符合图纸;

            b. 如果没支座,为什么?是画错了(画成虚接触)还是本身就没有支座;

        2. 如果梁有支座,OK!我根据平法规则自动分析节点并自动生成钢筋,完美;(这是后话,此篇不做节点分析与钢筋生成)

        开发这个功能还是想帮助建模人员去检查自己画的模型。中国之大,BIM建模人员参差不齐,一个人就一种画法。

        本篇会以图文代码结合的方式叙述,保证初来认识Revit的朋友也能看得懂,也希望高手能提提改进建议。

 

二、正文

        Revit 版本2016,

         主函数:IsBeamHasSeat(Element element),

         作用:判断梁构件是否有支座,适用于直梁弧形梁

         思路:因为梁有支座的话肯定要有2个构件作为其支座,不然就翘脚了。counter就是计数器,如果到2了,就不用执行了,返回true即可。

         说明:

                 1. 相交构件的函数GetJointElements是自己封装的,各位可根据实际自己编写,不暴露了。作用就是获取该梁周围一定范围内的所有构件;

                 2. IsStructrualColumn(),IsStructrualBeam()也是自己封装的,比较简单,不暴露了。作用就是要求作为梁支座的柱与梁是结构型构件,墙不用。

                 3. IsCoulmnBeSeatForBeam(),IsWallBeSeatForBeam(),IsBeamBeSeatForBeam() 这三个函数是核心,下面会慢慢展开讲。

复制代码
public static bool IsBeamHasSeat(Element element)
{
int counter = 0; //获取相交构件 var jointElements = BaseGeomUtils.GetJointElements(element); if (jointElements != null && jointElements.Any()) { //检查柱的 foreach (var column in jointElements) { if (column.IsStructuralColumn() && IsCoulmnBeSeatForBeam(element, column)) { counter++; } if (counter == 2) { return true; } } //检查墙的 foreach (var wall in jointElements) { if (IsWallBeSeatForBeam(element, wall)) { counter++; } if (counter == 2) { return true; } } //检查梁的 foreach (var beam in jointElements) { if (beam.IsStructuralBeam() && IsBeamBeSeatForBeam(element, beam)) { counter++; } if (counter == 2) { return true; } } } return false;}
复制代码

 

            A. 判断柱构件是否为当前梁的支座

            这时候要上图了,方便理解。

            第1个大条件

 

               如果不符合这个条件,说明梁与柱可能是侧面相交的关系:

 

复制代码
private static bool IsCoulmnBeSeatForBeam(Element currentBeam, Element jointColumn){     try     {         var minArea = 0.1;         var columnBottomFace = FaceUtils.GetBottomFace(jointColumn, minArea);         var beamBottomFace = FaceUtils.GetBottomFace(currentBeam, minArea);         //柱的下底面低于梁的下底面         bool isLower = columnBottomFace.Origin.Z < beamBottomFace.Origin.Z;         //取Location和LocationCurve         var columnLocation = jointColumn.Location as LocationPoint;         var beamLocationCurve = currentBeam.Location as LocationCurve;         if (columnLocation != null && beamLocationCurve != null)         {              //1.Column的Location在Beam的Location下面              //2.Column的LocationPoint能映射到Beam的下底面              //3.Beam中有点可以投影到Column的下底面              if (beamBottomFace.Project(columnLocation.Point) != null ||                  beamLocationCurve.Curve.Tessellate().Any(x => columnBottomFace.Project(x) != null                  && isLower))              {                  return true;              }              //侧面关系              else              {                  var bc = beamLocationCurve.Curve;                  //获取构件侧面(除去Z方向上下两个面)                   var columnFaces = FaceUtils.GetSideFaces(jointColumn);                  var beamFaces = FaceUtils.GetSideFaces(currentBeam);                  var line = bc as Line;                  if (line != null)                  {                      var beamLine = line.Direction;                      //梁两端的面                      var terminalFaces =                          beamFaces.Where(x => (x as PlanarFace).SafelyFaceNormal().IsAlmostEqualTo(beamLine) ||                                               (x as PlanarFace).SafelyFaceNormal().IsAlmostEqualTo(-beamLine));                      //判断梁的两端面与支座梁的侧面有没有相交                      if (columnFaces.Any(fc => terminalFaces.Any(tf => tf.Intersect(fc) == FaceIntersectionFaceResult.Intersecting)))                      {                         return true;                      }                      //没有相交则继续                      //找到梁与柱相交面                      var matchedItem =                                    columnFaces.Where(                                    x => (x as PlanarFace).SafelyFaceNormal().IsAlmostEqualTo(-beamLine) ||                                         (x as PlanarFace).SafelyFaceNormal().IsAlmostEqualTo(beamLine));                      var sp = line.GetEndPoint(0);                      var ep = line.GetEndPoint(1);                      //梁的端点能否投影到柱的相交面上                      if (matchedItem.Any())                      {                          var canProject = matchedItem.Any(face => face.Project(sp) != null || face.Project(ep) != null);                          if (canProject && isLower)                          {                               return true;                          }                      }                }                else if (bc is Arc)                {                            var sp = bc.GetEndPoint(0);                            var ep = bc.GetEndPoint(1);                            var points = bc.Tessellate().Where(x => !x.IsAlmostEqualTo(sp) && !x.IsAlmostEqualTo(ep));                            var closeSp = points.FirstOrDefault();                            var closeEp = points.LastOrDefault();                            var tangentSp = closeSp - sp;                            var tangentEp = closeEp - ep;                            //找到梁与柱相交面                            var matchedItem =                                columnFaces.Where(x => (x as PlanarFace).SafelyFaceNormal().AngleTo(-tangentSp) < UnitConverter.AngleToRad(30) ||                                (x as PlanarFace).SafelyFaceNormal().AngleTo(tangentSp) < UnitConverter.AngleToRad(30) ||                                (x as PlanarFace).SafelyFaceNormal().AngleTo(-tangentEp) < UnitConverter.AngleToRad(30) ||                                (x as PlanarFace).SafelyFaceNormal().AngleTo(tangentEp) < UnitConverter.AngleToRad(30));                            //梁的端点能否投影到柱的相交面上                            if (matchedItem.Any() && isLower)                            {                                var isInsect = columnFaces.Any(fc => beamFaces.Any(x => x.Intersect(fc) == FaceIntersectionFaceResult.Intersecting));                                var canProject = matchedItem.Any(face => face.Project(sp) != null || face.Project(ep) != null);                                if ((isInsect || canProject) && isLower)                                {                                    return true;                                }                            }                    }               }          }      }      catch (Exception)      {         return false;      }   return false;}
复制代码

 

              B. 判断墙构件是否为当前梁的支座

              墙的判断与柱类似,但是墙没有LocationPoint,但有LocationCurve,所以是这样的:

 

复制代码
        private static bool IsWallBeSeatForBeam(Element currentBeam, Element jointWall)        {            try            {                if (jointWall is Wall)                {                    var currentWall = jointWall as Wall;                    var minArea = 0.1;                    var wallBottomFace = FaceUtils.GetBottomFace(currentWall, minArea);                    var beamBottomFace = FaceUtils.GetBottomFace(currentBeam, minArea);                    //墙的下底面低于梁的下底面                    bool isLower = wallBottomFace.Origin.Z < beamBottomFace.Origin.Z;                    //取LocationCurve                    var wallLocationCurve = currentWall.Location as LocationCurve;                    var beamLocationCurve = currentBeam.Location as LocationCurve;                    if (wallLocationCurve != null && beamLocationCurve != null)                    {                        //1.Wall的Location在Beam的Location下面                        //2.Wall中有点可以投影到Beam的下底面                        //3.Beam中有点可以投影到Wall的下底面                        if (wallLocationCurve.Curve.Tessellate().Any(pt => beamBottomFace.Project(pt) != null ||                            beamLocationCurve.Curve.Tessellate().Any(x => wallBottomFace.Project(x) != null && isLower)))                        {                            return true;                        }                        //侧面关系                        else                        {                            var bc = beamLocationCurve.Curve;                            var wallFaces = FaceUtils.GetSideFaces(currentWall);                            var beamFaces = FaceUtils.GetSideFaces(currentBeam);                            var line = bc as Line;                            if (line != null)                            {                                var beamLine = line.Direction;                                //梁两端的面                                var terminalFaces =                                    beamFaces.Where(x => (x as PlanarFace).SafelyFaceNormal().IsAlmostEqualTo(beamLine) ||                                                             (x as PlanarFace).SafelyFaceNormal().IsAlmostEqualTo(-beamLine));                                //判断梁的两端面与支座梁的侧面有没有相交                                if (wallFaces.Any(fc => terminalFaces.Any(tf => tf.Intersect(fc) == FaceIntersectionFaceResult.Intersecting)))                                {                                    return true;                                }                                //没有相交则继续                                //找到梁与墙相交面                                var matchedItem =                                    wallFaces.Where(x => (x as PlanarFace).SafelyFaceNormal().IsAlmostEqualTo(-beamLine) ||                                                   (x as PlanarFace).SafelyFaceNormal().IsAlmostEqualTo(beamLine));                                var sp = line.GetEndPoint(0);                                var ep = line.GetEndPoint(1);                                //梁的端点能否投影到墙的相交面上                                if (matchedItem.Any())                                {                                    var canProject = matchedItem.Any(face => face.Project(sp) != null || face.Project(ep) != null);                                    if (canProject && isLower)                                    {                                        return true;                                    }                                }                            }                            else if (bc is Arc)                            {                                var sp = bc.GetEndPoint(0);                                var ep = bc.GetEndPoint(1);                                var points = bc.Tessellate().Where(x => !x.IsAlmostEqualTo(sp) && !x.IsAlmostEqualTo(ep));                                var closeSp = points.FirstOrDefault();                                var closeEp = points.LastOrDefault();                                var tangentSp = closeSp - sp;                                var tangentEp = closeEp - ep;                                //找到梁与墙相交面                                var matchedItem =                                wallFaces.Where(x => (x as PlanarFace).SafelyFaceNormal().AngleTo(-tangentSp) < UnitConverter.AngleToRad(30) ||                                (x as PlanarFace).SafelyFaceNormal().AngleTo(tangentSp) < UnitConverter.AngleToRad(30) ||                                (x as PlanarFace).SafelyFaceNormal().AngleTo(-tangentEp) < UnitConverter.AngleToRad(30) ||                                (x as PlanarFace).SafelyFaceNormal().AngleTo(tangentEp) < UnitConverter.AngleToRad(30));                                //梁的端点能否投影到墙的相交面上                                if (matchedItem.Any())                                {                                    var isInsect = wallFaces.Any(fc => beamFaces.Any(x => x.Intersect(fc) == FaceIntersectionFaceResult.Intersecting));                                    var canProject = matchedItem.Any(face => face.Project(sp) != null || face.Project(ep) != null);                                    if ((isInsect || canProject) && isLower)                                    {                                        return true;                                    }                                }                            }                        }                    }                }            }            catch (Exception)            {                return false;            }            return false;        }
复制代码

 

 

             C判断梁构件是否为当前梁的支座,这块是最最最烦的。

             为什么?因为:

         下面是梁作为另一个梁的支座的完整思路:

 

       如果两个构件不是上下关系,那就要检查侧面相交关系。

       我这里使用了若干个条件:conditionOne && (conditionTwo || conditionThree || conditionSp)

 

 

复制代码
        private static bool IsBeamBeSeatForBeam(Element currentBeam, Element jointBeam)        {            try            {                var beamLocationCurve = currentBeam.Location as LocationCurve;                var seatBeamLocationCurve = jointBeam.Location as LocationCurve;                var beamFaces = FaceUtils.GetSideFaces(currentBeam);                var seatBeamFaces = FaceUtils.GetSideFaces(jointBeam);                var seatBeamBottomFace = FaceUtils.GetBottomFace(jointBeam);                if (beamLocationCurve != null && seatBeamLocationCurve != null)                {                    var bc = beamLocationCurve.Curve;                    if (bc is Line)                    {                        var beamLine = (bc as Line).Direction;                        var sp = bc.GetEndPoint(0);                        var ep = bc.GetEndPoint(1);                        var matchedItem =                            seatBeamFaces.Where(x => (x as PlanarFace).SafelyFaceNormal().IsAlmostEqualTo(-beamLine) ||                                               (x as PlanarFace).SafelyFaceNormal().IsAlmostEqualTo(beamLine) ||                                               (x as PlanarFace).SafelyFaceNormal().AngleTo(beamLine) < UnitConverter.AngleToRad(30) ||                                               (x as PlanarFace).SafelyFaceNormal().AngleTo(-beamLine) < UnitConverter.AngleToRad(30));                        if (matchedItem.Any())                        {                            //支座梁在主体梁的下方                            var canBeamCurvePointProjectToSeatBeamBottomFace =                                bc.Tessellate().Any(x => seatBeamBottomFace.Project(x) != null);                            if (canBeamCurvePointProjectToSeatBeamBottomFace)                            {                                return true;                            }                        }                        //支座梁在主体梁的侧面                        //获取梁的两端的面                        var terminalFaces =                            beamFaces.Where(x => (x as PlanarFace).SafelyFaceNormal().IsAlmostEqualTo(beamLine) ||                                                     (x as PlanarFace).SafelyFaceNormal().IsAlmostEqualTo(-beamLine));                        if (terminalFaces.Count() != 2)                        {                            terminalFaces = beamFaces;                        }                        //判断梁的两端面与支座梁的侧面有没有相交                        var result = BeamHasSeatWithBeam(terminalFaces, seatBeamFaces, beamLine, matchedItem, sp, ep);                        if (result)                        {                            return true;                        }                    }                    else if (bc is Arc)                    {                        var sp = bc.GetEndPoint(0);                        var ep = bc.GetEndPoint(1);                        var points = bc.Tessellate().Where(x => !x.IsAlmostEqualTo(sp) && !x.IsAlmostEqualTo(ep));                        var closeSp = points.FirstOrDefault();                        var closeEp = points.LastOrDefault();                        var tangentSp = closeSp - sp;                        var tangentEp = closeEp - ep;                        var matchedItem =                            seatBeamFaces.Where(x => (x as PlanarFace).SafelyFaceNormal().AngleTo(-tangentSp) < UnitConverter.AngleToRad(30) ||                            (x as PlanarFace).SafelyFaceNormal().AngleTo(tangentSp) < UnitConverter.AngleToRad(30) ||                            (x as PlanarFace).SafelyFaceNormal().AngleTo(-tangentEp) < UnitConverter.AngleToRad(30) ||                            (x as PlanarFace).SafelyFaceNormal().AngleTo(tangentEp) < UnitConverter.AngleToRad(30));                        if (matchedItem.Any())                        {                            var isInsect = seatBeamFaces.Any(fc => beamFaces.Any(x => x.Intersect(fc) == FaceIntersectionFaceResult.Intersecting));                            var canProject = matchedItem.Any(face => face.Project(sp) != null || face.Project(ep) != null);                            if (isInsect || canProject)                            {                                return true;                            }                        }                    }                }            }            catch (Exception)            {                return false;            }            return false;        }
复制代码

 

复制代码
        private static bool BeamHasSeatWithBeam(IEnumerable<Face> terminalFaces, IEnumerable<Face> seatBeamFaces, XYZ beamLine, 
IEnumerable<Face> seatBeamSpecialFaces, XYZ startpoint, XYZ endpoint) { //梁任意端点能投影到支座梁的对迎面 var conditionSp = seatBeamSpecialFaces.Any() && seatBeamSpecialFaces.Any(x => x.Project(startpoint) != null || x.Project(endpoint) != null); foreach (var tf in terminalFaces) { foreach (var fc in seatBeamFaces) { //支座梁的Face生成Solid var seatBeamCl = (fc as PlanarFace).GetEdgesAsCurveLoops().ToList(); Solid seatBeamTempSolid = GeometryCreationUtilities.CreateExtrusionGeometry(seatBeamCl, fc.ComputeNormal(new UV().Negate()), UnitUtils.ConvertToInternalUnits(0.5, DisplayUnitType.DUT_MILLIMETERS)); var seatBeamDestFaces = (from object f in seatBeamTempSolid.Faces where (f as PlanarFace).SafelyFaceNormal().IsAlmostEqualTo(beamLine) ||
(f as PlanarFace).SafelyFaceNormal().IsAlmostEqualTo(-beamLine) ||
(f as PlanarFace).Project(startpoint) != null ||
(f as PlanarFace).Project(endpoint) != null select f as PlanarFace).ToList(); if (!seatBeamDestFaces.Any()) { seatBeamDestFaces = (from object f in seatBeamTempSolid.Faces select f as PlanarFace).ToList(); } //梁的Face生成Solid var beamCL = (tf as PlanarFace).GetEdgesAsCurveLoops().ToList(); Solid beamTempSolid = GeometryCreationUtilities.CreateExtrusionGeometry(beamCL, tf.ComputeNormal(new UV().Negate()), UnitUtils.ConvertToInternalUnits(0.5, DisplayUnitType.DUT_MILLIMETERS)); var beamDestFaces = (from object f in beamTempSolid.Faces select f as PlanarFace).ToList(); //梁与支座梁有相交 var conditionOne = seatBeamDestFaces.Any(x=> tf.Intersect(x) == FaceIntersectionFaceResult.Intersecting || x.Project(startpoint) != null || x.Project(endpoint) != null) || seatBeamDestFaces.Any(x=> beamDestFaces.Any(y=>y.Intersect(x) == FaceIntersectionFaceResult.Intersecting)); var fc1 = (tf as PlanarFace).SafelyFaceNormal(); var conditionTwo = seatBeamDestFaces.Any(x=> fc1.IsAlmostEqualTo(x.SafelyFaceNormal()) || fc1.IsAlmostEqualTo(-x.SafelyFaceNormal())); var conditionThree = seatBeamDestFaces.Any(x => fc1.AngleTo(x.SafelyFaceNormal()) < UnitConverter.AngleToRad(30) || fc1.AngleTo(x.SafelyFaceNormal()) < UnitConverter.AngleToRad(30)); if (conditionOne && (conditionTwo || conditionThree || conditionSp)) { return true; } } } return false; }
复制代码

 

代码中有一些自己封装的函数,比如求构件所有底面,求构件所有侧面,比较简单,这里就不暴露了。本篇主要以思路为主,掌握了思路代码也就清晰了。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 甲减引起的肥胖怎么办 18岁掉头发严重怎么办 5岁儿童掉头发严重怎么办 18头发掉的严重怎么办 甲癌碘131后腮腺肿大怎么办 头发出油发丝细怎么办 25岁总掉头发怎么办 25岁掉头发厉害怎么办 我25岁经常掉头发怎么办 25岁掉头发很厉害怎么办 我今年25岁掉头发怎么办 头顶头发稀少怎么办有方法吗 头发又干又黄怎么办 2岁宝宝头发细软怎么办 头发突然变得稀疏了怎么办 孕期掉头发很厉害怎么办 冬天头发掉的厉害怎么办 怀孕期间掉头发比较严重怎么办 头发油腻容易掉发怎么办 最近头发掉的厉害怎么办 头发新长的绒毛怎么办 久躺床上头发黏在一起怎么办 头发长油怎么办小妙招 头发出油多脱发怎么办 头发出油掉头发怎么办 在英国狂掉头发怎么办 我头发油头皮痒脱发怎么办 油性头发容易掉发怎么办 洗了头发很蓬松怎么办 小孩头皮黄掉头发怎么办 头发又油又掉发怎么办 英国的水掉头发怎么办 洗发为什么会掉头发怎么办 头发老掉怎么办吃什么 19岁掉头发严重怎么办 头发总是从根掉怎么办 18岁掉头发很厉害怎么办 20岁脱发严重该怎么办 22岁m型脱发严重怎么办 22掉头发很厉害怎么办 哺乳期头发掉的很厉害怎么办