diff --exclude .git -rupN ncWMS/src/java/uk/ac/rdg/resc/ncwms/controller/AbstractWmsController.java ncWMS-master/src/java/uk/ac/rdg/resc/ncwms/controller/AbstractWmsController.java --- ncWMS/src/java/uk/ac/rdg/resc/ncwms/controller/AbstractWmsController.java 2013-04-02 11:26:35.000000000 +0200 +++ ncWMS-master/src/java/uk/ac/rdg/resc/ncwms/controller/AbstractWmsController.java 2013-04-02 11:26:53.000000000 +0200 @@ -409,6 +409,7 @@ public abstract class AbstractWmsControl // This throws an InvalidFormatException if the MIME type is not supported ImageFormat imageFormat = ImageFormat.get(mimeType); float vectorScale = styleRequest.getVectorScale(); + float vectorStep = styleRequest.getVectorStep(); GetMapDataRequest dr = getMapRequest.getDataRequest(); @@ -500,6 +501,7 @@ public abstract class AbstractWmsControl .opacity(styleRequest.getOpacity()) .numColourBands(styleRequest.getNumColourBands()) .vectorScale(vectorScale) + .vectorStep(vectorStep) .units(layer.getUnits()) .equator_y_index(equator_y_index) .build(); diff --exclude .git -rupN ncWMS/src/java/uk/ac/rdg/resc/ncwms/controller/GetMapStyleRequest.java ncWMS-master/src/java/uk/ac/rdg/resc/ncwms/controller/GetMapStyleRequest.java --- ncWMS/src/java/uk/ac/rdg/resc/ncwms/controller/GetMapStyleRequest.java 2013-04-02 11:26:35.000000000 +0200 +++ ncWMS-master/src/java/uk/ac/rdg/resc/ncwms/controller/GetMapStyleRequest.java 2013-04-02 11:26:53.000000000 +0200 @@ -56,6 +56,7 @@ public class GetMapStyleRequest // colour scale private Range colorScaleRange; private float vectorScale; + private float vectorStep; /** * Creates a new instance of GetMapStyleRequest from the given parameters @@ -92,6 +93,7 @@ public class GetMapStyleRequest this.numColourBands = getNumColourBands(params); this.logarithmic = isLogScale(params); this.vectorScale = Float.parseFloat(params.getString("vectorScale", "1").toLowerCase()); + this.vectorStep = Float.parseFloat(params.getString("vectorStep", "1").toLowerCase()); } /** @@ -224,5 +226,8 @@ public class GetMapStyleRequest { return vectorScale; } - + public float getVectorStep() + { + return vectorStep; + } } diff --exclude .git -rupN ncWMS/src/java/uk/ac/rdg/resc/ncwms/graphics/ImageProducer.java ncWMS-master/src/java/uk/ac/rdg/resc/ncwms/graphics/ImageProducer.java --- ncWMS/src/java/uk/ac/rdg/resc/ncwms/graphics/ImageProducer.java 2013-04-02 11:26:35.000000000 +0200 +++ ncWMS-master/src/java/uk/ac/rdg/resc/ncwms/graphics/ImageProducer.java 2013-04-02 11:26:53.000000000 +0200 @@ -85,6 +85,7 @@ public final class ImageProducer * The scale factor between vectors */ private float vectorScale; + private float vectorStep; private String units; private int equator_y_index; private float arrowLength = 14.0f; @@ -207,23 +208,26 @@ public final class ImageProducer } Graphics2D g = image.createGraphics(); - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF); + // NOTE: this turns off antialiasing !! + // for the vector scaling we'd like to enable antialiasing but it behaves strangely so we can't :| + //g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); g.setColor(new Color(0,0,0,100)); //logger.debug("Drawing vectors, length = {} pixels", this.arrowLength); //List east = data.get(0); //List north = data.get(1); - float stepScale = 1.1f; - float imageLength = this.arrowLength; + // the vectorStep defines the distance between each vector symbol + // it is defined as a function of the size of the symbol glyph, multiplied by + // a scaling factor supplied in the request (default = 1), plus a small margin + // of 5 we found to be suitable for our data if (this.style == Style.BARB) { - imageLength = this.barbLength * this.vectorScale; - stepScale = 1.2f * this.vectorScale; - } else { - imageLength = this.arrowLength * this.vectorScale; - stepScale = 1.1f * this.vectorScale; - } + vectorStep = 5 + this.barbLength * vectorStep; + } else { + vectorStep = 5 + this.arrowLength * vectorStep; + } int index; int dataIndex; @@ -231,10 +235,19 @@ public final class ImageProducer Double mag; Float eastVal; Float northVal; + - for (int i = 0; i < this.picWidth; i += Math.ceil(imageLength + stepScale)) + // get the min and max of the data, will be used to scale the vectors + // relative to the max and min (for non-barb vector styles) + float scaleMin = this.scaleRange.getMinimum().floatValue(); + float scaleMax = this.scaleRange.getMaximum().floatValue(); + //logger.debug("vector step = {} ", vectorStep); + //logger.debug("vector scale = {} ", this.vectorScale); + + // use the vectorStep to walk across the image in the x and y directions + for (int i = 0; i < this.picWidth; i += Math.ceil(vectorStep)) { - for (int j = 0; j < this.picHeight; j += Math.ceil(imageLength + stepScale)) + for (int j = 0; j < this.picHeight; j += Math.ceil(vectorStep)) { dataIndex = this.getDataIndex(i, j); eastVal = comps.x.get(dataIndex); @@ -251,8 +264,19 @@ public final class ImageProducer g.setStroke(new BasicStroke(1)); BarbFactory.renderWindBarbForSpeed(mag, radangle, i, j, this.units, this.vectorScale, j >= this.equator_y_index, g); } else { - // Arrows. We need to pick the style arrow now - VectorFactory.renderVector(this.style.name(), mag, radangle, i, j, this.vectorScale, g); + // Arrows. We need to pick the style arrow now + //VectorFactory.renderVector(this.style.name(), mag, radangle, i, j, this.vectorScale, g); + + // use the vector scale factor when calling each individual vector symbol + + // calculate the vectorScaling factor as a function of where this cell value is + // in relation to the min and max. this is done by normalising the value to be between + // 0 and 1, and multiplying that value by the vectorScale (default=1) , + // and then by multiplying by 4 which was a number that 'seemed right' for our data + // following some experimentation + float theScale = 4 * this.vectorScale * (mag.floatValue() - scaleMin) / (scaleMax - scaleMin); + + VectorFactory.renderVector(this.style.name(), mag, radangle, i, j, theScale, g); } } } @@ -478,6 +502,7 @@ public final class ImageProducer private boolean transparent = false; private int opacity = 100; private float vectorScale = 1; + private float vectorStep = 1; private int numColourBands = ColorPalette.MAX_NUM_COLOURS; private Boolean logarithmic = null; private Color bgColor = Color.WHITE; @@ -579,6 +604,13 @@ public final class ImageProducer return this; } + /** Sets the vectorStep (defaults to 1.0) */ + public Builder vectorStep(float step) { + if (step <= 0) throw new IllegalArgumentException(); + this.vectorStep = step; + return this; + } + /** Sets the layers units */ public Builder units(String units) { this.units = units; @@ -627,6 +659,7 @@ public final class ImageProducer ? emptyRange : this.scaleRange; ip.vectorScale = this.vectorScale; + ip.vectorStep = this.vectorStep; ip.units = this.units; ip.equator_y_index = this.equator_y_index; return ip;