Пример #1
0
    def __init__(self, fname):
        # to be filled now...
        self.__authorName = "Unknown author"
        self.__authorLinks = set()  # all links associated with the author
        self.__trackName = "Unnamed track"
        self.__trackLinks = set(
        )  # all links associated with the track in general
        self.__trackCoords = list()
        self.__maxElevation = None  # maximum elevation in feet. none if unknown.

        # read and parse the xml file
        xml_data = xml.etree.ElementTree.parse(fname)
        xml_root = xml_data.getroot()
        xml_namespace = xml_root.tag.split("}")[0].strip("{}")
        xml_namespace = {"": xml_namespace}

        # collect the metadata
        track_name_node = xml_data.find("./metadata/name", xml_namespace)
        if not track_name_node is None:
            self.__trackName = track_name_node.text
        track_link_nodes = xml_data.findall("./metadata/link", xml_namespace)
        for node in track_link_nodes:
            self.__trackLinks.add(node.attrib["href"])
        author_name_node = xml_data.find("./metadata/author/name",
                                         xml_namespace)
        if not author_name_node is None:
            self.__authorName = author_name_node.text
        author_link_nodes = xml_data.findall("./metadata/author/link",
                                             xml_namespace)
        for node in author_link_nodes:
            self.__authorLinks.add(node.attrib["href"])

        # choose track point nodes
        track_point_nodes = _choose_track_point_nodes(
            xml_data.findall("./trk/trkseg", xml_namespace), xml_namespace)

        # collect the track coordinates
        if len(track_point_nodes) > 1:
            for node in track_point_nodes:
                # raw coordinates as strings
                lat = node.attrib["lat"]
                lon = node.attrib["lon"]

                # parse the coordinates
                lat = LatLon23.Latitude(float(lat))
                lon = LatLon23.Longitude(float(lon))
                coord = LatLon23.LatLon(lat, lon)

                # append the coordinates
                self.__trackCoords.append(coord)

                # elevation in this point?
                elevation_node = node.find("ele", xml_namespace)
                if not elevation_node is None:
                    if self.__maxElevation is None:
                        self.__maxElevation = 0.0
                    elevation = float(elevation_node.text)
                    self.__maxElevation = max(self.__maxElevation, elevation)
Пример #2
0
def routagePointDistance (latA, lonA, distance, hdg, unit='nm'):
	""" Returns the point from (latA, lonA) to the given (distance, hdg) """
	if unit == 'nm':
		d = nm2km(distance)
	elif unit == 'km':
		d = distance

	p = LatLon23.LatLon(LatLon23.Latitude(latA), LatLon23.Longitude(lonA))
	of = p.offset (math.degrees (hdg), d).to_string('D')
	return (float (of[0]), float (of[1]))
Пример #3
0
    def find_nearest(self, lat, lon):
        # convert to integers
        lat_idx = int(lat + 180.0)
        lon_idx = int(lon + 180.0)
        assert lat_idx >= 0 and lon_idx >= 0

        # find candidate airports
        lat_cands = set()
        lon_cands = set()
        for offset in range(-3, +4):
            # find candidates with latitude offset
            cand_idx = (lat_idx + offset) % 360
            if not self.__idxLat[cand_idx] is None:
                lat_cands.update(self.__idxLat[cand_idx])

            # find candidates with longitude offset
            cand_idx = (lon_idx + offset) % 360
            if not self.__idxLon[cand_idx] is None:
                lon_cands.update(self.__idxLon[cand_idx])
        cands = lat_cands.intersection(lon_cands)

        # target coordiate
        target_coord = LatLon23.LatLon(lat, lon)
        nearest_icao = None
        nearest_dist = 999999999.999

        # check all the candidates
        for icao in cands:
            # candidate coordinate
            info = self.__airportDict[icao]
            cand_coord = LatLon23.LatLon(info["lat"], info["lon"])

            # distance to the candidate
            dist = target_coord.distance(cand_coord)

            # smaller distance?
            if dist < nearest_dist:
                nearest_icao = icao
                nearest_dist = dist

        # retrieve information about the nearest airport
        info = self.__airportDict[nearest_icao]
        if not info["local_code"] is None:
            # TODO: need to figure out when to use the local code and when not
            nearest_icao = info["local_code"]
        nearest_lat = info["lat"]
        nearest_lon = info["lon"]
        nearest_ele = info["elevation"]
        nearest_name = info["name"]

        # finished
        return nearest_icao, nearest_lat, nearest_lon, int(
            nearest_ele), nearest_name
def parse_location(raw):
    raw = raw.strip()
    utm_mo = re.fullmatch(UTM_REGEX, raw)
    with contextlib.suppress(ValueError):
        if utm_mo:
            gps = utm.to_latlon(int(utm_mo[3]), int(utm_mo[4]), int(utm_mo[1]),
                                utm_mo[2])
            latlon = LatLon23.LatLon(gps[0], gps[1])
        else:
            _, lat, lon = raw.split()
            latlon = LatLon23.string2latlon(lat, lon, 'd%°%m%\'%S%"%H')
        return latlon
    return None
Пример #5
0
    def __next__(self):
        outsideCircle = True
        while outsideCircle:
            # TODO: Change of hemisphere ?
            self.lon_min += 0.001
            if self.lon_min >= 60.0:
                self.lon_min = 0.0
                # TODO: something's wrong here
                self.lon_deg += 1
            coord_lon = f'{self.lon_hemi} {self.lon_deg} {self.lon_min}'
            self.lon = LatLon23.string2geocoord(coord_lon, LatLon23.Longitude,
                                                'H% %d% %M')
            # TODO: Fix mess between lat and lon
            # TODO: no need of decimal degree in next line ???
            if self.lon.decimal_degree >= self.border_east.decimal_degree:
                self.lon = self.border_west
                self.lon_min = int(
                    self.border_west.decimal_minute * 1000) / 1000
                self.lon_deg = int(self.border_west.degree)
                self.lat_min += 0.001
                if self.lat_min >= 60.0:
                    self.lat_min = 0.0
                    self.lat_deg += 1
            # TODO: if latitude reaches border_north: raise StopIteration()
            coord_lat = f'{self.lat_hemi} {self.lat_deg} {self.lat_min}'
            self.lat = LatLon23.string2geocoord(coord_lat, LatLon23.Latitude,
                                                'H% %d% %M')
            if self.lat.decimal_degree > self.border_north.decimal_degree:
                raise StopIteration()
            self.point = LatLonGC(self.lat, self.lon)

            distance = self.point.distance(self.center)
            outsideCircle = distance > self.radius

        self.pointchecker = self.to_gc()
        # distance = self.point.distance(self.center)
        # print(distance, '  ', self.point)
        '''
        if self.lon_min > self.border_east:
            self.lon_min = self.border_west
            self.lat_min += 0.001
        '''
        # return (self.to_gc(), distance)
        # return (self.to_gc())
        return (self.point, self.pointchecker)
Пример #6
0
def douglas_peucker(coords, max_leg_length):
    # convert to a numpy array
    np_coords = np.empty((len(coords),2), dtype=np.float32)
    for i in range(len(coords)):
        np_coords[i,0] = float(coords[i].lat)
        np_coords[i,1] = float(coords[i].lon)
    
    # subdivide the polygon
    for _ in range(5):
        np_coords = skimage.measure.subdivide_polygon(np_coords, degree=2, preserve_ends=True)
    
    # approximate the polygon
    np_coords = skimage.measure.approximate_polygon(np_coords, tolerance=0.1)

    # convert back
    coords = list()
    for i in range(np_coords.shape[0]):
        c = LatLon23.LatLon(float(np_coords[i,0]), float(np_coords[i,1]))
        coords.append(c)
    
    # split into legs
    legs = list()
    cur_leg = [coords[0]]
    cur_len = 0.0
    for c in coords[1:]:
        assert type(c) == LatLon23.LatLon
        last_coord = cur_leg[-1]
        last_dist = c.distance(last_coord)
        new_len = cur_len + last_dist
        if new_len > max_leg_length:
            new_over = new_len - max_leg_length
            cur_under = max_leg_length - cur_len
            if new_over < cur_under:
                cur_leg.append(c)
                legs.append(cur_leg)
                cur_leg = [c]
                cur_len = 0.0
            else:
                legs.append(cur_leg)
                cur_leg = [last_coord, c]
                cur_len = last_dist
        else:
            cur_len = new_len
            cur_leg.append(c)
    if len(cur_leg) > 1:
        legs.append(cur_leg)
    
    # finished
    return legs
Пример #7
0
def pointDistance (latA, lonA, latB, lonB, unit='nm'):
	""" Returns the distance between two geo points """
	p1 = LatLon23.LatLon(LatLon23.Latitude(latA), LatLon23.Longitude(lonA))
	p2 = LatLon23.LatLon(LatLon23.Latitude(latB), LatLon23.Longitude(lonB))
	d = p1.distance (p2)

	if unit == 'nm':
		return km2nm(d)
	elif unit == 'km':
		return d
