com.opendoorlogistics.core.geometry.ImportShapefile.java Source code

Java tutorial

Introduction

Here is the source code for com.opendoorlogistics.core.geometry.ImportShapefile.java

Source

/*******************************************************************************
 * Copyright (c) 2014 Open Door Logistics (www.opendoorlogistics.com)
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License v3
 * which accompanies this distribution, and is available at http://www.gnu.org/licenses/lgpl.txt
 ******************************************************************************/
package com.opendoorlogistics.core.geometry;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.io.FilenameUtils;
import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFinder;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.geometry.jts.JTS;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeType;
import org.opengis.filter.FilterFactory2;
import org.opengis.filter.Id;
import org.opengis.filter.identity.FeatureId;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;

import com.opendoorlogistics.api.components.PredefinedTags;
import com.opendoorlogistics.api.geometry.ODLGeom;
import com.opendoorlogistics.api.tables.ODLColumnType;
import com.opendoorlogistics.api.tables.ODLDatastoreAlterable;
import com.opendoorlogistics.api.tables.ODLTableAlterable;
import com.opendoorlogistics.core.AppConstants;
import com.opendoorlogistics.core.geometry.rog.ODLRenderOptimisedGeom;
import com.opendoorlogistics.core.geometry.rog.RogReaderUtils;
import com.opendoorlogistics.core.geometry.rog.RogSingleton;
import com.opendoorlogistics.core.tables.ColumnValueProcessor;
import com.opendoorlogistics.core.tables.beans.BeanTypeConversion;
import com.opendoorlogistics.core.tables.memory.ODLDatastoreImpl;
import com.opendoorlogistics.core.tables.utils.TableUtils;
import com.opendoorlogistics.core.utils.LargeList;
import com.opendoorlogistics.core.utils.io.RelativeFiles;
import com.opendoorlogistics.core.utils.strings.Strings;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryCollection;
import com.vividsolutions.jts.geom.Polygon;

public final class ImportShapefile {

    //   static SimpleFeatureCollection selectFeaturesById(SimpleFeatureSource source, Set<String> ids) {
    //      FilterFactory2 factory = CommonFactoryFinder.getFilterFactory2(null);
    //
    //      HashSet<FeatureId> set = new HashSet<FeatureId>();
    //      for (String id : ids) {
    //         FeatureId fid = factory.featureId(id);
    //         set.add(fid);
    //      }
    //      Id filter = factory.id(set);
    //      try {
    //         return source.getFeatures(filter);
    //      } catch (Throwable e) {
    //         throw new RuntimeException(e);
    //      }
    //   }

    /**
     * Find and return all polygon objects within the geometry.
     * @param geometry
     * @return
     */
    public static List<Polygon> findPolygons(Geometry geometry) {
        final ArrayList<Polygon> ret = new ArrayList<>();
        class Recursor {
            void recurse(Geometry g) {
                if (g == null) {
                    return;
                }

                if (Polygon.class.isInstance(g)) {
                    ret.add((Polygon) g);
                } else if (GeometryCollection.class.isInstance(g)) {
                    int n = g.getNumGeometries();
                    for (int i = 0; i < n; i++) {
                        recurse(g.getGeometryN(i));
                    }
                }
            }
        }

        new Recursor().recurse(geometry);
        return ret;
    }

    public static ODLDatastoreAlterable<ODLTableAlterable> importShapefile(File file, boolean isLinkedGeometry) {
        ODLDatastoreAlterable<ODLTableAlterable> ds = ODLDatastoreImpl.alterableFactory.create();
        importShapefile(file, isLinkedGeometry, ds, false);
        return ds;
    }

