30 June 2006

Here I post a sample java class I developed some months ago, working with geometry creation in GeoTools 2. This class, given an input shapefile, will elaborate an output shapefile merging the input polygons on a common field.

Geotools is an open source (LGPL) Java code library which provides standards compliant methods for the manipulation of geospatial data, for example to implement Geographic Information Systems (GIS). The Geotools library implements Open Geospatial Consortium (OGC) specifications as they are developed, in close collaboration with the GeoAPI and GeoWidgets projects. The capabilities of Geotools are presented in the feature list.
/*
 * Created on 24-giu-2004
 */
package com.PaoloCorti.GIS.GeometryBuilder;

/**
 * @author corti
 * Richiede GeoTools2 e jts 1.4.0
 * Effettua il merge dei poligoni di uno shapefile in input sulla base di un campo, restituendo uno shapefile in output
 */
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.FileChannel;
import java.util.Arrays;
import org.geotools.data.DataUtilities;
import org.geotools.data.FeatureReader;
import org.geotools.data.FeatureResults;
import org.geotools.data.FeatureSource;
import org.geotools.data.FeatureStore;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.dbf.DbaseFileReader;
import org.geotools.feature.AttributeType;
import org.geotools.feature.AttributeTypeFactory;
import org.geotools.feature.Feature;
import org.geotools.feature.FeatureType;
import org.geotools.feature.FeatureTypeFactory;
import org.geotools.feature.IllegalAttributeException;
import org.geotools.filter.AttributeExpression;
import org.geotools.filter.CompareFilter;
import org.geotools.filter.FilterFactory;
import org.geotools.filter.FilterType;
import org.geotools.filter.LiteralExpression;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.MultiPolygon;

public class UnionPolygonByAttribute {

 /**
  * main, richiede come parametri:
  * 1. shapefile di input (es: C:\temp\datiGIS\province.shp)
  * 2. campo sul quale effettuare il merge (es: c:\temp\datiGIS\output.shp)
  * 3. shapefile di output (es: COD_REG)
  * Es per lanciarlo da linea di comando:
  * java -classpath C:/java/geotools/jars/gt2-main.jar;C:/java/geotools/jars/gt2-shapefile.jar;C:/java/geotools/lib/JTS-1.4.jar; com.PaoloCorti.GIS.GeometryBuilder.UnionPolygonByAttribute "file:/C:/temp/datiGIS/province" "COD_REG" "file:/C:/temp/datiGIS/output"
  * @param args
  * @throws Exception
  */
      public static void main(String[] args) throws Exception  {
             if(args.length>0){
                  String inputShape = args[0];
                  String fieldToUnionName = args[1];
                  String outputShape = args[2];
                  String inDBFName = inputShape.substring(6, inputShape.length()) + ".dbf";
                  Stampa("processo lo shape " + inputShape + " nello shape " + outputShape + " unendo le feature con lo stesso " + fieldToUnionName);
                  UnionPolyByField(inputShape, outputShape, fieldToUnionName, inDBFName);
             }
             else
               Stampa("specificare tutti i parametri!");
      }