Пример #8
0
def _distance_between_points(track_point_node_A, track_point_node_B):
    # first node
    lat = LatLon23.Latitude(float(track_point_node_A.attrib["lat"]))
    lon = LatLon23.Longitude(float(track_point_node_A.attrib["lon"]))
    coord_A = LatLon23.LatLon(lat, lon)

    # second node
    lat = LatLon23.Latitude(float(track_point_node_B.attrib["lat"]))
    lon = LatLon23.Longitude(float(track_point_node_B.attrib["lon"]))
    coord_B = LatLon23.LatLon(lat, lon)

    # finished
    return coord_A.distance(coord_B)
Пример #9
0
def _heading_of_track_segment(track_point_nodes, xml_namespace):
    # first node
    lat = LatLon23.Latitude(float(track_point_nodes[0].attrib["lat"]))
    lon = LatLon23.Longitude(float(track_point_nodes[0].attrib["lon"]))
    start = LatLon23.LatLon(lat, lon)

    # last node
    lat = LatLon23.Latitude(float(track_point_nodes[-1].attrib["lat"]))
    lon = LatLon23.Longitude(float(track_point_nodes[-1].attrib["lon"]))
    end = LatLon23.LatLon(lat, lon)

    # heading calculation and finish
    return start.heading_initial(end)
Пример #10
0
def _length_of_track_segment(track_point_nodes, xml_namespace):
    # sum up the distance
    distance = 0.0
    for i in range(1, len(track_point_nodes)):
        # current node
        lat = LatLon23.Latitude(float(track_point_nodes[i].attrib["lat"]))
        lon = LatLon23.Longitude(float(track_point_nodes[i].attrib["lon"]))
        cur = LatLon23.LatLon(lat, lon)

        # previous node
        lat = LatLon23.Latitude(float(track_point_nodes[i - 1].attrib["lat"]))
        lon = LatLon23.Longitude(float(track_point_nodes[i - 1].attrib["lon"]))
        prev = LatLon23.LatLon(lat, lon)

        # add the distance
        distance += cur.distance(prev)

    # finished
    return distance
Пример #11
0
def _minimal_distance_to_track(new_point, existing_segment):
    # first node
    lat = LatLon23.Latitude(float(new_point.attrib["lat"]))
    lon = LatLon23.Longitude(float(new_point.attrib["lon"]))
    new_coord = LatLon23.LatLon(lat, lon)

    # find the minimum distance
    min_dist = 999999.999
    for node in existing_segment:
        # existing node
        lat = LatLon23.Latitude(float(node.attrib["lat"]))
        lon = LatLon23.Longitude(float(node.attrib["lon"]))
        existing_coord = LatLon23.LatLon(lat, lon)

        # distance
        dist = existing_coord.distance(new_coord)
        min_dist = min(min_dist, dist)

    # finished
    return min_dist
Пример #12
0
#11 - Velocity str
#12 - Course str
#13 - Valid GPS Fix bool
#14 - In Emergency bool
#15 - Text str
#16 - Event str

d = datetime.datetime.strptime(str(kml.Document.Folder.Placemark[0].TimeStamp.when),'%Y-%m-%dT%H:%M:%SZ')
aprs_timestamp = d.strftime("%d%H%Mz")

inreach_lat = round(float(kml.Document.Folder.Placemark[0].ExtendedData.Data[8].value),2)
# print(inreach_lat)
inreach_lon = round(float(kml.Document.Folder.Placemark[0].ExtendedData.Data[9].value),2)
# print(inreach_lon)

aprs_pos = LatLon23.LatLon( LatLon23.Latitude(inreach_lat), LatLon23.Longitude(inreach_lon))

lat_deg, lon_deg = aprs_pos.to_string('d%')
lat_mins, lon_mins = aprs_pos.to_string('M%')
lat_hem, lon_hem = aprs_pos.to_string('H%')
aprs_lat_mins = format(float(lat_mins),'.2f')
aprs_lon_mins = format(float(lon_mins),'.2f')

try:
    aprs_lat = lat_deg.replace("-","") + aprs_lat_mins + lat_hem
    # print(aprs_lat, len(aprs_lat))
    aprs_lon = lon_deg.replace("-","") + aprs_lon_mins + lon_hem
    # print(aprs_lon, len(aprs_lon))
    assert len(aprs_lat)<=8
    assert len(aprs_lat)<=9
except AssertionError:
Пример #13
0
def routagePointDistance (latA,lonA,Distanza,Rotta):
	p = LatLon23.LatLon(LatLon23.Latitude(latA), LatLon23.Longitude(lonA))
	of = p.offset (math.degrees (Rotta), Distanza).to_string('D')
	return (float (of[0]), float (of[1]))
