РЕДАКТИРОВАТЬ : pymrt.geometry
было удалено в пользу raster_geometry
.
Учитывая, что цилиндр имеет выпуклую форму, онможно перебрать все, кроме 1 измерения и уменьшить проблему до 1D.Там (в 1D) легко написать эффективный способ заполнения пробелов, потому что все, что нужно, это, по сути, найти, где находятся границы (что можно сделать с помощью numpy.where()
), а затем заполнить все от минимумаи максимальные координаты.
Это реализовано в pymrt.geometry.fill_convex()
для N-мерных задач (пока недоступно в версии pypi
, необходимо взять из репозитория Bitbucket).Отказ от ответственности, я являюсь основным автором этого.
Вкратце, (упрощенный) код (адаптированный к 3D) выглядит так:
def fill_convex(arr):
for i in range(arr.shape[1]):
for j in range(arr.shape[2]):
mask = slice(None), slice(i, i + 1), slice(j, j + 1)
line = arr[mask]
k = np.where(line > 0)[0]
if len(k):
start, stop = np.min(k), np.max(k)
line[start:stop] = 1
return arr
Чтобы увидеть это в действии на бетоне (но2D и не цилиндрический / эллиптический) пример:
import numpy as np
import pymrt as mrt
import pymrt.geometry
# generate a convex border (although it is not elliptical)
points = ((1, 1), (0, 6), (5, 4), (4, 2))
line_points = tuple(x for x in mrt.geometry.bresenham_lines(points, True))
arr = mrt.geometry.render_at((8, 8), line_points)
print(arr.astype(int))
# [[0 0 0 0 1 1 1 0]
# [0 1 1 1 0 0 1 0]
# [0 1 0 0 0 1 0 0]
# [0 0 1 0 0 1 0 0]
# [0 0 1 0 1 0 0 0]
# [0 0 0 1 1 0 0 0]
# [0 0 0 0 0 0 0 0]
# [0 0 0 0 0 0 0 0]]
# fill everything inside the convex shape
arr = mrt.geometry.fill_convex(arr)
print(arr.astype(int)
# [[0 0 0 0 1 1 1 0]
# [0 1 1 1 1 1 1 0]
# [0 1 1 1 1 1 0 0]
# [0 0 1 1 1 1 0 0]
# [0 0 1 1 1 0 0 0]
# [0 0 0 1 1 0 0 0]
# [0 0 0 0 0 0 0 0]
# [0 0 0 0 0 0 0 0]]