changeset 2120:f021080cb409

Use improved caching for cross section lines data. flys-artifacts/trunk@3690 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Mon, 16 Jan 2012 17:38:39 +0000
parents dc28ea60b53d
children 70ef5fdc7414
files flys-artifacts/ChangeLog flys-artifacts/src/main/java/de/intevation/flys/artifacts/ChartArtifact.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/CrossSectionArtifact.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticWKmsArtifact.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/WaterLineArtifact.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CrossSectionWaterLineFacet.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FastCrossSectionLine.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/CrossSectionKMService.java flys-artifacts/src/main/java/de/intevation/flys/exports/CrossSectionGenerator.java
diffstat 10 files changed, 128 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- a/flys-artifacts/ChangeLog	Mon Jan 16 15:51:46 2012 +0000
+++ b/flys-artifacts/ChangeLog	Mon Jan 16 17:38:39 2012 +0000
@@ -1,3 +1,36 @@
+2012-01-16	Sascha L. Teichmann	<sascha.teichmann@intevation.de>
+
+	  Use improved caching for cross section data. 
+	  !!! This commit needs heavy testing !!!
+
+	* src/main/java/de/intevation/flys/artifacts/services/CrossSectionKMService.java:
+	  Refactored to provide the map to determine the nearest cross section line
+	  neighbors for a given km to the public. This is a bit hackish because
+	  it hhould have its own factory which is then used by this service and 
+	  other parts of the code.
+
+	* src/main/java/de/intevation/flys/artifacts/CrossSectionArtifact.java:
+	  searchCrossSectionLine() now returns a FastCrossSectionLine. To find this
+	  line efficiently it uses the map of the CrossSectionKMService which
+	  already provides a nearest neighbor searching mechanism for cross
+	  section lines. The FastCrossSectionLine is fetched with the
+	  FastCrossSectionLineFactory which uses a cache as described in the
+	  previous commit.
+
+	* src/main/java/de/intevation/flys/exports/CrossSectionGenerator.java
+	  src/main/java/de/intevation/flys/artifacts/WaterLineArtifact.java,
+	  src/main/java/de/intevation/flys/artifacts/model/CrossSectionWaterLineFacet.java,
+	  src/main/java/de/intevation/flys/artifacts/StaticWKmsArtifact.java,
+	  src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java: Uses
+	  the FastCrossSectionLine instead of CrossSectionLines now.
+
+	* src/main/java/de/intevation/flys/artifacts/model/FastCrossSectionLine.java:
+	  Added method fetchCrossSectionProfile() to access the point data in
+	  the profile generating compatible way.
+
+	* src/main/java/de/intevation/flys/artifacts/ChartArtifact.java: Removed
+	  superfluous import.
+
 2012-01-16	Sascha L. Teichmann	<sascha.teichmann@intevation.de>
 
 	* doc/conf/cache.xml: Added cache for fast section lines chunks.
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/ChartArtifact.java	Mon Jan 16 15:51:46 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/ChartArtifact.java	Mon Jan 16 17:38:39 2012 +0000
@@ -25,7 +25,6 @@
 import de.intevation.artifactdatabase.state.Output;
 import de.intevation.artifactdatabase.transition.TransitionEngine;
 
-import de.intevation.flys.model.River;
 import de.intevation.flys.utils.FLYSUtils;
 
 import de.intevation.flys.artifacts.states.DefaultState;
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/CrossSectionArtifact.java	Mon Jan 16 15:51:46 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/CrossSectionArtifact.java	Mon Jan 16 17:38:39 2012 +0000
@@ -2,6 +2,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.NavigableMap;
 
 import org.apache.log4j.Logger;
 
@@ -12,6 +13,8 @@
 import de.intevation.artifacts.CallMeta;
 
 import de.intevation.flys.artifacts.model.CrossSectionFacet;
+import de.intevation.flys.artifacts.model.FastCrossSectionLine;
+import de.intevation.flys.artifacts.model.FastCrossSectionLineFactory;
 
 import de.intevation.flys.model.CrossSection;
 import de.intevation.flys.model.CrossSectionLine;
@@ -26,6 +29,8 @@
 
 import de.intevation.flys.utils.FLYSUtils;
 
