Select to view content in your preferred language

Address Database Management Solution Object Not Found Error for new variables

715
5
09-21-2023 11:00 AM
masslc
by
Emerging Contributor

The schema I use for the ADMS solution is different to the one that comes out of the box, but when I define variables for attribute fields that I would like populated for the attribute rule "Create Site Address Points," they always come back as object not found. 

For example, here are the variables I would like to add under the "Define the Site Address fields" portion of the code:

 

// Define the Site Addresses fields
//existing
var addressptid_field = "addressid";
var addrnum_field = "housenumber";
var roadfullname_field = "fullname";
var status_field = "status";
var defaultstatus = "Pending";
var addrcapturemeth_field = "capturemethod";

//additional
var predir_field ="predir";
var streetname_field ="streetname";
var sufdir_field ="sufdir";
var suftype_field ="suftype";
var unittype_field ="unittype";

 

And here is the original vs updated code I have tried to use to populate these fields 

 

// Create an array of 1 or more new site address point as specified
// Store the related address point id, the calculated address number, the intersecting road name and set the status to Pending
var adds = []
for(var i=0; i<numpoints; i++) {
 Push(adds, {
     'attributes': Dictionary(addressptid_field, id, status_field, defaultstatus, addrnum_field, addrnum, roadfullname_field, intersectingRoad[fullname_field], addrcapturemeth_field, $feature[capturemeth_field]),
    'geometry': newPoint
   })
 addrNum += increment;
}

//updated
// Create an array of 1 or more new site address point as specified
// Store the related address point id, the calculated address number, the intersecting road name and set the status to Pending
// Do we need id in the attributes list?
var adds = []
for(var i=0; i<numpoints; i++) {
 Push(adds, {
     'attributes': Dictionary(addressptid_field, id, status_field, defaultstatus, addrnum_field, addrnum, roadfullname_field, intersectingRoad[fullname_field], addrcapturemeth_field, $feature[capturemeth_field], predir_field, intersectingRoad[predir], streetname_field, intersectingRoad[streetname], sufdir_field, intersectingRoad[sufdir], suftype_field, intersectingRoad[suftype], unittype_field, unittype),
    'geometry': newPoint
   })
 addrNum += increment;
}

 

 Any ideas as to what I am doing wrong here? @ChrisFox 

Thanks!

0 Kudos
5 Replies
TedHoward2
Esri Contributor

Have you defined "unittype" further up in the code? Might help if we can see the whole attribute rule and screen shot of the error.

0 Kudos
masslc
by
Emerging Contributor

So the first thing that gives me the error pertains to variable predir. Here is the original full code:

// This rule will create a new site address point when an address point is created along a road
// The site address point will be offset from the road by the distance and direction defined in the address point feature template

// Define the Address Points fields
var id_field = "addressptid";
var offdist_field = "offdist";
var offdir_field = "offdir";
var numpoints_field = "numpoints";
var incrementval_field = "incrementval";
var capturemeth_field = "capturemeth";

// 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";

// This function will return the new point offset perpendicularly from a 2-point line segment at a specified distance
// Positive distance is to the left of the line. Negative distance is to the right of the line 
function offsetPoint(firstPoint, secondPoint, fromPoint, dist) {
    var x1 = firstPoint.x;
    var y1 = firstPoint.y;
    var x2 = secondPoint.x;
    var y2 = secondPoint.y;
    var x3 = fromPoint.x;
    var y3 = fromPoint.y;

    var a = y1 - y2;
    var b = x2 - x1;

    var norm = Sqrt(a*a + b*b);
    a = a / norm;
    b = b / norm;

    return [x3 + a * dist, y3 + b * dist]
}

// 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;
}

If (!HasKey($feature, id_field)) return;
var id = $feature[id_field];

// Get the geometry of the feature
var geom = Geometry($feature);

// Get the distance and direction defined in the address point feature template/
// If none specified defaults to 0 and Left
var dist = 0;
if ($feature[offdist_field] != null) dist = $feature[offdist_field];
var dir = 'Left';
if ($feature[offdir_field] != null) dir = $feature[offdir_field]; 
if (Lower(dir) == 'right') dist *= -1

