예제 #1
0
def test_transform():
    pj_utm = osr_util.get_srs(32636)
    utm_x = [690950.4640, 688927.6381]
    utm_y = [3431318.8435, 3542183.4911]

    for gis_order in (False, True):
        axis_order = osr_util.get_axis_order_from_gis_order(gis_order)
        pj4326 = osr_util.get_srs(4326, axis_order=axis_order)
        ct = osr_util.get_transform(pj4326, pj_utm)
        lon = [35, 35]
        lat = [31, 32]
        x, y = (lon, lat) if gis_order else (lat, lon)
        osr_util.transform_points(ct, x, y)
        d = array_util.array_dist(x, utm_x), array_util.array_dist(y, utm_y)
        assert max(d) < 0.01
예제 #2
0
def test_gis_order2():
    pj4326_gis = osr_util.get_srs(4326, axis_order=osr.OAMS_TRADITIONAL_GIS_ORDER)
    pj4326_str = osr_util.get_srs_pj(4326)

    srs_from_epsg = osr.SpatialReference()
    srs_from_epsg.ImportFromEPSG(4326)

    assert srs_from_epsg.GetAxisMappingStrategy() == osr.OAMS_AUTHORITY_COMPLIANT
    srs_from_str = osr.SpatialReference()
    srs_from_str.ImportFromProj4(pj4326_str)
    assert srs_from_str.GetAxisMappingStrategy() == osr.OAMS_AUTHORITY_COMPLIANT
    assert srs_from_epsg.IsSame(srs_from_str)

    # testing that explicitly setting OAMS_AUTHORITY_COMPLIANT does not effect equivalence
    srs_from_epsg.SetAxisMappingStrategy(osr.OAMS_AUTHORITY_COMPLIANT)
    srs_from_str.SetAxisMappingStrategy(osr.OAMS_AUTHORITY_COMPLIANT)
    assert srs_from_epsg.IsSame(srs_from_str)

    srs_from_epsg.SetAxisMappingStrategy(osr.OAMS_TRADITIONAL_GIS_ORDER)
    srs_from_str.SetAxisMappingStrategy(osr.OAMS_TRADITIONAL_GIS_ORDER)

    srs_from_epsg2 = osr.SpatialReference()
    srs_from_epsg2.ImportFromEPSG(4326)
    srs_from_epsg2.SetAxisMappingStrategy(osr.OAMS_TRADITIONAL_GIS_ORDER)
    assert srs_from_epsg.IsSame(srs_from_epsg2)

    test_gis_order_proj_str_vs_epsg = False
    # explicitly setting OAMS_TRADITIONAL_GIS_ORDER triggers inequality between srs from proj-string and srs from epsg
    # if this issue is resolved these tests can be enabled
    if test_gis_order_proj_str_vs_epsg:
        assert srs_from_epsg.IsSame(srs_from_str)
        assert osr_util.are_srs_equivalent(pj4326_str, 4326)
        assert osr_util.are_srs_equivalent(pj4326_gis, pj4326_str)
예제 #3
0
def get_datum_and_zone_from_srs(srs: AnySRS) -> Tuple[str, Real]:
    srs = get_srs(srs)
    datum = srs.GetAttrValue('DATUM')
    central_meridian = srs.GetProjParm('central_meridian')
    if central_meridian:
        zone = get_utm_zone_by_lon(central_meridian)
    else:
        zone = None
    return datum, zone
예제 #4
0
def ogr_create_geometries_from_wkt(path: PathLikeOrStr,
                                   wkt_list: Sequence[str],
                                   of='ESRI Shapefile',
                                   srs: AnySRS = 4326):
    driver = ogr.GetDriverByName(of)
    ds = driver.CreateDataSource(os.fspath(path))
    srs = get_srs(srs)

    layer = ds.CreateLayer('', srs, ogr.wkbUnknown)
    for wkt in wkt_list:
        feature = ogr.Feature(layer.GetLayerDefn())
        geom = ogr.CreateGeometryFromWkt(wkt)
        feature.SetGeometry(geom)  # Set the feature geometry
        layer.CreateFeature(feature)  # Create the feature in the layer
        feature.Destroy()  # Destroy the feature to free resources
    # Destroy the data source to free resources
    ds.Destroy()
