求教一个查找网格边界的算法实现

洗洗睡去 2016-01-21 09:15:59
问题:有一个由很多三角形组成的网格,现在要找出它的最外面一圈边界。已知的信息有:
1.网格中每个点的坐标值浮点型(x,y),索引值整形i。
2.每个三角形三个点的索引值整形index1,index2,index3.

我写的基本算法:
1.建立一个结构,类似无向图的边,这样每个三角的边为e1=(index1,index2),e2=(index1,index3),e3=(index2,index3)
2.取一个边,循环查找这个边在剩下的网格边中被使用的次数,如果为0,则为边界边,如果大于等于1,则肯定是内部边.
3.循环取所有边进行上述比较。
基本算法的问题:
30w个三角形,有将近80w个 边,循环比较需要80w*80w次,复杂度为O(n*n),时间开销太大,有没有算法能降低到O(n)或者O(nlogn)
注意:网格可能是凸也可能是凹的,所有通过计算距离来比较是不行的
...全文
1061 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
洗洗睡去 2020-01-15
  • 打赏
  • 举报
回复
引用 11 楼 xiaoxiaoxiaoyang218 的回复:
优化了查找边界边的算法 思路:遍历三角形的三条边,求共边三角形的个数。只有一个的时候就是边界边。中间不产生额外的数组,内存占用少,效率也提升了一倍
不错的,我当时没用经典的半边算法,全部从0考虑的,所以算法效率不够高,后来偶然看到了半边算法,也没研究
  • 打赏
  • 举报
回复
优化了查找边界边的算法 思路:遍历三角形的三条边,求共边三角形的个数。只有一个的时候就是边界边。中间不产生额外的数组,内存占用少,效率也提升了一倍
  • 打赏
  • 举报
回复
不知道C语言为什么那么慢,可以考虑用链表实现。因为我是用 javascript 做的,40W三角形的网格,300ms左右就可以了 思路:先根据三角形求半边,半边再找它的twin。边界边就是没有 twin 的半边
qq_35799624 2017-04-27
  • 打赏
  • 举报
回复
楼主,最后实现的算法有木有,方便发我学习一下吗?
赵4老师 2016-01-22
  • 打赏
  • 举报
回复
最外面一圈边界如果是凹多边形的话……
洗洗睡去 2016-01-22
  • 打赏
  • 举报
回复
解决了 4-5s搞定,其实也很简单,首先e1,e2,e3内部2个int型从小到大排序,第二步将这些边放入vector里去,第三步,sort排序,这样排序之后的数组里,靠近位置相同的边便是内部边,剩下没相同的便是边界边。第一二步耗时大概1-2s,第三步排序太牛逼了,80w个2s搞定,最后检出边界边不到1s
洗洗睡去 2016-01-22
  • 打赏
  • 举报
回复
引用 5 楼 worldy 的回复:
[quote=引用 2 楼 sunnyloves 的回复:] [quote=引用 1 楼 worldy 的回复:] 使用一个中间数组,拷贝入所有边数据, 取出数组中下一个没有被移除的边(首次肯定是第一边),和其它各边进行比较(后续没有被移除边必须全部比较), 如果发现同边,则同边数据从数组中移除(做个标记) 取出下一个没有被移除的边,做上述操作(向后比较即可) 这样每边的线段都将只做一次比较
设标志位的改进方法我用过的,提升不大,等了10分钟下断点,外循环才到几k[/quote] 你没有把出现标志的边跳过吧?如果有跳过,理论上讲,每条边只比较一次,应该是最佳的方式了 话说,你单次80w次比较,也是够你蛋疼的,速度不可能快 换一个角度,如果做些预处理: 点可以使用16位表达,那么建议点数据合成long数据,直接32位比较,而不要去xy分别比较; 更进一步,最好能将边数据合成一个longlong数据,然后按64位编译,应该有明显效果 [/quote] 跳过的,主要因为边界一圈的边数量其实没多少也就几百个吧,跳过对整体影响不大。 32位直接比较我再试试
赵4老师 2016-01-21
  • 打赏
  • 举报
回复
《算法精解(C语言描述)》?
洗洗睡去 2016-01-21
  • 打赏
  • 举报
回复
引用 1 楼 worldy 的回复:
使用一个中间数组,拷贝入所有边数据, 取出数组中下一个没有被移除的边(首次肯定是第一边),和其它各边进行比较(后续没有被移除边必须全部比较), 如果发现同边,则同边数据从数组中移除(做个标记) 取出下一个没有被移除的边,做上述操作(向后比较即可) 这样每边的线段都将只做一次比较
设标志位的改进方法我用过的,提升不大,等了10分钟下断点,外循环才到几k
worldy 2016-01-21
  • 打赏
  • 举报
回复
引用 2 楼 sunnyloves 的回复:
[quote=引用 1 楼 worldy 的回复:] 使用一个中间数组,拷贝入所有边数据, 取出数组中下一个没有被移除的边(首次肯定是第一边),和其它各边进行比较(后续没有被移除边必须全部比较), 如果发现同边,则同边数据从数组中移除(做个标记) 取出下一个没有被移除的边,做上述操作(向后比较即可) 这样每边的线段都将只做一次比较
设标志位的改进方法我用过的,提升不大,等了10分钟下断点,外循环才到几k[/quote] 你没有把出现标志的边跳过吧?如果有跳过,理论上讲,每条边只比较一次,应该是最佳的方式了 话说,你单次80w次比较,也是够你蛋疼的,速度不可能快 换一个角度,如果做些预处理: 点可以使用16位表达,那么建议点数据合成long数据,直接32位比较,而不要去xy分别比较; 更进一步,最好能将边数据合成一个longlong数据,然后按64位编译,应该有明显效果
worldy 2016-01-21
  • 打赏
  • 举报
回复
使用一个中间数组,拷贝入所有边数据, 取出数组中下一个没有被移除的边(首次肯定是第一边),和其它各边进行比较(后续没有被移除边必须全部比较), 如果发现同边,则同边数据从数组中移除(做个标记) 取出下一个没有被移除的边,做上述操作(向后比较即可) 这样每边的线段都将只做一次比较
洗洗睡去 2016-01-21
  • 打赏
  • 举报
回复
看到有网站说可以用哈希表的方法查找,研究下

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