teichmann@5831: package org.dive4elements.river.exports; ingo@2706: rrenkert@4626: import java.util.Arrays; rrenkert@4626: ingo@2706: import org.apache.log4j.Logger; ingo@2706: ingo@2706: import org.jfree.data.xy.XYSeries; ingo@2706: ingo@2706: import org.w3c.dom.Document; ingo@2706: teichmann@5831: import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; teichmann@5831: import org.dive4elements.artifactdatabase.state.Facet; ingo@2706: teichmann@5831: import org.dive4elements.river.artifacts.FLYSArtifact; ingo@2706: teichmann@5831: import org.dive4elements.river.artifacts.access.FlowVelocityAccess; teichmann@5831: import org.dive4elements.river.artifacts.model.FacetTypes; teichmann@5831: import org.dive4elements.river.artifacts.model.FlowVelocityData; teichmann@5831: import org.dive4elements.river.artifacts.model.minfo.BedDiameterResult; teichmann@5831: import org.dive4elements.river.artifacts.model.minfo.BedloadDiameterResult; teichmann@5831: import org.dive4elements.river.model.FlowVelocityMeasurementValue; ingo@2706: teichmann@5831: import org.dive4elements.river.jfree.Bounds; teichmann@5831: import org.dive4elements.river.jfree.DoubleBounds; teichmann@5831: import org.dive4elements.river.jfree.FLYSAnnotation; teichmann@5831: import org.dive4elements.river.jfree.StyledXYSeries; teichmann@5831: teichmann@5831: import org.dive4elements.river.utils.FLYSUtils; ingo@2706: ingo@2706: ingo@2706: /** ingo@2706: * An OutGenerator that generates flow velocity curves. ingo@2706: * ingo@2706: * @author Ingo Weinzierl ingo@2706: */ ingo@2706: public class FlowVelocityGenerator ingo@2706: extends XYChartGenerator ingo@2706: implements FacetTypes ingo@2706: { ingo@2706: public enum YAXIS { ingo@2706: V(0), felix@4468: T(1), rrenkert@5549: Q(2), rrenkert@5549: D(3); felix@4457: /* TODO Q and Density will come as 4th and 3rd axis. */ ingo@2706: protected int idx; ingo@2706: private YAXIS(int c) { ingo@2706: idx = c; ingo@2706: } ingo@2706: } ingo@2706: ingo@2706: /** The logger that is used in this generator. */ ingo@2706: private static Logger logger = Logger.getLogger(FlowVelocityGenerator.class); ingo@2706: ingo@2706: /** Key to look up internationalized String for annotations label. */ ingo@2706: public static final String I18N_ANNOTATIONS_LABEL = ingo@2706: "chart.flow_velocity.annotations.label"; ingo@2706: ingo@2706: /** ingo@2706: * Key to look up internationalized String for LongitudinalSection diagrams ingo@2706: * titles. ingo@2706: */ ingo@2706: public static final String I18N_CHART_TITLE = ingo@2706: "chart.flow_velocity.section.title"; ingo@2706: ingo@2706: /** ingo@2706: * Key to look up internationalized String for LongitudinalSection diagrams ingo@2706: * subtitles. ingo@2706: */ ingo@2706: public static final String I18N_CHART_SUBTITLE = ingo@2706: "chart.flow_velocity.section.subtitle"; ingo@2706: ingo@2706: /** ingo@2706: * Key to look up internationalized String for LongitudinalSection diagrams ingo@2706: * short subtitles. ingo@2706: */ ingo@2706: public static final String I18N_CHART_SHORT_SUBTITLE = ingo@2706: "chart.flow_velocity.section.shortsubtitle"; ingo@2706: ingo@2706: public static final String I18N_XAXIS_LABEL = ingo@2706: "chart.flow_velocity.section.xaxis.label"; ingo@2706: ingo@2706: public static final String I18N_YAXIS_LABEL = ingo@2706: "chart.flow_velocity.section.yaxis.label"; ingo@2706: ingo@2706: public static final String I18N_2YAXIS_LABEL = ingo@2706: "chart.flow_velocity.section.yaxis.second.label"; ingo@2706: felix@4468: public static final String I18N_3YAXIS_LABEL = felix@4468: "chart.flow_velocity.section.yaxis.third.label"; rrenkert@5549: public static final String I18N_4YAXIS_LABEL = "chart.bedquality.yaxis.label.diameter"; felix@4468: ingo@2706: public static final String I18N_CHART_TITLE_DEFAULT = "Geschwindigkeit- und Schubspannung"; ingo@2706: public static final String I18N_XAXIS_LABEL_DEFAULT = "km"; ingo@2706: public static final String I18N_YAXIS_LABEL_DEFAULT = "Geschwindigkeit v [m/s]"; ingo@2706: public static final String I18N_2YAXIS_LABEL_DEFAULT = "Schubspannung Tau [N]"; felix@4468: public static final String I18N_3YAXIS_LABEL_DEFAULT = "Q [m³/s]"; rrenkert@5549: public static final String I18N_4YAXIS_LABEL_DEFAULT = "Durchmesser [mm]"; ingo@2706: ingo@2706: @Override ingo@2706: protected YAxisWalker getYAxisWalker() { ingo@2706: return new YAxisWalker() { ingo@2706: @Override ingo@2706: public int length() { ingo@2706: return YAXIS.values().length; ingo@2706: } ingo@2706: ingo@2706: @Override ingo@2706: public String getId(int idx) { ingo@2706: YAXIS[] yaxes = YAXIS.values(); ingo@2706: return yaxes[idx].toString(); ingo@2706: } ingo@2706: }; ingo@2706: } ingo@2706: ingo@2706: ingo@2706: /** ingo@2706: * Returns the default title for this chart. ingo@2706: * ingo@2706: * @return the default title for this chart. ingo@2706: */ ingo@2706: @Override ingo@2706: public String getDefaultChartTitle() { ingo@2706: Object[] args = new Object[] { ingo@2706: getRiverName() ingo@2706: }; ingo@2706: ingo@2706: return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT, args); ingo@2706: } ingo@2706: ingo@2706: ingo@2706: /** ingo@2706: * Get internationalized label for the x axis. ingo@2706: */ ingo@2706: @Override ingo@2706: protected String getDefaultXAxisLabel() { ingo@2706: FLYSArtifact flys = (FLYSArtifact) master; ingo@2706: ingo@2706: return msg( ingo@2706: I18N_XAXIS_LABEL, ingo@2706: I18N_XAXIS_LABEL_DEFAULT, ingo@2706: new Object[] { FLYSUtils.getRiver(flys).getName() }); ingo@2706: } ingo@2706: ingo@2706: ingo@2706: @Override ingo@2706: protected String getDefaultYAxisLabel(int index) { ingo@2706: String label = "default"; ingo@2706: ingo@2706: if (index == YAXIS.V.idx) { ingo@2706: label = getVAxisLabel(); ingo@2706: } ingo@2706: else if (index == YAXIS.T.idx) { ingo@2706: label = getTAxisLabel(); ingo@2706: } felix@4468: else if (index == YAXIS.Q.idx) { felix@4468: label = getQAxisLabel(); felix@4468: } rrenkert@5549: else if (index == YAXIS.D.idx) { rrenkert@5549: label = getDAxisLabel(); rrenkert@5549: } ingo@2706: ingo@2706: return label; ingo@2706: } ingo@2706: ingo@2706: ingo@2706: /** ingo@2706: * Get internationalized label for the y axis. ingo@2706: */ ingo@2706: protected String getVAxisLabel() { ingo@2706: return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); ingo@2706: } ingo@2706: ingo@2706: ingo@2706: /** ingo@2706: * Get internationalized label for the y axis. ingo@2706: */ felix@4468: protected String getQAxisLabel() { felix@4468: return msg(I18N_3YAXIS_LABEL, I18N_3YAXIS_LABEL_DEFAULT); felix@4468: } felix@4468: felix@4468: /** felix@4468: * Get internationalized label for the y axis. felix@4468: */ ingo@2706: protected String getTAxisLabel() { ingo@2706: return msg(I18N_2YAXIS_LABEL, I18N_2YAXIS_LABEL_DEFAULT); ingo@2706: } ingo@2706: rrenkert@5549: /** rrenkert@5549: * Get internationalized label for the y axis. rrenkert@5549: */ rrenkert@5549: protected String getDAxisLabel() { rrenkert@5549: return msg(I18N_4YAXIS_LABEL, I18N_4YAXIS_LABEL_DEFAULT); rrenkert@5549: } ingo@2706: ingo@2706: /** ingo@2706: * Produce output. felix@3270: * @param artifactAndFacet current facet. ingo@2706: * @param attr theme for facet felix@3270: * @param visible Whether this facets data is actually visible or not. ingo@2706: */ ingo@2706: public void doOut( ingo@2706: ArtifactAndFacet artifactAndFacet, ingo@2706: Document attr, ingo@2706: boolean visible ingo@2706: ) { ingo@2706: String name = artifactAndFacet.getFacetName(); ingo@2706: ingo@2706: logger.debug("FlowVelocityGenerator.doOut: " + name); ingo@2706: ingo@2706: if (name == null) { ingo@2706: logger.error("No facet name for doOut(). No output generated!"); ingo@2706: return; ingo@2706: } ingo@2706: ingo@2706: Facet facet = artifactAndFacet.getFacet(); ingo@2706: ingo@2706: if (facet == null) { ingo@2706: return; ingo@2706: } ingo@2706: rrenkert@4626: if (getXBounds(0) != null && getDomainAxisRange() != null) { rrenkert@4626: logger.debug(Arrays.toString(getDomainAxisRangeFromRequest())); rrenkert@4626: Bounds bounds = rrenkert@4626: calculateZoom(getXBounds(0), getDomainAxisRange()); rrenkert@4626: context.putContextValue("startkm", bounds.getLower()); rrenkert@4626: context.putContextValue("endkm", bounds.getUpper()); rrenkert@4626: } rrenkert@4626: else if (getXBounds(0) != null && getDomainAxisRange() == null) { rrenkert@4626: context.putContextValue("startkm", getXBounds(0).getLower()); rrenkert@4626: context.putContextValue("endkm", getXBounds(0).getUpper()); rrenkert@4626: } rrenkert@4626: else if (getXBounds(0) == null && getDomainAxisRange() == null) { rrenkert@4626: FLYSArtifact artifact = (FLYSArtifact)artifactAndFacet.getArtifact(); felix@4826: FlowVelocityAccess access = new FlowVelocityAccess(artifact, context); rrenkert@4626: context.putContextValue("startkm", access.getLowerKM()); rrenkert@4626: context.putContextValue("endkm", access.getUpperKM()); rrenkert@4626: } rrenkert@4626: else if (getXBounds(0) == null && getDomainAxisRange() != null){ rrenkert@4626: FLYSArtifact artifact = (FLYSArtifact)artifactAndFacet.getArtifact(); felix@4826: FlowVelocityAccess access = new FlowVelocityAccess(artifact, context); rrenkert@4626: Bounds b = new DoubleBounds(access.getLowerKM(), access.getUpperKM()); rrenkert@4626: Bounds bounds = rrenkert@4626: calculateZoom(b, getDomainAxisRange()); rrenkert@4626: context.putContextValue("startkm", bounds.getLower()); rrenkert@4626: context.putContextValue("endkm", bounds.getUpper()); rrenkert@4626: } ingo@2706: if (name.equals(FLOW_VELOCITY_MAINCHANNEL)) { ingo@2706: doMainChannelOut( ingo@2706: (FlowVelocityData) artifactAndFacet.getData(context), ingo@2706: artifactAndFacet, ingo@2706: attr, ingo@2706: visible); ingo@2706: } ingo@2706: else if (name.equals(FLOW_VELOCITY_TOTALCHANNEL)) { ingo@2706: doTotalChannelOut( ingo@2706: (FlowVelocityData) artifactAndFacet.getData(context), ingo@2706: artifactAndFacet, ingo@2706: attr, ingo@2706: visible); ingo@2706: } rrenkert@4669: else if (name.equals(FLOW_VELOCITY_MAINCHANNEL_FILTERED)) { rrenkert@4669: doMainChannelOut( rrenkert@4669: (FlowVelocityData) artifactAndFacet.getData(context), rrenkert@4669: artifactAndFacet, rrenkert@4669: attr, rrenkert@4669: visible); rrenkert@4669: } rrenkert@4669: else if (name.equals(FLOW_VELOCITY_TOTALCHANNEL_FILTERED)) { rrenkert@4669: doTotalChannelOut( rrenkert@4669: (FlowVelocityData) artifactAndFacet.getData(context), rrenkert@4669: artifactAndFacet, rrenkert@4669: attr, rrenkert@4669: visible); rrenkert@4669: } felix@4468: else if (name.equals(FLOW_VELOCITY_DISCHARGE)) { felix@4468: doQOut( felix@4468: (FlowVelocityData) artifactAndFacet.getData(context), felix@4468: artifactAndFacet, felix@4468: attr, felix@4468: visible); felix@4468: } ingo@2706: else if (name.equals(FLOW_VELOCITY_TAU)) { ingo@2706: doTauOut( ingo@2706: (FlowVelocityData) artifactAndFacet.getData(context), ingo@2706: artifactAndFacet, ingo@2706: attr, ingo@2706: visible); ingo@2706: } rrenkert@4669: else if (name.equals(FLOW_VELOCITY_TAU_FILTERED)) { rrenkert@4669: doTauOut( rrenkert@4669: (FlowVelocityData) artifactAndFacet.getData(context), rrenkert@4669: artifactAndFacet, rrenkert@4669: attr, rrenkert@4669: visible); rrenkert@4669: } rrenkert@4669: ingo@2706: else if (name.equals(FLOW_VELOCITY_ANNOTATION)) { ingo@2706: doAnnotations( ingo@2706: (FLYSAnnotation) artifactAndFacet.getData(context), ingo@2706: artifactAndFacet, ingo@2706: attr, ingo@2706: visible); ingo@2706: } ingo@2706: else if (FacetTypes.IS.AREA(name)) { ingo@2706: doArea( ingo@2706: artifactAndFacet.getData(context), ingo@2706: artifactAndFacet, ingo@2706: attr, ingo@2706: visible); ingo@2706: } ingo@2706: else if (FacetTypes.IS.MANUALPOINTS(name)) { ingo@2706: doPoints( ingo@2706: artifactAndFacet.getData(context), ingo@2706: artifactAndFacet, ingo@2706: attr, ingo@2706: visible, ingo@2706: YAXIS.V.idx); ingo@2706: } felix@4395: else if (name.equals(LONGITUDINAL_ANNOTATION)) { felix@4395: doAnnotations( felix@4395: (FLYSAnnotation) artifactAndFacet.getData(context), felix@4395: artifactAndFacet, felix@4395: attr, felix@4395: visible); felix@4395: } felix@4458: else if (name.equals(FLOW_VELOCITY_MEASUREMENT)) { felix@4458: doVPointOut( felix@4458: artifactAndFacet.getData(context), felix@4458: artifactAndFacet, felix@4458: attr, felix@4458: visible); felix@4458: } rrenkert@5549: else if (name.equals(BED_QUALITY_BED_DIAMETER_SUBLAYER)) { rrenkert@5549: doBedQualitySubLayerOut( rrenkert@5549: (BedDiameterResult)artifactAndFacet.getData(context), rrenkert@5549: artifactAndFacet, rrenkert@5549: attr, rrenkert@5549: visible); rrenkert@5549: } rrenkert@5549: else if (name.equals(BED_QUALITY_BED_DIAMETER_TOPLAYER)) { rrenkert@5549: doBedQualityTopLayerOut( rrenkert@5549: (BedDiameterResult)artifactAndFacet.getData(context), rrenkert@5549: artifactAndFacet, rrenkert@5549: attr, rrenkert@5549: visible); rrenkert@5549: } rrenkert@5549: else if (name.equals(BED_QUALITY_BEDLOAD_DIAMETER)) { rrenkert@5549: doBedQualityLoadDiameter( rrenkert@5549: (BedloadDiameterResult)artifactAndFacet.getData(context), rrenkert@5549: artifactAndFacet, rrenkert@5549: attr, rrenkert@5549: visible); rrenkert@5549: } ingo@2706: else { ingo@2706: logger.warn("Unknown facet name: " + name); ingo@2706: return; ingo@2706: } ingo@2706: } ingo@2706: ingo@2706: rrenkert@5549: private void doBedQualityLoadDiameter( rrenkert@5549: BedloadDiameterResult data, rrenkert@5549: ArtifactAndFacet aandf, rrenkert@5549: Document attr, rrenkert@5549: boolean visible) { rrenkert@5549: XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), attr); rrenkert@5549: StyledSeriesBuilder.addPoints(series, data.getDiameterData(), true); rrenkert@5549: rrenkert@5549: addAxisSeries(series, YAXIS.D.idx, visible); rrenkert@5549: } rrenkert@5549: rrenkert@5549: rrenkert@5549: private void doBedQualityTopLayerOut( rrenkert@5549: BedDiameterResult data, rrenkert@5549: ArtifactAndFacet aandf, rrenkert@5549: Document attr, rrenkert@5549: boolean visible) { rrenkert@5549: XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), attr); rrenkert@5549: StyledSeriesBuilder.addPoints(series, data.getDiameterSubData(), true); rrenkert@5549: addAxisSeries(series, YAXIS.D.idx, visible); rrenkert@5549: } rrenkert@5549: rrenkert@5549: rrenkert@5549: private void doBedQualitySubLayerOut( rrenkert@5549: BedDiameterResult data, rrenkert@5549: ArtifactAndFacet aandf, rrenkert@5549: Document attr, rrenkert@5549: boolean visible rrenkert@5549: ) { rrenkert@5549: logger.debug("Do beddiametersubout"); rrenkert@5549: XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), attr); rrenkert@5549: StyledSeriesBuilder.addPoints(series, data.getDiameterSubData(), true); rrenkert@5549: addAxisSeries(series, YAXIS.D.idx, visible); rrenkert@5549: } rrenkert@5549: rrenkert@5549: ingo@2706: /** ingo@2706: * Process the output for W facets in a longitudinal section curve. ingo@2706: * ingo@2706: * @param data A FlowVelocityData object felix@3270: * @param aandf The facet. This facet does NOT support any data objects. Use ingo@2706: * FLYSArtifact.getNativeFacet() instead to retrieve a Facet which supports ingo@2706: * data. ingo@2706: * @param theme The theme that contains styling information. ingo@2706: * @param visible The visibility of the curve. ingo@2706: */ ingo@2706: protected void doMainChannelOut( ingo@2706: FlowVelocityData data, ingo@2706: ArtifactAndFacet aandf, ingo@2706: Document theme, ingo@2706: boolean visible ingo@2706: ) { ingo@2706: logger.debug("FlowVelocityGenerator.doMainChannelOut"); ingo@2706: ingo@2706: XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); ingo@2706: ingo@2706: StyledSeriesBuilder.addPoints(series, data.getMainChannelPoints(), true); ingo@2706: ingo@2706: addAxisSeries(series, YAXIS.V.idx, visible); ingo@2706: } ingo@2706: felix@4464: felix@4464: /** Handle VWQKms. */ felix@4458: protected void doVPointOut ( felix@4458: Object data, felix@4458: ArtifactAndFacet aandf, felix@4458: Document theme, felix@4458: boolean visible felix@4458: ) { felix@4458: logger.debug("FlowVelocityGenerator.doVPointOut"); felix@4458: felix@4458: XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); felix@4458: felix@4464: FlowVelocityMeasurementValue.FastFlowVelocityMeasurementValue felix@4464: value = (FlowVelocityMeasurementValue.FastFlowVelocityMeasurementValue) felix@4464: data; felix@4464: felix@4464: StyledSeriesBuilder.addPoints(series, new double[][] {{value.getStation()},{value.getV()}}, true); felix@4458: felix@4458: addAxisSeries(series, YAXIS.V.idx, visible); felix@4458: } felix@4458: ingo@2706: ingo@2706: /** ingo@2706: * Add items to dataseries which describes the differences. ingo@2706: */ ingo@2706: protected void doTotalChannelOut( ingo@2706: FlowVelocityData data, ingo@2706: ArtifactAndFacet aandf, ingo@2706: Document theme, ingo@2706: boolean visible ingo@2706: ) { ingo@2706: logger.debug("FlowVelocityGenerator.doTotalChannelOut"); ingo@2706: ingo@2706: if (data == null) { ingo@2706: logger.warn("No data to add to FlowVelocity chart."); ingo@2706: return; ingo@2706: } ingo@2706: ingo@2706: XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); ingo@2706: ingo@2706: StyledSeriesBuilder.addPoints(series, data.getTotalChannelPoints(), true); ingo@2706: ingo@2706: addAxisSeries(series, YAXIS.V.idx, visible); ingo@2706: } ingo@2706: ingo@2706: ingo@2706: ingo@2706: /** ingo@2706: * @param data A FlowVelocityData object felix@3270: * @param aandf The facet. This facet does NOT support any data objects. Use ingo@2706: * FLYSArtifact.getNativeFacet() instead to retrieve a Facet which supports ingo@2706: * data. ingo@2706: * @param theme The theme that contains styling information. ingo@2706: * @param visible The visibility of the curve. ingo@2706: */ felix@4468: protected void doQOut( felix@4468: FlowVelocityData data, felix@4468: ArtifactAndFacet aandf, felix@4468: Document theme, felix@4468: boolean visible felix@4468: ) { felix@4468: logger.debug("FlowVelocityGenerator.doTauOut"); felix@4468: felix@4468: XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); felix@4468: felix@4468: StyledSeriesBuilder.addPoints(series, data.getQPoints(), true); felix@4468: felix@4468: addAxisSeries(series, YAXIS.Q.idx, visible); felix@4468: } felix@4468: felix@4468: /** felix@4468: * @param data A FlowVelocityData object felix@4468: * @param aandf The facet. This facet does NOT support any data objects. Use felix@4468: * FLYSArtifact.getNativeFacet() instead to retrieve a Facet which supports felix@4468: * data. felix@4468: * @param theme The theme that contains styling information. felix@4468: * @param visible The visibility of the curve. felix@4468: */ ingo@2706: protected void doTauOut( ingo@2706: FlowVelocityData data, ingo@2706: ArtifactAndFacet aandf, ingo@2706: Document theme, ingo@2706: boolean visible ingo@2706: ) { ingo@2706: logger.debug("FlowVelocityGenerator.doTauOut"); ingo@2706: ingo@2706: XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); ingo@2706: ingo@2706: StyledSeriesBuilder.addPoints(series, data.getTauPoints(), true); ingo@2706: ingo@2706: addAxisSeries(series, YAXIS.T.idx, visible); ingo@2706: } ingo@2706: ingo@2706: ingo@2706: /** Look up the axis identifier for a given facet type. */ ingo@2706: public int axisIdxForFacet(String facetName) { ingo@2706: if (FacetTypes.IS.V(facetName)) { ingo@2706: return YAXIS.V.idx; ingo@2706: } ingo@2706: else if (FacetTypes.IS.T(facetName)) { ingo@2706: return YAXIS.T.idx; ingo@2706: } ingo@2706: else { ingo@2706: logger.warn("Could not find axis for facet " + facetName); ingo@2706: return YAXIS.V.idx; ingo@2706: } ingo@2706: } ingo@2706: ingo@2706: ingo@2706: /** ingo@2706: * Do Area out. ingo@2706: * @param theme styling information. ingo@2706: * @param visible whether or not visible. ingo@2706: */ ingo@2706: protected void doArea( ingo@2706: Object o, ingo@2706: ArtifactAndFacet aandf, ingo@2706: Document theme, ingo@2706: boolean visible ingo@2706: ) { ingo@2706: logger.debug("FlowVelocityGenerator.doArea"); ingo@2706: logger.warn("TODO: Implement FlowVelocityGenerator.doArea"); ingo@2706: } ingo@2706: } ingo@2706: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :