Commit 6b536067 authored by Riegel's avatar Riegel
Browse files

Add rendering of GenericCityObject objects

Showing with 412 additions and 7 deletions
+412 -7
package de.hft.stuttgart.citydoctor2.datastructure;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.CityGmlUtils;
import de.hft.stuttgart.citydoctor2.utils.CopyHandler;
import de.hft.stuttgart.citydoctor2.utils.Copyable;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.citygml4j.core.model.core.AbstractCityObject;
import org.citygml4j.core.model.core.AbstractSpaceBoundaryProperty;
import org.citygml4j.core.util.geometry.GeometryFactory;
import org.xmlobjects.gml.model.geometry.aggregates.MultiSurface;
import org.xmlobjects.gml.model.geometry.aggregates.MultiSurfaceProperty;
import org.xmlobjects.gml.model.geometry.primitives.Solid;
import org.xmlobjects.gml.model.geometry.primitives.SolidProperty;
import java.io.Serial;
import java.util.ArrayList;
import java.util.List;
/**
*
*/
public class GenericCityObject extends CityObject{
@Serial
private static final long serialVersionUID = 5886527664552294353L;
private org.citygml4j.core.model.generics.GenericOccupiedSpace cgmlGos;
private static final Logger logger = LogManager.getLogger(GenericCityObject.class);
private final List<BoundarySurface> boundarySurfaceList = new ArrayList<>();
@Override
public void accept(Check c) {
super.accept(c);
if (c.canExecute(this)) {
c.check(this);
}
for (BoundarySurface bs : boundarySurfaceList) {
bs.accept(c);
}
}
@Override
public void reCreateGeometries(GeometryFactory factory, ParserConfiguration config) {
for (Geometry geom : getGeometries()) {
if (geom.getType() == GeometryType.MULTI_SURFACE) {
MultiSurface ms = CityGmlUtils.createMultiSurface(geom, factory, config);
setMultiSurfaceAccordingToLod(geom, ms);
} else {
Solid solid = CityGmlUtils.createSolid(geom, factory, config);
setSolidAccordingToLod(geom, solid);
}
}
for (BoundarySurface bs : boundarySurfaceList) {
reCreateBoundarySurface(factory, config, bs);
}
}
private void reCreateBoundarySurface(GeometryFactory factory, ParserConfiguration config, BoundarySurface bs) {
if (bs.getGeometries().isEmpty()) {
for (AbstractSpaceBoundaryProperty bsp : cgmlGos.getBoundaries()) {
if (bsp.getObject() != null && bsp.getObject() == bs.getGmlObject()) {
logger.warn("Found empty boundary surface: {}, removing from generic object", bs.getGmlId());
cgmlGos.getBoundaries().remove(bsp);
break;
}
}
return;
}
bs.reCreateGeometries(factory, config);
}
private void setMultiSurfaceAccordingToLod(Geometry geom, MultiSurface ms) {
switch (geom.getLod()) {
case LOD0:
cgmlGos.setLod0MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD2:
cgmlGos.setLod2MultiSurface(new MultiSurfaceProperty(ms));
break;
case LOD3:
cgmlGos.setLod3MultiSurface(new MultiSurfaceProperty(ms));
break;
default:
throw new IllegalStateException("Cannot add " + geom.getLod() + " multi surface to buildings");
}
}
private void setSolidAccordingToLod(Geometry geom, Solid solid) {
switch (geom.getLod()) {
case LOD1:
cgmlGos.setLod1Solid(new SolidProperty(solid));
break;
case LOD2:
cgmlGos.setLod2Solid(new SolidProperty(solid));
break;
case LOD3:
cgmlGos.setLod3Solid(new SolidProperty(solid));
break;
default:
throw new IllegalStateException("Cannot add " + geom.getLod() + " solid to buildings");
}
}
@Override
public void collectContainedErrors(List<CheckError> errors) {
super.collectContainedErrors(errors);
for (BoundarySurface bs : boundarySurfaceList) {
bs.collectContainedErrors(errors);
}
}
@Override
public void clearAllContainedCheckResults() {
super.clearAllContainedCheckResults();
for (BoundarySurface bs : boundarySurfaceList) {
bs.clearAllContainedCheckResults();
}
}
@Override
public boolean containsError(CheckId checkIdentifier) {
boolean hasError = super.containsError(checkIdentifier);
if (hasError) {
return true;
}
for (BoundarySurface bs : boundarySurfaceList) {
if (bs.containsError(checkIdentifier)) {
return true;
}
}
return false;
}
@Override
public boolean containsAnyError() {
boolean hasError = super.containsAnyError();
if (hasError) {
return true;
}
for (BoundarySurface bs : boundarySurfaceList) {
if (bs.containsAnyError()) {
return true;
}
}
return false;
}
@Override
public void prepareForChecking() {
super.prepareForChecking();
for (BoundarySurface bs : boundarySurfaceList) {
bs.prepareForChecking();
}
}
@Override
public void clearMetaInformation() {
super.clearMetaInformation();
for (BoundarySurface bs : boundarySurfaceList) {
bs.clearMetaInformation();
}
}
@Override
public void collectInstances(CopyHandler handler) {
super.collectInstances(handler);
handler.addInstance(boundarySurfaceList);
}
@Override
public void fillValues(Copyable original, CopyHandler handler) {
super.fillValues(original, handler);
GenericCityObject originalGos = (GenericCityObject) original;
for (BoundarySurface originalBs : originalGos.boundarySurfaceList) {
boundarySurfaceList.add(handler.getCopyInstance(originalBs));
}
cgmlGos = originalGos.cgmlGos;
}
@Override
public AbstractCityObject getGmlObject() {
return null;
}
@Override
public FeatureType getFeatureType() {
return FeatureType.GENERIC_CITY_OBJECT;
}
public List<BoundarySurface> getBoundarySurfaces() {
return boundarySurfaceList;
}
@Override
public void unsetGmlGeometries() {
cgmlGos.setLod1Solid(null);
cgmlGos.setLod2Solid(null);
cgmlGos.setLod3Solid(null);
cgmlGos.setLod2MultiSurface(null);
cgmlGos.setLod3MultiSurface(null);
for (BoundarySurface bs : boundarySurfaceList) {
bs.unsetGmlGeometries();
}
}
public void setGmlObject(org.citygml4j.core.model.generics.GenericOccupiedSpace gos){
this.cgmlGos = gos;
}
public void addBoundarySurface(BoundarySurface bs) {
boundarySurfaceList.add(bs);
bs.setParent(this);
}
@Override
public Copyable createCopyInstance() {
return new GenericCityObject();
}
}
......@@ -50,6 +50,7 @@ MainWindow.bridgeTab=Bridges
MainWindow.waterTab=Water
MainWindow.terrainTab=Terrain
MainWindow.cityfurnitureTab=CityFurniture
MainWindow.otherObjectsTab=Other
MainWindow.viewLabel=View
MainWindow.showLabel=Show:
MainWindow.searchLabel=Search:
......
......@@ -48,6 +48,7 @@ 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:
......
......@@ -67,6 +67,7 @@ public class CityDoctorController {
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;
......@@ -151,6 +152,7 @@ public class CityDoctorController {
buildWater(model);
buildLand(model);
buildCityFurniture(model);
buildOtherCityObjects(model);
}
private void resetFeatureChunks() {
......@@ -161,6 +163,7 @@ public class CityDoctorController {
waterChunkNr.set(0);
landChunkNr.set(0);
cityFurnitureChunkNr.set(0);
otherObjectsChunkNr.set(0);
}
private void buildLand(CityDoctorModel model) {
......@@ -227,6 +230,18 @@ public class CityDoctorController {
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;
......@@ -391,6 +406,7 @@ public class CityDoctorController {
mainWindow.getWaterView().setRoot(null);
mainWindow.getTerrainView().setRoot(null);
mainWindow.getCityFurnitureView().setRoot(null);
mainWindow.getOtherObjectsView().setRoot(null);
mainWindow.getErrorTree().getRoot().getChildren().clear();
mainWindow.getGlobalErrorsView().getItems().clear();
clearGeometryTrees();
......@@ -657,8 +673,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();
}
......@@ -703,6 +721,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;
}
......@@ -725,7 +745,7 @@ public class CityDoctorController {
CityDoctorModel newModel = new CityDoctorModel(model.getParserConfig(), model.getFile());
newModel.setCityModel(new CityModel());
newModel.addBuilding(b);
FileChooser fc = new FileChooser();
fc.getExtensionFilters().add(new ExtensionFilter("CityGML", "*.gml"));
fc.getExtensionFilters().add(new ExtensionFilter("OFF - Object File Format", "*.off"));
......@@ -806,9 +826,14 @@ public class CityDoctorController {
break;
case CITY_FURNITURE:
view = mainWindow.getCityFurnitureView();
cos = filterFeatures(searchString, model.getLand());
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");
}
......@@ -877,10 +902,15 @@ public class CityDoctorController {
chunkCounter = landChunkNr;
break;
case CITY_FURNITURE:
view = mainWindow.getCityFurnitureView();
cos = model.getCityFurniture();
chunkCounter = cityFurnitureChunkNr;
break;
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");
}
......@@ -960,6 +990,14 @@ public class CityDoctorController {
model.getCityFurniture(), cityFurnitureChunkNr);
}
public void fillTreeViewWithErrorOtherObjects(){
if (model == null) {
return;
}
fillTreeViewWithErrorCityObjects(mainWindow.getOtherObjectsView(),
model.getGenericCityObjects(), otherObjectsChunkNr);
}
public void fillTreeViewWithErrorTransportation() {
if (model == null) {
return;
......@@ -1028,6 +1066,10 @@ public class CityDoctorController {
buildCityFurniture(model);
updateTree(mainWindow.getCityFurnitureView().getRoot());
break;
case GENERIC_CITY_OBJECT:
buildOtherCityObjects(model);
updateTree(mainWindow.getOtherObjectsView().getRoot());
break;
default:
throw new IllegalStateException();
}
......@@ -1118,6 +1160,9 @@ public class CityDoctorController {
case CITY_FURNITURE:
fillTreeViewWithErrorCityFurniture();
break;
case GENERIC_CITY_OBJECT:
fillTreeViewWithErrorOtherObjects();
break;
default:
throw new IllegalStateException("Unknown selected feature tab: " + mainWindow.getSelectedTab());
}
......
......@@ -107,6 +107,9 @@ public class MainWindow extends Application {
@FXML
private TreeView<Renderable> cityFurnitureView;
@FXML
TreeView<Renderable> otherObjectsView;
@FXML
private TreeView<Renderable> polygonView;
......@@ -185,6 +188,9 @@ public class MainWindow extends Application {
@FXML
private Tab cityFurnitureTab;
@FXML
private Tab otherObjectsTab;
@FXML
private Tab errorsTab;
......@@ -424,6 +430,7 @@ public class MainWindow extends Application {
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"));
......@@ -642,6 +649,9 @@ public class MainWindow extends Application {
case 6:
selectedTab = FeatureType.CITY_FURNITURE;
break;
case 7:
selectedTab = FeatureType.GENERIC_CITY_OBJECT;
break;
default:
throw new IllegalStateException("Unknown tab index: " + index);
}
......@@ -727,6 +737,10 @@ public class MainWindow extends Application {
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());
......@@ -870,6 +884,10 @@ public class MainWindow extends Application {
return cityFurnitureView;
}
public TreeView<Renderable> getOtherObjectsView(){
return otherObjectsView;
}
public TreeView<Renderable> getPolygonsView() {
return polygonView;
}
......@@ -917,6 +935,7 @@ public class MainWindow extends Application {
waterView.getSelectionModel().clearSelection();
terrainView.getSelectionModel().clearSelection();
cityFurnitureView.getSelectionModel().clearSelection();
otherObjectsView.getSelectionModel().clearSelection();
bridgeView.getSelectionModel().clearSelection();
polygonView.getSelectionModel().clearSelection();
edgeView.getSelectionModel().clearSelection();
......
......@@ -401,6 +401,31 @@ public class Renderer {
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();
});
};
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);
......
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.CityFurniture;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
......
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.datastructure.GenericCityObject;
import de.hft.stuttgart.citydoctor2.gui.CheckStatus;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
import java.util.List;
public class AllOtherObjectsNode extends Renderable{
private final List<GenericCityObject> genericObjects;
public AllOtherObjectsNode(List<GenericCityObject> genericObjects) {
this.genericObjects = genericObjects;
}
@Override
public void refreshTextColor() {
boolean wasChecked = false;
for (GenericCityObject gco : genericObjects) {
if (gco.isValidated()) {
wasChecked = true;
if (gco.containsAnyError()) {
setStatus(CheckStatus.ERROR);
return;
}
}
}
if (wasChecked) {
setStatus(CheckStatus.OK);
} else {
setStatus(CheckStatus.NOT_CHECKED);
}
}
@Override
public String getText() {
return "GenericCityObjects";
}
@Override
public void visit(Renderer renderer) {
renderer.clearCurrentRender();
}
}
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.datastructure.GenericCityObject;
import de.hft.stuttgart.citydoctor2.gui.CheckStatus;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
public class GenericCityObjectsNode extends Renderable{
private final GenericCityObject gcobject;
public GenericCityObjectsNode(GenericCityObject gcobject) {
this.gcobject = gcobject;
}
@Override
public String getText() {
return gcobject.getGmlId().getGmlString();
}
@Override
public void visit(Renderer renderer) {
renderer.render(gcobject);
}
@Override
public void refreshTextColor() {
if (!gcobject.isValidated()) {
setStatus(CheckStatus.NOT_CHECKED);
} else if (gcobject.containsAnyError()) {
setStatus(CheckStatus.ERROR);
} else {
setStatus(CheckStatus.OK);
}
}
}
......@@ -93,6 +93,11 @@
<TreeView id="cityFurnitureTree" fx:id="cityFurnitureView" prefHeight="200.0" prefWidth="200.0" showRoot="false" />
</content>
</Tab>
<Tab fx:id="otherObjectsTab" text="Other">
<content>
<TreeView id="otherTree" fx:id="otherObjectsView" prefHeight="200.0" prefWidth="200.0" showRoot="false" />
</content>
</Tab>
</tabs>
</TabPane>
</children>
......
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