Mercurial > dive4elements > gnv-client
view gnv-artifacts/src/main/java/de/intevation/gnv/math/GridCell.java @ 605:e8ebdbc7f1e3
First step of removing the cache blob. The static part of the describe document will be created by using the input data stored at each state. Some TODOs left (see ChangeLog).
gnv-artifacts/trunk@671 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Ingo Weinzierl <ingo.weinzierl@intevation.de> |
---|---|
date | Tue, 09 Feb 2010 14:27:55 +0000 |
parents | b248531fa20b |
children | c4156275c1e1 |
line wrap: on
line source
package de.intevation.gnv.math; import com.vividsolutions.jts.algorithm.CGAlgorithms; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LinearRing; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jts.index.ItemVisitor; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.apache.log4j.Logger; /** * @author Sascha L. Teichmann (sascha.teichmann@intevation.de) */ public class GridCell implements Serializable { private static Logger log = Logger.getLogger(GridCell.class); public static final class CellFinder implements ItemVisitor { public GridCell found; protected Point point; public CellFinder() { } public void prepare(Coordinate center) { found = null; point = GEOMETRY_FACTORY.createPoint(center); } public void visitItem(Object item) { if (found == null) { GridCell cell = (GridCell)item; if (cell.contains(point)) { found = cell; } } } } // class CellFinder public Point2d p1; public Point2d p2; public Point2d p3; public Point2d p4; protected Polygon polygon; public static final GeometryFactory GEOMETRY_FACTORY = new GeometryFactory(); public GridCell() { } public GridCell(Point2d p1, Point2d p2, Point2d p3, Point2d p4) { this.p1 = p1; this.p2 = p2; this.p3 = p3; this.p4 = p4; createPolygon(); } protected void createPolygon() { Coordinate [] coords = new Coordinate [] { p1, p2, p3, p4, p1 }; if (!CGAlgorithms.isCCW(coords)) { for (int i = 0, j = coords.length-1; i < j; ++i, --j) { Coordinate c = coords[i]; coords[i] = coords[j]; coords[j] = c; } } LinearRing shell = GEOMETRY_FACTORY .createLinearRing(coords); if (!shell.isValid()) { log.warn("linear ring is not valid"); } polygon = GEOMETRY_FACTORY.createPolygon(shell, null); } public Envelope getEnvelope() { return polygon.getEnvelopeInternal(); } public boolean contains(Geometry coord) { return polygon.contains(coord); } public static List<GridCell> pointsToGridCells( List<? extends Point2d> points ) { return pointsToGridCells(points, null); } public static List<GridCell> pointsToGridCells( List<? extends Point2d> points, Envelope relevantArea ) { return pointsToGridCells(points, relevantArea, 0); } private static final int NEIGHBORS [][] = { { -1, -1 }, // 0 { -1, 0 }, // 1 { -1, +1 }, // 2 { 0, +1 }, // 3 { +1, +1 }, // 4 { +1, 0 }, // 5 { +1, -1 }, // 6 { 0, -1 } // 7 }; public static int extrapolate( HashMap<Integer, HashMap<Integer, Point2d>> rows, int minI, int maxI, int minJ, int maxJ, int rounds, Envelope relevantArea ) { Point2d [] neighbors = new Point2d[NEIGHBORS.length]; Point2d [] positions = new Point2d[NEIGHBORS.length]; int total = 0; ArrayList<ArrayList<IJKey>> prio = new ArrayList<ArrayList<IJKey>>(NEIGHBORS.length); for (int i = 0; i < NEIGHBORS.length; ++i) { prio.add(new ArrayList<IJKey>()); } while (rounds-- > 0) { for (int i = minI; i <= maxI; ++i) { for (int j = minJ; j <= maxJ; ++j) { Point2d p = get(rows, i, j); if (p != null) { continue; } int count = 0; for (int k = 0; k < neighbors.length; ++k) { neighbors[k] = positions[k] = null; int dij [] = NEIGHBORS[k]; Point2d n1 = get(rows, i+ dij[0], j+ dij[1]); Point2d n2 = get(rows, i+2*dij[0], j+2*dij[1]); if (n1 != null && n2 != null) { ++count; } } if (count > 0) { prio.get(count-1).add(new IJKey(i, j)); } } // for all columns } // for all rows int N = 0; for (int l = NEIGHBORS.length-1; l >= 0; --l) { ArrayList<IJKey> list = prio.get(l); for (IJKey ij: list) { int i = ij.i; int j = ij.j; for (int k = 0; k < neighbors.length; ++k) { neighbors[k] = positions[k] = null; int dij [] = NEIGHBORS[k]; Point2d n1 = get(rows, i+ dij[0], j+ dij[1]); Point2d n2 = get(rows, i+2*dij[0], j+2*dij[1]); if (n1 != null && n2 != null) { neighbors[k] = n1; positions[k] = n1.extrapolate(-1d, n2); } } Point2d avg = Point2d.average(positions); if (avg != null && avg.near(positions) && (relevantArea == null || relevantArea.contains(avg.x, avg.y))) { avg.i = i; avg.j = j; avg.inverseDistanceWeighting(neighbors); put(rows, avg, i, j); } } N += list.size(); list.clear(); } if (N == 0) { break; } total += N; } // for all rounds return total; } public static List<GridCell> pointsToGridCells( List<? extends Point2d> points, Envelope relevantArea, int extrapolationRounds ) { int minI = Integer.MAX_VALUE; int maxI = Integer.MIN_VALUE; int minJ = Integer.MAX_VALUE; int maxJ = Integer.MIN_VALUE; HashMap<Integer, HashMap<Integer, Point2d>> rows = new HashMap<Integer, HashMap<Integer, Point2d>>(); int culled = 0; for (Point2d p: points) { if (relevantArea != null && !relevantArea.contains(p.x, p.y)) { ++culled; continue; } if (p.i < minI) minI = p.i; if (p.i > maxI) maxI = p.i; if (p.j < minJ) minJ = p.j; if (p.j > maxJ) maxJ = p.j; HashMap<Integer, Point2d> row = rows.get(p.i); if (row == null) { rows.put(p.i, row = new HashMap<Integer, Point2d>()); } row.put(p.j, p); } ArrayList<GridCell> cells = new ArrayList<GridCell>(points.size()); int extrapolated = extrapolate( rows, minI, maxI, minJ, maxJ, extrapolationRounds, relevantArea); for (int i = minI + 1; i <= maxI; ++i) { HashMap<Integer, Point2d> row1 = rows.get(i-1); HashMap<Integer, Point2d> row2 = rows.get(i); if (row1 == null || row2 == null) { continue; } for (int j = minJ + 1; j < maxJ; ++j) { Point2d p1 = row1.get(j-1); Point2d p2 = row1.get(j); Point2d p3 = row2.get(j); Point2d p4 = row2.get(j-1); if (p1 != null && p2 != null && p3 != null && p4 != null) { cells.add(new GridCell(p1, p2, p3, p4)); } } } // for all rows if (log.isDebugEnabled()) { log.debug("culled points: " + culled); log.debug("extrapolated points: " + extrapolated); log.debug("min/max i: " + minI + " / " + maxI); log.debug("min/max j: " + minJ + " / " + maxJ); log.debug("cells found: " + cells.size()); } return cells; } private static Point2d get( HashMap<Integer, HashMap<Integer, Point2d>> rows, int i, int j ) { HashMap<Integer, Point2d> row = rows.get(i); return row != null ? row.get(j) : null; } private static void put( HashMap<Integer, HashMap<Integer, Point2d>> rows, Point2d point, int i, int j ) { Integer I = Integer.valueOf(i); HashMap<Integer, Point2d> row = rows.get(I); if (row == null) { rows.put(I, row = new HashMap<Integer, Point2d>()); } row.put(j, point); } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :