Отразить точку на решетке поперек плоскости

Я имею решетчатую трехмерную решетку размера lx * ly * lz с периодическими граничными условиями со всех трех сторон. Мои разрезы с плоской симметрией представляют собой две горизонтальные и вертикальные плоскости (наклон 0 и inf) плюс два диагональных разреза (наклон -1 и +1), перпендикулярных плоскости xy, плоскости yz и плоскости xz. Итак, у меня есть 9 типов плоскостей, все они проходят через точки решетки, а не между ними.

Каждый из этих разрезов может проходить в любом месте на плоскости, перпендикулярной им. Например, наклон 0, перпендикулярный плоскости xy, может проходить в любой из точек ly. Наклон inf inf, перпендикулярный плоскости xy, может проходить в любой из точек lx. Наклон +1, перпендикулярный плоскости xy, может проходить через любое из lx пересечений. Срез -1, перпендикулярный плоскости xy, может проходить через любые пересечения.

Теперь, когда сайт i находится на решетке между 0 и (lx * ly * lz)-1, я хотел бы отразить это на любом случайном разрезе c от 1 до 9. Какой будет самый быстрый алгоритм для расчета отраженного узел решетки предпочтительно в "с".

Алгоритм должен принимать три входа: сайт i, тип разреза c и точку пересечения, через которую проходит разрез, между 0 и lx-1 или 0 и ly-1 или 0 и lz-1, в зависимости от разреза и Вывести отраженный сайт.

1 ответ

Решение

Написание плоскости как уравнения

Вместо "откосов" я бы предпочел говорить о нормалях этих самолетов. Итак, насколько я понимаю ваш вопрос, у вас есть

xy plane, slope  0 ⇒ normal (0,  1,  0)
xy plane, slope  ∞ ⇒ normal (1,  0,  0)
xy plane, slope  1 ⇒ normal (1, -1,  0)
xy plane, slope -1 ⇒ normal (1,  1,  0)
xz plane, slope  0 ⇒ normal (0,  0,  1)
xz plane, slope  ∞ ⇒ normal (1,  0,  0)
xz plane, slope  1 ⇒ normal (1,  0, -1)
xz plane, slope -1 ⇒ normal (1,  0,  1)
yz plane, slope  0 ⇒ normal (0,  0,  1)
yz plane, slope  ∞ ⇒ normal (0,  1,  0)
yz plane, slope  1 ⇒ normal (0,  1, -1)
yz plane, slope -1 ⇒ normal (0,  1,  1)

Таким образом, 9 видов самолетов будут соответствовать нормальным направлениям

(1, 0, 0), (0, 1, 0), (0, 0, 1),
(1, 1, 0), (1, 0, 1), (0, 1, 1),
(1, -1, 0), (1, 0, -1), (0, 1, -1)

Для каждого из этих направлений можно взять вектор нормали (a, b, c) и превратить это в уравнение плоскости:

a*x + b*y + c*z = d

но какие значения для d предопределены? Для первого ряда выше, плоскостей, параллельных одной из координатных плоскостей, все просто: для (a, b, c) = (1, 0, 0) у тебя есть 0 ≤ d < lxи аналогичные для двух других. Для диагональных плоскостей соблюдены ваши (на мой взгляд, странные) правила перехвата. Если я вас правильно понимаю, то (1, -1, 0) самолеты могут проходить через любую точку x ось, ведущая к 0 ≤ d < lx снова. (1, 1, 0) самолеты могут проходить через любую точку y ось, так что вы бы 0 ≤ d < ly, Для других диагоналей, пожалуйста, определите границы d сам.

Отражая в такой плоскости

Итак, теперь у вас есть уравнение плоскости, и вы хотите отразить в этой плоскости. Ссылка, предоставленная Woodface, по сути, является правильной вещью, но вы можете предпочесть более простую формулировку этой идеи. Начните с переписывания уравнения плоскости в

a*x + b*y + c*z - d = 0

Если левая часть не равна нулю, то данная точка не лежит на плоскости. В этом случае полученное значение пропорционально расстоянию этой точки от плоскости. Предположим на данный момент, что a²+b²+c²=1, В этом случае значение левой стороны действительно будет расстоянием от плоскости. Умножение этого числа на нормальный вектор (a, b, c) Вы получаете вектор, который указывает от плоскости к рассматриваемой точке. Умножение количества на -(a, b, c) вместо этого вы получите вектор, указывающий от точки к плоскости, и умножить на -2*(a, b, c) Вы получаете вектор, указывающий от точки к ее зеркальному отображению.

Но что, если a²+b²+c²≠1? В этом случае значение левой части уравнения будет sqrt(a²+b²+c²) раз реальное расстояние. И вы умножаете это расстояние на вектор, который имеет не единицу длины, а длину sqrt(a²+b²+c²) вместо этого, поэтому ваш вектор конечного результата будет слишком большим в a²+b²+c² в целом. Так что вы делаете, вы масштабируете по этому фактору.

Подводя итог: отразить точку (x, y, z) в плоскости a*x + b*y + c*z = d ты вычисляешь

(x, y, z) - 2/(a² + b² + c²)*(a*x + b*y + c*z - d)*(a, b, c)

или написано в коде C:

int f = 2/(a*a + b*b + c*c)*(a*x + b*y + c*z - d);
x = x - f*a;
y = y - f*b;
z = y - f*z;

Ты можешь использовать int здесь, так как для ваших нормальных векторов, a²+b²+c² будет либо 1 или же 2, так 2/(a*a + b*b + c*c) всегда будет целым числом.

Другие вопросы по тегам