Closed allisonmuise closed 7 years ago
arcgis-portal-app-templates #1103
@allisonmuise,
We are able to reproduce this. However, we are not able to modify the tolerance in quantization parameters while executing the query. We tried to set the tolerance to 0, 1, 5, 10. But this seems to have no effect in the query, the API overwrites the tolerance with the one it generates internally. We tried to supply maxAllowableOffset, but even that is disregarded in the query.
Observation: Using the test app http://arcgis4localgov2.maps.arcgis.com/apps/CrowdsourceReporter/index.html?appid=a1fdf7c56ab94113adc49c75802f5e7a#, I intercepted and modified the query and got the same results every time. The API is generating a tolerance of 78271.51696399994; I tried 78.27151696399994, 78, 10, and removing the quantizationParameters. The numbers for coordinates, scaling, and translation varied with the different tolerances, but the display was the same in every case:
Updated observation: There are two fetches for the map features, and both are affected by bad tolerance values.
With the previous observation, I was only intercepting and adjusting the second query. When the API receives the result, it looks to see if it already has that feature layer and feature loaded; if found, it uses the previously loaded coordinates. So even though the service was returning good coordinates as a result of adjusting the quantizationParameters' tolerance, it didn't matter because the API discarded them. In order to get good results, quantizationParameters has to be right for the first query. With quantization removed for both queries, one gets both the map and highlight versions of the feature correctly:
The quantizationParameters' tolerance is set by the API to correct values, but I'm seeing a problem when the setting is occurring. It appears as if there is a different copy of the feature layer for the two queries, and only one is being updated as the map is zoom or resized. In addition, there may be a timing problem where the map is zoomed as a result of a selection, but the tolerance is based on the pre-zoom resolution.
I don't see a reason for secure vs. nonsecure causing the problem yet, but one of the requirements for the quantization parameter to be used by the API is that the service has the parameter "supportsCoordinatesQuantization" set to true. The 4.0 API has the comment, "Only works with ArcGIS Online hosted services.", which may be a clue for the 3.17 API behavior that the app is seeing, too.
There are three problems of coordination between the app and the JSAPI:
An example to illustrate these:
The two tolerances consistently yield a square and a triangle, respectively, because the graphics are never queried using updated tolerances:
@CTLocalGovTeam : It appears that this is an issue with Reporter. Could you please review Mike's information above?
@MikeTschudi , @allisonmuise
Mike, thanks for your analysis. Just to add more information to the analysis, the app actually works off of a graphic layer. When a map is selected, the featurelayer is initialized, but it is turned off. A separate graphic layer is created and maintained to query and display features from the featurelayer. This is done to support displaying features with increasing proximity (1 mile, 2 miles, so on) around the user's geolocation.
We are investigating this further based on the inputs you provided above.
@CTLocalGovTeam: Thanks. Some background: I put a pair of probes into the FeatureLayer API code (1. where the tolerance is set and 2. where the feature query is made) that tested and reported FeatureLayer instances, and that's how I saw multiple FeatureLayers being created and queried.
@MikeTschudi @allisonmuise
Reporter app has two instances of feature layer,
Copy (“B”) is hidden on the map and it is used to query all the features and to show them on the graphic layer.
We analyzed the issue and found following problems:
To fix this we did following code changes:
The code change required to fix this is very small ~ 3-4 lines.
@CTLocalGovTeam Nicely done to figure out a pinpoint fix!
@MikeTschudi @CTLocalGovTeam : Very nice! Thanks!
Is there any expected impact to performance when pulling in all features without generalization?
@allisonmuise We dont see any change or impact to the performance. The app's performance will remain exactly the same. The features were never generalized prior to this and are fetched on demand (when user clicks load more).
@allisonmuise, @MikeTschudi
We discovered during testing that the approach of setting the maxAllowableOffset to a small value (0.1) is not successful in all scenarios. It works only when the default extent of the webmap is set to a large scale , e.g., between 20k-50k approx. When you set the default extent to a large scale, e.g., >100k - 1million (city/region), we still see that features either are incorrect or do not appear at all.
We can confirm that quantization uses the tolerance from maxAllowableOffset i.e., "0.1" in the queries, we see that geometries are returned for all features, but the result features are not correctly de-quantized for display by the API for reasons we don't know yet.
Another aspect to this issue is that we haven't been able to figure out why this only occurs for secured hosted services with saved credentials. Public hosted services already work correctly without this maxAllowableOffset fix. The API automatically uses a very small quantization tolerance of approx 1.0 for public hosted services and features are rendered correctly, regardless of the default extent of the webmap. We are seeing that the API generates a different set of quantization tolerance parameters depending on whether a service is hosted public or hosted secured with stored creds.
Please suggest if we can have a separate call with Mike to demonstrate our investigation and findings so far.
@CTLocalGovTeam Were you able to rule out a correlation between the feature layer parameter "supportsCoordinatesQuantization" and the different quantization tolerance parameters for the services? In the API source, that parameter seemed to be the main reason for the difference, but I wasn't sure.
Notes from the call this morning: Still can't isolate the issue to just API or just app.
@MikeTschudi is going to build a sample app that reproduces the following issues:
We will approach API team with this info to see what bugs/enh can be logged for a future API release.
As mentioned in the first note of this issue, the "utility.arcgis.com" change is significant. For Crowdsource Reporter, an unshared secured service URL with stored credentials published to http://services.arcgis.com/ works fine; the same unshared secured service URL with stored credentials published to http://utility.arcgis.com/usrsvcs/servers/ fails.
Compared the JSON service description for the services.arcgis.com private service with the utility.arcgis.com private service; they're identical.
The private service failing in Crowdsource Reporter works fine in Basic Viewer, including with searches.
The layer contains 7 jagged-edge polygons drawn at the 1:24,000 scale or larger; with the roughness of the boundary and the large scale, these polygons change radically or disappear with coarse quantization. Each layer also contains 7 triangles that serve as pointers to the small polygons. The polygons are scattered around the Earth.
To test display and query, I created a webpage that loads this webmap; it comes up at 1:150,000,000 or so. While at that small scale, the app uses the operational layer in the webmap to query for all features and add them to the map's graphics layer. When I zoom in to the 1:24,000 level, I see that all polygons are drawn correctly, e.g., here are the two polygons in one location at 1:5,000:
where
To show wide extent of map combined with tiny polygons, here are all of the polygons:
The API's createMap function is the place where two FeatureLayers appear to be created for each operational layer. No FeatureLayers appear to be created by the API's query routines. Interestingly, none of the queries to the servers used quantization.
These details show the same webmap with bad quantization in Crowdsource Reporter and no quantization in the test program:
Zooming in to the detail in New York:
The complete webpage:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!-- based on http://developers.arcgis.com/javascript/sandbox/sandbox.html?sample=map_simple -->
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
<title>Simple Map</title>
<link rel="stylesheet" href="//jsdev.arcgis.com/3.18/dijit/themes/claro/claro.css" />
<link rel="stylesheet" href="//jsdev.arcgis.com/3.18/esri/css/esri.css" />
<style>
html, body, #map {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
</style>
<script type="text/javascript" src="//jsdev.arcgis.com/3.18"></script>
<script>
require([
"dojo/_base/array",
"dojo/Deferred",
"dojo/DeferredList",
"dojo/json",
"esri/arcgis/utils",
"esri/Color",
"esri/graphic",
"esri/dijit/Scalebar",
"esri/symbols/SimpleFillSymbol",
"esri/symbols/SimpleLineSymbol",
"esri/tasks/query",
"esri/tasks/QueryTask",
"dojo/domReady!"
], function (array, Deferred, DeferredList, JSON, arcgisUtils, Color, Graphic, Scalebar,
SimpleFillSymbol, SimpleLineSymbol, Query, QueryTask) {
arcgisUtils.createMap("637ccc9591c6472abb4876ba8b3693a1", "map", {
usePopupManager: false
}).then(function (response) {
var map, opLayers, requestArray = [], deferreds, symbols = [], iSymbol = 0;
map = response.map;
new Scalebar({
map: map,
attachTo: "bottom-center",
scalebarStyle: "line",
scalebarUnit: "dual"
});
opLayers = response.itemInfo.itemData.operationalLayers;
array.forEach(opLayers, function (opLayer) {
requestArray.push(_queryOnLayer(opLayer));
});
symbols.push(new SimpleFillSymbol(SimpleFillSymbol.STYLE_VERTICAL,
new SimpleLineSymbol(SimpleLineSymbol.STYLE_DASH, new Color([0, 0, 255]), 1),
new Color([0, 0, 255])));
deferreds = new DeferredList(requestArray);
deferreds.then(function (deferredsResults) {
array.forEach(deferredsResults, function (deferredResult) {
if (deferredResult[0]) {
console.warn(deferredResult[1].title + " OK with " +
deferredResult[1].queryResults.features.length + " features (" +
symbols[iSymbol].style + " lines)");
array.forEach(deferredResult[1].queryResults.features, function (graphicBase) {
map.graphics.add(new Graphic(graphicBase.geometry, symbols[iSymbol],
graphicBase.attributes));
});
} else {
console.warn(deferredResult[1].title + " failed with " +
JSON.stringify(deferredResult[1].queryResults));
}
});
});
function _queryOnLayer(opLayer) {
var queryTask, deferred, parameters, queryString, dateobj = new Date().getTime().toString();
deferred = new Deferred();
parameters = new Query();
queryString = "1=1 AND " + dateobj + "=" + dateobj;
// add layer definition in query parameters if it is available in layer object
if (opLayer.layerObject.defaultDefinitionExpression) {
queryString += " AND " + opLayer.layerObject.defaultDefinitionExpression;
}
parameters.where = queryString;
parameters.outFields = ["*"];
parameters.returnGeometry = true;
queryTask = new QueryTask(opLayer.url);
queryTask.execute(parameters, function (response) {
deferred.resolve({
title: opLayer.title,
queryResults: response
});
}, function (err) {
deferred.reject({
title: opLayer.title,
queryResults: err
});
});
return deferred;
}
});
});
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>
Update: created webmap with three public layers defined using public, org, and private services. Same program as previous note, but with additional symbols for each operational layer. The layers defined using org and private services have stored credentials.
All layers draw the same, and correctly.
If, instead of calling queryFeatures() on a layer, one calls an instance of QueryTask, this problem goes away in this app for all layer types. But adding queryFeatures() to the test program works. So I think that we have a fix for this particular issue but there's an underlying question that I haven't yet resolved to API and/or app.
@allisonmuise @CTLocalGovTeam, would you please see if these changes work for your examples, too?
@MikeTschudi @allisonmuise We did investigate using QueryTask in place of QueryFeatures(), however this switch will have a larger impact on the code base. After making the switch, we'd have to explicitly handle layer filters applied in webmap, popup definitions, etc. Because of that we didn't pursue this further.
@allisonmuise, the sample app is demonstrating that the JSAPI
There's no bug in or enhancement for the JSAPI at this point; we have to keep investigating the app.
@MikeTschudi Thanks, we'll keep investigating the app further to isolate the root cause. Can you please let us know if the sample app uses queryFeatures or queryTask? Also, is the layer's visibility always turned off, so to be as close as possible to conditions in the App.
@CTLocalGovTeam The sample app tried both queryFeatures and QueryTask, and the layer's visibility was turned off before the queries.
verified
ArcGIS Online 3.10
Data:
Feature Service CharlotteLargeExtent (item URL: http://ess.maps.arcgis.com/home/item.html?id=047185ce5f954c5f84ce6fa030cda764, service URL: http://services.arcgis.com/Wl7Y1m92PbjtJs5n/arcgis/rest/services/charlottelargeextent/FeatureServer/0, shared with ESS organization)
Steps to Reproduce:
1. Add the CharlotteLargeExtent feature service to a new ArcGIS Online webmap. Save the map.
2. Copy the CharlotteLargeExtent service URL. In My Content, add an item from the web, and add this feature service as an ArcGIS Server web service. It will be a secure service. Store your username and password with the item and give it a new name.
3. Add this layer with stored credentials to a new webmap and save the map. In the webmap's details, notice that the service URL now starts with utility.arcgis.com.
4. Create a new group, and share the webmaps and both service layers (secure and unsecure) to this new group.
5. In My Content, create a new Crowdsource Reporter application. In the configuration, set the group created above to be the group used for the application. Save the configuration.
6. Open the application, and you'll see two maps - the one with the secured service and the one without. Select the one with the unsecured service.
7. Click on one of the features with the unsecured service. You should see that the selection polygon is fairly close to the actual polygon.
8. Go back to select the map with the secured service. Click on the same feature. You should now see that the selection polygon does not match the actual polygon.
Testing notes:
It appears this difference is due to the tolerance in the quantization parameter, which can be seen in Fiddler. The unsecured service's tolerance is much lower than a secured service's tolerance.
Strangely enough, the quantization parameter tolerance for the secured service matches the resolution for a scale level in the webmap's basemap. For example, Fiddler showed the secured service's QP tolerance to be 76.43702828507324, which matches the resolution for Level 11 of the World Topo basemap (http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer).
Even when using secured services with other basemaps, the QP tolerance always matched the resolution for one of the levels of the basemap. The unsecured service QP tolerance does not match the basemap resolution.
It appears that a larger initial extent for the feature service creates a larger quantization parameter tolerance.
This cannot be reproduced in the webmap.
This has been reproduced with various spatial references.
Note: Securing a service is listed on the official Crowdsource Reporter documentation: http://solutions.arcgis.com/local-government/help/crowdsource-reporter/get-started/limit_access_to_public_agol_layers/
Salesforce Submitter: Mary Long
Salesforce Submit Date: 2/18/2016 4:51 AM
Salesforce Bug Type: Usability
Salesforce Severity: Medium
Repro Data: (n/a)
Work Around: Workaround 1: Use a service without stored credentials. Workaround 2: When publishing the feature service, use a smaller extent.
Product: ArcGIS Online
Functional Category: ArcGIS Online Application Templates
Client Platform: Windows 7.0 64 Bit
Version Found: 3.10
Planned Version Fixed: (n/a)
Comment: (n/a)