Index: main/trunk/greenstone2/perllib/doc.pm
===================================================================
--- main/trunk/greenstone2/perllib/doc.pm	(revision 33184)
+++ main/trunk/greenstone2/perllib/doc.pm	(revision 33185)
@@ -1110,4 +1110,12 @@
     #	print STDERR " Tried converting to utf8: $value\n";
     #    }
+
+	
+	# for every GPS.mapOverlay/sectionID (but sadly not for every doc, let alone every collection),
+	# we use a map to ensure uniqueness of CoordShorts for optimisation purposes
+	# That way we don't end up with the same CoordShort values a large number of times in the index
+	# We only get any savings with GPS.mapOverlay when using this map, not for "Latitude" and "Longitude" metadata
+	my $unique_coordshort_map = {};	
+
 
 	#If the metadata value is either a latitude or a longitude value then we want to save a shortened version for spacial searching purposes
@@ -1153,5 +1161,5 @@
 			my $latitude = $self->get_metadata_element ($section, "Latitude");			
 			# TODO: would like all Longitude info together followed by all Coordinate info, but the following will add all coord info meta and end of this function will add Longitude meta
-			$self->processCoordinate($section, $latitude, $value); # value is Longitude
+			$self->processCoordinate($section, $latitude, $value, $unique_coordshort_map); # value is Longitude
 		}
 	}
@@ -1159,14 +1167,7 @@
 	elsif($field eq "GPS.mapOverlay") { # then the value is a JSON string
 	
-		# TODO:
-		# If we already have Coordinate meta for this section of the document (as can happen during buildcol.pl),
-		# let's ASSUME this means we've already processed GPS.mapOverlay meta into Coordinate meta for this section (can have happened during import.pl)
-		# to avoid adding duplicate Coordinates meta, which then end up duplicated in the index
-		# Of course, the assumption is not always true! We could have an image with embedded Lat and Lng meta,
-		# and the same image doc's section could have GPS.mapOverlay meta (from shapes) added via the doc editor.
-		# This very function would then have converted Lat/Lng into Coordinate meta (just in the if stmt above) and added it to the section.
-		# And then by the time we process this section's GPS.mapOverlay meta here, we would notice the section has Coordinate meta already,
-		# and therefore skip converting the GPS.mapOverlay meta into Coordinate meta! What to dooooo?
-		# So the return statement immediately below is a temporary solution, until we find a better one that will always work.
+		# TODO: How can we prevent GPS.mapOverlay from being processed 4 or so times by buildcol.pl??
+		# Once for each pass (dummy, sidx, didx for lucene, info db pass)
+	
 	  if($cmd_line_mode eq "buildcol") {
 	   #my $metaMap = $self->get_metadata_hashmap($section); ## TODO: Check if necessary to avoid duplication of <Coordinate> meta in index\text\<coll>.jdb
@@ -1176,5 +1177,5 @@
 	
     	
-		print STDERR "GPS.mapOverlay before val: " . $value . "\n";
+		print STDERR "GPS.mapOverlay before decode, val: " . $value . "\n";
 		
 		# TODO html decode?
@@ -1182,5 +1183,5 @@
 		$value =~ s@&#093;@]@g;
 		$value =~ s@&quot;@"@g;
-		print STDERR "GPS.mapOverlay after val: " . $value . "\n";
+		print STDERR "GPS.mapOverlay after decode, val: " . $value . "\n";
 
 		my $json_array = decode_json $value;
@@ -1196,6 +1197,5 @@
 				#print STDERR "Found a circle:\n" . &printShape($json, $shape);
 		
-				# work out bounding box
-				# SCARY!
+				# Work out bounding box
 				# want the inverse of this useful page:
 				# https://stackoverflow.com/questions/639695/how-to-convert-latitude-or-longitude-to-meters
@@ -1243,8 +1243,8 @@
 				print STDERR "cos $centre_lat is $cos_lat\n";
 
-				$self->processCoordinate($section, $lat_north, $lng_east);
-				$self->processCoordinate($section, $lat_south, $lng_east);
-				$self->processCoordinate($section, $lat_south, $lng_west);
-				$self->processCoordinate($section, $lat_north, $lng_west);
+				$self->processCoordinate($section, $lat_north, $lng_east, $unique_coordshort_map);
+				$self->processCoordinate($section, $lat_south, $lng_east, $unique_coordshort_map);
+				$self->processCoordinate($section, $lat_south, $lng_west, $unique_coordshort_map);
+				$self->processCoordinate($section, $lat_north, $lng_west, $unique_coordshort_map);
 			
 			}
@@ -1252,10 +1252,10 @@
 				print STDERR "@@ MARKER FOUND WITH LAT: " . $shape->{"position"}->{"lat"} . "\n";
 				print STDERR "@@ MARKER FOUND WITH LNG: " . $shape->{"position"}->{"lng"} . "\n";
-				$self->processCoordinate($section, $shape->{"position"}->{"lat"}, $shape->{"position"}->{"lng"});				
+				$self->processCoordinate($section, $shape->{"position"}->{"lat"}, $shape->{"position"}->{"lng"}, $unique_coordshort_map);				
 			}
 			elsif ($type eq "polyline" || $type eq "polygon") {
 				my $path_array = $shape->{"path"};
 				foreach my $position (@$path_array) {									
-					$self->processCoordinate($section, $position->{"lat"}, $position->{"lng"});
+					$self->processCoordinate($section, $position->{"lat"}, $position->{"lng"}, $unique_coordshort_map);
 				}
 			}
