当前位置: 首页 > news >正文

24. Revit API: 几何对象(五)- (Sur)Face

一、前言

虽然Face是GeometryObject的子类,Surface不是,但这两者之间还是挺有关联的,每个Face都有一个对应的Surface,类似于EdgeCurve的关系。

Surface是数学意义上的面,纯定义。

Face是几何形状(实体)上的面,是Surface上截取了一块区域,有边界。

所以,Revit种面、线、点之类的关系的计算,都是在Face上,而Surface主要是对“抽象”面的定义。


二、Face

Face及其子类都没有构造函数,只能通过Solid获取。类方法,就是常规的相交、投影、计算面上点的法向、切向等方法。

2.1. 方法

// UV
public BoundingBoxUV GetBoundingBox();  // 面UV包围盒
// 点坐标、法向、切向
public Transform ComputeDerivatives(UV point);  // 一阶导。可得点坐标、法向、切向
public XYZ ComputeNormal(UV point);	// 计算法向,上面方法的简化版
public XYZ Evaluate(UV params);  // 计算点坐标public FaceSecondDerivatives ComputeSecondDerivatives(UV point);  // 二阶导// 获取边、面
public IList<CurveLoop> GetEdgesAsCurveLoops(); 
public Surface GetSurface();// 点、面、线关系
public IntersectionResult Project(XYZ point); // 点在面上的投影public FaceIntersectionFaceResult Intersect(Face face);  // 面-面相交
public SetComparisonResult Intersect(Curve curve);  // 面-线相交public bool IsInside(UV point);  // 指定UV是否在面上// 三角细分
public Mesh Triangulate(double levelOfDetail)

UV咋解释呢,模型贴图知道吧,把图片映射到模型上。怎么让图片贴准呢,建模软件里有个叫“展UV”的功能。

讲不来讲不来,看【Wiki】。

下图是方正的、填满了UV的,还有那种没填满的,有的区域是无映射的。

下面模型/贴图来自【sketchfab.com】

2.2. 属性

属性如下:

  • OrientationMatchesSurfaceOrientation:表示面朝向与其Surface的是否为同向,用到Surface时需要依此判断。
  • (Has/Get)Region:这个“Region”没有接触过,具体是个什么东西还不知道。查了好一会儿,才在【这篇】中找到一点信息,但测试发现,这只是在平面图中创建填充(FilledRegion)的方法,与面没有关系😑。

三、Surface

Revit中,有这些面:

FaceSurface
平面PlanarFacePlane
圆柱面CylindricalFaceCylindricalSurface
圆锥面ConicalFaceConicalSurface
旋转面RevolvedFaceRevolvedSurface
直纹(曲)面RuledFaceRuledSurface
埃尔米特曲面HermiteFaceHermiteSurface
Nurbs简化为其它类型的面NurbsSurface(Data)

前面6种面都是从某个类派生的,最后的 NurbsSurface 则是例外,它只有NurbsSurfaceData这个数据类,且只在BRepBuilderSurfaceGeometry中使用,最后创建出的面,也会被简化,由其它类型表示。

Face没有构造函数,Surface的属性也会出现在其对应的Face中,就直接看Surface。

在Revit几何对象中,都有使用Frame,用以确定局部坐标系,在18. Revit API: 元素位置与变换这篇写过。

3.1. 平面(Plane)

平面有属性:面原点、面法向、X轴向、Y轴向。

构造方法:

  1. 由Frame创建
  2. 由面法向,和面上原点创建
  3. 由原点,和X、Y轴创建,法向为 Vector3.Corss(dir_x,dir_y)
  4. 由面上三点创建,面方向按点顺序和右手螺旋确定,原点为第一个点。

warning:三点创建时,X轴的方向是怎么确定的?

尝试了几种方式,算到的和读取的都不一样,不清楚Revit三点创建平面时,XY轴的确定方式。

3.2. 圆柱面(CylindricalSurface)

定义: S(u, v) = center + radius*cos(u)*xVec + radius*sin(u)*yVec + v*zVec

圆柱面比较简单,属性:圆半径、坐标系原点、中心轴、X轴向、Y轴向

后四个组合就算一个Frame。

构造方法:

  • 由 Frame + 半径 创建。

3.3. 圆锥面(ConicalSurface)

定义:S(u, v) = center + v*[sin(halfAngle)(cos(u)*xVec + sin(u)*yVec) + cos(halfAngle)*zVec]

圆锥面属性:半角(弧度制)、顶点、中心轴、X轴、Y轴

构造方法:

  • 由 Frame + 半角 创建

3.4. 旋转面(RevolvedSurface)

吐槽:就一个旋转方程,现在的我已经看不懂了,现在我只是个API调用仔。

旋转面的属性:原点、轴、X、Y,方法中获取旋转轮廓。

构造方法

  • 从Frame(或类似表示方位的东西)创建
  • 可以设置旋转的起始和终点角度

Info:①构造方法返回的是Surface类型,可能简化为其它类型的面;②可以设置起始角度,即不转满1圈。但属性中没有没有角度信息。

  1. 返回类型很好理解,比如:当轮廓为直线且与旋转轴平行时,就算创建一个圆柱面。
  2. 起始角度计算:
