Python类(Class)在GIS上的应用

# -*- coding: utf-8 -*-
"""
Created on Tue Sep 18 14:01:47 2018

@author: dell
"""


class Point():
    '''Point类可以实现对点的增删改查,在图中画出相对位置,计算两个点的距离
        进一步实现,判断三点是否共线,求三点构成的夹角'''
    _arr=[]     #线性表
    def __init__(self,x,y,add=True):       #如果add=False,将不自动把该点加入点顺序表中
        self.Point_x = x
        self.Point_y = y
        self._tuple=(x,y)
        if add==True:
            self._arr.append(self)
        elif add==False:
            pass
        
        
    def AddPoint(self):                                                  
        '''使用该方法,把创建点(实例化对象)的加入顺序表。如果在实例化的过程中没有加入该点,可以通过此方法追加到表尾'''
        self._arr.append(self)
        return print("Finish!")
    
    def InsertPoint(self,location):
        '''将点插入表中指定位置'''
        if location==len(self._arr):
            self.AddPoint()
            return print("Finish!")
        elif location<len(self._arr):
            self._arr.append(0)               #给顺序表扩充一个位置
            for i in range(len(self._arr)-1,location,-1):
                self._arr[i]=self._arr[i-1]
            self._arr[location]=self
            return print("Finish!")
        else:
            return print('Input wrong parameter!')
    
    def PrintXY(self,method='only'):
        '''打印坐标'''
        if method=='only':               # only——打印指定点坐标
            return print(self._tuple)
        elif method=='all':              # all——打印所有点坐标
            for i in self._arr:
                print(i._tuple,end=' ')
            print('')#换行
        else:
            return print('Input wrong parameter!')
    
    def DeletePoint(self):
        '''在线性表中删除点'''
        self._arr.remove(self)
        return print("Finish!")
    
    def ModifyPoint(self,othp):
        '''在线性表中更替某点的位置'''
        self._arr.remove(othp)
        self._arr.append(self)
        return print("Finish!")        
    
    def DistancePoint(self,othp):
        '''计算指定两点的距离'''
        return ((self.Point_x-othp.Point_x)**2+(self.Point_y-othp.Point_y)**2)**0.5


    def Angle(self,side1,side2):
        '''判断由三个点(顶点和边上点)构成的角的方向和角度'''
        import math
        x1=side1.Point_x-self.Point_x
        y1=side1.Point_y-self.Point_y
        x2=side2.Point_x-self.Point_x
        y2=side2.Point_y-self.Point_y
        cross_product=x1*y2-x2*y1
        angle_c=math.acos((x1*x2+y1*y2)/(math.sqrt(x1*x1+y1*y1)*math.sqrt(x2*x2+y2*y2)))    #求叉积和计算角度用的向量积是不同的
        angle=angle_c*(180/math.pi)
        if cross_product>0:
            judgement='side1在side2的右侧(顺时针)'
        elif cross_product<0:
            judgement='side1在side2的左侧(逆时针)'
        elif cross_product==0:
            judgement='side1和side2共线'
        else:
            return print('Input wrong parameter!')
            
        return [judgement,angle]
    
    def PointOnLine(self,lineP1,lineP2):
        '''判断某点是否在lineP1,lineP2所构成的线段上'''
        x1=lineP1.Point_x-self.Point_x
        y1=lineP1.Point_y-self.Point_y
        x2=lineP2.Point_x-self.Point_x
        y2=lineP2.Point_y-self.Point_y
        cross_product=x1*y2-x2*y1
        if cross_product==0 and (min(lineP1.Point_x,lineP2.Point_x)<self.Point_x<max(lineP1.Point_x,lineP2.Point_x)):
            return True
        else :
            return False

        
    def DrawPoint(self,method='only',color='r'):
        '''画出点在坐标系中的相对位置'''
        import matplotlib.pyplot as plt
        if method=='only':
            plt.plot([self.Point_x],[self.Point_y],'.'+color)
        elif method=='all':
            for i in self._arr:
                plt.plot([i.Point_x],[i.Point_y],'.'+color)
        else:
            return print('Input wrong parameter!')
        plt.axis('equal')
            
        