+import de.intevation.flys.artifacts.services.CrossSectionKMService;
+
 
 /**
  * Artifact describing a cross-section.
@@ -90,10 +95,14 @@
         }
 
         List<Facet> fs = new ArrayList<Facet>();
-        CrossSection cs = CrossSectionFactory.getCrossSection(Integer.valueOf(ids));
-        CrossSectionLine csl = cs.getLines().get(0);
-        // Find min-km of cross sections, than set DATA_KM to min(DATA_KM, minCross).
-        if (csl != null) {
+        CrossSection cs = CrossSectionFactory.getCrossSection(
+            Integer.valueOf(ids));
+
+        List<CrossSectionLine> csls = cs.getLines();
+        if (!csls.isEmpty()) {
+            CrossSectionLine csl = csls.get(0);
+            // Find min-km of cross sections,
+            // then set DATA_KM to min(DATA_KM, minCross).
             double masterKm = Double.valueOf(getDataAsString(DATA_KM));
             if (masterKm < csl.getKm().doubleValue()) {
                 addStringData(DATA_KM, csl.getKm().toString());
@@ -222,7 +231,7 @@
     public double [][] getCrossSectionData() {
         logger.info("getCrossSectionData() for cross_section.km "
             + getDataAsString(DATA_KM));
-        CrossSectionLine line = searchCrossSectionLine();
+        FastCrossSectionLine line = searchCrossSectionLine();
 
         return line != null
                ? line.fetchCrossSectionProfile()
@@ -236,27 +245,35 @@
      *
      * @return CrossSectionLine closest to "cross_section.km".
      */
