724 lines
28 KiB
C#
724 lines
28 KiB
C#
using Autodesk.Revit.DB;
|
||
using RookieStation.ProjectConfig;
|
||
using RookieStation.Extension;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using static System.Net.WebRequestMethods;
|
||
using Autodesk.Revit.UI;
|
||
|
||
namespace RookieStation.Utils
|
||
{
|
||
internal static class RsRevitUtils
|
||
{
|
||
/// <summary>
|
||
/// 英尺转米
|
||
/// </summary>
|
||
/// <param name="valueToConvert"></param>
|
||
/// <returns></returns>
|
||
public static double ConvertFeetToMetre(double valueToConvert)
|
||
{
|
||
return UnitUtils.ConvertFromInternalUnits(valueToConvert, DisplayUnitType.DUT_METERS);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 平方英尺转平方米
|
||
/// </summary>
|
||
/// <param name="valueToConvert"></param>
|
||
/// <returns></returns>
|
||
public static double ConvertSquareFeetToSquareMetre(double valueToConvert)
|
||
{
|
||
return UnitUtils.ConvertFromInternalUnits(valueToConvert, DisplayUnitType.DUT_SQUARE_METERS);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 英尺转换成毫米单位
|
||
/// </summary>
|
||
/// <param name="valueToConvert"></param>
|
||
/// <returns></returns>
|
||
public static double ConvertFeetToMillimetre(double valueToConvert)
|
||
{
|
||
return UnitUtils.ConvertFromInternalUnits(valueToConvert, DisplayUnitType.DUT_MILLIMETERS);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 复制图例
|
||
/// </summary>
|
||
/// <param name="doc"></param>
|
||
/// <param name="viewScale"></param>
|
||
/// <returns></returns>
|
||
public static View CreateNewLegend(Document doc, string legendName, int viewScale)
|
||
{
|
||
IEnumerable<View> legends = doc.QueryByClassAndBuiltInCategory<View>(BuiltInCategory.OST_Views).Cast<Autodesk.Revit.DB.View>().Where(v => v.ViewType == ViewType.Legend);
|
||
Autodesk.Revit.DB.View newLegend = null;
|
||
|
||
if (legends.Count() == 0)
|
||
{
|
||
TaskDialog.Show("温馨提示", "请先新建图例");
|
||
return newLegend;
|
||
}
|
||
|
||
var legendToCopy = legends.FirstOrDefault();
|
||
|
||
var newLegendId = legendToCopy.Duplicate(ViewDuplicateOption.Duplicate);
|
||
newLegend = doc.GetElement(newLegendId) as Autodesk.Revit.DB.View;
|
||
for (int i = 0; i < 100; i++)
|
||
{
|
||
try
|
||
{
|
||
newLegend.Name = $"{legendName} {i}";
|
||
break;
|
||
}
|
||
catch (Exception)
|
||
{
|
||
continue;
|
||
}
|
||
}
|
||
newLegend.Scale = viewScale;
|
||
return newLegend;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置图例位置
|
||
/// </summary>
|
||
/// <param name="doc"></param>
|
||
/// <param name="newLegend"></param>
|
||
public static void SetLegendLocation(Document doc, View newLegend, XYZ location)
|
||
{
|
||
var viewport = Viewport.Create(doc, doc.ActiveView.Id, newLegend.Id, XYZ.Zero);
|
||
double l = viewport.GetBoxOutline().MaximumPoint.X - viewport.GetBoxOutline().MinimumPoint.X;
|
||
double w = viewport.GetBoxOutline().MaximumPoint.Y - viewport.GetBoxOutline().MinimumPoint.Y;
|
||
XYZ c = new XYZ(l / 2, w / 2, 0) + location;//边距均为7mm
|
||
|
||
viewport.SetBoxCenter(c);
|
||
|
||
var ele = new FilteredElementCollector(doc).OfClass(typeof(ElementType)).WhereElementIsElementType().FirstOrDefault(x => x.Name.Contains("无"));
|
||
viewport.ChangeTypeId(ele.Id);//选择视口-无标题
|
||
}
|
||
|
||
/// <summary>
|
||
/// 删除定位点重合的族实例
|
||
/// </summary>
|
||
/// <param name="doc"></param>
|
||
/// <param name="cardInstances"></param>
|
||
public static void DeleteOverlapFamilyInstance(Autodesk.Revit.DB.Document doc, List<FamilyInstance> cardInstances)
|
||
{
|
||
List<ElementId> idsToDelete = new List<ElementId>();
|
||
|
||
foreach (var ins in cardInstances)
|
||
{
|
||
var lp = RsRevitUtils.GetLocationPointByElement(ins);
|
||
foreach (var card in cardInstances)
|
||
{
|
||
var lpt = RsRevitUtils.GetLocationPointByElement(card);
|
||
if (!card.Id.Equals(ins.Id) && lp.IsAlmostEqualTo(lpt))
|
||
{
|
||
idsToDelete.Add(ins.Id);
|
||
idsToDelete.Add(card.Id);
|
||
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
doc.Delete(idsToDelete);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建表格
|
||
/// </summary>
|
||
/// <param name="doc"></param>
|
||
/// <param name="rowcount"></param>
|
||
/// <param name="columncount"></param>
|
||
/// <param name="gridwidth"></param>
|
||
/// <param name="gridheight"></param>
|
||
public static void CreateTable(Document doc, View legend, int rowcount, int columncount, double gridwidth, double gridheight)
|
||
{
|
||
CurveArray curveArray = new CurveArray();
|
||
|
||
for (int i = 0; i <= rowcount; i++)//水平网格
|
||
{
|
||
Curve l = Line.CreateBound(XYZ.Zero, XYZ.BasisX * gridwidth * columncount).CreateOffset(gridheight * i, -XYZ.BasisZ);
|
||
curveArray.Append(l);
|
||
}
|
||
Curve line = Line.CreateBound(XYZ.Zero, XYZ.BasisY * rowcount * gridheight);
|
||
curveArray.Append(line);
|
||
for (int i = 0; i <= columncount; i++)//垂直网格
|
||
{
|
||
line = line.CreateOffset(gridwidth, XYZ.BasisZ);
|
||
curveArray.Append(line);
|
||
}
|
||
doc.Create.NewDetailCurveArray(legend, curveArray);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建表格
|
||
/// </summary>
|
||
/// <param name="doc"></param>
|
||
/// <param name="legend">图例视图</param>
|
||
/// <param name="rowcount">行数</param>
|
||
/// <param name="columncount">列数</param>
|
||
/// <param name="gridheight">单元格高度</param>
|
||
/// <param name="gridwidths">各单元格对应的宽度</param>
|
||
public static void CreateTable(Document doc, View legend, int rowcount, int columncount, double gridheight, params double[] gridwidths)
|
||
{
|
||
if (columncount != gridwidths.Count())
|
||
{
|
||
return;
|
||
}
|
||
CurveArray curveArray = new CurveArray();
|
||
var width = 0.0;
|
||
foreach (var w in gridwidths)
|
||
{
|
||
width += w;
|
||
}
|
||
for (int i = 0; i <= rowcount; i++)//水平网格
|
||
{
|
||
Curve c = Line.CreateBound(XYZ.Zero, XYZ.BasisX * width).CreateOffset(gridheight * i, -XYZ.BasisZ);
|
||
curveArray.Append(c);
|
||
}
|
||
Curve line = Line.CreateBound(XYZ.Zero, XYZ.BasisY * rowcount * gridheight);
|
||
curveArray.Append(line);
|
||
for (int i = 0; i < columncount; i++)//垂直网格
|
||
{
|
||
line = line.CreateOffset(gridwidths[i], XYZ.BasisZ);
|
||
curveArray.Append(line);
|
||
}
|
||
doc.Create.NewDetailCurveArray(legend, curveArray);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 通过名称获取默认的墙类型完整厚度
|
||
/// </summary>
|
||
/// <param name="wallTypeName">墙类型包含的字符串</param>
|
||
/// <returns></returns>
|
||
public static WallType GetWallTypeByName(Document doc, string wallTypeName)
|
||
{
|
||
var walltypelist = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls).OfClass(typeof(WallType)).Cast<WallType>();
|
||
return walltypelist.FirstOrDefault(t => t.Name.Contains(wallTypeName));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取元素定位点
|
||
/// </summary>
|
||
/// <param name="instance">以点定位的实例</param>
|
||
/// <returns></returns>
|
||
public static XYZ GetLocationPointByElement(Element instance)
|
||
{
|
||
return instance.Location is LocationPoint lp ? lp.Point : null;
|
||
}
|
||
|
||
public static Curve GetLocationCurveByElement(Element instance)
|
||
{
|
||
return instance.Location is LocationCurve lc ? lc.Curve : null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 调整族实例位置
|
||
/// </summary>
|
||
/// <param name="doc"></param>
|
||
/// <param name="instances">需要偏移的族实例</param>
|
||
/// <param name="referLine">用于调整偏移和角度的参考线</param>
|
||
/// <param name="offest">偏移量</param>
|
||
public static void AdjustInstances(Document doc, List<FamilyInstance> instances, Line referLine, double offest)
|
||
{
|
||
XYZ zdir = XYZ.BasisZ;
|
||
|
||
//通过第三点垂直于直线的单位向量(无论左右侧)*偏移距离(一半的闸机长度)
|
||
XYZ offestVector = zdir.CrossProduct(referLine.Direction).Normalize();
|
||
|
||
//旋转角度
|
||
double angle = XYZ.BasisY.AngleTo(offestVector);
|
||
//判断相对于Y轴是正向角度(逆时针)还是逆向角度(顺时针)
|
||
XYZ z = offestVector.CrossProduct(XYZ.BasisY).Normalize();
|
||
if (z.IsAlmostEqualTo(XYZ.BasisZ))
|
||
{
|
||
//逆向旋转,角度取负值
|
||
angle = -angle;
|
||
//var ml = doc.Create.NewModelCurve(Line.CreateBound(XYZ.Zero, re), SketchPlane.Create(doc, Plane.CreateByNormalAndOrigin(XYZ.BasisZ, new XYZ())));
|
||
}
|
||
offestVector *= offest;
|
||
foreach (FamilyInstance instance in instances)
|
||
{
|
||
XYZ p = GetLocationPointByElement(instance);
|
||
Line l = Line.CreateUnbound(p, XYZ.BasisZ);
|
||
//旋转,移动
|
||
ElementTransformUtils.RotateElement(doc, instance.Id, l, angle);
|
||
ElementTransformUtils.MoveElement(doc, instance.Id, offestVector);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 朝着向量方向左侧偏移并调整角度对齐直线
|
||
/// </summary>
|
||
/// <param name="doc"></param>
|
||
/// <param name="fi"></param>
|
||
/// <param name="referLine"></param>
|
||
/// <param name="offest"></param>
|
||
public static void AdjustInstance(Document doc, FamilyInstance fi, Line referLine, double offest)
|
||
{
|
||
//朝着向量方向左侧偏移
|
||
XYZ zdir = XYZ.BasisZ;
|
||
|
||
//通过第三点垂直于直线的单位向量(无论左右侧)*偏移距离(一半的闸机长度)
|
||
XYZ offestVector = zdir.CrossProduct(referLine.Direction).Normalize() * offest;
|
||
//旋转角度
|
||
double angle = XYZ.BasisY.AngleTo(offestVector);
|
||
//判断相对于Y轴是正向角度(逆时针)还是逆向角度(顺时针)
|
||
XYZ z = offestVector.CrossProduct(XYZ.BasisY).Normalize();
|
||
if (z.IsAlmostEqualTo(XYZ.BasisZ))
|
||
{
|
||
//逆向旋转,角度取负值
|
||
angle = -angle;
|
||
}
|
||
|
||
XYZ p = GetLocationPointByElement(fi);
|
||
Line l = Line.CreateUnbound(p, XYZ.BasisZ);
|
||
//旋转,移动
|
||
ElementTransformUtils.RotateElement(doc, fi.Id, l, angle + Math.PI);
|
||
ElementTransformUtils.MoveElement(doc, fi.Id, offestVector);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加项目样板
|
||
/// </summary>
|
||
public static void AddProjectTemplate()
|
||
{
|
||
//Autodesk.Revit.ApplicationServices.Application.CurrentUsersDataFolderPath
|
||
string oriDateFilePath = @"" + Environment.GetEnvironmentVariable("appdata") + @"\Autodesk\Revit\Autodesk Revit 2020\Revit.ini";
|
||
string tmpDateFilePath = UserConstant.FamilyLibraryDirectory + "\\Rs.ini";
|
||
|
||
if (System.IO.File.Exists(oriDateFilePath))
|
||
{
|
||
using (StreamReader sr = new StreamReader(oriDateFilePath, Encoding.Unicode))
|
||
{
|
||
StreamWriter sw = new StreamWriter(tmpDateFilePath, false, Encoding.Unicode);
|
||
string inputLine = "";
|
||
|
||
while ((inputLine = sr.ReadLine()) != null)
|
||
{
|
||
if (inputLine.StartsWith("DefaultTemplate="))
|
||
{
|
||
inputLine.Insert(16, UserConstant.FamilyLibraryDirectory + "\\菜鸟驿站.rte,");
|
||
//if (inputLine.Contains("Example_SCHEMA.rte"))
|
||
//{
|
||
//}
|
||
//else
|
||
//{
|
||
// inputLine = inputLine + @", Example_SCHEMA=C:\temp\Example_SCHEMA.rte";
|
||
//}
|
||
}
|
||
sw.WriteLine(inputLine);
|
||
}
|
||
sw.Close();
|
||
}
|
||
|
||
System.IO.File.Replace(tmpDateFilePath, oriDateFilePath, null);
|
||
}
|
||
}
|
||
|
||
public static FamilySymbol GetGuideSymbol(Document doc)
|
||
{
|
||
FamilySymbol lineSymbol = null;
|
||
doc.Invoke(ts =>
|
||
{
|
||
Family lineFamily = GetLoadedFamily(doc, UserConstant.FamilyLibraryDirectory + "其他\\定位线.rfa");
|
||
if (lineFamily != null)
|
||
{
|
||
lineSymbol = doc.GetElement(lineFamily.GetFamilySymbolIds().FirstOrDefault()) as FamilySymbol;
|
||
}
|
||
}, "载入定位线并布置");
|
||
|
||
return lineSymbol;
|
||
}
|
||
|
||
public static Line GetGuideGeometryAndDeleteGuide(Document doc, List<ElementId> eleIdsAdded)
|
||
{
|
||
ElementId referLineId = eleIdsAdded.FirstOrDefault();
|
||
FamilyInstance guideLine = doc.GetElement(referLineId) as FamilyInstance;
|
||
LocationCurve lc = guideLine.Location as LocationCurve;
|
||
Line line = lc.Curve as Line;
|
||
doc.Invoke(ts =>
|
||
{
|
||
doc.Delete(referLineId);
|
||
}, "删除参考线");
|
||
|
||
return line;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 元素的所有面
|
||
/// </summary>
|
||
/// <param name="item">元素</param>
|
||
/// <param name="options">打开方式</param>
|
||
/// <returns>所有的面</returns>
|
||
public static List<Face> GetFaceByElement(Element item, Options options)
|
||
{
|
||
List<Face> faces = new List<Face>();
|
||
//根据打开的方式得到几何信息
|
||
GeometryElement geometry = item.get_Geometry(options);
|
||
foreach (GeometryObject geomObj in geometry)
|
||
{
|
||
//geomObj为几何实例
|
||
GeometryInstance geomInstance = geomObj as GeometryInstance;
|
||
if (geomInstance != null)
|
||
{
|
||
//从实例中找到实例的几何体
|
||
foreach (GeometryObject instObj in geomInstance.GetInstanceGeometry())
|
||
{
|
||
//三维的实体
|
||
Solid instSolid = instObj as Solid;
|
||
if (instSolid == null || instSolid.Faces.Size == 0 || instSolid.Edges.Size == 0)
|
||
{
|
||
continue;
|
||
}
|
||
foreach (Face face in instSolid.Faces)
|
||
{
|
||
faces.Add(face);
|
||
}
|
||
}
|
||
}
|
||
//geomObj为几何体
|
||
Solid solid = geomObj as Solid;
|
||
if (solid != null)
|
||
{
|
||
if (solid.Faces.Size == 0 || solid.Edges.Size == 0)
|
||
{
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
foreach (Face face in solid.Faces)
|
||
{
|
||
faces.Add(face);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return faces;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取族实例所有面(实际为族类型的所有面)
|
||
/// </summary>
|
||
/// <param name="item"></param>
|
||
/// <returns></returns>
|
||
public static List<Face> GetFacesByFamilyInstance(FamilyInstance instance, Options options)
|
||
{
|
||
List<Face> faces = new List<Face>();
|
||
//根据打开的方式得到几何信息
|
||
GeometryElement geometry = instance.get_Geometry(options);
|
||
foreach (GeometryObject geomObj in geometry)
|
||
{
|
||
//geomObj为几何实例
|
||
GeometryInstance geomInstance = geomObj as GeometryInstance;
|
||
if (geomInstance == null)
|
||
{
|
||
continue;
|
||
}
|
||
//族实例未修改过(连接,剪切,复制,扩展)
|
||
bool usesSymbolGeometry = (instance is FamilyInstance) && !(instance as FamilyInstance).HasModifiedGeometry();
|
||
var bo = instance.HasModifiedGeometry();
|
||
GeometryElement instanceGeometry = usesSymbolGeometry ? geomInstance.GetSymbolGeometry() : geomInstance.GetInstanceGeometry();
|
||
|
||
if (instanceGeometry != null)
|
||
{
|
||
//instanceGeometry.GetTransformed();
|
||
//从实例中找到实例的几何体
|
||
foreach (GeometryObject instObj in instanceGeometry)
|
||
{
|
||
//三维的实体
|
||
Solid instSolid = instObj as Solid;
|
||
if (instSolid == null || instSolid.Faces.Size == 0 || instSolid.Edges.Size == 0)
|
||
{
|
||
continue;
|
||
}
|
||
foreach (Face face in instSolid.Faces)
|
||
{
|
||
faces.Add(face);
|
||
}
|
||
}
|
||
}
|
||
//geomObj为几何体
|
||
Solid solid = geomObj as Solid;
|
||
if (solid != null)
|
||
{
|
||
if (solid.Faces.Size == 0 || solid.Edges.Size == 0)
|
||
{
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
foreach (Face face in solid.Faces)
|
||
{
|
||
faces.Add(face);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return faces;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取族实例所有面(无法用于尺寸标注)
|
||
/// </summary>
|
||
/// <param name="item"></param>
|
||
/// <returns></returns>
|
||
public static List<Face> GetFamilyInstanceFaces(FamilyInstance instance, Options options)
|
||
{
|
||
List<Face> faces = new List<Face>();
|
||
//根据打开的方式得到几何信息
|
||
GeometryElement geometry = instance.get_Geometry(options);
|
||
|
||
foreach (GeometryObject geomObj in geometry)
|
||
{
|
||
//geomObj为几何实例
|
||
GeometryInstance geomInstance = geomObj as GeometryInstance;
|
||
var ins = geomInstance.GetInstanceGeometry();
|
||
if (geomInstance != null)
|
||
{
|
||
//instanceGeometry.GetTransformed();
|
||
//从实例中找到实例的几何体
|
||
foreach (GeometryObject instObj in geomInstance.GetInstanceGeometry())
|
||
{
|
||
//三维的实体
|
||
Solid instSolid = instObj as Solid;
|
||
if (instSolid == null || instSolid.Faces.Size == 0 || instSolid.Edges.Size == 0)
|
||
{
|
||
continue;
|
||
}
|
||
foreach (Face face in instSolid.Faces)
|
||
{
|
||
faces.Add(face);
|
||
}
|
||
}
|
||
}
|
||
//geomObj为几何体
|
||
Solid solid = geomObj as Solid;
|
||
if (solid != null)
|
||
{
|
||
if (solid.Faces.Size == 0 || solid.Edges.Size == 0)
|
||
{
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
foreach (Face face in solid.Faces)
|
||
{
|
||
faces.Add(face);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return faces;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 找到嵌套族的默认面参照(仅针对只有一种嵌套族)
|
||
/// </summary>
|
||
/// <param name="doc"></param>
|
||
/// <param name="familyInstances"></param>
|
||
/// <returns></returns>
|
||
public static List<Face> GetFaceReferences(Document doc, FamilyInstance familyInstance)
|
||
{
|
||
//List<Reference> references = new List<Reference>();
|
||
var instance = familyInstance.GetSubComponentIds()
|
||
.Select(a => doc.GetElement(a))
|
||
.ToList();
|
||
var ops = new Options();
|
||
ops.ComputeReferences = true;//计算参照,为true时才能进行得到参照
|
||
List<Face> faces = GetFaceByElement(instance.FirstOrDefault(), ops);
|
||
//List<Element> listFamilyInstances = new FilteredElementCollector(doc, doc.ActiveView.Id)
|
||
// .OfClass(typeof(FamilyInstance))
|
||
// .Cast<FamilyInstance>()
|
||
// .Where(a => a.SuperComponent == null)
|
||
// .SelectMany(a => a.GetSubComponentIds())
|
||
// .Select(a => doc.GetElement(a))
|
||
// .ToList();
|
||
//foreach (var face in faces)
|
||
//{
|
||
// //face.GetSurface().
|
||
// references.Add(face.Reference);
|
||
//}
|
||
return faces;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取已载入同名族,若无,则载入
|
||
/// </summary>
|
||
/// <param name="doc"></param>
|
||
/// <param name="familyName"></param>
|
||
/// <returns></returns>
|
||
internal static Family GetLoadedFamily(Document doc, string familyName)
|
||
{
|
||
Family family;
|
||
FileInfo info = new FileInfo(familyName);
|
||
|
||
family = new FilteredElementCollector(doc)
|
||
.OfClass(typeof(Family))
|
||
.Cast<Family>()
|
||
.Where(f => f.Name == Path.GetFileNameWithoutExtension(familyName))
|
||
.FirstOrDefault();
|
||
if (family == null && info.Exists)
|
||
{
|
||
doc.LoadFamily(familyName, new RsFamilyLoadOption(), out family);
|
||
}
|
||
|
||
return family;
|
||
}
|
||
|
||
internal static FamilySymbol GetAndActiveDefaultFamilySymbol(Document doc, string file)
|
||
{
|
||
Family family = RsRevitUtils.GetLoadedFamily(doc, file);
|
||
FamilySymbol symbol = null;
|
||
if (family != null)
|
||
{
|
||
ElementId symbolId = family.GetFamilySymbolIds().FirstOrDefault();
|
||
symbol = doc.GetElement(symbolId) as FamilySymbol;
|
||
if (!symbol.IsActive)
|
||
{
|
||
symbol.Activate();
|
||
}
|
||
}
|
||
return symbol;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取垂直于基准线的最长边
|
||
/// </summary>
|
||
/// <param name="segments"></param>
|
||
/// <param name="baseLine"></param>
|
||
/// <returns></returns>
|
||
public static Line GetLongestSegmentLine(IList<BoundarySegment> segments, Line baseLine)
|
||
{
|
||
Line line = null;
|
||
//var m = doc.GetElement(refer.ElementId);
|
||
foreach (var seg in segments)
|
||
{
|
||
Line tempLine = seg.GetCurve() as Line;
|
||
//判断是否垂直
|
||
double dotp = Math.Abs(tempLine.Direction.DotProduct(baseLine.Direction));
|
||
if (dotp < 0.0001)
|
||
{
|
||
if (line == null || line.Length < tempLine.Length)
|
||
{
|
||
line = tempLine;
|
||
}
|
||
}
|
||
}
|
||
return line;
|
||
}
|
||
|
||
public static Face GetPlaceFaceOfWall(Wall wall, XYZ normal)
|
||
{
|
||
Face face = null;
|
||
Options geomOptions = new Options();
|
||
geomOptions.ComputeReferences = true;
|
||
GeometryElement wallGeom = wall.get_Geometry(geomOptions);
|
||
|
||
foreach (GeometryObject geomObj in wallGeom)
|
||
{
|
||
Solid geomSolid = geomObj as Solid;
|
||
if (null != geomSolid)
|
||
{
|
||
foreach (Face geomFace in geomSolid.Faces)
|
||
{
|
||
if (geomFace.ComputeNormal(geomFace.Reference.UVPoint).IsAlmostEqualTo(normal))
|
||
{
|
||
face = geomFace;
|
||
}
|
||
|
||
break;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
return face;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取元素侧面
|
||
/// </summary>
|
||
/// <param name="elem"></param>
|
||
/// <returns></returns>
|
||
public static List<Face> GetSideFacesByElement(Element elem)
|
||
{
|
||
Options opt = new Options();
|
||
opt.ComputeReferences = true;
|
||
opt.DetailLevel = ViewDetailLevel.Fine;
|
||
GeometryElement ge = elem.get_Geometry(opt);
|
||
List<Face> lstpf = new List<Face>();
|
||
foreach (GeometryObject obj in ge)
|
||
{
|
||
Solid solid = obj as Solid;
|
||
if (solid != null)
|
||
{
|
||
foreach (Face face in solid.Faces)
|
||
{
|
||
PlanarFace pf = face as PlanarFace;
|
||
if (pf != null)
|
||
{
|
||
//点乘,即面的法向与Z轴始终垂直
|
||
var dotp = pf.FaceNormal.DotProduct(XYZ.BasisZ);
|
||
if (dotp < 1.0e-09 && dotp > -1.0e-09)//近似为0
|
||
{
|
||
lstpf.Add(pf);
|
||
}
|
||
//if (pf.FaceNormal.CrossProduct(wall.Orientation).IsZeroLength())
|
||
//{
|
||
// lstpf.Add(pf);
|
||
//}
|
||
}
|
||
var cy = face as CylindricalFace;
|
||
if (cy != null)
|
||
{
|
||
lstpf.Add(cy);
|
||
}
|
||
}
|
||
return lstpf;
|
||
}
|
||
}
|
||
return lstpf;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取元素默认底面(单个)
|
||
/// </summary>
|
||
/// <param name="elem"></param>
|
||
/// <returns></returns>
|
||
public static PlanarFace GetBottomFaceByElement(Element elem)
|
||
{
|
||
Options opt = new Options();
|
||
opt.ComputeReferences = true;
|
||
opt.DetailLevel = ViewDetailLevel.Fine;
|
||
GeometryElement ge = elem.get_Geometry(opt);
|
||
PlanarFace pf = null;
|
||
foreach (GeometryObject obj in ge)
|
||
{
|
||
Solid solid = obj as Solid;
|
||
if (solid != null)
|
||
{
|
||
foreach (Face face in solid.Faces)
|
||
{
|
||
PlanarFace temppf = face as PlanarFace;
|
||
if (temppf != null)
|
||
{
|
||
if (temppf.FaceNormal.IsAlmostEqualTo(-XYZ.BasisZ))
|
||
{
|
||
pf = temppf;
|
||
break;
|
||
}
|
||
//if (pf.FaceNormal.CrossProduct(wall.Orientation).IsZeroLength())
|
||
//{
|
||
// lstpf.Add(pf);
|
||
//}
|
||
}
|
||
}
|
||
return pf;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
}
|
||
} |