Uses https://github.com/tsnow/ruby-geometry
For: https://github.com/ridecharge/rc/pull/779
INSTALL: gem 'ruby-geometry', :git => 'https://github.com/tsnow/ruby-geometry.git'
BB=RGeo::Cartesian::BoundingBox.create_from_geometry(Zone.last.area);
def BB.each_square(step)
(BB.min_y .. BB.max_y).step(step){|y|
(BB.min_x .. BB.max_x).step(step){|x|
yield x, y
}
}
end
def test(resolution = 0.0001) # 10-meter resolution == 13k test points
loads = []
inmems = []
marshals = []
geoms = []
a = Zone.select('area as a').last.a
Benchmark.bm do |x|
x.report('rgeo-inmem') {
@zone_last ||= Zone.last.reload;
BB.each_square(resolution) do |x,y|
inmems.push @zone_last.contains?(RGEO_FACTORY.point(x,y))
end
}
x.report('ruby-geometry') {
BB.each_square(resolution) do |x,y|
geoms.push ZonePointInPolygon.mysql_wkb_contains?(a,Point(x,y))
end
}
x.report('rgeo-marshal') {
@zone_marshal ||= Marshal.dump(Zone.last);
BB.each_square(resolution) do |x,y|
marshals.push Marshal.load(@zone_marshal).contains?(RGEO_FACTORY.point(x,y))
end
}
x.report('rgeo-load') {
BB.each_square(resolution) do |x,y|
loads.push Zone.last.reload.contains?(RGEO_FACTORY.point(x,y))
end
}
end
lc = loads.group_by{|i| i}.map{|a,b| [a,b.length]}
ic = inmems.group_by{|i| i}.map{|a,b| [a,b.length]}
mc = marshals.group_by{|i| i}.map{|a,b| [a,b.length]}
gc = geoms.group_by{|i| i}.map{|a,b| [a,b.length]}
[loads == inmems, inmems == marshals, marshals == geoms, lc,ic,mc,gc]
end
=> [true, true, true]
count=0; BB.each_square(0.1){ count+= 1}; count
=> 1
count=0; BB.each_square(0.01){ count+= 1}; count
=> 21
count=0; BB.each_square(0.001){ count+= 1}; count
=> 1403
count=0; BB.each_square(0.0001){ count+= 1}; count
=> 136278
count=0; BB.each_square(0.00001){ count+= 1}; count
=> 13599168
1.9.3-p545 :153 > test(0.01)
user system total real
rgeo-inmem 0.150000 0.010000 0.160000 ( 0.164758)
ruby-geometry 0.010000 0.000000 0.010000 ( 0.013450)
rgeo-marshal 0.970000 0.000000 0.970000 ( 0.979673)
rgeo-load 1.130000 0.010000 1.140000 ( 1.141370)
=> [true, true, true, [[false, 11], [true, 10]], [[false, 11], [true, 10]], [[false, 11], [true, 10]], [[false, 11], [true, 10]]]
The ruby-geometry point-in-polygon is 27x faster than rgeo geos-ffi with loading, and 25x slower than rgeo geos-ffi once geos-ffi has loaded the geometry.
(for 10000 tests) # done seperately, using the same point for each test
user system total real
rgeo-load 53.530000 0.280000 53.810000 ( 54.276759)
rgeo-inmem 0.070000 0.000000 0.070000 ( 0.080444)
rgeo-marshal 49.150000 0.110000 49.260000 ( 49.267587)
ruby-geometry 1.790000 0.000000 1.790000 ( 1.787872)
1.9.3-p545 :184 > 1.79 / 0.07
=> 25.57142857142857
1.9.3-p545 :185 > 49.0 / 1.79
=> 27.37430167597765
1.9.3-p545 :154 > test(0.001)
user system total real
rgeo-inmem 0.110000 0.000000 0.110000 ( 0.113264)
ruby-geometry 1.090000 0.010000 1.100000 ( 1.094457)
rgeo-marshal 70.730000 0.220000 70.950000 ( 71.048172)
rgeo-load 75.940000 0.430000 76.370000 ( 77.029119)
=> [true, true, true, [[false, 432], [true, 971]], [[false, 432], [true, 971]], [[false, 432], [true, 971]], [[false, 432], [true, 971]]]
1.9.3-p545 :155 > test(0.0001)
user system total real
rgeo-inmem 15.150000 0.030000 15.180000 ( 15.200548)
ruby-geometry 100.740000 0.200000 100.940000 (101.170947)