Если кому интересно вот сейчас рабочая часть кода(правда не судите строго, писал с помощью нейронки плюс там дебагер, в порядок пока не приводил)
P.S. Вообще начинаются думать, что проще полностью переписать - Тупо поверх объектов нарисовать нужный, а начальные удалить(ну то бишь как запись макроса работает)
P.S. Вообще начинаются думать, что проще полностью переписать - Тупо поверх объектов нарисовать нужный, а начальные удалить(ну то бишь как запись макроса работает)
Sub ProcessObjects()
' Объявляем переменные
Dim leftShape As shape
Dim rightShape As shape
Dim leftNode As node
Dim rightNode As node
Dim sr As New ShapeRange
' Получаем активный документ и выделенные объекты
Dim doc As Document
Set doc = ActiveDocument
If doc Is Nothing Then
MsgBox "Документ не найден!", vbExclamation
Exit Sub
End If
' Проверяем, что выделено ровно два объекта
If ActiveSelection.Shapes.Count <> 2 Then
MsgBox "Выделите ровно два объекта!", vbExclamation
Exit Sub
End If
' Определяем левый и правый объекты по координате X
If ActiveSelection.Shapes(1).PositionX < ActiveSelection.Shapes(2).PositionX Then
Set leftShape = ActiveSelection.Shapes(1)
Set rightShape = ActiveSelection.Shapes(2)
Else
Set leftShape = ActiveSelection.Shapes(2)
Set rightShape = ActiveSelection.Shapes(1)
End If
' Находим нужные узлы
Set leftNode = FindRightTopNode(leftShape)
Set rightNode = FindLeftTopNode(rightShape)
If leftNode Is Nothing Or rightNode Is Nothing Then
MsgBox "Не удалось найти нужные узлы!", vbExclamation
Exit Sub
End If
' Разъединяем узлы (BreakApart)
leftNode.BreakApart
rightNode.BreakApart
' Разделяем концевые узлы на верхние и нижние
Dim topBottomPairs As Collection
Set topBottomPairs = AssignTopAndBottomNodes(leftShape, rightShape)
' Выводим информацию о верхних и нижних узлах
Debug.Print "Верхние и нижние узлы:"
Dim i As Long
For i = 1 To topBottomPairs.Count Step 2
Dim topNode As node
Dim bottomNode As node
Dim topNeighbor As node
Dim bottomNeighbor As node
Set topNode = topBottomPairs(i)
Set bottomNode = topBottomPairs(i + 1)
' Находим соседние узлы для верхнего и нижнего узлов
Set topNeighbor = GetNeighborNode(leftShape, topNode)
Set bottomNeighbor = GetNeighborNode(leftShape, bottomNode)
Debug.Print "Пара " & (i \ 2 + 1) & ":"
Debug.Print " Верхний узел: Индекс = " & topNode.Index & ", X = " & topNode.PositionX & ", Y = " & topNode.PositionY
Debug.Print " Соседний узел: Индекс = " & topNeighbor.Index & ", X = " & topNeighbor.PositionX & ", Y = " & topNeighbor.PositionY
Debug.Print " Нижний узел: Индекс = " & bottomNode.Index & ", X = " & bottomNode.PositionX & ", Y = " & bottomNode.PositionY
Debug.Print " Соседний узел: Индекс = " & bottomNeighbor.Index & ", X = " & bottomNeighbor.PositionX & ", Y = " & bottomNeighbor.PositionY
Next i
' Объединяем объекты
Set sr = ActiveSelectionRange
sr.Combine
MsgBox "Обработка завершена!", vbInformation
End Sub
' Функция для разделения концевых узлов на верхние и нижние
Function AssignTopAndBottomNodes(leftShape As shape, rightShape As shape) As Collection
Dim topBottomPairs As New Collection
Dim node1 As node, node2 As node
Dim neighbor1 As node, neighbor2 As node
' Разделяем концевые узлы левого объекта
Set node1 = leftShape.Curve.nodes(1) ' Первый узел
Set node2 = leftShape.Curve.nodes(leftShape.Curve.nodes.Count) ' Последний узел
Set neighbor1 = GetNeighborNode(leftShape, node1)
Set neighbor2 = GetNeighborNode(leftShape, node2)
If Not neighbor1 Is Nothing And Not neighbor2 Is Nothing Then
If neighbor1.PositionY < neighbor2.PositionY Then
topBottomPairs.Add node1 ' Верхний узел
topBottomPairs.Add node2 ' Нижний узел
Else
topBottomPairs.Add node2 ' Верхний узел
topBottomPairs.Add node1 ' Нижний узел
End If
End If
' Разделяем концевые узлы правого объекта
Set node1 = rightShape.Curve.nodes(1) ' Первый узел
Set node2 = rightShape.Curve.nodes(rightShape.Curve.nodes.Count) ' Последний узел
Set neighbor1 = GetNeighborNode(rightShape, node1)
Set neighbor2 = GetNeighborNode(rightShape, node2)
If Not neighbor1 Is Nothing And Not neighbor2 Is Nothing Then
If neighbor1.PositionY < neighbor2.PositionY Then
topBottomPairs.Add node1 ' Верхний узел
topBottomPairs.Add node2 ' Нижний узел
Else
topBottomPairs.Add node2 ' Верхний узел
topBottomPairs.Add node1 ' Нижний узел
End If
End If
Set AssignTopAndBottomNodes = topBottomPairs
End Function
' Функция для поиска самого правого верхнего узла
Function FindRightTopNode(shape As shape) As node
Dim node As node
Dim resultNode As node
Dim maxX As Double, minY As Double
If shape.Type <> cdrCurveShape Then Exit Function
maxX = -1E+308
minY = 1E+308
For Each node In shape.Curve.nodes
With node
If .PositionY < minY Or (.PositionY = minY And .PositionX > maxX) Then
maxX = .PositionX
minY = .PositionY
Set resultNode = node
End If
End With
Next node
Set FindRightTopNode = resultNode
End Function
' Функция для поиска самого левого верхнего узла
Function FindLeftTopNode(shape As shape) As node
Dim node As node
Dim resultNode As node
Dim minX As Double, minY As Double
If shape.Type <> cdrCurveShape Then Exit Function
minX = 1E+308
minY = 1E+308
For Each node In shape.Curve.nodes
With node
If .PositionY < minY Or (.PositionY = minY And .PositionX < minX) Then
minX = .PositionX
minY = .PositionY
Set resultNode = node
End If
End With
Next node
Set FindLeftTopNode = resultNode
End Function
' Функция для поиска соседнего узла
Function GetNeighborNode(shape As shape, node As node) As node
Dim segment As segment
Dim neighborNode As node
' Перебираем все сегменты кривой
For Each segment In shape.Curve.Segments
If segment.StartNode.Index = node.Index Then
' Найден сегмент, начинающийся с текущего узла
Set neighborNode = segment.EndNode
Exit For
ElseIf segment.EndNode.Index = node.Index Then
' Найден сегмент, заканчивающийся текущим узлом
Set neighborNode = segment.StartNode
Exit For
End If
Next segment
Set GetNeighborNode = neighborNode
End Function
' Объявляем переменные
Dim leftShape As shape
Dim rightShape As shape
Dim leftNode As node
Dim rightNode As node
Dim sr As New ShapeRange
' Получаем активный документ и выделенные объекты
Dim doc As Document
Set doc = ActiveDocument
If doc Is Nothing Then
MsgBox "Документ не найден!", vbExclamation
Exit Sub
End If
' Проверяем, что выделено ровно два объекта
If ActiveSelection.Shapes.Count <> 2 Then
MsgBox "Выделите ровно два объекта!", vbExclamation
Exit Sub
End If
' Определяем левый и правый объекты по координате X
If ActiveSelection.Shapes(1).PositionX < ActiveSelection.Shapes(2).PositionX Then
Set leftShape = ActiveSelection.Shapes(1)
Set rightShape = ActiveSelection.Shapes(2)
Else
Set leftShape = ActiveSelection.Shapes(2)
Set rightShape = ActiveSelection.Shapes(1)
End If
' Находим нужные узлы
Set leftNode = FindRightTopNode(leftShape)
Set rightNode = FindLeftTopNode(rightShape)
If leftNode Is Nothing Or rightNode Is Nothing Then
MsgBox "Не удалось найти нужные узлы!", vbExclamation
Exit Sub
End If
' Разъединяем узлы (BreakApart)
leftNode.BreakApart
rightNode.BreakApart
' Разделяем концевые узлы на верхние и нижние
Dim topBottomPairs As Collection
Set topBottomPairs = AssignTopAndBottomNodes(leftShape, rightShape)
' Выводим информацию о верхних и нижних узлах
Debug.Print "Верхние и нижние узлы:"
Dim i As Long
For i = 1 To topBottomPairs.Count Step 2
Dim topNode As node
Dim bottomNode As node
Dim topNeighbor As node
Dim bottomNeighbor As node
Set topNode = topBottomPairs(i)
Set bottomNode = topBottomPairs(i + 1)
' Находим соседние узлы для верхнего и нижнего узлов
Set topNeighbor = GetNeighborNode(leftShape, topNode)
Set bottomNeighbor = GetNeighborNode(leftShape, bottomNode)
Debug.Print "Пара " & (i \ 2 + 1) & ":"
Debug.Print " Верхний узел: Индекс = " & topNode.Index & ", X = " & topNode.PositionX & ", Y = " & topNode.PositionY
Debug.Print " Соседний узел: Индекс = " & topNeighbor.Index & ", X = " & topNeighbor.PositionX & ", Y = " & topNeighbor.PositionY
Debug.Print " Нижний узел: Индекс = " & bottomNode.Index & ", X = " & bottomNode.PositionX & ", Y = " & bottomNode.PositionY
Debug.Print " Соседний узел: Индекс = " & bottomNeighbor.Index & ", X = " & bottomNeighbor.PositionX & ", Y = " & bottomNeighbor.PositionY
Next i
' Объединяем объекты
Set sr = ActiveSelectionRange
sr.Combine
MsgBox "Обработка завершена!", vbInformation
End Sub
' Функция для разделения концевых узлов на верхние и нижние
Function AssignTopAndBottomNodes(leftShape As shape, rightShape As shape) As Collection
Dim topBottomPairs As New Collection
Dim node1 As node, node2 As node
Dim neighbor1 As node, neighbor2 As node
' Разделяем концевые узлы левого объекта
Set node1 = leftShape.Curve.nodes(1) ' Первый узел
Set node2 = leftShape.Curve.nodes(leftShape.Curve.nodes.Count) ' Последний узел
Set neighbor1 = GetNeighborNode(leftShape, node1)
Set neighbor2 = GetNeighborNode(leftShape, node2)
If Not neighbor1 Is Nothing And Not neighbor2 Is Nothing Then
If neighbor1.PositionY < neighbor2.PositionY Then
topBottomPairs.Add node1 ' Верхний узел
topBottomPairs.Add node2 ' Нижний узел
Else
topBottomPairs.Add node2 ' Верхний узел
topBottomPairs.Add node1 ' Нижний узел
End If
End If
' Разделяем концевые узлы правого объекта
Set node1 = rightShape.Curve.nodes(1) ' Первый узел
Set node2 = rightShape.Curve.nodes(rightShape.Curve.nodes.Count) ' Последний узел
Set neighbor1 = GetNeighborNode(rightShape, node1)
Set neighbor2 = GetNeighborNode(rightShape, node2)
If Not neighbor1 Is Nothing And Not neighbor2 Is Nothing Then
If neighbor1.PositionY < neighbor2.PositionY Then
topBottomPairs.Add node1 ' Верхний узел
topBottomPairs.Add node2 ' Нижний узел
Else
topBottomPairs.Add node2 ' Верхний узел
topBottomPairs.Add node1 ' Нижний узел
End If
End If
Set AssignTopAndBottomNodes = topBottomPairs
End Function
' Функция для поиска самого правого верхнего узла
Function FindRightTopNode(shape As shape) As node
Dim node As node
Dim resultNode As node
Dim maxX As Double, minY As Double
If shape.Type <> cdrCurveShape Then Exit Function
maxX = -1E+308
minY = 1E+308
For Each node In shape.Curve.nodes
With node
If .PositionY < minY Or (.PositionY = minY And .PositionX > maxX) Then
maxX = .PositionX
minY = .PositionY
Set resultNode = node
End If
End With
Next node
Set FindRightTopNode = resultNode
End Function
' Функция для поиска самого левого верхнего узла
Function FindLeftTopNode(shape As shape) As node
Dim node As node
Dim resultNode As node
Dim minX As Double, minY As Double
If shape.Type <> cdrCurveShape Then Exit Function
minX = 1E+308
minY = 1E+308
For Each node In shape.Curve.nodes
With node
If .PositionY < minY Or (.PositionY = minY And .PositionX < minX) Then
minX = .PositionX
minY = .PositionY
Set resultNode = node
End If
End With
Next node
Set FindLeftTopNode = resultNode
End Function
' Функция для поиска соседнего узла
Function GetNeighborNode(shape As shape, node As node) As node
Dim segment As segment
Dim neighborNode As node
' Перебираем все сегменты кривой
For Each segment In shape.Curve.Segments
If segment.StartNode.Index = node.Index Then
' Найден сегмент, начинающийся с текущего узла
Set neighborNode = segment.EndNode
Exit For
ElseIf segment.EndNode.Index = node.Index Then
' Найден сегмент, заканчивающийся текущим узлом
Set neighborNode = segment.StartNode
Exit For
End If
Next segment
Set GetNeighborNode = neighborNode
End Function
Последнее редактирование: