Arcade within() actually queries the feature it is within

1597
16
09-06-2023 01:45 PM
JonathanMcDowell1
Occasional Contributor

I am using the within() function to query an underlying feature class. Then calculating fields based on the values pulled from the within(). If the feature is an odd shape it will return nothing or the wrong value. I am using this syntax, within( querylayer   ,centroid($feature)). Sometimes the centroid is outside of the feature.

In the image below, the within function is using the red point to query the 31E33AD polygon. I need the function to query the 31E33 polygon using the green point. If I remove the centroid function, within() returns nothing. 

Red is the centroid used by the within() function.Red is the centroid used by the within() function.

My suggestion is to create a function that uses a center point within the selected feature. Or fix the centroid function to place the point within the feature.

 

Tags (2)
16 Comments
MikeMillerGIS
JonathanMcDowell1

I am not sure this will work. I am using the values from one feature class to calculate values of another feature class. In this cause, the is a index feature class storing key values for the parcel layer. I use the attribute rule to pull a value from the index feature class. Then using that value calculate fields in the parcel layer.

If I am understanding the linked documentation, it is just performing a check to see if the features are related. 

MikeMillerGIS

It used DE-9IM to determine the spatial relationship.  You can use https://developers.arcgis.com/arcade/function-reference/geometry_functions/#intersects to get all intersecting points and if you need to ensure it is in your polygon, use related to ensure the point is in and not on the boundary.

 

Or maybe Intersect is enough for what you are looking for

MikeMillerGIS
JakeSimms1

@JonathanMcDowell1 is the 31E33 polygon a curved or "moon" shaped feature such as below. When getting geometry of the centroid it is actually outside the feature.

JakeSimms1_1-1694085838213.png

I have run into this issue before and the solution was to create a negative buffer object with the Buffer() function then use that object as the innerGeometry for the Within() function.

Note: I noticed in your first comments you had within( querylayer ,centroid($feature)), this is reversed how you want it. The syntax for within is Within(innerGeometry, outerGeometry). In your case, would the innerGeometry want to be the centroid($feature) and the outerGeometry be the querylayer? within( centroid($feature),querylayer).

JonathanMcDowell1

@JakeSimms1 This is the exact problem I am dealing with. The feature I am working with is a long curving railroad right-of-way. It is 60' wide and 2 miles long. I did try a negative buffer, however it did not move the point close to where it is needed. In this case, the features I am using for the within() are topologically identical. So a within() should work.

Thanks for pointing out the syntax. I will switch the inputs and see what happens.

My next test is to use intersect() with the negative buffer. If I am correct, I want to use the offset() function?

JakeSimms1

@JonathanMcDowell1 You should be able to use the Intersect() to get the field values you need without using Offset().

 

Code might not be what you're looking for but how you would roughly do it.

 

var bufferFeature = Buffer($feature,-10)//of some number
var fcIntersect = Intersects(FeatureSetByName($datastore, ["featureToIntersect"], ["fieldValue1","fieldValue2"], false), bufferFeature)

if (IsEmpty(fcIntersect)){
    return;
}

if (Count(fcIntersect) >= 1) {
    var select = first(fcIntersect)
    
    return {
        "result": { 
            "attributes": {
                "field1": select.fieldValue1,
                "field2": select.fieldValue2
            }
        }
    
    }
}

 

 

JonathanMcDowell1

@JakeSimms1 is exactly what I want to do. However, it throws an error when I try saving it. The error states the expression for line 2 is invalid. It cannot preform the function on an empty geometry.

HNTZK46

Hi @JonathanMcDowell1 ,

I may be wrong but the error thrown is because the "false" in the line 2.

Change the "false" to "true" like this:

var fcIntersect = Intersects(FeatureSetByName($datastore, ["featureToIntersect"], ["fieldValue1","fieldValue2"], true), bufferFeature)

 

JonathanMcDowell1

Esri nees to add an 'inside' parameter to the centroid() function, for example, centroid($feature, 'inside').  This addition has the potential to save developers a lot of time tryting to code around the problem.