1. 程式人生 > >FME 2018 無限精度的戰爭:自動容差如何在沒有捕捉的情況下擊敗無限精度 – 但是具有錨定頂點

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的幾何團隊發出呼喊,他們建立了這個功能,然後花了幾個小時向我解釋並提供反饋。他們非常容忍我的不準確(雙關語絕對是預期的)。你搖滾吧!