Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

Is there any way in ArcGIS to prevent symbols from being drawn when they overlap each other? I know this is possible for Labels using Placement Properties/Label Weight, but I can't seem to find corresponding functionality for symbology. The resulting map document will be published as an ArcGIS Server Map Service and displayed using the ArcGIS Javascript API. The data will be updated frequently, thus the service must be drawn dynamically (no caching).

Basically, I have a point feature class that can be very dense or very sparse depending on zoom scale. When zoomed out, there are too many symbols to display simultaneously in a coherent way. In an ideal world, I'd like to be able to prevent cluttering by specifying a buffer distance (in pixels) around each symbol where no other symbols can be drawn from the same layer. I don't want to cluster the symbols together - I only want to show a single point to represent the area.

My symbology is also fairly complex, and involves graduated symbols based on data value (as well as value-based rotation) as well as several labels with specific placement:

Short of thinning/downsampling the dataset before symbolizing, what are my options (if any) for reducing symbol density?

share|improve this question
    
Where will the ArcGIS Server map service be displayed? In ArcMap, in a website (if so do you have an API in mind?), or mobile device, etc? –  Stephen Lead Jul 25 '12 at 23:30
    
It will be on a website - I'm using the ArcGIS Javascript API to load the service as a DynamicMapServiceLayer. –  greenlaw Jul 26 '12 at 4:10
    
in that case I think you should change the title and tags. ArcMap isn't really the determining factor here - it's only used to create the web mapping service –  Stephen Lead Jul 26 '12 at 8:47
    
Yeah, probably a good idea. Tags/title/content has been updated. –  greenlaw Jul 26 '12 at 14:14

4 Answers 4

You might check out the following:

  1. Disperse Markers tools for representations. (ArcInfo aka Advanced only)
  2. Collect Events with rendering tool.
  3. ESRI tech article 22695 using the ESRI label engine to offset overlapping point symbols
  4. ArcObjects SDK point dispersal samples
  5. ETGEowizards disperse points tool. (Paid version)
  6. I've never tried this so it may be crazy, but if you make your point symbol invisible and only have a simple font character for its label, could you then use Maplex to set buffers, move the "labels" around, set weights, etc.
share|improve this answer
    
I appreciate your suggestions John, but unfortunately none of those options are what I'm looking for. #'s 1, 3, 4, and 5 each involve offsetting features, which is not feasible in my case as I need to preserve the feature's location (plus there would be too many features to display, even after dispersing). #2 won't work because I need to show a real data value rather than a combined value (the Integrate tool won't work either for the same reason). #6 is the closest to what I need but my symbology is too complex to be drawn with a simple font symbol. Thanks anyway though; +1 for effort. –  greenlaw Jul 24 '12 at 22:25
    
I've done #6 and it works quite well. It stops you from having to muck around with the settings for different scales, Maplex does the rejigging for you –  Loz Jul 24 '12 at 22:28
1  
@greenlaw #6 is an ingenious workaround - thanks for sharing this idea –  Stephen Lead Jul 24 '12 at 23:53
    
I agree #6 is a good idea, but unfortunately I can't use it for 2 reasons: 1) I need to publish this as an ArcGIS Server Dynamic Map Service (forgot to mention this, sorry), and using Maplex may reduce performance; and 2) I need to apply a symbol rotation based on another (angular) data value, which I don't think is possible using a simple font character (correct me if I'm wrong). –  greenlaw Jul 25 '12 at 15:39

Since you're now talking about a web map service, a suggestion is to modify the Esri cluster script.

This script takes a series of point graphics and clusters those which are too close together to draw individually. By default it draws a large symbol to represent clusters of points.

You can modify this to show a single point instead of the cluster - but the script will have done the hard work of removing the extraneous points. It'll automatically work at various scales.

Note that this would probably require that you submit a query against the point layer, or use a feature layer (rather than a dynamic layer). This is so that you can obtain access to each of the points individually. You would then submit the collection of points to the clusterer as input. The output would be a "cluster layer" which is a modified graphics layer.

share|improve this answer
    
Another good suggestion Stephen. It's probably the closest solution but unfortunately I don't think I can replicate my complex symbology using a Cluster Layer & client-side renderers (see edits/screenshot above). I also tried using FeatureLayers (without clustering), which uses the service symbology by default, but it wasn't applying my value-based rotation. –  greenlaw Jul 26 '12 at 14:32
    
I haven't tried this, but the MarkerSymbol specification contains both offset and angle properties. A PictureMarkerSymbol is a subclass of MarkerSymbol, so it might inherit these properties? –  Stephen Lead Jul 27 '12 at 0:22
    
Yes, I looked at those as well, but the prospect of recreating all my symbology on the client side is not very desirable - in addition to subclassing the Cluster Layer to do what I need I would have to create images of each of my graduated symbols (with transparent backgrounds and semi-transparent halos), which number around 50, and configure the proper renderers. Another downside to this approach is that every client is downloading way more data than they need, then throwing a bunch of it out, which is not optimal for server or client. I'm going to re-evaluate your thinning suggestion above. –  greenlaw Jul 27 '12 at 13:41

I don't want to cluster the symbols together - I only want to show a single point to represent the area.

Here's a suggestion to "thin" the data, which does require pre-processing.

You could create a mesh polygon, and count the number of points within each polygon.

If only one point is found, use it as the output point. If multiple points exists in a polygon, create an output point from the polygon's centroid (or pick one input point at random and convert it to the output point layer). You could symbolise this point differently to show that it represents a cluster of points (eg use a graduated symbol based on the number of points).

Repeat this process at various zoom levels (so you'll have an output point layer for each scale) and build a group layer from these points. Use scale dependency to switch the appropriate layer on/off at various scales.

When zoomed in you'll see all of your points, and when zooming out you'll show clusters of points.

share|improve this answer
    
Thanks Stephen - +1 for a good suggestion - but this too is what I was trying to avoid. My dataset will change sometimes every 6 minutes, and data points can appear or disappear during each update, so preprocessing might put too much strain on the system when running so frequently. I can't use graduated symbols either; I need to use the same symbology as an individual point. I was hoping the Arc drawing engine could take care of this for me, but it doesn't look like that's the case. –  greenlaw Jul 25 '12 at 15:33

This solution might not be feasible if you have a large number of points in a given view.

First, have a timeout check so that you do not run the thinning function until the user has stopped for a certain length of time.

Modify the clustering sample. When a cluster is created, grab the objectid of the first feature passed into that cluster and set it aside into an array, call it firstpoints. Remove all the graphics rendering portions of the layer, you will not need them.

Instead, where labels would be rendered, you pass a definition query to your map service. Where layer 0 is the symbol layer in your map service with your complex symbols:

layer.setLayerDefinitions(["OBJECTID IN (" + firstpoints.join() +")"]);

This will make your map service display only the first symbol from each cluster, hiding all the other overlapping symbols. Use the maximum pixel width of your symbols as the distance option for clustering. Note: Make sure you have a proxy set. You might need it for long firstpoint arrays.

share|improve this answer
    
I like this suggestion as well, but I don't believe it's feasible with the sheer number of points involved at small scales. I will keep this in mind for the future though - thanks. –  greenlaw Dec 17 '12 at 21:28

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.