@@ -1263,8 +1263,8 @@
 		
 				my $bounds = $shape->{"bounds"};
-				$self->processCoordinate($section, $bounds->{"north"}, $bounds->{"east"});
-				$self->processCoordinate($section, $bounds->{"south"}, $bounds->{"east"});
-				$self->processCoordinate($section, $bounds->{"south"}, $bounds->{"west"});
-				$self->processCoordinate($section, $bounds->{"north"}, $bounds->{"west"});
+				$self->processCoordinate($section, $bounds->{"north"}, $bounds->{"east"}, $unique_coordshort_map);
+				$self->processCoordinate($section, $bounds->{"south"}, $bounds->{"east"}, $unique_coordshort_map);
+				$self->processCoordinate($section, $bounds->{"south"}, $bounds->{"west"}, $unique_coordshort_map);
+				$self->processCoordinate($section, $bounds->{"north"}, $bounds->{"west"}, $unique_coordshort_map);
 			}	
 		
@@ -1272,4 +1272,13 @@
 	   #}
 	  }
+
+	  # We haven't yet written out any Coordshort meta! Write those out now,
+	  # since we've now finally ensured they're all unique CoordShort meta for this GPS.mapOverlay at least.
+	  foreach my $coordshort (keys %$unique_coordshort_map) {
+
+		#print STDERR "@@@@ creating new coordshort: $coordshort\n";
+		push (@{$section_ptr->{'metadata'}}, ["CoordShort", $coordshort ]);
+	  }
+	  
 	} # end GPS.mapOverlay meta
 
@@ -1305,9 +1314,12 @@
 	}
 	
-}	
-
+}
+
+# Beware: this method now ONLY writes out the Coordinate meta, but not the CoordShorts
+# At method's end, the CoordShorts are stored in the $unique_coordshort_map (for optimisation),
+# ready to be added to the doc section's meta once all Coordinates in a GPS.mapOverlay are done being processed.
 sub processCoordinate {
 	my $self = shift (@_);
-    my ($section, $latitude, $longitude) = @_;
+    my ($section, $latitude, $longitude, $unique_coordshort_map) = @_;
 
 	my $section_ptr = $self->_lookup_section($section);
@@ -1338,24 +1350,41 @@
 	}	
 	
