/* * @(#)PolygonLayer.java 0.5 17 April 1997 James Macgill * */ package uk.ac.leeds.ccg.geotools; import java.util.*; import java.awt.*; import java.util.HashSet; /** * A layer for storing geographic features that can be represented by polygons. * A polygon layer maintains a list of GeoPolygons. If each polygon is properly * assigned an ID then this will be used for both Highlights and for Shade colour lookups.

* Used (Like other layers) in themes for display in a Viewer.

* * Improved selection painting speed by implementing method directly insted of using * SimpleLayers repeated calles to paintHighlight * * Now extends ShapeLayer, which manages much of the common code used by layers containg GeoShape features * * @version 0.7.0, 9 Dec 99 * @author James Macgill */ public class PolygonLayer extends ShapeLayer implements Layer,ScaleChangedListener{ /** * Holds the scaled version of the map if bufferScale is on */ protected Polygon polys[][]; protected int ids[]; GeoPoint[] labelPoints; /** * setting this to true will force the buffer to be updated on the next * call to paintScaled. Note this will not disable buffer all together. * after the buffer has been updated, this variable will be set to false. * if you want to disable buffering (why would you do that?), you'd need * to set bufferScale to false. */ protected boolean forceBufferFlush = true; ContiguityMatrix matrix = null; /** * default constructor for an empty layer */ public PolygonLayer(){ super(); } /** * Constructs a PolygonLayer with bounds but no polygons.
* Usefull if you know what the exact bounds of the layer will be * prior to adding all the GeoPolygons to the layer at a later stage, or * if you want the PolygonLayer to 'lie' about its extent. * * @param bounds A GeoRectangle representing a box that will atleast contain * all of the polygons in this layer. */ public PolygonLayer(GeoRectangle bounds){ super(bounds); } /** * Do we treat anticlockwise polygons as holes? * V.Experimental */ protected boolean anticlockHoles = false; /** * Adds the specified GeoPolygon this PolygonLayer * @param polygon The GeoPolygon to be added */ public void addGeoPolygon(GeoPolygon polygon) { this.addGeoPolygon(polygon, false); } /** * Adds the specified GeoPolygon this PolygonLayer * @param polygon The GeoPolygon to be added * @param keepquiet Tell the method not to call a LayerChangedEvent * after adding the polgyon. Setting this to true more or less implies * that you will do this yourselve. */ public void addGeoPolygon(GeoPolygon polygon, boolean keepQuiet) { this.setForceBufferFlush(true); super.addGeoShape(polygon, keepQuiet); } /** * Use to determine if scale buffering is available for this layer. * Layers that use this feature should overide this mehtod. * @return boolean true if scale buffering can be used. */ public boolean isScaleBufferImplemented(){ return true; } /** * Set anticlockwise polygons up as holes. * this is v.experimental at the moment. * it defaults to off. * @param flag boolean that is true if anticlockwise polygons should be holes. */ public void setAnticlockwiseHoles(boolean flag){ this.anticlockHoles = flag; } /** * are anticlockwise polygons treated as holes? */ public boolean isAnticlockwiseHoles(){ return this.anticlockHoles; } public void drawPolyFeature(Graphics g,Polygon p,int width){ g.drawPolygon(p.xpoints,p.ypoints,p.npoints); } public void fillPolyFeature(Graphics g,Polygon p){ g.fillPolygon(p.xpoints,p.ypoints,p.npoints); } /** * Paints a scaled version of the layer to the given graphics contex. *
Generaly only called by a theme that contains this layer. * @param gg A GeoGraphics containing all of the info needed to paint this layer to screen */ public void paintScaled(GeoGraphics gg){ Graphics g = gg.getGraphics(); Scaler scale = gg.getScale(); Shader shade = gg.getShade(); GeoData data = gg.getData(); GeoData labelData = gg.getLabelData(); System.out.println("Loaded labelData "+labelData); ShadeStyle style = gg.getStyle(); Filter filter = gg.getFilter(); if(style.isLabeled() && (labelPoints==null || labelPoints.length !=countPolygons())){ labelPoints = new GeoPoint[countPolygons()]; forceBufferFlush=true; } //Tepory polygons used during scaling. GeoPolygon scaledPolygon,temp,tempMain; int w = style.getLineWidth(); //Test to see if the scale has not changed since //the last redering && see if we keeped a buffer of the //map at that scale. if(isExtentSame(scale.getMapExtent()) && bufferScale==true && forceBufferFlush==false){ for(int i = 0;i < countPolygons();i++) { if(filter==null || filter.isVisible(ids[i])){ for(int j=0;j Generaly only called by the theme that holds this layer. *
The highlight style should be definable, but it isn't yet. * @param g The graphics to paint into * @param scale The scaler to use. * @param id The id of the polygon to highlight */ public void paintHighlight(Graphics g,Scaler scale,int id,ShadeStyle style){ GeoPolygon scaledPolygon; int w = style.getLineWidth(); for(int i = 0;i < countPolygons();i++) { GeoPolygon temp = (GeoPolygon)shapeList.elementAt(i); if(temp.getID()==id){ for(int j=0;j Generaly only called by the theme that holds this layer. *
The highlight style should be definable, but it isn't yet. * Modified to select all parts of a multi-part polygon. * @param g The graphics to paint into * @param scale The scaler to use. * @param id The id of the polygon to highlight */ public void paintSelection(Graphics g,Scaler scale,int ids[],ShadeStyle style){ GeoPolygon scaledPolygon; int w = style.getLineWidth(); for(int i = 0;i < countPolygons();i++) { GeoPolygon temp = (GeoPolygon)shapeList.elementAt(i); for(int j=0;j * In order to work properly scale buffering must be enabled, as this is the
* default behavour for shapelayers this should not be a problem. * @return Polygon[][] A two dimensional array of awt polygons,(the second dymension is for * multipart polygons). */ public Polygon[][] getScaledShapes(){ return (Polygon[][])polys.clone(); } /** * Used in conjunction with getScaledPolygons this provides the true id for each * shape in the set of scaled polygons **/ public int[] getScaledShapesIdList(){ return (int[])ids.clone(); } }