/* * RPGConv.java 2005-04-28 * * Tobias Jacob, part of his bachelor thesis, FernUniversitaet Hagen * adapted by Dirk Ansorge, FernUniversitaet Hagen * */ package twodsack.io; import twodsack.set.*; import twodsack.setelement.datatype.basicdatatype.*; import twodsack.util.comparator.*; import twodsack.util.number.*; import java.io.*; /** * The RPGConv class is used to convert data provided in a certain format to the the internal * format of the 2DSack, i.e. {@link PointMultiSet}, {@link SegMultiSet} and {@link TriMultiSet}. The original data * is generated by a polygon generator which is able to construct point, segment and polygon * data.
* Three conversion methods are provided by this class. Additionally, there are two methods to * check for errors. */ public class RPGConv { /* * constructors */ /** * Don't use this constructor */ private RPGConv(){} //all data is rounded to 4 digits behind the point private final static int ROUND_VALUE_DIGITS = 4; private static boolean success; private static String errorMsg; private final static double SCALEFACTOR = 1000000.0; private final static double SCALEFACTOR2 = 100000.0; /** * Returns true if the last call of a conversion method was successful. * false otherwise. * * @return true/false depending on the result of the last conversion method */ public static boolean lastConversionSuccessful() { return success; }//end method lastConversionSuccessful /** * Returns the error message returned by the last call of a conversions method. * * @return the error message */ public static String lastConversionErrorMsg() { return errorMsg; }//end method lastConversionErrorMsg /** * Reads the region from disk using the fully qualified name of that file. * The name of this method is a little bit misleading: It does not return * a regions value, but is able to read one. The regions value is returned * as set of segments representing the regions' border. * * @param rpgFileName the fully qualified file name * @return the set of segments representing the regions' border */ public static SegMultiSet getRegions (String rpgFileName) { RPGConv.success = true; RPGConv.errorMsg = "Unknown Error in RPG conversion"; StreamTokenizer st = null; int token = 0; SegMultiSet r = new SegMultiSet(new SegmentComparator()); try { st = new StreamTokenizer (new FileReader (rpgFileName)); st.eolIsSignificant(false); st.commentChar('#'); //read interval for (int i = 0; i < 4; i++) { token = st.nextToken(); } //read no. of points token = st.nextToken(); int noOfPoints = 0; if (token == StreamTokenizer.TT_NUMBER) noOfPoints = (int) st.nval; else { RPGConv.errorMsg = "Error: wrong token type"; throw new Exception(); } Point[] points = new Point[noOfPoints]; //Point construction for (int i = 0; i < noOfPoints; i++) { double x = 0.0; double y = 0.0; token = st.nextToken(); if (token == StreamTokenizer.TT_NUMBER) x = (st.nval*SCALEFACTOR)/SCALEFACTOR2; else { RPGConv.errorMsg = "Error: wrong token type"; throw new Exception(); } token = st.nextToken(); if (token == StreamTokenizer.TT_NUMBER) y = (st.nval*SCALEFACTOR)/SCALEFACTOR2; else { RPGConv.errorMsg = "Error: wrong token type"; throw new Exception(); } points[i] = new Point (x,y); } //read number of Polygons token = st.nextToken(); if ((token != StreamTokenizer.TT_NUMBER) || (st.nval != 1.0)) { RPGConv.errorMsg = "File format error"; throw new Exception(); } //read word "POLYGON" token = st.nextToken(); if ((token != StreamTokenizer.TT_WORD) || (!st.sval.equals("POLYGON"))) { RPGConv.errorMsg = "File format error"; throw new Exception(); } int firstIndex = 0; int prevIndex = 0; int actIndex = 0; //read first point index token = st.nextToken(); if (token != StreamTokenizer.TT_NUMBER) { RPGConv.errorMsg = "File format error"; throw new Exception(); } firstIndex = (int) st.nval; prevIndex = (int) st.nval; //read second point index token = st.nextToken(); if (token != StreamTokenizer.TT_NUMBER) { RPGConv.errorMsg = "File format error"; throw new Exception(); } actIndex = (int) st.nval; int zaehl = 0; //read further point indices, construct Segments while (token != StreamTokenizer.TT_EOF) { //rounding... points[prevIndex-1].x.round(ROUND_VALUE_DIGITS); points[prevIndex-1].y.round(ROUND_VALUE_DIGITS); points[actIndex-1].x.round(ROUND_VALUE_DIGITS); points[actIndex-1].y.round(ROUND_VALUE_DIGITS); r.add (new Segment (points[prevIndex - 1], points [actIndex - 1])); prevIndex = actIndex; token = st.nextToken(); if ((token != StreamTokenizer.TT_NUMBER) && (token != StreamTokenizer.TT_EOF)) { RPGConv.errorMsg = "File format error"; throw new Exception(); } if (token != StreamTokenizer.TT_EOF) actIndex = (int) st.nval; } //rounding... points[actIndex-1].x.round(ROUND_VALUE_DIGITS); points[actIndex-1].y.round(ROUND_VALUE_DIGITS); points[firstIndex-1].x.round(ROUND_VALUE_DIGITS); points[firstIndex-1].y.round(ROUND_VALUE_DIGITS); r.add (new Segment (points[actIndex - 1], points[firstIndex - 1])); }catch (Exception e) { RPGConv.success = false; if (RPGConv.errorMsg.equals ("Unknown Error in RPG conversion")) RPGConv.errorMsg = e.getMessage(); try { while (token != StreamTokenizer.TT_EOF) token = st.nextToken(); }catch (Exception exc) {} SegMultiSet reg = new SegMultiSet(new SegmentComparator()); return reg; } return r; }//end method getRegions /** * Reads the line value from the disk using the fully qualified name of that file. * The name of this method is a little bit misleading, since it does not return * a lines value, but is able to read one. The lines value is returned as a set * of segments. * * @param rpgFileName the fully qualified file name * @return the set of segments representing the lines value */ public static SegMultiSet getLines (String rpgFileName) { RPGConv.success = true; RPGConv.errorMsg = "Unknown Error in RPG conversion"; StreamTokenizer st = null; int token = 0; SegMultiSet l = new SegMultiSet(new SegmentComparator()); try { st = new StreamTokenizer (new FileReader (rpgFileName)); st.eolIsSignificant(false); st.commentChar('#'); //read interval for (int i = 0; i < 4; i++) { token = st.nextToken(); } //read no. of points token = st.nextToken(); int noOfPoints = 0; if (token == StreamTokenizer.TT_NUMBER) noOfPoints = (int) st.nval; else { RPGConv.errorMsg = "Error: wrong token type"; throw new Exception(); } Point[] points = new Point[noOfPoints]; //Point construction for (int i = 0; i < noOfPoints; i++) { double x = 0.0; double y = 0.0; token = st.nextToken(); if (token == StreamTokenizer.TT_NUMBER) { x = (st.nval*SCALEFACTOR)/SCALEFACTOR2; } else { RPGConv.errorMsg = "Error: wrong token type"; throw new Exception(); } token = st.nextToken(); if (token == StreamTokenizer.TT_NUMBER) y = (st.nval*SCALEFACTOR)/SCALEFACTOR2; else { RPGConv.errorMsg = "Error: wrong token type"; throw new Exception(); } points[i] = new Point (x,y); } //read number of Polygons token = st.nextToken(); if ((token != StreamTokenizer.TT_NUMBER) || (st.nval != 1.0)) { RPGConv.errorMsg = "File format error"; throw new Exception(); } //read word "POLYGON" token = st.nextToken(); if ((token != StreamTokenizer.TT_WORD) || (!st.sval.equals("POLYGON"))) { RPGConv.errorMsg = "File format error"; throw new Exception(); } int prevIndex = 0; int actIndex = 0; //read first point index token = st.nextToken(); if (token != StreamTokenizer.TT_NUMBER) { RPGConv.errorMsg = "File format error"; throw new Exception(); } prevIndex = (int) st.nval; //read second point index token = st.nextToken(); if (token != StreamTokenizer.TT_NUMBER) { RPGConv.errorMsg = "File format error"; throw new Exception(); } actIndex = (int) st.nval; //read further point indices, construct Segments while (token != StreamTokenizer.TT_EOF) { //rounding... points[prevIndex-1].x.round(ROUND_VALUE_DIGITS); points[prevIndex-1].y.round(ROUND_VALUE_DIGITS); points[actIndex-1].x.round(ROUND_VALUE_DIGITS); points[actIndex-1].y.round(ROUND_VALUE_DIGITS); l.add (new Segment (points[prevIndex - 1], points [actIndex - 1])); prevIndex = actIndex; token = st.nextToken(); if ((token != StreamTokenizer.TT_NUMBER) && (token != StreamTokenizer.TT_EOF)) { RPGConv.errorMsg = "File format error"; throw new Exception(); } if (token != StreamTokenizer.TT_EOF) actIndex = (int) st.nval; } }catch (Exception e) { RPGConv.success = false; if (RPGConv.errorMsg.equals ("Unknown Error in RPG conversion")) RPGConv.errorMsg = e.getMessage(); try { while (token != StreamTokenizer.TT_EOF) token = st.nextToken(); }catch (Exception exc) {} SegMultiSet ln = new SegMultiSet(new SegmentComparator()); return ln; } return l; }//end method getLines /** * Reads only some parts of a lines value. * This method is can be used to read some parts of segments to construct an subset of the * segments in the file, that has overlapping segments. * * @param rpgFileName the fully qualified file name * @return the set of (partial) segments */ public static SegMultiSet getPartsOfLines (String rpgFileName) { //This method is used in ll_minus. RPGConv.success = true; RPGConv.errorMsg = "Unknown Error in RPG conversion"; StreamTokenizer st = null; int token = 0; SegMultiSet l = new SegMultiSet(new SegmentComparator()); try { st = new StreamTokenizer (new FileReader (rpgFileName)); st.eolIsSignificant(false); st.commentChar('#'); //read interval for (int i = 0; i < 4; i++) { token = st.nextToken(); } //read no. of points token = st.nextToken(); int noOfPoints = 0; if (token == StreamTokenizer.TT_NUMBER) noOfPoints = (int) st.nval; else { RPGConv.errorMsg = "Error: wrong token type"; throw new Exception(); } Point[] points = new Point[noOfPoints]; //Point construction for (int i = 0; i < noOfPoints; i++) { double x = 0.0; double y = 0.0; token = st.nextToken(); if (token == StreamTokenizer.TT_NUMBER) x = (st.nval*SCALEFACTOR)/SCALEFACTOR2; else { RPGConv.errorMsg = "Error: wrong token type"; throw new Exception(); } token = st.nextToken(); if (token == StreamTokenizer.TT_NUMBER) y = (st.nval*SCALEFACTOR)/SCALEFACTOR2; else { RPGConv.errorMsg = "Error: wrong token type"; throw new Exception(); } points[i] = new Point (x,y); } //read number of Polygons token = st.nextToken(); if ((token != StreamTokenizer.TT_NUMBER) || (st.nval != 1.0)) { RPGConv.errorMsg = "File format error"; throw new Exception(); } //read word "POLYGON" token = st.nextToken(); if ((token != StreamTokenizer.TT_WORD) || (!st.sval.equals("POLYGON"))) { RPGConv.errorMsg = "File format error"; throw new Exception(); } int prevIndex = 0; int actIndex = 0; //read first point index token = st.nextToken(); if (token != StreamTokenizer.TT_NUMBER) { RPGConv.errorMsg = "File format error"; throw new Exception(); } prevIndex = (int) st.nval; //read second point index token = st.nextToken(); if (token != StreamTokenizer.TT_NUMBER) { RPGConv.errorMsg = "File format error"; throw new Exception(); } actIndex = (int) st.nval; //read further point indices, construct Segments byte cnt = 0; while (token != StreamTokenizer.TT_EOF) { if (cnt == 0){ Segment helpSegment = new Segment (points[prevIndex - 1], points [actIndex - 1]); Segment s = null; Rational zwei = RationalFactory.constRational(2); if (!(helpSegment.getStartpoint().x.equal (helpSegment.getEndpoint().x))) { //non-vertical segment Rational newX = (points[prevIndex - 1]).x.plus(((points [actIndex - 1]).x)).dividedby(zwei); Rational gr = helpSegment.gradient(); Rational newY = gr.times(newX.minus((points[prevIndex - 1]).x)).plus((points[prevIndex - 1]).y); //rounding: points[prevIndex-1].x.round(ROUND_VALUE_DIGITS); points[prevIndex-1].y.round(ROUND_VALUE_DIGITS); newX.round(ROUND_VALUE_DIGITS); newY.round(ROUND_VALUE_DIGITS); s = new Segment (points[prevIndex - 1], new Point (newX, newY)); } else { //vertical segment Rational newY = (points[prevIndex - 1]).y.plus((points [actIndex - 1]).y).dividedby(zwei); s = new Segment (points[prevIndex - 1], new Point (points[prevIndex - 1].x, newY)); } l.add (s); } prevIndex = actIndex; token = st.nextToken(); if ((token != StreamTokenizer.TT_NUMBER) && (token != StreamTokenizer.TT_EOF)) { RPGConv.errorMsg = "File format error"; throw new Exception(); } if (token != StreamTokenizer.TT_EOF) actIndex = (int) st.nval; if (cnt != 2) cnt++; else cnt = 0; } }catch (Exception e) { RPGConv.success = false; if (RPGConv.errorMsg.equals ("Unknown Error in RPG conversion")) RPGConv.errorMsg = e.getMessage(); try { while (token != StreamTokenizer.TT_EOF) token = st.nextToken(); }catch (Exception exc) {} SegMultiSet ln = new SegMultiSet(new SegmentComparator()); return ln; } return l; }//end method getPartsOfLines /** * Reads the points value from disk using the fully qualified name of that file. * The name of this method is a little bit misleading, since it does not really * return a points value. Instead, it reads a points value and returns a * PointMultiSet. * * @param rpgFileName the fully qualified file name * @return the set of points as a {@link PointMultiSet} */ public static PointMultiSet getPoints (String rpgFileName) { RPGConv.success = true; RPGConv.errorMsg = "Unknown Error in RPG conversion"; StreamTokenizer st = null; int token = 0; PointMultiSet p = new PointMultiSet(new PointComparator()); try { st = new StreamTokenizer (new FileReader (rpgFileName)); st.eolIsSignificant(false); st.commentChar('#'); //read interval for (int i = 0; i < 4; i++) { token = st.nextToken(); } //read no. of points token = st.nextToken(); int noOfPoints = 0; if (token == StreamTokenizer.TT_NUMBER) noOfPoints = (int) st.nval; else { RPGConv.errorMsg = "Error: wrong token type"; throw new Exception(); } for (int i = 0; i < noOfPoints; i++) { double x = 0.0; double y = 0.0; token = st.nextToken(); if (token == StreamTokenizer.TT_NUMBER) x = (st.nval*SCALEFACTOR)/SCALEFACTOR2; else { RPGConv.errorMsg = "Error: wrong token type"; throw new Exception(); } token = st.nextToken(); if (token == StreamTokenizer.TT_NUMBER) y = (st.nval*SCALEFACTOR)/SCALEFACTOR2; else { RPGConv.errorMsg = "Error: wrong token type"; throw new Exception(); } //rounding... Rational xRat = RationalFactory.constRational(x); Rational yRat = RationalFactory.constRational(y); xRat.round(ROUND_VALUE_DIGITS); yRat.round(ROUND_VALUE_DIGITS); p.add(new Point(xRat,yRat)); } while (token != StreamTokenizer.TT_EOF) token = st.nextToken(); }catch (Exception e) { e.printStackTrace(); RPGConv.success = false; if (RPGConv.errorMsg.equals ("Unknown Error in RPG conversion")) RPGConv.errorMsg = e.getMessage(); try { while (token != StreamTokenizer.TT_EOF) token = st.nextToken(); }catch (Exception exc) {} PointMultiSet pts = new PointMultiSet(new PointComparator()); return pts; } return p; }//end method getPoints }//end class RPGConv