GeometryAdapter.py 6.8 KB
# coding=utf-8
#author:        4N
#createtime:    2021/6/3
#email:         nheweijun@sina.com
from osgeo import ogr,gdal
from osgeo.ogr import Geometry

class GeometryAdapter:

    @classmethod
    def getType(cls,layer):
        origin = layer.GetGeomType()  # type:str
        if origin == 1 or origin == 4:
            return "point"
        elif origin == 2 or origin == 5:
            return "linestring"
        elif origin == 3 or origin == 6:
            return "polygon"
        return str(origin)

    @classmethod
    def change_geom_type(cls,raw):
        if raw==2 or raw ==3:
            return raw+3
        if raw==4:
            return 1
        if raw==-2147483647 or raw.__eq__(-2147483644):
            return 1
        if raw==-2147483646 or raw.__eq__(-2147483643):
            return 5
        if raw==-2147483645 or raw.__eq__(-2147483642):
            return 6
        return raw

    @classmethod
    def change_geom(cls,geo:Geometry,geom_type):
        '''
        转换空间对象的类型,以适应dmap只支持Multi类型
        :param geo:
        :param geom_type:
        :return: 转换后的空间对象
        '''


        # Point = 1,
        # LineString = 2,
        # Polygon = 3,
        # MultiPoint = 4,
        # MultiLineString = 5,
        # MultiPolygon = 6,
        # GeometryCollection = 7,
        # CircularString = 8,
        # CompoundCurve = 9,
        # CurvePolygon = 10,
        # MultiCurve = 11,
        # MultiSurface = 12,
        # PolyhedralSurface = 15,
        # LinearRing = 101,

        # MultiPointZ = -2147483644
        # MultiLineStringZ = -2147483643
        # MultiPolygonZ = -2147483642



        # PointZ = -2147483647
        # LINESTRINGZ=-2147483646
        # POLYGONZ=-2147483645

        if geom_type==5 or geom_type.__eq__(-2147483646) or geom_type.__eq__(-2147483643):
            return ogr.ForceToMultiLineString(geo)
        if geom_type==6 or geom_type.__eq__(-2147483645) or geom_type.__eq__(-2147483642):
            return ogr.ForceToMultiPolygon(geo)
        if geom_type==1:
            return geo.Centroid()
        return geo

    @classmethod
    def get_table_type(cls, raw):
        # Point = 1,
        # LineString = 2,
        # Polygon = 3,
        # MultiPoint = 4,
        # MultiLineString = 5,
        # MultiPolygon = 6,
        # GeometryCollection = 7,
        # CircularString = 8,
        # CompoundCurve = 9,
        # CurvePolygon = 10,
        # MultiCurve = 11,
        # MultiSurface = 12,
        # PolyhedralSurface = 15,
        # LinearRing = 101,

        # PointZ = -2147483647
        # LINESTRINGZ=-2147483646
        # POLYGONZ=-2147483645

        # PointZM = 3001
        # LINESTRINGZM= 3002
        # POLYGONZM= 3003

        # MultiPointZ = -2147483644
        # MultiLineStringZ = -2147483643
        # MultiPolygonZ = -2147483642

        # MultiPointZM = 3004
        # MultiLineStringZM = 3005
        # MultiPolygonZM = 3006


        if raw in [1, 4, -2147483644, -2147483647, 3001, 3004] :
            return 1
        elif raw in [2, 5, -2147483643, -2147483646, 3002, 3005]:
            return 2
        elif raw in [3, 6, -2147483642, -2147483645, 3003, 3006] :
            return 3
        return raw

    def move(self,geo: Geometry, offx, offy):

        g = geo.GetGeometryRef(0)
        num = g.GetPointCount()

        coor = []

        for j in range(num):
            point = g.GetPoint(j)
            x = point[0]
            y = point[1]
            x += offx
            y += offy
            coor.append([x, y])
        if num == 1:
            point = ogr.Geometry(ogr.wkbPoint)
            point.AddPoint(coor[0][0], coor[0][1])
            return point
        elif coor[0].__eq__(coor[-1]):
            ring = ogr.Geometry(ogr.wkbLinearRing)
            for co in coor:
                ring.AddPoint(co[0], co[1])
            poly = ogr.Geometry(ogr.wkbPolygon)
            poly.AddGeometry(ring)
            return poly
        else:
            line = ogr.Geometry(ogr.wkbLineString)
            for co in coor:
                line.AddPoint(co[0], co[1])
            return line

    @classmethod
    def envelop_2_polygon(cls,env):
        ring = ogr.Geometry(ogr.wkbLinearRing)
        ring.AddPoint(env[0], env[2])
        ring.AddPoint(env[0], env[3])
        ring.AddPoint(env[1], env[3])
        ring.AddPoint(env[1], env[2])
        ring.AddPoint(env[0], env[2])
        # Create polygon
        poly = ogr.Geometry(ogr.wkbPolygon)
        poly.AddGeometry(ring)
        return poly

    @classmethod
    def bbox_2_polygon(cls,bbox):
        ring = ogr.Geometry(ogr.wkbLinearRing)
        ring.AddPoint(bbox[0], bbox[1])
        ring.AddPoint(bbox[0], bbox[3])
        ring.AddPoint(bbox[2], bbox[3])
        ring.AddPoint(bbox[2], bbox[1])
        ring.AddPoint(bbox[0], bbox[1])
        # Create polygon
        poly = ogr.Geometry(ogr.wkbPolygon)
        poly.AddGeometry(ring)
        return poly

    @classmethod
    def tuple_2_point(cls,tup):
        point = ogr.Geometry(ogr.wkbPoint)
        point.AddPoint(tup[0], tup[1])
        return point

    @classmethod
    def get_geometry_type(cls,layer):
        geom_type = layer.GetGeomType()
        if geom_type.__eq__(0):
            fea = layer.GetNextFeature()
            if fea:
                g: Geometry = fea.geometry()
                geom_type = g.GetGeometryType()
            layer.ResetReading()
        return geom_type


    @classmethod
    def convert(cls, geometry: Geometry, bbox, xy_res):
        '''
        根据Geometry和bbox将空间对象栅格化
        :param geometry: 空间对象
        :param bbox: 栅格化范围
        :param xy_res: 分辨率
        :return:
        '''

        # 计算像素大小
        x_min, y_min, x_max, y_max = bbox
        pixel_size = (x_max - x_min) / xy_res
        # 创建内存栅格对象
        target_ds = gdal.GetDriverByName('MEM').Create('', xy_res, xy_res, gdal.GDT_Byte)
        target_ds.SetGeoTransform((x_min, pixel_size, 0, y_max, 0, -pixel_size))
        band = target_ds.GetRasterBand(1)
        # 创建内存图层对象,因为gdal只提供栅格化图层的方法
        layer_ds = ogr.GetDriverByName('Memory').CreateDataSource('')
        mem_layer = layer_ds.CreateLayer("mem", geom_type=ogr.wkbUnknown)
        feature_defn = mem_layer.GetLayerDefn()
        feature = ogr.Feature(feature_defn)
        feature.SetGeometry(geometry)
        mem_layer.CreateFeature(feature)
        # 栅格化
        gdal.RasterizeLayer(target_ds, [1], mem_layer, burn_values=[1])
        data = band.ReadAsArray()
        del target_ds
        del layer_ds
        # Read as array
        return data