예제 #5
0
def gdal_to_json(ds: gdal.Dataset):
    gt = ds.GetGeoTransform(can_return_null=True)
    xsize = ds.RasterXSize
    ysize = ds.RasterYSize
    srs = get_srs(ds)
    srs = srs.ExportToProj4()
    minx = gt[0] + gt[1] * 0 + gt[2] * 0
    miny = gt[3] + gt[4] * 0 + gt[5] * 0
    maxx = gt[0] + gt[1] * xsize + gt[2] * ysize
    maxy = gt[3] + gt[4] * xsize + gt[5] * ysize
    bbox = miny, minx, maxy, maxx
    band_list = range(1, ds.RasterCount + 1)
    data = [
        ds.ReadAsArray(band_list=[bnd]).ravel().tolist() for bnd in band_list
    ]
    ndv = [ds.GetRasterBand(i).GetNoDataValue() for i in band_list]
    result = dict(bbox=bbox,
                  gt=gt,
                  srs=srs,
                  size=(xsize, ysize),
                  data=data,
                  ndv=ndv)
    return result
예제 #6
0
def gdallocationinfo(
    filename_or_ds: PathOrDS,
    x: ArrayOrScalarLike,
    y: ArrayOrScalarLike,
    srs: CoordinateTransformationOrSRS = None,
    axis_order: Optional[OAMS_AXIS_ORDER] = None,
    open_options: Optional[dict] = None,
    ovr_idx: Optional[int] = None,
    band_nums: Optional[Sequence[int]] = None,
    inline_xy_replacement: bool = False,
    return_ovr_pixel_line: bool = False,
    transform_round_digits: Optional[float] = None,
    allow_xy_outside_extent: bool = True,
    pixel_offset: Real = -0.5,
    line_offset: Real = -0.5,
    resample_alg=gdalconst.GRIORA_NearestNeighbour,
    quiet_mode: bool = True,
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    ds = open_ds(filename_or_ds, open_options=open_options)
    filename = filename_or_ds if is_path_like(filename_or_ds) else ''
    if ds is None:
        raise Exception(f'Could not open {filename}.')
    if not isinstance(x, ArrayLike.__args__):
        x = [x]
    if not isinstance(y, ArrayLike.__args__):
        y = [y]
    if len(x) != len(y):
        raise Exception(
            f'len(x)={len(x)} should be the same as len(y)={len(y)}')
    point_count = len(x)

    dtype = np.float64
    if not isinstance(x, np.ndarray) or not isinstance(y, np.ndarray):
        x = np.array(x, dtype=dtype)
        y = np.array(y, dtype=dtype)
        inline_xy_replacement = True

    if srs is None:
        srs = LocationInfoSRS.PixelLine

    # Build Spatial Reference object based on coordinate system, fetched from the opened dataset
    if srs != LocationInfoSRS.PixelLine:
        if srs != LocationInfoSRS.SameAsDS_SRS:
            ds_srs = ds.GetSpatialRef()
            ct = None
            if isinstance(srs, osr.CoordinateTransformation):
                ct = srs
            else:
                if srs == LocationInfoSRS.SameAsDS_SRS_GeogCS:
                    points_srs = ds_srs.CloneGeogCS()
                else:
                    points_srs = get_srs(srs, axis_order=axis_order)
                ct = get_transform(points_srs, ds_srs)
            if ct is not None:
                if not inline_xy_replacement:
                    x = x.copy()
                    y = y.copy()
                    inline_xy_replacement = True
                transform_points(ct, x, y)
                if transform_round_digits is not None:
                    x.round(transform_round_digits, out=x)
                    y.round(transform_round_digits, out=y)

        # Read geotransform matrix and calculate corresponding pixel coordinates
        geotransform = ds.GetGeoTransform()
        inv_geotransform = gdal.InvGeoTransform(geotransform)
        if inv_geotransform is None:
            raise Exception("Failed InvGeoTransform()")

        # can we inline this transformation ?
        x, y = \
            (inv_geotransform[0] + inv_geotransform[1] * x + inv_geotransform[2] * y), \
            (inv_geotransform[3] + inv_geotransform[4] * x + inv_geotransform[5] * y)
        inline_xy_replacement = True

    xsize, ysize = ds.RasterXSize, ds.RasterYSize
    bands = get_bands(ds, band_nums, ovr_idx=ovr_idx)
    ovr_xsize, ovr_ysize = bands[0].XSize, bands[0].YSize
    pixel_fact, line_fact = (ovr_xsize / xsize,
                             ovr_ysize / ysize) if ovr_idx else (1, 1)
    bnd_count = len(bands)

    shape = (bnd_count, point_count)
    np_dtype, np_dtype = GDALTypeCodeAndNumericTypeCodeFromDataSet(ds)
    results = np.empty(shape=shape, dtype=np_dtype)

    check_outside = not quiet_mode or not allow_xy_outside_extent
    if check_outside and (np.any(x < 0) or np.any(x >= xsize) or np.any(y < 0)
                          or np.any(y >= ysize)):
        msg = 'Passed coordinates are not in dataset extent!'
        if not allow_xy_outside_extent:
            raise Exception(msg)
        elif not quiet_mode:
            print(msg)

    if pixel_fact == 1:
        pixels_q = x
    elif return_ovr_pixel_line:
        x *= pixel_fact
        pixels_q = x
    else:
        pixels_q = x * pixel_fact

    if line_fact == 1:
        lines_q = y
    elif return_ovr_pixel_line:
        y *= line_fact
        lines_q = y
    else:
        lines_q = y * line_fact

    buf_xsize = buf_ysize = 1
    buf_type, typecode = GDALTypeCodeAndNumericTypeCodeFromDataSet(ds)
    buf_obj = np.empty([buf_ysize, buf_xsize], dtype=typecode)

    for idx, (pixel, line) in enumerate(zip(pixels_q, lines_q)):
        for bnd_idx, band in enumerate(bands):
            if BandRasterIONumPy(band, 0, pixel - 0.5, line - 0.5, 1, 1,
                                 buf_obj, buf_type, resample_alg, None,
                                 None) == 0:
                results[bnd_idx][idx] = buf_obj[0][0]

    is_scaled, scales, offsets = get_scales_and_offsets(bands)
    if is_scaled:
        for bnd_idx, (scale, offset) in enumerate(zip(scales, offsets)):
            results[bnd_idx] = results[bnd_idx] * scale + offset

    return x, y, results
예제 #7
0
def test_gdallocationinfo_py_7():
    filename_template = 'tmp/byte{}.tif'
    overview_list = [2]
    overview_list, file_list = copy_raster_and_add_overviews(
        filename_src='../gcore/data/byte.tif',
        output_filename_template=filename_template,
        overview_list=overview_list)
    temp_files.extend(file_list)

    ds = open_ds(filename_template.format(''))
    ds_srs = ds.GetSpatialRef()
    gt = ds.GetGeoTransform()
    ovr_fact = 1
    pix_offset = 0
    p0 = list(i * ovr_fact + pix_offset for i in range(0, 3))
    l0 = list(i * ovr_fact + pix_offset for i in range(0, 3))
    p0, l0 = zip(*product(p0, l0))
    x0 = list(gt[0] + pixel * gt[1] for pixel in p0)
    y0 = list(gt[3] + line * gt[5] for line in l0)

    dtype = np.float64
    p0 = np.array(p0, dtype=dtype)
    l0 = np.array(l0, dtype=dtype)
    x0 = np.array(x0, dtype=dtype)
    y0 = np.array(y0, dtype=dtype)

    expected_results = [[(0.0, 0.0, 107), (0.0, 1.0, 115), (0.0, 2.0, 115),
                         (1.0, 0.0, 123), (1.0, 1.0, 132), (1.0, 2.0, 132),
                         (2.0, 0.0, 132), (2.0, 1.0, 107), (2.0, 2.0, 140)],
                        [(0.0, 0.0, 120), (0.0, 0.5, 120), (0.0, 1.0, 132),
                         (0.5, 0.0, 120), (0.5, 0.5, 120), (0.5, 1.0, 132),
                         (1.0, 0.0, 124), (1.0, 0.5, 124), (1.0, 1.0, 129)]]
    expected_results = np.array(expected_results, dtype=dtype)

    do_print = False
    for ovr_idx, f in enumerate(overview_list):
        for srs in [
                LocationInfoSRS.PixelLine, LocationInfoSRS.SameAsDS_SRS, 4326
        ]:
            if srs == LocationInfoSRS.PixelLine:
                x = p0
                y = l0
            elif srs == LocationInfoSRS.SameAsDS_SRS:
                x = x0
                y = y0
            else:
                points_srs = get_srs(srs,
                                     axis_order=osr.OAMS_TRADITIONAL_GIS_ORDER)
                ct = get_transform(ds_srs, points_srs)
                x = x0.copy()
                y = y0.copy()
                transform_points(ct, x, y)
            pixels, lines, results = gdallocationinfo.gdallocationinfo(
                filename_or_ds=ds,
                ovr_idx=ovr_idx,
                x=x,
                y=y,
                transform_round_digits=2,
                return_ovr_pixel_line=True,
                srs=srs,
                axis_order=osr.OAMS_TRADITIONAL_GIS_ORDER)

            actual = list(zip(pixels, lines, *results))
            actual = np.array(actual, dtype=dtype)
            expected = expected_results[ovr_idx]
            if do_print:
                print(actual)
                print(expected)
                outputs = list(zip(x, y, pixels, lines, *results))
                print(
                    f'ovr: {ovr_idx}, srs: {srs}, x/y/pixel/line/result: {outputs}'
                )
            assert_allclose(expected, actual, rtol=1e-4, atol=1e-3)
예제 #8
0
def test_gis_order():
    pj4326_gis2 = osr_util.get_srs(4326)  # tests the correct default
    if gdal.GetConfigOption('OSR_DEFAULT_AXIS_MAPPING_STRATEGY') is None:
        assert pj4326_gis2.GetAxisMappingStrategy(
        ) == osr.OAMS_AUTHORITY_COMPLIANT

    pj4326_auth = osr_util.get_srs(4326,
                                   axis_order=osr.OAMS_AUTHORITY_COMPLIANT)
    assert pj4326_auth.GetAxisMappingStrategy() == osr.OAMS_AUTHORITY_COMPLIANT

    pj4326_gis = osr_util.get_srs(4326,
                                  axis_order=osr.OAMS_TRADITIONAL_GIS_ORDER)
    assert pj4326_gis.GetAxisMappingStrategy(
    ) == osr.OAMS_TRADITIONAL_GIS_ORDER

    assert not osr_util.are_srs_equivalent(pj4326_gis, pj4326_auth)
    if gdal.GetConfigOption('OSR_DEFAULT_AXIS_MAPPING_STRATEGY') is None:
        assert osr_util.are_srs_equivalent(pj4326_auth, 4326)
        assert not osr_util.are_srs_equivalent(pj4326_gis, 4326)

    pj4326_str = osr_util.get_srs_pj(pj4326_auth)
    pj4326_str2 = osr_util.get_srs_pj(pj4326_gis)

    # axis order is not reflected in proj strings
    assert isinstance(pj4326_str, str) and pj4326_str == pj4326_str2

    if gdal.GetConfigOption('OSR_DEFAULT_AXIS_MAPPING_STRATEGY') is None:
        assert osr_util.are_srs_equivalent(pj4326_str, 4326)
    assert osr_util.are_srs_equivalent(pj4326_auth, pj4326_str)
    assert not osr_util.are_srs_equivalent(pj4326_gis, pj4326_str)

    osr_util.set_default_axis_order(
        osr.OAMS_TRADITIONAL_GIS_ORDER)  # sets gis order

    srs = osr_util.get_srs(4326)  # check the the default was changed
    if gdal.GetConfigOption('OSR_DEFAULT_AXIS_MAPPING_STRATEGY') is None:
        assert srs.GetAxisMappingStrategy() == osr.OAMS_TRADITIONAL_GIS_ORDER

    # check that srs object is not affected by default
    srs = osr_util.get_srs(pj4326_auth)
    assert srs.GetAxisMappingStrategy() == osr.OAMS_AUTHORITY_COMPLIANT
    assert osr_util.are_srs_equivalent(srs, pj4326_auth)

    # check that srs object is also affected if explicitly set
    srs = osr_util.get_srs(pj4326_auth,
                           axis_order=osr.OAMS_TRADITIONAL_GIS_ORDER)
    assert srs.GetAxisMappingStrategy() == osr.OAMS_TRADITIONAL_GIS_ORDER

    # check that the default does not effect explicit order
    srs = osr_util.get_srs(4326, axis_order=osr.OAMS_TRADITIONAL_GIS_ORDER)
    assert srs.GetAxisMappingStrategy() == osr.OAMS_TRADITIONAL_GIS_ORDER

    srs = osr_util.get_srs(pj4326_str)
    assert srs.GetAxisMappingStrategy() == osr.OAMS_TRADITIONAL_GIS_ORDER

    srs = osr_util.get_srs(4326, axis_order=osr.OAMS_AUTHORITY_COMPLIANT)
    assert srs.GetAxisMappingStrategy() == osr.OAMS_AUTHORITY_COMPLIANT

    assert not osr_util.are_srs_equivalent(pj4326_gis, pj4326_auth)
    assert not osr_util.are_srs_equivalent(pj4326_auth, 4326)
    assert osr_util.are_srs_equivalent(pj4326_gis, 4326)

    # restore the default and repeat some tests
    osr_util.set_default_axis_order()

    srs = osr_util.get_srs(4326)  # check the the default was restored
    if gdal.GetConfigOption('OSR_DEFAULT_AXIS_MAPPING_STRATEGY') is None:
        assert srs.GetAxisMappingStrategy() == osr.OAMS_AUTHORITY_COMPLIANT

    srs = osr_util.get_srs(pj4326_str)
    if gdal.GetConfigOption('OSR_DEFAULT_AXIS_MAPPING_STRATEGY') is None:
        assert srs.GetAxisMappingStrategy() == osr.OAMS_AUTHORITY_COMPLIANT

    # check that srs object is not affected by default
    srs = osr_util.get_srs(
        pj4326_gis)  # check that srs object is also affected
    assert srs.GetAxisMappingStrategy() == osr.OAMS_TRADITIONAL_GIS_ORDER

    # check that srs object is also affected if explicitly set
    srs = osr_util.get_srs(pj4326_gis, axis_order=osr.OAMS_AUTHORITY_COMPLIANT)
    assert srs.GetAxisMappingStrategy() == osr.OAMS_AUTHORITY_COMPLIANT

    srs = osr_util.get_srs(4326, axis_order=osr.OAMS_TRADITIONAL_GIS_ORDER)
    assert srs.GetAxisMappingStrategy() == osr.OAMS_TRADITIONAL_GIS_ORDER
예제 #9
0
def gdallocationinfo(
    filename_or_ds: PathOrDS,
    x: NumpyCompatibleArrayOrReal,
    y: NumpyCompatibleArrayOrReal,
    gis_order: bool = False,
    open_options: Optional[dict] = None,
    ovr_idx: Optional[int] = None,
    band_nums: Optional[Sequence[int]] = None,
    srs: CoordinateTransformationOrSRS = None,
    inline_xy_replacement: bool = True,
    quiet_mode: bool = True,
    allow_xy_outside_extent: bool = True,
    pixel_offset: Real = -0.5,
    line_offset: Real = -0.5,
    resample_alg=gdalconst.GRIORA_NearestNeighbour
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:

    ds = open_ds(filename_or_ds, open_options=open_options)
    filename = filename_or_ds if is_path_like(filename_or_ds) else ''
    if ds is None:
        raise Exception(f'Could not open {filename}.')
    if not isinstance(x, NumpyCompatibleArray.__args__):
        x = [x]
    if not isinstance(y, NumpyCompatibleArray.__args__):
        y = [y]
    if len(x) != len(y):
        raise Exception(
            f'len(x)={len(x)} should be the same as len(y)={len(y)}')
    point_count = len(x)

    if not isinstance(x, np.ndarray):
        x = np.ndarray(x)
    if not isinstance(y, np.ndarray):
        y = np.ndarray(y)

    if srs is None:
        srs = LocationInfoSRS.PixelLine

    # Build Spatial Reference object based on coordinate system, fetched from the opened dataset
    if srs != LocationInfoSRS.PixelLine:
        if srs != LocationInfoSRS.SameAsDS_SRS:
            ds_srs = ds.GetSpatialRef()
            ct = None
            if isinstance(srs, osr.CoordinateTransformation):
                ct = srs
            else:
                if srs == LocationInfoSRS.SameAsDS_SRS_GeogCS:
                    points_srs = ds_srs.CloneGeogCS()
                else:
                    points_srs = get_srs(srs, gis_order=gis_order)
                ct = get_transform(points_srs, ds_srs)
            x, y, _z = transform_points(ct, x, y)

        # Read geotransform matrix and calculate corresponding pixel coordinates
        geomatrix = ds.GetGeoTransform()
        inv_geometrix = gdal.InvGeoTransform(geomatrix)
        if inv_geometrix is None:
            raise Exception("Failed InvGeoTransform()")

        x, y = \
            (inv_geometrix[0] + inv_geometrix[1] * x + inv_geometrix[2] * y), \
            (inv_geometrix[3] + inv_geometrix[4] * x + inv_geometrix[5] * y)

    xsize, ysize = ds.RasterXSize, ds.RasterYSize
    bands = get_bands(ds, band_nums, ovr_idx=ovr_idx)
    ovr_xsize, ovr_ysize = bands[0].XSize, bands[0].YSize
    pixel_fact, line_fact = (ovr_xsize / xsize,
                             ovr_ysize / ysize) if ovr_idx else (1, 1)
    bnd_count = len(bands)

    shape = (bnd_count, point_count)
    np_dtype, np_dtype = GDALTypeCodeAndNumericTypeCodeFromDataSet(ds)
    results = np.empty(shape=shape, dtype=np_dtype)

    check_outside = not quiet_mode or not allow_xy_outside_extent
    if check_outside and (np.any(x < 0) or np.any(x >= xsize) or np.any(y < 0)
                          or np.any(y >= ysize)):
        msg = 'Passed coordinates are not in dataset extent!'
        if not allow_xy_outside_extent:
            raise Exception(msg)
        elif not quiet_mode:
            print(msg)

    pixels = np.clip(x * pixel_fact + pixel_offset,
                     0,
                     ovr_xsize - 1,
                     out=x if inline_xy_replacement else None)
    lines = np.clip(y * line_fact + line_offset,
                    0,
                    ovr_ysize - 1,
                    out=y if inline_xy_replacement else None)

    for idx, (pixel, line) in enumerate(zip(pixels, lines)):
        for bnd_idx, band in enumerate(bands):
            val = band.ReadAsArray(pixel,
                                   line,
                                   1,
                                   1,
                                   resample_alg=resample_alg)
            val = val[0][0]
            results[bnd_idx][idx] = val

    is_scaled, scales, offsets = get_scales_and_offsets(bands)
    if is_scaled:
        for bnd_idx, scale, offset in enumerate(zip(scales, offsets)):
            results[bnd_idx] = results[bnd_idx] * scale + offset

    return pixels, lines, results