Пример #14
0
def pointDistance (latA, lonA, latB, lonB):
	p1 = LatLon23.LatLon(LatLon23.Latitude(latA), LatLon23.Longitude(lonA))
	p2 = LatLon23.LatLon(LatLon23.Latitude(latB), LatLon23.Longitude(lonB))
	return p1.distance (p2)
Пример #15
0
def ortodromic (latA,lonA,latB,lonB):
	p1 = LatLon23.LatLon(LatLon23.Latitude(latA), LatLon23.Longitude(lonA))
	p2 = LatLon23.LatLon(LatLon23.Latitude(latB), LatLon23.Longitude(lonB))

	return (p1.distance (p2), math.radians (p1.heading_initial(p2)))
Пример #16
0
 elif name == 'Długość [m] w tym szacowane [m]':
     val = columns[1].get_text().strip()
     val = re.sub('  +', ' ', val)
     d[name] = val.replace('\r\n \n\r\n ', ';')
 elif name == 'Współrzędne WGS84':
     str_gps = columns[1].get_text().strip()
     # from https://github.com/hickeroar/LatLon23
     str_gps_arr = str_gps.replace(',', '.').split('. ')
     d['D lat'] = ''
     d['D lon'] = ''
     d['DM lat'] = ''
     d['DM lon'] = ''
     d['DMS lat'] = ''
     d['DMS lon'] = ''
     if len(str_gps_arr) == 2:
         caveLatLon = LatLon23.string2latlon(str_gps_arr[1][2:], str_gps_arr[0][2:], 'd%°%m%′%S%″')
         d['D lat'] = caveLatLon.to_string('D% %H')[0]
         d['D lon'] = caveLatLon.to_string('D% %H')[1]
         d['DM lat'] = caveLatLon.to_string('d% %M% %H')[0]
         d['DM lon'] = caveLatLon.to_string('d% %M% %H')[1]
         d['DMS lat'] = caveLatLon.to_string('d% %m% %S% %H')[0]
         d['DMS lon'] = caveLatLon.to_string('d% %m% %S% %H')[1]
 else:
     if columns[1].find('style') is not None:
         columns[1].style.extract()
     val = columns[1].get_text().strip()
     val = re.sub('  +', ' ', val)
     d[name.strip()] = val  # unicodedata.normalize("NFKD", val)
     
     invalid_tags = ['div']
     for tag in invalid_tags: 
