Почему patch.contains_point() ведет себя иначе, чем patch.get_path().contains_point() при проверке, находятся ли точки внутри многоугольника?

#python #matplotlib #path #patch

#python #matplotlib #путь #patch

Вопрос:

С matplotlib.patches patch.contains_point(xy) метод, похоже, работает иначе patch.get_path().contains_point(xy) , по крайней мере, после добавления исправления к осям. Смотрите разницу True/True и True/False ниже. Я не могу найти никакой документации по этому различию. Кто-нибудь знает? Мне также трудно понять, как contains_point() определить, находится ли точка внутри пути, учитывая, что вершины пути в данном случае являются единичным прямоугольником, а не прямоугольником, который я указал.

 fig, ax = plt.subplots()
rect = patches.Rectangle([0.2, 0.3], 0.8, 0.5)

pnt = [0.4, 0.45] # point inside rect
print("Before adding patch to axes:")
print(rect.get_path().vertices)
print(rect.contains_point(pnt))
print(rect.get_path().contains_point(pnt))

print("After adding patch to axes")
ax.add_patch(rect)
print(rect.get_path().vertices)
print(rect.contains_point(pnt))
print(rect.get_path().contains_point(pnt))

plt.show()

Before adding patch to axes:
[[0. 0.]
 [1. 0.]
 [1. 1.]
 [0. 1.]
 [0. 0.]]
True
True
After adding patch to axes
[[0. 0.]
 [1. 0.]
 [1. 1.]
 [0. 1.]
 [0. 0.]]
False
True
  

Ответ №1:

Хотя этот вопрос старый, я только что столкнулся с той же проблемой и решил ее.

Проблема заключается в том, что после добавления исправления к осям вам необходимо указать координаты / точки в системе отсчета отображения. Это может быть выполнено с помощью:

 ax.transData.transform()
  

Я добавил одну строку в ваш код, игнорируя операторы импорта. Итак, код идет здесь:

 import matplotlib.pyplot as plt
import matplotlib.patches as patches

fig, ax = plt.subplots()
rect = patches.Rectangle([0.2, 0.3], 0.8, 0.5)

pnt = [0.4, 0.45] # point inside rect
print("Before adding patch to axes:")
print(rect.get_path().vertices)
print(rect.contains_point(pnt))
print(rect.get_path().contains_point(pnt))

print("After adding patch to axes")
ax.add_patch(rect)
print(rect.get_path().vertices)
# added lines
pnt_in_display_coordiantes = ax.transData.transform(pnt)
print(rect.contains_point(pnt_in_display_coordiantes))
print(rect.get_path().contains_point(pnt))

plt.show()
  

Вывод:

 Before adding patch to axes:
[[0. 0.]
[1. 0.]
[1. 1.]
[0. 1.]
[0. 0.]]
True
True
After adding patch to axes
[[0. 0.]
[1. 0.]
[1. 1.]
[0. 1.]
[0. 0.]]
True
True
  

Подробнее: https://matplotlib.org/stable/tutorials/advanced/transforms_tutorial.html