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 :