Вообщем, это может быть очень хреновым алгоритмом, но я не вижу где он будет сбоить...
Я подумал еще раз и мне кажется что вариант с думми-атомами который я излагал как блок-схему несколько страниц назад самый надежный в отношении переориентаций и определения длины векторов в плоскости среза.
1) получаем от пользователя один вектор: L,M,N
2) ставим 3 dummy атома:
- если буква не равна нулю - на соответствуюшем векторе (то есть например 0,1/M,0, это не декартова координата а фракционная/кристаллографическая),
- если буква равна нулю - дубль ненулевой буквы сдвинутый вдоль этого вектора.
Звучит ужасно. Смотрим.
Код: Выделить всё
Запись 1,1,1 дает точки 1,0,0 0,1,0 0,0,1
Запись 2,1,1 дает точки 1/2,0,0 0,1,0 0,0,1
Запись 1,1,0 дает точки 1,0,0 0,1,0 1,0,1
Запись 2,0,1 дает точки 1/2,0,0 1/2,1,0 0,0,1
Запись 1,0,0 дает точки 1,0,0 1,1,0 1,0,1
Запись 0,0,2 дает точки 1,0,1/2 0,1,1/2 0,0,1/2
Запись 3,2,1 дает точки 1/3,0,0 0,1/2,0 0,0,1
3) имеем три пары точек, домножаем каждую на наименьшее общее кратное знаменателей
Для вектора 3,2,1 и точек
получаем пары точек.
2,0,0 – 0,3,0
1,0,0 – 0,0,3
0,1,0 – 0,0,2
Все эти точки расположены в углах ячеек то есть являются эквивалентными/периодическими (и лежат в плоскости перпендикулярной заказанному вектору).
Вычисляем длину каждого из 3 отрезков, самый длинный выбрасываем. Два оставшихся представляют собой векторы удовлетворяющие нашим условиям (так как расстояние между концами векторов, у которых общее начало соответствует векторной разности, то это вектора 2,-3,0 ; 1,0,-3 или 0,1,-2). Эти вектора обеспечивают минимальную площадь среза, хотя и не обязательно являются минимальной длины сами. Можно попробовать модифицировать один из векторов вычитая из него другой (это допустимо так как мы просто попадаем в другой угол ячейки). Например, если изначально выбранными являются вектора 1,0,-3 и 0,1,-2 то можно вычесть второй вектор из первого, получив 1,-1,-1 что весьма вероятно более короткий вектор чем 1,0,-3
Примечание-контроль: если среди L,M,N есть 0, то соответствующий вектор переходит на ячейку среза напрямую а соответствующая точка исключается из рассмотрения. То есть 2,0,1 дает 2 вектора: 0,1,0 и вектор между точками 1/2,0,0 и 0,0,1, то есть вектор 1,0,-2
Можно еще убедиться получилась ли правовращающая система векторов (и при необходимости поменять знаки у одного вектора или поменять вектора местами), но мне это кажется бесполезным.
Визуализируем точки и визуализируем параллелограмм построенный на этих 2 векторах.