/** * Render image consisting of computation result. This method will be run in background thread, so * it can have a while. Implementation should periodically check if status.isCancelled() and abort * (return null) if so. * * @param xAxis values for x dimension * @param yAxis values for y dimension * @param status status to be checked periodically * @return computation result as two-dimensional array * @throws Exception if computational error occurs */ public BufferedImage renderImage( Axis<Number> xAxis, Axis<Number> yAxis, ImageRendererStatus status) throws Exception { ImageResult result; int width = (int) xAxis.getWidth(); int height = (int) yAxis.getHeight(); double xMin = xAxis.getValueForDisplay(0.0).doubleValue(); double xMax = xAxis.getValueForDisplay(width - 1).doubleValue(); double yMin = yAxis.getValueForDisplay(0.0).doubleValue(); double yMax = yAxis.getValueForDisplay(height - 1).doubleValue(); PreferencesWithAxes<P> pax = new PreferencesWithAxes<P>(getPreferences(), width, height, xMin, xMax, yMin, yMax); CachedImageResult<PreferencesWithAxes<P>> cache = cache_; if (cache != null && cache.preferences.equals(pax)) { result = cache.result; } else { result = compute(pax, status); if (result == null) { return null; } cache_ = new CachedImageResult<PreferencesWithAxes<P>>(pax, result); } BufferedImage image = new BufferedImage(pax.width, pax.height, BufferedImage.TYPE_INT_RGB); if (result == null) { return null; } double max = 0; for (int ix = 0; ix < pax.width; ++ix) { for (int iy = 0; iy < pax.height; ++iy) { max = Math.max(max, result.values[ix][iy].abs()); } } int[] palette = palette_.getPalette(); boolean inverted = inverted_; for (int ix = 0; ix < pax.width; ++ix) { if (status.isCancelled()) { return null; } for (int iy = 0; iy < pax.height; ++iy) { double t = result.values[ix][iy].abs() / max; if (inverted) { t = 1.0 - t; } int value = palette[Math.min((int) Math.floor(t * palette.length), palette.length - 1)]; image.setRGB(ix, iy, value); } } return image; }
@Override public Iterable<Data<X, Y>> getVisibleData() { final Axis<X> xAxis = getChart().getXAxis(); final double width = xAxis.getWidth(); List<Data<X, Y>> visible = getData() .filtered( new Predicate<Data<X, Y>>() { @Override public boolean test(Data<X, Y> item) { final double p = xAxis.getDisplayPosition(item.getXValue()); return p >= 0 && p <= width; } }); return visible; }