Thursday, April 13, 2017

Open Layers 3 - Playing with Projections

I big issue when plotting GIS maps is the projection of your data. Open layers 3 gives much more flexibility, than Open layers 2 used to do, on that field. With the latest versions of OL3 you can even reproject rasters and tiles on the client side. This is awesome in it?
But how is it working?
Lets go through some example cases.

 Case 1.I am not a mapping geek. I just want to show a map.
This is the simplest case. Just load a tile layer and let ol3 to choose the projection. This would be the EPSG:3857  as most public tile layers services provide their tile data in EPSG:3857. This is OSM, Google, Bing map etc. So ,just to make clear, if you dont provide any projection during map config EPSG:3857 shall be used and any layer we add on map should be reprojected on that projection on client side if needed.

 ------> Here is an example (CASE1). And its fiddle here

 var map = new ol.Map({  
     layers: [  
      new ol.layer.Tile({  
       source: new ol.source.OSM()  
      })  
     ],  
     target: 'map',  
     view: new ol.View({  
      center: [0, 0],  
      zoom: 2  
     })  
    });  


 Case 2.I am a bit more advanced user. So I want to have control of the map projection
Now if you want to give your map a projection other than EPSG:3857 then you have to assign it to the ol.view of your map. In this case there are 2 sub cases.

   - subcase1. I want to project in EPSG:4326
In this subcase there is no special treatment. Just assign EPSG:4326 on the view of your map.


-------> Here is an example (CASE2 - subcase1). And its fiddle here

 var map = new ol.Map({  
  layers: [  
   new ol.layer.Tile({  
    source: new ol.source.OSM()  
   })  
  ],  
  target: 'map',  
  view: new ol.View({  
   projection:'EPSG:4326',//here is your 4326 projection
   center: [0, 0],  
   zoom: 2  
  })  
 });  

- subcase2. I want to project in a projection other than 4326 or 3857 and the projection code I am looking for exist in the epsg.io database.
In this subcase ol3 need an external library to go on. This is proj4js.js (further info and download here)
So we need to follow the steps below.
1. Load the external library within our html page
2. Search for our projection in the http://epsg.io/. Once we find the projection we are looking for  we go to Export --> Proj4js and then we do copy-paste the javascript definition of our projection.



3. Next step is to add the line of code we just copied to our javascript section.
So lets say we are looking for EPSG:2100 which is the National Greek Projection. Then we need to add this line of code:
 proj4.defs("EPSG:2100","+proj=tmerc +lat_0=0 +lon_0=24 +k=0.9996 +x_0=500000 +y_0=0 +ellps=GRS80 +towgs84=-199.87,74.79,246.62,0,0,0,0 +units=m +no_defs");  

So now ol3 is aware about our new projection. It would also be good to add the extent for our new projection, using the following

 var 2100extent= [-34387.6695, 3691163.5140, 1056496.8434, 4641211.3222];  
 proj.get('EPSG:2100').setExtent(2100extent);  

So lets put in all together now. We want our map to be projected on EPSG:2100 and thus all layers added on map to be reprojected on EPSG:2100


 var extent2100 = [-34387.6695, 3691163.5140, 1056496.8434, 4641211.3222];  
  proj4.defs("EPSG:2100","+proj=tmerc +lat_0=0 +lon_0=24 +k=0.9996 +x_0=500000 +y_0=0 +ellps=GRS80 +towgs84=-199.87,74.79,246.62,0,0,0,0 +units=m +no_defs");  
 ol.proj.get('EPSG:2100').setExtent(extent2100);  
 var layer = new ol.layer.Tile({  
     source: new ol.source.OSM()  
   });  
 var map = new ol.Map({  
  layers: [layer],  
  target: 'map',  
  view: new ol.View({  
   projection: 'EPSG:2100',  
    center: [510457.300375, 4150059.924838],  
   zoom: 4  
  })  
 });  


An here is a fiddle

What if I want to add a wms layer to the map with my custom projection???? Do I need to tell ol3 so reproject my wms layer?????

