2015-03-15 3 views
1

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

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

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

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

+2

Этот вопрос, похоже, более подходит для http://math.stackexchange.com/ – sashas

+0

См. [Отражение точки относительно плоскости с использованием преобразования матрицы] (http://math.stackexchange.com/q/952092) –

+0

Является ли преобразование домашних хозяйств излишним для этого ... Я ищу простую и оптимальную реализацию – gforce89

ответ

2

Дать плоскости как уравнение

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

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

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

Так что теперь у вас есть уравнение плоскости, и хотите, чтобы отразить в этой плоскости. The link Woodface provided - это, по сути, правильная вещь для рассмотрения здесь, но вы можете предпочесть более простую формулировку этой идеи. Для начала перезаписи уравнения плоскости

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) всегда будет целым числом.