Monday, November 4, 2019

Convert Oracle ResultSet to GeoJson file.

This  is  a java approach to convert an oracle java resultset to a single GeoJson file.

Before we go through the code example. Lets see the prerequisites.
(these are copy-paste from my other post --> sdo2gml)
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.

The following geotools jars shall be referenced to your project. (geotools version 13)
-->  gt-xsd-filter
-->  gt-jdbc-oracle
-->  gt-data
-->  gt-shapefile
So lets start coding.

Fisrt we need to create a class to obtain a jdbc connection to oracle database.
class accepts 5 parameters (ip, port, dbname, user, pass) I shall give you an example at the end of this post. Lets go through the code of our first classs
(these are copy-paste from my other post --> sdo2gml)
GetOraConnection class CODE
package gis.openfreegis.rdbms;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 *
 * @author pt
 */
public class GetOraConnection {


    public static Connection main (String ip, String port, String db, String user, String pass)
            throws InstantiationException, IllegalAccessException{
    try {
         Class.forName ("oracle.jdbc.OracleDriver").newInstance();
        } catch (ClassNotFoundException e) {
            System.out.println("Oracle JDBC Driver missing.");
            e.printStackTrace();
        }
        System.out.println("Oracle JDBC Driver Found and Registered.");
        Connection connection = null;
        try {
            System.out.println("jdbc:oracle:thin:@"+ip+":"+port+":"+db);
            connection = DriverManager.getConnection(
                                "jdbc:oracle:thin:@"+ip+":"+port+":"+db,
                    user,
                    pass);
        
        } catch (SQLException e) {

                System.out.println("Connection Failed!");
                e.printStackTrace();
        }

        if (connection != null) {
                System.out.println("Connection succeed!");
        } else {
                System.out.println("Failed to create connection!");
        }
        return connection;
    }
}

Once we have this class we may create the class that does the job.
RsetToGeoJSON  class CODE



 

/**
 * A class to support the convertion of an JAVA oracle result set to a single GeoJson File. 
 * @author p_tsagkis 
 * 29/10/2019
 */


package gis.openfreegis.rdbms;

import com.vividsolutions.jts.geom.Geometry;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import oracle.jdbc.OracleConnection;
import oracle.sql.STRUCT;
import org.geotools.data.oracle.sdo.GeometryConverter;
import org.geotools.geojson.geom.GeometryJSON;

public class RsetToGeoJSON {
    private static String geoJsonStr; 
    //Constructor
    public RsetToGeoJSON(ResultSet rset, Connection con, String geoJSONSRID) {
        ArrayList<String> featsSts = new ArrayList<>();
        int numOfColumns;

        try {
            numOfColumns = rset.getMetaData().getColumnCount();  
            while (rset.next()) {
                ArrayList<HashMap<String, String>> attrs = new ArrayList<>();
                HashMap<String, String> currAttrs = new HashMap<>();
                Geometry jtsGeom = null;
                    for (int i=1;i<numOfColumns+1;i++){
                        String colName = rset.getMetaData().getColumnName(i);
                        String type = rset.getMetaData().getColumnTypeName(i);
                        String value = rset.getString(rset.getMetaData().getColumnName(i));
                       
                        if (type.equals("MDSYS.SDO_GEOMETRY")){
                            
                           GeometryConverter geomCon = new GeometryConverter((OracleConnection) con);
                           jtsGeom = geomCon.asGeometry((STRUCT) rset.getObject(i));
                           
                        } else {
                           currAttrs.put(colName, value);
                           attrs.add(currAttrs);
                        }
                    }   
                 String rowFeatureStrr = createFeatureObject(jtsGeom,attrs);
                 featsSts.add(rowFeatureStrr);
                }
                generateFinalGeoJSON(featsSts,geoJSONSRID);  
        } catch(SQLException ex) {
            Logger.getLogger(RsetToGeoJSON.class.getName()).log(Level.SEVERE, null, ex);
        } 
    }
    

    /**
     * getter
     * @return 
     */
    public String getGeoJsonStr(){
    return geoJsonStr;
    }
    
   /**
    * Save geoJsonStr to geojson file in supplied directory (local disk)
    * @param filepath
    */
   public void writeToGeoJsonFile(String filepath){     
        try (BufferedWriter bw = new BufferedWriter(new FileWriter(new File(filepath)))) {
            bw.write(geoJsonStr);
            bw.close();
        }  catch (FileNotFoundException ex) { 
             Logger.getLogger(RsetToGeoJSON.class.getName()).log(Level.SEVERE, null, ex);
         } catch (IOException ex) {
            Logger.getLogger(RsetToGeoJSON.class.getName()).log(Level.SEVERE, null, ex);
        }
   }
    
   
   
   
     //******************Private  methods this point forward ********************// 
   
    /**
     * Put them all together.
     * @param feats 
     * @params SRID getted from first geometry parsed
     */
    private void generateFinalGeoJSON(ArrayList<String> feats, String srid){
        StringBuilder finjson = new StringBuilder();
        finjson.append("{");
        finjson.append("\"type\": \"FeatureCollection\",");
        finjson.append("   \"crs\": {");
        finjson.append("     \"type\": \"name\",");
        finjson.append("     \"properties\": {");
        finjson.append("       \"name\": \"").append(srid).append("\"");
        finjson.append("     }");
        finjson.append("   }, ");
        finjson.append("\"features\":[");
          for (int i=0;i<feats.size();i++) {     
                if (i<feats.size()-1){
                   finjson.append(feats.get(i)).append(",");
                } else {
                finjson.append(feats.get(i)).append("]");
                }
          }
        finjson.append("}");
        //trim spaces and new lines
        geoJsonStr = finjson.toString().replaceAll("[\\n\\t ]", "");  
        
    }
    