Well, the direct answer is no you dont have to. Unless you want the reprojection to take place on the server side. Which is not normal for myself. Reprojecting on the server side would stretch my server. So as long as I have the option to do it on client and so not heavy-load my server I prefer to do it on client.

So lets go back to the question. You just have to cofigure your WMS layer and add it to your map. Like so:


 var wmslayer = new ol.layer.Image({  
      source: new ol.source.ImageWMS({  
       url: 'http://suite.opengeo.org/geoserver/wms',  
       params: {'LAYERS': 'opengeo:countries'},  
       serverType: 'geoserver'  
      })  
     }) 
map.addLayer(wmslayer);


And here is one more fiddle to see it live

TO BE CONTINUED WITH FEW MORE CASES ..........

Thursday, December 8, 2016

Integrating OL3 with geostats.js to produce Thematic Maps for Socio-Economic Data

Lately, I had a requirement building a "thematic mapping" application using openlayers 3 in order to visualise socio-economic data. OL3 does not provide any functionality related to statistical mapping. So googling it, I fell into geostats .
A tiny standalone JS library for classification. It is like a hidden treasure, which I never had the chance to test it. Within the project page there are a few examples related to OL2 but nothing related to OL3. So I though it would be nice to share my experience and give a boost to all GIS geeks looking forward to use the library in conjunction with OL3.

It currently supports the following statistical methods
  • equal intervals
  • quantiles
  • standard deviation (seems to have a small bug here)
  • arithmetic progression
  • geometric progression
  • jenks (natural breaks)
  • uniques values
  • user defined classification
So lets go for an example. Lets build a thematic population map for  world countries.

If you are too impatient ...... get a snapshot

But lets examine our code step by step:
Here is your html:
Nothing special. A selector for the method selected, a number spinner to get the number classes and two divs. One for the map and one to place the generated legend. And of course a button to draw our thematic map.

<select id="methodselector" class="form-control">
  <option value="method_EI" >Equal Interval</option>
  <option value="method_Q" selected>Quantile</option>
  <option value="method_SD" >Standard Deviation</option>
  <option value="method_AP" >Arithmetic Progression</option>
  <option value="method_GP" >Geometric Progression</option>
  <option value="method_CJ">Class Jenks</option>                  
</select>
Number of Classes:
<input type="number" id="classcount" min="1" value="5" max="10">
<input type="button" id="drawitbtn"  value='draw themmatic'/>

<div id="map" class="map"></div>

<div id='legend'></div>

Dont forget to reference the necessary js, css libs within your html file. These are::
<link rel="stylesheet" type="text/css" href="https://openlayers.org/en/v3.19.1/css/ol.css" />
<script src="https://openlayers.org/en/v3.19.1/build/ol-debug.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chroma-js/1.2.1/chroma.min.js"></script>
<script src="https://www.intermezzo-coop.eu/mapping/geostats/lib/geostats.js"></script>
:
Here is your css:
Again nothing special. Just a few classes to support the legend.


.geostats-legend div {
  margin: 3px 10px 5px 10px
}

.geostats-legend-title {
  font-weight: bold;
  margin-bottom: 4px;
}

.geostats-legend-block {
  border: 1px solid #555555;
  display: block;
  float: left;
  height: 12px;
  margin: 0 5px 0 20px;
  width: 20px;
}

.geostats-legend-counter {
  font-size: 0.8em;
  color: #666;
  font-style: italic;
}

And finally your JAVASCRIPT:
just go through the comments of code

$('#drawitbtn').click(drawIt);

//some global vars here
var classSeries;
var classColors;
//color start from
var colorFrom ='FFFFFF';
//color end to
var colorTo = '1A8B16';
var defaultStyle = new ol.style.Style({
  fill: new ol.style.Fill({
    color: 'rgba(255, 255, 255, 0.3)'
  }),
  stroke: new ol.style.Stroke({
    color: 'rgba(0, 255, 0, 1)',
    width: 1
  }),
  text: new ol.style.Text({
    font: '12px Calibri,sans-serif',
    fill: new ol.style.Fill({
      color: '#000'
    }),
    stroke: new ol.style.Stroke({
      color: '#fff',
      width: 3
    })
  })
});


