null extent for dynamically generated polygon geometry from KMLLayer

1918
14
Jump to solution
04-27-2012 11:26 AM
AndrewMurdoch
Occasional Contributor
I get this error when attempting to use the FeatureLayer selectFeatures method using a dynamically generated polygon geometry:

In "?v=2.8 [dynamic]":
Microsoft JScript runtime error: 'xmin' is null or not an object (Ln 48, Col 41494, Ch 41494)

Ultimately, I want to use the actual geometry in a KML Layer to query another FeatureLayer, rather than use the Extent object of the KML geometries.  I'm trying to create a new geometry object that contains all of the KML Layer geometries.  There may be a better way to do this...

When evaluating breakpoints I can tell that the code fails on this line:
   targetLayer.selectFeatures(query);

Looking closer, I can see that the extent property is null for the new Geometry object after this line:
                           geom.addRing(graphic.geometry);
The graphic.geometry has a valid extent property (and presumably a valid geometry), but the geom object has an invalid extent after this line. 

Any thoughts or suggestions for me?

Thanks for your help!
Andrew




I'm using JavaScript API v2.8

Where kmlLayer = an esri KMLLayer object that contains a polygon for the state of Wyoming (http://dl.dropbox.com/u/2654618/kml/Wyoming.kml) and targetLayer = an esri FeatureLayer object:

function selectByLoadedLayer() {       if (kmlLayer) {         var geom;          var layers = kmlLayer.getLayers();         dojo.forEach(layers, function (lyr) {             if (lyr.graphics && lyr.graphics.length > 0) {                  if (lyr.declaredClass == "esri.layers.FeatureLayer") {                     if (lyr.geometryType == "esriGeometryPoint") {                         geom = new esri.geometry.Multipoint(map.spatialReference);                         dojo.forEach(lyr.graphics, function (graphic) {                             geom.addPoint(graphic.geometry);                         });                      } else if (lyr.geometryType == "esriGeometryPolygon") {                         geom = new esri.geometry.Polygon(map.spatialReference);                         dojo.forEach(lyr.graphics, function (graphic) {                             geom.addRing(graphic.geometry);                         });                      } else if (lyr.geometryType == "esriGeometryPolyline") {                         geom = new esri.geometry.PolyLine(map.spatialReference);                         dojo.forEach(lyr.graphics, function (graphic) {                             geom.addPath(graphic.geometry);                         });                     }                 } else {                     alert("KML layer contains a non-FeatureLayer layer object");                 }              }          });     } else {         alert("Please load an uploaded file or a network link first.");     }      //initialize & execute query     var query = new esri.tasks.Query();     query.geometry = geom;     query.returnGeometry = true;          targetLayer.selectFeatures(query);        }
0 Kudos
1 Solution

Accepted Solutions
derekswingley1
Frequent Contributor
addRing does not accept a geometry object??? it expects "an array of numbers, an array of points, or a JSON object". The same goes for addPath.

You probably want to reference your graphic.geometry's rings (for polygons) or paths (for polylines) properties. That can get tricky if you have to handle data that has holes or is multi-part. Have you thought about using the geometry service's union operation instead?

View solution in original post

0 Kudos
14 Replies
derekswingley1
Frequent Contributor
addRing does not accept a geometry object??? it expects "an array of numbers, an array of points, or a JSON object". The same goes for addPath.

You probably want to reference your graphic.geometry's rings (for polygons) or paths (for polylines) properties. That can get tricky if you have to handle data that has holes or is multi-part. Have you thought about using the geometry service's union operation instead?
0 Kudos
SiqiLi
by Esri Contributor
Esri Contributor
Ultimately, I want to use the actual geometry in a KML Layer ...


Why not try this:
if (lyr.geometryType == "esriGeometryPolygon") {
        kmlGeoms = dojo.map(lyr.graphics, function(g) {return g.geometry;});
}
0 Kudos
AndrewMurdoch
Occasional Contributor
Thanks for your quick reply!
I'm now trying to use the GeometryService union method, but I'm running into this error message in the unionError handler method:
"'geom' is undefined"
When I look at the code in debug mode, it looks like geom is a valid array of Geometry objects...

I'm trying to create an array of Geometry objects and that must be where I'm going wrong.  Can you take a look at this code?  Specifically I might be doing something wrong at this line: geom.push(graphic.geometry);

Thanks for your help.

function selectByLoadedLayer() {

    if (kmlLayer) {
        
        var geom = new Array();

        var layers = kmlLayer.getLayers();

        dojo.forEach(layers, function (lyr) {
            if (lyr.graphics && lyr.graphics.length > 0) {
                if (lyr.declaredClass == "esri.layers.FeatureLayer") {
                    dojo.forEach(lyr.graphics, function (graphic) {
                        geom.push(graphic.geometry);
                    });
                }
            }

        });

      //Union Geometries in KML
      geomService.union(geom, unionComplete, unionError);

    } else {
        alert("Please load an uploaded file or a network link first.");
    }

}

function unionComplete(geometry) {
    //Initialize Query and use new union geometry
    var query = new esri.tasks.Query();
    query.geometry = geom;
    query.returnGeometry = true;
    targetLayer.selectFeatures(query);
 }

function unionError(error) {
    alert(error.message);
}

0 Kudos
derekswingley1
Frequent Contributor
Why not try this:
if (lyr.geometryType == "esriGeometryPolygon") {
        kmlGeoms = dojo.map(lyr.graphics, function(g) {return g.geometry;});
}


That will give you an array of polygons�?? you'll still need some other method, like the geometry service's union operation, to create a single geometry from the array of polygons.
0 Kudos
AndrewMurdoch
Occasional Contributor
My problem was a simple typo on the variable name in the unionComplete handler. The "geom" object should have been "geometry" (or vice versa).

function unionComplete(geometry) {
    //Initialize Query and use new union geometry
    var query = new esri.tasks.Query();
    query.geometry = geom;
    query.returnGeometry = true;
    targetLayer.selectFeatures(query);


In order to get below the 2000 character feature layer .selectFeatures(query) limit, I had to also use the "generalize" method of the GeometryService. So I first Generalized my array of geometries and then Unioned the generalized output. Finally, I used the unioned geometry as the query geometry in selectFeatures.

Is there a way to evaluate the geometry object as a JSON string and get the number of characters prior to running selectFeatures? If so, I could at best keep generalizing until the geometry fit that 2000 character limit, or at worst, notify the user of the problem.

Thanks for your help,
Andrew
0 Kudos
AndrewMurdoch
Occasional Contributor
OK, I was able to answer one of my questions, on the length of the JSON string.

    var geomJson = geom.toJson();
    var jsonText = JSON.stringify(geomJson);
    var jsonLength = jsonText.length;


However, I would like to know how long the query geometry (as a JSON string length) can be. I have successfully queried with a JSON string of 2300 characters (using a proxy page to bypass the 2000 character query string limit). However, if I used the ungeneralized version of that query string, the JSON string would be 30,000 characters, which fails to select features (and fails to present any useful error or warning message).

What is the length limit on a query's geometry JSON string object when using the FeatureLayer selectFeatures() method?

I've done more testing and determined (at least for this install and these map services) that the max length of a query geometry object is between 4400 and 4900 characters. This was for a geometry object that was a collection of polyline objects unioned together. I'm not sure if this is based on a setting in the GeometryServer's config file? There is no error message when the query geometry object turns out to be too big. Also not sure if the query geometry object is limited strictly by the JSON length or some other measure of complexity...

Thanks,
Andrew
0 Kudos
derekswingley1
Frequent Contributor
There isn't a limit on geometry size that can be used to query, but larger geometries require a proxy.

Due to browser limitations (old IE), the JS API switches to using a proxy when it needs to fetch a URL longer than 2000 characters. As you've noted, you can go well past this limit when using a large geometry. The best option is to configure a proxy that runs on the same server as your web app so that you can use it to send large geometries to your service to be used in a query. See the link above for more info on setting up and configuring the proxy. Configuring a proxy is absolutely worth the time to do as the need for it will likely come up again as you develop apps with the API.

Alternatively, if you don't need to run in old IE, you could mess around with increasing esri.config.defaults.io.postLength. But I wouldn't recommend this approach as it could have unintended side effects (and will almost certainly break your app in old versions of Internet Explorer).
0 Kudos
AndrewMurdoch
Occasional Contributor
Thanks for the reply Derek.
However I'm not sure that answers the question.  I am using a proxy for large queries, but after the query geometry JSON string length exceeds about 4400 characters in length, the selectFeatures method fails to select any features.

Even with a proxy page, (downloaded from the ESRI link), this problem occurs.  Just curious what the limit for large query length might be.  Or should I not be seeing this strange arbitrary limit on my end?  This is using IE8, btw.

Thanks,
Andrew
0 Kudos
derekswingley1
Frequent Contributor
Is the problem only in IE8?
0 Kudos