    public static DataStore openDataStore(File file) {
        Map<String, URL> map = new HashMap<String, URL>();
        try {
            map.put("url", file.toURL());
            return DataStoreFinder.getDataStore(map);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Import the shapefile. All geometry is transformed into WGS84.
     * 
     * @param file
     * @param ds
     */
    @SuppressWarnings("deprecation")
    public static HashMap<ShapefileLink, ODLGeom> importShapefile(File file, boolean isLinkedGeometry,
            ODLDatastoreAlterable<? extends ODLTableAlterable> ds, boolean returnGeometry) {
        Spatial.initSpatial();

        file = RelativeFiles.validateRelativeFiles(file.getPath(), AppConstants.SHAPEFILES_DIRECTORY);
        if (file == null) {
            return new HashMap<>();
        }

        // check if we're actually opening a render optimised geometry file... do something if we are? 
        String ext = FilenameUtils.getExtension(file.getAbsolutePath());
        boolean isRog = Strings.equalsStd(ext, RogReaderUtils.RENDER_GEOMETRY_FILE_EXT);
        File originalFile = file;
        List<ODLRenderOptimisedGeom> rogs = null;
        if (isRog) {
            rogs = new LargeList<>();
            RogSingleton.singleton().createLoader(file, rogs);

            // get the shapefile from the main one
            String shpFile = FilenameUtils.removeExtension(file.getPath()) + ".shp";
            file = new File(shpFile);
        }

        SimpleFeatureIterator it = null;
        DataStore shapefile = null;

        // create return object
        HashMap<ShapefileLink, ODLGeom> ret = null;
        if (returnGeometry) {
            ret = new HashMap<>();
        }

        try {
            shapefile = openDataStore(file);
            if (shapefile == null) {
                throw new RuntimeException("Could not open shapefile: " + file);
            }

            // get the linkfile using the *original file*, not the potentially redirected file
            String linkFile = RelativeFiles.getFilenameToSaveInLink(originalFile,
                    AppConstants.SHAPEFILES_DIRECTORY);

            for (String type : shapefile.getTypeNames()) {

                // make table
                ODLTableAlterable table = null;
                if (ds != null) {
                    String tableName = type;
                    if (TableUtils.findTable(ds, tableName) != null) {
                        tableName = TableUtils.getUniqueNumberedTableName(type, ds);
                    }
                    table = ds.createTable(type, -1);
                }

                // add columns for each usable feature
                SimpleFeatureType schema = shapefile.getSchema(type);
                int nAttrib = schema.getAttributeCount();
                int[] mapped = new int[nAttrib];
                Arrays.fill(mapped, -1);
                if (ds != null) {
                    for (int i = 0; i < nAttrib; i++) {
                        AttributeType attributeType = schema.getType(i);
                        Class<?> binding = attributeType.getBinding();
                        ODLColumnType colType = BeanTypeConversion.getInternalType(binding);
                        if (colType != null) {
                            String attributeName = schema.getDescriptor(i).getLocalName();
                            if (table.addColumn(i, attributeName, colType, 0) != -1) {
                                mapped[i] = table.getColumnCount() - 1;
                                if (colType == ODLColumnType.GEOM) {
                                    table.setColumnTags(mapped[i], Strings.toTreeSet(PredefinedTags.GEOMETRY));
                                }
                            }
                        }
                    }
                }

                // get coord transform to turn into wgs84 long-lat
                MathTransform toWGS84 = getTransformToWGS84(shapefile, type);

                SimpleFeatureSource source = shapefile.getFeatureSource(type);
                SimpleFeatureCollection collection = source.getFeatures();

                // parse all features recording all attributes, including geometry
                it = collection.features();
                int objectIndex = 0;
                while (it.hasNext()) {
                    SimpleFeature feature = it.next();

                    //System.out.println(feature.getID());

                    if (SimpleFeature.class.isInstance(feature)) {
                        SimpleFeature sf = (SimpleFeature) feature;

                        // create row if we're outputting to a datastore
                        int row = -1;
                        if (ds != null) {
                            row = table.createEmptyRow(-1);
                        }

                        for (int i = 0; i < nAttrib; i++) {
                            Object value = sf.getAttribute(i);

                            // process geometry
                            ShapefileLink link = null;
                            if (value != null && Geometry.class.isInstance(value)) {

                                if (!isLinkedGeometry || ret != null) {
                                    if (rogs != null) {
                                        value = rogs.get(objectIndex);
                                    } else {
                                        // Transform the geometry to wgs84 if we need it 
                                        value = JTS.transform((Geometry) value, toWGS84);
                                        value = new ODLLoadedGeometry((Geometry) value);
                                    }
                                } else {
                                    // Geometry not needed
                                    value = null;
                                }

                                // Create geometry link
                                link = new ShapefileLink(linkFile, type, sf.getID());

                                // Save the transformed geometry if flagged
                                if (ret != null) {
                                    ret.put(link, (ODLGeom) value);
                                }

                                // If we're using linked geometry the value for the table is the link
                                if (isLinkedGeometry) {
                                    value = new ODLShapefileLinkGeom(link);
                                }
                            }

                            // save to table if mapped
                            int col = mapped[i];
                            if (col != -1) {
                                ODLColumnType odlType = table.getColumnType(col);
                                value = ColumnValueProcessor.convertToMe(odlType, value);
                                table.setValueAt(value, row, col);
                            }
                        }

                        objectIndex++;

                    } else {
                        throw new RuntimeException();
                    }

                }

            }

        } catch (Throwable e) {
            throw new RuntimeException(e);
        } finally {
            if (it != null) {
                it.close();
            }
            if (shapefile != null) {
                shapefile.dispose();
            }
        }

        return ret;
    }

    public static MathTransform getTransformToWGS84(DataStore shapefile, String type) throws IOException {
        CoordinateReferenceSystem crs = shapefile.getSchema(type).getCoordinateReferenceSystem();
        MathTransform toWGS84 = Spatial.toWgs84(crs);
        return toWGS84;
    }

    public static void main(String[] args) {
        for (String filename : new String[] { "C:\\Processing\\all\\districts.shp",
                "C:\\Processing\\all\\districts2.shp", "districts2.shp", "dir2\\dir3\\districts2.shp" }) {
            ShapefileLink link = new ShapefileLink(filename, "", "");
            try {
                File validated = RelativeFiles.validateRelativeFiles(link.getFile(),
                        AppConstants.SHAPEFILES_DIRECTORY);
                String saveAs = RelativeFiles.getFilenameToSaveInLink(validated, AppConstants.SHAPEFILES_DIRECTORY);
                System.out.println("Load from: " + validated + " Save as:" + saveAs);
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
        //      // C:\Users\Phil\Dropbox\Business\Data\Shapefiles\Antartica\natural.shp
        //      String filename = "C:\\Processing\\all\\districts.shp";
        //      
        //      System.out.println("Starting1 " + new Date());
        //      importShapefile(new File(filename),false);
        //      System.out.println("Finished1 " + new Date());
        //      
        //      System.out.println("Starting2 " + new Date());
        //      for(int i =0 ;i <2767 ; i++){
        //         ShapefileLink link = new ShapefileLink(filename, "districts", "districts." + i);
        //         Object geometry = Spatial.loadLink(link);
        //         //System.out.println(link + "->" + (geometry==null? "Not loaded" : "Loaded"));
        //      }
        //      System.out.println("Finishing2 " + new Date());
        //
        //      System.out.println("Starting3 " + new Date());
        //      importShapefile(new File(filename),false);
        //      System.out.println("Finished3 " + new Date());
    }
}