Spatial join for serial chart - efficiently using the Contains function

615
4
Jump to solution
02-17-2022 12:33 AM
ChrisH2
New Contributor III

Hi community. I have the data expression below pulling some data from one of my hosted layers with point features, and reformatting it to drive some charts in my Dashboard. So far so good.

What I'm needing to do now is add an attribute to every point/record based on the REGION polygon that it falls within (a good old spatial join)

I think what I need to do is to use the Contains() function and loop through each point in fs, find the polygon in poly_fs that it falls within, grab the value in the NAME field of poly_fs, and append it to the dictionary that I'm building that contains my modified fs table.

Seeking any advice on an efficient way to loop through this given that the geometry function may make this slow to execute anyway.

The only change that I've made to prepare for this new function is adding a new variable in line 13

//ground actions - time of day
//obtains the hour in military (long) format from the creation_date field

// Write an expression that returns a FeatureSet.
// Documentation: https://arcg.is/3c419TD
// Samples: https://arcg.is/38SEWWz



// Create a FeatureSet from the Feature Layer containing the Ground action data.
var fs =FeatureSetByPortalItem(Portal('https://gis.ABCCD.au/portal'), '0116ef7ee89c4de0829fe554315e2177', 0)

var poly_fs =FeatureSetByPortalItem(Portal('https://gis.ABCCD.au/portal'), 'e09bf35374724d04b413bbb09db9ff40', 3)


var outDict = { 
  'fields': [{ 'name': 'hr_num', 'type': 'esriFieldTypeInteger'},
  {'name': 'OBJECTID','type': 'esriFieldTypeInteger'},
  {'name': 'creation_date','type': 'esriFieldTypeDate'},
  {'name': 'militaryhr', 'type': 'esriFieldTypeString'},
  {'name': 'ABC_Organisation','type': 'esriFieldTypeString'},
  {'name': 'Operation_Number','type': 'esriFieldTypeString'},
  {'name': 'species', 'type': 'esriFieldTypeString'}], 
  'geometryType': '', 
  'features': [] 
}; 

var index = 0; 

for (var feature in fs) { 

    outDict.features[index] = { 
        'attributes': { 
            'hr_num': Hour(feature['creation_date']), 
            'objectid': feature['OBJECTID'],
            'creation_date': number(feature['creation_date']),
            'militaryhr': Text(feature['creation_date'], 'HH'),
            'ABC_Organisation': feature['ABC_Organisation'],
            'Operation_Number': feature['Operation_Number'],
            'species': feature['species_common_name'] 
        }} 
    index++;} 

// Convert dictionary to feature set. 
var fs_dict = FeatureSet(Text(outDict)); 

// Return data 
return fs_dict;

 

 

 

0 Kudos
1 Solution

Accepted Solutions
jcarlson
MVP Esteemed Contributor

Try using a real if/else statement, rather than iif.

var int_poly = Intersects(feature, poly_fs)

if (Count(int_poly) > 0){
    var poly_name = First(int_poly)['VEA_NAME']
} else {
    var poly_name = 'None'
}

Any luck?

- Josh Carlson
Kendall County GIS

View solution in original post

0 Kudos
4 Replies
jcarlson
MVP Esteemed Contributor

Since you're working with points (that is, there's no possibility for partial containment), you can just do Intersects. Throw these lines into your for loop:

var xs_poly = First(Intersects(feature, poly_fs))

var poly_name = xs_poly['NAME']

 

Then pipe poly_name into the feature attributes. Oh, and make a field for it in your dictionary, obviously.

- Josh Carlson
Kendall County GIS
0 Kudos
ChrisH2
New Contributor III

thanks @jcarlson that's almost got me over the line. I was chasing an error until I realised that the test polygon dataset that I'm using doesn't always completely cover the point dataset. When I switch over to the real polygon dataset this should be unlikely, but there's still the chance that a user may add a point over the ocean somewhere, so best I counter this in the code!! Thus I've been trying to check for where the Intersects returns a null but without much success

 

What I was trying to do with line 42 was to insert "None" into the table if there wasn't a result from the point in polygon intersection, otherwise use the real value from xs_poly.  Line 43 will work, but when I switch this out and replace it with line 42 still fails everytime time a 0 is encountered

 

//ground action - time of day
//obtains the hour in military (long) format from the creation_date field

// Write an expression that returns a FeatureSet.
// Documentation: https://arcg.is/3c419TD
// Samples: https://arcg.is/38SEWWz



// Create a FeatureSet from the Feature Layer containing the Ground action data.
var fs =FeatureSetByPortalItem(Portal('https://gis.ABCD.au/portal'), '0116ef7ee89c4de0829fe554315e2177', 0)

var poly_fs =FeatureSetByPortalItem(Portal('https://gis.ABCD.au/portal'), 'e09bf35374724d04b413bbb09db9ff40', 3)