//our methods here

var vectorLayer = new ol.layer.Vector({
  style:defaultStyle,
  source: new ol.source.Vector({
    url: 'https://gist.githubusercontent.com/ptsagkis/dacbe5a42856dee041294b54579095d4/raw/730879d0d4909622b273818235b9c7f510bab5ee/countries_siplified.geojson',
   format: new ol.format.GeoJSON({
              defaultDataProjection:'EPSG:4326',
              featureProjection:'EPSG:3857'
            })
  })
});

var map = new ol.Map({
  layers: [
    new ol.layer.Tile({
      source: new ol.source.OSM()
    }),
    vectorLayer
  ],
  target: 'map',
  view: new ol.View({
    center: [0, 0],
    zoom: 1
  })
});



/**
 * do the themmatic
 */
function drawIt(){
var countryPopVals = new Array();
vectorLayer.getSource().getFeatures().forEach(function(feat) {
countryPopVals.push(feat.get("POP2005"))
});
console.info("countryPopVals",countryPopVals);
getAndSetClassesFromData(countryPopVals, getClassNum(), getMethod());
vectorLayer.setStyle(setStyle);
}


/**
 * @data {Array} the array of numbers (these are the pop data for all countries)
 * @numclasses {Integer} get the number of classes
 * @method {String}  get the classification method
 * 
 *
 * set geostats object
 * set the series
 * set the colors ramp        
 * 
 */
function getAndSetClassesFromData(data, numclasses, method) {
  var serie = new geostats(data);
  var legenLabel = ""; 
  if (method === "method_EI") {
    serie.getClassEqInterval(numclasses);
    methodLabel = "Equal Interval";
  } else if (method === "method_Q") {
    serie.getClassQuantile(numclasses);
    methodLabel = "Quantile";
  } else if (method === "method_SD") {
    serie.getClassStdDeviation(numclasses);
    methodLabel = "Standard Deviation ";
  } else if (method === "method_AP") {
    serie.getClassArithmeticProgression(numclasses);
    methodLabel = "Arithmetic Progression";
  } else if (method === "method_GP") {
    serie.getClassGeometricProgression(numclasses);
    methodLabel = "Geometric Progression ";
  } else if (method === "method_CJ") {
    serie.getClassJenks(numclasses);
    methodLabel = "Class Jenks";
  } else {
  alert("error: no such method.")
  }
 var colors_x = chroma.scale([colorFrom, colorTo]).colors(numclasses)

serie.setColors(colors_x);
document.getElementById('legend').innerHTML = serie.getHtmlLegend(null, "World Population</br> Method:"+methodLabel, 1);
classSeries = serie;
classColors = colors_x; 
}




/**
 * function to verify the style for the feature
 */
function setStyle(feat,res) {
  var currVal = parseFloat(feat.get("POP2005")); 
  var bounds = classSeries.bounds;
  var numRanges = new Array();
  for (var i = 0; i < bounds.length-1; i++) { 
  numRanges.push({
      min: parseFloat(bounds[i]),
      max: parseFloat(bounds[i+1])
    });  
  }  
  var classIndex = verifyClassFromVal(numRanges, currVal);
  var polyStyleConfig = {
    stroke: new ol.style.Stroke({
      color: 'rgba(255, 0, 0,0.3)',
      width: 1
    })
  };

  var textStyleConfig = {};
  var label = res < 5000 ? feat.get('NAME') : '';
  if (classIndex !== -1) {
    polyStyleConfig = {
      stroke: new ol.style.Stroke({
        color: 'rgba(0, 0, 255, 1.0)',
        width: 1
      }),
      fill: new ol.style.Stroke({
        color: hexToRgbA(classColors[classIndex],0.7)
      })
    };
    textStyleConfig = {
      text: new ol.style.Text({
        text: label,
        font: '12px Calibri,sans-serif',
        fill: new ol.style.Fill({
          color: "#000000"
        }),
        stroke: new ol.style.Stroke({
          color: "#FFFFFF",
          width: 2
        })
      }),
      geometry: function(feature) {
        var retPoint;
        if (feature.getGeometry().getType() === 'MultiPolygon') {
          retPoint = getMaxPoly(feature.getGeometry().getPolygons()).getInteriorPoint();
        } else if (feature.getGeometry().getType() === 'Polygon') {
          retPoint = feature.getGeometry().getInteriorPoint();
        }
        
        return retPoint;
      }
    }
  };

  var textStyle = new ol.style.Style(textStyleConfig);
  var style = new ol.style.Style(polyStyleConfig);
  return [style, textStyle];
}

