应用程序:MultiplanarRebar
Revit平台:结构
Revit版本:2012.0
首次发布版本:2012.0
编程语言:C#
技能水平:高
类别:结构
类型:ExternalCommand
主题:创建多平面钢筋。
摘要:本示例演示API创建多平面钢筋。多平面钢筋的一个用户场景是悬臂梁的加固。本示例是用于加固倾斜悬臂板。
类:
Autodesk.Revit.UI.IExternalCommand
Autodesk.Revit.Creation.Document
Autodesk.Revit.DB.FamilyInstance
Autodesk.Revit.DB.Structure.Rebar
Autodesk.Revit.DB.Structure.RebarShape
Autodesk.Revit.DB.Structure.RebarShapeDefinition
Autodesk.Revit.DB.Structure.RebarShapeDefinitionBySegments
Autodesk.Revit.DB.Structure.RebarShapeMultiplanarDefinition
Autodesk.Revit.DB.Structure.StructuralType
Autodesk.Revit.DB.Parameter
Autodesk.Revit.DB.DefinitionGroup
Autodesk.Revit.DB.ExternalDefinition
Autodesk.Revit.DB.Solid
项目文件:
Command.cs
这是示例的入口点。它实现了IExternalCommand Execute方法。
CorbelFrame.cs
它表示悬臂板的框架,包括梯形剖面和挤压线。可以通过沿着挤压线展开梯形剖面来构建悬臂板。
CorbelReinforcementOptions.cs
此类表示悬臂板的加固选项。选项包括通过UI输入从用户收集的钢筋类型和钢筋数量。
CorbelReinforcementOptionsForm.cs
这个类是一个表单,用于收集用户对悬臂板钢筋创建的选项。
GeometryUtil.cs
此类用于解析给定悬臂板FamilyInstance的几何信息,并根据解析的几何信息最终构造一个CorbelFrame。
SharedParameterUtil.cs
这是一个实用程序类,用于在Revit文档中创建共享参数。它简化了共享参数创建过程。
描述:
1. 本示例将重点关注悬臂板的加固,悬臂板的主体(墙、柱)的加固超出了此范围,除了需要锚定悬臂板箍筋的直钢筋之外。
2. 悬臂板的钢筋包括水平直钢筋、箍筋和一根多平面钢筋。在悬臂板主体中有两根垂直直钢筋用于锚定悬臂板箍筋。
3. 本示例将提供一个简单的UI来收集钢筋创建选项,如钢筋类型和数量。
详细设计:
1. 第一步是悬臂板几何分析:
a)悬臂板是一个族实例,因此可以通过Element.Geometry()获取其几何形状。本示例需要过滤掉悬臂板的梯形面,因此我们必须获取Solid以进行更深入的解析。
b)遍历Solid的所有面以过滤出梯形面,这是整个示例的关键,多平面钢筋形状和所有钢筋的放置都依赖于这个梯形面。
2. 多平面钢筋形状的创建:
钢筋形状由两个直线段组成,因此我们应该创建RebarShapeDefinitionBySegments,然后根据梯形面添加几何约束。为了创建多平面形状,必须创建一个RebarShapeMultiplanarDefinition。最后,我们调用静态方法RebarShape.Create(…)完成钢筋形状的创建。
3. 在悬臂板和其主体中创建钢筋:
a)使用Rebar.CreateFromCurves创建悬臂板水平直钢筋和悬臂板主体的垂直直钢筋。布置规则设置为固定数量,并使用SetLayoutAsFixedNumber方法。
b)使用形状“T1”通过Rebar.CreateFromRebarShape方法创建箍筋,布置规则使用SetLayoutAsFixedNumber方法设置为固定数量。(三角形区域中填充的箍筋单独放置)。Rebar.ScaleToBox用于将箍筋放置在一个精确计算的边界框中。
c)创建多平面钢筋的第一步是创建多平面形状,然后使用Rebar.CreateFromRebarShape方法来创建钢筋。Rebar.ScaleToBoxFor3D()用于将多平面放置在给定的边界框中。根据梯形面计算边界框。
4.挑战:
这个示例的挑战是对钢筋位置的计算。有几个因素需要考虑:
a)钢筋类型-它包含钢筋直径和弯曲半径的定义。
b)悬臂板和其主体的覆盖距离。
c)多平面钢筋形状的平面弯曲直径。
d)在本示例中,我们考虑了钢筋直径和覆盖距离,但是我们不考虑弯曲半径。换句话说,我们将每个弯曲半径视为零。
说明:
1.设置插件文件并让Revit加载此示例。
2.打开示例文件“Reinforce Corbels.rvt”。
3.选择文档中的悬臂板。支持矩形选择;样本将过滤选择集中的悬臂板。
4.如果选择集包含可以通过此示例加固的悬臂板,则会显示一个窗口并让用户输入简单选项。如果选择不满足条件,则会显示一个警告消息,告知发生了什么。
5.单击窗口上的“确定”按钮以加固悬臂板。
6.在Revit UI中检查此示例创建的钢筋。
7.结束。
源代码
完整的源代码请加入QQ群649037449,在群文件中下载RevitSDK.exe,解压后在文件夹中搜索本文中应用程序名称即可获得完整源码
CorbelFrame.cs
//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Structure;
namespace Revit.SDK.Samples.MultiplanarRebar.CS
{
/// <summary>
/// This class represents the trapezoid wire frame profile of corbel.
/// Its two main functionalities are to create a multi-planar rebar shape and
/// to calculate the location for rebar creation when reinforcing corbel.
/// </summary>
class Trapezoid
{
//
// TOP
// |---------\
// Vertical| \Slanted
// | Bottom \
//---------|------------\
//
// Top -> Vertical -> Bottom -> Slanted form counter clockwise orientation.
/// <summary>
/// Top bound line of this trapezoid.
/// </summary>
public Line Top { get; set; }
/// <summary>
/// Left vertical bound line of this trapezoid.
/// </summary>
public Line Vertical { get; set; }
/// <summary>
/// Bottom bound line of this trapezoid.
/// </summary>
public Line Bottom { get; set; }
/// <summary>
/// Right slanted bound line of this trapezoid.
/// </summary>
public Line Slanted { get; set; }
/// <summary>
/// Constructor to initialize the fields.
/// </summary>
/// <param name="top">Top Line</param>
/// <param name="vertical">Left Vertical Line</param>
/// <param name="bottom">Bottom Line</param>
/// <param name="slanted">Right slanted Line</param>
public Trapezoid(Line top, Line vertical, Line bottom, Line slanted)
{
Top = top;
Vertical = vertical;
Bottom = bottom;
Slanted = slanted;
}
/// <summary>
/// Draw the trapezoid wire-frame with Revit Model curves.
/// It's for debug use, to help developer see the exact location.
/// </summary>
/// <param name="revitDoc">Revit DB Document</param>
public void Draw(Document revitDoc)
{
XYZ topDir = (Top.GetEndPoint(1) - Top.GetEndPoint(0)).Normalize();
XYZ verticalDir = (Vertical.GetEndPoint(0) - Vertical.GetEndPoint(1)).Normalize();
XYZ normal = topDir.CrossProduct(verticalDir);
SketchPlane sketchplane = SketchPlane.Create(revitDoc, Plane.CreateByNormalAndOrigin(normal, Vertical.GetEndPoint(0)));
CurveArray curves = new CurveArray();
curves.Append(Top.Clone());
curves.Append(Vertical.Clone());
curves.Append(Bottom.Clone());
curves.Append(Slanted.Clone());
revitDoc.Create.NewModelCurveArray(curves, sketchplane);
}
/// <summary>
/// Offset the top line with given value, if the value is positive,
/// the offset direction is outside, otherwise inside.
/// </summary>
/// <param name="offset">Offset value</param>
public void OffsetTop(double offset)
{
XYZ verticalDir = (Vertical.GetEndPoint(0) - Vertical.GetEndPoint(1)).Normalize();
XYZ verticalDelta = verticalDir * offset;
XYZ verticalFinal = Vertical.GetEndPoint(0) + verticalDelta;
double verticalLengthNew = Vertical.Length + offset;
double slantedLengthNew = verticalLengthNew * Slanted.Length / Vertical.Length;
XYZ slantedDir = (Slanted.GetEndPoint(1) - Slanted.GetEndPoint(0)).Normalize();
XYZ slantedFinal = Slanted.GetEndPoint(0) + slantedDir * slantedLengthNew;
Vertical = Line.CreateBound(verticalFinal, Vertical.GetEndPoint(1));
Top = Line.CreateBound(slantedFinal, verticalFinal);
Slanted = Line.CreateBound(Slanted.GetEndPoint(0), slantedFinal);
}
/// <summary>
/// Offset the Left Vertical line with given value, if the value is positive,
/// the offset direction is outside, otherwise inside.
/// </summary>
/// <param name="offset">Offset value</param>
public void OffsetLeft(double offset)
{
XYZ topDir = (Top.GetEndPoint(1) - Top.GetEndPoint(0)).Normalize();
XYZ topDelta = topDir * offset;
XYZ topFinal = Top.GetEndPoint(1) + topDelta;
XYZ bottomFinal = Bottom.GetEndPoint(0) + topDelta;
Vertical = Line.CreateBound(topFinal, bottomFinal);
Bottom = Line.CreateBound(bottomFinal, Bottom.GetEndPoint(1));
Top = Line.CreateBound(Top.GetEndPoint(0), topFinal);
}
/// <summary>
/// Offset the bottom line with given value, if the value is positive,
/// the offset direction is outside, otherwise inside.
/// </summary>
/// <param name="offset">Offset value</param>
public void OffsetBottom(double offset)
{
XYZ verticalDir = (Vertical.GetEndPoint(1) - Vertical.GetEndPoint(0)).Normalize();
XYZ verticalDelta = verticalDir * offset;
XYZ verticalFinal = Vertical.GetEndPoint(1) + verticalDelta;
double verticalLengthNew = Vertical.Length + offset;
double slantedLengthNew = verticalLengthNew * Slanted.Length / Vertical.Length;
XYZ slantedDir = (Slanted.GetEndPoint(0) - Slanted.GetEndPoint(1)).Normalize();
XYZ slantedFinal = Slanted.GetEndPoint(1) + slantedDir * slantedLengthNew;
Vertical = Line.CreateBound(Vertical.GetEndPoint(0), verticalFinal);
Bottom = Line.CreateBound(verticalFinal, slantedFinal);
Slanted = Line.CreateBound(slantedFinal, Slanted.GetEndPoint(1));
}
/// <summary>
/// Offset the right slanted line with given value, if the value is positive,
/// the offset direction is outside, otherwise inside.
/// </summary>
/// <param name="offset">Offset value</param>
public void OffsetRight(double offset)
{
XYZ bottomDir = (Bottom.GetEndPoint(1) - Bottom.GetEndPoint(0)).Normalize();
XYZ bottomDelta = bottomDir * (offset * Slanted.Length / Vertical.Length);
XYZ topFinal = Top.GetEndPoint(0) + bottomDelta;
XYZ bottomFinal = Bottom.GetEndPoint(1) + bottomDelta;
Top = Line.CreateBound(topFinal, Top.GetEndPoint(1));
Bottom = Line.CreateBound(Bottom.GetEndPoint(0), bottomFinal);
Slanted = Line.CreateBound(bottomFinal, topFinal);
}
/// <summary>
/// Deep clone, to avoid mess up the original data during offsetting the boundary.
/// </summary>
/// <returns>Cloned object</returns>
public Trapezoid Clone()
{
return new Trapezoid(
Top.Clone() as Line,
Vertical.Clone() as Line,
Bottom.Clone() as Line,
Slanted.Clone() as Line);
}
/// <summary>
/// Create the multi-planar Rebar Shape according to the trapezoid wire-frame.
/// </summary>
/// <param name="revitDoc">Revit DB Document</param>
/// /// <param name="bendDiameter">OutOfPlaneBendDiameter for multi-planar shape</param>
/// <returns>Created multi-planar Rebar Shape</returns>
public RebarShape ConstructMultiplanarRebarShape(Document revitDoc, double bendDiameter)
{
// Construct a segment definition with 2 lines.
RebarShapeDefinitionBySegments shapedef = new RebarShapeDefinitionBySegments(revitDoc, 2);
// Define parameters for the dimension.
ElementId B = SharedParameterUtil.GetOrCreateDef("B", revitDoc);
ElementId H = SharedParameterUtil.GetOrCreateDef("H", revitDoc);
ElementId K = SharedParameterUtil.GetOrCreateDef("K", revitDoc);
ElementId MM = SharedParameterUtil.GetOrCreateDef("MM", revitDoc);
// Set parameters default values according to the size Trapezoid shape.
shapedef.AddParameter(B, Top.Length);
shapedef.AddParameter(H, Bottom.Length - Top.Length);
shapedef.AddParameter(K, Vertical.Length);
shapedef.AddParameter(MM, 15);
// Rebar shape geometry curves consist of Line S0 and Line S1.
//
//
// |Y V1
// |--S0(B)--\
// | \S1(H, K)
// | \
//---------|O-----------\----X
// |
// Define Segment 0 (S0)
//
// S0's direction is fixed in positive X Axis.
shapedef.SetSegmentFixedDirection(0, 1, 0);
// S0's length is determined by parameter B
shapedef.AddConstraintParallelToSegment(0, B, false, false);
// Define Segment 1 (S1)
//
// Fix S1's direction.
shapedef.SetSegmentFixedDirection(1, Bottom.Length - Top.Length, -Vertical.Length);
// S1's length in positive X Axis is parameter H.
shapedef.AddConstraintToSegment(1, H, 1, 0, 1, false, false);
// S1's length in negative Y Axis is parameter K.
shapedef.AddConstraintToSegment(1, K, 0, -1, 1, false, false);
// Define Vertex 1 (V1)
//
// S1 at V1 is turn to right and the angle is acute.
shapedef.AddBendDefaultRadius(1, RebarShapeVertexTurn.Right, RebarShapeBendAngle.Acute);
// Check to see if it's full constrained.
if (!shapedef.Complete)
{
throw new Exception("Shape was not completed.");
}
// Try to solve it to make sure the shape can be resolved with default parameter value.
if (!shapedef.CheckDefaultParameterValues(0, 0))
{
throw new Exception("Can't resolve rebar shape.");
}
// Define multi-planar definition
RebarShapeMultiplanarDefinition multiPlanarDef = new RebarShapeMultiplanarDefinition(bendDiameter);
multiPlanarDef.DepthParamId = MM;
// Realize the Rebar shape with creation static method.
// The RebarStype is stirrupTie, and it will attach to the top cover.
RebarShape newshape = RebarShape.Create(revitDoc, shapedef, multiPlanarDef,
RebarStyle.StirrupTie, StirrupTieAttachmentType.InteriorFace,
0, RebarHookOrientation.Left, 0, RebarHookOrientation.Left, 0);
// Give a readable name
newshape.Name = "API Corbel Multi-Shape " + newshape.Id;
// Make sure we can see the created shape from the browser.
IList<Curve> curvesForBrowser = newshape.GetCurvesForBrowser();
if (curvesForBrowser.Count == 0)
{
throw new Exception("The Rebar shape is invisible in browser.");
}
return newshape;
}
/// <summary>
/// Calculate the boundary coordinate of the wire-frame.
/// </summary>
/// <param name="origin">Origin coordinate</param>
/// <param name="vX">X Vector</param>
/// <param name="vY">Y Vector</param>
public void Boundary(out XYZ origin, out XYZ vX, out XYZ vY)
{
origin = Vertical.GetEndPoint(1);
vX = Bottom.GetEndPoint(1) - Bottom.GetEndPoint(0);
vY = Vertical.GetEndPoint(0) - Vertical.GetEndPoint(1);
}
}
/// <summary>
/// It represents the frame of Corbel, which is consist of a trapezoid profile and a extrusion line.
/// Corbel can be constructed by sweeping a trapezoid profile along the extrusion line.
/// </summary>
class CorbelFrame
{
/// <summary>
/// Trapezoid profile of corbel family instance.
/// </summary>
private Trapezoid m_profile;
/// <summary>
/// Extrusion line of corbel family instance.
/// </summary>
private Line m_extrusionLine;
/// <summary>
/// Corbel family instance.
/// </summary>
private FamilyInstance m_corbel;
/// <summary>
/// Depth of corbel host.
/// </summary>
private double m_hostDepth;
/// <summary>
/// Cover distance of corbel family instance.
/// </summary>
private double m_corbelCoverDistance;
/// <summary>
/// Cover distance of corbel host.
/// </summary>
private double m_hostCoverDistance;
/// <summary>
/// Constructor to initialize the fields.
/// </summary>
/// <param name="corbel">Corbel family instance</param>
/// <param name="profile">Trapezoid profile</param>
/// <param name="path">Extrusion Line</param>
/// <param name="hostDepth">Corbel Host Depth</param>
/// <param name="hostTopCorverDistance">Corbel Host cover distance</param>
public CorbelFrame(FamilyInstance corbel, Trapezoid profile,
Line path, double hostDepth, double hostTopCorverDistance)
{
m_profile = profile;
m_extrusionLine = path;
m_corbel = corbel;
m_hostDepth = hostDepth;
m_hostCoverDistance = hostTopCorverDistance;
// Get the cover distance of corbel from CommonCoverType.
RebarHostData rebarHost = RebarHostData.GetRebarHostData(m_corbel);
m_corbelCoverDistance = rebarHost.GetCommonCoverType().CoverDistance;
}
/// <summary>
/// Parse the geometry of given Corbel and create a CorbelFrame if the corbel is slopped,
/// otherwise exception thrown.
/// </summary>
/// <param name="corbel">Corbel to parse</param>
/// <returns>A created CorbelFrame</returns>
public static CorbelFrame Parse(FamilyInstance corbel)
{
// This just delegates a call to GeometryUtil class.
return GeometryUtil.ParseCorbelGeometry(corbel);
}
/// <summary>
/// Add bars to reinforce the Corbel FamilyInstance with given options.
/// The bars including:
/// a multi-planar bar,
/// top straight bars,
/// stirrup bars,
/// and host straight bars.
/// </summary>
/// <param name="rebarOptions">Options for Rebar Creation</param>
public void Reinforce(CorbelReinforcementOptions rebarOptions)
{
PlaceStraightBars(rebarOptions);
PlaceMultiplanarRebar(rebarOptions);
PlaceStirrupBars(rebarOptions);
PlaceCorbelHostBars(rebarOptions);
}
/// <summary>
/// Add straight bars into corbel with given options.
/// </summary>
/// <param name="options">Options for Rebar Creation</param>
private void PlaceStraightBars(CorbelReinforcementOptions options)
{
Trapezoid profileCopy = m_profile.Clone();
profileCopy.OffsetTop(-m_corbelCoverDistance);
profileCopy.OffsetLeft(-m_corbelCoverDistance
- options.MultiplanarBarType.BarDiameter
- options.TopBarType.BarDiameter * 0.5);
profileCopy.OffsetBottom(m_hostDepth - m_hostCoverDistance
- options.StirrupBarType.BarDiameter
- options.HostStraightBarType.BarDiameter);
profileCopy.OffsetRight(-m_corbelCoverDistance);
//m_profile.Draw(options.RevitDoc);
//profileCopy.Draw(options.RevitDoc);
XYZ extruDir = (m_extrusionLine.GetEndPoint(1) - m_extrusionLine.GetEndPoint(0)).Normalize();
double offset = m_corbelCoverDistance +
options.StirrupBarType.BarDiameter +
options.MultiplanarBarType.BarDiameter +
0.5 * options.TopBarType.BarDiameter;
Line vetical = profileCopy.Vertical;
XYZ delta = extruDir * offset;
Curve barLine = Line.CreateBound(vetical.GetEndPoint(1) + delta, vetical.GetEndPoint(0) + delta);
IList<Curve> barCurves = new List<Curve>();
barCurves.Add(barLine);
Rebar bars = Rebar.CreateFromCurves(options.RevitDoc, RebarStyle.Standard,
options.TopBarType, null, null, m_corbel, extruDir, barCurves,
RebarHookOrientation.Left, RebarHookOrientation.Left, true, true);
bars.GetShapeDrivenAccessor().SetLayoutAsFixedNumber(options.TopBarCount + 2,
m_extrusionLine.Length - 2 * offset, true, false, false);
ShowRebar3d(bars);
}
/// <summary>
/// Add a multi-planar bar into corbel with given options.
/// </summary>
/// <param name="options">Options for Rebar Creation</param>
private void PlaceMultiplanarRebar(CorbelReinforcementOptions options)
{
Trapezoid profileCopy = m_profile.Clone();
profileCopy.OffsetTop(-m_corbelCoverDistance
- options.StirrupBarType.BarDiameter - 0.5 * options.MultiplanarBarType.BarDiameter);
profileCopy.OffsetLeft(-m_corbelCoverDistance - 0.5 * options.MultiplanarBarType.BarDiameter);
profileCopy.OffsetBottom(m_hostDepth - m_hostCoverDistance
- options.HostStraightBarType.BarDiameter * 4
- options.StirrupBarType.BarDiameter);
profileCopy.OffsetRight(-m_corbelCoverDistance - options.StirrupBarType.BarDiameter
- 0.5 * options.StirrupBarType.BarDiameter);
//m_profile.Draw(options.RevitDoc);
//profileCopy.Draw(options.RevitDoc);
XYZ origin, vx, vy;
profileCopy.Boundary(out origin, out vx, out vy);
XYZ vecX = vx.Normalize();
XYZ vecY = vy.Normalize();
RebarShape barshape = profileCopy.ConstructMultiplanarRebarShape(options.RevitDoc,
0.5 * options.MultiplanarBarType.StirrupTieBendDiameter);
Rebar newRebar = Rebar.CreateFromRebarShape(
options.RevitDoc, barshape,
options.MultiplanarBarType,
m_corbel, origin, vecX, vecY);
XYZ extruDir = (m_extrusionLine.GetEndPoint(1) - m_extrusionLine.GetEndPoint(0)).Normalize();
double offset = m_corbelCoverDistance +
options.StirrupBarType.BarDiameter +
0.5 * options.MultiplanarBarType.BarDiameter;
newRebar.GetShapeDrivenAccessor().ScaleToBoxFor3D(origin + extruDir * (m_extrusionLine.Length - offset),
vx, vy, m_extrusionLine.Length - 2 * offset);
ShowRebar3d(newRebar);
}
/// <summary>
/// Add stirrup bars into corbel with given options.
/// </summary>
/// <param name="options">Options for Rebar Creation</param>
private void PlaceStirrupBars(CorbelReinforcementOptions options)
{
var filter = new FilteredElementCollector(options.RevitDoc)
.OfClass(typeof(RebarShape)).ToElements().Cast<RebarShape>()
.Where<RebarShape>(shape => shape.RebarStyle == RebarStyle.StirrupTie);
RebarShape stirrupShape = null;
foreach (RebarShape shape in filter)
{
if (shape.Name.Equals("T1"))
{
stirrupShape = shape; break;
}
}
Trapezoid profileCopy = m_profile.Clone();
profileCopy.OffsetTop(-m_corbelCoverDistance - 0.5 * options.StirrupBarType.BarDiameter);
profileCopy.OffsetLeft(-m_corbelCoverDistance - 0.5 * options.StirrupBarType.BarDiameter);
profileCopy.OffsetBottom(m_hostDepth - m_hostCoverDistance - 0.5 * options.StirrupBarType.BarDiameter);
profileCopy.OffsetRight(-m_corbelCoverDistance - 0.5 * options.StirrupBarType.BarDiameter);
XYZ extruDir = (m_extrusionLine.GetEndPoint(1) - m_extrusionLine.GetEndPoint(0)).Normalize();
double offset = m_corbelCoverDistance + 0.5 * options.StirrupBarType.BarDiameter;
XYZ origin = profileCopy.Vertical.GetEndPoint(0) + extruDir * offset;
XYZ xAxis = extruDir;
XYZ yAxis = (profileCopy.Vertical.GetEndPoint(1) - profileCopy.Vertical.GetEndPoint(0)).Normalize();
Rebar stirrupBars = Rebar.CreateFromRebarShape(options.RevitDoc, stirrupShape,
options.StirrupBarType, m_corbel, origin, xAxis, yAxis);
double xLength = m_extrusionLine.Length - 2 * offset;
double yLength = profileCopy.Vertical.Length;
stirrupBars.GetShapeDrivenAccessor().SetLayoutAsFixedNumber(options.StirrupBarCount + 1, profileCopy.Top.Length, false, false, true);
stirrupBars.GetShapeDrivenAccessor().ScaleToBox(origin, xAxis * xLength, yAxis * yLength);
ShowRebar3d(stirrupBars);
double space = profileCopy.Top.Length / options.StirrupBarCount;
double step = space * m_profile.Vertical.Length / (m_profile.Bottom.Length - m_profile.Top.Length);
XYZ dirTop = (m_profile.Top.GetEndPoint(0) - m_profile.Top.GetEndPoint(1)).Normalize();
XYZ dirVertical = yAxis;
XYZ deltaStep = dirTop * space + dirVertical * step;
origin = profileCopy.Top.GetEndPoint(0) + extruDir * offset;
int count = (int)((m_profile.Vertical.Length - m_corbelCoverDistance - 0.5 * options.StirrupBarType.BarDiameter) / step);
for (int i = 1; i <= count; i++)
{
origin += deltaStep;
Rebar stirrupBars2 = Rebar.CreateFromRebarShape(options.RevitDoc, stirrupShape,
options.StirrupBarType, m_corbel, origin, xAxis, yAxis);
stirrupBars2.GetShapeDrivenAccessor().ScaleToBox(origin, xAxis * xLength, yAxis * (yLength - i * step));
ShowRebar3d(stirrupBars2);
}
}
/// <summary>
/// Add straight bars into corbel Host to anchor corbel stirrup bars.
/// </summary>
/// <param name="options">Options for Rebar Creation</param>
private void PlaceCorbelHostBars(CorbelReinforcementOptions options)
{
Trapezoid profileCopy = m_profile.Clone();
profileCopy.OffsetBottom(m_hostDepth - m_hostCoverDistance
- options.HostStraightBarType.BarDiameter * 0.5
- options.StirrupBarType.BarDiameter);
//profileCopy.Draw(options.RevitDoc);
XYZ extruDir = (m_extrusionLine.GetEndPoint(1) - m_extrusionLine.GetEndPoint(0)).Normalize();
double offset = m_corbelCoverDistance + options.StirrupBarType.BarDiameter
+ options.HostStraightBarType.BarDiameter * 0.5;
XYZ delta = extruDir * offset;
XYZ pt1 = profileCopy.Bottom.GetEndPoint(0) + delta;
XYZ pt2 = profileCopy.Bottom.GetEndPoint(1) + delta;
Curve barLine = Line.CreateBound(pt1, pt2);
IList<Curve> barCurves = new List<Curve>();
barCurves.Add(barLine);
Rebar bars = Rebar.CreateFromCurves(
options.RevitDoc, RebarStyle.Standard,
options.HostStraightBarType, null, null, m_corbel.Host, extruDir, barCurves,
RebarHookOrientation.Left, RebarHookOrientation.Left, true, true);
bars.GetShapeDrivenAccessor().SetLayoutAsFixedNumber(2, m_extrusionLine.Length - 2 * offset, true, true, true);
ShowRebar3d(bars);
}
/// <summary>
/// Show the given rebar as solid in 3d view.
/// </summary>
/// <param name="rebar">Rebar to show in 3d view as solid</param>
private void ShowRebar3d(Rebar rebar)
{
var filter = new FilteredElementCollector(rebar.Document)
.OfClass(typeof(View3D));
foreach (View3D view in filter)
{
rebar.IsUnobscuredInView(view);
rebar.SetSolidInView(view, true);
}
}
}
}
CorbelReinforcementOptions.cs
//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Structure;
namespace Revit.SDK.Samples.MultiplanarRebar.CS
{
/// <summary>
/// Represent the reinforcement options of corbel.
/// The options include bar type and bar counts which are collected from user via UI input.
/// </summary>
class CorbelReinforcementOptions
{
/// <summary>
/// Active Revit DB Document.
/// </summary>
public Document RevitDoc { get; set; }
/// <summary>
/// List of RebarBarTypes in active document.
/// </summary>
public List<RebarBarType> RebarBarTypes { get; set; }
/// <summary>
/// RebarBarType for corbel top straight bars.
/// </summary>
public RebarBarType TopBarType { get; set; }
/// <summary>
/// RebarBarType for corbel stirrup bars.
/// </summary>
public RebarBarType StirrupBarType { get; set; }
/// <summary>
/// RebarBarType for corbel multi-planar bar.
/// </summary>
public RebarBarType MultiplanarBarType { get; set; }
/// <summary>
/// RebarBarType for corbel host straight bars.
/// </summary>
public RebarBarType HostStraightBarType { get; set; }
/// <summary>
/// Count of corbel straight bars.
/// </summary>
public int TopBarCount { get; set; }
/// <summary>
/// Count of corbel stirrup bars.
/// </summary>
public int StirrupBarCount { get; set; }
/// <summary>
/// Constructor to initialize the fields.
/// </summary>
/// <param name="revitDoc">Revit DB Document</param>
public CorbelReinforcementOptions(Document revitDoc)
{
RevitDoc = revitDoc;
FilteredElementCollector filteredElementCollector = new FilteredElementCollector(RevitDoc);
filteredElementCollector.OfClass(typeof(RebarBarType));
RebarBarTypes = filteredElementCollector.Cast<RebarBarType>().ToList<RebarBarType>();
}
}
}
CorbelReinforcementOptionsForm.cs
namespace Revit.SDK.Samples.MultiplanarRebar.CS
{
partial class CorbelReinforcementOptionsForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.okButton = new System.Windows.Forms.Button();
this.cancelButton = new System.Windows.Forms.Button();
this.topBarTypeComboBox = new System.Windows.Forms.ComboBox();
this.stirrupBarTypeComboBox = new System.Windows.Forms.ComboBox();
this.topBarTypeLabel = new System.Windows.Forms.Label();
this.stirrupBarTypeLabel = new System.Windows.Forms.Label();
this.multiplanarBarTypeLabel = new System.Windows.Forms.Label();
this.multiplanarBarTypeComboBox = new System.Windows.Forms.ComboBox();
this.topBarCountTextBox = new System.Windows.Forms.TextBox();
this.stirrupBarCountTextBox = new System.Windows.Forms.TextBox();
this.topBarGroupBox = new System.Windows.Forms.GroupBox();
this.topBarCountLabel = new System.Windows.Forms.Label();
this.stirrupBarGroupBox = new System.Windows.Forms.GroupBox();
this.stirrupBarCountLabel = new System.Windows.Forms.Label();
this.multiplanarBarGroupBox = new System.Windows.Forms.GroupBox();
this.columnGroupBox = new System.Windows.Forms.GroupBox();
this.columnBarTypeComboBox = new System.Windows.Forms.ComboBox();
this.columnBarTypeLabel = new System.Windows.Forms.Label();
this.topBarGroupBox.SuspendLayout();
this.stirrupBarGroupBox.SuspendLayout();
this.multiplanarBarGroupBox.SuspendLayout();
this.columnGroupBox.SuspendLayout();
this.SuspendLayout();
//
// okButton
//
this.okButton.Location = new System.Drawing.Point(144, 332);
this.okButton.Name = "okButton";
this.okButton.Size = new System.Drawing.Size(75, 23);
this.okButton.TabIndex = 0;
this.okButton.Text = "OK";
this.okButton.UseVisualStyleBackColor = true;
this.okButton.Click += new System.EventHandler(this.okButton_Click);
//
// cancelButton
//
this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.cancelButton.Location = new System.Drawing.Point(269, 332);
this.cancelButton.Name = "cancelButton";
this.cancelButton.Size = new System.Drawing.Size(75, 23);
this.cancelButton.TabIndex = 1;
this.cancelButton.Text = "Cancel";
this.cancelButton.UseVisualStyleBackColor = true;
//
// topBarTypeComboBox
//
this.topBarTypeComboBox.FormattingEnabled = true;
this.topBarTypeComboBox.Location = new System.Drawing.Point(86, 22);
this.topBarTypeComboBox.Name = "topBarTypeComboBox";
this.topBarTypeComboBox.Size = new System.Drawing.Size(121, 21);
this.topBarTypeComboBox.TabIndex = 2;
this.topBarTypeComboBox.SelectedIndexChanged += new System.EventHandler(this.topBarTypeComboBox_SelectedIndexChanged);
//
// stirrupBarTypeComboBox
//
this.stirrupBarTypeComboBox.FormattingEnabled = true;
this.stirrupBarTypeComboBox.Location = new System.Drawing.Point(86, 26);
this.stirrupBarTypeComboBox.Name = "stirrupBarTypeComboBox";
this.stirrupBarTypeComboBox.Size = new System.Drawing.Size(121, 21);
this.stirrupBarTypeComboBox.TabIndex = 3;
this.stirrupBarTypeComboBox.SelectedIndexChanged += new System.EventHandler(this.stirrupBarTypeComboBox_SelectedIndexChanged);
//
// topBarTypeLabel
//
this.topBarTypeLabel.AutoSize = true;
this.topBarTypeLabel.Location = new System.Drawing.Point(7, 22);
this.topBarTypeLabel.Name = "topBarTypeLabel";
this.topBarTypeLabel.Size = new System.Drawing.Size(53, 13);
this.topBarTypeLabel.TabIndex = 4;
this.topBarTypeLabel.Text = "Bar Type:";
//
// stirrupBarTypeLabel
//
this.stirrupBarTypeLabel.AutoSize = true;
this.stirrupBarTypeLabel.Location = new System.Drawing.Point(7, 26);
this.stirrupBarTypeLabel.Name = "stirrupBarTypeLabel";
this.stirrupBarTypeLabel.Size = new System.Drawing.Size(53, 13);
this.stirrupBarTypeLabel.TabIndex = 5;
this.stirrupBarTypeLabel.Text = "Bar Type:";
//
// multiplanarBarTypeLabel
//
this.multiplanarBarTypeLabel.AutoSize = true;
this.multiplanarBarTypeLabel.Location = new System.Drawing.Point(7, 25);
this.multiplanarBarTypeLabel.Name = "multiplanarBarTypeLabel";
this.multiplanarBarTypeLabel.Size = new System.Drawing.Size(53, 13);
this.multiplanarBarTypeLabel.TabIndex = 6;
this.multiplanarBarTypeLabel.Text = "Bar Type:";
//
// multiplanarBarTypeComboBox
//
this.multiplanarBarTypeComboBox.FormattingEnabled = true;
this.multiplanarBarTypeComboBox.Location = new System.Drawing.Point(86, 22);
this.multiplanarBarTypeComboBox.Name = "multiplanarBarTypeComboBox";
this.multiplanarBarTypeComboBox.Size = new System.Drawing.Size(121, 21);
this.multiplanarBarTypeComboBox.TabIndex = 7;
this.multiplanarBarTypeComboBox.SelectedIndexChanged += new System.EventHandler(this.multiplanarBarTypeComboBox_SelectedIndexChanged);
//
// topBarCountTextBox
//
this.topBarCountTextBox.Location = new System.Drawing.Point(334, 22);
this.topBarCountTextBox.Name = "topBarCountTextBox";
this.topBarCountTextBox.Size = new System.Drawing.Size(100, 20);
this.topBarCountTextBox.TabIndex = 8;
this.topBarCountTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.topBarCountTextBox_Validating);
//
// stirrupBarCountTextBox
//
this.stirrupBarCountTextBox.Location = new System.Drawing.Point(334, 26);
this.stirrupBarCountTextBox.Name = "stirrupBarCountTextBox";
this.stirrupBarCountTextBox.Size = new System.Drawing.Size(100, 20);
this.stirrupBarCountTextBox.TabIndex = 9;
this.stirrupBarCountTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.stirrupBarCountTextBox_Validating);
//
// topBarGroupBox
//
this.topBarGroupBox.Controls.Add(this.topBarCountLabel);
this.topBarGroupBox.Controls.Add(this.topBarTypeComboBox);
this.topBarGroupBox.Controls.Add(this.topBarTypeLabel);
this.topBarGroupBox.Controls.Add(this.topBarCountTextBox);
this.topBarGroupBox.Location = new System.Drawing.Point(12, 80);
this.topBarGroupBox.Name = "topBarGroupBox";
this.topBarGroupBox.Size = new System.Drawing.Size(448, 54);
this.topBarGroupBox.TabIndex = 10;
this.topBarGroupBox.TabStop = false;
this.topBarGroupBox.Text = "Top Bars";
//
// topBarCountLabel
//
this.topBarCountLabel.AutoSize = true;
this.topBarCountLabel.Location = new System.Drawing.Point(254, 22);
this.topBarCountLabel.Name = "topBarCountLabel";
this.topBarCountLabel.Size = new System.Drawing.Size(57, 13);
this.topBarCountLabel.TabIndex = 9;
this.topBarCountLabel.Text = "Bar Count:";
//
// stirrupBarGroupBox
//
this.stirrupBarGroupBox.Controls.Add(this.stirrupBarCountLabel);
this.stirrupBarGroupBox.Controls.Add(this.stirrupBarTypeComboBox);
this.stirrupBarGroupBox.Controls.Add(this.stirrupBarTypeLabel);
this.stirrupBarGroupBox.Controls.Add(this.stirrupBarCountTextBox);
this.stirrupBarGroupBox.Location = new System.Drawing.Point(12, 164);
this.stirrupBarGroupBox.Name = "stirrupBarGroupBox";
this.stirrupBarGroupBox.Size = new System.Drawing.Size(448, 54);
this.stirrupBarGroupBox.TabIndex = 11;
this.stirrupBarGroupBox.TabStop = false;
this.stirrupBarGroupBox.Text = "Stirrup Bars";
//
// stirrupBarCountLabel
//
this.stirrupBarCountLabel.AutoSize = true;
this.stirrupBarCountLabel.Location = new System.Drawing.Point(254, 26);
this.stirrupBarCountLabel.Name = "stirrupBarCountLabel";
this.stirrupBarCountLabel.Size = new System.Drawing.Size(57, 13);
this.stirrupBarCountLabel.TabIndex = 10;
this.stirrupBarCountLabel.Text = "Bar Count:";
//
// multiplanarBarGroupBox
//
this.multiplanarBarGroupBox.Controls.Add(this.multiplanarBarTypeComboBox);
this.multiplanarBarGroupBox.Controls.Add(this.multiplanarBarTypeLabel);
this.multiplanarBarGroupBox.Location = new System.Drawing.Point(12, 251);
this.multiplanarBarGroupBox.Name = "multiplanarBarGroupBox";
this.multiplanarBarGroupBox.Size = new System.Drawing.Size(448, 54);
this.multiplanarBarGroupBox.TabIndex = 12;
this.multiplanarBarGroupBox.TabStop = false;
this.multiplanarBarGroupBox.Text = "Multiplanar Bars";
//
// columnGroupBox
//
this.columnGroupBox.Controls.Add(this.columnBarTypeComboBox);
this.columnGroupBox.Controls.Add(this.columnBarTypeLabel);
this.columnGroupBox.Location = new System.Drawing.Point(12, 12);
this.columnGroupBox.Name = "columnGroupBox";
this.columnGroupBox.Size = new System.Drawing.Size(448, 54);
this.columnGroupBox.TabIndex = 13;
this.columnGroupBox.TabStop = false;
this.columnGroupBox.Text = "Host Straight Bars";
//
// columnBarTypeComboBox
//
this.columnBarTypeComboBox.FormattingEnabled = true;
this.columnBarTypeComboBox.Location = new System.Drawing.Point(86, 22);
this.columnBarTypeComboBox.Name = "columnBarTypeComboBox";
this.columnBarTypeComboBox.Size = new System.Drawing.Size(121, 21);
this.columnBarTypeComboBox.TabIndex = 7;
this.columnBarTypeComboBox.SelectedIndexChanged += new System.EventHandler(this.columnBarTypeComboBox_SelectedIndexChanged);
//
// columnBarTypeLabel
//
this.columnBarTypeLabel.AutoSize = true;
this.columnBarTypeLabel.Location = new System.Drawing.Point(7, 25);
this.columnBarTypeLabel.Name = "columnBarTypeLabel";
this.columnBarTypeLabel.Size = new System.Drawing.Size(53, 13);
this.columnBarTypeLabel.TabIndex = 6;
this.columnBarTypeLabel.Text = "Bar Type:";
//
// CorbelReinforcementOptionsForm
//
this.AcceptButton = this.okButton;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.Control;
this.CancelButton = this.cancelButton;
this.ClientSize = new System.Drawing.Size(476, 387);
this.ControlBox = false;
this.Controls.Add(this.columnGroupBox);
this.Controls.Add(this.multiplanarBarGroupBox);
this.Controls.Add(this.stirrupBarGroupBox);
this.Controls.Add(this.topBarGroupBox);
this.Controls.Add(this.cancelButton);
this.Controls.Add(this.okButton);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MinimizeBox = false;
this.Name = "CorbelReinforcementOptionsForm";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.Text = "Corbel Reinforcement Options";
this.topBarGroupBox.ResumeLayout(false);
this.topBarGroupBox.PerformLayout();
this.stirrupBarGroupBox.ResumeLayout(false);
this.stirrupBarGroupBox.PerformLayout();
this.multiplanarBarGroupBox.ResumeLayout(false);
this.multiplanarBarGroupBox.PerformLayout();
this.columnGroupBox.ResumeLayout(false);
this.columnGroupBox.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button okButton;
private System.Windows.Forms.Button cancelButton;
private System.Windows.Forms.ComboBox topBarTypeComboBox;
private System.Windows.Forms.ComboBox stirrupBarTypeComboBox;
private System.Windows.Forms.Label topBarTypeLabel;
private System.Windows.Forms.Label stirrupBarTypeLabel;
private System.Windows.Forms.Label multiplanarBarTypeLabel;
private System.Windows.Forms.ComboBox multiplanarBarTypeComboBox;
private System.Windows.Forms.TextBox topBarCountTextBox;
private System.Windows.Forms.TextBox stirrupBarCountTextBox;
private System.Windows.Forms.GroupBox topBarGroupBox;
private System.Windows.Forms.GroupBox stirrupBarGroupBox;
private System.Windows.Forms.GroupBox multiplanarBarGroupBox;
private System.Windows.Forms.Label topBarCountLabel;
private System.Windows.Forms.Label stirrupBarCountLabel;
private System.Windows.Forms.GroupBox columnGroupBox;
private System.Windows.Forms.ComboBox columnBarTypeComboBox;
private System.Windows.Forms.Label columnBarTypeLabel;
}
}
GeometryUtil.cs
//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Structure;
namespace Revit.SDK.Samples.MultiplanarRebar.CS
{
/// <summary>
/// This class is to parse the geometry information of given Corbel FamilyInstance,
/// and finally construct a CorbelFrame according to the parsed geometry information.
/// </summary>
class GeometryUtil
{
/// <summary>
/// This method parses geometry information of given Corbel to construct the CorbelFrame.
/// </summary>
/// <param name="corbel">Given corbel family instance to parse</param>
/// <returns>CorbelFrame object</returns>
public static CorbelFrame ParseCorbelGeometry(FamilyInstance corbel)
{
// Get Corbel Host information.
Element corbelHost = corbel.Host;
Reference corbelHostFace = corbel.HostFace;
PlanarFace hostPlane = corbelHost.GetGeometryObjectFromReference(corbelHostFace) as PlanarFace;
XYZ hostNormal = GetNormalOutside(hostPlane);
// Extract the faces in Corbel parallel with Corbel host face.
Solid corbelSolid = GetElementSolid(corbel);
PlanarFace corbelTopFace = null;
PlanarFace corbelBottomFace = null;
foreach (Face face in corbelSolid.Faces)
{
PlanarFace planarFace = face as PlanarFace;
XYZ normal = GetNormalOutside(planarFace);
if (normal.IsAlmostEqualTo(hostNormal))
{
corbelTopFace = planarFace;
}
else if (normal.IsAlmostEqualTo(-hostNormal))
{
corbelBottomFace = planarFace;
}
}
// Extract the faces in Corbel Host parallel with Corbel host face.
Solid hostSolid = GetElementSolid(corbelHost);
PlanarFace hostTopFace = null;
PlanarFace hostBottomFace = hostPlane;
foreach (Face face in hostSolid.Faces)
{
PlanarFace planarFace = face as PlanarFace;
XYZ normal = GetNormalOutside(planarFace);
if (normal.IsAlmostEqualTo(-hostNormal))
{
hostTopFace = planarFace;
}
}
// Parse the side faces to find out the Trapezoid face.
Edge topEdge = null;
Edge leftEdge = null;
Edge bottomEdge = null;
Edge rightEdge = null;
PlanarFace trapezoidFace = null;
int foundEdgeIndex = -1;
bool foundTrapezoid = false;
EdgeArray bottomEdges = corbelBottomFace.EdgeLoops.get_Item(0);
foreach (Edge edge in bottomEdges)
{
bottomEdge = edge;
foundEdgeIndex++;
foundTrapezoid = IsTrapezoid(hostNormal, corbelBottomFace, bottomEdge,
out trapezoidFace, out topEdge, out leftEdge, out rightEdge);
if (foundTrapezoid)
{
break;
}
}
// Check to see if the Trapezoid faces was found.
if (!foundTrapezoid)
{
// Throw if no any trapezoid face in corbel.
throw new Exception("Didn't find the trapezoid face in corbel [Id:" + corbel.Id + "].");
}
Edge depthEdge = bottomEdges.get_Item((foundEdgeIndex + 1) % bottomEdges.Size);
double hostDepth = GetDistance(hostTopFace, hostBottomFace);
// Compute the host face cover distance.
RebarHostData corbelHostData = RebarHostData.GetRebarHostData(corbelHost);
// Get CoverType of the given host face
RebarCoverType coverType = corbelHostData.GetCoverType(hostTopFace.Reference);
// if the host face don't have a CoverType, then try to get the common CoverType.
if (coverType == null)
coverType = corbelHostData.GetCommonCoverType();
// Get the Cover Distance
double coverDistance = coverType.CoverDistance;
// Construct the CorbelFrame from the given parsed trapezoid information.
return ConstructCorbelFrame(
corbel, depthEdge,
leftEdge, bottomEdge, rightEdge, topEdge,
corbel.Document, trapezoidFace,
hostDepth, coverDistance);
}
/// <summary>
/// Check if the given bottom edge was shared by a trapezoid face with left edge vertical.
/// </summary>
/// <param name="hostNormal">Corbel Host face Normal</param>
/// <param name="corbelBottomFace">Bottom Face of Corbel</param>
/// <param name="bottomEdge">Given bottom edge to test</param>
/// <param name="trapezoidFace">Output the trapezoid Face</param>
/// <param name="topEdge">Output trapezoid top edge</param>
/// <param name="leftEdge">Output trapezoid left edge</param>
/// <param name="rightEdge">Output trapezoid right edge</param>
/// <returns>True if there is a trapezoid face share the given bottom edge, otherwise false.</returns>
private static bool IsTrapezoid(
XYZ hostNormal, PlanarFace corbelBottomFace, Edge bottomEdge,
out PlanarFace trapezoidFace, out Edge topEdge,
out Edge leftEdge, out Edge rightEdge)
{
PlanarFace face1 = bottomEdge.GetFace(0) as PlanarFace;
PlanarFace face2 = bottomEdge.GetFace(1) as PlanarFace;
trapezoidFace = face1 == corbelBottomFace ? face2 : face1;
EdgeArray trapezoidFaceEdges = trapezoidFace.EdgeLoops.get_Item(0);
XYZ bottomEdgeDir = (bottomEdge.Evaluate(1.0) - bottomEdge.Evaluate(0.0)).Normalize();
int bottomEdgeIndex = -1;
topEdge = null;
for (int i = 0; i < trapezoidFaceEdges.Size; i++)
{
Edge edge = trapezoidFaceEdges.get_Item(i);
XYZ edgeDir = (edge.Evaluate(1.0) - edge.Evaluate(0.0)).Normalize();
if (edgeDir.IsAlmostEqualTo(bottomEdgeDir) ||
edgeDir.IsAlmostEqualTo(-bottomEdgeDir))
{
if (edge.Evaluate(0.0).IsAlmostEqualTo(bottomEdge.Evaluate(0.0)))
{
bottomEdge = edge;
bottomEdgeIndex = i;
}
else
{
topEdge = edge;
}
}
}
leftEdge = trapezoidFaceEdges.get_Item((trapezoidFaceEdges.Size + bottomEdgeIndex - 1) % trapezoidFaceEdges.Size);
rightEdge = trapezoidFaceEdges.get_Item((bottomEdgeIndex + 1) % trapezoidFaceEdges.Size);
XYZ leftEdgeDir = (leftEdge.Evaluate(1.0) - leftEdge.Evaluate(0.0)).Normalize();
bool isLeftEdgeVertical = false;
if (leftEdgeDir.IsAlmostEqualTo(hostNormal) ||
leftEdgeDir.IsAlmostEqualTo(-hostNormal))
{
isLeftEdgeVertical = true;
}
XYZ rightEdgeDir = (rightEdge.Evaluate(1.0) - rightEdge.Evaluate(0.0)).Normalize();
bool rightEdgeIsVertical = false;
if (rightEdgeDir.IsAlmostEqualTo(hostNormal) ||
rightEdgeDir.IsAlmostEqualTo(-hostNormal))
{
rightEdgeIsVertical = true;
}
return isLeftEdgeVertical && !rightEdgeIsVertical;
}
/// <summary>
/// Create the CorbelFrame object with the given trapezoid face, corbel and its host information.
/// </summary>
/// <param name="corbel">Corbel instance</param>
/// <param name="depthEdge">Depth Edge which is vertical with trapezoid face</param>
/// <param name="leftEdge">Left edge of trapezoid</param>
/// <param name="bottomEdge">Bottom edge of trapezoid</param>
/// <param name="rightEdge">Right edge of trapezoid</param>
/// <param name="topEdge">Top edge of trapezoid</param>
/// <param name="revitDoc">Revit Document</param>
/// <param name="trapezoidFace">Trapezoid Face</param>
/// <param name="hostDepth">Corbel Host depth</param>
/// <param name="hostTopCoverDistance">Corbel Host Top face cover distance</param>
/// <returns>CorbelFrame object</returns>
private static CorbelFrame ConstructCorbelFrame(
FamilyInstance corbel,
Edge depthEdge, Edge leftEdge, Edge bottomEdge, Edge rightEdge, Edge topEdge,
Document revitDoc, PlanarFace trapezoidFace,
double hostDepth, double hostTopCoverDistance)
{
XYZ leftEdgeDir = (leftEdge.Evaluate(1.0) - leftEdge.Evaluate(0.0)).Normalize();
XYZ leftEdgeV0 = leftEdge.Evaluate(0.0);
Line leftEdgeLine = Line.CreateUnbound(leftEdgeV0, leftEdgeDir);
XYZ rightEdgeDir = (rightEdge.Evaluate(1.0) - rightEdge.Evaluate(0.0)).Normalize();
XYZ rightEdgeV0 = rightEdge.Evaluate(0.0);
Line rightEdgeLine = Line.CreateUnbound(rightEdgeV0, rightEdgeDir);
XYZ topEdgeDir = (topEdge.Evaluate(1.0) - topEdge.Evaluate(0.0)).Normalize();
XYZ topEdgeV0 = topEdge.Evaluate(0.0);
Line topEdgeLine = Line.CreateUnbound(topEdgeV0, topEdgeDir);
IntersectionResultArray intersections;
topEdgeLine.Intersect(leftEdgeLine, out intersections);
XYZ prevX = intersections.get_Item(0).XYZPoint;
topEdgeLine.Intersect(rightEdgeLine, out intersections);
XYZ nextX = intersections.get_Item(0).XYZPoint;
XYZ edgeV0 = GetCommonVertex(bottomEdge, leftEdge);
XYZ edgeV1 = GetCommonVertex(bottomEdge, rightEdge);
Line topBoundLine = Line.CreateBound(nextX, prevX);
Line leftBoundLine = Line.CreateBound(prevX, edgeV0);
Line bottomBoundLine = Line.CreateBound(edgeV0, edgeV1);
Line rightBoundLine = Line.CreateBound(edgeV1, nextX);
Trapezoid profile = new Trapezoid(topBoundLine, leftBoundLine, bottomBoundLine, rightBoundLine);
XYZ depthEdgeV0 = depthEdge.Evaluate(0.0);
XYZ depthEdgeV1 = depthEdge.Evaluate(1.0);
Line depthLine = null;
if (depthEdgeV0.IsAlmostEqualTo(edgeV0))
{
depthLine = Line.CreateBound(depthEdgeV0, depthEdgeV1);
}
else if (depthEdgeV1.IsAlmostEqualTo(edgeV0))
{
depthLine = Line.CreateBound(depthEdgeV1, depthEdgeV0);
}
CorbelFrame frame = new CorbelFrame(corbel, profile, depthLine, hostDepth, hostTopCoverDistance);
return frame;
}
/// <summary>
/// Get the common vertex XYZ of two edges.
/// </summary>
/// <param name="edge1">Edge 1</param>
/// <param name="edge2">Edge 2</param>
/// <returns>Common vertex XYZ</returns>
private static XYZ GetCommonVertex(Edge edge1, Edge edge2)
{
XYZ edge1V0 = edge1.Evaluate(0.0);
XYZ edge1V1 = edge1.Evaluate(1.0);
XYZ edge2V0 = edge2.Evaluate(0.0);
XYZ edge2V1 = edge2.Evaluate(1.0);
if (edge1V0.IsAlmostEqualTo(edge2V0) ||
edge1V0.IsAlmostEqualTo(edge2V1))
{
return edge1V0;
}
else if (edge1V1.IsAlmostEqualTo(edge2V0) ||
edge1V1.IsAlmostEqualTo(edge2V1))
{
return edge1V1;
}
return null;
}
/// <summary>
/// Extract the Solid of given element.
/// </summary>
/// <param name="element">Given Element to get its Solid</param>
/// <returns>Solid of given element</returns>
private static Solid GetElementSolid(Element element)
{
Options goption = new Options();
goption.ComputeReferences = true;
GeometryElement gelem = element.get_Geometry(goption);
Solid resultSolid = null;
//foreach (GeometryObject gobj in gelem.Objects)
IEnumerator<GeometryObject> Objects = gelem.GetEnumerator();
while (Objects.MoveNext())
{
GeometryObject gobj = Objects.Current;
GeometryInstance gIns = gobj as GeometryInstance;
if (gIns != null)
{
GeometryElement finalGeom = gIns.GetInstanceGeometry();
//foreach (GeometryObject gobj2 in finalGeom.Objects)
IEnumerator<GeometryObject> Objects1 = finalGeom.GetEnumerator();
while (Objects1.MoveNext())
{
GeometryObject gobj2 = Objects1.Current;
Solid tSolid = gobj2 as Solid;
if (tSolid != null && tSolid.Faces.Size > 0 && tSolid.Volume > 0)
{
resultSolid = tSolid;
break;
}
}
}
if (resultSolid == null)
{
Solid tSolid2 = gobj as Solid;
if (tSolid2 != null && tSolid2.Faces.Size > 0 && tSolid2.Volume > 0)
{
resultSolid = tSolid2;
break;
}
}
}
return resultSolid;
}
/// <summary>
/// Compute the outside normal of given face.
/// </summary>
/// <param name="face">Given face to get its outside normal</param>
/// <returns>Outside normal of given face</returns>
private static XYZ GetNormalOutside(Face face)
{
Edge edge = face.EdgeLoops.get_Item(0).get_Item(0);
UV pt = edge.EvaluateOnFace(0.5, face);
XYZ faceNormal = face.ComputeNormal(pt);
return faceNormal;
}
/// <summary>
/// Compute the distance between two planar faces.
/// </summary>
/// <param name="face1">Face 1</param>
/// <param name="face2">Face 2</param>
/// <returns>Distance of the two planar faces</returns>
private static double GetDistance(PlanarFace face1, PlanarFace face2)
{
BoundingBoxUV boxUV = face2.GetBoundingBox();
UV center = (boxUV.Max + boxUV.Min) * 0.5;
XYZ centerPt = face2.Evaluate(center);
IntersectionResult result = face1.Project(centerPt);
return face1.Project(centerPt).Distance;
}
}
}
SharedParameterUtil.cs
//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System;
using Autodesk.Revit.DB;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB.Structure;
using System.Reflection;
using System.IO;
namespace Revit.SDK.Samples.MultiplanarRebar.CS
{
/// <summary>
/// This is an utility class used to create shared parameter in Revit Document.
/// It simplifies the process of shared parameters creation.
/// </summary>
class SharedParameterUtil
{
/// <summary>
/// Get existed or create a new shared parameters with the given name and Revit DB Document.
/// </summary>
/// <param name="name">Shared parameter name</param>
/// <param name="revitDoc">Revit DB Document</param>
/// <returns>ElementId of get or created shared parameter</returns>
public static ElementId GetOrCreateDef(string name, Document revitDoc)
{
ExternalDefinition ed = GetOrCreateDef(name, revitDoc.Application);
return RebarShapeParameters.GetOrCreateElementIdForExternalDefinition(revitDoc, ed);
}
/// <summary>
/// Get existed or create a new shared parameters with the given name and Revit DB Application.
/// </summary>
/// <param name="name">Shared parameter name</param>
/// <param name="revitApp">Revit DB Application</param>
/// <returns>ExternalDefinition of get or created shared parameter</returns>
public static ExternalDefinition GetOrCreateDef(string name, Application revitApp)
{
return GetOrCreateDef(name, "Rebar Shape", revitApp);
}
/// <summary>
/// Get existed or create a new shared parameters with the given name, group and Revit DB Application.
/// </summary>
/// <param name="name">Shared parameter name</param>
/// <param name="groupName">Shared parameter group name</param>
/// <param name="revitApp">Revit DB Application</param>
/// <returns>ExternalDefinition of get or created shared parameter</returns>
public static ExternalDefinition GetOrCreateDef(string name, string groupName, Application revitApp)
{
DefinitionFile parameterFile = GetSharedParameterFile(revitApp);
DefinitionGroup group = parameterFile.Groups.get_Item(groupName);
if (group == null)
group = parameterFile.Groups.Create(groupName);
ExternalDefinition Bdef = group.Definitions.get_Item(name) as ExternalDefinition;
if (Bdef == null)
{
ExternalDefinitionCreationOptions ExternalDefinitionCreationOptions = new ExternalDefinitionCreationOptions(name, ParameterType.ReinforcementLength);
Bdef = group.Definitions.Create(ExternalDefinitionCreationOptions) as ExternalDefinition;
}
return Bdef;
}
/// <summary>
/// Get shared parameter DefinitionFile of given Revit DB Application.
/// </summary>
/// <param name="revitApp">Revit DB Application</param>
/// <returns>DefinitionFile of Revit DB Application</returns>
public static DefinitionFile GetSharedParameterFile(Application revitApp)
{
DefinitionFile file = null;
int count = 0;
// A count is to avoid infinite loop
while (null == file && count < 100)
{
file = revitApp.OpenSharedParameterFile();
if (file == null)
{
// If Shared parameter file does not exist, then create a new one.
string shapeFile =
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
+ "\\MultiplanarParameterFiles.txt";
// Fill Schema data of Revit shared parameter file.
// If no this schema data, OpenSharedParameterFile may alway return null.
System.Text.StringBuilder contents = new System.Text.StringBuilder();
contents.AppendLine("# This is a Revit shared parameter file.");
contents.AppendLine("# Do not edit manually.");
contents.AppendLine("*META VERSION MINVERSION");
contents.AppendLine("META 2 1");
contents.AppendLine("*GROUP ID NAME");
contents.AppendLine("*PARAM GUID NAME DATATYPE DATACATEGORY GROUP VISIBLE");
// Write Schema data of Revit shared parameter file.
File.WriteAllText(shapeFile, contents.ToString());
// Set Revit shared parameter file
revitApp.SharedParametersFilename = shapeFile;
}
// To avoid infinite loop.
++count;
}
return file;
}
}
}
版权所有 :无锡模信建筑科技有限公司 苏ICP备2021028830号-1 BIM建模|BIM技术应用|BIM软件开发
联系地址:江苏省无锡市新吴区龙山路4号B座705 手机:18761516598