All Forums
 Категория Visio
 Для заказчиков
 Обработка графических схем
Author Previous Topic Topic Next Topic  

bdfy

Belarus
267 Posts

Posted - 03/29/2010 :  16:45:10
Есть схема - план цеха с нанесенной сетью освещения. точнее много схем разных. см. рис 10, 20

сеть освещения рисуется макросом в принципе и выходит неплохо - но коннекторы от щитка освещения (ЩО, ЩАО на схеме) до светильников визио рисует как попало. а нужно аккуратно по стенам/тросам.
помещения определены как специальные смарт шейпы box'ы.
тросы - тоже как шейпы.
щитки освещения - тоже спец. шейпы.

необходимо растащить коннекторы по стенам/тросам с минимальным количеством пересечений. как на рис. 20_0
поставить выключатели в помещениях и протянуть к ним проводку. вот тут незадача ибо дверные проемы определены не всегда однозначно. а ставятся они рядом с дверями.

пример файлика прилагаю в архиве 10test. там же и все скриншоты.
http://rapidshare.com/files/369588617/___________________.rar.html

вот и думаю - реально ли эту работу автоматизировать ? ибо стоит задача либо платить людям за эту тупую механическую работу либо заплатить программисту за универсальное решение...
и я бы предпочел второй вариант. ибо у меня идеи закончились (

Tumanov

Russia
1198 Posts

Posted - 03/30/2010 :  04:50:01
1. А что служит исходными данными для макроса, который сейчас рисует сеть освещения?
2. Вообще без ручной работы едва ли получится. Будут, например, случаи, когда дверей две и надо указать, у какой из них выключатель ставить. Логично было бы человеку как-то "мазнуть", наметить путь, а макрос красиво уложил бы все в намеченный след.
Go to Top of Page

bdfy

Belarus
267 Posts

Posted - 03/30/2010 :  22:45:19
quote:
1. А что служит исходными данными для макроса, который сейчас рисует сеть освещения?

схема вручную размечается прямоугольниками задающими границы помещений. щитки ЩО ЩАО выставляются руками. светильники "выход" тоже руками.
потом на основании размеров помещений и ряда других свойств по заданной методике идет расчет и выбор светильников. развешиваются светильники, тянутся связи к одной точке щитка ЩО/ЩАО. потом макрос сортирует присоединения на щитке - но даже здесь алгоритм толковый не выходит - все равно бывает некорректная сортировка.

quote:
2. Вообще без ручной работы едва ли получится. Будут, например, случаи, когда дверей две и надо указать, у какой из них выключатель ставить. Логично было бы человеку как-то "мазнуть", наметить путь, а макрос красиво уложил бы все в намеченный след.

насчет дверей это просто ) если две - лепить к примеру к любой )
"Логично было бы человеку как-то "мазнуть", наметить путь"
вот это совсем неясно. читал вот про path find алгоритмы с учетом "весов" квадратов... в игрушках используется. если считать участки сетки близкие к стене-тросу участками с меньшим весом... может чего и вышло. но реализацию не представляю пока.
Go to Top of Page

Tumanov

Russia
1198 Posts

Posted - 03/31/2010 :  16:00:14
quote:
"Логично было бы человеку как-то "мазнуть", наметить путь"
вот это совсем неясно.

Это я подумал, нельзя ли что-то выжать из перекрытия шейпов...
Например, толстой ломаной грубо наносим желательный путь, некий виртуальный кабельный канал. Потом вычисляем стены, тросы, дверные проемы, светильники (выводы), которые он накрыл (или пересек), и имеем информацию, что надо соединять и по рядом с какими шейпами вести соединения. То есть грубо "мазнули", нажали кнопку, получили уложенные провода.
Но это пока голая идея, поэкспериментировать надо...
Go to Top of Page

bdfy

Belarus
267 Posts