//*************helper functions this point forward***************//
 
function verifyClassFromVal(rangevals, val) {
  var retIndex = -1;
  for (var i = 0; i < rangevals.length; i++) {
    if (val >= rangevals[i].min && val <= rangevals[i].max) {
      retIndex = i;
    }
  }
  return retIndex;
}

/**
 *   get the user selected method
 */
function getMethod(){
var elem = document.getElementById("methodselector");
var val = elem.options[elem.selectedIndex].value;
return val;
}

/**
 *   get the user selected number of classes
 */
function getClassNum(){
var elem = document.getElementById("classcount");
return parseInt(elem.value);
}


/**
 * convert hex to rgba 
 *
 */
function hexToRgbA(hex,opacity) {
  var c;
  if (/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)) {
    c = hex.substring(1).split('');
    if (c.length == 3) {
      c = [c[0], c[0], c[1], c[1], c[2], c[2]];
    }
    c = '0x' + c.join('');
    return 'rgba(' + [(c >> 16) & 255, (c >> 8) & 255, c & 255].join(',') + ','+opacity+')';
  }
  throw new Error('Bad Hex');
}
/**
 *    get the maximum polygon out of the supllied  array of polygon
 *    used for labeling the bigger one
 */
function getMaxPoly(polys) {
  var polyObj = [];
  //now need to find which one is the greater and so label only this
  for (var b = 0; b < polys.length; b++) {
    polyObj.push({
      poly: polys[b],
      area: polys[b].getArea()
    });
  }
  polyObj.sort(function(a, b) {
    return a.area - b.area
  });

  return polyObj[polyObj.length - 1].poly;
}


Enjoy all of you

Monday, June 27, 2016

KML,GPX,GeoJson,WKT Online Parser and Viewer

Here is a simple online formats parser, I have recently develop, and I would like to share.
May handle KML,GPX,GeoJson,WKT formats. It is just an html file with a few javascript. May be freely downloaded from here.
You may view the online parser here (full screen)
Or get a snapshot

Wednesday, February 17, 2016

Importing esri shapefiles into DBs (Oracle, postGIS) using JAVA


Today we will walk through the process of importing shapefiles into Oracle SDO geometry type and PostGIS ST geometry type.
For the case of Oracle you have two options. You may use eitheir native oracle native  jars (sdoutl.jar and sdoapi.jar) or GEOTOOLS  java library. 

Oracle Case 1 (in my personal opinion this is the simplest way to do it)

1) You need to download sdoutl.jar and sdoapi.jar. These 2 jars may be found in the Oracle Companion CD which may be freely downloaded from oracle. Else just google it and you may found some downloading links.
2) You need to download ojdbc6.jar which may be found here ojdbc6.jar
3) Once you have these three jars you may reference them to your project.

Once you have the above create a JAVA class as follows:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gis.openfreegis.rdbms;

import java.io.IOException;
import java.sql.DriverManager;
import oracle.jdbc.OracleConnection;
import oracle.spatial.util.ShapefileReaderJGeom;
import oracle.spatial.util.DBFReaderJGeom;
import oracle.spatial.util.ShapefileFeatureJGeom;

