示例#1
0
 def get_visible_area(self):
     a = self.screenpoint2coord((0, 0))
     b = self.screenpoint2coord((self.map_width, self.map_height))
     return geo.Coordinate(min(a.lat, b.lat), min(a.lon,
                                                  b.lon)), geo.Coordinate(
                                                      max(a.lat, b.lat),
                                                      max(a.lon, b.lon))
示例#2
0
    def fit_to_bounds(self, minlat, maxlat, minlon, maxlon):
        if minlat == maxlat and minlon == maxlon:
            self.set_center(geo.Coordinate(minlat, minlon))
            self.set_zoom(self.get_max_zoom())
            return
        logger.debug("Settings Bounds: lat(%f, %f) lon(%f, %f)" %
                     (minlat, maxlat, minlon, maxlon))
        req_deg_per_pix_lat = (maxlat - minlat) / self.map_height
        prop_zoom_lat = math.log(
            ((180.0 / req_deg_per_pix_lat) / self.tile_loader.TILE_SIZE), 2)

        req_deg_per_pix_lon = (maxlon - minlon) / self.map_width
        prop_zoom_lon = math.log(
            ((360.0 / req_deg_per_pix_lon) / self.tile_loader.TILE_SIZE), 2)

        target_zoom = math.floor(min(prop_zoom_lat, prop_zoom_lon))
        logger.debug(
            "Proposed zoom lat: %f, proposed zoom lon: %f, target: %f" %
            (prop_zoom_lat, prop_zoom_lon, target_zoom))

        center = geo.Coordinate((maxlat + minlat) / 2.0,
                                (maxlon + minlon) / 2.0)
        logger.debug("New Center: %s" % center)

        self.set_center(center, False)
        self.set_zoom(
            max(min(target_zoom, self.get_max_zoom()), self.get_min_zoom()))
示例#3
0
    def fix_from_tuple(self, f, device):
        a = Fix()
        # check if this is an actual fix
        if (not f[1] &
            (location.GPS_DEVICE_LATLONG_SET | location.GPS_DEVICE_ALTITUDE_SET
             | location.GPS_DEVICE_TRACK_SET)):
            return a

        if f[0] in (location.GPS_DEVICE_MODE_NOT_SEEN,
                    location.GPS_DEVICE_MODE_NO_FIX):
            return a

        # location independent data
        a.sats = device.satellites_in_use
        a.sats_known = device.satellites_in_view
        a.dgps = False  #LOCATION_GPS_DEVICE_STATUS_DGPS_FIX The device has a DGPS fix. Deprecated: this constant is not used anymore.
        a.quality = 0

        # if this fix is too old, discard it
        if f[2] == f[2]:  # is not NaN
            a.timestamp = datetime.utcfromtimestamp(f[2])
        else:
            a.timestamp = datetime.utcfromtimestamp(0)

        Fix.min_timediff = min(Fix.min_timediff,
                               datetime.utcnow() - a.timestamp)
        # if this fix is too old, discard it
        if ((datetime.utcnow() - a.timestamp) -
                Fix.min_timediff).seconds > LocationGpsReader.TIMEOUT:
            logger.info(
                "Discarding fix: Timestamp diff is %d, should not be > %d" %
                (((datetime.utcnow() - a.timestamp) -
                  Fix.min_timediff).seconds, LocationGpsReader.TIMEOUT))
            return a

        # now on for location dependent data
        #if f[10] > Fix.BEARING_HOLD_EPD:
        #    a.bearing = Fix.last_bearing
        #else:
        a.altitude = f[7]
        a.speed = f[11]
        if a.speed > self.BEARING_HOLD_SPEED:
            a.bearing = f[9]
            self.last_gps_bearing = a.bearing
        else:
            a.bearing = self.last_gps_bearing

        #    Fix.last_bearing = a.bearing
        a.position = geo.Coordinate(f[4], f[5])

        a.error = f[6] / 100.0
        a.error_bearing = f[10]

        return a
示例#4
0
    def search(self, search, nearest_street=False):
        logger.info("Trying to search geonames for %s" % search)
        qurl = self.URL % {'query': self.my_quote(search), 'max_rows': 1}
        logger.debug("Query URL: %s" % qurl)
        page = self.downloader.get_reader(url=qurl, login=False).read()
        values = json.loads(page)
        if int(values['totalResultsCount']) == 0:
            raise Exception('No Record found for query "%s"' % search)
        res = values['geonames'][0]
        c = geo.Coordinate(float(res['lat']), float(res['lng']), search)

        logger.info("Using %s for query '%s'" % (c, search))
        return c
