Workflow computations
Understanding how workflow computations work
Overview
Workflow Computations (WFC) provide you with a way to compute and set attribute values based on their result. You can also create more general computations such as adding numeric attribute values together or concatenating strings and assigning the result to another attribute value.
The functionality of the Workflow Computations has been designed to be as general as possible to allow you to cater for as many applications as possible. The following examples illustrate the scenarios of what is possible:
When an inspection is carried out on a reported pot hole, inspectors would capture the length, width and depth of the pot hole, this workflow would turn that into a calculated area and depth.
"parameters": [
{
//saves area (length*width) into the specified attribute
"attributeCode": "attributes_potHoleWFCArea",
"value": {
"script": "return length*width;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
},
"discriminator": "WorkflowComputedItemAttributeWebModel"
},
{
//saves volume (length*width*depth) into the specified attribute
"attributeCode": "attributes_potHoleWFCVolume",
"value": {
"script": "return length*width*depth;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
},
"discriminator": "WorkflowComputedItemAttributeWebModel"
}
],
"variables": [
{
//gets Length number attribute from current node input
"name": "length",
"value": {
"inputParent": 0,
"itemValue": {
"attributeCode": "attributes_potHoleWFCLength",
"discriminator": "WorkflowSyntaxArgumentItemValueAttributeWebModel"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
},
{
//gets Width number attribute from current node input
"name": "width",
"value": {
"inputParent": 0,
"itemValue": {
"attributeCode": "attributes_potHoleWFCWidth",
"discriminator": "WorkflowSyntaxArgumentItemValueAttributeWebModel"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
},
{
//gets Depth number attribute from current node input
"name": "depth",
"value": {
"inputParent": 0,
"itemValue": {
"attributeCode": "attributes_potHoleWFCDepth",
"discriminator": "WorkflowSyntaxArgumentItemValueAttributeWebModel"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
}
]
The Depth and Volume values would be combined and then assigned to their respective attributes.
Similar to the previous example, this example takes the input from an item’s own geometry. Alloy stores geometry using the WGS84 coordinate system (Longitude/Latitude). The geometry here is converted to a local coordinate system (British National Grid) then area is calculated in square metres.
"parameters": [
{
//saves area (sqm) to the specified attribute
"attributeCode": "attributes_polygonAssetArea",
"value": {
"script": "return area;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
},
"discriminator": "WorkflowComputedItemAttributeWebModel"
}
],
"variables": [
{
//gets Geometry attribute from current node input
"name": "geometryWGS84",
"value": {
"inputParent": 0,
"itemValue": {
"discriminator": "WorkflowSyntaxArgumentItemValueAttributeWebModel",
"attributeCode": "attributes_itemsGeometry"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
},
{
//reprojects geometry to British National Grid (Easting/Northing) which uses metres
"name": "geometryBNG",
"value": {
"script": "var geometryBNG = GeometryMath.ProjectFromAlloyCrs(geometryWGS84,\"+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +towgs84=446.448,-125.157,542.06,0.15,0.247,0.842,-20.489 +units=m +no_defs\");return geometryBNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//computes area
"name": "area",
"value": {
"script": "return GeometryMath.Area(geometryBNG);",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
}
]
This example shows how to calculate the length of an item from its geometry and store that in an attribute on the item.
"parameters": [
{
//saves length (m) into the specified attribute
"attributeCode": "attributes_linearAssetLength",
"value": {
"script": "return length;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
},
"discriminator": "WorkflowComputedItemAttributeWebModel"
}
],
"variables": [
{
//gets Geometry attribute from current node input
"name": "geometryWGS84",
"value": {
"inputParent": 0,
"itemValue": {
"discriminator": "WorkflowSyntaxArgumentItemValueAttributeWebModel",
"attributeCode": "attributes_itemsGeometry"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
},
{
//reprojects geometry to British National Grid (Easting/Northing) which uses metres
"name": "geometryBNG",
"value": {
"script": "var geometryBNG = GeometryMath.ProjectFromAlloyCrs(geometryWGS84,\"+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +towgs84=446.448,-125.157,542.06,0.15,0.247,0.842,-20.489 +units=m +no_defs\");return geometryBNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//computes length
"name": "length",
"value": {
"script": "return GeometryMath.Length(geometryBNG);",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
}
]
This example takes the value in a Date Time Attribute and strips out the Time element of the value and stores only the Date into another attribute.
"parameters": [
{
//saves date into the specified attribute
"attributeCode": "attributes_jobStartDate",
"value": {
"script": "return startDate;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
},
"discriminator": "WorkflowComputedItemAttributeWebModel"
}
],
"variables": [
{
//gets Start Time datetime attribute from current node input
"name": "startDateTime",
"value": {
"inputParent": 0,
"itemValue": {
"discriminator": "WorkflowSyntaxArgumentItemValueAttributeWebModel",
"attributeCode": "attributes_tasksStartTime"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
},
{
//convert datetime to date
"name": "startDate",
"value": {
"script": "var startDate = Date(startDateTime); return startDate;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
}
]
In this example, the workflow checks the date value held in the Start Time attribute on a task and, depending on the day the date value falls, writes ‘Weekday’ or ‘Weekend’ into another attribute.
"parameters": [
{
//saves day type text into the specified attribute
"attributeCode": "attributes_jobDayType",
"value": {
"script": "return dayType;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
},
"discriminator": "WorkflowComputedItemAttributeWebModel"
}
],
"variables": [
{
//gets Start Time datetime attribute from current node input
"name": "startDateTime",
"value": {
"inputParent": 0,
"itemValue": {
"discriminator": "WorkflowSyntaxArgumentItemValueAttributeWebModel",
"attributeCode": "attributes_tasksStartTime"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
},
{
//converts date time to DayOfWeek and checks whether it is a Saturday or Sunday or not.
//If True returns "weekend", if False returns "weekday"
"name": "dayType",
"value": {
"script": "var dayType= \"weekday\";var day = startDateTime.Value.DayOfWeek;if((day == DayOfWeek.Saturday) || (day == DayOfWeek.Sunday)){dayType=\"weekend\";} return dayType;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
}
]
This example computes the duration between two Date Time attributes and enters the number of hours, minutes and seconds into three seperate attributes.
"parameters": [
{
//saves task duration in hours into the specified attribute
"attributeCode": "attributes_jobTotalHours",
"value": {
"script": "return totalHours;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
},
"discriminator": "WorkflowComputedItemAttributeWebModel"
},
{
//saves task duration in minutes into the specified attribute
"attributeCode": "attributes_jobTotalMinutes",
"value": {
"script": "return totalMinutes;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
},
"discriminator": "WorkflowComputedItemAttributeWebModel"
},
{
//saves task duration in seconds into the specified attribute
"attributeCode": "attributes_jobTotalSeconds",
"value": {
"script": "return totalSeconds;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
},
"discriminator": "WorkflowComputedItemAttributeWebModel"
}
],
"variables": [
{
//gets Start Time datetime attribute from current node input
"name": "startDateTime",
"value": {
"inputParent": 0,
"itemValue": {
"discriminator": "WorkflowSyntaxArgumentItemValueAttributeWebModel",
"attributeCode": "attributes_tasksStartTime"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
},
{
//gets Completion Time datetime attribute from current node input
"name": "completionDateTime",
"value": {
"inputParent": 0,
"itemValue": {
"discriminator": "WorkflowSyntaxArgumentItemValueAttributeWebModel",
"attributeCode": "attributes_tasksCompletionTime"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
},
{
//Computes task duration and converts it to hours
"name": "totalHours",
"value": {
"script": "var totalHours = (completionDateTime - startDateTime).Value.TotalHours; return totalHours;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//Computes task duration and converts it to minutes
"name": "totalMinutes",
"value": {
"script": "var totalMinutes = (completionDateTime - startDateTime).Value.TotalMinutes; return totalMinutes;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//Computes task duration and converts it to seconds
"name": "totalSeconds",
"value": {
"script": "var totalSeconds = (completionDateTime - startDateTime).Value.TotalSeconds; return totalSeconds;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
}
]
This example shows how to compute the centroid point of a geometry and save the longitude and latituge into two attributes.
"parameters": [
{
//saves centroid latitude into the specified attribute
"attributeCode": "attributes_jobCentroidLatitude",
"value": {
"script": "return latitude;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
},
"discriminator": "WorkflowComputedItemAttributeWebModel"
},
{
//saves centroid longitude into the specified attribute
"attributeCode": "attributes_jobTestCentroidLongitude",
"value": {
"script": "return longitude;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
},
"discriminator": "WorkflowComputedItemAttributeWebModel"
}
],
"variables": [
{
//gets Geometry attribute from current node input
"name": "geometryWGS84",
"value": {
"inputParent": 0,
"itemValue": {
"discriminator": "WorkflowSyntaxArgumentItemValueAttributeWebModel",
"attributeCode": "attributes_itemsGeometry"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
},
{
//computes centroid point
"name": "centroidGeometry",
"value": {
"script": "return GeometryMath.Centroid(geometryWGS84);",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//gets latitude from centroid point
"name": "latitude",
"value": {
"script": "var centroidPoint = centroidGeometry as GeoJSON.Net.Geometry.Point; var latitude = centroidPoint.Coordinates.Latitude;return latitude;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//gets longitude from centroid point
"name": "longitude",
"value": {
"script": "var centroidPoint = centroidGeometry as GeoJSON.Net.Geometry.Point; var longitude = centroidPoint.Coordinates.Longitude;return longitude;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
}
]
This example computes the extent of an item geometry and stores the SE and NW corners of a box that encapsulates the item.
"parameters": [
{
//saves SW "Longitude,Latitude" pair into the specified text attribute
"attributeCode": "attributes_assetSWExtent",
"value": {
"script": "return WGS84_BBOX_West+\",\"+WGS84_BBOX_South;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
},
"discriminator": "WorkflowComputedItemAttributeWebModel"
},
{
//saves NE "Longitude,Latitude" pair into the specified text attribute
"attributeCode": "attributes_assetNEExtent",
"value": {
"script": "return WGS84_BBOX_East+\",\"+WGS84_BBOX_North;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
},
"discriminator": "WorkflowComputedItemAttributeWebModel"
}
],
"variables": [
{
//gets Geometry attribute from current node input
"name": "geometryWGS84",
"value": {
"inputParent": 0,
"itemValue": {
"discriminator": "WorkflowSyntaxArgumentItemValueAttributeWebModel",
"attributeCode": "attributes_itemsGeometry"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
},
{
//computes centroid point
//if input geometry is a point -> centroid is a point geometry
//else centroid is a polygon geometry
"name": "geometryWGS84_BBOX",
"value": {
"script": "return GeometryMath.BoundingBox(geometryWGS84);",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//checks whether input is a point or a polygon and gets south latitude
"name": "WGS84_BBOX_South",
"value": {
"script": "var WGS84_BBOX_South=\"\"; var jsonGeom=Json(geometryWGS84_BBOX);var geometryTypeString = jsonGeom[\"type\"].ToString();if(geometryTypeString==\"Point\"){WGS84_BBOX_South=jsonGeom[\"coordinates\"][1].ToString();}else{WGS84_BBOX_South=jsonGeom[\"coordinates\"][0][0][1].ToString();}return WGS84_BBOX_South;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//checks whether input is a point or a polygon and gets west longitude
"name": "WGS84_BBOX_West",
"value": {
"script": "var WGS84_BBOX_West=\"\"; var jsonGeom=Json(geometryWGS84_BBOX);var geometryTypeString = jsonGeom[\"type\"].ToString();if(geometryTypeString==\"Point\"){WGS84_BBOX_West=jsonGeom[\"coordinates\"][0].ToString();}else{WGS84_BBOX_West=jsonGeom[\"coordinates\"][0][0][0].ToString();}return WGS84_BBOX_West;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//checks whether input is a point or a polygon and gets north latitude
"name": "WGS84_BBOX_North",
"value": {
"script": "var WGS84_BBOX_North=\"\"; var jsonGeom=Json(geometryWGS84_BBOX);var geometryTypeString = jsonGeom[\"type\"].ToString();if(geometryTypeString==\"Point\"){WGS84_BBOX_North=jsonGeom[\"coordinates\"][1].ToString();}else{WGS84_BBOX_North=jsonGeom[\"coordinates\"][0][2][1].ToString();}return WGS84_BBOX_North;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//checks whether input is a point or a polygon and gets east longitude
"name": "WGS84_BBOX_East",
"value": {
"script": "var WGS84_BBOX_East=\"\"; var jsonGeom=Json(geometryWGS84_BBOX);var geometryTypeString = jsonGeom[\"type\"].ToString();if(geometryTypeString==\"Point\"){WGS84_BBOX_East=jsonGeom[\"coordinates\"][0].ToString();}else{WGS84_BBOX_East=jsonGeom[\"coordinates\"][0][2][0].ToString();}return WGS84_BBOX_East;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
}
]
This workflow intercepts a message action and changes the text included in the message.
"parameters": [
{
//SMS message type id
"attribute": {
"attributeCode": "attributes_workflowMessageActionMessageType",
"value": [
"5c66bcd44b4d4259071069df"
]
},
"discriminator": "WorkflowConstantItemAttributeWebModel"
},
{
//edits message text using template model. Combine static text with dynamic text from the input item attributes
"attributeCode": "attributes_workflowMessageActionMessageText",
"value": {
"template": "A new defect has been reported. Id: & $itemId &. Title: & $title &. Subtitle: & $subtitle",
"discriminator": "WorkflowSyntaxNodeTemplateWebModel"
},
"discriminator": "WorkflowComputedItemAttributeWebModel"
},
{
"attribute": {
"attributeCode": "attributes_workflowMessageActionRecipientName",
"value": "Arnau"
},
"discriminator": "WorkflowConstantItemAttributeWebModel"
},
{
"attribute": {
"attributeCode": "attributes_workflowMessageActionMobileNumber",
"value": "+447436425222"
},
"discriminator": "WorkflowConstantItemAttributeWebModel"
}
],
"variables": [
{
//gets title from current node input
"name": "title",
"value": {
"inputParent": 0,
"itemValue": {
"discriminator": "WorkflowSyntaxArgumentItemValueAttributeWebModel",
"attributeCode": "attributes_itemsTitle"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
},
{
//gets subtitle from current node input "name": "subtitle",
"value": {
"inputParent": 0,
"itemValue": {
"discriminator": "WorkflowSyntaxArgumentItemValueAttributeWebModel",
"attributeCode": "attributes_itemsSubtitle"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
},
{
//gets item ID from current node input
"name": "itemId",
"value": {
"inputParent": 0,
"itemValue": {
"discriminator": "WorkflowSyntaxArgumentItemValueItemPropertyWebModel",
"property": "ItemId"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
}
]
This example demonstrates how to calculate the tree crown spread given a central point for the tree and spread in the four compass directions in metres. This allows for a tree spread to then be set as a polygon using Bézier Curves.
"parameters": [
{
"attributeCode": "attributes_treesSpreadGeometry",
"value": {
"script": "return polygon_WGS84;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
},
"discriminator": "WorkflowComputedItemAttributeWebModel"
}
],
"variables": [
{
//gets Geometry attribute from current node input (tree point)
"name": "geometry_WGS84",
"value": {
"inputParent": 0,
"itemValue": {
"discriminator": "WorkflowSyntaxArgumentItemValueAttributeWebModel",
"attributeCode": "attributes_itemsGeometry"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
},
{
//gets spread north attribute value (m)
"name": "spread_north",
"value": {
"inputParent": 0,
"itemValue": {
"discriminator": "WorkflowSyntaxArgumentItemValueAttributeWebModel",
"attributeCode": "attributes_treesSpreadNorth"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
},
{
//gets spread west attribute value (m)
"name": "spread_west",
"value": {
"inputParent": 0,
"itemValue": {
"discriminator": "WorkflowSyntaxArgumentItemValueAttributeWebModel",
"attributeCode": "attributes_treesSpreadWest"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
},
{
//gets spread south attribute value (m)
"name": "spread_south",
"value": {
"inputParent": 0,
"itemValue": {
"discriminator": "WorkflowSyntaxArgumentItemValueAttributeWebModel",
"attributeCode": "attributes_treesSpreadSouth"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
},
{
//gets spread east attribute value (m)
"name": "spread_east",
"value": {
"inputParent": 0,
"itemValue": {
"discriminator": "WorkflowSyntaxArgumentItemValueAttributeWebModel",
"attributeCode": "attributes_treesSpreadEast"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
},
{
// convert geometry to British National Grid
"name": "geometry_BNG",
"value": {
"script": "var geometry_BNG = GeometryMath.ProjectFromAlloyCrs(geometry_WGS84,\"+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +towgs84=446.448,-125.157,542.06,0.15,0.247,0.842,-20.489 +units=m +no_defs\");return geometry_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//gets X coordinate of the tree
"name": "tree_x_BNG",
"value": {
"script": "var tree_x_BNG=double.Parse(Json(geometry_BNG)[\"coordinates\"][0].ToString()); return tree_x_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//gets Y coordinate of the tree
"name": "tree_y_BNG",
"value": {
"script": "var tree_y_BNG=double.Parse(Json(geometry_BNG)[\"coordinates\"][1].ToString()); return tree_y_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//computes X coordinate of north spread
"name": "spread_north_x_BNG",
"value": {
"script": "return tree_x_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//computes Y coordinate of north spread
"name": "spread_north_y_BNG",
"value": {
"script": "var spread_north_y_BNG=tree_y_BNG+spread_north; return spread_north_y_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//computes X coordinate of east spread
"name": "spread_east_x_BNG",
"value": {
"script": "var spread_east_x_BNG=tree_x_BNG+spread_east; return spread_east_x_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//computes Y coordinate of east spread
"name": "spread_east_y_BNG",
"value": {
"script": "return tree_y_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//computes X coordinate of south spread
"name": "spread_south_x_BNG",
"value": {
"script": "return tree_x_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//computes Y coordinate of south spread
"name": "spread_south_y_BNG",
"value": {
"script": "var spread_south_y_BNG=tree_y_BNG-spread_south; return spread_south_y_BNG;;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//computes X coordinate of west spread
"name": "spread_west_x_BNG",
"value": {
"script": "var spread_west_x_BNG=tree_x_BNG-spread_west; return spread_west_x_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//computes Y coordinate of east spread
"name": "spread_west_y_BNG",
"value": {
"script": "return tree_y_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
//Computes XY coordinates of significant points of the 4 curves that connect the cardinal points
//uses Bézier formula to get points of the curve given a start, end and control point
{
"name": "spread_ne_25_x_BNG",
"value": {
"script": "var t=0.25;var spread_ne_25_x_BNG=(1-t)*(1-t)*spread_north_x_BNG.Value+2*(1-t)*t*spread_east_x_BNG.Value+t*t*spread_east_x_BNG.Value; return spread_ne_25_x_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_ne_25_y_BNG",
"value": {
"script": "var t=0.25;var spread_ne_25_y_BNG=(1-t)*(1-t)*spread_north_y_BNG.Value+2*(1-t)*t*spread_north_y_BNG.Value+t*t*spread_east_y_BNG.Value; return spread_ne_25_y_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_ne_50_x_BNG",
"value": {
"script": "var t=0.5;var spread_ne_50_x_BNG=(1-t)*(1-t)*spread_north_x_BNG.Value+2*(1-t)*t*spread_east_x_BNG.Value+t*t*spread_east_x_BNG.Value; return spread_ne_50_x_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_ne_50_y_BNG",
"value": {
"script": "var t=0.5;var spread_ne_50_y_BNG=(1-t)*(1-t)*spread_north_y_BNG.Value+2*(1-t)*t*spread_north_y_BNG.Value+t*t*spread_east_y_BNG.Value; return spread_ne_50_y_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_ne_75_x_BNG",
"value": {
"script": "var t=0.75;var spread_ne_75_x_BNG=(1-t)*(1-t)*spread_north_x_BNG.Value+2*(1-t)*t*spread_east_x_BNG.Value+t*t*spread_east_x_BNG.Value; return spread_ne_75_x_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_ne_75_y_BNG",
"value": {
"script": "var t=0.75;var spread_ne_75_y_BNG=(1-t)*(1-t)*spread_north_y_BNG.Value+2*(1-t)*t*spread_north_y_BNG.Value+t*t*spread_east_y_BNG.Value; return spread_ne_75_y_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_se_25_x_BNG",
"value": {
"script": "var t=0.25;var spread_se_25_x_BNG=(1-t)*(1-t)*spread_east_x_BNG.Value+2*(1-t)*t*spread_east_x_BNG.Value+t*t*spread_south_x_BNG.Value; return spread_se_25_x_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_se_25_y_BNG",
"value": {
"script": "var t=0.25;var spread_se_25_y_BNG=(1-t)*(1-t)*spread_east_y_BNG.Value+2*(1-t)*t*spread_south_y_BNG.Value+t*t*spread_south_y_BNG.Value; return spread_se_25_y_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_se_50_x_BNG",
"value": {
"script": "var t=0.5;var spread_se_50_x_BNG=(1-t)*(1-t)*spread_east_x_BNG.Value+2*(1-t)*t*spread_east_x_BNG.Value+t*t*spread_south_x_BNG.Value; return spread_se_50_x_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_se_50_y_BNG",
"value": {
"script": "var t=0.5;var spread_se_50_y_BNG=(1-t)*(1-t)*spread_east_y_BNG.Value+2*(1-t)*t*spread_south_y_BNG.Value+t*t*spread_south_y_BNG.Value; return spread_se_50_y_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_se_75_x_BNG",
"value": {
"script": "var t=0.75;var spread_se_75_x_BNG=(1-t)*(1-t)*spread_east_x_BNG.Value+2*(1-t)*t*spread_east_x_BNG.Value+t*t*spread_south_x_BNG.Value; return spread_se_75_x_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_se_75_y_BNG",
"value": {
"script": "var t=0.75;var spread_se_75_y_BNG=(1-t)*(1-t)*spread_east_y_BNG.Value+2*(1-t)*t*spread_south_y_BNG.Value+t*t*spread_south_y_BNG.Value; return spread_se_75_y_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_sw_25_x_BNG",
"value": {
"script": "var t=0.25;var spread_sw_25_x_BNG=(1-t)*(1-t)*spread_south_x_BNG.Value+2*(1-t)*t*spread_west_x_BNG.Value+t*t*spread_west_x_BNG.Value; return spread_sw_25_x_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_sw_25_y_BNG",
"value": {
"script": "var t=0.25;var spread_sw_25_y_BNG=(1-t)*(1-t)*spread_south_y_BNG.Value+2*(1-t)*t*spread_south_y_BNG.Value+t*t*spread_west_y_BNG.Value; return spread_sw_25_y_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_sw_50_x_BNG",
"value": {
"script": "var t=0.5;var spread_sw_50_x_BNG=(1-t)*(1-t)*spread_south_x_BNG.Value+2*(1-t)*t*spread_west_x_BNG.Value+t*t*spread_west_x_BNG.Value; return spread_sw_50_x_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_sw_50_y_BNG",
"value": {
"script": "var t=0.5;var spread_sw_50_y_BNG=(1-t)*(1-t)*spread_south_y_BNG.Value+2*(1-t)*t*spread_south_y_BNG.Value+t*t*spread_west_y_BNG.Value; return spread_sw_50_y_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_sw_75_x_BNG",
"value": {
"script": "var t=0.75;var spread_sw_75_x_BNG=(1-t)*(1-t)*spread_south_x_BNG.Value+2*(1-t)*t*spread_west_x_BNG.Value+t*t*spread_west_x_BNG.Value; return spread_sw_75_x_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_sw_75_y_BNG",
"value": {
"script": "var t=0.75;var spread_sw_75_y_BNG=(1-t)*(1-t)*spread_south_y_BNG.Value+2*(1-t)*t*spread_south_y_BNG.Value+t*t*spread_west_y_BNG.Value; return spread_sw_75_y_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_nw_25_x_BNG",
"value": {
"script": "var t=0.25;var spread_nw_25_x_BNG=(1-t)*(1-t)*spread_west_x_BNG.Value+2*(1-t)*t*spread_west_x_BNG.Value+t*t*spread_north_x_BNG.Value; return spread_nw_25_x_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_nw_25_y_BNG",
"value": {
"script": "var t=0.25;var spread_nw_25_y_BNG=(1-t)*(1-t)*spread_west_y_BNG.Value+2*(1-t)*t*spread_north_y_BNG.Value+t*t*spread_north_y_BNG.Value; return spread_nw_25_y_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_nw_50_x_BNG",
"value": {
"script": "var t=0.5;var spread_nw_50_x_BNG=(1-t)*(1-t)*spread_west_x_BNG.Value+2*(1-t)*t*spread_west_x_BNG.Value+t*t*spread_north_x_BNG.Value; return spread_nw_50_x_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_nw_50_y_BNG",
"value": {
"script": "var t=0.5;var spread_nw_50_y_BNG=(1-t)*(1-t)*spread_west_y_BNG.Value+2*(1-t)*t*spread_north_y_BNG.Value+t*t*spread_north_y_BNG.Value; return spread_nw_50_y_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_nw_75_x_BNG",
"value": {
"script": "var t=0.75;var spread_nw_75_x_BNG=(1-t)*(1-t)*spread_west_x_BNG.Value+2*(1-t)*t*spread_west_x_BNG.Value+t*t*spread_north_x_BNG.Value; return spread_nw_75_x_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "spread_nw_75_y_BNG",
"value": {
"script": "var t=0.75;var spread_nw_75_y_BNG=(1-t)*(1-t)*spread_west_y_BNG.Value+2*(1-t)*t*spread_north_y_BNG.Value+t*t*spread_north_y_BNG.Value; return spread_nw_75_y_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//computes a polygon geometry by joining together all the XY coordinates
//Polygon -> array of LineStrings -> array of Positions
"name": "polygon_WGS84",
"value": {
"script": "var polygon_BNG=Polygon(LineString(Position(spread_north_y_BNG.Value, spread_north_x_BNG.Value),Position(spread_ne_25_y_BNG.Value, spread_ne_25_x_BNG.Value),Position(spread_ne_50_y_BNG.Value, spread_ne_50_x_BNG.Value),Position(spread_ne_75_y_BNG.Value, spread_ne_75_x_BNG.Value),Position(spread_east_y_BNG.Value, spread_east_x_BNG.Value),Position(spread_se_25_y_BNG.Value, spread_se_25_x_BNG.Value),Position(spread_se_50_y_BNG.Value, spread_se_50_x_BNG.Value),Position(spread_se_75_y_BNG.Value, spread_se_75_x_BNG.Value),Position(spread_south_y_BNG.Value, spread_south_x_BNG.Value),Position(spread_sw_25_y_BNG.Value, spread_sw_25_x_BNG.Value),Position(spread_sw_50_y_BNG.Value, spread_sw_50_x_BNG.Value),Position(spread_sw_75_y_BNG.Value, spread_sw_75_x_BNG.Value),Position(spread_west_y_BNG.Value, spread_west_x_BNG.Value),Position(spread_nw_25_y_BNG.Value, spread_nw_25_x_BNG.Value),Position(spread_nw_50_y_BNG.Value, spread_nw_50_x_BNG.Value),Position(spread_nw_75_y_BNG.Value, spread_nw_75_x_BNG.Value),Position(spread_north_y_BNG.Value, spread_north_x_BNG.Value)));var polygon_WGS84=GeometryMath.ProjectToAlloyCrs(polygon_BNG,\"+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +towgs84=446.448,-125.157,542.06,0.15,0.247,0.842,-20.489 +units=m +no_defs\");return polygon_WGS84;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
}
]
This example workflow computation can be used to generate a circular polygon centred on a given point. A good example use of this is to generate a Root Protection Area for a tree.
"parameters": [
{
//update the geometry with the new computed geometry
"attributeCode": "attributes_itemsGeometry",
"value": {
"script": "return buffered_geometry_WGS84;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
},
"discriminator": "WorkflowComputedItemAttributeWebModel"
}
],
"variables": [
{
//get the current asset geometry (using a Tree asset in this example - point geometry) - adjust the "inputParent" as necessary
"name": "geometry_WGS84",
"value": {
"inputParent": 2,
"itemValue": {
"attributeCode": "attributes_itemsGeometry",
"discriminator": "WorkflowSyntaxArgumentItemValueAttributeWebModel"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
},
{
//convert the geometry to BNG so that it can be manipulated
"name": "geometry_BNG",
"value": {
"script": "var geometry_BNG = GeometryMath.ProjectFromAlloyCrs(geometry_WGS84,\"+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +towgs84=446.448,-125.157,542.06,0.15,0.247,0.842,-20.489 +units=m +no_defs\");return geometry_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//get or set the distance from the point that you want to buffer from - in this case the distance from the tree
"name": "tree_radius",
"value": {
"inputParent": 2,
"itemValue": {
"attributeCode": "attributes_treesRootProtectionAreaRadius",
"discriminator": "WorkflowSyntaxArgumentItemValueAttributeWebModel"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
},
{
//calculate the new polygon using GeometryMath.Buffer
"name": "buffered_geometry_BNG",
"value": {
"script": "var buffered_geometry_BNG = GeometryMath.Buffer(tree_radius.Value,geometry_BNG) ;return buffered_geometry_BNG;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
//convert the BNG geometry back to WGS84 so that it can be saved back to alloy
"name": "buffered_geometry_WGS84",
"value": {
"script": "var buffered_geometry_WGS84 = GeometryMath.ProjectToAlloyCrs(buffered_geometry_BNG,\"+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +towgs84=446.448,-125.157,542.06,0.15,0.247,0.842,-20.489 +units=m +no_defs\"); return buffered_geometry_WGS84;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
}
]
This example works through identifying where a point geometry, in this case of a newly created job, intersects with a polygon. It is used to identify which ward the job has been created within and links the two.
The example programmatically creates an AQS query to be used within a Query node, taking the job’s geometry and inserting it as text into the AQS query at the relevant node.
"parameters": [
{
"attributeCode": "attributes_workflowQueryActionsAqsQuery",
"value": {
"script": "return Aqs(aqs_json);",
"returnOptions": {
"dodiCode": "designs_ward",
"discriminator": "DodiAttributeOptionsAqsWebModel"
},
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
},
"discriminator": "WorkflowComputedItemAttributeWebModel"
},
{
"discriminator": "WorkflowConstantItemAttributeWebModel",
"attribute": {
"attributeCode": "attributes_workflowQueryActionsSingleInstance",
"value": false
}
}
],
"variables": [
{
"name": "geometry",
"value": {
"inputParent": 0,
"itemValue": {
"attributeCode": "attributes_itemsGeometry",
"discriminator": "WorkflowSyntaxArgumentItemValueAttributeWebModel"
},
"discriminator": "WorkflowSyntaxNodeInputWebModel"
}
},
{
"name": "geometry_string",
"value": {
"script": "var geometry_string = Json(geometry).ToString(); return geometry_string;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "aqs_string",
"value": {
"script": "string json = @\"{'type': 'Query','properties': {'attributes': [],'collectionCode': ['Live'],'dodiCode': 'designs_ward'},'children': [{'type': 'GeomIntersects','children': [{'type': 'Attribute','properties': {'attributeCode': 'attributes_itemsGeometry'}},{'type': 'Geometry','properties': {'value':\"+ geometry_string+\"}}]}]}\"; return json.Replace(\"'\",\"\\\"\");",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
},
{
"name": "aqs_json",
"value": {
"script": "var o = JToken.Parse(aqs_string); return o;",
"discriminator": "WorkflowSyntaxNodeScriptWebModel"
}
}
]