FME 2018 无限精度的战争:自动容差如何在没有捕捉的情况下击败无限精度 – 但是具有锚定顶点

FME 2018 无限精度的战争:自动容差如何在没有捕捉的情况下击败无限精度 – 但是具有锚定顶点

 

前言

FME 2018为许多转换器引入了容差参数。这些参数看起来很简单,但它们包含的内容比你想象的要多得多。事实上,它们相当于FME几何对象处理的哲学彻底改变!

 

你知道,我们一直对自己感到自豪的一件事是FME不会在转换过程中改变你的数据。当然,有一些问题需要解决。例如,当格式不支持弧时,我们将它们写为线,但是开始/结束的坐标和图形的形状保持不变。

 

此外,FME在几何对象计算中总是精确的,例如线交叉。非常精确。尤其是在64位的环境下尽可能地精确。

 

简而言之,除非您特别需要,否则FME永远不会更改数据的坐标,并且始终将计算延伸到其极限以提供正确的转换结果。

 

不幸的是 - 也许令人惊讶的是 - 这些技术并不一定能在所有情况下提供最佳解决方案。64位二进制数学的本质,加上对绝对精度的渴望,如果不加以控制,可能会给数据带来奇怪的现象。这些通常显示为非常非常小的线段或三角形。

 

因此,FME 2018 - 通过容差参数 - 解决了这些数学怪异问题。这意味着打破了我们的一些基本规则,但事实证明这是一件好事。

 

本文解释了原因。它涉及到相当多的细节。我试图让它变得尽可能简单 – 否则我不会理解它 - 但如果你发现它太技术化,请跳到最后的“FME中的实际使用”部分。

 

https://cdn.blog.safe.com/wp-content/uploads/2013/09/EvangelistBanner7.png

 

容差,精度和二进制数学

让我们来看看计算机上数学中出现的两个问题。首先是以64位存储十进制值的问题。

在64位中存储小数

考虑将十除以三(10/3)的结果。你是如何表示这个结果的?嗯,它是3.3333333333等。数字3重复到无穷大,你通常将它舍入到你想要的任何精度。

 

好吧,一些计算同样最终会以二进制形式重复出现。例如,一除以五(1/5)的十进制为0.2; 但二进制的结果是0.0111 1111 1001 0011 0011 0011 0011 0011等。你可以看到0011重复,并且会重复到无穷大,就像十进制的10/3一样。计算机将其四舍五入到最接近的数学值,即十六进制的0x3FC999999999999A或十进制,它是0.200000000000000011102230246252

 

我可以通过放置2DGridCreator并将列/行宽度设置为0.2来查看FME中的效果:

https://cdn.blog.safe.com/wp-content/uploads/2018/08/07102305/Precision2018-1.png

 

FME严格避免舍入或更改收到的数字,并返回计算机所说的正确坐标。但是,在这种情况下,很容易看出这不是特别有用。

 

这就是在64位浮点中表示十进制值的问题。我们在计算机上面临的第二个问题是空间网格分辨率......

 

空间网格和精度

此问题与十进制和二进制之间的转换无关; 它纯粹是关于二进制计算值。FME将空间数据存储为64位二进制坐标。如果将所有可能的坐标绘制为点,则会得到一个网格。如果添加线条,它们的顶点将位于该网格上:

 

https://cdn.blog.safe.com/wp-content/uploads/2018/08/07100610/Precision2018-2.png

两条红线在哪里相交?在网格上标记的坐标处。很明显,对吧?但是,如果线条像这样交叉会发生什么:

https://cdn.blog.safe.com/wp-content/uploads/2018/08/07100940/Precision2018-3.png

现在他们在哪里相交?好吧,如果那些小点相距0.1米,我们可以猜测并说它是x = 0.41m,y = 0.59m。

 

但是如果我们放大直到0.01m的点,我们发现交叉点仍然没有落在特定的网格点上呢?所以我们进一步放大,直到每个网格间隔仅代表0.000000000000001m,并且交叉点仍然没有落在网格点上:

 

我们可以无限制地做这个动作,但在某些时候你必须接受四舍五入的结果。在计算上,FME以二进制和舍入方式工作到64位。这非常精确(相比之下,它的十进制大约是17位数),一般来说高精度是一件好事。那是因为舍入坐标会略微移动交点。精度越高,通过舍入移动的点越少。

 

