Visio Guy

Visio Discussions => General Visio => Topic started by: clintdavis on July 02, 2010, 06:21:15 PM

Title: Add arrow to middle of connector?
Post by: clintdavis on July 02, 2010, 06:21:15 PM
I have a complex diagram and in order to help follow the paths I would like to have an arrow in the middle of the connector as well as the end to indicate direction. If I can have multiple arrows along the path that would be great as well.

I'm using Visio 2010 now but if there is a solution for any version I am open to it.

Thanks,

Clint
Title: Re: Add arrow to middle of connector?
Post by: Jumpy on July 03, 2010, 10:48:29 AM
What kind of connectors are you using? Only straight arrows or the automatic connector that goes right angled around other shapes?
Because in the last case a second arrowhead in the middle of the path won't look nice, because the middle of the path does not mean the middle of the segment that is in the middle of the path. I had problems with that, too and solved it with a shape, that is only an arrowhead. When I drag it from a stencil and unto a connector line, it will place itself in the middle of the path segment, with VBA.

Worked fine for me, but I can use it  only, when the drawing is in its final stages, because when a connector is adjusted, the new arrowhead won't follow it, because it is still a different shape.

When you think, that could help you I can post the VBA code on tuesday
Title: Re: Add arrow to middle of connector?
Post by: Yacine on July 03, 2010, 03:17:05 PM
You may want to use line patterns.
Cheers
Yacine
Title: Re: Add arrow to middle of connector?
Post by: Visio Guy on July 03, 2010, 10:49:04 PM
More examples of what can be done with custom line patterns in Visio, and links to further resources:

