在NX二次开发中,对象的预览是一种比较常规的需求,一般来说有这么几种常见的方式
1、直接使用API复制对象(Ufun.Trns.TransformObjects,Wrapper method for uf5947),然后按需求对复制出来的对象做位置变换操作,
这种方式呢可行,对于简单的零件完全可以这样, 对于复杂的零件,这时候会有一些性能问题
2、从对象上提取边曲线,若有一些特征边曲线来描述不是特别理想,这时可以按UV来提取一些关键的位置点,然后再来创建样条来模拟面的网格,
如一些曲面,对于一些特定的面如球面和柱面,可以通过查询面的尺寸,通过直线+圆弧的方式来做描述。然后再按需求做位置变换等操作实现预览,
一般来说这种方式要比方式一的性能要好上不好。

3、在方式2的基础上,我们对实体的边信息提取成NX中对应的曲线信息,比如直边,提取两个端点,圆弧提取
圆心,直径,起始终止角度,样条提取控制点等等,然后按照对应的类型定义好数据结构,然后使用NX的UDO
来绘制还原这些信息,性能是通过绘制曲线再更新3到10倍,越是复杂的零件这两者的差距越明显
4、NX中对于大图档的轻量化加载和显示是通过缓存的小平面的方式来实现的, 那这里又给了我们一个思路,
我们可以获取实体的小平面数据,然后再分离(UF_FACET_disassoc_from_solid)出来做预览,然后直接使用操作
对象的API来复制和移动,按需求完成位置变换的预览,实际上的体感也是非常流畅的,比直接实体的预览要好上不少,
唯一的开销就是在对象小平面化(UF_FACET_facet_solid)有一定耗时,取决于零件复杂度。

5、那于在方法4的基础上我们可以也可以结合UDO来做对象的预览,UF中有一个API(UF_DISP_display_facets)

我们可以把提取出来的小平面数据,按它的参数做传递,然后通过UDO的方式来做预览,这时如果要做变换,直接对小平面的点和矢量
做变换,然后调用UDO的显示更新即可,性能也非常棒接近曲线的方式。


需要注意的是这个API在NET的开发包中是不存在的,需要自己重新封装一下,这种工作交给AI现在能完成的非常好。
以下是Deepseek做的pinvoke的封装:
public static void DisplayFacets(List tripInfos, IntPtr handle)
{
if (tripInfos == null || tripInfos.Count == 0) return;
int vertexCount = tripInfos[0].Points.Length;
int facetCount = tripInfos.Count;
int totalVertices = vertexCount * facetCount;
int doubleCountPerFacet = vertexCount * 3;
int totalDoubles = totalVertices * 3;
IntPtr allVertsPtr = Marshal.AllocHGlobal(totalDoubles * sizeof(double));
IntPtr allNormalsPtr = Marshal.AllocHGlobal(totalDoubles * sizeof(double));
IntPtr facetsArrayPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(UF_DISP_facet_t)) * facetCount);
try
{
unsafe
{
double* pVerts = (double*)allVertsPtr.ToPointer();
double* pNormals = (double*)allNormalsPtr.ToPointer();
for (int i = 0; i < facetCount; i++)
{
var trip = tripInfos[i];
for (int v = 0; v < vertexCount; v++)
{
*pVerts++ = trip.Points[v].X;
*pVerts++ = trip.Points[v].Y;
*pVerts++ = trip.Points[v].Z;
*pNormals++ = trip.Normals[v].X;
*pNormals++ = trip.Normals[v].Y;
*pNormals++ = trip.Normals[v].Z;
}
}
}
// 构造 UF_DISP_facet_t 数组
int structSize = Marshal.SizeOf(typeof(UF_DISP_facet_t));
long vertsStep = doubleCountPerFacet * sizeof(double);
long normsStep = doubleCountPerFacet * sizeof(double);
for (int i = 0; i < facetCount; i++)
{
IntPtr facetPtr = (IntPtr)((long)facetsArrayPtr + i * structSize);
UF_DISP_facet_t facet = new UF_DISP_facet_t
{
vertices = (IntPtr)((long)allVertsPtr + i * vertsStep),
normals = (IntPtr)((long)allNormalsPtr + i * normsStep)
};
Marshal.StructureToPtr(facet, facetPtr, false);
}
int status = UF_DISP_display_facets(facetsArrayPtr, vertexCount, facetCount,
UF_DISP_facet_type_t.UF_DISP_TRIANGLE, handle);
if (status != 0)
NXLog.WriteLog($"UF_DISP_display_facets error: {status}");
}
finally
{
Marshal.FreeHGlobal(allVertsPtr);
Marshal.FreeHGlobal(allNormalsPtr);
Marshal.FreeHGlobal(facetsArrayPtr);
}
}
