# -*- 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)
'''三个类中还有些其他方法,因为比较简单,所以没有一一实现'''
Python类(Class)在GIS上的应用
最新推荐文章于 2024-03-31 18:00:00 发布