示例#5
0
 def find_nearest_intersection(self, c):
     logger.info("trying to find nearest street...")
     url = self.URL_STREETS % (c.lat, c.lon)
     page = self.downloader.get_reader(url, login=False).read()
     values = json.loads(page)
     if (len(values) == 0):
         logger.warning(
             "Could NOT find nearest intersection to %s, using this" % c)
         return c
     intersection = values['intersection']
     c = geo.Coordinate(float(intersection['lat']),
                        float(intersection['lng']))
     logger.info("Using nearest intersection at %s" % c)
     return c
示例#6
0
 def search_all(self,
                search,
                max_results=15,
                name_string="%(name)s, %(countryCode)s"):
     logger.info("Trying to search geonames for %s" % search)
     qurl = self.URL % {
         'query': self.my_quote(search),
         'max_rows': max_results
     }
     logger.debug("Query URL: %s" % qurl)
     page = self.downloader.get_reader(url=qurl, login=False).read()
     logger.debug("Result:\n%s\n" % page)
     values = json.loads(page)
     return [
         geo.Coordinate(float(res['lat']), float(res['lng']),
                        name_string % res) for res in values['geonames']
         if 'countryCode' in res
     ]
示例#7
0
    def find_route(self, c1, c2, min_distance):
        page = self.downloader.get_reader(url=self.ORS_URL,
                                          values=self.ORS_DATA %
                                          (c1.lon, c1.lat, c2.lon, c2.lat),
                                          login=False).read()
        import xml.dom.minidom
        from xml.dom.minidom import Node
        doc = xml.dom.minidom.parseString(page)
        # @type doc xml.dom.minidom.Document
        errors = doc.getElementsByTagName('xls:Error')
        if len(errors) > 0:
            if errors[0].getAttribute(
                    'locationPath') == 'PathFinder - getPath()':
                raise Exception(
                    "Could not find route. Please try another street as start or endpoint. The server said: ''%s''\n"
                    % errors[0].getAttribute('message'))
            raise Exception("Could not find route. The server said: ''%s''\n" %
                            errors[0].getAttribute('message'))
        segments = doc.getElementsByTagName('gml:LineString')
        route_points = []

        # min_distance is in km, we need m
        mdist = (min_distance * 1000.0) / self.DIST_FACTOR

        for s in segments:
            for p in s.childNodes:
                if p.nodeType != Node.ELEMENT_NODE:
                    continue
                lon, tmp, lat = p.childNodes[0].data.partition(' ')
                c = geo.Coordinate(float(lat), float(lon))
                stop = False
                for o in route_points:
                    if c.distance_to(o) < mdist:
                        stop = True
                        break
                if not stop:
                    route_points.append(c)

                if len(route_points) > self.MAX_NODES:
                    raise Exception("Too many waypoints! Try a bigger radius.")
        logger.info("Using the following Waypoints:")
        return route_points
示例#8
0
    def get_data(self):
        import random
        if self.index < len(self.data) - 1:
            self.index += 1
        if self.data[self.index][0] == '0':
            return Fix()
        pos = geo.Coordinate(float(self.data[self.index][0]),
                             float(self.data[self.index][1]))

        if self.lastpos != None:
            bearing = self.lastpos.bearing_to(pos)
        else:
            bearing = 0
        self.lastpos = pos
        return Fix(position=pos,
                   altitude=5,
                   bearing=bearing,
                   speed=4,
                   sats=12,
                   sats_known=6,
                   dgps=True,
                   quality=0,
                   error=random.randrange(10, 100),
                   error_bearing=10)
示例#9
0
 def get_target():
     return geo.Coordinate(50.0000798795372000, 6.9949468020349700)