/**
 *
 * @author pt
 */
public class ShapeToSDO2 {
public  ShapeToSDO2 (
        String shploc,          //location of shapefile and name without any file extension
        String oraTableName,    //oracle table name to give
        String geomColName,     //geometry column name to give
        int Srid,               //srid to asign rto the table
        double tol,             //the spatial tolerance to asign to metadata
        String IdCol,           //unique id column
        int IdStart,            //starting point for integer to asign to IdCol
        int commitFreq,         //num of records to insert before commiting
        int printFreq,          //num of records to insert to LOG
        boolean encFileExist,   // whther .cpg file exist and you want to use it in order to encode characters
        String dbip,            //the idb ip to connect to
        String dbport,          // the db port
        String dbname,          //the instance name
        String dbuser,          // the user
        String dbpass           // and the passwrod
        ) throws IOException, Exception{
    


    
    
ShapefileReaderJGeom shpr = new ShapefileReaderJGeom(shploc);
DBFReaderJGeom dbfr = new DBFReaderJGeom(shploc);
//force to use the charset encoding if encFileExist true
if (encFileExist) {
    dbfr.readCodePage(shploc);
}
ShapefileFeatureJGeom sf = new ShapefileFeatureJGeom();
double minX = shpr.getMinX();
double minY = shpr.getMinY();
double maxX = shpr.getMaxX();
double maxY = shpr.getMaxY();
double minZ = shpr.getMinZ();
double maxZ = shpr.getMaxZ();
double minM = shpr.getMinMeasure();
double maxM = shpr.getMaxMeasure();
int shapeType = shpr.getShpFileType();
int shpDims = shpr.getShpDims(shapeType,maxM);

//these are the metadata
String dimArray = 
sf.getDimArray(
    shpDims, 
    String.valueOf(tol),
    String.valueOf(minX),
    String.valueOf(maxX), 
    String.valueOf(minY),
    String.valueOf(maxY), 
    minZ,
    maxZ,
    minM,
    maxM
    );
//create the oracle connection
  OracleConnection  myDbCon = (OracleConnection) DriverManager.getConnection(
                   "jdbc:oracle:thin:@"+
                    dbip+":"+dbport+":"+dbname,
                    dbuser,
                    dbpass
          );
  //create the table and metadata. If table exist shall be deleted  
    sf.prepareTableForData(myDbCon,dbfr,oraTableName,IdCol,geomColName,Srid,dimArray);
  //and finally do the insert
    sf.insertFeatures(myDbCon,dbfr,shpr,oraTableName,IdCol,IdStart,commitFreq,printFreq,Srid,dimArray);
  //close both shp,dbf files  
    shpr.closeShapefile();
    dbfr.closeDBF();
    
    
}
}

an then you may call you class like so:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
ShapeToSDO2 SHPSDO2 = new ShapeToSDO2(
            "C:\\myfiles\\shapefilename",//no file extension just the file name
            "MYNEWTABLENAME",//the table name you want to create and import the shapefile data.If exists it will be deleted and recreated
            "GEOM",//the geometry name to asign to the table
            2100,//the SRID code as Oracle understands it
            0.05,//the spatial tolerance
            "ID",//the Unique identifier column to create
            1,//the starting point of the above column
            10,//the frequency commit shall take place (every 10 insert staments)
            10,//the frequency logging shall take place (every 10 insert staments)
            true,//if the shapefile has a .cpg file to verify the charset to use for the dbf translation. May be true or false 
            "localhost", //the DB ip
            "1521",//the DB port
            "orcl",//the DB instance
            "USER",//the DB user
            "PASS"//the DB password
            );