但在某些情况下,有用(的高)精度确实存在限制。当FME返回具有氢原子精度的坐标时......我们觉得这条线已被交叉(没有双关语)。

 

所以这两个问题就是为什么我们在2018年实施了一些变化。我们将看看这些变化,但首先让我们看一个出问题的例子,并纠正一些我自己的错误观念......

 

https://cdn.blog.safe.com/wp-content/uploads/2013/09/EvangelistBanner7.png

 

容差和无知

过去,如果您遇到需要容差或精度问题,我建议使用两种解决方案中的一种。我会说要么使用CoordinateRounder来截断(四舍五入)坐标,要么使用Snapper来闭合小间隙。这很简单,而且很有效。至少,它适用于简单的场景。

 

我很天真,因为我不明白问题究竟是什么。这只是截断坐标的问题,对吧?它能有多难?!好吧,让我们举一个例子(点击下载工作区)----在多条线相交的地方:

 

https://cdn.blog.safe.com/wp-content/uploads/2018/08/07130532/Precision2018-6.png

 

这里有十根线,每根线比前一根多旋转10度。在没有容差的情况下通过Intersector运行它,结果是什么?理想情况下它应该只有20个要素,但事实上我们得到584个!这些要素中的大多数都非常小,即使放大到Data Inspector的最大范围也不会显示它们。

 

到底发生了?好吧,两条线相交,它们的交点 - 不完全符合网格分辨率 - 是圆形的。然后另一条线相交。它也不太适合分辨率并且是圆形的,但它被四舍五入到几纳米之外的不同网格点。这个过程继续,而且,每次添加一个节点时,必须重新检查该线,以查看这条不再完美的直线是否会引起另一个交叉点; 如果是这样,再次添加另一个新计算的节点!

 

最后,在数据的中心,在完成所有的交叉点的截断(在某小数位之后进行四舍五入)之后,我们得到了这个:

 

https://cdn.blog.safe.com/wp-content/uploads/2018/08/07132647/Precision2018-7.png

 

问题在于,不将数据截断到容差,多个交叉点计算累积了错误。

 

584个要素中的大多数都是交叉点交叉出的微小多边形。我甚至可以对它们运行一个LengthCalculator来查找它们的大小。其中一个随机挑选的是6.206335383118183×10 -17米!由于1×10 -12是万亿分之一米,而最小的原子只有30万亿分之一,你可以看到对于你的平均空间数据来说精度水平有“点”过分!

 

这就是当我们不采取任何措施来防止64位计算出现问题时会发生什么。现在让我们来看看处理这些问题的技巧......

 

https://cdn.blog.safe.com/wp-content/uploads/2013/09/EvangelistBanner7.png

 

容差与启示

在我们的首席科学家Kevin Wiebe的演讲中,我发现有许多不同的解决方案,不同的产品各自使用不同的方法。顺便提一下,如果我提到一种技术的缺点,不要把它当作对这些产品的批评。他们的开发人员无疑比我更了解这个主题,并且会以特殊的方式实现一种技术以满足他们的需求。我只是强调我们自己的决定背后的原因。

 

无论如何,解决几何计算中的许多问题的关键是迭代。实际上,迭代,迭代和更多迭代!

 

捕捉截断

捕捉截断 - 就像名字所表示的那样 - 几乎就是我试图用转换器实现的方法。您将数据截断(四舍五入)到最近的网格点,对其执行处理,然后将结果捕捉到网格。它可以工作,但最后的捕捉可以导致新的交叉点清理:

 

https://cdn.blog.safe.com/wp-content/uploads/2018/08/28185446/Precision2018-20.png

 

 

这里,例如,A处的交点与最近的网格点对齐; 但这样做会移动线并在B处创建一个新的交叉点。

 

修复新的交叉点是通过迭代整个过程直到没有更多的交叉点来完成的:这被称作迭代的捕捉截断(四舍五入)

 

总的来说,它既快速又简单,但也存在一些缺点。首先,这将调整所有数据,而不仅仅是需要调整的部分,其次,可以将坐标移离其原始位置。这些都可以(理论上)导致拓扑破坏或崩溃的问题; 而且技术上来说,对弧线不起作用。

 

如果您想了解更多信息,请参阅学术论文CGAL文档中的简单描述以及GitHub上的实际代码。

 

打破/聚类

打破/聚类是一种更复杂的解决方案。虽然捕捉截断可以单独处理要素,但是打破/聚类会将数据集作为一个整体来看待,以确定如何处理它。通常是使用由软件计算的容差值来执行打破和聚类。

 