Release the Power of Visio Custom Line Patterns (http://www.visguy.com/2008/03/03/release-the-power-of-visio-custom-line-patterns/)
Title: Re: Add arrow to middle of connector?
Post by: Yacine on July 04, 2010, 08:09:03 PM
Chris,
what settings would you recommend to put exactly one arrow head at the middle of a line/connector with line patterns.
Creating a group could be a possibility, but would be hard to implement for connectors.
Title: Re: Add arrow to middle of connector?
Post by: JuneTheSecond on July 05, 2010, 06:22:49 AM
I thought someone mentioned about group.
Here is a kind of his idea.
A connector is a group that has arrows.
Unfortunately, you need to run macro,"testArrows", if number of segments changed.
The connectors need to be rectangle conectors.
Title: Re: Add arrow to middle of connector?
Post by: JuneTheSecond on July 05, 2010, 01:04:26 PM
Enhancement.

Added right click menu "Update Arrows" to each connector shape.
Now you can update arrows on a connector, when you changed the number of segments.
Number of maximum segment is increased from 6 to 9.
Title: Re: Add arrow to middle of connector?
Post by: Visio Guy on July 05, 2010, 01:10:55 PM
I think putting just one arrowhead directly in the middle of the connector is only possible in Visio 2010 (without code, that is)

Visio 2010 has some new ways to access geometry sections arbitrarily, and locate stuff certain percentages along a path.
Title: Re: Add arrow to middle of connector?
Post by: JuneTheSecond on July 06, 2010, 12:59:48 PM
Made an example by the best suggestion of Visio Guy, though for only Visio 2010.
Title: Re: Add arrow to middle of connector?
Post by: clintdavis on July 06, 2010, 01:23:09 PM
Thanks for all the help guys! Line patterns are exactly what I was looking for. I knew I couldn't be the only one who had this problem. Thanks to Yacine for giving me the pattern. I modified it to make the arrows more spaced out but it works perfectly!
Title: Re: Add arrow to middle of connector?
Post by: Visio Guy on July 06, 2010, 03:10:27 PM
Nice job, June, very cool!
Title: Re: Add arrow to middle of connector?
Post by: Yacine on July 07, 2010, 06:43:27 AM
thougth about that group idea... here's a first sketch.
The laborious part remains to calculate how the grouped connectors bend first, so to orient the arrow accordingly.
Title: Re: Add arrow to middle of connector?
Post by: JuneTheSecond on July 08, 2010, 01:00:13 PM
My sample has a problem, when the corners of connector are rounded with menu Rounding.
This is because the PATHSEGMENT function counts a corner as 1 segment,
but on the other hand the number of rows of Geometry section does not increase by rounding.
Here is a modified example that re-calculates geometry's rows from the the result of PATHSEGMENT function.
Now you can round the corner of connectors.
And more, shape sheet formulas are simplified using INDEX function.
Title: Re: Add arrow to middle of connector?
Post by: JuneTheSecond on July 08, 2010, 11:03:35 PM
Above drawing file was replaced after a modification.
Title: Re: Add arrow to middle of connector?
Post by: JuneTheSecond on July 09, 2010, 08:29:19 AM
Here is the most interesting example that uses POINTALONGPATH function at Visio Insights.
"The Point Along Path ShapeSheet Functions in Visio 2010" at
http://blogs.msdn.com/b/visio/archive/2010/01/15/the-point-along-path-shapesheet-functions-in-visio-2010.aspx
Please, visit there and check the example drawing.
Title: Re: Add arrow to middle of connector?
Post by: JuneTheSecond on July 12, 2010, 08:05:02 AM
You need to move arrow on the connector back or forth, when connectors are crossing each other.
Here is adjustable arrow on connector.
Right click menu on a connector moves arrow back or forth, and resets to the center.
Title: Re: Add arrow to middle of connector?
Post by: JuneTheSecond on July 14, 2010, 12:10:38 AM
You might need more functionality, when one segment is too long.
You wish to move arrow on one segment back and forth.
Here added menues "Back on Segment", and so on.
Title: Re: Add arrow to middle of connector?
Post by: JuneTheSecond on July 14, 2010, 04:23:07 AM
If you need more quick access to arrow on connecotor,
please, enable VBA macro and press direct shortcut keys.
Title: Re: Add arrow to middle of connector?
Post by: Jumpy on July 26, 2010, 01:50:54 PM
Hello June,

very nice solution, that makes me rethink, what I have done in my solution. Maybe I generate sth. new of both ways, when there's time, because I'm not satisfied with the current version.

I used a filled triangle shape (my "arrowhead"), which calls a makro on drop, to see, if the arrow is placed on a certain type of connector ("Leitung"). It then turns the arrowhead in the right direction and places it in the centre of the connector segment it was droped on. It is still a separate shape, so when moving the connector the arrowhead stays behind. Therefore it is only used in the final stages of a drawing, when the layout is complete. The reason, why I stay with an extra shape (not grouped to the connector) is that I can move the shape slightly afterwards if neccessary and align it with a arrowhead on a connector that runs parallel(?alongside?) the first connector. Also I can place more than one arrowhead on the same path segment (if it's a long one that may become neccessary).

Here's the code I use for this. Maybe someone gets an idea:

Public Sub Pfeil_Drop(dropee As Visio.Shape)
'*********************************************************
'* Drop Makro für Arrow-Heads                            *
'* Startet from Callthis-Fkt. in Arrowhead-Shape         *
'* Makro only tests, if arrowhead is droped on connector *
'* ("Leitung"). If yes is starts a further makro         *
'*********************************************************
Dim shp As Visio.Shape
On Error Resume Next
For Each shp In ActivePage.Shapes
If shp.DistanceFrom(dropee, 0) <= 0 And shp <> dropee Then         'Hit
  If shp.CellExists("User.Typ", False) Then
   If shp.Cells("User.Typ").ResultStr(0) = "Leitung" Then
    Pfeil_Leitung dropee, shp
    Exit Sub
   End If
  End If
End If
Next

End Sub

Public Sub Pfeil_Leitung(ByVal Pfeil As Visio.Shape, ByVal Leitung As Visio.Shape, Optional Range As Integer = 2)
'******************************************************
'* Makro for arrowhead placement on connector segment *
'* Startet from Makro Pfeil_Drop                      *
'******************************************************

Dim vsoShape As Visio.Shape
Dim adblXYPoints() As Double
Dim strPointsList As String
Dim intOuterLoopCounter As Integer
Dim intInnerLoopCounter, Pfadsegment, Segmentanzahl, a, b, i As Integer
Dim X(50), Y(50), PX, PY As Double

Pfadsegment = 0
PX = Pfeil.Cells("PinX").Result("MM")
PY = Pfeil.Cells("PinY").Result("MM")

'Here the points along the path are sored in X(i)/Y(i) Variables
'---------------------------------------------------------------------------------------
    Set vsoShape = Leitung
    For intOuterLoopCounter = 1 To vsoShape.Paths.Count

        vsoShape.Paths(intOuterLoopCounter).Points 0.5, adblXYPoints
        a = 1
        b = 1
        For intInnerLoopCounter = LBound(adblXYPoints) To UBound(adblXYPoints)
            If a Mod 2 = 1 Then
             X(b) = (adblXYPoints(intInnerLoopCounter) * 25.4)
            Else
             Y(b) = (adblXYPoints(intInnerLoopCounter) * 25.4)
             b = b + 1
            End If
            strPointsList = strPointsList & a & ": " & (adblXYPoints(intInnerLoopCounter) * 25.4) & Chr(10)
            a = a + 1
        Next intInnerLoopCounter
    If Trim(X(1)) = Trim(Leitung.Cells("BeginX").Result("MM")) And Trim(Y(1)) = Trim(Leitung.Cells("BeginY").Result("MM")) Then
     intOuterLoopCounter = vsoShape.Paths.Count
    End If
    Next intOuterLoopCounter
       
Segmentanzahl = b - 2
'---------------------------------------------------------------------------------------


'Now analyse, on witch segment of the connector the arrowhead was droped
'---------------------------------------------------------------------------------------
For i = 1 To Segmentanzahl
If X(i + 1) - X(i) = 0 Then                        'vertical Segment
If PX > X(i) - Range And PX < X(i) + Range Then   'Test if arrowhead on X coordinate
  If Y(i + 1) - Y(i) > 0 Then                      'Direction "up"
   If PY < Y(i + 1) And PY > Y(i) Then             'arrowhead in Y Intervall
    Pfadsegment = i
    i = Segmentanzahl
   End If
  ElseIf Y(i + 1) - Y(i) < 0 Then                  'Direction "down"
   If PY > Y(i + 1) And PY < Y(i) Then             'arrowhead in Y Intervall
    Pfadsegment = i
    i = Segmentanzahl
   End If
  Else
  'Nix tun
  End If
End If
ElseIf Y(i + 1) - Y(i) = 0 Then                    'horizontal Segment
If PY > Y(i) - Range And PY < Y(i) + Range Then   'Test if arrowhead on Y coordinate
  If X(i + 1) - X(i) > 0 Then                      'Direction "right"
   If PX < X(i + 1) And PX > X(i) Then             'arrowhead in X Intervall
    Pfadsegment = i
    i = Segmentanzahl
   End If
  ElseIf X(i + 1) - X(i) < 0 Then                  'Direction "left"
   If PX > X(i + 1) And PX < X(i) Then             'arrowhead in X Intervall
    Pfadsegment = i
    i = Segmentanzahl
   End If
  Else
  'Nix tun
  End If
End If
Else                                       'Diagonales Segment
'is ignored, but could be captured
End If
Next i
'---------------------------------------------------------------------------------------

'Now place arrowhead in the middle of the Pathsegment (in the right direction)
'---------------------------------------------------------------------------------------
If Pfadsegment = 0 Then Exit Sub '...oder auch nicht ;-)

If X(Pfadsegment) - X(Pfadsegment + 1) = 0 Then     'vertical Segment
Pfeil.Cells("PinX").Result("MM") = X(Pfadsegment)
  Pfeil.Cells("PinY").Result("MM") = Y(Pfadsegment) + (Y(Pfadsegment + 1) - Y(Pfadsegment)) / 2
  If Y(Pfadsegment + 1) - Y(Pfadsegment) > 0 Then   'up
   Pfeil.Cells("Angle").Result("deg") = 0
  Else                                              'down
   Pfeil.Cells("Angle").Result("deg") = 180
  End If
Else                                                'horizontal Segment
Pfeil.Cells("PinY").Result("MM") = Y(Pfadsegment)
  Pfeil.Cells("PinX").Result("MM") = X(Pfadsegment) + (X(Pfadsegment + 1) - X(Pfadsegment)) / 2
  If X(Pfadsegment + 1) - X(Pfadsegment) > 0 Then   'right
   Pfeil.Cells("Angle").Result("deg") = -90
  Else                                              'left
   Pfeil.Cells("Angle").Result("deg") = 90
  End If
End If

'Give it the right color based on temperature (interesting only for my solution)
Pfeil.Cells("Prop.Temperatur").Result("") = Leitung.Cells("Prop.Temperatur").Result("")

'---------------------------------------------------------------------------------------

End Sub