From: Matthew K. <mat...@gm...> - 2010-04-14 03:26:33
|
Hi guys! geotools newbie here so apologies in advance if this is a silly question or if I abuse terminology... I'm writing a custom layer engine for a 3rd party application that uses geotools to draw custom rendering. I have data that occurs multiple times per single location (fire unit responses) over many addresses, so I'm drawing a TextSymbolizer of the integer count on top of the address to indicate how many incidents occured there. this is all good, but the problem I'm having is that as you zoom out the labels start to cluster together and then geotools stops drawing some of the symbols as they overlap, so it looks like there are fewer points of interest overall. eg at max zoom you might see 20 addresses with incidents and associated counts. zoom out to double, they move together and half the labels disappear, double again and another half disappear, and so on til only one remains. I understand the technical reasons for this happening, but I know the client is going to insist they see all incidents, even if they overlap or occlude. I can manually change the drawing styles (not using SLDs, directly doing this in Java) to use a different style at higher scales (eg just a small circle), but I'm wondering if there's a way I can tell geotools not to perform this optimisation so that even at high scale you can still see overlapping symbols? eg something like renderer.setOverlapStrategy(RenderStrategy.ALWAYS_RENDER); //pseudo code thanks! my code: // create a query for this entity with this filter (bounding box) and returning these 3 columns Query query = new DefaultQuery(entityName, ffilter, new String[] { "UCV_PER_M2", entityKey, geom }); FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = dataStore.getView(query); StyleBuilder sb = new StyleBuilder(); StyleFactory styleFactory = sb.getStyleFactory(); FilterFactory ff = sb.getFilterFactory(); List<Rule> rules = new ArrayList<Rule>(); FeatureCollection<SimpleFeatureType, SimpleFeature> fc = featureSource.getFeatures(); // do get counts FeatureCollection<SimpleFeatureType, SimpleFeature> copy = featureSource.getFeatures(); Iterator<SimpleFeature> iter = fc.iterator(); try { while (iter.hasNext()) { SimpleFeature feature = iter.next(); String key = (String) feature.getAttribute("LAISKEY"); Color color = new Color(key.hashCode()); Stroke stroke = sb.createStroke(color, 2.0); Fill fill = sb.createFill(color, 0.5); Symbolizer symbolizer = sb.createPolygonSymbolizer(stroke, fill); // create label of text String count = "69"; TextSymbolizer textSymbolizer = sb.createTextSymbolizer( sb.createFill(Color.BLACK) , new Font[] { sb.createFont("Lucida Sans", 10),sb.createFont("Arial", 10) } , sb.createHalo() , sb.literalExpression(count) , new PointPlacementImpl() , "GEOMETRY" ); Mark circle = sb.createMark(StyleBuilder.MARK_CIRCLE, Color.RED); Graphic graph2 = sb.createGraphic(null, circle, null, 1, 35, 0); PointSymbolizer pointSymbolizer = sb.createPointSymbolizer(graph2); // back to normal Filter f = sb.getFilterFactory().equals(ff.property("LAISKEY"), ff.literal(key)); Rule rule = styleFactory.createRule(); rule.setFilter(f); rule.setSymbolizers(new Symbolizer[] { symbolizer, pointSymbolizer, textSymbolizer}); rules.add(rule); } } finally { fc.close(iter); } FeatureTypeStyle fts = sb.createFeatureTypeStyle("Feature", (Rule[]) rules.toArray(new Rule[rules.size()])); Style style = styleFactory.createStyle(); style.setFeatureTypeStyles(new FeatureTypeStyle[] { fts }); MapLayer mapLayer = new DefaultMapLayer(featureSource, style); mapLayers.add(mapLayer); Graphics2D gr = image.createGraphics(); CoordinateReferenceSystem crs = mapDesc.getExtent().getCoordinateReferenceSystem(); LOG.debug("Creating map context"); MapContext mc = new DefaultMapContext(mapLayers.toArray(new MapLayer[mapLayers.size()]), crs); LOG.debug("Setting area of interest"); mc.setAreaOfInterest((ReferencedEnvelope) mapDesc.getExtent()); LOG.debug("Creating streaming renderer"); final StreamingRenderer renderer = new StreamingRenderer(); RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); renderer.setJava2DHints(hints); renderer.setContext(mc); Rectangle outputArea = new Rectangle(width, height); ReferencedEnvelope dataArea = mc.getAreaOfInterest(); renderer.paint(gr, outputArea, dataArea); -- Matthew Kerle http://threebrightlights.blogspot.com |