예제 #1
0
    def geteastingshift(self, zonen: float, zonel: float) -> Optional[float]:
        """
        If the lat, lon coordinates being converted are located in a
        different UTM zone than the canvas reference point, the UTM meters
        may need to be shifted.
        This picks a reference point in the same longitudinal band
        (UTM zone number) as the provided zone, to calculate the shift in
        meters for the x coordinate.

        :param zonen: zonen
        :param zonel: zone1
        :return: the x shift value
        """
        rzonen = int(self.refutm[0][0])
        # same zone number, no x shift required
        if zonen == rzonen:
            return None
        z = (zonen, zonel)
        # x shift already calculated, cached
        if z in self.zoneshifts and self.zoneshifts[z][0] is not None:
            return self.zoneshifts[z][0]

        rlat, rlon, _ralt = self.refgeo
        # ea. zone is 6deg band
        lon2 = rlon + 6 * (zonen - rzonen)
        # ignore northing
        e2, _n2, _zonen2, _zonel2 = utm.from_latlon(rlat, lon2)
        # NOTE: great circle distance used here, not reference ellipsoid!
        xshift = utm.haversine(rlon, rlat, lon2, rlat) - e2
        # cache the return value
        yshift = None
        if z in self.zoneshifts:
            yshift = self.zoneshifts[z][1]
        self.zoneshifts[z] = (xshift, yshift)
        return xshift
예제 #2
0
    def getutmzoneshift(
        self, e: float, n: float
    ) -> Tuple[float, float, Tuple[float, str]]:
        """
        Given UTM easting and northing values, check if they fall outside
        the reference point's zone boundary. Return the UTM coordinates in a
        different zone and the new zone if they do. Zone lettering is only
        changed when the reference point is in the opposite hemisphere.

        :param e: easting value
        :param n: northing value
        :return: modified easting, northing, and zone values
        """
        zone = self.refutm[0]
        rlat, rlon, _ralt = self.refgeo
        if e > 834000 or e < 166000:
            num_zones = (int(e) - 166000) / (utm.R / 10)
            # estimate number of zones to shift, E (positive) or W (negative)
            rlon2 = self.refgeo[1] + (num_zones * 6)
            _e2, _n2, zonen2, zonel2 = utm.from_latlon(rlat, rlon2)
            xshift = utm.haversine(rlon, rlat, rlon2, rlat)
            # after >3 zones away from refpt, the above estimate won't work
            # (the above estimate could be improved)
            if not 100000 <= (e - xshift) < 1000000:
                # move one more zone away
                num_zones = (abs(num_zones) + 1) * (abs(num_zones) / num_zones)
                rlon2 = self.refgeo[1] + (num_zones * 6)
                _e2, _n2, zonen2, zonel2 = utm.from_latlon(rlat, rlon2)
                xshift = utm.haversine(rlon, rlat, rlon2, rlat)
            e = e - xshift
            zone = (zonen2, zonel2)
        if n < 0:
            # refpt in northern hemisphere and we crossed south of equator
            n += 10000000
            zone = (zone[0], "M")
        elif n > 10000000:
            # refpt in southern hemisphere and we crossed north of equator
            n -= 10000000
            zone = (zone[0], "N")
        return e, n, zone
예제 #3
0
    def getnorthingshift(self, zonen: float, zonel: float) -> Optional[float]:
        """
        If the lat, lon coordinates being converted are located in a
        different UTM zone than the canvas reference point, the UTM meters
        may need to be shifted.
        This picks a reference point in the same latitude band (UTM zone letter)
        as the provided zone, to calculate the shift in meters for the
        y coordinate.

        :param zonen: zonen
        :param zonel:  zone1
        :return: calculated y shift
        """
        rzonel = self.refutm[0][1]
        # same zone letter, no y shift required
        if zonel == rzonel:
            return None
        z = (zonen, zonel)
        # y shift already calculated, cached
        if z in self.zoneshifts and self.zoneshifts[z][1] is not None:
            return self.zoneshifts[z][1]

        rlat, rlon, _ralt = self.refgeo
        # zonemap is used to calculate degrees difference between zone letters
        latshift = self.zonemap[zonel] - self.zonemap[rzonel]
        # ea. latitude band is 8deg high
        lat2 = rlat + latshift
        _e2, n2, _zonen2, _zonel2 = utm.from_latlon(lat2, rlon)
        # NOTE: great circle distance used here, not reference ellipsoid
        yshift = -(utm.haversine(rlon, rlat, rlon, lat2) + n2)
        # cache the return value
        xshift = None
        if z in self.zoneshifts:
            xshift = self.zoneshifts[z][0]
        self.zoneshifts[z] = (xshift, yshift)
        return yshift