package uk.ac.leeds.ccg.andyt.misc; import java.awt.geom.Point2D; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.StreamTokenizer; import java.util.Vector; /** * @author A.G.D.Turner@leeds.ac.uk * * This program is for converting data from a GSHHS ascii format to an ESRI ArcGIS ungenerate ascii format. * A description of how the program works is given in: * Andy Nelson , Andy Turner (2004) 'Processing Global Self-consistent Hierarchical High Resolution Shoreline * Data Version 1.3 Into ESRI ArcGIS Vector And Raster Data.' CCG, School of Geography Working Paper, * December 2004. */ public class GSHHS2ArcGIS { /** Creates a new instance of DataConverter */ public GSHHS2ArcGIS() { } /** * @param args the command line arguments */ public static void main( String[] args ) { GSHHS2ArcGIS aGSHHS2ArcGIS = new GSHHS2ArcGIS(); aGSHHS2ArcGIS.run( args ); } public void run( String[] args ) { //asciiGSHHS2UngenerateArcInfo0( init( args ) ); //asciiGSHHS2UngenerateArcInfo1( init( args ) ); asciiGSHHS2UngenerateArcInfo2( init( args ) ); } /** * Initialisiation method for checking command line arguements and setting * defaults if arguments are not supplied correctly. */ public Object[] init( String[] args ) { Object[] initArgs = new Object[ 3 ]; // Defaults //File inputAsciiGSHHSFile = new File( "gshhs_f.dat" ); //File outputUngenerateArcInfoFile = new File( "gshhs_f.ungenerate" ); File inputAsciiGSHHSFile = new File( "C:/cygwin/home/geoagdt/gshhs/gshhs_1.3/SourceData/gshhs_f.dat" ); //File outputUngenerateArcInfoFile = new File( "C:/cygwin/home/geoagdt/gshhs/gshhs_1.3/gshhs_f2.ungenerate0" ); //File outputUngenerateArcInfoFile = new File( "C:/cygwin/home/geoagdt/gshhs/gshhs_1.3/gshhs_f2.ungenerate1" ); File outputUngenerateArcInfoFile = new File( "C:/cygwin/home/geoagdt/gshhs/gshhs_1.3/gshhs_f2.ungenerate2" ); initArgs[ 2 ] = new Double( 1.0d ); //initArgs[ 2 ] = new Double( 60.0d ); // Try using args try { File file = new File( args[ 0 ] ); if ( ! file.exists() ) { System.out.println( "Error opening file " + args[ 0 ] ); } else { inputAsciiGSHHSFile = file; } try { file = new File( args[ 1 ] ); if ( file.exists() ) { System.out.println( "Overwriting file " + args[ 1 ] ); } outputUngenerateArcInfoFile = file; } catch ( ArrayIndexOutOfBoundsException aoobe0 ) { outputUngenerateArcInfoFile = new File( inputAsciiGSHHSFile + ".ungenerate" ); } initArgs[ 2 ] = new Double( args[ 2 ] ); } catch ( Exception e0 ) { System.out.println( "Expected 3 arguments: The full path to the input file; The full path to the input file; A number to multiply input coordinates by."); System.out.println( "These were not supplied or the program will probably fail for another reason."); System.out.println( "Attempting to continue using some defaults." ); } try { StreamTokenizer streamTokenizer = new StreamTokenizer( new BufferedReader( new InputStreamReader( new FileInputStream( inputAsciiGSHHSFile ) ) ) ); streamTokenizer.eolIsSignificant( true ); initArgs[ 0 ] = streamTokenizer; initArgs[ 1 ] = new PrintWriter( new BufferedWriter( new OutputStreamWriter( new FileOutputStream( outputUngenerateArcInfoFile ) ) ) ); } catch ( IOException e0 ) { e0.printStackTrace(); } System.out.println( inputAsciiGSHHSFile + " " + outputUngenerateArcInfoFile + " " + initArgs[ 2 ] ); return initArgs; } /** * Conversion method to directly convert ASCII GSHHS data into an * Ungenerate ArcInfo data format. */ public void asciiGSHHS2UngenerateArcInfo0( Object[] args ) { // Initialisation StreamTokenizer streamTokenizer = ( StreamTokenizer ) args[ 0 ]; PrintWriter printWriter = ( PrintWriter ) args[ 1 ]; double units = ( ( Double ) args[ 2 ] ).doubleValue(); int token; //long counter = 0L; long id = 1L; boolean readx = true; double x = Double.NaN; try { token = streamTokenizer.nextToken(); // deal with first line while ( token != StreamTokenizer.TT_EOL ) { token = streamTokenizer.nextToken(); } token = streamTokenizer.nextToken(); printWriter.println( id ); while ( token != streamTokenizer.TT_EOF ) { switch ( streamTokenizer.ttype ) { case StreamTokenizer.TT_NUMBER : if ( readx ) { x = streamTokenizer.nval; readx = false; } else { printWriter.println( Double.toString( x * units ) + " " + Double.toString( streamTokenizer.nval * units ) ); readx = true; } break; case StreamTokenizer.TT_WORD : printWriter.println( "END" ); id ++; while ( token != StreamTokenizer.TT_EOL ) { token = streamTokenizer.nextToken(); } token = streamTokenizer.nextToken(); if ( token != StreamTokenizer.TT_EOF ) { printWriter.println("" + id); streamTokenizer.pushBack(); } break; } token = streamTokenizer.nextToken(); } printWriter.println( "END" ); printWriter.println( "END" ); } catch ( IOException e0 ) { e0.printStackTrace(); } printWriter.flush(); printWriter.close(); } /** * Converts formats and multiplies coordinates to change units */ public void asciiGSHHS2UngenerateArcInfo1( Object[] args ) { // Initialisation StreamTokenizer streamTokenizer = ( StreamTokenizer ) args[ 0 ]; PrintWriter printWriter = ( PrintWriter ) args[ 1 ]; double units = ( ( Double ) args[ 2 ] ).doubleValue(); int token; //long counter = 0L; long id = 1L; boolean readx = true; double x = Double.NaN; double xmin = Double.POSITIVE_INFINITY; double xmax = Double.NEGATIVE_INFINITY; Vector line = new Vector(); try { token = streamTokenizer.nextToken(); // deal with first line while ( token != StreamTokenizer.TT_EOL ) { token = streamTokenizer.nextToken(); } token = streamTokenizer.nextToken(); while ( token != streamTokenizer.TT_EOF ) { switch ( streamTokenizer.ttype ) { case StreamTokenizer.TT_NUMBER : if ( readx ) { x = streamTokenizer.nval; xmin = Math.min( xmin, x ); xmax = Math.max( xmax, x ); readx = false; } else { line.add( new Point2D.Double( x * units, streamTokenizer.nval * units ) ); readx = true; } break; case StreamTokenizer.TT_WORD : if ( xmax - xmin == 360.0d ) { writeAntarcticPolygon1( line, id, printWriter, xmin * units, xmax * units, units ); } else { writePolygon1( line, id, printWriter ); } xmin = Double.POSITIVE_INFINITY; xmax = Double.NEGATIVE_INFINITY; line = new Vector(); id ++; while ( token != StreamTokenizer.TT_EOL ) { token = streamTokenizer.nextToken(); } break; } token = streamTokenizer.nextToken(); } // write last line if ( xmax - xmin == 360.0d ) { writeAntarcticPolygon1( line, id, printWriter, xmin * units, xmax * units, units ); } else { writePolygon1( line, id, printWriter ); } printWriter.println( "END" ); } catch ( IOException e0 ) { e0.printStackTrace(); } printWriter.flush(); printWriter.close(); } /** * Method */ public void writePolygon1( Vector line, long id, PrintWriter printWriter ) { //System.out.println( Long.toString( id ) ); printWriter.println( Long.toString( id ) ); for ( int i = 0; i < line.size(); i++ ) { writePoint( printWriter, ( Point2D.Double ) line.elementAt( i ) ); } printWriter.println( "END" ); } public void writeAntarcticPolygon1( Vector line, long id, PrintWriter printWriter, double xmin, double xmax, double units ) { System.out.println( "Antarctic Polygon ID " + Long.toString( id ) ); printWriter.println( Long.toString( id ) ); Point2D.Double point; int xminCounter = 0; int xmaxCounter = 0; for ( int i = 0; i < line.size() - 1; i++ ) { point = ( Point2D.Double ) line.elementAt( i ); //if ( i == 0 || i == 1 || i == 3 || i == line.size() - 3 || i == line.size() - 2 || i == line.size() - 1 ) { // System.out.println( point.getX() + " " + point.getY() ); //} if ( point.getX() == xmax ) { // Check xmaxCounter ++; writePoint( printWriter, new Point2D.Double( xmin, -90.0d * units ) ); writePoint( printWriter, new Point2D.Double( xmax, -90.0d * units ) ); } writePoint( printWriter, point ); if ( point.getX() == xmin ) { // Check xminCounter ++; writePoint( printWriter, new Point2D.Double( xmin, -90.0d * units ) ); } } printWriter.println( "END" ); if ( xminCounter > 1 ) { System.out.println("Bug0 in writeAntarcticPolygon(Vector,long,PrintWriter,xmin,xmax)"); } if ( xmaxCounter > 1 ) { System.out.println("Bug1 in writeAntarcticPolygon(Vector,long,PrintWriter,xmin,xmax)"); } } /** * Converts formats and reprojects data from a geographic projection with * coordinates given in Decimal Degree (DD) units with: * -90 as the lowest line of latitude (y axis); * 90 as the highest line of latitude; and, * values of 360 as the rightmost line of longitude (x axis). * Input data are assumed to be in gshhs ascii format. * The output data are ArcInfo ungenerate file format. * The method has not been tested with handling lines that cross -90 or 90 * latitudes. */ public void asciiGSHHS2UngenerateArcInfo2( Object[] args ) { // Initialisation StreamTokenizer streamTokenizer = ( StreamTokenizer ) args[ 0 ]; PrintWriter printWriter = ( PrintWriter ) args[ 1 ]; double units = ( ( Double ) args[ 2 ] ).doubleValue(); int token; long counter = 0L; long id = 1L; boolean readx = true; double x = Double.NEGATIVE_INFINITY; double y = Double.NEGATIVE_INFINITY; double lastx = Double.NEGATIVE_INFINITY; double lasty = Double.NEGATIVE_INFINITY; double xmin = Double.POSITIVE_INFINITY; double xmax = Double.NEGATIVE_INFINITY; double xToWrite = Double.NEGATIVE_INFINITY; boolean firstPoint = true; String intersection = null; Vector points = new Vector(); Vector line0 = new Vector(); Vector line1 = new Vector(); Vector lines0 = new Vector(); Vector lines1 = new Vector(); boolean writeToLine0 = true; boolean longitude180CrossedAlready = false; try { token = streamTokenizer.nextToken(); // deal with first line while ( token != StreamTokenizer.TT_EOL ) { token = streamTokenizer.nextToken(); } token = streamTokenizer.nextToken(); while ( token != streamTokenizer.TT_EOF ) { switch ( streamTokenizer.ttype ) { case StreamTokenizer.TT_NUMBER : if ( readx ) { x = streamTokenizer.nval; xmin = Math.min( xmin, x ); xmax = Math.max( xmax, x ); if ( x > 180.0d ) { xToWrite = ( x - 360.0d ) * units; } else { xToWrite = x * units; } readx = false; } else { y = streamTokenizer.nval; points.add( new Point2D.Double( x, y ) ); if ( firstPoint ) { // Add to polygon0 line0.add( new Point2D.Double( xToWrite, y * units ) ); firstPoint = false; } else { boolean longitude180Crossed = longitude180Crossed2( writeToLine0, line0, line1, x, lastx, units ); //boolean longitude180Crossed = longitude180Crossed2( x, lastx ); if ( longitude180Crossed ) { double yIntersect = getYIntersect2( x, y, lastx, lasty ); double xIntersect = getXIntersect2( x, lastx ); // If longitude180CrossedAlready: // add intersect point to line1; // add line1 to lines1; // reinitialise line1; // add intersect point to line0 changing sign; // add point to line0; if ( longitude180CrossedAlready ) { //line1.add( new Point2D.Double( xIntersect * units, yIntersect * units ) ); line1.add( new Point2D.Double( xIntersect * units * -1.0d, yIntersect * units ) ); lines1.add( copyToArray( line1 ) ); line1 = new Vector(); // Add intersection point to polygon0 flipping sign //line0.add( new Point2D.Double( xIntersect * units * -1.0d, yIntersect * units ) ); line0.add( new Point2D.Double( xIntersect * units, yIntersect * units ) ); line0.add( new Point2D.Double( xToWrite, y * units ) ); longitude180CrossedAlready = false; writeToLine0 = true; } else { //line0.add( new Point2D.Double( xIntersect * units, yIntersect * units ) ); line0.add( new Point2D.Double( xIntersect * units * -1.0d, yIntersect * units ) ); lines0.add( copyToArray( line0 ) ); line0 = new Vector(); // Add intersection point to polygon0 flipping sign //line1.add( new Point2D.Double( xIntersect * units * -1.0d, yIntersect * units ) ); line1.add( new Point2D.Double( xIntersect * units, yIntersect * units ) ); line1.add( new Point2D.Double( xToWrite, y * units ) ); longitude180CrossedAlready = true; writeToLine0 = false; } } else { if ( writeToLine0 ) { line0.add( new Point2D.Double( xToWrite, y * units ) ); } else { line1.add( new Point2D.Double( xToWrite, y * units ) ); } } } readx = true; lastx = x; lasty = y; } break; case StreamTokenizer.TT_WORD : lines0.add( copyToArray( line0 ) ); lines1.add( copyToArray( line1 ) ); if ( ( xmax - xmin == 360.0d ) && xmin == 0.0d ) { //System.out.println("This should be Antarctica coastline"); id = writeAntarcticPolygon2( points, id, printWriter, xmin, xmax, units ); } else { id = writePolygons2( lines0, lines1, id, printWriter, units ); } points = new Vector(); line0 = new Vector(); line1 = new Vector(); lines0 = new Vector(); lines1 = new Vector(); writeToLine0 = true; while ( token != StreamTokenizer.TT_EOL ) { token = streamTokenizer.nextToken(); } token = streamTokenizer.nextToken(); if ( token != StreamTokenizer.TT_EOF ) { streamTokenizer.pushBack(); } longitude180CrossedAlready = false; lastx = Double.NEGATIVE_INFINITY; lasty = Double.NEGATIVE_INFINITY; xmin = Double.POSITIVE_INFINITY; xmax = Double.NEGATIVE_INFINITY; firstPoint = true; break; } token = streamTokenizer.nextToken(); counter ++; } // Add final line if ( writeToLine0 ) { if ( line0.size() > 2 ) { lines0.add( copyToArray( line0 ) ); } } else { if ( line1.size() > 2 ) { lines1.add( copyToArray( line1 ) ); } } if ( xmax - xmin == 360.0d && xmin == 0.0d ) { //System.out.println("This should be Antarctica coastline"); id = writeAntarcticPolygon2( points, id, printWriter, xmin, xmax, units ); } else { id = writePolygons2( lines0, lines1, id, printWriter, units ); } // End printWriter.println( "END" ); //System.out.println( "END" ); } catch ( IOException e0 ) { e0.printStackTrace(); } printWriter.flush(); printWriter.close(); } /** * Returns true iff the 180.0d longitude line is crossed. * @param x a value of longitude * @param lastx the previous value of longitude */ public boolean longitude180Crossed2( double x, double lastx ) { if ( ( x < 180.0d && lastx > 180.0d ) || ( x > 180.0d && lastx < 180.0d ) ) { if ( lastx != Double.NEGATIVE_INFINITY ) { return true; } } return false; } /** * Returns true iff the 180.0d longitude line is crossed. * @param writeToLine0 indicates if line0 or line1 is to be used should the * last non180 x coordinate should be calculated * @param line0 a Vector containing points that may be used to calculate * the last non180x if necessary and writeToLine0 = true. * @param line1 a Vector containing points that may be used to calculate * the last non180x if necessary and writeToLine0 = false. * @param x a value of longitude * @param lastx the previous value of longitude */ public boolean longitude180Crossed2( boolean writeToLine0, Vector line0, Vector line1, double x, double lastx, double units ) { if ( lastx == Double.NEGATIVE_INFINITY ) { return false; } if ( lastx != 180.0d ) { if ( x == 180.0d ) { if ( lastx > 180.0d ) { return true; } return false; } else { return longitude180Crossed2( x, lastx ); } } else { if ( x < 180.0d ) { return false; } double lastNon180x; if ( writeToLine0 ) { lastNon180x = getLastNon180x( line0, units ) / units; } else { lastNon180x = getLastNon180x( line1, units ) / units; } if ( x == 180.0d ) { if ( lastNon180x > 180.0d ) { //System.out.println("x " + x + " lastNon180x " + lastNon180x); return true; } //System.out.println("x " + x + " lastNon180x " + lastNon180x); return false; } else { //System.out.println("x " + x + " lastNon180x " + lastNon180x); return longitude180Crossed2( x, lastNon180x ); } } } /** * Returns true iff the 180.0d longitude line is crossed. * @param points a Vector containing points that may be used to calculate * the last non180x if necessary. * @param x a value of longitude * @param lastx the previous value of longitude */ public boolean longitude180Crossed2( Vector points, double x, double lastx ) { if ( lastx == Double.NEGATIVE_INFINITY ) { return false; } if ( lastx != 180.0d ) { if ( x == 180.0d ) { if ( lastx > 180.0d ) { return true; } return false; } else { return longitude180Crossed2( x, lastx ); } } else { if ( x < 180.0d ) { return false; } double lastNon180x; lastNon180x = getLastNon180x( points ); if ( x == 180.0d ) { if ( lastNon180x > 180.0d ) { //System.out.println("x " + x + " lastNon180x " + lastNon180x); return true; } return false; } else { //System.out.println("x " + x + " lastNon180x " + lastNon180x); return longitude180Crossed2( x, lastNon180x ); } } } /** * Returns the last x coordinate in line that is not equal to 180.0d else * returns Double.NEGATIVE_INFINITY. */ public double getLastNon180x( Vector line ) { Point2D.Double point; double x; for ( int pointID = line.size() - 1; pointID >= 0; pointID -- ) { x = ( ( Point2D.Double ) line.elementAt( pointID ) ).getX(); if ( x != 180.0d ) { return x; } } return Double.NEGATIVE_INFINITY; } /** * Returns the lastmost x coordinate in line divided by units provided this * is not equal to 180.0d else returns Double.NEGATIVE_INFINITY. */ public double getLastNon180x( Vector line, double units ) { Point2D.Double point; double x; for ( int pointID = line.size() - 1; pointID >= 0; pointID -- ) { x = ( ( Point2D.Double ) line.elementAt( pointID ) ).getX() / units; if ( x != 180.0d ) { return x; } } return Double.NEGATIVE_INFINITY; } /** * Returns the YIntersect to be used in intersection. */ public double getYIntersect2( double x, double y, double lastx, double lasty ) { //if ( lastx == Double.NEGATIVE_INFINITY ) { // System.out.println( "Bug0 in getXIntersect2( x ( " + x + " ), lastx ( " + lastx + " ) )" ); //} if ( lastx == 180.0d ) { if ( x == 180.0d ) { return y; } return lasty; } if ( x == 180.0d ) { return y; } if ( x < 180.0d && lastx > 180.0d ) { if ( y == lasty ) { return y; } else { if ( y < lasty ) { double ydiff = ( ( lasty - y ) / ( lastx - x ) ) * ( lastx - 180.0d ); //System.out.println("Case 1"); return lasty - ydiff; } else { double ydiff = ( ( y - lasty ) / ( lastx - x ) ) * ( lastx - 180.0d ); //System.out.println("Case 2"); return lasty + ydiff; } } } else { if ( x > 180.0d && lastx < 180.0d ) { if ( y == lasty ) { return y; } else { if ( y < lasty ) { double ydiff = ( ( y - lasty ) / ( x - lastx ) ) * ( x - 180.0d ); //System.out.println("Case 3"); return y + ydiff; } else { double ydiff = ( ( y - lasty ) / ( x - lastx ) ) * ( 180.0d - lastx ); //System.out.println("Case 4"); return lasty + ydiff; } } } } System.out.println( "Bug1 in getYIntersect2( x ( " + x + " ), y ( " + y + " ), lastx ( " + lastx + " ), lasty ( " + lasty + " ) ) " ); return y; } /** * Returns the XIntersect to be used in intersection. */ public double getXIntersect2( double x, double lastx ) { //if ( lastx == Double.NEGATIVE_INFINITY ) { // System.out.println( "Bug0 in getXIntersect2( x ( " + x + " ), lastx ( " + lastx + " ) )" ); //} if ( x <= 180.0d && lastx >= 180.0d ) { return 180.0d; } if ( ( x >= 180.0d && lastx <= 180.0d ) ) { return -180.0d; } System.out.println( "Bug1 in getXIntersect2( x ( " + x + " ), lastx ( " + lastx + " ) )" ); return -180.0d; } /** * Writes out polygons */ public long writePolygons2( Vector lines0, Vector lines1, long id, PrintWriter printWriter, double units ) { Point2D.Double[] line; if ( lines0.size() > 1 && lines1.size() > 1 ) { System.out.println("Need to decide which are trunk and which are limbs!"); double maxy; double miny; double[] xdiff = new double[ lines0.size() + lines1.size() ]; int line0ID; Point2D.Double[] line0; double maxDiff = Double.MIN_VALUE; for ( line0ID = 0; line0ID < lines0.size(); line0ID ++ ) { line0 = ( Point2D.Double[] ) lines0.elementAt( line0ID ); maxy = Double.MIN_VALUE; miny = Double.MAX_VALUE; for ( int coordinateID = 0; coordinateID < line0.length; coordinateID ++ ) { if ( line0[ coordinateID ].getX() == 180.0d || line0[ coordinateID ].getX() == -180.0d ) { maxy = Math.max( maxy, line0[ coordinateID ].getY() ); miny = Math.min( miny, line0[ coordinateID ].getY() ); } } xdiff[ line0ID ] = maxy - miny; maxDiff = Math.max( maxDiff, xdiff[ line0ID ] ); } Point2D.Double[] line1; for ( int line1ID = 0; line1ID < lines1.size(); line1ID ++ ) { line1 = ( Point2D.Double[] ) lines1.elementAt( line1ID ); maxy = Double.MIN_VALUE; miny = Double.MAX_VALUE; for ( int coordinateID = 0; coordinateID < line1.length; coordinateID ++ ) { if ( line1[ coordinateID ].getX() == 180.0d || line1[ coordinateID ].getX() == -180.0d ) { maxy = Math.max( maxy, line1[ coordinateID ].getY() ); miny = Math.min( miny, line1[ coordinateID ].getY() ); } } xdiff[ line0ID + line1ID + 1 ] = maxy - miny; maxDiff = Math.max( maxDiff, xdiff[ line0ID + line1ID + 1 ] ); } int index = 0; for ( int lineID = 0; lineID < lines0.size() + lines1.size(); lineID ++ ) { if ( xdiff[ lineID ] == maxDiff ) { index = lineID; } } if ( index < lines0.size() ) { if ( lines0.size() > 0 ) { printWriter.println( Long.toString( id ) ); for ( int lineID = 0; lineID < lines0.size(); lineID ++ ) { line = ( Point2D.Double[] ) lines0.elementAt( lineID ); if ( line.length > 1 ) { for ( int pointID = 0; pointID < line.length; pointID ++ ) { writePoint( printWriter, line[ pointID ] ); } } } printWriter.println( "END" ); } id ++; if ( lines1.size() > 0 ) { for ( int lineID = 0; lineID < lines1.size(); lineID ++ ) { line = ( Point2D.Double[] ) lines1.elementAt( lineID ); writePolygon( printWriter, id, line ); id ++; } } } else { if ( lines1.size() > 0 ) { printWriter.println( Long.toString( id ) ); for ( int lineID = 0; lineID < lines1.size(); lineID ++ ) { line = ( Point2D.Double[] ) lines1.elementAt( lineID ); if ( line.length > 1 ) { for ( int pointID = 0; pointID < line.length; pointID ++ ) { writePoint( printWriter, line[ pointID ] ); } } } printWriter.println( "END" ); } id ++; if ( lines0.size() > 0 ) { for ( int lineID = 0; lineID < lines0.size(); lineID ++ ) { line = ( Point2D.Double[] ) lines0.elementAt( lineID ); writePolygon( printWriter, id, line ); id ++; } } } } else { System.out.println("There should only be one of each!"); if ( lines0.size() > 0 ) { printWriter.println( Long.toString( id ) ); for ( int lineID = 0; lineID < lines0.size(); lineID ++ ) { line = ( Point2D.Double[] ) lines0.elementAt( lineID ); if ( line.length > 1 ) { for ( int pointID = 0; pointID < line.length; pointID ++ ) { writePoint( printWriter, line[ pointID ] ); } } } printWriter.println( "END" ); } id ++; if ( lines1.size() > 0 ) { for ( int lineID = 0; lineID < lines1.size(); lineID ++ ) { line = ( Point2D.Double[] ) lines1.elementAt( lineID ); writePolygon( printWriter, id, line ); id ++; } } } return id; } /** * Deals with writing out the polygon which is antarctica */ public long writeAntarcticPolygon2( Vector points, long id, PrintWriter printWriter, double xmin, double xmax, double units ) { System.out.println( "Identified Antarctic Coastline: " ); System.out.println( "ID " + id ); System.out.println( "Number of points " + points.size() ); Point2D.Double point; //int index; //index = 0; //point = ( Point2D.Double ) points.elementAt( index ); //System.out.println( "Point" + index + " (" + point.getX() + "," + point.getY() + ")" ); //index = 1; //point = ( Point2D.Double ) points.elementAt( index ); //System.out.println( "Point" + index + " (" + point.getX() + "," + point.getY() + ")" ); //index = 2; //point = ( Point2D.Double ) points.elementAt( index ); //System.out.println( "Point" + index + " (" + point.getX() + "," + point.getY() + ")" ); //index = points.size() - 3; //point = ( Point2D.Double ) points.elementAt( index ); //System.out.println( "Point" + index + " (" + point.getX() + "," + point.getY() + ")" ); //index = points.size() - 2; //point = ( Point2D.Double ) points.elementAt( index ); //System.out.println( "Point" + index + " (" + point.getX() + "," + point.getY() + ")" ); //index = points.size() - 1; //point = ( Point2D.Double ) points.elementAt( index ); //System.out.println( "Point" + index + " (" + point.getX() + "," + point.getY() + ")" ); double scaledXmin = -180.0d * units; double scaledXmax = 180.0d * units; Vector line0 = new Vector(); Vector line1 = new Vector(); Vector lines0 = new Vector(); Vector lines1 = new Vector(); int xminCounter = 0; int xmaxCounter = 0; double x; double y; double xToWrite; boolean longitude180CrossedAlready = false; boolean writeToLine0 = true; double lastx = Double.NEGATIVE_INFINITY; double lasty = Double.NEGATIVE_INFINITY; for ( int pointID = 0; pointID < points.size() - 1; pointID ++ ) { point = ( Point2D.Double ) points.elementAt( pointID ); x = point.getX(); if ( x > 180.0d ) { xToWrite = ( x - 360.0d ) * units; } else { xToWrite = x * units; } y = point.getY(); // Check if longitude 180 is crossed boolean longitude180Crossed = longitude180Crossed2( points, x, lastx ); if ( longitude180Crossed ) { System.out.println( "longitude180Crossed2 x " + x + ", lastx " + lastx ); double yIntersect = getYIntersect2( x, y, lastx, lasty ); double xIntersect = getXIntersect2( x, lastx ); if ( longitude180CrossedAlready ) { //line1.add( new Point2D.Double( xIntersect * units, yIntersect * units ) ); line1.add( new Point2D.Double( xIntersect * units * -1.0d, yIntersect * units ) ); lines1.add( copyToArray( line1 ) ); line1 = new Vector(); // Add intersection point to polygon0 flipping sign //line0.add( new Point2D.Double( xIntersect * units * -1.0d, yIntersect * units ) ); line0.add( new Point2D.Double( xIntersect * units, yIntersect * units ) ); line0.add( new Point2D.Double( xToWrite, y * units ) ); longitude180CrossedAlready = false; writeToLine0 = true; } else { //line0.add( new Point2D.Double( xIntersect * units, yIntersect * units ) ); line0.add( new Point2D.Double( xIntersect * units * -1.0d, yIntersect * units ) ); lines0.add( copyToArray( line0 ) ); line0 = new Vector(); // Add intersection point to polygon0 flipping sign //line1.add( new Point2D.Double( xIntersect * units * -1.0d, yIntersect * units ) ); line1.add( new Point2D.Double( xIntersect * units, yIntersect * units ) ); line1.add( new Point2D.Double( xToWrite, y * units ) ); longitude180CrossedAlready = true; writeToLine0 = false; } } else { if ( writeToLine0 ) { line0.add( new Point2D.Double( xToWrite, y * units ) ); } else { line1.add( new Point2D.Double( xToWrite, y * units ) ); } } lastx = x; lasty = y; } // Add final line if ( writeToLine0 ) { //if ( line0.size() > 2 ) { lines0.add( copyToArray( line0 ) ); //} else { // System.out.println( "Bug0 in writeAntarcticPolygon2(Vector,long,PrintWriter,double,double,double)" ); //} } else { //if ( line1.size() > 2 ) { lines1.add( copyToArray( line1 ) ); //} else { // System.out.println( "Bug1 in writeAntarcticPolygon2(Vector,long,PrintWriter,double,double,double)" ); //} } // Write out printWriter.println( Long.toString( id ) ); if ( lines0.size() != lines1.size() ) { System.out.println( "Bug2 in writeAntarcticPolygon2(Vector,long,PrintWriter,double,double,double)" ); System.out.println( "lines0.size() " + lines0.size() ); System.out.println( "lines1.size() " + lines1.size() ); } Point2D.Double[] line; for ( int lineID = 0; lineID < lines0.size(); lineID ++ ) { line = ( Point2D.Double[] ) lines0.elementAt( lineID ); for ( int pointID = 0; pointID < line.length; pointID ++ ) { writePoint( printWriter, line[ pointID ] ); } if ( lineID == 0 ) { printWriter.println( scaledXmin + " " + ( -90.0d * units ) ); printWriter.println( scaledXmax + " " + ( -90.0d * units ) ); } line = ( Point2D.Double[] ) lines1.elementAt( lineID ); for ( int pointID = 0; pointID < line.length; pointID ++ ) { writePoint( printWriter, line[ pointID ] ); } } printWriter.println( "END" ); id ++; return id; } /** * Writes a polygon */ public void writePolygon( PrintWriter printWriter, long id, Point2D.Double[] line ) { if ( line.length > 2 ) { printWriter.println( Long.toString( id ) ); for ( int i = 0; i < line.length; i++ ) { writePoint( printWriter, line[ i ] ); } if ( ( line[ 0 ].getX() != line[ line.length - 1 ].getX() ) || ( line[ 0 ].getY() != line[ line.length - 1 ].getY() ) ) { writePoint( printWriter, line[ 0 ] ); } printWriter.println( "END" ); } } /** * Writes a line */ public void writeLine( PrintWriter printWriter, long id, Point2D.Double[] line ) { printWriter.println( "" + id ); for ( int i = 0; i < line.length; i++ ) { writePoint( printWriter, line[ i ] ); } printWriter.println( "END" ); } /** * Writes the x and y coordinates of the Point2D.Double point to a * PrintWriter printWriter. The values are seperated by whitespace. The * print writer is not flushed. */ public void writePoint( PrintWriter printWriter, Point2D.Double point ) { printWriter.println( Double.toString( point.getX() ) + " " + Double.toString( point.getY() ) ); //System.out.println( Double.toString( point.getX() ) + " " + Double.toString( point.getY() ) ); } /** * Returns a new Point2D.Double[] containing coordinates loaded from line * @param line a vector containing Point2D.Double coordinates */ public Point2D.Double[] copyToArray( Vector line ) { Point2D.Double[] points = new Point2D.Double[ line.size() ]; for ( int i = 0; i < line.size(); i ++ ) { points[ i ] = ( Point2D.Double ) line.elementAt( i ); } return points; } }