Hey Esri community!
I'm hoping someone can help me out with a little problem I'm having. I'm trying to create an attribute rule that only allows certain assets to be created if they're either at the start or end of a line, or not on a line at all.
To do this, I need to check an array of arrays to see if another freshly built array is contained within it. Is this even possible?
If anyone has any suggestions or solutions, I'd be really grateful! Thanks in advance for any help you can give.
This is the code i currently have:
// Define target asset groups and types as touples
var tagt = [
[3, 957], // asset 1
[900, 901], // asset 2
[910, 911], // asset 3
[950, 951], // asset 4
[13, 710] // asset 5
];
// Create touple of feature asset group and type
var fagt = [$feature.assetgroup, $feature.assettype]
// Check if current feature triggers attribute rule
if (Includes(tagt, fagt)){
// Get pipeline features from datastore
var pipelines = FeatureSetByName($datastore, "PipelineLine", ["globalId"], false);
// Get all intersecting pipeline features
var intersectingPipes = Intersects(pipelines, $feature);
// If no line is intersected, allow edit process
if (isEmpty(intersectingPipes)){
return true;
} else {
// Else, iterate over inersecting pipeline features
for (var pipe in intersectingPipes) {
// Get start and endpoint of intersected line feature
var endPoint = Geometry(pipe).paths[-1][-1];
var startPoint = Geometry(pipe).paths[0][0];
// Check if the current feature intersects start or endpoint of line
if (Intersects(endPoint, $feature)) {
// If yes, allow edit process
return true;
} else if (Intersects(startPoint, $feature)) {
// If yes, allow edit process
return true;
}
}
// Else, hinder edit process
return false;
}
} else {
return true;
}
Solved! Go to Solution.
Hi all,
in the end this code managed to do what i want.
// Define target asset groups and types as touples
var tagt = [
[3, 957],
[900, 901],
[910, 911],
[950, 951],
[13, 710]
];
// Create touple of feature asset group and type
var fagt = [$feature.assetgroup, $feature.assettype]
// Function to check if an array is contained in an array of arrays
function arrayIsInArray(arrayToCheck, arrayContainingArrays)
{
for(var i in arrayContainingArrays)
{
var currentArray = arrayContainingArrays[i]
if(Count(currentArray) == Count(arrayToCheck))
{
var allValuesMatch = true;
for(var j in arrayToCheck)
{
if(currentArray[j] != arrayToCheck[j])
{
allValuesMatch = false;
break
}
}
if(allValuesMatch)
{
return true;
}
}
}
return false;
}
// Check if current feature triggers attribute rule
if (arrayIsInArray(fagt, tagt)){
// Get pipeline features from datastore
var pipelines = FeatureSetByName($datastore, "PipelineLine", ["*"], true);
// Get all intersecting pipeline features
var intersectingPipes = Intersects(pipelines, $feature);
// If no line is intersected, allow edit process
if (count(intersects(pipelines, geometry($feature))) == 0){
return true;
} else {
// Else, iterate over intersecting pipeline features
for (var pipe in intersectingPipes) {
// Get start and endpoint of intersected line feature
var endPoint = Geometry(pipe).paths[-1][-1];
var startPoint = Geometry(pipe).paths[0][0];
// Check if the current feature intersects start or endpoint of line
if (Intersects(endPoint, $feature)) {
// If yes, allow edit process
return true;
} else if (Intersects(startPoint, $feature)) {
// If yes, allow edit process
return true;
}
}
// Else, hinder edit process
return false;
}
} else {
return true;
}
Some rather interessting remarks:
-it seems like that the geometry parameter at featuresetbyname hasnt any impact if intersections are possible to detect or not. i tried it with false and with true, both times it worked just fine.
-the only way to actually detect an intersect was with line 50. all other methods with e.g. (if(Intersects(pipelines, $feature))) wouldnt work for whatever reason
PS: has anybody a idea where to console messages actually go to? I cant find any terminal in arcpro which makes debugging a real pain.
To post code:
function ArrayEquals(arr_1, arr_2) {
if(Count(arr_1) != Count(arr_2)) { return false }
arr_1 = Sort(arr_1)
arr_2 = Sort(arr_2)
for(var i in arr_1) {
if(arr_1[i] != arr_2[i]) { return false }
}
return true
}
function IncludesArray(outer, inner) {
for(var i in outer) {
if(ArrayEquals(outer[i], inner)) { return true }
}
return false
}
if (IncludesArray(tagt, fagt)){
//...
It is hard to follow posted as text, but it looks pretty good. The only change I see is that your FSByName is not returning geometry, which is probably why any downstream intersect fails
change:
var pipelines = FeatureSetByName($datastore, "PipelineLine", ["globalId"], false);
to
var pipelines = FeatureSetByName($datastore, "PipelineLine", ["globalId"], true);
Yes, the geometry has to be included in this case.
But Stefan's code didn't even get to that point, because the Includes function doesn't work for inner array:
Thanks for the tip with inserting code @JohannesLindner ! And also thanks for mentioning the Geometry Bug @MikeMillerGIS . Is there any way to check the containment of inner arrays? or do i have to implement this myself?
Greets
Stefan!
Hi all,
in the end this code managed to do what i want.
// Define target asset groups and types as touples
var tagt = [
[3, 957],
[900, 901],
[910, 911],
[950, 951],
[13, 710]
];
// Create touple of feature asset group and type
var fagt = [$feature.assetgroup, $feature.assettype]
// Function to check if an array is contained in an array of arrays
function arrayIsInArray(arrayToCheck, arrayContainingArrays)
{
for(var i in arrayContainingArrays)
{
var currentArray = arrayContainingArrays[i]
if(Count(currentArray) == Count(arrayToCheck))
{
var allValuesMatch = true;
for(var j in arrayToCheck)
{
if(currentArray[j] != arrayToCheck[j])
{
allValuesMatch = false;
break
}
}
if(allValuesMatch)
{
return true;
}
}
}
return false;
}
// Check if current feature triggers attribute rule
if (arrayIsInArray(fagt, tagt)){
// Get pipeline features from datastore
var pipelines = FeatureSetByName($datastore, "PipelineLine", ["*"], true);
// Get all intersecting pipeline features
var intersectingPipes = Intersects(pipelines, $feature);
// If no line is intersected, allow edit process
if (count(intersects(pipelines, geometry($feature))) == 0){
return true;
} else {
// Else, iterate over intersecting pipeline features
for (var pipe in intersectingPipes) {
// Get start and endpoint of intersected line feature
var endPoint = Geometry(pipe).paths[-1][-1];
var startPoint = Geometry(pipe).paths[0][0];
// Check if the current feature intersects start or endpoint of line
if (Intersects(endPoint, $feature)) {
// If yes, allow edit process
return true;
} else if (Intersects(startPoint, $feature)) {
// If yes, allow edit process
return true;
}
}
// Else, hinder edit process
return false;
}
} else {
return true;
}
Some rather interessting remarks:
-it seems like that the geometry parameter at featuresetbyname hasnt any impact if intersections are possible to detect or not. i tried it with false and with true, both times it worked just fine.
-the only way to actually detect an intersect was with line 50. all other methods with e.g. (if(Intersects(pipelines, $feature))) wouldnt work for whatever reason
PS: has anybody a idea where to console messages actually go to? I cant find any terminal in arcpro which makes debugging a real pain.
At 3.1, the FSByName geometry parameter is required to be set correctly, before that, I believe it was ignored or it did not matter for intersect, but it does now.
It is expensive performance wise to call count on a featureset and then loop over it. Best to just loop over it and do nothing if there are no iterations.
This is better
// Get pipeline features from datastore
var pipelines = FeatureSetByName($datastore, "PipelineLine", ["*"], true);
// Get all intersecting pipeline features
var intersectingPipes = Intersects(pipelines, $feature);
var no_intersect = true
// Else, iterate over intersecting pipeline features
for (var pipe in intersectingPipes) {
no_intersect = false
// Get start and endpoint of intersected line feature
var endPoint = Geometry(pipe).paths[-1][-1];
var startPoint = Geometry(pipe).paths[0][0];
// Check if the current feature intersects start or endpoint of line
if (Intersects(endPoint, $feature)) {
// If yes, allow edit process
return true;
} else if (Intersects(startPoint, $feature)) {
// If yes, allow edit process
return true;
}
}
// Else, hinder edit process
return no_intersect;
}