Oracle Case 2 (using Geotools)
In this case things are a bit complicated. Although there are varius examples on the net, when it comes down to oracle none of them is working. The problem comes because oracle converts column names to capital letters, so when mathching fields between shapefile and DB column names you get errors and your job fails. To overcome the issue create a JAVA class as follows


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gis.openfreegis.rdbms;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.geotools.data.DataStore;
import org.geotools.data.DataUtilities;
import org.geotools.data.DefaultTransaction;
import org.geotools.data.FeatureStore;
import org.geotools.data.Transaction;
import org.geotools.data.oracle.OracleNGDataStoreFactory;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.feature.FeatureIterator;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.jdbc.JDBCDataStoreFactory;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.filter.Filter;
import org.opengis.referencing.FactoryException;




public class ShapeToSdo {
public  ShapeToSdo (String shploc) throws FactoryException, MalformedURLException, IOException {

String path = shploc;
        ShapefileDataStore shp = new ShapefileDataStore(new File(path).toURL());
        //THIS IS CRUCIAL FOR GREEK CHARS parsing
        shp.setCharset(Charset.forName("ISO-8859-7"));
        //IF NOT GREEK JUST OMMIT IT OR SET IT TO UTF_8
        //shp.setCharset(Charset.forName("UTF-8"));



        
        
        Map<Serializable, Object> params = new HashMap<Serializable, Object>();
        params.put(JDBCDataStoreFactory.USER.key, "USER");
        params.put(JDBCDataStoreFactory.PASSWD.key, "PASS");
        params.put(JDBCDataStoreFactory.HOST.key, "localhost");
        params.put(JDBCDataStoreFactory.PORT.key, "1521");
        params.put(JDBCDataStoreFactory.DATABASE.key, "orcl");
        params.put(JDBCDataStoreFactory.DBTYPE.key, "oracle");

        
        DataStore oracle = new OracleNGDataStoreFactory().createDataStore(params);
        if(oracle != null && oracle.getTypeNames() != null)
            System.out.println("Oracle connected");
        System.out.println("oracle.getTypeNames()"+oracle.getTypeNames());
        String typeName = shp.getTypeNames()[0].toUpperCase();

        System.out.println("shp.getTypeNames()[0]===="+shp.getTypeNames()[0]);
        if(!Arrays.asList(oracle.getTypeNames()).contains(typeName)){
            System.out.println("shp.getSchema()"+shp.getSchema());
            oracle.createSchema(shp.getSchema());
        }
        FeatureStore oraStore = (FeatureStore) oracle.getFeatureSource(typeName);
        oraStore.removeFeatures(Filter.INCLUDE);
        
        SimpleFeatureType targetSchema = (SimpleFeatureType) oraStore.getSchema();
        SimpleFeatureBuilder builder = new SimpleFeatureBuilder(targetSchema);
        
        
        FeatureIterator fi = shp.getFeatureSource().getFeatures().features();
        SimpleFeatureType sourceSchema = shp.getSchema();
        
        Transaction t = new DefaultTransaction();
        oraStore.setTransaction(t);
        while(fi.hasNext()) {
            SimpleFeature source = (SimpleFeature) fi.next();
        
            for(AttributeDescriptor ad : sourceSchema.getAttributeDescriptors()) {
                String attribute = ad.getLocalName();
                String passAtrr = attribute.toUpperCase();
                
                builder.set(passAtrr, source.getAttribute(attribute));
                }
            
            oraStore.addFeatures(DataUtilities.collection(builder.buildFeature(null)));
        }
        t.commit();
        t.close();
        
    }
}

And then you may call it like so:

1
ShapeToSdo SHPSDO = new ShapeToSdo("C:\\myfiles\\myshapefile.shp");



POSTGIS (using Geotools)
First of all you need to include the PostGIS Plugin within your project.
If you are using maven add the following tag within your pom.xml file

<dependency>
  <groupId>org.geotools.jdbc</groupId>
  <artifactId>gt-jdbc-postgis</artifactId>
  <version>13.0</version>
  <type>jar</type>
</dependency>

Then create a java class and name it ShapeToPostGIS as follows:


