ym4r 0.4.1 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,28 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'ym4r/google_maps/geocoding'
4
+ require 'test/unit'
5
+
6
+ include Ym4r::GoogleMaps
7
+
8
+ class TestGmGeocoding< Test::Unit::TestCase
9
+ def test_google_maps_geocoding
10
+ placemarks = Ym4r::GoogleMaps::Geocoding.get("Rue Clovis Paris")
11
+ assert_equal(Ym4r::GoogleMaps::Geocoding::GEO_SUCCESS,placemarks.status)
12
+ assert_equal(1,placemarks.length)
13
+ placemark = placemarks[0]
14
+ assert_equal("FR",placemark.country_code)
15
+ assert_equal("Paris",placemark.locality)
16
+ assert_equal("75005",placemark.postal_code)
17
+ end
18
+
19
+ def test_google_maps_pakistan
20
+ placemarks = Ym4r::GoogleMaps::Geocoding.get("Lahore PK")
21
+ assert_equal(Ym4r::GoogleMaps::Geocoding::GEO_SUCCESS,placemarks.status)
22
+ assert_equal(1,placemarks.length)
23
+ placemark = placemarks[0]
24
+ assert_equal("PK",placemark.country_code)
25
+ assert_equal("Lahore",placemark.locality)
26
+ assert_equal("",placemark.thoroughfare)
27
+ end
28
+ end
data/tools/tile_image.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  $:.unshift(File.dirname(__FILE__) + '/../lib')
2
- require 'ym4r/google_maps/tiler/image_tiler'
2
+
3
+ require 'ym4r/google_maps/image_tiler'
3
4
  include Ym4r::GoogleMaps::Tiler
4
5
 
5
6
  require 'optparse'
data/tools/tile_wms.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  $:.unshift(File.dirname(__FILE__) + '/../lib')
2
- require 'ym4r/google_maps/tiler/wms_tiler'
2
+
3
+ require 'ym4r/google_maps/wms_tiler'
3
4
  include Ym4r::GoogleMaps::Tiler
4
5
 
5
6
  require 'optparse'
@@ -45,10 +46,10 @@ opts = OptionParser.new do |opts|
45
46
  opts.on("-g","--gmap-setting SETTING",WmsTiler::FurthestZoom,"Corner coordinates, furthest zoom level, tile width and height") do |fz|
46
47
  options.furthest_zoom = fz
47
48
  end
48
- opts.on("-w","--[no-]geographic","Query the WMS server with LatLon coordinates isntead of using the Mercator projection") do |g|
49
+ opts.on("-w","--[no-]geographic","Query the WMS server with LatLon coordinates instead of using the Mercator projection") do |g|
49
50
  options.geographic = g
50
51
  end
51
- opts.on("-e", "--epsg SRS","SRS to query the WMS server. Should be a the SRS id of a Simple Mercator projection. Can vary between WMS servers. Is 54004 (Simple Mercator for Mapserver) by default") do |srs|
52
+ opts.on("-e", "--epsg SRS","SRS to query the WMS server. Should be a the SRS id of a Simple Mercator projection. Can vary between WMS servers. Is 54004 (Simple Mercator for Mapserver) by default. For GeoServer use 41001.") do |srs|
52
53
  options.srs = srs
53
54
 
54
55
  end
metadata CHANGED
@@ -1,11 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.8.11
2
+ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: ym4r
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.4.1
7
- date: 2006-07-01 00:00:00 +05:00
8
- summary: Using Google Maps and Yahoo! Maps from Ruby and Rails
6
+ version: 0.5.1
7
+ date: 2006-07-09 00:00:00 +05:00
8
+ summary: Helping the use of Google Maps and Yahoo! Maps API's from Ruby and Rails
9
9
  require_paths:
10
10
  - lib
11
11
  email: guilhem.vellut+ym4r@gmail.com
@@ -25,6 +25,7 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
25
25
  platform: ruby
26
26
  signing_key:
27
27
  cert_chain:
28
+ post_install_message:
28
29
  authors:
29
30
  - Guilhem Vellut
30
31
  files:
@@ -32,41 +33,21 @@ files:
32
33
  - lib/ym4r/google_maps.rb
