Select to view content in your preferred language

Javascript API Snapping with Many Polygons

2245
5
05-29-2017 11:12 PM
HenryKo2
Regular Contributor

Hi, we have a requirement to allow web-based editing and snap against a polygon map service. Snapping works with graphics or feature services, but our polygons can have many vertices and there can be many polygons to snap to, which might or might not have performance issues in the browser. Does anyone have any experience with snapping against many polygons? Or, is it possible to use dynamic map service somehow for snapping? We are using Javascript API 3.13.

5 Replies
ThomasSolow
Frequent Contributor

Can you clarify what you mean by snapping?  Should the mouse "snap" to the edge of a polygon when the user mouses near the polygon?  Or should the popup open when the mouse is near a polygon?

You may be able to snap to polygons based on their extent and the mouse position.  It's fairly cheap to test if a point is located inside an extent, and every polygon has an extent, which is the smallest bounding box around that polygon.

I'm not sure the best way to approach this with an image service though.  My understanding is that an image service will just serve up an image, which won't differentiate between different polygon geometries.  If this is accurate, it seems probable that you'd have to do this kind of a query on the back-end, where the polygon geometries actually exist.

0 Kudos
HenryKo2
Regular Contributor

Thanks for the reply. Yes, by "snapping" I meant the standard ArcGIS editing snapping - user moves mouse to create/edit geometries, and the mouse point snaps to the closest polygon from a layer/service. 

0 Kudos
ThomasSolow
Frequent Contributor

Like I said above, I'm unsure if this is doable on an image service.  My understanding is that you don't actually have the geometries in the client with the image service, just an image.  If you have a feature service or a graphics layer with polygon geometries, here's how I would approach this:

1.  Add an on-mouse-move event to the map.

2.  When the event fires, loop through every polygon geometry in the layer (first you can filter by the map's current extent to rule out polygons not currently visible).

3. For each polygon check to see if some condition is met.  If it is, break from the loop and "snap" to that polygon.

Some considerations:

1.  You can check for intersection with the extent like this: <Polygon Graphic>.geometry.extent.intersects(<point geometry>) -> true|false.

2.  You can use the geometryEngine to check if a polygon intersects a point.  You might try this, but the extent check is much faster, which you may want to consider depending on how much polygons you have.  Also the extent check may be better If you want a fuzzy search, which it sounds like you might.

3.  You might look at geometryEngine.buffer/geodesicBuffer.  You could buffer each polygon at some distance and check for the mouse point's intersection with the buffer (or the extent of the buffer).  This should give a better fuzzy search.

4.  Another option is  the geometryEngine's nearestVertex/nearestVertices methods.  You could define some distance and check for a vertex in each polygon within that distance, and snap to that polygon if a vertex is found within that distance.  This is probably the best solution, but I'm unsure how well it will perform.

5.  Something you'll have to consider is what you want to do if the mouse meets your condition for multiple polygons.

6.  You may want to add a debounce on the search.  Mouse move events trigger a lot, and you probably don't want to do a search for every event.  Underscore.js has a debounce function that you can copy if needed: underscore.js 

7.  "Snapping" the cursor is not allowed in the browser.  There is no way to move the cursor programmatically.  I imagine this is for security reasons.  I would recommend that you replace "snapping" with some kind of highlight to show which polygon the mouse is near.

0 Kudos
HenryKo2
Regular Contributor

Thanks, there are some interesting points here.

HemingZhu
Frequent Contributor

I would look into 'esri/geometry/geometryEngine' moudle, it has a lots of methods that can achieve your goals.