【Revit二次开发】几何
几何
在Autodesk. Revit, DB命名空间里包含了- -些几何图形相关的类型,它们在API中用
于几何图形的表示和处理。从基类继承的情况分,API提供了三大种几何类型来描述和存
储几何信息:
●几何基元类:包括所有从GeometryObject派生出来的子类。
●几何辅助类:包括一些从APIObject派生出来的几何相关的子类和一些值类型。
●几何集合类:包括一些实现了lEnumerable或者lEnumerator 接口的几何相关的
类型。
在Revit二次开发中,几何是非常重要的一部分,因为在Revit中,所有的构件都是由几何形状组成的。Revit中的几何可以分为以下几种类型:
点(Point):代表三维空间中的一个点,可以用X、Y、Z坐标表示。
线(Line):由两个点组成的直线段。
平面(PlanarFace):由三个或以上的点组成的平面。
多边形(Polygon):由三个或以上的点组成的封闭形状。
三角形(Triangle):由三个点组成的三角形。
矩形(Rectangle):由四个点组成的矩形。
圆形(Circle):由一个中心点和半径组成的圆形。
在Revit二次开发中,我们可以使用以下几种方式来获取构件的几何信息:
获取构件的几何信息对象(GeometryObject),可以通过GeometryInstance对象获取。
获取构件的几何信息(Geometry),可以通过Element对象的Geometry属性获取。
获取构件的几何图形(Solid),可以通过Element对象的GetSolidGeometry方法获取。
例如,以下代码可以获取某一构件的几何信息:
Element element = ... // 获取某一构件
GeometryElement geometry = element.Geometry; // 获取构件的几何信息
获取到几何信息后,我们可以使用以下方法来获取具体的几何形状:
获取点(Point):通过Point对象的Coordinates属性获取。
获取线(Line):通过Curve对象的GetEndPoint和GetStartPoint方法获取。
获取平面(PlanarFace):通过PlanarFace对象的Vertices属性获取。
获取多边形(Polygon):通过Polygon对象的Vertices属性获取。
获取三角形(Triangle):通过Triangle对象的Vertices属性获取。
获取矩形(Rectangle):通过Rectangle对象的Vertices属性获取。
获取圆形(Circle):通过Circle对象的Center属性和Radius属性获取。
例如,以下代码可以获取某一构件的所有点:
GeometryElement geometry = ... // 获取某一构件的几何信息
foreach (GeometryObject geoObj in geometry)
{
Point point = geoObj as Point;
if (point != null)
{
XYZ coordinates = point.Coordinates; // 获取点的坐标
// 处理点的坐标
}
}
需要注意的是,几何信息中的坐标是以Revit内部的坐标系表示的,需要进行转换才能与其他外部坐标系进行对比。
例子
Revit二次开发中常用的几何计算方法如下:
获取两点之间的距离:
可以通过XYZ对象的DistanceTo方法获取两个点之间的距离。
XYZ point1 = ... // 获取第一个点的坐标
XYZ point2 = ... // 获取第二个点的坐标
double distance = point1.DistanceTo(point2); // 获取两个点之间的距离
获取两线之间的夹角:
可以通过两条线段的方向向量计算出它们之间的夹角。
Line line1 = ... // 获取第一条线段
Line line2 = ... // 获取第二条线段
double angle = line1.Direction.AngleTo(line2.Direction); // 获取两条线段之间的夹角
获取平面内两线的交点:
可以通过Plane对象的Intersect方法获取平面内两条线段的交点。
Plane plane = ... // 获取平面
Line line1 = ... // 获取第一条线段
Line line2 = ... // 获取第二条线段
XYZ intersection = plane.Intersect(line1, line2); // 获取两条线段在平面上的交点
获取平面内点到直线的距离:
可以通过Plane对象的Project方法将点投影到直线上,然后计算投影点与原点之间的距离。
Plane plane = ... // 获取平面
Line line = ... // 获取直线
XYZ point = ... // 获取点
XYZ projection = plane.Project(point, line.Direction); // 将点投影到直线上
double distance = projection.DistanceTo(point); // 计算投影点与原点之间的距离
获取平面内点到线段的距离:
可以先将点投影到直线上,然后判断投影点是否在线段上,最后计算投影点与原点之间的距离。
Plane plane = ... // 获取平面
Line line = ... // 获取直线
XYZ point = ... // 获取点
XYZ projection = plane.Project(point, line.Direction); // 将点投影到直线上
if (projection.IsOnLine(line)) // 判断投影点是否在线段上
{
double distance = projection.DistanceTo(point); // 计算投影点与原点之间的距离
}
计算平面内点是否在多边形内:
可以通过Polygon对象的Contains方法判断一个点是否在多边形内。
Plane plane = ... // 获取平面
Polygon polygon = ... // 获取多边形
XYZ point = ... // 获取点
bool isInPolygon = polygon.Contains(point); // 判断点是否在多边形内
public Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
try
{
UIDocument uidoc = commandData.Application.ActiveUIDocument;
Document doc = uidoc.Document;
Selection selection = uidoc.Selection;
string msg = string.Empty;
//选择墙
ISelectionFilter wallFilter = new WallSelectionFilter(doc);
Reference eleRef = selection.PickObject(ObjectType.Element, wallFilter);
if (null == eleRef || ElementId.InvalidElementId == eleRef.ElementId)
{
return Result.Cancelled;
}
//获取墙的信息
Element element = doc.GetElement(eleRef);
Wall wall = element as Wall;
if (wall == null)
return Result.Failed;
//structuralUsage枚举
Enum structuralUsage = wall.StructuralUsage;
List<double> areas = GetArea(wall);
double volumn = GetVolumn(wall);
int i = 0;
foreach (double area in areas)
{
i++;
msg += " 面" + i + " :" + area + "平方米 ";
}
msg = "是否为结构:" + structuralUsage.ToString() + " ElementId:" + element.Id + " 体积:" + volumn + "立方米" + msg;
TaskDialog.Show(this.GetType().Name, msg);
return Result.Succeeded;
}
catch (Exception ex)
{
message = ex.Message;
return Result.Failed;
}
}
/// <summary>
/// 获取几何元素的面积
/// </summary>
/// <param name="element"></param>
/// <returns>平方米</returns>
public static List<double> GetArea(Element element)
{
List<double> area = new List<double>();
GeometryElement geometryElement = element.get_Geometry(new Options());
foreach (GeometryObject geometryObject in geometryElement)
{
if (geometryObject is Solid)
{
Solid solid = geometryObject as Solid;
foreach (Face face in solid.Faces)
{
double v = UnitUtils.ConvertFromInternalUnits(face.Area, UnitTypeId.SquareMeters);
area.Add(v);
}
}
}
return area;
}
/// <summary>
/// 获取几何元素的体积
/// </summary>
/// <param name="element"></param>
/// <returns>立方米</returns>
public static double GetVolumn(Element element)
{
double volumn = 0;
GeometryElement geometryElement = element.get_Geometry(new Options());
foreach (GeometryObject geometryObject in geometryElement)
{
if (geometryObject is Solid)
{
Solid solid = geometryObject as Solid;
volumn += solid.Volume;
}
}
volumn = UnitUtils.ConvertFromInternalUnits(volumn, UnitTypeId.CubicMeters);
return volumn;
}
}
public class WallSelectionFilter : ISelectionFilter
{
Document m_doc = null;
/// <summary>
/// Constructor the filter and initialize the document.
/// </summary>
/// <param name="doc">The document.</param>
public WallSelectionFilter(Document doc)
{
m_doc = doc;
}
/// <summary>
/// Allow all the element to be selected
/// </summary>
/// <param name="element">A candidate element in selection operation.</param>
/// <returns>Return true to allow the user to select this candidate element.</returns>
public bool AllowElement(Element elem)
{
return elem is Wall;
}
/// <summary>
/// Allow planar face reference to be selected
/// </summary>
/// <param name="refer">A candidate reference in selection operation.</param>
/// <param name="point">The 3D position of the mouse on the candidate reference.</param>
/// <returns>Return true for planar face reference. Return false for non planar face reference.</returns>
public bool AllowReference(Reference reference, XYZ position)
{
return false; //设置为不允许
}
本文来自博客园,作者:Patrick-Rex,转载请注明原文链接:https://www.cnblogs.com/patrickrex/p/18028749
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升