-	#if(defined $beforeDec && defined $afterDec)
-	#{
-		my $name = "CoordShort";
-		push (@{$section_ptr->{'metadata'}}, [$name, "$latBeforeDec$lat_direction $lngBeforeDec$lng_direction"]);
+	# We have to deal with 0 decimal places for either lat or lng, or no dec places for only one of them
+	# And we have to store all combinations of lats and lngs as CoordShort.
+	
+	#my $name = "CoordShort";
+	#push (@{$section_ptr->{'metadata'}}, [$name, "$latBeforeDec$lat_direction $lngBeforeDec$lng_direction"]);
+
+	my @lat_array = ("$latBeforeDec$lat_direction");
+	my @lng_array = ("$lngBeforeDec$lng_direction");
+
+	for(my $i = 2; $i <= 4; $i++)
+	{
+		my $latDecPlaces = (length($latAfterDec) >= $i) ? substr($latAfterDec, 0, $i) : "";			
+		my $lngDecPlaces = (length($lngAfterDec) >= $i) ? substr($lngAfterDec, 0, $i) : "";
+
+		push(@lat_array, $latBeforeDec . $lat_direction. $latDecPlaces) unless $latDecPlaces eq "";
+		push(@lng_array, $lngBeforeDec . $lng_direction. $lngDecPlaces) unless $lngDecPlaces eq "";
+
+		#push (@{$section_ptr->{'metadata'}}, [$name, 
+		#		$latBeforeDec . $lat_direction. $latDecPlaces . " " . $lngBeforeDec . $lng_direction. $lngDecPlaces]);
+		
+	}		
+		
+	for(my $i = 0; $i < scalar(@lat_array); $i++) {
+		for(my $j = 0; $j < scalar(@lng_array); $j++) {
+			#push (@{$section_ptr->{'metadata'}}, [$name, $lat_array[$i] . " " . $lng_array[$j] ]);
+			my $coordshort = $lat_array[$i] . " " . $lng_array[$j];
+			$unique_coordshort_map->{$coordshort} = "1"; # just store it
 			
-		for(my $i = 2; $i <= 4; $i++)
-		{
-			my $latDecPlaces = (length($latAfterDec) >= $i) ? substr($latAfterDec, 0, $i) : "";			
-			my $lngDecPlaces = (length($lngAfterDec) >= $i) ? substr($lngAfterDec, 0, $i) : "";
-
-			push (@{$section_ptr->{'metadata'}}, [$name, 
-					$latBeforeDec . $lat_direction. $latDecPlaces . " " . $lngBeforeDec . $lng_direction. $lngDecPlaces]);
+			#print STDERR "@@@@ pushed new value: " . $coordshort . " into map\n";
 			
 		}
-			
-		#Only add the metadata if it has not already been added
-		#my $metaMap = $self->get_metadata_hashmap($section); ### TODO: metaMap not used. Unnecesssary step? (Called function has no side-effects.)
-	#}
-
-
+	}
+	
+	
+		
+	#Only add the metadata if it has not already been added
+	#my $metaMap = $self->get_metadata_hashmap($section); ### TODO: metaMap not used. Unnecesssary step? (Called function has no side-effects.)
 }
 
Index: main/trunk/greenstone3/web/interfaces/default/js/map-scripts.js
===================================================================
--- main/trunk/greenstone3/web/interfaces/default/js/map-scripts.js	(revision 33184)
+++ main/trunk/greenstone3/web/interfaces/default/js/map-scripts.js	(revision 33185)
@@ -150,4 +150,5 @@
 	//Check which increment to use for longitude (i.e. 0.001, 0.01, 0.1 or 1 degree increments)
 	var lngDelta;
+	var lngPrecision;
 	for(var i = 3; i >= 0; i--)
 	{
@@ -205,5 +206,5 @@
 	var query = "";
 	var iMax = Math.floor(latDistance / latDelta) + 1;
-	var jMax = Math.floor(lngDistance / lngDelta) + 1;;
+	var jMax = Math.floor(lngDistance / lngDelta) + 1;
 	for(var i = 0; i <= iMax; i++) //for(var i = 0; i <= Math.floor(latDistance / latDelta) + 1; i++)
 	{
@@ -355,5 +356,4 @@
 		{
 			if(doc.shapes) {
-				//console.log("@@@ making doc.shapes["+x+"] visible");
 				for(var x = 0; x < doc.shapes.length; x++) {					
 					doc.shapes[x].setVisible(true);
@@ -369,5 +369,10 @@
 		if(doc.shapes) {
 			console.log("@@@@ HERE IN doc.shapes");
-			bounds = ShapesUtil.overlayBounds(doc.shapes);
+			var docSection_overlay_bounds = ShapesUtil.overlayBounds(doc.shapes);
+			// We now have the current document or document subsection's bounds.
+			// Use this to extend the overall bounds (the cumulative bounds for all nearby documents,
+			// or at least the cumulative bounds for this document with all its subsections).
+			bounds.extend(docSection_overlay_bounds.getNorthEast());
+			bounds.extend(docSection_overlay_bounds.getSouthWest()); 
 		}
 		else {