/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gis.openfreegis.rdbms;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFinder;
import org.geotools.data.FeatureSource;
import org.geotools.data.FeatureStore;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.referencing.CRS;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.ReferenceIdentifier;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

/**
 *
 * @author pt
 */
public class ShapeToPostGIS {
    public ShapeToPostGIS () throws FactoryException, MalformedURLException, IOException, ClassNotFoundException, SQLException {
    String shapeFileLoc = "C:\\various_tests\\myfile.shp"; //location of the shapefile
    String postGISTblName = "MYSHAPETABLE";//name to give to the newly created table 
    String shapeEPSG = "EPSG:2100";//the epsg to use if not found from shpefile
        try {

            // shapefile loader
            Map<Object,Serializable> shapeParams = new HashMap<Object,Serializable>();
            shapeParams.put("url", new File(shapeFileLoc).toURL());
            shapeParams.put( "charset", "ISO-8859-7" );//for greek chars
            DataStore shapeDataStore = DataStoreFinder.getDataStore(shapeParams);       

            // feature type
            String typeName = shapeDataStore.getTypeNames()[0];
            FeatureSource<SimpleFeatureType,SimpleFeature> featSource = shapeDataStore.getFeatureSource(typeName);
            FeatureCollection<SimpleFeatureType,SimpleFeature> featSrcCollection = featSource.getFeatures();
            SimpleFeatureType ft = shapeDataStore.getSchema(typeName);

            // feature type copy to set the new name
            SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
            builder.setName(postGISTblName);
            builder.setAttributes(ft.getAttributeDescriptors());
            builder.setCRS(ft.getCoordinateReferenceSystem());

            SimpleFeatureType newSchema = builder.buildFeatureType();

            // management of the projection system
            CoordinateReferenceSystem crs = ft.getCoordinateReferenceSystem();

            // test of the CRS based on the .prj file
            Integer crsCode = CRS.lookupEpsgCode(crs, true);

            Set<ReferenceIdentifier> refIds = ft.getCoordinateReferenceSystem().getIdentifiers();
            if ( ( (refIds == null) || (refIds.isEmpty() ) ) && (crsCode == null) ) {
                CoordinateReferenceSystem crsEpsg = CRS.decode(shapeEPSG);
                newSchema = SimpleFeatureTypeBuilder.retype(newSchema,crsEpsg);
            }

            Map postGISParams = new HashMap<String,Object>();
            postGISParams.put("dbtype", "postgis");         //must be postgis
            postGISParams.put("host", "localhost");         //the name or ip address of the machine running PostGIS
            postGISParams.put("port",5444);                 //the port that PostGIS is running on (generally 5432)
            postGISParams.put("database", "gisapps");       //the name of the database to connect to.
            postGISParams.put("user", "gis-user");          //the user to connect with
            postGISParams.put("passwd", "gis-user-pwd");    //the password of the user.
            postGISParams.put("schema", "myschema");        //the schema of the database
            postGISParams.put("create spatial index", Boolean.TRUE);
            DataStore dataStore = null;
            try {
            // storage in PostGIS
            dataStore = DataStoreFinder.getDataStore(postGISParams);
            } catch (Exception e){
            System.out.println("problem with datastore:"+e);
            }
           
            if (dataStore == null) {
             System.out.println("ERROR:dataStore is null");
            } 
            
            dataStore.createSchema(newSchema);
            FeatureStore<SimpleFeatureType,SimpleFeature> featStore = (FeatureStore<SimpleFeatureType,SimpleFeature>)dataStore.getFeatureSource(postGISTblName);
            featStore.addFeatures(featSrcCollection);
           

        } catch (IOException e) {
            System.out.println("ERROR:"+e);
        }

       System.out.println("Perfect, works as a charm!!!!!");

}
}

Finally, to call your class just create a new class and call:

ShapeToPostGIS SHPTOPOSTGIS = new ShapeToPostGIS();

Urban Growth Lab - UGLab

Proud to release a first version of the UGLab project .  UGLab is a python open source project capable to execute Urban Growth predictions f...