请选择 进入手机版 | 继续访问电脑版

唐康林NX二次开发论坛

 找回密码
 立即注册
查看: 649|回复: 8

[技术分享] NX二次开发判断曲线集相连及封闭的方法-唐康林原创

[复制链接]

543

主题

715

帖子

3124

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3124
发表于 2018-3-12 14:31:11 | 显示全部楼层 |阅读模式
文/唐康林 独家原创 QQ125317589
       关于在NX二次开发中,判断曲线集是否相连及封闭这种类似问题,我曾经是在开发一具批量创建管道功能时用到的。
       业务场景:当用户通过UI批量框选了一堆无序曲线后,要求自动创建出管道。(NX自带的管道,每次只能创建一根)
       解决问题:
       1、用户选择了一堆曲线,首先就是要分类,哪些曲线,可以被当成是“相连的曲线”,因为只有相连曲线,才可能创建管道;(准确的说,要相切曲线才可以)
       2、分完类了,就再判断相连的曲线是否是连续的,如果有尖角,它也不能成功创建管道;
       3、如果不连续,要求利用“连结曲线”功能,将它连成一样条,再进行创建管道;
       回到最初的问题,给定一堆无序的曲线集,判断它们是否封闭!  
       如果是单条曲线,判断其封闭,可以用这几个函数:
       UF_EVAL_ask_arc (判断圆弧是否封闭)
       UF_EVAL_ask_ellipse  (判断椭圆是否封闭)
       UF_EVAL_ask_spline  (判断样条是否封闭)
       UF_MODL_ask_curve_closed (这个函数经过我的测试,曲线与边都可以判断)

       如果是无序曲线集可以考虑以下方法:
       1、将曲线集A全部用UF_CURVE_auto_join_curves函数进行连结一下,连结后,可以得到输出曲线的数量;
       2、判断曲线的数量,如果为1,说明曲线集A能组成相连曲线,如果不为1,说明选择的曲线集A,不连续;
       3、如果2中判断出曲线集为连续的,就直接拿创建的样条,进行判断它的封闭性。
判断曲线是否封闭.png

回复

使用道具 举报

6

主题

32

帖子

369

积分

终身VIP会员

Rank: 6Rank: 6

积分
369
发表于 2018-3-13 11:32:26 | 显示全部楼层
本帖最后由 w181034988 于 2018-3-13 11:37 编辑

我也想了一下,写了一下高效的数学方法。只供参考. 得到所有边的端点和尾点进行判断是否封闭
  1. public bool IsClose(Point3d[] 点集)
  2. {
  3.         for (int i = 0; i < 点集.Length; i++)
  4.         {
  5.                 int TempValue = 0;
  6.                 for (int j = 0; j < 点集.Length; j++)
  7.                 {
  8.                         if (点集[i] == 点集[j])
  9.                         {
  10.                                 TempValue++;
  11.                         }
  12.                 }
  13.                 if (TempValue != 2)
  14.                 {
  15.                         return false;
  16.                 }
  17.         }
  18. return true;
  19. }
复制代码



回复 支持 反对

使用道具 举报

543

主题

715

帖子

3124

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3124
 楼主| 发表于 2018-3-13 11:45:08 | 显示全部楼层
w181034988 发表于 2018-3-13 11:32
我也想了一下,写了一下高效的数学方法。只供参考. 得到所有边的端点和尾点进行判断是否封闭
蛤,你写得太高大上,解释一下,你这东西,让我们学习一下,我都没有看懂。
我看过官方用数学方法写的,比你这个代码多多了。很长的,
所以我才想了这个他连接曲线的方法。
回复 支持 反对

使用道具 举报

6

主题

32

帖子

369

积分

终身VIP会员

Rank: 6Rank: 6

积分
369
发表于 2018-3-13 12:59:08 来自手机 | 显示全部楼层
唐康林 发表于 2018-3-13 11:45
蛤,你写得太高大上,解释一下,你这东西,让我们学习一下,我都没有看懂。
我看过官方用数学方法写的,比 ...

一堆线。全部都是一个点是相同的就是封闭。多个点相同就是交叉。有一个不相同就是不封闭。我也是临时想出来的。也没测试过。你测试一下不就知道了
回复 支持 反对

使用道具 举报

543

主题

715

帖子

3124

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3124
 楼主| 发表于 2018-3-13 13:23:20 | 显示全部楼层
w181034988 发表于 2018-3-13 12:59
一堆线。全部都是一个点是相同的就是封闭。多个点相同就是交叉。有一个不相同就是不封闭。我也是临时想出 ...

帮你理一下你说的逻辑:
1、得到曲线集合A中每条曲线的端点坐标 集合B;
2、将B中每一个坐标拿出来统计在B中出现的次数;
     ① 如果每一个都是出现两次,就说明是曲线封闭;
     ② 只要有一个点出现次数为1,就说明曲线是开放的;
     ③ 只要有一个点坐标次数出现大于2,说明有交叉;
     如下图A情况,但是这种算法,有可能有BUG,如下图B,如果先得到所有曲线的端点,判断出来,它是封闭的,但有可能实际业务,这种封闭,不是想要的封闭。

封闭曲线BUG.png

回复 支持 反对

使用道具 举报

6

主题

32

帖子

369

积分

终身VIP会员

Rank: 6Rank: 6

积分
369
发表于 2018-3-13 15:28:01 | 显示全部楼层
你要这种封闭,数学方法也是可以的,就是麻烦点,刚才花了点时间写了下,大概测试了下,程序OK
  1. public class CurveData
  2. {
  3.         public Tag tag;
  4.         public Point3d StartPt;
  5.         public Point3d endPt;
  6.         public int P;//要用哪点查找对象 0为起始点 1为终始点 -1为未知
  7.         public CurveData()
  8.         {
  9.                 this.P = -1;
  10.         }
  11. }

  12. public static bool IsClosed(List<CurveData> CurveDataList, double tol)
  13. {
  14.         int OldCount = CurveDataList.Count;
  15.         //选判断单条是否封闭
  16.         for (int i = 0; i < CurveDataList.Count; i++)
  17.         {
  18.                 if (UFSession.GetUFSession().Modl.AskCurveClosed(CurveDataList.tag) == 1)
  19.                 {
  20.                         if (CurveDataList.Count == 1)//链表共一条边
  21.                         {
  22.                                 return true;
  23.                         }
  24.                         else
  25.                         {
  26.                                 return false;
  27.                         }
  28.                 }
  29. }

  30. bool IsOK = false;//是否回路

  31. //用于查找连接对象链表
  32. List<CurveData> ConnectCurve = new List<CurveData>();
  33. CurveDataList[0].P = 0;//设用起点查找对象
  34. ConnectCurve.Add(CurveDataList[0]);//插入起始曲线,查找连接曲线

  35. CurveDataList.Remove(CurveDataList[0]);//删除
  36. for (int i = 0; i < ConnectCurve.Count; i++)
  37. {
  38.         //点
  39.         Point3d tempPt = new Point3d();
  40.         if (ConnectCurve.P == 0)
  41.         {
  42.                 tempPt = ConnectCurve.StartPt;
  43.         }
  44.         else if (ConnectCurve.P == 1)
  45.         {
  46.                 tempPt = ConnectCurve.endPt;
  47.         }
  48.         else
  49.         {
  50.                 tempPt = ConnectCurve.StartPt;
  51.         }

  52.         //向连表里连查找连接曲线
  53.         bool isGet = false;
  54.         for (int j = 0; j < CurveDataList.Count; j++)
  55.         {
  56.                 if (Math.Abs(tempPt.X - CurveDataList[j].StartPt.X) < tol &&
  57.                         Math.Abs(tempPt.Y - CurveDataList[j].StartPt.Y) < tol &&
  58.                         Math.Abs(tempPt.Z - CurveDataList[j].StartPt.Z) < tol)//点位置相同 起点找到
  59.                 {
  60.                         ConnectCurve.Add(CurveDataList[j]);//收集对象
  61.                         ConnectCurve[ConnectCurve.Count-1].P = 1;//起点找到就用终点查找
  62.                         CurveDataList.RemoveAt(j);//移除对象
  63.                         isGet = true;
  64.                         break;
  65.                 }
  66.                 else if (Math.Abs(tempPt.X - CurveDataList[j].endPt.X) < tol &&
  67.                         Math.Abs(tempPt.Y - CurveDataList[j].endPt.Y) < tol &&
  68.                         Math.Abs(tempPt.Z - CurveDataList[j].endPt.Z) < tol)//点位置相同 终点找到
  69.                 {
  70.                         ConnectCurve.Add(CurveDataList[j]);//收集对象
  71.                         ConnectCurve[ConnectCurve.Count - 1].P = 0;//终点找到就用起点查找
  72.                         CurveDataList.RemoveAt(j);//移除对象
  73.                         isGet = true;
  74.                         break;
  75.                 }
  76.         }

  77.         //上面没找到对象就头尾查找是否回路
  78.         if (!isGet)
  79.         {
  80.                 Point3d tempPt2 = new Point3d();
  81.                 if (ConnectCurve[0].P == 0)
  82.                 {
  83.                         tempPt2 = ConnectCurve[0].endPt;
  84.                 }
  85.                 else if (ConnectCurve[0].P == 1)
  86.                 {
  87.                         tempPt2 = ConnectCurve[0].StartPt;
  88.                 }

  89.                 if (Math.Abs(tempPt.X - tempPt2.X) < tol &&
  90.                         Math.Abs(tempPt.Y - tempPt2.Y) < tol &&
  91.                         Math.Abs(tempPt.Z - tempPt2.Z) < tol)//点位置相同
  92.                 {
  93.                         IsOK = true;
  94.                 }
  95.         }
  96. }

  97.         if (ConnectCurve.Count == OldCount && IsOK)//排序点接曲线数量等于选择曲线数量并且是回路就是封闭
  98.         {
  99.                 return true;
  100.         }
  101.         else
  102.         {
  103.                 return false;
  104.         }
  105. }
复制代码



回复 支持 反对

使用道具 举报

543

主题

715

帖子

3124

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3124
 楼主| 发表于 2018-3-13 15:45:04 | 显示全部楼层
w181034988 发表于 2018-3-13 15:28
你要这种封闭,数学方法也是可以的,就是麻烦点,刚才花了点时间写了下,大概测试了下,程序OK
牛B了……
用这个Modl.AskCurveClosed 去判断单条曲线是否封闭,有BUG,我用过的,有些曲线是封闭的,但用这个判断出来不封闭。
最好是判断端点距离。
回复 支持 反对

使用道具 举报

6

主题

32

帖子

369

积分

终身VIP会员

Rank: 6Rank: 6

积分
369
发表于 2018-3-13 16:08:29 | 显示全部楼层
本帖最后由 w181034988 于 2018-3-13 16:10 编辑
唐康林 发表于 2018-3-13 15:45
牛B了……
用这个Modl.AskCurveClosed 去判断单条曲线是否封闭,有BUG,我用过的,有些曲线是封闭 ...

刚看了,那个判断是多余的,可以删掉单条判断。直接走下面代码也没问题
回复 支持 反对

使用道具 举报

543

主题

715

帖子

3124

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3124
 楼主| 发表于 2018-3-13 16:16:00 | 显示全部楼层
w181034988 发表于 2018-3-13 16:08
刚看了,那个判断是多余的,可以删掉单条判断。直接走下面代码也没问题 ...

我看过官方例子,差不多,就是这个思路,先对曲线用端点的方式,进行排序,就可以找出可能组成 相连曲线集,然后才是对这个曲线集进行判断是否封闭。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋| ( 蜀ICP备16014681号

GMT+8, 2018-7-19 16:01 , Processed in 0.097580 second(s), 26 queries .

Powered by www.nxopen.cn

© 2001-2013 nxopen.cn

快速回复 返回顶部 返回列表