对于梁式桥,因为平竖曲线的存在,无法简单地用拉伸去模拟桥梁的形状。如果强行用拉伸去生成,粱段与粱段之间会出现缺口,中心线也变成一段段折线,效果不理想。
在曲线和曲面模拟这块,revit提供了自适应公制常规模型,能够非常灵活地去近似模拟复杂的曲线和曲面。针对存在平竖曲线的粱段,可以通过以下步骤来模拟:
如果桥梁截面为箱梁截面,外轮廓生成实体,内轮廓生成剪切体,就能得到粱段的箱梁实体。
下面将为大家展示一个粱段生成的代码
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()
{
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()
{
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()
{
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()
{
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;
}
///
/// 创建箱梁
///
///
///
///
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();
}
///
/// 将YOZ平面内的截面点位移动并旋转到实际截面位置
///
///
///
///
///
///
///
private List MoveAndRotate(List pointInputs, XYZ originInput, XYZ normalInput, XYZ originTarget, XYZ normalTarget)
{
var pointOutputs = new List();
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;
}
///
/// 截面类
///
private class Section
{
public XYZ Location { get; set; }//截面位置
public XYZ Direction { get; set; }//前进方向
public List PointsInner { get; set; }//内轮廓
public List PointsOuter { get; set; }//外轮廓
public Section(XYZ location, XYZ direction, List pointsInner, List pointsOuter)
{
Location = location;
Direction = direction;
PointsInner = pointsInner;
PointsOuter = pointsOuter;
}
}
}
}