POST
|
A bug was logged for this back in 2021: BUG-000146399. In February of this year the bug was closed and the status was updated to "Known Limitation." "This is related to a known limitation with the software that lies outside of Esri's control. " I don't know for sure, but I suspect what is happening is that there isn't a warning/error process to alert you if individual vector tiles get too big, so some attributes just get dropped to keep the .pbf tiles small enough. IMHO, I think Esri sees vector tiles more as basemaps and less for serving feature data. The "Esri way" is to use feature layer views and renderers. So changing this isn't a top priority. I've read that Geoanalytics Engine can be used to create the vector tiles (analogous to Tippecanoe, see below) but I haven't personally used it: https://developers.arcgis.com/geoanalytics/data/data-sources/vector-tiles/ It includes more controls than AGOL and produces a vector tile package that can be uploaded to AGOL, so if you have a Geoanalytics Engine license this may be the easiest option. I've successfully used 2 work different arounds, though both take a bit of effort. The first was to build the tiles myself using Mapbox's Tippecanoe command line software. This gives you granular control over tile creation so you can, for example, include certain attributes at different scales and/or use simplified geometries at some scales. This can reduce the file size of individual .pbf tiles (and will throw a warning if you exceed the max tile size & features get dropped). Then, you can write a Node.js vector tile server to server up those tiles. This takes some patience, but there's some good resources out there to help with this: https://community.esri.com/t5/arcgis-javascript-maps-sdk-questions/is-it-possible-to-render-mapbox-vector-tiles-pbf/m-p/291888#M26788 https://support.woolpert.io/hc/en-us/articles/360047005294 https://www.danieltrone.com/post/aws-vector-tiles-cloudfront/ The other approach I've used is to publish my data as vector tiles to AGOL, but with only a single attribute that serves as a feature unique ID. Then separately, upload all of the other attributes to a csv file. On the initial app load, the CSV gets downloaded and parsed into a JS object. Then use a function to find all of the Unique IDs for each class of a given symbology. So, for example, if I have polygons of forest type I write a function to go through the CSV file and find all the Unique IDs for "Oak-Confier" and add these IDs to an array. So you end up with arrays of IDs for each symbology class. You can then use a Mapbox expression to style the vector tiles based on those arrays of IDs. Finally, I've also read of folks serving vector tiles directly from S3 (e.g. https://gis.stackexchange.com/questions/304483/is-it-possible-to-serve-vector-tiles-directly-from-s3), but I haven't done this personally. Good luck -- it's a frustrating limitation, but the process of going through these workarounds definitely deepened my understanding of vector tiles, so that's a silver lining.
... View more
10-03-2023
05:14 AM
|
0
|
1
|
272
|
IDEA
|
I am likewise following this with interest. Specifically, I would like to be able to bring in and work with COGs in an ArcGIS JS API map. So far as I have been able to tell, this is not currently possible. Are there plans to implement this functionality? Thanks, Erik
... View more
10-26-2022
07:23 AM
|
0
|
0
|
3115
|
POST
|
I concur - the geometry is building fine, but attributes are not being attached when selected and the cache is rebuilt. I did find that if I symbolize the layer in ArcGIS Pro before sharing as vector tiles, then the resulting tiles will have an automatically-generated "_symbol" attribute populated with integer values that correspond to each of the symbol classes in my data. And the tiles draw up with the correct colors based on the styling in ArcGIS Pro. In JavaScript, I am successfully able to use this "_symbol" attribute as a property to style my fill-color. The actual attribute, however, is not accessible nor are any of the other attributes I selected to pass into the vector tiles.
... View more
12-20-2021
03:28 PM
|
0
|
0
|
424
|
POST
|
Thanks for the update. I just finished running a test on another vector tile service that I created a couple months ago. It is still working properly, passing the requested attributes into the vector tiles, to support client-side data-driven styling. I just used the exact same .aprx project and re-published it as a new vector tile service with a new name (without deleting the old one). After publishing, I went into AGOL and selected the attributes to include in the tile cache and rebuilt the cache. However, the attributes are not being passed through into the tiles on the new service. The original tile service is still working as expected. This makes me wonder if there was a change on the back end that has broken this functionality. Coincidently, I noticed that the checkboxes on the dialog to select attributes are not behaving normally. If you check in the actual box, it will not select. If you click on the attribute name, however, it does select. This behavior happens in both Chrome and Firefox and makes me wonder if it is an AGOL front-end problem. Or, maybe just coincidence.
... View more
12-20-2021
01:55 PM
|
1
|
1
|
425
|
POST
|
Have you had any success figuring this out? I have a vector tile service that I had previously published, enabled attributes, and rebuilt the cache. I had been successfully using this in a web app for data-driven attributes. I recently updated the vector tile, rebuilt the cache, abut now the attributes are not included in the vector tile service. I have tried overwriting the old service, publishing a new service with a different name, creating a new .aprx project and publishing from that, all to no avail. My data is not particularly large (continental US, 11k records), and I had previously published and enabled attributes with success. -Erik
... View more
12-20-2021
01:12 PM
|
0
|
3
|
853
|
POST
|
Thank you, Undral, for the reply. Those were good suggestions but, after wracking my brain for hours staring at the JS, it turns out my issue was in the vector tile generation -- needed to go back, select the attributes I wanted to include in the tiles and rebuild the cache. Thanks again for the help!
... View more
10-04-2021
01:37 PM
|
0
|
0
|
644
|
POST
|
I am trying to apply attribute-driven client-side styling to a custom vector tile layer (published to ArcGIS Online from Pro) in the ArcGIS JavaScript API v 4.20 . Specifically, I would like to use color stops to style polygon fill-color based on an attribute. I have been able to use setPaintProperties to change the default color of the layer (code below). However, I have not been able to set the "property" to an attribute, as described in the Mapbox style layer documentation that is linked from the setPaintProperties documentation. I have successfully used this approach with Mapbox GL using vector tiles, but am unsure if it is possible in the JS API v4.20. This is the code I'm trying to get to work. When executed, it applies the red default color. styleMap(){
const paintProperties = vtLayer.getPaintProperties("myLayer");
var fill ={
property: "myAttribute",
default: 'red',
stops: [
[0 , '#a1a1a1'],
[10000, '#ccece6'],
[200000, '#99d8c9'],
[500000, '#66c2a4'],
[1000000, '#2ca25f'],
[15000000, '#006d2c'],
]
}
paintProperties["fill-color"] =fill;
vtLayer.setPaintProperties("myLayer", paintProperties);
} Is this supported and/or are there plans for it to be supported in future versions? Thanks, Erik
... View more
09-21-2021
06:45 AM
|
0
|
3
|
710
|
POST
|
The Dojo Dialog has worked well by building up the HTML string in javascript -- including HTML tags as part of the string -- then passing it to the Dialog as the content variable.
... View more
09-30-2014
05:15 AM
|
0
|
0
|
287
|
POST
|
I am trying to take the text results of a geoprocessing service and display them in a popup in a javascript map. I am able to do this successfully using a Dojo Dialog, but I'm wondering if there are options with more formatting control of the text -- more akin to an Esri Popup with formatted text, links, images, etc. -- but associated with a submitJob result, not an Identify/Query event. Is the Dojo Dialog my best bet? Possible with an Esri Popup? JQuery? Other options? Thanks Erik
... View more
09-24-2014
02:19 PM
|
0
|
1
|
753
|
POST
|
In the end, adding a pause fixed this issue. Based on the documentation (as bolded above) this shouldn't be necessary, but it fixed the problem.
protected function gp_jobCompleteHandler(event:GeoprocessorEvent):void
{
gpResEvent = event;
if (event.jobInfo.jobStatus == JobInfo.STATUS_SUCCEEDED)
{
statusArea.appendText("Retrieving results from server..." + "\n");
scenarioIterator += 1
//wait a bit before adding the result so map service has time to start
trace("starting delay...")
var Timer:uint = setTimeout(delay, 1000);
function delay():void {
resMapServ = gp.getResultMapServiceLayer(gp.submitJobLastResult.jobId)
resMapServ.name = "Scenario" + String(scenarioIterator)
trace("delayed!");
clearInterval(Timer); //stops the function from being called again
if (resMapServ){trace("successfully added")}
else{trace("did not add")}
if (resMapServ.loaded)
{
map.addLayer(resMapServ)
}
else //this is the workaround to resubmit parameters if map doesn't load
{
resMapServ.addEventListener(LayerEvent.LOAD, resMapServ_loadHandler, false, 0, true);
resMapServ.addEventListener(LayerEvent.LOAD_ERROR, resMapServ_loadErrorHandler, false, 0, true);
function resMapServ_loadHandler(event:LayerEvent):void
{
resMapServ.removeEventListener(LayerEvent.LOAD, resMapServ_loadHandler);
resMapServ.removeEventListener(LayerEvent.LOAD_ERROR, resMapServ_loadErrorHandler);
map.addLayer(resMapServ)
}
function resMapServ_loadErrorHandler(event:LayerEvent):void
{
Alert.show("There was a problem loading the result. \n JOBID " + gp.submitJobLastResult.jobId + "\n The analysis is being re-run. \n Sorry for the inconvenience.\n" +event.fault.message)
gp.submitJob(requestObject);
}
}
}
}
else
{
var messages1:Array = event.jobInfo.messages;
var count1:int = messages1.length;
var index1:int = count1-4;
var message1:String = messages1[index1].description;
Alert.show("Geoprocessing Error:\n" + message1);
}
}
... View more
05-29-2014
12:23 PM
|
0
|
0
|
216
|
POST
|
I have an asynchronous geoprocessing service which returns a raster result via a map service. The GP service is fully functional -- I can run it via the REST endpoint or inside ArcMap with no problems. I developed a custom widget which sits inside the Flex Viewer (3.6) to allow user to pass the input parameters to the GP service and handle the result. This setup is working for me most of the time. I've run the GP service several times in a row with no problems -- the result is returned, displayed properly & all is well. Other times, the result is not returned and I get a this error: "faultCode:400 faultString:'Invalid or missing input parameters.' faultDetail:''". To be clear, this is a geoprocessing result map service. I can see that the GP service completed successfully -- the event.jobInfo.jobStatus == JobInfo.STATUS_SUCCEEDED. But the map service that is supposed to be created isn't always created. As a workaround, I've gone through various iterations of trying to reload the map service and finally made an error handler that fires if the map service does not load. It resubmits the GP Service requestObject and runs the whole thing again. Sometimes it will work on the 2nd go round, other times it takes a a couple tries. I've tried inserting a 1 second pause (after STATUS_SUCCEEDED) before trying to load the map, but to no avail. (This should also not be necessary since "getResultMapServiceLayer(jobId:String):ArcGISDynamicMapServiceLayer Creates and configures an ArcGISDynamicMapServiceLayer instance ready to be added to a Map." I've pasted in the relevant code below. Any thoughts or guidance would be much appreciated. -Erik //fires when geoprocessor finishes. retrives result data protected function gp_jobCompleteHandler(event:GeoprocessorEvent):void { if (event.jobInfo.jobStatus == JobInfo.STATUS_SUCCEEDED) { statusArea.appendText("Retrieving results from server..." + "\n"); scenarioIterator += 1 resMapServ = gp.getResultMapServiceLayer(gp.submitJobLastResult.jobId) resMapServ.name = "Scenario" + String(scenarioIterator) if (resMapServ.loaded) { map.addLayer(resMapServ) } else { resMapServ.addEventListener(LayerEvent.LOAD, resMapServ_loadHandler, false, 0, true); resMapServ.addEventListener(LayerEvent.LOAD_ERROR, resMapServ_loadErrorHandler, false, 0, true); function resMapServ_loadHandler(event:LayerEvent):void { resMapServ.removeEventListener(LayerEvent.LOAD, resMapServ_loadHandler); resMapServ.removeEventListener(LayerEvent.LOAD_ERROR, resMapServ_loadErrorHandler); map.addLayer(resMapServ) } function resMapServ_loadErrorHandler(event:LayerEvent):void { Alert.show("There was a problem loading the result. \n The analysis is being re-run. \n Sorry for the inconvenience.\n" +event.fault.message) gp.submitJob(requestObject); } } } else { var messages1:Array = event.jobInfo.messages; var count1:int = messages1.length; var index1:int = count1-4; var message1:String = messages1[index1].description; Alert.show("Geoprocessing Error:\n" + message1); } }
... View more
05-22-2014
11:58 AM
|
0
|
1
|
1950
|
POST
|
Sorry for the long delayed response-- thanks for the reminder jaydubbbbb. Here's the script, and attached is a toolbox with a tool w/ parameters all set up to work with it. It uses the geometric network tools, so Arc 10.1 or greater is needed. There's some basic metadata in the tool description. Each line segment is looped through, so it takes a little while to run. My dataset with ~400,000 records took between a day and a day and a half to run. -Erik
import arcpy
Workspace = "in_memory"
arcpy.env.overwriteOutput = True
arcpy.env.workspace = Workspace
#variables
network = arcpy.GetParameterAsText(0)
netHydroFC_path = arcpy.GetParameterAsText(1)
nonNetHydroFC = arcpy.GetParameterAsText(2)
accumSourceField = arcpy.GetParameterAsText(3)
accumTargetField = arcpy.GetParameterAsText(4)
calculateMe = arcpy.GetParameterAsText(5)
#get the text name of the network FC without the full path by taking what's after the last "\"
netHydroFC = netHydroFC_path.split("\\")[-1].strip()
#list fields to include in cursor
fields = ("OBJECTID", accumSourceField, accumTargetField)
arcpy.AddMessage("Running...")
#open arcpy.da cursor
with arcpy.da.UpdateCursor(nonNetHydroFC, fields) as rows:
for row in rows:
#get values for each row
rowObjID = row[0]
rowCtchVal = float(row[1])
DAval = float(row[2])
#If there's already an accumulated value skip that record
if DAval <> int(calculateMe):
arcpy.AddMessage("ObjectID " + str(rowObjID) + " is already calculated")
#If the value is equal to the "calculate me" flag run the operation
if DAval == int(calculateMe):
arcpy.AddMessage("Calculating ObjectID # " + str(rowObjID))
#make a feature layer in memory and select the record that is active in the cursor
arcpy.MakeFeatureLayer_management(nonNetHydroFC, "sel_lyr")
selection = '"OBJECTID" = {}'.format(rowObjID)
arcpy.SelectLayerByAttribute_management("sel_lyr", "NEW_SELECTION", selection)
#create a point at the start vertex of the selected record
arcpy.FeatureVerticesToPoints_management("sel_lyr", "flag", "START")
#select the upstream network & take the line layer from the returned layer group (network + junctions)
flag = "flag"
arcpy.TraceGeometricNetwork_management(network, "netLayer", flag, "TRACE_UPSTREAM")
usSelection = arcpy.SelectData_management("netLayer", netHydroFC)
field = accumSourceField
usVals = [r[0] for r in arcpy.da.SearchCursor(usSelection, (field))]
sumUSVals = float(sum(usVals))
newDAVal = float(sumUSVals + rowCtchVal)
row[2] = newDAVal
rows.updateRow(row)
... View more
10-28-2013
10:07 AM
|
1
|
0
|
558
|
POST
|
I have a custom widget in the Flex Viewer and I would like to add an image to the map via ActionScript in my custom widget. The following works when it is called in the code, but it adds the image at the bottom of my widget, not in map: At the top: private var img:Image = new Image; then the function: private function addImage():void
{
trace("trying to add legend")
img.source = "assets/images/image.png";
this.addChild(img)
} When I try the following, the trace happens, but no image is added. private function addImage():void
{
trace("trying to add legend")
img.source = "assets/images/image.png";
map.addChild(img)
} Any advice would be appreciated. Thanks, -Erik
... View more
06-13-2013
11:48 AM
|
0
|
0
|
418
|
POST
|
Thanks, Chris... It really is cool how much you can do with Python data structures. I have used dictionaries before, but in much simpler key:value pair format with simple int or string keys, not tuple keys. The way we've been using them here brings it to a whole other level of power (and complexity!). Thanks again.
... View more
05-02-2013
09:56 AM
|
0
|
0
|
813
|
POST
|
Bingo! That was the piece that was missing. Again, many, many thanks to both of you!
... View more
05-02-2013
08:56 AM
|
0
|
0
|
813
|
Title | Kudos | Posted |
---|---|---|
1 | 12-20-2021 01:55 PM | |
1 | 10-28-2013 10:07 AM |
Online Status |
Offline
|
Date Last Visited |
10-31-2023
09:42 AM
|