Select to view content in your preferred language

Combining feature layers with different geometry types into one list with working pan and zoom actions.

222
1
06-16-2024 09:31 PM
Labels (1)
Bloomers3166
New Contributor II

Hi,

I'm trying to create a data expression with ArcGIS Enterprise 11.1 and multiple hosted feature layers with different geometry types (multipoint, lines, polygon)

I want to combine these features into one list and the user can click on it and the map element would zoom and pan to these features. 

Sadly, the pan and zoom action does not work. I tried adding the parameter "esriGeometryAny" in line 32 as the geometry type of the combined dictionary but it returned an invalid parameter error.

Pan and zoom only work if I set the parameter as esriGeometry-Multipoint, Polyline or Polygon but it only works for the features with the same geometry as expected.

I can't find any solution in the community. Is this possible? or is returning multiple feature sets with geometry type set to point, line or polygon the workaround (I haven't tested this yet)?

var p = Portal('https:**unspecified**');

var defect_points = FeatureSetByPortalItem(
  p,
  '83ff17cc88c74db397701135399a3234',
  1,
  ['defect_name','asset_category'],
  true
);

var defect_lines = FeatureSetByPortalItem(
  p,
  '83ff17cc88c74db397701135399a3234',
  2,
  ['defect_name','asset_category'],
  true
);

var defect_polygons = FeatureSetByPortalItem(
  p,
  '83ff17cc88c74db397701135399a3234',
  3,
  ['defect_name','asset_category'],
  true
);

var combDict = {
    fields: [
        { 'name': 'NAME', 'type': 'esriFieldTypeString' },
        { 'name': 'asset_category', 'type': 'esriFieldTypeString' },
    ],
    geometryType: "",
    features: [],
};

var index = 0;
for (var feature in defect_points) {
    combDict.features[index++] = {
        'attributes': {
            'NAME':feature['defect_name'],
            'asset_category':feature['asset_category'],
        },
        geometryType: "esriGeometryMultipoint",
        geometry: Geometry(feature),
    }
};

for (var feature in defect_lines) {
    combDict.features[index++] = {
        'attributes': {
            'NAME':feature['defect_name'],
            'asset_category':feature['asset_category'],
        },
        geometryType: "esriGeometryLine",
        geometry: Geometry(feature),    
    }
};

for (var feature in defect_polygons) {
    combDict.features[index++] = {
        'attributes': {
            'NAME':feature['defect_name'],
            'asset_category':feature['asset_category'],
        },
        geometryType: "GeometryPolygon",
        geometry: Geometry(feature),    
    }
};
return FeatureSet(Text(combDict))

 

0 Kudos
1 Reply
Wes_S
by
New Contributor II

This is possible and I have set it up two different ways in the past. One is much slower but more convenient. The other, which I usually use, has a few extra steps, but better performance.

The main idea behind doing this is creating a buffer of all of you features (points, lines, polygons) so that they can all be treated as one polygon feature.

Method 1 (slow but convenient)

This method uses a data expression that creates the buffer on the fly. Like I said, it is convenient but slow due to it running the buffers every time. If you do not have too many features this may be good enough for you.

var portal = Portal("https://arcportal");   //Portal URL
var points = FeatureSetByPortalItem(
    portal,
    "12345678912345678912345678912345",     //Item ID
    0,                                      //Item Sublayer (get it in the URL of your feature layer)
    ["*"],
    true);

var lines = FeatureSetByPortalItem(
    portal,
    "12345678912345678912345678912345",
    1,
    ["*"],
    true);

var polygons = FeatureSetByPortalItem(
    portal,
    "12345678912345678912345678912345",
    2,
    ["*"],
    true);

var features = [];
var feat;

for (var n in points) {
        feat = {
            attributes: {
            Field_Alias_1: n["Field_Name_1"],   //Field alias and name of desired field
            Field_Alias_2: n["Field_Name_2"],   //Another example of above
            },'geometry': Buffer(n,1,'feet')
        }
    Push(features, feat)
    }

for (var l in lines) {
        feat = {
            attributes: {
            Field_Alias_1: s["Field_Name_1"],
            Field_Alias_2: s["Field_Name_2"],
            },'geometry': Buffer(l,1,'feet')
        }
    Push(features, feat)
    }

for (var p in polygons) {
        feat = {
        attributes: {
            Field_Alias_1: s["Field_Name_1"],
            Field_Alias_2: s["Field_Name_2"],
            },'geometry': Buffer(p,1,'feet')
        }  
    Push(features, feat)
    }
    
    
var joinedDict = {
    fields: [
        { name: "Field_Name_1", type: "esriFieldTypeString" },
        { name: "Field_Alias_2", type: "esriFieldTypeString" }
    ],
    'geometryType': "esriGeometryPolygon",
    'features':features
};

return FeatureSet(Text(joinedDict));

 

Method 2 (better performance, extra steps)

This is my preferred method, especially if you would like to use other widgets such as category selectors or indicators or lists on the combined data (utilize the data in a non-spatial manner essentially). This uses a very similar data expression to the above script, the only difference is it does not do the buffers. It requires an additionally buffer feature layer to be created and added to your web map. I am using this currently on a dataset that is edited often, so I have set up a nightly python script that will make a new updated buffer layer. Doing the buffer all at once ahead of time makes the dashboard run so much faster. If your data set is not often updated, you could just create the buffer layer as often as you need to. You will then set your widgets that need to zoom/pan to the buffer layer, and set your other widgets to this data expression.

var portal = Portal("https://arcportal");   //Portal URL
var points = FeatureSetByPortalItem(
    portal,
    "12345678912345678912345678912345",     //Item ID
    0,                                      //Item Sublayer (get it in the URL of your feature layer)
    ["*"],
    true);

var lines = FeatureSetByPortalItem(
    portal,
    "12345678912345678912345678912345",
    1,
    ["*"],
    true);

var polygons = FeatureSetByPortalItem(
    portal,
    "12345678912345678912345678912345",
    2,
    ["*"],
    true);

var features = [];
var feat;

for (var n in points) {
        feat = {
            attributes: {
            Field_Alias_1: n["Field_Name_1"],   //Field alias and name of desired field
            Field_Alias_2: n["Field_Name_2"],   //Another example of above
            },
        }
    Push(features, feat)
    }

for (var l in lines) {
        feat = {
            attributes: {
            Field_Alias_1: s["Field_Name_1"],
            Field_Alias_2: s["Field_Name_2"],
            },
        }
    Push(features, feat)
    }

for (var p in polygons) {
        feat = {
        attributes: {
            Field_Alias_1: s["Field_Name_1"],
            Field_Alias_2: s["Field_Name_2"],
            },
        }  
    Push(features, feat)
    }
    
    
var joinedDict = {
    fields: [
        { name: "Field_Name_1", type: "esriFieldTypeString" },
        { name: "Field_Alias_2", type: "esriFieldTypeString" }
    ],
    'geometryType': "esriGeometryPolygon",
    'features':features
};

return FeatureSet(Text(joinedDict));

 

Feel free to reach out to me if you have questions. If you want to set up a python script, we can talk about that too.

 

Good luck!

0 Kudos