package uk.ac.leeds.ccg.geotools; import uk.ac.leeds.ccg.geotools.*; import java.awt.*; public class PointLayer extends uk.ac.leeds.ccg.geotools.ShapeLayer implements LockableSize { /** * debug switch. used to control debug output. Output will be identified with prefix 'PiLa>' */ private final static boolean DEBUG=false; protected int points[][]=null; protected int ids[]=null; protected int defaultSize = 4; /** * 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; public PointLayer(){ super(false); } public PointLayer(boolean useQuadtree){ super(useQuadtree); } public void addGeoPoint(GeoPoint p){ super.addGeoShape(p); } public void addGeoPoint(GeoPoint p,boolean quiet){ super.addGeoShape(p,quiet); } /** * Paints a scaled version of the layer to the given graphics contex. *
Generaly only called by a theme that contains this layer.
* 08/May/2000 - fixed bug#103835 bufferd redraw nologer throws null pointer exception. * @author James Macgill JM * @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(); ShadeStyle style = gg.getStyle(); Filter filter = gg.getFilter(); int p[],r; //if(!style.isFilled()&&!style.isOutlined()) return; GeoPoint temp; r = style.getLineWidth(); int id; //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 < countFeatures();i++) { if(points[i]==null) continue; p = points[i]; if(filter==null || filter.isVisible(ids[i])){ g.setColor(shade.getColor(data.getValue(ids[i]))); if( style.isFilled() ){ g.fillOval(p[0]-r,p[1]-r,2*r+1,2*r+1); } if( style.isOutlined() ) { if(!style.isLineColorFromShader()){ g.setColor(style.getLineColor()); } g.drawOval(p[0]-r,p[1]-r,2*r+1,2*r+1); } } } }else{ //we don't have a pre scaled version to hand //so we caclulate it now. if(bufferScale){ points = new int[countFeatures()][2]; ids = new int[countFeatures()]; } for(int i = 0;i < shapeList.size() ;i++) { temp = (GeoPoint)shapeList.elementAt(i); //Clip to visible area. if (temp.getBounds().createIntersect(scale.getMapExtent())==null){ continue; } p = scale.toGraphics(temp.getX(),temp.getY()); //Add thematic colour here id = temp.getID(); if(filter==null || filter.isVisible(id)){ double value = data.getValue(id); g.setColor(shade.getColor(value)); if(style.isFilled()){ g.fillOval(p[0]-r,p[1]-r,2*r+1,2*r+1); } if(style.isOutlined()){ if(!style.isLineColorFromShader()){ g.setColor(style.getLineColor()); } g.drawOval(p[0]-r,p[1]-r,2*r+1,2*r+1); } } if(bufferScale){ //keep a record of the scaled version points[i] = p; ids[i] = id; } temp = null; } // we've just updated the buffer, so why force it to flush? setForceBufferFlush(false); } } public void paintHighlight(Graphics g, Scaler scale, int id, ShadeStyle style) { int p[],r; r = style.getLineWidth(); for(int i = 0;i < shapeList.size();i++) { GeoPoint temp = (GeoPoint)shapeList.elementAt(i); if(temp.getID()==id){ p = scale.toGraphics(temp.getX(),temp.getY()); //Add thematic colour here g.setColor(style.getFillColor()); g.fillOval(p[0]-r,p[1]-r,2*r,2*r); g.drawOval(p[0]-r,p[1]-r,2*r,2*r); return; } } } public void setDefaultSize(int size){ defaultSize = size; } /** * Find the feature that contains this point. * Note This method will return the first feature found to contain the point only, * even if multiple, overlapping features, contain the same point. * @param point The GeoPoint to test each feature against. * @return int The ID of the first feature to contain this point, -1 if no feature was found */ public int getID(GeoPoint p,Scaler s){ double r = s.toMap(defaultSize); if(DEBUG)System.out.println("PiLa>Looking"); for(int i = 0;i < shapeList.size();i++) { GeoPoint temp = (GeoPoint)shapeList.elementAt(i); if(temp.getDistance(p)>=r){continue;} if(DEBUG)System.out.println("PiLa>Found one"); return temp.getID(); } return -1; } /** * Called when the scale last used to scale this layer has changed. * as a result the buffer is of no use and will have to be rebuilt next * paint scaled * @param sce A ScaleChangedEvent as thrown by a scaler. */ public void scaleChanged(ScaleChangedEvent sce){ lastScale = null; } /** * 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; } public void setForceBufferFlush(boolean newValue) { forceBufferFlush = newValue; } public boolean isForceBufferFlush() { return forceBufferFlush; } }