Curved arrows- can I create or purchase?

Is there a way to get curved arrows in Omnigraffle vers 7.19?

Curved arrows

Like these ones ?

[Stencil: Curved block arrows - The Omni Group Forums](http://forums.omnigroup.com/showthread.php?t=23531)

Thank youThese would work for what I need.
Being a newbie—how would I access this collection and get in “into” omnigraffle?

At top right of the OmniGraffle window you have the Stencils icon (under Inspect).

You should be able to import that set of arrows into the stencils collection by:

  1. Unzipping the file,
  2. manually adding the extension .gstencil
  3. double-clicking the resulting .gstencil file, and accepting the offer to add it to the stencils folder, when it opens.
  4. closing the .gstencil file in the edit window.

If you pull a circle of arrows into an OmniGraffle diagram from their listing in the stencils area, Arrange -> Ungroup will enable you to move individual arrows around, apply colors, etc.

For more flexibility, you can go through AppleScript rather than the Stencil system by first creating and selecting any shape in your canvas:

and then circumscribing with any number of arrows, of any width, by running the AppleScript here in Script Editor:

Expand disclosure triangle to view AppleScript
property pTitle : "Make Circles of N Block Arrows"
property pVer : "0.07"

--  Copyright © 2010, Robin Trew
--  All rights reserved.
--     
--     Redistribution and use in source and binary forms, with or without modification, 
--     are permitted provided that the following conditions are met:
--     
--         - Redistributions of source code must retain the above copyright notice, 
--           this list of conditions and the following disclaimer.
--         - Redistributions in binary form must reproduce the above copyright notice, 
--           this list of conditions and the following disclaimer in the documentation 
--           and/or other materials provided with the distribution.
--         
--     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
--     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
--     THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
--     IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
--     ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
--      (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
--      LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
--      WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
--      ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

-- ver 0.05 Takes account of any rotation of the template shape to determine where first arrow starts
-- ver 0.06 Corrects radius of non-block arrows (when inner or outer fit has been specified)

property pstrHelp : "\n\tNumber\t\t\tNumber of arrows\n\ta=N\t\t\t\tNumber of arrows\n\tw=N\t\t\twidth of block arrows\n\th=true|false\t\theader arrow ?\n\tt=true|false\t\ttail arrrow ?\n\tb=true|false\t\tblock arrows ?\n\tr=c\t\t\t\tradius=corner\n\tr=e\t\t\t\tradius=mid edge\n\tf=i\t\t\t\tfit=inside\n\tf=o\t\t\t\tfit=outside\n\tf=m\t\t\tfit=mid arrow\n\t?\t\t\t\tHelp\n"

property pstrPrompt : "Number of arrows ?\nWidth of block arrows ?\nHead and or tail arrow ?\nBlock arrows ? (or simple line arrows)\nCircle radius:\n\tto corner of shape ?\n\tto mid-edge of shape ?\nCircle fit:\n\t fits inside shape ?\n\t fits outside shape ?\n\t covers edge of shape ?\n\nHELP ?\t(enter a question mark)\n"

property plngArrows : 4
property plngRadius : 150

property pblnBlockArrow : true
property pArrowWidth : 20

property peMidEdgeRadius : 1
property peCornerRadius : 2
property peInnerFit : 1
property peOuterFit : 2
property peMidArrowFit : 3

property pRadiusMatch : 2 -- peCornerRadius
property pFit : 2 -- peOuterFit

property pArcAnglePoints : 0.25

property pHeadArrow : true
property pTailArrow : false


property pstrLineArrowHead : "FilledArrow"
property plstLineArrowColor : {1.0, 0.0, 0.0}
property prLineArrowThickness : 2
property pblnLineArrowShadow : true

property plstBlockArrowLineColor : {34081, 38505, 51776}

-- User data keys (adjust if they happen to clash with keys already in use)

property pGap : 1 / 400

property pDeg : 180 / pi

-- FUNCTION:
-- CREATES A CYCLE DIAGRAM, IN WHICH A SET OF SHAPES ARE LINKED IN A CIRCLE
-- BY ARC ARROWS

on run
    tell application id "OGfl"
        activate
        
        set oShape to self
        try
            oShape
        on error
            if my isFullScreen("OGfl") then
                set oWin to window 2
            else
                set oWin to window 1
            end if
            if id of oWin < 0 then return
            
            set lstSeln to selection of oWin
            if length of lstSeln < 1 then
                display dialog "First position, size, and select a rectangle, then run again." buttons {"OK"} default button "OK" with title pTitle & "  ver. " & pVer
                return
            end if
            set oShape to item 1 of lstSeln
        end try
        
        set strReturned to "?"
        repeat until strReturned ≠ "?"
            tell oShape
                
                
                set strDefault to "arrows=" & (plngArrows as string) & space & "w=" & pArrowWidth & " h=" & pHeadArrow & " t=" & pTailArrow & " b=" & pblnBlockArrow
                if pRadiusMatch = peCornerRadius then
                    set strDefault to strDefault & " radius=corner"
                else
                    set strDefault to strDefault & " radius=edge"
                end if
                if pFit = peInnerFit then
                    set strDefault to strDefault & " fit=innner"
                else
                    set strDefault to strDefault & " fit=outer"
                end if
                
                try
                    tell (display dialog pstrPrompt default answer strDefault with title pTitle & tab & pVer)
                        set strReturned to text returned
                    end tell
                on error
                    return
                end try
                
                set {dlm, my text item delimiters} to {my text item delimiters, " "}
                set lstParts to text items of strReturned
                set lngParts to length of lstParts
                if lngParts < 1 then return
                set my text item delimiters to dlm
                
                set {dlm, my text item delimiters} to {my text item delimiters, "="}
                repeat with iPart from 1 to lngParts
                    set strPart to item iPart of lstParts
                    set lstKeyValue to text items of strPart
                    if length of lstKeyValue = 2 then
                        set {strKey, strvalue} to lstKeyValue
                        if strKey begins with "a" then
                            try
                                set plngArrows to (strvalue as integer)
                            on error
                                display alert strvalue & " could not be read as an integer"
                                return
                            end try
                        else if strKey begins with "h" then
                            try
                                set pHeadArrow to strvalue as boolean
                            on error
                                display dialog strvalue & " could not be interpreted as a boolean value ..."
                                return
                            end try
                        else if strKey begins with "t" then
                            try
                                set pTailArrow to strvalue as boolean
                            on error
                                display dialog strvalue & " could not be interpreted as a boolean value ..."
                                return
                            end try
                        else if strKey begins with "w" then
                            try
                                set pArrowWidth to strvalue as number
                            on error
                                display dialog strvalue & " could not be interpreted as a number ..."
                                return
                            end try
                        else if strKey begins with "b" then
                            try
                                set pblnBlockArrow to strvalue as boolean
                            on error
                                display dialog strvalue & " could not be interpreted as a boolean value ..."
                                return
                            end try
                        else if strKey begins with "r" then
                            if strvalue begins with "c" then
                                set pRadiusMatch to peCornerRadius
                            else
                                set pRadiusMatch to peMidEdgeRadius
                                
                            end if
                        else if strKey begins with "f" then
                            if strvalue begins with "i" then
                                set pFit to peInnerFit
                            else if strvalue begins with "o" then
                                set pFit to peOuterFit
                            else
                                set pFit to peMidArrowFit
                            end if
                        end if
                    else
                        if strPart begins with "?" then
                            display dialog pstrHelp buttons {"OK"} default button "OK" with title pTitle & "  ver. " & pVer
                        else
                            try
                                set plngArrows to (strPart as integer)
                            on error
                                display alert strpars & " could not be read as an integer"
                                return
                            end try
                        end if
                    end if
                end repeat
                set my text item delimiters to dlm
                
                if plngArrows < 1 or plngArrows > 100 then
                    display alert "Number of arrows must be in range 1-100 ..."
                    return
                end if
                
                if strReturned ≠ "?" then
                    set oCanvas to its canvas
                    set automatic layout of layout info of oCanvas to false
                    
                    
                    set {rX, rY} to origin
                    set {rWidth, rHeight} to size
                    set rRotn to rotation
                    
                    
                    -- DETERMINE RADIUS AS A FUNCTION OF  radius type and fit type
                    if rWidth ≥ rHeight then
                        set plngRadius to (rWidth / 2)
                    else
                        set plngRadius to (rHeight / 2) + pArrowWidth
                    end if
                    
                    if pRadiusMatch = peCornerRadius then
                        set plngRadius to ((rWidth / 2) ^ 2 + (rHeight / 2) ^ 2) ^ 0.5
                    else
                        if rWidth ≥ rHeight then
                            set plngRadius to (rHeight / 2)
                        else
                            set plngRadius to (rWidth / 2)
                        end if
                    end if
                    
                    if pblnBlockArrow then
                        if pFit = peInnerFit then
                            set plngRadius to plngRadius - pArrowWidth / 2
                        else if pFit = peOuterFit then
                            set plngRadius to plngRadius + pArrowWidth / 2
                        end if
                    end if
                    
                    set lstCenter to {rX + rWidth / 2, rY + rHeight / 2}
                    set rTheta to rRotn
                    set rDelta to 360 / plngArrows
                    set rNext to rTheta + rDelta
                    
                    -- DRAW A CURVED ARC (ARROW) BETWEEN EACH SUCCESSIVE PAIR OF SHAPES
                    repeat with i from 1 to plngArrows
                        set oArc to my MakeArc(pblnBlockArrow, lstCenter, plngRadius, rTheta, rNext, ¬
                            pArrowWidth, pArcAnglePoints, pHeadArrow, pTailArrow, oCanvas)
                        if oArc is not missing value then
                            tell oArc
                                --set value of user data item pstrArcData to "{From:" & idLast & ", To:" & idNext & "}"
                                set idArc to its id
                            end tell
                        end if
                        set rTheta to rNext
                        set rNext to rTheta + rDelta
                    end repeat
                end if
            end tell
        end repeat
    end tell
end run

-- CENTER, RADIUS, FROM DEGREES, TO DEGREES, WIDTH, 
-- BEZIER POINTS PER DEGREE OF ARC, HEAD ARROW, TAIL ARROW
on MakeArc(pblnBlockArrow, {rX, rY}, rRadius, rFrom, rTo, rWidth, rPointsPerDegree, blnHeadArrow, blnTailArrow, oCanvas)
    -- (CURRENTLY A SIMPLE FUNCTION OF THE ARROW WIDTH)
    set {rStart, rEnd} to {rFrom, rTo}
    
    if pblnBlockArrow then
        -- CALCULATE THE LENGTH OF ANY ARROWS 
        if (blnHeadArrow or blnTailArrow) then
            set rArrow to (rWidth / (pi * rRadius)) * 180
            if blnHeadArrow then set rEnd to rTo - rArrow
            if blnTailArrow then set rStart to rFrom + rArrow
        end if
    end if
    
    -- AND THE AMOUNT OF ARC WHICH IT TRAVELS
    set rArc to rEnd - rStart
    if rArc < 0 then set rArc to (rEnd + 360) - rStart
    
    -- HOW MANY POINTS WILL WE USE TO DRAW THE SHAFT ?
    set lngPoints to (rArc * rPointsPerDegree) as integer
    if lngPoints > 0 then
        set rDelta to rArc / lngPoints
        
        if pblnBlockArrow then
            set oGraphic to BlockArrow(oCanvas, {rX, rY}, rFrom, rTo, rStart, rEnd, rDelta, lngPoints, rWidth, blnHeadArrow, blnTailArrow, rRadius)
        else
            set oGraphic to ArcArrow(oCanvas, {rX, rY}, rFrom, rTo, rDelta, lngPoints, blnHeadArrow, blnTailArrow, rRadius)
        end if
        
        return oGraphic
    else
        return missing value
    end if
end MakeArc

on ArcArrow(oCanvas, {rX, rY}, rFrom, rTo, rDelta, lngPoints, blnHeadArrow, blnTailArrow, rRadius)
    set rTheta to rFrom
    set lstPoints to {}
    repeat with i from 1 to lngPoints
        set end of lstPoints to {rX + (rRadius * (sin(rTheta))), rY - rRadius * (cos(rTheta))}
        set rTheta to rTheta + rDelta
    end repeat
    set end of lstPoints to {rX + (rRadius * (sin(rTheta))), rY - rRadius * (cos(rTheta))}
    
    --     property pstrLineArrowHead : "FilledArrow"
    -- property plstLineArrowColor : {1.0, 0.0, 0.0}
    -- property plngLineArrowThickness : 2
    -- property pblnLineArrowShadow : true
    
    
    tell application id "OGfl"
        tell oCanvas
            set recStyle to {draws stroke:true, thickness:prLineArrowThickness, draws shadow:pblnLineArrowShadow, stroke color:plstLineArrowColor}
            if blnHeadArrow then set recStyle to recStyle & {head type:pstrLineArrowHead}
            if blnTailArrow then set recStyle to recStyle & {tail type:pstrLineArrowHead}
            set oLine to (make new line with properties {point list:lstPoints, line type:curved} & recStyle)
        end tell
    end tell
    return oLine
end ArcArrow

on BlockArrow(oCanvas, {rX, rY}, rFrom, rTo, rStart, rEnd, rDelta, lngPoints, rWidth, blnHeadArrow, blnTailArrow, rRadius)
    
    -- GET THE INNER AND OUTER RADII OF THE BLOCK ARROW
    set rW to rWidth / 2
    set {rRadOut, rRadin} to {rRadius + rW, rRadius - rW}
    
    -- COLLECT THE POINTS FOR THE OUTER AND INNER FLANKS OF THE ARROW
    set {lstOuter, lstInner} to {{}, {}}
    set rTheta to rStart
    repeat with i from 1 to lngPoints
        set {dX, dY} to {sin(rTheta), cos(rTheta)}
        set end of lstOuter to {rX + (rRadOut * dX), rY - rRadOut * dY}
        set end of lstInner to {rX + (rRadin * dX), rY - rRadin * dY}
        set rTheta to rTheta + rDelta
    end repeat
    set {dX, dY} to {sin(rTheta), cos(rTheta)}
    set end of lstOuter to {rX + (rRadOut * dX), rY - rRadOut * dY}
    set end of lstInner to {rX + (rRadin * dX), rY - rRadin * dY}
    
    -- MAKE HEAD AND/OR TAIL ARROWS IF REQUIRED
    set {lstHead, lstTail} to {{}, {}}
    set {rInnerBarb, rOuterBarb} to {rRadius - rWidth, rRadius + rWidth}
    -- TAIL ARROW ?
    if blnTailArrow then
        -- inner barb, tip, outer barb
        set lstTail to {{rX + (rInnerBarb * (sin(rStart))), rY - rInnerBarb * (cos(rStart))}, ¬
            {rX + (rRadius * (sin(rFrom))), rY - rRadius * (cos(rFrom))}, ¬
            {rX + (rOuterBarb * (sin(rStart))), rY - rOuterBarb * (cos(rStart))}}
    end if
    -- HEAD ARROW ?
    if blnHeadArrow then
        set lstHead to {{rX + (rOuterBarb * (sin(rEnd))), rY - rOuterBarb * (cos(rEnd))}, ¬
            {rX + (rRadius * (sin(rTo))), rY - rRadius * (cos(rTo))}, ¬
            {rX + (rInnerBarb * (sin(rEnd))), rY - rInnerBarb * (cos(rEnd))}}
    end if
    
    -- JOIN THE SHAFT TO ANY ARROW TIPS
    set lstPoints to (lstOuter & lstHead & reverse of lstInner & lstTail)
    
    -- GATHER THE POINTS IN THE TRIPLET FORMAT EXPECTED FOR CUSTOM SHAPES
    set oFirstPoint to item 1 of lstPoints
    set lstBezier to {oFirstPoint, oFirstPoint}
    repeat with i from 2 to length of lstPoints
        set oPoint to item i of lstPoints
        set lstBezier to lstBezier & {oPoint, oPoint, oPoint}
    end repeat
    set end of lstBezier to oFirstPoint
    
    -- AND RETURN A CUSTOM SHAPE
    tell application id "OGfl"
        tell oCanvas to set oShape to make new shape with properties {point list:lstBezier, draws stroke:true, stroke color:plstBlockArrowLineColor}
        set notes of oShape to "From " & rFrom & "º" & return & "To " & rTo & "º"
    end tell
    return oShape
end BlockArrow



-- If Lion is running, are we in full screen mode ?
on isFullScreen(strAppID)
    tell application "Finder" to set blnPreLion to (version < "10.7")
    if blnPreLion then
        return false
    else
        tell application id "sevs"
            set lstApps to application processes where creator type = strAppID
            if length of lstApps < 1 then return false
            set lstWins to windows of first item of lstApps
            if length of lstWins < 1 then return false
            return value of attribute "AXFullScreen" of item 1 of lstWins
        end tell
    end if
end isFullScreen

-- on sin(rDegrees)
--     (do shell script "echo 'echo $((sin(" & (rDegrees / 180) * pi & ")))' | ksh") as number
-- end sin
-- 
-- on cos(rDegrees)
--     (do shell script "echo 'echo $((cos(" & (rDegrees / 180) * pi & ")))' | ksh") as number
-- end cos
-- 
-- on sin(rDegrees)
--     (do shell script "echo 's(" & (rDegrees / 180) * pi & ")' | bc -l") as number
-- end sin
-- 
-- on cos(rDegrees)
--     (do shell script "echo 'c(" & (rDegrees / 180) * pi & ")' | bc -l") as number
-- end cos


-- BASIC TRIG FUNCTIONS PUBLISHED BY OTHERS
-- COULD USE THE KSH SHELL, BUT THESE ARE PROBABLY FASTER ...

-- Trig functions from:
-- http://lists.apple.com/archives/applescript-users/2004/Feb/msg00939.html

on cos(x) -- degrees
    local myCos, numerator, denominator, factor
    
    set myCos to 0
    if (x = 90) or (x = 270) then
        set myCos to 0
    else
        set x to (x - (((x / 360) div 1) * 360)) * (pi / 180)
        set {myCos, numerator, denominator, factor} to {0, 1, 1, -(x ^ 2)}
        repeat with i from 2 to 40 by 2
            set myCos to myCos + numerator / denominator
            set numerator to numerator * factor
            set denominator to denominator * i * (i - 1)
        end repeat
    end if
    return myCos
end cos
-- 
-- ----------------------------
on sin(x) -- degrees
    local mySin, numerator, denomintator, factor
    
    set mySin to 0
    if (x = 180) or (x = 360) then
        set mySin to 0
    else
        set x to (x - (((x / 360) div 1) * 360)) * (pi / 180)
        set {mySin, numerator, denominator, factor} to {0, x, 1, -(x ^ 2)}
        repeat with i from 3 to 40 by 2
            set mySin to mySin + numerator / denominator
            set numerator to numerator * factor
            set denominator to denominator * i * (i - 1)
        end repeat
    end if
    return mySin
end sin

accepting or editing the prompt for details:

and obtaining something like this circumscription of the selected shape:

Whoo Hoo- Thank you draft8—Winna Winna Chikn dinna!!

1 Like