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;
}
}