Python实现点shp文件读取并转换成geojson

Python实现点shp文件读取并转换成geojson

不调用shapefile库的一种写法~

import os
import struct



class GISPoints(object):
    def __init__(self,x,y,att=None):
        self.x=x
        self.y=y
        self.att=att

    def __str__(self):
        return "E"

class GISShapefile(object):
    def __init__(self):
        # 无效字段
        self.Unused=[None for i in range(7)]
        # 版本
        self.verson=None
        # 类型
        self.ShapeType=None
        self.ShapeName="None"
        # 范围
        self.GeoRange=[None for i in range(4)]
        # 三维
        self.Unused1=[None for i in range(4)]
        # 所有点
        self.Points=[]

    def ReadPoint(self,by:bytes)->object:
        x,y=struct.unpack('d',by[:8])[0],struct.unpack('d',by[8:16])[0]

        return GISPoints(x,y)


    def ReadFileHead(self,shapename=None):
        if not shapename:
            raise Exception("None FilePath")
        if not os.path.exists(shapename):
            raise Exception("Error Path")
        file,ext=os.path.splitext(shapename)
        self.ShapeName=file.split("\\")[-1]+ext
        try:
            f=open("%s%s"%(file,ext),"rb")
            self.ReadShpaeHeader(f)
            try:
                while True:
                    self.ReadRecordHeader(f)
            except:
                pass
            finally:
                f.close()
        except IOError:
            try:
                f = open("%s%s" % (file, ext.upper()), "rb")
                self.ReadShpaeHeader(f)
                try:
                    while True:
                        self.ReadRecordHeader(f)
                except:
                    pass
                finally:
                    f.close()
            except IOError:
                pass

    def ReadShpaeHeader(self,f):

        for _ in range(7):
            self.Unused[_]=struct.unpack("i",f.read(4))[0]
        self.verson=struct.unpack("i",f.read(4))[0]
        self.ShapeType=struct.unpack("i",f.read(4))[0]
        for _ in range(4):
            self.GeoRange[_]=struct.unpack("d",f.read(8))[0]
        for _ in range(4):
            self.Unused1[_]=struct.unpack("d",f.read(8))[0]

    def __str__(self):
        print("Verson: ",self.verson)
        print("ShapeTyep: ",self.__map__(self.ShapeType))
        print("Xmin:%f,Ymin:%f,Xmax:%f,Ymax:%f"%(self.GeoRange[0],self.GeoRange[1],
                                                    self.GeoRange[2],self.GeoRange[3]))
        print("Points: ",len(self.Points))

        return self.ShapeName

    def __map__(self,a:int)->str:
        if a==1:
            return "Point"
        elif a==3:
            return "Line"
        elif a==5:
            return "Polygon"
        else:
            return "UNKNOWN"

    def ReadRecordHeader(self,f):
        tem=[0 for i in range(3)] # 记录数量 记录长度 空间类型
        for i in range(3):
            a=self.change(f.read(4))
            tem[i]=int.from_bytes(a,byteorder="little",signed=False)
        Recordlenth=tem[1]*2-4
        byte_content=f.read(Recordlenth)
        newpoints=self.ReadPoint(byte_content)
        byte_content=byte_content[16:]
        self.Points.append(newpoints)
        return self.Points

    def change(self,by):
        return by[::-1]

    def sequencing(self,path):
        size=len(self.Points)
        if size==0:
            raise Exception("No Points!")
        elif size==1:
            Type='"Point"'
        else:
            Type='"MultiPoint"'
        with open(path,"w") as f:
            f.write('"geometry":{'+"\n")
            f.write('   "type":%s'%Type+","+"\n")
            Coordinates=[]
            for i in self.Points:
                Coordinates.append([i.x,i.y])
            f.write('   "coordinates":'+str(Coordinates)+"\n")
            f.write("}")
te=GISShapefile()
te.ReadFileHead(r"\Desktop\云南县城.shp")
te.sequencing(r"\Desktop\云南县城.geojson")
print(te)

结果与shapefile库读取的一致(磕了半天shapefile库源码,别问我为什么不用,问就是老师把写好的第三方库ban了)

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值