Last active
August 29, 2015 14:03
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 --> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 --> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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