按照我的理解,打破执行交叉并将这些点捕捉到网格上。然后聚类获取要素顶点并将它们组合在这些交叉点之一上。通过这种方式,您可以避免平面交叉引起的微三角形。

 

例如,这里需要交叉的三条线(A,B,C)。让我们尝试通过捕捉来解决这个问题:

 

https://cdn.blog.safe.com/wp-content/uploads/2018/08/28185549/Precision2018-21.png

在第一个图中是三条相交的线。请注意,它们实际上并未在网格点处相遇。在中间的图中,A和B相交,它们的交点与网格对齐。

 

在最后的图中,B和C相交。这会导致线C略微移动,因此A和C的交点会捕捉到新的网格点。结果是三角形重叠变得更大并且实际上表现为顶点。那是因为每个交叉点都是分开处理的,而不是一起处理的。由于多条线需要多个交叉点,这里很容易看出三角形和其他奇怪的形状是如何被创建的。

 

然而,对于打破/聚类 - 数据集作为一个整体进行评估 - 结果将更像是这样:

https://cdn.blog.safe.com/wp-content/uploads/2018/08/28185622/Precision2018-22.png

 

它不一定是B/C实际相交的最近网格点,但它是一个更明智的解决方案; 并且提供的网格间隔非常小,不会影响输出的质量。

 

因为顶点移动,所以该过程重复(迭代)直到满足一组预定义的条件。

 

如果您想了解更多相关信息,请参见Esri就此主题发表一份白皮书

 

FME方法

在Safe,我们研究创建自己的方法,看看我们是否可以改善结果。我们将解决方案称为锚定顶点调整。

 

锚定顶点调整的基础是锚定到要素周围已存在的点上,而不一定是网格点。这样,如果没有任何变化,要素受影响较小,我们尽可能少地移动数据。这也意味着网络或覆盖范围内的要素更有可能被连接到拓扑上重要的位置上。

 

该技术不是两步过程; 相反,我们调整所有交叉直接为一步。使用该方法,上面的示例很好地展示了20个在相同坐标处相交的要素:

 

https://cdn.blog.safe.com/wp-content/uploads/2018/08/08121832/Precision2018-11.png

 

让我们看看FME中用户是如何完成的......

 

https://cdn.blog.safe.com/wp-content/uploads/2013/09/EvangelistBanner7.png

 

FME的实际应用

首先让我们通过精确度和容差来澄清我的意思。坐标精度通常是用于表示单位的一小部分的有效位数; 例如12345.6789引用一个分数为四(4)位精度,并且比12345.67更精确。

 

容差更能衡量准确性。如果容差为0.01米,则表示每个坐标仅精确到1厘米。例如,这可能是我的调查设备的限制。

 

容差通常控制或限制精度。这是因为当我知道它仅精确到2位小数时,将坐标引用到4位小数是毫无意义的。

 

说到FME,重要的是:FME(除了少数例外)从未应用过容差,并且总是给你尽可能多的精度。

 

在某些情况下,缺乏容差(和最大精度)是有帮助的; 其他情况下,应用容差设置来限制精度,从而返回更好的结果。

 

这就是我们在许多转换器中创建容差参数的原因,以便您选择应用哪个转换器。在Intersector变换器中,它看起来像这样:

 

 

NONE(无)意味着FME像以前一样工作。没有容差,FME计算坐标以达到最大精度。FME不会尝试解决所讨论的两个问题(以64位存储小数,以及空间网格和精度)。

 

Automatic(自动)是一种模式,FME使用其人工智能来选择最适合数据的容差。

 

此设置允许FME选择更多有用的坐标位置,这些位置位于容差范围内,可防止因使用过多精度而导致的问题。容差将非常非常小,并且不会以任何视觉上显著的方式调整您的数据。请注意,它不会修复源数据的问题(稍后会详细介绍)。

 

实例

例如,让我们用一个工作空间(点击下载)来处理温哥华的“视锥”。视锥是一块具有规划限制的土地区域,以免破坏特定的景观:

 

https://cdn.blog.safe.com/wp-content/uploads/2018/08/16091717/Precision2018-14.png

 

因为温哥华是一个如此美丽的城市,北面有山脉,所以有许多视锥指向这个方向:

 

https://cdn.blog.safe.com/wp-content/uploads/2018/08/16091836/Precision2018-15.png

 

