예제 #1
0
def llh2xyz(lat, lon, ellht=0, ellipsoid=grs80):
    """
    Converts Geographic Latitude, Longitude and Ellipsoid Height to Cartesian
    X, Y and Z Coordinates. Default Ellipsoid parameters used are GRS80.
    :param lat: Geographic Latitude
    :type lat: Float (Decimal Degrees), DMSAngle or DDMAngle
    :param lon: Geographic Longitude
    :type lon: Float (Decimal Degrees), DMSAngle or DDMAngle
    :param ellht: Ellipsoid Height (metres, default is 0m)
    :param ellipsoid: Ellipsoid Object
    :type ellipsoid: Ellipsoid
    :return: Cartesian X, Y, Z Coordinate in metres
    :rtype: tuple
    """
    # Convert lat & long to radians
    lat = radians(angular_typecheck(lat))
    lon = radians(angular_typecheck(lon))
    # Calculate Ellipsoid Radius of Curvature in the Prime Vertical - nu
    if lat == 0:
        nu = grs80.semimaj
    else:
        nu = ellipsoid.semimaj / (sqrt(1 - ellipsoid.ecc1sq * (sin(lat)**2)))
    # Calculate x, y, z
    x = (nu + ellht) * cos(lat) * cos(lon)
    y = (nu + ellht) * cos(lat) * sin(lon)
    z = ((ellipsoid.semimin**2 / ellipsoid.semimaj**2) * nu + ellht) * sin(lat)
    return x, y, z
예제 #2
0
 def test_angular_typecheck(self):
     class_exs = [deca_exs, hpa_exs, gona_exs, dms_exs, ddm_exs]
     for class_ex in class_exs:
         for num, ex in enumerate(class_ex):
             self.assertAlmostEqual(angular_typecheck(ex), dec_exs[num], 13)
             self.assertAlmostEqual(angular_typecheck(-ex), -dec_exs[num],
                                    13)
     for ex in dec_exs:
         self.assertEqual(angular_typecheck(ex), ex)
         self.assertEqual(angular_typecheck(-ex), -ex)
예제 #3
0
def psfandgridconv(xi1,
                   eta1,
                   lat,
                   lon,
                   cm,
                   conf_lat,
                   ellipsoid=grs80,
                   prj=utm):
    """
    Calculates Point Scale Factor and Grid Convergence. Used in convert.geo2grid
    and convert.grid2geo
    :param xi1: Transverse Mercator Ratio Xi
    :param eta1: Transverse Mercator Ratio Eta
    :param lat: Latitude
    :type lat: Decimal Degrees, DMSAngle or DDMAngle
    :param lon: Longitude
    :type lon: Decimal Degrees, DMSAngle or DDMAngle
    :param cm: Central Meridian
    :param conf_lat: Conformal Latitude
    :param ellipsoid: Ellipsoid Object (default: GRS80)
    :return: Point Scale Factor, Grid Convergence (Decimal Degrees)
    :rtype: tuple
    """
    lat = angular_typecheck(lat)
    lon = angular_typecheck(lon)
    A = rect_radius(ellipsoid)
    a = alpha_coeff(ellipsoid)
    lat = radians(lat)
    long_diff = radians(lon - cm)

    # Point Scale Factor
    p = 1
    q = 0
    for r in range(1, 9):
        p += 2 * r * a[r - 1] * cos(2 * r * xi1) * cosh(2 * r * eta1)
        q += 2 * r * a[r - 1] * sin(2 * r * xi1) * sinh(2 * r * eta1)
    q = -q
    psf = (float(prj.cmscale) * (A / ellipsoid.semimaj) * sqrt(q**2 + p**2) *
           ((sqrt(1 + (tan(lat)**2)) * sqrt(1 - ellipsoid.ecc1sq *
                                            (sin(lat)**2))) /
            sqrt((tan(conf_lat)**2) + (cos(long_diff)**2))))

    # Grid Convergence
    grid_conv = degrees(
        atan(abs(q / p)) +
        atan(abs(tan(conf_lat) * tan(long_diff)) / sqrt(1 + tan(conf_lat)**2)))
    if cm > lon and lat < 0:
        grid_conv = -grid_conv
    elif cm < lon and lat > 0:
        grid_conv = -grid_conv

    return psf, grid_conv