// 1. 从Surface本身无法获得,如下:Curve curve = Line.CreateBound(new XYZ(10, 0, 0), new XYZ(9, 0, 10));
Surface revolvedSurface = RevolvedSurface.Create(new Frame(), curve, 0, Math.PI / 2); // 1/4 PIArc arc = Arc.Create(XYZ.Zero, 10, 0, Math.PI * 2, XYZ.BasisX, XYZ.BasisY); // 2 PI
IList<XYZ> points = arc.Tessellate();string msg = string.Empty;
for (int i = 0; i < points.Count; i++)
{revolvedSurface.Project(points[i], out UV uv, out double dis);  // 期望有1/4的点投影距离为0,msg += $"{i}\t {dis.Round(5)}\t {uv.Round(4)}\r\n";
}
TaskDialog.Show("project", msg);// 实际所有的 dis 全部 0,表示投影计算时,是投影到“完整转一圈”的面上
// 2. 如果是从Face上获取的旋转面,可以计算出该面的旋转角度Reference faceRef = this.Selection.PickObject(ObjectType.Face);
GeometryObject geoObj = this.Document.GetElement(faceRef).GetGeometryObjectFromReference(faceRef);
RevolvedFace revolvedFace = geoObj as RevolvedFace;XYZ startDir = revolvedFace.get_Radius(0);  // 这个获取起点轴方向 (Xvec)
// XYZ endDir = revolvedFace.get_Radius(1);  // YvecUV startUV = new UV(startDir.X, startDir.Y);
//UV endUV = new UV(endDir.X, endDir.Y);double startAngle = UV.BasisU.AngleTo(startUV).RadToDeg();
//double endAngle = UV.BasisU.AngleTo(endUV).RadToDeg();BoundingBoxUV uvBounding = revolvedFace.GetBoundingBox();double rangeAngle = (uvBounding.Max.U - uvBounding.Min.U).RadToDeg();
double endAngle = startAngle + rangeAngle;TaskDialog.Show("Revolved", $"RevolvedFace info:\r\n" +$"min:{uvBounding.Min}\r\n" +$"max:{uvBounding.Max}\r\n" +$"Xvec:{revolvedFace.get_Radius(0)}\r\n" +$"Yvec:{revolvedFace.get_Radius(1)}\r\n" +$"startAngle:{startAngle}\r\n" +$"range:{rangeAngle}\r\n" +$"endAngle:{endAngle}");

RevolvedFace上的Radius属性,表示的不是直径信息,而是(当前的)X轴向量和Y轴向量。

3.5. 直纹面(RuledSurface)

直纹(曲)面【Wiki】,没啥特殊的属性,创建结果可能简化为其它类型的面。

它有2类形式:① 两条Curve,② 点+Curve。

2个轨道,一根棍子搭在轨道上向前滚(按长度比例),滚过的区域就是直纹面。

结合Revit里的定义:S(u,v) = C1(u) + v⋅(C2(u)−C1(u))

3.6. NurbsSurface(Data)

Tips:NurbSpline叫非均匀有理样条线,参照这个问题链接。

Revit中并不支持NurbsSurface(会被简化),而是提供了一个对应的数据类NurbsSurfaceData

NurbsSurfaceData

① 该类只在BRepBuilderSurfaceGeometry中使用;

② 在ExportUtils工具类中提供了一个由面获取近似NurbsSurface数据的方法,只支持HermiteFaceRuledFace

我对这东西一知半解,就不多写了。

使用示例,请查看SDK下的示例“SDKSample/BRepBuilderExample/CreateNURBS.cs”,或者看【GitHub】,生成的模型长下面的样子。


四、总结

这篇,补充了几何对象中 Face、Surface 相关的内容,由于Face没有构造方法,主要写的是Surface。


http://www.mrgr.cn/news/34531.html

相关文章:

  • QT中添加资源文件
  • 隐匿发案:David律所代理艺术家Ina Tomecek的两张青蛙版权画维权
  • 在 macOS 上安装 FFmpeg 的详细指南
  • 有关在.Net Core中以TEXT类型将Json格式字段存到数据库的学习
  • 通义千问模型升级:2.5正式上线的使用体验
  • 设计模式介绍
  • 动态时间【JavaScript】
  • 通过spring-boot创建web项目
  • PostgreSQL的学习心得和知识总结(一百五十一)|[performance] PostgreSQL列对齐
  • 杰发科技——Eclipse环境安装
  • 很有意思的css动态渐变
  • 基于SpringBoot+Vue+MySQL的电影院购票管理系统
  • JavaEE: 深入探索TCP网络编程的奇妙世界(六)
  • 怎么开通GitHub Copilot?不会开通GitHub Copilot?一文看懂
  • AUTOSAR_EXP_ARAComAPI的5章笔记(11)
  • 【洛谷】AT_abc371_e [ABC371E] I Hate Sigma Problems 的题解
  • 栈:只允许在一端进行插入或删除操作的线性表
  • MySQL外连接与子查询
  • C语言编译与链接
  • 字母与符号检测系统源码分享