diff --git a/src/main/java/de/hft/stuttgart/citygml/viewer/CityGMLViewer.java b/src/main/java/de/hft/stuttgart/citygml/viewer/CityGMLViewer.java index f8b8afcb9e3523a78c3c85db3b265db05a883888..f38157bca7aca41eb39463595917ba564a4b2209 100644 --- a/src/main/java/de/hft/stuttgart/citygml/viewer/CityGMLViewer.java +++ b/src/main/java/de/hft/stuttgart/citygml/viewer/CityGMLViewer.java @@ -23,6 +23,9 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.nio.DoubleBuffer; import java.nio.FloatBuffer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; @@ -71,9 +74,11 @@ import de.hft.stuttgart.citygml.viewer.datastructure.BoundingBox; import de.hft.stuttgart.citygml.viewer.datastructure.Polygon; import de.hft.stuttgart.citygml.viewer.math.Vector3d; import de.hft.stuttgart.citygml.viewer.parser.CityGMLParser; +import de.hft.stuttgart.citygml.viewer.parser.ColorHandler; import de.hft.stuttgart.citygml.viewer.parser.FeatureMapper; import de.hft.stuttgart.citygml.viewer.parser.ObservedInputStream; import de.hft.stuttgart.citygml.viewer.parser.ParserConfiguration; +import de.hft.stuttgart.citygml.viewer.parser.PolygonColorMapper; public class CityGMLViewer { @@ -100,6 +105,10 @@ public class CityGMLViewer { private static final String CITY_OBJECT_MEMBER = "cityObjectMember"; private static List<QName> chunkProperties = new ArrayList<>(); + private static PolygonColorMapper colorMapper = null; + private static ColorHandler colorHandler = null; + private static boolean useDebug = false; + static { chunkProperties.add(new QName(CityGMLConstants.CITYGML_1_0_CORE_NAMESPACE, CITY_OBJECT_MEMBER)); chunkProperties.add(new QName(CityGMLConstants.CITYGML_2_0_CORE_NAMESPACE, CITY_OBJECT_MEMBER)); @@ -107,23 +116,9 @@ public class CityGMLViewer { } public static void main(String[] args) { - boolean useDebug = false; - for (String arg : args) { - if (arg.equals("-debug")) { - useDebug = true; - } - } File f = null; - if (args != null && args.length == 1) { - f = new File(args[0]); - if (!f.exists() || f.isDirectory()) { - // no file given - f = null; - } - } - if (f == null) { - f = showFileChooserDialog(); - } + f = parseArguments(args, f); + try { setupWindow(f, useDebug); } catch (Exception e) { @@ -131,7 +126,7 @@ public class CityGMLViewer { if (e.getCause() != null) { message += "\nCause: " + e.getCause().getClass().getSimpleName() + ": " + e.getCause().getMessage(); } - JOptionPane.showMessageDialog(null, message, "Error", JOptionPane.ERROR_MESSAGE); + showErrorDialog(message); } finally { for (PolygonViewInformation view : viewing) { view.destroy(); @@ -139,6 +134,68 @@ public class CityGMLViewer { } } + private static File parseArguments(String[] args, File f) { + Path colorsPath = null; + Path mappingPath = null; + boolean nextColorsFile = false; + boolean nextMappingsFile = false; + for (String arg : args) { + if (nextColorsFile) { + nextColorsFile = false; + String file = arg; + Path path = Paths.get(file); + if (!Files.exists(path) || !Files.isRegularFile(path)) { + showErrorDialog("Name specified for colors is not a file"); + System.exit(1); + } + colorsPath = path; + } else if (nextMappingsFile) { + nextMappingsFile = false; + String file = arg; + Path path = Paths.get(file); + if (!Files.exists(path) || !Files.isRegularFile(path)) { + showErrorDialog("Name specified for mapping is not a file"); + System.exit(2); + } + mappingPath = path; + } else if (arg.equals("-debug")) { + useDebug = true; + } else if (arg.equals("-colors")) { + // next argument must be a file for the color properties + nextColorsFile = true; + } else if (arg.equals("-mapping")) { + nextMappingsFile = true; + } else { + // this must be the citygml file + String file = arg; + Path path = Paths.get(file); + if (!Files.exists(path) || !Files.isRegularFile(path)) { + showErrorDialog("CityGML file specified does is not a file or does not exist"); + System.exit(3); + } + } + } + + // default values for missing parameters + if (colorsPath == null) { + colorsPath = Paths.get("color.properties"); + } + if (mappingPath == null) { + mappingPath = Paths.get("colorMappings.csv"); + } + if (f == null) { + f = showFileChooserDialog(); + } + + colorMapper = new PolygonColorMapper(mappingPath); + colorHandler = new ColorHandler(colorsPath); + return f; + } + + public static void showErrorDialog(String msg) { + JOptionPane.showMessageDialog(null, msg, "Error", JOptionPane.ERROR_MESSAGE); + } + private static File showFileChooserDialog() { File f = null; try (MemoryStack stack = MemoryStack.stackPush()) { @@ -160,7 +217,7 @@ public class CityGMLViewer { int[] pixels = new int[width * height]; int bindex; // allocate space for RBG pixels - ByteBuffer fb = ByteBuffer.allocateDirect(width * height * 3); + ByteBuffer fb = MemoryUtil.memAlloc(width * height * 3); // grab a copy of the current frame contents as RGB GL11.glReadPixels(0, 0, width, height, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, fb); @@ -171,6 +228,7 @@ public class CityGMLViewer { bindex = i * 3; pixels[i] = (fb.get(bindex) << 16) + (fb.get(bindex + 1) << 8) + (fb.get(bindex + 2)); } + MemoryUtil.memFree(fb); // Allocate colored pixel to buffered Image imageIn.setRGB(0, 0, width, height, pixels, 0, width); @@ -405,7 +463,7 @@ public class CityGMLViewer { while (reader.hasNext()) { CityGMLChunk nextChunk = reader.nextChunk(); mappers.add(service.submit(() -> { - FeatureMapper mapper = new FeatureMapper(config); + FeatureMapper mapper = new FeatureMapper(config, colorMapper, colorHandler); AbstractFeature feature = nextChunk.build(); feature.accept(mapper); return mapper; diff --git a/src/main/java/de/hft/stuttgart/citygml/viewer/parser/ColorHandler.java b/src/main/java/de/hft/stuttgart/citygml/viewer/parser/ColorHandler.java index a7f2708a59c70ef80142acc1d2e947c3b5fb50ab..00144fae4993f2cb17f415c4d28dd08180daa404 100644 --- a/src/main/java/de/hft/stuttgart/citygml/viewer/parser/ColorHandler.java +++ b/src/main/java/de/hft/stuttgart/citygml/viewer/parser/ColorHandler.java @@ -2,6 +2,7 @@ package de.hft.stuttgart.citygml.viewer.parser; import java.awt.Color; import java.io.FileReader; +import java.nio.file.Path; import java.util.Properties; import java.util.logging.Logger; @@ -9,19 +10,19 @@ public class ColorHandler { private static final Logger logger = Logger.getLogger(ColorHandler.class.getName()); - private static Color groundColor = new Color(0.9411765f, 0.9019608f, 0.54901963f); - private static Color roofColor = Color.RED; - private static Color doorColor = Color.ORANGE; - private static Color windowColor = new Color(0.0f, 0.5019608f, 0.5019608f); - private static Color wallColor = Color.WHITE; - private static Color bridgeColor = new Color(1.0f, 0.49803922f, 0.3137255f); - private static Color landColor = new Color(0.64705884f, 0.16470589f, 0.16470589f); - private static Color transportationColor = new Color(1.0f, 1.0f, 0.0f); - private static Color vegetationColor = new Color(0.5647059f, 0.93333334f, 0.5647059f); - private static Color waterColor = new Color(0.5294118f, 0.80784315f, 0.98039216f); + private Color groundColor = new Color(0.9411765f, 0.9019608f, 0.54901963f); + private Color roofColor = Color.RED; + private Color doorColor = Color.ORANGE; + private Color windowColor = new Color(0.0f, 0.5019608f, 0.5019608f); + private Color wallColor = Color.WHITE; + private Color bridgeColor = new Color(1.0f, 0.49803922f, 0.3137255f); + private Color landColor = new Color(0.64705884f, 0.16470589f, 0.16470589f); + private Color transportationColor = new Color(1.0f, 1.0f, 0.0f); + private Color vegetationColor = new Color(0.5647059f, 0.93333334f, 0.5647059f); + private Color waterColor = new Color(0.5294118f, 0.80784315f, 0.98039216f); - static { - try (FileReader reader = new FileReader("color.properties")) { + public ColorHandler(Path path) { + try (FileReader reader = new FileReader(path.toFile())) { Properties props = new Properties(); props.load(reader); Color parsedGroundColor = parseColor(props.getProperty("groundColor")); @@ -69,10 +70,7 @@ public class ColorHandler { } } - private ColorHandler() { - } - - private static Color parseColor(String colorString) { + private Color parseColor(String colorString) { if (colorString == null) { return null; } @@ -88,43 +86,43 @@ public class ColorHandler { } } - public static Color getGroundColor() { + public Color getGroundColor() { return groundColor; } - public static Color getRoofColor() { + public Color getRoofColor() { return roofColor; } - public static Color getDoorColor() { + public Color getDoorColor() { return doorColor; } - public static Color getWindowColor() { + public Color getWindowColor() { return windowColor; } - public static Color getWallColor() { + public Color getWallColor() { return wallColor; } - public static Color getBridgeColor() { + public Color getBridgeColor() { return bridgeColor; } - public static Color getLandColor() { + public Color getLandColor() { return landColor; } - public static Color getTransportationColor() { + public Color getTransportationColor() { return transportationColor; } - public static Color getVegetationColor() { + public Color getVegetationColor() { return vegetationColor; } - public static Color getWaterColor() { + public Color getWaterColor() { return waterColor; } diff --git a/src/main/java/de/hft/stuttgart/citygml/viewer/parser/FeatureMapper.java b/src/main/java/de/hft/stuttgart/citygml/viewer/parser/FeatureMapper.java index b350a2cc0fa72b04f3480430d0116c123d71831e..3d415082d902dbc31a5252d120aa2162c442ea4c 100644 --- a/src/main/java/de/hft/stuttgart/citygml/viewer/parser/FeatureMapper.java +++ b/src/main/java/de/hft/stuttgart/citygml/viewer/parser/FeatureMapper.java @@ -79,9 +79,14 @@ public class FeatureMapper extends ObjectWalker { private ProjCoordinate p1 = new ProjCoordinate(); private ProjCoordinate p2 = new ProjCoordinate(); - public FeatureMapper(ParserConfiguration config) { - currentColor = ColorHandler.getWallColor(); + private PolygonColorMapper colorMapper; + private ColorHandler colorHandler; + + public FeatureMapper(ParserConfiguration config, PolygonColorMapper colorMapper, ColorHandler colorHandler) { + this.colorMapper = colorMapper; + this.colorHandler = colorHandler; this.config = config; + currentColor = colorHandler.getWallColor(); lod1Polygons = new ArrayList<>(); lod2Polygons = new ArrayList<>(); lod3Polygons = new ArrayList<>(); @@ -95,7 +100,7 @@ public class FeatureMapper extends ObjectWalker { } Color setColor = currentColor; if (gmlPoly.getId() != null) { - Color mappedColor = PolygonColorMapper.getColorForPolygon(gmlPoly.getId()); + Color mappedColor = colorMapper.getColorForPolygon(gmlPoly.getId()); if (mappedColor != null) { setColor = mappedColor; } @@ -140,46 +145,46 @@ public class FeatureMapper extends ObjectWalker { } currentPolygons.add(viewerPoly); } - + @Override public void visit(OtherConstruction otherConstruction) { - currentColor = ColorHandler.getWallColor(); + currentColor = colorHandler.getWallColor(); super.visit(otherConstruction); } - + @Override public void visit(CityFurniture cityFurniture) { - currentColor = ColorHandler.getWallColor(); + currentColor = colorHandler.getWallColor(); super.visit(cityFurniture); } - + @Override public void visit(CityObjectGroup cityObjectGroup) { - currentColor = ColorHandler.getWallColor(); + currentColor = colorHandler.getWallColor(); super.visit(cityObjectGroup); } - + @Override public void visit(GenericLogicalSpace genericLogicalSpace) { - currentColor = ColorHandler.getWallColor(); + currentColor = colorHandler.getWallColor(); super.visit(genericLogicalSpace); } - + @Override public void visit(GenericOccupiedSpace genericOccupiedSpace) { - currentColor = ColorHandler.getWallColor(); + currentColor = colorHandler.getWallColor(); super.visit(genericOccupiedSpace); } - + @Override public void visit(GenericThematicSurface genericThematicSurface) { - currentColor = ColorHandler.getWallColor(); + currentColor = colorHandler.getWallColor(); super.visit(genericThematicSurface); } - + @Override public void visit(GenericUnoccupiedSpace genericUnoccupiedSpace) { - currentColor = ColorHandler.getWallColor(); + currentColor = colorHandler.getWallColor(); super.visit(genericUnoccupiedSpace); } @@ -270,10 +275,10 @@ public class FeatureMapper extends ObjectWalker { parseAbstractGeometry(ab.getLod2Solid(), lod2Polygons); parseAbstractGeometry(ab.getLod3Solid(), lod3Polygons); } - + @Override public void visit(AbstractBuilding ab) { - currentColor = ColorHandler.getWallColor(); + currentColor = colorHandler.getWallColor(); super.visit(ab); DeprecatedPropertiesOfAbstractBuilding deprecatedProperties = ab.getDeprecatedProperties(); parseAbstractGeometry(deprecatedProperties.getLod1MultiSurface(), lod1Polygons); @@ -303,13 +308,13 @@ public class FeatureMapper extends ObjectWalker { currentPolygons = lod1Polygons; break; } - currentColor = ColorHandler.getLandColor(); + currentColor = colorHandler.getLandColor(); super.visit(tinRelief); } @Override public void visit(WaterBody wb) { - currentColor = ColorHandler.getWaterColor(); + currentColor = colorHandler.getWaterColor(); super.visit(wb); parseAbstractGeometry(wb.getDeprecatedProperties().getLod1MultiSurface(), lod1Polygons); parseAbstractGeometry(wb.getDeprecatedProperties().getLod4Solid(), lod4Polygons); @@ -317,7 +322,7 @@ public class FeatureMapper extends ObjectWalker { @Override public void visit(PlantCover pc) { - currentColor = ColorHandler.getVegetationColor(); + currentColor = colorHandler.getVegetationColor(); super.visit(pc); parseAbstractGeometry(pc.getDeprecatedProperties().getLod1MultiSurface(), lod1Polygons); parseMultiSolid(pc.getDeprecatedProperties().getLod1MultiSolid(), lod1Polygons); @@ -325,7 +330,6 @@ public class FeatureMapper extends ObjectWalker { parseMultiSolid(pc.getDeprecatedProperties().getLod3MultiSolid(), lod3Polygons); parseMultiSolid(pc.getDeprecatedProperties().getLod4MultiSolid(), lod4Polygons); } - private void parseMultiSolid(MultiSolidProperty ms, List<Polygon> polygons) { if (ms == null || ms.getObject() == null) { @@ -338,27 +342,27 @@ public class FeatureMapper extends ObjectWalker { @Override public void visit(SolitaryVegetationObject svo) { - currentColor = ColorHandler.getVegetationColor(); + currentColor = colorHandler.getVegetationColor(); super.visit(svo); parseAbstractGeometry(svo.getDeprecatedProperties().getLod1Geometry(), lod1Polygons); parseAbstractGeometry(svo.getDeprecatedProperties().getLod2Geometry(), lod2Polygons); parseAbstractGeometry(svo.getDeprecatedProperties().getLod3Geometry(), lod3Polygons); parseAbstractGeometry(svo.getDeprecatedProperties().getLod4Geometry(), lod4Polygons); } - + @Override public void visit(GroundSurface groundSurface) { Color oldColor = currentColor; - currentColor = ColorHandler.getGroundColor(); + currentColor = colorHandler.getGroundColor(); // process window super.visit(groundSurface); currentColor = oldColor; } - + @Override public void visit(RoofSurface roofSurface) { Color oldColor = currentColor; - currentColor = ColorHandler.getRoofColor(); + currentColor = colorHandler.getRoofColor(); // process window super.visit(roofSurface); currentColor = oldColor; @@ -377,13 +381,13 @@ public class FeatureMapper extends ObjectWalker { @Override public void visit(LandUse landUse) { - currentColor = ColorHandler.getLandColor(); + currentColor = colorHandler.getLandColor(); super.visit(landUse); } - + @Override public void visit(AbstractTransportationSpace ats) { - currentColor = ColorHandler.getTransportationColor(); + currentColor = colorHandler.getTransportationColor(); DeprecatedPropertiesOfAbstractTransportationSpace deprecatedProperties = ats.getDeprecatedProperties(); parseAbstractGeometry(ats.getLod1Solid(), lod1Polygons); parseAbstractGeometry(ats.getLod2Solid(), lod1Polygons); @@ -394,25 +398,24 @@ public class FeatureMapper extends ObjectWalker { parseAbstractGeometry(ats.getLod3MultiSurface(), lod3Polygons); parseAbstractGeometry(deprecatedProperties.getLod4MultiSurface(), lod4Polygons); } - + @Override public void visit(Window window) { Color oldColor = currentColor; - currentColor = ColorHandler.getWindowColor(); + currentColor = colorHandler.getWindowColor(); // process window super.visit(window); currentColor = oldColor; } - + @Override public void visit(Door door) { Color oldColor = currentColor; - currentColor = ColorHandler.getDoorColor(); + currentColor = colorHandler.getDoorColor(); super.visit(door); currentColor = oldColor; } - - + @Override public void visit(AbstractFillingElement ao) { super.visit(ao); @@ -428,7 +431,7 @@ public class FeatureMapper extends ObjectWalker { @Override public void visit(AbstractBridge ab) { - currentColor = ColorHandler.getBridgeColor(); + currentColor = colorHandler.getBridgeColor(); super.visit(ab); parseAbstractGeometry(ab.getDeprecatedProperties().getLod1MultiSurface(), lod1Polygons); parseAbstractGeometry(ab.getDeprecatedProperties().getLod4MultiSurface(), lod4Polygons); @@ -437,7 +440,7 @@ public class FeatureMapper extends ObjectWalker { @Override public void visit(BuildingInstallation bi) { - currentColor = ColorHandler.getWallColor(); + currentColor = colorHandler.getWallColor(); super.visit(bi); } diff --git a/src/main/java/de/hft/stuttgart/citygml/viewer/parser/PolygonColorMapper.java b/src/main/java/de/hft/stuttgart/citygml/viewer/parser/PolygonColorMapper.java index e0ee135abc4679a7574278d148b3447938246ef0..4a976d70fc11920e2c4dbc552a4ccfe985af8efe 100644 --- a/src/main/java/de/hft/stuttgart/citygml/viewer/parser/PolygonColorMapper.java +++ b/src/main/java/de/hft/stuttgart/citygml/viewer/parser/PolygonColorMapper.java @@ -14,15 +14,11 @@ import javax.swing.JOptionPane; public class PolygonColorMapper { private static final String IGNORING_ALL_POLYGON_COLOR_MAPPINGS = "\nIgnoring all polygon color mappings"; - private static Function<String, Color> producer; - private static Map<String, Color> colorMap; + private Function<String, Color> producer; + private Map<String, Color> colorMap; - static { - loadColorMap(); - } - - private static void loadColorMap() { + private void loadColorMap(Path path) { Path colorMappingPath = Path.of("colorMappings.csv"); if (!Files.exists(colorMappingPath)) { producer = s -> null; @@ -73,11 +69,12 @@ public class PolygonColorMapper { } - public static Color getColorForPolygon(String polygonId) { + public Color getColorForPolygon(String polygonId) { return producer.apply(polygonId); } - private PolygonColorMapper() { + public PolygonColorMapper(Path path) { + loadColorMap(path); } }