Здравствуйте!
В продолжение этой темы (и, так называемого, "проекта" Шри Янтра), появилось некоторое продолжение.
В принципе, оставалось самое легкое - Внешний Контур. Он сильно "ломаный", но много-симметричный - главное, определить координаты первых пяти точек (я начал с верхнего левого угла).
Сразу же, пришли два варианта: первый - как с "лепестками": вычислить вектора этих точек и по определенному циклу установить остальные точки массива координат. Второй - даже легче: нарисовать квадрат, который в центре и, затем, 4 пары прямоугольников, которые образуют выступы в Контуре.
Всё работает, но решил пойти, как всегда, более трудным путем (хоть и интересным) - через отражения.
Так и не смог найти этот метод (хотя в ЛО есть такая возможность как отразить фигуры - по горизонтали или вертикали) - предполагаю, что в макросах этим мало кто пользуется.
Пришлось самому "соорудить" такую функцию. Она определяет координаты отраженной точки: задается центр построения, угол линии для отражения (против часовой стрелки) и сама точка (эта точка, и которая получается - в абсолютных координатах и в структурах ("...awt.Point").
Но столкнулся с "непонятками" с функцией MOD (остаток от деления). В таблицах Calc она работает как нужно (насколько я могу себе это представить), а в Basic выдает другой результат. На примере: Calc: -57 MOD 360 результат 303, а Basic: -57 MOD 360 результат -57.
Не знаю какой вариант правильно решается, но для моей программы подходит первый вариант. К тому же, сама функция возвращает значение округленное до целого - это снижает точность расчета. Сделал свой вариант этой функции.
' Функция определения остатка от деления
' делимое, делитель, количество разрядов для сохранения результата
Function ModDoubleDigits(NumberInput#, NumberMod#, Digits&) As Double
Dim dg&
dg = 10^Digits
ModDoubleDigits = ((NumberInput * dg + NumberMod * dg) Mod NumberMod * dg) / dg
End Function
======
Сама функция отражения точки получилась не совсем "легкая", так как уверен, что есть более "изящное" и простое решение. Возможно, что в этом случае, не нужна и дополнительная функция (MOD для углов).
Эту функцию я уже завел в свой макрос - всё работает, за пару дней тестирования ни разу не подвела.
' Функция для отражения точки
' Задается центр, через который проходит линия отражения,
' Координаты точки в структуре и угол линии отражения, в направлении против часовой стрелки
Function MirrorPoint(CenterXX, CenterYY, CoordPoint As "com.sun.star.awt.Point", AngleMirror#) As "com.sun.star.awt.Point"
Dim CoordMirror As New com.sun.star.awt.Point
Dim Quadrant% ' Квадрант, в котором находится заданная Точка
Dim LenVector# ' Длина Вектора Точки
Dim AngleVector# ' Угол Вектора Точки
Dim AngleReflect# ' Угол Отражения
Dim xP#, yP# ' Координаты заданной Точки
Dim Z1, Z2
AngleMirror = ModDoubleDigits(AngleMirror, 360, 4)
xP = CoordPoint.X - CenterXX
yP = CoordPoint.Y - CenterYY
' Определяется Квадрант (если точка в центре построения - результат 0)
If xP > 0 Then
If yP >= 0 Then Quadrant = 4 Else Quadrant = 1
ElseIf xP < 0 Then
If yP >= 0 Then Quadrant = 3 Else Quadrant = 2
ElseIf yP > 0 Then Quadrant = 4
ElseIf yP < 0 Then Quadrant = 1 Else Quadrant = 0
End If
' Вычисляются Длина Вектора Точки и его Угол
LenVector = Sqr(xP ^ 2 + yP ^ 2)
If Quadrant = 0 Then
AngleVector = 0
Else AngleVector = dArcCOS(Abs (xP) / LenVector) / dDegRad
End If
' В зависимости от Квадранта, определяется Угол Вектора в диапазоне (0; 359)
Z1 = 180 * (1 - ((Quadrant Mod 3) Mod 2))
Z2 = (((Quadrant * -1 Mod 2) + 3) MOD 3) - 1
AngleVector = ModDoubleDigits((Z1 + Z2 * AngleVector), 360, 4)
' Определяется угол, относительно которого отражается точка
' Между Вектором и Линией Зеркала угол должно быть не больше 90 градусов
AngleReflect = ABS(AngleMirror - AngleVector)
If AngleReflect > 90 And AngleReflect < 270 Then AngleMirror = AngleMirror + 180 Else AngleMirror = AngleMirror
AngleMirror = ModDoubleDigits(AngleMirror, 360, 4)
' Величина Угла Отражения (угол между заданным Вектором и отраженным)
AngleReflect = ModDoubleDigits(2 * AngleMirror - AngleVector, 360, 4)
' Полученные координаты отраженной точки
CoordMirror.X = CenterXX + COS(AngleReflect * dDegRad) * LenVector
CoordMirror.Y = CenterYY + SIN(AngleReflect * dDegRad) * LenVector * (-1)
MirrorPoint = CoordMirror
End Function
Хочу попросить, по возможности и при желание, посмотреть, есть ли какие-нибудь ошибки. Кто-то, возможно, опытным и профессиональным взглядом уведет недочёты. Может быть, есть и готовые решения или варианты улучшить эту функцию.
Я оставил комментарии и некоторые лишние выражения для удобства - это всегда можно убрать.