revit开发__箱梁粱体生成

revit开发__箱梁粱体生成

问题描述

对于梁式桥,因为平竖曲线的存在,无法简单地用拉伸去模拟桥梁的形状。如果强行用拉伸去生成,粱段与粱段之间会出现缺口,中心线也变成一段段折线,效果不理想。

解决思路

在曲线和曲面模拟这块,revit提供了自适应公制常规模型,能够非常灵活地去近似模拟复杂的曲线和曲面。针对存在平竖曲线的粱段,可以通过以下步骤来模拟:

  1. 新建族,族样板文件选择自适应公制常规模型;
  2. 计算粱段起点、终点的几何位置和前进方向;
  3. 生成粱段的前后端截面内外轮廓;
  4. 外轮廓生成实体,内轮廓生成剪切体,并添加其他必要的族参数;
  5. 族文件载入模型,并在相应位置创建实例;
  6. 重复1~5过程,生成全部的粱段。

如果桥梁截面为箱梁截面,外轮廓生成实体,内轮廓生成剪切体,就能得到粱段的箱梁实体。

代码实现

下面将为大家展示一个粱段生成的代码

using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Structure;

namespace ToolSet.Command
{
    [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
    class Bridge : ToolSetCommandBase
    {
        public override Result RunImpl(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            var uiApp = commandData.Application;
            #region 数据准备
            var pointStart = new XYZ(0, 0, 0);
            var dirStart = new XYZ(1, 0.1, 0).Normalize();
            var pointEnd = new XYZ(10, 0.5, 0.5);
            var dirEnd = new XYZ(1, 0.2, 0).Normalize();
            var pointsOuterStart = new List<XYZ>()
            {
                new XYZ(0,0,0.1),
                new XYZ(0,5,0),
                new XYZ(0,5,-0.2),
                new XYZ(0,3,-0.2),
                new XYZ(0,3,-3),
                new XYZ(0,-3,-3),
                new XYZ(0,-3,-0.2),
                new XYZ(0,-5,-0.2),
                new XYZ(0,-5,0)
            };
            var pointsOuterEnd = new List<XYZ>()
            {
                new XYZ(0,0,0.1),
                new XYZ(0,5,0),
                new XYZ(0,5,-0.2),
                new XYZ(0,3,-0.2),
                new XYZ(0,3,-3.2),
                new XYZ(0,-3,-3.2),
                new XYZ(0,-3,-0.2),
                new XYZ(0,-5,-0.2),
                new XYZ(0,-5,0)
            };
            var pointsInnerStart = new List<XYZ>()
            {
                new XYZ(0,2.7,-0.2),
                new XYZ(0,2.7,-2.8),
                new XYZ(0,-2.7,-2.8),
                new XYZ(0,-2.7,-0.2)
            };
            var pointsInnerEnd = new List<XYZ>()
            {
                new XYZ(0,2.7,-0.2),
                new XYZ(0,2.7,-3.0),
                new XYZ(0,-2.7,-3.0),
                new XYZ(0,-2.7,-0.2)
            };
            var sectionStart = new Section(pointStart, dirStart, pointsInnerStart, pointsOuterStart);
            var sectionEnd = new Section(pointEnd, dirEnd, pointsInnerEnd, pointsOuterEnd);
            #endregion
            CreateBoxGirder(uiApp, sectionStart, sectionEnd);//创建箱梁
            return Result.Succeeded;
       }

        /// <summary>
        /// 创建箱梁
        /// </summary>
        /// <param name="uiApp"></param>
        /// <param name="sectionStart"></param>
        /// <param name="sectionEnd"></param>
        private void CreateBoxGirder(UIApplication uiApp, Section sectionStart, Section sectionEnd)
        {
            var doc = uiApp.ActiveUIDocument.Document;
            var pointsInnerStart = sectionStart.PointsInner;
            var pointsOuterStart = sectionStart.PointsOuter;
            var pointsInnerEnd = sectionEnd.PointsInner;
            var pointsOuterEnd = sectionEnd.PointsOuter;
            var pointStart = sectionStart.Location;
            var dirStart = sectionStart.Direction;
            var pointEnd = sectionEnd.Location;
            var dirEnd = sectionEnd.Direction;
           pointsInnerStart = MoveAndRotate(pointsInnerStart, pointsOuterStart[0], XYZ.BasisX, pointStart, dirStart);
            pointsInnerStart.Reverse();
            pointsOuterStart = MoveAndRotate(pointsOuterStart, pointsOuterStart[0], XYZ.BasisX, pointStart, dirStart);
            pointsInnerEnd = MoveAndRotate(pointsInnerEnd, pointsOuterEnd[0], XYZ.BasisX, pointEnd, dirEnd);
            pointsInnerEnd.Reverse();
            pointsOuterEnd = MoveAndRotate(pointsOuterEnd, pointsOuterEnd[0], XYZ.BasisX, pointEnd, dirEnd);
            var lineOuterStart = pointsOuterStart.Select((t, i) => Line.CreateBound(t, pointsOuterStart[(i + 1) % pointsOuterStart.Count])).ToList();
            var lineInnerStart = pointsInnerStart.Select((t, i) => Line.CreateBound(t, pointsInnerStart[(i + 1) % pointsInnerStart.Count])).ToList();
            var lineOuterEnd = pointsOuterEnd.Select((t, i) => Line.CreateBound(t, pointsOuterEnd[(i + 1) % pointsOuterEnd.Count])).ToList();
            var lineInnerEnd = pointsInnerEnd.Select((t, i) => Line.CreateBound(t, pointsInnerEnd[(i + 1) % pointsInnerEnd.Count])).ToList();
            const string path = @"F:\自适应公制常规模型.rft";
            var familyDoc = uiApp.Application.NewFamilyDocument(path);
            var transaction1 = new Transaction(familyDoc);
            transaction1.Start("CreateFamily");
            var plane1 = Plane.CreateByNormalAndOrigin(dirStart, pointStart);
            var plane2 = Plane.CreateByNormalAndOrigin(dirEnd, pointEnd);
            var sketchPlaneStart = SketchPlane.Create(familyDoc, plane1);
            var sketchPlaneEnd = SketchPlane.Create(familyDoc, plane2);
           var profiles0 = new ReferenceArray();
            var profiles1 = new ReferenceArray();
            lineOuterStart.ForEach(x => profiles0.Append(familyDoc.FamilyCreate.NewModelCurve(x, sketchPlaneStart).GeometryCurve.Reference));
            lineOuterEnd.ForEach(x => profiles1.Append(familyDoc.FamilyCreate.NewModelCurve(x, sketchPlaneEnd).GeometryCurve.Reference));
            var profilesArray = new ReferenceArrayArray();
            profilesArray.Append(profiles0);
            profilesArray.Append(profiles1);
            familyDoc.FamilyCreate.NewLoftForm(true, profilesArray);
            profiles0 = new ReferenceArray();
            profiles1 = new ReferenceArray();
            lineInnerStart.ForEach(x => profiles0.Append(familyDoc.FamilyCreate.NewModelCurve(x, sketchPlaneStart).GeometryCurve.Reference));
            lineInnerEnd.ForEach(x => profiles1.Append(familyDoc.FamilyCreate.NewModelCurve(x, sketchPlaneEnd).GeometryCurve.Reference));
            profilesArray = new ReferenceArrayArray();
            profilesArray.Append(profiles0);
            profilesArray.Append(profiles1);
            familyDoc.FamilyCreate.NewLoftForm(false, profilesArray);
            transaction1.Commit();
            var loadedFamily = familyDoc.LoadFamily(doc, new MyFamilyLoadOptions());
            familyDoc.Close(false);

            var trans = new Transaction(doc, "CreateBoxGirder");
            trans.Start();
            if (doc.GetElement(loadedFamily.GetFamilySymbolIds().First()) is FamilySymbol familySymbol)
            {
                familySymbol.Activate();
                doc.Create.NewFamilyInstance(new XYZ(0, 0, 0), familySymbol, StructuralType.NonStructural);
            }
            trans.Commit();
        }

        /// <summary>
        /// 将YOZ平面内的截面点位移动并旋转到实际截面位置
        /// </summary>
        /// <param name="pointInputs"></param>
        /// <param name="originInput"></param>
        /// <param name="normalInput"></param>
        /// <param name="originTarget"></param>
        /// <param name="normalTarget"></param>
        /// <returns></returns>
        private List<XYZ> MoveAndRotate(List<XYZ> pointInputs, XYZ originInput, XYZ normalInput, XYZ originTarget, XYZ normalTarget)
        {
            var pointOutputs = new List<XYZ>();
            foreach (var pointInput in pointInputs)
            {
                var pointOutput = pointInput + originTarget - originInput;
                var angle = -normalTarget.AngleOnPlaneTo(normalInput, XYZ.BasisZ);
                var xyz1 = pointOutput - originTarget;
                xyz1 = xyz1 - XYZ.BasisZ * xyz1.Z;
                var xyz2 = xyz1.GetLength() * XYZ.BasisZ.CrossProduct(xyz1).Normalize();
                var pointTemp = originTarget + xyz1 * Math.Cos(angle) + xyz2 * Math.Sin(angle);
                pointOutput = pointTemp + XYZ.BasisZ * (-pointTemp.Z + pointOutput.Z);
                pointOutputs.Add(pointOutput);
            }

            return pointOutputs;
        }
        
        /// <summary>
        /// 截面类
        /// </summary>
        private class Section
        {
            public XYZ Location { get; set; }//截面位置
            public XYZ Direction { get; set; }//前进方向
            public List<XYZ> PointsInner { get; set; }//内轮廓
            public List<XYZ> PointsOuter { get; set; }//外轮廓
            public Section(XYZ location, XYZ direction, List<XYZ> pointsInner, List<XYZ> pointsOuter)
            {
                Location = location;
                Direction = direction;
                PointsInner = pointsInner;
                PointsOuter = pointsOuter;
            }
        }
    }
}

运行效果

运行前将“自适应公制常规模型.rft”放到代码中指定位置,或者修改相关路径,然后运行。运行效果下图示:
图1

着色后效果如下图2所示:
在这里插入图片描述

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值