// *********************************************************************************** // $Source: /home/cvsroot/Esri2NodusPlugin/src/org/fucam/gtm/nodus/plugins/EsriImport.java,v $ // $RCSfile: EsriImport.java,v $ // $Revision: 1.2 $ // $Date: 2005/11/11 15:29:09 $ // $Author: jourquin $ // *********************************************************************************** package org.fucam.gtm.nodus.plugins; import java.io.*; import java.net.*; import java.util.*; import javax.swing.*; import org.fucam.gtm.nodus.*; import org.fucam.gtm.nodus.database.dbf.*; import org.fucam.gtm.nodus.utils.*; import com.bbn.openmap.dataAccess.shape.*; import com.bbn.openmap.dataAccess.shape.input.*; import com.bbn.openmap.dataAccess.shape.output.*; import com.bbn.openmap.layer.util.*; import com.bbn.openmap.proj.*; import com.bbn.openmap.util.PropUtils; /** * *
Title: Nodus 5.0
*Description: Nodus offers the possibility to import generic ESRI (ArcInfo) files.
*
* - Polylines : The import process generates a point layer (ouputpoints) containing the origin and
* destination points of each polyline. Moreover, the database (.dbf) structure
* of the polyline layers is adapted to be compatible with the mandatory fields
* needed by Nodus. (num, style, org, dst, mode, means)
* - Points : Point layers can also be imported. In this case, only the .dbf structure is
* adapted (num, style, tranship). These poinst are NOT atached to any polyline.
*
* The user can control the way the esri objects are imported, giving a default style (0 by default), a default
* mode and means for the links (both 1 by default), the default transhipment status of the nodes (0 by default)
*
*
*
* Sample import file (must have a ".import" extension)
*
*
* inputdir=/home/jourquin/nodus5shp/esriimport/backup
* outputdir=/home/jourquin/nodus5shp/esriimport
*
* polyline1.layer=rdline
* polyline1.defstyle=9
* polyline1.defmode=4
* polyline1.defmeans=1
*
* polyline2.layer=rrline
* polyline2.defstyle=12
* polyline2.defmode=2
* polyline2.defmeans=1
*
* point1.layer=aepoint
* point1.defstyle=2
* point1.deftranship=1
*
* point2.layer=awscitie
* point2.defstyle=10
* point2.deftranship=0
*
* outputpoints.layer=nodes
* outputpoints.defstyle=5
* outputpoints.deftranship=1
*
Copyright : Copyright (c) 2004
*Société : FUCaM-GTM
* @author Bart Jourquin * @version 1.0 */ public class EsriImport implements ShapeConstants { HashMap pointsHashMap = new HashMap(); String inputDir, outputDir, outputPoints; int defLinkStyle, defNodeStyle, defMode, defMeans, defTranship, defSpeed, defCapacity; static int nodeNum = 0; static int linkNum = 0; NodusMainFrame nodusMainFrame; /** * Only a reference to the NodusMainFrame is needed. Informatio will be further gathered * from the project. * @param frame NodusMainFrame */ public EsriImport(NodusMainFrame frame) { nodusMainFrame = frame; // Main import routine // Open a impport project file (is a properties file with a .import extension) JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileFilter(new NodusFileFilter(NodusC.TYPE_IMPORT, "Nodus import project files")); int returnVal = fileChooser.showOpenDialog(null); if (returnVal != JFileChooser.APPROVE_OPTION) { return; } Properties p = new Properties(); try { p.load(new FileInputStream(fileChooser.getSelectedFile().getCanonicalPath())); } catch (IOException ex) { JOptionPane.showMessageDialog(null, ex.toString(), NodusC.APPNAME, JOptionPane.ERROR_MESSAGE); return; } // Get mandatory information inputDir = p.getProperty(NodusC.PROP_INPUT_DIR, null); outputDir = p.getProperty(NodusC.PROP_OUTPUT_DIR, null); outputPoints = p.getProperty(NodusC.PROP_OUPUT_POINTS + NodusC.PROP_DOTLAYER, NodusC.IMPORTED_POINTS_DEFNAME); if (inputDir == null) { JOptionPane.showMessageDialog(nodusMainFrame, "\"" + NodusC.PROP_INPUT_DIR + "\" property missing", NodusC.APPNAME, JOptionPane.ERROR_MESSAGE); return; } if (outputDir == null) { JOptionPane.showMessageDialog(nodusMainFrame, "\"" + NodusC.PROP_OUTPUT_DIR + "\" property missing", NodusC.APPNAME, JOptionPane.ERROR_MESSAGE); return; } if (inputDir.compareTo(outputDir) == 0) { JOptionPane.showMessageDialog(nodusMainFrame, "OutputDir must be different from InputDir", NodusC.APPNAME, JOptionPane.ERROR_MESSAGE); return; } if (!inputDir.endsWith("/")) { inputDir += "/"; } if (!outputDir.endsWith("/")) { outputDir += "/"; } defNodeStyle = PropUtils.intFromProperties(p, NodusC.PROP_OUPUT_POINTS + NodusC.PROP_DOTDEFSTYLE, 0); defTranship = PropUtils.intFromProperties(p, NodusC.PROP_OUPUT_POINTS + NodusC.PROP_DOTDEFTRANSHIP, 0); nodusMainFrame.setBusy(true); // Import all the polyline layers int index = 1; while (true) { // Get info for layer 'index' String fileName = p.getProperty(NodusC.PROP_POLYLINE + index + NodusC.PROP_DOTLAYER, null); if (fileName == null) { break; } // Get defaults for style, mode and means defLinkStyle = PropUtils.intFromProperties(p, NodusC.PROP_POLYLINE + index + NodusC.PROP_DOTDEFSTYLE, 0); defMode = PropUtils.intFromProperties(p, NodusC.PROP_POLYLINE + index + NodusC.PROP_DOTDEFMODE, 1); defMeans = PropUtils.intFromProperties(p, NodusC.PROP_POLYLINE + index + NodusC.PROP_DOTDEFMEANS, 1); defSpeed = PropUtils.intFromProperties(p, NodusC.PROP_POLYLINE + index + NodusC.PROP_DOTDEFSPEED, 1); defCapacity = PropUtils.intFromProperties(p, NodusC.PROP_POLYLINE + index + NodusC.PROP_DOTDEFCAPACITY, 1); File f = new File(inputDir + fileName + NodusC.TYPE_SHP); if (!f.exists()) { JOptionPane.showMessageDialog(null, inputDir + fileName + NodusC.TYPE_SHP + " not found.", NodusC.APPNAME, JOptionPane.ERROR_MESSAGE); nodusMainFrame.setText(""); return; } boolean b = generateEsriPoints(fileName); if (!b) { nodusMainFrame.setBusy(false); nodusMainFrame.setText(""); return; } index++; } EsriPointList pointList = getPointList(); if (pointList != null) { boolean b = saveEsriPoints(pointList); if (!b) { nodusMainFrame.setBusy(false); nodusMainFrame.setText(""); return; } } // Import all the point layers index = 1; while (true) { // Get info for layer 'index' String fileName = p.getProperty(NodusC.PROP_POINT + index + NodusC.PROP_DOTLAYER, null); if (fileName == null) { break; } // Get defaults for style, mode and means //defNodeStyle = LayerUtils.intFromProperties(p, PROP_POINT + index + PROP_DOTDEFSTYLE, 0); //defMode = LayerUtils.intFromProperties(p, PROP_POINT + index + PROP_DOTDEFMODE, 1); //defMeans = LayerUtils.intFromProperties(p, PROP_POINT + index + PROP_DOTDEFMEANS, 1); File f = new File(inputDir + fileName + NodusC.TYPE_SHP); if (!f.exists()) { JOptionPane.showMessageDialog(null, inputDir + fileName + NodusC.TYPE_SHP + " not found.", NodusC.APPNAME, JOptionPane.ERROR_MESSAGE); nodusMainFrame.setText(""); return; } boolean b = importEsriPoints(fileName); if (!b) { nodusMainFrame.setBusy(false); nodusMainFrame.setText(""); return; } index++; } nodusMainFrame.setBusy(false); nodusMainFrame.setText(""); JOptionPane.showMessageDialog(null, "Nodus compatible layers successfully created", NodusC.APPNAME, JOptionPane.PLAIN_MESSAGE); } /** * Convenience function that returns the EsriGraphicList for a give shp/shx files pair. * @param shp URL * @param shx URL * @return EsriGraphicList */ EsriGraphicList getGeometry(URL shp, URL shx) { return EsriGraphicList.getEsriGraphicList(shp, shx, null, null); } /** * Generates the end points of the polylines (in order to create the "nodes" layers needed * by Nodus. * @param fileName String * @return boolean */ boolean generateEsriPoints(String fileName) { nodusMainFrame.setText("Importing " + fileName + "..."); String shp = inputDir + fileName + NodusC.TYPE_SHP; String shx = inputDir + fileName + NodusC.TYPE_SHX; // Read the shapes in a list EsriGraphicList list = null; DBFWriter dbfOutput; DBFReader dbfInput; try { // Only polylines can be imported ShpInputStream pis = new ShpInputStream(new FileInputStream(shp)); if (pis.readHeader() != SHAPE_TYPE_POLYLINE) { JOptionPane.showMessageDialog(null, shp + " is not a valid POLYLINE shapefile", NodusC.APPNAME, JOptionPane.ERROR_MESSAGE); return false; } // Read the shapes File shpf = new File(shp); File shxf = new File(shx); list = getGeometry(shpf.toURL(), shxf.toURL()); if (list == null) { return false; } // The shapes must be copied in outputdir... FileUtils.copyFile(shp, outputDir + fileName + NodusC.TYPE_SHP); FileUtils.copyFile(shx, outputDir + fileName + NodusC.TYPE_SHX); // The structure of the dbf file associated with this polyline must be adapted // to meet the Nodus specs (num, style, from, to, mode, means). The existant // fields are added to this mandatory structure // 1. Open the existant dbf file dbfInput = new DBFReader(inputDir + fileName + NodusC.TYPE_DBF); // 2. Create the new dbf file with mandatory fields and existant fields int nbFields = NodusC.NB_LINKS_MANDATORY_FIELDS + dbfInput.getFieldCount(); JDBField field[] = new JDBField[nbFields]; Object o[] = new Object[nbFields]; for (int i = 0; i < NodusC.NB_LINKS_MANDATORY_FIELDS; i++) { field[i] = new JDBField(NodusC.LINKS_MANDATORY_NAMES[i], NodusC.LINKS_MANDATORY_TYPES[i], NodusC.LINKS_MANDATORY_LENGTHS[i], NodusC.LINKS_MANDATORY_DECIMAL_COUNTS[i]); } for (int i = 0; i < dbfInput.getFieldCount(); i++) { field[NodusC.NB_LINKS_MANDATORY_FIELDS + i] = dbfInput.getField(i); } dbfOutput = new DBFWriter(outputDir + fileName + NodusC.TYPE_DBF, field); // Iterate through the list to find and store unique nodes into hash table Iterator it = list.iterator(); while (it.hasNext()) { // Get the polyline EsriPolyline epl = (EsriPolyline) it.next(); int org, dst; // Find the coordinates of its end nodes // Get the lat/lon and transform in degrees float pts[] = epl.getLatLonArray(); for (int k = 0; k < pts.length; k++) { pts[k] = ProjMath.radToDeg(pts[k]); } // Build a key from the lat/lon pairs and store into hash table // 1) Origin node Float key = new Float(1000 * pts[0] + pts[1]); EsriPoint ep = (EsriPoint) pointsHashMap.get(key); if (ep == null) { nodeNum++; org = nodeNum; ep = new EsriPoint(pts[0], pts[1]); ep.setAppObject(new NodeData(nodeNum)); pointsHashMap.put(key, ep); } else { NodeData nd = (NodeData) ep.getAppObject(); org = nd.getNum(); } // 2) Destination node key = new Float(1000 * pts[pts.length - 2] + pts[pts.length - 1]); ep = (EsriPoint) pointsHashMap.get(key); if (ep == null) { nodeNum++; dst = nodeNum; ep = new EsriPoint(pts[pts.length - 2], pts[pts.length - 1]); ep.setAppObject(new NodeData(nodeNum)); pointsHashMap.put(key, ep); } else { NodeData nd = (NodeData) ep.getAppObject(); dst = nd.getNum(); } // Now update the associated dbf file Object oold[] = dbfInput.nextRecord(); o[NodusC.DBF_IDX_NUM] = new Integer(++linkNum); o[NodusC.DBF_IDX_STYLE] = new Integer(defLinkStyle); o[NodusC.DBF_IDX_NODE1] = new Integer(org); o[NodusC.DBF_IDX_NODE2] = new Integer(dst); o[NodusC.DBF_IDX_MODE] = new Integer(defMode); o[NodusC.DBF_IDX_MEANS] = new Integer(defMeans); o[NodusC.DBF_IDX_SPEED] = new Double(defSpeed); o[NodusC.DBF_IDX_CAPACITY] = new Double(defCapacity); for (int i = 0; i < oold.length; i++) { o[NodusC.NB_LINKS_MANDATORY_FIELDS + i] = oold[i]; } dbfOutput.addRecord(o); } // end of list iteration dbfOutput.close(); } catch (Exception ex) { JOptionPane.showMessageDialog(null, ex.toString(), NodusC.APPNAME, JOptionPane.ERROR_MESSAGE); return false; } return true; } /** * Imports Esri points and modify the .dbf file to be Nodus compatible (mandatory fields) * @param fileName String * @return boolean */ boolean importEsriPoints(String fileName) { nodusMainFrame.setText("Importing " + fileName + "..."); String shp = inputDir + fileName + NodusC.TYPE_SHP; String shx = inputDir + fileName + NodusC.TYPE_SHX; DBFWriter dbfOutput; DBFReader dbfInput; try { // Only points can be imported ShpInputStream pis = new ShpInputStream(new FileInputStream(shp)); if (pis.readHeader() != SHAPE_TYPE_POINT) { JOptionPane.showMessageDialog(null, shp + " is not a valid POINT shapefile", NodusC.APPNAME, JOptionPane.ERROR_MESSAGE); return false; } // The shapes must be copied in outputdir... FileUtils.copyFile(shp, outputDir + fileName + NodusC.TYPE_SHP); FileUtils.copyFile(shx, outputDir + fileName + NodusC.TYPE_SHX); // The structure of the dbf file associated with this point file must be adapted // to meet the Nodus specs (num, style, tranship). The existant // fields are added to this mandatory structure // 1. Open the existant dbf file dbfInput = new DBFReader(inputDir + fileName + NodusC.TYPE_DBF); // System.out.println(InputDir + fileName + TYPEdbf); // 2. Create the new dbf file with mandatory fields and existant fields int nbFields = NodusC.NB_NODES_MANDATORY_FIELDS + dbfInput.getFieldCount(); JDBField field[] = new JDBField[nbFields]; Object o[] = new Object[nbFields]; for (int i = 0; i < NodusC.NB_NODES_MANDATORY_FIELDS; i++) { field[i] = new JDBField(NodusC.NODES_MANDATORY_NAMES[i], NodusC.NODES_MANDATORY_TYPES[i], NodusC.NODES_MANDATORY_LENGTHS[i], NodusC.NODES_MANDATORY_DECIMAL_COUNTS[i]); } for (int i = 0; i < dbfInput.getFieldCount(); i++) { field[NodusC.NB_NODES_MANDATORY_FIELDS + i] = dbfInput.getField(i); } dbfOutput = new DBFWriter(outputDir + fileName + NodusC.TYPE_DBF, field); //System.out.println(OutputDir + fileName + TYPEdbf); while (dbfInput.hasNextRecord()) { // Now update the associated dbf file Object oold[] = dbfInput.nextRecord(); o[NodusC.DBF_IDX_NUM] = new Integer(++nodeNum); o[NodusC.DBF_IDX_STYLE] = new Integer(defNodeStyle); o[NodusC.DBF_IDX_TRANSHIP] = new Integer(defTranship); for (int i = 0; i < oold.length; i++) { o[NodusC.NB_NODES_MANDATORY_FIELDS + i] = oold[i]; } dbfOutput.addRecord(o); } dbfOutput.close(); } catch (Exception ex) { JOptionPane.showMessageDialog(null, ex.toString(), NodusC.APPNAME, JOptionPane.ERROR_MESSAGE); return false; } return true; } /** * Returns a list that contains the points hold by the different node layers * @return EsriPointList */ EsriPointList getPointList() { EsriPointList epl = new EsriPointList(); Iterator it = pointsHashMap.values().iterator(); while (it.hasNext()) { EsriPoint ep = (EsriPoint) it.next(); epl.add(ep); } return epl; } /** * Save a point list in Esri format (including .dbf file) * @param epl EsriPointList * @return boolean */ boolean saveEsriPoints(EsriPointList epl) { // Don't save empty lists if (epl.size() == 0) { return false; } // Create default dbf file DBFWriter dbf = null; JDBField field[] = new JDBField[NodusC.NB_NODES_MANDATORY_FIELDS]; Object record[] = new Object[NodusC.NB_NODES_MANDATORY_FIELDS]; try { for (int i = 0; i < NodusC.NB_NODES_MANDATORY_FIELDS; i++) { field[i] = new JDBField(NodusC.NODES_MANDATORY_NAMES[i], NodusC.NODES_MANDATORY_TYPES[i], NodusC.NODES_MANDATORY_LENGTHS[i], NodusC.NODES_MANDATORY_DECIMAL_COUNTS[i]); } dbf = new DBFWriter(outputDir + outputPoints + NodusC.TYPE_DBF, field); // Fill the table Iterator it = epl.iterator(); while (it.hasNext()) { EsriPoint ep = (EsriPoint) it.next(); NodeData nd = (NodeData) ep.getAppObject(); record[NodusC.DBF_IDX_NUM] = new Integer(nd.getNum()); record[NodusC.DBF_IDX_STYLE] = new Integer(defNodeStyle); record[NodusC.DBF_IDX_TRANSHIP] = new Integer(defTranship); dbf.addRecord(record); } dbf.close(); } catch (JDBFException ex) { JOptionPane.showMessageDialog(null, ex.toString(), NodusC.APPNAME, JOptionPane.ERROR_MESSAGE); return false; } // Save the generated points in an Esri file String filePath = outputDir + outputPoints; File shpFile = new File(filePath + NodusC.TYPE_SHP); File shxFile = new File(filePath + NodusC.TYPE_SHX); try { ShpOutputStream pos = new ShpOutputStream(new FileOutputStream( shpFile)); int[][] indexData = pos.writeGeometry(epl); ShxOutputStream xos = new ShxOutputStream(new FileOutputStream( shxFile)); xos.writeIndex(indexData, epl.getType()); } catch (IOException ex) { JOptionPane.showMessageDialog(null, ex.toString(), NodusC.APPNAME, JOptionPane.ERROR_MESSAGE); return false; } return true; } }