首页 > 解决方案 > 在 Python 中使用 matplotlib 注释二维线图的距离

问题描述

有谁知道,如何显示情节中每个点的距离。为此,我正在使用 matplotlib。距离函数已经在 for 循环下工作以打印每个线段的距离。但我希望在每个线段图上显示这些距离。在这方面的任何帮助将不胜感激。

from math import *

import matplotlib.pyplot as plt

import numpy as np

def DistanceBwPoints(ln1):

    x1 , y1 = ln1[0][0] , ln1[0][1]
    x2 , y2 = ln1[1][0] , ln1[1][1]

    dis = sqrt ((x2 - x1)**2 + (y2 - y1)**2 )

    return dis


def visualization2(a,b):

    x1 = []
    y1 = []
    for pt in a:
        x1 += [pt[0]]
        y1 += [pt[1]]
    plt.plot(x1,y1, 'yo')
    
    m1=[]
    m1 = range(len(x1))
    for i in np.arange(0,len(m1)-1,2):
        plt.plot(x1[i:i+2],y1[i:i+2], color=b)

my_list = [[416689.15984457487, 5961369.921824793], [416463.47437214176, 5961262.376170568], [416784.93559347134, 5961169.622417776], [416662.37786889425, 5961110.342221191], [416882.24253254064, 5960968.447021521], [416861.28136564675, 5960958.308271814]]
for i in range(0,len(my_list)-1,2):
    ln = my_list[i] , my_list[i+1]
    print(round(DistanceBwPoints(ln),2))

visualization2(my_list,'red') 
plt.axis('equal')
plt.show()

标签: pythonmatplotlib

解决方案


Matplotlib 具有将文本绘制成图形的text和函数。annotate在你的情况下,text就足够了。在原始答案(见下文)中,我试图尽可能地保持你的结构,但由于无论如何都必须为绘图计算距离,我已将其集成到绘图循环中以避免代码重复。但最初的简单方法对于斜坡以外的斜坡看起来很奇怪。所以,这是一个改进的版本,同时保持你的一般结构:

from math import sqrt
import matplotlib.pyplot as plt
import numpy as np

my_list = [[1, 2], [10, 20], [30, 80], [70, 50], [110, 120], [180, 190], [130, 20], [180, 20], [10, 120], [10, 150]]
    
def DistanceBwPoints(ln1):
    x1 , y1 = ln1[0][0] , ln1[0][1]
    x2 , y2 = ln1[1][0] , ln1[1][1]    
    dis = sqrt ((x2 - x1)**2 + (y2 - y1)**2 )    
    return dis
  
def visualization2(a,b):    
    x1 = []
    y1 = []
    for pt in a:
        x1 += [pt[0]]
        y1 += [pt[1]]
    plt.plot(x1,y1, 'yo')
    
    m1 = range(len(x1))
    for i in np.arange(0,len(m1)-1,2):
        #plot line
        plt.plot(x1[i:i+2],y1[i:i+2], color=b)
        #calculate distance
        curr_dist = round(DistanceBwPoints([my_list[i], my_list[i+1]]),2)
        print(f"Line number {i//2+1} with distance", curr_dist)
        
        #determine slope direction of line to set text anchors correctly
        ln_slope = 1 + int(np.sign(np.diff(x1[i:i+2]) * np.diff(y1[i:i+2])))
        text_anchor_ha = ["left", "center", "right"][ln_slope]
        text_anchor_va = "bottom"
        #special case vertical line
        if not np.diff(x1[i:i+2]):
            text_anchor_ha, text_anchor_va = "right", "center"
        #annotate line    
        plt.text(x=np.mean(x1[i:i+2]), y=np.mean(y1[i:i+2]), s=curr_dist, ha=text_anchor_ha, va=text_anchor_va)

visualization2(my_list,'red') 
plt.axis('equal')
plt.show()

样本输出: 在此处输入图像描述

还有一件事——我变了from math import *。请阅读这里为什么import *是一个坏主意。

原始答案

from math import sqrt
import matplotlib.pyplot as plt
import numpy as np

def DistanceBwPoints(ln1):

    x1 , y1 = ln1[0][0] , ln1[0][1]
    x2 , y2 = ln1[1][0] , ln1[1][1]

    dis = sqrt ((x2 - x1)**2 + (y2 - y1)**2 )

    return dis


def visualization2(a,b):

    x1 = []
    y1 = []
    for pt in a:
        x1 += [pt[0]]
        y1 += [pt[1]]
    plt.plot(x1,y1, 'yo')
    
    m1 = range(len(x1))
    for i in np.arange(0,len(m1)-1,2):
        plt.plot(x1[i:i+2],y1[i:i+2], color=b)
        curr_dist = round(DistanceBwPoints([my_list[i], my_list[i+1]]),2)
        print(i, curr_dist)
        plt.text(x=np.mean(x1[i:i+2]), y=np.mean(y1[i:i+2]), s=curr_dist, ha="right", va="bottom")

my_list = [[416689.15984457487, 5961369.921824793], [416463.47437214176, 5961262.376170568], [416784.93559347134, 5961169.622417776], [416662.37786889425, 5961110.342221191], [416882.24253254064, 5960968.447021521], [416861.28136564675, 5960958.308271814]]

visualization2(my_list,'red') 
plt.axis('equal')
plt.show()

样本输出: 在此处输入图像描述


推荐阅读