def use_site(self, site, mapwin): """Given a starting site, center the map on it and show the map. """ if len(site) > 3 and site[3]: collection = self.find_collection(site[3]) else: collection = self.find_collection(self.default_collection) if not collection: return False mapwin.collection = collection # site[1] and site[2] are the long and lat in deg.minutes # print(site[0], site[1], site[2]) mapwin.center_lon = MapUtils.deg_min2dec_deg(site[1]) mapwin.center_lat = MapUtils.deg_min2dec_deg(site[2]) mapwin.pin_lon = mapwin.center_lon mapwin.pin_lat = mapwin.center_lat # print("Center in decimal degrees:", centerLon, centerLat) if (self.Debug): print(site[0] + ":", \ MapUtils.dec_deg2deg_min_str(mapwin.center_lon), \ MapUtils.dec_deg2deg_min_str(mapwin.center_lat)) if len(site) > 4 and collection.zoom_to: collection.zoom_to(site[4]) mapwin.draw_map() return True
def use_site(self, site, mapwin): collection = self.find_collection(site[3]) if not collection: return False mapwin.collection = collection # site[1] and site[2] are the long and lat in deg.minutes # print site[0], site[1], site[2] mapwin.center_lon = MapUtils.deg_min2dec_deg(site[1]) mapwin.center_lat = MapUtils.deg_min2dec_deg(site[2]) mapwin.pin_lon = mapwin.center_lon mapwin.pin_lat = mapwin.center_lat # print "Center in decimal degrees:", centerLon, centerLat if (self.Debug): print site[0] + ":", \ MapUtils.dec_deg2deg_min_str(mapwin.center_lon), \ MapUtils.dec_deg2deg_min_str(mapwin.center_lat) if len(site) > 4 and collection.zoom_to: collection.zoom_to(site[4]) mapwin.draw_map() return True
def get_maplet(self, longitude, latitude): """Get the maplet containing the specified coordinates. Returns pixbuf, x_offset, y_offset, filename where offsets are pixels from top left of the specified coords and pixbuf or (less often) filename may be None. """ filename = self.coords_to_filename(longitude - self.lon_correction, latitude - self.lat_correction) if (self.Debug): print "T1MC get_maplet(", MapUtils.dec_deg2deg_min_str(longitude), print ",", MapUtils.dec_deg2deg_min_str(latitude), "):", filename # Calculate offsets. # Maplets are self.series minutes wide and tall, # so any offset from that is an offset into the maplet: # the number of pixels in X and Y that have to be added # to get from the maplet's upper left corner to the # indicated coordinates. # But then we have to correct to get to WGS84 coordinates. # XXX the WGS84 part doesn't work right yet. # longitude increases rightward: x_off = int((longitude - MapUtils.truncate2frac(longitude, self.frac) - self.lon_correction) * self.xscale) if (self.Debug): print "truncated", MapUtils.dec_deg2deg_min_str(longitude), "to", print MapUtils.dec_deg2deg_min_str(MapUtils.truncate2frac(longitude, self.frac)) # Latitude decreases downward: y_off = int((MapUtils.truncate2frac(latitude, self.frac) + self.frac - latitude - self.lat_correction) * self.yscale) if (self.Debug): print "truncated", MapUtils.dec_deg2deg_min_str(latitude), "to", print MapUtils.dec_deg2deg_min_str(MapUtils.truncate2frac(latitude, self.frac)) print "y_off is", y_off if not os.access(filename, os.R_OK): return None, x_off, y_off, filename pixbuf = MapWindow.load_image_from_file(filename) return pixbuf, x_off, y_off, filename
def get_maplet(self, longitude, latitude): """Get the maplet containing the specified coordinates. Returns pixbuf, x_offset, y_offset, filename where offsets are pixels from top left of the specified coords and pixbuf or (less often) filename may be None. """ filename = self.coords_to_filename(longitude - self.lon_correction, latitude - self.lat_correction) if (self.Debug): print "T1MC get_maplet(", MapUtils.dec_deg2deg_min_str(longitude), print ",", MapUtils.dec_deg2deg_min_str(latitude), "):", filename # Calculate offsets. # Maplets are self.series minutes wide and tall, # so any offset from that is an offset into the maplet: # the number of pixels in X and Y that have to be added # to get from the maplet's upper left corner to the # indicated coordinates. # But then we have to correct to get to WGS84 coordinates. # XXX the WGS84 part doesn't work right yet. # longitude increases rightward: x_off = int((longitude - MapUtils.truncate2frac(longitude, self.frac) - self.lon_correction) * self.xscale) if (self.Debug): print "truncated", MapUtils.dec_deg2deg_min_str(longitude), "to", print MapUtils.dec_deg2deg_min_str( MapUtils.truncate2frac(longitude, self.frac)) # Latitude decreases downward: y_off = int((MapUtils.truncate2frac(latitude, self.frac) + self.frac - latitude - self.lat_correction) * self.yscale) if (self.Debug): print "truncated", MapUtils.dec_deg2deg_min_str(latitude), "to", print MapUtils.dec_deg2deg_min_str( MapUtils.truncate2frac(latitude, self.frac)) print "y_off is", y_off if not os.access(filename, os.R_OK): return None, x_off, y_off, filename pixbuf = MapWindow.load_image_from_file(filename) return pixbuf, x_off, y_off, filename
def parse_args(self, mapwin, args): """Parse runtime arguments.""" args = args[1:] while len(args) > 0: if args[0][0] == '-' and not args[0][1].isdigit(): if args[0] == "-v" or args[0] == "--version": print(self.get_version()) sys.exit(0) elif args[0] == "-h" or args[0] == "--help": self.Usage() # Next clause is impossible because of the prev isdigit check: # if args[0] == "-15": # series = 15 elif args[0] == "-p": self.print_sites() elif args[0] == "-g": try: import socket from gpsdPoller import GpsdPoller # mapwin.gps_poller = GpsdPoller(10, self.gps_poll) mapwin.gps_poller = GpsdPoller(10, mapwin.gpsd_callback) except ImportError as e: print(str(e)) print() print("Can't follow GPS: python-gps isn't installed") mapwin.gps_poller = None except socket.error as e: print(str(e)) print() print("Can't follow GPS: can't open GPS device") mapwin.gps_poller = None elif args[0] == "-c": # Specify a collection: if len(args) < 2: print("-c must specify collection") self.Usage() mapwin.collection = self.find_collection(args[1]) if mapwin.collection is None: self.error_out("Can't find a map collection called " + args[1]) # Start initially at top left, but subsequent args # may change this: mapwin.center_lon, mapwin.center_lat = \ mapwin.collection.get_top_left() if (self.Debug): print("Collection", mapwin.collection.name, end=' ') print("Starting at", \ MapUtils.dec_deg2deg_min_str(mapwin.center_lon), \ ", ", \ MapUtils.dec_deg2deg_min_str(mapwin.center_lat)) args = args[1:] elif args[0].startswith("-d"): try: debuglevel = int(args[0][2:]) self.Debug = debuglevel except: self.Debug = 1 print("Debugging level", self.Debug) elif args[0] == "-r": self.reload_tiles = time.time() elif args[0] == "-t" and len(args) > 1: if mapwin.trackpoints is None: mapwin.trackpoints = TrackPoints() # Is it a known track? for tr in self.KnownTracks: if args[1] == tr[0]: if self.Debug: print("Reading known track", tr[0], tr[1]) args[1] = tr[1] break try: mapwin.trackpoints.read_track_file(args[1]) except IOError: print("Can't read track file", args[1]) args = args[1:] else: self.error_out("Unknown flag " + args[0]) # Done processing this flag args = args[1:] continue # args[0] doesn't start with '-'. Is it a track file? if not mapwin.trackpoints: mapwin.trackpoints = TrackPoints() try: mapwin.trackpoints.read_track_file(args[0]) args = args[1:] continue except IOError: print("Can't read track file", args[0]) args = args[1:] continue # Catch a special case for a common KML error: except xml.parsers.expat.ExpatError: print("Can't read %s: syntax error." % args[0]) lowerarg = args[0].lower() if lowerarg.endswith(".kml") or \ lowerarg.endswith(".kmz"): print(""" Is this a KML made with ArcGIS? It may have an illegal xsi:schemaLocation. If so, try changing xsi:schemaLocation to just schemaLocation.""") args = args[1:] sys.exit(1) except (RuntimeError, FileNotFoundError): # It wasn't a track file; continue trying to parse it # print(args[0], "is not a track file") pass # Try to match a known site: for site in self.KnownSites: if args[0] == site[0]: if not self.use_site(site, mapwin): continue break if mapwin.collection and mapwin.center_lon and mapwin.center_lat: args = args[1:] continue # Doesn't match a known site. Maybe the args are coordinates? try: if len(args) >= 2 and \ len(args[0]) > 1 and args[0][1].isdigit() and \ len(args[1]) > 1 and args[1][1].isdigit(): mapwin.center_lat = float(args[0]) mapwin.center_lon = float(args[1]) # Set a pin on the specified point. mapwin.pin_lat = mapwin.center_lat mapwin.pin_lon = mapwin.center_lon args = args[2:] if args: mapwin.collection = self.find_collection(args[0]) args = args[1:] else: mapwin.collection = \ self.find_collection(self.default_collection) continue print("Can't make sense of argument:", args[0]) args = args[1:] continue except ValueError: print("Couldn't parse coordinates") self.Usage() # If we get here, we still have an argument but it doesn't # match anything we know: flag, collection, site or coordinate. print("Problem parsing arguments. Remaining args:", args) self.Usage() # Now we've parsed all the arguments. # If we didn't get a collection, use the default, if any: if not mapwin.collection and self.default_collection: mapwin.collection = self.find_collection(self.default_collection) if not mapwin.collection: print("Can't find a default Map Collection!") print("There may be something wrong with your pytopo.sites") print() sys.exit(1) mapwin.collection.Debug = self.Debug # If we have a collection and a track but no center point, # center it on the trackpoints, and set scale appropriately: if mapwin.trackpoints and mapwin.collection is not None \ and not (mapwin.center_lat and mapwin.center_lon): minlon, minlat, maxlon, maxlat = mapwin.trackpoints.get_bounds() mapwin.center_lon = (maxlon + minlon) / 2 mapwin.center_lat = (maxlat + minlat) / 2 mapwin.collection.zoom_to_bounds(minlon, minlat, maxlon, maxlat) if self.reload_tiles and 'set_reload_tiles' in dir(mapwin.collection): mapwin.collection.set_reload_tiles(self.reload_tiles) elif self.reload_tiles: print("Collection can't re-download tiles") # By now, we hope we have the mapwin positioned with a collection # and starting coordinates: if mapwin.collection and mapwin.center_lon and mapwin.center_lat: return # If we're following GPS, it's okay if we don't have center coords yet; # the mapwin will wait for a fix. if mapwin.collection and mapwin.gps_poller: return raise(ArgParseException)
def draw_map(self, center_lon, center_lat, mapwin): """Draw maplets at the specified coordinates, to fill the mapwin.""" self.mapwin = mapwin # Get the current window size: win_width, win_height = mapwin.get_size() if (self.Debug): print("Window is", win_width, "x", win_height) # Now that we have a latitude, call zoom so we can finally # set the x and y scales accurately. self.zoom(0, center_lat) # Find the coordinate boundaries for the set of maps to draw. # This may (indeed, usually will) include maps partly off the screen, # so the coordinates will span a greater area than the visible window. if (self.Debug): print("Calculating boundaries: min =", \ MapUtils.dec_deg2deg_min_str(center_lon), \ center_lon, "+/-", win_width, \ "/", self.xscale, "/ 2") min_lon = center_lon - win_width / self.xscale / 2 max_lon = center_lon + win_width / self.xscale / 2 min_lat = center_lat - win_height / self.yscale / 2 max_lat = center_lat + win_height / self.yscale / 2 if (self.Debug): print("Map from", min_lon, MapUtils.dec_deg2deg_min_str(min_lon), \ MapUtils.dec_deg2deg_min_str(min_lat), \ "to", MapUtils.dec_deg2deg_min_str(max_lon), \ MapUtils.dec_deg2deg_min_str(max_lat)) # Start from the upper left: min_lon, max_lat # pdb.set_trace() curlat = max_lat cur_y = 0 y_maplet_name = None initial_x_off = None while cur_y < win_height: curlon = min_lon cur_x = 0 x_maplet_name = None while cur_x < win_width: # Reset the expected image size: w = self.img_width h = self.img_height # Is it the first maplet in this row? if x_maplet_name is None: # Is it the first maplet in the map -- # usually the one in the upper left corner? # Then we need to specify coordinates. if y_maplet_name is None: pixbuf, x_off, y_off, x_maplet_name = \ self.get_maplet(curlon, curlat) # Save the x offset: we'll need it for the # beginning of each subsequent row. initial_x_off = x_off # Not upper left corner -- # must be the beginning of a new row. # Get the maplet below the beginning of the last row. else: pixbuf, x_maplet_name = \ self.get_next_maplet(y_maplet_name, 0, 1) x_off = initial_x_off y_off = 0 # Either way, whether or not we got a pixbuf, # if we're at the beginning of a row, save the # beginning-of-row maplet name and the offset: if cur_x == 0: y_maplet_name = x_maplet_name # Continuing an existing row. # Get the maplet to the right of the last one. else: pixbuf, x_maplet_name = self.get_next_maplet( x_maplet_name, 1, 0) x_off = 0 if self.Debug: print(" ", x_maplet_name) x = cur_x y = cur_y w, h = self.draw_tile_at_position(pixbuf, mapwin, x, y, x_off, y_off) # You may ask, why not just do this subtraction before # draw_pixbuf so we don't have to subtract w and h twice? # Alas, we may not have the real w and h until we've done # pixbuf.get_width(), so we'd be subtracting the wrong thing. # XXX Not really true any more, since we're assuming fixed # XXX tile size. Revisit this! cur_x += w curlon += float(w) / self.xscale if (self.Debug): print(" ") print("New row: adding y =", h, end=' ') print("Subtracting lat", float(h) / self.yscale) cur_y += h curlat -= float(h) / self.yscale # curlat -= float(self.img_height) / self.yscale # Free all pixbuf data. Just letting pixbuf go out of scope # isn't enough; it's necessary to force garbage collection # otherwise Python will let the process grow until it # fills all of memory. # http://www.daa.com.au/pipermail/pygtk/2003-December/006499.html # (At this indentation level, we free after drawing the whole map.) gc.collect()
def parse_args(self, mapwin, args): """Parse runtime arguments.""" args = args[1:] while len(args) > 0: if args[0][0] == '-' and not args[0][1].isdigit(): if args[0] == "-v" or args[0] == "--version": print self.get_version() sys.exit(0) elif args[0] == "-h" or args[0] == "--help": self.Usage() # Next clause is impossible because of the prev isdigit check: # if args[0] == "-15": # series = 15 elif args[0] == "-p": self.print_sites() elif args[0] == "-c": # Specify a collection: if len(args) < 2: print "-c must specify collection" self.Usage() mapwin.collection = self.find_collection(args[1]) if mapwin.collection is None: self.error_out("Can't find a map collection called " + args[1]) # Start initially at top left, but subsequent args # may change this: mapwin.center_lon, mapwin.center_lat = \ mapwin.collection.get_top_left() if (self.Debug): print "Collection", mapwin.collection.name, print "Starting at", \ MapUtils.dec_deg2deg_min_str(mapwin.center_lon), \ ", ", \ MapUtils.dec_deg2deg_min_str(mapwin.center_lat) args = args[1:] elif args[0] == "-d": self.Debug = True elif args[0] == "-r": self.reload_tiles = time.time() elif args[0] == "-t" and len(args) > 1: if mapwin.trackpoints is None: mapwin.trackpoints = TrackPoints() # Is it a known track? for tr in self.KnownTracks: if args[1] == tr[0]: if self.Debug: print "Reading known track", tr[0], tr[1] args[1] = tr[1] break try: mapwin.trackpoints.read_track_file(args[1]) except IOError: print "Can't read track file", args[1] args = args[1:] else: self.error_out("Unknown flag " + args[0]) # Done processing this flag args = args[1:] continue # args[0] doesn't start with '-'. Is it a track file? if args[0].endswith(".gpx") \ or args[0].endswith(".kml") \ or args[0].endswith(".kmz") \ or args[0].endswith("json"): try: if mapwin.trackpoints: mapwin.trackpoints.read_track_file(args[0]) else: trackpoints = TrackPoints() trackpoints.read_track_file(args[0]) mapwin.trackpoints = trackpoints except IOError: print "Can't read track file", args[0] except xml.parsers.expat.ExpatError: print "Can't read %s: syntax error." % args[0] if args[0].lower().endswith(".kml") or \ args[0].lower().endswith(".kmz"): print """ Is this a KML made with ArcGIS? It may have an illegal xsi:schemaLocation. If so, try changing xsi:schemaLocation to just schemaLocation.""" args = args[1:] continue # Try to match a known site: for site in self.KnownSites: if args[0] == site[0]: if not self.use_site(site, mapwin): continue break if mapwin.collection and mapwin.center_lon and mapwin.center_lat: args = args[1:] continue # Doesn't match a known site. Maybe the args are coordinates? try: if len(args) >= 2 and \ len(args[0]) > 1 and args[0][1].isdigit() and \ len(args[1]) > 1 and args[1][1].isdigit(): mapwin.center_lon = MapUtils.deg_min2dec_deg(float(args[0])) mapwin.center_lat = MapUtils.deg_min2dec_deg(float(args[2])) mapwin.collection = self.find_collection(args[3]) args = args[2:] continue print "Can't make sense of argument:", args[0] self.Usage() except ValueError: print "Couldn't parse coordinates" self.Usage() # If we get here, we still have an argument but it doesn't # match anything we know: flag, collection, site or coordinate. print "Problem parsing arguments. Remaining args:", args self.Usage() # Now we've parsed all the arguments. # If we didn't get a collection, use the default, if any: if not mapwin.collection and self.default_collection: mapwin.collection = self.find_collection(self.default_collection) # If we have a collection and a track but no center point, # center it on the trackpoints, and set scale appropriately: if mapwin.trackpoints is not None and mapwin.collection is not None \ and not (mapwin.center_lat and mapwin.center_lon): minlon, minlat, maxlon, maxlat = mapwin.trackpoints.get_bounds() mapwin.center_lon = (maxlon + minlon) / 2 mapwin.center_lat = (maxlat + minlat) / 2 mapwin.collection.zoom_to_bounds(minlon, minlat, maxlon, maxlat) if self.reload_tiles and 'set_reload_tiles' in dir(mapwin.collection): mapwin.collection.set_reload_tiles(self.reload_tiles) elif self.reload_tiles: print "Collection can't re-download tiles" # By now, we hope we have the mapwin positioned with a collection # and starting coordinates: if mapwin.collection and mapwin.center_lon and mapwin.center_lat: return # Didn't match any known run mode: # start in GUI mode choosing a location: if not mapwin.selection_window(): sys.exit(0)
def parse_args(self, mapwin, args): """Parse runtime arguments.""" args = args[1:] while len(args) > 0: if args[0][0] == '-' and not args[0][1].isdigit(): if args[0] == "-v" or args[0] == "--version": print self.get_version() sys.exit(0) elif args[0] == "-h" or args[0] == "--help": self.Usage() # Next clause is impossible because of the prev isdigit check: # if args[0] == "-15": # series = 15 elif args[0] == "-p": self.print_sites() elif args[0] == "-c": # Specify a collection: if len(args) < 2: print "-c must specify collection" self.Usage() mapwin.collection = self.find_collection(args[1]) if mapwin.collection is None: self.error_out("Can't find a map collection called " + args[1]) # Start initially at top left, but subsequent args # may change this: mapwin.center_lon, mapwin.center_lat = \ mapwin.collection.get_top_left() if (self.Debug): print "Collection", mapwin.collection.name, print "Starting at", \ MapUtils.dec_deg2deg_min_str(mapwin.center_lon), \ ", ", \ MapUtils.dec_deg2deg_min_str(mapwin.center_lat) args = args[1:] elif args[0] == "-d": self.Debug = True print "Debugging on" elif args[0] == "-r": self.reload_tiles = time.time() elif args[0] == "-t" and len(args) > 1: if mapwin.trackpoints is None: mapwin.trackpoints = TrackPoints() # Is it a known track? for tr in self.KnownTracks: if args[1] == tr[0]: if self.Debug: print "Reading known track", tr[0], tr[1] args[1] = tr[1] break try: mapwin.trackpoints.read_track_file(args[1]) except IOError: print "Can't read track file", args[1] args = args[1:] else: self.error_out("Unknown flag " + args[0]) # Done processing this flag args = args[1:] continue # args[0] doesn't start with '-'. Is it a track file? if args[0].endswith(".gpx") \ or args[0].endswith(".kml") \ or args[0].endswith(".kmz") \ or args[0].endswith("json"): try: if mapwin.trackpoints: mapwin.trackpoints.read_track_file(args[0]) else: trackpoints = TrackPoints() trackpoints.read_track_file(args[0]) mapwin.trackpoints = trackpoints except IOError: print "Can't read track file", args[0] except xml.parsers.expat.ExpatError: print "Can't read %s: syntax error." % args[0] if args[0].lower().endswith(".kml") or \ args[0].lower().endswith(".kmz"): print """ Is this a KML made with ArcGIS? It may have an illegal xsi:schemaLocation. If so, try changing xsi:schemaLocation to just schemaLocation.""" args = args[1:] continue # Try to match a known site: for site in self.KnownSites: if args[0] == site[0]: if not self.use_site(site, mapwin): continue break if mapwin.collection and mapwin.center_lon and mapwin.center_lat: args = args[1:] continue # Doesn't match a known site. Maybe the args are coordinates? try: if len(args) >= 2 and \ len(args[0]) > 1 and args[0][1].isdigit() and \ len(args[1]) > 1 and args[1][1].isdigit(): mapwin.center_lon = MapUtils.deg_min2dec_deg(float( args[0])) mapwin.center_lat = MapUtils.deg_min2dec_deg(float( args[2])) mapwin.collection = self.find_collection(args[3]) args = args[2:] continue print "Can't make sense of argument:", args[0] args = args[1:] continue except ValueError: print "Couldn't parse coordinates" self.Usage() # If we get here, we still have an argument but it doesn't # match anything we know: flag, collection, site or coordinate. print "Problem parsing arguments. Remaining args:", args self.Usage() # Now we've parsed all the arguments. # If we didn't get a collection, use the default, if any: if not mapwin.collection and self.default_collection: mapwin.collection = self.find_collection(self.default_collection) mapwin.collection.Debug = self.Debug # If we have a collection and a track but no center point, # center it on the trackpoints, and set scale appropriately: if mapwin.trackpoints is not None and mapwin.collection is not None \ and not (mapwin.center_lat and mapwin.center_lon): minlon, minlat, maxlon, maxlat = mapwin.trackpoints.get_bounds() mapwin.center_lon = (maxlon + minlon) / 2 mapwin.center_lat = (maxlat + minlat) / 2 mapwin.collection.zoom_to_bounds(minlon, minlat, maxlon, maxlat) if self.reload_tiles and 'set_reload_tiles' in dir(mapwin.collection): mapwin.collection.set_reload_tiles(self.reload_tiles) elif self.reload_tiles: print "Collection can't re-download tiles" # By now, we hope we have the mapwin positioned with a collection # and starting coordinates: if mapwin.collection and mapwin.center_lon and mapwin.center_lat: return # Didn't match any known run mode: # start in GUI mode choosing a location: if not mapwin.selection_window(): sys.exit(0)