Commit 4d665835 authored by Luna Riegel's avatar Luna Riegel
Browse files

Refactor: Extract construction of feature-subtrees

parent 986041f2
Pipeline #12360 failed with stage
in 47 seconds
...@@ -10,10 +10,10 @@ import java.util.Map; ...@@ -10,10 +10,10 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Stream; import java.util.stream.Stream;
import de.hft.stuttgart.citydoctor2.gui.tree.node.NodeTreeBuilder;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.citygml4j.core.model.core.CityModel; import org.citygml4j.core.model.core.CityModel;
...@@ -23,36 +23,17 @@ import de.hft.stuttgart.citydoctor2.check.Checker; ...@@ -23,36 +23,17 @@ import de.hft.stuttgart.citydoctor2.check.Checker;
import de.hft.stuttgart.citydoctor2.check.ErrorId; import de.hft.stuttgart.citydoctor2.check.ErrorId;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration; import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.database.UnconnectedCache; import de.hft.stuttgart.citydoctor2.database.UnconnectedCache;
import de.hft.stuttgart.citydoctor2.datastructure.AbstractBuilding;
import de.hft.stuttgart.citydoctor2.datastructure.AbstractFurniture;
import de.hft.stuttgart.citydoctor2.datastructure.AbstractRoom;
import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface;
import de.hft.stuttgart.citydoctor2.datastructure.BoundingBox; 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.BridgeObject;
import de.hft.stuttgart.citydoctor2.datastructure.Building; import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.BuildingConstructiveElement;
import de.hft.stuttgart.citydoctor2.datastructure.BuildingPart;
import de.hft.stuttgart.citydoctor2.datastructure.BuildingUnit;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel; import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.CityFurniture; import de.hft.stuttgart.citydoctor2.datastructure.CityFurniture;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject; import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
import de.hft.stuttgart.citydoctor2.datastructure.FeatureType; import de.hft.stuttgart.citydoctor2.datastructure.FeatureType;
import de.hft.stuttgart.citydoctor2.datastructure.GenericCityObject; import de.hft.stuttgart.citydoctor2.datastructure.GenericCityObject;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GmlId; import de.hft.stuttgart.citydoctor2.datastructure.GmlId;
import de.hft.stuttgart.citydoctor2.datastructure.Installation;
import de.hft.stuttgart.citydoctor2.datastructure.Opening;
import de.hft.stuttgart.citydoctor2.datastructure.Storey;
import de.hft.stuttgart.citydoctor2.datastructure.TopLevelTransportFeature;
import de.hft.stuttgart.citydoctor2.datastructure.TrafficAreaObject;
import de.hft.stuttgart.citydoctor2.datastructure.TrafficSpaceObject;
import de.hft.stuttgart.citydoctor2.datastructure.TransportSection;
import de.hft.stuttgart.citydoctor2.datastructure.TransportationObject; import de.hft.stuttgart.citydoctor2.datastructure.TransportationObject;
import de.hft.stuttgart.citydoctor2.datastructure.TransportationSpace;
import de.hft.stuttgart.citydoctor2.datastructure.Tunnel; import de.hft.stuttgart.citydoctor2.datastructure.Tunnel;
import de.hft.stuttgart.citydoctor2.datastructure.TunnelConstructiveElement;
import de.hft.stuttgart.citydoctor2.datastructure.TunnelPart;
import de.hft.stuttgart.citydoctor2.datastructure.Vegetation; import de.hft.stuttgart.citydoctor2.datastructure.Vegetation;
import de.hft.stuttgart.citydoctor2.datastructure.WaterObject; import de.hft.stuttgart.citydoctor2.datastructure.WaterObject;
import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException; import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException;
...@@ -61,10 +42,6 @@ import de.hft.stuttgart.citydoctor2.gui.tree.AddMoreButtonRunnable; ...@@ -61,10 +42,6 @@ import de.hft.stuttgart.citydoctor2.gui.tree.AddMoreButtonRunnable;
import de.hft.stuttgart.citydoctor2.gui.tree.ButtonRenderable; import de.hft.stuttgart.citydoctor2.gui.tree.ButtonRenderable;
import de.hft.stuttgart.citydoctor2.gui.tree.Renderable; import de.hft.stuttgart.citydoctor2.gui.tree.Renderable;
import de.hft.stuttgart.citydoctor2.gui.tree.node.CityObjectGroupNode; import de.hft.stuttgart.citydoctor2.gui.tree.node.CityObjectGroupNode;
import de.hft.stuttgart.citydoctor2.gui.tree.node.CityObjectNode;
import de.hft.stuttgart.citydoctor2.gui.tree.node.GeometryNode;
import de.hft.stuttgart.citydoctor2.gui.tree.node.OpeningNode;
import de.hft.stuttgart.citydoctor2.gui.tree.node.TopLevelCityObjectNode;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException; import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParser; import de.hft.stuttgart.citydoctor2.parser.CityGmlParser;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException; import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
...@@ -194,7 +171,6 @@ public class CityDoctorController { ...@@ -194,7 +171,6 @@ public class CityDoctorController {
buildLand(model); buildLand(model);
buildCityFurniture(model); buildCityFurniture(model);
buildGenericCityObjects(model); buildGenericCityObjects(model);
buildTunnel(model);
} }
private void resetFeatureChunks() { private void resetFeatureChunks() {
...@@ -226,11 +202,8 @@ public class CityDoctorController { ...@@ -226,11 +202,8 @@ public class CityDoctorController {
private void buildLandTreeFromList(Supplier<Stream<CityObject>> supply, TreeItem<Renderable> root) { private void buildLandTreeFromList(Supplier<Stream<CityObject>> supply, TreeItem<Renderable> root) {
int landChunk = landChunkNr.get(); int landChunk = landChunkNr.get();
supply.get().skip((long) landChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(land ->{ supply.get().skip((long) landChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(land ->{
CityObjectNode node = new CityObjectNode(land); TreeItem<Renderable> item = NodeTreeBuilder.buildFeatureSubTree(land);
TreeItem<Renderable> item = new TreeItem<>(node);
item.setExpanded(true);
root.getChildren().add(item); root.getChildren().add(item);
createGeometryNodes(land, item);
}); });
} }
...@@ -336,51 +309,6 @@ public class CityDoctorController { ...@@ -336,51 +309,6 @@ public class CityDoctorController {
addMoreButtonForVegetation(vegetationsView, vegRoot, vegetationChunkNr, supply, model.getVegetationCount()); addMoreButtonForVegetation(vegetationsView, vegRoot, vegetationChunkNr, supply, model.getVegetationCount());
} }
private void addMoreButtonIfNecessary(List<? extends CityObject> list, TreeView<Renderable> view,
TreeItem<Renderable> root, AtomicInteger chunkCounter) {
if ((chunkCounter.get() + 1) * MAX_FEATURES_PER_CHUNK < list.size()) {
Runnable run = new Runnable() {
public void run() {
// 29 is the height of one item
int numberOfDisplayedItems = (int) (view.getHeight() / 29);
int selectedIndex = view.getSelectionModel().getSelectedIndex();
// remove button node
root.getChildren().remove(root.getChildren().size() - 1);
chunkCounter.incrementAndGet();
int visibleFeatures = countVisibleNodes(view);
// buildTreeFromList(list, root, chunkCounter);
updateTree(root);
if (selectedIndex >= 0) {
view.getSelectionModel().select(selectedIndex);
}
if ((chunkCounter.get() + 1) * MAX_FEATURES_PER_CHUNK < list.size()) {
root.getChildren().add(new TreeItem<>(new ButtonRenderable(this)));
}
view.scrollTo(visibleFeatures - numberOfDisplayedItems + 1);
}
};
// add button for expansion
root.getChildren().add(new TreeItem<>(new ButtonRenderable(run)));
}
}
private void moreButton(CityDoctorModel model, TreeView<Renderable> view, TreeItem<Renderable> root,
AtomicInteger chunkCounter, Supplier<Stream<CityObject>> streamSupplier){
int featureCount = model.getBuildingCount();
if ((chunkCounter.get() + 1) * MAX_FEATURES_PER_CHUNK < featureCount) {
AddMoreButtonRunnable run = new AddMoreButtonRunnable(featureCount, view, root, chunkCounter) {
@Override
public void buildNodeTreeCall() {
buildTreeFromList(streamSupplier, root, chunkCounter);
updateTree(root);
}
};
//add button
root.getChildren().add(new TreeItem<>(new ButtonRenderable(run)));
}
}
private void buildBuildings(CityDoctorModel model) { private void buildBuildings(CityDoctorModel model) {
if (model.getBuildingCount() == 0) { if (model.getBuildingCount() == 0) {
return; return;
...@@ -393,35 +321,6 @@ public class CityDoctorController { ...@@ -393,35 +321,6 @@ public class CityDoctorController {
Supplier<Stream<Building>> supply = model::getBuildings; Supplier<Stream<Building>> supply = model::getBuildings;
buildBuildingTreeFromList(supply, root); buildBuildingTreeFromList(supply, root);
addMoreButtonForBuildings(buildingsView, root, buildingChunkNr, supply, model.getBuildingCount()); addMoreButtonForBuildings(buildingsView, root, buildingChunkNr, supply, model.getBuildingCount());
}
private void addMoreButtonToBuildingsIfNecessary(List<Building> list, TreeView<Renderable> view,
TreeItem<Renderable> root, AtomicInteger chunkCounter) {
if ((chunkCounter.get() + 1) * MAX_FEATURES_PER_CHUNK < list.size()) {
Runnable run = new Runnable() {
public void run() {
// 29 is the height of one item
int numberOfDisplayedItems = (int) (view.getHeight() / 29);
int selectedIndex = view.getSelectionModel().getSelectedIndex();
// remove button node
root.getChildren().remove(root.getChildren().size() - 1);
chunkCounter.getAndIncrement();
int visibleFeatures = countVisibleNodes(view);
// buildBuildingTreeFromList(list, root);
updateTree(root);
if (selectedIndex >= 0) {
view.getSelectionModel().select(selectedIndex);
}
if ((chunkCounter.get() + 1) * MAX_FEATURES_PER_CHUNK < list.size()) {
root.getChildren().add(new TreeItem<>(new ButtonRenderable(this)));
}
view.scrollTo(visibleFeatures - numberOfDisplayedItems + 1);
}
};
// add button for expansion
root.getChildren().add(new TreeItem<>(new ButtonRenderable(run)));
}
} }
private void addMoreButtonForBuildings(TreeView<Renderable> view, TreeItem<Renderable> root, private void addMoreButtonForBuildings(TreeView<Renderable> view, TreeItem<Renderable> root,
...@@ -573,30 +472,6 @@ public class CityDoctorController { ...@@ -573,30 +472,6 @@ public class CityDoctorController {
return visibleFeatures; return visibleFeatures;
} }
private void buildTreeFromList(Supplier<Stream<CityObject>> supply, TreeItem<Renderable> root,
AtomicInteger chunkCounter) {
int buildingChunk = buildingChunkNr.get();
supply.get().skip((long) buildingChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(co ->{
CityObjectNode node = new CityObjectNode(co);
TreeItem<Renderable> nodeItem = new TreeItem<>(node);
nodeItem.setExpanded(true);
root.getChildren().add(nodeItem);
createGeometryNodes(co, nodeItem);
});
}
private <T extends CityObject> void buildTreeFromListWithProducer(List<T> cos, TreeItem<Renderable> root,
AtomicInteger chunkCounter, Function<T, Renderable> nodeProducer) {
int chunk = chunkCounter.get();
for (int i = chunk * MAX_FEATURES_PER_CHUNK; i < (chunk + 1) * MAX_FEATURES_PER_CHUNK && i < cos.size(); i++) {
T co = cos.get(i);
Renderable node = nodeProducer.apply(co);
TreeItem<Renderable> nodeItem = new TreeItem<>(node);
nodeItem.setExpanded(true);
root.getChildren().add(nodeItem);
createGeometryNodes(co, nodeItem);
}
}
private void clearTrees() { private void clearTrees() {
mainWindow.getBuildingsView().setRoot(null); mainWindow.getBuildingsView().setRoot(null);
...@@ -620,64 +495,20 @@ public class CityDoctorController { ...@@ -620,64 +495,20 @@ public class CityDoctorController {
mainWindow.getVertexView().getRoot().getChildren().clear(); mainWindow.getVertexView().getRoot().getChildren().clear();
} }
private TreeItem<Renderable> buildTopLevelCityObjectNode(CityObject co, TreeItem<Renderable> root) {
return buildTopLevelCityObjectNode(co, root, Collections.emptyList());
}
private TreeItem<Renderable> buildTopLevelCityObjectNode(CityObject co, TreeItem<Renderable> root,
List<BoundarySurface> surfaces) {
TopLevelCityObjectNode node = new TopLevelCityObjectNode(co);
TreeItem<Renderable> nodeItem = new TreeItem<>(node);
nodeItem.setExpanded(true);
root.getChildren().add(nodeItem);
createGeometryNodes(co, nodeItem);
if (!surfaces.isEmpty()) {
createBoundarySurfaceNodes(surfaces, nodeItem);
}
return nodeItem;
}
private TreeItem<Renderable> buildCityObjectNode(CityObject co, TreeItem<Renderable> root) {
return buildCityObjectNode(co, root, Collections.emptyList());
}
private TreeItem<Renderable> buildCityObjectNode(CityObject co, TreeItem<Renderable> root, List<BoundarySurface> surfaces) {
CityObjectNode node = new CityObjectNode(co);
TreeItem<Renderable> nodeItem = new TreeItem<>(node);
nodeItem.setExpanded(false);
root.getChildren().add(nodeItem);
createGeometryNodes(co, nodeItem);
if (!surfaces.isEmpty()) {
createBoundarySurfaceNodes(surfaces, nodeItem);
}
return nodeItem;
}
private void buildBuildingTreeFromList(Supplier<Stream<Building>> supply, TreeItem<Renderable> root) { private void buildBuildingTreeFromList(Supplier<Stream<Building>> supply, TreeItem<Renderable> root) {
int buildingChunk = buildingChunkNr.get(); int buildingChunk = buildingChunkNr.get();
supply.get().skip((long) buildingChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(b ->{ supply.get().skip((long) buildingChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(b ->{
TreeItem<Renderable> item = buildTopLevelCityObjectNode(b, root, b.getBoundarySurfaces()); TreeItem<Renderable> item = NodeTreeBuilder.buildFeatureSubTree(b);
root.getChildren().add(item);
createBuildingInstallationNodes(b, item);
createBuildingConstructiveElementsNodes(b, item);
createBuildingRoomNodes(b, item);
createBuildingFurnitureNodes(b, item);
createBuildingStoreyNodes(b, item);
createBuildingUnitNodes(b, item);
createBuildingPartNodes(b, item);
}); });
} }
private void buildBridgeTreeFromList(Supplier<Stream<BridgeObject>> supply, TreeItem<Renderable> root) { private void buildBridgeTreeFromList(Supplier<Stream<BridgeObject>> supply, TreeItem<Renderable> root) {
int bridgeChunk = bridgeChunkNr.get(); int bridgeChunk = bridgeChunkNr.get();
supply.get().skip((long) bridgeChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(bridge ->{ supply.get().skip((long) bridgeChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(bridge ->{
TreeItem<Renderable> item = buildTopLevelCityObjectNode(bridge, root, bridge.getBoundarySurfaces()); TreeItem<Renderable> item = NodeTreeBuilder.buildFeatureSubTree(bridge);
root.getChildren().add(item);
createBridgeRoomNodes(bridge, item);
createBridgeInstallationNodes(bridge, item);
createBridgeFurnitureNodes(bridge, item);
createBridgeConstructiveElementsNodes(bridge, item);
createBridgePartNodes(bridge, item);
}); });
} }
...@@ -685,16 +516,16 @@ public class CityDoctorController { ...@@ -685,16 +516,16 @@ public class CityDoctorController {
private void buildTransportationTreeFromList(Supplier<Stream<TransportationObject>> supply, TreeItem<Renderable> root) { private void buildTransportationTreeFromList(Supplier<Stream<TransportationObject>> supply, TreeItem<Renderable> root) {
int transportChunk = transportationChunkNr.get(); int transportChunk = transportationChunkNr.get();
supply.get().skip((long) transportChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(trans ->{ supply.get().skip((long) transportChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(trans ->{
TreeItem<Renderable> item = buildTopLevelCityObjectNode(trans, root); TreeItem<Renderable> item = NodeTreeBuilder.buildFeatureSubTree(trans);
createTransportSectionNodes(trans, item); root.getChildren().add(item);
createTrafficSpacesNodes(trans, item);
}); });
} }
private void buildVegetationTreeFromList(Supplier<Stream<Vegetation>> supply, TreeItem<Renderable> root) { private void buildVegetationTreeFromList(Supplier<Stream<Vegetation>> supply, TreeItem<Renderable> root) {
int vegetationChunk = vegetationChunkNr.get(); int vegetationChunk = vegetationChunkNr.get();
supply.get().skip((long) vegetationChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(veg ->{ supply.get().skip((long) vegetationChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(veg ->{
buildTopLevelCityObjectNode(veg, root); TreeItem<Renderable> item = NodeTreeBuilder.buildFeatureSubTree(veg);
root.getChildren().add(item);
}); });
} }
...@@ -702,373 +533,34 @@ public class CityDoctorController { ...@@ -702,373 +533,34 @@ public class CityDoctorController {
private void buildWaterTreeFromList(Supplier<Stream<WaterObject>> supply, TreeItem<Renderable> root) { private void buildWaterTreeFromList(Supplier<Stream<WaterObject>> supply, TreeItem<Renderable> root) {
int waterChunk = waterChunkNr.get(); int waterChunk = waterChunkNr.get();
supply.get().skip((long) waterChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(wat ->{ supply.get().skip((long) waterChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(wat ->{
buildTopLevelCityObjectNode(wat, root); TreeItem<Renderable> item = NodeTreeBuilder.buildFeatureSubTree(wat);
root.getChildren().add(item);
}); });
} }
private void buildCityFurnitureTreeFromList(Supplier<Stream<CityFurniture>> supply, TreeItem<Renderable> root) { private void buildCityFurnitureTreeFromList(Supplier<Stream<CityFurniture>> supply, TreeItem<Renderable> root) {
int cityFurnChunk = cityFurnitureChunkNr.get(); int cityFurnChunk = cityFurnitureChunkNr.get();
supply.get().skip((long) cityFurnChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(cf ->{ supply.get().skip((long) cityFurnChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(cf ->{
buildTopLevelCityObjectNode(cf, root); TreeItem<Renderable> item = NodeTreeBuilder.buildFeatureSubTree(cf);
root.getChildren().add(item);
}); });
} }
private void buildOtherCityObjectsTreeFromList(Supplier<Stream<CityObject>> supply, TreeItem<Renderable> root) { private void buildOtherCityObjectsTreeFromList(Supplier<Stream<CityObject>> supply, TreeItem<Renderable> root) {
int genericObjectChunk = otherCityObjectsChunkNr.get(); int genericObjectChunk = otherCityObjectsChunkNr.get();
supply.get().skip((long) genericObjectChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(gen ->{ supply.get().skip((long) genericObjectChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(gen ->{
buildTopLevelCityObjectNode(gen, root); TreeItem<Renderable> item = NodeTreeBuilder.buildFeatureSubTree(gen);
root.getChildren().add(item);
}); });
} }
private void createTransportSectionNodes(TransportationObject t, TreeItem<Renderable> root) {
if (t instanceof TopLevelTransportFeature top) {
if (!top.getSections().isEmpty()) {
CityObjectGroupNode sectionsGroupNode = new CityObjectGroupNode(top.getSections(),
"Sections", Color.YELLOW);
TreeItem<Renderable> sectionsGroupItem = new TreeItem<>(sectionsGroupNode);
root.getChildren().add(sectionsGroupItem);
for (TransportSection ts : top.getSections()) {
TreeItem<Renderable> tsNodeItem = buildCityObjectNode(ts, sectionsGroupItem);
createTrafficSpacesNodes(ts, tsNodeItem);
}
}
if (!top.getIntersections().isEmpty()) {
CityObjectGroupNode intersectionsGroupNode = new CityObjectGroupNode(top.getIntersections(),
"Intersections", Color.YELLOW);
TreeItem<Renderable> intersectionsGroupItem = new TreeItem<>(intersectionsGroupNode);
root.getChildren().add(intersectionsGroupItem);
for (TransportSection ts : top.getIntersections()) {
TreeItem<Renderable> tsNodeItem = buildCityObjectNode(ts, intersectionsGroupItem);
createTrafficSpacesNodes(ts, tsNodeItem);
}
}
}
}
private void createTrafficSpacesNodes(TransportationObject t, TreeItem<Renderable> root) {
if (t instanceof TransportationSpace space) {
if (!space.getTrafficSpaces().isEmpty()) {
CityObjectGroupNode trafficSpacesGroupNode = new CityObjectGroupNode(space.getTrafficSpaces(),
"TRAFFIC_SPACE", Color.YELLOW);
TreeItem<Renderable> trafficSpacesGroupItem = new TreeItem<>(trafficSpacesGroupNode);
root.getChildren().add(trafficSpacesGroupItem);
trafficSpacesGroupItem.setExpanded(true);
for (TrafficSpaceObject tso : space.getTrafficSpaces()) {
TreeItem<Renderable> tsoNodeItem = buildCityObjectNode(tso, trafficSpacesGroupItem);
createTrafficAreaNodes(tso, tsoNodeItem, TrafficAreaObject.TrafficAreaType.TRAFFIC_AREA);
}
}
if (!space.getAuxTrafficSpaces().isEmpty()) {
CityObjectGroupNode auxTrafficSpacesGroupNode = new CityObjectGroupNode(space.getAuxTrafficSpaces(),
"AUXILIARY_TRAFFIC_SPACE", Color.YELLOW);
TreeItem<Renderable> auxTrafficSpacesGroupItem = new TreeItem<>(auxTrafficSpacesGroupNode);
root.getChildren().add(auxTrafficSpacesGroupItem);
auxTrafficSpacesGroupItem.setExpanded(true);
for (TrafficSpaceObject atso : space.getAuxTrafficSpaces()) {
TreeItem<Renderable> atsoNodeItem = buildCityObjectNode(atso, auxTrafficSpacesGroupItem);
createTrafficAreaNodes(atso, atsoNodeItem, TrafficAreaObject.TrafficAreaType.AUXILIARY_TRAFFIC_AREA);
}
}
}
}
public void createTrafficAreaNodes(TransportationObject t, TreeItem<Renderable> root, TrafficAreaObject.TrafficAreaType type) {
if (t instanceof TrafficSpaceObject space && !space.getTrafficAreas().isEmpty()) {
CityObjectGroupNode trafficAreaGroupNode = new CityObjectGroupNode(space.getTrafficAreas(), type.toString(), Color.YELLOW);
TreeItem<Renderable> trafficAreaGroupItem = new TreeItem<>(trafficAreaGroupNode);
root.getChildren().add(trafficAreaGroupItem);
trafficAreaGroupItem.setExpanded(true);
for (TrafficAreaObject tao : space.getTrafficAreas()) {
buildCityObjectNode(tao, trafficAreaGroupItem);
}
}
}
private void buildTunnelTreeFromList(Supplier<Stream<Tunnel>> supply, TreeItem<Renderable> root) { private void buildTunnelTreeFromList(Supplier<Stream<Tunnel>> supply, TreeItem<Renderable> root) {
int tunnelChunk = tunnelChunkNr.get(); int tunnelChunk = tunnelChunkNr.get();
supply.get().skip((long) tunnelChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(tunnel ->{ supply.get().skip((long) tunnelChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(tunnel ->{
TreeItem<Renderable> item = buildTopLevelCityObjectNode(tunnel, root); TreeItem<Renderable> item = NodeTreeBuilder.buildFeatureSubTree(tunnel);
root.getChildren().add(item);
createTunnelHollowNodes(tunnel, item);
createTunnelInstallationNodes(tunnel, item);
createTunnelFurnitureNodes(tunnel, item);
createTunnelConstructiveElementsNodes(tunnel, item);
createTunnelPartNodes(tunnel, item);
});
}
private void createTunnelInstallationNodes(Tunnel tunnel, TreeItem<Renderable> root) {
createInstallationNodes(tunnel.getTunnelInstallations(), root);
}
private void createTunnelHollowNodes(Tunnel tunnel, TreeItem<Renderable> root) {
createRoomNodes(tunnel.getTunnelHollows(), root);
}
private void createTunnelFurnitureNodes(Tunnel tunnel, TreeItem<Renderable> root) {
createFurnitureNodes(tunnel.getTunnelFurniture(), root);
}
private void createTunnelConstructiveElementsNodes(Tunnel tunnel, TreeItem<Renderable> root){
if (tunnel.getTunnelConstructiveElements().isEmpty()){
return;
}
CityObjectGroupNode constructiveElementsGroupNode = new CityObjectGroupNode(tunnel.getTunnelConstructiveElements(),
"Constructive Elements", Color.DARKGRAY);
TreeItem<Renderable> constructiveElementsGroupItem = new TreeItem<>(constructiveElementsGroupNode);
root.getChildren().add(constructiveElementsGroupItem);
for (TunnelConstructiveElement tce : tunnel.getTunnelConstructiveElements()) {
buildCityObjectNode(tce, constructiveElementsGroupItem, tce.getBoundarySurfaces());
}
}
private void createTunnelPartNodes(Tunnel tunnel, TreeItem<Renderable> root) {
if (tunnel.getTunnelParts().isEmpty()) {
return;
}
CityObjectGroupNode tunnelPartsGroupNode = new CityObjectGroupNode(tunnel.getTunnelParts(), "Tunnel parts", Color.DARKGRAY);
TreeItem<Renderable> tunnelPartsGroupItem = new TreeItem<>(tunnelPartsGroupNode);
root.getChildren().add(tunnelPartsGroupItem);
for (TunnelPart tp : tunnel.getTunnelParts()) {
TreeItem<Renderable> tpNodeItem = buildCityObjectNode(tp, tunnelPartsGroupItem, tp.getBoundarySurfaces());
createTunnelHollowNodes(tunnel, tpNodeItem);
createTunnelInstallationNodes(tunnel, tpNodeItem);
createTunnelFurnitureNodes(tunnel, tpNodeItem);
createTunnelConstructiveElementsNodes(tunnel, tpNodeItem);
}
}
private void createBridgeRoomNodes(BridgeObject bridge, TreeItem<Renderable> root) {
createRoomNodes(bridge.getBridgeRooms(), root);
}
private void createBridgeInstallationNodes(BridgeObject bridge, TreeItem<Renderable> root) {
createInstallationNodes(bridge.getBridgeInstallations(), root);
}
private void createBridgeFurnitureNodes(BridgeObject bridge, TreeItem<Renderable> root) {
createFurnitureNodes(bridge.getBridgeFurniture(), root);
}
private void createBridgeConstructiveElementsNodes(BridgeObject bridge, TreeItem<Renderable> item) {
if (bridge.getConstructiveElements().isEmpty()) {
return;
}
CityObjectGroupNode constructiveElementsGroupNode = new CityObjectGroupNode(
bridge.getConstructiveElements(), "Constructive Elements", Color.CORAL);
TreeItem<Renderable> constructiveElementsGroupItem = new TreeItem<>(constructiveElementsGroupNode);
item.getChildren().add(constructiveElementsGroupItem);
for (BridgeConstructiveElement bce : bridge.getConstructiveElements()) {
buildCityObjectNode(bce, constructiveElementsGroupItem, bce.getBoundarySurfaces());
}
}
private void createBridgePartNodes(BridgeObject bridge, TreeItem<Renderable> item) {
if (bridge.getParts().isEmpty()) {
return;
}
CityObjectGroupNode bridgePartsGroupNode = new CityObjectGroupNode(bridge.getParts(), "Bridge Parts", Color.CORAL);
TreeItem<Renderable> bridgePartsGroupItem = new TreeItem<>(bridgePartsGroupNode);
item.getChildren().add(bridgePartsGroupItem);
for (BridgeObject bp : bridge.getParts()) {
TreeItem<Renderable> bpNodeItem = buildCityObjectNode(bp, bridgePartsGroupItem, bp.getBoundarySurfaces());
createBridgeRoomNodes(bp, bpNodeItem);
createBridgeInstallationNodes(bp, bpNodeItem);
createBridgeFurnitureNodes(bp, bpNodeItem);
createBridgeConstructiveElementsNodes(bp, bpNodeItem);
}
}
private void createBuildingInstallationNodes(AbstractBuilding ab, TreeItem<Renderable> root) {
createInstallationNodes(ab.getBuildingInstallations(), root);
}
private void createInstallationNodes(List<Installation> installations, TreeItem<Renderable> root) {
if (installations.isEmpty()) {
return;
}
CityObjectGroupNode installationsGroupNode = new CityObjectGroupNode(installations, "Installations", null);
TreeItem<Renderable> installationsGroupItem = new TreeItem<>(installationsGroupNode);
root.getChildren().add(installationsGroupItem);
for (Installation bi : installations) {
buildCityObjectNode(bi, installationsGroupItem, bi.getBoundarySurfaces());
}
}
private void createBuildingRoomNodes(AbstractBuilding ab, TreeItem<Renderable> root) {
createRoomNodes(ab.getBuildingRooms(), root);
}
private void createBuildingConstructiveElementsNodes(AbstractBuilding ab, TreeItem<Renderable> root) {
if (ab.getConstructiveElements().isEmpty()) {
return;
}
CityObjectGroupNode constructiveElementsGroupNode = new CityObjectGroupNode(
ab.getConstructiveElements(), "Constructive Elements", Color.CORAL);
TreeItem<Renderable> constructiveElementsGroupItem = new TreeItem<>(constructiveElementsGroupNode);
root.getChildren().add(constructiveElementsGroupItem);
for (BuildingConstructiveElement bce : ab.getConstructiveElements()) {
buildCityObjectNode(bce, constructiveElementsGroupItem, bce.getBoundarySurfaces());
}
}
private void createRoomNodes(List<? extends AbstractRoom> rooms, TreeItem<Renderable> root) {
if (rooms.isEmpty()) {
return;
}
CityObjectGroupNode roomsGroupNode = new CityObjectGroupNode(rooms, "Rooms", null);
TreeItem<Renderable> roomsGroupItem = new TreeItem<>(roomsGroupNode);
root.getChildren().add(roomsGroupItem);
for (AbstractRoom room : rooms) {
buildCityObjectNode(room, roomsGroupItem, room.getBoundarySurfaces());
}
}
private void createBuildingStoreyNodes(AbstractBuilding ab, TreeItem<Renderable> root) {
List<Storey> storeys = ab.getBuildingStoreys();
if (storeys.isEmpty()) {
return;
}
CityObjectGroupNode storeysGroupNode = new CityObjectGroupNode(storeys, "Storeys", null);
TreeItem<Renderable> storeysGroupItem = new TreeItem<>(storeysGroupNode);
root.getChildren().add(storeysGroupItem);
for (Storey storey : storeys) {
buildCityObjectNode(storey, storeysGroupItem, storey.getBoundarySurfaces());
}
}
public void createBuildingUnitNodes(AbstractBuilding ab, TreeItem<Renderable> root) {
List<BuildingUnit> buildingUnits = ab.getBuildingUnits();
if (buildingUnits.isEmpty()) {
return;
}
CityObjectGroupNode buildingUnitsGroupNode = new CityObjectGroupNode(buildingUnits, "Building Units", null);
TreeItem<Renderable> buildingUnitsGroupItem = new TreeItem<>(buildingUnitsGroupNode);
root.getChildren().add(buildingUnitsGroupItem);
for (BuildingUnit buildingUnit : buildingUnits) {
buildCityObjectNode(buildingUnit, buildingUnitsGroupItem, buildingUnit.getBoundarySurfaces());
}
}
private void createBuildingFurnitureNodes(AbstractBuilding ab, TreeItem<Renderable> root) {
createFurnitureNodes(ab.getBuildingRoomFurnitureList(), root);
}
private void createFurnitureNodes(List<? extends AbstractFurniture> furniture, TreeItem<Renderable> root) {
if (furniture.isEmpty()) {
return;
}
CityObjectGroupNode furnitureGroupNode = new CityObjectGroupNode(furniture, "Furniture", null);
TreeItem<Renderable> furnitureGroupItem = new TreeItem<>(furnitureGroupNode);
root.getChildren().add(furnitureGroupItem);
for (AbstractFurniture fn : furniture) {
buildCityObjectNode(fn, furnitureGroupItem, fn.getBoundarySurfaces());
}
}
private void createBoundarySurfaceNodes(List<BoundarySurface> bsList, TreeItem<Renderable> root) {
if (bsList.isEmpty()) {
return;
}
CityObjectGroupNode boundarySurfacesGroupNode = new CityObjectGroupNode(bsList, "Boundary Surfaces", null);
TreeItem<Renderable> boundarySurfacesGroupItem = new TreeItem<>(boundarySurfacesGroupNode);
root.getChildren().add(boundarySurfacesGroupItem);
boundarySurfacesGroupItem.getChildren().add(new TreeItem<>());
boundarySurfacesGroupItem.expandedProperty().addListener((obs, old, newV) -> {
if (Boolean.TRUE.equals(newV) && boundarySurfacesGroupItem.getChildren().size() == 1) {
Platform.runLater(() -> {
boundarySurfacesGroupItem.getChildren().clear();
for (BoundarySurface bs : bsList) {
CityObjectNode bsText = new CityObjectNode(bs);
TreeItem<Renderable> bsTextItem = new TreeItem<>(bsText);
bsTextItem.setExpanded(true);
boundarySurfacesGroupItem.getChildren().add(bsTextItem);
createGeometryNodes(bs, bsTextItem);
createOpeningNodes(bs.getOpenings(), bsTextItem);
}
updateTree(boundarySurfacesGroupItem);
});
}
}); });
}
private void createOpeningNodes(List<Opening> openings, TreeItem<Renderable> root) {
if (openings == null || openings.isEmpty()) {
return;
}
CityObjectGroupNode openingsGroupNode = new CityObjectGroupNode(openings, "Openings", null);
TreeItem<Renderable> openingsGroupItem = new TreeItem<>(openingsGroupNode);
root.getChildren().add(openingsGroupItem);
for (Opening o : openings) {
OpeningNode openingNode = new OpeningNode(o);
TreeItem<Renderable> openingItem = new TreeItem<>(openingNode);
openingsGroupItem.getChildren().add(openingItem);
}
}
private void createBuildingPartNodes(Building ab, TreeItem<Renderable> item) {
if (ab.getBuildingParts().isEmpty()) {
return;
}
CityObjectGroupNode buildingPartsGroupNode = new CityObjectGroupNode(ab.getBuildingParts(), "Building Parts", null);
TreeItem<Renderable> buildingPartsGroupItem = new TreeItem<>(buildingPartsGroupNode);
item.getChildren().add(buildingPartsGroupItem);
for (BuildingPart bp : ab.getBuildingParts()) {
TreeItem<Renderable> bpNodeItem = buildCityObjectNode(bp, buildingPartsGroupItem, bp.getBoundarySurfaces());
createBuildingInstallationNodes(bp, bpNodeItem);
createBuildingRoomNodes(bp, bpNodeItem);
createBuildingFurnitureNodes(bp, bpNodeItem);
createBuildingStoreyNodes(bp, bpNodeItem);
createBuildingUnitNodes(bp, bpNodeItem);
}
}
private void createGeometryNodes(CityObject co, TreeItem<Renderable> item) {
for (Geometry geom : co.getGeometries()) {
GeometryNode geomNode = new GeometryNode(geom);
TreeItem<Renderable> geomItem = new TreeItem<>(geomNode);
item.getChildren().add(geomItem);
}
} }
public void startChecks(ValidationConfiguration config, ProgressListener l) { public void startChecks(ValidationConfiguration config, ProgressListener l) {
......
package de.hft.stuttgart.citydoctor2.gui.tree.node;
import com.sun.source.tree.Tree;
import de.hft.stuttgart.citydoctor2.check.CheckableUtilsVisitor;
import de.hft.stuttgart.citydoctor2.datastructure.*;
import de.hft.stuttgart.citydoctor2.gui.tree.Renderable;
import javafx.application.Platform;
import javafx.scene.control.TreeItem;
import java.util.List;
import java.util.Objects;
public class NodeTreeBuilder extends CheckableUtilsVisitor {
private TreeItem<Renderable> result;
private NodeTreeBuilder() {}
@Override
public void check(BridgeObject bo) {
result = NodeTreeBuilder.buildFeatureSubTree(bo);
}
@Override
public void check(Building b) {
result = NodeTreeBuilder.buildFeatureSubTree(b);
}
@Override
public void check(LandObject lo) {
result = NodeTreeBuilder.buildFeatureSubTree(lo);
}
@Override
public void check(TopLevelTransportFeature top) {
result = NodeTreeBuilder.buildFeatureSubTree(top);
}
@Override
public void check(TransportationObject to) {
if (to.getTransportationType() == TransportationObject.TransportationType.TRANSPORTATION_COMPLEX){
result = NodeTreeBuilder.buildFeatureSubTree(to);
}
}
@Override
public void check(Vegetation veg) {
result = NodeTreeBuilder.buildFeatureSubTree(veg);
}
@Override
public void check(WaterObject wo) {
result = NodeTreeBuilder.buildFeatureSubTree(wo);
}
@Override
public void check(ReliefObject relief) {
result = NodeTreeBuilder.buildFeatureSubTree(relief);
}
@Override
public void check(GenericCityObject gco) {
result = NodeTreeBuilder.buildFeatureSubTree(gco);
}
@Override
public void check(OtherConstructionObject oco) {
result = NodeTreeBuilder.buildFeatureSubTree(oco);
}
public static TreeItem<Renderable> buildFeatureSubTree(Building b){
TreeItem<Renderable> bNode = buildTopLevelCityObjectNode(b);
createAbstractBuildingNodes(b, bNode);
createBuildingPartNodes(b, bNode);
return bNode;
}
public static TreeItem<Renderable> buildFeatureSubTree(BridgeObject bo){
TreeItem<Renderable> boNode = buildTopLevelCityObjectNode(bo);
createAbstractBridgeNodes(bo, boNode);
createBridgePartNodes(bo, boNode);
return boNode;
}
public static TreeItem<Renderable> buildFeatureSubTree(Tunnel tu){
TreeItem<Renderable> tuNode = buildTopLevelCityObjectNode(tu);
createAbstractTunnelNodes(tu, tuNode);
createTunnelPartNodes(tu, tuNode);
return tuNode;
}
public static TreeItem<Renderable> buildFeatureSubTree(Vegetation v){
TreeItem<Renderable> vNode = buildTopLevelCityObjectNode(v);
createBoundedSpaceNodes(v, vNode);
return vNode;
}
public static TreeItem<Renderable> buildFeatureSubTree(CityFurniture cf){
TreeItem<Renderable> cfNode = buildTopLevelCityObjectNode(cf);
createBoundedSpaceNodes(cf, cfNode);
return cfNode;
}
public static TreeItem<Renderable> buildFeatureSubTree(GenericCityObject gc){
TreeItem<Renderable> gcNode = buildTopLevelCityObjectNode(gc);
createBoundedSpaceNodes(gc, gcNode);
return gcNode;
}
public static TreeItem<Renderable> buildFeatureSubTree(LandObject l){
return buildTopLevelCityObjectNode(l);
}
public static TreeItem<Renderable> buildFeatureSubTree(ReliefObject r){
TreeItem<Renderable> rNode = buildTopLevelCityObjectNode(r);
createReliefComponentNodes(r, rNode);
return rNode;
}
public static TreeItem<Renderable> buildFeatureSubTree(WaterObject w){
TreeItem<Renderable> wNode = buildTopLevelCityObjectNode(w);
createBoundedSpaceNodes(w, wNode);
return wNode;
}
public static TreeItem<Renderable> buildFeatureSubTree(TransportationObject t){
TreeItem<Renderable> tNode;
if (t instanceof TopLevelTransportFeature top){
tNode = buildTopLevelCityObjectNode(top);
createTopLevelTransportNodes(top, tNode);
} else {
tNode = buildTopLevelCityObjectNode(t);
createBoundedSpaceNodes(t, tNode);
}
return tNode;
}
public static TreeItem<Renderable> buildFeatureSubTree(OtherConstructionObject oc){
TreeItem<Renderable> ocNode = buildTopLevelCityObjectNode(oc);
createBoundedSpaceNodes(oc, ocNode);
return ocNode;
}
public static TreeItem<Renderable> buildFeatureSubTree(CityObject co){
return buildSubTreeFromUnknownCityObject(co);
}
private static TreeItem<Renderable> buildSubTreeFromUnknownCityObject(CityObject co) {
NodeTreeBuilder builder = new NodeTreeBuilder();
co.accept(builder);
return Objects.requireNonNullElseGet(builder.result, () -> buildTopLevelCityObjectNode(co));
}
private static TreeItem<Renderable> buildTopLevelCityObjectNode(CityObject co) {
TopLevelCityObjectNode node = new TopLevelCityObjectNode(co);
TreeItem<Renderable> nodeItem = new TreeItem<>(node);
nodeItem.setExpanded(true);
createGeometryNodes(co, nodeItem);
return nodeItem;
}
private static TreeItem<Renderable> buildCityObjectNode(CityObject co) {
CityObjectNode node = new CityObjectNode(co);
TreeItem<Renderable> nodeItem = new TreeItem<>(node);
nodeItem.setExpanded(false);
createGeometryNodes(co, nodeItem);
return nodeItem;
}
private static TreeItem<Renderable> buildBoundarySurfaceNode(BoundarySurface bs){
TreeItem<Renderable> node = buildCityObjectNode(bs);
createOpeningNodes(bs.getOpenings(), node);
node.setExpanded(true);
return node;
}
private static void createGeometryNodes(CityObject co, TreeItem<Renderable> item) {
for (Geometry geom : co.getGeometries()) {
GeometryNode geomNode = new GeometryNode(geom);
TreeItem<Renderable> geomItem = new TreeItem<>(geomNode);
item.getChildren().add(geomItem);
}
}
private static void createBoundedSpaceNodes(BoundedSpace space, TreeItem<Renderable> item) {
createBoundarySurfaceNodes(space.getBoundarySurfaces(), item);
}
private static void createBoundarySurfaceNodes(List<BoundarySurface> bsList, TreeItem<Renderable> root) {
if (bsList.isEmpty()) {
return;
}
CityObjectGroupNode boundarySurfacesGroupNode = new CityObjectGroupNode(bsList, "Boundary Surfaces", null);
TreeItem<Renderable> boundarySurfacesGroupItem = new TreeItem<>(boundarySurfacesGroupNode);
root.getChildren().add(boundarySurfacesGroupItem);
boundarySurfacesGroupItem.getChildren().add(new TreeItem<>());
boundarySurfacesGroupItem.expandedProperty().addListener((obs, old, newV) -> {
if (Boolean.TRUE.equals(newV) && boundarySurfacesGroupItem.getChildren().size() == 1) {
Platform.runLater(() -> {
boundarySurfacesGroupItem.getChildren().clear();
bsList.forEach(bs -> {
TreeItem<Renderable> bsNode = buildBoundarySurfaceNode(bs);
boundarySurfacesGroupItem.getChildren().add(bsNode);
});
updateTree(boundarySurfacesGroupItem);
});
}
});
}
private static void createOpeningNodes(List<Opening> openings, TreeItem<Renderable> root) {
if (openings == null || openings.isEmpty()) {
return;
}
CityObjectGroupNode openingsGroupNode = new CityObjectGroupNode(openings, "Openings", null);
TreeItem<Renderable> openingsGroupItem = new TreeItem<>(openingsGroupNode);
root.getChildren().add(openingsGroupItem);
for (Opening o : openings) {
OpeningNode openingNode = new OpeningNode(o);
TreeItem<Renderable> openingItem = new TreeItem<>(openingNode);
openingsGroupItem.getChildren().add(openingItem);
}
}
private static void createAbstractBuildingNodes(AbstractBuilding ab, TreeItem<Renderable> root) {
createBoundedSpaceNodes(ab, root);
createConstructionObjectNodes(ab, root);
createBuildingSubdivisionNodes(ab, root);
}
private static void createBuildingPartNodes(Building b, TreeItem<Renderable> root) {
if (b.getBuildingParts().isEmpty()) {
return;
}
CityObjectGroupNode buildingPartsGroupNode = new CityObjectGroupNode(b.getBuildingParts(),
"Building Parts", null);
TreeItem<Renderable> buildingPartsGroupItem = new TreeItem<>(buildingPartsGroupNode);
root.getChildren().add(buildingPartsGroupItem);
b.getBuildingParts().forEach(buildingPart -> {
TreeItem<Renderable> bpNode = buildCityObjectNode(buildingPart);
buildingPartsGroupItem.getChildren().add(bpNode);
createAbstractBuildingNodes(buildingPart, bpNode);
});
}
private static void createBuildingSubdivisionNodes(AbstractBuilding ab, TreeItem<Renderable> root) {
createBuildingUnitNodes(ab.getBuildingUnits(), root);
createStoreyNodes(ab.getStoreys(), root);
}
private static void createBuildingUnitNodes(List<BuildingUnit> units, TreeItem<Renderable> root) {
if(units.isEmpty()) {
return;
}
CityObjectGroupNode buildingUnitsGroupNode = new CityObjectGroupNode(units,
"Building Units", null);
TreeItem<Renderable> groupItem = new TreeItem<>(buildingUnitsGroupNode);
root.getChildren().add(groupItem);
units.forEach(buildingUnit -> {
TreeItem<Renderable> buNode = buildAbstractSubdivisionNode(buildingUnit);
createShallowStoreyNodes(buildingUnit.getStoreys(), buNode);
groupItem.getChildren().add(buNode);
});
}
private static void createStoreyNodes(List<Storey> storeys, TreeItem<Renderable> root) {
if(storeys.isEmpty()) {
return;
}
CityObjectGroupNode storeysGroupNode = new CityObjectGroupNode(storeys, "Storeys", null);
TreeItem<Renderable> groupItem = new TreeItem<>(storeysGroupNode);
root.getChildren().add(groupItem);
storeys.forEach(storey -> {
TreeItem<Renderable> storeyNode = buildAbstractSubdivisionNode(storey);
createShallowBuildingUnitNodes(storey.getBuildingUnits(), storeyNode);
groupItem.getChildren().add(storeyNode);
});
}
private static void createShallowStoreyNodes(List<Storey> storeys, TreeItem<Renderable> root) {
if (storeys.isEmpty()) {
return;
}
CityObjectGroupNode storeysGroupNode = new CityObjectGroupNode(storeys, "Storeys", null);
TreeItem<Renderable> groupItem = new TreeItem<>(storeysGroupNode);
root.getChildren().add(groupItem);
storeys.forEach(storey -> {
TreeItem<Renderable> storeyNode = buildAbstractSubdivisionNode(storey);
createBuildingUnitsLoaderNode(storey.getBuildingUnits(), storeyNode);
groupItem.getChildren().add(storeyNode);
});
}
private static void createShallowBuildingUnitNodes(List<BuildingUnit> units, TreeItem<Renderable> root) {
if (units.isEmpty()) {
return;
}
CityObjectGroupNode buildingUnitsGroupNode = new CityObjectGroupNode(units,
"Building Units", null);
TreeItem<Renderable> groupItem = new TreeItem<>(buildingUnitsGroupNode);
root.getChildren().add(groupItem);
units.forEach(buildingUnit -> {
TreeItem<Renderable> buNode = buildAbstractSubdivisionNode(buildingUnit);
createStoreysLoaderNode(buildingUnit.getStoreys(), buNode);
groupItem.getChildren().add(buNode);
});
}
private static void createBuildingUnitsLoaderNode(List<BuildingUnit> buildingUnits, TreeItem<Renderable> root) {
if (buildingUnits.isEmpty()) {
return;
}
CityObjectGroupNode buildingUnitsGroupNode = new CityObjectGroupNode(buildingUnits, "Building Units", null);
TreeItem<Renderable> groupItem = new TreeItem<>(buildingUnitsGroupNode);
root.getChildren().add(groupItem);
groupItem.getChildren().add(new TreeItem<>());
groupItem.expandedProperty().addListener((obs, old, newV) -> {
if (Boolean.TRUE.equals(newV) && groupItem.getChildren().size() == 1) {
Platform.runLater(() -> {
groupItem.getChildren().clear();
createShallowBuildingUnitNodes(buildingUnits, groupItem);
updateTree(groupItem);
});
}
});
}
private static void createStoreysLoaderNode(List<Storey> storeys, TreeItem<Renderable> root) {
if (storeys.isEmpty()) {
return;
}
CityObjectGroupNode buildingUnitsGroupNode = new CityObjectGroupNode(storeys, "Storeys", null);
TreeItem<Renderable> groupItem = new TreeItem<>(buildingUnitsGroupNode);
root.getChildren().add(groupItem);
groupItem.getChildren().add(new TreeItem<>());
groupItem.expandedProperty().addListener((obs, old, newV) -> {
if (Boolean.TRUE.equals(newV) && groupItem.getChildren().size() == 1) {
Platform.runLater(() -> {
groupItem.getChildren().clear();
createShallowStoreyNodes(storeys, groupItem);
updateTree(groupItem);
});
}
});
}
private static TreeItem<Renderable> buildAbstractSubdivisionNode(AbstractBuildingSubdivision abs) {
TreeItem<Renderable> absNode = buildCityObjectNode(abs);
createBoundedSpaceNodes(abs, absNode);
createConstructionObjectNodes(abs, absNode);
return absNode;
}
private static void createAbstractBridgeNodes(AbstractBridgeObject abo, TreeItem<Renderable> root) {
createBoundedSpaceNodes(abo, root);
createConstructionObjectNodes(abo, root);
}
private static void createBridgePartNodes(BridgeObject bridge, TreeItem<Renderable> root) {
if (bridge.getParts().isEmpty()) {
return;
}
CityObjectGroupNode partsGroupNode = new CityObjectGroupNode(bridge.getParts(), "Bridge Parts", null);
TreeItem<Renderable> groupItem = new TreeItem<>(partsGroupNode);
root.getChildren().add(groupItem);
bridge.getParts().forEach(part -> {
TreeItem<Renderable> bpNode = buildCityObjectNode(part);
createAbstractBridgeNodes(part, bpNode);
groupItem.getChildren().add(bpNode);
});
}
private static void createAbstractTunnelNodes(AbstractTunnel atu, TreeItem<Renderable> root) {
createBoundedSpaceNodes(atu, root);
createConstructionObjectNodes(atu, root);
}
private static void createTunnelPartNodes(Tunnel tunnel, TreeItem<Renderable> root) {
if (tunnel.getTunnelParts().isEmpty()) {
return;
}
CityObjectGroupNode partsNode = new CityObjectGroupNode(tunnel.getTunnelParts(), "Tunnel Parts", null);
TreeItem<Renderable> groupItem = new TreeItem<>(partsNode);
root.getChildren().add(groupItem);
tunnel.getTunnelParts().forEach(part -> {
TreeItem<Renderable> bpNode = buildCityObjectNode(part);
createAbstractTunnelNodes(part, bpNode);
groupItem.getChildren().add(bpNode);
});
}
private static void createReliefComponentNodes(ReliefObject relief, TreeItem<Renderable> root) {
if (relief.getComponents().isEmpty()) {
return;
}
CityObjectGroupNode componentsGroupNode = new CityObjectGroupNode(relief.getComponents(), "Components", null);
TreeItem<Renderable> groupItem = new TreeItem<>(componentsGroupNode);
root.getChildren().add(groupItem);
relief.getComponents().forEach(component -> {
TreeItem<Renderable> bpNode = buildCityObjectNode(component);
groupItem.getChildren().add(bpNode);
});
}
private static void createTopLevelTransportNodes(TopLevelTransportFeature top, TreeItem<Renderable> root) {
createTransportationSpaceNodes(top, root);
if (!top.getSections().isEmpty()) {
CityObjectGroupNode sectionGroupNode = new CityObjectGroupNode(top.getSections(), "Sections", null);
TreeItem<Renderable> groupItem = new TreeItem<>(sectionGroupNode);
root.getChildren().add(groupItem);
top.getSections().forEach(section -> {
TreeItem<Renderable> bpNode = buildCityObjectNode(section);
createTransportationSpaceNodes(section, bpNode);
groupItem.getChildren().add(bpNode);
});
}
if (!top.getIntersections().isEmpty()) {
CityObjectGroupNode intersectionGroupNode = new CityObjectGroupNode(top.getIntersections(), "Intersections", null);
TreeItem<Renderable> groupItem = new TreeItem<>(intersectionGroupNode);
root.getChildren().add(groupItem);
top.getIntersections().forEach(intersection -> {
TreeItem<Renderable> bpNode = buildCityObjectNode(intersection);
createTransportationSpaceNodes(intersection, bpNode);
groupItem.getChildren().add(bpNode);
});
}
}
private static void createTransportationSpaceNodes(TransportationSpace ts, TreeItem<Renderable> root) {
createBoundedSpaceNodes(ts, root);
createTrafficSpaceNodes(ts, root, TrafficSpaceObject.TrafficSpaceType.TRAFFIC_SPACE);
createTrafficSpaceNodes(ts, root, TrafficSpaceObject.TrafficSpaceType.AUXILIARY_TRAFFIC_SPACE);
}
private static void createTrafficSpaceNodes(TransportationSpace ts, TreeItem<Renderable> root, TrafficSpaceObject.TrafficSpaceType spaceType) {
List<TrafficSpaceObject> trafficSpaces;
String nodeText;
switch (spaceType) {
case TRAFFIC_SPACE -> {
trafficSpaces = ts.getTrafficSpaces();
nodeText = "Traffic Spaces";
}
case AUXILIARY_TRAFFIC_SPACE -> {
trafficSpaces =ts.getAuxTrafficSpaces();
nodeText = "Auxiliary Traffic Spaces";
}
default -> {
trafficSpaces = ts.getTrafficSpaces();
nodeText = "UNKNOWN TRAFFIC SPACES";
}
}
if (trafficSpaces.isEmpty()) {
return;
}
CityObjectGroupNode trafficSpaceNode = new CityObjectGroupNode(trafficSpaces, nodeText, null);
TreeItem<Renderable> groupItem = new TreeItem<>(trafficSpaceNode);
root.getChildren().add(groupItem);
trafficSpaces.forEach(trafficSpace -> {
TreeItem<Renderable> bpNode = buildCityObjectNode(trafficSpace);
createBoundedSpaceNodes(trafficSpace, bpNode);
createTrafficAreaNodes(trafficSpace, bpNode, spaceType);
groupItem.getChildren().add(bpNode);
});
}
private static void createTrafficAreaNodes(TrafficSpaceObject tso, TreeItem<Renderable> root, TrafficSpaceObject.TrafficSpaceType spaceType) {
String nodeText;
List<TrafficAreaObject> trafficAreas = tso.getTrafficAreas();
if (trafficAreas.isEmpty()){
return;
}
switch (spaceType) {
case TRAFFIC_SPACE -> nodeText = "Traffic Areas";
case AUXILIARY_TRAFFIC_SPACE -> nodeText = "Auxiliary Traffic Areas";
default -> nodeText = "UNKNOWN TRAFFIC AREAS";
}
CityObjectGroupNode trafficAreaNode = new CityObjectGroupNode(trafficAreas, nodeText, null);
TreeItem<Renderable> groupItem = new TreeItem<>(trafficAreaNode);
root.getChildren().add(groupItem);
trafficAreas.forEach(trafficArea -> {
TreeItem<Renderable> bpNode = buildCityObjectNode(trafficArea);
createBoundedSpaceNodes(trafficArea, bpNode);
groupItem.getChildren().add(bpNode);
});
}
private static void createConstructionObjectNodes(ConstructionObject co, TreeItem<Renderable> root) {
createConstructiveElementNodes(co.getConstructiveElements(), root);
createInstallationNodes(co.getInstallations(), root);
createFurnitureNodes(co.getFurniture(), root);
createRoomNodes(co.getRooms(), root);
}
private static void createConstructiveElementNodes(List<? extends AbstractConstructiveElement> aces, TreeItem<Renderable> root) {
if (aces.isEmpty()) {
return;
}
CityObjectGroupNode constructionGroupNode = new CityObjectGroupNode(aces, "Construction Elements", null);
TreeItem<Renderable> groupItem = new TreeItem<>(constructionGroupNode);
root.getChildren().add(groupItem);
aces.forEach(ace -> {
TreeItem<Renderable> constructionNode = buildCityObjectNode(ace);
createBoundedSpaceNodes(ace, constructionNode);
createFillingNodes(ace, constructionNode);
groupItem.getChildren().add(constructionNode);
});
}
private static void createFillingNodes(AbstractConstructiveElement ab, TreeItem<Renderable> root) {
if (ab.getFillings().isEmpty()) {
return;
}
CityObjectGroupNode fillingsGroupNode = new CityObjectGroupNode(ab.getFillings(), "Fillings", null);
TreeItem<Renderable> groupItem = new TreeItem<>(fillingsGroupNode);
root.getChildren().add(groupItem);
ab.getFillings().forEach(filling -> {
TreeItem<Renderable> fillingNode = buildCityObjectNode(filling);
createBoundedSpaceNodes(filling, fillingNode);
groupItem.getChildren().add(fillingNode);
});
}
private static void createInstallationNodes(List<? extends Installation> installations, TreeItem<Renderable> root) {
if (installations.isEmpty()) {
return;
}
CityObjectGroupNode installationsGroupNode = new CityObjectGroupNode(installations, "Installations", null);
TreeItem<Renderable> groupItem = new TreeItem<>(installationsGroupNode);
root.getChildren().add(groupItem);
installations.forEach(installation -> {
TreeItem<Renderable> installationNode = buildCityObjectNode(installation);
createBoundedSpaceNodes(installation, installationNode);
groupItem.getChildren().add(installationNode);
});
}
private static void createFurnitureNodes(List<? extends AbstractFurniture> afs, TreeItem<Renderable> root) {
if (afs.isEmpty()) {
return;
}
CityObjectGroupNode furnitureGroupNode = new CityObjectGroupNode(afs, "Furniture", null);
TreeItem<Renderable> groupItem = new TreeItem<>(furnitureGroupNode);
root.getChildren().add(groupItem);
afs.forEach(af -> {
TreeItem<Renderable> furnitureNode = buildCityObjectNode(af);
createBoundedSpaceNodes(af, furnitureNode);
groupItem.getChildren().add(furnitureNode);
});
}
private static void createRoomNodes(List<? extends AbstractRoom> rooms, TreeItem<Renderable> root) {
if (rooms.isEmpty()) {
return;
}
String nodeText = rooms.get(0).getGroupNodeText();
CityObjectGroupNode roomsGroupNode = new CityObjectGroupNode(rooms, nodeText, null);
TreeItem<Renderable> groupItem = new TreeItem<>(roomsGroupNode);
root.getChildren().add(groupItem);
rooms.forEach(room -> {
TreeItem<Renderable> roomNode = buildCityObjectNode(room);
createBoundedSpaceNodes(room, roomNode);
createInstallationNodes(room.getInstallations(), roomNode);
createFurnitureNodes(room.getFurniture(), roomNode);
groupItem.getChildren().add(roomNode);
});
}
private static void updateTree(TreeItem<Renderable> root) {
if (root == null) {
return;
}
for (TreeItem<Renderable> item : root.getChildren()) {
updateItem(item);
}
}
private static void updateItem(TreeItem<Renderable> item) {
if (item.getValue() == null) {
return;
}
item.getValue().refreshTextColor();
for (TreeItem<Renderable> child : item.getChildren()) {
updateItem(child);
}
}
}
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