|
POST
|
Hi @JamesBurton1, yes unfortunately it will only grab the correct left and right if the line is coincident with the boundary. The offset is used to test if a portion of the road is coincident with the boundary but then turns and enters completely within one of the two municipalities. I think the rule could be enhanced to use an offset distance but would likely need some significant changes to make it work and account for all the edge scenarios. I will think about this for a future update.
... View more
10-17-2022
01:54 PM
|
0
|
2
|
2474
|
|
IDEA
|
The Transit Safety and Transit Outreach solutions include layers that model transit lines and stops in ArcGIS. In addition, they also included an ArcGIS Pro project that provides tasks that walk you through importing your transit lines and stops from GTFS.
... View more
10-05-2022
06:08 AM
|
0
|
0
|
1371
|
|
POST
|
@JamesBurton1, When you deploy a new version of a solution we will never modify or delete items from a previous deployment. In some cases we may reuse items, such as a shared service in a new web map delivered with the update, but we will only create new items. This is to ensure your existing deployment will be unaffected. In the case of Citizen Problem Reporter v2.0 we updated everything and are deploying a complete new feature service so you will get a new folder in your content with all new items. There will be no shared items between v1.0 and v2.0 and v1.0 will be unaffected while you evaluate v2.0.
... View more
08-30-2022
02:21 PM
|
2
|
3
|
1527
|
|
POST
|
We are not releasing a 3.x version of the Solution Deployment Tool add-in for ArcGIS Pro. As @ChristopherCounsell described we started delivering the new ArcGIS Solutions app with Enterprise starting at 10.9. In addition. at Enterprise 11.0 the ArcGIS Solutions app will be available with the base install of ArcGIS Enterprise. This will be the recommended way to deploy solutions in Enterprise moving forward. For previous version of Enterprise (10.5 - 10.8.1) you will need ArcGIS Pro 2.x and the ArcGIS Solutions Deployment Tool add-in.
... View more
07-20-2022
08:53 AM
|
1
|
9
|
5239
|
|
POST
|
Hi @MatthewWoodhamCOD, I am the product owner for the Capital Project solutions and unfortunately the current design of the solution does not make it easy to add new project types. Maybe if you could describe which components of the solution(s) you want to use we could figure out the easiest way to do it. I know that if you are leveraging everything nearly every information product would need to be updated. We have an update to these solutions planned in our roadmap (see below) and we will consider the ability to add/modify project types in the update to make this easier. https://www.esri.com/arcgis-blog/products/arcgis-solutions/announcements/arcgis-solutions-2022-product-roadmap/
... View more
06-15-2022
01:43 PM
|
0
|
0
|
1797
|
|
POST
|
Hi @FrancescaColich, we document the Capital Project Planning and Tracking solutions and specifically a walkthrough of how to use them here: https://docdev.arcgis.com/en/arcgis-solutions/latest/reference/use-capital-project-planning.htm https://docdev.arcgis.com/en/arcgis-solutions/latest/reference/use-capital-project-tracking.htm The order they are deployed doesn't matter, they will share the same underlying services and work together if you deploy both. We don't document had to add new project types, it is pretty complex and involves a lot of changes in many of the items. My recommendation would be to see if you could use an existing project type such as Water. The project status options are driven by a list configured on the field in the layer. You can edit this list using the steps described in the topic below: https://doc.arcgis.com/en/arcgis-online/manage-data/define-attribute-lists-and-ranges.htm
... View more
06-14-2022
01:32 PM
|
0
|
3
|
1936
|
|
POST
|
@RachaelMurtaugh, yes it will. Maintenance history is written to a related table on the planting space/tree. You can view the history using the Tree Management Center included in the solution by selecting a planting space/tree and viewing the maintenance history table.
... View more
06-10-2022
12:26 PM
|
0
|
0
|
1610
|
|
POST
|
Hi @ChrisMartinez, Yes, that is exactly how I would approach it. I tried this out and was able to update the rule below to handle this exact scenario. I added a new field called startnum to the AddressLine feature class and exposed it in the editing template for the layer. Then using the updated code below it behaved exactly as you described, if you leave it blank it will use the original logic, otherwise it will use the number you specify for the 1st address point and then increment by the value you specify after that. // This rule will create one or more site addresses at each vertex along a line
// The first vertex must intersect a road and is used to determine the initial address of the first site address point (2nd vertex). The 2nd vertex is also used to determine the side of the road the addresses fall on. Each additional vertex in the line will create a site address point and the address number will increment by the value passed in the feature template.
// A new address point will also be added for each new site address point located at the closest point to the site address along the road
// Define the Address Line fields
var incrementval_field = "incrementval";
var linecapturemeth_field = "capturemeth";
var linepointtype_field = "pointtype";
var startnum_field = "startnum";
// Define the Site Addresses fields
var addressptid_field = "addressptid";
var addrnum_field = "addrnum";
var roadfullname_field = "fullname";
var status_field = "status";
var defaultstatus = "Pending";
var addrcapturemeth_field = "capturemeth";
// Define the Road Centerline fields
var fromleft_field = "fromleft";
var fromright_field = "fromright";
var toleft_field = "toleft";
var toright_field = "toright";
var fullname_field = "fullname";
// Define the Address Points field names and defaults
var id_field = "addressptid";
var pointtype_field = "pointtype";
var capturemeth_field = "capturemeth";
var offdist_field = "offdist";
var offdir_field = "offdir";
var numpoints_field = "numpoints";
// This function will Get a new id for the address point
function getAddressPointID() {
// Define the name of the database sequence and the format for the id
// Text on either side of the ${ ... } will be added to the id
var sequence_name = "AddressPointID";
var id = NextSequenceValue(sequence_name);
return `ADD-${id}`;
}
// This function will find the closest point on line_feature from point_feature
function closestPointInfo(point_feature, line_feature) {
var vertices = line_feature["paths"]
var x = point_feature["x"];
var y = point_feature["y"];
// Loop through each part of the geometry and each segment, tracking the shortest distance
var shortest = [1e10];
for (var i in vertices) {
var part = vertices[i];
var previous = part[0];
for (var j = 1; j < Count(part); j++) {
var current = part[j];
var result = pDistance(x, y, previous["x"], previous["y"], current["x"], current["y"]);
if (result[0] < shortest[0]) shortest = result
previous = current;
}
}
// Couldn't find anything
if (Count(shortest) == 1) return null
return {"distance": shortest[0],
"coordinates": shortest[1],
"isVertex": shortest[2],
"lineSide": shortest[3]}
}
// This function will get distance between 2 points
function pDistance(x, y, x1, y1, x2, y2) {
var A = x - x1;
var B = y - y1;
var C = x2 - x1;
var D = y2 - y1;
var dot = A * C + B * D;
var len_sq = C * C + D * D;
var param = -1;
if (len_sq != 0) //in case of 0 length line
param = dot / len_sq;
var xx, yy;
var is_vertex = true;
if (param < 0) {
xx = x1;
yy = y1;
}
else if (param > 1) {
xx = x2;
yy = y2;
}
else {
is_vertex = false;
xx = x1 + param * C;
yy = y1 + param * D;
}
var dx = x - xx;
var dy = y - yy;
return [Sqrt(dx * dx + dy * dy), [xx, yy], is_vertex, sideOfLine(x,y,x1,y1,x2,y2)];
}
// This function will get side of line segment that a point (x, y) is on based on the direction of segment [[x1, y1], [x2, y2]]
function sideOfLine(x, y, x1, y1, x2, y2) {
var d = (x - x1) * (y2 - y1) - (y - y1) * (x2 - x1)
if (d < 0) {
return 'Left'
} else if (d > 0) {
return 'Right'
} else {
return null
}
}
// This function will create point geometry from coordinates [x, y]
function createPoint(coordinates, spatial_ref) {
return Point({"x": coordinates[0], "y": coordinates[1], "z" : 0, "spatialReference": spatial_ref})
}
// This function will return the segment intersected and the distance along the line
function intersectDistanceAlong(sourceGeometry, interestedLine){
var distanceAlongLine = 0;
// Loop through the segments of the line. Handle multipart geometries
for (var part in Geometry(interestedLine).paths) {
var segment = Geometry(interestedLine).paths[part];
// Loop through the points in the segment
for (var i in segment) {
if (i == 0) continue;
// Construct a 2-point line segment from the current and previous point
var firstPoint = segment[i-1];
var secondPoint = segment[i]
var twoPointLine = Polyline({ 'paths' : [[[firstPoint.x, firstPoint.y], [secondPoint.x, secondPoint.y]]], 'spatialReference' : firstPoint.spatialReference});
// Test if the point intersects the 2-point line segment
if (Intersects(sourceGeometry, twoPointLine)) {
// Construct a 2-point line segment using the previous point and the address point
var lastSegment = Polyline({ 'paths' : [[[firstPoint.x, firstPoint.y], [sourceGeometry.x, sourceGeometry.y]]], 'spatialReference' : firstPoint.spatialReference});
// Add to the total distance along the line and break the loop
distanceAlongLine += Length(lastSegment);
return [twoPointLine, distanceAlongLine]
}
// Add to the toal distance along the line
distanceAlongLine += Length(twoPointLine);
}
}
return null;
}
// This function will return the address number of the new site address point
// It determines this based on the from and to address range on the intersecting road and the direction of the offset
function getAddrNum(road, percentAlong, dir) {
var addrNum = null;
var from = road[fromleft_field];
var to = road[toleft_field];
if (Lower(dir) == 'right') {
var from = road[fromright_field];
var to = road[toright_field];
}
if (from == null || to == null) return null;
var val = percentAlong * (to - from);
var addrNum = 0;
if ((Floor(val) % 2) == 0) addrNum = Floor(val);
else if ((Ceil(val) % 2) == 0) addrNum = Ceil(val);
else addrNum = Floor(val) - 1;
return from + addrNum;
}
// Get the increment value from the construct site address points feature template
// Defaults to 2
var increment = 2;
If (!HasKey($feature, incrementval_field)) return;
if ($feature[incrementval_field] != null) increment = $feature[incrementval_field]
// Get the starting number
var addrnum = $feature[startnum_field];
// Get the global id and geometry of the line
var globalid = $feature.globalid;
var geom = Geometry($feature);
var capturemeth = $feature[linecapturemeth_field];
var pointtype = $feature[linepointtype_field];
// Get the vertices of the feature
var vertices = []
var firstPoint = null;
var vertices = []
for (var part in geom.paths) {
var segment = geom.paths[part];
// Loop through the points in the segment
for (var i in segment) {
if (IsEmpty(firstPoint)) {
firstPoint = segment[i];
continue;
}
Push(vertices, segment[i]);
}
}
if (Count(vertices) < 1) return { "errorMessage" : "Line must have at least 2 vertices" }
// Find any intersecting roads with the first vertex
// If no roads intersect, buffer the point to handle cases where point isn't exactly snapped to line and try again
// If no roads intersect the the buffer return an error message and prevent the address point from being created
var intersectingRoads = Intersects(FeatureSetByName($datastore, "RoadCenterline", [fullname_field, fromleft_field, toleft_field, fromright_field, toright_field], true), firstPoint);
if (Count(intersectingRoads) == 0) {
intersectingRoads = Intersects(FeatureSetByName($datastore, "RoadCenterline", [fullname_field, fromleft_field, toleft_field, fromright_field, toright_field], true), Buffer(firstPoint, 5));
if (Count(intersectingRoads) == 0) return { "errorMessage": "First vertex must intersect at least one Road Centerline" }
}
var intersectingRoad = First(intersectingRoads);
// Get the offset direction based on the second vertex in the line
var data = closestPointInfo(vertices[0], Geometry(intersectingRoad));
var dir = data["lineSide"]
// Snap the first vertex to the closest place along the line and find the distance along the line it intersects
var data = closestPointInfo(firstPoint, Geometry(intersectingRoad));
var closest_point = createPoint(data["coordinates"], Geometry($feature)["spatialReference"])
var results = intersectDistanceAlong(closest_point, intersectingRoad)
var distanceAlongLine = results[1];
// Get the new address number of the site address point based on the distance along the road and direction of the offset
var percentAlong = distanceAlongLine / Length(intersectingRoad);
// If no starting address number was specified, find it based on the distance along the road
if (IsEmpty(addrnum)) {
addrnum = getAddrNum(intersectingRoad, percentAlong, dir)
}
// Loop through each vertext and find the closest point along the road
// Store a new site address and related address point for each vertex in the line
// Increment the address number by the value passed in the feature template
var addressPointAdds = []
var siteAddressAdds = []
for(var i in vertices) {
if (i == 0) {
data["lineSide"] = dir
data["distance"] = Sqrt(Pow(closest_point["x"] - vertices[i]["x"], 2) + Pow(closest_point["y"] - vertices[i]["y"], 2))
}
else {
var data = closestPointInfo(vertices[i], Geometry(intersectingRoad))
var closest_point = createPoint(data["coordinates"], Geometry($feature)["spatialReference"])
}
// Get a new id for the Address Point
var addressptid = getAddressPointID();
// Add a new Address Point
Push(addressPointAdds, {
'attributes': Dictionary(
id_field, addressptid,
numpoints_field, 0,
capturemeth_field, capturemeth,
pointtype_field, pointtype,
offdir_field, data["lineSide"],
offdist_field, data["distance"]
),
'geometry': closest_point
})
// Add a new Site Address
Push(siteAddressAdds, {
'attributes': Dictionary(addressptid_field, addressptid, status_field, defaultstatus,
addrnum_field, addrnum, roadfullname_field, intersectingRoad[fullname_field],
addrcapturemeth_field, capturemeth),
'geometry': vertices[i]
})
data = null;
addrNum += increment;
}
// Using the edit parameter create 1 or more new site addresses and related address points
// Delete the line used to sketch the site addresses
return {
'edit': [{
'className': 'SiteAddressPoint',
'adds': siteAddressAdds
},{
'className': 'AddressPoint',
'adds': addressPointAdds
},{
'className': 'AddressLine',
'deletes': [{
'globalID': globalid
}]
}]
}
... View more
05-18-2022
08:33 AM
|
1
|
4
|
2858
|
|
POST
|
Hi @ChrisMartinez, The methods for constructing new Site Addresses don't consider the address numbers of other Site Addresses when placing new addresses. The logic uses the address range of the road and the distance along the road where the address point is placed to determine the address number. So if the road has a range of 101 to 199 and the address is placed around half way it will get an address number of 149. Additionally, with the Address Line Method, you have the ability to specify the value addresses should increment by, so if you specify 4, the first site address point will get an address number using the logic above and every site address point you place after that will increment by 4. Based on what you describe It sounds like the address range of the road may not accurately reflect the correct address numbers along the road. Some communities calculate the address range of the road based on the length of the road and a defined distance between address numbers. We include a disabled rule on the Road Centerlines called Logical Block Addressing. In this rule you can define the interval or distance between unique addresses and when the rule is enabled when you define the left from and right from address number on a road it will automatically calculate the correct left to and right to values based on this interval and the length of the road. You just need to customize the addressIntervalDistance shown below to meet your community's requirements. // This rule will calculate the left to and right to address number using the left from and right from address numbers, the length of the road and an interval or distance between unique addresses
// This rule is disabled by default. It can be configured by updating the addressIntervalDistance and unit variables below. Enable the rule when you are ready for it to run as the road left and right from values are updated.
// Specify the interval or distance between unique addresses
var addressIntervalDistance = 50;
// Specify the unity of measure. Valid options are feet, meters, yards, miles, kilometers
var unit = "feet";
... View more
05-13-2022
07:00 AM
|
0
|
0
|
2880
|
|
POST
|
@RobynSnookCCB, the solution is configured with custom filter expression on the layer in the view. This kind of expression can't be configured through the UI. The easiest way to replicate it would be use a tool like ArcGIS Assistant to edit the web map and update the "definitionExpression" of the layer to be something like below. In the example below endtime is the name of a date field in the service. endtime IS NULL OR endtime >= CURRENT_TIMESTAMP
... View more
03-30-2022
02:09 PM
|
1
|
0
|
1162
|
|
IDEA
|
Great suggestion, we will look into this for a future release.
... View more
03-23-2022
06:14 AM
|
0
|
0
|
1909
|
|
POST
|
The Swap Parity tool like other gp tools honors the selection set on a layer. If you have multiple layers in the map with the same name you are likely selecting the layer with no selection and as a result is running for all roads in the layer. The easiest fix would be to give them unique names. Alternatively, you can drag/drop the layer from the Contents pane into the parameter of the gp tool, this will ensure you are selecting the correct layer from the map.
... View more
03-22-2022
11:07 AM
|
0
|
0
|
1025
|
|
POST
|
@CochranBob, we were able to find the issue. It appears that the logic for Cut changed at 2.9 and rather than returning an empty array when the feature was not cut, it is returning 1 feature, the original geometry. So it is a fairly easy fix, on line 61 rather than checking if their are 0 features in the array, check if there are less than 2 features. See the screenshot below.
... View more
02-10-2022
11:58 AM
|
3
|
8
|
4216
|
|
POST
|
@CochranBob, I was able to reproduce this issue started with 2.9. It seems to occur if the road you sketch overlaps a road or touches more than one road. If it just touches one road the rule runs succesfully. We are looking into this now and will respond back with our findings and potential fixes to the rule.
... View more
02-10-2022
07:43 AM
|
0
|
9
|
4224
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 03-05-2026 06:12 AM | |
| 1 | 02-06-2026 09:24 AM | |
| 1 | 11-07-2025 07:59 AM | |
| 1 | 11-06-2025 07:04 AM | |
| 1 | 08-28-2025 08:25 AM |
| Online Status |
Offline
|
| Date Last Visited |
03-17-2026
01:31 PM
|