2012-11-30 18 views
5

rgeo-activerecord 0.4.5 taşına sahip PostGIS 1.5 veritabanına bağlanan r4o 0.3.19 proj4 desteğine sahip bir ray uygulamasına sahibim.RGeo Öngörülen Tampon Çokgen çok küçük

Uygulamamın coğrafi nokta, yarıçap ve çokgen şekli içeren Bölge adlı bir modeli var. Yeni bir bölge kaydetmek üzereyken, yarıçapı ve coğrafi noktayı kullanarak bir poligon oluşturmak için bölgenin geofactory's buffer işlevini kullanır. İşte

bölge modeli için kullanılıyor geofactory olan

GEOFACTORY = RGeo::Geographic.projected_factory(:buffer_resolution => 8, :projection_proj4 => '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m [email protected] +wktext +no_defs', :projection_srid => 3857) 

kullanıyorum projection_srid Apple ve Google Mercator projeksiyonu 3857. eşler arasında sorun olduğunu olduğunu oluşturuluyor tampon elma haritalarında veya google haritalarında çizdiğim ile aynı boyutta değil. Kullandığım Örneğin, MapKit fonksiyonu MKCircle

[MKCircle circleWithCenterCoordinate:self.coordinate radius:50]; 

daire çizin ve böyle kaplayacaktır inşa. iOS Drawing Radius

Ancak oluşturulan koordinatları alırsam, veritabanındaki çokgen şeklini oluşturan arabellek işlevini oluşturur ve bunları Google haritalarında çizerim. Gördüğünüz gibi

GoogleMaps Radius

, aynı projeksiyon sistemi kullanılarak oluşturulan poligon olması gerekenden daha küçüktür. Bu problem, tanımlanmış yarıçapın boyutuna bağlı olarak kontrol dışına büyür. Ben de aynı sonuçları veren RGeo'da tanımlandığı gibi simple_mercator fabrikasını kullanmaya çalıştım.

Umarız birisinin, bir boylam, enlemin yansıtıldığı noktanın arabelleğe alındığı zaman, yanlış boyutta bir çokgenin neden oluştuğuna dair bir içgörüsü vardır.

cevap

9

Burada gözlemlediğiniz şey, Mercator distorsiyonudur. Bir mercator projeksiyonunda "50" lik bir mesafe, Equator'da olmadığınız sürece gerçek gezegen yüzeyinde 50 metreye karşılık gelmez.

iOS haritanız tarafından çizilen daire doğrudur: bu, 50 metrelik yarıçaptır. İkinci resminizi yarattığınızdan şüphelendiğim şey, noktayı bir Mercator projeksiyonuna yansıtmaktı (sağladığınız Proj4'e göre). Sonra, yansıtılan koordinat sisteminde yarıçapı 50 olan bir arabellek oluşturmaya devam ettiniz. Bununla birlikte, enlem 40.61'deki 50 Mercator birimi, dünya mesafesinin yüzeyinde sadece yaklaşık 37.96 metreye karşılık gelir. Bu poligonu enlem ve boylamlara geri yansıtıp çizdiğinizde, gördüğünüz şey bu: 38 metrelik bir daire.

Bunu görselleştirmenin bir yolu, Google Haritalar'daki tüm dünya haritasına bakmaktır. Ekvatorda yarıçap 50 piksellik bir daire çizin. Daha sonra Grönland'ın üzerinde 50 piksellik başka bir daire çizin. Haritada (Mercator koordinatlarında), bu daireler aynı boyuttadır. Fakat, eğer Mercator projeksiyonunuzu biliyorsanız, Grönland'ı çarpıttığını biliyorsunuz çünkü Grönland ekvatordan çok uzaktadır, bu yüzden Grönland üzerindeki daireniz aslında ekvatorun üzerindeki dairenizden çok daha küçüktür. 40 derece enlemde, çarpıklık şiddetli değil, ama hala var.

Bunu düzeltmek isterseniz, oldukça kolaydır. Mercator projeksiyonunun neden olduğu boyut bozulması, enlemin sekantı ile orantılıdır. Yani, ekvatordaki 50 mercator birimi 50 metreye eşittir, ancak enlem x (radyan cinsinden) 50 mercator birimi 50/sn (x) metrelere karşılık gelir. Yani, 50 metrelik bir yarıçap istiyorsanız, 50 ms (enlem) ile çarpın ve bu sayıyı mercator koordinatlarında yarıçap olarak kullanın.RGeo-konuş:

p_lonlat = GEOFACTORY.point(40.610355377197266, -75.38220214843749) 
p_proj = p_lonlat.projection 
buf_proj = p_proj.buffer(50.0 * (1/Math.cos(p_lonlat.y/180.0 * Math::PI))) 
buf_lonlat = GEOFACTORY.unproject(buf_proj) 
+0

Düzenleme için teşekkürler, MobileOverlord. Ruby'de bir sekreter fonksiyonu olmadığını unuttum. İlk önce test etmeden kod yayınladığım şey bu ... :-) –

İlgili konular