Files
ShrlAlgoToolkit/ShrlAlgoToolkit.RevitAddins/RvCivil/SlopedFloorCmd.cs
2025-10-04 08:52:23 +08:00

205 lines
8.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
using Nice3point.Revit.Toolkit.External;
namespace ShrlAlgoToolkit.RevitAddins.RvCivil;
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
public class SlopedFloorCmd : ExternalCommand
{
public override void Execute()
{
Document.Invoke(
_ =>
{
Line line1 = null;
Line line2 = null;
HostObject obj1 = null;
HostObject obj2 = null;
var refer = UiDocument.Selection.PickObject(
ObjectType.Edge,
new FuncFilter(
elem => elem is HostObject,
(r, _) =>
{
obj1 = Document.GetElement(r) as HostObject;
var edge = obj1?.GetGeometryObjectFromReference(r) as Edge;
if (edge?.AsCurve() is Line l && l.Direction.Z < 0.0001)
{
line1 = l;
return true;
}
return false;
}
),
"请选择主体元素其中的一条水平边"
);
var elem = Document.GetElement(refer);
UiDocument.Selection.PickObject(
ObjectType.Edge,
new FuncFilter(
elem => elem is HostObject && elem.Id != obj1.Id,
(r, _) =>
{
obj2 = Document.GetElement(r) as HostObject;
var edge1 = obj2?.GetGeometryObjectFromReference(r) as Edge;
if (
edge1?.AsCurve() is Line l
&& l.Direction.Z < 0.0001
&& l.Direction.CrossProduct(line1.Direction).IsAlmostEqualTo(XYZ.Zero)
&& l.Distance(line1.Origin) > Application.ShortCurveTolerance / 304.8
)
{
line2 = l;
return true;
}
return false;
}
),
"请选择与另一条平行的水平边"
);
var level1 = Document.GetElement(obj1.LevelId) as Level;
var level2 = Document.GetElement(obj2.LevelId) as Level;
var baseLevel = level1?.Elevation > level2?.Elevation ? level2 : level1;
//基准边,低的边
var lineBase = line1.Origin.Z < line2.Origin.Z ? line1 : line2;
var lineAnother = line1.Origin.Z < line2.Origin.Z ? line2 : line1;
//if (line1.Origin.Z < line2.Origin.Z)
//{
// lineBase = line1;
// lineAnother = line2;
//}
//else
//{
// lineBase = line2;
// lineAnother = line1;
//}
var curveArr = new CurveArray();
var planeToProject = Plane.CreateByNormalAndOrigin(XYZ.BasisZ, lineBase.Origin);
var p1 = planeToProject.ProjectOf(lineBase.GetEndPoint(0));
var p2 = planeToProject.ProjectOf(lineBase.GetEndPoint(1));
var p3 = planeToProject.ProjectOf(lineAnother.GetEndPoint(0));
var p4 = planeToProject.ProjectOf(lineAnother.GetEndPoint(1));
Line l1;
Line l2;
Line l3;
Line l4;
if (lineBase.Direction.IsAlmostEqualTo(lineAnother.Direction))
{
l1 = Line.CreateBound(p1, p2);
l3 = Line.CreateBound(p4, p3);
l4 = Line.CreateBound(p3, p1);
l2 = Line.CreateBound(p2, p4);
}
else
{
l1 = Line.CreateBound(p1, p2);
l3 = Line.CreateBound(p3, p4);
l4 = Line.CreateBound(p4, p1);
l2 = Line.CreateBound(p2, p3);
}
curveArr.Append(l1);
curveArr.Append(l2);
curveArr.Append(l3);
curveArr.Append(l4);
//var isStructure = obj1.get_Parameter(BuiltInParameter.FLOOR_PARAM_IS_STRUCTURAL).AsInteger();
//选择线的中点连线
var centerLine = Line.CreateBound(lineBase.Evaluate(0.5, true), lineAnother.Evaluate(0.5, true));
//中线和边线叉乘,求出楼板面的法向量
var floorNormal = lineBase.Direction.CrossProduct(centerLine.Direction);
if (floorNormal.Z < 0)
{
floorNormal = floorNormal.Negate();
}
//坡度角
var radian = floorNormal.AngleTo(XYZ.BasisZ);
//另一条楼板边垂直xy的平面
var normal = lineAnother.Direction.CrossProduct(XYZ.BasisZ);
var plane = Plane.CreateByNormalAndOrigin(normal, lineAnother.Evaluate(0.5, true));
//点与平面的距离
var centerPoint = lineBase.Evaluate(0.5, true);
var perpPoint = plane.ProjectOf(centerPoint);
var slopedArrow = Line.CreateBound(centerPoint, new XYZ(perpPoint.X, perpPoint.Y, centerPoint.Z));
//if (lineBase.Origin.Z > lineAnother.Origin.Z)
//{
// slopedArrow = slopedArrow.CreateReversed() as Line;
//}
//即板上表面法向量和Z轴正向之间
//double radian = slopedArrow.Direction.AngleOnPlaneTo(XYZ.BasisX, XYZ.BasisZ);
//double slope = Math.Abs(line1.Evaluate(0.5, true).Z - line2.Evaluate(0.5, true).Z);
//slopedArrow用以指定在XY平面上绘制的板轮廓是沿着哪个方向进行坡度变化的。因此这条线实际上是XY平面上垂直于板上表面与XY平面交线的一条线。
#if REVIT2018 || REVIT2020
Document.Create.NewSlab(curveArr, baseLevel, slopedArrow, Math.Tan(radian), true);
#elif REVIT2025
var floorType = Floor.GetDefaultFloorType(Document, false);
if (elem is Floor floor)
{
floorType = floor.GetTypeId();
}
var loops = new List<CurveLoop>() { CurveLoop.Create(new List<Curve>() { l1, l2, l3, l4 }) };
Floor.Create(Document, loops, floorType, baseLevel.Id, true, slopedArrow, Math.Tan(radian));
#endif
},
"坡度楼板"
);
}
private static bool IfSameHeight(List<double> vs)
{
//判断楼板中各端点标高是否相等
List<double> list = new();
foreach (var z in vs)
{
if (list.Contains(z) == false)
{
list.Add(z);
}
}
return list.Count == 1;
}
//编辑子图元
private void EditSubElements(Floor floor)
{
#if REVIT2018 || REVIT2020
var slabShapeEditor = floor.SlabShapeEditor;
#elif REVIT2025
var slabShapeEditor = floor.GetSlabShapeEditor();
#endif
if (slabShapeEditor.IsEnabled)
{
var vertices = slabShapeEditor.SlabShapeVertices;
var zList = new List<double>();
foreach (SlabShapeVertex slabShapeVertex in vertices)
{
zList.Add(slabShapeVertex.Position.Z);
}
//判断为水平板后重设形状
if (IfSameHeight(zList))
{
var floorLevel = floor.Document.GetElement(floor.LevelId) as Level; //获取楼板所在标高
var levelHeight = floorLevel.LookupParameter("立面").AsDouble(); //获取所在标高的标高
var offsetHeight = zList.FirstOrDefault() - levelHeight;
floor.get_Parameter(BuiltInParameter.FLOOR_HEIGHTABOVELEVEL_PARAM).Set(offsetHeight);
slabShapeEditor.ResetSlabShape();
}
}
}
}