示例#10
0
    def get_data(self):
        try:
            if not self.connected:
                self.connect()
                if not self.connected:
                    return self.EMPTY
            self.gpsd_connection.send("%s\r\n" % 'o')
            data = self.gpsd_connection.recv(512)
            self.gpsd_connection.send("%s\r\n" % 'y')
            quality_data = self.gpsd_connection.recv(512)
            # 1: Parse Quality Data

            # example output:
            # GPSD,Y=- 1243847265.000 10:32 3 105 0 0:2 36 303 20 0:16 9 65 26
            #  1:13 87 259 35 1:4 60 251 30 1:23 54 60 37 1:25 51 149 24 0:8 2
            #  188 0 0:7 33 168 24 1:20 26 110 28 1:
            if quality_data.strip() == "GPSD,Y=?":
                sats = 0
                sats_known = 0
                dgps = False
            else:
                sats = 0
                dgps = False
                groups = quality_data.split(':')
                sats_known = int(groups[0].split(' ')[2])
                for i in xrange(1, sats_known):
                    sat_data = groups[i].split(' ')
                    if sat_data[4] == "1":
                        sats = sats + 1
                    if int(sat_data[0]) > 32:
                        dgps = True

            if data.strip() == "GPSD,O=?":
                self.status = "No GPS signal"
                return Fix(sats=sats, sats_known=sats_known, dgps=dgps)

            # 2: Get current position, altitude, bearing and speed

            # example output:
            # GPSD,O=- 1243530779.000 ? 49.736876 6.686998 271.49 1.20 1.61 49.8566 0.050 -0.175 ? ? ? 3
            # GPSD,O=- 1251325613.000 ? 49.734453 6.686360 ? 10.55 ? 180.1476 1.350 ? ? ? ? 2
            # that means:
            # [tag, timestamp, time_error, lat, lon, alt, err_hor, err_vert, track, speed, delta_alt, err_track, err_speed, err_delta_alt, mode]
            #  0    1          2           3    4    5    6        7         8      9      10         11         12         13             14
            # or
            # GPSD,O=?
            try:
                splitted = data.split(' ')
                lat, lon, alt, err_hor = splitted[3:7]
                track, speed = splitted[8:10]
                err_track = splitted[11]
                time = datetime.utcfromtimestamp(int(float(splitted[1])))
            except:
                logger.info("GPSD Output: \n%s\n  -- cannot be parsed." % data)
                self.status = "Could not read GPSD output."
                return Fix()
            alt = self.to_float(alt)
            track = self.to_float(track)
            speed = self.to_float(speed)
            err_hor = self.to_float(err_hor)
            err_track = self.to_float(err_track)

            # the following is probably wrong:
            #
            # it seems that gpsd doesn't take into account that the
            # receiver may get signals from space base augmentation systems
            # like egnos. therefore, we estimate that the error is about
            # self.DGPS_ADVANTAGE meters lower. this is a complete guess.

            if dgps:
                err_hor -= self.DGPS_ADVANTAGE

            if err_hor <= 0:
                quality = 1
            elif err_hor > self.QUALITY_LOW_BOUND:
                quality = 0
            else:
                quality = 1 - err_hor / self.QUALITY_LOW_BOUND

            # enable this to track speeds and see the max speed
            #self.speeds.append(speed)
            #print "Aktuell %f, max: %f" % (speed, max(self.speeds))

            return Fix(position=geo.Coordinate(float(lat), float(lon)),
                       altitude=alt,
                       bearing=track,
                       speed=speed,
                       sats=int(sats),
                       sats_known=sats_known,
                       dgps=dgps,
                       quality=quality,
                       error=err_hor,
                       error_bearing=err_track,
                       timestamp=time)
        except Exception, e:
            logger.exception("Fehler beim Auslesen der Daten: %s " % e)
            return self.EMPTY