-    public CrossSectionLine searchCrossSectionLine() {
-        double wishKM = getKm();
+    public FastCrossSectionLine searchCrossSectionLine() {
 
-        CrossSection crossSection = CrossSectionFactory.getCrossSection(getDBID());
-        logger.debug("dbid " + getDBID() + " : " + crossSection);
-        List<CrossSectionLine> crossSectionLines =
-            crossSection.getLines();
-            
-        // Get the cross section closest to requested km.
-        // Naive, linear approach.
-        CrossSectionLine oldLine = crossSectionLines.get(0);
-        double oldDiff = Math.abs(wishKM - oldLine.getKm().doubleValue());
-        for (CrossSectionLine line: crossSectionLines) {
-            double diff = Math.abs(wishKM - line.getKm().doubleValue());
-            if (diff > oldDiff) {
-                break;
-            }
-            oldDiff = diff;
-            oldLine = line;
+        CrossSection crossSection = CrossSectionFactory
+            .getCrossSection(getDBID());
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("dbid " + getDBID() + " : " + crossSection);
         }
-        return oldLine;
+
+        NavigableMap<Double, Integer> kms = CrossSectionKMService
+            .getKms(crossSection.getId());
+
+        Double wishKM = getKm();
+
+        Double floor = kms.floorKey(wishKM);
+        Double ceil  = kms.ceilingKey(wishKM);
+
+        double floorD = floor != null
+            ? Math.abs(floor - wishKM)
+            : Double.MAX_VALUE;
+
+        double ceilD = ceil != null
+            ? Math.abs(ceil - wishKM)
+            : Double.MAX_VALUE;
+
+        double km = floorD < ceilD ? floor : ceil;
+
+        return FastCrossSectionLineFactory
+            .getCrossSectionLine(crossSection, km);
     }
 
 
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticWKmsArtifact.java	Mon Jan 16 15:51:46 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticWKmsArtifact.java	Mon Jan 16 17:38:39 2012 +0000
@@ -30,7 +30,8 @@
 import de.intevation.artifacts.common.utils.XMLUtils;
 
 import de.intevation.flys.geom.Lines;
-import de.intevation.flys.model.CrossSectionLine;
+
+import de.intevation.flys.artifacts.model.FastCrossSectionLine;
 
 /**
  * Artifact to access additional "waterlevel"-type of data, like the height
@@ -256,14 +257,15 @@
      * @return an array holding coordinates of points of surface of water (
      *         in the form {{x1, x2} {y1, y2}} ).
      */
-    public double [][] getWaterLines(int idx, CrossSectionLine csl) {
+    @Override
+    public double [][] getWaterLines(int idx, FastCrossSectionLine csl) {
         logger.debug("getWaterLines(" + idx + ")");
 
-        List<Point2D> points = csl.fetchCrossSectionLinesPoints();
+        List<Point2D> points = csl.getPoints();
 
         WKms wkms = getWKms(0);
 
-        double km = csl.getKm().doubleValue();
+        double km = csl.getKm();
 
         // Find W at km.
         double wAtKm = getWAtKm(wkms, km);
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java	Mon Jan 16 15:51:46 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java	Mon Jan 16 17:38:39 2012 +0000
@@ -36,6 +36,7 @@
 import de.intevation.flys.artifacts.model.WQKms;
 import de.intevation.flys.artifacts.model.WstValueTable;
 import de.intevation.flys.artifacts.model.WstValueTableFactory;
+import de.intevation.flys.artifacts.model.FastCrossSectionLine;
 
 import de.intevation.flys.artifacts.states.DefaultState;
 import de.intevation.flys.artifacts.states.LocationDistanceSelect;
@@ -44,7 +45,6 @@
 
 import de.intevation.flys.model.Gauge;
 import de.intevation.flys.model.River;
-import de.intevation.flys.model.CrossSectionLine;
 
 import de.intevation.flys.utils.DoubleUtil;
 import de.intevation.flys.utils.FLYSUtils;
@@ -660,10 +660,10 @@
      * @return an array holding coordinates of points of surface of water (
      *         in the form {{x1, x2} {y1, y2}} ).
      */
-    public double [][] getWaterLines(int idx, CrossSectionLine csl) {
+    public double [][] getWaterLines(int idx, FastCrossSectionLine csl) {
         logger.debug("getWaterLines(" + idx + ")");
 
-        List<Point2D> points = csl.fetchCrossSectionLinesPoints();
+        List<Point2D> points = csl.getPoints();
 
         // Need W at km
         WQKms [] wqkms = (WQKms[]) getWaterlevelData().getData();
@@ -681,7 +681,7 @@
         WQKms triple = wqkms[idx];
 
         // Find index of km.
-        double wishKM = csl.getKm().doubleValue();
+        double wishKM = csl.getKm();
         int old_idx = 0;
 
         if (triple.size() == 0) {
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WaterLineArtifact.java	Mon Jan 16 15:51:46 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WaterLineArtifact.java	Mon Jan 16 17:38:39 2012 +0000
@@ -1,13 +1,14 @@
 package de.intevation.flys.artifacts;
 
-import de.intevation.flys.model.CrossSectionLine;
+
+import de.intevation.flys.artifacts.model.FastCrossSectionLine;
 /**
- * Interfacet, Artifact can create WaterLines (Water against Cross-Profile).
+ * Interface, Artifact can create WaterLines (Water against Cross-Profile).
  */
 public interface WaterLineArtifact {
 
     /** Get points that define a line of a (water)facet against a cross-
      * section. */
-    public double [][] getWaterLines(int facetIdx, CrossSectionLine csl);
+    public double [][] getWaterLines(int facetIdx, FastCrossSectionLine csl);
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CrossSectionWaterLineFacet.java	Mon Jan 16 15:51:46 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CrossSectionWaterLineFacet.java	Mon Jan 16 17:38:39 2012 +0000
@@ -4,8 +4,6 @@
 
 import java.util.List;
 
-import de.intevation.flys.model.CrossSectionLine;
-
 import de.intevation.artifacts.Artifact;
 import de.intevation.artifacts.CallContext;
 
@@ -14,6 +12,7 @@
 
 import de.intevation.flys.artifacts.WaterLineArtifact;
 
+import de.intevation.flys.artifacts.model.FastCrossSectionLine;
 
 /**
  * Facet for Waterlines in Cross Sections.
@@ -49,7 +48,7 @@
 
         WaterLineArtifact winfo = (WaterLineArtifact)artifact;
 
-        return winfo.getWaterLines(this.getIndex(), (CrossSectionLine) crossSection);
+        return winfo.getWaterLines(this.getIndex(), (FastCrossSectionLine) crossSection);
     }
 
 
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FastCrossSectionLine.java	Mon Jan 16 15:51:46 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FastCrossSectionLine.java	Mon Jan 16 17:38:39 2012 +0000
@@ -59,5 +59,9 @@
     public void setPoints(List<Point2D> points) {
         this.points = points;
     }
+
+    public double [][] fetchCrossSectionProfile() {
+        return CrossSectionLine.fetchCrossSectionProfile(points);
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/CrossSectionKMService.java	Mon Jan 16 15:51:46 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/CrossSectionKMService.java	Mon Jan 16 17:38:39 2012 +0000
@@ -76,8 +76,6 @@
         NodeList crossSectionNodes =
             data.getElementsByTagName("art:cross-section");
 
-        Cache cache = CacheFactory.getCache(CACHE_NAME);
-
         Document document = XMLUtils.newDocument();
 
         Element all = document.createElement("cross-sections");
@@ -111,25 +109,7 @@
                 continue;
             }
 
-            NavigableMap<Double, Integer> map;
-
-            if (cache == null) {
-                map = getUncached(crossSectionId);
-            }
-            else {
-                net.sf.ehcache.Element element = cache.get(crossSectionId);
-                if (element == null) {
-                    map = getUncached(crossSectionId);
-                    if (map != null) {
-                        element = new net.sf.ehcache.Element(
-                            crossSectionId, map);
-                        cache.put(element);
-                    }
-                }
-                else {
-                    map = (NavigableMap<Double, Integer>)element.getValue();
-                }
-            }
+            NavigableMap<Double, Integer> map = getKms(crossSectionId);
 
             if (map == null) {
                 logger.debug("cannot find cross section " + crossSectionId);
@@ -159,6 +139,32 @@
         return document;
     }
 
+    public static NavigableMap<Double, Integer> getKms(int crossSectionId) {
+
+        Cache cache = CacheFactory.getCache(CACHE_NAME);
+
+        if (cache == null) {
+            return getUncached(crossSectionId);
+        }
+
+        NavigableMap<Double, Integer> map;
+
+        net.sf.ehcache.Element element = cache.get(crossSectionId);
+        if (element == null) {
+            map = getUncached(crossSectionId);
+            if (map != null) {
+                element = new net.sf.ehcache.Element(
+                    crossSectionId, map);
+                cache.put(element);
+            }
+        }
+        else {
+            map = (NavigableMap<Double, Integer>)element.getValue();
+        }
+
+        return map;
+    }
+
 
     /**
      * @param km  the kilometer from which to start searching for other
@@ -173,9 +179,10 @@
         Deque<Map.Entry<Double, Integer>> result =
             new ArrayDeque<Map.Entry<Double, Integer>>(2*N);
 
-        if(map.get(km) != null) {
-            result.add(new AbstractMap.SimpleEntry<Double, Integer>(km,map.get(km)));
+        Integer v = map.get(km);
 
+        if (v != null) {
+            result.add(new AbstractMap.SimpleEntry<Double, Integer>(km, v));
         }
 
         int i = 0;
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/CrossSectionGenerator.java	Mon Jan 16 15:51:46 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/CrossSectionGenerator.java	Mon Jan 16 17:38:39 2012 +0000
@@ -14,12 +14,12 @@
 
 import de.intevation.artifactdatabase.state.ArtifactAndFacet;
 
-import de.intevation.flys.model.CrossSectionLine;
-
 import de.intevation.flys.artifacts.model.FacetTypes;
 import de.intevation.flys.artifacts.model.CrossSectionFacet;
 import de.intevation.flys.jfree.StyledXYSeries;
 
+import de.intevation.flys.artifacts.model.FastCrossSectionLine;
+
 /**
  * An OutGenerator that generates cross section graphs.
  */
@@ -96,10 +96,10 @@
             context.getDataProvider(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA);
         double km = 0d;
         if (providers.size() > 0) {
-            CrossSectionLine csl = (CrossSectionLine) providers.get(0).
+            FastCrossSectionLine csl = (FastCrossSectionLine) providers.get(0).
                 provideData(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA,
                     null, context);
-            km = csl.getKm().doubleValue();
+            km = csl.getKm();
         }
 
         Object[] args = new Object[] {

http://dive4elements.wald.intevation.org