我从很远的地方开始解释我的问题,因此您可以建议完全不同的方法并理解自定义对象和功能。 多年来,我录制了许多自行车GPS轨道(.gpx)。我决定将这些(大部分是重叠的)曲目合并为一个大图,并合并/删除大多数曲目点。到目前为止,我已经设法简化了轨道(gpxpy模块中的功能,删除了大约90%的跟踪点,同时保留了角落的位置)并将它们加载到我当前的程序中。
当前的Python 3程序包括加载gpx轨道和使用四次扫描优化图形。这是我计划中的计划步骤:
在我的程序中,我开始计算0的步骤,因为第一个只是打开和解析文件。 Stackoverflow不允许我从0开始排序。
为了存储图形,我有一个字典 punktid (指向爱沙尼亚语),其中 punkt (点)对象存储在密钥uid / ui(唯一ID)中。唯一ID也存储在点本身。在第2步和第3步中使用权重属性来查找点的平均值,同时考虑先前的合并。
class punkt:
def __init__(self,lo,la,idd,edge=set(),ele=0, wei=1):
self.lng=lo #Longtitude
self.lat=la #Latitude
self.uid=idd #Unique ID
self.edges=edge #Set of neighbour nodes
self.att=ele #Elevation
self.weight=wei #Used to get weighted average
>>> punktid
{1: <__main__.punkt object at 0x0000006E9A9F7FD0>,
2: <__main__.punkt object at 0x0000006E9AADC470>, 3: ...}
>>> punktid[1].__dict__
{'weight': 90, 'uid': 9000, 'att': 21.09333333333333, 'lat': 59.41757, 'lng': 24.73907, 'edges': {1613, 1218, 1530}}
正如您所看到的,清理中存在一个小错误,其中uid未更新。我现在已经修好了,但我把它留了下来,所以你可以看到图表的比例。朋克蒂的最大指数是1699/11787。
假设我有3个点:A,B和C(i,lyhem(2)和lyhem(0)分别在下面的代码片中)。 A与B和C具有共同边,但B和C可能没有共同边。 C更接近于A而不是B.为了减小图的大小,我想将C移近边AB(同时考虑B和C的权重)并将AB重定向到C.
我想出的解决方法是在AB上找到最接近C的临时点D.然后找到D和C之间的加权平均值,将其保存为E并将所有C边和AB重定向到该点。 Simplified figure - 请注意,E =(C + D)/ 2并不完全准确。我不能添加两个以上的链接,但我还有2个图像说明了我的问题。
最大的问题是找到D的坐标。我在Mathematica网站上找到possible solution,但它包含±符号,因为找到坐标时有两个可能的坐标。但我有线,点在哪里。无论如何,我不知道如何正确实现它,我的代码变得非常混乱:
# 2-nd run: Merge edges under small angles
for i in set(punktid.keys()):
try:
naabrid1=frozenset(punktid[i].edges) # naabrid / neighbours
for e in naabrid1:
t=set(naabrid1)
t.remove(e)
for u in t:
try:
a=nurk_3(punktid[i], punktid[e], punktid[u]) #Returns angle EIU in degrees. 0<=a<=180
if a<10:
de=((punktid[i].lat-punktid[e].lat)**2+
((punktid[i].lng-punktid[u].lng))*2 **2) #distance i-e
du=((punktid[i].lat-punktid[u].lat)**2+
((punktid[i].lng-punktid[u].lng)*2) **2) #distance i-u
b=radians(a)
if du<de:
lyhem=[u,du,e] # lühem in English is shorter
else: # but currently it should be lähem/closer
lyhem=[e,de,u]
if sin(b)*lyhem[1]<r:
lr=abs(sin(b)*lyhem[1])
ml=tan(nurk_coor(punktid[i],punktid[lyhem[0]])) #Lühema tõus / Slope of closer (C)
mp=tan(nurk_coor(punktid[i],punktid[lyhem[2]])) #Pikema / ...farer / B
mr=-1/ml #Ristsirge / ...BD
p1=(punktid[i].lng+lyhem[1]*(1/(1+ml**2)**0.5), punktid[i].lat+lyhem[1]*(ml/(1+ml**2)**0.5))
p2=(punktid[i].lng-lyhem[1]*(1/(1+ml**2)**0.5), punktid[i].lat-lyhem[1]*(ml/(1+ml**2)**0.5))
d1=((punktid[lyhem[0]].lat-p1[1])**2+
((punktid[lyhem[0]].lng-p1[0])*2)**2)**0.5 #distance i-e
d2=((punktid[lyhem[0]].lat-p2[1])**2+
((punktid[lyhem[0]].lng-p2[0])*2)**2)**0.5 #distance i-u
if d1<d2: # I experimented with one idea,
x=p1[0]#but it made things worse.
y=p1[1]#Originally I simply used p1 coordinates
else:
x=p2[0]
y=p2[1]
lo=punktid[lyhem[2]].weight*p2[0] # Finding weighted average
la=punktid[lyhem[2]].weight*p2[1]
la+=punktid[lyhem[0]].weight*punktid[lyhem[0]].lat
lo+=punktid[lyhem[0]].weight*punktid[lyhem[0]].lng
kaal=punktid[lyhem[2]].weight+punktid[lyhem[0]].weight #kaal = weight
c=(la/kaal,lo/kaal)
punktid[ui]=punkt(c[1],c[0], ui,punktid[lyhem[0]].edges, punktid[lyhem[0]].att,kaal)
punktid[i].edges.remove(lyhem[2])
punktid[lyhem[2]].edges.remove(i)
try:
for n in punktid[ui].edges: #In all neighbours
try: #Remove link to old point
punktid[n].edges.remove(lyhem[0])
except KeyError:
pass #If it doesn't link to current
punktid[n].edges.add(ui) #And add new point
if log:
printf(punktid[n].edges,'naabri '+str(n)+' edges')
except KeyError: #If neighbour itself has been removed
pass #(in same merge), Ignore
punktid[ui].edges.add(lyhem[2])
punktid[lyhem[2]].edges.add(ui)
punktid.pop(lyhem[0])
ui+=1
except KeyError: # u has been removed
pass
except KeyError: # i has been removed
pass
这是一个代码段,由于缺少变量/函数,它很可能在复制粘贴后不能运行。在从第if sin(b)*lyhem[1]<r
开始到punktid[ui]=..
的第3个if语句中,第22到43行计算新点。之后将旧边重定向到新节点。
明确说明问题:如果已知线段(AC)的两个坐标和这些点处的角度(角度ACB应为90度),如何找到光线上的点(AB)?如何在Python 3.5中实现它?
PS。 (Meta)如果有人需要完整的资源,我怎么能提供它(上传单个文本文件而不注册)?粘贴或粘贴(垃圾邮件)它在这里?如果我将其上传到其他网站,如何提供链接,如果新手用户被限制为两个?