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

io.jeo.ogr.OGRDataset Maven / Gradle / Ivy

The newest version!
/* Copyright 2014 The jeo project. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.jeo.ogr;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Map;

import io.jeo.geom.Bounds;
import io.jeo.vector.FeatureAppendCursor;
import io.jeo.vector.FeatureCursor;
import io.jeo.vector.FeatureWriteCursor;
import org.gdal.ogr.DataSource;
import org.gdal.ogr.FeatureDefn;
import org.gdal.ogr.FieldDefn;
import org.gdal.ogr.Layer;
import org.gdal.osr.SpatialReference;
import io.jeo.data.Driver;
import io.jeo.data.FileData;
import io.jeo.vector.VectorQuery;
import io.jeo.vector.VectorQueryPlan;
import io.jeo.vector.VectorDataset;
import io.jeo.vector.Schema;
import io.jeo.vector.SchemaBuilder;
import io.jeo.proj.Proj;
import io.jeo.util.Key;
import io.jeo.util.Pair;
import org.osgeo.proj4j.CoordinateReferenceSystem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryCollection;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;

import static org.gdal.ogr.ogrConstants.*;

public class OGRDataset implements VectorDataset, FileData {

    public static final Logger LOG = LoggerFactory.getLogger(OGR.class);

    String name;
    OGRWorkspace workspace;

    public OGRDataset(String name, OGRWorkspace workspace) {
        this.name = name;
        this.workspace = workspace;
    }

    @Override
    public File file() {
        return workspace.file();
    }

    @Override
    public Driver driver() {
        return workspace.driver();
    }

    @Override
    public Map, Object> driverOptions() {
        return workspace.driverOptions();
    }

    @Override
    public String name() {
        return name;
    }

    @Override
    public Schema schema() throws IOException {
        Pair data = open();
        try {
            return toSchema(data.first);
            
        }
        finally {
            close(data);
        }
    }

    Schema toSchema(Layer l) {

        FeatureDefn defn = l.GetLayerDefn();

        SchemaBuilder sb = Schema.build(defn.GetName());

        Class geotype = toGeometryType(defn);
        if (geotype != null) {
            CoordinateReferenceSystem crs = toCRS(l);
            sb.field("geometry", geotype, crs);
        }

        for (int i = 0; i < defn.GetFieldCount(); i++) {
            FieldDefn fd = defn.GetFieldDefn(i);
            sb.field(fd.GetName(), toType(fd));
        }

        return sb.schema();
    }

    CoordinateReferenceSystem toCRS(Layer l) {
        SpatialReference sref = l.GetSpatialRef();
        if (sref != null) {
            return Proj.crs(sref.ExportToProj4());
        }
        return null;
    }

    Class toGeometryType(FeatureDefn defn) {
        int g = defn.GetGeomType();

        if (g == wkbNone) {
            return null;
        }
        if (g == wkbPoint || g == wkbPoint25D) {
            return Point.class;
        } 
        if (g == wkbLinearRing) {
            return LinearRing.class;
        } 
        if (g == wkbLineString || g == wkbLineString25D
            || g == wkbMultiLineString || g == wkbMultiLineString25D) {
            return MultiLineString.class;
        } 
        if (g == wkbPolygon || g == wkbPolygon25D
                || g == wkbMultiPolygon || g == wkbMultiPolygon25D) {
            return MultiPolygon.class;
        } 
        if (g == wkbGeometryCollection || g == wkbGeometryCollection25D) {
            return GeometryCollection.class;
        }
        if (g == wkbUnknown) {
            return Geometry.class;
        }

        LOG.debug("unknown ogr geometry type: " + g);
        return null;
    }

    Class toType(FieldDefn defn) {
        int type = defn.GetFieldType();
        int width = defn.GetWidth();

        if (type == OFTInteger) {
            if (width <= 3) {
                return Byte.class;
            } else if (width <= 5) {
                return Short.class;
            } else if (width <= 9) {
                return Integer.class;
            } else if (width <= 19) {
                return Long.class;
            } else {
                return BigDecimal.class;
            }
        }
        
        if (type == OFTIntegerList) {
            return int[].class;
        }

        if (type == OFTReal) {
            if (width <= 12) {
                return Float.class;
            } else if (width <= 22) {
                return Double.class;
            } else {
                return BigDecimal.class;
            }
        }

        if (type == OFTRealList) {
            return double[].class;
        }

        if (type == OFTBinary) {
            return byte[].class;
        }

        if (type == OFTDate) {
            return java.sql.Date.class;
        } 

        if (type == OFTTime) {
            return java.sql.Time.class;
        }

        if (type == OFTDateTime) {
            return java.sql.Timestamp.class;
        }

        if (type == OFTString) {
            return String.class;
        }

        if (type == OFTStringList) {
            return String[].class;
        }

        LOG.debug("unknown field type:" + type);
        return String.class;
    }

    @Override
    public CoordinateReferenceSystem crs() throws IOException {
        Pair data = open();
        try {
            SpatialReference sref = data.first.GetSpatialRef();
            if (sref == null) {
                return null;
            }

            try {
                // have ogr try to map random projection into a well known code
                sref.AutoIdentifyEPSG();
            }
            catch(Exception e) {
                LOG.debug("error auto identifying epsg code", e);
            }

            CoordinateReferenceSystem crs = null;

            // first try by mapping directly epsg code
            String code = sref.GetAuthorityCode(null);
            if (code != null) {
                crs = Proj.crs("epsg:" + code);
            }

            if (crs == null) {
                // use proj string
                crs = Proj.crs(sref.ExportToProj4());
            }

            return crs;
        }
        finally {
            close(data);
        }
    }
    
    @Override
    public Bounds bounds() throws IOException {
        Pair data = open();
        try {
            double[] d = data.first.GetExtent(true);
            return new Bounds(d[0], d[1], d[2], d[3]);
        }
        catch(Exception e) {
            throw new IOException("Error calculating bounds", e);
        }
        finally {
            close(data);
        }
    }

    @Override
    public long count(VectorQuery q) throws IOException {

        Pair data = open();
        try {
            Layer l = data.first;

            if (!Bounds.isNull(q.bounds())) {
                Bounds bb = q.bounds();
                l.SetSpatialFilterRect(bb.getMinX(), bb.getMinY(), bb.getMaxX(), bb.getMaxY());
            }

            if (!q.isFiltered()) {
                return q.adjustCount(l.GetFeatureCount());
            }

            //TODO: convert attribute filter to ogr sql
            return read(q).count();

        }
        catch(Exception e) {
            throw new IOException("Error calculating count", e);
        }
        finally {
            close(data);
        }
    }

    @Override
    public FeatureCursor read(VectorQuery q) throws IOException {
        Pair data = open();

        Layer l = data.first;

        VectorQueryPlan qp = new VectorQueryPlan(q);
        if (!Bounds.isNull(q.bounds())) {
            Bounds bb = q.bounds();
            l.SetSpatialFilterRect(bb.getMinX(), bb.getMinY(), bb.getMaxX(), bb.getMaxY());
            qp.bounded();
        }

        return qp.apply(new OGRCursor(l, data.second, this));
    }

    @Override
    public FeatureWriteCursor update(VectorQuery q) throws IOException {
        throw new UnsupportedOperationException();
    }

    @Override
    public FeatureAppendCursor append(VectorQuery q) throws IOException {
        throw new UnsupportedOperationException();
    }

    Pair open() throws IOException {
        DataSource ds = workspace.open();
        return Pair.of(ds.GetLayer(0), ds);
    }

    void close(Pair data) {
        data.first.delete();
        data.second.delete();
    }

    @Override
    public void close() {
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy