[CDR 2025] Дорисовать скомбинированный объект макросом

Dinosaur

Участник
Топикстартер
Сообщения
9
Реакции
0
Добрый день! Я немного знаком с макросами, писал но немного застопорился
В кратце что делает макрос: после получения координат пересечений строит кривые по ним, и комбинирует их в один объект (картинку прикрепил)
Теперь мне нужно соединить промежутки.
Я пробовал скопировать в массив координаты всех точек и построить новую кривую по ним, но тк направление сегментов и порядок subpath разный,
получается не правильное соединение.

Я вижу выход только высчитывать ближайшие точки, с что-то придумать чтоб их соединить

Но хотел узнать, может есть способ по легче?
Спасибо!

Untitled-1.jpg
 
А чем вы планируете заполнять пространство между висячими нодами и по какому принципу будет соответствие проводится? В общем случае задача, конечно, нетривиальна, но хотелось бы посмотреть пример "было-стало", да и вообще непонятна окончательная задача полностью.
 
А принципиально макрос? Окошко Join curves (Соединить кривые) не подойдет?
1765462849076.png
1765462856880.png
 
Покажите, как должно получиться в приведенном вами примере
 
Покажите, как должно получиться в приведенном вами примере
Ты внимательно ТЗ прочитай. Предполагается, что произвольное количество разнонаправленных отрезков надо обьединить в необязательно односвязный шейп.
 
Вот получено из примера ТС. Вверху его картинка, внизу воспроизведены векторные линии, справа - результат join curves
1765463357887.png
 
а вот так?
Код:
Sub JoinSelectedCurves()
    Dim s As Shape
    Dim sr As ShapeRange
    Dim tol As Double 'допуск для совмещения'
     
     Set doc = ActiveDocument
    If doc Is Nothing Then Exit Sub
   
    Dim originalUnit As cdrUnit
    originalUnit = doc.Unit
    doc.Unit = cdrMillimeter
    ' Устанавливаем допуск (расстояние, на котором узлы соединятся)
    tol = 0.5 ' Например, 0.5 мм (единицы зависят от настроек документа)
   
    Set sr = ActiveSelectionRange
   
    ' 1. Сначала нужно объединить отдельные объекты в один (Combine)
    If sr.Count > 1 Then
        Set s = sr.Combine
    Else
        Set s = sr(1)
    End If
   
    ' 2. Если объект — кривая, соединяем разомкнутые пути
    If s.Type = cdrCurveShape Then
        ' Метод ищет разомкнутые концы в пределах допуска и соединяет их
        s.Curve.JoinTouchingSubpaths True, tol
    End If
End Sub
Главное, допуск правильно выбрать (tol)
Точки просто стянутся друг к другу!
1765464541674.png
 
Последнее редактирование:
Ньет, нье поньимать, при чём здесь односвязность?
 
А чем вы планируете заполнять пространство между висячими нодами
как-то соединить текущую фигуру или полностью перерисовать на основе текущей - новую кривую (но тут нужно какой-то алгоритм придумать, чтобы правильная последовательность точек получилась). Панель Join Curves (chamfer) - то, что нужно, только макросом это изобразить бы.
Картинку прикрепил до/после
Untitled-1.jpg
 
Ньет, нье поньимать, при чём здесь односвязность?
Субконтура - так понятнее?
как-то соединить текущую фигуру или полностью перерисовать на основе текущей - новую кривую (но тут нужно какой-то алгоритм придумать, чтобы правильная последовательность точек получилась). Панель Join Curves (chamfer) - то, что нужно, только макросом это изобразить бы.
Картинку прикрепил до/послеПосмотреть вложение 177030
Ну такое простое действительно и без макроса можно, как выше описано. Проблема решена?
 
  • Спасибо
Реакции: Dinosaur
Проблема решена?
Нет, дело в том, что это часть макроса на которой я застрял, после этого еще будут манипуляции с этими фигурами. А весь процесс описывать слишком долго. Я просто думал, что есть функция про которую я не знаю.
Но в любом случае спасибо всем!!
 
Ну и вызывайте докер join curves в макросе
Application.FrameWork.Automation.InvokeItem guid
guide найдете.
Вам все равно придется допуски задавать. Нужно экпериментировать
 
Последнее редактирование:
  • Спасибо
Реакции: mnemonix и Dinosaur
Ну и вызывайте докер join curves в макросе
Это очень интересно, я попробовал:
Код:
    Dim sr As ShapeRange
    Set sr = ActiveSelectionRange

    Application.FrameWork.Automation.InvokeItem "259d7733-648b-4eb3-ae96-3768ea6370d3"
    'or
    ActiveDocument.Application.FrameWork.Automation.InvokeItem ("e916b384-dc13-7aaa-4fdb-0de63d3c640b")

но что-то не то делаю
Если вас не затруднит, можете готовый пример скинуть с любым InvokeItem, меня синтаксис интересует, а дальше думаю разберусь. Спасибо!
 
Код:
Sub JoinMultipleCurvesWithBridges()
    ActiveDocument.Unit = cdrMillimeter
    Application.Optimization = True
    ActiveDocument.BeginCommandGroup "Smart Join Curves"
    On Error GoTo ErrorHandler

    Dim sr As ShapeRange
    Dim s As Shape
    Dim crv As Curve
    Dim sp As SubPath
    Dim nodes() As Node
    Dim used() As Boolean
    Dim nCount As Long
    Dim i As Long, j As Long
    Dim tol As Double
    Dim dx As Double, dy As Double, d As Double
    Dim bestD As Double, bestJ As Long
    Dim bridges As New ShapeRange ' Коллекция для новых линий-перемычек
    Dim bridge As Shape

    ' === НАСТРОЙКИ ===
    tol = 5 ' Допуск поиска пары в мм (увеличьте, если разрывы большие)
    ' =================

    Set sr = ActiveSelectionRange
    
    If sr.Count < 1 Then
        MsgBox "Выделите несколько кривых.", vbExclamation
        GoTo ExitLabel
    End If

    ' 1. Объединяем выделенное в один объект, чтобы работать с SubPaths
    ' Если выделен уже один объект, Combine вернет его же
    Set s = sr.Combine
    
    ' Преобразуем в кривые, если вдруг там были прямоугольники/эллипсы
    If s.Type <> cdrCurveShape Then s.ConvertToCurves
    
    Set crv = s.Curve
    nCount = 0

    ' 2. Собираем концы всех открытых подпутей
    For Each sp In crv.SubPaths
        If Not sp.Closed Then
            nCount = nCount + 2
            ReDim Preserve nodes(1 To nCount)
            ReDim Preserve used(1 To nCount)
            
            Set nodes(nCount - 1) = sp.StartNode
            Set nodes(nCount) = sp.EndNode
            
            used(nCount - 1) = False
            used(nCount) = False
        End If
    Next sp

    If nCount < 2 Then
        ' Если всё уже замкнуто - отлично
        GoTo ExitLabel
    End If

    ' 3. Ищем пары и строим "мосты"
    For i = 1 To nCount
        If Not used(i) Then
            bestD = 1E+30
            bestJ = 0
            
            For j = 1 To nCount
                If j <> i And Not used(j) Then
                    dx = nodes(j).PositionX - nodes(i).PositionX
                    dy = nodes(j).PositionY - nodes(i).PositionY
                    d = Sqr(dx * dx + dy * dy)
                    
                    If d < bestD Then
                        bestD = d
                        bestJ = j
                    End If
                End If
            Next j
            
            ' Если нашли пару в пределах допуска
            If bestJ > 0 And bestD <= tol Then
                used(i) = True
                used(bestJ) = True
                
                ' Создаем линию соединения
                Set bridge = ActiveLayer.CreateLineSegment( _
                    nodes(i).PositionX, nodes(i).PositionY, _
                    nodes(bestJ).PositionX, nodes(bestJ).PositionY)
                
                bridges.Add bridge
            End If
        End If
    Next i

    ' 4. Финальная сборка: объединяем исходную кривую с новыми мостами
    If bridges.Count > 0 Then
        bridges.Add s ' Добавляем исходную кривую в группу к мостам
        Set s = bridges.Combine ' Сливаем всё вместе
        
        ' 5. Теперь у нас единый объект, но узлы в местах стыков могут быть "раздвоены"
        ' (конец линии + начало моста). Используем JoinTouchingSubpaths, чтобы "сварить" их.
        ' Допуск ставим маленький (0.01), т.к. мы построили мосты точно в координаты.
        s.Curve.JoinTouchingSubpaths True, 0.1
    End If

ExitLabel:
    ActiveDocument.EndCommandGroup
    Application.Optimization = False
    Application.Refresh
    Exit Sub

ErrorHandler:
    MsgBox "Ошибка: " & Err.Description
    Resume ExitLabel
End Sub
Но это будет работать не на всех наборах данных.
И нужно подбирать допуск (tol)
Мопед не мой, я только объявление разместил.

1765517454835.png