001/* 002 * Constants -- Global variables and methods used for reading an IGES file. 003 * 004 * Copyright (C) 2010-2025, Joseph A. Huwaldt. All rights reserved. 005 * 006 * This library is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 2.1 of the License, or (at your option) any later version. 010 * 011 * This library is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public License 017 * along with this program; if not, write to the Free Software 018 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 019 * Or visit: http://www.gnu.org/licenses/lgpl.html 020 * 021 * Based on, but heavily modified from, IGESView ( http://ts.nist.gov/Standards/IGES/igesTools.cfm ) 022 */ 023package geomss.geom.reader.iges; 024 025import java.awt.Color; 026import java.io.IOException; 027import java.io.PrintWriter; 028import java.io.RandomAccessFile; 029import java.util.Locale; 030import java.util.ResourceBundle; 031import javax.measure.quantity.Length; 032import javax.measure.unit.SI; 033import javax.measure.unit.Unit; 034 035/** 036 * The Constants class is a holding area for any "global" variables that are needed for 037 * multiple classes. Also included are several utility methods that may be used any place 038 * that needs them. It is hoped that there will be no hard-coded values anywhere. 039 * 040 * <p> Modified by: Joseph A. Huwaldt </p> 041 * 042 * @author JDN, Version 1.0 043 * @version February 22, 2025 044 */ 045public class Constants { 046 047 /** 048 * Sets debug mode. 049 */ 050 public static final boolean DEBUG = false; 051 052 /** 053 * The String resources used by this package. 054 */ 055 public static final ResourceBundle RESOURCES 056 = ResourceBundle.getBundle("geomss.geom.reader.iges.IGESResources", java.util.Locale.getDefault()); 057 058 /** 059 * The IGES ASCII file format must always be written using the US locale. 060 */ 061 public static final Locale US = Locale.US; 062 063 /** 064 * Column in IGES file with section identifier ('S', 'G', etc) 065 */ 066 public static final int SECTID_COL = 72; 067 068 /** 069 * Column in IGES file Parameter Data delimiting free-form data with DENum of the 070 * entity. According to the IGES specification, this must be a space (' '). 071 */ 072 public static final int PDID_COL = 64; 073 074 /** 075 * String type identifier. Used when reading in parameters from file. 076 */ 077 public static final int TYPE_STRING = 0; 078 079 /** 080 * Integer type identifier. Used when reading in parameters from file. 081 */ 082 public static final int TYPE_INT = 1; 083 084 /** 085 * Real type identifier. Used when reading in parameters from file. 086 */ 087 public static final int TYPE_FLOAT = 2; 088 089 /** 090 * Character type identifier. Used when reading in parameters from file. 091 */ 092 public static final int TYPE_CHAR = 3; 093 094 /** 095 * Globalized terminate character. Done this way because Part.getGlobal().getTerm() 096 * was too long to type over and over. 097 */ 098 public static char Term; 099 100 /** 101 * Globalized delimiter character. Done this way because Part.getGlobal().getDelim() 102 * was too long to type over and over. 103 */ 104 public static char Delim; 105 106 /** 107 * Globalized grain value. Done this way because Part.getGlobal().getGrain() was too 108 * long to type over and over. 109 */ 110 public static double Grain; 111 112 /** 113 * Globalized length units for the file. Done this way because 114 * Part.getGlobal().getUnit() was too long to type over and over. 115 */ 116 public static Unit<Length> unit = SI.METER; 117 118 /** 119 * X-Axis 120 */ 121 public static final int X_AXIS = 0; 122 123 /** 124 * Y-Axis 125 */ 126 public static final int Y_AXIS = 1; 127 128 /** 129 * Z-Axis 130 */ 131 public static final int Z_AXIS = 2; 132 133 /** 134 * Standard IGES Colors (Index 0, "undefined" is set to black). 135 */ 136 public static final Color IGESColor[] = new Color[9]; 137 138 /** 139 * Initialize IGES color array. Sets up array with standard IGES colors. Index 0, 140 * "undefined", will be displayed as black. 141 */ 142 static { 143 IGESColor[0] = Color.BLACK; 144 IGESColor[1] = Color.BLACK; 145 IGESColor[2] = Color.RED; 146 IGESColor[3] = Color.GREEN; 147 IGESColor[4] = Color.BLUE; 148 IGESColor[5] = Color.YELLOW; 149 IGESColor[6] = Color.MAGENTA; 150 IGESColor[7] = Color.CYAN; 151 IGESColor[8] = Color.WHITE; 152 } 153 154 /** 155 * Set up globals from GlobalSection 156 * 157 * @param g Global Section object 158 */ 159 public static void initGlobals(GlobalSection g) { 160 Term = g.getTerm(); 161 Delim = g.getDelim(); 162 Grain = g.getGrain(); 163 unit = g.getUnit(); 164 } 165 166 /** 167 * Reads in a line of text, 80 characters, ignoring any EOL chars 168 * 169 * @param in input file 170 * @return the single text line of input 171 * @exception IOException if end of file is reached, or other generic file I/O error. 172 */ 173 public static String myReadLine(RandomAccessFile in) throws IOException { 174 char[] line = new char[80]; 175 int i; 176 177 do { 178 for (i = 0; i < 80; i++) { 179 char ch = (char)in.readByte(); 180 181 if ((ch == '\r') || (ch == '\n')) 182 break; 183 184 line[i] = ch; 185 } 186 } while (i == 0); 187 188 return new String(line); 189 } 190 191 /** 192 * Converts the string to an integer. This method can handle "integers" that are 193 * technically real, such as 1.000D+001. A zero length string results in the value 194 * 0 being returned. 195 * 196 * @param s the string to be parsed. Assumed to be trimmed of whitespace. 197 * @return resulting integer 198 */ 199 public static int toInt(String s) { 200 if (s.length() == 0) 201 return 0; 202 203 if ((s.indexOf('E') < 0) && (s.indexOf('e') < 0) && (s.indexOf('D') < 0) && (s.indexOf('d') < 0) 204 && s.indexOf('.') < 0) { 205 return Integer.parseInt(s); 206 207 } else { 208 s = s.replace('d', 'e'); 209 s = s.replace('D', 'e'); 210 return (Double.valueOf(s)).intValue(); 211 } 212 } 213 214 /** 215 * Converts the string to an double. This method can handle IGES floats of single 216 * ("1.00e+010") or double ("1.00d+010") precision. A zero length string results 217 * in the value 0.0 being returned. 218 * 219 * @param s the string to be parsed. Assumed to be trimmed of whitespace. 220 * @return resulting double value 221 */ 222 public static double toDouble(String s) { 223 if (s.length() == 0) 224 return 0.0; 225 226 s = s.replace('d', 'e'); 227 s = s.replace('D', 'e'); 228 229 return Double.valueOf(s); 230 } 231 232 /** 233 * 2D distance. Distance between two points in a plane. 234 * 235 * @param x1 abscissa of first point 236 * @param y1 ordinate of first point 237 * @param x2 abscissa of 2nd point 238 * @param y2 ordinate of second point 239 * @return 2D distance between the points 240 */ 241 public static double dist(double x1, double y1, double x2, double y2) { 242 double dx = x2 - x1; 243 double dy = y2 - y1; 244 return Math.sqrt(dx * dx + dy * dy); 245 } 246 247 /** 248 * 3D distance. Distance between two points in space. 249 * 250 * @param x1 X-coordinate of 251 * @param y1 Y-coordinate of 252 * @param z1 Z-coordinate of first point 253 * @param x2 X-coordinate of second point 254 * @param y2 Y-coordinate of second point 255 * @param z2 Z-coordinate of second point 256 * @return 3D distance between the points 257 */ 258 public static double dist(double x1, double y1, double z1, double x2, double y2, double z2) { 259 double dx = x2 - x1; 260 double dy = y2 - y1; 261 double dz = z2 - z1; 262 return Math.sqrt(dx * dx + dy * dy + dz * dz); 263 } 264 265 /** 266 * Add the specified pad character to the left of the input String until it is the 267 * specified length. 268 * 269 * @param string The string to be made the specified length. 270 * @param pad The character to insert into the beginning of the string to reach the 271 * specified length. 272 * @param length The desired length of the padded string. 273 * @return The input string padded with the specified pad character on the left until 274 * the length matches the specified length. 275 */ 276 public static String padLeft(String string, char pad, int length) { 277 StringBuilder buffer = new StringBuilder(string); 278 while (buffer.length() < length) { 279 buffer.insert(0, pad); 280 } 281 return buffer.toString(); 282 } 283 284 /** 285 * Add the specified pad character to the right of the input String until it is the 286 * specified length. 287 * 288 * @param string The string to be made the specified length. 289 * @param pad The character to append onto the string to reach the specified 290 * length. 291 * @param length The desired length of the padded string. 292 * @return The input string padded with the specified pad character on the right until 293 * the length matches the specified length. 294 */ 295 public static String padRight(String string, char pad, int length) { 296 if (string.length() < length) { 297 StringBuilder buffer = new StringBuilder(string); 298 for (int i = buffer.length(); i < length; ++i) { 299 buffer.append(pad); 300 } 301 string = buffer.toString(); 302 } 303 return string; 304 } 305 306 /** 307 * Create a sequence number using the specified integer and padding it with zeros on 308 * the left until it is 7 characters long. 309 * 310 * @param number The number to turn into a sequence number. 311 * @return A properly formatted sequence number made from the input integer. 312 */ 313 public static String makeSequenceNumber(int number) { 314 return padLeft(String.valueOf(number), '0', 7); 315 } 316 317 /** 318 * Write out a single section of an IGES file. The section is provided as a single 319 * String that contains no line-breaks or control characters. The output will be 320 * limited to 72 characters plus a section code and sequence index. 321 * 322 * @param writer The PrintWriter to write the section to. 323 * @param startIndex The starting sequence index for this section. 324 * @param deNumber The 7 character DE number code (made with "makeSequenceNumber") 325 * for this part or "". 326 * @param sectionCode The code used to identify this section's type ('S', 'G', 'P', 327 * etc"). 328 * @param data A String containing the data for the section. 329 * @return The index for the next sequence following this section. 330 * @throws java.io.IOException if the section could not be written. 331 */ 332 public static int writeSection(PrintWriter writer, int startIndex, String deNumber, 333 char sectionCode, StringBuilder data) throws IOException { 334 if (DEBUG) 335 System.out.println("length = " + data.length() + ", data = " + data); 336 337 int deNumberLength = deNumber.length(); 338 int strLen = 71 - deNumberLength; 339 boolean notDone; 340 do { 341 notDone = data.length() > strLen; 342 if (notDone) { 343 String tmp = data.substring(0, strLen); 344 int idx = tmp.lastIndexOf(',') + 1; 345 tmp = data.substring(0, idx); 346 writer.print(padRight(tmp, ' ', strLen)); 347 data = data.delete(0, idx); 348 349 } else { 350 writer.print(padRight(data.toString(), ' ', strLen)); 351 } 352 353 writer.print(' '); 354 writer.print(deNumber); 355 writer.print(sectionCode); 356 writer.println(makeSequenceNumber(startIndex++)); 357 358 } while (notDone); 359 360 return startIndex; 361 } 362 363}