33
34
  - lib/ym4r/yahoo_maps.rb
34
35
  - lib/ym4r/google_maps/api_key.rb
35
- - lib/ym4r/google_maps/control.rb
36
36
  - lib/ym4r/google_maps/geocoding.rb
37
- - lib/ym4r/google_maps/helper.rb
38
- - lib/ym4r/google_maps/layer.rb
39
- - lib/ym4r/google_maps/map.rb
40
- - lib/ym4r/google_maps/mapping.rb
41
- - lib/ym4r/google_maps/overlay.rb
42
- - lib/ym4r/google_maps/point.rb
43
- - lib/ym4r/google_maps/geocoding/geocoding.rb
44
- - lib/ym4r/google_maps/tiler/image_tiler.rb
45
- - lib/ym4r/google_maps/tiler/wms_tiler.rb
37
+ - lib/ym4r/google_maps/image_tiler.rb
38
+ - lib/ym4r/google_maps/wms_tiler.rb
46
39
  - lib/ym4r/yahoo_maps/app_id.rb
47
40
  - lib/ym4r/yahoo_maps/building_block.rb
48
- - lib/ym4r/yahoo_maps/flash.rb
49
41
  - lib/ym4r/yahoo_maps/building_block/exception.rb
50
42
  - lib/ym4r/yahoo_maps/building_block/geocoding.rb
51
43
  - lib/ym4r/yahoo_maps/building_block/local_search.rb
52
44
  - lib/ym4r/yahoo_maps/building_block/map_image.rb
53
45
  - lib/ym4r/yahoo_maps/building_block/traffic.rb
54
- - lib/ym4r/yahoo_maps/flash/latlon.rb
55
- - lib/ym4r/yahoo_maps/flash/map.rb
56
- - lib/ym4r/yahoo_maps/flash/mapping.rb
57
- - lib/ym4r/yahoo_maps/flash/marker.rb
58
- - lib/ym4r/yahoo_maps/flash/overlay.rb
59
- - lib/ym4r/yahoo_maps/flash/tool.rb
60
- - lib/ym4r/yahoo_maps/flash/widget.rb
61
46
  - lib/ym4r/google_maps/config/config.yml
62
- - lib/ym4r/google_maps/javascript/clusterer.js
63
- - lib/ym4r/google_maps/javascript/geoRssOverlay.js
64
- - lib/ym4r/google_maps/javascript/markerGroup.js
65
- - lib/ym4r/google_maps/javascript/wms-gs.js
66
47
  - tools/tile_image.rb
67
48
  - tools/tile_wms.rb
68
49
  - test/test_geocoding.rb
69
- - test/test_google_maps.rb
50
+ - test/test_gm_geocoding.rb
70
51
  - test/test_local_search.rb
71
52
  - test/test_map_image.rb
72
53
  - test/test_traffic.rb
@@ -75,7 +56,7 @@ files:
75
56
  - rakefile.rb
76
57
  test_files:
77
58
  - test/test_geocoding.rb
78
- - test/test_google_maps.rb
59
+ - test/test_gm_geocoding.rb
79
60
  - test/test_local_search.rb
80
61
  - test/test_map_image.rb
81
62
  - test/test_traffic.rb
