Маскировка Matplotlib - Сбрасывает zorder пикселей в зависимости от их текущего значения цвета? - PullRequest
1 голос
/ 22 сентября 2019

1) Мне нужна маскирующая способность, которой нет в Matplotlib.(Пожалуйста, дайте мне знать, если это не так).

2) Matplotlib имеет возможность обрезки, но «обрезанные» области используют один и тот же zorder, поэтому рендеринг нескольких перекрывающихся многоугольников должен быть основан наих Zorder терпит неудачу в областях, где отсечение использовалось, чтобы визуализировать одну из них, потому что все, что мы ранее визуализировали ниже обрезанных областей, стирается (все так сказать белым).

3) Если бы это быломожно «обнулить» zorder данного цвета пикселя (наш цвет фона) в любое время при рендеринге, тогда мы бы решили проблему с отсечкой.Нам даже не понадобится отсечение, так как мы можем просто использовать данное значение zorder для частей, которые определяют желаемые области маски, и более низкое zorder для части, которая будет обрезана, и после рендеринга рассматриваемой детали мы меняем zorder всех«белые» пиксели до очень низкого значения zorder, и у нас есть возможность маскирования!

Вот очень простой пример кода, иллюстрирующий необходимость:

'''Example of two overlapping squares having arbitrary openings in them.
In this example the opening is just two smaller overlapping square, but it can be anything.
We want to paint the green and red squares so that we see what is behind the opening(s)'''
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(6, 6))

# This is to test if a well ordered polygon with slits (to define holes) can be rendered
quad_small = [(-0.2, -0.2), (-0.2, 0.2), (0.2, 0.2), (0.2, -0.2), (-0.2, -0.2)]
quad1x1 = [(-1, 1.), (-1, -1.), (1, -1.), (1., 1.), (-1, 1.)]

#Fill quad1x1 with green
x11 = [coord[0] for coord in quad1x1]
y11 = [coord[1] for coord in quad1x1]
plt.fill(x11, y11, facecolor='green', zorder=5)

'''Now make one or more holes, possibly overlapping holes, 
NOTE: if we use clipping to define the holes, Matplotlib sets the same zorder over all the clippped areas 
which was used. Also clipping does not work well with overlapping small squares. Would only work with nonoverlapping
squares.'''
xsq = [coord[0] for coord in quad_small]
ysq = [coord[1] for coord in quad_small]
plt.fill(xsq, ysq, facecolor='white', zorder=5)
xsq = [coord[0]+0.2 for coord in quad_small]
ysq = [coord[1]+0.2 for coord in quad_small]
plt.fill(xsq, ysq, facecolor='white', zorder=5)

'''At this point green and white openings have the same zorder=5.
We would need a call to change the zorder of all the 'white' pixels to a lower value, say 3'''

'''Now we want to render another polygon (red) with holes, but ONLY on areas not covered by the previous rendering,
we use a lower zorder so that we do not paint on the green part'''
x11 = [coord[0]+0.3 for coord in quad1x1]
y11 = [coord[1]+0.3 for coord in quad1x1]
plt.fill(x11, y11, facecolor='red', zorder=4)
xsq = [coord[0]+0.3 for coord in quad_small]
ysq = [coord[1]+0.3 for coord in quad_small]
plt.fill(xsq, ysq, facecolor='white', zorder=4)
xsq = [coord[0]+0.5 for coord in quad_small]
ysq = [coord[1]+0.5 for coord in quad_small]
plt.fill(xsq, ysq, facecolor='white', zorder=4)

'''The hole (white area) of the green square is not painted in red because the zorder of the white area is higher'''

plt.show()

Снимок рендеринга, выполненного с помощью кода выше

Ответы [ 2 ]

1 голос
/ 23 сентября 2019

Кажется, отсечение даже не нужно;потому что все поверхности закрыты.

import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(6, 6))


xi, yi = np.array([(-0.2, -0.2), (-0.2, 0.2), (0.2, 0.2), (0.2, -0.2), (-0.2, -0.2)]).T
xo, yo = np.array([(-1, 1.), (-1, -1.), (1, -1.), (1., 1.), (-1, 1.)]).T

plt.fill(list(xo)+list(xi), list(yo)+list(yi), facecolor='green', zorder=5)
plt.fill(list(xo+.3)+list(xi+.3), list(yo+.3)+list(yi+.3), facecolor='red', zorder=4)

plt.show()

enter image description here

0 голосов
/ 24 сентября 2019

Предложенное выше решение НЕ работает, потому что оно предназначено для одиночного непересекающегося небольшого квадрата.Когда мы используем два перекрывающихся четырехугольника (небольшое изменение в вашем примере):

import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(6, 6))

xi, yi = np.array([(-0.2, -0.2), (-0.2, 0.2), (0.2, 0.2), (0.2, -0.2), (-0.2, -0.2)]).T
xo, yo = np.array([(-1, 1.), (-1, -1.), (1, -1.), (1., 1.), (-1, 1.)]).T

plt.fill(list(xo)+list(xi)+list(xi+0.1), list(yo)+list(yi)+list(yi+0.1), facecolor='green', zorder=5)
plt.fill(list(xo+.3)+list(xi+.3), list(yo+.3)+list(yi+.3), facecolor='red', zorder=4)

plt.show()

Результаты такие, как показано в этом снимке

Кроме того, даже в вашем примере содин неперекрывающийся маленький квадрат, если этот квадрат не полностью «внутри» большего многоугольника, существует проблема рендеринга, как показано ниже:

mport numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(6, 6))

xi, yi = np.array([(-0.2, -0.2), (-0.2, 0.2), (0.2, 0.2), (0.2, -0.2), (-0.2, -0.2)]).T
#xo, yo = np.array([(-1, 1.), (-1, -1.), (1, -1.), (1., 1.), (-1, 1.)]).T
xo, yo = np.array([(-.1, .1), (-1, -1.), (1, -1.), (1., 1.), (-.1, .1)]).T

#plt.fill(list(xo)+list(xi)+list(xi+0.1), list(yo)+list(yi)+list(yi+0.1), facecolor='green', zorder=5)
plt.fill(list(xo)+list(xi), list(yo)+list(yi), facecolor='green', zorder=5)
plt.fill(list(xo+.3)+list(xi+.3), list(yo+.3)+list(yi+.3), facecolor='red', zorder=4)

plt.show()

Это результат: Плохой рендеринг, когдамаленький квадрат частично снаружи

Возможно, с помощью Shapely union вы можете решить первую проблему с перекрытием маленьких квадратов, но как мы собираемся решить проблему с частично квадратами снаружи?Пожалуйста, дайте мне знать, что лучше для этого случая.

...