using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Structure;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BeamReinforcingBars
{
/// <summary>
/// 创建冠梁配筋,以1000mm*1000mm为例,主要针对常规构建进行配筋设置
/// </summary>
[Transaction(TransactionMode.Manual)]
public class Class1 : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIDocument uidoc = commandData.Application.ActiveUIDocument;
Document doc = uidoc.Document;
//获得当前视图
#region 判断是否为3D视图,不是则跳转3D视图
View3D view3d;
var Vtype = doc.ActiveView.GetType();
if (!typeof(View3D).Equals(Vtype))
{
using (Transaction ts = new Transaction(doc, "3dview"))
{
ts.Start();
ViewFamilyType viewtype = new FilteredElementCollector(doc).OfClass(typeof(ViewFamilyType))
.Cast<ViewFamilyType>()
.FirstOrDefault<ViewFamilyType>(
x => ViewFamily.ThreeDimensional
== x.ViewFamily);
view3d = View3D.CreateIsometric(doc, viewtype.Id);
ts.Commit();
uidoc.ActiveView = view3d;
}
}
#endregion
View3D view3D = doc.ActiveView as View3D;
//MainWindows mainWindows = new MainWindows();
//mainWindows.ShowDialog();
//选择梁
Reference reference = uidoc.Selection.PickObject(ObjectType.Element, "选择梁");
//创建梁数据结构
BeamInfo beamInfo = new BeamInfo();
beamInfo.ele = doc.GetElement(reference);
FamilyInstance beam = beamInfo.ele as FamilyInstance;
//获取梁控制线
beamInfo.curve = (beam.Location as LocationCurve).Curve;
//获取梁原始集合包围框
Options options = new Options();
GeometryElement geoEle = beam.GetOriginalGeometry(options);
BoundingBoxXYZ boundingBox = geoEle.GetBoundingBox();
//获得梁的长、宽、高,由于梁是可载入族,用b、h等参数不可靠
//建议通过包围框获得梁的宽和高
beamInfo.length = beamInfo.curve.Length;
beamInfo.h = boundingBox.Max.Z - boundingBox.Min.Z;
beamInfo.b = boundingBox.Max.Y - boundingBox.Min.Y;
//获得梁的坐标系
beamInfo.tf = beam.GetTransform();
beamInfo.protect = 40 / 304.8;
beamInfo.origin = beamInfo.curve.GetEndPoint(0); //注意控制线位置在梁顶部
#region 获取相应的钢筋类型
//获得钢筋的类型。以12HRB400为例
FilteredElementCollector rbTypeCol_12 = new FilteredElementCollector(doc);
rbTypeCol_12.OfClass(typeof(RebarBarType));
IEnumerable<RebarBarType> rTypes_12 = from elem in rbTypeCol_12
let r = elem as RebarBarType
where r.Name == "12 HRB400"
select r;
RebarBarType type_12 = rTypes_12.First();
//外箍筋形状
FilteredElementCollector rShapesColGJ = new FilteredElementCollector(doc);
rShapesColGJ.OfClass(typeof(RebarShape));
IEnumerable<RebarShape> rShapesGJ = from ele in rShapesColGJ
let barshape = ele as RebarShape
where barshape.Name == "33"
select barshape;
RebarShape rShapeGJ = rShapesGJ.First();
//中部筋类型
FilteredElementCollector rbTypeZ = new FilteredElementCollector(doc);
rbTypeZ.OfClass(typeof(RebarBarType));
IEnumerable<RebarBarType> rtypesZ = from ele in rbTypeZ
let barshape = ele as RebarBarType
where barshape.Name == "20 HRB400"
select barshape;
RebarBarType rtypeZ = rtypesZ.First();
//侧边钢筋类型
FilteredElementCollector rbtyprColJJ = new FilteredElementCollector(doc);
rbtyprColJJ.OfClass(typeof(RebarBarType));
IEnumerable<RebarBarType> rbTypesJJ = from ele in rbtyprColJJ
let barType = ele as RebarBarType
where barType.Name == "25 HRB400"
select barType;
RebarBarType rTypeJJ = rbTypesJJ.First();
FilteredElementCollector rShapeCol01 = new FilteredElementCollector(doc);
rShapeCol01.OfClass(typeof(RebarShape));
IEnumerable<RebarShape> rShapes01 = from ele in rShapeCol01
let barshape = ele as RebarShape
where barshape.Name == "01"
select barshape;
RebarShape rShape01 = rShapes01.First();
#endregion
double space = 400 / 304.8;
int num = 5;
int num2 = 9;
//创建并启动事务
Transaction transaction = new Transaction(doc, "钢筋");
transaction.Start();
CreateGJ(doc, beamInfo, space, view3D, type_12, rShapeGJ);
CreateZb(doc, beamInfo, num, view3D, rtypeZ, rShape01, type_12);
CreateCb(doc, beamInfo, num2, view3D, rTypeJJ, rShape01, type_12);
transaction.Commit();
return Result.Succeeded;
}
public struct BeamInfo
{
public Element ele; //冠梁
public Curve curve;//冠梁控制线
public Transform tf;//冠梁坐标系
public double protect;//保护层厚度
public XYZ origin;//冠梁中心坐标
public double b;//冠梁b长
public double h;//冠梁h长
public double length;//冠梁长度
}
/// <summary>
/// 外箍筋创建
/// </summary>
/// <param name="doc">doc</param>
/// <param name="bInfo">冠梁参数结构体</param>
/// <param name="view3D">3D视图</param>
/// <param name="rbtype">钢筋类型</param>
/// <param name="rShape">钢筋形状</param>
public void CreateGJ(Document doc, BeamInfo bInfo, double space, View3D view3D, RebarBarType rbtype, RebarShape rShape)
{
//外箍筋数量
int num = (int)Math.Ceiling(bInfo.length / space);
//箍筋中心离冠梁侧边距离,保护层以40mm为例,注意包含箍筋半径
double ct = bInfo.protect + rbtype.BarDiameter / 2;
Element ele = bInfo.ele;
for (int i = 0; i < num; i++)
{
double depth = ct + i * space;//外箍筋位置
//冠梁底部中心点
XYZ origin = bInfo.tf.Inverse.OfPoint(bInfo.origin);
//获得箍筋控制点
XYZ delta1 = new XYZ(depth, -bInfo.b / 2 + ct, -bInfo.h + ct);
XYZ delta2 = new XYZ(depth, -bInfo.b / 2 + ct, -ct);
XYZ delta3 = new XYZ(depth, bInfo.b / 2 - ct, -ct);
XYZ delta4 = new XYZ(depth, bInfo.b / 2 - ct, -bInfo.h + ct);
XYZ p1 = bInfo.tf.OfPoint(origin + delta1);
XYZ p2 = bInfo.tf.OfPoint(origin + delta2);
XYZ p3 = bInfo.tf.OfPoint(origin + delta3);
XYZ p4 = bInfo.tf.OfPoint(origin + delta4);
//钢筋形态放置方向,以p1为放置点
XYZ xVec = (p2 - p1);
XYZ yVec = (p4 - p1);
//创建钢筋
Rebar rb = Rebar.CreateFromRebarShape(doc, rShape, rbtype, ele, p1, xVec, yVec);
//设置钢筋在范围框内
rb.GetShapeDrivenAccessor().ScaleToBox(p1, xVec, yVec);
//作为实体查看,false时钢筋以线的形式表示
rb.SetSolidInView(view3D, true);
//清晰的视图设置
rb.SetUnobscuredInView(view3D, true);
}
}
/// <summary>
/// 中部创建横向钢筋
/// </summary>
/// <param name="doc"></param>
/// <param name="bInfo"></param>
/// <param name="view3D"></param>
/// <param name="rt"></param>
/// <param name="rs"></param>
/// <param name="rTG"></param>
public void CreateZb(Document doc, BeamInfo bInfo, int num, View3D view3D, RebarBarType rt, RebarShape rs, RebarBarType rTG)
{
//获得冠梁的b、h、高和transform
Element ele = bInfo.ele;
double b = bInfo.b;
double h = bInfo.h;
double length = bInfo.length;
Transform tf = bInfo.tf;
//冠梁定位点通过ofpoint转成冠梁transform的坐标,否则钢筋不在主体内
XYZ origin = bInfo.tf.Inverse.OfPoint(bInfo.origin);
XYZ norm = bInfo.tf.BasisZ;
//纵筋区域起始位置离冠梁边距离
double depth = bInfo.protect + rTG.BarDiameter + rt.BarDiameter / 2;
//获得b纵筋间距,案例以num条中部筋为例
double spaceB = (bInfo.b - bInfo.protect * 2 - rt.BarDiameter - rTG.BarDiameter * 2) / (num + 1);
//B侧,案例以3条中部筋为例
for (int i = 0; i < num; i++)
{
//放置点位置
double set = (i + 1) * spaceB + depth;
//b上侧
XYZ p1 = tf.OfPoint(origin + new XYZ(0, -b / 2 + set, -depth));
XYZ p11 = tf.OfPoint(origin + new XYZ(length, -b / 2 + set, -depth));
//b下侧
XYZ p2 = tf.OfPoint(origin + new XYZ(0, -b / 2 + set, -h + depth));
XYZ p22 = tf.OfPoint(origin + new XYZ(length, -b / 2 + set, -h + depth));
//保存创建的钢筋用于显示
List<Rebar> rbs = new List<Rebar>();
//获得中部筋的控制线
IList<Curve> c1 = new List<Curve>();
IList<Curve> c2 = new List<Curve>();
c1.Add(Line.CreateBound(p1, p11));
c2.Add(Line.CreateBound(p2, p22));
//角筋弯钩方向和放置方向,没有弯钩时不影响结果
RebarHookOrientation rho = RebarHookOrientation.Left;
//创建角筋
rbs.Add(Rebar.CreateFromCurvesAndShape(doc, rs, rt, null, null, ele, norm, c1, rho, rho));
rbs.Add(Rebar.CreateFromCurvesAndShape(doc, rs, rt, null, null, ele, norm, c2, rho, rho));
foreach (Rebar rb in rbs)
{
//作为实体查看,false时钢筋以线的形式表示
rb.SetSolidInView(view3D, true);
//清晰的视图设置
rb.SetUnobscuredInView(view3D, true);
}
}
}
/// <summary>
///侧边创建横向钢筋
/// </summary>
/// <param name="doc"></param>
/// <param name="bInfo"></param>
/// <param name="view3D"></param>
/// <param name="rt"></param>
/// <param name="rs"></param>
/// <param name="rTG"></param>
public void CreateCb(Document doc, BeamInfo bInfo, int num, View3D view3D, RebarBarType rt, RebarShape rs, RebarBarType rTG)
{
//获得冠梁的b、h、高和transform
Element ele = bInfo.ele;
double b = bInfo.b;
double h = bInfo.h;
double length = bInfo.length;
Transform tf = bInfo.tf;
//冠梁定位点通过ofpoint转成冠梁transform的坐标,否则钢筋不在主体内
XYZ origin = bInfo.tf.Inverse.OfPoint(bInfo.origin);
XYZ norm = bInfo.tf.BasisY;
//纵筋区域起始位置离冠梁边距离
double depth = bInfo.protect + rTG.BarDiameter + rt.BarDiameter / 2;
//获得b纵筋间距,案例以num条中部筋为例
double spaceB = (bInfo.h - bInfo.protect * 2 - rTG.BarDiameter * 2-rt.BarDiameter) / (num - 1);
//B侧,案例以3条中部筋为例
for (int i = 0; i < num; i++)
{
//放置点位置
double set =i * spaceB + depth;
//b上侧
XYZ p1 = tf.OfPoint(origin + new XYZ(0, b/2-depth, -h+set));
XYZ p11 = tf.OfPoint(origin + new XYZ(length,b/2 -depth, -h+set));
//b下侧
XYZ p2 = tf.OfPoint(origin + new XYZ(0, -b/2 + depth,-h+set));
XYZ p22 = tf.OfPoint(origin + new XYZ(length, -b/2 + depth, -h+set));
//保存创建的钢筋用于显示
List<Rebar> rbs = new List<Rebar>();
//获得中部筋的控制线
IList<Curve> c1 = new List<Curve>();
IList<Curve> c2 = new List<Curve>();
c1.Add(Line.CreateBound(p1, p11));
c2.Add(Line.CreateBound(p2, p22));
//角筋弯钩方向和放置方向,没有弯钩时不影响结果
RebarHookOrientation rho = RebarHookOrientation.Left;
//创建角筋
rbs.Add(Rebar.CreateFromCurvesAndShape(doc, rs, rt, null, null, ele, norm, c1, rho, rho));
rbs.Add(Rebar.CreateFromCurvesAndShape(doc, rs, rt, null, null, ele, norm, c2, rho, rho));
foreach (Rebar rb in rbs)
{
//作为实体查看,false时钢筋以线的形式表示
rb.SetSolidInView(view3D, true);
//清晰的视图设置
rb.SetUnobscuredInView(view3D, true);
}
}
}
}
}