Commit b2d40f78 authored by Riegel's avatar Riegel
Browse files

Merge branch 'dev_citygml3' into 'dev'

CityGML 3.0. Support

See merge request !10
parents ec3bffa6 45b8f722
Pipeline #10321 passed with stage
in 1 minute and 35 seconds
......@@ -122,6 +122,9 @@ public class CityGmlParser {
private static CityGMLContext context;
private static List<QName> chunkProperties = new ArrayList<>();
// Toggle to suppress logger output for parsing of libraryObjects
private static boolean gagged = false;
static {
System.setProperty("javax.xml.transform.TransformerFactory", "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
FACTORY = SAXParserFactory.newInstance();
......@@ -326,20 +329,29 @@ public class CityGmlParser {
return writer;
}
/**
* Suppresses logger output of {@link #readAndKeepFeatures} for the next parse.
* Used to prevent logging spam while resolving implicit geometries.
*/
public static void gagLogger(boolean value){
gagged = value;
}
private static CityDoctorModel readAndKeepFeatures(ParserConfiguration config, Path file,
CityGMLInputFactory inputFactory, ObservedInputStream ois) throws CityGMLReadException {
try (CityGMLReader reader = inputFactory.createCityGMLReader(ois)) {
Citygml3FeatureMapper mapper = new Citygml3FeatureMapper(config, file);
CityGMLVersion version = null;
// model is read in chunked mode
// object members are replaced by href in model
// need to remove the refs and re-add unparsed objects
List<AbstractCityObject> acos = new ArrayList<>();
while (reader.hasNext()) {
AbstractFeature chunk = reader.next();
version = CityGMLModules.getCityGMLVersion(reader.getName().getNamespaceURI());
if (chunk instanceof CityModel cModel) {
cModel.setCityObjectMembers(null);
mapper.setCityModel(cModel);
CityGMLVersion version = CityGMLModules.getCityGMLVersion(reader.getName().getNamespaceURI());
mapper.setCityGMLVersion(version);
} else if (chunk instanceof AbstractCityObject aco) {
acos.add(aco);
......@@ -362,10 +374,14 @@ public class CityGmlParser {
for (AbstractCityObject aco : acos) {
cModel.getCityObjectMembers().add(new AbstractCityObjectProperty(aco));
}
if (logger.isInfoEnabled()) {
if (logger.isInfoEnabled() && !gagged) {
logger.info(Localization.getText("CityGmlParser.parsedObjects"),
mapper.getModel().getNumberOfFeatures());
} else if (gagged){
// Remove gag
gagged = false;
}
mapper.setCityGMLVersion(version);
return mapper.getModel();
}
}
......
......@@ -18,35 +18,30 @@
*/
package de.hft.stuttgart.citydoctor2.utils;
import java.util.ArrayList;
import java.util.List;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.*;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import org.citygml4j.core.util.geometry.GeometryFactory;
import org.locationtech.proj4j.BasicCoordinateTransform;
import org.locationtech.proj4j.ProjCoordinate;
import org.xmlobjects.gml.model.geometry.aggregates.MultiSurface;
import org.xmlobjects.gml.model.geometry.complexes.CompositeSurface;
import org.xmlobjects.gml.model.geometry.primitives.AbstractRingProperty;
import org.xmlobjects.gml.model.geometry.primitives.Shell;
import org.xmlobjects.gml.model.geometry.primitives.ShellProperty;
import org.xmlobjects.gml.model.geometry.primitives.Solid;
import org.xmlobjects.gml.model.geometry.primitives.SurfaceProperty;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import org.xmlobjects.gml.model.geometry.primitives.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Utility class dedicated to create CityGML4j datastructures.
*
* @author Matthias Betz
*
*/
public final class CityGmlUtils {
private CityGmlUtils() {
// util class
}
......@@ -81,6 +76,22 @@ public final class CityGmlUtils {
return gmlPoly;
}
public static CompositeSurface createGmlComposite(GeometryFactory factory, CompositeCollection comp,
ParserConfiguration config) {
List<SurfaceProperty> surfaces = new ArrayList<>();
for (ConcretePolygon cd : comp.getNonRecursiveCompositeMembers()) {
surfaces.add(new SurfaceProperty(createGmlPolygon(factory, cd, config)));
}
for (CompositeCollection cc : comp.getChildComposites()) {
surfaces.add(new SurfaceProperty(createGmlComposite(factory, cc, config)));
}
if (surfaces.isEmpty()) {
return null;
}
return new CompositeSurface(surfaces);
}
public static org.xmlobjects.gml.model.geometry.primitives.LinearRing createGmlRing(GeometryFactory factory,
ParserConfiguration config, LinearRing lr) {
......@@ -141,12 +152,15 @@ public final class CityGmlUtils {
public static MultiSurface createMultiSurface(Geometry geom, GeometryFactory factory,
ParserConfiguration config) {
if (geom.getType() != GeometryType.MULTI_SURFACE) {
if (geom.getType() != GeometryType.MULTI_SURFACE && geom.getType() != GeometryType.COMPOSITE_SURFACE) {
throw new IllegalArgumentException("This can only handle MultiSurfaces");
}
List<SurfaceProperty> surfaces = new ArrayList<>();
Set<CompositeCollection> compositeCollections = new HashSet<>();
for (Polygon cdPoly : geom.getPolygons()) {
if (!cdPoly.isLink()) {
if (cdPoly instanceof ConcretePolygon conc && conc.isCompositeMember()) {
compositeCollections.add(conc.getPartOfComposite());
} else if (!cdPoly.isLink()) {
// is not part of a boundary surface
org.xmlobjects.gml.model.geometry.primitives.Polygon gmlPoly = createGmlPolygon(factory, cdPoly, config);
if (gmlPoly != null) {
......@@ -157,6 +171,9 @@ public final class CityGmlUtils {
surfaces.add(new SurfaceProperty("#" + cdPoly.getGmlId().getGmlString()));
}
}
for (CompositeCollection cdPoly : compositeCollections) {
surfaces.add(new SurfaceProperty(createGmlComposite(factory, cdPoly, config)));
}
if (surfaces.isEmpty()) {
return null;
}
......
......@@ -68,7 +68,7 @@ public class CityGMLWriterUtils {
public static void writeCityModel(String file, CityDoctorModel model) throws CityDoctorWriteException {
CityGMLContext gmlContext = CityGmlParser.getContext();
CityModel cModel = model.getCityModel();
CityGMLOutputFactory factory = gmlContext.createCityGMLOutputFactory(CityGMLVersion.v2_0);
CityGMLOutputFactory factory = gmlContext.createCityGMLOutputFactory(model.getCityGMLVersion());
try (CityGMLWriter writer = factory.createCityGMLWriter(new File(file))) {
writer.withIndent(" ");
writer.withDefaultPrefixes();
......@@ -92,6 +92,9 @@ public class CityGMLWriterUtils {
storeCityObjects(model.getLand(), gmlFactory, model, cModel, val);
storeCityObjects(model.getTransportation(), gmlFactory, model, cModel, val);
storeCityObjects(model.getWater(), gmlFactory, model, cModel, val);
storeCityObjects(model.getCityFurniture(), gmlFactory, model, cModel, val);
storeCityObjects(model.getGenericCityObjects(), gmlFactory, model, cModel, val);
storeCityObjects(model.getTunnels(), gmlFactory, model, cModel, val);
writer.write(cModel);
cModel.getCityObjectMembers().clear();
......@@ -169,6 +172,7 @@ public class CityGMLWriterUtils {
if (model.isValidated() && val != null) {
QualityADEUtils.writeQualityAde(co, val);
}
co.reCreateGeometries(gmlFactory, model.getParserConfig());
cModel.getCityObjectMembers().add(new AbstractCityObjectProperty(co.getGmlObject()));
}
......
......@@ -29,6 +29,9 @@ MainToolBar.wireframe=Show/Hide Wireframe
MainToolBar.culling=Enable/Disable Culling
MainToolBar.writeReports=Write Reports
MainToolBar.executeChecks=Execute Checks
MainToolBar.showWorld=Show entire city model
MainToolBar.resetCamera=Reset view
MainToolBar.hideRoof=Show/Hide roof BoundarySurfaces
MainWindow.missingConfig=Could not find configuration file.
MainWindow.loadGivenFile=Loading given file, please wait
MainWindow.finishedLoading=Finished loading
......@@ -46,9 +49,12 @@ MainWindow.languageChange=For the change in language to apply, restart CityDocto
MainWindow.buildingsTab=Buildings
MainWindow.vegetationTab=Vegetation
MainWindow.transportationTab=Transportation
MainWindow.tunnelTab=Tunnels
MainWindow.bridgeTab=Bridges
MainWindow.waterTab=Water
MainWindow.terrainTab=Terrain
MainWindow.cityfurnitureTab=CityFurniture
MainWindow.otherObjectsTab=Other
MainWindow.viewLabel=View
MainWindow.showLabel=Show:
MainWindow.searchLabel=Search:
......@@ -58,6 +64,7 @@ MainWindow.errorsTab=Errors
MainWindow.polygonsTab=Polygons
MainWindow.edgesTab=Edges
MainWindow.verticesTab=Vertices
MainWindow.attributeTab=Attributes
MainWindow.logTab=Log
MainWindow.globalErrorsTab=Global Errors
OpenFileDialog.fileLabel=File:
......
......@@ -27,6 +27,9 @@ MainToolBar.wireframe=Zeige/Verstecke Gitternetz
MainToolBar.culling=Aktiviere/Deaktiviere Entfernen der R\u00fcckseiten
MainToolBar.writeReports=Schreibe Reports
MainToolBar.executeChecks=F\u00fchre Pr\u00fcfungen aus
MainToolBar.showWorld=Gesamtes Stadtmodell anzeigen
MainToolBar.resetCamera=Ansicht zur\u00fccksetzen
MainToolBar.hideRoof=Zeige/Verstecke Dach BoundarySurfaces
MainWindow.missingConfig=Konnte Konfigurationsdatei nicht finden.
MainWindow.loadGivenFile=Lade vorhandene Datei, bitte warten
MainWindow.finishedLoading=Fertig geladen
......@@ -44,9 +47,12 @@ MainWindow.languageChange=Um die Spracheinstellung zu \u00fcbernehmen muss CityD
MainWindow.buildingsTab=Geb\u00e4ude
MainWindow.vegetationTab=Vegetation
MainWindow.transportationTab=Verkehrsobjekte
MainWindow.tunnelTab=Tunnel
MainWindow.bridgeTab=Br\u00fccken
MainWindow.waterTab=Gew\u00e4sser
MainWindow.terrainTab=Gel\u00e4nde
MainWindow.cityfurnitureTab=Stadtm\u00f6bel
MainWindow.otherObjectsTab=Andere
MainWindow.viewLabel=Ansicht
MainWindow.showLabel=Zeige:
MainWindow.searchLabel=Suche:
......@@ -56,6 +62,7 @@ MainWindow.errorsTab=Fehler
MainWindow.polygonsTab=Polygone
MainWindow.edgesTab=Kanten
MainWindow.verticesTab=Punkte
MainWindow.attributeTab=Attribute
MainWindow.logTab=Log
MainWindow.globalErrorsTab=Globale Fehler
OpenFileDialog.fileLabel=Datei:
......
......@@ -28,6 +28,7 @@ import java.util.List;
import java.util.UUID;
import org.citygml4j.core.ade.ADEException;
import org.citygml4j.core.model.CityGMLVersion;
import org.citygml4j.core.model.core.AbstractFeatureProperty;
import org.citygml4j.core.model.core.CityModel;
import org.citygml4j.xml.writer.CityGMLWriteException;
......@@ -131,6 +132,7 @@ public class CityDoctorModelTest {
File f = Mockito.mock(File.class);
ParserConfiguration config = new ParserConfiguration(8, false);
CityDoctorModel model = new CityDoctorModel(config, f);
model.setParsedCityGMLVersion(CityGMLVersion.v2_0);
CityModel cModel = new CityModel();
model.setCityModel(cModel);
Building b = new Building();
......@@ -156,6 +158,7 @@ public class CityDoctorModelTest {
File f = Mockito.mock(File.class);
ParserConfiguration config = new ParserConfiguration(8, false);
CityDoctorModel model = new CityDoctorModel(config, f);
model.setParsedCityGMLVersion(CityGMLVersion.v2_0);
CityModel cModel = new CityModel();
ValidationPlan plan = new ValidationPlan();
plan.setId("CD_PLAN_" + UUID.randomUUID().toString());
......
package de.hft.stuttgart.citydoctor2.datastructure;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParser;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
public class CompositePolygonTest {
@Test
public void testCompositePolygonParsing() throws CityGmlParseException, InvalidGmlFileException {
ParserConfiguration config = new ParserConfiguration(8, false);
CityDoctorModel m = CityGmlParser.parseCityGmlFile("src/test/resources/FZK_haus.gml", config);
Building b = m.getBuildings().get(0);
assertNotNull(b);
assertFalse(b.getBoundarySurfaces().isEmpty());
for (BoundarySurface bs : b.getBoundarySurfaces()) {
assertNotNull(bs);
assertFalse(bs.getGeometries().isEmpty());
for (Geometry geom : bs.getGeometries()) {
assertNotNull(geom);
assertFalse(geom.getPolygons().isEmpty());
}
}
}
}
package de.hft.stuttgart.citydoctor2.datastructure;
import de.hft.stuttgart.citydoctor2.check.AbstractCheck;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import org.citygml4j.core.model.core.ImplicitGeometry;
import org.citygml4j.core.model.core.TransformationMatrix4x4;
import org.junit.Before;
import org.junit.Test;
import org.xmlobjects.gml.model.geometry.DirectPosition;
import org.xmlobjects.gml.model.geometry.primitives.Point;
import org.xmlobjects.gml.model.geometry.primitives.PointProperty;
import org.xmlobjects.gml.util.jama.Matrix;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.atomic.AtomicInteger;
import static org.junit.Assert.*;
public class ImplicitGeometryTest {
private Path path;
private ParserConfiguration config;
private String pathString = "src/test/resources/ImplicitTestGeom.gml";
private TransformationMatrix4x4 origin;
@Before
public void setUp() {
path = Paths.get(pathString);
config = new ParserConfiguration(8, false);
Matrix og = new Matrix(4, 4);
og.set(0, 0, 1);
og.set(1, 1, 1);
og.set(2, 2, 1);
origin = new TransformationMatrix4x4(og);
}
@Test
public void testLibraryObjectParsing() {
LibraryObject lo = LibraryObject.of(path, config);
assertNotNull(lo);
LibraryObject lo2 = LibraryObject.of(path, config);
assertSame(lo, lo2);
}
@Test
public void testObjectTransform() {
LibraryObject lo = LibraryObject.of(path, config);
assertNotNull(lo);
ImplicitGeometry geom = new ImplicitGeometry();
geom.setTransformationMatrix(origin);
geom.setReferencePoint(new PointProperty(new Point(new DirectPosition(0, 0))));
ImplicitGeometryHolder igh = new ImplicitGeometryHolder(geom, lo);
assertNotNull(igh);
geom.setReferencePoint(new PointProperty(new Point(new DirectPosition(5, 8))));
ImplicitGeometryHolder igh2 = new ImplicitGeometryHolder(geom, lo);
assertNotNull(igh2);
assertNotEquals(igh, igh2);
BoundingBox bb1 = BoundingBox.of(igh.getPolygons());
BoundingBox bb2 = BoundingBox.of(igh2.getPolygons());
assertNotEquals(bb1, bb2);
}
@Test
public void testAccept() {
LibraryObject lib = LibraryObject.of(path, config);
assertNotNull(lib);
ImplicitGeometry geom = new ImplicitGeometry();
geom.setTransformationMatrix(origin);
geom.setReferencePoint(new PointProperty(new Point(new DirectPosition(0, 0))));
int polyCount = lib.getPolygons().size();
ImplicitGeometryHolder igh = new ImplicitGeometryHolder(geom, lib);
AtomicInteger loCounter = new AtomicInteger(0);
AbstractCheck c = new AbstractCheck() {
@Override
public void check(Polygon lo) {
loCounter.incrementAndGet();
}
};
igh.accept(c);
assertEquals("ImplicitGeometryHolder should only check polygons of prototype geometry",
polyCount, loCounter.intValue());
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
<?xml version="1.0" encoding="utf-8"?>
<core:CityModel xmlns:core='http://www.opengis.net/citygml/2.0' xmlns:xlink='http://www.w3.org/1999/xlink' xmlns:gml='http://www.opengis.net/gml' xmlns:xAL='urn:oasis:names:tc:ciq:xsdschema:xAL:2.0' xmlns:app='http://www.opengis.net/citygml/appearance/2.0' xmlns:brid='http://www.opengis.net/citygml/bridge/2.0' xmlns:bldg='http://www.opengis.net/citygml/building/2.0' xmlns:frn='http://www.opengis.net/citygml/cityfurniture/2.0' xmlns:grp='http://www.opengis.net/citygml/cityobjectgroup/2.0' xmlns:gen='http://www.opengis.net/citygml/generics/2.0' xmlns:luse='http://www.opengis.net/citygml/landuse/2.0' xmlns:dem='http://www.opengis.net/citygml/relief/2.0' xmlns:tex='http://www.opengis.net/citygml/texturedsurface/2.0' xmlns:tran='http://www.opengis.net/citygml/transportation/2.0' xmlns:tun='http://www.opengis.net/citygml/tunnel/2.0' xmlns:veg='http://www.opengis.net/citygml/vegetation/2.0' xmlns:wtr='http://www.opengis.net/citygml/waterbody/2.0' xmlns:smil20='http://www.w3.org/2001/SMIL20/' xmlns:smil='http://www.w3.org/2001/SMIL20/Language' xmlns:xml='http://www.w3.org/XML/1998/namespace' xmlns:xs='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.opengis.net/citygml/profiles/base/2.0 http://schemas.opengis.net/citygml/profiles/base/2.0/CityGML.xsd' gml:id='0'>
<core:cityObjectMember>
<frn:CityFurniture gml:id='ImplicitGeometryLod2'>
<gml:name>TestGeometry</gml:name>
<frn:lod2ImplicitRepresentation>
<core:ImplicitGeometry gml:id='ImplicitGeometry'>
<core:transformationMatrix>
1.0 0.0 0.0 0.0
0.0 1.0 0.0 0.0
0.0 0.0 1.0 0.0
0.0 0.0 0.0 1.0
</core:transformationMatrix>
<core:relativeGMLGeometry>
<gml:CompositeSurface gml:id='1' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:surfaceMember>
<gml:Polygon gml:id='2' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='3' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> 4.034 -2.193 58.441 4.034 -2.193 58.158 4.034 -1.750 58.441 4.034 -2.193 58.441</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='4' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='5' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> 4.034 -0.039 100.000 4.034 1.864 58.441 4.034 -1.750 58.441 4.034 -0.039 59.536 4.034 -0.039 100.000</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='6' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='7' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> 6.111 -37.093 35.821 6.110 -0.039 59.536 4.034 -0.039 59.536 4.034 -1.750 58.441 4.034 -2.193 58.158 4.035 -37.093 35.821 6.111 -37.093 35.821</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='8' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='9' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> 6.110 -0.039 100.000 6.110 1.973 56.052 4.034 1.973 56.052 4.034 1.864 58.441 4.034 -0.039 100.000 6.110 -0.039 100.000</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='10' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='11' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> 4.035 -37.093 35.821 4.034 -2.164 55.986 4.034 -2.050 56.052 6.110 -2.050 56.052 6.111 -37.093 35.821 4.035 -37.093 35.821</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='12' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='13' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> 6.111 -37.093 35.821 6.110 -2.050 56.052 6.110 37.015 35.821 6.110 1.973 56.052 6.110 -0.039 100.000 6.110 -0.039 59.536 6.111 -37.093 35.821</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='14' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='15' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> 4.035 -37.093 35.821 4.034 -2.193 58.158 4.034 -2.193 55.986 4.034 -2.164 55.986 4.035 -37.093 35.821</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='16' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='17' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> 4.034 37.015 35.821 4.034 -1.923 55.986 4.034 2.087 55.986 4.034 37.015 35.821</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='18' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='19' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> 1.696 -0.979 55.986 -0.000 -1.958 55.986 -0.000 -1.958 0.000 1.696 -0.979 0.000 1.696 -0.979 55.986</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='20' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='21' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> 4.034 -2.164 55.986 4.034 -1.923 55.986 4.034 -2.050 56.052 4.034 -2.164 55.986</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='22' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='23' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> 6.110 37.015 35.821 6.110 -2.050 56.052 4.034 -2.050 56.052 4.034 -1.923 55.986 4.034 37.015 35.821 6.110 37.015 35.821</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='24' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='25' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> 4.034 37.015 35.821 4.034 2.087 55.986 4.034 1.973 56.052 6.110 1.973 56.052 6.110 37.015 35.821 4.034 37.015 35.821</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='26' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='27' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> -0.000 1.958 0.000 1.696 0.979 0.000 1.696 -0.979 0.000 -0.000 -1.958 0.000 -1.696 -0.979 0.000 -1.696 0.979 0.000 -0.000 1.958 0.000</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='28' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='29' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> -1.696 0.979 55.986 -0.000 1.958 55.986 -0.000 1.958 0.000 -1.696 0.979 0.000 -1.696 0.979 55.986</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='30' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='31' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> -3.336 -2.193 58.441 4.034 -2.193 58.441 4.034 -1.750 58.441 4.034 1.864 58.441 4.034 2.116 58.441 -3.336 2.116 58.441 -3.336 -2.193 58.441</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='32' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='33' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> -3.336 -2.193 55.986 4.034 -2.193 55.986 4.034 -2.193 58.158 4.034 -2.193 58.441 -3.336 -2.193 58.441 -3.336 -2.193 55.986</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='34' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='35' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> 4.034 -0.039 100.000 4.034 -0.039 59.536 6.110 -0.039 59.536 6.110 -0.039 100.000 4.034 -0.039 100.000</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='36' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='37' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> -0.000 1.958 55.986 1.696 0.979 55.986 1.696 0.979 0.000 -0.000 1.958 0.000 -0.000 1.958 55.986</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='38' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='39' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> 4.034 2.116 58.441 4.034 1.864 58.441 4.034 1.973 56.052 4.034 2.087 55.986 4.034 2.116 55.986 4.034 2.116 58.441</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='40' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='41' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> 1.696 0.979 55.986 1.696 -0.979 55.986 1.696 -0.979 0.000 1.696 0.979 0.000 1.696 0.979 55.986</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='42' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='43' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> -0.000 -1.958 55.986 -1.696 -0.979 55.986 -1.696 -0.979 0.000 -0.000 -1.958 0.000 -0.000 -1.958 55.986</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='44' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='45' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> -3.336 2.116 55.986 4.034 2.116 55.986 4.034 2.087 55.986 4.034 -1.923 55.986 4.034 -2.164 55.986 4.034 -2.193 55.986 -3.336 -2.193 55.986 -3.336 2.116 55.986</gml:posList>
</gml:LinearRing>
</gml:exterior>
<gml:interior>
<gml:LinearRing gml:id='46' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> -0.000 1.958 55.986 -1.696 0.979 55.986 -1.696 -0.979 55.986 -0.000 -1.958 55.986 1.696 -0.979 55.986 1.696 0.979 55.986 -0.000 1.958 55.986</gml:posList>
</gml:LinearRing>
</gml:interior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='47' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='48' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> -1.696 -0.979 55.986 -1.696 0.979 55.986 -1.696 0.979 0.000 -1.696 -0.979 0.000 -1.696 -0.979 55.986</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='49' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='50' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> -3.336 2.116 55.986 -3.336 -2.193 55.986 -3.336 -2.193 58.441 -3.336 2.116 58.441 -3.336 2.116 55.986</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id='51' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:exterior>
<gml:LinearRing gml:id='52' srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'>
<gml:posList srsName='urn:ogc:def:crs:EPSG::-1' srsDimension='3'> -3.336 2.116 58.441 4.034 2.116 58.441 4.034 2.116 55.986 -3.336 2.116 55.986 -3.336 2.116 58.441</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:CompositeSurface>
</core:relativeGMLGeometry>
<core:referencePoint>
<gml:Point><gml:pos srsDimension="3">0.0 0.0 0.0</gml:pos>
</gml:Point></core:referencePoint>
</core:ImplicitGeometry>
</frn:lod2ImplicitRepresentation>
</frn:CityFurniture>
</core:cityObjectMember>
</core:CityModel>
......@@ -22,6 +22,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.datastructure.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
......@@ -34,21 +35,6 @@ import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.UnknownCheckError;
import de.hft.stuttgart.citydoctor2.datastructure.AbstractBuilding;
import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface;
import de.hft.stuttgart.citydoctor2.datastructure.BridgeObject;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.Installation;
import de.hft.stuttgart.citydoctor2.datastructure.BuildingPart;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.LandObject;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Opening;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.TransportationObject;
import de.hft.stuttgart.citydoctor2.datastructure.Vegetation;
import de.hft.stuttgart.citydoctor2.datastructure.WaterObject;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.Localization;
......@@ -244,6 +230,24 @@ public class CheckContainer extends Check {
}
}
@Override
public void check(CityFurniture cf){
try {
check.check(cf);
} catch (Exception e) {
handleException(e, cf);
}
}
@Override
public void check(GenericCityObject gco) {
try {
check.check(gco);
} catch (Exception e) {
handleException(e, gco);
}
}
@Override
public RequirementType getType() {
return check.getType();
......
package de.hft.stuttgart.citydoctor2.gui;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.StringJoiner;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.citygml4j.core.model.core.CityModel;
import org.xml.sax.SAXParseException;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.Checker;
import de.hft.stuttgart.citydoctor2.check.ErrorId;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.check.error.SchematronError;
import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface;
import de.hft.stuttgart.citydoctor2.datastructure.BridgeConstructiveElement;
import de.hft.stuttgart.citydoctor2.datastructure.BridgeObject;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.Installation;
import de.hft.stuttgart.citydoctor2.datastructure.BuildingPart;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
import de.hft.stuttgart.citydoctor2.datastructure.FeatureType;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.LandObject;
import de.hft.stuttgart.citydoctor2.datastructure.Opening;
import de.hft.stuttgart.citydoctor2.datastructure.ReliefObject;
import de.hft.stuttgart.citydoctor2.datastructure.TinObject;
import de.hft.stuttgart.citydoctor2.datastructure.TransportationObject;
import de.hft.stuttgart.citydoctor2.datastructure.Vegetation;
import de.hft.stuttgart.citydoctor2.datastructure.*;
import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException;
import de.hft.stuttgart.citydoctor2.gui.table.ErrorStat;
import de.hft.stuttgart.citydoctor2.gui.tree.AllBoundarySurfacesNode;
import de.hft.stuttgart.citydoctor2.gui.tree.AllBridgeConstructiveElementsNode;
import de.hft.stuttgart.citydoctor2.gui.tree.AllBridgePartsNode;
import de.hft.stuttgart.citydoctor2.gui.tree.AllBridgesNode;
import de.hft.stuttgart.citydoctor2.gui.tree.AllInstallationsNode;
import de.hft.stuttgart.citydoctor2.gui.tree.AllBuildingPartsNode;
import de.hft.stuttgart.citydoctor2.gui.tree.AllBuildingsNode;
import de.hft.stuttgart.citydoctor2.gui.tree.AllOpeningsNode;
import de.hft.stuttgart.citydoctor2.gui.tree.AllTerrainNode;
import de.hft.stuttgart.citydoctor2.gui.tree.AllTinNode;
import de.hft.stuttgart.citydoctor2.gui.tree.AllTransportationNode;
import de.hft.stuttgart.citydoctor2.gui.tree.AllVegetationNode;
import de.hft.stuttgart.citydoctor2.gui.tree.AllWaterNode;
import de.hft.stuttgart.citydoctor2.gui.tree.BoundarySurfaceNode;
import de.hft.stuttgart.citydoctor2.gui.tree.BridgeConstructiveElementNode;
import de.hft.stuttgart.citydoctor2.gui.tree.BridgeNode;
import de.hft.stuttgart.citydoctor2.gui.tree.InstallationNode;
import de.hft.stuttgart.citydoctor2.gui.tree.BuildingNode;
import de.hft.stuttgart.citydoctor2.gui.tree.BuildingPartNode;
import de.hft.stuttgart.citydoctor2.gui.tree.ButtonRenderable;
import de.hft.stuttgart.citydoctor2.gui.tree.CityObjectNode;
import de.hft.stuttgart.citydoctor2.gui.tree.GeometryNode;
import de.hft.stuttgart.citydoctor2.gui.tree.LandUseNode;
import de.hft.stuttgart.citydoctor2.gui.tree.OpeningNode;
import de.hft.stuttgart.citydoctor2.gui.tree.ReliefNode;
import de.hft.stuttgart.citydoctor2.gui.tree.Renderable;
import de.hft.stuttgart.citydoctor2.gui.tree.TinNode;
import de.hft.stuttgart.citydoctor2.gui.tree.VegetationNode;
import de.hft.stuttgart.citydoctor2.gui.tree.*;
import de.hft.stuttgart.citydoctor2.mapper.citygml3.GMLValidationHandler;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParser;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.parser.ProgressListener;
import de.hft.stuttgart.citydoctor2.parser.*;
import de.hft.stuttgart.citydoctor2.utils.Localization;
import javafx.application.Platform;
import javafx.scene.chart.XYChart.Data;
......@@ -84,6 +21,15 @@ import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.citygml4j.core.model.core.CityModel;
import org.xml.sax.SAXParseException;
import java.io.File;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
public class CityDoctorController {
......@@ -101,13 +47,17 @@ public class CityDoctorController {
private HighlightController highlightController;
private Renderer renderer;
private BoundingBox originBB = null;
private AtomicInteger buildingChunkNr = new AtomicInteger(0);
private AtomicInteger vegetationChunkNr = new AtomicInteger(0);
private AtomicInteger transportationChunkNr = new AtomicInteger(0);
private AtomicInteger tunnelChunkNr = new AtomicInteger(0);
private AtomicInteger bridgeChunkNr = new AtomicInteger(0);
private AtomicInteger waterChunkNr = new AtomicInteger(0);
private AtomicInteger landChunkNr = new AtomicInteger(0);
private AtomicInteger cityFurnitureChunkNr = new AtomicInteger(0);
private AtomicInteger otherObjectsChunkNr = new AtomicInteger(0);
public CityDoctorController(MainWindow mainWindow, HighlightController highlightController, Renderer renderer) {
this.mainWindow = mainWindow;
......@@ -176,6 +126,11 @@ public class CityDoctorController {
mainWindow.getLod4Btn().setDisable(false);
mainWindow.getWorldBtn().setDisable(false);
mainWindow.getSaveBtn().setDisable(false);
mainWindow.getResetCameraBtn().setDisable(false);
mainWindow.getHideRoofBtn().setDisable(false);
mainWindow.getNorthArrow().setVisible(true);
mainWindow.alignNorthArrow();
setupFeatureTabs();
buildTrees();
});
} finally {
......@@ -183,6 +138,18 @@ public class CityDoctorController {
}
}
private void setupFeatureTabs() {
mainWindow.setDisableOfFeatureTab(FeatureType.BUILDING, model.getBuildings().isEmpty());
mainWindow.setDisableOfFeatureTab(FeatureType.VEGETATION, model.getVegetation().isEmpty());
mainWindow.setDisableOfFeatureTab(FeatureType.TRANSPORTATION, model.getTransportation().isEmpty());
mainWindow.setDisableOfFeatureTab(FeatureType.TUNNEL, model.getTunnels().isEmpty());
mainWindow.setDisableOfFeatureTab(FeatureType.BRIDGE, model.getBridges().isEmpty());
mainWindow.setDisableOfFeatureTab(FeatureType.WATER, model.getWater().isEmpty());
mainWindow.setDisableOfFeatureTab(FeatureType.LAND, model.getLand().isEmpty());
mainWindow.setDisableOfFeatureTab(FeatureType.CITY_FURNITURE, model.getCityFurniture().isEmpty());
mainWindow.setDisableOfFeatureTab(FeatureType.GENERIC_CITY_OBJECT, model.getGenericCityObjects().isEmpty());
}
public void buildTrees() {
resetFeatureChunks();
buildBuildings(model);
......@@ -191,15 +158,20 @@ public class CityDoctorController {
buildBridges(model);
buildWater(model);
buildLand(model);
buildCityFurniture(model);
buildOtherCityObjects(model);
}
private void resetFeatureChunks() {
buildingChunkNr.set(0);
vegetationChunkNr.set(0);
transportationChunkNr.set(0);
tunnelChunkNr.set(0);
bridgeChunkNr.set(0);
waterChunkNr.set(0);
landChunkNr.set(0);
cityFurnitureChunkNr.set(0);
otherObjectsChunkNr.set(0);
}
private void buildLand(CityDoctorModel model) {
......@@ -254,6 +226,30 @@ public class CityDoctorController {
}
}
private void buildCityFurniture(CityDoctorModel model) {
if (model.getCityFurniture().isEmpty()) {
return;
}
TreeView<Renderable> cityFurnitureView = mainWindow.getCityFurnitureView();
TreeItem<Renderable> cityFurnitureRoot = new TreeItem<>(new AllCityFurnitureNode(model.getCityFurniture()));
cityFurnitureRoot.setExpanded(true);
cityFurnitureView.setRoot(cityFurnitureRoot);
buildTreeFromList(model.getCityFurniture(), cityFurnitureView.getRoot(), cityFurnitureChunkNr);
addMoreButtonIfNecessary(model.getCityFurniture(), cityFurnitureView, cityFurnitureRoot, cityFurnitureChunkNr);
}
private void buildOtherCityObjects(CityDoctorModel model) {
if (model.getGenericCityObjects().isEmpty()) {
return;
}
TreeView<Renderable> otherObjectsView = mainWindow.getOtherObjectsView();
TreeItem<Renderable> otherObjectsRoot = new TreeItem<>(new AllOtherObjectsNode(model.getGenericCityObjects()));
otherObjectsRoot.setExpanded(true);
otherObjectsView.setRoot(otherObjectsRoot);
buildTreeFromList(model.getGenericCityObjects(), otherObjectsView.getRoot(), otherObjectsChunkNr);
addMoreButtonIfNecessary(model.getGenericCityObjects(), otherObjectsView, otherObjectsRoot, otherObjectsChunkNr);
}
private void buildWater(CityDoctorModel model) {
if (model.getWater().isEmpty()) {
return;
......@@ -290,6 +286,18 @@ public class CityDoctorController {
addMoreButtonIfNecessary(trans, transView, transRoot, transportationChunkNr);
}
private void buildTunnel(List<Tunnel> tunnels) {
if (tunnels.isEmpty()) {
return;
}
TreeView<Renderable> transView = mainWindow.getTunnelView();
TreeItem<Renderable> transRoot = new TreeItem<>(new AllTunnelsNode(model.getTunnels()));
transRoot.setExpanded(true);
transView.setRoot(transRoot);
buildTreeFromList(tunnels, transView.getRoot(), tunnelChunkNr);
addMoreButtonIfNecessary(tunnels, transView, transRoot, tunnelChunkNr);
}
private void buildVegetation(List<Vegetation> veg) {
if (veg.isEmpty()) {
return;
......@@ -417,7 +425,10 @@ public class CityDoctorController {
mainWindow.getBridgeView().setRoot(null);
mainWindow.getWaterView().setRoot(null);
mainWindow.getTerrainView().setRoot(null);
mainWindow.getCityFurnitureView().setRoot(null);
mainWindow.getOtherObjectsView().setRoot(null);
mainWindow.getErrorTree().getRoot().getChildren().clear();
mainWindow.getAttributeView().getRoot().getChildren().clear();
mainWindow.getGlobalErrorsView().getItems().clear();
clearGeometryTrees();
}
......@@ -441,6 +452,10 @@ public class CityDoctorController {
createGeometryNodes(b, item);
createBoundarySurfaceNodes(b.getBoundarySurfaces(), item);
createBuildingInstallationNodes(b, item);
createBuildingRoomNodes(b, item);
createBuildingFurnitureNodes(b, item);
createBuildingStoreyNodes(b, item);
createBuildingUnitNodes(b, item);
createBuildingPartNodes(b, item);
}
}
......@@ -526,6 +541,88 @@ public class CityDoctorController {
}
}
private void createBuildingRoomNodes(Building ab, TreeItem<Renderable> root) {
createRoomNodes(ab.getBuildingRooms(), root);
}
private void createRoomNodes(List<? extends AbstractRoom> rooms, TreeItem<Renderable> root) {
if (rooms.isEmpty()) {
return;
}
AllRoomsNode allRoNode = new AllRoomsNode(rooms);
TreeItem<Renderable> allRoNodeTextItem = new TreeItem<>(allRoNode);
root.getChildren().add(allRoNodeTextItem);
for (AbstractRoom room : rooms) {
RoomNode roomNode = new RoomNode(room);
TreeItem<Renderable> roomNodeTextItem = new TreeItem<>(roomNode);
roomNodeTextItem.setExpanded(true);
allRoNodeTextItem.getChildren().add(roomNodeTextItem);
createGeometryNodes(room, roomNodeTextItem);
createBoundarySurfaceNodes(room.getBoundarySurfaces(), roomNodeTextItem);
}
}
private void createBuildingStoreyNodes(Building ab, TreeItem<Renderable> root) {
List<Storey> storeys = ab.getBuildingStoreys();
if (storeys.isEmpty()) {
return;
}
AllStoreysNode allSNode = new AllStoreysNode(storeys);
TreeItem<Renderable> allSNodeTextItem = new TreeItem<>(allSNode);
root.getChildren().add(allSNodeTextItem);
for (Storey storey : storeys) {
StoreyNode storeyNode = new StoreyNode(storey);
TreeItem<Renderable> storeyNodeTextItem = new TreeItem<>(storeyNode);
storeyNodeTextItem.setExpanded(true);
allSNodeTextItem.getChildren().add(storeyNodeTextItem);
createGeometryNodes(storey, storeyNodeTextItem);
createBoundarySurfaceNodes(storey.getBoundarySurfaces(), storeyNodeTextItem);
}
}
public void createBuildingUnitNodes(Building ab, TreeItem<Renderable> root) {
List<BuildingUnit> buildingUnits = ab.getBuildingUnits();
if (buildingUnits.isEmpty()) {
return;
}
AllBuildingUnitsNode allSNode = new AllBuildingUnitsNode(buildingUnits);
TreeItem<Renderable> allSNodeTextItem = new TreeItem<>(allSNode);
root.getChildren().add(allSNodeTextItem);
for (BuildingUnit buildingUnit : buildingUnits) {
BuildingUnitNode buildingUnitNode = new BuildingUnitNode(buildingUnit);
TreeItem<Renderable> storeyNodeTextItem = new TreeItem<>(buildingUnitNode);
storeyNodeTextItem.setExpanded(true);
allSNodeTextItem.getChildren().add(storeyNodeTextItem);
createGeometryNodes(buildingUnit, storeyNodeTextItem);
createBoundarySurfaceNodes(buildingUnit.getBoundarySurfaces(), storeyNodeTextItem);
}
}
private void createBuildingFurnitureNodes(Building ab, TreeItem<Renderable> root) {
createFurnitureNodes(ab.getBuildingRoomFurnitureList(), root);
}
private void createFurnitureNodes(List<? extends AbstractFurniture> furniture, TreeItem<Renderable> root) {
if (furniture.isEmpty()) {
return;
}
AllFurnitureNode allFnNode = new AllFurnitureNode(furniture);
TreeItem<Renderable> allFnNodeTextItem = new TreeItem<>(allFnNode);
root.getChildren().add(allFnNodeTextItem);
for (AbstractFurniture fn : furniture) {
FurnitureNode fnNode = new FurnitureNode(fn);
TreeItem<Renderable> fnNodeTextItem = new TreeItem<>(fnNode);
fnNodeTextItem.setExpanded(true);
allFnNodeTextItem.getChildren().add(fnNodeTextItem);
createGeometryNodes(fn, fnNodeTextItem);
createBoundarySurfaceNodes(fn.getBoundarySurfaceList(), fnNodeTextItem);
}
}
private void createBoundarySurfaceNodes(List<BoundarySurface> bsList, TreeItem<Renderable> root) {
if (bsList.isEmpty()) {
return;
......@@ -636,8 +733,10 @@ public class CityDoctorController {
updateTree(mainWindow.getVegetationView().getRoot());
updateTree(mainWindow.getBridgeView().getRoot());
updateTree(mainWindow.getTerrainView().getRoot());
updateTree(mainWindow.getCityFurnitureView().getRoot());
updateTree(mainWindow.getTransportationView().getRoot());
updateTree(mainWindow.getWaterView().getRoot());
updateTree(mainWindow.getOtherObjectsView().getRoot());
renderer.updateErrors();
}
......@@ -682,6 +781,8 @@ public class CityDoctorController {
addErrorStats(stats, model.getTransportation());
addErrorStats(stats, model.getVegetation());
addErrorStats(stats, model.getWater());
addErrorStats(stats, model.getCityFurniture());
addErrorStats(stats, model.getGenericCityObjects());
return stats;
}
......@@ -773,6 +874,11 @@ public class CityDoctorController {
cos = filterFeatures(searchString, model.getTransportation());
chunkCounter = transportationChunkNr;
break;
case TUNNEL:
view = mainWindow.getTunnelView();
cos = model.getTunnels();
chunkCounter = tunnelChunkNr;
break;
case WATER:
view = mainWindow.getWaterView();
cos = filterFeatures(searchString, model.getWater());
......@@ -783,6 +889,16 @@ public class CityDoctorController {
cos = filterFeatures(searchString, model.getLand());
chunkCounter = landChunkNr;
break;
case CITY_FURNITURE:
view = mainWindow.getCityFurnitureView();
cos = filterFeatures(searchString, model.getCityFurniture());
chunkCounter = cityFurnitureChunkNr;
break;
case GENERIC_CITY_OBJECT:
view = mainWindow.getOtherObjectsView();
cos = filterFeatures(searchString, model.getGenericCityObjects());
chunkCounter = otherObjectsChunkNr;
break;
default:
throw new IllegalStateException("Unknown selected feature tab");
}
......@@ -840,6 +956,11 @@ public class CityDoctorController {
cos = model.getTransportation();
chunkCounter = transportationChunkNr;
break;
case TUNNEL:
view = mainWindow.getTunnelView();
cos = model.getTunnels();
chunkCounter = tunnelChunkNr;
break;
case WATER:
view = mainWindow.getWaterView();
cos = model.getWater();
......@@ -850,6 +971,16 @@ public class CityDoctorController {
cos = model.getLand();
chunkCounter = landChunkNr;
break;
case CITY_FURNITURE:
view = mainWindow.getCityFurnitureView();
cos = model.getCityFurniture();
chunkCounter = cityFurnitureChunkNr;
break;
case GENERIC_CITY_OBJECT:
view = mainWindow.getOtherObjectsView();
cos = model.getGenericCityObjects();
chunkCounter = otherObjectsChunkNr;
break;
default:
throw new IllegalStateException("Unknown selected feature tab");
}
......@@ -921,6 +1052,22 @@ public class CityDoctorController {
fillTreeViewWithErrorCityObjects(mainWindow.getTerrainView(), model.getLand(), landChunkNr);
}
public void fillTreeViewWithErrorCityFurniture() {
if (model == null) {
return;
}
fillTreeViewWithErrorCityObjects(mainWindow.getCityFurnitureView(),
model.getCityFurniture(), cityFurnitureChunkNr);
}
public void fillTreeViewWithErrorOtherObjects() {
if (model == null) {
return;
}
fillTreeViewWithErrorCityObjects(mainWindow.getOtherObjectsView(),
model.getGenericCityObjects(), otherObjectsChunkNr);
}
public void fillTreeViewWithErrorTransportation() {
if (model == null) {
return;
......@@ -929,6 +1076,13 @@ public class CityDoctorController {
transportationChunkNr);
}
public void fillTreeViewWithErrorTunnel() {
if (model == null) {
return;
}
fillTreeViewWithErrorCityObjects(mainWindow.getTunnelView(), model.getTunnels(), tunnelChunkNr);
}
public void fillTreeViewWithErrorWater() {
if (model == null) {
return;
......@@ -985,6 +1139,14 @@ public class CityDoctorController {
buildWater(model);
updateTree(mainWindow.getWaterView().getRoot());
break;
case CITY_FURNITURE:
buildCityFurniture(model);
updateTree(mainWindow.getCityFurnitureView().getRoot());
break;
case GENERIC_CITY_OBJECT:
buildOtherCityObjects(model);
updateTree(mainWindow.getOtherObjectsView().getRoot());
break;
default:
throw new IllegalStateException();
}
......@@ -1029,6 +1191,7 @@ public class CityDoctorController {
Settings.set(Settings.LAST_OPEN_FOLDER, f.getParent());
try {
storeModel(f, saveWithQualityAde);
logger.info("Saving successful");
} catch (CityDoctorWriteException e) {
mainWindow.showExceptionDialog(e);
}
......@@ -1072,6 +1235,12 @@ public class CityDoctorController {
case WATER:
fillTreeViewWithErrorWater();
break;
case CITY_FURNITURE:
fillTreeViewWithErrorCityFurniture();
break;
case GENERIC_CITY_OBJECT:
fillTreeViewWithErrorOtherObjects();
break;
default:
throw new IllegalStateException("Unknown selected feature tab: " + mainWindow.getSelectedTab());
}
......@@ -1083,4 +1252,13 @@ public class CityDoctorController {
public ParserConfiguration getCurrentConfig() {
return currentConfig;
}
public void setOriginBB(BoundingBox origin) {
this.originBB = origin;
}
public BoundingBox getOriginBB() {
return originBB;
}
}
package de.hft.stuttgart.citydoctor2.gui;
import java.io.IOException;
import java.io.InputStream;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import de.hft.stuttgart.citydoctor2.gui.tree.Renderable;
import de.hft.stuttgart.citydoctor2.utils.Localization;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.Tooltip;
import javafx.scene.control.TreeView;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.io.InputStream;
public class MainToolBar {
......@@ -49,6 +43,18 @@ public class MainToolBar {
@FXML
private ImageView showWorldImageView;
@FXML
private ToggleButton hideRoofBtn;
@FXML
private ImageView hideRoofView;
@FXML
private Button resetCameraBtn;
@FXML
private ImageView resetCameraView;
@FXML
private Button schematronBtn;
......@@ -139,7 +145,8 @@ public class MainToolBar {
setupLodButtons();
setupAboutButton();
setupReportButton();
setupResetCameraButton();
setupHideRoofButton();
loadImages();
gridButton.setOnAction(ae -> renderer.showWireFrame(gridButton.isSelected()));
......@@ -156,6 +163,7 @@ public class MainToolBar {
}
controller.showWorld();
});
showWorldBtn.setTooltip(new Tooltip(Localization.getText("MainToolBar.showWorld")));
}
private void loadImages() {
......@@ -208,6 +216,14 @@ public class MainToolBar {
Image img = new Image(inStream);
saveView.setImage(img);
}
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/reset_camera.png")) {
Image img = new Image(inStream);
resetCameraView.setImage(img);
}
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/hide_roof.png")) {
Image img = new Image(inStream);
hideRoofView.setImage(img);
}
} catch (IOException e) {
// ignore close exception
}
......@@ -298,6 +314,27 @@ public class MainToolBar {
});
}
private void setupResetCameraButton() {
resetCameraBtn.setDisable(true);
resetCameraBtn.setTooltip(new Tooltip(Localization.getText("MainToolBar.resetCamera")));
resetCameraBtn.setOnAction(ae -> mainWindow.resetCamera());
}
private void setupHideRoofButton() {
hideRoofBtn.setDisable(true);
hideRoofBtn.setSelected(false);
hideRoofBtn.setTooltip(new Tooltip(Localization.getText("MainToolBar.hideRoof")));
hideRoofBtn.setOnAction(ae -> {
if (hideRoofBtn.isSelected()) {
renderer.hideRoofs();
} else {
renderer.showRoofs();
}
});
}
public Button getCheckButton() {
return checkBtn;
}
......@@ -310,6 +347,10 @@ public class MainToolBar {
return cullingButton;
}
public Button getSaveButton() {
return saveBtn;
}
public Button getWriteReportButton() {
return reportBtn;
}
......@@ -330,6 +371,10 @@ public class MainToolBar {
return lod4Btn;
}
public ToggleButton getHideRoofBtn() {
return hideRoofBtn;
}
public Button getWorldBtn() {
return showWorldBtn;
}
......@@ -338,6 +383,10 @@ public class MainToolBar {
return saveBtn;
}
public Button getResetCameraBtn() {
return resetCameraBtn;
}
public HBox getToolBar() {
return toolBar;
}
......
package de.hft.stuttgart.citydoctor2.gui;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.Timer;
import java.util.TimerTask;
import javax.imageio.ImageIO;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import de.hft.stuttgart.citydoctor2.CityDoctorValidation;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.datastructure.BoundingBox;
......@@ -34,35 +19,9 @@ import javafx.beans.value.ChangeListener;
import javafx.embed.swing.SwingFXUtils;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.AmbientLight;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.SubScene;
import javafx.scene.control.Alert;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.RadioButton;
import javafx.scene.control.SplitPane;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.control.ToolBar;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
......@@ -77,6 +36,15 @@ import javafx.scene.layout.Priority;
import javafx.scene.paint.Color;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.*;
public class MainWindow extends Application {
......@@ -95,6 +63,9 @@ public class MainWindow extends Application {
@FXML
private TreeView<Renderable> transView;
@FXML
private TreeView<Renderable> tunnelView;
@FXML
private TreeView<Renderable> bridgeView;
......@@ -104,6 +75,15 @@ public class MainWindow extends Application {
@FXML
private TreeView<Renderable> terrainView;
@FXML
private TreeView<Renderable> cityFurnitureView;
@FXML
private TreeView<Renderable> attributeView;
@FXML
TreeView<Renderable> otherObjectsView;
@FXML
private TreeView<Renderable> polygonView;
......@@ -170,6 +150,9 @@ public class MainWindow extends Application {
@FXML
private Tab transportationTab;
@FXML
private Tab tunnelTab;
@FXML
private Tab bridgeTab;
......@@ -179,6 +162,12 @@ public class MainWindow extends Application {
@FXML
private Tab terrainTab;
@FXML
private Tab cityFurnitureTab;
@FXML
private Tab otherObjectsTab;
@FXML
private Tab errorsTab;
......@@ -191,6 +180,9 @@ public class MainWindow extends Application {
@FXML
private Tab verticesTab;
@FXML
private Tab attributeTab;
@FXML
private Tab logTab;
......@@ -218,6 +210,9 @@ public class MainWindow extends Application {
@FXML
private Label availableLabel;
private Image north;
private Image northFlip;
private Group meshGroup;
private Group world;
......@@ -250,6 +245,7 @@ public class MainWindow extends Application {
private MainToolBar mainToolBar;
private SubScene geomScene;
private ImageView northArrow;
private static boolean loadFileAtStartup = false;
private static String inputFile;
......@@ -414,9 +410,12 @@ public class MainWindow extends Application {
buildingsTab.setText(Localization.getText("MainWindow.buildingsTab"));
vegetationTab.setText(Localization.getText("MainWindow.vegetationTab"));
transportationTab.setText(Localization.getText("MainWindow.transportationTab"));
tunnelTab.setText(Localization.getText("MainWindow.tunnelTab"));
bridgeTab.setText(Localization.getText("MainWindow.bridgeTab"));
waterTab.setText(Localization.getText("MainWindow.waterTab"));
terrainTab.setText(Localization.getText("MainWindow.terrainTab"));
cityFurnitureTab.setText(Localization.getText("MainWindow.cityfurnitureTab"));
otherObjectsTab.setText(Localization.getText("MainWindow.otherObjectsTab"));
viewLabel.setText(Localization.getText("MainWindow.viewLabel"));
showLabel.setText(Localization.getText("MainWindow.showLabel"));
searchLabel.setText(Localization.getText("MainWindow.searchLabel"));
......@@ -426,6 +425,7 @@ public class MainWindow extends Application {
polygonsTab.setText(Localization.getText("MainWindow.polygonsTab"));
edgesTab.setText(Localization.getText("MainWindow.edgesTab"));
verticesTab.setText(Localization.getText("MainWindow.verticesTab"));
attributeTab.setText(Localization.getText("MainWindow.attributeTab"));
logTab.setText(Localization.getText("MainWindow.logTab"));
globalErrorsTab.setText(Localization.getText("MainWindow.globalErrorsTab"));
memoryLabel.setText(Localization.getText("MainWindow.memoryLabel"));
......@@ -624,20 +624,77 @@ public class MainWindow extends Application {
selectedTab = FeatureType.TRANSPORTATION;
break;
case 3:
selectedTab = FeatureType.BRIDGE;
selectedTab = FeatureType.TUNNEL;
break;
case 4:
selectedTab = FeatureType.WATER;
selectedTab = FeatureType.BRIDGE;
break;
case 5:
selectedTab = FeatureType.WATER;
break;
case 6:
selectedTab = FeatureType.LAND;
break;
case 7:
selectedTab = FeatureType.CITY_FURNITURE;
break;
case 8:
selectedTab = FeatureType.GENERIC_CITY_OBJECT;
break;
default:
throw new IllegalStateException("Unknown tab index: " + index);
}
});
}
public void setDisableOfFeatureTab(FeatureType featureType, boolean value) {
switch (featureType) {
case BUILDING:
buildingsTab.setDisable(value);
break;
case VEGETATION:
vegetationTab.setDisable(value);
break;
case TRANSPORTATION:
transportationTab.setDisable(value);
break;
case TUNNEL:
tunnelTab.setDisable(value);
break;
case BRIDGE:
bridgeTab.setDisable(value);
break;
case WATER:
waterTab.setDisable(value);
break;
case LAND:
terrainTab.setDisable(value);
break;
case CITY_FURNITURE:
cityFurnitureTab.setDisable(value);
break;
case GENERIC_CITY_OBJECT:
otherObjectsTab.setDisable(value);
break;
default:
throw new IllegalArgumentException("Unknown feature type: " + featureType);
}
}
public void activateAllTabs() {
buildingsTab.setDisable(false);
vegetationTab.setDisable(false);
transportationTab.setDisable(false);
tunnelTab.setDisable(false);
bridgeTab.setDisable(false);
waterTab.setDisable(false);
terrainTab.setDisable(false);
cityFurnitureTab.setDisable(false);
otherObjectsTab.setDisable(false);
}
public void resetSearchBar() {
searchField.setText("");
}
......@@ -696,11 +753,16 @@ public class MainWindow extends Application {
vegetationView.setShowRoot(true);
setupSelectListener(vegetationView);
vegetationView.setCellFactory(param -> new RenderableTreeCell());
vegetationView.setContextMenu(cMenu);
transView.setShowRoot(true);
setupSelectListener(transView);
transView.setCellFactory(param -> new RenderableTreeCell());
tunnelView.setShowRoot(true);
setupSelectListener(tunnelView);
tunnelView.setCellFactory(param -> new RenderableTreeCell());
bridgeView.setShowRoot(true);
setupSelectListener(bridgeView);
bridgeView.setCellFactory(param -> new RenderableTreeCell());
......@@ -713,6 +775,14 @@ public class MainWindow extends Application {
setupSelectListener(terrainView);
terrainView.setCellFactory(param -> new RenderableTreeCell());
cityFurnitureView.setShowRoot(true);
setupSelectListener(cityFurnitureView);
cityFurnitureView.setCellFactory(param -> new RenderableTreeCell());
otherObjectsView.setShowRoot(true);
setupSelectListener(otherObjectsView);
otherObjectsView.setCellFactory(param -> new RenderableTreeCell());
setupSelectListener(vertexView);
vertexView.setRoot(new TreeItem<>());
vertexView.setCellFactory(param -> new RenderableTreeCell());
......@@ -724,6 +794,10 @@ public class MainWindow extends Application {
setupSelectListener(edgeView);
edgeView.setRoot(new TreeItem<>());
edgeView.setCellFactory(param -> new RenderableTreeCell());
setupSelectListener(attributeView);
attributeView.setRoot(new TreeItem<>());
attributeView.setCellFactory(param -> new RenderableTreeCell());
}
private void setupSelectListener(TreeView<Renderable> view) {
......@@ -766,9 +840,18 @@ public class MainWindow extends Application {
meshGroup = new Group();
world.getChildren().add(meshGroup);
north = new Image(getClass().getResourceAsStream("icons/north.png"), 50, 50, true, true);
northFlip = new Image(getClass().getResourceAsStream("icons/north_flip.png"), 50, 50, true, true);
northArrow = new ImageView(north);
northArrow.setFitHeight(50);
northArrow.setFitWidth(50);
northArrow.setX(10);
northArrow.setY(10);
meshView.getChildren().add(northArrow);
northArrow.setVisible(false);
AmbientLight al = new AmbientLight(Color.WHITE);
root.getChildren().add(al);
buildCamera();
cameraXRotation.setAxis(Rotate.X_AXIS);
cameraZRotation.setAxis(Rotate.Z_AXIS);
......@@ -786,6 +869,10 @@ public class MainWindow extends Application {
dragX = me.getScreenX();
dragY = me.getScreenY();
}
if (me.getButton() == MouseButton.SECONDARY) {
dragX = me.getScreenX();
dragY = me.getScreenY();
}
});
meshView.setOnScroll(se -> {
......@@ -810,6 +897,17 @@ public class MainWindow extends Application {
cameraZRotation.setAngle(cameraXRot);
cameraXRotation.setAngle(cameraYRot);
alignNorthArrow();
}
if (me.getButton() == MouseButton.SECONDARY) {
double translationSpeed = Math.abs(camera.getTranslateZ()) / 1000;
double deltaX = me.getScreenX() - dragX;
double deltaY = me.getScreenY() - dragY;
dragX = me.getScreenX();
dragY = me.getScreenY();
camera.setTranslateX(camera.getTranslateX() - deltaX * translationSpeed);
camera.setTranslateY(camera.getTranslateY() - deltaY * translationSpeed);
}
});
}
......@@ -823,6 +921,39 @@ public class MainWindow extends Application {
cameraXRotation.setAngle(cameraYRot);
}
public void alignNorthArrow() {
double absRotZ = cameraZRotation.getAngle() - 360 * Math.floor(cameraZRotation.getAngle() / 360);
double absRotX = cameraXRotation.getAngle() - 360 * Math.floor(cameraXRotation.getAngle() / 360);
double northRot;
if (80 <= absRotX && absRotX <= 260) {
northRot = 360 - absRotZ;
if (northArrow.getImage() != north) {
northArrow.setImage(north);
}
} else {
//Camera is below horizon line -> flip north arrow horizontally
northRot = (absRotZ + 180) % 360;
if (northArrow.getImage() != northFlip) {
northArrow.setImage(northFlip);
}
}
northArrow.setRotate(northRot);
}
public void resetCamera() {
cameraXRot = CAMERA_INITIAL_X_ANGLE;
cameraYRot = CAMERA_INITIAL_Y_ANGLE;
cameraZRotation.setAngle(cameraXRot);
cameraXRotation.setAngle(cameraYRot);
alignNorthArrow();
camera.setTranslateX(0);
camera.setTranslateY(0);
if (controller.getOriginBB() != null) {
zoomOutForBoundingBox(controller.getOriginBB());
}
}
public void addFileNameToTitle(String fileName) {
String version = Localization.getText(Localization.VERSION);
stage.setTitle("CityDoctor " + version + " - " + fileName);
......@@ -840,6 +971,10 @@ public class MainWindow extends Application {
return transView;
}
public TreeView<Renderable> getTunnelView() {
return tunnelView;
}
public TreeView<Renderable> getBridgeView() {
return bridgeView;
}
......@@ -852,6 +987,18 @@ public class MainWindow extends Application {
return terrainView;
}
public TreeView<Renderable> getCityFurnitureView() {
return cityFurnitureView;
}
public TreeView<Renderable> getAttributeView() {
return attributeView;
}
public TreeView<Renderable> getOtherObjectsView() {
return otherObjectsView;
}
public TreeView<Renderable> getPolygonsView() {
return polygonView;
}
......@@ -896,12 +1043,16 @@ public class MainWindow extends Application {
buildingsView.getSelectionModel().clearSelection();
vegetationView.getSelectionModel().clearSelection();
transView.getSelectionModel().clearSelection();
tunnelView.getSelectionModel().clearSelection();
waterView.getSelectionModel().clearSelection();
terrainView.getSelectionModel().clearSelection();
cityFurnitureView.getSelectionModel().clearSelection();
otherObjectsView.getSelectionModel().clearSelection();
bridgeView.getSelectionModel().clearSelection();
polygonView.getSelectionModel().clearSelection();
edgeView.getSelectionModel().clearSelection();
vertexView.getSelectionModel().clearSelection();
attributeView.getSelectionModel().clearSelection();
errorView.getSelectionModel().clearSelection();
}
......@@ -925,6 +1076,18 @@ public class MainWindow extends Application {
return mainToolBar.getWorldBtn();
}
public Button getResetCameraBtn() {
return mainToolBar.getResetCameraBtn();
}
public ToggleButton getHideRoofBtn() {
return mainToolBar.getHideRoofBtn();
}
public ImageView getNorthArrow() {
return northArrow;
}
public Button getSaveBtn() {
return mainToolBar.getSaveBtn();
}
......@@ -949,7 +1112,10 @@ public class MainWindow extends Application {
double d = longestSide / Math.tan(Math.toRadians(30) / 2);
translateZ = -d;
camera.setTranslateZ(translateZ);
camera.setTranslateX(0);
camera.setTranslateY(0);
highlightController.changeScaling(-translateZ);
controller.setOriginBB(b);
}
public MainToolBar getMainToolbar() {
......
package de.hft.stuttgart.citydoctor2.gui;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.Checkable;
import de.hft.stuttgart.citydoctor2.datastructure.AbstractBuilding;
import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface;
import de.hft.stuttgart.citydoctor2.datastructure.BoundingBox;
import de.hft.stuttgart.citydoctor2.datastructure.BridgeConstructiveElement;
import de.hft.stuttgart.citydoctor2.datastructure.BridgeObject;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.Installation;
import de.hft.stuttgart.citydoctor2.datastructure.BuildingPart;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
import de.hft.stuttgart.citydoctor2.datastructure.Edge;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Lod;
import de.hft.stuttgart.citydoctor2.datastructure.Opening;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.ReliefObject;
import de.hft.stuttgart.citydoctor2.datastructure.TinObject;
import de.hft.stuttgart.citydoctor2.datastructure.TransportationObject;
import de.hft.stuttgart.citydoctor2.datastructure.Vegetation;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.datastructure.WaterObject;
import de.hft.stuttgart.citydoctor2.datastructure.*;
import de.hft.stuttgart.citydoctor2.gui.filter.ViewFilter;
import de.hft.stuttgart.citydoctor2.gui.tree.EdgeNode;
import de.hft.stuttgart.citydoctor2.gui.tree.ErrorItemVisitor;
import de.hft.stuttgart.citydoctor2.gui.tree.ErrorNode;
import de.hft.stuttgart.citydoctor2.gui.tree.LinearRingNode;
import de.hft.stuttgart.citydoctor2.gui.tree.PolygonNode;
import de.hft.stuttgart.citydoctor2.gui.tree.Renderable;
import de.hft.stuttgart.citydoctor2.gui.tree.VertexNode;
import de.hft.stuttgart.citydoctor2.gui.tree.*;
import de.hft.stuttgart.citydoctor2.math.Triangle3d;
import javafx.application.Platform;
import javafx.scene.control.TreeItem;
import javafx.scene.paint.Color;
import javafx.scene.shape.CullFace;
import javafx.scene.shape.DrawMode;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.util.*;
public class Renderer {
......@@ -57,7 +24,7 @@ public class Renderer {
private TriangulatedGeometry currentTriGeom;
private Geometry currentGeometry;
private CullFace currentCulling = CullFace.BACK;
private CullFace currentCulling = CullFace.NONE;
private DrawMode currentDrawMode = DrawMode.FILL;
private MainWindow mainWindow;
......@@ -67,7 +34,7 @@ public class Renderer {
private LoadingInfoDialog loadingDialog;
private List<ViewFilter> lodFilters = new ArrayList<>();
private ViewFilter roofFilter;
private Runnable refresher;
private Runnable errorUpdater;
......@@ -119,6 +86,25 @@ public class Renderer {
return geom.getLod() == Lod.LOD4;
}
});
roofFilter = new ViewFilter() {
@Override
public boolean allowedToUse(CityObject co, Geometry geom) {
if (!this.isEnabled()) {
return true;
}
return this.useGeometry(co, geom);
}
@Override
public boolean useGeometry(CityObject co, Geometry geom) {
if (co instanceof BoundarySurface bs) {
return bs.getType() != BoundarySurfaceType.ROOF;
}
return true;
}
};
roofFilter.setEnable(false);
}
public void enableLod1() {
......@@ -177,6 +163,20 @@ public class Renderer {
}
}
public void hideRoofs() {
roofFilter.setEnable(true);
if (refresher != null) {
refresher.run();
}
}
public void showRoofs() {
roofFilter.setEnable(false);
if (refresher != null) {
refresher.run();
}
}
public void render(Building building) {
refresher = () -> {
Set<ConcretePolygon> setupBuildingPolygons = setupBuildingPolygons(building);
......@@ -185,6 +185,7 @@ public class Renderer {
Platform.runLater(() -> {
errorUpdater = () -> displayErrors(building);
errorUpdater.run();
addGenericAttributesToView(building);
});
};
refresher.run();
......@@ -208,6 +209,18 @@ public class Renderer {
}
}
}
for (BuildingRoom br : b.getBuildingRooms()) {
addPolygons(br, polygons);
for (BoundarySurface bs : br.getBoundarySurfaces()) {
addPolygons(bs, polygons);
}
}
for (BuildingRoomFurniture brf : b.getBuildingRoomFurnitureList()) {
addPolygons(brf, polygons);
for (BoundarySurface bs : brf.getBoundarySurfaceList()) {
addPolygons(bs, polygons);
}
}
for (BuildingPart bp : b.getBuildingParts()) {
polygons.addAll(setupBuildingPartPolygons(bp));
}
......@@ -222,6 +235,7 @@ public class Renderer {
Platform.runLater(() -> {
errorUpdater = () -> displayErrors(bp);
errorUpdater.run();
addGenericAttributesToView(bp);
});
};
refresher.run();
......@@ -248,6 +262,178 @@ public class Renderer {
return polygons;
}
public void render(AbstractRoom room) {
refresher = () -> {
Set<ConcretePolygon> setupRoomPolygons = setupRoomPolygons(room);
mainWindow.zoomOutForBoundingBox(BoundingBox.of(setupRoomPolygons));
render(setupRoomPolygons);
Platform.runLater(() -> {
errorUpdater = () -> displayErrors(room);
errorUpdater.run();
addGenericAttributesToView(room);
});
};
refresher.run();
}
private Set<ConcretePolygon> setupRoomPolygons(AbstractRoom room) {
Set<ConcretePolygon> polygons = new HashSet<>();
addPolygons(room, polygons);
for (BoundarySurface bs : room.getBoundarySurfaces()) {
addPolygons(bs, polygons);
for (Opening op : bs.getOpenings()) {
addPolygons(op, polygons);
}
}
return polygons;
}
public void render(AbstractFurniture furniture) {
refresher = () -> {
Set<ConcretePolygon> setupFurniturePolygons = setupFurniturePolygons(furniture);
mainWindow.zoomOutForBoundingBox(BoundingBox.of(setupFurniturePolygons));
render(setupFurniturePolygons);
Platform.runLater(() -> {
errorUpdater = () -> displayErrors(furniture);
errorUpdater.run();
addGenericAttributesToView(furniture);
});
};
refresher.run();
}
private Set<ConcretePolygon> setupFurniturePolygons(AbstractFurniture furniture) {
Set<ConcretePolygon> polygons = new HashSet<>();
addPolygons(furniture, polygons);
for (BoundarySurface bs : furniture.getBoundarySurfaceList()) {
addPolygons(bs, polygons);
for (Opening op : bs.getOpenings()) {
addPolygons(op, polygons);
}
}
return polygons;
}
public void render(Storey storey) {
refresher = () -> {
Set<ConcretePolygon> setupStoreyPolygons = setupStoreyPolygons(storey);
mainWindow.zoomOutForBoundingBox(BoundingBox.of(setupStoreyPolygons));
render(setupStoreyPolygons);
Platform.runLater(() -> {
errorUpdater = () -> displayErrors(storey);
errorUpdater.run();
addGenericAttributesToView(storey);
});
};
refresher.run();
}
private Set<ConcretePolygon> setupStoreyPolygons(Storey storey) {
Set<ConcretePolygon> polygons = new HashSet<>();
addPolygons(storey, polygons);
for (BoundarySurface bs : storey.getBoundarySurfaces()) {
addPolygons(bs, polygons);
for (Opening op : bs.getOpenings()) {
addPolygons(op, polygons);
}
}
return polygons;
}
public void render(BuildingUnit buildingUnit) {
refresher = () -> {
Set<ConcretePolygon> setupBuildingUnitPolgons = setupBuildingUnitPolygons(buildingUnit);
mainWindow.zoomOutForBoundingBox(BoundingBox.of(setupBuildingUnitPolgons));
render(setupBuildingUnitPolgons);
Platform.runLater(() -> {
errorUpdater = () -> displayErrors(buildingUnit);
errorUpdater.run();
addGenericAttributesToView(buildingUnit);
});
};
refresher.run();
}
private Set<ConcretePolygon> setupBuildingUnitPolygons(BuildingUnit buildingUnit) {
Set<ConcretePolygon> polygons = new HashSet<>();
addPolygons(buildingUnit, polygons);
for (BoundarySurface bs : buildingUnit.getBoundarySurfaces()) {
addPolygons(bs, polygons);
for (Opening op : bs.getOpenings()) {
addPolygons(op, polygons);
}
}
return polygons;
}
public void render(Tunnel tunnel) {
refresher = () -> {
Set<ConcretePolygon> setupTunnelPolygons = setupTunnelPolygons(tunnel);
mainWindow.zoomOutForBoundingBox(BoundingBox.of(setupTunnelPolygons));
render(setupTunnelPolygons);
Platform.runLater(() -> {
errorUpdater = () -> displayErrors(tunnel);
errorUpdater.run();
addGenericAttributesToView(tunnel);
});
};
refresher.run();
}
private Set<ConcretePolygon> setupTunnelPolygons(Tunnel tunnel) {
Set<ConcretePolygon> polygons = new HashSet<>();
addPolygons(tunnel, polygons);
for (BoundarySurface bs : tunnel.getBoundarySurfaces()) {
addPolygons(bs, polygons);
}
for (Installation ti : tunnel.getTunnelInstallations()) {
addPolygons(ti, polygons);
for (BoundarySurface bs : ti.getBoundarySurfaces()) {
addPolygons(bs, polygons);
for (Opening op : bs.getOpenings()) {
addPolygons(op, polygons);
}
}
}
for (TunnelHollow th : tunnel.getTunnelHollows()) {
addPolygons(th, polygons);
for (BoundarySurface bs : th.getBoundarySurfaces()) {
addPolygons(bs, polygons);
}
}
for (TunnelFurniture tf : tunnel.getTunnelFurnitureList()) {
addPolygons(tf, polygons);
for (BoundarySurface bs : tf.getBoundarySurfaceList()) {
addPolygons(bs, polygons);
}
}
for (TunnelPart tp : tunnel.getTunnelParts()) {
polygons.addAll(setupTunnelPartPolygons(tp));
}
return polygons;
}
private Set<ConcretePolygon> setupTunnelPartPolygons(TunnelPart tp) {
Set<ConcretePolygon> polygons = new HashSet<>();
addPolygons(tp, polygons);
for (BoundarySurface bs : tp.getBoundarySurfaces()) {
addPolygons(bs, polygons);
for (Opening op : bs.getOpenings()) {
addPolygons(op, polygons);
}
}
for (Installation bi : tp.getTunnelInstallations()) {
addPolygons(bi, polygons);
for (BoundarySurface bs : bi.getBoundarySurfaces()) {
addPolygons(bs, polygons);
for (Opening op : bs.getOpenings()) {
addPolygons(op, polygons);
}
}
}
return polygons;
}
public void render(BridgeObject bridge) {
refresher = () -> {
Set<ConcretePolygon> setupBridgePolygons = setupBridgePolygons(bridge);
......@@ -256,6 +442,7 @@ public class Renderer {
Platform.runLater(() -> {
errorUpdater = () -> displayErrors(bridge);
errorUpdater.run();
addGenericAttributesToView(bridge);
});
};
refresher.run();
......@@ -290,6 +477,7 @@ public class Renderer {
Platform.runLater(() -> {
errorUpdater = () -> displayErrors(co);
errorUpdater.run();
addGenericAttributesToView(co);
});
};
refresher.run();
......@@ -303,6 +491,7 @@ public class Renderer {
Platform.runLater(() -> {
errorUpdater = () -> displayErrors(relief);
errorUpdater.run();
addGenericAttributesToView(relief);
});
};
refresher.run();
......@@ -325,6 +514,7 @@ public class Renderer {
Platform.runLater(() -> {
errorUpdater = () -> displayErrors(bi);
errorUpdater.run();
addGenericAttributesToView(bi);
});
};
refresher.run();
......@@ -342,6 +532,52 @@ public class Renderer {
return polygons;
}
public void render(CityFurniture cf) {
refresher = () -> {
Set<ConcretePolygon> setupCityFurniturePolygons = setupCityFurniturePolygons(cf);
mainWindow.zoomOutForBoundingBox(BoundingBox.of(setupCityFurniturePolygons));
render(setupCityFurniturePolygons);
Platform.runLater(() -> {
errorUpdater = () -> displayErrors(cf);
errorUpdater.run();
addGenericAttributesToView(cf);
});
};
refresher.run();
}
private Set<ConcretePolygon> setupCityFurniturePolygons(CityFurniture cf) {
Set<ConcretePolygon> polygons = new HashSet<>();
addPolygons(cf, polygons);
return polygons;
}
public void render(GenericCityObject gco) {
refresher = () -> {
Set<ConcretePolygon> setupGenericCityObjectPolygons = setupGenericCityObjectPolygons(gco);
mainWindow.zoomOutForBoundingBox(BoundingBox.of(setupGenericCityObjectPolygons));
render(setupGenericCityObjectPolygons);
Platform.runLater(() -> {
errorUpdater = () -> displayErrors(gco);
errorUpdater.run();
addGenericAttributesToView(gco);
});
};
refresher.run();
}
private Set<ConcretePolygon> setupGenericCityObjectPolygons(GenericCityObject gco) {
Set<ConcretePolygon> polygons = new HashSet<>();
addPolygons(gco, polygons);
for (BoundarySurface bs : gco.getBoundarySurfaces()) {
addPolygons(bs, polygons);
for (Opening op : bs.getOpenings()) {
addPolygons(op, polygons);
}
}
return polygons;
}
public void render(BoundarySurface bs) {
refresher = () -> {
Set<ConcretePolygon> setupBoundarySurfacePolygons = setupBoundarySurfacePolygons(bs);
......@@ -350,6 +586,7 @@ public class Renderer {
Platform.runLater(() -> {
errorUpdater = () -> displayErrors(bs);
errorUpdater.run();
addGenericAttributesToView(bs);
});
};
refresher.run();
......@@ -380,10 +617,12 @@ public class Renderer {
}
}
if (used) {
if (roofFilter.allowedToUse(co, geom)) {
addConcretePolygons(polygons, geom);
}
}
}
}
private void displayErrors(Checkable c) {
if (!c.isValidated()) {
......@@ -423,6 +662,7 @@ public class Renderer {
currentGeometry = geom;
}
addGeometryDataToView(geom);
addGenericAttributesToView(geom.getParent());
mainWindow.zoomOutForBoundingBox(BoundingBox.of(geom.getPolygons()));
errorUpdater = () -> displayErrors(geom);
errorUpdater.run();
......@@ -443,6 +683,13 @@ public class Renderer {
}
}
private void addGenericAttributesToView(CityObject co) {
clearAttributes();
for (GenericAttribute gen : co.getGenericAttributes()) {
addGenericAttributeToView(gen);
}
}
private void addVertexToView(Vertex v) {
Renderable cf = new VertexNode(v);
TreeItem<Renderable> ti = new TreeItem<>(cf);
......@@ -486,6 +733,12 @@ public class Renderer {
}
}
private void addGenericAttributeToView(GenericAttribute gen) {
GenericAttributeNode genNode = new GenericAttributeNode(gen);
TreeItem<Renderable> ti = new TreeItem<>(genNode);
mainWindow.getAttributeView().getRoot().getChildren().add(ti);
}
private CheckStatus determineCheckStatus(Checkable c) {
if (!c.isValidated()) {
return CheckStatus.NOT_CHECKED;
......@@ -517,13 +770,14 @@ public class Renderer {
Platform.runLater(() -> {
loadingDialog.show();
clearGeometryTrees();
clearAttributes();
});
Thread t = new Thread(() -> {
Set<ConcretePolygon> polygons = new HashSet<>();
for (Building b : objects) {
collectPolygons(polygons, b);
collectBuildingPolygons(polygons, b);
for (BuildingPart bp : b.getBuildingParts()) {
collectPolygons(polygons, bp);
collectBuildingPolygons(polygons, bp);
}
}
currentTriGeom = TriangulatedGeometry.of(polygons);
......@@ -549,6 +803,7 @@ public class Renderer {
Platform.runLater(() -> {
loadingDialog.show();
clearGeometryTrees();
clearAttributes();
});
Thread t = new Thread(() -> {
currentTriGeom = TriangulatedGeometry.of(model, lodFilters);
......@@ -577,13 +832,73 @@ public class Renderer {
}
public void renderBridges(List<BridgeObject> bridges) {
renderCityObjects(bridges, Color.CORAL);
errorUpdater = null;
refresher = () -> {
Platform.runLater(() -> {
loadingDialog.show();
clearGeometryTrees();
clearAttributes();
});
Thread t = new Thread(() -> {
Set<ConcretePolygon> polygons = new HashSet<>();
for (BridgeObject b : bridges) {
collectBridgePolygons(polygons, b);
for (BridgeObject bp : b.getParts()) {
collectBridgePolygons(polygons, bp);
}
}
currentTriGeom = TriangulatedGeometry.of(polygons, Color.CORAL);
errVisitor.setGeometry(currentTriGeom);
Platform.runLater(() -> {
setupRenderState();
mainWindow.zoomOutForBoundingBox(BoundingBox.of(polygons));
loadingDialog.hide();
});
});
t.setUncaughtExceptionHandler((thread, e) -> {
Platform.runLater(() -> loadingDialog.hide());
logger.catching(e);
});
t.start();
};
refresher.run();
}
public void renderWater(List<WaterObject> water) {
renderCityObjects(water, Color.LIGHTSKYBLUE);
}
public void renderCityFurniture(List<CityFurniture> cityFurniture) {
errorUpdater = null;
refresher = () -> {
Platform.runLater(() -> {
loadingDialog.show();
clearGeometryTrees();
clearAttributes();
});
Thread t = new Thread(() -> {
Set<ConcretePolygon> polygons = new HashSet<>();
for (CityFurniture cf : cityFurniture) {
collectCityFurniture(polygons, cf);
}
currentTriGeom = TriangulatedGeometry.of(polygons, Color.BLUEVIOLET);
errVisitor.setGeometry(currentTriGeom);
Platform.runLater(() -> {
setupRenderState();
mainWindow.zoomOutForBoundingBox(BoundingBox.of(polygons));
loadingDialog.hide();
});
});
t.setUncaughtExceptionHandler((thread, e) -> {
Platform.runLater(() -> loadingDialog.hide());
logger.catching(e);
});
t.start();
};
refresher.run();
}
public void renderTerrain(List<CityObject> land) {
renderLandObjects(land, Color.BROWN);
}
......@@ -594,6 +909,7 @@ public class Renderer {
Platform.runLater(() -> {
loadingDialog.show();
clearGeometryTrees();
clearAttributes();
});
Thread t = new Thread(() -> {
Set<ConcretePolygon> polygons = new HashSet<>();
......@@ -626,6 +942,7 @@ public class Renderer {
Platform.runLater(() -> {
loadingDialog.show();
clearGeometryTrees();
clearAttributes();
});
Thread t = new Thread(() -> {
Set<ConcretePolygon> polygons = new HashSet<>();
......@@ -646,7 +963,40 @@ public class Renderer {
refresher.run();
}
private void collectPolygons(Set<ConcretePolygon> polygons, AbstractBuilding ab) {
public void renderTunnels(List<Tunnel> objects) {
errorUpdater = null;
refresher = () -> {
Platform.runLater(() -> {
loadingDialog.show();
clearGeometryTrees();
clearAttributes();
});
Thread t = new Thread(() -> {
Set<ConcretePolygon> polygons = new HashSet<>();
for (Tunnel tunnel : objects) {
collectTunnelPolygons(polygons, tunnel);
for (TunnelPart tp : tunnel.getTunnelParts()) {
collectTunnelPolygons(polygons, tp);
}
}
currentTriGeom = TriangulatedGeometry.of(polygons);
errVisitor.setGeometry(currentTriGeom);
Platform.runLater(() -> {
setupRenderState();
mainWindow.zoomOutForBoundingBox(BoundingBox.of(polygons));
loadingDialog.hide();
});
});
t.setUncaughtExceptionHandler((thread, e) -> {
Platform.runLater(() -> loadingDialog.hide());
logger.catching(e);
});
t.start();
};
refresher.run();
}
private void collectBuildingPolygons(Set<ConcretePolygon> polygons, AbstractBuilding ab) {
addPolygons(ab, polygons);
for (Installation bi : ab.getBuildingInstallations()) {
addPolygons(bi, polygons);
......@@ -657,6 +1007,12 @@ public class Renderer {
}
}
}
for (BuildingRoom br : ab.getBuildingRooms()) {
addPolygons(br, polygons);
for (BoundarySurface bs : br.getBoundarySurfaces()) {
addPolygons(bs, polygons);
}
}
for (BoundarySurface bs : ab.getBoundarySurfaces()) {
addPolygons(bs, polygons);
for (Opening o : bs.getOpenings()) {
......@@ -665,8 +1021,77 @@ public class Renderer {
}
}
private void collectBridgePolygons(Set<ConcretePolygon> polygons, BridgeObject br) {
addPolygons(br, polygons);
for (Installation bi : br.getBridgeInstallations()) {
addPolygons(bi, polygons);
for (BoundarySurface bs : bi.getBoundarySurfaces()) {
addPolygons(bs, polygons);
for (Opening o : bs.getOpenings()) {
addPolygons(o, polygons);
}
}
}
for (BridgeRoom r : br.getBridgeRooms()) {
addPolygons(r, polygons);
for (BoundarySurface bs : r.getBoundarySurfaces()) {
addPolygons(bs, polygons);
}
}
for (BridgeConstructiveElement bce : br.getConstructiveElements()) {
addPolygons(bce, polygons);
for (BoundarySurface bs : bce.getBoundarySurfaces()) {
addPolygons(bs, polygons);
}
}
for (BoundarySurface bs : br.getBoundarySurfaces()) {
addPolygons(bs, polygons);
for (Opening o : bs.getOpenings()) {
addPolygons(o, polygons);
}
}
}
public void collectTunnelPolygons(Set<ConcretePolygon> polygons, AbstractTunnel at) {
addPolygons(at, polygons);
for (Installation ti : at.getTunnelInstallations()) {
addPolygons(ti, polygons);
for (BoundarySurface bs : ti.getBoundarySurfaces()) {
addPolygons(bs, polygons);
for (Opening o : bs.getOpenings()) {
addPolygons(o, polygons);
}
}
}
for (TunnelHollow th : at.getTunnelHollows()) {
addPolygons(th, polygons);
for (BoundarySurface bs : th.getBoundarySurfaces()) {
addPolygons(bs, polygons);
}
}
for (TunnelConstructiveElement tce : at.getTunnelConstructiveElements()) {
addPolygons(tce, polygons);
for (BoundarySurface bs : tce.getBoundarySurfaces()) {
addPolygons(bs, polygons);
}
}
for (BoundarySurface bs : at.getBoundarySurfaces()) {
addPolygons(bs, polygons);
for (Opening o : bs.getOpenings()) {
addPolygons(o, polygons);
}
}
}
private void collectCityFurniture(Set<ConcretePolygon> polygons, CityFurniture cf) {
addPolygons(cf, polygons);
}
private void addConcretePolygons(Set<ConcretePolygon> polygons, Geometry geom) {
for (Polygon p : geom.getPolygons()) {
if (p.getOriginal().getPartOfSurface() != null &&
!roofFilter.allowedToUse(p.getOriginal().getPartOfSurface(), p.getParent())) continue;
polygons.add(p.getOriginal());
}
}
......@@ -709,9 +1134,14 @@ public class Renderer {
Platform.runLater(() -> {
mainWindow.getMeshGroup().getChildren().clear();
clearGeometryTrees();
clearAttributes();
});
}
private void clearAttributes() {
mainWindow.getAttributeView().getRoot().getChildren().clear();
}
public void highlight(Polygon p) {
highlightController.highlight(p, currentTriGeom);
}
......
package de.hft.stuttgart.citydoctor2.gui;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface;
import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurfaceType;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.Installation;
import de.hft.stuttgart.citydoctor2.datastructure.BuildingPart;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.Opening;
import de.hft.stuttgart.citydoctor2.datastructure.OpeningType;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.*;
import de.hft.stuttgart.citydoctor2.gui.filter.ViewFilter;
import de.hft.stuttgart.citydoctor2.math.Triangle3d;
import de.hft.stuttgart.citydoctor2.math.UnitVector3d;
......@@ -24,11 +9,9 @@ import de.hft.stuttgart.citydoctor2.math.Vector3d;
import de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.CullFace;
import javafx.scene.shape.DrawMode;
import javafx.scene.shape.MeshView;
import javafx.scene.shape.TriangleMesh;
import javafx.scene.shape.VertexFormat;
import javafx.scene.shape.*;
import java.util.*;
public class TriangulatedGeometry {
......@@ -105,11 +88,13 @@ public class TriangulatedGeometry {
triGeom.movedBy = triGeom.findCenter(points);
addPolygonDataFromBuildings(model.getBuildings(), triGeom, filters);
addPolygonDataFromCityObjects(model.getBridges(), triGeom, Color.CORAL, filters);
addPolygonDataFromBridges(model.getBridges(), triGeom, filters);
addPolygonDataFromCityObjects(model.getLand(), triGeom, Color.BROWN, filters);
addPolygonDataFromCityObjects(model.getTransportation(), triGeom, Color.YELLOW, filters);
addPolygonDataFromCityObjects(model.getVegetation(), triGeom, Color.LIGHTGREEN, filters);
addPolygonDataFromCityObjects(model.getWater(), triGeom, Color.LIGHTSKYBLUE, filters);
addPolygonDataFromCityObjects(model.getCityFurniture(), triGeom, Color.BLUEVIOLET, filters);
addPolygonDataFromCityObjects(model.getGenericCityObjects(), triGeom, Color.DARKGRAY, filters);
return triGeom;
}
......@@ -130,6 +115,23 @@ public class TriangulatedGeometry {
}
}
private static void addPolygonDataFromBridges(List<BridgeObject> bridges, TriangulatedGeometry triGeom, List<ViewFilter> filters) {
for (BridgeObject b : bridges) {
addPolygonData(b, triGeom, Color.CORAL, filters);
addPolygonDataFromBoundarySurfaces(b.getBoundarySurfaces(), triGeom, filters);
addPolygonDataFromCityObjects(b.getBridgeInstallations(), triGeom, Color.CORAL, filters);
for (Installation bi : b.getBridgeInstallations()) {
addPolygonData(bi, triGeom, Color.CORAL, filters);
addPolygonDataFromCityObjects(bi.getBoundarySurfaces(), triGeom, Color.CORAL, filters);
}
for (BridgeConstructiveElement bce : b.getConstructiveElements()) {
addPolygonData(bce, triGeom, Color.CORAL, filters);
addPolygonDataFromCityObjects(bce.getBoundarySurfaces(), triGeom, Color.CORAL, filters);
}
addPolygonDataFromBridges(b.getParts(), triGeom, filters);
}
}
private static void addPolygonDataFromBoundarySurfaces(List<BoundarySurface> boundarySurfaces,
TriangulatedGeometry triGeom, List<ViewFilter> filters) {
for (BoundarySurface bs : boundarySurfaces) {
......
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.datastructure.BuildingUnit;
import de.hft.stuttgart.citydoctor2.gui.CheckStatus;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
import java.util.List;
public class AllBuildingUnitsNode extends Renderable{
private final List<BuildingUnit> buildingUnits;
public AllBuildingUnitsNode(List<BuildingUnit> buildingUnits) {
this.buildingUnits = buildingUnits;
}
@Override
public String getText() {
return "Building Units";
}
@Override
public void visit(Renderer renderer) {
renderer.clearCurrentRender();
}
@Override
public void refreshTextColor() {
boolean wasChecked = false;
for (BuildingUnit buildingUnit : buildingUnits) {
if (buildingUnit.isValidated()) {
wasChecked = true;
if (buildingUnit.containsAnyError()) {
setStatus(CheckStatus.ERROR);
return;
}
}
}
if (wasChecked) {
setStatus(CheckStatus.OK);
} else {
setStatus(CheckStatus.NOT_CHECKED);
}
}
}
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.datastructure.CityFurniture;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
import java.util.List;
public class AllCityFurnitureNode extends Renderable{
private final List<CityFurniture> cityFurnitures;
public AllCityFurnitureNode(List<CityFurniture> cityFurnitures) {
this.cityFurnitures = cityFurnitures;
}
@Override
public void refreshTextColor() {
// no color changes
}
@Override
public String getText() {
return "CityFurniture";
}
@Override
public void visit(Renderer renderer) {
renderer.clearCurrentRender();
renderer.renderCityFurniture(cityFurnitures);
}
}
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.datastructure.AbstractFurniture;
import de.hft.stuttgart.citydoctor2.gui.CheckStatus;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
import java.util.List;
public class AllFurnitureNode extends Renderable{
private final List<? extends AbstractFurniture> furniture;
public AllFurnitureNode(List<? extends AbstractFurniture> furniture) {
this.furniture = furniture;
}
@Override
public String getText() {
return "Furniture";
}
@Override
public void visit(Renderer renderer) {
renderer.clearCurrentRender();
}
@Override
public void refreshTextColor() {
boolean wasChecked = false;
for (AbstractFurniture af : furniture) {
if (af.isValidated()) {
wasChecked = true;
if (af.containsAnyError()) {
setStatus(CheckStatus.ERROR);
return;
}
}
}
if (wasChecked) {
setStatus(CheckStatus.OK);
} else {
setStatus(CheckStatus.NOT_CHECKED);
}
}
}
......@@ -16,13 +16,21 @@ public class AllOpeningsNode extends Renderable {
@Override
public void refreshTextColor() {
for (Opening bp : openings) {
if (bp.containsAnyError()) {
boolean wasChecked = false;
for (Opening op : openings) {
if (op.isValidated()) {
wasChecked = true;
if (op.containsAnyError()) {
setStatus(CheckStatus.ERROR);
return;
}
}
}
if (wasChecked) {
setStatus(CheckStatus.OK);
} else {
setStatus(CheckStatus.NOT_CHECKED);
}
}
@Override
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment