0 / 0 / 0
Регистрация: 12.01.2019
Сообщений: 79
1

Рисование концентрической фигуры - внутри другой фигуры

10.07.2019, 14:47. Показов 2137. Ответов 7
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте.

Подскажите с решением.

Суть такая.
На листе есть замкнутая ломаная линия.
Как нарисовать концентрическую фигуру - ориентируясь на эту основную фигуру ?

Это значит, что макрос должен как-то изменить координаты что новая фигура - будет вписанной, но с каким-то небольшим отступом внутрь.
Это сложно словами объяснить, в файле - нужную фигуру - я обозначил пунктиром.

Алгоритм такой:
По координатам исходной полилинии
1. Вычисляем уравнение прямой с учётом направления обхода для каждой последовательной пары.
2. Вычисляем параллельные прямые, смещённые от данных внутрь полилинии на заданную величину.
3. Находим последовательно точки пересечения этих смещённых прямых.
4. По этим точкам строим ту самую пунктирную полилинию.

Как это сделать макросом ?
Вложения
Тип файла: xls Файл.xls (34.5 Кб, 10 просмотров)
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
10.07.2019, 14:47
Ответы с готовыми решениями:

Рисование фигуры в форме ракушки
Необходимо сделать закручивание в форме ракушки и одинаковое расстояние между ее последовательными...

Передвижение фигуры при клике на область внутри фигуры
Есть прямоугольник 100 на 50. При удерживании мышки фигура передвигается как карта в пасьянсе. При...

Программа вычисления местонахождения точки относительно фигуры (лежит ли точка внутри, на контуре или вне фигуры)
Нужно написать программу вычисления местонахождения точки относительно фигуры(лежит ли данная точка...

рисование фигуры
procedure TFigure.Show; var T:array of TPoint; r:real; begin Canvas.Pen.Color:=clblack;...

7
1802 / 1127 / 343
Регистрация: 11.07.2014
Сообщений: 3,977
10.07.2019, 15:14 2
Glass4217, думаю, что ваш алгоритм незаслуженно громоздок. Каждая фигура имеет параметры прямоугольника, в который она заключена: Left, Width, Top, Height. Копируете исходную полилинию, пропорционально уменьшаете Width и Height. Left и Top увеличиваете на половину разностей Width и Height в исходной и вторичной фигурах. Сможете сами осилить, не знаю уровень вашей квалификации в ВБА?
1
0 / 0 / 0
Регистрация: 12.01.2019
Сообщений: 79
10.07.2019, 15:27  [ТС] 3
Burk, спасибо за совет.
А как этот более совершенный алгоритм представить в виде макроса ?
0
1802 / 1127 / 343
Регистрация: 11.07.2014
Сообщений: 3,977
10.07.2019, 16:16 4
Glass4217, я малость поспешил с советами, на выпуклом многоугольнике эта методика пройдет, а вот в вашем случае проблема с вогнутым внутрь участком, он у внутренней фигуры должен быть шире исходной! Подумаю ещё, хотелось как попроще. Алгоритм совершенно простой и я его написал (10 строк кода), но раз у вас возникли такие вопросы значит вы имеете очень смутное представление о макросах. Буду думать. Незаслуженную мной единичку уберите.
0
SoftIce
10.07.2019, 16:25
  #5

Не по теме:

Цитата Сообщение от Burk Посмотреть сообщение
не знаю уровень вашей квалификации в ВБА?
Burk, имхо, это один и тот же человек создаёт темы про фигуры.

0
1802 / 1127 / 343
Регистрация: 11.07.2014
Сообщений: 3,977
10.07.2019, 17:32 6
SoftIce, так он что под двумя никами выступает? В предыдущей, похожей теме был другой ник, правда мне они тоже показались похожими и единичку мне выставил там Glass4217. Тогда уровень ясен. Но постараюсь помочь. Правда, Pashulka в таких темах больше меня шарит, я редко с этим сталкиваюсь, может он что подскажет.
0
6076 / 1320 / 195
Регистрация: 12.12.2012
Сообщений: 1,023
11.07.2019, 01:42 7
Лучший ответ Сообщение было отмечено Glass4217 как решение

Решение

Здравствуйте,
Темы, связанные с геометрией - мои любимые.

Вот что у меня получилось:

Программа рисования контура полилинии
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
Option Explicit
'Тип, описывающий точку на плоскости.
Type GeomPoint
    x As Double 'X-координата точки.
    y As Double 'Y-координата точки.
End Type
'Тип, описывающий направляющий вектор.
Type GeomVector
    dx As Double 'Смещение по координате X.
    dy As Double 'Смещение по координате Y.
End Type
'Тип, описывающий линию на плоскости.
Type GeomLine
    p As GeomPoint 'Координаты точки, через которую проходит прямая.
    v As GeomVector 'Координаты направляющего вектора прямой.
End Type
'Процедура получения массива точек полилинии.
'shp - ссылка на полилинию, для которой требуется получить массив ее точек.
'n - ссылка на переменную, в которую будет записано количество точек полилинии.
'polyPoints - ссылка на массив, в который будут записаны координаты точек полилинии.
Sub GetPolylinePoints(ByVal shp As Shape, ByRef n As Long, ByRef polyPoints() As GeomPoint)
    Dim nds As ShapeNodes, nd As ShapeNode
    Dim dx As Double, dy As Double, d As Double
    Dim i As Long, j As Long
    Set nds = shp.Nodes
    n = nds.Count
    ReDim polyPoints(1 To n + 1)
    For i = 1 To n
        Set nd = nds(i)
        polyPoints(i).x = nd.Points(1, 1)
        polyPoints(i).y = nd.Points(1, 2)
    Next
    polyPoints(n + 1).x = polyPoints(1).x
    polyPoints(n + 1).y = polyPoints(1).y
    For i = n To 1 Step -1
        dx = polyPoints(i).x - polyPoints(i + 1).x
        dy = polyPoints(i).y - polyPoints(i + 1).y
        If dx * dx + dy * dy < 1 Then
            For j = i To n
                polyPoints(i).x = polyPoints(i + 1).x
                polyPoints(i).y = polyPoints(i + 1).y
            Next
            n = n - 1
        End If
    Next
    ReDim Preserve polyPoints(1 To n)
End Sub
'Процедура получения координат направляющего вектора.
'p1 - точка, из которой идет направляющий вектор.
'p2 - точка, в которую направлен направляющий вектор.
'v - результат.
Sub GetVector(ByRef p1 As GeomPoint, ByRef p2 As GeomPoint, ByRef v As GeomVector)
    v.dx = p2.x - p1.x
    v.dy = p2.y - p1.y
End Sub
'Процедура получения канонического уравнения прямой по двум точкам.
'p1 - первая точка прямой.
'p2 - вторая точка прямой.
'l - результат.
Sub GetLine(ByRef p1 As GeomPoint, ByRef p2 As GeomPoint, ByRef l As GeomLine)
    l.p = p1
    GetVector p1, p2, l.v
End Sub
'Процедура получения канонического уравнения прямой,
'проходящей через заданную точку и параллельной другой прямой.
'p1 - точка, через которую проходит искомая прямая.
'parallelTo - линия, которой должна быть параллельна искомая прямая.
'l - результат.
Sub GetParallelLine(ByRef p As GeomPoint, ByRef parallelTo As GeomLine, ByRef l As GeomLine)
    l.p = p
    l.v = parallelTo.v
End Sub
'Процедура получения вектора, ортогонального заданному.
'v - исходный вектор.
'leftHand - True, если обход идет по правилу левой руки, False иначе.
'o - результат.
Function OrthoVector(ByRef v As GeomVector, ByVal leftHand As Boolean, ByRef o As GeomVector)
    If leftHand Then
        o.dx = v.dy
        o.dy = -v.dx
    Else
        o.dx = -v.dy
        o.dy = v.dx
    End If
End Function
'Процедура нормализации вектора.
'v - вектор, длину которого необходимо приравнять единице.
Sub NormalizeVector(ByRef v As GeomVector)
    Dim vec_len As Double
    vec_len = Math.Sqr(v.dx * v.dx + v.dy * v.dy)
    v.dx = v.dx / vec_len
    v.dy = v.dy / vec_len
End Sub
'Процедура получения прямой, параллельной заданной
'и отстоящей от нее на некоторое расстояние.
'parallelTo - линия, которой должна быть параллельна искомая прямая.
'd - расстояние от исходной прямой до параллельной.
'leftHand - True, если искомая прямая по левую руку от исходной, False иначе.
'l - результат.
Sub GetParallelLine2(ByRef parallelTo As GeomLine, ByRef d As Double, _
ByVal leftHand As Boolean, ByRef l As GeomLine)
    Dim v As GeomVector, p As GeomPoint
    OrthoVector parallelTo.v, leftHand, v
    NormalizeVector v
    p.x = parallelTo.p.x + v.dx * d
    p.y = parallelTo.p.y + v.dy * d
    GetParallelLine p, parallelTo, l
End Sub
'Процедура получения уравнения общего вида для прямой, заданной каноническим уравнением.
'l - прямая, заданная каноническим уравнением.
'a, b, c - коэффициенты в уравнении общего вида для прямой (ax + by + c = 0).
Sub GenericCoefs(ByRef l As GeomLine, ByRef a As Double, ByRef b As Double, ByRef c As Double)
    a = l.v.dy
    b = -l.v.dx
    c = l.p.y * l.v.dx - l.p.x * l.v.dy
End Sub
'Функция, возвращающая определитель матрицы:
'| a b |
'| c d |
Function Determinant( _
    ByVal a As Double, ByVal b As Double, _
    ByVal c As Double, ByVal d As Double) As Double
    Determinant = a * d - b * c
End Function
'Процедура получения координат точки пересечения двух прямых.
'l1 - первая прямая.
'l2 - вторая прямая.
'p - результат (точка пересечения двух прямых)
Sub GetIntersectionPoint(ByRef l1 As GeomLine, ByRef l2 As GeomLine, ByRef p As GeomPoint)
    Dim a1 As Double, b1 As Double, c1 As Double
    Dim a2 As Double, b2 As Double, c2 As Double
    Dim d As Double, d1 As Double, d2 As Double
    GenericCoefs l1, a1, b1, c1
    GenericCoefs l2, a2, b2, c2
    d = Determinant(a1, b1, a2, b2)
    d1 = Determinant(-c1, b1, -c2, b2)
    d2 = Determinant(a1, -c1, a2, -c2)
    p.x = d1 / d
    p.y = d2 / d
End Sub
'Процедура рисования контура полилинии.
'shp - ссылка на исходную полилинию.
'd - расстояние от исходной полилинии до рисуемого контура.
'leftHand - True, если обход идет по правилу левой руки, False иначе.
Sub PolylineСontour(ByVal shp As Shape, ByVal d As Double, ByVal leftHand As Boolean)
    Dim polyPoints() As GeomPoint, polyPoints2() As Single
    Dim ls() As GeomLine, l As GeomLine
    Dim i As Long, n As Long
    GetPolylinePoints shp, n, polyPoints
    ReDim ls(1 To n)
    For i = 1 To n
        GetLine polyPoints(i), polyPoints(i Mod n + 1), l
        GetParallelLine2 l, d, leftHand, ls(i)
    Next
    ReDim polyPoints2(1 To n + 1, 1 To 2) As Single
    For i = 1 To n
        GetIntersectionPoint ls(i), ls(i Mod n + 1), polyPoints(i)
        polyPoints2(i, 1) = polyPoints(i).x
        polyPoints2(i, 2) = polyPoints(i).y
    Next
    polyPoints2(n + 1, 1) = polyPoints(1).x
    polyPoints2(n + 1, 2) = polyPoints(1).y
    Set shp = shp.Parent.Shapes.AddPolyline(polyPoints2)
    shp.Fill.Visible = msoFalse
    shp.Line.ForeColor.RGB = 0
    shp.Line.DashStyle = msoLineDash
End Sub
'Диалог рисования контура.
Sub СontourWizard()
    Dim shp As Shape, d As Double, res As VbMsgBoxResult
    On Error Resume Next
    Set shp = Selection.ShapeRange(1)
    On Error GoTo 0
    If shp Is Nothing Then
        MsgBox "Вы не выделили фигуру, для которой необходимо нарисовать контур.", vbExclamation, "Ошибка"
    Else
        If shp.Type <> msoFreeform Then
            MsgBox "Выделенная фигура не похожа на полилинию.", vbExclamation, "Ошибка"
        Else
            d = Val(InputBox("Введите расстояние от исходной полилинии до ее контура", "Расстояние", 10))
            If d < 1 Or d > 100 Then
                MsgBox "Расстояние либо введено неправильно, либо не удовлетворяет ограничениям", vbExclamation, "Ошибка"
            Else
                res = MsgBox("Обход ведем по правилу левой руки?", vbYesNo Or vbQuestion, "Порядок обхода")
                Select Case res
                    Case VbMsgBoxResult.vbYes
                        PolylineСontour shp, d, True
                    Case VbMsgBoxResult.vbNo
                        PolylineСontour shp, d, False
                End Select
            End If
        End If
    End If
End Sub


Если будут вопросы, обращайтесь.

С уважением,
Аксима.
3
0 / 0 / 0
Регистрация: 12.01.2019
Сообщений: 79
11.07.2019, 10:34  [ТС] 8
Аксима, спасибо большое.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
11.07.2019, 10:34
Помогаю со студенческими работами здесь

Рисование фигуры в PaintBox
Доброго времени суток! Помогите пожалуйста нарисовать фигуру...

Рисование объёмной фигуры
Добрый день. Нужно нарисовать трёхмерную фигуру - параллелепипед, который искажается, &quot;ломаясь&quot;...

Рисование фигуры на кнопке
Хочу нарисовать на кнопке, но почему размер кнопки усекается на половину? &lt;Button...

Рисование фигуры в OpenGL
Здравствуйте, дан файл в котором имеется массив точек, нужно по нему построить точечное изображение...

Рисование геометрической фигуры С(Си)
# include&lt;stdio.h&gt; int main() { int n=10, i,j; //C for (i=0; i&lt;n; i++) ...

Рисование фигуры по клику мыши
добрый день, делаю программу в которой по нажатию мыши рисуется допустим прямоугольник на форме и...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru