有效地将线段排序成循环

2024-02-21

我正在使用一个图书馆(JavaScript-Voronoi https://github.com/gorhill/Javascript-Voronoi),它生成表示闭合多边形的线段数组。这些线段显示无序,无论是线段出现的顺序还是线段每端点的顺序。

(Edit: As noted in a comment below, I was wrong: the segments from the library are well-ordered. However, the question stands as written: let's assume that the segments do not have any ordering, as this makes it more generally useful.)

例如:

var p1 = {x:13.6,y:13.1}, p2 = {x:37.2,y:35.8}, p3 = {x:99.9,y:14.6},
    p4 = {x:99.9,y:45.5}, p5 = {x:33.7,y:66.7};
var segments = [
  { va:p1, vb:p2 },
  { va:p3, vb:p4 },
  { va:p5, vb:p4 },
  { va:p3, vb:p2 },
  { va:p1, vb:p5 } ];

请注意第一个片段如何链接到最后一个片段(它们共享一个公共点)以及倒数第二个片段。保证每个段与另一个段恰好共享一端。

我想将其转换为点列表以生成正确的 SVG 多边形:

console.log( orderedPoints(segments) );
// [
//   {"x":33.7,"y":66.7},
//   {"x":13.6,"y":13.1},
//   {"x":37.2,"y":35.8},
//   {"x":99.9,"y":14.6},
//   {"x":99.9,"y":45.5}
// ]

这些点是按顺时针顺序还是逆时针顺序并不重要。

以下代码是我想出的,但在最坏的情况下,它需要n^2+n点比较。是否有更有效的算法将所有这些连接在一起?

function orderedPoints(segs){
  segs = segs.concat(); // make a mutable copy
  var seg = segs.pop(), pts = [seg.va], link = seg.vb;
  for (var ct=segs.length;ct--;){
    for (var i=segs.length;i--;){
      if (segs[i].va==link){
        seg = segs.splice(i,1)[0]; pts.push(seg.va); link = seg.vb;
        break;
      }else if (segs[i].vb==link){
        seg = segs.splice(i,1)[0]; pts.push(seg.vb); link = seg.va;
        break;
      }
    }
  }
  return pts;
}

如果你的多边形是凸的,你可以选择每条线段的中点,然后使用凸包 http://en.wikipedia.org/wiki/Convex_hull算法通过中间项找到凸多边形,之后,因为你知道中间项的排列是什么,也知道哪个中间项属于哪一段,所以你可以在原始数组中找到一个排列。

如果你只是想找到一个凸包,直接使用凸包算法,它是O(n log n),这已经足够快了,而且你也可以在javascript中找到一个Quickhull算法here http://en.literateprograms.org/Quickhull_%28Javascript%29。快船也在O(n logn),但平均而言,最坏的情况是 O(n^2),但由于常数因子较少,因此速度很快。


但在一般算法的情况下:

将每个段的一端设置为第一端,另一端设置为第二端(随机)。

按第一个细分对您的细分进行排序x并将其放入数组中First之后在数组中首先对具有相同第一个的段进行排序x由他们的第一个y并额外放两个int进入您的结构以保存具有相同第一个项目的开始和结束位置x.

然后再次用第二个对你的片段进行排序x值,....并制作数组second.

上述动作的复杂度都是 O(n log n)。

现在选择数组中的第一个段First, 寻找第二个x两个数组中的值First and second,如果您发现相似的值,请搜索它们y相关子数组中的值(您具有相同项目的开始和结束位置x)。您知道只有一个段具有此顺序(也不是当前段),因此查找下一个段需要O(log n)因为在一切之中都有n-1下一段需要O(n logn)(也是预处理),这比O(n^2).

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

有效地将线段排序成循环 的相关文章

随机推荐

  • 修剪字符字段

    我们目前使用的是 Delphi 和 Borland 数据库 我们计划从 borland 迁移到 Firebird 库 borland lib 有内存泄漏 我们现在遇到的问题是 Firebird 库返回一个带有尾随空格的字符 这是 borla
  • 实体框架表拆分:不在同一类型层次结构中/没有有效的一对一外键关系

    我使用实体框架 6 和代码优先方法 并且我希望将两个实体放入同一个表中 我究竟做错了什么 Table Review public class Review public int Id get set public PictureInfo P
  • 为什么Koala无法编译默认的Bootstrap 3 less文件?

    我正在努力学习 Bootstrap 3 及 Less 但在开始之前我就陷入了死胡同 经过两天的反复试验 我最终选择了Koala来将Less编译成CSS 我使用的是 Mac OS 10 7 所以 Codekit 已经出来了 现在只能在 8 上
  • Ruby 1.9 中的垃圾收集器调整

    我知道关于GC enable disable 但是有什么方法可以控制 Ruby1 9垃圾收集器更详细吗 在分析我的代码时 使用 perftools rb 我注意到 GC 最多占总样本的 30 我想看看是否可以调整 GC 以减少这个数字 是否
  • Java中的局部变量清空对GC有帮助吗

    我 被迫 添加myLocalVar null 在离开方法之前将语句放入finally子句中 原因是为了帮助GC 有人告诉我下次服务器崩溃时我会在晚上收到短信 所以我最好这样做 我认为这是毫无意义的 因为 myLocalVar 的范围仅限于方
  • 在 SQL 中多次连接同一个表[重复]

    这个问题在这里已经有答案了 我有一个表 每个 tran ref 列有 3 行或更多行 每行都有 amount 以及 tran id 以下是我的输入表 tran ref tran id amount T1 01 9 T1 02 8 T1 03
  • 如何将小数属性格式化为货币?

    我想将小数值格式化为货币值 我怎样才能做到这一点 属性可以返回它们想要的任何内容 但需要返回正确的类型 private decimal amount public string FormattedAmount get return stri
  • 一张图中的多个图

    我有以下代码 我想将相空间图组合成一个图形 我已经对这些函数进行了编码 但我不知道如何让 MATLAB 将它们放入一张图中 正如你所看到的 这是变量r a b and d这会改变 我如何将它们结合起来 我还想使用以下方法绘制这些相空间图的矢
  • C# 中的等效 char*

    我有一个用 C 编写的 dll 我正在 p invoking 来调用这些函数 我有这个 C 声明 int dll registerAccount char username char password 我已经完成了这个 dllimport
  • 在 C# 中处理整数溢出的最佳方法?

    处理整数溢出是一项常见任务 但在 C 中处理它的最佳方法是什么 是否有一些语法糖可以使其比其他语言更简单 或者这真的是最好的方法吗 int x foo int test x common if test common x Console W
  • LARAVEL 获取视图中 withErrors 的结果

    在我使用的控制器中 if validator gt fails return Redirect to admin profile gt withErrors validator gt withInput 如何在视图中获取 withError
  • PHP 5.2.17 的 round() 模式 ROUND_HALF_DOWN

    我需要在 PHP 5 2 17 中模拟 ROUND HALF DOWN 模式 我无法升级服务器的 PHP 版本 有什么想法如何实现这一目标 基本思想是 1 895 变成 1 89 而不是像通常使用 round 那样变成 1 90 编辑 这个
  • ILMerge - 命令退出,代码为 255

    我正在尝试使用 ILMerge 将 DLL 嵌入到单个可执行文件中 我在构建事件 gt 构建后事件命令行中添加了此命令行 C Program Files Microsoft ILMerge ILMerge exe out TargetDir
  • 模型输入必须来自“tf.keras.Input”...,它们不能是先前非输入层的输出

    我正在使用Python 3 7 7 和张量流 2 1 0 我有一个预先训练过的 U Net 网络 我想要得到它的编码器 and 它的解码器 如下图所示 您可以看到卷积编码器 解码器架构 我想要获取编码器部分 即出现在图像左侧的图层 以及解码
  • ASMX Web 服务公开类

    我正在使用简单的 ASMX 服务在 asp net c 中创建基本的 Web 服务 当我创建返回类的方法时 服务的客户端可以发现该类定义 我想知道是否有一种方法可以将类公开给不直接在任何服务方法中使用的服务 我需要我的服务客户端了解特定的类
  • 在javascript刷新中调用php函数

    我在 javascript 中有一个简单的函数 可以在设定的时间后刷新页面 function AutoRefresh t setTimeout location reload true t 现在每次刷新后 我希望它调用 PHP 函数 例如
  • 如何从列表中发出每个项目之间有延迟的项目?

    我想从列表中发出项目 并且在每次发射之间我想要一个延迟 我试过这个 final Subscription subscription Observable from listOfItems delay 2000 TimeUnit MILLIS
  • Eclipse 和 Maven 多模块项目的问题

    我创建了一个 Maven 项目 其结构如下 root project pom xml pom sub projectA jar sub projectB jar 我已完成以下步骤 mvn 原型 创建 DgroupId my group id
  • 如何在sql选择中隐藏不同的列

    我正在 sql 中执行查询以查找具有不同值的行name如下 select distinct name age sex from person 它有效 但我不想在结果集中显示名称列 有没有办法隐藏此栏 EDIT1我说的原因distinct n
  • 有效地将线段排序成循环

    我正在使用一个图书馆 JavaScript Voronoi https github com gorhill Javascript Voronoi 它生成表示闭合多边形的线段数组 这些线段显示无序 无论是线段出现的顺序还是线段每端点的顺序