@@ -1,66 +0,0 @@
1
- require 'ym4r/google_maps/mapping'
2
-
3
- module Ym4r
4
- module GoogleMaps
5
- #Small map control. Report to the Google Maps API documentation for details.
6
- class GSmallMapControl
7
- include MappingObject
8
- def create
9
- "new GSmallMapControl()"
10
- end
11
- end
12
- #Large Map control. Report to the Google Maps API documentation for details.
13
- class GLargeMapControl
14
- include MappingObject
15
- def create
16
- "new GLargeMapControl()"
17
- end
18
- end
19
- #Small Zoom control. Report to the Google Maps API documentation for details.
20
- class GSmallZoomControl
21
- include MappingObject
22
- def create
23
- "new GSmallZoomControl()"
24
- end
25
- end
26
- #Scale control. Report to the Google Maps API documentation for details.
27
- class GScaleControl
28
- include MappingObject
29
- def create
30
- "new GScaleControl()"
31
- end
32
- end
33
- #Map type control. Report to the Google Maps API documentation for details.
34
- class GMapTypeControl
35
- include MappingObject
36
- def create
37
- "new GMapTypeControl()"
38
- end
39
- end
40
- #Overview map control. Report to the Google Maps API documentation for details.
41
- class GOverviewMapControl
42
- include MappingObject
43
- def create
44
- "new GOverviewMapControl()"
45
- end
46
- end
47
-
48
- #An object representing a position of a control.
49
- #The first argument of the constructor is one of the following : :top_right, :top_left, :bottom_right, :bottom_left.
50
- class GControlPosition < Struct.new(:anchor,:offset)
51
- include MappingObject
52
- def create
53
- js_anchor = if anchor == :top_right
54
- "G_ANCHOR_TOP_RIGHT"
55
- elsif anchor == :top_left
56
- "G_ANCHOR_TOP_LEFT"
57
- elsif anchor == :bottom_right
58
- "G_ANCHOR_BOTTOM_RIGHT"
59
- else
60
- "G_ANCHOR_BOTTOM_LEFT"
61
- end
62
- "new GControlPosition(#{js_anchor},#{offset})"
63
- end
64
- end
65
- end
66
- end
@@ -1,80 +0,0 @@
1
- require 'ym4r/google_maps/api_key'
2
- require 'open-uri'
3
- require 'rexml/document'
4
-
5
- module Ym4r
6
- module GoogleMaps
7
- module Geocoding
8
-
9
- GEO_SUCCESS = 200
10
- GEO_MISSING_ADDRESS = 601
11
- GEO_UNKNOWN_ADDRESS = 602
12
- GEO_UNAVAILABLE_ADDRESS = 603
13
- GEO_BAD_KEY = 610
14
- GEO_TOO_MANY_QUERIES = 620
15
- GEO_SERVER_ERROR = 500
16
-
17
- #Gets placemarks by querying the Google Maps Geocoding service with the +request+ string
18
- def self.get(request)
19
-
20
- url = "http://maps.google.com/maps/geo?q=#{request}&key=#{API_KEY}&output=xml"
21
- begin
22
- xml = open(URI.encode(url)).read
23
- rescue
24
- raise ConnectionException.new("Unable to connect to Google Maps Geocoding service")
25
- end
26
-
27
- doc = REXML::Document.new(xml)
28
-
29
- response = doc.elements['//Response']
30
- placemarks = Placemarks.new(response.elements['name'].text,response.elements['Status/code'].text.to_i)
31
- response.elements.each("Placemark") do |placemark|
32
- data = placemark.elements
33
- data_country = data['//CountryNameCode']
34
- data_administrative = data['//AdministrativeAreaName']
35
- data_sub_administrative = data['//SubAdministrativeAreaName']
36
- data_locality = data['//LocalityName']
37
- data_dependent_locality = data['//DependentLocalityName']
38
- data_thoroughfare = data['//ThoroughfareName']
39
- data_postal_code = data['//PostalCodeNumber']
40
- placemarks << Geocoding::Placemark.new(data['address'].text,
41
- data_country.nil? ? "" : data_country.text,
42
- data_administrative.nil? ? "" : data_administrative.text,
43
- data_sub_administrative.nil? ? "" : data_sub_administrative.text,
44
- data_locality.nil? ? "" : data_locality.text,
45
- data_dependent_locality.nil? ? "" : data_dependent_locality.text,
46
- data_thoroughfare.nil? ? "" : data_thoroughfare.text,
47
- data_postal_code.nil? ? "" : data_postal_code.text,
48
- *(data['//coordinates'].text.split(",")[0..1].collect {|l| l.to_f }))
49
- end
50
- placemarks
51
- end
52
-
53
- #Group of placemarks returned by the Geocoding service. If the result is valid the +statius+ attribute should be equal to <tt>Geocoding::GEI_SUCCESS</tt>
54
- class Placemarks < Array
55
- attr_accessor :name,:status
56
-
57
- def initialize(name,status)
58
- super(0)
59
- @name = name
60
- @status = status
61
- end
62
- end
63
-
64
- #A result from the Geocoding service.
65
- class Placemark < Struct.new(:address,:country_code,:administrative_area,:sub_administrative_area,:locality,:dependent_locality,:thoroughfare,:postal_code,:longitude,:latitude)
66
- def lonlat
67
- [longitude,latitude]
68
- end
69
-
70
- def latlon
71
- [latitude,longitude]
72
- end
73
- end
74
-
75
- #Raised when the connection to the service is not possible
76
- class ConnectionException < StandardError
77
- end
78
- end
79
- end
80
- end
@@ -1,22 +0,0 @@
1
-
2
- Ym4r::GoogleMaps::GPolyline.class_eval do
3
- #Creates a GPolyline object from a georuby line string. Assumes the points of the line strings are stored in Longitude(x)/Latitude(y) order.
4
- def self.from_georuby(line_string,color = nil,weight = nil,opacity = nil)
5
- GPolyline.new(line_string.points.collect { |point| GLatLng.new([point.y,point.x])},color,weight,opacity)
6
- end
7
- end
8
-
9
- Ym4r::GoogleMaps::GMarker.class_eval do
10
- #Creates a GMarker object from a georuby point. Accepts the same options as the GMarker constructor. Assumes the points of the line strings are stored in Longitude(x)/Latitude(y) order.
11
- def self.from_georuby(point,options = {})
12
- GMarker.new([point.y,point.x],options)
13
- end
14
- end
15
-
16
- Ym4r::GoogleMaps::GLatLng.class_eval do
17
- #Creates a GLatLng object from a georuby point. Assumes the points of the line strings are stored in Longitude(x)/Latitude(y) order.
18
- def self.from_georuby(point,unbounded = nil)
19
- GLatLng.new([point.y,point.x],unbounded)
20
- end
21
- end
22
-
@@ -1,444 +0,0 @@
1
- // Clusterer.js - marker clustering routines for Google Maps apps
2
- //
3
- // The original version of this code is available at:
4
- // http://www.acme.com/javascript/
5
- //
6
- // Copyright � 2005,2006 by Jef Poskanzer <jef@mail.acme.com>.
7
- // All rights reserved.
8
- //
9
- // Modified for inclusion into the YM4R library in accordance with the
10
- // following license:
11
- //
12
- // Redistribution and use in source and binary forms, with or without
13
- // modification, are permitted provided that the following conditions
14
- // are met:
15
- // 1. Redistributions of source code must retain the above copyright
16
- // notice, this list of conditions and the following disclaimer.
17
- // 2. Redistributions in binary form must reproduce the above copyright
18
- // notice, this list of conditions and the following disclaimer in the
19
- // documentation and/or other materials provided with the distribution.
20
- //
21
- // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22
- // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
- // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
- // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25
- // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
- // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
- // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
- // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
- // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
- // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
- // SUCH DAMAGE.
32
- //
33
- // For commentary on this license please see http://www.acme.com/license.html
34
-
35
-
36
- // Constructor.
37
- Clusterer = function(markers,icon,maxVisibleMarkers,gridSize,minMarkersPerCluster,maxLinesPerInfoBox) {
38
- this.markers = [];
39
- if(markers){
40
- for(var i =0 ; i< markers.length ; i++){
41
- this.addMarker(markers[i]);
42
- }
43
- }
44
- this.clusters = [];
45
- this.timeout = null;
46
-
47
- this.maxVisibleMarkers = maxVisibleMarkers || 150;
48
- this.gridSize = gridSize || 5;
49
- this.minMarkersPerCluster = minMarkersPerCluster || 5;
50
- this.maxLinesPerInfoBox = maxLinesPerInfoBox || 10;
51
-
52
- this.icon = icon || G_DEFAULT_ICON;
53
- }
54
-
55
- Clusterer.prototype = new GOverlay();
56
-
57
- Clusterer.prototype.initialize = function ( map ){
58
- this.map = map;
59
- this.currentZoomLevel = map.getZoom();
60
-
61
- GEvent.addListener( map, 'zoomend', Clusterer.makeCaller( Clusterer.display, this ) );
62
- GEvent.addListener( map, 'moveend', Clusterer.makeCaller( Clusterer.display, this ) );
63
- GEvent.addListener( map, 'infowindowclose', Clusterer.makeCaller( Clusterer.popDown, this ) );
64
- //Set map for each marker
65
- for(var i = 0,len = this.markers.length ; i < len ; i++){
66
- this.markers[i].setMap( map );
67
- }
68
- this.displayLater();
69
- }
70
-
71
- Clusterer.prototype.remove = function(){
72
- for ( var i = 0; i < this.markers.length; ++i ){
73
- this.removeMarker(this.markers[i]);
74
- }
75
- }
76
-
77
- Clusterer.prototype.copy = function(){
78
- return new Clusterer(this.markers,this.icon,this.maxVisibleMarkers,this.gridSize,this.minMarkersPerCluster,this.maxLinesPerInfoBox);
79
- }
80
-
81
- Clusterer.prototype.redraw = function(force){
82
- this.displayLater();
83
- }
84
-
85
- // Call this to change the cluster icon.
86
- Clusterer.prototype.setIcon = function ( icon ){
87
- this.icon = icon;
88
- }
89
-
90
- // Call this to add a marker.
91
- Clusterer.prototype.addMarker = function ( marker, description){
92
- marker.onMap = false;
93
- this.markers.push( marker );
94
- marker.description = marker.description || description;
95
- if(this.map != null){
96
- marker.setMap(this.map);
97
- this.displayLater();
98
- }
99
- };
100
-
101
-
102
- // Call this to remove a marker.
103
- Clusterer.prototype.removeMarker = function ( marker ){
104
- for ( var i = 0; i < this.markers.length; ++i )
105
- if ( this.markers[i] == marker ){
106
- if ( marker.onMap )
107
- this.map.removeOverlay( marker );
108
- for ( var j = 0; j < this.clusters.length; ++j ){
109
- var cluster = this.clusters[j];
110
- if ( cluster != null ){
111
- for ( var k = 0; k < cluster.markers.length; ++k )
112
- if ( cluster.markers[k] == marker ){
113
- cluster.markers[k] = null;
114
- --cluster.markerCount;
115
- break;
116
- }
117
- if ( cluster.markerCount == 0 ){
118
- this.clearCluster( cluster );
119
- this.clusters[j] = null;
120
- }
121
- else if ( cluster == this.poppedUpCluster )
122
- Clusterer.rePop( this );
123
- }
124
- }
125
- this.markers[i] = null;
126
- break;
127
- }
128
- this.displayLater();
129
- };
130
-
131
- Clusterer.prototype.displayLater = function (){
132
- if ( this.timeout != null )
133
- clearTimeout( this.timeout );
134
- this.timeout = setTimeout( Clusterer.makeCaller( Clusterer.display, this ), 50 );
135
- };
136
-
137
- Clusterer.display = function ( clusterer ){
138
- var i, j, marker, cluster, len, len2;
139
-
140
- clearTimeout( clusterer.timeout );
141
-
142
- var newZoomLevel = clusterer.map.getZoom();
143
- if ( newZoomLevel != clusterer.currentZoomLevel ){
144
- // When the zoom level changes, we have to remove all the clusters.
145
- for ( i = 0 , len = clusterer.clusters.length; i < len; ++i ){
146
- if ( clusterer.clusters[i] != null ){
147
- clusterer.clearCluster( clusterer.clusters[i] );
148
- clusterer.clusters[i] = null;
149
- }
150
- }
151
- clusterer.clusters.length = 0;
152
- clusterer.currentZoomLevel = newZoomLevel;
153
- }
154
-
155
- // Get the current bounds of the visible area.
156
- var bounds = clusterer.map.getBounds();
157
-
158
- // Expand the bounds a little, so things look smoother when scrolling
159
- // by small amounts.
160
- var sw = bounds.getSouthWest();
161
- var ne = bounds.getNorthEast();
162
- var dx = ne.lng() - sw.lng();
163
- var dy = ne.lat() - sw.lat();
164
- dx *= 0.10;
165
- dy *= 0.10;
166
- bounds = new GLatLngBounds(
167
- new GLatLng( sw.lat() - dy, sw.lng() - dx ),
168
- new GLatLng( ne.lat() + dy, ne.lng() + dx )
169
- );
170
-
171
- // Partition the markers into visible and non-visible lists.
172
- var visibleMarkers = [];
173
- var nonvisibleMarkers = [];
174
- for ( i = 0, len = clusterer.markers.length ; i < len; ++i ){
175
- marker = clusterer.markers[i];
176
- if ( marker != null )
177
- if ( bounds.contains( marker.getPoint() ) )
178
- visibleMarkers.push( marker );
179
- else
180
- nonvisibleMarkers.push( marker );
181
- }
182
-
183
- // Take down the non-visible markers.
184
- for ( i = 0, len = nonvisibleMarkers.length ; i < len; ++i ){
185
- marker = nonvisibleMarkers[i];
186
- if ( marker.onMap ){
187
- clusterer.map.removeOverlay( marker );
188
- marker.onMap = false;
189
- }
190
- }
191
-
192
- // Take down the non-visible clusters.
193
- for ( i = 0, len = clusterer.clusters.length ; i < len ; ++i ){
194
- cluster = clusterer.clusters[i];
195
- if ( cluster != null && ! bounds.contains( cluster.marker.getPoint() ) && cluster.onMap ){
196
- clusterer.map.removeOverlay( cluster.marker );
197
- cluster.onMap = false;
198
- }
199
- }
200
-
201
- // Clustering! This is some complicated stuff. We have three goals
202
- // here. One, limit the number of markers & clusters displayed, so the
203
- // maps code doesn't slow to a crawl. Two, when possible keep existing
204
- // clusters instead of replacing them with new ones, so that the app pans
205
- // better. And three, of course, be CPU and memory efficient.
206
- if ( visibleMarkers.length > clusterer.maxVisibleMarkers ){
207
- // Add to the list of clusters by splitting up the current bounds
208
- // into a grid.
209
- var latRange = bounds.getNorthEast().lat() - bounds.getSouthWest().lat();
210
- var latInc = latRange / clusterer.gridSize;
211
- var lngInc = latInc / Math.cos( ( bounds.getNorthEast().lat() + bounds.getSouthWest().lat() ) / 2.0 * Math.PI / 180.0 );
212
- for ( var lat = bounds.getSouthWest().lat(); lat <= bounds.getNorthEast().lat(); lat += latInc )
213
- for ( var lng = bounds.getSouthWest().lng(); lng <= bounds.getNorthEast().lng(); lng += lngInc ){
214
- cluster = new Object();
215
- cluster.clusterer = clusterer;
216
- cluster.bounds = new GLatLngBounds( new GLatLng( lat, lng ), new GLatLng( lat + latInc, lng + lngInc ) );
217
- cluster.markers = [];
218
- cluster.markerCount = 0;
219
- cluster.onMap = false;
220
- cluster.marker = null;
221
- clusterer.clusters.push( cluster );
222
- }
223
-
224
- // Put all the unclustered visible markers into a cluster - the first
225
- // one it fits in, which favors pre-existing clusters.
226
- for ( i = 0, len = visibleMarkers.length ; i < len; ++i ){
227
- marker = visibleMarkers[i];
228
- if ( marker != null && ! marker.inCluster ){
229
- for ( j = 0, len2 = clusterer.clusters.length ; j < len2 ; ++j ){
230
- cluster = clusterer.clusters[j];
231
- if ( cluster != null && cluster.bounds.contains( marker.getPoint() ) ){
232
- cluster.markers.push( marker );
233
- ++cluster.markerCount;
234
- marker.inCluster = true;
235
- }
236
- }
237
- }
238
- }
239
-
240
- // Get rid of any clusters containing only a few markers.
241
- for ( i = 0, len = clusterer.clusters.length ; i < len ; ++i )
242
- if ( clusterer.clusters[i] != null && clusterer.clusters[i].markerCount < clusterer.minMarkersPerCluster ){
243
- clusterer.clearCluster( clusterer.clusters[i] );
244
- clusterer.clusters[i] = null;
245
- }
246
-
247
- // Shrink the clusters list.
248
- for ( i = clusterer.clusters.length - 1; i >= 0; --i )
249
- if ( clusterer.clusters[i] != null )
250
- break;
251
- else
252
- --clusterer.clusters.length;
253
-
254
- // Ok, we have our clusters. Go through the markers in each
255
- // cluster and remove them from the map if they are currently up.
256
- for ( i = 0, len = clusterer.clusters.length ; i < len; ++i ){
257
- cluster = clusterer.clusters[i];
258
- if ( cluster != null ){
259
- for ( j = 0 , len2 = cluster.markers.length ; j < len2; ++j ){
260
- marker = cluster.markers[j];
261
- if ( marker != null && marker.onMap ){
262
- clusterer.map.removeOverlay( marker );
263
- marker.onMap = false;
264
- }
265
- }
266
- }
267
- }
268
-
269
- // Now make cluster-markers for any clusters that need one.
270
- for ( i = 0, len = clusterer.clusters.length; i < len; ++i ){
271
- cluster = clusterer.clusters[i];
272
- if ( cluster != null && cluster.marker == null ){
273
- // Figure out the average coordinates of the markers in this
274
- // cluster.
275
- var xTotal = 0.0, yTotal = 0.0;
276
- for ( j = 0, len2 = cluster.markers.length; j < len2 ; ++j ){
277
- marker = cluster.markers[j];
278
- if ( marker != null ){
279
- xTotal += ( + marker.getPoint().lng() );
280
- yTotal += ( + marker.getPoint().lat() );
281
- }
282
- }
283
- var location = new GLatLng( yTotal / cluster.markerCount, xTotal / cluster.markerCount );
284
- marker = new GMarker( location, { icon: clusterer.icon } );
285
- cluster.marker = marker;
286
- GEvent.addListener( marker, 'click', Clusterer.makeCaller( Clusterer.popUp, cluster ) );
287
- }
288
- }
289
- }
290
-
291
- // Display the visible markers not already up and not in clusters.
292
- for ( i = 0, len = visibleMarkers.length; i < len; ++i ){
293
- marker = visibleMarkers[i];
294
- if ( marker != null && ! marker.onMap && ! marker.inCluster )
295
- {
296
- clusterer.map.addOverlay( marker );
297
- marker.addedToMap();
298
- marker.onMap = true;
299
- }
300
- }
301
-
302
- // Display the visible clusters not already up.
303
- for ( i = 0, len = clusterer.clusters.length ; i < len; ++i ){
304
- cluster = clusterer.clusters[i];
305
- if ( cluster != null && ! cluster.onMap && bounds.contains( cluster.marker.getPoint() )){
306
- clusterer.map.addOverlay( cluster.marker );
307
- cluster.onMap = true;
308
- }
309
- }
310
-
311
- // In case a cluster is currently popped-up, re-pop to get any new
312
- // markers into the infobox.
313
- Clusterer.rePop( clusterer );
314
- };
315
-
316
-
317
- Clusterer.popUp = function ( cluster ){
318
- var clusterer = cluster.clusterer;
319
- var html = '<table width="300">';
320
- var n = 0;
321
- for ( var i = 0 , len = cluster.markers.length; i < len; ++i )
322
- {
323
- var marker = cluster.markers[i];
324
- if ( marker != null )
325
- {
326
- ++n;
327
- html += '<tr><td>';
328
- if ( marker.getIcon().smallImage != null )
329
- html += '<img src="' + marker.getIcon().smallImage + '">';
330
- else
331
- html += '<img src="' + marker.getIcon().image + '" width="' + ( marker.getIcon().iconSize.width / 2 ) + '" height="' + ( marker.getIcon().iconSize.height / 2 ) + '">';
332
- html += '</td><td>' + marker.description + '</td></tr>';
333
- if ( n == clusterer.maxLinesPerInfoBox - 1 && cluster.markerCount > clusterer.maxLinesPerInfoBox )
334
- {
335
- html += '<tr><td colspan="2">...and ' + ( cluster.markerCount - n ) + ' more</td></tr>';
336
- break;
337
- }
338
- }
339
- }
340
- html += '</table>';
341
- clusterer.map.closeInfoWindow();
342
- cluster.marker.openInfoWindowHtml( html );
343
- clusterer.poppedUpCluster = cluster;
344
- };
345
-
346
- Clusterer.rePop = function ( clusterer ){
347
- if ( clusterer.poppedUpCluster != null )
348
- Clusterer.popUp( poppedUpCluster );
349
- };
350
-
351
- Clusterer.popDown = function ( clusterer ){
352
- clusterer.poppedUpCluster = null;
353
- };
354
-
355
- Clusterer.prototype.clearCluster = function ( cluster ){
356
- var i, marker;
357
-
358
- for ( i = 0; i < cluster.markers.length; ++i ){
359
- if ( cluster.markers[i] != null ){
360
- cluster.markers[i].inCluster = false;
361
- cluster.markers[i] = null;
362
- }
363
- }
364
-
365
- cluster.markers.length = 0;
366
- cluster.markerCount = 0;
367
-
368
- if ( cluster == this.poppedUpCluster )
369
- this.map.closeInfoWindow();
370
-
371
- if ( cluster.onMap )
372
- {
373
- this.map.removeOverlay( cluster.marker );
374
- cluster.onMap = false;
375
- }
376
- };
377
-
378
- // This returns a function closure that calls the given routine with the
379
- // specified arg.
380
- Clusterer.makeCaller = function ( func, arg ){
381
- return function () { func( arg ); };
382
- };
383
-
384
-
385
- // Augment GMarker so it handles markers that have been created but
386
- // not yet addOverlayed.
387
- GMarker.prototype.setMap = function ( map ){
388
- this.map = map;
389
- };
390
-
391
- GMarker.prototype.getMap = function (){
392
- return this.map;
393
- }
394
-
395
- GMarker.prototype.addedToMap = function (){
396
- this.map = null;
397
- };
398
-
399
-
400
- GMarker.prototype.origOpenInfoWindow = GMarker.prototype.openInfoWindow;
401
- GMarker.prototype.openInfoWindow = function ( node, opts ){
402
- if ( this.map != null )
403
- return this.map.openInfoWindow( this.getPoint(), node, opts );
404
- else
405
- return this.origOpenInfoWindow( node, opts );
406
- };
407
-
408
- GMarker.prototype.origOpenInfoWindowHtml = GMarker.prototype.openInfoWindowHtml;
409
- GMarker.prototype.openInfoWindowHtml = function ( html, opts ){
410
- if ( this.map != null )
411
- return this.map.openInfoWindowHtml( this.getPoint(), html, opts );
412
- else
413
- return this.origOpenInfoWindowHtml( html, opts );
414
- };
415
-
416
- GMarker.prototype.origOpenInfoWindowTabs = GMarker.prototype.openInfoWindowTabs;
417
- GMarker.prototype.openInfoWindowTabs = function ( tabNodes, opts ){
418
- if ( this.map != null )
419
- return this.map.openInfoWindowTabs( this.getPoint(), tabNodes, opts );
420
- else
421
- return this.origOpenInfoWindowTabs( tabNodes, opts );
422
- };
423
-
424
- GMarker.prototype.origOpenInfoWindowTabsHtml = GMarker.prototype.openInfoWindowTabsHtml;
425
- GMarker.prototype.openInfoWindowTabsHtml = function ( tabHtmls, opts ){
426
- if ( this.map != null )
427
- return this.map.openInfoWindowTabsHtml( this.getPoint(), tabHtmls, opts );
428
- else
429
- return this.origOpenInfoWindowTabsHtml( tabHtmls, opts );
430
- };
431
-
432
- GMarker.prototype.origShowMapBlowup = GMarker.prototype.showMapBlowup;
433
- GMarker.prototype.showMapBlowup = function ( opts ){
434
- if ( this.map != null )
435
- return this.map.showMapBlowup( this.getPoint(), opts );
436
- else
437
- return this.origShowMapBlowup( opts );
438
- };
439
-
440
-
441
- function addDescriptionToMarker(marker, description){
442
- marker.description = description;
443
- return marker;
444
- }