All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.h2gis.functions.spatial.create.GridRowSet Maven / Gradle / Ivy

There is a newer version: 1.3.2
Show newest version
/**
 * H2GIS is a library that brings spatial support to the H2 Database Engine
 * . H2GIS is developed by CNRS
 * .
 *
 * This code is part of the H2GIS project. H2GIS is free software; 
 * you can redistribute it and/or modify it under the terms of the GNU
 * Lesser General Public License as published by the Free Software Foundation;
 * version 3.0 of the License.
 *
 * H2GIS is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 * for more details .
 *
 *
 * For more information, please consult: 
 * or contact directly: info_at_h2gis.org
 */

package org.h2gis.functions.spatial.create;

import com.vividsolutions.jts.geom.*;
import org.h2.tools.SimpleResultSet;
import org.h2.tools.SimpleRowSource;
import org.h2gis.utilities.JDBCUtilities;
import org.h2gis.utilities.SFSUtilities;
import org.h2gis.utilities.TableLocation;

import java.sql.*;
import java.util.List;

/**
 * GridRowSet is used to populate a result set with all grid cells. A cell could
 * be represented as a polygon or its center point.
 *
 * @author Erwan Bocher
 */
public class GridRowSet implements SimpleRowSource {

    private static final GeometryFactory GF = new GeometryFactory();
    private static int cellI = 0;
    private static int cellJ = 0;
    private int maxI, maxJ;
    private double deltaX, deltaY;
    private double minX, minY;
    private int id = 0;
    private final Connection connection;
    private boolean firstRow = true;
    private Envelope envelope;
    private boolean isTable;
    private String tableName;
    private boolean isCenterCell = false;

    /**
     * The grid will be computed according a table stored in the database
     *
     * @param connection
     * @param deltaX
     * @param deltaY
     * @param tableName
     */
    public GridRowSet(Connection connection, double deltaX, double deltaY, String tableName) {
        this.connection = connection;
        this.deltaX = deltaX;
        this.deltaY = deltaY;
        this.tableName = tableName;
        this.isTable = true;
    }

    /**
     * The grid will be computed according an envelope
     *
     * @param connection
     * @param deltaX
     * @param deltaY
     * @param envelope
     */
    public GridRowSet(Connection connection, double deltaX, double deltaY, Envelope envelope) {
        this.connection = connection;
        this.deltaX = deltaX;
        this.deltaY = deltaY;
        this.envelope = envelope;
        this.isTable = false;
    }

    @Override
    public Object[] readRow() throws SQLException {
        if (firstRow) {
            reset();
        }
        if (cellI == maxI) {
            cellJ++;
            cellI = 0;
        }
        if (cellJ >= maxJ) {
            cellJ = 0;
            return null;
        }
        if (isCenterCell) {
            return new Object[]{getCellPoint(), id++, cellI, cellJ + 1};
        }
        return new Object[]{getCellPolygon(), id++, cellI, cellJ + 1};
    }

    @Override
    public void close() {
    }

    @Override
    public void reset() throws SQLException {
        cellI = 0;
        cellJ = 0;
        firstRow = false;
        //We compute the extend according the first input value
        if (isTable) {
            Statement statement = connection.createStatement();
            ResultSet rs = statement.executeQuery("select ST_Extent(" + getFirstGeometryField(tableName, connection) + ")  from " + tableName);
            try {
                rs.next();
                Geometry geomExtend = (Geometry) rs.getObject(1);
                if (geomExtend == null) {
                    throw new SQLException("The envelope cannot be null.");
                } else {
                    envelope = geomExtend.getEnvelopeInternal();
                    initParameters();
                }

            } finally {
                rs.close();
            }
        } else {
            if (envelope == null) {
                throw new SQLException("The input geometry used to compute the grid cannot be null.");
            } else {
                initParameters();
            }
        }
    }

    /**
     * Compute the polygon corresponding to the cell
     *
     * @return Polygon of the cell
     */
    private Polygon getCellPolygon() {
        final Coordinate[] summits = new Coordinate[5];
        double x1 = minX + cellI * deltaX;
        double y1 = minY + cellJ * deltaY;
        double x2 = minX + (cellI + 1) * deltaX;
        double y2 = minY + (cellJ + 1) * deltaY;
        summits[0] = new Coordinate(x1, y1);
        summits[1] = new Coordinate(x2, y1);
        summits[2] = new Coordinate(x2, y2);
        summits[3] = new Coordinate(x1, y2);
        summits[4] = new Coordinate(x1, y1);
        final LinearRing g = GF.createLinearRing(summits);
        final Polygon gg = GF.createPolygon(g, null);
        cellI++;
        return gg;
    }

    /**
     * Compute the point of the cell
     *
     * @return Center point of the cell
     */
    private Point getCellPoint() {
        double x1 = (minX + cellI * deltaX) + (deltaX / 2d);
        double y1 = (minY + cellJ * deltaY) + (deltaY / 2d);
        cellI++;
        return GF.createPoint(new Coordinate(x1, y1));
    }

    /**
     * Return true is cell is represented as point, false as a polygon
     *
     * @return
     */
    public boolean isCenterCell() {
        return isCenterCell;
    }

    /**
     * Set if the cell must be represented as a point or a polygon
     *
     * @param isCenterCell
     */
    public void setCenterCell(boolean isCenterCell) {
        this.isCenterCell = isCenterCell;
    }

    /**
     * Return the first spatial geometry field name
     *
     * @param tableName
     * @param connection
     * @return the name of the first geometry column
     * @throws SQLException
     */
    private static String getFirstGeometryField(String tableName, Connection connection) throws SQLException {
        // Find first geometry column
        List geomFields = SFSUtilities.getGeometryFields(connection, TableLocation.parse(tableName, JDBCUtilities.isH2DataBase(connection.getMetaData())));
        if (!geomFields.isEmpty()) {
            return geomFields.get(0);
        } else {
            throw new SQLException("The table " + tableName + " does not contain a geometry field");
        }
    }

    /**
     * Compute the parameters need to create each cells
     *
     */
    private void initParameters() {
        this.minX = envelope.getMinX();
        this.minY = envelope.getMinY();
        double cellWidth = envelope.getWidth();
        double cellHeight = envelope.getHeight();
        this.maxI = (int) Math.ceil(cellWidth
                / deltaX);
        this.maxJ = (int) Math.ceil(cellHeight
                / deltaY);
    }

    /**
     * Give the regular grid
     *
     * @return ResultSet
     * @throws SQLException
     */
    public ResultSet getResultSet() throws SQLException {
        SimpleResultSet srs = new SimpleResultSet(this);
        srs.addColumn("THE_GEOM", Types.JAVA_OBJECT, "GEOMETRY", 0, 0);
        srs.addColumn("ID", Types.INTEGER, 10, 0);
        srs.addColumn("ID_COL", Types.INTEGER, 10, 0);
        srs.addColumn("ID_ROW", Types.INTEGER, 10, 0);
        return srs;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy