Commit 81be0b1d authored by Riegel's avatar Riegel
Browse files

Merge branch 'dev_GUI' into 'dev'

Open source release of CityDoctorGUI and other extensions.

See merge request !6
parents 12d96d95 5a4d0a74
Pipeline #10056 passed with stage
in 1 minute and 6 seconds
package de.hft.stuttgart.citydoctor2.healer.gui;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
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.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.Checker;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.datastructure.AbstractBuilding;
import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface;
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.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
import de.hft.stuttgart.citydoctor2.datastructure.GmlId;
import de.hft.stuttgart.citydoctor2.datastructure.LinkedPolygon;
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.gui.AutoProWindow;
import de.hft.stuttgart.citydoctor2.gui.HighlightController;
import de.hft.stuttgart.citydoctor2.gui.ListErrorVisitor;
import de.hft.stuttgart.citydoctor2.gui.TriangulatedGeometry;
import de.hft.stuttgart.citydoctor2.healer.Healer;
import de.hft.stuttgart.citydoctor2.optimization.MeshGenerator;
import de.hft.stuttgart.citydoctor2.utils.Copy;
import javafx.collections.ObservableList;
import javafx.scene.control.TextInputDialog;
import javafx.scene.control.TreeItem;
import javafx.scene.shape.CullFace;
import javafx.scene.shape.DrawMode;
public class HealerController {
private CityDoctorModel model;
private HealerView healerView;
private CityObject currentFeature;
private Geometry currentGeometry;
private CityObject nextFeature;
private Geometry nextGeometry;
private Checker checker;
private CullFace culling = CullFace.BACK;
private DrawMode drawMode = DrawMode.FILL;
private TriangulatedGeometry nextTriangulatedGeometry;
private TriangulatedGeometry currentTriangulatedGeometry;
private ListErrorVisitor currentErrorVisitor;
private ListErrorVisitor nextErrorVisitor;
private HighlightController currentHighlights;
private HighlightController nextHighlights;
private SolidInjectorDialog injectorDialog;
public HealerController(HealerView healerView) {
this.healerView = healerView;
this.currentHighlights = new HighlightController(healerView.getCurrentWorld());
this.nextHighlights = new HighlightController(healerView.getNextWorld());
currentErrorVisitor = new ListErrorVisitor(currentHighlights);
nextErrorVisitor = new ListErrorVisitor(nextHighlights);
healerView.translateZProperty().addListener((obs, oldV, newV) -> {
currentHighlights.changeScaling(-newV.doubleValue());
nextHighlights.changeScaling(-newV.doubleValue());
});
}
public void showSimplyfication() {
if (model == null) {
return;
}
model.createFeatureStream().forEach(CityObject::prepareForChecking);
AutoProWindow window = new AutoProWindow(model);
window.setLocationRelativeTo(null);
window.setVisible(true);
}
public void setCurrentModel(CityDoctorModel model) {
if (this.model != model) {
healerView.getCurrentMeshGroup().getChildren().clear();
healerView.getNextMeshGroup().getChildren().clear();
healerView.getCurrentErrorList().getItems().clear();
}
this.model = model;
}
public void selectFeatureClicked() {
if (model == null) {
return;
}
ChooseFeatureDialog dialog = healerView.getChooseFeatureDialog();
dialog.getBuildingsTree().getRoot().getChildren().clear();
model.getBuildings().forEach(b -> {
if (hasBuildingGeometryErrors(b)) {
addBuildingToTree(b, dialog);
}
});
dialog.show();
}
private boolean hasBuildingGeometryErrors(Building b) {
boolean hasError = hasAbstractBuildingGeometryErrors(b);
if (hasError) {
return true;
}
for (BuildingPart bp : b.getBuildingParts()) {
if (hasAbstractBuildingGeometryErrors(bp)) {
return true;
}
}
return false;
}
private boolean hasAbstractBuildingGeometryErrors(AbstractBuilding b) {
for (Geometry geom : b.getGeometries()) {
if (geom.containsAnyError()) {
return true;
}
}
if (doBoundarySurfaceHaveGeometryErrors(b.getBoundarySurfaces())) {
return true;
}
return doBuildingInstallationsContainGeometryErrors(b.getBuildingInstallations());
}
private void addBuildingToTree(Building b, ChooseFeatureDialog dialog) {
TreeItem<SelectableFeature> buildingItem = new TreeItem<>(new SelectableFeature(b.getGmlId().getGmlString()));
dialog.getBuildingsTree().getRoot().getChildren().add(buildingItem);
buildingItem.setExpanded(true);
buildGeometryTreeItems(b, buildingItem);
buildBoundarySurfaceItems(b.getBoundarySurfaces(), buildingItem);
buildBuildingInstallationItems(b.getBuildingInstallations(), buildingItem);
}
private void buildBuildingInstallationItems(List<Installation> buildingInstallations,
TreeItem<SelectableFeature> buildingItem) {
boolean hasBiError = doBuildingInstallationsContainGeometryErrors(buildingInstallations);
if (hasBiError) {
TreeItem<SelectableFeature> allInstItem = new TreeItem<>(new SelectableFeature("BuildingInstallations"));
buildingItem.getChildren().add(allInstItem);
for (Installation bi : buildingInstallations) {
if (!hasBuildingInstallationGeometryError(bi)) {
continue;
}
TreeItem<SelectableFeature> instItem = new TreeItem<>(
new SelectableFeature(bi.getGmlId().getGmlString()));
allInstItem.getChildren().add(instItem);
buildBoundarySurfaceItems(bi.getBoundarySurfaces(), instItem);
}
}
}
private boolean doBuildingInstallationsContainGeometryErrors(List<Installation> buildingInstallations) {
for (Installation bi : buildingInstallations) {
boolean hasError = hasBuildingInstallationGeometryError(bi);
if (hasError) {
return true;
}
}
return false;
}
private boolean hasBuildingInstallationGeometryError(Installation bi) {
for (Geometry geom : bi.getGeometries()) {
if (geom.containsAnyError()) {
return true;
}
}
return doBoundarySurfaceHaveGeometryErrors(bi.getBoundarySurfaces());
}
private void buildBoundarySurfaceItems(List<BoundarySurface> boundarySurfaces, TreeItem<SelectableFeature> root) {
boolean hasBsError = doBoundarySurfaceHaveGeometryErrors(boundarySurfaces);
if (hasBsError) {
TreeItem<SelectableFeature> surfacesItem = new TreeItem<>(new SelectableFeature("BoundarySurfaces"));
root.getChildren().add(surfacesItem);
// dummy
TreeItem<SelectableFeature> dummyItem = new TreeItem<>(null);
surfacesItem.getChildren().add(dummyItem);
// expand listener to actually load the boundary surfaces
// this is for saving memory
surfacesItem.expandedProperty().addListener((obs, oldV, newV) -> {
if (Boolean.TRUE.equals(newV) && surfacesItem.getChildren().size() == 1) {
surfacesItem.getChildren().clear();
for (BoundarySurface bs : boundarySurfaces) {
if (hasBoundarySurfaceGeometryError(bs)) {
TreeItem<SelectableFeature> surfaceItem = new TreeItem<>(
new SelectableFeature(bs.getGmlId().getGmlString() + " [" + bs.getType() + "]"));
surfacesItem.getChildren().add(surfaceItem);
buildGeometryTreeItems(bs, surfaceItem);
}
}
}
});
}
}
private boolean hasBoundarySurfaceGeometryError(BoundarySurface bs) {
for (Geometry geom : bs.getGeometries()) {
if (geom.containsAnyError()) {
return true;
}
}
return false;
}
private void buildGeometryTreeItems(CityObject co, TreeItem<SelectableFeature> root) {
for (Geometry geom : co.getGeometries()) {
if (!geom.containsAnyError()) {
continue;
}
TreeItem<SelectableFeature> geomItem = new TreeItem<>(
new SelectableGeometry(createGeometryText(geom), geom, co));
root.getChildren().add(geomItem);
}
}
private boolean doBoundarySurfaceHaveGeometryErrors(List<BoundarySurface> boundarySurfaces) {
for (BoundarySurface bs : boundarySurfaces) {
boolean hasError = hasBoundarySurfaceGeometryError(bs);
if (hasError) {
return true;
}
}
return false;
}
private String createGeometryText(Geometry geom) {
StringBuilder sb = new StringBuilder();
sb.append("Geometry [");
sb.append(geom.getType());
sb.append(", ");
sb.append(geom.getLod());
if (geom.getGmlId().isGenerated()) {
sb.append("]");
} else {
sb.append("] ");
sb.append(geom.getGmlId());
}
return sb.toString();
}
public void itemSelected(TreeItem<SelectableFeature> item, ChooseFeatureDialog dialog) {
if (item == null) {
return;
}
SelectableFeature value = item.getValue();
dialog.setOkButtonEnabled(value.isGeometry());
}
public void setCurrentChecker(Checker checker) {
this.checker = checker;
}
public void featureSelectionConfirmed(SelectableFeature selectedItem) {
if (!(selectedItem instanceof SelectableGeometry)) {
return;
}
SelectableGeometry selectedGeometry = (SelectableGeometry) selectedItem;
currentGeometry = selectedGeometry.getGeometry();
currentFeature = selectedGeometry.getFeature();
currentTriangulatedGeometry = TriangulatedGeometry.of(currentGeometry);
currentErrorVisitor.setGeometry(currentTriangulatedGeometry);
currentTriangulatedGeometry.setCullFace(culling);
currentTriangulatedGeometry.setDrawMode(drawMode);
healerView.setSelectedFeatureText(currentFeature.getGmlId().getGmlString());
healerView.setFeatureTypeText(currentFeature.getFeatureType().toString());
healerView.setGeometryText(currentGeometry.getLod().toString() + ", " + currentGeometry.getType().toString());
updateCurrentErrors();
healerView.zoomOutForBoundingBox(currentGeometry.calculateBoundingBox());
healerView.getCurrentMeshGroup().getChildren().clear();
healerView.getNextMeshGroup().getChildren().clear();
healerView.getCurrentMeshGroup().getChildren().addAll(currentTriangulatedGeometry.getMeshes());
healerView.getNextStepBtn().setDisable(false);
healerView.getHealCompleteBtn().setDisable(false);
healerView.getAcceptBtn().setDisable(true);
healerView.getCancelBtn().setDisable(true);
}
private void updateCurrentErrors() {
List<CheckError> errors = new ArrayList<>();
currentGeometry.collectContainedErrors(errors);
healerView.getCurrentErrorList().getItems().clear();
for (CheckError err : errors) {
healerView.getCurrentErrorList().getItems().add(err);
}
}
public void nextStepClicked() {
if (currentGeometry == null || checker == null || currentFeature == null) {
return;
}
healerView.getHealCompleteBtn().setDisable(true);
currentFeature.prepareForChecking();
if (nextGeometry == null) {
GmlId id = currentGeometry.getGmlId();
nextFeature = Copy.copy(currentFeature);
nextGeometry = findNextGeometry(id, nextFeature);
}
nextFeature.prepareForChecking();
Healer healer = new Healer(checker);
healer.heal(nextGeometry, nextFeature, 1);
nextFeature.prepareForChecking();
checker.executeChecksForCheckable(nextFeature);
updateNextErrors();
updateNextGeometryView();
}
private void updateNextGeometryView() {
nextTriangulatedGeometry = TriangulatedGeometry.of(nextGeometry);
nextErrorVisitor.setGeometry(nextTriangulatedGeometry);
nextTriangulatedGeometry.setCullFace(culling);
nextTriangulatedGeometry.setDrawMode(drawMode);
healerView.getNextMeshGroup().getChildren().clear();
healerView.getNextMeshGroup().getChildren().addAll(nextTriangulatedGeometry.getMeshes());
healerView.getAcceptBtn().setDisable(false);
healerView.getCancelBtn().setDisable(false);
healerView.getSolidInjectorBtn().setDisable(true);
}
public void healCompleteClicked() {
if (currentGeometry == null) {
return;
}
// generate a gml id if there is none, so the selected geometry can be found
// later
// needs to be done befoe copy, otherwise copy will copy null
GmlId gmlId = currentGeometry.getGmlId();
nextFeature = Copy.copy(currentFeature);
nextGeometry = findNextGeometry(gmlId, nextFeature);
Healer healer = new Healer(checker);
healer.heal(nextGeometry, nextFeature);
updateNextErrors();
nextTriangulatedGeometry = TriangulatedGeometry.of(nextGeometry);
nextErrorVisitor.setGeometry(nextTriangulatedGeometry);
nextTriangulatedGeometry.setCullFace(culling);
nextTriangulatedGeometry.setDrawMode(drawMode);
healerView.getNextMeshGroup().getChildren().clear();
healerView.getNextMeshGroup().getChildren().addAll(nextTriangulatedGeometry.getMeshes());
healerView.getAcceptBtn().setDisable(false);
healerView.getNextStepBtn().setDisable(true);
healerView.getHealCompleteBtn().setDisable(true);
healerView.getCancelBtn().setDisable(false);
}
private void updateNextErrors() {
List<CheckError> errors = new ArrayList<>();
nextGeometry.collectContainedErrors(errors);
ObservableList<CheckError> items = healerView.getNextErrorList().getItems();
items.clear();
for (CheckError err : errors) {
items.add(err);
}
}
private Geometry findNextGeometry(GmlId gmlId, CityObject nextFeature) {
Geometry[] foundGeom = new Geometry[1];
Check geomFinder = new Check() {
@Override
public void check(Geometry geom) {
if (geom.getGmlId().equals(gmlId)) {
foundGeom[0] = geom;
}
}
@Override
public RequirementType getType() {
return null;
}
@Override
public Check createNewInstance() {
return null;
}
@Override
public CheckId getCheckId() {
return null;
}
@Override
public Set<Requirement> appliesToRequirements() {
return null;
}
};
nextFeature.accept(geomFinder);
return foundGeom[0];
}
public void acceptHealingClicked() {
if (model == null || checker == null || nextFeature == null || currentFeature == null) {
return;
}
nextFeature.prepareForChecking();
checker.executeChecksForCheckable(nextFeature);
model.replaceFeature(currentFeature, nextFeature);
currentFeature = nextFeature;
currentGeometry = nextGeometry;
updateCurrentErrors();
healerView.getNextErrorList().getItems().clear();
healerView.getCurrentMeshGroup().getChildren().clear();
healerView.getCurrentMeshGroup().getChildren().addAll(nextTriangulatedGeometry.getMeshes());
currentTriangulatedGeometry = nextTriangulatedGeometry;
currentErrorVisitor.setGeometry(currentTriangulatedGeometry);
nextTriangulatedGeometry = null;
// nextHighlights = new HighlightController(healerView.getNextWorld());
// nextErrorVisitor = new ListErrorVisitor(nextHighlights);
healerView.getNextMeshGroup().getChildren().clear();
healerView.getHealCompleteBtn().setDisable(false);
healerView.getNextStepBtn().setDisable(false);
healerView.getAcceptBtn().setDisable(true);
healerView.getCancelBtn().setDisable(true);
}
public void setWireframe(boolean b) {
if (b) {
drawMode = DrawMode.LINE;
} else {
drawMode = DrawMode.FILL;
}
if (currentTriangulatedGeometry != null) {
currentTriangulatedGeometry.setDrawMode(drawMode);
}
if (nextTriangulatedGeometry != null) {
nextTriangulatedGeometry.setDrawMode(drawMode);
}
}
public void setCulling(CullFace culling) {
this.culling = culling;
if (currentTriangulatedGeometry != null) {
currentTriangulatedGeometry.setCullFace(culling);
}
if (nextTriangulatedGeometry != null) {
nextTriangulatedGeometry.setCullFace(culling);
}
}
public void cancelClicked() {
if (model == null || nextFeature == null) {
return;
}
healerView.getNextErrorList().getItems().clear();
healerView.getNextMeshGroup().getChildren().clear();
healerView.getAcceptBtn().setDisable(true);
healerView.getCancelBtn().setDisable(true);
healerView.getNextStepBtn().setDisable(false);
healerView.getHealCompleteBtn().setDisable(false);
nextFeature = null;
nextGeometry = null;
nextTriangulatedGeometry = null;
}
public void currentHighlight(CheckError err) {
if (err == null) {
currentHighlights.clearHighlights();
return;
}
err.accept(currentErrorVisitor);
}
public void nextHighlight(CheckError err) {
if (err == null) {
nextHighlights.clearHighlights();
return;
}
err.accept(nextErrorVisitor);
}
public void onHide() {
currentHighlights.clearHighlights();
nextHighlights.clearHighlights();
healerView.getCurrentErrorList().getSelectionModel().clearSelection();
healerView.getNextErrorList().getSelectionModel().clearSelection();
healerView.getSelectFeatureBtn().setDisable(true);
}
public void onShow(CityDoctorModel model, Checker checker) {
if (model != null) {
// solid injector and meshing works without validation first
this.model = model;
healerView.getSolidInjectorBtn().setDisable(false);
healerView.getMeshBtn().setDisable(false);
} else {
healerView.getSolidInjectorBtn().setDisable(true);
healerView.getMeshBtn().setDisable(true);
}
// TODO: refactor this better
if (model == null || checker == null) {
resetGUI();
healerView.getSelectFeatureBtn().setDisable(true);
healerView.getFixBtn().setDisable(true);
healerView.getHealerToolBar().getSaveBtn().setDisable(true);
return;
}
if (model != this.model || checker != this.checker) {
this.model = model;
this.checker = checker;
resetGUI();
healerView.getSelectFeatureBtn().setDisable(false);
healerView.getFixBtn().setDisable(false);
healerView.getHealerToolBar().getSaveBtn().setDisable(false);
}
}
private void resetGUI() {
healerView.getAcceptBtn().setDisable(true);
healerView.getCancelBtn().setDisable(true);
healerView.getNextStepBtn().setDisable(true);
healerView.getHealCompleteBtn().setDisable(true);
healerView.getCurrentErrorList().getItems().clear();
healerView.getNextErrorList().getItems().clear();
healerView.getCurrentMeshGroup().getChildren().clear();
healerView.getNextMeshGroup().getChildren().clear();
healerView.setSelectedFeatureText("");
healerView.setFeatureTypeText("");
healerView.setGeometryText("");
}
public void injectSolid(boolean useBs, boolean useBi, boolean useLod2, boolean useLod3, boolean useLod4) {
if (model == null || currentFeature == null) {
return;
}
CityObject oldFeature = currentFeature;
currentFeature.prepareForChecking();
if (currentFeature instanceof BoundarySurface) {
BoundarySurface surface = (BoundarySurface) currentFeature;
currentFeature = surface.getParent();
}
if (!(currentFeature instanceof Building)) {
return;
}
// collect polygons
Map<Lod, List<Polygon>> availablePolygons = new EnumMap<>(Lod.class);
Map<Lod, Set<Polygon>> existingPolygons = new EnumMap<>(Lod.class);
Building b = (Building) currentFeature;
collectPolygons(useBs, useBi, availablePolygons, existingPolygons, b);
if (useLod2) {
insertSolidGeometry(availablePolygons, b, existingPolygons, Lod.LOD2);
}
if (useLod3) {
insertSolidGeometry(availablePolygons, b, existingPolygons, Lod.LOD3);
}
if (useLod4) {
insertSolidGeometry(availablePolygons, b, existingPolygons, Lod.LOD4);
}
nextFeature = null;
nextGeometry = null;
Lod lod = currentGeometry.getLod();
GeometryType type = GeometryType.SOLID;
currentGeometry = Objects.requireNonNull(currentFeature.getGeometry(type, lod));
checker.executeChecksForCheckable(currentFeature);
healerView.getNextErrorList().getItems().clear();
healerView.getNextMeshGroup().getChildren().clear();
updateCurrentErrors();
currentTriangulatedGeometry = TriangulatedGeometry.of(currentGeometry);
currentErrorVisitor.setGeometry(currentTriangulatedGeometry);
currentTriangulatedGeometry.setCullFace(culling);
currentTriangulatedGeometry.setDrawMode(drawMode);
healerView.zoomOutForBoundingBox(currentGeometry.calculateBoundingBox());
healerView.getCurrentMeshGroup().getChildren().clear();
healerView.getCurrentMeshGroup().getChildren().addAll(currentTriangulatedGeometry.getMeshes());
healerView.getNextStepBtn().setDisable(false);
healerView.getHealCompleteBtn().setDisable(false);
healerView.getAcceptBtn().setDisable(true);
healerView.getCancelBtn().setDisable(true);
healerView.getSolidInjectorBtn().setDisable(true);
currentFeature = oldFeature;
}
private void collectPolygons(boolean useBs, boolean useBi, Map<Lod, List<Polygon>> availablePolygons,
Map<Lod, Set<Polygon>> existingPolygons, Building b) {
if (useBs) {
collectPolygons(availablePolygons, b.getBoundarySurfaces());
}
if (useBi) {
for (Installation bi : b.getBuildingInstallations()) {
for (Geometry geom : bi.getGeometries()) {
List<Polygon> polygons = availablePolygons.computeIfAbsent(geom.getLod(), l -> new ArrayList<>());
polygons.addAll(geom.getPolygons());
}
collectPolygons(availablePolygons, bi.getBoundarySurfaces());
}
}
for (Geometry geom : b.getGeometries()) {
Set<Polygon> polygons = existingPolygons.computeIfAbsent(geom.getLod(), l -> new HashSet<>());
polygons.addAll(geom.getPolygons());
}
}
private void insertSolidGeometry(Map<Lod, List<Polygon>> availablePolygons, Building b,
Map<Lod, Set<Polygon>> existingPolygons, Lod lod) {
List<Polygon> newPolygons = availablePolygons.get(lod);
if (newPolygons != null) {
// found polygons to be added
Geometry newGeometry = new Geometry(GeometryType.SOLID, lod);
Set<Polygon> polygons = existingPolygons.get(lod);
if (polygons != null) {
// add existing polygons
for (Polygon p : polygons) {
newGeometry.addPolygon(p);
}
}
for (Polygon p : newPolygons) {
if (p instanceof ConcretePolygon && !newGeometry.containsPolygon(p)) {
LinkedPolygon newPoly = new LinkedPolygon((ConcretePolygon) p, newGeometry);
newGeometry.addPolygon(newPoly);
}
}
// remove existing geometry, if possible
b.removeGeometry(lod);
// add new geometry
b.addGeometry(newGeometry);
newGeometry.updateEdgesAndVertices();
if (currentGeometry == null) {
currentGeometry = newGeometry;
}
}
}
private void collectPolygons(Map<Lod, List<Polygon>> availablePolygons, List<BoundarySurface> surfaces) {
for (BoundarySurface bs : surfaces) {
for (Geometry geom : bs.getGeometries()) {
List<Polygon> polygons = availablePolygons.computeIfAbsent(geom.getLod(), l -> new ArrayList<>());
polygons.addAll(geom.getPolygons());
}
for (Opening o : bs.getOpenings()) {
for (Geometry geom : o.getGeometries()) {
List<Polygon> polygons = availablePolygons.computeIfAbsent(geom.getLod(), l -> new ArrayList<>());
polygons.addAll(geom.getPolygons());
}
}
}
}
public void solidInjectorClicked() {
if (injectorDialog == null) {
injectorDialog = new SolidInjectorDialog(this);
}
injectorDialog.show();
}
public void fixModel() {
if (model == null || checker == null) {
return;
}
Healer healer = new Healer(checker);
healer.healModel(model);
}
public void meshBtnClicked() {
if (model == null) {
return;
}
TextInputDialog dialog = new TextInputDialog("1");
dialog.setTitle("Mesh Parameter Input");
dialog.setHeaderText("Input a number > 0.01");
dialog.setContentText("Maximum Area of meshed triangles in m²:");
Optional<String> result = dialog.showAndWait();
if (result.isPresent()){
String areaString = result.get();
try {
double area = Double.parseDouble(areaString);
if (area < 0.01) {
// triangle area is too small, ignore
return;
}
for (Building b : model.getBuildings()) {
MeshGenerator.replaceGeometryWithMeshedGeometry(b, area);
}
} catch (NumberFormatException e) {
// no real number was inserted, do nothing
}
}
}
}
package de.hft.stuttgart.citydoctor2.healer.gui;
import de.hft.stuttgart.citydoctor2.gui.MainWindow;
import de.hft.stuttgart.citydoctor2.gui.ViewRegistration;
public class HealerGUI {
public static void main(String[] args) {
ViewRegistration.registerView(new HealerView());
MainWindow.main(args);
}
}
package de.hft.stuttgart.citydoctor2.healer.gui;
import java.io.IOException;
import de.hft.stuttgart.citydoctor2.gui.CityDoctorController;
import de.hft.stuttgart.citydoctor2.gui.MainToolBar;
import de.hft.stuttgart.citydoctor2.gui.MainWindow;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.ToggleButton;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.shape.CullFace;
public class HealerToolbar {
private HealerController controller;
private HBox toolBar;
@FXML
private ToggleButton wireframeBtn;
@FXML
private ToggleButton cullingBtn;
@FXML
private ImageView cullingImage;
@FXML
private ImageView wireframeImage;
@FXML
private HBox spacer;
@FXML
private Button saveBtn;
@FXML
private ImageView saveImage;
@FXML
private Button simplyBtn;
@FXML
private ImageView simplyImageView;
private CityDoctorController cdController;
public HealerToolbar(HealerController controller, MainWindow mainWindow) throws IOException {
this.controller = controller;
cdController = mainWindow.getController();
FXMLLoader loader = new FXMLLoader(getClass().getResource("healerToolbar.fxml"));
loader.setController(this);
toolBar = loader.load();
}
public void initialize() {
HBox.setHgrow(spacer, Priority.ALWAYS);
cullingImage.setImage(new Image(MainToolBar.class.getResourceAsStream("icons/Culling.png")));
wireframeImage.setImage(new Image(MainToolBar.class.getResourceAsStream("icons/wireframe32x32.png")));
simplyImageView.setImage(new Image(HealerToolbar.class.getResourceAsStream("autopro32x32.png")));
wireframeBtn.selectedProperty().addListener((obs, oldV, newV) -> controller.setWireframe(newV));
cullingBtn.selectedProperty().addListener((obs, oldV, newV) -> {
if (Boolean.TRUE.equals(newV)) {
controller.setCulling(CullFace.BACK);
} else {
controller.setCulling(CullFace.NONE);
}
});
saveBtn.setOnAction(ae -> cdController.askAndSave());
saveBtn.setDisable(true);
saveImage.setImage(new Image(MainWindow.class.getResourceAsStream("icons/save.png")));
simplyBtn.setOnAction(ae -> controller.showSimplyfication());
}
public HBox getToolBar() {
return toolBar;
}
public Button getSaveBtn() {
return saveBtn;
}
}
package de.hft.stuttgart.citydoctor2.healer.gui;
import java.io.IOException;
import java.util.Optional;
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.Checker;
import de.hft.stuttgart.citydoctor2.datastructure.BoundingBox;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.gui.FilterPane;
import de.hft.stuttgart.citydoctor2.gui.MainWindow;
import de.hft.stuttgart.citydoctor2.gui.View;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
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.SceneAntialiasing;
import javafx.scene.SubScene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.Tooltip;
import javafx.scene.control.cell.TextFieldListCell;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.transform.Rotate;
import javafx.stage.Window;
import javafx.util.StringConverter;
public class HealerView extends View {
private static final Logger logger = LogManager.getLogger(HealerView.class);
private static final double CAMERA_TRANSLATE_Z = -100.0;
private static final double CAMERA_INITIAL_X_ANGLE = 20.0;
private static final double CAMERA_INITIAL_Y_ANGLE = 120.0;
private Image image;
private Node healerWindow;
private Window parent;
private HealerController controller;
private ChooseFeatureDialog chooseFeatureDialog;
private HealerToolbar toolBar;
private DoubleProperty translateZ;
private DoubleProperty cameraXRot;
private DoubleProperty cameraYRot;
private double dragX;
private double dragY;
@FXML
private Button fixBtn;
@FXML
private Button selectFeatureBtn;
@FXML
private Pane currentCanvas;
@FXML
private Pane nextCanvas;
@FXML
private Label selectedFeatureLabel;
@FXML
private Label featureTypeLabel;
@FXML
private Label geometryLabel;
@FXML
private ListView<CheckError> currentErrorList;
@FXML
private Button nextStep;
@FXML
private Button healCompleteBtn;
@FXML
private Button acceptBtn;
@FXML
private ListView<CheckError> nextErrorList;
@FXML
private Button cancelButton;
@FXML
private ImageView selectImageView;
@FXML
private ImageView nextStepImage;
@FXML
private ImageView healCompleteImage;
@FXML
private ImageView acceptBtnImage;
@FXML
private ImageView cancelImage;
@FXML
private Button solidInjectorBtn;
@FXML
private Button meshBtn;
private Group currentWorld;
private Group nextWorld;
private Group currentMeshGroup;
private Group nextMeshGroup;
public HealerView() {
image = new Image(getClass().getResourceAsStream("healing.png"));
}
@Override
public void initializeView(MainWindow mainWindow) {
this.parent = mainWindow.getMainStage();
FXMLLoader loader = new FXMLLoader(getClass().getResource("healerGUI.fxml"));
loader.setController(this);
try {
healerWindow = loader.load();
controller = new HealerController(this);
toolBar = new HealerToolbar(controller, mainWindow);
} catch (IOException e) {
logger.catching(e);
}
}
public void initialize() {
setup3dViews();
currentErrorList.getSelectionModel().selectedItemProperty()
.addListener((obs, oldV, newV) -> controller.currentHighlight(newV));
currentErrorList.setCellFactory(TextFieldListCell.forListView(new StringConverter<CheckError>() {
@Override
public String toString(CheckError err) {
return err.getErrorId().toString();
}
@Override
public CheckError fromString(String string) {
return null;
}
}));
nextErrorList.getSelectionModel().selectedItemProperty()
.addListener((obs, oldV, newV) -> controller.nextHighlight(newV));
nextErrorList.setCellFactory(TextFieldListCell.forListView(new StringConverter<CheckError>() {
@Override
public String toString(CheckError err) {
return err.getErrorId().toString();
}
@Override
public CheckError fromString(String string) {
return null;
}
}));
nextStep.setOnAction(ae -> controller.nextStepClicked());
nextStep.setTooltip(new Tooltip("Heal one Error"));
selectFeatureBtn.setOnAction(ae -> controller.selectFeatureClicked());
selectFeatureBtn.setTooltip(new Tooltip("Select Feature for Healing"));
healCompleteBtn.setOnAction(ae -> controller.healCompleteClicked());
healCompleteBtn.setTooltip(new Tooltip("Heal Complete"));
acceptBtn.setOnAction(ae -> controller.acceptHealingClicked());
acceptBtn.setTooltip(new Tooltip("Accept Healing"));
selectImageView.setImage(new Image(getClass().getResourceAsStream("list.png")));
nextStepImage.setImage(new Image(getClass().getResourceAsStream("step.png")));
healCompleteImage.setImage(new Image(getClass().getResourceAsStream("fastforward.png")));
acceptBtnImage.setImage(new Image(getClass().getResourceAsStream("tick.png")));
cancelButton.setOnAction(ae -> controller.cancelClicked());
cancelImage.setImage(new Image(FilterPane.class.getResourceAsStream("icons/Delete.png")));
solidInjectorBtn.setOnAction(ae -> controller.solidInjectorClicked());
meshBtn.setOnAction(ae -> controller.meshBtnClicked());
fixBtn.setOnAction(ae -> controller.fixModel());
}
private void setup3dViews() {
translateZ = new SimpleDoubleProperty(CAMERA_TRANSLATE_Z);
cameraXRot = new SimpleDoubleProperty(CAMERA_INITIAL_X_ANGLE);
cameraYRot = new SimpleDoubleProperty(CAMERA_INITIAL_Y_ANGLE);
buildCurrent3dView();
buildNext3dView();
}
private void buildCurrent3dView() {
Group currentRoot = new Group();
SubScene currentScene = new SubScene(currentRoot, 500, 300, true, SceneAntialiasing.BALANCED);
currentScene.heightProperty().bind(currentCanvas.heightProperty());
currentScene.widthProperty().bind(currentCanvas.widthProperty());
currentScene.setFill(Color.AZURE);
currentCanvas.getChildren().add(currentScene);
currentWorld = new Group();
currentRoot.getChildren().add(currentWorld);
currentMeshGroup = new Group();
currentWorld.getChildren().add(currentMeshGroup);
AmbientLight al = new AmbientLight(Color.WHITE);
currentRoot.getChildren().add(al);
PerspectiveCamera currentCamera = new PerspectiveCamera(true);
currentCamera.setNearClip(0.1);
currentCamera.setFarClip(10000d);
currentCamera.translateZProperty().bind(translateZ);
Rotate cameraZRotation = new Rotate();
Rotate cameraXRotation = new Rotate();
cameraXRotation.setAxis(Rotate.X_AXIS);
cameraZRotation.setAxis(Rotate.Z_AXIS);
cameraZRotation.angleProperty().bind(cameraXRot);
cameraXRotation.angleProperty().bind(cameraYRot);
currentWorld.getTransforms().add(cameraXRotation);
currentWorld.getTransforms().add(cameraZRotation);
currentRoot.getChildren().add(currentCamera);
currentScene.setCamera(currentCamera);
setupMeshViewControls(currentCanvas);
}
private void buildNext3dView() {
Group nextRoot = new Group();
SubScene nextScene = new SubScene(nextRoot, 500, 300, true, SceneAntialiasing.BALANCED);
nextScene.heightProperty().bind(nextCanvas.heightProperty());
nextScene.widthProperty().bind(nextCanvas.widthProperty());
nextScene.setFill(Color.AZURE);
nextCanvas.getChildren().add(nextScene);
nextWorld = new Group();
nextRoot.getChildren().add(nextWorld);
nextMeshGroup = new Group();
nextWorld.getChildren().add(nextMeshGroup);
AmbientLight al = new AmbientLight(Color.WHITE);
nextRoot.getChildren().add(al);
PerspectiveCamera nextCamera = new PerspectiveCamera(true);
nextCamera.setNearClip(0.1);
nextCamera.setFarClip(10000d);
nextCamera.translateZProperty().bind(translateZ);
Rotate cameraZRotation = new Rotate();
Rotate cameraXRotation = new Rotate();
cameraXRotation.setAxis(Rotate.X_AXIS);
cameraZRotation.setAxis(Rotate.Z_AXIS);
cameraZRotation.angleProperty().bind(cameraXRot);
cameraXRotation.angleProperty().bind(cameraYRot);
nextWorld.getTransforms().add(cameraXRotation);
nextWorld.getTransforms().add(cameraZRotation);
nextRoot.getChildren().add(nextCamera);
nextScene.setCamera(nextCamera);
setupMeshViewControls(nextCanvas);
}
public void zoomOutForBoundingBox(BoundingBox b) {
double longestSide = b.getDiagonalLength() * 0.4;
double d = longestSide / Math.tan(Math.toRadians(30) / 2);
translateZ.set(-d);
}
private void setupMeshViewControls(Pane canvas) {
canvas.setOnMousePressed(me -> {
if (me.getButton() == MouseButton.PRIMARY) {
dragX = me.getScreenX();
dragY = me.getScreenY();
}
});
canvas.setOnScroll(se -> translateZ.set(translateZ.get() + se.getDeltaY() / 10d));
canvas.setOnMouseDragged(me -> {
if (me.getButton() == MouseButton.PRIMARY) {
double deltaX = me.getScreenX() - dragX;
double deltaY = me.getScreenY() - dragY;
dragX = me.getScreenX();
dragY = me.getScreenY();
cameraXRot.set(cameraXRot.get() + ((deltaX / 3d) % 360));
cameraYRot.set(cameraYRot.get() + ((deltaY / 3d) % 360));
}
});
}
@Override
public Optional<HBox> getToolbar() {
return Optional.of(toolBar.getToolBar());
}
@Override
public Node getMainScreen() {
return healerWindow;
}
@Override
public Image getViewLogo() {
return image;
}
@Override
public void onHide() {
controller.onHide();
}
@Override
public void onShow(CityDoctorModel model, Checker checker) {
controller.onShow(model, checker);
}
public ChooseFeatureDialog getChooseFeatureDialog() {
if (chooseFeatureDialog == null) {
chooseFeatureDialog = new ChooseFeatureDialog(parent, controller);
}
return chooseFeatureDialog;
}
public Group getCurrentWorld() {
return currentWorld;
}
public Group getNextWorld() {
return nextWorld;
}
public void setSelectedFeatureText(String text) {
selectedFeatureLabel.setText(text);
}
public void setFeatureTypeText(String text) {
featureTypeLabel.setText(text);
}
public void setGeometryText(String text) {
geometryLabel.setText(text);
}
public ListView<CheckError> getCurrentErrorList() {
return currentErrorList;
}
public ListView<CheckError> getNextErrorList() {
return nextErrorList;
}
public Button getSelectFeatureBtn() {
return selectFeatureBtn;
}
public Button getAcceptBtn() {
return acceptBtn;
}
public Button getHealCompleteBtn() {
return healCompleteBtn;
}
public Button getNextStepBtn() {
return nextStep;
}
public Button getCancelBtn() {
return cancelButton;
}
public DoubleProperty translateZProperty() {
return translateZ;
}
public Group getNextMeshGroup() {
return nextMeshGroup;
}
public Group getCurrentMeshGroup() {
return currentMeshGroup;
}
public Button getSolidInjectorBtn() {
return solidInjectorBtn;
}
public Button getMeshBtn() {
return meshBtn;
}
public Button getFixBtn() {
return fixBtn;
}
public HealerToolbar getHealerToolBar() {
return toolBar;
}
}
package de.hft.stuttgart.citydoctor2.healer.gui;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
public class SelectableFeature {
private String text;
public SelectableFeature(String text) {
this.text = text;
}
public boolean isGeometry() {
return false;
}
public Geometry getGeometry() {
return null;
}
public CityObject getFeature() {
return null;
}
@Override
public String toString() {
return "SelectableFeature [text=" + text + "]";
}
public String getText() {
return text;
}
}
package de.hft.stuttgart.citydoctor2.healer.gui;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
public class SelectableGeometry extends SelectableFeature {
private Geometry geometry;
private CityObject feature;
public SelectableGeometry(String text, Geometry geometry, CityObject feature) {
super(text);
this.geometry = geometry;
this.feature = feature;
}
@Override
public boolean isGeometry() {
return true;
}
@Override
public CityObject getFeature() {
return feature;
}
@Override
public Geometry getGeometry() {
return geometry;
}
@Override
public String toString() {
return "SelectableGeometry [geometry=" + geometry + ", feature=" + feature + "]";
}
}
package de.hft.stuttgart.citydoctor2.healer.gui;
import java.io.IOException;
import java.io.UncheckedIOException;
import de.hft.stuttgart.citydoctor2.gui.MainWindow;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.image.Image;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class SolidInjectorDialog {
@FXML
private CheckBox useBiCheckBox;
@FXML
private CheckBox useBsCheckBox;
@FXML
private Button okBtn;
@FXML
private Button cancelBtn;
@FXML
private CheckBox lod2Box;
@FXML
private CheckBox lod3Box;
@FXML
private CheckBox lod4Box;
private HealerController controller;
private Stage stage;
public SolidInjectorDialog(HealerController controller) {
this.controller = controller;
FXMLLoader loader = new FXMLLoader(getClass().getResource("solidInjectorDialog.fxml"));
loader.setController(this);
try {
Parent n = loader.load();
stage = new Stage();
stage.getIcons().add(new Image(MainWindow.class.getResourceAsStream("icons/CityDoctor-Logo-rot_klein.jpg")));
Scene scene = new Scene(n);
stage.setScene(scene);
stage.initModality(Modality.APPLICATION_MODAL);
stage.setTitle("Solid Injector");
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void initialize() {
okBtn.setOnAction(ae -> {
controller.injectSolid(useBsCheckBox.isSelected(), useBiCheckBox.isSelected(), lod2Box.isSelected(),
lod3Box.isSelected(), lod4Box.isSelected());
stage.close();
});
cancelBtn.setOnAction(ae -> stage.close());
}
public void show() {
stage.showAndWait();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.TreeView?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx/8.0.221" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TabPane fx:id="tabPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="500.0" tabClosingPolicy="UNAVAILABLE" VBox.vgrow="ALWAYS">
<tabs>
<Tab text="Buildings">
<content>
<TreeView fx:id="buildingsView" prefHeight="200.0" prefWidth="200.0" />
</content>
</Tab>
<Tab text="Vegetation">
<content>
<TreeView fx:id="vegetationView" prefHeight="200.0" prefWidth="200.0" />
</content>
</Tab>
<Tab text="Transportation">
<content>
<TreeView fx:id="transportationView" prefHeight="200.0" prefWidth="200.0" />
</content>
</Tab>
<Tab text="Bridges">
<content>
<TreeView fx:id="bridgesView" prefHeight="200.0" prefWidth="200.0" />
</content>
</Tab>
<Tab text="Water">
<content>
<TreeView fx:id="waterView" prefHeight="200.0" prefWidth="200.0" />
</content>
</Tab>
<Tab text="Terrain">
<content>
<TreeView fx:id="terrainView" prefHeight="200.0" prefWidth="200.0" />
</content>
</Tab>
</tabs>
</TabPane>
<HBox alignment="CENTER_RIGHT" nodeOrientation="LEFT_TO_RIGHT" spacing="5.0" VBox.vgrow="NEVER">
<children>
<Button fx:id="okButton" mnemonicParsing="false" text="OK" />
<Button fx:id="cancelButton" mnemonicParsing="false" text="Cancel" />
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</HBox>
</children>
</VBox>
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.ToolBar?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<SplitPane dividerPositions="0.7" orientation="VERTICAL" xmlns="http://javafx.com/javafx/8.0.221" xmlns:fx="http://javafx.com/fxml/1">
<items>
<HBox maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity">
<children>
<SplitPane dividerPositions="0.5" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" HBox.hgrow="ALWAYS">
<items>
<VBox spacing="5.0">
<children>
<Label text="Current">
<font>
<Font size="18.0" />
</font></Label>
<Pane fx:id="currentCanvas" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" VBox.vgrow="ALWAYS" />
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</VBox>
<VBox spacing="5.0">
<children>
<Label text="Next">
<font>
<Font size="18.0" />
</font></Label>
<Pane fx:id="nextCanvas" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" VBox.vgrow="ALWAYS" />
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</VBox>
</items>
</SplitPane>
</children>
</HBox>
<VBox maxWidth="1.7976931348623157E308">
<children>
<ToolBar maxWidth="1.7976931348623157E308" prefHeight="50.0">
<items>
<Button fx:id="selectFeatureBtn" disable="true" mnemonicParsing="false">
<graphic>
<ImageView fx:id="selectImageView" fitHeight="32.0" fitWidth="32.0" pickOnBounds="true" preserveRatio="true" />
</graphic></Button>
<Button fx:id="nextStep" disable="true" mnemonicParsing="false">
<graphic>
<ImageView fx:id="nextStepImage" fitHeight="32.0" fitWidth="32.0" pickOnBounds="true" preserveRatio="true" />
</graphic></Button>
<Button fx:id="healCompleteBtn" disable="true" mnemonicParsing="false">
<graphic>
<ImageView fx:id="healCompleteImage" fitHeight="32.0" fitWidth="32.0" pickOnBounds="true" preserveRatio="true" />
</graphic></Button>
<Button fx:id="acceptBtn" disable="true" mnemonicParsing="false">
<graphic>
<ImageView fx:id="acceptBtnImage" fitHeight="32.0" fitWidth="32.0" pickOnBounds="true" preserveRatio="true" />
</graphic></Button>
<Button fx:id="cancelButton" disable="true" mnemonicParsing="false">
<graphic>
<ImageView fx:id="cancelImage" fitHeight="32.0" fitWidth="32.0" pickOnBounds="true" preserveRatio="true" />
</graphic></Button>
<Pane maxWidth="1.7976931348623157E308" />
<Button fx:id="meshBtn" disable="true" mnemonicParsing="false" text="Create Mesh" />
<Button fx:id="solidInjectorBtn" disable="true" mnemonicParsing="false" text="SolidInjector" />
<Button fx:id="fixBtn" disable="true" mnemonicParsing="false" text="Fix All" />
</items>
</ToolBar>
<HBox spacing="5.0">
<children>
<VBox spacing="5.0" HBox.hgrow="NEVER">
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
<children>
<Label text="Selected Feature:" />
<Label fx:id="selectedFeatureLabel" />
<Label text="Feature Type:" />
<Label fx:id="featureTypeLabel" />
<Label text="Geometry:" />
<Label fx:id="geometryLabel" />
</children>
</VBox>
<VBox spacing="5.0" HBox.hgrow="NEVER">
<children>
<Label text="Current Errors:" />
<ListView fx:id="currentErrorList" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minWidth="0.0" prefWidth="350.0" />
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</VBox>
<VBox spacing="5.0">
<children>
<Label text="Next Errors:" />
<ListView fx:id="nextErrorList" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minWidth="0.0" prefWidth="350.0" />
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</VBox>
</children>
</HBox>
</children>
</VBox>
</items>
</SplitPane>
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.ToggleButton?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.HBox?>
<HBox maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" spacing="5.0" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml">
<children>
<ToggleButton fx:id="cullingBtn" mnemonicParsing="false" selected="true">
<graphic>
<ImageView fx:id="cullingImage" fitHeight="32.0" fitWidth="32.0" pickOnBounds="true" preserveRatio="true" />
</graphic>
</ToggleButton>
<ToggleButton fx:id="wireframeBtn" mnemonicParsing="false">
<graphic>
<ImageView fx:id="wireframeImage" fitHeight="32.0" fitWidth="32.0" pickOnBounds="true" preserveRatio="true" />
</graphic>
</ToggleButton>
<Separator orientation="VERTICAL" />
<Button id="loadBtn" fx:id="simplyBtn" mnemonicParsing="false">
<graphic>
<ImageView fx:id="simplyImageView" fitHeight="32.0" fitWidth="32.0" pickOnBounds="true" preserveRatio="true" />
</graphic>
</Button>
<HBox fx:id="spacer" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minWidth="0.0" />
<Button fx:id="saveBtn" mnemonicParsing="false">
<graphic>
<ImageView fx:id="saveImage" fitHeight="32.0" fitWidth="32.0" pickOnBounds="true" preserveRatio="true" />
</graphic>
</Button>
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</HBox>
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" spacing="5.0" xmlns="http://javafx.com/javafx/8.0.221" xmlns:fx="http://javafx.com/fxml/1">
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
<children>
<CheckBox fx:id="useBsCheckBox" mnemonicParsing="false" selected="true" text="Use BoundarySurfaces" />
<CheckBox fx:id="useBiCheckBox" mnemonicParsing="false" selected="true" text="Use BuildingInstallations" />
<Separator prefWidth="200.0" />
<CheckBox fx:id="lod2Box" mnemonicParsing="false" selected="true" text="LOD 2" />
<CheckBox fx:id="lod3Box" mnemonicParsing="false" selected="true" text="LOD 3" />
<CheckBox fx:id="lod4Box" mnemonicParsing="false" selected="true" text="LOD 4" />
<HBox alignment="CENTER_RIGHT" fillHeight="false" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" spacing="5.0">
<children>
<Button fx:id="okBtn" alignment="CENTER_RIGHT" mnemonicParsing="false" text="OK" />
<Button fx:id="cancelBtn" alignment="CENTER_RIGHT" mnemonicParsing="false" text="Cancel" />
</children>
</HBox>
</children>
</VBox>
GUISettings.properties
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2">
<ns prefix="gml" uri="http://www.opengis.net/gml"/>
<ns prefix="bldg" uri="http://www.opengis.net/citygml/building/2.0"/>
<pattern>
<rule context="//*:Building">
<assert test="count(descendant::*:lod1Solid) &gt; 0 or count(descendant::*:lod2Solid) &gt; 0 or count(descendant::*:lod3Solid) &gt; 0 or count(descendant::*:lod4Solid) &gt; 0"><value-of select="@gml:id | @id"/>||||SE_ATTRIBUTE_MISSING||any solid</assert>
</rule>
<rule context="//*:BuildingPart">
<assert test="count(*:lod1Solid) = 1 or count(*:lod2Solid) = 1 or count(*:lod3Solid) = 1 or count(*:lod4Solid) = 1"><value-of select="ancestor::*:Building/@*:id"/>||<value-of select="@gml:id | @id"/>||SE_ATTRIBUTE_MISSING||any solid</assert>
</rule>
</pattern>
</schema>
<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<parent>
<groupId>de.hft.stuttgart</groupId>
<artifactId>CityDoctorParent</artifactId>
<version>3.14.1</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>CityDoctorHealerGenetic</artifactId>
<dependencies>
<dependency>
<groupId>de.hft.stuttgart</groupId>
<artifactId>CityDoctorHealerGUI</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
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