class Line(Point):
    '''线,(如果调用Point的方法,是使用构成线的第一个点坐标),
    可实现方法:线要素的增删改查,计算线段长度、线段斜率、画出线段在坐标系中的位置、判断两直线是否有交点、求交点'''
    line_list=[]            #存放线要素的顺序表
    PointToline_list=[]     #存放由Point顺序表构成的线要素
    def __init__(self,x1,y1,x2,y2,add=True):
        super(Point,self).__init__()
        self.Point_x=x1
        self.Point_y=y1
        self.Point_x0=x2
        self.Point_y0=y2
        if add==True:
            self.line_list.append(self)
        elif add==False:
            pass
        
    def InsertLine(self,location):
        '''将线要素插入表中指定位置'''
        if location==len(self.line_list):
            self.AddLine()
            return print("Finish!")
        elif location<len(self.line_list):
            self.line_list.append(0)               #给顺序表扩充一个位置
            for i in range(len(self.line_list)-1,location,-1):
                self.line_list[i]=self.line_list[i-1]
            self.line_list[location]=self
            return print("Finish!")
        else:
            return print('Input wrong parameter!')
    
    
    def DeleteLine(self):
        '''在线性表中删除线要素'''
        self.line_list.remove(self)
        return print("Finish!")
    
    def ModifyPoint(self,othp):
        '''在顺序表中更替某线的位置'''
        self.line_list.remove(othp)
        self.line_list.append(self)
        return print("Finish!")        
    

    
    def LengthLine(self):
        '''返回线段长度'''
        return ((self.Point_x-self.Point_x0)**2+(self.Point_y-self.Point_y0)**2)**0.5
    
    def SlopeLine(self):
        '''返回线段斜率'''
        import math
        return math.tan((self.Point_y-self.Point_y0)/(self.Point_x-self.Point_x0))
    
    def AddLine(self):                     
        '''将线要素添加进线顺序表表尾,'''
        self.line_list.append(self)
        return print("Finish!")
    
    def DrawLine(self,amount='only',color='r'):
        '''在图中画出线的相对位置'''
        import matplotlib.pyplot as plt 
        if amount=='only':
            plt.plot([self.Point_x,self.Point_x0],[self.Point_y,self.Point_y0],color)
        
        elif amount=='all':
            for i in self.line_list:
                plt.plot([i.Point_x,i.Point_x0],[i.Point_y,i.Point_y0],color)
                
        else:
            return print('Input wrong parameter!')
        plt.axis('equal')
        plt.show()
        
        
    def PointToLine(self,draw=False):
        '''把从基类继承的点(存放在'线性表PointToline_list'中的)转换成线(准确的说只是线的列表,并不能代表线的对象)
        如果有n个点,也应该有n条线'''
        for i in range(0,len(self._arr)-1):
            self.PointToline_list.append([self._arr[i].Point_x,self._arr[i].Point_y,self._arr[i+1].Point_x,self._arr[i+1].Point_y])
        self.PointToline_list.append([self._arr[len(self._arr)-1].Point_x,self._arr[len(self._arr)-1].Point_y,self._arr[0].Point_x,self._arr[0].Point_y])
        if draw==False:
            pass
        elif draw==True:
            import matplotlib.pyplot as plt
            for i in self.PointToline_list:
                plt.plot([i[0],i[2]],[i[1],i[3]],'r')
        else:
            return print('Input wrong parameter!')
        
                
    def Intersect(self,othL,PointRe=False):#这种方法还值得商榷
        '''判断线段是否有交点,也可进一步选择输出交点,求交点代码参考:https://blog.csdn.net/ADwenwen/article/details/80242759'''
        maxSY=max(self.Point_y,self.Point_y0)   #快速排斥实验
        minSY=min(self.Point_y,self.Point_y0)
        maxSX=max(self.Point_x,self.Point_x0)
        minSX=min(self.Point_x,self.Point_x0)
        
        maxOY=max(othL.Point_y,othL.Point_y0)
        minOY=min(othL.Point_y,othL.Point_y0)
        maxOX=max(othL.Point_x,othL.Point_x0)
        minOX=min(othL.Point_x,othL.Point_x0)
        
        
        if minSY>maxOY or maxSY<minOY or minSX>maxOX or maxSX<minOX:
            return False
        else:
            x0=self.Point_x0-self.Point_x
            y0=self.Point_y0-self.Point_y
            x1=othL.Point_x0-self.Point_x
            y1=othL.Point_y0-self.Point_y
            x2=othL.Point_x-self.Point_x
            y2=othL.Point_y-self.Point_y
        
            cross_product1=x0*y1-x1*y0
            cross_product2=x0*y2-x2*y0
            PR=cross_product1*cross_product2
            if PR>0:
                if cross_product1==cross_product2:
                    return True
                else:
                    return False
            else:
                k1=(self.Point_y-self.Point_y0)*1.0/(self.Point_x-self.Point_x0)        #计算k1,由于点均为整数,需要进行浮点数转化
                b1=self.Point_y*1.0-self.Point_x*k1*1.0                                 #整型转浮点型是关键
                if (othL.Point_x-othL.Point_x0)==0:                                     #L2直线斜率不存在操作
                    k2=None
                    b2=0
                else:
                    k2=(othL.Point_y-othL.Point_y0)*1.0/(othL.Point_x-othL.Point_x0)    #斜率存在操作
                    b2=othL.Point_y*1.0-othL.Point_x*k2*1.0
                if k2==None:
                    x=othL.Point_x
                else:
                    x=(b2-b1)*1.0/(k1-k2)
                y=k1*x*1.0+b1*1.0
                intersectPoint=(round(x,2),round(y,2))
                inPoint=Point(x,y)
                Point1=Point(self.Point_x,self.Point_y)
                Point2=Point(self.Point_x0,self.Point_y0)
                Point3=Point(othL.Point_x,othL.Point_y)
                Point4=Point(othL.Point_x0,othL.Point_y0)
                if (inPoint.PointOnLine(Point1,Point2)==False or inPoint.PointOnLine(Point3,Point4)==False):
                    return False
                
                if PointRe==True:
                    return intersectPoint
                elif PointRe==False:
                    return True
                else:
                    return print('Input wrong parameter!')



