找到给定2个坐标的(右)三角形的第三个坐标,并将光线映射到第三个

时间:2016-07-27 15:24:37

标签: python algorithm coordinates trigonometry

我从很远的地方开始解释我的问题,因此您可以建议完全不同的方法并理解自定义对象和功能。 多年来,我录制了许多自行车GPS轨道(.gpx)。我决定将这些(大部分是重叠的)曲目合并为一个大图,并合并/删除大多数曲目点。到目前为止,我已经设法简化了轨道(gpxpy模块中的功能,删除了大约90%的跟踪点,同时保留了角落的位置)并将它们加载到我当前的程序中。

当前的Python 3程序包括加载gpx轨道和使用四次扫描优化图形。这是我计划中的计划步骤:

  1. 从gpx(工作)
  2. 导入点
  3. 加入彼此靠近的点(工作)
  4. 在小角度下合并边缘(问题在于此步骤)
  5. 去除直道上的点(两条边之间的角度超过170度)。看起来它正在运作。
  6. 通过重置点的唯一索引(工作)进行清理
  7. 最终检查图表中的所有边缘。
  8. 在我的程序中,我开始计算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)如果有人需要完整的资源,我怎么能提供它(上传单个文本文件而不注册)?粘贴或粘贴(垃圾邮件)它在这里?如果我将其上传到其他网站,如何提供链接,如果新手用户被限制为两个?

0 个答案:

没有答案