Select to view content in your preferred language

Jagged polygons at large scales - how to smooth them out?

3544
17
01-13-2012 07:35 AM
MikeOnzay
Regular Contributor
Are the concepts that are presented in the generalize and performance samples under feature layers going to solve the problem of jagged edges at large scales?

I have one featurelayer (150 mb featureclass) that displays 1-4 features at a time at most. At large scales I get really jagged edges. The source data, as viewed in ArcMap, is more detailed. I have included the maxAllowableOffset parameter as described in the generalize features sample. This does help with the speed of initially displaying some of the larger features based on what I am seeing in firebug. However, I'm struggling to make sense of the two samples and how I should implement the code in my own application.

It seems that the code in the generalize sample might be all I need:

    var maxOffset = function maxOffset(map, pixelTolerance) {
      return Math.floor(map.extent.getWidth() / map.width) * pixelTolerance;
    };

but the performance sample uses a different calculation:

function calcOffset() {
        return (globals.map.extent.getWidth() / globals.map.width);
        // console.log('extent changed...maxOffset: ', globals.maxOffset);
      }

I'm not sure what to do or whether it will fix this problem.
0 Kudos
17 Replies
derekswingley1
Frequent Contributor II
The performance sample is a simplified version of the code from the generalize sample. The performance sample assumes you don't want to display more than one vertex per pixel (anything more than that is wasted effort) so there's not pixel tolerance parameter. In other words, pixel tolerance is always 1. This is effectively the same as the generalize sample as the generalize sample always uses 1 for pixel tolerance.

Regarding your question about jagged edges, yes, max offset should be able to address this for you. The key is to generate the correct value. Two things would help get to the bottom of this:
-post a screen shot of your geometry in ArcMap as well as in your JS app
-post the code your using to generate max offset as well as the code that sets up the event listener to calculate max offset

The second point is relevant because it's possible that you're calculating max offset based on an old scale rather than the map's current scale.
0 Kudos
MikeOnzay
Regular Contributor
[ATTACH=CONFIG]11168[/ATTACH][ATTACH=CONFIG]11169[/ATTACH]

Thanks for your help.

This is inside my init function:

dojo.connect(map, 'onLoad', function (theMap) {
                    //resize the map when the browser resizes
                    dojo.connect(dijit.byId('mapDiv'), 'resize', map, map.resize);
                    var maxOffset = function maxOffset(map, pixelTolerance) {
                            return Math.floor(map.extent.getWidth() / map.width) * pixelTolerance;
                        };
                });


This is a function that I use to query my feature and then add the graphic(s) to the map:

function zoomToEFH_Feature(name) {
  
                //set up maxOffset for performance
                var maxOffset = function maxOffset(map, pixelTolerance) {
                        return Math.floor(map.extent.getWidth() / map.width) * pixelTolerance;
                    };

                //create feature layer   
                var efhLayer = new esri.layers.FeatureLayer("http://<internal server>/ArcGIS/rest/services/NMFS/EFH_MapperData/MapServer/6", {
                    maxAllowableOffset: maxOffset(map, 1),
                    outFields: ["*"],
                    opacity: 0.75,
                    id: "efhL"
                });
                efhLayer.setDefinitionExpression("TYPE='EFH'");

                //initialize query
                EFH_Fquery = new esri.tasks.Query();
                EFH_Fquery.where = "DDBOX = '" + name + "' AND FMC = '" + regionName + "'";
                //console.log(EFH_Fquery.where);
    //execute query
                efhLayer.queryFeatures(EFH_Fquery, function showResults(featureSet) {
                    //console.log('inside show Results for EFH query');
                    map.graphics.clear();
                    var symbol = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID).setColor(new dojo.Color([255, 255, 0, 0.5]));
                    
                    //console.log(featureSet.features.length);
      var legendcode = '<table border=0 cellspacing="5" cellpadding="5"><caption>Lifestages</caption>';
     //Loop through features in the featureSet and add them to the map.
                    for (var i = 0, il = featureSet.features.length; i < il; i++) {
                        //Get the current feature from the featureSet.
                        //Feature is a graphic
                        var graphic = featureSet.features;
                        graphic.setSymbol(symbol);
                        var featureextent = graphic.geometry.getExtent();
                        map.setExtent(featureextent, true);
                        //Add graphic to the map graphics layer.
                        map.graphics.add(graphic);   })  
            }
0 Kudos
derekswingley1
Frequent Contributor II
Thanks. When is zoomToEFH_Feature called?

To make sure you're using the correct scale when you calculate max offset, I recommend re-caculating it each time onZoomEnd fires and storing that value in an app wide variable. This is what is done in the performance sample.
0 Kudos
MikeOnzay
Regular Contributor
"When is zoomToEFH_Feature called?" - it is called from a select box on a form. The user chooses an item and it calls this function.

I do have maxOffset set as a global variable.

I was looking at my code again after your last response and I noticed that I used this twice:

var maxOffset = function maxOffset(map, pixelTolerance) {
                            return Math.floor(map.extent.getWidth() / map.width) * pixelTolerance;
                        };


once in the init function and once in the zoomtoEFH_Feature function. Is that right?

I also noticed that I am not using the setMaxAllowableOffset anywhere. Should I put that inside the zoomtoEFH_Feature function?

 
  dojo.connect(efhLayer, "onLoad", function() {
     dojo.connect(map, "onZoomEnd", function() {
     efhLayer.setMaxAllowableOffset(maxOffset(map,1));
     });
    });
0 Kudos
derekswingley1
Frequent Contributor II
When you re-calculate max offset, you should also set it on your feature layer. This is shown in the performance sample:
dojo.connect(globals.map, 'onZoomEnd', function() {
  globals.maxOffset = calcOffset();
  dojo.forEach(globals.featureLayers, function(fl) {
    fl.setMaxAllowableOffset(globals.maxOffset);
  });
});
0 Kudos
MikeOnzay
Regular Contributor
I'm having a hard time understanding how to solve this. Although I'm sure the answer is right in front of me. 🙂
0 Kudos
derekswingley1
Frequent Contributor II
I'm having a hard time understanding how to solve this. Although I'm sure the answer is right in front of me. 🙂


Yep :). You need to set up an event listener for onZoomEnd. When that event fires, calculate a value for maxAllowableOffset and then pass it to your feature layer's setMaxAllowableOffset method. The feature layer will then update with new geometries that are appropriate for the map's new scale.
0 Kudos
MikeOnzay
Regular Contributor
Yep :). You need to set up an event listener for onZoomEnd. When that event fires, calculate a value for maxAllowableOffset and then pass it to your feature layer's setMaxAllowableOffset method. The feature layer will then update with new geometries that are appropriate for the map's new scale.


I have this partially solved. When I can get the feature to display and I zoom in/out for more/less detail my shapes are not jagged anymore (Yea!). However, if the feature is large it won't draw at all and I get a script error

Error: timeout exceeded
http://serverapi.arcgisonline.com/jsapi/arcgis/?v=2.6
Line 14

plus a "script too large" error.
0 Kudos
derekswingley1
Frequent Contributor II
if the feature is large it won't draw at all and I get a script error

Error: timeout exceeded
http://serverapi.arcgisonline.com/jsapi/arcgis/?v=2.6
Line 14

plus a "script too large" error.


Post your code? Is your server endpoint public?
0 Kudos