      /**
       * Effettua il merge dello shape di input in uno shape di output
       * @param InputShape Shapefile di input (da mergiare)
       * @param OutputShape Shapefile di output (mergiato)
       * @param FieldToUnionName Campo sul quale effettuare il merge nello shapefile di input
       * @param InDBFName Nome tabella DBF
       * @throws Exception
       */
      private static void UnionPolyByField(String InputShape, String OutputShape, String FieldToUnionName, String InDBFName) throws Exception
      {
            FileChannel in = new FileInputStream(InDBFName).getChannel();
                         DbaseFileReader r = new DbaseFileReader(in);
                         int fields = r.getHeader().getNumFields();
                         int recordCount = r.getHeader().getNumRecords();
                         int fieldToUnionIndex=0;
                         Class fieldType = null;
                         for (int i=0; i<fields; i++){
                             String fieldName = r.getHeader().getFieldName(i);
                             //Stampa(fieldName);
                             //Stampa(FieldToUnionName);
                             if(fieldName.equalsIgnoreCase(FieldToUnionName))
                             {
                                   fieldToUnionIndex = i;
                                   //leggiamo il datatype
                                   fieldType = r.getHeader().getFieldClass(i);
                                   break;
                             }
                         }
                         Stampa("tipo campo: " + fieldType.toString());
                         String fieldUniqueValueArr[] = new String[recordCount];
                         int j = 0;
                         while (r.hasNext()) {
                             DbaseFileReader.Row row = r.readRow();
                             //Stampa(row.read(fieldToUnionIndex).toString());
                             //make array
                             fieldUniqueValueArr[j]=row.read(fieldToUnionIndex).toString();
                             j++;
                         }
                         //shape da leggere e interrogare (input)
                         ShapefileDataStore sds = new ShapefileDataStore(new URL(InputShape));
                         String name = sds.getTypeNames()[0];  //solo 1 parametro per gli shape
                         Stampa("DATASTORE.getTypeNames() = " + name);
                         //leggo le feature
                         FeatureSource fs = sds.getFeatureSource(name);
                         FeatureType featureType = fs.getSchema();
                         FeatureResults fres = fs.getFeatures();
                         Stampa(fres.getCount() + " features nello shapefile");
                         //creiamo lo shapefile
                         ShapefileDataStore newShapeFileDatastore = new ShapefileDataStore(new URL(OutputShape));
                         //creiamo lo schema dello shape
                         AttributeType attUnionGeom = AttributeTypeFactory.newAttributeType("the_geom", MultiPolygon.class);
                         AttributeType attArea = AttributeTypeFactory.newAttributeType("AREA", Double.class);
                         AttributeType attPerimeter = AttributeTypeFactory.newAttributeType("PERIMETER", Double.class);
                         FeatureType newFeatureType = FeatureTypeFactory.newFeatureType(new AttributeType[] {attUnionGeom, attArea, attPerimeter}, name);
                         newShapeFileDatastore.createSchema(newFeatureType);
                         FeatureSource newFeatureSource = newShapeFileDatastore.getFeatureSource(name);
                         FeatureStore newFeatureStore = (FeatureStore)newFeatureSource;
                         //sort array
                         Arrays.sort(fieldUniqueValueArr);
                         String oldValue = fieldUniqueValueArr[0];
                         Stampa(oldValue);
                         for(int i=0; i<fieldUniqueValueArr.length; i++){
                           if(!fieldUniqueValueArr.equalsIgnoreCase(oldValue) || i==0){
                                oldValue = fieldUniqueValueArr;
                                Stampa(oldValue);
                                //faccio il filtro
                                    FilterFactory ff = FilterFactory.createFilterFactory();
                                    CompareFilter cf = ff.createCompareFilter(FilterType.COMPARE_EQUALS);
                                    AttributeExpression attExpression = ff.createAttributeExpression(featureType, FieldToUnionName);
                                    LiteralExpression l1;
                                    l1 = ff.createLiteralExpression(Double.parseDouble(oldValue)); //qui va modificato a seconda del datatype
                                    cf.addLeftValue(attExpression);
                                    cf.addRightValue(l1);
                                    Stampa(cf.toString());
                                    //faccio la query
                                    FeatureResults fQueryResults = fs.getFeatures(cf);
                                    int numFeat = fQueryResults.getCount();
                                    Stampa(numFeat + " features con " + FieldToUnionName + " = " + oldValue);
                                    //leggiamo le feature ottenute
                                    FeatureReader featureReader = fQueryResults.reader();
                                    //edit
                                    if(numFeat>0){
                                    Transaction t = newFeatureStore.getTransaction();
                                    //aggiungiamo le feature
                                    Geometry polyUnion = PolygonUnion(featureReader, numFeat);
                                    if(polyUnion instanceof MultiPolygon)
                                    {
                                          Double area = new Double(polyUnion.getArea());
                                          Double perimeter = new Double(polyUnion.getLength());
                                          Feature f = newFeatureType.create(new Object[] {polyUnion, area, perimeter});
                                          FeatureReader newFeatureReader = DataUtilities.reader(new Feature[] {f});
                                          newFeatureStore.addFeatures(newFeatureReader);
                                     }
                                    t.commit();
                                    t.close();
                                    }
                           }
                         }                      
      }

      /**
       * Unisce n poligoni in un poligono
       * @param fr
       * @param nfeat
       * @return
       */
      private static Geometry PolygonUnion(FeatureReader fr, int nfeat) {
            try {
                             //array Geometry jts
                             int i=0;
                             Geometry geomarr[] = new Geometry[nfeat];
                          while(fr.hasNext()) {
                               Feature feature = fr.next();
                               //Stampa(String.valueOf(feature.getDefaultGeometry().getArea()));
                               geomarr[i++] = feature.getDefaultGeometry();
                             //System.out.print(i + "/" + nfeat + "-");
                          }
                             //ora faccio buffer
                             Geometry geom = geomarr[0];
                             for (i=0; i<nfeat; i++) {
                                   geom = geom.union(geomarr);
                             }
                             //Stampa(String.valueOf(String.valueOf(geom.getArea())));
                             Stampa("CREATO POLIGONO!");
                             return geom;
            }
            catch(IllegalAttributeException error){
                  Stampa("errore geometrico!");
                  return null;            
            }
            catch(IOException error){
                  Stampa("errore geometrico!");
                  return null;            
            }
      }

      private static void Stampa(String stringa){
                  System.out.println(stringa);
            }
}


blog comments powered by Disqus