예제 #4
0
def polar2rect(r, theta):
    """
    Converts point in polar coordinates to corresponding rectangular coordinates
    Theta is degrees and is measured clockwise from the positive y axis
    (i.e. north)
    :param r: Radius
    :param theta: Angle (decimal degrees)
    :type theta: Float (decimal degrees), DMSAngle or DDMAngle
    :return: Rectangular Coordinates X, Y
    """
    theta = angular_typecheck(theta)
    x = r * sin(radians(theta))
    y = r * cos(radians(theta))
    return x, y
예제 #5
0
def geo2grid(lat, lon, zone=0, ellipsoid=grs80):
    """
    Takes a geographic co-ordinate (latitude, longitude) and returns its
    corresponding Hemisphere, Zone and Projection Easting and Northing, Point
    Scale Factor and Grid Convergence. Default Projection is Universal
    Transverse Mercator Projection using
    GRS80 Ellipsoid parameters.
    :param lat: Latitude
    :type lat: Float (Decimal Degrees), DMSAngle or DDMAngle
    :param lon: Longitude
    :type lon: Float (Decimal Degrees, DMSAngle or DDMAngle
    :param zone: Optional Zone Number - Only required if calculating grid
                                        co-ordinate outside zone boundaries
    :param ellipsoid: Ellipsoid Object
    :type ellipsoid: Ellipsoid
    :return: hemisphere, zone, east (m), north (m), Point Scale Factor,
             Grid Convergence (Decimal Degrees)
    :rtype: tuple
    """

    # Convert DMSAngle and DDMAngle to Decimal Angle
    lat = angular_typecheck(lat)
    lon = angular_typecheck(lon)
    # Input Validation - UTM Extents and Values
    zone = int(zone)
    if zone < 0 or zone > 60:
        raise ValueError('Invalid Zone - Zones from 1 to 60')

    if lat < -80 or lat > 84:
        raise ValueError('Invalid Latitude - Latitudes from -80 to +84')

    if lon < -180 or lon > 180:
        raise ValueError('Invalid Longitude - Longitudes from -180 to +180')

    A = rect_radius(ellipsoid)
    a = alpha_coeff(ellipsoid)
    lat = radians(lat)
    # Calculate Zone
    if zone == 0:
        zone = int((float(lon) - (proj.initialcm - (1.5 * proj.zonewidth))) /
                   proj.zonewidth)
    cm = float(zone * proj.zonewidth) + (proj.initialcm - proj.zonewidth)

    # Conformal Latitude
    sigx = (ellipsoid.ecc1 * tan(lat)) / sqrt(1 + (tan(lat)**2))
    sig = sinh(ellipsoid.ecc1 * (0.5 * log((1 + sigx) / (1 - sigx))))
    conf_lat = tan(lat) * sqrt(1 + sig**2) - sig * sqrt(1 + (tan(lat)**2))
    conf_lat = atan(conf_lat)

    # Longitude Difference
    long_diff = radians(lon - cm)
    # Gauss-Schreiber Ratios
    xi1 = atan(tan(conf_lat) / cos(long_diff))
    eta1x = sin(long_diff) / (sqrt(tan(conf_lat)**2 + cos(long_diff)**2))
    eta1 = log(eta1x + sqrt(1 + eta1x**2))

    # Transverse Mercator Ratios
    eta = eta1
    xi = xi1
    for r in range(1, 9):
        eta += a[r - 1] * cos(2 * r * xi1) * sinh(2 * r * eta1)
        xi += a[r - 1] * sin(2 * r * xi1) * cosh(2 * r * eta1)

    # Transverse Mercator Co-ordinates
    x = A * eta
    y = A * xi

    # Hemisphere-dependent UTM Projection Co-ordinates
    east = proj.cmscale * x + proj.falseeast
    if y < 0:
        hemisphere = 'South'
        north = proj.cmscale * y + proj.falsenorth
    else:
        hemisphere = 'North'
        falsenorth = 0
        north = proj.cmscale * y + falsenorth

    # Point Scale Factor and Grid Convergence
    psf, grid_conv = psfandgridconv(xi1, eta1, degrees(lat), lon, cm, conf_lat)

    return (hemisphere, zone, round(float(east),
                                    4), round(float(north),
                                              4), round(psf, 8), grid_conv)