/* * @(#)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
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
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
* 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();
}
}