2018.7.17.南京。外面36°,宜烧烤,感谢麻老师,k神。喵的Leo周*(本人)好饿。早知道不学C#了。。。
环境:revit2018
首先先介绍几个比较重要的先行条件。如果知道最好,不知道我接下来也会给你讲解。
柱的中线点:通过 Location 类,你可以得到指定柱子的中心点。这个对你以后revit二次开发生涯很有帮助。中线点,就是在柱子的俯视图的2条对角线的交点,且高度为柱子的地面高度。
下面是去中线点的代码示意:
LocationPoint columnPoint = column.Location as LocationPoint;
XYZ point =columnPoint.Point;
柱子有中心点,梁则有中心线。
图1-1
如图1-1所示,箭头所指即为中心线的交点。根据上面柱子的中心点,你是否发现。当梁不发生偏移时,梁的中心线的2个端点与柱子的中线点在二维平面重合。
取得中心线的代码示意:
LocationCurve BeamLoactionCurve = beam.Location as LocationCurve;
Curve BeamLoaction = BeamLoactionCurve.Curve;
在revit2018中梁作为FamilyInstance拥有了一新的方法叫Split,它可以根据百分比分段梁,并提供新生的梁的ID(梁被分成2断,一段继承原来梁的id,一段生成新的ID)。本人思路:根据柱子中心点,可以得到各个柱子点到指点柱子点的距离(指定点一般是梁的2端的任意一端),也就得知各个段所占百分比。然后梁根据这个在进行劈~~~~完美!perfect!
namespace SplitBeamEI
{
[Transaction(TransactionMode.Manual)]
public class SplitBeamWithLean : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIDocument uidoc = commandData.Application.ActiveUIDocument;
Document doc = uidoc.Document;
try
{
BeamAndColumnSlectionFileter beamAndColumnSelectionFileter = new BeamAndColumnSlectionFileter();
IList<Reference> refers = uidoc.Selection.PickObjects(ObjectType.Element, beamAndColumnSelectionFileter);
List<Element> BeamList = new List<Element>();
List<Element> ColumnList = new List<Element>();
if (refers.Count > 0)
{
if (refers.Count < 4)
{
TaskDialog.Show("Error", "选择数量错误,梁+柱必大于等于4!");
return Result.Failed;
}
foreach (var refer in refers)
{
Element elem = doc.GetElement(refer.ElementId) as Element;
if (elem.Category.Name == "结构框架")
{
BeamList.Add(elem);
}
else if (elem.Category.Name == "结构柱")
{
ColumnList.Add(elem);
}
}
if (BeamList.Count != 1 || ColumnList.Count < 3)
{
TaskDialog.Show("Error", "选择数量错误,梁仅能一个且柱数量大于3!");
return Result.Failed;
}
}
Element beam = BeamList[0];
LocationCurve BeamLoactionCurve = beam.Location as LocationCurve;
Curve BeamLoaction = BeamLoactionCurve.Curve;
XYZ BeamPoint = BeamLoaction.GetEndPoint(0);//取梁中心线前点
List<XYZ> ColumnPointList = new List<XYZ>();
foreach (var column in ColumnList)
{
LocationPoint columnPoint = column.Location as LocationPoint;
ColumnPointList.Add(columnPoint.Point);
}
List<XYZ> newColumnList = BubbleSort(ColumnPointList, BeamPoint);//排序,按照到到梁前点的距离从小到大排列
List<double> distanceList = new List<double>(); //存放距离数组
foreach (var point in newColumnList)
{
XYZ zero = newColumnList[0];
double distance = Math.Sqrt(Math.Pow((point.X - zero.X), 2) + Math.Pow((point.Y - zero.Y), 2) + Math.Pow((point.Z - zero.Z), 2));
distanceList.Add(distance);
}
distanceList.RemoveAt(0);//移除第一个
distanceList.Reverse();//数列反转
FamilyInstance beamFamilyInstance = beam as FamilyInstance;
using (Transaction tran = new Transaction(doc))
{
tran.Start("beam start edit");
for (int i = 0; i < distanceList.Count - 1; i++)
{
double percentage = distanceList[i + 1] / distanceList[i];
beamFamilyInstance.Split(percentage);
}
tran.Commit();
}
}
catch (Exception ex)
{
message = ex.ToString();
return Result.Failed;
}
return Result.Succeeded;
}
/// <summary>
/// 仅供选择要分段的梁和与之相连接的柱
/// </summary>
public class BeamAndColumnSlectionFileter : ISelectionFilter
{
public bool AllowElement(Element elem)
{
if (elem.Category.Name == "结构框架" || elem.Category.Name == "结构柱")
{
return true;
}
return false;
}
public bool AllowReference(Reference reference, XYZ position)
{
return false;
}
}
/// <summary>
/// 冒泡排序,按距离从小到大
/// </summary>
/// <param name="column">柱子数组</param>
/// <param name="beam">唯一的梁</param>
/// <returns></returns>
public static List<XYZ> BubbleSort(List<XYZ> column, XYZ beam)
{
for (int i = 0; i < column.Count; i++)
{
for (int j = 0; j < column.Count - 1 - i; j++)
{
double diatance = Math.Sqrt(Math.Pow((beam.X - column[j].X), 2) + Math.Pow((beam.Y - column[j].Y), 2) + Math.Pow((beam.Z - column[j].Z), 2));
double diatance1 = Math.Sqrt(Math.Pow((beam.X - column[j + 1].X), 2) + Math.Pow((beam.Y - column[j + 1].Y), 2) + Math.Pow((beam.Z - column[j + 1].Z), 2));
if (diatance > diatance1)
{
XYZ temp = column[j + 1];
column[j + 1] = column[j];
column[j] = temp;
}
}
}
List<XYZ> newColumn = column;
return newColumn;
}
/// <summary>
/// 已知2点的一条直线,求第三点到的最短距离的点
/// </summary>
/// <param name="BeamList"></param>
/// <param name="column"></param>
/// <returns></returns>
private static XYZ GetPoint(List<XYZ> BeamList, XYZ column)
{
XYZ point;
double x1 = BeamList[0].X;
double y1 = BeamList[0].Y;
double x2 = column.X;
double y2 = column.Y;
double tana = (BeamList[0].Y - BeamList[1].Y) / (BeamList[0].X - BeamList[1].X);//梁的斜率
double x = (y2 + x2 / tana - y1 + tana * x1) / (tana + 1 / tana);
double y = tana * x + y1 - tana * x1;
point = new XYZ(x, y, BeamList[0].Z);
return point;
}
}
}