Posted - 04/01/2010 :  21:43:08
вот макрос сортировки который сейчас использую. и тот далек от совершенства ((
Public Function ConnectedShapes(ByVal Sh As Visio.Shape)
Dim Passive() As Visio.Shape
Dim Active() As Visio.Shape

    'Set sh = ActiveWindow.Selection.Item(1) 'выделенный шейп
    'Активные связи 2D-шейпа
    If Sh.Connects.Count > 0 Then 'условие наличия активных связей
    For i = 1 To Sh.Connects.Count 'цикл перебора всех активных связей
    ReDim Preserve Active(i)
    Set Active(i - 1) = Sh.Connects(i).ToSheet 'активные связи (к чему приклеен)
   ' Debug.Print "active " & Active(I - 1).Name
    Next
    End If

    'Пассивные связи 2D-шейпа
    If Sh.FromConnects.Count > 0 Then 'условие наличия пассивных связей
    For i = 1 To Sh.FromConnects.Count 'цикл перебора всех пассивных связей
    ReDim Preserve Passive(i)
    Set Passive(i - 1) = Sh.FromConnects(i).FromSheet 'пассивные связи (какие шейпы приклеены к выделенному)
  '  Debug.Print "passive " & Passive(I - 1).Name
    Next
    End If
    
    ConnectedShapes = Array(Active, Passive)
End Function
Sub сортировать_присоединения()

dx_con = 0
For Each vid In Array("ЩО", "ЩАО")
Set sho = найти_шкаф(vid) 'находим щит освещения на схеме

               ar = ConnectedShapes(sho)
                Active = ar(0)
                Passive = ar(1)
                

Debug.Print "щиток " & shape0 & " " & имеет & UBound(Passive) & " присоедениний"
        Dim svet() As Variant
        Dim y() As Variant
        Dim room() As Variant
        Dim num() As Variant
        Dim dx(), dy(), atan(), qvadr() As Variant
        
        ReDim svet(UBound(Passive)), y(UBound(Passive)), room(UBound(Passive)), num(UBound(Passive)), _
        atan(UBound(Passive)), dx(UBound(Passive)), dy(UBound(Passive)), atan(UBound(Passive)), qvadr(UBound(Passive))
        
        
                      For i = 0 To UBound(Passive) - 1 'Passive присоединения к щитку все пассивные
                      
                      Set svet(i) = ConnectedShapes(Passive(i))(0)(1)
                      y(i) = Round(svet(i).Cells("pinY"), 2)
                      room(i) = Getroom(svet(i))
                      num(i) = i
                      'угол от -180 до 180 найдем
                      dx(i) = svet(i).Cells("pinX") - sho.Cells("pinX")
                      dy(i) = svet(i).Cells("pinY") - sho.Cells("pinY")
                        atan(i) = Round(Atn(dy(i) / dx(i)) * 180 / 3.14, 2) - sho.Cells("angle")
                        If dx(i) < 0 Then
                            If dy(i) >= 0 Then
                            atan(i) = atan(i) + 180
                            ElseIf dy(i) < 0 Then
                            atan(i) = atan(i) - 180
                            End If
                        End If
                        'против часовой из нижнего левого угла 4-3-2-1
                            If atan(i) >= -180 And atan(i) <= -90 Then
                                qvadr(i) = 1
                            ElseIf atan(i) > -90 And atan(i) <= 0 Then
                                qvadr(i) = 2
                            ElseIf atan(i) > 0 And atan(i) <= 90 Then
                                qvadr(i) = 3
                            ElseIf atan(i) > 90 And atan(i) <= 180 Then
                                qvadr(i) = 4
                            Else
                                qvadr(i) = 0
                            End If
                      Debug.Print svet(i).NameU & " " & dx(i) & " - " & dy(i) & " " & atan(i) & " " & qvadr(i)
                    '    svet(i).Characters.text = CStr(atan(i))
                    '  Debug.Print Passive(i) & " " & svet(i).Name & " " & y(i) & "  " & room(i)
                      Next i

Debug.Print "---------------sort-------------"


         For i = 0 To UBound(Passive) - 1
            For j = i + 1 To UBound(Passive) - 1
        
                If qvadr(i) > qvadr(j) Then
                   
                  Set temp = Passive(i)
                  Set Passive(i) = Passive(j)
                  Set Passive(j) = temp
                  
                  temp = room(i)
                  room(i) = room(j)
                  room(j) = temp
                  
                  temp = atan(i)
                  atan(i) = atan(j)
                  atan(j) = temp
                  
                  temp = num(i)
                  num(i) = num(j)
                  num(j) = temp
                 
                  temp = qvadr(i)
                  qvadr(i) = qvadr(j)
                  qvadr(j) = temp
                  
                 ElseIf qvadr(i) = qvadr(j) Then
                         If Passive(i).Cells("pinY") - Passive(j).Cells("pinY") > 0.2 Then
                         
                              Set temp = Passive(i)
                              Set Passive(i) = Passive(j)
                              Set Passive(j) = temp
                              
                              temp = room(i)
                              room(i) = room(j)
                              room(j) = temp
                              
                                temp = num(i)
                                num(i) = num(j)
                                num(j) = temp
                                
                              temp = atan(i)
                              atan(i) = atan(j)
                              atan(j) = temp
            
                              temp = qvadr(i)
                              qvadr(i) = qvadr(j)
                              qvadr(j) = temp
                              
                          ElseIf Passive(i).Cells("pinY") - Passive(j).Cells("pinY") <= 0.2 Then
                                If Passive(i).Cells("pinX") > Passive(j).Cells("pinX") Then
                                      Set temp = Passive(i)
                                      Set Passive(i) = Passive(j)
                                      Set Passive(j) = temp
                                      
                                      temp = room(i)
                                      room(i) = room(j)
                                      room(j) = temp
                                      
                                temp = num(i)
                                num(i) = num(j)
                                num(j) = temp
                                
                                      temp = atan(i)
                                      atan(i) = atan(j)
                                      atan(j) = temp
                    
                                      temp = qvadr(i)
                                      qvadr(i) = qvadr(j)
                                      qvadr(j) = temp
                                 End If
                          End If
                End If
            Next j
        Next i

delta_x = 1.5
dx_con = 0
dx_con = dx_con + delta_x

If sho.Cells("angle") < -3.14 * 0.95 Or sho.Cells("angle") > 3.14 * 0.95 Then
endI = 0
startI = UBound(Passive) - 1
stepi = -1

Else
startI = 0
endI = UBound(Passive) - 1
stepi = 1

End If
Debug.Print formi
              For i = startI To endI Step stepi 'Passive присоединения к щитку все пассивные
              Debug.Print Passive(i) & " " & room(i) & " " _
              & Round(Passive(i).Cells("pinY"), 1) & " " & Round(Passive(i).Cells("pinX"), 1) _
              & " " & qvadr(i) & " " & atan(i)
              'место на шейпе ЩО
              If stepi = 1 Then sho.Cells("Connections.Y" & num(i) + 1).FormulaU = "=height*" & (i + 1) * (1 / (UBound(Passive) + 1))
              If stepi = -1 Then sho.Cells("Connections.Y" & num(i) + 1).FormulaU = "=height*(1-" & (i + 1) * (1 / (UBound(Passive) + 1)) & ")"
            '  Passive(i).Cells("Geometry1.X3").FormulaU = "=" & dx_con & " mm"
            ' Passive(i).Cells("Geometry1.X2").FormulaU = "=" & dx_con & " mm"
           '   dx_con = dx_con + delta_x
              Next

    ActiveWindow.DeselectAll
    ActiveWindow.Select sho, visSelect
    Application.ActiveWindow.Selection.Move -0.01, 0#
    Application.ActiveWindow.Selection.Move 0.01, 0#
    
 Next vid
 
Debug.Print "---------------------------------"



End Sub

для начала хоть его бы отладить )

quote:
Потом вычисляем стены, тросы, дверные проемы, светильники (выводы), которые он накрыл (или пересек)

не ясна идея. есть
- границы комнат
по ним надо бы вычислить положение дверей. как ? по идее надо пройтись по периметру проверяя "есть прямая ли линия (читай стена) в непосредственно близости". если нет - это дверь. вопрос как выполнить эту проверку ?
Логично было бы человеку как-то "мазнуть", наметить путь, а макрос красиво уложил бы все в намеченный след.

на каком основании макрос бы уложил красиво то ? ибо если можно уложить по намеченному руками пути - можно потом попробовать путь вычислить машинно.
в принципе при верной сортировке на щитке (см. макрос выше) все ручное укладывание шейпов заключается в смещении буквально двух трех прямых отрезков ближе к стене/другим линиям... вот думаю может в эти ворота сыграть...



Go to Top of Page

bdfy

Belarus
267 Posts

Posted - 04/02/2010 :  09:35:35
все идет к тому что делать все придется руками (( что выливается в несколько человеко суток ((
что не нравится в визио - коннектор можно тащить только за сгиб или за середину линии. а можно ли сделать так чтобы прямую коннектора можно было оттянуть в сторону взявшись в любом месте ?
Go to Top of Page

Tumanov

Russia
1198 Posts

Posted - 04/02/2010 :  16:21:14
quote:
все идет к тому что делать все придется руками

Ну, как-то слишком пессимистично...
Я, в общем-то, давно собирался поисследовать возможности Visio в графической навигации, да все повода не было. Вот может как раз случай представился :) Глядишь, что-нибудь и получится.
Смотрю, из инструментов есть функция шейп-листа, позволяющая определить точку пересечения прямых.
=INTERSECTY(PinX,PinY,Angle,Sheet.2!PinX,Sheet.2!PinY,Sheet.2!Angle)
Может помочь для прогнозирования возможных точек пересечения. Это если вместо коннекторов самому строить соединительные линии.
Есть возможность вычислить особенности взаимного расположения шейпов, например, факт пересечения. В том числе и коннекторов.
Debug.Print sh1.SpatialRelation(sh2, 0.1, 0)
при пересечении коннекторов возвращает 8, для непересекающихся - 0.
То есть наблюдая реальную ситуацию, можно найти пересекающиеся коннекторы. Затем, переключая один из концов коннектора, добиться отсутствия перемещений.
В определении положения дверей скорее всего может помочь имеющийся шейп типа дверного проема (название не помню). Выглядит, как дырка в стене, но на самом деле является шейпом. Нужно только использовать их при рисовании, если это допускает технология.
С коннекторами, помнится, тоже был момент, когда не удавалось добиться нужного поведения. Так я после проводки коннекторов превращал их макросом в обычные ломаные (с той же геометрией) и потом уже перетаскивал нужные куски. То есть, можно еще поискать варианты :)
А предварительная наметка пути, как мне кажется, может помочь вот в чем. Если просто взять пару соединений (четыре точки в помещении), то в зависимости от того, по какой стене идти (по часовой или против), коннекторы либо перекрестятся, либо нет. Поэтому путь важен. Хочу извлечь из него последовательность шейпов, мимо которых нужно пройти. А потом последовательно от одного шейпа до другого (рядом) тянуть свои связи.
Можно, наверно, и без предварительной наметки обойтись, но тогда придется путь вычислять алгоритмически. А значит, отрабатывать для этого еще один алгоритм, может быть не очень простой.
Короче, результаты пока прогнозировать рано, но в целом задача видится разрешимой.
Go to Top of Page

bdfy

Belarus
267 Posts

Posted - 04/02/2010 :  17:24:28
quote:
Ну, как-то слишком пессимистично...

дедлайн просто числа 15-20 - а схем сейчас уже под 50,а будет больше (
пока я задачу вижу из 3 пунктов
- разместить выключатели (это я примерно представляю еще как сделать). только вот использовать какие то шейпы нельзя для дверей - схемы все были изначально рисованы в автокаде, потом конвертированы. сейчас их править таким образом достаточно сложно.
- отсортировать соединения на самом щитке ЩО/ЩАО. наработки есть - но работает не всегда корректно.
- провести проводники по тросам/стенам. вот это наиболее сложная и трудоемкая часть. я сегодня чертежей пять сделал - убил наверное часа полтора и удовольствия не получил никакого ((
quote:
А предварительная наметка пути, как мне кажется, может помочь вот в чем. Если просто взять пару соединений (четыре точки в помещении), то в зависимости от того, по какой стене идти (по часовой или против), коннекторы либо перекрестятся, либо нет. Поэтому путь важен. Хочу извлечь из него последовательность шейпов, мимо которых нужно пройти. А потом последовательно от одного шейпа до другого (рядом) тянуть свои связи.

а если просто засечь ближайшие стены,тросы и уже уложенные коннекторы и просто максимально "прижать" коннектор к ним ? только как это запускаться то хотя бы будет ? "предварительный путь" можно словить через Document_ShapeAdded предположим, а как указать какой из коннекторов по нему ложить ? если просто по порядку, то порядок еще надо определить...
quote:
С коннекторами, помнится, тоже был момент, когда не удавалось добиться нужного поведения. Так я после проводки коннекторов превращал их макросом в обычные ломаные (с той же геометрией) и потом уже перетаскивал нужные куски.

у коннектора есть свойство line routing - reroute - never
если верить справке - это автоматические смещения прекращает.

в любом случае еще недельку в принципе можно подергатся ) все же ведь "лучше день потерять... потом за пять минут долететь".
могу залить на мыло проект целиком если это поможет. все файлы метров в 10 уложатся думаю. мыло только подскажите )





Go to Top of Page

bdfy

Belarus
267 Posts

Posted - 04/02/2010 :  17:28:34
была еще идея закрыть "условно непроходимые зоны", т.е центральную часть помещений большим шейпом со свойством route around - тогда по идее визио обязан был бы просчитать вокруг него пути, но не выходит из этого ничего пока (( бывает дейсвительно более менее корректно отталкивает коннекторы - потом сам улетает... как то странно эта фича работает.
....
а ведь даже работает )) даже почти похоже на правду получается.
только надо шейпами фейковыми закрыть еще и просветы между комнатами - а то коннекторы уходят туда.
....
вот что получилось если их закрыть ручками:
http://rapidshare.com/files/371217425/__________________10.rar.html
вопрос как закрыть подобными псевдношейпами все промежутки между комнатами ? и как отсортировать шейпы внутри "каналов" между шейпами.
хотя может это и тупиковое решение...

Edited by - bdfy on 04/02/2010 18:29:45
Go to Top of Page

Tumanov

Russia
1198 Posts

Posted - 04/04/2010 :  12:08:50
1. Да, сроки слишком жесткие. Я в них (на фоне других работ) точно не уложусь :( Разве что в следующий раз когда-нибудь пригодится...
2. Сортировка коннекторов. Сейчас видится ряд функций, которые могли бы помочь в работе:
2.1. Выбрать коннекторы, касающиеся заданного коннектора (например, селектированного). Функция работает на основе SpatialNeighbors. Причем за счет параметра Tolerance можно ловить как непосредственно касающиеся (и пересекающие), так и близко проходящие.
2.2. Функция перестановки двух соседних коннекторов. На том участке, где линии коннекторов идут рядом, пытается обвести второй коннектор вокруг первого. В зависимости от направления поворота первого коннектора в очередной точке излома смещает сегмент второго коннектора в нужную сторону.
Результат контролируется функцией 2.1. Если коннекторы все равно касаются, значит меняются местами их подключения к ЩО и операция повторяется.
Сегмент коннектора вроде тянется без проблем за две точки. Типа, вот так:
sh1.Cells("Geometry1.X2") = sh1.Cells("Geometry1.X2") + 0.2
sh1.Cells("Geometry1.X3") = sh1.Cells("Geometry1.X3") + 0.2
Скорее всего по ходу дела тут еще несколько мелких вспомогательных функций сформируется. Типа вычисления направления поворота, поиска близлежащих сегментов двух коннекторов и т.д.
3. Идея закрыть "непроходимые зоны" вроде хорошая. Для закрытия промежутков между помещениями можно ведь и просто слепить шейп, пользуясь операциями Subtract и Union. Если еще и стены в нескольких цехах совпадают, то такой шейп можно применять на нескольких листах. Или слегка изменять при необходимости.
А если все-таки не получится, можно попробовать провести несколько направляющих и пытаться тянуться к ним. В принципе, они обсчитываются, как обычные шейпы. Удается определить расстояние до них и т.д.
quote:
могу залить на мыло проект целиком если это поможет. все файлы метров в 10 уложатся думаю. мыло только подскажите

С учетом того, что я в срок задачу не решу, вроде как и смысла нет заливать. А если с учетом перспективы, то реальные данные никогда не помешают. Больше особенностей можно учесть. Так что, смотрите сами. почта ttt@post.rzn.ru В несколько Мб письма вроде проходили.
Go to Top of Page

bdfy

Belarus
267 Posts

Posted - 04/04/2010 :  15:53:47
сроки уже не горят - хлопчыка раскидывать это дело вручную я уже нанял , но нормально автоматическое решение все равно интересно. ибо хлопчыки девайс в общем случае менее надежный и менее производительный чем программа ) да и задачи подобные мне попадаются периодически.
quote:
3. Идея закрыть "непроходимые зоны" вроде хорошая. Для закрытия промежутков между помещениями можно ведь и просто слепить шейп, пользуясь операциями Subtract и Union. Если еще и стены в нескольких цехах совпадают, то такой шейп можно применять на нескольких листах.

все таки решение ищется автоматическое ) внутри комнат заполнить пространство легко, вот между ними сложнее - если комнаты вложены одна в другую - да субстракт поможет. а если просто рядом стоят с просветами ? как эти просветы посчитать и заполнить ?
а так если фигуры эти корректно поставить - остается только отсортировать коннекторы в "коридорах" образаванных этими шейпами. тут правда опять стоит вопрос как...
quote:
Сегмент коннектора вроде тянется без проблем за две точки. Типа, вот так:

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

на прожект ссылка на почте. будет время, скажите пару добрых ) не уверен правда что разберетесь в этом комбайне )
Go to Top of Page
  Previous Topic Topic Next Topic  
Данный сайт является архивом форума visio.artberg.ru, который был закрыт в связи с переходом на новую платформу visio.getbb.ru
Все материалы доступны только для чтения! Если у вас появились вопросы, или вы хотите что-то обсудить, связанное с Visio, обращайтесь на новый форум!
Архив был создан благодаря совместным усилиям Генадия Туманова @Tumanov (visio.artberg.ru), Александра ака @Surrogate (visio.getbb.ru), и Николая Белых @nbelyh (unmanagedvisio.com)