测量曲线段的直线度(以折线表示)


11

我正在研究一种自动的高程轮廓标注算法,在确定标签位置时要考虑的因素之一是轮廓的特定段的“直度”。它越直,就越有可能将标签用于该线段。

每个轮廓由一条折线表示(但点彼此靠近,看起来像肉眼的曲线)。然后,我有一个固定的长度(标签的宽度),例如100像素。如果我随机(或以其他方式)选择宽度为100像素的轮廓线段,我希望能够获得其直线度的数值定量值(对于完全笔直的轮廓线段为零,对于非直线形轮廓线段则大于零。直线段,并且该值会随着弯曲度的增加而增加)。

我一直在寻找答案,但是找不到任何真正有用的东西。我将不胜感激任何指针。

Answers:


9

答案取决于上下文:如果您仅研究少量(有界)段,则可能能够提供计算上昂贵的解决方案。但是,您似乎可能希望将此计算合并到某种形式的对良好标记点的搜索中。如果是这样,那么具有一个计算速度快或在候选线段略有变化时允许快速更新解决方案的解决方案将非常有利。

例如,假设您打算进行系统的搜索分布在轮廓的整个连接分量上,表示为点P(0),P(1),...,P(n)的序列。这可以通过将一个指针(序列的索引)s = 0(“ s”表示“开始”)和另一个指针f(用于“ finish”)初始化为距离(P(f), P(s))> = 100,然后将s向前推进,直到距离(P(f),P(s + 1))> =100。这将生成候选折线(P(s),P(s + 1)...,P(f-1),P(f))进行评估。评估其“适合度”以支持标签后,您将s加1(s = s + 1),然后将f增加到(例如)f',将s增加到s',直到候选折线再次超过最小值跨度为100,表示为(P(s'),... P(f),P(f + 1),...,P(f'))。这样,顶点P(s)... P(s' 高度期望可以仅根据落下和添加的顶点的知识来快速更新适应度。 (此扫描过程将一直持续到s = n;照例,在此过程中,必须允许f从n“回绕”到0。)

这种考虑排除了健身的许多可能的措施弯度弯曲度等),否则可能是有吸引力的。它使我们支持基于L2的度量,因为当基础数据稍有变化时,它们通常可以快速更新。与主成分分析类似,建议我们采取以下措施(应要求,取小者为佳):使用协方差矩阵的两个特征值中较小的一个点坐标。在几何上,这是折线的候选部分内顶点“典型”侧向偏移的一种度量。(一种解释是,它的平方根是椭圆的较小半轴,代表折线顶点的第二惯性矩。)仅对于共线顶点集,该值等于零;否则,它将超过零。它测量相对于由折线的起点和终点创建的100像素基线的平均左右偏差,从而具有简单的解释。

因为协方差矩阵只有2 x 2,所以通过求解单个二次方程可以快速找到特征值。此外,协方差矩阵是折线中每个顶点的贡献之和。因此,当删除或添加点时,它会快速更新,从而导致针对n点轮廓的O(n)算法:这将很好地缩放到应用程序中设想的高度详细的轮廓。

这是此算法的结果示例。黑点是轮廓的顶点。红色实线是该轮廓内端到端长度大于100的最佳候选折线段。(右上角视觉上明显的候选对象不够长。)

数字


哇,你让我迷路了:)。您对系统搜索是正确的,我已经必须这样做才能获取每个折线/多边形顶点的切线(水平标签优先于垂直标签),因此从理论上讲,我可以将此搜索扩展到其他度量。顺便说一句:您是使用实际算法还是手动生成样本图?
伊戈尔·布雷希

1
该图是真实的,但我使用的实现未使用协方差更新过程,因此在计算上不是最佳的。
Whuber

2
最后的图表使这个答案更加
出色

2
伊戈尔,我应该提到标签方向是免费提供的:它是由椭圆的长轴方向(与较大特征值相关的特征向量)给出的。因此,您可以同时高效地搜索标签方向和轮廓线的线性度的最佳组合。
Whuber

3

在计算机图形社区中,通常有必要在对象周围找到边界框。因此,对于快速算法,这是一个经过充分研究的问题。例如,请参阅Wikipedia的“ 最小边界框算法”文章。您可以找到折线周围的最小面积矩形,然后使用该矩形的长宽比(高度/长度)。为了获得更精确的度量,您可以查看折线与该边界矩形的中心线的偏差。


1
我考虑过要使用min。边界框,但我看到两个问题:a)计算一个框的计算复杂度实际上是最小值(并因此而旋转),b)具有相同长宽比的两个曲线段的曲率会非常不同(例如正弦曲线)振幅相同但波周期不同的曲线)。
伊戈尔·布赖克

1
很高兴在GIS页面上看到您,约瑟夫!
Whuber

1
是的,我现在手上有《 C的计算几何》一书:)
Igor Brejc

1
谢谢大家的欢迎!:-)我意识到我的建议不是理想的方法,但是编码是现成的(如果您的货架合适)。这种类型的问题已经在制造环境中进行了很多研究,在制造环境中,他们需要测量加工零件的质量。
约瑟夫·奥洛克

3

我不知道这是否有帮助,甚至不算是一个答案,但是当我坐在这里思考刚刚发布的问题时,我有一个想法:

如果在轮廓线上放置特定半径的圆,该怎么办。该圆将在至少两个位置与轮廓线相交。直线越直,两个相交点之间沿着轮廓线的距离越短。沿交点之间的轮廓线的距离越长,该线越弯曲。如果有两个以上的交点,则轮廓线太弯曲了。

您可以找出最能指示直线度的长度,然后建立例程以沿着每条轮廓线移动,并在直线足够的地方放置标签。

我敢肯定,这并没有太大帮助,无论您使用哪种编程语言,用英语说的要困难得多,但这可能是一个开始吗?


有趣的主意。为了更简单,您可以计算一侧的线段长度与起点和终点之间的距离之比。它不是那么精确,但是计算起来很快。您使用圆的想法将使直线度的计算更加精确。
伊戈尔·布赖克

3

我能想到的最简单的方法是起点和终点之间的实际路径长度与起点到终点之间最短距离(直线)之间的比率。直线的比例接近1,而非常弯曲的直线则比例很高。

这应该是一个非常容易实现的解决方案。


更新:正如Mike正确注意到的,这等于Sinuosity

在此处输入图片说明


阅读雷克斯(Rex)的回答后,我的脑海中
浮现的

4
基本上是对立的对立
Mike T

恰好:) ....
暗处

2
没错,这很容易实现,因为在搜索适当的片段以进行标记时更新长度就像在连续顶点之间添加和减去长度一样简单。但是,正弦不能有效地捕捉曲线偏离线性的感觉。例如,将直径为100 的半圆与直径为1的半圆的线性序列进行比较:两条曲线具有相同的正弦度,但是第一个曲线的左右偏差是第二个曲线的左右偏差的100倍(这是不错的底数标签)。

考虑到如果您的折线画一个圆,此方法将给您无限的弯曲度,这可能不是您想要的结果。
obchardon

1

通过搜索“曲率”和“折线”,我获得了此信息。 如何找到折线的曲率?。在那里他建议使用回去定义曲率- K= DF/Ds。这里由F他的意思phi,或T在维基百科的符号在这里(http://en.wikipedia.org/wiki/Curvature)。

假设您有一个序列,分别是p0,p1和p2三个点。假设点彼此足够近,计算sp0和p1之间的距离,即s(Ds)的增量。然后,您需要T(DT)的增量,它是p0和p1之间的单位切向矢量的变化。可能有一种复杂的方法,但是我可以想到的粗略方法是取两个bector p0-> p1,p1-> p2,将每个标准化为长度为1,然后对这两个进行矢量减法,然后确定幅度。那是DT。除法产生曲率K0_1。抓取p1,p2和p3进行计算K1_2,依此类推。

我想知道是否将轮廓作为多义线而不是渲染像素。您说了100px,让我有些担心。


感谢您的链接,我将不得不研究其背后的数学。我之所以提到100px仅仅是因为呈现的标签文本具有一定的宽度(以像素为单位),100px只是一个示例。
伊戈尔·布赖克

曲率的思考是一个不错的主意。跨度足够长的高度平滑轮廓部分的曲率可能是适当的,但曲率本身不适合:例如,一个小的之字形曲率会非常高,但总体上却无关紧要。因此,实际上,您将使用某些折线跨段线性偏差的统计摘要。在可能的候选对象中,曲率将是要执行的更复杂的计算之一。
Whuber
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.