server-side-google-maps 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -77,8 +77,37 @@ module ServerSideGoogleMaps
77
77
  ret << create_interpolated_point(points[-1], points[-1], 0.0, :distance_along_path => points[-1].distance_along_path)
78
78
  end
79
79
 
80
+ def simplify(latlng_error2)
81
+ simplified_points = douglas_peucker_step(points, latlng_error2)
82
+ Path.new(simplified_points)
83
+ end
84
+
80
85
  private
81
86
 
87
+ def douglas_peucker_step(points, latlng_error2)
88
+ simple_points = [ points.first, points.last ]
89
+ max_i = 0
90
+ max_d = 0
91
+
92
+ points.each_with_index do |point, i|
93
+ next if i == 0 || i == points.length - 1
94
+ d = point.latlng_distance_squared_from_segment(points.first, points.last)
95
+ if d > max_d
96
+ max_d = d
97
+ max_i = i
98
+ end
99
+ end
100
+
101
+ if max_d > latlng_error2
102
+ simple1 = douglas_peucker_step(points[0..max_i], latlng_error2)
103
+ simple2 = douglas_peucker_step(points[max_i..-1], latlng_error2)
104
+ simple1.pop
105
+ return simple1.concat(simple2)
106
+ else
107
+ return simple_points
108
+ end
109
+ end
110
+
82
111
  def create_interpolated_point(point_before, point_after, fraction_after, options = {})
83
112
  fraction_before = 1.0 - fraction_after
84
113
 
@@ -45,5 +45,32 @@ module ServerSideGoogleMaps
45
45
  longitude_difference = longitude - other.longitude
46
46
  latitude_difference * latitude_difference + longitude_difference * longitude_difference
47
47
  end
48
+
49
+ def latlng_distance_squared_from_segment(p1, p2)
50
+ vx = p1.latitude - latitude
51
+ vy = p1.longitude - longitude
52
+
53
+ return vx*vx + vy*vy if p1 == p2
54
+
55
+ ux = p2.latitude - p1.latitude
56
+ uy = p2.longitude - p1.longitude
57
+ length2 = ux*ux + uy*uy
58
+
59
+ det = (-vx*ux) + (-vy*uy)
60
+
61
+ if det < 0 || det > length2
62
+ # We're outside the line segment
63
+ wx = p2.latitude - latitude
64
+ wy = p2.longitude - longitude
65
+
66
+ d1 = vx*vx + vy*vy
67
+ d2 = wx*wx + wy*wy
68
+ return d1 < d2 ? d1 : d2
69
+ end
70
+
71
+ det = ux*vy - uy*vx
72
+
73
+ return det * det / length2
74
+ end
48
75
  end
49
76
  end
@@ -1,3 +1,3 @@
1
1
  module ServerSideGoogleMaps
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
data/spec/path_spec.rb CHANGED
@@ -116,5 +116,61 @@ module ServerSideGoogleMaps
116
116
  interpolated[4].elevation.should == 50
117
117
  end
118
118
  end
119
+
120
+ describe('#simplify') do
121
+ it('should remove duplicate points') do
122
+ p1 = Point.new(1.0, 2.0)
123
+ p2 = Point.new(7.0, 2.0)
124
+ p2_2 = Point.new(7.0, 2.0)
125
+ p3 = Point.new(7.0, 1.0)
126
+
127
+ path = Path.new([p1, p2, p2_2, p3])
128
+ simplified = path.simplify(0.00001)
129
+ simplified.points.length.should == 3
130
+ simplified.points[0].should == p1
131
+ simplified.points[1].should == p2
132
+ simplified.points[2].should == p3
133
+ end
134
+
135
+ it('should remove useless points') do
136
+ p1 = Point.new(1.0, 2.0)
137
+ p2 = Point.new(6.0, 1.23)
138
+ p3 = Point.new(7.0, 1.0)
139
+
140
+ path = Path.new([p1, p2, p3])
141
+ simplified = path.simplify(0.005)
142
+ simplified.points.length.should == 2
143
+ simplified.points[0].should == p1
144
+ simplified.points[1].should == p3
145
+ end
146
+
147
+ it('should retain useful points') do
148
+ p1 = Point.new(1.0, 2.0)
149
+ p2 = Point.new(6.0, 1.23)
150
+ p3 = Point.new(7.0, 1.0)
151
+
152
+ path = Path.new([p1, p2, p3])
153
+ simplified = path.simplify(0.0005)
154
+ simplified.points.length.should == 3
155
+ simplified.points[0].should == p1
156
+ simplified.points[1].should == p2
157
+ end
158
+
159
+ it('should retain :distance_along_path, :elevation, :object') do
160
+ p1 = Point.new(1.0, 2.0, :distance_along_path => 0, :elevation => 0, :object => 0)
161
+ p2 = Point.new(6.0, 1.23, :distance_along_path => 1, :elevation => 1, :object => 1)
162
+ p3 = Point.new(7.0, 1.0, :distance_along_path => 2, :elevation => 2, :object => 2)
163
+
164
+ path = Path.new([p1, p2, p3])
165
+ simplified = path.simplify(0.005)
166
+ simplified.points.length.should == 2
167
+ simplified.points[0].object.should == p1.object
168
+ simplified.points[0].distance_along_path.should == p1.distance_along_path
169
+ simplified.points[0].elevation.should == p1.elevation
170
+ simplified.points[1].object.should == p3.object
171
+ simplified.points[1].distance_along_path.should == p3.distance_along_path
172
+ simplified.points[1].elevation.should == p3.elevation
173
+ end
174
+ end
119
175
  end
120
176
  end
data/spec/point_spec.rb CHANGED
@@ -39,6 +39,29 @@ module ServerSideGoogleMaps
39
39
  end
40
40
  end
41
41
 
42
+ describe('#latlng_distance_squared_from_segment') do
43
+ it('should catch when point is outside segment edges') do
44
+ # p1 ------------*---------
45
+ # p2 --*------------------- <- this point is farther than it'd be if the
46
+ # p3 -------------------*-- line segment were an infinite line
47
+ p1 = Point.new(1.0, 7.0)
48
+ p2 = Point.new(-1.0, 9.1)
49
+ p3 = Point.new(7.0, 1.0)
50
+
51
+ distance2 = p2.latlng_distance_squared_from_segment(p1, p3)
52
+ distance2.should == p2.latlng_distance_squared(p1)
53
+ end
54
+
55
+ it('should work when segment is a singularity') do
56
+ p1 = Point.new(1.0, 7.0)
57
+ p2 = Point.new(-1.0, 9.1)
58
+ p3 = Point.new(1.0, 7.0)
59
+
60
+ distance2 = p2.latlng_distance_squared_from_segment(p1, p3)
61
+ distance2.should == p2.latlng_distance_squared(p1)
62
+ end
63
+ end
64
+
42
65
  describe('#distance') do
43
66
  it('should calculate the distance') do
44
67
  point1 = Point.new(1.0, 4.0)
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: server-side-google-maps
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 31
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 1
10
- version: 0.1.1
9
+ - 2
10
+ version: 0.1.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Adam Hooper