Search code examples
arcgisarcgis-js-api

ArcGIS JS not performing GeometryService cut method


I have an app where users can draw a shape on the map to indicate potential land use, and they can also draw a shape to indicate a 'no change' zone, where we want to indicate no development plans.

Basically, they can create a shape to indicate an industrial zone, and then they could draw an overlapping shape to basically cut out that industrial zone, and designate that zone as a no-development zone.

Here's my code:

function cutOutNoChangeZone () {
    var geometries = land_use_planning.graphics,
        geometries_to_be_cut,
        geoService = new esri.tasks.GeometryService("http://gis.website.com/ArcGIS/rest/services/Geometry/GeometryServer");

    for (var i = 0, len = geometries.length; i < len; i++) {
        var geometry = geometries[i];
        if (geometry.planning_type === 'no_change') {
            // cut ALL polygons that are under the no change zone
            geometries_to_be_cut = geometries.slice(0, i);
            // NEXT LINE THROWS ERROR
            geoService.cut(geometries_to_be_cut, geometry);
        }
    }
}

It throws an error in the console:

TypeError: Cannot read property 'toJson' of undefined

It's coming from the minified ArcGIS 3.9 init.js file on the js.arcgis.com server. I have already debugged the for loop to check that the geometries are valid geometries, with toJson methods. I was trying to follow the example on this esri forum, which shows a similar function: https://geonet.esri.com/thread/63777.

Also note that I am testing this on only two shapes: one industrial and one "no-change" that overlaps. geometries_to_be_cut is an array of the single geometry, and geometry is the "no-change" geometry.

It seems like this should be a simple function. I'm not sure where I'm going wrong, and thought someone might have some insight on this.


Solution

  • Stepping into the code, we see that the cut method calls toJson() on a few different objects:

    cut: function(a, c, f, g) {
        var e = a[0].spatialReference, p = l.map(a, function(a) {
            return a.toJson()
        });
        a = k.mixin({}, this._url.query, {f: "json",sr: n.toJson(e.toJson()),target: n.toJson({geometryType: u.getJsonType(a[0]),geometries: p}),cutter: n.toJson(c.toJson())});
        var m = this._cutHandler, s = this._errorHandler, B = new h(b._dfdCanceller);
        B._pendingDfd = d({url: this._url.path + "/cut",content: a,callbackParamName: "callback",
            load: function(a, b) {
                m(a, b, e, f, g, B)
            },error: function(a) {
                s(a, g, B)
            }});
        return B
    }
    

    This method calls toJson() on the cutting geometry and on the spatial reference of the first geometry in the list. I suspect that you somehow have a geometry with an undefined spatialReference property. Can you check for that please?

    Another possible issue is that according to the documentation, the cutting geometry must be a polyline, not a polygon. You didn't specify which one you used, but since you said "draw a shape," maybe the cutting geometry is a polygon. I can't tell yet, because that issue would manifest itself only after the service gets called and returns an error, and because of your toJson() error, you're not yet calling the service.

    Finally, I'm not sure that the cut method does what you need. If you get it working, cut will split the input polygons by the cutting polyline, returning the new split polygons. From your description, it sounds like either difference or intersect would be closer to what you need. But maybe I misunderstood what you wanted to do.

    Sorry for the laundry list but hopefully something here is useful. :-)