Отразить точку на решетке поперек плоскости
Я имею решетчатую трехмерную решетку размера 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)
всегда будет целым числом.