Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save mbohun/180ff230128d4b1c069d to your computer and use it in GitHub Desktop.
Save mbohun/180ff230128d4b1c069d to your computer and use it in GitHub Desktop.
Fix for 4326 in WMS, Scatterplot service, Fix for fqs in qids in WMS
Index: src/main/java/au/org/ala/biocache/web/ScatterplotController.java
===================================================================
--- src/main/java/au/org/ala/biocache/web/ScatterplotController.java (revision 0)
+++ src/main/java/au/org/ala/biocache/web/ScatterplotController.java (revision 4552)
@@ -0,0 +1,230 @@
+package au.org.ala.biocache.web;
+
+import au.org.ala.biocache.dao.SearchDAO;
+import au.org.ala.biocache.dto.IndexFieldDTO;
+import au.org.ala.biocache.dto.SearchResultDTO;
+import au.org.ala.biocache.dto.SpatialSearchRequestParams;
+import org.apache.log4j.Logger;
+import org.apache.solr.common.SolrDocumentList;
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.ChartRenderingInfo;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.encoders.EncoderUtil;
+import org.jfree.chart.encoders.ImageFormat;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.data.xy.DefaultXYDataset;
+import org.jfree.ui.RectangleEdge;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import javax.inject.Inject;
+import javax.servlet.http.HttpServletResponse;
+import java.awt.*;
+import java.awt.geom.Ellipse2D;
+import java.awt.image.BufferedImage;
+import java.util.*;
+
+/**
+ * This controller is responsible for providing basic scatterplot services.
+ *
+ * Basic scatterplot is
+ * - occurrences, standard biocache query
+ * - x, numerical stored value field
+ * - y, numerical stored value field
+ * - height, integer default 256
+ * - width, integer default 256
+ * - title, string default query-display-name
+ * - pointcolour, colour as RGB string like FF0000 for red, default 0000FF
+ * - pointradius, double default 3
+ *
+ */
+@Controller
+public class ScatterplotController {
+
+ private static Logger logger = Logger.getLogger(ScatterplotController.class);
+
+ private final static int PAGE_SIZE = 100000000;
+ private final static String DEFAULT_SCATTERPLOT_TITLE = " ";
+ private final static String DEFAULT_SCATTERPLOT_HEIGHT = "256";
+ private final static String DEFAULT_SCATTERPLOT_WIDTH = "256";
+ private final static String DEFAULT_SCATTERPLOT_POINTCOLOUR = "0000FF";
+ private final static String DEFAULT_SCATTERPLOT_POINTRADIUS = "3";
+ private final static String [] VALID_DATATYPES = {"double","int","long"};
+
+ @Inject
+ protected SearchDAO searchDAO;
+
+ @RequestMapping(value = {"/scatterplot"}, method = RequestMethod.GET)
+ public void scatterplot(SpatialSearchRequestParams requestParams,
+ @RequestParam(value = "x", required = true) String x,
+ @RequestParam(value = "y", required = true) String y,
+ @RequestParam(value = "height", required = false, defaultValue=DEFAULT_SCATTERPLOT_HEIGHT) Integer height,
+ @RequestParam(value = "width", required = false, defaultValue=DEFAULT_SCATTERPLOT_WIDTH) Integer width,
+ @RequestParam(value = "title", required = false, defaultValue=DEFAULT_SCATTERPLOT_TITLE) String title,
+ @RequestParam(value = "pointcolour", required = false, defaultValue=DEFAULT_SCATTERPLOT_POINTCOLOUR) String pointcolour,
+ @RequestParam(value = "pointradius", required = false, defaultValue = DEFAULT_SCATTERPLOT_POINTRADIUS) Double pointradius,
+ HttpServletResponse response) throws Exception {
+ JFreeChart jChart = makeScatterplot(requestParams, x, y, title, pointcolour, pointradius);
+
+ //produce image
+ ChartRenderingInfo chartRenderingInfo = new ChartRenderingInfo();
+ BufferedImage bi = jChart.createBufferedImage(width, height, BufferedImage.TRANSLUCENT, chartRenderingInfo);
+ byte[] bytes = EncoderUtil.encode(bi, ImageFormat.PNG, true);
+
+ //output image
+ response.setContentType("image/png");
+ response.getOutputStream().write(bytes);
+ }
+
+ @RequestMapping(value = {"/scatterplot/point"}, method = RequestMethod.GET)
+ public Map scatterplotPointInfo(SpatialSearchRequestParams requestParams,
+ @RequestParam(value = "x", required = true) String x,
+ @RequestParam(value = "y", required = true) String y,
+ @RequestParam(value = "height", required = false, defaultValue=DEFAULT_SCATTERPLOT_HEIGHT) Integer height,
+ @RequestParam(value = "width", required = false, defaultValue=DEFAULT_SCATTERPLOT_WIDTH) Integer width,
+ @RequestParam(value = "title", required = false, defaultValue=DEFAULT_SCATTERPLOT_TITLE) String title,
+ @RequestParam(value = "pointx1", required = true) Integer pointx1,
+ @RequestParam(value = "pointy1", required = true) Integer pointy1,
+ @RequestParam(value = "pointx2", required = true) Integer pointx2,
+ @RequestParam(value = "pointy2", required = true) Integer pointy2) throws Exception {
+
+ JFreeChart jChart = makeScatterplot(requestParams, x, y, title, "000000", 1.0);
+
+ //produce image
+ ChartRenderingInfo chartRenderingInfo = new ChartRenderingInfo();
+ BufferedImage bi = jChart.createBufferedImage(width, height, BufferedImage.TRANSLUCENT, chartRenderingInfo);
+
+ XYPlot plot = (XYPlot) jChart.getPlot();
+
+ //identify point range across x and y
+ double tx1 = plot.getRangeAxis().java2DToValue(pointx1, chartRenderingInfo.getPlotInfo().getDataArea(), RectangleEdge.BOTTOM);
+ double tx2 = plot.getRangeAxis().java2DToValue(pointx2, chartRenderingInfo.getPlotInfo().getDataArea(), RectangleEdge.BOTTOM);
+ double ty1 = plot.getDomainAxis().java2DToValue(pointy1, chartRenderingInfo.getPlotInfo().getDataArea(), RectangleEdge.LEFT);
+ double ty2 = plot.getDomainAxis().java2DToValue(pointy2, chartRenderingInfo.getPlotInfo().getDataArea(), RectangleEdge.LEFT);
+ double x1 = Math.min(tx1, tx2);
+ double x2 = Math.max(tx1, tx2);
+ double y1 = Math.min(ty1, ty2);
+ double y2 = Math.max(ty1, ty2);
+
+ Map map = new HashMap();
+ map.put("xaxis_pixel_selection",new int[] {pointx1, pointx2});
+ map.put("yaxis_pixel_selection",new int[] {pointy1, pointy2});
+ map.put("xaxis",x);
+ map.put("yaxis",y);
+ map.put("xaxis_range",new double[]{x1, x2});
+ map.put("yaxis_range",new double[]{y1, y2});
+
+ return map;
+
+ /*
+ //add new fqs
+ String [] fqs_old = requestParams.getFq();
+ String [] fqs_new = new String[fqs_old.length + 2];
+ System.arraycopy(fqs_old,0,fqs_new,0,fqs_old.length);
+ fqs_new[fqs_old.length] = x + ":[" + x1 + " TO " + x2 + "]";
+ fqs_new[fqs_old.length + 1] = y + ":[" + y1 + " TO " + y2 + "]";
+ requestParams.setFq(fqs_new);
+ return searchDAO.findByFulltextSpatialQuery(requestParams, null);
+ */
+ }
+
+ JFreeChart makeScatterplot(SpatialSearchRequestParams requestParams, String x, String y
+ , String title, String pointcolour, Double pointradius) throws Exception {
+ //verify x and y are numerical and stored
+ String displayNameX = null;
+ String displayNameY = null;
+ for (IndexFieldDTO indexFieldDTO : searchDAO.getIndexFieldDetails(new String[]{x}) ){
+ if (!Arrays.asList(VALID_DATATYPES).contains(indexFieldDTO.getDataType() )) {
+ throw new Exception("Invalid datatype: " + indexFieldDTO.getDataType() + " for x: " + x);
+ }
+ if(!indexFieldDTO.isStored()) {
+ throw new Exception("Cannot use x: " + x + ". It is not a stored field.");
+ }
+ displayNameX = indexFieldDTO.getDescription();
+ }
+ for (IndexFieldDTO indexFieldDTO : searchDAO.getIndexFieldDetails(new String[]{y}) ){
+ if (!Arrays.asList(VALID_DATATYPES).contains(indexFieldDTO.getDataType() )) {
+ throw new Exception("Invalid datatype: " + indexFieldDTO.getDataType() + " for y: " + y);
+ }
+ if(!indexFieldDTO.isStored()) {
+ throw new Exception("Cannot use y: " + y + ". It is not a stored field.");
+ }
+ displayNameY = indexFieldDTO.getDescription();
+ }
+ if(displayNameX == null) {
+ throw new Exception("Unknown value for x: " + x);
+ }
+ if(displayNameY == null) {
+ throw new Exception("Unknown value for y: " + y);
+ }
+
+ //get data
+ requestParams.setPageSize(PAGE_SIZE);
+ requestParams.setFl(x + "," + y);
+ SolrDocumentList sdl = searchDAO.findByFulltext(requestParams);
+ int size = sdl.size();
+ double [][] data = new double[2][size];
+ int count = 0;
+ for(int i=0;i<size;i++) {
+ try {
+ Object a = sdl.get(i).getFieldValue(y);
+ Object b = sdl.get(i).getFieldValue(x);
+ data[1][i] = Double.parseDouble(String.valueOf(sdl.get(i).getFieldValue(y)));
+ if(a instanceof Double) {
+ data[0][i] = (Double) a;
+ } else {
+ data[0][i] = Double.parseDouble(String.valueOf(a));
+ }
+
+ if(b instanceof Double) {
+ data[1][i] = (Double) b;
+ } else {
+ data[1][i] = Double.parseDouble(String.valueOf(b));
+ }
+
+ count++;
+ } catch (Exception e) {
+ data[0][i] = Double.NaN;
+ data[1][i] = Double.NaN;
+ }
+ }
+
+ if(count == 0) {
+ throw new Exception("valid records found for these input parameters");
+ }
+
+ //create dataset
+ DefaultXYDataset xyDataset = new DefaultXYDataset();
+ xyDataset.addSeries("series", data);
+
+ //create chart
+ JFreeChart jChart = ChartFactory.createScatterPlot(
+ title.equals(" ")?requestParams.getDisplayString():title //chart display name
+ , displayNameX //x-axis display name
+ , displayNameY //y-axis display name
+ , xyDataset
+ , PlotOrientation.HORIZONTAL, false, false, false);
+ jChart.setBackgroundPaint(Color.white);
+
+ //styling
+ XYPlot plot = (XYPlot) jChart.getPlot();
+ Font axisfont = new Font("Arial", Font.PLAIN, 10);
+ Font titlefont = new Font("Arial", Font.BOLD, 11);
+ plot.getDomainAxis().setLabelFont(axisfont);
+ plot.getDomainAxis().setTickLabelFont(axisfont);
+ plot.getRangeAxis().setLabelFont(axisfont);
+ plot.getRangeAxis().setTickLabelFont(axisfont);
+ plot.setBackgroundPaint(new Color(220, 220, 220));
+ jChart.getTitle().setFont(titlefont);
+
+ //point shape and colour
+ Color c = new Color(Integer.parseInt(pointcolour, 16));
+ plot.getRenderer().setSeriesPaint(0, c);
+ plot.getRenderer().setSeriesShape(0, new Ellipse2D.Double(-pointradius, -pointradius, pointradius*2, pointradius*2));
+
+ return jChart;
+ }
+}
Index: src/main/java/au/org/ala/biocache/web/WMSController.java
===================================================================
--- src/main/java/au/org/ala/biocache/web/WMSController.java (revision 4535)
+++ src/main/java/au/org/ala/biocache/web/WMSController.java (revision 4552)
@@ -152,7 +152,7 @@
//store the title if necessary
if(title == null)
title = requestParams.getDisplayString();
- String[] fqs = requestParams.getFq();
+ String[] fqs = getFq(requestParams);
if(fqs != null && fqs.length==1 && fqs[0].length()==0){
fqs =null;
}
@@ -537,6 +537,14 @@
/ (1 - Math.sin(lat * Math.PI / 180))) / 2);
}
+ int convertLatToPixel4326(double lat, double top, double bottom, int pixelHeight) {
+ return (int) (((lat - top) / (bottom - top)) * pixelHeight);
+ }
+
+ int convertLngToPixel4326(double lng, double left, double right, int pixelWidth) {
+ return (int) (((lng - left) / (right - left)) * pixelWidth);
+ }
+
int convertLngToPixel(double lng) {
return (int) Math.round(map_offset + map_radius * lng * Math.PI / 180);
}
@@ -606,11 +614,12 @@
* @param pbbox the pbbox to initialise
* @return
*/
- private double getBBoxes(String bboxString, int width, int height, int size, boolean uncertainty, double[] mbbox, double[] bbox, double[] pbbox) {
+ private double getBBoxes(String bboxString, int width, int height, int size, boolean uncertainty, double[] mbbox, double[] bbox, double[] pbbox, double [] tilebbox) {
int i = 0;
for (String s : bboxString.split(",")) {
try {
- mbbox[i] = Double.parseDouble(s);
+ tilebbox[i] = Double.parseDouble(s);
+ mbbox[i] = tilebbox[i];
i++;
} catch (Exception e) {
logger.error("Problem parsing BBOX: '" + bboxString + "'", e);
@@ -658,6 +667,75 @@
return degreesPerPixel;
}
+ /**
+ *
+ * @param bboxString
+ * @param width
+ * @param height
+ * @param size
+ * @param uncertainty
+ * @param mbbox the mbbox to initialise
+ * @param bbox the bbox to initialise
+ * @param pbbox the pbbox to initialise
+ * @return
+ */
+ private double getBBoxes4326(String bboxString, int width, int height, int size, boolean uncertainty, double[] mbbox, double[] bbox, double[] pbbox, double [] tilebbox) {
+ int i = 0;
+ for (String s : bboxString.split(",")) {
+ try {
+ tilebbox[i] = Double.parseDouble(s);
+ mbbox[i] = tilebbox[i];
+ i++;
+ } catch (Exception e) {
+ logger.error("Problem parsing BBOX: '" + bboxString + "'", e);
+ }
+ }
+
+ //adjust bbox extents with half pixel width/height
+ double pixelWidth = (mbbox[2] - mbbox[0]) / width;
+ double pixelHeight = (mbbox[3] - mbbox[1]) / height;
+ mbbox[0] += pixelWidth / 2;
+ mbbox[2] -= pixelWidth / 2;
+ mbbox[1] += pixelHeight / 2;
+ mbbox[3] -= pixelHeight / 2;
+
+ //offset for points bounding box by dot size
+ double xoffset = (mbbox[2] - mbbox[0]) / (double) width * size;
+ double yoffset = (mbbox[3] - mbbox[1]) / (double) height * size;
+
+ //check offset for points bb by maximum uncertainty
+ if (uncertainty) {
+ //estimate 0.01 degrees is 1000m
+ double scale = 0.01 / 1000;
+ if (xoffset < MAX_UNCERTAINTY * scale) {
+ xoffset = MAX_UNCERTAINTY * scale;
+ }
+ if (yoffset < MAX_UNCERTAINTY * scale) {
+ yoffset = MAX_UNCERTAINTY * scale;
+ }
+ }
+
+ //adjust offset for pixel height/width
+ xoffset += pixelWidth;
+ yoffset += pixelHeight;
+
+ /* not required for 4326
+ pbbox[0] = convertLngToPixel(convertMetersToLng(mbbox[0]));
+ pbbox[1] = convertLatToPixel(convertMetersToLat(mbbox[1]));
+ pbbox[2] = convertLngToPixel(convertMetersToLng(mbbox[2]));
+ pbbox[3] = convertLatToPixel(convertMetersToLat(mbbox[3]));
+ */
+
+ //actual bounding box
+ bbox[0] = mbbox[0] - xoffset;
+ bbox[1] = mbbox[1] - yoffset;
+ bbox[2] = mbbox[2] + xoffset;
+ bbox[3] = mbbox[3] + yoffset;
+
+ double degreesPerPixel = Math.min(pixelWidth, pixelHeight);
+ return degreesPerPixel;
+ }
+
private String getQ(String cql_filter) {
String q = cql_filter;
int p1 = cql_filter.indexOf("qid:");
@@ -697,7 +775,7 @@
SpatialSearchRequestParams requestParams = new SpatialSearchRequestParams();
requestParams.setQ(request.getQ());
requestParams.setQc(request.getQc());
- requestParams.setFq(request.getFq());
+ requestParams.setFq(getFq(request));
//test for cutpoints on the back of colourMode
String[] s = colourMode.split(",");
@@ -785,7 +863,7 @@
String[] dir = {"asc", "asc", "desc", "desc"};
//remove instances of null longitude or latitude
- String[] fq = (String[]) ArrayUtils.addAll(requestParams.getFq(), new String[]{"longitude:[* TO *]", "latitude:[* TO *]"});
+ String[] fq = (String[]) ArrayUtils.addAll(getFq(requestParams), new String[]{"longitude:[* TO *]", "latitude:[* TO *]"});
requestParams.setFq(fq);
requestParams.setPageSize(10);
@@ -959,10 +1037,11 @@
double[] mbbox = new double[4];
double[] bbox = new double[4];
double[] pbbox = new double[4];
+ double[] tilebbox = new double[4];
int size = vars.size + (vars.highlight != null ? HIGHLIGHT_RADIUS * 2 + (int) (vars.size * 0.2) : 0) + 5; //bounding box buffer
//what is the size of the dot in degrees
- double resolution = getBBoxes(bboxString, width, height, size, vars.uncertainty, mbbox, bbox, pbbox);
+ double resolution = getBBoxes(bboxString, width, height, size, vars.uncertainty, mbbox, bbox, pbbox, tilebbox);
//resolution should be a value < 1
PointType pointType = getPointTypeForDegreesPerPixel(resolution);
@@ -1401,16 +1480,24 @@
response.setHeader("Cache-Control", "max-age=86400"); //age == 1 day
response.setContentType("image/png"); //only png images generated
- if("EPSG:4326".equals(srs))
- bboxString = convertBBox4326To900913(bboxString); // to work around a UDIG bug
-
+ boolean is4326 = false;
WmsEnv vars = new WmsEnv(env, styles);
double[] mbbox = new double[4];
double[] bbox = new double[4];
double[] pbbox = new double[4];
+ double[] tilebbox = new double[4];
int size = vars.size + (vars.highlight != null ? HIGHLIGHT_RADIUS * 2 + (int) (vars.size * 0.2) : 0) + 5; //bounding box buffer
- double resolution = getBBoxes(bboxString, width, height, size, vars.uncertainty, mbbox, bbox, pbbox);
+ double resolution;
+ if("EPSG:4326".equals(srs)) {
+ is4326 = true;
+ //bboxString = convertBBox4326To900913(bboxString); // to work around a UDIG bug
+
+ resolution = getBBoxes4326(bboxString, width, height, size, vars.uncertainty, mbbox, bbox, pbbox, tilebbox);
+ } else {
+ resolution = getBBoxes(bboxString, width, height, size, vars.uncertainty, mbbox, bbox, pbbox, tilebbox);
+ }
+
PointType pointType = getPointTypeForDegreesPerPixel(resolution);
logger.debug("Rendering: " + pointType.name());
@@ -1421,7 +1508,7 @@
q = getQ(cql_filter);
} else if(StringUtils.trimToNull(layers) != null && !"ALA:Occurrences".equalsIgnoreCase(layers)){
q = convertLayersParamToQ(layers);
- }
+ }
String[] boundingBoxFqs = new String[2];
boundingBoxFqs[0] = String.format("longitude:[%f TO %f]", bbox[0], bbox[2]);
@@ -1434,6 +1521,8 @@
//build request
if (q.length() > 0) {
requestParams.setQ(q);
+ } else {
+ q = requestParams.getQ();
}
//bounding box test (q must be 'qid:' + number)
@@ -1446,7 +1535,7 @@
}
}
- String[] originalFqs = requestParams.getFq();
+ String[] originalFqs = getFq(requestParams);
//get from cache
WMSTile wco = null;
@@ -1460,11 +1549,11 @@
if (wco == null) {
imgObj = wmsUncached(requestParams, vars, pointType, pbbox, mbbox,
width, height, width_mult, height_mult, pointWidth,
- originalFqs, hq, boundingBoxFqs, outlinePoints, outlineColour, response);
+ originalFqs, hq, boundingBoxFqs, outlinePoints, outlineColour, response, is4326, tilebbox);
} else {
imgObj = wmsCached(wco, requestParams, vars, pointType, pbbox, bbox, mbbox,
width, height, width_mult, height_mult, pointWidth,
- originalFqs, hq, boundingBoxFqs, outlinePoints, outlineColour, response);
+ originalFqs, hq, boundingBoxFqs, outlinePoints, outlineColour, response, is4326, tilebbox);
}
if (imgObj != null && imgObj.g != null) {
@@ -1638,7 +1727,8 @@
double height_mult, int pointWidth, String[] originalFqs, Set<Integer> hq,
String[] boundingBoxFqs, boolean outlinePoints,
String outlineColour,
- HttpServletResponse response) throws Exception {
+ HttpServletResponse response,
+ boolean is4326, double [] tilebbox) throws Exception {
ImgObj imgObj = null;
@@ -1677,6 +1767,12 @@
continue;
}
+ //for 4326
+ double top = tilebbox[3];
+ double bottom = tilebbox[1];
+ double left = tilebbox[0];
+ double right = tilebbox[2];
+
if (vars.colourMode.equals("grid")) {
//render grids
int[] count = counts.get(j);
@@ -1687,9 +1783,16 @@
float lat = ps[i + 1];
if (lng >= bbox[0] && lng <= bbox[2]
&& lat >= bbox[1] && lat <= bbox[3]) {
- x = (int) ((convertLngToPixel(lng) - pbbox[0]) * grid_width_mult);
- y = (int) ((convertLatToPixel(lat) - pbbox[3]) * grid_height_mult);
+
+ if (is4326) {
+ x = convertLngToPixel4326(lng, left, right, width);
+ y = convertLatToPixel4326(lat, top, bottom, height);
+ } else {
+ x = (int) ((convertLngToPixel(lng) - pbbox[0]) * grid_width_mult);
+ y = (int) ((convertLatToPixel(lat) - pbbox[3]) * grid_height_mult);
+ }
+
if (x >= 0 && x < divs && y >= 0 && y < divs) {
gridCounts[x][y] += count[i / 2];
}
@@ -1705,9 +1808,15 @@
float lat = ps[i + 1];
if (lng >= bbox[0] && lng <= bbox[2]
&& lat >= bbox[1] && lat <= bbox[3]) {
- x = (int) ((convertLngToPixel(lng) - pbbox[0]) * width_mult);
- y = (int) ((convertLatToPixel(lat) - pbbox[3]) * height_mult);
+ if (is4326) {
+ x = convertLngToPixel4326(lng, left, right, width);
+ y = convertLatToPixel4326(lat, top, bottom, height);
+ } else {
+ x = (int) ((convertLngToPixel(lng) - pbbox[0]) * width_mult);
+ y = (int) ((convertLatToPixel(lat) - pbbox[3]) * height_mult);
+ }
+
imgObj.g.fillOval(x - vars.size, y - vars.size, pointWidth, pointWidth);
if(outlinePoints){
imgObj.g.setPaint(oColour);
@@ -1742,18 +1851,18 @@
}
}
} else {
- drawUncertaintyCircles(requestParams, vars, height, pbbox, mbbox, width_mult, height_mult, imgObj.g, originalFqs, boundingBoxFqs);
+ drawUncertaintyCircles(requestParams, vars, height, width, pbbox, mbbox, width_mult, height_mult, imgObj.g, originalFqs, boundingBoxFqs, is4326, tilebbox);
}
//highlight
if (vars.highlight != null) {
- imgObj = drawHighlight(requestParams, vars, pointType, width, height, pbbox, width_mult, height_mult, imgObj, originalFqs, boundingBoxFqs);
+ imgObj = drawHighlight(requestParams, vars, pointType, width, height, pbbox, width_mult, height_mult, imgObj, originalFqs, boundingBoxFqs, is4326, tilebbox);
}
return imgObj;
}
- void drawUncertaintyCircles(SpatialSearchRequestParams requestParams, WmsEnv vars, int height, double[] pbbox, double[] mbbox, double width_mult, double height_mult, Graphics2D g, String[] originalFqs, String[] boundingBoxFqs) throws Exception {
+ void drawUncertaintyCircles(SpatialSearchRequestParams requestParams, WmsEnv vars, int height, int width, double[] pbbox, double[] mbbox, double width_mult, double height_mult, Graphics2D g, String[] originalFqs, String[] boundingBoxFqs, boolean is4326, double [] tilebbox) throws Exception {
//draw uncertainty circles
double hmult = (height / (mbbox[3] - mbbox[1]));
@@ -1787,6 +1896,12 @@
//TODO: paging
SolrDocumentList sdl = searchDAO.findByFulltext(requestParams);
+ //for 4326
+ double top = tilebbox[3];
+ double bottom = tilebbox[1];
+ double left = tilebbox[0];
+ double right = tilebbox[2];
+
double lng, lat;
int x, y;
int uncertaintyRadius = (int) Math.ceil(uncertaintyR[j] * hmult);
@@ -1800,8 +1915,13 @@
lng = (Double) sdl.get(i).getFieldValue("longitude");
lat = (Double) sdl.get(i).getFieldValue("latitude");
- x = (int) ((convertLngToPixel(lng) - pbbox[0]) * width_mult);
- y = (int) ((convertLatToPixel(lat) - pbbox[3]) * height_mult);
+ if (is4326) {
+ x = convertLngToPixel4326(lng, left, right, width);
+ y = convertLatToPixel4326(lat, top, bottom, height);
+ } else {
+ x = (int) ((convertLngToPixel(lng) - pbbox[0]) * width_mult);
+ y = (int) ((convertLatToPixel(lat) - pbbox[3]) * height_mult);
+ }
if (uncertaintyRadius > 0) {
g.drawOval(x - uncertaintyRadius, y - uncertaintyRadius, uncertaintyRadius * 2, uncertaintyRadius * 2);
@@ -1816,7 +1936,7 @@
ImgObj drawHighlight(SpatialSearchRequestParams requestParams, WmsEnv vars, PointType pointType,
int width, int height, double[] pbbox, double width_mult,
- double height_mult, ImgObj imgObj, String[] originalFqs, String[] boundingBoxFqs) throws Exception {
+ double height_mult, ImgObj imgObj, String[] originalFqs, String[] boundingBoxFqs, boolean is4326, double [] tilebbox) throws Exception {
String[] fqs = new String[originalFqs.length + 3];
System.arraycopy(originalFqs, 0, fqs, 3, originalFqs.length);
fqs[0] = vars.highlight;
@@ -1837,13 +1957,25 @@
imgObj.g.setStroke(new BasicStroke(2));
imgObj.g.setColor(new Color(255, 0, 0, 255));
int x, y;
+
+ //for 4326
+ double top = tilebbox[3];
+ double bottom = tilebbox[1];
+ double left = tilebbox[0];
+ double right = tilebbox[2];
+
for (int i = 0; i < ps.size(); i++) {
OccurrencePoint pt = ps.get(i);
float lng = pt.getCoordinates().get(0).floatValue();
float lat = pt.getCoordinates().get(1).floatValue();
- x = (int) ((convertLngToPixel(lng) - pbbox[0]) * width_mult);
- y = (int) ((convertLatToPixel(lat) - pbbox[3]) * height_mult);
+ if (is4326) {
+ x = convertLngToPixel4326(lng, left, right, width);
+ y = convertLatToPixel4326(lat, top, bottom, height);
+ } else {
+ x = (int) ((convertLngToPixel(lng) - pbbox[0]) * width_mult);
+ y = (int) ((convertLatToPixel(lat) - pbbox[3]) * height_mult);
+ }
imgObj.g.drawOval(x - highightRadius, y - highightRadius, highlightWidth, highlightWidth);
}
@@ -1888,7 +2020,7 @@
//points count
SpatialSearchRequestParams r = new SpatialSearchRequestParams();
r.setQ(requestParams.getQ());
- r.setFq(requestParams.getFq());
+ r.setFq(getFq(requestParams));
r.setQc(requestParams.getQc());
r.setPageSize(0);
r.setFacet(false);
@@ -1903,8 +2035,8 @@
ArrayList<String> forNulls = new ArrayList<String>(sz);
String[] fqs = null;
- String[] originalFqs = requestParams.getFq();
- if (requestParams.getFq() == null || requestParams.getFq().length == 0) {
+ String[] originalFqs = getFq(requestParams);
+ if (originalFqs == null || originalFqs.length == 0) {
fqs = new String[1];
} else {
fqs = new String[originalFqs.length + 1];
@@ -1986,6 +2118,39 @@
}
}
+ private String[] getFq(SpatialSearchRequestParams requestParams) {
+ int requestParamsFqLength = requestParams.getFq() != null ? requestParams.getFq().length : 0;
+
+ String [] qidFq = null;
+ int qidFqLength = 0;
+ String q = requestParams.getQ();
+ if (q.startsWith("qid:")) {
+ try {
+ qidFq = ParamsCache.get(Long.parseLong(q.substring(4))).getFqs();
+ if (qidFq != null) {
+ qidFqLength = qidFq.length;
+ }
+ } catch (Exception e) {
+ }
+ }
+
+ if (requestParamsFqLength + qidFqLength == 0) {
+ return null;
+ }
+
+ String [] allFqs = new String[requestParamsFqLength + qidFqLength];
+
+ if (requestParamsFqLength > 0) {
+ System.arraycopy(requestParams.getFq(), 0, allFqs, 0, requestParamsFqLength);
+ }
+
+ if (qidFqLength > 0) {
+ System.arraycopy(qidFq, 0, allFqs, requestParamsFqLength, qidFqLength);
+ }
+
+ return allFqs;
+ }
+
/**
* TODO remove code duplicate between wmsUncached and wmsCached
*
@@ -1996,7 +2161,8 @@
WmsEnv vars, PointType pointType, double[] pbbox,
double[] mbbox, int width, int height, double width_mult,
double height_mult, int pointWidth, String[] originalFqs, Set<Integer> hq,
- String[] boundingBoxFqs, boolean outlinePoints, String outlineColour, HttpServletResponse response) throws Exception {
+ String[] boundingBoxFqs, boolean outlinePoints, String outlineColour, HttpServletResponse response,
+ boolean is4326, double[] tilebbox) throws Exception {
//colour mapping
List<LegendItem> colours = (vars.colourMode.equals("-1") || vars.colourMode.equals("grid")) ? null : getColours(requestParams, vars.colourMode);
@@ -2008,7 +2174,7 @@
List<String> forNulls = new ArrayList<String>(sz);
String[] fqs = null;
String[] origAndBBoxFqs = null;
- if (requestParams.getFq() == null || requestParams.getFq().length == 0) {
+ if (originalFqs == null || originalFqs.length == 0) {
fqs = new String[3];
fqs[1] = boundingBoxFqs[0];
fqs[2] = boundingBoxFqs[1];
@@ -2057,7 +2223,16 @@
} else if (colours.size() >= colourList.length - 1) {
fqs = new String[forNulls.size()];
forNulls.toArray(fqs);
- requestParams.setFq(fqs);
+
+ String [] newFqs = new String[originalFqs.length + forNulls.size()];
+ if (originalFqs.length > 0) {
+ System.arraycopy(originalFqs, 0, newFqs, 0, originalFqs.length);
+ }
+ if (fqs.length > 0) {
+ System.arraycopy(fqs, 0, newFqs, originalFqs.length, fqs.length);
+ }
+ requestParams.setFq(newFqs);
+
points.add(searchDAO.getFacetPoints(requestParams, pointType));
pColour.add(colourList[colourList.length - 1] | (vars.alpha << 24));
}
@@ -2074,6 +2249,12 @@
double grid_height_mult = (height / (pbbox[1] - pbbox[3])) / (height / divs);
int x, y;
+ //for 4326
+ double top = tilebbox[3];
+ double bottom = tilebbox[1];
+ double left = tilebbox[0];
+ double right = tilebbox[2];
+
for (int j = 0; j < points.size(); j++) {
if(hq != null && hq.contains(j)){
@@ -2098,15 +2279,20 @@
float lng = pt.getCoordinates().get(0).floatValue();
float lat = pt.getCoordinates().get(1).floatValue();
- x = (int) ((convertLngToPixel(lng) - pbbox[0]) * grid_width_mult);
- y = (int) ((convertLatToPixel(lat) - pbbox[3]) * grid_height_mult);
+ if (is4326) {
+ x = convertLngToPixel4326(lng, left, right, width);
+ y = convertLatToPixel4326(lat, top, bottom, height);
+ } else {
+ x = (int) ((convertLngToPixel(lng) - pbbox[0]) * grid_width_mult);
+ y = (int) ((convertLatToPixel(lat) - pbbox[3]) * grid_height_mult);
+ }
if (x >= 0 && x < divs && y >= 0 && y < divs) {
gridCounts[x][y] += pt.getCount();
}
}
} else {
- renderPoints(vars, pbbox, width_mult, height_mult, pointWidth, outlinePoints, outlineColour, pColour, imgObj, j, ps);
+ renderPoints(vars, pbbox, width_mult, height_mult, pointWidth, outlinePoints, outlineColour, pColour, imgObj, j, ps, is4326, tilebbox, height, width);
}
}
@@ -2132,31 +2318,42 @@
}
}
} else {
- drawUncertaintyCircles(requestParams, vars, height, pbbox, mbbox, width_mult, height_mult, imgObj.g, originalFqs, boundingBoxFqs);
+ drawUncertaintyCircles(requestParams, vars, height, width, pbbox, mbbox, width_mult, height_mult, imgObj.g, originalFqs, boundingBoxFqs, is4326, tilebbox);
}
//highlight
if (vars.highlight != null) {
- imgObj = drawHighlight(requestParams, vars, pointType, width, height, pbbox, width_mult, height_mult, imgObj, originalFqs, boundingBoxFqs);
+ imgObj = drawHighlight(requestParams, vars, pointType, width, height, pbbox, width_mult, height_mult, imgObj, originalFqs, boundingBoxFqs, is4326, tilebbox);
}
return imgObj;
}
- private void renderPoints(WmsEnv vars, double[] pbbox, double width_mult, double height_mult, int pointWidth, boolean outlinePoints, String outlineColour, List<Integer> pColour, ImgObj imgObj, int j, List<OccurrencePoint> ps) {
+ private void renderPoints(WmsEnv vars, double[] pbbox, double width_mult, double height_mult, int pointWidth, boolean outlinePoints, String outlineColour, List<Integer> pColour, ImgObj imgObj, int j, List<OccurrencePoint> ps, boolean is4326, double [] tilebbox, int height, int width) {
int x;
int y;
Paint currentFill = new Color(pColour.get(j), true);
imgObj.g.setPaint(currentFill);
Color oColour = Color.decode(outlineColour);
+ //for 4326
+ double top = tilebbox[3];
+ double bottom = tilebbox[1];
+ double left = tilebbox[0];
+ double right = tilebbox[2];
+
for (int i = 0; i < ps.size(); i++) {
OccurrencePoint pt = ps.get(i);
float lng = pt.getCoordinates().get(0).floatValue();
float lat = pt.getCoordinates().get(1).floatValue();
- x = (int) ((convertLngToPixel(lng) - pbbox[0]) * width_mult);
- y = (int) ((convertLatToPixel(lat) - pbbox[3]) * height_mult);
+ if (is4326) {
+ x = convertLngToPixel4326(lng, left, right, width);
+ y = convertLatToPixel4326(lat, top, bottom, height);
+ } else {
+ x = (int) ((convertLngToPixel(lng) - pbbox[0]) * width_mult);
+ y = (int) ((convertLatToPixel(lat) - pbbox[3]) * height_mult);
+ }
//System.out.println("Drawing an oval.....");
imgObj.g.fillOval(x - vars.size, y - vars.size, pointWidth, pointWidth);
Index: pom.xml
===================================================================
--- pom.xml (revision 4535)
+++ pom.xml (revision 4552)
@@ -359,6 +359,12 @@
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
+ <!-- charting -->
+ <dependency>
+ <groupId>jfree</groupId>
+ <artifactId>jfreechart</artifactId>
+ <version>1.0.13</version>
+ </dependency>
</dependencies>
<repositories>
<!-- ALA repository -->
Index: src/main/java/au/org/ala/biocache/web/ScatterplotController.java
===================================================================
--- src/main/java/au/org/ala/biocache/web/ScatterplotController.java (revision 0)
+++ src/main/java/au/org/ala/biocache/web/ScatterplotController.java (revision 4552)
@@ -0,0 +1,230 @@
+package au.org.ala.biocache.web;
+
+import au.org.ala.biocache.dao.SearchDAO;
+import au.org.ala.biocache.dto.IndexFieldDTO;
+import au.org.ala.biocache.dto.SearchResultDTO;
+import au.org.ala.biocache.dto.SpatialSearchRequestParams;
+import org.apache.log4j.Logger;
+import org.apache.solr.common.SolrDocumentList;
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.ChartRenderingInfo;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.encoders.EncoderUtil;
+import org.jfree.chart.encoders.ImageFormat;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.data.xy.DefaultXYDataset;
+import org.jfree.ui.RectangleEdge;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import javax.inject.Inject;
+import javax.servlet.http.HttpServletResponse;
+import java.awt.*;
+import java.awt.geom.Ellipse2D;
+import java.awt.image.BufferedImage;
+import java.util.*;
+
+/**
+ * This controller is responsible for providing basic scatterplot services.
+ *
+ * Basic scatterplot is
+ * - occurrences, standard biocache query
+ * - x, numerical stored value field
+ * - y, numerical stored value field
+ * - height, integer default 256
+ * - width, integer default 256
+ * - title, string default query-display-name
+ * - pointcolour, colour as RGB string like FF0000 for red, default 0000FF
+ * - pointradius, double default 3
+ *
+ */
+@Controller
+public class ScatterplotController {
+
+ private static Logger logger = Logger.getLogger(ScatterplotController.class);
+
+ private final static int PAGE_SIZE = 100000000;
+ private final static String DEFAULT_SCATTERPLOT_TITLE = " ";
+ private final static String DEFAULT_SCATTERPLOT_HEIGHT = "256";
+ private final static String DEFAULT_SCATTERPLOT_WIDTH = "256";
+ private final static String DEFAULT_SCATTERPLOT_POINTCOLOUR = "0000FF";
+ private final static String DEFAULT_SCATTERPLOT_POINTRADIUS = "3";
+ private final static String [] VALID_DATATYPES = {"double","int","long"};
+
+ @Inject
+ protected SearchDAO searchDAO;
+
+ @RequestMapping(value = {"/scatterplot"}, method = RequestMethod.GET)
+ public void scatterplot(SpatialSearchRequestParams requestParams,
+ @RequestParam(value = "x", required = true) String x,
+ @RequestParam(value = "y", required = true) String y,
+ @RequestParam(value = "height", required = false, defaultValue=DEFAULT_SCATTERPLOT_HEIGHT) Integer height,
+ @RequestParam(value = "width", required = false, defaultValue=DEFAULT_SCATTERPLOT_WIDTH) Integer width,
+ @RequestParam(value = "title", required = false, defaultValue=DEFAULT_SCATTERPLOT_TITLE) String title,
+ @RequestParam(value = "pointcolour", required = false, defaultValue=DEFAULT_SCATTERPLOT_POINTCOLOUR) String pointcolour,
+ @RequestParam(value = "pointradius", required = false, defaultValue = DEFAULT_SCATTERPLOT_POINTRADIUS) Double pointradius,
+ HttpServletResponse response) throws Exception {
+ JFreeChart jChart = makeScatterplot(requestParams, x, y, title, pointcolour, pointradius);
+
+ //produce image
+ ChartRenderingInfo chartRenderingInfo = new ChartRenderingInfo();
+ BufferedImage bi = jChart.createBufferedImage(width, height, BufferedImage.TRANSLUCENT, chartRenderingInfo);
+ byte[] bytes = EncoderUtil.encode(bi, ImageFormat.PNG, true);
+
+ //output image
+ response.setContentType("image/png");
+ response.getOutputStream().write(bytes);
+ }
+
+ @RequestMapping(value = {"/scatterplot/point"}, method = RequestMethod.GET)
+ public Map scatterplotPointInfo(SpatialSearchRequestParams requestParams,
+ @RequestParam(value = "x", required = true) String x,
+ @RequestParam(value = "y", required = true) String y,
+ @RequestParam(value = "height", required = false, defaultValue=DEFAULT_SCATTERPLOT_HEIGHT) Integer height,
+ @RequestParam(value = "width", required = false, defaultValue=DEFAULT_SCATTERPLOT_WIDTH) Integer width,
+ @RequestParam(value = "title", required = false, defaultValue=DEFAULT_SCATTERPLOT_TITLE) String title,
+ @RequestParam(value = "pointx1", required = true) Integer pointx1,
+ @RequestParam(value = "pointy1", required = true) Integer pointy1,
+ @RequestParam(value = "pointx2", required = true) Integer pointx2,
+ @RequestParam(value = "pointy2", required = true) Integer pointy2) throws Exception {
+
+ JFreeChart jChart = makeScatterplot(requestParams, x, y, title, "000000", 1.0);
+
+ //produce image
+ ChartRenderingInfo chartRenderingInfo = new ChartRenderingInfo();
+ BufferedImage bi = jChart.createBufferedImage(width, height, BufferedImage.TRANSLUCENT, chartRenderingInfo);
+
+ XYPlot plot = (XYPlot) jChart.getPlot();
+
+ //identify point range across x and y
+ double tx1 = plot.getRangeAxis().java2DToValue(pointx1, chartRenderingInfo.getPlotInfo().getDataArea(), RectangleEdge.BOTTOM);
+ double tx2 = plot.getRangeAxis().java2DToValue(pointx2, chartRenderingInfo.getPlotInfo().getDataArea(), RectangleEdge.BOTTOM);
+ double ty1 = plot.getDomainAxis().java2DToValue(pointy1, chartRenderingInfo.getPlotInfo().getDataArea(), RectangleEdge.LEFT);
+ double ty2 = plot.getDomainAxis().java2DToValue(pointy2, chartRenderingInfo.getPlotInfo().getDataArea(), RectangleEdge.LEFT);
+ double x1 = Math.min(tx1, tx2);
+ double x2 = Math.max(tx1, tx2);
+ double y1 = Math.min(ty1, ty2);
+ double y2 = Math.max(ty1, ty2);
+
+ Map map = new HashMap();
+ map.put("xaxis_pixel_selection",new int[] {pointx1, pointx2});
+ map.put("yaxis_pixel_selection",new int[] {pointy1, pointy2});
+ map.put("xaxis",x);
+ map.put("yaxis",y);
+ map.put("xaxis_range",new double[]{x1, x2});
+ map.put("yaxis_range",new double[]{y1, y2});
+
+ return map;
+
+ /*
+ //add new fqs
+ String [] fqs_old = requestParams.getFq();
+ String [] fqs_new = new String[fqs_old.length + 2];
+ System.arraycopy(fqs_old,0,fqs_new,0,fqs_old.length);
+ fqs_new[fqs_old.length] = x + ":[" + x1 + " TO " + x2 + "]";
+ fqs_new[fqs_old.length + 1] = y + ":[" + y1 + " TO " + y2 + "]";
+ requestParams.setFq(fqs_new);
+ return searchDAO.findByFulltextSpatialQuery(requestParams, null);
+ */
+ }
+
+ JFreeChart makeScatterplot(SpatialSearchRequestParams requestParams, String x, String y
+ , String title, String pointcolour, Double pointradius) throws Exception {
+ //verify x and y are numerical and stored
+ String displayNameX = null;
+ String displayNameY = null;
+ for (IndexFieldDTO indexFieldDTO : searchDAO.getIndexFieldDetails(new String[]{x}) ){
+ if (!Arrays.asList(VALID_DATATYPES).contains(indexFieldDTO.getDataType() )) {
+ throw new Exception("Invalid datatype: " + indexFieldDTO.getDataType() + " for x: " + x);
+ }
+ if(!indexFieldDTO.isStored()) {
+ throw new Exception("Cannot use x: " + x + ". It is not a stored field.");
+ }
+ displayNameX = indexFieldDTO.getDescription();
+ }
+ for (IndexFieldDTO indexFieldDTO : searchDAO.getIndexFieldDetails(new String[]{y}) ){
+ if (!Arrays.asList(VALID_DATATYPES).contains(indexFieldDTO.getDataType() )) {
+ throw new Exception("Invalid datatype: " + indexFieldDTO.getDataType() + " for y: " + y);
+ }
+ if(!indexFieldDTO.isStored()) {
+ throw new Exception("Cannot use y: " + y + ". It is not a stored field.");
+ }
+ displayNameY = indexFieldDTO.getDescription();
+ }
+ if(displayNameX == null) {
+ throw new Exception("Unknown value for x: " + x);
+ }
+ if(displayNameY == null) {
+ throw new Exception("Unknown value for y: " + y);
+ }
+
+ //get data
+ requestParams.setPageSize(PAGE_SIZE);
+ requestParams.setFl(x + "," + y);
+ SolrDocumentList sdl = searchDAO.findByFulltext(requestParams);
+ int size = sdl.size();
+ double [][] data = new double[2][size];
+ int count = 0;
+ for(int i=0;i<size;i++) {
+ try {
+ Object a = sdl.get(i).getFieldValue(y);
+ Object b = sdl.get(i).getFieldValue(x);
+ data[1][i] = Double.parseDouble(String.valueOf(sdl.get(i).getFieldValue(y)));
+ if(a instanceof Double) {
+ data[0][i] = (Double) a;
+ } else {
+ data[0][i] = Double.parseDouble(String.valueOf(a));
+ }
+
+ if(b instanceof Double) {
+ data[1][i] = (Double) b;
+ } else {
+ data[1][i] = Double.parseDouble(String.valueOf(b));
+ }
+
+ count++;
+ } catch (Exception e) {
+ data[0][i] = Double.NaN;
+ data[1][i] = Double.NaN;
+ }
+ }
+
+ if(count == 0) {
+ throw new Exception("valid records found for these input parameters");
+ }
+
+ //create dataset
+ DefaultXYDataset xyDataset = new DefaultXYDataset();
+ xyDataset.addSeries("series", data);
+
+ //create chart
+ JFreeChart jChart = ChartFactory.createScatterPlot(
+ title.equals(" ")?requestParams.getDisplayString():title //chart display name
+ , displayNameX //x-axis display name
+ , displayNameY //y-axis display name
+ , xyDataset
+ , PlotOrientation.HORIZONTAL, false, false, false);
+ jChart.setBackgroundPaint(Color.white);
+
+ //styling
+ XYPlot plot = (XYPlot) jChart.getPlot();
+ Font axisfont = new Font("Arial", Font.PLAIN, 10);
+ Font titlefont = new Font("Arial", Font.BOLD, 11);
+ plot.getDomainAxis().setLabelFont(axisfont);
+ plot.getDomainAxis().setTickLabelFont(axisfont);
+ plot.getRangeAxis().setLabelFont(axisfont);
+ plot.getRangeAxis().setTickLabelFont(axisfont);
+ plot.setBackgroundPaint(new Color(220, 220, 220));
+ jChart.getTitle().setFont(titlefont);
+
+ //point shape and colour
+ Color c = new Color(Integer.parseInt(pointcolour, 16));
+ plot.getRenderer().setSeriesPaint(0, c);
+ plot.getRenderer().setSeriesShape(0, new Ellipse2D.Double(-pointradius, -pointradius, pointradius*2, pointradius*2));
+
+ return jChart;
+ }
+}
Index: src/main/java/au/org/ala/biocache/web/WMSController.java
===================================================================
--- src/main/java/au/org/ala/biocache/web/WMSController.java (revision 4551)
+++ src/main/java/au/org/ala/biocache/web/WMSController.java (revision 4552)
@@ -152,7 +152,7 @@
//store the title if necessary
if(title == null)
title = requestParams.getDisplayString();
- String[] fqs = requestParams.getFq();
+ String[] fqs = getFq(requestParams);
if(fqs != null && fqs.length==1 && fqs[0].length()==0){
fqs =null;
}
@@ -537,6 +537,14 @@
/ (1 - Math.sin(lat * Math.PI / 180))) / 2);
}
+ int convertLatToPixel4326(double lat, double top, double bottom, int pixelHeight) {
+ return (int) (((lat - top) / (bottom - top)) * pixelHeight);
+ }
+
+ int convertLngToPixel4326(double lng, double left, double right, int pixelWidth) {
+ return (int) (((lng - left) / (right - left)) * pixelWidth);
+ }
+
int convertLngToPixel(double lng) {
return (int) Math.round(map_offset + map_radius * lng * Math.PI / 180);
}
@@ -606,11 +614,12 @@
* @param pbbox the pbbox to initialise
* @return
*/
- private double getBBoxes(String bboxString, int width, int height, int size, boolean uncertainty, double[] mbbox, double[] bbox, double[] pbbox) {
+ private double getBBoxes(String bboxString, int width, int height, int size, boolean uncertainty, double[] mbbox, double[] bbox, double[] pbbox, double [] tilebbox) {
int i = 0;
for (String s : bboxString.split(",")) {
try {
- mbbox[i] = Double.parseDouble(s);
+ tilebbox[i] = Double.parseDouble(s);
+ mbbox[i] = tilebbox[i];
i++;
} catch (Exception e) {
logger.error("Problem parsing BBOX: '" + bboxString + "'", e);
@@ -658,6 +667,75 @@
return degreesPerPixel;
}
+ /**
+ *
+ * @param bboxString
+ * @param width
+ * @param height
+ * @param size
+ * @param uncertainty
+ * @param mbbox the mbbox to initialise
+ * @param bbox the bbox to initialise
+ * @param pbbox the pbbox to initialise
+ * @return
+ */
+ private double getBBoxes4326(String bboxString, int width, int height, int size, boolean uncertainty, double[] mbbox, double[] bbox, double[] pbbox, double [] tilebbox) {
+ int i = 0;
+ for (String s : bboxString.split(",")) {
+ try {
+ tilebbox[i] = Double.parseDouble(s);
+ mbbox[i] = tilebbox[i];
+ i++;
+ } catch (Exception e) {
+ logger.error("Problem parsing BBOX: '" + bboxString + "'", e);
+ }
+ }
+
+ //adjust bbox extents with half pixel width/height
+ double pixelWidth = (mbbox[2] - mbbox[0]) / width;
+ double pixelHeight = (mbbox[3] - mbbox[1]) / height;
+ mbbox[0] += pixelWidth / 2;
+ mbbox[2] -= pixelWidth / 2;
+ mbbox[1] += pixelHeight / 2;
+ mbbox[3] -= pixelHeight / 2;
+
+ //offset for points bounding box by dot size
+ double xoffset = (mbbox[2] - mbbox[0]) / (double) width * size;
+ double yoffset = (mbbox[3] - mbbox[1]) / (double) height * size;
+
+ //check offset for points bb by maximum uncertainty
+ if (uncertainty) {
+ //estimate 0.01 degrees is 1000m
+ double scale = 0.01 / 1000;
+ if (xoffset < MAX_UNCERTAINTY * scale) {
+ xoffset = MAX_UNCERTAINTY * scale;
+ }
+ if (yoffset < MAX_UNCERTAINTY * scale) {
+ yoffset = MAX_UNCERTAINTY * scale;
+ }
+ }
+
+ //adjust offset for pixel height/width
+ xoffset += pixelWidth;
+ yoffset += pixelHeight;
+
+ /* not required for 4326
+ pbbox[0] = convertLngToPixel(convertMetersToLng(mbbox[0]));
+ pbbox[1] = convertLatToPixel(convertMetersToLat(mbbox[1]));
+ pbbox[2] = convertLngToPixel(convertMetersToLng(mbbox[2]));
+ pbbox[3] = convertLatToPixel(convertMetersToLat(mbbox[3]));
+ */
+
+ //actual bounding box
+ bbox[0] = mbbox[0] - xoffset;
+ bbox[1] = mbbox[1] - yoffset;
+ bbox[2] = mbbox[2] + xoffset;
+ bbox[3] = mbbox[3] + yoffset;
+
+ double degreesPerPixel = Math.min(pixelWidth, pixelHeight);
+ return degreesPerPixel;
+ }
+
private String getQ(String cql_filter) {
String q = cql_filter;
int p1 = cql_filter.indexOf("qid:");
@@ -697,7 +775,7 @@
SpatialSearchRequestParams requestParams = new SpatialSearchRequestParams();
requestParams.setQ(request.getQ());
requestParams.setQc(request.getQc());
- requestParams.setFq(request.getFq());
+ requestParams.setFq(getFq(request));
//test for cutpoints on the back of colourMode
String[] s = colourMode.split(",");
@@ -785,7 +863,7 @@
String[] dir = {"asc", "asc", "desc", "desc"};
//remove instances of null longitude or latitude
- String[] fq = (String[]) ArrayUtils.addAll(requestParams.getFq(), new String[]{"longitude:[* TO *]", "latitude:[* TO *]"});
+ String[] fq = (String[]) ArrayUtils.addAll(getFq(requestParams), new String[]{"longitude:[* TO *]", "latitude:[* TO *]"});
requestParams.setFq(fq);
requestParams.setPageSize(10);
@@ -959,10 +1037,11 @@
double[] mbbox = new double[4];
double[] bbox = new double[4];
double[] pbbox = new double[4];
+ double[] tilebbox = new double[4];
int size = vars.size + (vars.highlight != null ? HIGHLIGHT_RADIUS * 2 + (int) (vars.size * 0.2) : 0) + 5; //bounding box buffer
//what is the size of the dot in degrees
- double resolution = getBBoxes(bboxString, width, height, size, vars.uncertainty, mbbox, bbox, pbbox);
+ double resolution = getBBoxes(bboxString, width, height, size, vars.uncertainty, mbbox, bbox, pbbox, tilebbox);
//resolution should be a value < 1
PointType pointType = getPointTypeForDegreesPerPixel(resolution);
@@ -1401,16 +1480,24 @@
response.setHeader("Cache-Control", "max-age=86400"); //age == 1 day
response.setContentType("image/png"); //only png images generated
- if("EPSG:4326".equals(srs))
- bboxString = convertBBox4326To900913(bboxString); // to work around a UDIG bug
-
+ boolean is4326 = false;
WmsEnv vars = new WmsEnv(env, styles);
double[] mbbox = new double[4];
double[] bbox = new double[4];
double[] pbbox = new double[4];
+ double[] tilebbox = new double[4];
int size = vars.size + (vars.highlight != null ? HIGHLIGHT_RADIUS * 2 + (int) (vars.size * 0.2) : 0) + 5; //bounding box buffer
- double resolution = getBBoxes(bboxString, width, height, size, vars.uncertainty, mbbox, bbox, pbbox);
+ double resolution;
+ if("EPSG:4326".equals(srs)) {
+ is4326 = true;
+ //bboxString = convertBBox4326To900913(bboxString); // to work around a UDIG bug
+
+ resolution = getBBoxes4326(bboxString, width, height, size, vars.uncertainty, mbbox, bbox, pbbox, tilebbox);
+ } else {
+ resolution = getBBoxes(bboxString, width, height, size, vars.uncertainty, mbbox, bbox, pbbox, tilebbox);
+ }
+
PointType pointType = getPointTypeForDegreesPerPixel(resolution);
logger.debug("Rendering: " + pointType.name());
@@ -1421,7 +1508,7 @@
q = getQ(cql_filter);
} else if(StringUtils.trimToNull(layers) != null && !"ALA:Occurrences".equalsIgnoreCase(layers)){
q = convertLayersParamToQ(layers);
- }
+ }
String[] boundingBoxFqs = new String[2];
boundingBoxFqs[0] = String.format("longitude:[%f TO %f]", bbox[0], bbox[2]);
@@ -1434,6 +1521,8 @@
//build request
if (q.length() > 0) {
requestParams.setQ(q);
+ } else {
+ q = requestParams.getQ();
}
//bounding box test (q must be 'qid:' + number)
@@ -1446,7 +1535,7 @@
}
}
- String[] originalFqs = requestParams.getFq();
+ String[] originalFqs = getFq(requestParams);
//get from cache
WMSTile wco = null;
@@ -1460,11 +1549,11 @@
if (wco == null) {
imgObj = wmsUncached(requestParams, vars, pointType, pbbox, mbbox,
width, height, width_mult, height_mult, pointWidth,
- originalFqs, hq, boundingBoxFqs, outlinePoints, outlineColour, response);
+ originalFqs, hq, boundingBoxFqs, outlinePoints, outlineColour, response, is4326, tilebbox);
} else {
imgObj = wmsCached(wco, requestParams, vars, pointType, pbbox, bbox, mbbox,
width, height, width_mult, height_mult, pointWidth,
- originalFqs, hq, boundingBoxFqs, outlinePoints, outlineColour, response);
+ originalFqs, hq, boundingBoxFqs, outlinePoints, outlineColour, response, is4326, tilebbox);
}
if (imgObj != null && imgObj.g != null) {
@@ -1638,7 +1727,8 @@
double height_mult, int pointWidth, String[] originalFqs, Set<Integer> hq,
String[] boundingBoxFqs, boolean outlinePoints,
String outlineColour,
- HttpServletResponse response) throws Exception {
+ HttpServletResponse response,
+ boolean is4326, double [] tilebbox) throws Exception {
ImgObj imgObj = null;
@@ -1677,6 +1767,12 @@
continue;
}
+ //for 4326
+ double top = tilebbox[3];
+ double bottom = tilebbox[1];
+ double left = tilebbox[0];
+ double right = tilebbox[2];
+
if (vars.colourMode.equals("grid")) {
//render grids
int[] count = counts.get(j);
@@ -1687,9 +1783,16 @@
float lat = ps[i + 1];
if (lng >= bbox[0] && lng <= bbox[2]
&& lat >= bbox[1] && lat <= bbox[3]) {
- x = (int) ((convertLngToPixel(lng) - pbbox[0]) * grid_width_mult);
- y = (int) ((convertLatToPixel(lat) - pbbox[3]) * grid_height_mult);
+
+ if (is4326) {
+ x = convertLngToPixel4326(lng, left, right, width);
+ y = convertLatToPixel4326(lat, top, bottom, height);
+ } else {
+ x = (int) ((convertLngToPixel(lng) - pbbox[0]) * grid_width_mult);
+ y = (int) ((convertLatToPixel(lat) - pbbox[3]) * grid_height_mult);
+ }
+
if (x >= 0 && x < divs && y >= 0 && y < divs) {
gridCounts[x][y] += count[i / 2];
}
@@ -1705,9 +1808,15 @@
float lat = ps[i + 1];
if (lng >= bbox[0] && lng <= bbox[2]
&& lat >= bbox[1] && lat <= bbox[3]) {
- x = (int) ((convertLngToPixel(lng) - pbbox[0]) * width_mult);
- y = (int) ((convertLatToPixel(lat) - pbbox[3]) * height_mult);
+ if (is4326) {
+ x = convertLngToPixel4326(lng, left, right, width);
+ y = convertLatToPixel4326(lat, top, bottom, height);
+ } else {
+ x = (int) ((convertLngToPixel(lng) - pbbox[0]) * width_mult);
+ y = (int) ((convertLatToPixel(lat) - pbbox[3]) * height_mult);
+ }
+
imgObj.g.fillOval(x - vars.size, y - vars.size, pointWidth, pointWidth);
if(outlinePoints){
imgObj.g.setPaint(oColour);
@@ -1742,18 +1851,18 @@
}
}
} else {
- drawUncertaintyCircles(requestParams, vars, height, pbbox, mbbox, width_mult, height_mult, imgObj.g, originalFqs, boundingBoxFqs);
+ drawUncertaintyCircles(requestParams, vars, height, width, pbbox, mbbox, width_mult, height_mult, imgObj.g, originalFqs, boundingBoxFqs, is4326, tilebbox);
}
//highlight
if (vars.highlight != null) {
- imgObj = drawHighlight(requestParams, vars, pointType, width, height, pbbox, width_mult, height_mult, imgObj, originalFqs, boundingBoxFqs);
+ imgObj = drawHighlight(requestParams, vars, pointType, width, height, pbbox, width_mult, height_mult, imgObj, originalFqs, boundingBoxFqs, is4326, tilebbox);
}
return imgObj;
}
- void drawUncertaintyCircles(SpatialSearchRequestParams requestParams, WmsEnv vars, int height, double[] pbbox, double[] mbbox, double width_mult, double height_mult, Graphics2D g, String[] originalFqs, String[] boundingBoxFqs) throws Exception {
+ void drawUncertaintyCircles(SpatialSearchRequestParams requestParams, WmsEnv vars, int height, int width, double[] pbbox, double[] mbbox, double width_mult, double height_mult, Graphics2D g, String[] originalFqs, String[] boundingBoxFqs, boolean is4326, double [] tilebbox) throws Exception {
//draw uncertainty circles
double hmult = (height / (mbbox[3] - mbbox[1]));
@@ -1787,6 +1896,12 @@
//TODO: paging
SolrDocumentList sdl = searchDAO.findByFulltext(requestParams);
+ //for 4326
+ double top = tilebbox[3];
+ double bottom = tilebbox[1];
+ double left = tilebbox[0];
+ double right = tilebbox[2];
+
double lng, lat;
int x, y;
int uncertaintyRadius = (int) Math.ceil(uncertaintyR[j] * hmult);
@@ -1800,8 +1915,13 @@
lng = (Double) sdl.get(i).getFieldValue("longitude");
lat = (Double) sdl.get(i).getFieldValue("latitude");
- x = (int) ((convertLngToPixel(lng) - pbbox[0]) * width_mult);
- y = (int) ((convertLatToPixel(lat) - pbbox[3]) * height_mult);
+ if (is4326) {
+ x = convertLngToPixel4326(lng, left, right, width);
+ y = convertLatToPixel4326(lat, top, bottom, height);
+ } else {
+ x = (int) ((convertLngToPixel(lng) - pbbox[0]) * width_mult);
+ y = (int) ((convertLatToPixel(lat) - pbbox[3]) * height_mult);
+ }
if (uncertaintyRadius > 0) {
g.drawOval(x - uncertaintyRadius, y - uncertaintyRadius, uncertaintyRadius * 2, uncertaintyRadius * 2);
@@ -1816,7 +1936,7 @@
ImgObj drawHighlight(SpatialSearchRequestParams requestParams, WmsEnv vars, PointType pointType,
int width, int height, double[] pbbox, double width_mult,
- double height_mult, ImgObj imgObj, String[] originalFqs, String[] boundingBoxFqs) throws Exception {
+ double height_mult, ImgObj imgObj, String[] originalFqs, String[] boundingBoxFqs, boolean is4326, double [] tilebbox) throws Exception {
String[] fqs = new String[originalFqs.length + 3];
System.arraycopy(originalFqs, 0, fqs, 3, originalFqs.length);
fqs[0] = vars.highlight;
@@ -1837,13 +1957,25 @@
imgObj.g.setStroke(new BasicStroke(2));
imgObj.g.setColor(new Color(255, 0, 0, 255));
int x, y;
+
+ //for 4326
+ double top = tilebbox[3];
+ double bottom = tilebbox[1];
+ double left = tilebbox[0];
+ double right = tilebbox[2];
+
for (int i = 0; i < ps.size(); i++) {
OccurrencePoint pt = ps.get(i);
float lng = pt.getCoordinates().get(0).floatValue();
float lat = pt.getCoordinates().get(1).floatValue();
- x = (int) ((convertLngToPixel(lng) - pbbox[0]) * width_mult);
- y = (int) ((convertLatToPixel(lat) - pbbox[3]) * height_mult);
+ if (is4326) {
+ x = convertLngToPixel4326(lng, left, right, width);
+ y = convertLatToPixel4326(lat, top, bottom, height);
+ } else {
+ x = (int) ((convertLngToPixel(lng) - pbbox[0]) * width_mult);
+ y = (int) ((convertLatToPixel(lat) - pbbox[3]) * height_mult);
+ }
imgObj.g.drawOval(x - highightRadius, y - highightRadius, highlightWidth, highlightWidth);
}
@@ -1888,7 +2020,7 @@
//points count
SpatialSearchRequestParams r = new SpatialSearchRequestParams();
r.setQ(requestParams.getQ());
- r.setFq(requestParams.getFq());
+ r.setFq(getFq(requestParams));
r.setQc(requestParams.getQc());
r.setPageSize(0);
r.setFacet(false);
@@ -1903,8 +2035,8 @@
ArrayList<String> forNulls = new ArrayList<String>(sz);
String[] fqs = null;
- String[] originalFqs = requestParams.getFq();
- if (requestParams.getFq() == null || requestParams.getFq().length == 0) {
+ String[] originalFqs = getFq(requestParams);
+ if (originalFqs == null || originalFqs.length == 0) {
fqs = new String[1];
} else {
fqs = new String[originalFqs.length + 1];
@@ -1986,6 +2118,39 @@
}
}
+ private String[] getFq(SpatialSearchRequestParams requestParams) {
+ int requestParamsFqLength = requestParams.getFq() != null ? requestParams.getFq().length : 0;
+
+ String [] qidFq = null;
+ int qidFqLength = 0;
+ String q = requestParams.getQ();
+ if (q.startsWith("qid:")) {
+ try {
+ qidFq = ParamsCache.get(Long.parseLong(q.substring(4))).getFqs();
+ if (qidFq != null) {
+ qidFqLength = qidFq.length;
+ }
+ } catch (Exception e) {
+ }
+ }
+
+ if (requestParamsFqLength + qidFqLength == 0) {
+ return null;
+ }
+
+ String [] allFqs = new String[requestParamsFqLength + qidFqLength];
+
+ if (requestParamsFqLength > 0) {
+ System.arraycopy(requestParams.getFq(), 0, allFqs, 0, requestParamsFqLength);
+ }
+
+ if (qidFqLength > 0) {
+ System.arraycopy(qidFq, 0, allFqs, requestParamsFqLength, qidFqLength);
+ }
+
+ return allFqs;
+ }
+
/**
* TODO remove code duplicate between wmsUncached and wmsCached
*
@@ -1996,7 +2161,8 @@
WmsEnv vars, PointType pointType, double[] pbbox,
double[] mbbox, int width, int height, double width_mult,
double height_mult, int pointWidth, String[] originalFqs, Set<Integer> hq,
- String[] boundingBoxFqs, boolean outlinePoints, String outlineColour, HttpServletResponse response) throws Exception {
+ String[] boundingBoxFqs, boolean outlinePoints, String outlineColour, HttpServletResponse response,
+ boolean is4326, double[] tilebbox) throws Exception {
//colour mapping
List<LegendItem> colours = (vars.colourMode.equals("-1") || vars.colourMode.equals("grid")) ? null : getColours(requestParams, vars.colourMode);
@@ -2008,7 +2174,7 @@
List<String> forNulls = new ArrayList<String>(sz);
String[] fqs = null;
String[] origAndBBoxFqs = null;
- if (requestParams.getFq() == null || requestParams.getFq().length == 0) {
+ if (originalFqs == null || originalFqs.length == 0) {
fqs = new String[3];
fqs[1] = boundingBoxFqs[0];
fqs[2] = boundingBoxFqs[1];
@@ -2057,7 +2223,16 @@
} else if (colours.size() >= colourList.length - 1) {
fqs = new String[forNulls.size()];
forNulls.toArray(fqs);
- requestParams.setFq(fqs);
+
+ String [] newFqs = new String[originalFqs.length + forNulls.size()];
+ if (originalFqs.length > 0) {
+ System.arraycopy(originalFqs, 0, newFqs, 0, originalFqs.length);
+ }
+ if (fqs.length > 0) {
+ System.arraycopy(fqs, 0, newFqs, originalFqs.length, fqs.length);
+ }
+ requestParams.setFq(newFqs);
+
points.add(searchDAO.getFacetPoints(requestParams, pointType));
pColour.add(colourList[colourList.length - 1] | (vars.alpha << 24));
}
@@ -2074,6 +2249,12 @@
double grid_height_mult = (height / (pbbox[1] - pbbox[3])) / (height / divs);
int x, y;
+ //for 4326
+ double top = tilebbox[3];
+ double bottom = tilebbox[1];
+ double left = tilebbox[0];
+ double right = tilebbox[2];
+
for (int j = 0; j < points.size(); j++) {
if(hq != null && hq.contains(j)){
@@ -2098,15 +2279,20 @@
float lng = pt.getCoordinates().get(0).floatValue();
float lat = pt.getCoordinates().get(1).floatValue();
- x = (int) ((convertLngToPixel(lng) - pbbox[0]) * grid_width_mult);
- y = (int) ((convertLatToPixel(lat) - pbbox[3]) * grid_height_mult);
+ if (is4326) {
+ x = convertLngToPixel4326(lng, left, right, width);
+ y = convertLatToPixel4326(lat, top, bottom, height);
+ } else {
+ x = (int) ((convertLngToPixel(lng) - pbbox[0]) * grid_width_mult);
+ y = (int) ((convertLatToPixel(lat) - pbbox[3]) * grid_height_mult);
+ }
if (x >= 0 && x < divs && y >= 0 && y < divs) {
gridCounts[x][y] += pt.getCount();
}
}
} else {
- renderPoints(vars, pbbox, width_mult, height_mult, pointWidth, outlinePoints, outlineColour, pColour, imgObj, j, ps);
+ renderPoints(vars, pbbox, width_mult, height_mult, pointWidth, outlinePoints, outlineColour, pColour, imgObj, j, ps, is4326, tilebbox, height, width);
}
}
@@ -2132,31 +2318,42 @@
}
}
} else {
- drawUncertaintyCircles(requestParams, vars, height, pbbox, mbbox, width_mult, height_mult, imgObj.g, originalFqs, boundingBoxFqs);
+ drawUncertaintyCircles(requestParams, vars, height, width, pbbox, mbbox, width_mult, height_mult, imgObj.g, originalFqs, boundingBoxFqs, is4326, tilebbox);
}
//highlight
if (vars.highlight != null) {
- imgObj = drawHighlight(requestParams, vars, pointType, width, height, pbbox, width_mult, height_mult, imgObj, originalFqs, boundingBoxFqs);
+ imgObj = drawHighlight(requestParams, vars, pointType, width, height, pbbox, width_mult, height_mult, imgObj, originalFqs, boundingBoxFqs, is4326, tilebbox);
}
return imgObj;
}
- private void renderPoints(WmsEnv vars, double[] pbbox, double width_mult, double height_mult, int pointWidth, boolean outlinePoints, String outlineColour, List<Integer> pColour, ImgObj imgObj, int j, List<OccurrencePoint> ps) {
+ private void renderPoints(WmsEnv vars, double[] pbbox, double width_mult, double height_mult, int pointWidth, boolean outlinePoints, String outlineColour, List<Integer> pColour, ImgObj imgObj, int j, List<OccurrencePoint> ps, boolean is4326, double [] tilebbox, int height, int width) {
int x;
int y;
Paint currentFill = new Color(pColour.get(j), true);
imgObj.g.setPaint(currentFill);
Color oColour = Color.decode(outlineColour);
+ //for 4326
+ double top = tilebbox[3];
+ double bottom = tilebbox[1];
+ double left = tilebbox[0];
+ double right = tilebbox[2];
+
for (int i = 0; i < ps.size(); i++) {
OccurrencePoint pt = ps.get(i);
float lng = pt.getCoordinates().get(0).floatValue();
float lat = pt.getCoordinates().get(1).floatValue();
- x = (int) ((convertLngToPixel(lng) - pbbox[0]) * width_mult);
- y = (int) ((convertLatToPixel(lat) - pbbox[3]) * height_mult);
+ if (is4326) {
+ x = convertLngToPixel4326(lng, left, right, width);
+ y = convertLatToPixel4326(lat, top, bottom, height);
+ } else {
+ x = (int) ((convertLngToPixel(lng) - pbbox[0]) * width_mult);
+ y = (int) ((convertLatToPixel(lat) - pbbox[3]) * height_mult);
+ }
//System.out.println("Drawing an oval.....");
imgObj.g.fillOval(x - vars.size, y - vars.size, pointWidth, pointWidth);
Index: pom.xml
===================================================================
--- pom.xml (revision 4551)
+++ pom.xml (revision 4552)
@@ -359,6 +359,12 @@
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
+ <!-- charting -->
+ <dependency>
+ <groupId>jfree</groupId>
+ <artifactId>jfreechart</artifactId>
+ <version>1.0.13</version>
+ </dependency>
</dependencies>
<repositories>
<!-- ALA repository -->
# checkout the svn project
bash-3.2$ cd ~/src
bash-3.2$ svn checkout http://ala-portal.googlecode.com/svn/trunk/biocache-service svn_biocache-service
bash-3.2$ cd svn_biocache-service
# generate the patch
bash-3.2$ svn diff -c r4552 ./ > Fix_for_4326_in_WMS-Scatterplot_service.patch
# OR use: svn diff -r $(SOME_REVISION):$(SOME_REVISION+n) ./ > your_patch_name.patch
bash-3.2$ svn diff -r r4535:r4552 ./ > Fix_for_4326_in_WMS-Scatterplot_service-revisions-diff.patch
# checkout the git version of the project
bash-3.2$ cd ~/src
bash-3.2$ git clone [email protected]:AtlasOfLivingAustralia/biocache-service.git
bash-3.2$ cd biocache-service
# review/test the patch/changes from svn with --dry-run
bash-3.2$ patch -p0 < ../svn_biocache-service/Fix_for_4326_in_WMS-Scatterplot_service.patch --dry-run
# apply the patch/changes from svn to the git version
bash-3.2$ patch -p0 < ../svn_biocache-service/Fix_for_4326_in_WMS-Scatterplot_service.patch
patching file src/main/java/au/org/ala/biocache/web/ScatterplotController.java
patching file src/main/java/au/org/ala/biocache/web/WMSController.java
patching file pom.xml
# verify what changed
bash-3.2$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: pom.xml
modified: src/main/java/au/org/ala/biocache/web/WMSController.java
Untracked files:
(use "git add <file>..." to include in what will be committed)
src/main/java/au/org/ala/biocache/web/ScatterplotController.java
no changes added to commit (use "git add" and/or "git commit -a")
# add the new files, etc.
bash-3.2$ git add src/main/java/au/org/ala/biocache/web/ScatterplotController.java
bash-3.2$ git add pom.xml
bash-3.2$ git add src/main/java/au/org/ala/biocache/web/WMSController.java
# review
bash-3.2$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: pom.xml
new file: src/main/java/au/org/ala/biocache/web/ScatterplotController.java
modified: src/main/java/au/org/ala/biocache/web/WMSController.java
bash-3.2$ git commit -m "Fix for 4326 in WMS, Scatterplot service, Fix for fqs in qids in WMS"
[master 41722dd] Fix for 4326 in WMS, Scatterplot service, Fix for fqs in qids in WMS
3 files changed, 474 insertions(+), 41 deletions(-)
create mode 100644 src/main/java/au/org/ala/biocache/web/ScatterplotController.java
# push, send pull request, etc.
bash-3.2$ git push
###
result: https://github.com/AtlasOfLivingAustralia/biocache-service/commit/41722dd707bc8d985e7f0aecbcb9c2b8a6dcfc91
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment