GeometryEngine 3.15 union error when using try-catch

5796
12
12-11-2015 12:10 AM
AndrewBiggins
New Contributor III

I have tried the GeometryEngine.union method (within JavaScript 3.15 API) but it throws the following error when it is placed within a try-catch statement:

TypeError: Unable to get property 'hq' of undefined or null reference

It seems to work when not placed within a try-catch, but since it is throwing this error I'm concerned about using it within a production application. Also, the equivalent Union method in the ArcGIS Server GeometryService does not throw an error.

I thought the error might be due to undefined spatial references in the array of geometries passed to it, but I have checked and they are all defined.

Can anyone please advise why this error is being thrown?

arrayUtils.forEach(AdviceGlobal.savedFeaturesGraphicsLayer.graphics, function (savedGraphic) {
 // Define spatial reference for geometryEngine
 var thisGeometry = savedGraphic.geometry;
 console.log(thisGeometry.spatialReference);
 if (thisGeometry.spatialReference == null) {
  thisGeometry.spatialReference = map.spatialReference;
 }
 geometryToCapture.push(thisGeometry);
});
// Try geometryEngine
try {
    var unionedGeometry = geometryEngine.union(geometryToCapture);
    saveFeature(unionedGeometry);
}
catch (e) {
    onUnionError(e);
}

12 Replies
JoelBennett
MVP Regular Contributor

I too have had the same issue, which has been occurring since geometryEngine's introduction in 3.13.  I hadn't noticed (and therefore can't verify) the try/catch issue since my code doesn't have any of those clauses around this operation.  My code executes the combine operation inside of a callback from a QueryTask, so there's probably a try/catch somewhere up the call stack in the JavaScript API.

Since I'm not the only person this is happening to, I was emboldened to look into this further.  Unfortunately, the code for geometryEngine is much too obfuscated to readily understand what's going on, but here's the function where things foul up:

b.prototype.iL=function(a){
 for(var d=[],c=[],h=this.sn,l=b.bc(h),g=0;g<l.length;g++){
  var m=l,n=h;
  if(this.Fc||1E4<n.hq&&1<n.Ci.length){
   this.bp-=n.Ci.length;
   for(this.Qo-=n.Ci.length;0<n.Ci.length;)
    d.push(n.Cv().hw),n.OQ();
   c.push(m)
  }
 }
 for(g=0;g<c.length;g++)
  delete h[c];
 return d
};

The error is thrown when comparing if 1E4 is less than n.hq, and occurs because n is undefined.  If we look further up, we see n was set to the value of h...that is, an element of some array.  In my case, h was an array with a length of 4, but elements with index 0, 1, and 2 were undefined.  However, this code wrongly assumes all the elements in the array it references are defined...hence the error.

I use a locally hosted version of the API, and so I tweaked it a little to check for a valid value of n before proceeding.

Therefore, the original code (which you can ctrl-f to find):

if(this.Fc||1E4<n.hq&&1<n.Ci.length)

became

if((n)&&(this.Fc||1E4<n.hq&&1<n.Ci.length))

This appears to have fixed the problem, although I haven't performed any rigorous testing...as such, if you try this, proceed with caution.  Also, if you do, you'll probably need to delete temporary internet files before reloading your app to ensure you get the updated version.

JoelBennett
MVP Regular Contributor

ESRI did not fix this bug in version 3.16 of the ArcGIS API for JavaScript.

KenDoman
Occasional Contributor II

ESRI has not fixed this bug in version 3.17 of the ArcGIS API for JavaScript, either.

0 Kudos
JoelBennett
MVP Regular Contributor

Thanks Ken...I also have confirmed this is still an issue in 3.17.

0 Kudos
SumitZ
by
New Contributor III

Have you tried simplifying the geometry before doing it union?

Before pushing the geometry to array  'geometryToCapture' simplify using geometryEngine and if the result is valid then only consider that geometry for union.

0 Kudos
KristianEkenes
Esri Regular Contributor

This hasn't been fixed because there hasn't been a bug report logged for it. Once somebody logs as a bug it will be looked at and fixed.

0 Kudos
YohanBienvenue
Occasional Contributor II

This still seems to be an issue with 3.21?

I'm trying to do a simple union of two polygons and I get a TypeError at the exact same line as shown above by Joel Bennett. I don't have any try-catch and the spatialReference (32188) is the same for both polygons. I tried geometryEngine.simplify on each of those polygons before doing a union on them, but it didn't help. The union of the GeometryService works fine. What am I doing wrong with geometryEngine.union?

Update: I tried to figure out how I could apply a fix to that problem function at runtime, but it's not accessible from outside geometryEngine. So I ended up doing something similar to Joel Bennet. I recreated my own version of the geometryEngine (I called it app.geometryEngine), replaced the define at the top from esri/geometry/geometryEngine to app/geometryEngine and also added the "if (n)" at the same problem line. Everything seems fine now. Will update if that changes in the future.

0 Kudos
JoelBennett
MVP Regular Contributor

I've missed a few releases, being busy with other things, but have found this is still an issue in 3.23.  I haven't tried union this time around, but it happens with buffer. The workaround is still the same, although some variable names have changed.

Look for

if(this.Ec||1E4<u.jq&&1<u.Ci.length)

Replace with

if((u)&&(this.Ec||1E4<u.jq&&1<u.Ci.length))
0 Kudos
ReneRubalcava
Frequent Contributor

Just tested this out with 3.23, 4.6, 3.24, and 4.7 in Chrome, FF, Edge, IE11 and can't repro. Do you have a repro case to test with?

It's possible this was already fixed somewhere along the line. Tried union, buffer, and geodesicBuffer.

Thanks!

0 Kudos