    /**
     * Construct the feature object. 
     * Put together geometry and attributes into a single feature
     * @param geom (JGeometry)
     * @param as (ArrayList<HashMap<String, String>>)
     * @return 
     */
    private String createFeatureObject(Geometry geom, ArrayList<HashMap<String, String>> as) {
        String propsStr = propsFromAttrs(as);
        StringBuilder featjson = new StringBuilder();
        featjson.append("{");
        featjson.append("\"type\": \"Feature\",");
        featjson.append("\"geometry\":");
        featjson.append(geoJsonGeomFromJGeom(geom));
        featjson.append(",");
        featjson.append(propsStr);
        featjson.append("}");
        return featjson.toString();
    }
   
    /**
     * Create the geojson representation string for the supplied jts geometry
     * @Geometry geom Geometry JTS geometry
     * @return  String
     */
   private String geoJsonGeomFromJGeom(Geometry geom){
   String gJson = "";
        try {  
            GeometryJSON gjson = new GeometryJSON();
            StringWriter writer = new StringWriter();
            gjson.write(geom, writer);
            gJson = writer.toString();        
        } catch (IOException ex) {
            Logger.getLogger(RsetToGeoJSON.class.getName()).log(Level.SEVERE, null, ex);
        }     
    return gJson;    
   }
   
   /**
    * Pass a hashmap for attributes like key:value (column name: value) and get back the geojson representation 
    * @param as
    * @return String
    */
   private String propsFromAttrs( ArrayList<HashMap<String, String>> as){
       StringBuilder porpertiesStr = new StringBuilder();
       porpertiesStr.append("\"properties\":{");
       
       for ( int i=0;i<as.size();i++){
           System.out.println("i===="+i);
           HashMap<String, String> curEntry = as.get(i);
           porpertiesStr.append("\"");
           porpertiesStr.append(curEntry.keySet().toArray()[i]);
           porpertiesStr.append("\":\"");
           porpertiesStr.append(curEntry.get((String) curEntry.keySet().toArray()[i]));
           porpertiesStr.append("\"");
           if (i<as.size()-1){
               porpertiesStr.append(",");
           } else {
               porpertiesStr.append("}");
           }
       }
   return porpertiesStr.toString();
   }   
   
   
   
}



And finally we need to call our new method passing a resultset, the connection and the SRID code



    String dbip = "xxx.xx.x.xxx";
    String dbport = "1521";
    String dbname = "orcl";
    String dbuser = "GEO";
    String dbpass = "GEO"; 
    
    
    
     String sqlquery = "select * from geotable";
       try {
           Connection con = GetOraConnection.main(dbip,dbport, dbname, dbuser, dbpass);
           if (con !=null){
           Statement stmt = null;
            try {
                stmt = con.createStatement ();
            } catch (SQLException e) {
                System.out.println("ERROR:"+e.getMessage());
            }
            ResultSet rset = null;
            try {
                System.out.println("start query execution ==== "+sqlquery);
                rset = stmt.executeQuery (sqlquery);
            } catch (SQLException e) {
                System.out.println("ERROR:"+e.getMessage());
            }
            if( rset != null )
            {
              System.out.println("start geojson conversion");  
           
          
          //NOW TEST THE GEOJSON]
          RsetToGeoJSON geoJsonConv = new RsetToGeoJSON(rset,con, "EPSG:2100");
          String geoJson = geoJsonConv.getGeoJsonStr();
          System.out.println("geoJson====="+geoJson);
          geoJsonConv.writeToGeoJsonFile("D:\\work\\rsetgeom.geojson");
          
          

         
            stmt.close();
            rset.close();
            con.close();
            }
          
           }
       } catch (InstantiationException ex) {
           Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
       } catch (IllegalAccessException ex) {
           Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
       }
   
   

Tuesday, June 4, 2019

Measure Fields , Parcels, Paths etc using smart phone GPS sensor. GaiaFieldTracker (Google play store)

Here is a mobile application (Geia Field Tracker) I have recently developed and uploaded on Google play store. Unfortunately, the app is developed for the private company I am working for, so code is not available but app is still free and contains zero ads.
Users can measure fields , parcels or even paths by using the smartphone's GPS sensor. User is able to save the measurement on the device and manage it from the application.
User can also attach camera shots to any path.
Measurements may be modified using the app build in tools for editing functionality.
App supports various projections and also offers a build in tool to execute projection transformations among the following projection EPSG codes

-- WGS84 (World - 4326)
-- EGSA87 (Greece - 2100)
-- ED50/UTM zone 30N (Spain - 23030)
-- CGRS93 / Cyprus Local (Cyprus - 6312)
-- WGS 84/Pseudo-Mercator (World - 3857)
-- US National Atlas Equal Area (US - 2163)
-- OSGB 1936/Brit. National (UK - 27700)
-- Amersfoort/RD New (Holland - 28992)
-- ETRS89/LAEA Europe (EU - 3035)

Finally, measurement may be sent , either as a kml file by email including camera pictures and a csv file containing measure coordinates or directly at the gaia service.

App may be used by anyone who wants to measure plots, fileds, parcels, paths etc regardless of whether they are subscribers to gaia services or not.


Some screen shots to get the idea. .
No Ads, No Fees !!!!!!! Enjoy.




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...