Пример #17
0
    def write(self, fname, airport_db):
        # sanity checks
        assert not airport_db is None

        # select waypoints to write
        coords = copy.deepcopy(self.__flightCoords)

        # HINT: microsoft flight simulator seems to loose the last waypoint when finishing in the air.
        # this is why we add the last waypoint twice when not using the airport database.
        # the destination airport will sometimes not be consistent and then the same behaviour occurs and we
        # will finish in the air.
        # this looks strange on the world map when planning a flight, but the vfr map seems to be okay.

        # nearest departure airport
        lat = float(coords[0].lat)
        lon = float(coords[0].lon)
        departure_id, departure_lat, departure_lon, departure_ele, departure_name = airport_db.find_nearest(
            lat, lon)
        departure_type = "Airport"
        departure_coord = _coord2str(
            LatLon23.LatLon(departure_lat, departure_lon), departure_ele)

        # nearest destination airport
        lat = float(coords[-1].lat)
        lon = float(coords[-1].lon)
        destination_id, destination_lat, destination_lon, destination_ele, destination_name = airport_db.find_nearest(
            lat, lon)
        destination_type = "Airport"
        destination_coord = _coord2str(
            LatLon23.LatLon(destination_lat, destination_lon), destination_ele)

        # are the two airports the same?
        if departure_id == destination_id:
            # distances to the departure and destination
            departure_dist = coords[0].distance(
                LatLon23.LatLon(departure_lat, departure_lon))
            destination_dist = coords[-1].distance(
                LatLon23.LatLon(destination_lat, destination_lon))

            # use the airport to the nearest waypoint
            if departure_dist < destination_dist:
                # destination info
                destination_id = "CUSTA"
                destination_type = "Intersection"
                lat = float(coords[-1].lat) + DEGREE_OFFSET_END_IN_FLIGHT
                lon = float(coords[-1].lon) + DEGREE_OFFSET_END_IN_FLIGHT
                destination_coord = _coord2str(LatLon23.LatLon(lat, lon),
                                               self.__flightElevation)
                destination_name = "GPX destination"
            else:
                # departure info
                departure_id = "CUSTD"
                departure_type = "Intersection"
                departure_coord = _coord2str(coords[0], self.__flightElevation)
                departure_name = "GPX departure"

                # trim the coordinates
                coords = coords[1:]

        # empty xml document
        xml_root = xml.etree.ElementTree.Element("SimBase.Document", {
            "Type": "AceXML",
            "version": "1,0"
        })
        xml_data = xml.etree.ElementTree.ElementTree(xml_root)

        # general information
        xml.etree.ElementTree.SubElement(xml_root,
                                         "Descr").text = "AceXML Document"

        # flight plan
        flightplan_node = xml.etree.ElementTree.SubElement(
            xml_root, "FlightPlan.FlightPlan")
        xml.etree.ElementTree.SubElement(flightplan_node,
                                         "Title").text = self.__flightTitle
        xml.etree.ElementTree.SubElement(flightplan_node,
                                         "FPType").text = "VFR"
        xml.etree.ElementTree.SubElement(
            flightplan_node, "CruisingAlt").text = str(self.__flightElevation)
        xml.etree.ElementTree.SubElement(flightplan_node,
                                         "DepartureID").text = departure_id
        xml.etree.ElementTree.SubElement(flightplan_node,
                                         "DepartureLLA").text = departure_coord
        xml.etree.ElementTree.SubElement(flightplan_node,
                                         "DestinationID").text = destination_id
        xml.etree.ElementTree.SubElement(
            flightplan_node, "DestinationLLA").text = destination_coord
        xml.etree.ElementTree.SubElement(
            flightplan_node, "Descr").text = self.__flightDescription
        xml.etree.ElementTree.SubElement(flightplan_node,
                                         "DepartureName").text = departure_name
        xml.etree.ElementTree.SubElement(
            flightplan_node, "DestinationName").text = destination_name

        # app version
        app_version_node = xml.etree.ElementTree.SubElement(
            flightplan_node, "AppVersion")
        xml.etree.ElementTree.SubElement(app_version_node,
                                         "AppVersionMajor").text = "11"
        xml.etree.ElementTree.SubElement(app_version_node,
                                         "AppVersionBuild").text = "282174"

        # write the departure
        departure_node = xml.etree.ElementTree.SubElement(
            flightplan_node, "ATCWaypoint", {"id": departure_id})
        xml.etree.ElementTree.SubElement(
            departure_node, "ATCWaypointType").text = departure_type
        xml.etree.ElementTree.SubElement(
            departure_node, "WorldPosition").text = departure_coord
        xml.etree.ElementTree.SubElement(departure_node,
                                         "SpeedMaxFP").text = "-1"
        icao_node = xml.etree.ElementTree.SubElement(departure_node, "ICAO")
        xml.etree.ElementTree.SubElement(icao_node,
                                         "ICAOIdent").text = departure_id

        # write the waypoints
        for i in range(len(coords)):
            coord = coords[i]
            name = "Cust" + str(i + 1)
            type = "User"
            waypoint_node = xml.etree.ElementTree.SubElement(
                flightplan_node, "ATCWaypoint", {"id": name})
            xml.etree.ElementTree.SubElement(waypoint_node,
                                             "ATCWaypointType").text = type
            xml.etree.ElementTree.SubElement(
                waypoint_node,
                "WorldPosition").text = _coord2str(coord,
                                                   self.__flightElevation)
            xml.etree.ElementTree.SubElement(waypoint_node,
                                             "SpeedMaxFP").text = "-1"

        # write the destination
        destination_node = xml.etree.ElementTree.SubElement(
            flightplan_node, "ATCWaypoint", {"id": destination_id})
        xml.etree.ElementTree.SubElement(
            destination_node, "ATCWaypointType").text = destination_type
        xml.etree.ElementTree.SubElement(
            destination_node, "WorldPosition").text = destination_coord
        xml.etree.ElementTree.SubElement(destination_node,
                                         "SpeedMaxFP").text = "-1"
        icao_node = xml.etree.ElementTree.SubElement(destination_node, "ICAO")
        xml.etree.ElementTree.SubElement(icao_node,
                                         "ICAOIdent").text = destination_id

        # write the xml document to the file
        xml_data.write(fname, encoding="utf-8", xml_declaration=True)
Пример #18
0
def lossodromic (latA,lonA,latB,lonB):
	p1 = LatLon23.LatLon(LatLon23.Latitude(latA), LatLon23.Longitude(lonA))
	p2 = LatLon23.LatLon(LatLon23.Latitude(latB), LatLon23.Longitude(lonB))

	return (p1.distance (p2, ellipse = 'sphere'), math.radians (p1.heading_initial(p2)))