var outDict = { 
  'fields': [{ 'name': 'hr_num', 'type': 'esriFieldTypeInteger'},
  {'name': 'OBJECTID','type': 'esriFieldTypeInteger'},
  {'name': 'creation_date','type': 'esriFieldTypeDate'},
  {'name': 'militaryhr', 'type': 'esriFieldTypeString'},
  {'name': 'actioner_Organisation','type': 'esriFieldTypeString'},
  {'name': 'Operation_Number','type': 'esriFieldTypeString'},
  {'name': 'species', 'type': 'esriFieldTypeString'}, 
  {'name': 'pvregion', 'type': 'esriFieldTypeString'}], 
  'geometryType': '', 
  'features': [] 
}; 

var index = 0; 


for (var feature in fs) { 

    var int_poly = Intersects(feature, poly_fs)
	var xs_poly = First(int_poly)
	//var poly_name = xs_poly['VEA_NAME']
	
	var countPolys = Count(int_poly)
	
	Console(countPolys)
	
  //  var poly_name = iif(countPolys>0,'None',xs_poly['VEA_NAME'])
	var poly_name = iif(countPolys>0,'PolygonIntersected','NoPolygonintersection')
	
    Console(poly_name)

    outDict.features[index] = { 
        'attributes': { 
            'hr_num': Hour(feature['creation_date']), 
            'objectid': feature['OBJECTID'],
            'creation_date': number(feature['creation_date']),
            'militaryhr': Text(feature['creation_date'], 'HH'),
            'actioner_Organisation': feature['actioner_Organisation'],
            'Operation_Number': feature['Operation_Number'],
            'species': feature['species_common_name'],
			'pvregion': poly_name
        }} 
    index++;} 

// Convert dictionary to feature set. 
var fs_dict = FeatureSet(Text(outDict)); 

// Return data 
return fs_dict;

 

0 Kudos
jcarlson
MVP Esteemed Contributor

Try using a real if/else statement, rather than iif.

var int_poly = Intersects(feature, poly_fs)

if (Count(int_poly) > 0){
    var poly_name = First(int_poly)['VEA_NAME']
} else {
    var poly_name = 'None'
}

Any luck?

- Josh Carlson
Kendall County GIS
0 Kudos
ChrisH2
New Contributor III

perfect!! Thanks @jcarlson Hope you have a lovely weekend wherever you are!

final code:

//ground action - time of day
//obtains the hour in military (long) format from the creation_date field

// Write an expression that returns a FeatureSet.
// Documentation: https://arcg.is/3c419TD
// Samples: https://arcg.is/38SEWWz



// Create a FeatureSet from the Feature Layer containing the Ground action data.
var fs =FeatureSetByPortalItem(Portal('https://gis.ABCD.au/portal'), '0116ef7ee89c4de0829fe554315e2177', 0)

var poly_fs =FeatureSetByPortalItem(Portal('https://gis.ABCD.au/portal'), 'e09bf35374724d04b413bbb09db9ff40', 3)


var outDict = { 
  'fields': [{ 'name': 'hr_num', 'type': 'esriFieldTypeInteger'},
  {'name': 'OBJECTID','type': 'esriFieldTypeInteger'},
  {'name': 'creation_date','type': 'esriFieldTypeDate'},
  {'name': 'militaryhr', 'type': 'esriFieldTypeString'},
  {'name': 'actioner_Organisation','type': 'esriFieldTypeString'},
  {'name': 'Operation_Number','type': 'esriFieldTypeString'},
  {'name': 'species', 'type': 'esriFieldTypeString'}, 
  {'name': 'pvregion', 'type': 'esriFieldTypeString'}], 
  'geometryType': '', 
  'features': [] 
}; 

var index = 0; 


for (var feature in fs) { 

    var int_poly = Intersects(feature, poly_fs)
	var xs_poly = First(int_poly)
	
	
   // If statement to check if there is a successful point in polygon intersection. 
   // If successful, then relevant values from the VEA_NAME field are appended to the Ground action table. If not, then insert 'None' into the table.

	if (Count(int_poly) > 0){
		var poly_name = First(int_poly)['VEA_NAME']
	} else {
		var poly_name = 'None'
	}

    outDict.features[index] = { 
        'attributes': { 
            'hr_num': Hour(feature['creation_date']), 
            'objectid': feature['OBJECTID'],
            'creation_date': number(feature['creation_date']),
            'militaryhr': Text(feature['creation_date'], 'HH'),
            'actioner_Organisation': feature['actioner_Organisation'],
            'Operation_Number': feature['Operation_Number'],
            'species': feature['species_common_name'],
			'pvregion': poly_name
        }} 
    index++;} 

// Convert dictionary to feature set. 
var fs_dict = FeatureSet(Text(outDict)); 

// Return data 
return fs_dict;

 

0 Kudos