如果我想用覆盖视锥的数量来划分城市中的土地,我可能会使用AreaOnAreaOverlayer:

 

https://cdn.blog.safe.com/wp-content/uploads/2018/08/16092127/Precision2018-16.png

有趣的是,没有容差,我得到了621个重叠区域。使用自动容差我只得到538.为什么?

 

如果我通过AreaCalculator运行零容差结果,因为严格坚持64位算术,看到的是复杂的数据,导致一组多边形只是平方米的无穷小部分:

 

https://cdn.blog.safe.com/wp-content/uploads/2018/08/16092601/Precision2018-17.png

 

然而,凭借自动容差,FME发挥其神奇作用,并在其锚定顶点调整方法中使用非常小的容差值,以避免这些荒谬的微小结果。

 

容差有多小?好吧,我可以在日志文件中看到:

 

AreaOnAreaOverlayer_2(OverlayFactory):覆盖自动容差为1.0923954585830338e-8

 

 

 

现在我知道容差是什么。我也知道计算不会创建任何数学引起的假象,或者以破坏拓扑的方式移动我的数据。

 

何时使用自动容差

通常,如果可以使用自动容差,则应尽量使用它。如果转换器有可用的容差参数,那么这是一个潜在有用的方案。如果没有容差参数,那么这不是容差有用的场景。因此,当我注意到Intersector变换器具有容差参数,但PointOnAreaOverlayer没有时,我理解这是为什么。限制精度在交叉点中很重要,但对于“点在多边形上(Point-In-Polygon)”的测试无关紧要。

 

此外,无论如何,有时FME忽略了容忍度。Clipper变换器有一个容差参数,但让我们想象一下所有Clippees都是点要素的场景:

 

https://cdn.blog.safe.com/wp-content/uploads/2018/08/08094021/Precision2018-9.png

 

即使您设置Tolerance = Automatic,它也只是一个Point-In-Polygon操作,因此FME忽略了容差。

 

但是,如果Clippees是面要素:

https://cdn.blog.safe.com/wp-content/uploads/2018/08/08094317/Precision2018-10.png

 

...然后适用容差(如果设置)。那是因为它是一个交叉操作,在这种情况下容差很有用。

 

简而言之,自动化是前进的方向,并将成为FME 2019中的默认选项。只有当您希望数据维持以前的FME行为时,才使用None,精确到原子水平!

 

自定义价值

我还没有涉及的选项是Custom Value。这意味着您可以输入自己的容差选择。

 

自定义容差的一个用途是调整FME生成的自动参数。例如,即使在自动模式下,视锥覆盖也会导致一些非常小的多边形:

 

https://cdn.blog.safe.com/wp-content/uploads/2018/08/16093307/Precision2018-18.png

如果我想尝试解决这些问题,我该怎么办?好吧,我可以采取原始的容差(1.0923954585830338e-8),并增加一点,看看是否有帮助。我试验了一下,发现这个新的容差(1.0923954585830338e-5)......

 

https://cdn.blog.safe.com/wp-content/uploads/2018/08/16093713/Precision2018-19.png

 

...将多边形进一步减少到533(而不是538)。基本上它摆脱了五个最小的多边形,如果我愿意,我可以进一步增加容差。

 

但手动容差的另一个用途是纠正数据本身的问题......

 

自定义容差数据清理

例如,如果由于数字化不好视锥不能正确对齐,那么我可以在这里设置一个容差来强制它们连在一起。这样有效果吗?嗯,是的。锚定顶点调整可修复错误并维护拓扑结构,以及大规模数据问题,如同在算术级别的微观层面那样。

 

我们以这个道路网为例:

 

 

在左图中,我们将源数据相交而没有容差。非常小的间隙和较大的间隙都保持不对齐。

 

在中间的图中,让图形用自动容差相交。FME修复了非常微小的间隙,捕捉到一个新的顶点,以便让该线正确相交。

 

在右图中,设置1米的手动容差让图形相交,并且对于具有相当合理容差的道路网络。锚定顶点调整表示现有点比创建新顶点更好(因为它不需要更改南北线),因此在容差范围内捕捉到现有顶点。

 

因此,通过设置手动容差参数,我们可以看到通过更大规模清理数据。一个潜在的缺点是,移动的道路现在不再处于直接的东西方向(尽管我夸大了图像的效果)。因此,FME以较小的美学成本对数据进行了最少的改变。这样的改变在微观层面很好,因为你永远无法放大到足以看到它;但是如果手动容差很大,就需要认真考虑了。

 

