server-side-google-maps 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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