Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

31 Март 2020, 15:45 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
Новости: Доступно и просто о работе в офисных пакетах
 
   Начало   Помощь Поиск Войти Регистрация    задать вопрос  
Страниц: « 1 2 3 »   Вниз
  Печать  
Автор Тема: Построение фигур в Basic(LibreOffice)  (Прочитано 1661 раз)
0 Пользователей и 1 Гость смотрят эту тему.
rami
Гуру
*******
Offline Offline

Пол: Мужской
Сообщений: 2 885


MacBook Pro, LibreOffice и Apache OpenOffice


« Ответ #15: 12 Март 2020, 21:24 »

У вас получилось почти как у меня, единственное хочу заметить, что вместо двух строчек:
Код:
Dim Point
Point = createUnoStruct("com.sun.star.awt.Point")
лучше писать одну:
Код:
Dim aPoint As New "com.sun.star.awt.Point"
так меньше кода и переменная сразу создаётся как структура.

Вот моя функция:
Код:
Sub circle(oDoc, oDrawPage, x, y, r, color)
Dim oShape, aPoint As New "com.sun.star.awt.Point", aSize As New "com.sun.star.awt.Size"
oShape = oDoc.createInstance("com.sun.star.drawing.EllipseShape")
aPoint.X = x - r
aPoint.Y = y - r
aSize.Width = 2 * r
aSize.Height = 2 * r
oShape.setPosition(aPoint)
oShape.setSize(aSize)
oShape.FillColor = color
oDrawPage.add(oShape)
End Sub


Правильно ли я понимаю, что лепестки нарисованы, скорее всего, с помощью ClosedBezierShape?
Да, иначе вы её не закрасите. На каждый лепесток нужно 6 точек, все они могут быть типа CONTROL (но я не знаю, это нормально или фича)

Некоторая сложность - вывести формулу для вычисления самих координат точек, но... надо подумать.
Вычислить координаты точки в зависимости от угла и радиуса — это 5 класс. Формула в одну строчку (всего две строчки для X и Y)

В целом вы на правильном пути.
Записан

Tigrik
Участник
**
Offline Offline

Сообщений: 43


« Ответ #16: 12 Март 2020, 23:53 »

Да, так эти лепестки рисуются ГОРАЗДО легче.

Код:
Sub petals(oDoc, oDrawPage, x, y, r, n, color)
'Этот макрос будете писать после того, как получится рисовать круги (этот макрос содержит всего лишь 15 строк кода)
'    УРА!!! РАБОТАЕТ!!!
Dim oShape, Point As New "com.sun.star.awt.Point", i%
Dim oCoords As New "com.sun.star.drawing.PolyPolygonBezierCoords"   '   Координаты точек для кривой Безье
Dim CoordPetal(n * 6) As New com.sun.star.awt.Point     '  Координаты точек "лепестка"
Dim Flags(n * 6)                                 '  Флаги точек
  For i = LBound(CoordPetal) To UBound(CoordPetal)
' Заполняем фактическими координатами.
Point.X = x + r(i MOD 2) * SIN((360 / 6 / n) * i * (Pi / 180))
Point.Y = y - r(i MOD 2) * COS((360 / 6 / n) * i * (Pi / 180))
  CoordPetal(i) = Point
' Заполняем флагами
  If  (i MOD 3) = 0 Then Flags(i) = 0 Else Flags(i) = 2
  Next
oCoords.Coordinates = Array( CoordPetal )
oCoords.Flags = Array( Flags)
oShape = oDoc.createInstance("com.sun.star.drawing.ClosedBezierShape")
oDrawPage.add(oShape)
oShape.PolyPolygonBezier = oCoords
oShape.FillColor = color
End Sub
Правильно, так и должно быть?

=========
Но вопрос про "зеркало" для Фигур, а, также, есть ли возможность выносить центр вращение фигуры за границы самой фигуры - остался открытым!
« Последнее редактирование: 13 Март 2020, 00:20 от Tigrik » Записан
rami
Гуру
*******
Offline Offline

Пол: Мужской
Сообщений: 2 885


MacBook Pro, LibreOffice и Apache OpenOffice


« Ответ #17: 13 Март 2020, 12:59 »

Переменная Point As New "com.sun.star.awt.Point" не нужна, есть же массив структур CoordPetal(n * 6) As New com.sun.star.awt.Point, да и градусы не нужны.
Вместо:
Код:
Point.X = x + r(i MOD 2) * SIN((360 / 6 / n) * i * (Pi / 180))
Point.Y = y - r(i MOD 2) * COS((360 / 6 / n) * i * (Pi / 180))
  CoordPetal(i) = Point
можно:
Код:
CoordPetal(i).X = x+r(i Mod 2)*cos(i*pi/3/n)
CoordPetal(i).Y = y+r(i Mod 2)*sin(i*pi/3/n)
Записан

Tigrik
Участник
**
Offline Offline

Сообщений: 43


« Ответ #18: 13 Март 2020, 13:28 »

Переменная Point As New "com.sun.star.awt.Point" не нужна, есть же массив структур CoordPetal(n * 6) As New com.sun.star.awt.Point, да и градусы не нужны.
Градусы я оставил для наглядности, поэтому не стал сокращать цифры.
А с Point - это да, я "погорячился" - уже автоматически ставлю, даже куда не нужно.

Главное, что я чуть не проигнорировал такую ценную возможность (во всяком случае, для моих целей) как кривые Безье - я с ними начал разбираться, но как-то "вяло".
Поэтому, в очередной раз, хочу сказать Вам Спасибо - за очень своевременную и ценную подсказку (картинка с кругами многое "рассказала").
Записан
mikekaganski
Мастер
*****
Online Online

Пол: Мужской
Расположение: Хабаровск -> Москва
Сообщений: 1 755


« Ответ #19: 13 Март 2020, 13:36 »

Хм. То есть "(360 / 6 / n) * i * (Pi / 180)" нагляднее, чем "i * 2*Pi/(6*n)" - то есть прямо по-русски написанного "i-тая точка на окружности, поделённой на 6n"?
Записан

С уважением,
Михаил Каганский
Tigrik
Участник
**
Offline Offline

Сообщений: 43


« Ответ #20: 13 Март 2020, 13:55 »

Хм. То есть "(360 / 6 / n) * i * (Pi / 180)" нагляднее, чем "i * 2*Pi/(6*n)" - то есть прямо по-русски написанного "i-тая точка на окружности, поделённой на 6n"?

Я не успел исправить/дописать своё предыдущее сообщение, тогда оформлю как новое.

И ещё один небольшой вопрос - вспомнил об этом и решил дописать - по теме градусов.
В первой своей части, я использую глобальную переменную и в самом начале инициирую её (ещё и поэтому я не сокращал выражение, что бы там проставить переменную):
dDegRad = Pi / 180
Хотел объявить её константой, но не получается - ругается "Синтаксическая ошибка Basic", указывая на цифру "180".
Я понял, что нельзя константе присвоить выражение. Или как-то можно?

---
И для меня, первое выражение было более нагляднее.
Для меня, было более логичнее выражение (360/n)/6 * i * (Pi/180), где (360/n)/6 - приращение угла каждой i-ой точки при задание n лепестков.
« Последнее редактирование: 13 Март 2020, 14:01 от Tigrik » Записан
mikekaganski
Мастер
*****
Online Online

Пол: Мужской
Расположение: Хабаровск -> Москва
Сообщений: 1 755


« Ответ #21: 13 Март 2020, 14:05 »

Это потому, что число "360" магическим образом ассоциируется со словом "окружность", а "2π" почему-то нет Подмигивающий
Записан

С уважением,
Михаил Каганский
rami
Гуру
*******
Offline Offline

Пол: Мужской
Сообщений: 2 885


MacBook Pro, LibreOffice и Apache OpenOffice


« Ответ #22: 13 Март 2020, 14:18 »

Я понял, что нельзя константе присвоить выражение. Или как-то можно?
Если в выражении будут только цифры:
Код:
Const dDegRad =  3.14159265358979 / 180
Записан

mikekaganski
Мастер
*****
Online Online

Пол: Мужской
Расположение: Хабаровск -> Москва
Сообщений: 1 755


« Ответ #23: 13 Март 2020, 14:19 »

В первой своей части, я использую глобальную переменную и в самом начале инициирую её (ещё и поэтому я не сокращал выражение, что бы там проставить переменную):
dDegRad = Pi / 180
Хотел объявить её константой, но не получается - ругается "Синтаксическая ошибка Basic", указывая на цифру "180".
Я понял, что нельзя константе присвоить выражение. Или как-то можно?

Можно присвоить выражение константе. Нужно только чтобы это выражение было вычисляемо во время компиляции, а для этого все входящие туда символы сами должны быть константами. А Pi, как ни забавно, не константа. Вы всегда можете присвоить ей значение, и поступать с ней как в военное время Подмигивающий

Сравните:

Код:
const ccc = 2 / 3
const ddd = ccc + 1
pi = 4
ccc = 4
« Последнее редактирование: 13 Март 2020, 14:21 от mikekaganski » Записан

С уважением,
Михаил Каганский
rami
Гуру
*******
Offline Offline

Пол: Мужской
Сообщений: 2 885


MacBook Pro, LibreOffice и Apache OpenOffice


« Ответ #24: 13 Март 2020, 14:28 »

Вы всегда можете присвоить ей значение, и поступать с ней как в военное время
Ругается на pi = 3Ошибка чтения.Свойство только для чтения. (LibreOffice 6.4.1.2)
Записан

mikekaganski
Мастер
*****
Online Online

Пол: Мужской
Расположение: Хабаровск -> Москва
Сообщений: 1 755


« Ответ #25: 13 Март 2020, 14:32 »

Version: 6.4.2.1 (x64)
Build ID: c92dba0b4728c0ec26c4b83e2c0fbf3284425375
CPU threads: 12; OS: Windows 10.0 Build 18363; UI render: GL; VCL: win;
Locale: ru-RU (ru_RU); UI-Language: en-US
Calc: CL

EDIT: ага, вижу. Моя ошибка - времени компиляции; Ваша - времени выполнения.
А в VBA работает...

Тем не менее, это дела не меняет: Pi - это не константа; даже если это "свойство только для чтения", это не делает его вычислимым во время компиляции Улыбка


* pi=3.png (55.07 Кб, 860x683 - просмотрено 2 раз.)
« Последнее редактирование: 13 Март 2020, 14:37 от mikekaganski » Записан

С уважением,
Михаил Каганский
rami
Гуру
*******
Offline Offline

Пол: Мужской
Сообщений: 2 885


MacBook Pro, LibreOffice и Apache OpenOffice


« Ответ #26: 13 Март 2020, 14:54 »

Тем не менее, это дела не меняет: Pi - это не константа
А Справка говорит, что константа типа Double. (для сведения)
Записан

mikekaganski
Мастер
*****
Online Online

Пол: Мужской
Расположение: Хабаровск -> Москва
Сообщений: 1 755


« Ответ #27: 13 Март 2020, 15:01 »

Тем не менее, это дела не меняет: Pi - это не константа
А Справка говорит, что константа типа Double. (для сведения)

Да, так и написано. И лучше бы так и было.
Я полагаю, что это не сделано технически константой исходя из кросс-платформенности пакета, из-за которого константа, определённая на одной машине, может теоретически оказаться не лучшим возможным приближением числа π на другой. А предкомпилированный результат выполняется, например, при запароленной библиотеке, и там использовалось бы жёстко заданное значение...
« Последнее редактирование: 13 Март 2020, 15:09 от mikekaganski » Записан

С уважением,
Михаил Каганский
Tigrik
Участник
**
Offline Offline

Сообщений: 43


« Ответ #28: 13 Март 2020, 15:30 »

Спасибо за помощь и, для себя, я выбрал такое решение:
Код:
Const Pi = 3.14159265358979
Const dDegRad = Pi / 180
Проверил - работает.
Записан
Tigrik
Участник
**
Offline Offline

Сообщений: 43


« Ответ #29: 21 Март 2020, 19:01 »

Здравствуйте!

В продолжение этой темы (и, так называемого, "проекта" Шри Янтра), появилось некоторое продолжение.
В принципе, оставалось самое легкое - Внешний Контур. Он сильно "ломаный", но много-симметричный - главное, определить координаты первых пяти точек (я начал с верхнего левого угла).
Сразу же, пришли два варианта: первый - как с "лепестками": вычислить вектора этих точек и по определенному циклу установить остальные точки массива координат. Второй - даже легче: нарисовать квадрат, который в центре и, затем, 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
Хочу попросить, по возможности и при желание, посмотреть, есть ли какие-нибудь ошибки. Кто-то, возможно, опытным и профессиональным взглядом уведет недочёты. Может быть, есть и готовые решения или варианты улучшить эту функцию.
Я оставил комментарии и некоторые лишние выражения для удобства - это всегда можно убрать.
« Последнее редактирование: 21 Март 2020, 19:09 от Tigrik » Записан
Страниц: « 1 2 3 »   Вверх
  Печать  
 
Перейти в:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!