简而言之,自定义容差既可用于调整和改进FME的自动容差,也可用于修复总数据错误。

 

https://cdn.blog.safe.com/wp-content/uploads/2013/09/EvangelistBanner7.png

 

常见问题

让我试着预测你可能会有什么问题:

 

问:所有几何相关的转换器都有这个新的容差参数吗?

答:否。有些可能会在将来获得,但其他的可能永远不需要容差参数,因为它们的功能不会通过使用容差来改善。

 

问:你提到迭代。我应该将转换器放在一个循环中来迭代过程直到它是正确的吗?

答:否。所有需要的迭代都内置在功能中。如果将Tolerance设置为automatic,则会生成干净的数据,而无需重复任何操作。

 

问:现在自动功能完成了吗?它总能产生相同的结果吗?

答:是的,它是完整的,应该使用。然而,随着我们了解更多,我们将调整我们的算法以产生更好的结果。

 

问:坐标系对此过程有影响吗?

答:否。坐标系没有效果。FME像在普通网格上一样进行计算。因此,如果您输入自定义容差,请务必牢记单位:以米为单位的1.xe-5容差显然与十进制度的相同容差大不相同。

 

问:自动模式是否真的可以对这样的数字进行舍入?它不会搞砸我的数据吗?

答:是(没关系),没有(它不会弄乱你的数据)。为什么?请记住,准确度(“我的GPS精确到1厘米”)和精度(“我的坐标精确到7位小数”)之间存在差异。自动模式仅以高于您的数据准确度的精度移动项目。除非您的空间数据是使用电子显微镜实际创建的,并且具有皮米级精度,否则我们所做的任何事情都不会减少输入值。此外,除非有明显的好处,否则我们根本不会移动数据; 并且如果在容差范围内,我们的锚顶点方法意味着我们将它移动到现有的输入顶点。

 

稍微扩展最后一点可以是一个很好的笑话。想象一下博物馆导游告诉游客恐龙骨骼是100,000,003年零6个月。因为有人告诉他,在他3年零6个月前开始在那里工作时,它已有1亿年了!这也太搞了吧。但现在想象一台计算机告诉你计算出的坐标是100.0000035米。这是同一件事。舍入任一数字都不是问题,因为我们知道它在计算的准确性范围内。

 

https://cdn.blog.safe.com/wp-content/uploads/2013/09/EvangelistBanner7.png

 

总结

https://cdn.blog.safe.com/wp-content/uploads/2018/08/31080730/Precision2018-BottomImage.png总而言之,FME总是以最纯粹的形式返回几何计算的结果,以避免人为改变坐标。我们向用户返回了他们的计算机数学芯片告诉我们的正确结果。

 

然而,计算机对计算的含义一无所知,我们有责任改进其逻辑以改善我们的结果。这就是FME新的自动容差选项。它可以识别何时在数学误差范围内重新解释计算机告诉我们的内容,以避免空间数据中的奇怪现象。

 

这种新模式将FME的行为与其他空间数据软件更紧密地看齐,其他空间数据软件默认情况下已经使用了类似的技术。但是这种模式在FME中是可选的。您可以选择是否应用自动容差(如其他软件),关闭容差以支持最大精度(以可能的计算问题为代价),或输入您自己的自定义容差值。

 

这就是我写这篇文章的原因。我们希望我们的用户知道我们已做出改变,但我们也想让您放心。FME的计算结果可能会产生与以前略有不同的结果,但结果却很好。事实上,很长一段时间以来我一直在要求这种改变,因为纯粹的计算给我带来了很多问题。

 

在FME 2018中,我的地理空间数据可能不再精确到最近的氢原子,但它更清洁,没有数学异常,更适合我能想象的任何可能的用途。

 

有一句非常有名的说法是“宽容不是软弱的表现,而是力量的象征”。我想这同样适用于FME!

 

https://cdn.blog.safe.com/wp-content/uploads/2013/09/NewBlogSignature.png

 

PS:我想向Safe的几何团队发出呼喊,他们创建了这个功能,然后花了几个小时向我解释并提供反馈。他们非常容忍我的不准确(双关语绝对是预期的)。你摇滚吧!

 

 

猜你喜欢

转载自blog.csdn.net/fmechina/article/details/82982870