class Polygon(Line):
    '''多边形示例的产生,来自于当下点顺序表的点构成的多边形'''
    polygon_list=[]
    def __init__(self):
        self.geo=self._arr
        
    
    #def AddPolygon(self):
        #'''将有点构成的多边形作为一个元素添加到多边形线性表中'''
        #self.polygon_list.append(self._arr)
        #return print('Finish!')
    
    def Area(self,draw=False):
        '''通过传入的Point线性表,可计算由点构成多边形的面积,同时绘制出多边形图形。目前只实现了多边形坐标点按照顺时针顺序录入'''
        import matplotlib.pyplot as plt 
        min_y=min(i.Point_y for i in self.geo)     #获取点坐标中纵坐标最小的值,以便后期平移坐标轴
        area_s=0
        for i in range(0,len(self.geo)-1):
            height=self.geo[i+1].Point_x-self.geo[i].Point_x
            up_down=self.geo[i+1].Point_y+self.geo[i].Point_y-2*min_y#将最小坐标平移到X轴上去
            iarea=height*(up_down*0.5)
            area_s+=iarea
            if draw==True:
                plt.plot([self.geo[i].Point_x,self.geo[i+1].Point_x],[self.geo[i].Point_y,self.geo[i+1].Point_y],'r-')
        height=self.geo[0].Point_x-self.geo[len(self.geo)-1].Point_x             #完成起点与终点的衔接
        up_down=self.geo[0].Point_y+self.geo[len(self.geo)-1].Point_y-2*min_y
        iarea=height*(up_down*0.5)
        area_s+=iarea
        if draw==True:
            plt.plot([self.geo[0].Point_x,self.geo[len(self.geo)-1].Point_x],[self.geo[0].Point_y,self.geo[len(self.geo)-1].Point_y],'r-')
            plt.axis('equal')
        return area_s
    
    def Perimeter(self):
        '''计算点构成多边形的周长'''
        peri_s=0
        for i in range(0,len(self.geo)-1):
            iperi=self.geo[i+1].DistancePoint(self.geo[i])
            peri_s+=iperi
        iperi=self.geo[0].DistancePoint(self.geo[len(self.geo)-1])             #完成起点与终点的衔接
        peri_s+=iperi
        return peri_s    
    
    def PointInPolygon(self,othp):#这种方法还值得商榷
        '''判断点是否在多边形内'''
        Polygon_line_list=[]
        line=Line(othp.Point_x,othp.Point_y,9999,othp.Point_y)      #一条平行于X轴的线段(或者射线)
        intersect_num=0
        for i in range(0,len(self._arr)-1):
            Polygon_line_list.append([self.geo[i].Point_x,self.geo[i].Point_y,self.geo[i+1].Point_x,self.geo[i+1].Point_y])
        Polygon_line_list.append([self.geo[len(self.geo)-1].Point_x,self.geo[len(self.geo)-1].Point_y,self.geo[0].Point_x,self.geo[0].Point_y])

        for i in Polygon_line_list:
            j=Line(i[0],i[1],i[2],i[3])
            if line.Intersect(j)==False:
                intersect_num+=1

        
        if intersect_num%2==0:
            return False
        elif intersect_num%2==1:
            return True
        else:
            return print('Something wrong!')
            
        
        
            
            
       
p1=Point(-3,3)
p2=Point(2,6)
p3=Point(6,5)
p4=Point(5,-3)
p5=Point(-2,-2)
p6=Point(-4,2,False)
p7=Point(2,0,False)



po1=Polygon()
print('多边形面积为:',po1.Area(True))
print('多边形周长为:%.2f'%po1.Perimeter())
print('p6是否在多边形内',po1.PointInPolygon(p6))
print('p7是否在多边形内',po1.PointInPolygon(p7))
[a,b]=p1.Angle(p2,p5)
print('p1为端点形成的夹角为;%.2f'%b)

'''三个类中还有些其他方法,因为比较简单,所以没有一一实现'''






  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值