概述
梁随板是较为实用的工具,下面是能直接找到的找到的代码:
早先梁随板案例
这个代码实现的功能会发现与橄榄山插件做到的不一样,上述插件是利用坐标转换的方式得到原有梁到既定平面的投影。
这种投影法会出现梁水平方向的偏移
橄榄山插件做法
方法代码
查阅软件研发教材关于坐标转换章节的内容,理解坐标转换。
微调后的方法
微调内容是根据定位点分别做竖直点,再根据线与面的交点得到需求点,根据两个需求点将定位线做一个变更
下面的代码依旧保留了坐标转换以及投影线部分的内容,而没有用线与面的交点的方法,主要是为了保留一些投影线的案例,实际使用本代码时注意选择最优解。
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
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 AlignedBeamWPF
{
/// <summary>
/// 梁随斜板
/// </summary>
[Transaction(TransactionMode.Manual)]
class Class1 : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIDocument uidoc = commandData.Application.ActiveUIDocument;
Document doc = uidoc.Document;
FloorISelection floorISelection = new FloorISelection();
MainWindow wpf = new MainWindow();//实例化主窗口
wpf.ShowDialog();//展示界面
if (!wpf.IsClickClose)
{
return Result.Cancelled;
}
//【1】拾取楼板和梁
Reference reference;
try
{
reference = uidoc.Selection.PickObject(ObjectType.Element, floorISelection, "选择楼板");
}
catch
{
return Result.Succeeded;
}
BeamISelection beamISelection = new BeamISelection();
IList<Reference> beamReferences =new List<Reference> ();
try
{
beamReferences = uidoc.Selection.PickObjects(ObjectType.Element, beamISelection, "框选所需操作的梁");
}
catch
{
return Result.Succeeded;
}
List<ElementId> ids = new List<ElementId>();
foreach (var item in beamReferences)
{
ElementId id = doc.GetElement(item).Id;
ids.Add(id);
}
//【2】获得元素表面,根据交互选择确定是获取楼板底面,还是楼板顶面并偏移梁后距离的面
//这里补充说明一下, 梁默认的定位线位置在梁顶部,如果单纯按照梁顶面求交点的方式,梁会埋没在板中间,与橄榄山插件的效果类似
//按照实际工程需要这里对相对平面进行一个梁厚的偏移
foreach (var id in ids)//注意修改数据需要将楼板参数放入循环内容里面,要不然会持续报错
{
Floor floor = doc.GetElement(reference) as Floor;
double floorH = floor.LookupParameter("厚度").AsDouble();
//获取几何表面
Reference bottomFaceRef = HostObjectUtils.GetBottomFaces(floor).First();
Reference GetTopFaceRef = HostObjectUtils.GetTopFaces(floor).First();
Face GetTopFace = floor.GetGeometryObjectFromReference(GetTopFaceRef) as Face;
Face bottomFace = floor.GetGeometryObjectFromReference(bottomFaceRef) as Face;
FamilyInstance beam = doc.GetElement(id) as FamilyInstance;
//梁高度
//获取梁定位线
LocationCurve beamLocation = beam.Location as LocationCurve;
Line bLine = beamLocation.Curve as Line;
//获取梁的两个端点
XYZ pStart = bLine.GetEndPoint(0);
XYZ pEnd = bLine.GetEndPoint(1);
//通过两个端点做z方向直线,然后利用直线与面的交点求出对应位置的梁端点
Line lStart = Line.CreateUnbound(pStart, XYZ.BasisZ);
Line lEnd = Line.CreateUnbound(pEnd, XYZ.BasisZ);
//与目标面相交的两个端点
XYZ startPoint = null;
XYZ endPoint = null;
if (wpf.btnselect == false) //交互界面选择为对齐底面时
{
startPoint = IntersectPointOfFaceAndCurve(bottomFace, lStart);
endPoint = IntersectPointOfFaceAndCurve(bottomFace, lEnd);
}
if (wpf.btnselect == true)//交互界面选择为对齐顶面时
{
double h = beam.Symbol.LookupParameter("h").AsDouble();
startPoint = IntersectPointOfFaceAndCurve(bottomFace, lStart);
endPoint = IntersectPointOfFaceAndCurve(bottomFace, lEnd);
//获取顶面交点
XYZ startPoint2 = IntersectPointOfFaceAndCurve(GetTopFace, lStart);
XYZ endPoint2 = IntersectPointOfFaceAndCurve(GetTopFace, lEnd);
//相似三角形计算得出,这里就不用坐标转化了,坐标转化结果显示有问题,可能斜梁显示逻辑理解不对
startPoint = new XYZ(startPoint2.X, startPoint2.Y, (startPoint2.Z - startPoint.Z) * h / floorH + startPoint2.Z);
endPoint = new XYZ(endPoint2.X, endPoint2.Y, (endPoint2.Z - endPoint.Z) * h / floorH + endPoint2.Z);
进行坐标系转化,实现交点往平面法向方向顺延h的目的;
//PlanarFace planeFace = GetTopFace as PlanarFace;
顶面定位线坐标
//Transform tf = Transform.Identity;
//tf.BasisX = planeFace.XVector;
//tf.BasisY = planeFace.YVector;
//tf.BasisZ = planeFace.FaceNormal;
//tf.Origin = planeFace.Origin;
//XYZ p = tf.Inverse.OfPoint(startPoint);
//p = new XYZ(p.X, p.Y, h);
//startPoint = tf.OfPoint(p);
//XYZ p2 = tf.Inverse.OfPoint(endPoint);
//p2 = new XYZ(p2.X, p2.Y, h);
//endPoint = tf.OfPoint(p2);
}
if (startPoint == null || endPoint == null)
{
TaskDialog.Show("提示信息", "梁超出附板范围,需手动调整");
return Result.Succeeded;
}
else
{
Transaction transaction = new Transaction(doc, "梁随板");
transaction.Start();
beamLocation.Curve = Line.CreateBound(startPoint, endPoint);
transaction.Commit();
}
}
return Result.Succeeded;
}
class FloorISelection : ISelectionFilter
{
public bool AllowElement(Element elem)
{
Categories categories = elem.Document.Settings.Categories;
if ((elem is Floor && elem.Category.Id == categories.get_Item(BuiltInCategory.OST_Floors).Id) || (elem is Floor && elem.Category.Id == categories.get_Item(BuiltInCategory.OST_StructuralFoundation).Id))
{
return true;
}
else
{
return false;
}
;//返回true时内容可被鼠标选定
}
public bool AllowReference(Reference reference, XYZ position)
{
return true;//返回true时表示内容可以被边、点、面选中
}
}
class BeamISelection : ISelectionFilter
{
public bool AllowElement(Element elem)
{
Categories categories = elem.Document.Settings.Categories;
if (elem is FamilyInstance && elem.Category.Id == categories.get_Item(BuiltInCategory.OST_StructuralFraming).Id)
{
return true;
}
else
{
return false;
}
;//返回true时内容可被鼠标选定
}
public bool AllowReference(Reference reference, XYZ position)
{
return true;//返回true时表示内容可以被边、点、面选中
}
}
#region IntersectPointOfFaceAndCurve:求面与线的交点
public XYZ IntersectPointOfFaceAndCurve(Face face, Curve curve)
{
//交点数组
IntersectionResultArray result = null;
//枚举,用于判断相交类型
SetComparisonResult setResult = face.Intersect(curve, out result);
XYZ interResult = null;
//Disjoint为不相交
if (SetComparisonResult.Disjoint != setResult)
{
//isEmpty判断是否为空
if (!result.IsEmpty)
interResult = result.get_Item(0).XYZPoint;
}
return interResult;
}
#endregion
}
}