Module: GeoFaker
- Defined in:
- lib/geo_faker.rb,
lib/geo_faker/point.rb,
lib/geo_faker/version.rb,
lib/geo_faker/geo_transform.rb
Defined Under Namespace
Classes: GeoTransform, Point
Constant Summary
collapse
- BASE_URL =
'https://nominatim.openstreetmap.org/search'
- VERSION =
"0.1.0"
- @@geo_data =
{}
Class Method Summary
collapse
Class Method Details
.around(query, radius_in_km:) ⇒ Object
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
# File 'lib/geo_faker.rb', line 36
def self.around(query, radius_in_km:)
data = geo_data(query)
lat = data['lat'].to_f
lon = data['lon'].to_f
angle = 2 * Math::PI * rand()
distance = nil
loop do
distance = radius_in_km * gaussian_rand()
break if distance.abs < 3 * radius_in_km
end
delta_lat = GeoTransform.km_to_degree_lat(distance * Math.cos(angle))
delta_lon = GeoTransform.km_to_degree_lon(distance * Math.sin(angle), lat)
Point.new(
lat: lat + delta_lat,
lon: lon + delta_lon,
)
end
|
.gaussian_rand ⇒ Object
57
58
59
60
61
62
63
|
# File 'lib/geo_faker.rb', line 57
def self.gaussian_rand
theta = 2 * Math::PI * rand
rho = Math.sqrt(-2 * Math.log(1 - rand))
x = rho * Math.cos(theta)
x
end
|
.geo_data(query, with_polygon: false) ⇒ Object
13
14
15
16
17
18
19
|
# File 'lib/geo_faker.rb', line 13
def self.geo_data(query, with_polygon: false)
@@geo_data[query] ||= load_geo_data(query, with_polygon: with_polygon)
if with_polygon && !@@geo_data[query].key?('geojson')
@@geo_data[query] = load_geo_data(query, with_polygon: with_polygon)
end
@@geo_data[query]
end
|
.load_geo_data(query, with_polygon: false) ⇒ Object
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
# File 'lib/geo_faker.rb', line 21
def self.load_geo_data(query, with_polygon: false)
response = RestClient.get(BASE_URL, params: {
q: query,
format: 'json',
limit: 1,
polygon_geojson: with_polygon ? '1' : '0',
})
raise "API error: #{response.code}" unless response.code == 200
data = JSON.parse(response.body)
raise "No matching result." if data.empty?
data.first
end
|
.point_in_poly(poly, point) ⇒ Object
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
# File 'lib/geo_faker.rb', line 103
def self.point_in_poly(poly, point)
last_point = poly[-1]
oddNodes = false
y = point.lon
x = point.lat
poly.each do |p|
yi = p[0]
xi = p[1]
yj = last_point[0]
xj = last_point[1]
if yi < y && yj >= y ||
yj < y && yi >= y
oddNodes = !oddNodes if xi + (y - yi) / (yj - yi) * (xj - xi) < x
end
last_point = p
end
oddNodes
end
|
.within(query) ⇒ Object
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
# File 'lib/geo_faker.rb', line 80
def self.within(query)
data = geo_data(query, with_polygon: true)
bounds = data['boundingbox'].map(&:to_f)
south = bounds[0]
north = bounds[1]
west = bounds[2]
east = bounds[3]
geojson = data['geojson']
raise 'geojson is not Polygon' unless geojson['type'] == 'Polygon'
outer_poly = geojson['coordinates'][0]
loop do
point = Point.new(
lat: rand(south..north),
lon: rand(west..east),
)
return point if point_in_poly(outer_poly, point)
end
end
|
.within_bounds(query) ⇒ Object
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
# File 'lib/geo_faker.rb', line 65
def self.within_bounds(query)
data = geo_data(query)
bounds = data['boundingbox'].map(&:to_f)
south = bounds[0]
north = bounds[1]
west = bounds[2]
east = bounds[3]
Point.new(
lat: rand(south..north),
lon: rand(west..east),
)
end
|