// Get the number of site address points and increment value from the address point feature template
// Defaults to 1 and 0 respectively
var numpoints = 1;
if ($feature[numpoints_field] != null) numpoints = $feature[numpoints_field];
var increment = 0;
if ($feature[incrementval_field] != null) increment = $feature[incrementval_field];
   
// If not creating any site addresses return
if (numpoints < 1) return;
   
// Find any intersecting roads with the address point
// 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), geom);
if (Count(intersectingRoads) == 0) {
 intersectingRoads = Intersects(FeatureSetByName($datastore, "RoadCenterline", [fullname_field, fromleft_field, toleft_field, fromright_field, toright_field], true), Buffer(geom, 5));
 if (Count(intersectingRoads) == 0) return { "errorMessage": "Address Point must intersect at least one Road Centerline" }
}
var intersectingRoad = First(intersectingRoads);

// Snap the point to the closest place along the line and find the segment it intersects and the distance along the line
var data = closestPointInfo(geom, Geometry(intersectingRoad));
var closest_point = createPoint(data["coordinates"], Geometry($feature)["spatialReference"])
var results = intersectDistanceAlong(closest_point, intersectingRoad)
var twoPtSegment = results[0];
var distanceAlongLine = results[1];

// Construct a new point geometry offset perpendicularly from the road
var xy = offsetPoint(twoPtSegment.paths[0][0], twoPtSegment.paths[0][1], geom, dist)
var newPoint = Point({ 'x' : xy[0], 'y' : xy[1], 'z' : 0, 'spatialReference' : geom.spatialReference });

// 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);
var addrnum = getAddrNum(intersectingRoad, percentAlong, dir)

// Create an array of 1 or more new site address point as specified
// Store the related address point id, the calculated address number, the intersecting road name and set the status to Pending
var adds = []
for(var i=0; i<numpoints; i++) {
 Push(adds, {
    'attributes': Dictionary(id_field, id, status_field, defaultstatus, 
                             addrnum_field, addrnum, roadfullname_field, intersectingRoad[fullname_field],
                             addrcapturemeth_field, $feature[capturemeth_field]),
    'geometry': newPoint
   })
 addrNum += increment;
}

// Create new site address points
return {
    'edit': [{
        'className': "SiteAddressPoint",
        'adds': adds
    }]
}

At line 18, I'd like to add these variables which reference columns of my attribute table for the Site Address Points:

var predir_field ="predir";
var streetname_field ="streetname";
var sufdir_field ="sufdir";
var suftype_field ="suftype";
var unittype_field ="unittype";

And then update line 229 to have them auto-populated per site point, like this:

// Create an array of 1 or more new site address point as specified
// Store the related address point id, the calculated address number, the intersecting road name and set the status to Pending
var adds = []
for(var i=0; i<numpoints; i++) {
 Push(adds, {
    'attributes': Dictionary(addressptid_field, id, status_field, defaultstatus, addrnum_field, addrnum, roadfullname_field, intersectingRoad[fullname_field], addrcapturemeth_field, $feature[capturemeth_field], predir_field, intersectingRoad[predir], streetname_field, intersectingRoad[streetname], sufdir_field, intersectingRoad[sufdir], suftype_field, intersectingRoad[suftype], unittype_field, unittype),
    'geometry': newPoint
   })
 addrNum += increment;
}

Now I am not getting an error, which originally was: Arcade object not found (predir). However, the fields in the attributes are not populating with the information requested when I create the site address point. 

Thanks for your help!

 

0 Kudos
TedHoward2
Esri Contributor

the last code snippet in your last post (10 lines long) may have variables that have not been defined from what I can tell

TedHoward2_0-1695326366554.png

predir is not a defined variable - just a guess that it should be "intersectingRoad[predir_field]"

TedHoward2_1-1695326429103.png

unittype is not a defined variable - best guess is that is should be "intersectingRoad[unittype_field]":

0 Kudos
masslc
by
Emerging Contributor

Thanks for spotting that, I updated those and got my original error again, attached below. 

masslc_0-1695327841509.png

 

0 Kudos
TedHoward2
Esri Contributor

I think you need to reference how the Dictionary function works in Arcade. The rule builds the attributes payload using this function and you need to provide the field name followed by a value that you want inserted into that field. The value has to come from somewhere.

If intersectingRoad featureset does not have a field named "predir", then I would expect that error. Is it supposed to come from $feature? It's unclear what you are trying to do.

0 Kudos