All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gov.nasa.worldwind.formats.vpf.GeoSymAttributeConverter Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2012 United States Government as represented by the Administrator of the
 * National Aeronautics and Space Administration.
 * All Rights Reserved.
 */
package gov.nasa.worldwind.formats.vpf;

import gov.nasa.worldwind.util.*;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.util.ArrayList;

/**
 * The GeoSymAttributeConverter application converts GeoSym line attributes, area attributes, and area patterns into a
 * form usable by World Wind VPF shapes. Outputs to "gsac-out" a comma-separated-value (CSV) file containing line and
 * area attributes for VPF line and area shapes, and PNG images containing area patterns for VPF area shapes.
 * 

* GeoSymAttributeConverter is used to build the VPF symbol JAR file vpf-symbols.jar. For instructions on * how to build vpf-symbols.jar, see the file VPF_README.txt, which is distributed in each * World Wind release. *

* Usage: java -cp worldwind.jar gov.nasa.worldwind.formats.vpf.GeoSymAttributeConverter [full path to * "GeoSymEd2Final/GRAPHICS/CTEXT"] * * @author dcollins * @version $Id: GeoSymAttributeConverter.java 1171 2013-02-11 21:45:02Z dcollins $ */ public class GeoSymAttributeConverter { protected static String TYPE_POINT = "Point"; protected static String TYPE_LINE_PLAIN = "LinePlain"; protected static String TYPE_LINE_COMPLEX = "LineComplex"; protected static String TYPE_AREA_PLAIN = "AreaPlain"; protected static String TYPE_AREA_PATTERN = "AreaPattern"; protected static class CGMFile { protected File file; protected String content; protected String type; protected int[] colorTable; protected int[] patternTable; protected int lineCount = 0; protected int polylineCount = 0; protected int shapeCount = 0; protected int polygonCount = 0; protected int patternCount = 0; protected int pentagonCount = 0; protected int lineElementCount = 0; protected int lineColorIndex = -1; protected int fillColorIndex = -1; protected int lineWidth = -1; protected double scale = 1; protected short stipplePattern; protected int stippleFactor = 0; protected String edgeVis = ""; public CGMFile(File file) { this.file = file; processCGMFile(file); // TODO: process line stipple pattern if (this.type.equals(TYPE_LINE_COMPLEX)) this.processStipplePattern(); } protected void processCGMFile(File file) { this.content = readTextFile(file).replaceAll("\r", ""); String[] lines = this.content.split("\n"); String CGMLine = ""; for (String line : lines) { if (!line.endsWith(";")) line = line.trim() + " "; CGMLine += line; if (CGMLine.endsWith(";")) { this.processCGMLine(CGMLine); CGMLine = ""; } } this.type = getType(); } protected void processCGMLine(String line) { if (line.startsWith("LINE ")) { if (getNumValues(line) == 4) this.lineCount++; else this.polylineCount++; } else if (line.startsWith("CIRCLE ")) this.shapeCount++; else if (line.startsWith("ELLIPARC ")) this.shapeCount++; else if (line.startsWith("POLYGONSET ")) this.shapeCount++; else if (line.startsWith("POLYGON ")) { this.polygonCount++; if (getNumValues(line) == 12) this.pentagonCount++; } else if (line.startsWith("PATTABLE ")) { this.patternCount++; this.patternTable = getIntegerValues(line); } else if (line.startsWith("LINECOLR ")) this.lineColorIndex = getIntegerValue(line); else if (line.startsWith("FILLCOLR ")) this.fillColorIndex = getIntegerValue(line); else if (line.startsWith("LINEWIDTH ")) this.lineWidth = getIntegerValue(line); else if (line.contains("LineComponentElement")) this.lineElementCount++; else if (line.startsWith("EDGEVIS ")) this.edgeVis = getStringValue(line); else if (line.startsWith("COLRTABLE ")) this.colorTable = getIntegerValues(line); else if (line.startsWith("COLRTABLE ")) this.colorTable = getIntegerValues(line); else if (line.startsWith("SCALEMODE ")) this.scale = getScaleValue(line); } protected int getIntegerValue(String line) { return Integer.parseInt(getStringValue(line)); } protected int[] getIntegerValues(String line) { line = line.substring(0, line.length() - 1); // remove end line ";" String[] values = line.split(" "); int[] ints = new int[values.length - 1]; int idx = 0; for (int i = 1; i < values.length; i++) { if (values[i].length() > 0) ints[idx++] = Integer.parseInt(values[i]); } return ints; } protected String getStringValue(String line) { line = line.substring(0, line.length() - 1); // remove end line ";" return line.split(" ")[1]; } protected double getScaleValue(String line) { line = line.substring(0, line.length() - 1); // remove end line ";" String[] values = line.split(" "); return Double.parseDouble(values[2]); } protected int getNumValues(String line) { return line.split(" ").length - 1; } protected String getColor(int idx) { if (idx < 0 || idx * 3 + 3 > this.colorTable.length - 1) return "#FFFFFF"; String color = String.format("#%02x%02x%02x", this.colorTable[idx * 3 + 1], this.colorTable[idx * 3 + 2], this.colorTable[idx * 3 + 3]); if (color.length() > 7) System.out.println( "Color error: idx: " + idx + ", color: " + color + ", components: " + String.format("%d %d %d", this.colorTable[idx * 3 + 1], this.colorTable[idx * 3 + 2], this.colorTable[idx * 3 + 3])); return color; } protected String getType() { if (this.patternCount > 0) return TYPE_AREA_PATTERN; else if (this.polygonCount == 1 && this.pentagonCount == 1 && this.edgeVis.equals("OFF") && this.lineCount == 0 && this.polylineCount == 0 && this.shapeCount == 0) return TYPE_AREA_PLAIN; else if (this.lineElementCount > 0) return TYPE_LINE_COMPLEX; else if (this.lineCount == 1 && this.polylineCount == 0 && this.shapeCount == 0 && this.polygonCount == 0) return TYPE_LINE_PLAIN; else return TYPE_POINT; } protected void processStipplePattern() { //String elementType = ""; double elementLength = 0; double totalLength = 0; ArrayList lengths = new ArrayList(); String[] lines = this.content.split("\n"); // Gather pattern segments for (String line : lines) { if (line.contains("Component.1.Element")) { if (elementLength > 0) { lengths.add(elementLength); totalLength += elementLength; elementLength = 0; } } else if (line.startsWith("APSATTR \"ElementType\"")) { //elementType = getLastValue(line); } else if (line.startsWith("APSATTR \"ElementLength\"")) { elementLength = Double.parseDouble(getLastValue(line)); } else if (line.contains("Component.2") || line.startsWith("BEGAPS \"IC_ViewportTable\"")) { break; } } // Gather last pattern portion if any if (elementLength > 0) { lengths.add(elementLength); totalLength += elementLength; } // Determine the stipple 16 bit pattern out of the length sequence // This assumes the sequence starts with a dash and follows with gaps/dashes double bitLength = totalLength / 16; String bitMask = ""; char bit = '1'; for (Double d : lengths) { int bits = (int) Math.round(d / bitLength); for (int i = 0; i < bits; i++) { bitMask += bit; } bit = bit == '1' ? '0' : '1'; } // Padd or trim the bit mask to 16 bits if (bitMask.length() == 0 || !bitMask.contains("0") || !bitMask.contains("1")) bitMask = "1111110001111000"; // default mask while (bitMask.length() < 16) { bitMask += bitMask.substring(bitMask.length() - 1); } bitMask = bitMask.substring(0, 16); // Set stipple pattern and factor this.stipplePattern = (short) Integer.parseInt(bitMask, 2); this.stippleFactor = (int) Math.max(1, Math.min(3, Math.ceil(totalLength / 6))); // Trace //System.out.print(this.file.getName() + ", bitmask: " + bitMask + " (" + bitMask.length() + ")" + ", pattern length: " + totalLength + ", num segements: " + lengths.size() + " - "); //for (Double d : lengths) // System.out.print(d + ", "); //System.out.println(""); } protected String getLastValue(String line) { String[] tokens = line.replaceAll("\"", "").replaceAll(";", "").split("\\s"); return tokens[tokens.length - 1]; } protected BufferedImage getPattern() { if (this.patternTable == null) return null; Color color = Color.decode(getColor(this.fillColorIndex)); int width = this.patternTable[1]; int height = this.patternTable[2]; int idx = 4; // bit data start BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (this.patternTable[idx++] > 0) image.setRGB(x, y, color.getRGB()); } } return image; } public String toRecordString() { String code = this.file.getName().split("\\.")[0]; String type = this.type; String lineWidth = ""; String lineColor = ""; String stipplePattern = ""; String stippleFactor = ""; String fillColor = ""; if (this.type.equals(TYPE_AREA_PATTERN) || this.type.equals(TYPE_AREA_PLAIN)) { // Set fill color for patterns too as a backup fillColor = getColor(this.fillColorIndex); } else if (this.type.equals(TYPE_LINE_PLAIN) || this.type.equals(TYPE_LINE_COMPLEX)) { // Use .5 if no line width found lineWidth = this.lineWidth > 0 ? String.format("%.1f", this.lineWidth * this.scale).replace(',', '.') : ".5"; // Use fill color if no line color found lineColor = this.lineColorIndex >= 0 ? getColor(this.lineColorIndex) : getColor(this.fillColorIndex); if (this.type.equals(TYPE_LINE_COMPLEX)) { stipplePattern = String.format("#%04x", this.stipplePattern); stippleFactor = "" + this.stippleFactor; } } return String.format("%s,%s,%s,%s,%s,%s,%s", code, type, lineWidth, lineColor, stipplePattern, stippleFactor, fillColor); } public String readTextFile(File file) { if (file == null) { String msg = Logging.getMessage("nullValue.FileIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } StringBuilder sb = new StringBuilder(); BufferedReader reader = null; try { reader = new BufferedReader(new FileReader(file)); String line; while ((line = reader.readLine()) != null) { sb.append(line); sb.append(System.getProperty("line.separator")); // add back line separator } } catch (IOException e) { String msg = Logging.getMessage("generic.ExceptionAttemptingToReadFile", file.getPath()); Logging.logger().log(java.util.logging.Level.SEVERE, msg); return null; } finally { WWIO.closeStream(reader, file.getPath()); } return sb.toString(); } } public static void main(String[] args) { if (args == null || args.length == 0) { printUsage(); return; } File[] cgmFiles = new File(args[0]).listFiles(); PrintStream outAttrs = null; try { File outFile = new File(OUT_ATTRS_PATH); //noinspection ResultOfMethodCallIgnored outFile.getParentFile().mkdirs(); outAttrs = new PrintStream(new FileOutputStream(outFile)); // CSV Output outAttrs.println("# GeoSym line and area attributes"); outAttrs.println( "# GeoSym code, Feature type, Line width, Line color, Stipple pattern, Stipple factor, Fill color"); outAttrs.println("#"); for (File file : cgmFiles) { if (file.getName().toUpperCase().endsWith(".CGM")) { CGMFile cgmf = new CGMFile(file); if (!cgmf.type.equals(TYPE_POINT)) outAttrs.println(cgmf.toRecordString()); if (cgmf.type.equals(TYPE_AREA_PATTERN)) writeAreaPattern(cgmf); } } System.out.println("Done."); } catch (IOException e) { e.printStackTrace(); } finally { WWIO.closeStream(outAttrs, OUT_ATTRS_PATH); } } protected static final String OUT_DIR = "gsac-out"; protected static final String OUT_ATTRS_PATH = OUT_DIR + "/geosym/symasgn/ascii/geosym-line-area-attr.csv"; protected static final String OUT_PATTERNS_PATH = OUT_DIR + "/geosym/graphics/bin"; protected static void printUsage() { System.out.println("GeoSymAttributeConverter"); System.out.println(); System.out.println("Converts GeoSym line attributes, area attributes, and area patterns into a form usable by"); System.out.println("World Wind VPF shapes. Outputs to \"" + OUT_DIR + "\" a comma-separated-value file"); System.out.println("containing line and area attributes for VPF line and area shapes, and PNG files"); System.out.println("containing area patterns for VPF area shapes."); System.out.println(); System.out.println( "Usage: java -cp worldwind.jar gov.nasa.worldwind.formats.vpf.GeoSymAttributeConverter [full path to \"GeoSymEd2Final/GRAPHICS/CTEXT\"]"); System.out.println(); } protected static void writeAreaPattern(CGMFile cgmf) { String fileName = cgmf.file.getName().toUpperCase().replace(".CGM", ".png"); File outFile = new File(OUT_PATTERNS_PATH, fileName); try { //noinspection ResultOfMethodCallIgnored outFile.getParentFile().mkdirs(); ImageIO.write(cgmf.getPattern(), "png", outFile); } catch (Exception e) { System.out.println("Could not save pattern " + fileName); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy