/*- * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart * * This file is part of CityDoctor2. * * CityDoctor2 is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CityDoctor2 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with CityDoctor2. If not, see . */ package de.hft.stuttgart.citydoctor2.writer; import java.io.File; import java.time.ZonedDateTime; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; import org.citygml4j.core.model.CityGMLVersion; import org.citygml4j.core.model.core.AbstractCityObjectProperty; import org.citygml4j.core.model.core.AbstractFeatureProperty; import org.citygml4j.core.model.core.CityModel; import org.citygml4j.core.util.geometry.GeometryFactory; import org.citygml4j.xml.CityGMLContext; import org.citygml4j.xml.writer.CityGMLOutputFactory; import org.citygml4j.xml.writer.CityGMLWriteException; import org.citygml4j.xml.writer.CityGMLWriter; import de.hft.stuttgart.citydoctor2.check.CheckError; import de.hft.stuttgart.citydoctor2.check.ErrorId; import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel; import de.hft.stuttgart.citydoctor2.datastructure.CityObject; import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException; import de.hft.stuttgart.citydoctor2.parser.CityGmlParser; import de.hft.stuttgart.citydoctor2.utils.Localization; import de.hft.stuttgart.citydoctor2.utils.QualityADEUtils; import de.hft.stuttgart.quality.QualityADEModule; import de.hft.stuttgart.quality.model.properties.ErrorProperty; import de.hft.stuttgart.quality.model.properties.FeatureStatisticsProperty; import de.hft.stuttgart.quality.model.properties.StatisticsProperty; import de.hft.stuttgart.quality.model.properties.ValidationPlanProperty; import de.hft.stuttgart.quality.model.types.FeatureStatistics; import de.hft.stuttgart.quality.model.types.Statistics; import de.hft.stuttgart.quality.model.types.Validation; public class CityGMLWriterUtils { public static void writeCityModel(String file, CityDoctorModel model) throws CityDoctorWriteException { CityGMLContext gmlContext = CityGmlParser.getContext(); CityModel cModel = model.getCityModel(); CityGMLOutputFactory factory = gmlContext.createCityGMLOutputFactory(CityGMLVersion.v2_0); try (CityGMLWriter writer = factory.createCityGMLWriter(new File(file))) { writer.withIndent(" "); writer.withDefaultPrefixes(); writer.withDefaultSchemaLocations(); Validation val = null; if (model.isValidated()) { writer.withPrefix("qual", QualityADEModule.NAMESPACE_URI); writer.withSchemaLocation(QualityADEModule.NAMESPACE_URI, QualityADEModule.NAMESPACE_URI + "/qualityAde.xsd"); // create new quality ade validation datastructures val = createValidation(model); // add to city model cModel.getFeatureMembers().add(new AbstractFeatureProperty(val)); } GeometryFactory gmlFactory = GeometryFactory.newInstance(); storeCityObjects(model.getBuildings(), gmlFactory, model, cModel, val); storeCityObjects(model.getVegetation(), gmlFactory, model, cModel, val); storeCityObjects(model.getBridges(), gmlFactory, model, cModel, val); storeCityObjects(model.getLand(), gmlFactory, model, cModel, val); storeCityObjects(model.getTransportation(), gmlFactory, model, cModel, val); storeCityObjects(model.getWater(), gmlFactory, model, cModel, val); writer.write(cModel); } catch (CityGMLWriteException e) { throw new CityDoctorWriteException(e); } } private static Validation createValidation(CityDoctorModel model) { Validation val = new Validation(); val.setId("CD" + UUID.randomUUID().toString()); val.setValidationDate(ZonedDateTime.now()); val.setValidationSoftware("CityDoctor " + Localization.getText(Localization.VERSION)); Statistics statistics = new Statistics(); Set errors = model.collectErrors(); Map errorCount = new HashMap<>(); for (CheckError e : errors) { errorCount.compute(e.getErrorId(), (k, v) -> { if (v == null) { return new AtomicInteger(1); } v.incrementAndGet(); return v; }); } for (Entry e : errorCount.entrySet()) { de.hft.stuttgart.quality.model.types.Error stats = new de.hft.stuttgart.quality.model.types.Error(); stats.setOccurrences(e.getValue().get()); de.hft.stuttgart.quality.model.enums.ErrorId adeId = QualityADEUtils.mapErrorIdToAdeId(e.getKey()); if (adeId == null) { // error that is not part of the ade standard continue; } stats.setName(adeId); statistics.getErrors().add(new ErrorProperty(stats)); } statistics.setNumErrorBuildings(new FeatureStatisticsProperty(countValidatedCityObjects(model.getBuildings()))); statistics.setNumErrorBridgeObjects(new FeatureStatisticsProperty(countValidatedCityObjects(model.getBridges()))); statistics.setNumErrorLandObjects(new FeatureStatisticsProperty(countValidatedCityObjects(model.getLand()))); statistics.setNumErrorTransportation(new FeatureStatisticsProperty(countValidatedCityObjects(model.getTransportation()))); statistics.setNumErrorVegetation(new FeatureStatisticsProperty(countValidatedCityObjects(model.getVegetation()))); statistics.setNumErrorWaterObjects(new FeatureStatisticsProperty(countValidatedCityObjects(model.getWater()))); val.setStatistics(new StatisticsProperty(statistics)); val.setValidationPlan(new ValidationPlanProperty(model.getValidationPlan())); return val; } private static FeatureStatistics countValidatedCityObjects(List cos) { int numChecked = 0; int numError = 0; for (CityObject co : cos) { if (co.isValidated()) { numChecked++; if (co.containsAnyError()) { numError++; } } } return new FeatureStatistics(numChecked, numError); } private static void storeCityObjects(List cos, GeometryFactory gmlFactory, CityDoctorModel model, CityModel cModel, Validation val) { for (CityObject co : cos) { if (model.isValidated() && val != null) { QualityADEUtils.writeQualityAde(co, val); } co.reCreateGeometries(gmlFactory, model.getParserConfig()); cModel.getCityObjectMembers().add(new AbstractCityObjectProperty(co.getGmlObject())); } } }