ingo@1115: /*
ingo@1115: * Copyright (c) 2010 by Intevation GmbH
ingo@1115: *
ingo@1115: * This program is free software under the LGPL (>=v2.1)
ingo@1115: * Read the file LGPL.txt coming with the software for details
ingo@1115: * or visit http://www.gnu.org/licenses/ if it does not exist.
ingo@1115: */
ingo@1115:
tim@335: package de.intevation.gnv.state.profile.verticalcrosssection;
tim@335:
ingo@837: import au.com.bytecode.opencsv.CSVWriter;
ingo@837:
ingo@527: import java.awt.Color;
sascha@521: import java.awt.Dimension;
sascha@521: import java.awt.Paint;
sascha@521: import java.io.IOException;
sascha@521: import java.io.OutputStream;
sascha@521: import java.io.UnsupportedEncodingException;
sascha@521: import java.util.ArrayList;
sascha@521: import java.util.Arrays;
sascha@521: import java.util.Collection;
sascha@521: import java.util.HashMap;
sascha@521: import java.util.Iterator;
sascha@521: import java.util.List;
sascha@521: import java.util.Locale;
sascha@521: import java.util.Map;
sascha@521:
ingo@632: import net.sf.ehcache.Cache;
sascha@521: import net.sf.ehcache.Element;
sascha@521:
sascha@521: import org.apache.log4j.Logger;
tim@830: import org.jfree.chart.ChartTheme;
sascha@521:
tim@830: import com.vividsolutions.jts.geom.Coordinate;
tim@830:
tim@830: import de.intevation.artifacts.CallContext;
tim@830: import de.intevation.gnv.artifacts.cache.CacheFactory;
tim@830: import de.intevation.gnv.artifacts.context.GNVArtifactContext;
tim@830: import de.intevation.gnv.artifacts.ressource.RessourceFactory;
tim@830: import de.intevation.gnv.chart.Chart;
tim@830: import de.intevation.gnv.chart.ChartLabels;
tim@830: import de.intevation.gnv.chart.VerticalCrossSectionChart;
ingo@837: import de.intevation.gnv.exports.DefaultProfile;
ingo@837: import de.intevation.gnv.exports.Export;
ingo@837: import de.intevation.gnv.exports.VerticalCrossODVExport;
tim@830: import de.intevation.gnv.geobackend.base.Result;
tim@830: import de.intevation.gnv.geobackend.base.ResultDescriptor;
tim@830: import de.intevation.gnv.geobackend.base.query.QueryExecutor;
tim@830: import de.intevation.gnv.geobackend.base.query.QueryExecutorFactory;
tim@830: import de.intevation.gnv.geobackend.base.query.exception.QueryException;
tim@830: import de.intevation.gnv.geobackend.sde.datasources.RasterObject;
tim@830: import de.intevation.gnv.jfreechart.PolygonDataset;
tim@830: import de.intevation.gnv.jfreechart.PolygonSeries;
tim@830: import de.intevation.gnv.math.AttributedXYColumns;
tim@830: import de.intevation.gnv.math.HeightValue;
tim@830: import de.intevation.gnv.math.IJKey;
tim@830: import de.intevation.gnv.math.Interpolation3D;
tim@830: import de.intevation.gnv.math.LinearMetrics;
tim@830: import de.intevation.gnv.math.QueriedXYDepth;
tim@830: import de.intevation.gnv.math.XYColumn;
tim@830: import de.intevation.gnv.raster.Filter;
tim@830: import de.intevation.gnv.raster.IsoAttributeGenerator;
tim@830: import de.intevation.gnv.raster.IsoPolygonSeriesProducer;
tim@830: import de.intevation.gnv.raster.Palette;
tim@830: import de.intevation.gnv.raster.PaletteManager;
tim@830: import de.intevation.gnv.raster.PolygonDatasetProducer;
tim@830: import de.intevation.gnv.raster.Raster;
tim@830: import de.intevation.gnv.raster.Vectorizer;
tim@830: import de.intevation.gnv.state.InputData;
tim@830: import de.intevation.gnv.state.describedata.KeyValueDescibeData;
tim@830: import de.intevation.gnv.state.exception.StateException;
tim@830: import de.intevation.gnv.state.timeseries.TimeSeriesOutputState;
tim@830: import de.intevation.gnv.statistics.Statistics;
tim@830: import de.intevation.gnv.statistics.VerticalCrossSectionStatistics;
tim@830: import de.intevation.gnv.utils.DistanceCalculator;
tim@830: import de.intevation.gnv.utils.StringUtils;
tim@830: import de.intevation.gnv.utils.WKTUtils;
sascha@463:
tim@335: /**
sascha@780: * @author Tim Englich
sascha@780: * @author Ingo Weinzierl
sascha@780: * @author Sascha L. Teichmann
tim@335: */
tim@335: public class VerticalCrossSectionOutputState extends TimeSeriesOutputState {
tim@335:
ingo@492: public static final String CHART_TYPE = "verticalcrosssection";
ingo@492:
sascha@521: public static final Integer GROUND_FILL_INDEX = Integer.valueOf(-2);
sascha@521:
sascha@528: public static final boolean USE_INDEX_BUFFER =
sascha@528: Boolean.getBoolean("gnv.vertical.cross.section.index.buffer");
sascha@528:
ingo@429: public static final String[] ATTRIBUTE_LIST = {
ingo@429: "SHAPE",
ingo@429: "Z",
ingo@429: "YORDINATE",
ingo@429: "IPOSITION",
ingo@429: "JPOSITION",
ingo@429: "KPOSITION"
ingo@429: };
ingo@429:
ingo@429: private static Logger log = Logger.getLogger(
ingo@429: VerticalCrossSectionOutputState.class);
ingo@429:
ingo@429: private String ijkQueryID = "horizontalprofile_meshpoint_cross_ij";
ingo@429:
ingo@492: private String rangeLabel;
ingo@492:
tim@335: /**
tim@335: * The UID of this Class
tim@335: */
tim@335: private static final long serialVersionUID = 3233620652465061860L;
tim@335:
tim@335: /**
tim@335: * Constructor
tim@335: */
tim@335: public VerticalCrossSectionOutputState() {
tim@335: super();
ingo@343: super.domainLable = "chart.verticalcrosssection.title.xaxis";
ingo@492: this.rangeLabel = "chart.verticalcrosssection.title.yaxis";
ingo@492: }
ingo@492:
ingo@533: @Override
ingo@533: public void initialize(String uuid, CallContext callContext)
ingo@533: throws StateException {
ingo@533: super.initialize(uuid, callContext);
sascha@778:
ingo@533: getChartResult(uuid, callContext);
ingo@533: }
ingo@492:
ingo@492: @Override
ingo@492: protected ChartLabels createChartLabels(Locale locale, String uuid) {
ingo@492: RessourceFactory factory = RessourceFactory.getInstance();
ingo@654: InputData input = inputData.get(parameterValuesName);
ingo@654: String parameterName = input.getDescription()[0];
ingo@492:
ingo@492: if (parameterName == null)
ingo@492: parameterName = "parameterid";
ingo@492:
ingo@492: return new ChartLabels(
ingo@492: createChartTitle(locale, uuid),
ingo@492: createChartSubtitle(locale, uuid),
ingo@492: factory.getRessource(locale, domainLable, domainLable),
ingo@492: factory.getRessource(locale, rangeLabel, rangeLabel),
ingo@492: parameterName
ingo@492: );
ingo@492: }
ingo@492:
ingo@492:
ingo@492: @Override
ingo@492: protected String createChartSubtitle(Locale locale, String uuid) {
ingo@654: InputData data = inputData.get(dateValueName);
ingo@654: String date = data.getDescription()[0];
ingo@492:
ingo@492: if (date == null)
ingo@492: date = "dateid";
ingo@492:
ingo@492: RessourceFactory factory = RessourceFactory.getInstance();
ingo@492: String chartType = factory.getRessource(
ingo@492: locale, CHART_TYPE, CHART_TYPE);
ingo@492:
ingo@492: return chartType + ": " + date;
tim@335: }
tim@335:
ingo@429:
ingo@429: @Override
sascha@439: protected Object getChartResult(String uuid, CallContext callContext) {
ingo@429: log.debug("VerticalCrossSectionOutputState.getChartResult");
ingo@1060: String key = getHash();
ingo@429:
ingo@632: CacheFactory factory = CacheFactory.getInstance();
ingo@632: if (factory.isInitialized()) {
ingo@1030: log.info("Using a cachce - key: " + key);
ingo@632: Cache cache = factory.getCache();
ingo@429:
ingo@632: Element element = cache.get(key);
ingo@632: if (element != null)
ingo@632: return element.getObjectValue();
ingo@429:
ingo@632: log.debug("No results in cache yet.");
ingo@632: Object obj = getData(uuid, callContext);
ingo@632: cache.put(new Element(key, obj));
ingo@632:
ingo@632: return obj;
ingo@632: }
ingo@632: else {
ingo@632: log.info("Not using a cache.");
ingo@632: return getData(uuid, callContext);
ingo@632: }
ingo@632: }
ingo@632:
ingo@632:
ingo@804: /**
ingo@804: * Retrieves the data used to create a VerticalCrossProfileChart.
ingo@804: *
ingo@804: * @param uuid The UUID of the current artifact.
ingo@804: * @param callContext The CallContext object.
ingo@804: * @return the data used to create a VerticalCrossProfileChart.
ingo@804: */
ingo@632: protected Object getData(String uuid, CallContext callContext) {
ingo@632: Collection result = null;
ingo@632: InputData meshId = inputData.get("meshid");
ingo@1090: String meshLine = getLineString();
ingo@429:
sascha@440: if (meshLine == null) {
sascha@440: log.error("mesh_linestring is not defined");
sascha@440: throw new IllegalStateException("missing mesh_linestring");
ingo@429: }
ingo@429:
sascha@440: if (meshId == null) {
sascha@440: log.error("meshid is not defined");
sascha@440: throw new IllegalStateException("missing meshid");
sascha@440: }
sascha@440:
sascha@440: Coordinate [] coords = WKTUtils.toCoordinates(
ingo@1090: meshLine);
sascha@440:
sascha@440: if (coords == null) {
sascha@440: throw new IllegalStateException("cannot read coordinates");
sascha@440: }
sascha@440:
sascha@440: try {
sascha@528: String additionWhere = USE_INDEX_BUFFER
sascha@528: ? WKTUtils.worldCoordinatesToIndex(
sascha@528: coords,
sascha@528: result,
sascha@528: meshId.getValue(),
sascha@528: ijkQueryID)
sascha@528: : WKTUtils.TRUE_EXPRESSION;
sascha@440:
sascha@440: String[] addedFilterValues = StringUtils.append(
sascha@440: generateFilterValuesFromInputData(),
sascha@440: additionWhere);
sascha@440:
sascha@440: QueryExecutor exec = QueryExecutorFactory
sascha@440: .getInstance()
sascha@440: .getQueryExecutor();
sascha@440:
sascha@440: result = exec.executeQuery(queryID, addedFilterValues);
sascha@440: }
sascha@440: catch (QueryException qe) {
sascha@440: log.error(qe, qe);
sascha@440: }
sascha@440:
sascha@440: Object obj = process(
sascha@440: Arrays.asList(coords),
sascha@440: preProcess(result),
sascha@440: callContext);
sascha@440:
ingo@429: return obj;
ingo@429: }
ingo@429:
ingo@492:
ingo@1090: protected String getLineString() {
ingo@1090: InputData meshLine = inputData.get("mesh_linestring");
ingo@1090:
ingo@1090: return meshLine != null ? meshLine.getValue() : null;
ingo@1090: }
ingo@1090:
ingo@1090:
ingo@804: @Override
ingo@492: protected String getSelectedInputDataName(String uuid, String id) {
ingo@492: Collection values = getCollection(id, uuid);
ingo@492:
ingo@492: if (values != null) {
ingo@492: Iterator it = values.iterator();
ingo@492:
ingo@492: while (it.hasNext()) {
ingo@492: KeyValueDescibeData data = (KeyValueDescibeData) it.next();
ingo@492:
ingo@492: if (data.isSelected()) {
ingo@492: return data.getValue();
ingo@492: }
ingo@492: }
ingo@492: }
ingo@492: return null;
ingo@492: }
ingo@492:
sascha@463: private static int getGroundInterpolation(CallContext callContext) {
sascha@778: GNVArtifactContext context =
sascha@463: (GNVArtifactContext)callContext.globalContext();
sascha@463:
sascha@463: String interpolation = (String)context.get(
sascha@463: GNVArtifactContext.VERTICAL_CROSS_SECTION_GROUND_INTERPOLATION_KEY);
sascha@463:
sascha@463: return RasterObject.getInterpolationType(interpolation);
sascha@463: }
sascha@463:
sascha@445: private static Dimension getRasterSize(CallContext callContext) {
sascha@778: GNVArtifactContext context =
sascha@445: (GNVArtifactContext)callContext.globalContext();
sascha@445: Dimension size = (Dimension)context.get(
sascha@445: GNVArtifactContext.VERTICAL_CROSS_SECTION_SAMPLES_KEY);
sascha@445: return size != null
sascha@445: ? size
sascha@445: : GNVArtifactContext.DEFAULT_VERTICAL_CROSS_SECTION_SAMPLES;
sascha@445: }
sascha@445:
sascha@446: private static List getFilterFactories(
sascha@446: CallContext callContext
sascha@446: ) {
sascha@778: GNVArtifactContext context =
sascha@445: (GNVArtifactContext)callContext.globalContext();
sascha@445: List factories = (List)context.get(
sascha@445: GNVArtifactContext.VERTICAL_CROSS_SECTION_FILTER_FACTORIES_KEY);
sascha@445: return factories != null
sascha@445: ? factories
sascha@445: : new ArrayList();
sascha@445: }
sascha@445:
sascha@445: private static Map getPalettes(
sascha@445: CallContext callContext
sascha@445: ) {
sascha@778: GNVArtifactContext context =
sascha@445: (GNVArtifactContext)callContext.globalContext();
sascha@445: Map palettes =
sascha@445: (Map)context.get(
sascha@445: GNVArtifactContext.PALETTES_KEY);
sascha@445: return palettes != null
sascha@445: ? palettes
sascha@445: : new HashMap();
sascha@445: }
sascha@445:
sascha@521: private static Paint getGroundFill(CallContext callContext) {
sascha@778: GNVArtifactContext context =
sascha@521: (GNVArtifactContext)callContext.globalContext();
sascha@521: Paint fill = (Paint)context.get(
sascha@521: GNVArtifactContext.VERTICAL_CROSS_SECTION_GROUND_FILL_KEY);
sascha@521: return fill != null
sascha@521: ? fill
sascha@521: : GNVArtifactContext.DEFAULT_VERTICAL_CROSS_SECTION_GROUND_FILL;
sascha@521: }
sascha@521:
sascha@445: public static final double EPSILON = 1e-5d;
ingo@429:
ingo@804:
ingo@804: /**
ingo@804: * Finalize the data used for chart generation. Isolines are added, colors
ingo@804: * are assigned to polygons and the seabed is added.
ingo@804: *
ingo@804: * @param path The path which have been inserted while parameterization.
ingo@804: * @param columns The data used to be displayed in a 2D chart.
ingo@804: * @param callContext The CallContext object.
ingo@804: * @return the finalized data ready for chart generation.
ingo@804: */
sascha@440: protected Object process(
sascha@440: List path,
sascha@440: AttributedXYColumns columns,
sascha@440: CallContext callContext
sascha@440: ) {
sascha@445: Integer parameterId =
sascha@445: (Integer)columns.getAttribute("GROUP1"); // XXX: hardcoded
ingo@429:
sascha@445: if (parameterId == null) {
sascha@445: log.error("missing parameter id");
sascha@445: return null;
sascha@445: }
sascha@445:
sascha@445: Map paletteManagers =
sascha@445: getPalettes(callContext);
sascha@445:
sascha@445: PaletteManager paletteManager = paletteManagers.get(parameterId);
sascha@445:
sascha@445: if (paletteManager == null) {
sascha@445: log.error("no palette found for parameter id " + parameterId);
sascha@445: return null;
sascha@445: }
sascha@445:
sascha@445: boolean debug = log.isDebugEnabled();
sascha@445:
sascha@445: if (debug) {
sascha@445: log.debug("using palette '" + paletteManager.getName() + "'");
sascha@445: }
sascha@445:
sascha@445: Dimension rasterSize = getRasterSize(callContext);
sascha@445: List filterFactories = getFilterFactories(callContext);
sascha@445: Interpolation3D interpolation = new Interpolation3D(rasterSize);
sascha@445:
sascha@446: double distance = DistanceCalculator.calculateDistance(path);
sascha@445:
sascha@445: if (distance < EPSILON) {
sascha@445: log.warn("distance too short for interpolation");
sascha@445: return null;
sascha@445: }
sascha@445:
sascha@445: boolean success = interpolation.interpolate(
sascha@445: path,
sascha@445: columns.getXYColumns(),
sascha@445: 0d,
sascha@445: distance,
sascha@445: LinearMetrics.INSTANCE,
sascha@463: new QueriedXYDepth(
sascha@463: getGroundInterpolation(callContext)));
sascha@445:
sascha@445: if (!success) {
sascha@445: log.warn("interpolation failed");
sascha@445: return null;
sascha@445: }
sascha@445:
sascha@445: // Do the post processing
sascha@445: Raster raster = new Raster(
sascha@445: interpolation.getRaster(),
sascha@445: rasterSize.width);
sascha@445:
sascha@445: for (Filter.Factory factory: filterFactories) {
sascha@445: raster = factory.create().filter(raster);
sascha@445: }
sascha@445:
sascha@445: if (debug) {
sascha@445: log.debug("to indexed raster");
sascha@445: }
sascha@445:
sascha@445: // scan for regions with base palette
sascha@448: Palette basePalette = paletteManager.getBase();
sascha@445:
sascha@448: int [] intRaster = raster.toIndexed(basePalette);
sascha@445:
sascha@445: // produce JFreeChart compatible polygons
sascha@445:
sascha@445: if (debug) {
sascha@445: log.debug("vectorize indexed raster");
sascha@445: }
sascha@445:
sascha@447: double maxDepth = interpolation.getMaxDepth();
sascha@447:
sascha@445: PolygonDatasetProducer pdsp = new PolygonDatasetProducer(
sascha@445: 0, 0,
sascha@447: distance, maxDepth);
sascha@445:
sascha@447: int numRegions = new Vectorizer(intRaster, rasterSize.width)
sascha@447: .process(pdsp);
sascha@445:
sascha@448: PolygonDataset pds = pdsp.getPolygonDataset();
sascha@446:
sascha@521: // Count number of colors before generating seabed
sascha@521: // because its used to determine the number of iso lines.
sascha@448: int numColors = pds.getSeriesCount();
sascha@445:
sascha@445: if (debug) {
sascha@445: log.debug("number of regions: " + numRegions);
sascha@448: log.debug("number of colors: " + numColors);
sascha@445: }
sascha@445:
sascha@521: // generate seabed polygon
sascha@521:
sascha@521: PolygonSeries seabed = OutputHelper.createSeabedPolygon(
sascha@521: interpolation,
sascha@521: GROUND_FILL_INDEX);
sascha@521:
sascha@521: if (seabed != null) {
sascha@521: pds.addSeries(seabed);
sascha@521: }
sascha@521:
sascha@447: // generate iso lines
sascha@447:
sascha@448: int numIso;
sascha@447:
sascha@448: if (numColors < 5) { numIso = 5; }
sascha@448: else if (numColors < 10) { numIso = 2; }
sascha@448: else { numIso = 0; }
sascha@448:
sascha@448: Palette isoPalette;
sascha@448:
sascha@448: if (numIso == 0) { // same palette
sascha@448: isoPalette = basePalette;
sascha@448: /* intRaster = intRaster; */
sascha@448: }
sascha@448: else {
sascha@448: isoPalette = paletteManager.getLevel(numIso);
sascha@448: intRaster = raster.toIndexed(isoPalette);
sascha@448: }
sascha@447:
sascha@447: IsoPolygonSeriesProducer ipsp = new IsoPolygonSeriesProducer(
sascha@447: 0, 0,
sascha@447: distance, maxDepth);
sascha@447:
sascha@447: numRegions = new Vectorizer(false, intRaster, rasterSize.width)
sascha@447: .process(ipsp);
sascha@447:
sascha@448: IsoAttributeGenerator iag = new IsoAttributeGenerator(isoPalette);
sascha@778: Collection ps = ipsp.getSeries(iag);
sascha@448: ipsp.clear();
sascha@447:
sascha@447: if (debug) {
sascha@447: log.debug("num of iso regions: " + numRegions);
sascha@447: log.debug("num of iso series: " + ps.size());
sascha@447: }
sascha@447:
sascha@447: pds.addAllSeries(ps);
sascha@447:
sascha@446: columns.setInterpolation(interpolation);
sascha@446: columns.setPolygonDataset(pds);
sascha@446:
sascha@446: return columns;
ingo@429: }
ingo@429:
ingo@429:
ingo@804: /**
ingo@804: * Pre-process the data returned by database query. The resulting data is
ingo@804: * not ready for chart creation!
ingo@804: *
ingo@804: * @param results Data returned by database.
ingo@804: * @return Pre-processed data which is not ready for chart creation yet.
ingo@804: */
ingo@429: protected AttributedXYColumns preProcess(Collection results) {
sascha@432:
ingo@429: AttributedXYColumns attColumns = new AttributedXYColumns();
sascha@432: Map map = new HashMap(1013);
ingo@429: Iterator iter = results.iterator();
ingo@429:
ingo@429: int sIdx = -1;
ingo@429: int iIdx = -1;
ingo@429: int jIdx = -1;
ingo@429: int kIdx = -1;
ingo@429: int vIdx = -1;
ingo@429: int zIdx = -1;
ingo@429:
ingo@429: while (iter.hasNext()) {
ingo@429: Result result = (Result) iter.next();
ingo@429:
ingo@429: if (sIdx == -1) {
ingo@429: ResultDescriptor rd = result.getResultDescriptor();
ingo@429: int columnCount = rd.getColumnCount();
ingo@429:
ingo@429: sIdx = rd.getColumnIndex("SHAPE");
ingo@429: iIdx = rd.getColumnIndex("IPOSITION");
ingo@429: jIdx = rd.getColumnIndex("JPOSITION");
ingo@429: kIdx = rd.getColumnIndex("KPOSITION");
ingo@429: vIdx = rd.getColumnIndex("YORDINATE");
ingo@429: zIdx = rd.getColumnIndex("Z");
ingo@429:
ingo@429: for (int i = 0; i < columnCount; i++) {
ingo@429: String colName = rd.getColumnName(i);
ingo@429:
sascha@439: if (!StringUtils.contains(ATTRIBUTE_LIST, colName)) {
ingo@429: attColumns.setAttribute(
ingo@429: colName,
ingo@429: result.getObject(colName));
ingo@429: }
ingo@429: }
ingo@429: }
ingo@429:
sascha@432: double v = result.getDouble(vIdx);
sascha@432: double z = result.getDouble(zIdx);
sascha@432: int i = result.getInteger(iIdx);
sascha@432: int j = result.getInteger(jIdx);
sascha@432: int k = result.getInteger(kIdx);
ingo@429:
sascha@432: IJKey key = new IJKey(i, j);
sascha@431:
sascha@432: XYColumn col = (XYColumn)map.get(key);
ingo@429:
sascha@432: if (col == null) {
sascha@432: Coordinate coord = WKTUtils.toCoordinate(result.getString(sIdx));
sascha@432: if (coord == null) coord = new Coordinate();
sascha@445: col = new XYColumn(coord.x, coord.y, i, j);
sascha@432: map.put(key, col);
ingo@429: }
sascha@432:
sascha@432: col.add(new HeightValue(z, v, k));
ingo@429: }
ingo@429:
sascha@432: ArrayList cols = new ArrayList(map.values());
ingo@429: attColumns.setXYColumns(cols);
ingo@429:
ingo@429: return attColumns;
ingo@429: }
ingo@429:
ingo@429:
ingo@804: /**
ingo@804: * This getChart
method returns a 2D VerticalCrossSectionChart
ingo@804: * displaying polygon data with isolines and a legend describing the colors
ingo@804: * used in that chart.
ingo@804: *
ingo@804: * @param chartLables Labels used to decorate the chart.
ingo@804: * @param theme The theme used to adjust the look of the chart.
ingo@804: * @param parameters A collection with parameters this chart contains.
ingo@804: * @param measurements A collection with measurement this chart contains.
ingo@804: * @param dates A collection with dates this chart contains.
ingo@804: * @param result The data collection used to be displayed in this chart.
ingo@804: * @param locale The Locale used to determine the language.
ingo@804: * @param uuid The uuid of the current artifact.
ingo@804: * @param linesVisible A boolean property to determine the visibility of
ingo@804: * lines connecting two points in a chart (not used in this chart type).
ingo@804: * @param shapesVisible A boolean property to determine the visiblity of
ingo@804: * datapoints in this chart (not used in this chart type).
ingo@804: * @param callContext The CallContext object.
ingo@804: * @return a 2D chart representing the data as polygons.
ingo@804: */
tim@335: @Override
tim@335: protected Chart getChart(
tim@335: ChartLabels chartLables,
ingo@358: ChartTheme theme,
tim@335: Collection parameters,
tim@335: Collection measurements,
tim@335: Collection dates,
ingo@429: Object result,
tim@335: Locale locale,
tim@335: String uuid,
tim@335: boolean linesVisible,
sascha@439: boolean shapesVisible,
sascha@439: CallContext callContext
tim@335: ) {
tim@335: Chart chart = null;
tim@335:
tim@335: if (CACHE_CHART) {
tim@335: log.info("Try to get verticalcrosssection chart from cache.");
sascha@439: chart = (Chart) getChartFromCache(uuid, callContext);
tim@335: }
tim@335:
tim@335: if (chart != null)
tim@335: return chart;
tim@335:
tim@335: log.info("Chart not in cache yet.");
ingo@429:
sascha@462: if (!(result instanceof AttributedXYColumns)) {
sascha@462: log.error("result of wrong type");
sascha@462: return null;
sascha@462: }
sascha@462:
sascha@521: AttributedXYColumns columns = (AttributedXYColumns)result;
sascha@446:
sascha@446: Integer parameterId =
sascha@446: (Integer)columns.getAttribute("GROUP1"); // XXX: hardcoded
sascha@446:
sascha@446: if (parameterId == null) {
sascha@446: log.error("missing parameter id");
sascha@446: return null;
sascha@446: }
sascha@446:
sascha@446: Map paletteManagers =
sascha@446: getPalettes(callContext);
sascha@446:
sascha@446: PaletteManager paletteManager = paletteManagers.get(parameterId);
sascha@446:
sascha@446: if (paletteManager == null) {
sascha@446: log.error("no palette found for parameter id " + parameterId);
sascha@446: return null;
sascha@446: }
sascha@446:
sascha@521: HashMap special = new HashMap();
sascha@521: special.put(GROUND_FILL_INDEX, getGroundFill(callContext));
sascha@521:
sascha@446: chart = new VerticalCrossSectionChart(
sascha@446: columns,
sascha@446: paletteManager.getBase(),
sascha@521: special,
ingo@492: locale,
ingo@492: chartLables);
sascha@446:
tim@335: chart.generateChart();
ingo@527: ((VerticalCrossSectionChart)chart).setBackgroundPaint(Color.WHITE);
tim@335:
tim@335: if (CACHE_CHART) {
tim@335: log.info("Put chart into cache.");
tim@335: purifyChart(chart, uuid);
tim@335: }
tim@335:
tim@335: return chart;
tim@335: }
tim@335:
ingo@804:
tim@335: @Override
tim@335: protected Statistics getStatisticsGenerator() {
sascha@454: return new VerticalCrossSectionStatistics();
tim@335: }
ingo@429:
tim@335: /**
ingo@804: * Nothing happens here. This method should never be called until
ingo@804: * there is a wise implementation of a csv representation of the polygon
ingo@804: * data.
ingo@804: *
ingo@804: * @param outputStream The output stream used to write the csv file to.
ingo@804: * @param chartResult The data used to be written to csv file.
ingo@804: * @throws UnsupportedEncodingException if the encoding is not supported.
ingo@804: * @throws IOException if an error occured while writing to output stream.
ingo@804: * @throws StateException if an error occured while csv file creation.
tim@335: */
tim@335: @Override
sascha@432: protected void createCSV(
sascha@432: OutputStream outputStream,
sascha@432: Collection chartResult
sascha@432: )
sascha@778: throws UnsupportedEncodingException, IOException, StateException
sascha@432: {
sascha@521: // TODO: Implement a substitution which makes sense.
tim@335: }
tim@830:
tim@830: @Override
ingo@837: protected void createODV(
ingo@837: OutputStream outputStream,
ingo@837: String uuid,
ingo@837: CallContext callContext)
ingo@837: throws IOException, StateException
ingo@837: {
ingo@837: // 'Profilschnitte' contain one parameter only
ingo@837: Collection tmp = getParameters(uuid);
ingo@837: KeyValueDescibeData param = (KeyValueDescibeData) tmp.toArray()[0];
ingo@837:
ingo@837: String [] COLUMN_HEADER = {
ingo@837: "Cruise",
ingo@837: "Station",
ingo@837: "Type",
ingo@837: "yyyy-mm-dd hh:mm",
ingo@837: "Lon (°E)",
ingo@837: "Lat (°N)",
ingo@837: "Bot. Depth [m]",
ingo@837: "Depth [m]",
ingo@837: "QF",
ingo@837: param.getValue()
ingo@837: };
ingo@837:
ingo@837: Export.Profile ODV_PROFILE = new DefaultProfile(
ingo@837: COLUMN_HEADER,
ingo@837: '\t',
ingo@837: CSVWriter.NO_QUOTE_CHARACTER,
ingo@837: CSVWriter.NO_ESCAPE_CHARACTER,
ingo@837: "ODV",
ingo@837: "ISO-8859-1");
ingo@837:
ingo@837: Object chartResult = getChartResult(uuid, callContext);
ingo@837:
ingo@837: if (chartResult == null) {
ingo@837: log.error("No data for export found.");
ingo@837: return;
ingo@837: }
ingo@837:
ingo@837: List result = new ArrayList(1);
ingo@837: result.add(chartResult);
ingo@837:
ingo@837: InputData data = inputData.get(dateValueName);
ingo@837: String date = data.getDescription()[0];
ingo@837:
ingo@837: Interpolation3D interpol = ((AttributedXYColumns)
ingo@837: chartResult).getInterpolation();
ingo@837:
ingo@837: Coordinate[] coords = interpol.getCoordinates();
ingo@837: double[] depth = interpol.getDepths();
ingo@837: double[] raster = interpol.getRaster();
ingo@837:
ingo@837: Export export = new VerticalCrossODVExport(
ingo@837: interpol.getCoordinates(),
ingo@837: interpol.getCellHeight(),
ingo@852: interpol.getCellWidth(),
ingo@837: interpol.getRaster(),
ingo@837: date,
ingo@837: interpol.getWidth(),
ingo@837: interpol.getHeight());
ingo@837:
ingo@837: export.create(ODV_PROFILE, outputStream, null);
tim@830: }
tim@335: }
sascha@521: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :