In a previous blog post about new ShapeSheet functions, we introduced a set of new functions called the Point Along Path functions. These functions allow interactions with geometry paths of shapes. This post provides more detail about these new functions.
The following functions open up a broad set of shape interactions for shape and solution developers:
|ANGLEALONGPATH(section,travel [,segment])||Returns the angle of the tangent to the path at a given point.|
|DISTTOPATH(section,x,y)||Returns the shortest distance from the point represented by the specified coordinates to a point on the path.|
|NEARESTPOINTONPATH(section,x,y)||Returns the percentage of the distance along the path of the point that is nearest to the specified coordinates, as a value between 0 and 1.|
|PATHLENGTH(section[,segment])||Returns the length of the path that is defined in the specified Geometry section.|
|PATHSEGMENT(section,travel)||Returns the 1-based segment number at the specified percentage mark along the specified path.|
|POINTALONGPATH(section,travel[,offset][,segment])||Returns the coordinates of a point on, or offset from, the path.|
|SEGMENTCOUNT(pathRef)||Returns the number of line segments that make up the path.|
In the above functions:
- Arguments in brackets [ ] are optional
- Section always refers to a Geometry path. The correct way to reference a geometry path section is to enter the section reference followed by “.Path” (for example, Sheet.1!Geometry2.Path)
- Travel is a measure of the position along the path between the beginning and the end points, defined as a percentage. It is always represented by a number between 0 and 1, where 0 represents the beginning point, and 1 represents the end point
- Segment is a 1-based index of a line segment in the path that corresponds to a row in the geometry section.
To give you an idea of what you can do with these functions, we’ll explore three examples.
Adorning a Connector
We’ve seen shape developers create connector adornments to convey additional information. With the Point Along Path functions, this is now easier than ever to do.
Here’s a simple triangle shape that sits at the midpoint of the connector, and changes direction with the connector. It works with curved and right angle connectors:
To create this adornment, you only need a few ShapeSheet formulas:
- First, make sure that the adornment shape will be ignored by the Visio routing engine. To do this, select the shape, and click "Behavior" from the Developer tab. In the ensuing dialog, click on the "Placement" tab, and ensure that placement behavior is set to "Do not lay out and route around".
- Create a user cell in the adornment shape (we’ll call it User.ConnectorGluePoint, and use the POINTALONGPATH() function and reference the connector that the shape will adorn:
- POINTALONGPATH(Dynamic connector.23!Geometry1.Path,0.5)
- This returns a point in local coordinates to the connector
- Create another user cell, User.PageCoord, and use the LOCTOPAR() function to translate the local coordinates to page coordinates:
- LOCTOPAR(User.ConnectorGluePoint,Dynamic connector.23!User.msvThemeColors,User.msvThemeColors)
- The LOCTOPAR function needs cell references for the source and destination of the translation. Here we arbitrarily use User.msvThemeColors because the property exists in both the source and destination.
- Now, set PinX,PinY, and Angle cells on the adornment shape accordingly (found in the Shape Transform section):
- PinX: GUARD(PNTX(User.PageCoord))
- PinY: GUARD(PNTY(User.PageCoord))
- Angle: ANGLEALONGPATH(Dynamic connector.23!Geometry1.Path,0.5)-PI()/2
- We subtract PI/2 because we’re using a triangle and the point is not aligned with the 0 angle. The ANGLEALONGPATH() function returns the tangent angle to the specified point on the path.
Finding the Nearest Point on a Path
You can use the NEARESTPOINTONPATH() function to find the coordinates of a point along a path that is closest to a given point. In the picture below, the triangle shape is showing the nearest point along the path to the center of the circular shape:
Here’s how we setup the triangle to do this:
- Create a user cell in the triangle shape to store the point of the circle shape (we’ll call it User.LocalPoint) Use the following formula to transform the LocPin point of the circle into local coordinates relative to the curve:
- We use the PNT function to turn the LocPinX and LocPinY into a point
- Create another user cell in the triangle (we’ll call it User.Travel) to store the percentage along the path (the travel) that is nearest to the circle. Use the following formula:
- This returns the percentage along ArcLine!Geometry1.Path that has the nearest point to the center of the circle shape
- Create another user cell (we’ll call it User.ArcGluePoint) to store the point along the path of the arc that is closest to the circle. Use the following formula:
- This will return the point on the arc where the triangle should be glued, in local coordinates relative to the arc.
Just like the example above, you then need to transform the local coordinates, and set the PinX and PinY of the triangle so that its glued to the arc.
As you change the curve of the timeline, the milestone shapes stay attached to the curve, which allows you to create a great looking visual.
The main difference between this example and the previous one is that we’ve introduced a mechanism for automatically attaching adornments to the arc geometry. Here we turned the arc shape into a custom container to give the milestone shapes a universal reference. Since they are members of the container, we use the CONTAINERSHEETREF() function to reference the geometry of the arc. When you make multiple copies of the milestone shape, their reference to the timeline arc geometry is preserved as long as they are members of the container. (For more info on custom containers, see our previous post ).
To place the milestones accurately on the timeline arc, we used the POINTALONGPATH() function. Each timeline shape stores its own date. The timeline arc contains the “begin” and “end” dates of the timeline.
The attached VSD file includes the curved timeline, and the other two examples, so you can take a look at the formulas and play around with them.
We think these new functions will open up a new set of scenarios for shape developers. Some things you might try to create with them are:
- Placing text or adornments at fixed distances from the beginning or end of a connector
- Detecting whether a point is inside or outside a closed path
- Calculating the lengths of curved paths in a diagram
- Drawing a line that terminates on a complex path
As usual, please tell us what you think by using the Send a Smile feedback tool or by commenting on this post.