From: <db...@sv...> - 2005-11-27 15:31:42
|
Author: dblasby Date: 2005-11-27 07:30:59 -0800 (Sun, 27 Nov 2005) New Revision: 17009 Modified: geotools/branches/2.1.x/module/main/src/org/geotools/renderer/lite/Ren= dererUtilities.java geotools/branches/2.1.x/module/main/src/org/geotools/renderer/lite/Str= eamingRenderer.java Log: updated to be compatible with trunk (only one outstanding issue regarding= the gridcoverage renderer) Modified: geotools/branches/2.1.x/module/main/src/org/geotools/renderer/l= ite/RendererUtilities.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- geotools/branches/2.1.x/module/main/src/org/geotools/renderer/lite/Re= ndererUtilities.java 2005-11-27 11:32:29 UTC (rev 17008) +++ geotools/branches/2.1.x/module/main/src/org/geotools/renderer/lite/Re= ndererUtilities.java 2005-11-27 15:30:59 UTC (rev 17009) @@ -2,8 +2,11 @@ =20 import java.awt.Rectangle; import java.awt.geom.*; -import java.awt.geom.AffineTransform; =20 +import org.geotools.referencing.CRS; +import org.opengis.referencing.crs.CoordinateReferenceSystem; + +import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Envelope; =20 /* @@ -16,7 +19,7 @@ */ =20 /** - * Class for holding utility functions that are common tasks for peopl= e using the "StreamingRenderer/Renderer". + * Class for holding utility functions that are common tasks for people = using the "StreamingRenderer/Renderer". *=20 *=20 * @author dblasby @@ -72,4 +75,47 @@ Math.min(x1, x2), Math.max(x1, x2), Math.min(y1, y2), Math.max(y1, y2)); =20 } + + /** + * Find the scale denominator of the map. + * Method: + * 1. find the diagonal distance (meters) + * 2. find the diagonal distance (pixels) + * 3. find the diagonal distance (meters) -- use DPI + * 4. calculate scale (#1/#2) + * + * NOTE: return the scale denominator not the actual scale (1/scal= e =3D denominator) + * + * TODO: (SLD spec page 28): + * Since it is common to integrate the output of multiple servers in= to a single displayed result in the + * web-mapping environment, it is important that different map serve= rs have consistent behaviour with respect to + * processing scales, so that all of the independent servers will se= lect or deselect rules at the same scales. + * To insure consistent behaviour, scales relative to coordinate spa= ces must be handled consistently between map + * servers. For geographic coordinate systems, which use angular uni= ts, the angular coverage of a map should be + * converted to linear units for computation of scale by using the c= ircumference of the Earth at the equator and + * by assuming perfectly square linear units. For linear coordinate = systems, the size of the coordinate space + * should be used directly without compensating for distortions in i= t with respect to the shape of the real Earth. + * + * NOTE: we are actually doing a a much more exact calculation, and = accounting for non-square pixels (which are allowed in WMS) + * + * @param envelope + * @param coordinateReferenceSystem + * @param imageWidth + * @param imageHeight + * @param DPI screen dots per inch (OGC standard is 90) + * @return + */ + public static double calculateScale(Envelope envelope, CoordinateRef= erenceSystem coordinateReferenceSystem,int imageWidth,int imageHeight,dou= ble DPI) throws Exception { + double diagonalGroundDistance =3D CRS.distance( + new Coordinate(envelope.getMinX(),envelope.getMinY()), + new Coordinate(envelope.getMaxX(),envelope.getMaxY()), + coordinateReferenceSystem + ); + // pythagorus theorm + double diagonalPixelDistancePixels =3D Math.sqrt( imageWidth*ima= geWidth+imageHeight*imageHeight); + double diagonalPixelDistanceMeters =3D diagonalPixelDistancePixe= ls / DPI * 2.54 / 100; // 2.54 =3D cm/inch, 100=3D cm/m + =20 + =20 + return diagonalGroundDistance/diagonalPixelDistanceMeters; // re= member, this is the denominator, not the actual scale; + } } \ No newline at end of file Modified: geotools/branches/2.1.x/module/main/src/org/geotools/renderer/l= ite/StreamingRenderer.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- geotools/branches/2.1.x/module/main/src/org/geotools/renderer/lite/St= reamingRenderer.java 2005-11-27 11:32:29 UTC (rev 17008) +++ geotools/branches/2.1.x/module/main/src/org/geotools/renderer/lite/St= reamingRenderer.java 2005-11-27 15:30:59 UTC (rev 17009) @@ -9,14 +9,24 @@ package org.geotools.renderer.lite; =20 import java.awt.AlphaComposite; +import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; +import java.awt.Point; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.geom.AffineTransform; import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.Point2D; import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferDouble; +import java.awt.image.Raster; +import java.awt.image.RenderedImage; +import java.awt.image.SampleModel; +import java.awt.image.WritableRaster; +import java.awt.image.renderable.ParameterBlock; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -27,8 +37,17 @@ import java.util.logging.Level; import java.util.logging.Logger; =20 +import javax.media.jai.JAI; +import javax.media.jai.PlanarImage; +import javax.media.jai.ROI; +import javax.media.jai.RasterFactory; +import javax.media.jai.RenderedOp; +import javax.media.jai.TiledImage; import javax.media.jai.util.Range; =20 +import org.geotools.coverage.Category; +import org.geotools.coverage.GridSampleDimension; +import org.geotools.coverage.grid.GridCoverage2D; import org.geotools.data.DataUtilities; import org.geotools.data.DefaultQuery; import org.geotools.data.FeatureReader; @@ -52,13 +71,13 @@ import org.geotools.geometry.JTS; import org.geotools.map.MapContext; import org.geotools.map.MapLayer; -import org.geotools.referencing.CRS; import org.geotools.referencing.FactoryFinder; -import org.geotools.referencing.operation.GeneralMatrix; + import org.geotools.renderer.GTRenderer; - +import org.geotools.renderer.RenderListener; import org.geotools.renderer.style.SLDStyleFactory; import org.geotools.renderer.style.Style2D; +import org.geotools.styling.ColorMapEntry; import org.geotools.styling.FeatureTypeStyle; import org.geotools.styling.LineSymbolizer; import org.geotools.styling.PointSymbolizer; @@ -70,6 +89,7 @@ import org.geotools.styling.Symbolizer; import org.geotools.styling.TextSymbolizer; import org.geotools.util.NumberRange; +import org.opengis.coverage.SampleDimension; import org.opengis.coverage.grid.GridCoverage; import org.opengis.referencing.FactoryException; import org.opengis.referencing.crs.CoordinateReferenceSystem; @@ -84,46 +104,44 @@ import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryCollection; -import org.geotools.renderer.RenderListener; =20 /** - * A lite implementation of the Renderer interface. Lite means that: + * A streaming implementation of the GTRenderer interface.=20 * <ul> * <li>The code is relatively simple to understand, so it can be used as= a simple example of an SLD * compliant rendering code</li> - * <li>Uses as few memory as possible</li> + * <li>Uses as little memory as possible</li> * </ul> * Use this class if you need a stateless renderer that provides low mem= ory footprint and decent * rendering performance on the first call but don't need good optimal p= erformance on subsequent * calls on the same data. Notice: for the time being, this class doesn'= t support GridCoverage * stylers, that will be rendered using the non geophisics version of th= e GridCoverage, if * available, with the geophisics one, otherwise. - *=20 + * * @author James Macgill * @author dblasby * @author jessie eichar * @author Andrea Aime - *=20 + * * @version $Id$ */ -public class StreamingRenderer implements GTRenderer -{ -=09 - public HashMap symbolizerAssociationHT =3D new HashMap(); //associate a= symbolizer with some data -=09 +public class StreamingRenderer implements GTRenderer { + =20 + public HashMap symbolizerAssociationHT =3D new HashMap(); //associat= e a symbolizer with some data + =20 /** Tolerance used to compare doubles for equality */ private static final double TOLERANCE =3D 1e-6; - + =20 /** The logger for the rendering module. */ private static final Logger LOGGER =3D Logger.getLogger("org.geotool= s.rendering"); int error =3D 0; =20 - /**=20 + /** * This listener is added to the list of listeners automatically. I= t should be removed * if the default logging is not needed. */ public static final DefaultRenderListener DEFAULT_LISTENER=3Dnew Def= aultRenderListener(); - + =20 /** Filter factory for creating bounding box filters */ private FilterFactory filterFactory =3D FilterFactory.createFilterFa= ctory(); private final static CoordinateOperationFactory operationFactory; @@ -136,74 +154,74 @@ Hints hints=3Dnew Hints(Hints.LENIENT_DATUM_SHIFT, Boolean.TRUE)= ; mathTransformFactory=3DFactoryFinder.getMathTransformFactory(hin= ts); } - + =20 /** * This is used to control what type of image the system will draw = into. */ public int defaultImageType =3D BufferedImage.TYPE_4BYTE_ABGR; -=09 + =20 /** * Context which contains the layers and the bouning box which needs= to be rendered. */ private MapContext context; - + =20 /** * Flag which determines if the renderer is interactive or not. An i= nteractive renderer will * return rather than waiting for time consuming operations to compl= ete (e.g. Image Loading). A * non-interactive renderer (e.g. a SVG or PDF renderer) will block = for these operations. */ private boolean interactive =3D true; - + =20 /** * Flag which controls behaviour for applying affine transformation = to the graphics object. If * true then the transform will be concatenated to the existing tran= sform. If false it will be * replaced. */ private boolean concatTransforms =3D false; - + =20 /** Geographic map extent */ private Envelope mapExtent =3D null; - + =20 /** Graphics object to be rendered to. Controlled by set output. */ private Graphics2D outputGraphics; - + =20 /** The size of the output area in output units. */ private Rectangle screenSize; - + =20 /** * This flag is set to false when starting rendering, and will be ch= ecked during the rendering * loop in order to make it stop forcefully */ private boolean renderingStopRequested; - + =20 /** * The ratio required to scale the features to be rendered so that t= hey fit into the output * space. */ private double scaleDenominator; - + =20 /** Maximun displacement for generalization during rendering */ private double generalizationDistance =3D 1.0; - + =20 /** Factory that will resolve symbolizers into rendered styles */ private SLDStyleFactory styleFactory =3D new SLDStyleFactory(); - + =20 LabelCache labelCache=3Dnew LabelCacheDefault(); =20 /** The painter class we use to depict shapes onto the screen */ private StyledShapePainter painter =3D new StyledShapePainter(labelC= ache); - + =20 /** The math transform cache */ private HashMap transformMap =3D new HashMap(); - + =20 /** Set to false if the reprojection fails */ private boolean canTransform =3D true; - - + =20 + =20 private IndexedFeatureResults indexedFeatureResults; =20 private ListenerList renderListeners=3D new ListenerList(); - + =20 private RenderingHints java2dHints; =20 private boolean optimizedDataLoadingEnabledDEFAULT =3D false; @@ -221,62 +239,61 @@ */ private Map rendererHints =3D null; =20 - + =20 /** * Creates a new instance of LiteRenderer without a context. Use it = only to gain access to * utility methods of this class or if you want to render random fea= ture collections instead of * using the map context interface */ - public StreamingRenderer()=20 - { + public StreamingRenderer() { addRenderListener(DEFAULT_LISTENER); } - - + =20 + =20 /** * Sets the flag which controls behaviour for applying affine transf= ormation to the graphics * object. - *=20 + * * @param flag If true then the transform will be concatenated to th= e existing transform. If * false it will be replaced. */ private void setConcatTransforms( boolean flag ) { concatTransforms =3D flag; } - + =20 /** * Returns the amount of time the renderer waits for loading an exte= rnal image before giving up * and examining the other images in the Graphic object - *=20 + * * @return the timeout in milliseconds */ private static long getImageLoadingTimeout() { return ImageLoader.getTimeout(); } - + =20 /** * Sets the maximum time to wait for getting an external image. Set = it to -1 to wait * undefinitely. The default value is 10 seconds - *=20 + * * @param newTimeout the new timeout value in milliseconds */ private static void setImageLoadingTimeout( long newTimeout ) { ImageLoader.setTimeout(newTimeout); } - + =20 /** * Flag which controls behaviour for applying affine transformation = to the graphics object. - *=20 + * * @return a boolean flag. If true then the transform will be concat= enated to the existing * transform. If false it will be replaced. */ private boolean getConcatTransforms() { return concatTransforms; } - + =20 /** * Called before {@link render}, this sets where any output will be = sent. - *=20 + * * @param g A graphics object for future rendering to be sent to. No= te: must be an instance of * lite renderer. * @param bounds The size of the output area, required so that scale= can be calculated. @@ -288,9 +305,9 @@ } /** * adds a listener that responds to error events of feature rendered= events. - *=20 + * * @see RenderListener - *=20 + * * @param listener the listener to add. */ public void addRenderListener(RenderListener listener){ @@ -298,9 +315,9 @@ } /** * Removes a render listener. - *=20 + * * @see RenderListener - *=20 + * * @param listener the listener to remove. */ public void removeRenderListener(RenderListener listener){ @@ -314,7 +331,7 @@ listener.featureRenderer(feature); } } - + =20 private void fireErrorEvent(Exception e) { Object[] objects=3DrenderListeners.getListeners(); for( int i =3D 0; i < objects.length; i++ ) { @@ -322,34 +339,34 @@ listener.errorOccurred(e); } } - =20 + =20 /** * Setter for property scaleDenominator. - *=20 + * * @param scaleDenominator New value of property scaleDenominator. */ private void setScaleDenominator( double scaleDenominator ) { this.scaleDenominator =3D scaleDenominator; } - + =20 /** * If you call this method from another thread than the one that cal= led <code>paint</code> or * <code>render</code> the rendering will be forcefully stopped befo= re termination */ public void stopRendering() { renderingStopRequested =3D true; - labelCache.stop(); + labelCache.stop(); } - + =20 /** Renders features based on the map layers and their styles as spe= cified - * in the map context using <code>setContext</code>.=20 + * in the map context using <code>setContext</code>. * <p/> * This version of the method assumes that the size of the output ar= ea * and the transformation from coordinates to pixels are known. * The latter determines the map scale. The viewport (the visible * part of the map) will be calculated internally. - *=20 + * * @param graphics The graphics object to draw to. * @param paintArea The size of the output area in output units (eg:= pixels). * @param worldToScreen A transform which converts World coordinates= to Screen coordinates. @@ -371,14 +388,14 @@ fireErrorEvent(new Exception("Can't create pixel to world tr= ansform", e)); } } - + =20 /** Renders features based on the map layers and their styles as spe= cified - * in the map context using <code>setContext</code>.=20 + * in the map context using <code>setContext</code>. * <p/> * This version of the method assumes that the area of the visible p= art * of the map and the size of the output area are known. The transfo= rm * between the two is calculated internally. - *=20 + * * @param graphics The graphics object to draw to. * @param paintArea The size of the output area in output units (eg:= pixels). * @param envelope the map's visible area (viewport) in map coordina= tes. @@ -388,46 +405,46 @@ LOGGER.info("renderer passed null arguments"); return; } //Other arguments get checked later - paint(graphics, paintArea, mapArea, worldToScreenTransform(mapAr= ea, paintArea)); + paint(graphics, paintArea, mapArea, RendererUtilities.worldToScr= eenTransform(mapArea, paintArea)); } - =20 - /** - * Renders features based on the map layers and their styles as = specified - * in the map context using <code>setContext</code>.=20 - * <p/> - * This version of the method assumes that paint area, enelope a= nd - * worldToScreen transform are already computed. Use this method= to - * avoid recomputation. <b>Note however that no check is perform= ed that - * they are really in sync!<b/> - *=20 - * @param graphics The graphics object to draw to. - * @param paintArea The size of the output area in output units = (eg: pixels). - * @param envelope the map's visible area (viewport) in map coor= dinates. - * @param worldToScreen A transform which converts World coordin= ates to Screen coordinates. - */ - public void paint( Graphics2D graphics, Rectangle paintArea, - Envelope mapArea, AffineTransform worldToScreen) { - //Check for null arguments, recompute missing ones if possib= le - if (graphics =3D=3D null || paintArea =3D=3D null) { + =20 + /** + * Renders features based on the map layers and their styles as spec= ified + * in the map context using <code>setContext</code>. + * <p/> + * This version of the method assumes that paint area, enelope and + * worldToScreen transform are already computed. Use this method to + * avoid recomputation. <b>Note however that no check is performed t= hat + * they are really in sync!<b/> + * + * @param graphics The graphics object to draw to. + * @param paintArea The size of the output area in output units (eg:= pixels). + * @param envelope the map's visible area (viewport) in map coordina= tes. + * @param worldToScreen A transform which converts World coordinates= to Screen coordinates. + */ + public void paint( Graphics2D graphics, Rectangle paintArea, + Envelope mapArea, AffineTransform worldToScreen) { + //Check for null arguments, recompute missing ones if possible + if (graphics =3D=3D null || paintArea =3D=3D null) { + LOGGER.info("renderer passed null arguments"); + return; + } else if (mapArea =3D=3D null && paintArea =3D=3D null) { + LOGGER.info("renderer passed null arguments"); + return; + } else if (mapArea =3D=3D null){ + try{ + mapArea =3D RendererUtilities.createMapEnvelope( + paintArea, worldToScreen); + } catch (NoninvertibleTransformException e) { + //TODO: Throw error here as in the other paint method? LOGGER.info("renderer passed null arguments"); return; - } else if (mapArea =3D=3D null && paintArea =3D=3D null) { - LOGGER.info("renderer passed null arguments"); - return; - } else if (mapArea =3D=3D null){ - try{ - mapArea =3D RendererUtilities.createMapEnvelope( - paintArea, worldToScreen); - } catch (NoninvertibleTransformException e) { - //TODO: Throw error here as in the other paint metho= d? - LOGGER.info("renderer passed null arguments"); - return; - } - } else if (worldToScreen =3D=3D null){ - worldToScreen =3D RendererUtilities.worldToScreenTransfo= rm( - mapArea, paintArea); } - + } else if (worldToScreen =3D=3D null){ + worldToScreen =3D RendererUtilities.worldToScreenTransform( + mapArea, paintArea); + } + =20 error =3D 0; if ( java2dHints !=3D null ) graphics.setRenderingHints(java2dHints); @@ -453,45 +470,44 @@ //setScaleDenominator(1 / at.getScaleX()); //DJB old method =20 try{ - setScaleDenominator( calculateScale(mapArea,context.getCoordin= ateReferenceSystem(),paintArea.width,paintArea.height,90));// 90 =3D OGC = standard DPI (see SLD spec page 37) + setScaleDenominator( RendererUtilities.calculateScale(mapAr= ea,context.getCoordinateReferenceSystem(),paintArea.width,paintArea.heigh= t,90));// 90 =3D OGC standard DPI (see SLD spec page 37) + } catch (Exception e) // probably either (1) no CRS (2) error xf= orming + { + setScaleDenominator(1 / at.getScaleX()); //DJB old method - = the best we can do } - catch (Exception e) // probably either (1) no CRS (2) error xfor= ming - { - setScaleDenominator(1 / at.getScaleX()); //DJB old method - the= best we can do - } =20 MapLayer[] layers =3D context.getLayers(); // get detstination CRS CoordinateReferenceSystem destinationCrs =3D context.getCoordina= teReferenceSystem(); -=20 + =20 labelCache.start(); for( int i =3D 0; i < layers.length; i++ ) //DJB: for each layer= (ie. one SLD or one LAYER=3D STYLE=3D for WMS request) { MapLayer currLayer =3D layers[i]; - + =20 if (!currLayer.isVisible()) { // Only render layer when layer is visible continue; } - + =20 if (renderingStopRequested) { return; } labelCache.startLayer(); try { // DJB: get a featureresults (so you can get a feature r= eader) for the data - FeatureResults results =3D queryLayer(currLayer, mapArea= , destinationCrs); =20 - + FeatureResults results =3D queryLayer(currLayer, mapArea= , destinationCrs); + =20 // extract the feature type stylers from the style objec= t // and process them - this.screenSize =3D paintArea;=20 - processStylers(graphics, results, currLayer.getStyle().getFeatureTyp= eStyles(), at, + this.screenSize =3D paintArea; + processStylers(graphics, results, currLayer.getStyle().g= etFeatureTypeStyles(), at, context.getCoordinateReferenceSystem(), currLayer.getFeatureSource().getSchema().getDefa= ultGeometry().getCoordinateSystem()); //src CRS } catch (Exception exception) { fireErrorEvent(new Exception("Exception rendering layer = " + currLayer,exception)); } - + =20 labelCache.endLayer(graphics, screenSize); } =20 @@ -504,52 +520,8 @@ LOGGER.warning("Number of Errors during paint(Graphics2D, Af= fineTransform) =3D " + error); } } - - /** - * Find the scale denominator of the map. - * Method: - * 1. find the diagonal distance (meters) - * 2. find the diagonal distance (pixels) - * 3. find the diagonal distance (meters) -- use DPI - * 4. calculate scale (#1/#2) - *=20 - * NOTE: return the scale denominator not the actual scale (1/scale = =3D denominator) - *=20 - * TODO: (SLD spec page 28): - * Since it is common to integrate the output of multiple servers into= a single displayed result in the=20 - * web-mapping environment, it is important that different map servers= have consistent behaviour with respect to=20 - * processing scales, so that all of the independent servers will sele= ct or deselect rules at the same scales. - * To insure consistent behaviour, scales relative to coordinate space= s must be handled consistently between map=20 - * servers. For geographic coordinate systems, which use angular units= , the angular coverage of a map should be=20 - * converted to linear units for computation of scale by using the cir= cumference of the Earth at the equator and=20 - * by assuming perfectly square linear units. For linear coordinate sy= stems, the size of the coordinate space=20 - * should be used directly without compensating for distortions in it = with respect to the shape of the real Earth. - *=20 - * NOTE: we are actually doing a a much more exact calculation, and ac= counting for non-square pixels (which are allowed in WMS) - *=20 - * @param envelope - * @param coordinateReferenceSystem - * @param imageWidth - * @param imageHeight - * @param DPI screen dots per inch (OGC standard is 90) - * @return - */ - private static double calculateScale(Envelope envelope, CoordinateRefer= enceSystem coordinateReferenceSystem,int imageWidth,int imageHeight,doubl= e DPI) throws Exception=20 - { - double diagonalGroundDistance =3D CRS.distance( - new Coordinate(envelope.getMinX(),envelope.getMinY()), - new Coordinate(envelope.getMaxX(),envelope.getMaxY()), - coordinateReferenceSystem - ); - // pythagorus theorm - double diagonalPixelDistancePixels =3D Math.sqrt( imageWidth*imageWidt= h+imageHeight*imageHeight); - double diagonalPixelDistanceMeters =3D diagonalPixelDistancePixels / D= PI * 2.54 / 100; // 2.54 =3D cm/inch, 100=3D cm/m - =09 - - return diagonalGroundDistance/diagonalPixelDistanceMeters; // remember= , this is the denominator, not the actual scale; - } - - /** + =20 + /** * Queries a given layer's features to be rendered based on the targ= et rendering bounding box. * <p> * If <code>optimizedDataLoadingEnabled</code> attribute has been se= t to <code>true</code>, @@ -576,7 +548,7 @@ * <code>paint(Graphics2D, Rectangle, AffineTransform)</code>. It is= package protected just * to allow unit testing it. * </p> - *=20 + * * @param currLayer the actually processing layer for renderition * @param envelope the spatial extent wich is the target area fo the= rendering process * @param destinationCrs DOCUMENT ME! @@ -587,7 +559,10 @@ * @throws IllegalAttributeException * @see MapLayer#setQuery(org.geotools.data.Query) */ - private FeatureResults queryLayer( MapLayer currLayer, Envelope enve= lope, + /* + * Default visibility for testing purposes + */ + FeatureResults queryLayer( MapLayer currLayer, Envelope envelope, CoordinateReferenceSystem destinationCrs ) throws IllegalFil= terException, IOException, IllegalAttributeException { FeatureResults results =3D null; @@ -595,11 +570,11 @@ FeatureType schema =3D featureSource.getSchema(); Query query =3D Query.ALL; MathTransform transform =3Dnull; - + =20 if (isOptimizedDataLoadingEnabled()) { // see what attributes we really need by exploring the style= s String[] attributes =3D findStyleAttributes(currLayer, schem= a); - + =20 try { // Then create the geometry filters. We have to create o= ne for each // geometric @@ -607,22 +582,20 @@ // than one // and the styles could use non default geometric ones CoordinateReferenceSystem sourceCrs =3D currLayer.getFea= tureSource().getSchema() - .getDefaultGeometry().getCoordinateSystem(); - + .getDefaultGeometry().getCoordinateSystem(); + =20 if (sourceCrs !=3D null && !sourceCrs.equals(destination= Crs)) { // get an unprojected envelope since the feature sou= rce is operating on // unprojected geometries transform =3D operationFactory.createOperation(desti= nationCrs,sourceCrs).getMathTransform(); - if (transform !=3D null && !transform.isIdentity()) - { - // Envelope eee=3D JTS.transform(envelope, trans= form);// this is the old way - //10 =3D make 10 points on each side of the bbo= x & transform the polygon + if (transform !=3D null && !transform.isIdentity()) = { + // Envelope eee=3D JTS.transform(envelope, tran= sform);// this is the old way + //10 =3D make 10 points on each side of the bbox= & transform the polygon envelope =3D JTS.transform(envelope, transform,1= 0); // this will usually be a "bigger" bbox - } - else - transform =3D null; //reset transform + } else + transform =3D null; //reset transform } - + =20 Filter filter =3D null; if (!isMemoryPreloadingEnabled()) { BBoxExpression rightBBox =3D filterFactory.createBBo= xExpression(envelope); @@ -630,7 +603,7 @@ } else { filter =3D Filter.NONE; } - + =20 // now build the query using only the attributes and the= bounding // box needed DefaultQuery q =3D new DefaultQuery(schema.getTypeName()= ); @@ -657,11 +630,11 @@ query =3D q; } } - + =20 // now, if a definition query has been established for this laye= r, be // sure to respect it by combining it with the bounding box one. Query definitionQuery =3D currLayer.getQuery(); - + =20 if (definitionQuery !=3D Query.ALL) { if (query =3D=3D Query.ALL) { query =3D definitionQuery; @@ -671,49 +644,44 @@ } =20 if (!(query instanceof DefaultQuery)) - query =3D new DefaultQuery(query); - =20 + query =3D new DefaultQuery(query); + =20 ((DefaultQuery)query).setCoordinateSystem( - currLayer.getFeatureSource().getSchema().getDefaultGeometry().= getCoordinateSystem()); - =09 - - if (isMemoryPreloadingEnabled())=20 - { + currLayer.getFeatureSource().getSchema().getDefaultGeome= try().getCoordinateSystem()); + =20 + =20 + if (isMemoryPreloadingEnabled()) { // TODO: attache a feature listener, we must erase the memor= y cache if // anything changes in the data store - if (indexedFeatureResults =3D=3D null)=20 - { + if (indexedFeatureResults =3D=3D null) { indexedFeatureResults =3D new IndexedFeatureResults(feat= ureSource.getFeatures(query)); } indexedFeatureResults.setQueryBounds(envelope); results =3D indexedFeatureResults; - }=20 - else=20 - { // insert a debug point here to check your query + } else { // insert a debug point here to check your query results =3D featureSource.getFeatures(query); } - + =20 return results; } - + =20 /** - * @return - */ - private boolean isMemoryPreloadingEnabled()=20 - { - if (rendererHints =3D=3D null) - return memoryPreloadingEnabledDEFAULT; - Boolean result =3D (Boolean) rendererHints.get("memoryPreloadingEna= bled"); - if (result =3D=3D null) - return memoryPreloadingEnabledDEFAULT; + * @return + */ + private boolean isMemoryPreloadingEnabled() { + if (rendererHints =3D=3D null) + return memoryPreloadingEnabledDEFAULT; + Boolean result =3D (Boolean) rendererHints.get("memoryPreloading= Enabled"); + if (result =3D=3D null) + return memoryPreloadingEnabledDEFAULT; return result.booleanValue(); - } - - - /** + } + =20 + =20 + /** * Inspects the <code>MapLayer</code>'s style and retrieves it's nee= ded attribute names, * returning at least the default geometry attribute name. - *=20 + * * @param layer the <code>MapLayer</code> to determine the needed at= tributes from * @param schema the <code>layer</code>'s featuresource schema * @return the minimun set of attribute names needed to render <code= >layer</code> @@ -721,9 +689,9 @@ private String[] findStyleAttributes( MapLayer layer, FeatureType sc= hema ) { StyleAttributeExtractor sae =3D new StyleAttributeExtractor(); sae.visit(layer.getStyle()); - + =20 String[] ftsAttributes =3D sae.getAttributeNames(); - + =20 /* * GR: if as result of sae.getAttributeNames() ftsAttributes alr= eady contains geometry * attribue names, they gets duplicated, wich produces an error = in AbstracDatastore when @@ -734,30 +702,30 @@ List atts =3D new LinkedList(Arrays.asList(ftsAttributes)); AttributeType[] attTypes =3D schema.getAttributeTypes(); String attName; - + =20 for( int i =3D 0; i < attTypes.length; i++ ) { attName =3D attTypes[i].getName(); - + =20 //DJB: This geometry check was commented out. I think it sh= ould actually be back in or // you get ALL the attributes back, which isnt what you = want. - //ALX: For rasters I need even the "grid" attribute. - if ((attTypes[i].isGeometry() || attTypes[i].getName().equal= sIgnoreCase("grid")) && !atts.contains(attName)) { + //ALX: For rasters I need even the "grid" attribute. + if ((attTypes[i] instanceof GeometryAttributeType || attType= s[i].getName().equalsIgnoreCase("grid")) && !atts.contains(attName)) { atts.add(attName); LOGGER.fine("added attribute " + attName); } } - + =20 ftsAttributes =3D new String[atts.size()]; atts.toArray(ftsAttributes); - + =20 return ftsAttributes; } - + =20 /** * Creates the bounding box filters (one for each geometric attribut= e) needed to query a * <code>MapLayer</code>'s feature source to return just the feature= s for the target * rendering extent - *=20 + * * @param schema the layer's feature source schema * @param attributes set of needed attributes * @param bbox the expression holding the target rendering bounding = box @@ -767,9 +735,9 @@ * @throws IllegalFilterException if something goes wrong creating t= he filter */ private Filter createBBoxFilters( FeatureType schema, String[] attri= butes, BBoxExpression bbox ) - throws IllegalFilterException { + throws IllegalFilterException { Filter filter =3D null; - + =20 for( int j =3D 0; j < attributes.length; j++ ) { AttributeType attType =3D schema.getAttributeType(attributes= [j]); =20 @@ -777,19 +745,19 @@ if (attType =3D=3D null) { LOGGER.fine("Could not find '"+attributes[j]+"' in the Feat= ureType ("+schema.getTypeName()+")"); - throw new IllegalFilterException("Could not find '"+attribu= tes[j]+"' in the FeatureType ("+schema.getTypeName()+")"); + throw new IllegalFilterException("Could not find '"+attr= ibutes[j]+"' in the FeatureType ("+schema.getTypeName()+")"); } - - if (attType.isGeometry()) { + =20 + if (attType instanceof GeometryAttributeType) { GeometryFilter gfilter =3D filterFactory.createGeometryF= ilter(Filter.GEOMETRY_BBOX); - + =20 // TODO: how do I get the full xpath of an attribute sho= uld // feature composition be used? Expression left =3D filterFactory .createAttributeExpression(schema, attType.getNa= me()); gfilter.addLeftGeometry(left); gfilter.addRightGeometry(bbox); - + =20 if (filter =3D=3D null) { filter =3D gfilter; } else { @@ -797,17 +765,17 @@ } } } - + =20 return filter; } - + =20 /** * Performs the actual rendering process to the graphics context set= in setOutput. * <p> * The style parameter controls the appearance features. Rules withi= n the style object may cause * some features to be rendered multiple times or not at all. * </p> - *=20 + * * @param features the feature collection to be rendered * @param map Controls the full extent of the input space. Used in t= he calculation of scale. * @param s A style object. Contains a set of FeatureTypeStylers tha= t are to be applied in order @@ -816,19 +784,19 @@ private void render( FeatureCollection features, Envelope map, Style= s ) { if (outputGraphics =3D=3D null) { LOGGER.info("renderer passed null graphics"); - + =20 return; } - + =20 // reset the abort flag renderingStopRequested =3D false; - - =20 + =20 + =20 mapExtent =3D map; - + =20 // set up the affine transform and calculate scale values - AffineTransform at =3D worldToScreenTransform(mapExtent, screenS= ize); - + AffineTransform at =3D RendererUtilities.worldToScreenTransform(= mapExtent, screenSize); + =20 /* * If we are rendering to a component which has already set up s= ome form of transformation * then we can concatenate our transformation to it. An example = of this is the ZoomPane @@ -840,10 +808,10 @@ // outputGraphics.setTransform(at); // } scaleDenominator =3D 1 / outputGraphics.getTransform().getScaleX= (); - + =20 // extract the feature type stylers from the style object and pr= ocess them FeatureTypeStyle[] featureStylers =3D s.getFeatureTypeStyles(); - + =20 try { processStylers(outputGraphics, DataUtilities.results(feature= s), featureStylers, at, null,null); @@ -853,31 +821,10 @@ fireErrorEvent(new Exception("Illegal attribute exception wh= ile rendering the layer" ,iae)); } } - + =20 /** - * Sets up the affine transform - *=20 - * @param mapExtent the map extent - * @param screenSize the screen size - * @return a transform that maps from real world coordinates to the = screen - */ - public AffineTransform worldToScreenTransform( Envelope mapExtent, R= ectangle screenSize ) { - double scaleX =3D screenSize.getWidth() / mapExtent.getWidth(); - double scaleY =3D screenSize.getHeight() / mapExtent.getHeight()= ; - - double tx =3D -mapExtent.getMinX() * scaleX ; - double ty =3D (mapExtent.getMinY() * scaleY) + screenSize.getHei= ght(); - =20 - AffineTransform at =3D new AffineTransform(scaleX, 0.0d, 0.0d, -= scaleY, tx, ty); - AffineTransform originTranslation=3DAffineTransform.getTranslate= Instance(screenSize.x, screenSize.y); - originTranslation.concatenate(at); - - return originTranslation!=3Dnull?originTranslation:at; - } - - /** * Converts a coordinate expressed on the device space back to real = world coordinates - *=20 + * * @param x horizontal coordinate on device space * @param y vertical coordinate on device space * @param map The map extent @@ -886,13 +833,13 @@ private Coordinate pixelToWorld( int x, int y, Envelope map ) { if (outputGraphics =3D=3D null) { LOGGER.info("no graphics yet deffined"); - + =20 return null; } - + =20 // set up the affine transform and calculate scale values - AffineTransform at =3D worldToScreenTransform(map, screenSize); - + AffineTransform at =3D RendererUtilities.worldToScreenTransform(= map, screenSize); + =20 /* * If we are rendering to a component which has already set up s= ome form of transformation * then we can concatenate our transformation to it. An example = of this is the ZoomPane @@ -903,69 +850,66 @@ } else { outputGraphics.setTransform(at); } - + =20 try { Point2D result =3D at.inverseTransform(new java.awt.geom.Poi= nt2D.Double(x, y), new java.awt.geom.Point2D.Double()); Coordinate c =3D new Coordinate(result.getX(), result.getY()= ); - + =20 return c; } catch (Exception e) { fireErrorEvent(e); } - + =20 return null; } - + =20 /** * Checks if a rule can be triggered at the current scale level - *=20 + * * @param r The rule * @return true if the scale is compatible with the rule settings */ private boolean isWithInScale( Rule r ) { return ((r.getMinScaleDenominator() - TOLERANCE) <=3D scaleDenom= inator) - && ((r.getMaxScaleDenominator() + TOLERANCE) > scaleDeno= minator); + && ((r.getMaxScaleDenominator() + TOLERANCE) > scaleDenominator)= ; } =20 /** * creates a list of LiteFeatureTypeStyles * a) out-of-scale rules removed * b) incompatible FeatureTypeStyles removed - * =20 - *=20 + * + * * @param featureStylers * @param features * @return * @throws Exception */ - private ArrayList createLiteFeatureTypeStyles( FeatureTypeStyle[] fe= atureStylers,FeatureResults features, Graphics2D graphics) throws IOExcep= tion - { - ArrayList result =3D new ArrayList(); - =09 - int itemNumber =3D0; - =09 + private ArrayList createLiteFeatureTypeStyles( FeatureTypeStyle[] fe= atureStylers,FeatureResults features, Graphics2D graphics) throws IOExcep= tion { + ArrayList result =3D new ArrayList(); + =20 + int itemNumber =3D0; + =20 for( int i =3D 0; i < featureStylers.length; i++ ) //DJB: for ea= ch FeatureTypeStyle in the SLD (each on is drawn indpendently) { FeatureTypeStyle fts =3D featureStylers[i]; String typeName =3D features.getSchema().getTypeName(); - + =20 if ((typeName !=3D null) - && (features.getSchema().isDescendedFrom(null, - fts.getFeatureTypeName()) || typeName.equals= IgnoreCase(fts - .getFeatureTypeName())))=20 - { - //DJB: this FTS is compatible with this FT. - =09 + && (features.getSchema().isDescendedFrom(null, + fts.getFeatureTypeName()) || typeName.equalsIgnoreCa= se(fts + .getFeatureTypeName()))) { + //DJB: this FTS is compatible with this FT. + =20 // get applicable rules at the current scale Rule[] rules =3D fts.getRules(); ArrayList ruleList =3D new ArrayList(); ArrayList elseRuleList =3D new ArrayList(); - - for( int j =3D 0; j < rules.length; j++ )=20 - { + =20 + for( int j =3D 0; j < rules.length; j++ ) { Rule r =3D rules[j]; - + =20 if (isWithInScale(r)) { if (r.hasElseFilter()) { elseRuleList.add(r); @@ -975,18 +919,16 @@ } } if ( (ruleList.size() =3D=3D 0) && (elseRuleList.size()=3D= =3D0) ) - continue; //DJB: optimization - nothing to render, don= t do anything!! + continue; //DJB: optimization - nothing to render, = dont do anything!! =20 LiteFeatureTypeStyle lfts =3Dnull; if (itemNumber =3D=3D 0) //we can optimize this one! { - lfts =3D new LiteFeatureTypeStyle(graphics,ruleList,els= eRuleList); + lfts =3D new LiteFeatureTypeStyle(graphics,ruleList,= elseRuleList); + } else { + BufferedImage image =3D new BufferedImage(screenSize= .width, screenSize.height,defaultImageType); + lfts =3D new LiteFeatureTypeStyle(image,graphics.get= Transform(),ruleList,elseRuleList,java2dHints); } - else - { - BufferedImage image =3D new BufferedImage(screenSize.wi= dth, screenSize.height,defaultImageType); =20 - lfts =3D new LiteFeatureTypeStyle(image,graphics.get= Transform(),ruleList,elseRuleList,java2dHints); =09 - } result.add(lfts); itemNumber++; =20 @@ -995,44 +937,40 @@ =20 return result; } - - private FeatureReader getReader(FeatureResults features,CoordinateRe= ferenceSystem sourceCrs) throws IOException - { - FeatureReader reader =3D features.reader(); - =20 - //DJB: dont do reprojection here - do it after decimation - // but we ensure that the reader is producing geometries wi= th the correct CRS - //NOTE: it, by default, produces ones that are are tagged with = the CRS of the datastore, which - // maybe incorrect. - // The correct value is in sourceCrs. - =20 - // this is the reader's CRS - CoordinateReferenceSystem rCS =3D reader.getFeatureType().getDe= faultGeometry().getCoordinateSystem(); - =20 - // sourceCrs =3D=3D source's real SRS - =20 - //if we need to recode the incoming geometries - =20 - if (rCS !=3D sourceCrs) //not both null or both EXACTLY the sa= me CRS object - { - if (sourceCrs !=3D null) //dont re-tag to null, keep the DataS= tore's CRS (this shouldnt really happen) - { - // if the datastore is producing null CRS, we recode. - // if the datastore's CRS !=3D real CRS, then we recode - if ( ( rCS =3D=3Dnull) || (!rCS .equals ( sourceCrs) )) - { - //need to retag the features - try{ - reader =3D new ForceCoordinateSystemFeatureReader(rea= der,sourceCrs ); - } - catch(Exception ee) - { - ee.printStackTrace(); // do nothing but warn user - } - } - } - } - return reader; + =20 + private FeatureReader getReader(FeatureResults features,CoordinateRe= ferenceSystem sourceCrs) throws IOException { + FeatureReader reader =3D features.reader(); + =20 + //DJB: dont do reprojection here - do it after decimation + // but we ensure that the reader is producing geometries wit= h the correct CRS + //NOTE: it, by default, produces ones that are are tagged with t= he CRS of the datastore, which + // maybe incorrect. + // The correct value is in sourceCrs. + =20 + // this is the reader's CRS + CoordinateReferenceSystem rCS =3D reader.getFeatureType().getDef= aultGeometry().getCoordinateSystem(); + =20 + // sourceCrs =3D=3D source's real SRS + =20 + //if we need to recode the incoming geometries + =20 + if (rCS !=3D sourceCrs) //not both null or both EXACTLY the sam= e CRS object + { + if (sourceCrs !=3D null) //dont re-tag to null, keep the Dat= aStore's CRS (this shouldnt really happen) + { + // if the datastore is producing null CRS, we recode. + // if the datastore's CRS !=3D real CRS, then we recode + if ( ( rCS =3D=3Dnull) || (!rCS .equals( sourceCrs) )) { + //need to retag the features + try{ + reader =3D new ForceCoordinateSystemFeatureReade= r(reader,sourceCrs ); + } catch(Exception ee) { + ee.printStackTrace(); // do nothing but warn use= r + } + } + } + } + return reader; } =20 =20 @@ -1051,7 +989,7 @@ * </p> * <p> * </p> - *=20 + * * @param graphics DOCUMENT ME! * @param features An array of features to be rendered * @param featureStylers An array of feature stylers to be applied @@ -1060,15 +998,14 @@ * @throws IOException DOCUMENT ME! * @throws IllegalAttributeException DOCUMENT ME! */ - private void processStylers(final Graphics2D graphics,=20 - final FeatureResults features, - final FeatureTypeStyle[] featureStylers,=20 - AffineTransform at, - CoordinateReferenceSystem destinationCrs, - CoordinateReferenceSystem sourceCrs - )=20 - throws IOException, IllegalAttributeException=20 - { + private void processStylers(final Graphics2D graphics, + final FeatureResults features, + final FeatureTypeStyle[] featureStylers, + AffineTransform at, + CoordinateReferenceSystem destinationCrs, + CoordinateReferenceSystem sourceCrs + ) + throws IOException, IllegalAttributeException { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("processing " + featureStylers.length + " styler= s for "+features.getSchema().getTypeName()); } @@ -1076,104 +1013,93 @@ transformMap =3D new HashMap(); NumberRange scaleRange =3D new NumberRange(scaleDenominator, sca= leDenominator); =20 - + =20 symbolizerAssociationHT =3D new HashMap(); ArrayList lfts=3D createLiteFeatureTypeStyles(featureStylers,fea= tures,graphics); if (lfts.size() =3D=3D0) - return; // nothing to do + return; // nothing to do FeatureReader reader =3D getReader(features,sourceCrs); int n_lfts =3D lfts.size(); LiteFeatureTypeStyle[] fts_array =3D (LiteFeatureTypeStyle[]) l= fts.toArray( new LiteFeatureTypeStyle[n_lfts] ); -=20 =20 + =20 try{ - =20 - while( true )=20 - { - try { - if (renderingStopRequested) { - break; - } =20 - if (!reader.hasNext()) { - break; - } - Feature feature =3D reader.next(); // read the feat= ure - for (int t=3D0;t<n_lfts;t++) - { - process(feature,fts_array[t],scaleRange,at,destina= tionCrs); //draw the feature on the image(s) - } - } - catch (Exception e) { + =20 + while( true ) { + try { + if (renderingStopRequested) { + break; + } + if (!reader.hasNext()) { + break; + } + Feature feature =3D reader.next(); // read the featu= re + for (int t=3D0;t<n_lfts;t++) { + process(feature,fts_array[t],scaleRange,at,desti= nationCrs); //draw the feature on the image(s) + } + } catch (Exception e) { fireErrorEvent(e); } - } - + } + =20 + } finally { + reader.close(); } - finally - { - reader.close(); - } //have to re-form the image now. - // graphics.setTransform( new AffineTransform() ); - for (int t=3D0;t<n_lfts;t++) - { - if (fts_array[t].myImage !=3D null) // this is the case for the= first one (ie. fts_array[t].graphics =3D=3D graphics) =09 + // graphics.setTransform( new AffineTransform() ); + for (int t=3D0;t<n_lfts;t++) { + if (fts_array[t].myImage !=3D null) // this is the case for = the first one (ie. fts_array[t].graphics =3D=3D graphics) { - graphics.drawImage(fts_array[t].myImage,0,0,null); - fts_array[t].graphics.dispose(); - } + graphics.drawImage(fts_array[t].myImage,0,0,null); + fts_array[t].graphics.dispose(); + } } - =20 - + =20 + =20 } - + =20 /** - * @param feature - * @param style - */ - final private void process(Feature feature, LiteFeatureTypeStyle style,= Range scaleRange,AffineTransform at, CoordinateReferenceSystem destinatio= nCrs) throws TransformException,FactoryException=20 - { - boolean doElse =3D true; - Rule[] elseRuleList =3D style.elseRules; - Rule[] ruleList =3D style.ruleList; - =09 - Graphics2D graphics =3D style.graphics; - =09 - // applicable rules - for( int t=3D0;t<ruleList.length;t++ )=20 - { - Rule r =3D ruleList[t]; - Filter filter =3D r.getFilter(); - - if ((filter =3D=3D null) || filter.contains(feature))=20 - { - doElse =3D false; =20 - Symbolizer[] symbolizers =3D r.getSymbolizers(); - processSymbolizers(graphics, feature, symbolizers, s= caleRange, - at, destinationCrs); =20 - } + * @param feature + * @param style + */ + final private void process(Feature feature, LiteFeatureTypeStyle sty= le,Range scaleRange,AffineTransform at, CoordinateReferenceSystem destina= tionCrs) throws TransformException,FactoryException { + boolean doElse =3D true; + Rule[] elseRuleList =3D style.elseRules; + Rule[] ruleList =3D style.ruleList; + =20 + Graphics2D graphics =3D style.graphics; + =20 + // applicable rules + for( int t=3D0;t<ruleList.length;t++ ) { + Rule r =3D ruleList[t]; + Filter filter =3D r.getFilter(); + =20 + if ((filter =3D=3D null) || filter.contains(feature)) { + doElse =3D false; + Symbolizer[] symbolizers =3D r.getSymbolizers(); + processSymbolizers(graphics, feature, symbolizers, scale= Range, + at, destinationCrs); + } } - - if (doElse)=20 - { - for( int tt=3D0;tt<elseRuleList.length;tt++ )=20 - { + =20 + if (doElse) { + for( int tt=3D0;tt<elseRuleList.length;tt++ ) { Rule r =3D elseRuleList[tt]; Symbolizer[] symbolizers =3D r.getSymbolizers(); - + =20 processSymbolizers(graphics, feature, symbolizers, scale= Range, at, destinationCrs); - =20 + =20 } } - } - - /** + } + =20 + /** * Applies each of a set of symbolizers in turn to a given feature. * <p> * This is an internal method and should only be called by processSt= ylers. * </p> - *=20 + * * @param graphics * @param feature The feature to be rendered * @param symbolizers An array of symbolizers which actually perform= the rendering. @@ -1182,48 +1108,42 @@ * @param shape * @param destinationCrs * @throws TransformException - * @throws FactoryException=20 + * @throws FactoryException */ private void processSymbolizers( final Graphics2D graphics, final Fe= ature feature, final Symbolizer[] symbolizers, Range scaleRange, AffineTran= sform at, - CoordinateReferenceSystem destinationCrs ) throws TransformE= xception, FactoryException=20 - { - LiteShape2 shape; - =09 - for( int m =3D 0; m < symbolizers.length; m++ )=20 - { - =20 - - if (symbolizers[m] instanceof RasterSymbolizer)=20 - { + CoordinateReferenceSystem destinationCrs ) throws TransformE= xception, FactoryException { + LiteShape2 shape; + =20 + for( int m =3D 0; m < symbolizers.length; m++ ) { + =20 + =20 + if (symbolizers[m] instanceof RasterSymbolizer) { AffineTransform tempTransform =3D graphics.getTransform(= ); graphics.setTransform(at); - renderRaster(graphics, feature, (RasterSymbolizer) symbo= lizers[m]); - graphics.setTransform(tempTransform); =20 - }=20 - else - { - Geometry g =3D findGeometry(feature, symbolizers[m]); //= pulls the geometry=20 + renderRaster(graphics, feature, (RasterSymbolizer) symbo= lizers[m], destinationCrs); + graphics.setTransform(tempTransform); + } else { + Geometry g =3D findGeometry(feature, symbolizers[m]); //= pulls the geometry =20 SymbolizerAssociation sa =3D (SymbolizerAssociation) sym= bolizerAssociationHT.get(symbolizers[m]); - if (sa=3D=3Dnull) - { - sa=3D new SymbolizerAssociation(); - sa.setCRS(findGeometryCS(feature, symbolizers[m])); - MathTransform2D transform =3D null; - try { - // DJB: this should never be necessary since we've = already taken care to make sure the reader is - // producing the correct coordinate system + if (sa=3D=3Dnull) { + sa=3D new SymbolizerAssociation(); + sa.setCRS(findGeometryCS(feature, symbolizers[m])); + MathTransform2D transform =3D null; + try { + // DJB: this should never be necessary since we'= ve already taken care to make sure the reader is + //... [truncated message content] |