示例#11
0
    def draw(self):
        surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self.map.map_width, self.map.map_height)
        cr = gtk.gdk.CairoContext(cairo.Context(surface))

        coords = self.get_geocaches_callback(self.map.get_visible_area(), self.MAX_NUM_RESULTS_SHOW)

        if self.map.get_zoom() < self.CACHES_ZOOM_LOWER_BOUND:
            self.map.set_osd_message('Zoom in to see geocaches.')
            self.visualized_geocaches = []
            self.result = surface
            return
        elif len(coords) >= self.MAX_NUM_RESULTS_SHOW:
            self.map.set_osd_message('Too many geocaches to display.')
            self.visualized_geocaches = []
            self.result = surface
            return
        self.map.set_osd_message(None)
        self.visualized_geocaches = coords
        draw_short = (len(coords) > self.TOO_MANY_POINTS)

        default_radius = self.CACHE_DRAW_SIZE
        found, regular, multi, default = self.COLOR_FOUND, self.COLOR_REGULAR, self.COLOR_MULTI, self.COLOR_DEFAULT



        for c in coords: # for each geocache
            radius = default_radius
            if c.found:
                color = found
            elif c.type == geocaching.GeocacheCoordinate.TYPE_REGULAR:
                color = regular
            elif c.type == geocaching.GeocacheCoordinate.TYPE_MULTI:
                color = multi
            else:
                color = default
            cr.set_source_color(color)


            p = self.map.coord2point(c)

            if c.alter_lat != None and (c.alter_lat != 0 and c.alter_lon != 0):
                x = self.map.coord2point(geo.Coordinate(c.alter_lat, c.alter_lon))
                if x != p:
                    cr.move_to(p[0], p[1])
                    cr.line_to(x[0], x[1])
                    cr.set_line_width(2)
                    cr.stroke()

            if draw_short:
                radius = radius / 2.0

            if c.marked:
                cr.set_source_rgba(1, 1, 0, 0.5)
                cr.rectangle(p[0] - radius, p[1] - radius, radius * 2, radius * 2)
                cr.fill()


            cr.set_source_color(color)
            cr.set_line_width(4)
            cr.rectangle(p[0] - radius, p[1] - radius, radius * 2, radius * 2)
            cr.stroke()

            if draw_short:
                continue




            # if we have a description for this cache...
            if c.was_downloaded():
                # draw something like:
                # ----
                # ----
                # ----
                # besides the icon
                width = 6
                dist = 3
                count = 3
                pos_x = p[0] + radius + 3 + 1
                pos_y = p[1] + radius - (dist * count) + dist
                cr.set_line_width(1)
                for i in xrange(count):
                    cr.move_to(pos_x, pos_y + dist * i)
                    cr.line_to(pos_x + width, pos_y + dist * i)
                    cr.set_line_width(2)
                cr.stroke()

            # if this cache is the active cache
            if self.current_cache != None and c.name == self.current_cache.name:
                cr.set_line_width(1)
                cr.set_source_color(self.COLOR_CURRENT_CACHE)
                #radius = 7
                radius_outline = radius + 3
                cr.rectangle(p[0] - radius_outline, p[1] - radius_outline, radius_outline * 2, radius_outline * 2)
                cr.stroke()

            # if this cache is disabled
            if c.status == geocaching.GeocacheCoordinate.STATUS_DISABLED:
                cr.set_line_width(3)
                cr.set_source_color(self.COLOR_DISABLED)
                radius_disabled = 7
                cr.move_to(p[0]-radius_disabled, p[1]-radius_disabled)
                cr.line_to(p[0] + radius_disabled, p[1] + radius_disabled)
                cr.stroke()

            # if this cache is archived
            if c.status == geocaching.GeocacheCoordinate.STATUS_ARCHIVED:
                cr.set_line_width(3)
                cr.set_source_color(self.COLOR_ARCHIVED)
                radius_disabled = 7
                cr.move_to(p[0]-radius_disabled, p[1]-radius_disabled)
                cr.line_to(p[0] + radius_disabled, p[1] + radius_disabled)
                cr.stroke()


            # print the name?
            if self.show_name:
                layout = self.map.create_pango_layout(AbstractGeocacheLayer.shorten_name(c.title, 20))
                layout.set_font_description(self.CACHE_DRAW_FONT)
                width, height = layout.get_pixel_size()

                cr.move_to(p[0] + 4 + radius, p[1] - height + 2)
                #cr.set_line_width(1)
                cr.set_source_color(self.CACHE_DRAW_FONT_COLOR)
                cr.show_layout(layout)

            cr.set_source_color(self.COLOR_CACHE_CENTER)
            cr.set_line_width(1)
            cr.move_to(p[0], p[1] - 3)
            cr.line_to(p[0], p[1] + 3) # |
            cr.move_to(p[0] - 3, p[1],)
            cr.line_to(p[0] + 3, p[1]) # ---
            cr.stroke()

        # draw additional waypoints
        # --> print description!
        if self.current_cache != None:
            cr.set_source_color(self.COLOR_WAYPOINTS)
            cr.set_line_width(1)
            radius = 5
            num = 0
            seen = ["%9.6f %9.6f" % (self.current_cache.lat, self.current_cache.lon)]
            
            for w in self.current_cache.get_collected_coordinates(format = self.current_cache.FORMAT_DM, include_unknown = False).values():
                text = "%9.6f %9.6f" % (w.lat, w.lon)
                if text in seen:
                    continue
                seen.append(text)
                num = num + 1
                p = self.map.coord2point(w)
                if not self.map.point_in_screen(p):
                    continue
                cr.move_to(p[0], p[1] - radius)
                cr.line_to(p[0], p[1] + radius) #  |
                #cr.stroke()
                cr.move_to(p[0] - radius, p[1])
                cr.line_to(p[0] + radius, p[1]) # ---
                #cr.stroke()
                cr.arc(p[0], p[1], radius, 0, math.pi * 2)
                layout = self.map.create_pango_layout('')
                layout.set_markup('<i>%s</i>' % (self.shorten_name(w.display_text, 25)))
                layout.set_font_description(self.CACHE_DRAW_FONT)

                cr.move_to(p[0] + 3 + radius, p[1] - 3 - radius)
                #cr.set_line_width(1)
                cr.set_source_color(self.COLOR_WAYPOINTS)
                cr.show_layout(layout)
            cr.stroke()
        self.result = surface
示例#12
0
 def num2deg(self, xtile, ytile):
     n = 2**self.zoom
     lon_deg = xtile / n * 360.0 - 180.0
     lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * ytile / n)))
     lat_deg = lat_rad * 180.0 / math.pi
     return geo.Coordinate(lat_deg, lon_deg)