Commit 4ef4c11f authored by Matthias Betz's avatar Matthias Betz
Browse files

added type adapters

added validation tests
parent 5fe70e14
package de.hft.stuttgart.quality.adapter.types;
import javax.xml.namespace.QName;
import org.xmlobjects.annotation.XMLElement;
import org.xmlobjects.builder.ObjectBuildException;
import org.xmlobjects.serializer.ObjectSerializeException;
import org.xmlobjects.xml.Element;
import org.xmlobjects.xml.Namespaces;
import de.hft.stuttgart.quality.QualityADEModule;
import de.hft.stuttgart.quality.model.types.SolidTooFewPolygonsError;
@XMLElement(name = "GE_S_TOO_FEW_POLYGONS", namespaceURI = QualityADEModule.NAMESPACE_URI)
public class SolidTooFewPolygonsErrorAdapter extends AbstractSolidErrorAdapter<SolidTooFewPolygonsError> {
@Override
public SolidTooFewPolygonsError createObject(QName name, Object parent) throws ObjectBuildException {
return new SolidTooFewPolygonsError();
}
@Override
public Element createElement(SolidTooFewPolygonsError object, Namespaces namespaces)
throws ObjectSerializeException {
return Element.of(QualityADEModule.NAMESPACE_URI, "GE_S_TOO_FEW_POLYGONS");
}
}
package de.hft.stuttgart.quality.adapter.types;
import javax.xml.namespace.QName;
import org.xmlobjects.annotation.XMLElement;
import org.xmlobjects.builder.ObjectBuildException;
import org.xmlobjects.builder.ObjectBuilder;
import org.xmlobjects.serializer.ObjectSerializeException;
import org.xmlobjects.serializer.ObjectSerializer;
import org.xmlobjects.stream.XMLReadException;
import org.xmlobjects.stream.XMLReader;
import org.xmlobjects.stream.XMLWriteException;
import org.xmlobjects.stream.XMLWriter;
import org.xmlobjects.xml.Attributes;
import org.xmlobjects.xml.Element;
import org.xmlobjects.xml.Namespaces;
import de.hft.stuttgart.quality.QualityADEModule;
import de.hft.stuttgart.quality.adapter.properties.FeatureStatisticsPropertyAdapter;
import de.hft.stuttgart.quality.model.types.Statistics;
@XMLElement(name = "Statistics", namespaceURI = QualityADEModule.NAMESPACE_URI)
public class StatisticsAdapter implements ObjectBuilder<Statistics>, ObjectSerializer<Statistics> {
@Override
public Statistics createObject(QName name, Object parent) throws ObjectBuildException {
return new Statistics();
}
@Override
public void buildChildObject(Statistics object, QName name, Attributes attributes, XMLReader reader)
throws ObjectBuildException, XMLReadException {
if (!QualityADEModule.NAMESPACE_URI.equals(name.getNamespaceURI())) {
return;
}
switch (name.getLocalPart()) {
case "numErrorBuildings" -> object
.setNumErrorBuildings(reader.getObjectUsingBuilder(FeatureStatisticsPropertyAdapter.class));
case "numErrorVegetation" -> object
.setNumErrorVegetation(reader.getObjectUsingBuilder(FeatureStatisticsPropertyAdapter.class));
case "numErrorLandObjects" -> object
.setNumErrorLandObjects(reader.getObjectUsingBuilder(FeatureStatisticsPropertyAdapter.class));
case "numErrorBridgeObjects" -> object
.setNumErrorBridgeObjects(reader.getObjectUsingBuilder(FeatureStatisticsPropertyAdapter.class));
case "numErrorWaterObjects" -> object
.setNumErrorWaterObjects(reader.getObjectUsingBuilder(FeatureStatisticsPropertyAdapter.class));
case "numErrorTransportation" -> object
.setNumErrorTransportation(reader.getObjectUsingBuilder(FeatureStatisticsPropertyAdapter.class));
default -> throw new IllegalStateException("Cannot handle name " + name + " when building Statistics element");
}
}
@Override
public Element createElement(Statistics object, Namespaces namespaces) throws ObjectSerializeException {
return Element.of(QualityADEModule.NAMESPACE_URI, "Statistics");
}
@Override
public void writeChildElements(Statistics object, Namespaces namespaces, XMLWriter writer)
throws ObjectSerializeException, XMLWriteException {
if (object.getNumErrorBuildings() != null) {
writer.writeElementUsingSerializer(Element.of(QualityADEModule.NAMESPACE_URI, "numErrorBuildings"),
object.getNumErrorBuildings(), FeatureStatisticsPropertyAdapter.class, namespaces);
}
if (object.getNumErrorVegetation() != null) {
writer.writeElementUsingSerializer(Element.of(QualityADEModule.NAMESPACE_URI, "numErrorVegetation"),
object.getNumErrorVegetation(), FeatureStatisticsPropertyAdapter.class, namespaces);
}
if (object.getNumErrorLandObjects() != null) {
writer.writeElementUsingSerializer(Element.of(QualityADEModule.NAMESPACE_URI, "numErrorLandObjects"),
object.getNumErrorLandObjects(), FeatureStatisticsPropertyAdapter.class, namespaces);
}
if (object.getNumErrorBridgeObjects() != null) {
writer.writeElementUsingSerializer(Element.of(QualityADEModule.NAMESPACE_URI, "numErrorBridgeObjects"),
object.getNumErrorBridgeObjects(), FeatureStatisticsPropertyAdapter.class, namespaces);
}
if (object.getNumErrorWaterObjects() != null) {
writer.writeElementUsingSerializer(Element.of(QualityADEModule.NAMESPACE_URI, "numErrorWaterObjects"),
object.getNumErrorWaterObjects(), FeatureStatisticsPropertyAdapter.class, namespaces);
}
if (object.getNumErrorTransportation() != null) {
writer.writeElementUsingSerializer(Element.of(QualityADEModule.NAMESPACE_URI, "numErrorTransportation"),
object.getNumErrorTransportation(), FeatureStatisticsPropertyAdapter.class, namespaces);
}
}
}
package de.hft.stuttgart.quality.adapter.types;
import javax.xml.namespace.QName;
import org.citygml4j.xml.adapter.core.AbstractFeatureAdapter;
import org.xmlobjects.annotation.XMLElement;
import org.xmlobjects.builder.ObjectBuildException;
import org.xmlobjects.serializer.ObjectSerializeException;
import org.xmlobjects.stream.XMLReadException;
import org.xmlobjects.stream.XMLReader;
import org.xmlobjects.stream.XMLWriteException;
import org.xmlobjects.stream.XMLWriter;
import org.xmlobjects.xml.Attributes;
import org.xmlobjects.xml.Element;
import org.xmlobjects.xml.Namespaces;
import de.hft.stuttgart.quality.QualityADEModule;
import de.hft.stuttgart.quality.adapter.properties.StatisticsPropertyAdapter;
import de.hft.stuttgart.quality.adapter.properties.ValidationPlanPropertyAdapter;
import de.hft.stuttgart.quality.model.types.Validation;
@XMLElement(name = "Validation", namespaceURI = QualityADEModule.NAMESPACE_URI)
public class ValidationAdapter extends AbstractFeatureAdapter<Validation> {
private static final ZonedDateTimeAdapter DATE_TIME_ADAPTER = new ZonedDateTimeAdapter();
@Override
public Validation createObject(QName name, Object parent) throws ObjectBuildException {
return new Validation();
}
@Override
public void buildChildObject(Validation object, QName name, Attributes attributes, XMLReader reader)
throws ObjectBuildException, XMLReadException {
if (!QualityADEModule.NAMESPACE_URI.equals(name.getNamespaceURI())) {
return;
}
switch (name.getLocalPart()) {
case "validationDate" -> reader.getTextContent()
.ifPresent(s -> object.setValidationDate(DATE_TIME_ADAPTER.fromString(s)));
case "validationSoftware" -> reader.getTextContent().ifPresent(object::setValidationSoftware);
case "statistics" -> object.setStatistics(reader.getObjectUsingBuilder(StatisticsPropertyAdapter.class));
case "validationPlan" -> object
.setValidationPlan(reader.getObjectUsingBuilder(ValidationPlanPropertyAdapter.class));
default -> super.buildChildObject(object, name, attributes, reader);
}
}
@Override
public Element createElement(Validation object, Namespaces namespaces) throws ObjectSerializeException {
return Element.of(QualityADEModule.NAMESPACE_URI, "Validation");
}
@Override
public void writeChildElements(Validation object, Namespaces namespaces, XMLWriter writer)
throws ObjectSerializeException, XMLWriteException {
super.writeChildElements(object, namespaces, writer);
if (object.getValidationDate() != null) {
writer.writeElement(Element.of(QualityADEModule.NAMESPACE_URI, "validationDate")
.addTextContent(DATE_TIME_ADAPTER.toString(object.getValidationDate())));
}
if (object.getValidationSoftware() != null) {
writer.writeElement(Element.of(QualityADEModule.NAMESPACE_URI, "validationSoftware")
.addTextContent(object.getValidationSoftware()));
}
if (object.getStatistics() != null) {
writer.writeElementUsingSerializer(Element.of(QualityADEModule.NAMESPACE_URI, "statistics"),
object.getStatistics(), StatisticsPropertyAdapter.class, namespaces);
}
if (object.getValidationPlan() != null) {
writer.writeElementUsingSerializer(Element.of(QualityADEModule.NAMESPACE_URI, "validationPlan"),
object.getValidationPlan(), ValidationPlanPropertyAdapter.class, namespaces);
}
}
}
package de.hft.stuttgart.quality.adapter.types;
import javax.xml.namespace.QName;
import org.xmlobjects.annotation.XMLElement;
import org.xmlobjects.builder.ObjectBuildException;
import org.xmlobjects.builder.ObjectBuilder;
import org.xmlobjects.serializer.ObjectSerializeException;
import org.xmlobjects.serializer.ObjectSerializer;
import org.xmlobjects.stream.XMLReadException;
import org.xmlobjects.stream.XMLReader;
import org.xmlobjects.stream.XMLWriteException;
import org.xmlobjects.stream.XMLWriter;
import org.xmlobjects.xml.Attributes;
import org.xmlobjects.xml.Element;
import org.xmlobjects.xml.Namespaces;
import de.hft.stuttgart.quality.QualityADEModule;
import de.hft.stuttgart.quality.adapter.properties.FilterPropertyAdapter;
import de.hft.stuttgart.quality.adapter.properties.GlobalParametersPropertyAdapter;
import de.hft.stuttgart.quality.adapter.properties.RequirementPropertyAdapter;
import de.hft.stuttgart.quality.model.properties.RequirementProperty;
import de.hft.stuttgart.quality.model.types.ValidationPlan;
@XMLElement(name = "ValidationPlan", namespaceURI = QualityADEModule.NAMESPACE_URI)
public class ValidationPlanAdapter implements ObjectBuilder<ValidationPlan>, ObjectSerializer<ValidationPlan> {
@Override
public ValidationPlan createObject(QName name, Object parent) throws ObjectBuildException {
return new ValidationPlan();
}
@Override
public void buildChildObject(ValidationPlan object, QName name, Attributes attributes, XMLReader reader)
throws ObjectBuildException, XMLReadException {
if (!QualityADEModule.NAMESPACE_URI.equals(name.getNamespaceURI())) {
return;
}
switch (name.getLocalPart()) {
case "globalParameters" -> object
.setGlobalParameters(reader.getObjectUsingBuilder(GlobalParametersPropertyAdapter.class));
case "filter" -> object.setFilter(reader.getObjectUsingBuilder(FilterPropertyAdapter.class));
case "requirement" -> object.getRequirements()
.add(reader.getObjectUsingBuilder(RequirementPropertyAdapter.class));
default -> throw new IllegalStateException(
"Cannot handle name " + name + " when building ValidationPlan element");
}
}
@Override
public Element createElement(ValidationPlan object, Namespaces namespaces) throws ObjectSerializeException {
return Element.of(QualityADEModule.NAMESPACE_URI, "ValidationPlan");
}
@Override
public void writeChildElements(ValidationPlan object, Namespaces namespaces, XMLWriter writer)
throws ObjectSerializeException, XMLWriteException {
if (object.getGlobalParameters() != null) {
writer.writeElementUsingSerializer(Element.of(QualityADEModule.NAMESPACE_URI, "globalParameters"),
object.getGlobalParameters(), GlobalParametersPropertyAdapter.class, namespaces);
}
if (object.getFilter() != null) {
writer.writeElementUsingSerializer(Element.of(QualityADEModule.NAMESPACE_URI, "filter"), object.getFilter(),
FilterPropertyAdapter.class, namespaces);
}
for (RequirementProperty req : object.getRequirements()) {
writer.writeElementUsingSerializer(Element.of(QualityADEModule.NAMESPACE_URI, "requirement"), req,
RequirementPropertyAdapter.class, namespaces);
}
}
}
package de.hft.stuttgart.quality.adapter.types;
import javax.xml.namespace.QName;
import org.xmlobjects.annotation.XMLElement;
import org.xmlobjects.builder.ObjectBuildException;
import org.xmlobjects.builder.ObjectBuilder;
import org.xmlobjects.gml.adapter.base.ReferenceAdapter;
import org.xmlobjects.serializer.ObjectSerializeException;
import org.xmlobjects.serializer.ObjectSerializer;
import org.xmlobjects.stream.XMLReadException;
import org.xmlobjects.stream.XMLReader;
import org.xmlobjects.stream.XMLWriteException;
import org.xmlobjects.stream.XMLWriter;
import org.xmlobjects.xml.Attributes;
import org.xmlobjects.xml.Element;
import org.xmlobjects.xml.Namespaces;
import de.hft.stuttgart.quality.QualityADEModule;
import de.hft.stuttgart.quality.adapter.properties.AbstractErrorPropertyAdapter;
import de.hft.stuttgart.quality.model.enums.ResultType;
import de.hft.stuttgart.quality.model.properties.AbstractErrorProperty;
import de.hft.stuttgart.quality.model.types.ValidationResult;
@XMLElement(name = "ValidationResult", namespaceURI = QualityADEModule.NAMESPACE_URI)
public class ValidationResultAdapter implements ObjectBuilder<ValidationResult>, ObjectSerializer<ValidationResult> {
@Override
public ValidationResult createObject(QName name, Object parent) throws ObjectBuildException {
return new ValidationResult();
}
@Override
public void buildChildObject(ValidationResult object, QName name, Attributes attributes, XMLReader reader)
throws ObjectBuildException, XMLReadException {
if (!QualityADEModule.NAMESPACE_URI.equals(name.getNamespaceURI())) {
return;
}
switch (name.getLocalPart()) {
case "validationPlanID" -> object.setValidationPlanID(reader.getObjectUsingBuilder(ReferenceAdapter.class));
case "error" -> object.getErrors().add(reader.getObjectUsingBuilder(AbstractErrorPropertyAdapter.class));
case "resultType" -> reader.getTextContent().ifPresent(s -> object.setResultType(ResultType.valueOf(s)));
default -> throw new IllegalStateException(
"Cannot handle name " + name + " when building ValidationResult element");
}
}
@Override
public Element createElement(ValidationResult object, Namespaces namespaces) throws ObjectSerializeException {
return Element.of(QualityADEModule.NAMESPACE_URI, "ValidationResult");
}
@Override
public void writeChildElements(ValidationResult object, Namespaces namespaces, XMLWriter writer)
throws ObjectSerializeException, XMLWriteException {
if (object.getValidationPlanID() != null) {
writer.writeElementUsingSerializer(Element.of(QualityADEModule.NAMESPACE_URI, "validationPlanID"),
object.getValidationPlanID(), ReferenceAdapter.class, namespaces);
}
for (AbstractErrorProperty err : object.getErrors()) {
writer.writeElementUsingSerializer(Element.of(QualityADEModule.NAMESPACE_URI, "error"), err,
AbstractErrorPropertyAdapter.class, namespaces);
}
if (object.getResultType() != null) {
writer.writeElement(Element.of(QualityADEModule.NAMESPACE_URI, "resultType")
.addTextContent(object.getResultType().toString()));
}
}
}
/*- /*-
* Copyright 2020 Hochschule für Technik Stuttgart * Copyright 2022 Hochschule für Technik Stuttgart
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -13,25 +13,25 @@ ...@@ -13,25 +13,25 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package de.hft.stuttgart.quality.util; package de.hft.stuttgart.quality.adapter.types;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import org.citygml4j.xml.reader.MissingADESchemaException; public class ZonedDateTimeAdapter {
public class UncheckedMissingADESchemaException extends RuntimeException { public ZonedDateTime fromString(String v) {
try {
private static final long serialVersionUID = -5684499826072882203L; return ZonedDateTime.from(DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(v));
} catch (Exception e) {
private MissingADESchemaException cause; return LocalDateTime.parse(v).atZone(ZoneId.systemDefault());
}
public UncheckedMissingADESchemaException(MissingADESchemaException e) {
super(e);
this.cause = e;
} }
@Override public String toString(ZonedDateTime v) {
public synchronized MissingADESchemaException getCause() { return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(v);
return cause;
} }
} }
/*-
* Copyright 2022 Hochschule für Technik Stuttgart
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.hft.stuttgart.quality.model.properties;
import java.io.Serial;
import org.citygml4j.core.model.ade.ADEObject;
import org.xmlobjects.gml.model.base.AbstractInlineOrByReferenceProperty;
import de.hft.stuttgart.quality.model.types.ValidationResult;
public class ValidationResultProperty extends AbstractInlineOrByReferenceProperty<ValidationResult> implements ADEObject {
@Serial
private static final long serialVersionUID = 480940868730913996L;
public ValidationResultProperty() {
super();
}
public ValidationResultProperty(ValidationResult object) {
super(object);
}
public ValidationResultProperty(String href) {
super(href);
}
@Override
public Class<ValidationResult> getTargetType() {
return ValidationResult.class;
}
}
...@@ -4,18 +4,20 @@ import java.io.Serial; ...@@ -4,18 +4,20 @@ import java.io.Serial;
import org.citygml4j.core.model.core.ADEOfAbstractCityObject; import org.citygml4j.core.model.core.ADEOfAbstractCityObject;
import de.hft.stuttgart.quality.model.properties.ValidationResultProperty;
public class CityObjectProperties extends ADEOfAbstractCityObject { public class CityObjectProperties extends ADEOfAbstractCityObject {
@Serial @Serial
private static final long serialVersionUID = 1273072314736964714L; private static final long serialVersionUID = 1273072314736964714L;
private ValidationResult validationResult; private ValidationResultProperty validationResult;
public ValidationResult getValidationResult() { public ValidationResultProperty getValidationResult() {
return validationResult; return validationResult;
} }
public void setValidationResult(ValidationResult validationResult) { public void setValidationResult(ValidationResultProperty validationResult) {
this.validationResult = asChild(validationResult); this.validationResult = asChild(validationResult);
} }
} }
...@@ -27,17 +27,17 @@ public class MultipleComponentsError extends AbstractSolidError { ...@@ -27,17 +27,17 @@ public class MultipleComponentsError extends AbstractSolidError {
@Serial @Serial
private static final long serialVersionUID = 4322219502819024437L; private static final long serialVersionUID = 4322219502819024437L;
private List<ComponentListProperty> edges; private List<ComponentListProperty> components;
public List<ComponentListProperty> getEdges() { public List<ComponentListProperty> getComponents() {
if (edges == null) { if (components == null) {
edges = new ChildList<>(this); components = new ChildList<>(this);
} }
return edges; return components;
} }
public void setEdges(List<ComponentListProperty> edges) { public void setComponents(List<ComponentListProperty> edges) {
this.edges = asChild(edges); this.components = asChild(edges);
} }
} }
...@@ -17,28 +17,21 @@ package de.hft.stuttgart.quality.model.types; ...@@ -17,28 +17,21 @@ package de.hft.stuttgart.quality.model.types;
import java.io.Serial; import java.io.Serial;
import de.hft.stuttgart.quality.model.properties.EdgeListProperty;
public class PolygonWrongOrientationError extends AbstractSolidError { public class PolygonWrongOrientationError extends AbstractSolidError {
@Serial @Serial
private static final long serialVersionUID = 4975827693656963892L; private static final long serialVersionUID = 4975827693656963892L;
private String polygonId1; private EdgeListProperty edges;
private String polygonId2;
public String getPolygonId1() {
return polygonId1;
}
public void setPolygonId1(String polygonId1) {
this.polygonId1 = polygonId1;
}
public String getPolygonId2() { public EdgeListProperty getEdges() {
return polygonId2; return edges;
} }
public void setPolygonId2(String polygonId2) { public void setEdges(EdgeListProperty edges) {
this.polygonId2 = polygonId2; this.edges = edges;
} }
} }
...@@ -19,7 +19,26 @@ import java.io.Serial; ...@@ -19,7 +19,26 @@ import java.io.Serial;
public class SolidSelfIntersectionError extends AbstractSolidError { public class SolidSelfIntersectionError extends AbstractSolidError {
@Serial @Serial
private static final long serialVersionUID = 5070991901664859830L; private static final long serialVersionUID = 5070991901664859830L;
private String polygonId1;
private String polygonId2;
public String getPolygonId1() {
return polygonId1;
}
public void setPolygonId1(String polygonId1) {
this.polygonId1 = polygonId1;
}
public String getPolygonId2() {
return polygonId2;
}
public void setPolygonId2(String polygonId2) {
this.polygonId2 = polygonId2;
}
} }
...@@ -51,14 +51,14 @@ public class ValidationPlan extends GMLObject implements ADEObject { ...@@ -51,14 +51,14 @@ public class ValidationPlan extends GMLObject implements ADEObject {
this.filter = asChild(filter); this.filter = asChild(filter);
} }
public List<RequirementProperty> getRequirement() { public List<RequirementProperty> getRequirements() {
if (requirement == null) { if (requirement == null) {
requirement = new ChildList<>(this); requirement = new ChildList<>(this);
} }
return requirement; return requirement;
} }
public void setRequirement(List<RequirementProperty> requirement) { public void setRequirements(List<RequirementProperty> requirement) {
this.requirement = asChild(requirement); this.requirement = asChild(requirement);
} }
......
...@@ -561,8 +561,8 @@ ...@@ -561,8 +561,8 @@
<enumeration value="NOT_CHECKED"/> <enumeration value="NOT_CHECKED"/>
</restriction> </restriction>
</simpleType> </simpleType>
<element name="SEM_ATTRIBUTE_MISSING" substitutionGroup="qual:AbstractSemanticError" type="qual:SEM_ATTRIBUTE_MISSINGType"/> <element name="SE_ATTRIBUTE_MISSING" substitutionGroup="qual:AbstractSemanticError" type="qual:SE_ATTRIBUTE_MISSINGType"/>
<complexType name="SEM_ATTRIBUTE_MISSINGType"> <complexType name="SE_ATTRIBUTE_MISSINGType">
<complexContent> <complexContent>
<extension base="qual:AbstractSemanticErrorType"> <extension base="qual:AbstractSemanticErrorType">
<sequence> <sequence>
...@@ -573,13 +573,13 @@ ...@@ -573,13 +573,13 @@
</extension> </extension>
</complexContent> </complexContent>
</complexType> </complexType>
<complexType name="SEM_ATTRIBUTE_MISSINGPropertyType"> <complexType name="SE_ATTRIBUTE_MISSINGPropertyType">
<sequence> <sequence>
<element ref="qual:SEM_ATTRIBUTE_MISSING"/> <element ref="qual:SE_ATTRIBUTE_MISSING"/>
</sequence> </sequence>
</complexType> </complexType>
<element name="SEM_ATTRIBUTE_WRONG_VALUE" substitutionGroup="qual:AbstractSemanticError" type="qual:SEM_ATTRIBUTE_WRONG_VALUEType"/> <element name="SE_ATTRIBUTE_WRONG_VALUE" substitutionGroup="qual:AbstractSemanticError" type="qual:SE_ATTRIBUTE_WRONG_VALUEType"/>
<complexType name="SEM_ATTRIBUTE_WRONG_VALUEType"> <complexType name="SE_ATTRIBUTE_WRONG_VALUEType">
<complexContent> <complexContent>
<extension base="qual:AbstractSemanticErrorType"> <extension base="qual:AbstractSemanticErrorType">
<sequence> <sequence>
...@@ -590,20 +590,20 @@ ...@@ -590,20 +590,20 @@
</extension> </extension>
</complexContent> </complexContent>
</complexType> </complexType>
<complexType name="SEM_ATTRIBUTE_WRONG_VALUEPropertyType"> <complexType name="SE_ATTRIBUTE_WRONG_VALUEPropertyType">
<sequence> <sequence>
<element ref="qual:SEM_ATTRIBUTE_WRONG_VALUE"/> <element ref="qual:SE_ATTRIBUTE_WRONG_VALUE"/>
</sequence> </sequence>
</complexType> </complexType>
<element name="Statistics" substitutionGroup="gml:_Object" type="qual:StatisticsType"/> <element name="Statistics" substitutionGroup="gml:_Object" type="qual:StatisticsType"/>
<complexType name="StatisticsType"> <complexType name="StatisticsType">
<sequence> <sequence>
<element name="numErrorBuildings" type="qual:FeatureStatisticsPropertyType"/> <element minOccurs="0" name="numErrorBuildings" type="qual:FeatureStatisticsPropertyType"/>
<element name="numErrorVegetation" type="qual:FeatureStatisticsPropertyType"/> <element minOccurs="0" name="numErrorVegetation" type="qual:FeatureStatisticsPropertyType"/>
<element name="numErrorLandObjects" type="qual:FeatureStatisticsPropertyType"/> <element minOccurs="0" name="numErrorLandObjects" type="qual:FeatureStatisticsPropertyType"/>
<element name="numErrorBridgeObjects" type="qual:FeatureStatisticsPropertyType"/> <element minOccurs="0" name="numErrorBridgeObjects" type="qual:FeatureStatisticsPropertyType"/>
<element name="numErrorWaterObjects" type="qual:FeatureStatisticsPropertyType"/> <element minOccurs="0" name="numErrorWaterObjects" type="qual:FeatureStatisticsPropertyType"/>
<element name="numErrorTransportation" type="qual:FeatureStatisticsPropertyType"/> <element minOccurs="0" name="numErrorTransportation" type="qual:FeatureStatisticsPropertyType"/>
<element maxOccurs="unbounded" minOccurs="0" name="error" type="qual:ErrorPropertyType"/> <element maxOccurs="unbounded" minOccurs="0" name="error" type="qual:ErrorPropertyType"/>
</sequence> </sequence>
</complexType> </complexType>
......
...@@ -15,1368 +15,546 @@ ...@@ -15,1368 +15,546 @@
*/ */
package de.hft.stuttgart.quality; package de.hft.stuttgart.quality;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.ZonedDateTime;
import java.util.Locale;
import javax.xml.XMLConstants;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.citygml4j.core.ade.ADEException;
import org.citygml4j.core.ade.ADERegistry;
import org.citygml4j.core.model.CityGMLVersion;
import org.citygml4j.core.model.building.Building;
import org.citygml4j.core.model.core.AbstractCityObjectProperty;
import org.citygml4j.core.model.core.AbstractFeatureProperty;
import org.citygml4j.core.model.core.CityModel;
import org.citygml4j.xml.CityGMLContext;
import org.citygml4j.xml.CityGMLContextException;
import org.citygml4j.xml.module.citygml.CoreModule;
import org.citygml4j.xml.schema.CityGMLSchemaHandler;
import org.citygml4j.xml.writer.CityGMLOutputFactory;
import org.citygml4j.xml.writer.CityGMLWriteException;
import org.citygml4j.xml.writer.CityGMLWriter;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xmlobjects.gml.model.base.Reference;
import org.xmlobjects.gml.model.geometry.DirectPosition;
import org.xmlobjects.gml.model.measures.Angle;
import org.xmlobjects.gml.model.measures.Length;
import org.xmlobjects.schema.SchemaHandlerException;
import de.hft.stuttgart.quality.model.enums.RequirementId;
import de.hft.stuttgart.quality.model.enums.ResultType;
import de.hft.stuttgart.quality.model.enums.RingSelfIntType;
import de.hft.stuttgart.quality.model.enums.TopLevelFeatureType;
import de.hft.stuttgart.quality.model.properties.AbstractErrorProperty;
import de.hft.stuttgart.quality.model.properties.CheckingProperty;
import de.hft.stuttgart.quality.model.properties.ComponentListProperty;
import de.hft.stuttgart.quality.model.properties.EdgeListProperty;
import de.hft.stuttgart.quality.model.properties.EdgeProperty;
import de.hft.stuttgart.quality.model.properties.FeatureStatisticsProperty;
import de.hft.stuttgart.quality.model.properties.FilterProperty;
import de.hft.stuttgart.quality.model.properties.GlobalParametersProperty;
import de.hft.stuttgart.quality.model.properties.ParameterProperty;
import de.hft.stuttgart.quality.model.properties.PolygonIdListProperty;
import de.hft.stuttgart.quality.model.properties.RequirementProperty;
import de.hft.stuttgart.quality.model.properties.StatisticsProperty;
import de.hft.stuttgart.quality.model.properties.ValidationPlanProperty;
import de.hft.stuttgart.quality.model.properties.ValidationResultProperty;
import de.hft.stuttgart.quality.model.types.AllPolygonsOrientedWrongError;
import de.hft.stuttgart.quality.model.types.Checking;
import de.hft.stuttgart.quality.model.types.CityObjectProperties;
import de.hft.stuttgart.quality.model.types.ComponentList;
import de.hft.stuttgart.quality.model.types.ConsecutivePointsSameError;
import de.hft.stuttgart.quality.model.types.Edge;
import de.hft.stuttgart.quality.model.types.EdgeList;
import de.hft.stuttgart.quality.model.types.FeatureStatistics;
import de.hft.stuttgart.quality.model.types.Filter;
import de.hft.stuttgart.quality.model.types.GlobalParameters;
import de.hft.stuttgart.quality.model.types.HoleOutsideError;
import de.hft.stuttgart.quality.model.types.InnerRingsNestedError;
import de.hft.stuttgart.quality.model.types.InteriorDisconnectedError;
import de.hft.stuttgart.quality.model.types.IntersectingRingsError;
import de.hft.stuttgart.quality.model.types.MultipleComponentsError;
import de.hft.stuttgart.quality.model.types.NonManifoldEdgeError;
import de.hft.stuttgart.quality.model.types.NonManifoldVertexError;
import de.hft.stuttgart.quality.model.types.OrientationRingsSameError;
import de.hft.stuttgart.quality.model.types.Parameter;
import de.hft.stuttgart.quality.model.types.PlanarDistancePlaneError;
import de.hft.stuttgart.quality.model.types.PlanarNormalsDeviationError;
import de.hft.stuttgart.quality.model.types.PolygonIdList;
import de.hft.stuttgart.quality.model.types.PolygonWrongOrientationError;
import de.hft.stuttgart.quality.model.types.Requirement;
import de.hft.stuttgart.quality.model.types.RingNotClosedError;
import de.hft.stuttgart.quality.model.types.RingSelfIntersectionError;
import de.hft.stuttgart.quality.model.types.RingTooFewPointsError;
import de.hft.stuttgart.quality.model.types.SemanticAttributeMissingError;
import de.hft.stuttgart.quality.model.types.SemanticAttributeWrongValueError;
import de.hft.stuttgart.quality.model.types.SolidNotClosedError;
import de.hft.stuttgart.quality.model.types.SolidSelfIntersectionError;
import de.hft.stuttgart.quality.model.types.SolidTooFewPolygonsError;
import de.hft.stuttgart.quality.model.types.Statistics;
import de.hft.stuttgart.quality.model.types.Validation;
import de.hft.stuttgart.quality.model.types.ValidationPlan;
import de.hft.stuttgart.quality.model.types.ValidationResult;
class QualityAdeTests { class QualityAdeTests {
/* @BeforeAll
static void setUsLocale() throws ADEException {
Locale.setDefault(Locale.US);
ADERegistry.getInstance().loadADE(new QualityADEContext());
}
@Test @Test
void testValidationPlan() throws ADEException, CityGMLContextException, CityGMLWriteException { void testAllPolygonsOrientedWrong() throws ADEException, CityGMLContextException, CityGMLWriteException, SAXException, IOException, SchemaHandlerException {
CityModel model = new CityModel(); CityModel model = new CityModel();
ValidationResult res = fillCityModel(model);
Validation v = new Validation(); AllPolygonsOrientedWrongError err = new AllPolygonsOrientedWrongError();
model.getFeatureMembers().add(new AbstractFeatureProperty(v)); err.setGeometryId("geomId");
v.setValidationSoftware("testSoftware"); res.getErrors().add(new AbstractErrorProperty(err));
v.setValidationDate(ZonedDateTime.now());
ValidationPlan plan = new ValidationPlan();
Requirement req = new Requirement();
req.setEnabled(true);
req.setName(RequirementId.R_GE_P_HOLE_OUTSIDE);
plan.getRequirements().add(req);
Checking checking = new Checking();
checking.setFeatureType(TopLevelFeatureType.BRIDGE);
plan.getFilter().add(checking);
Parameter param = new Parameter();
param.setName("test");
param.setUom("uom");
param.setValue("5");
plan.getGlobalParameters().add(param);
v.setValidationPlan(plan);
ADERegistry.getInstance().loadADE(new QualityADEContext());
CityGMLContext context = CityGMLContext.newInstance();
CityGMLVersion version = CityGMLVersion.v2_0;
CityGMLOutputFactory out = context.createCityGMLOutputFactory(version);
byte[] buf = writeModel(model);
try (CityGMLChunkWriter writer = out.createCityGMLChunkWriter(Paths.get("test.gml"), StandardCharsets.UTF_8.name())) { assertTrue(validate(new ByteArrayInputStream(buf)));
writer.withIndent(" ")
.withSchemaLocation(QualityADEModule.NAMESPACE_URI, getClass().getResource("/qualityAde.xsd").toString())
.withDefaultPrefixes()
.withDefaultNamespace(CoreModule.of(version).getNamespaceURI())
.writeMember(v);
}
} }
@Test
void testReadingConsecutiveSameError()
throws ADEException, CityGMLBuilderException, CityGMLReadException, FileNotFoundException {
CityModel cityModel = readCityGml("src/test/resources/SimpleSolid_Error_QualityADE.gml");
testValidationPlan(cityModel);
List<CityObjectMember> cityObjectMember = cityModel.getCityObjectMember();
assertEquals(1, cityObjectMember.size());
CityObjectMember com = cityObjectMember.get(0);
AbstractCityObject aco = com.getCityObject();
assertNotNull(aco);
assertTrue(aco instanceof Building);
Building b = (Building) aco;
List<ADEComponent> gen = b.getGenericApplicationPropertyOfCityObject();
ADEComponent resultComp = gen.get(0);
assertTrue(resultComp instanceof ValidationResult);
ValidationResult result = (ValidationResult) resultComp;
assertEquals(ResultType.ERROR, result.getResult());
assertFalse(result.getErrors().isEmpty());
List<ValidationError> errors = result.getErrors();
assertEquals(1, errors.size());
ValidationError validationError = errors.get(0);
assertTrue(validationError instanceof ConsecutivePointsSame);
ConsecutivePointsSame err = (ConsecutivePointsSame) validationError;
assertEquals("_Simple_BD.1_PG.6_LR.1", err.getLinearRingId());
Double x1 = err.getVertex1().getValue().get(0);
assertEquals(11.5, x1, 0.0000001);
Double x2 = err.getVertex2().getValue().get(0);
assertEquals(11.5, x2, 0.0000001);
}
@Test
void testReadingTooFewPointsError()
throws ADEException, CityGMLBuilderException, CityGMLReadException, FileNotFoundException {
CityModel cityModel = readCityGml("src/test/resources/SimpleSolid_TooFewPoints.gml");
List<CityObjectMember> cityObjectMember = cityModel.getCityObjectMember();
CityObjectMember com = cityObjectMember.get(0);
AbstractCityObject aco = com.getCityObject();
Building b = (Building) aco;
List<ADEComponent> gen = b.getGenericApplicationPropertyOfCityObject();
ADEComponent resultComp = gen.get(0);
ValidationResult result = (ValidationResult) resultComp;
assertEquals(ResultType.ERROR, result.getResult());
assertFalse(result.getErrors().isEmpty());
List<ValidationError> errors = result.getErrors();
ValidationError validationError = errors.get(0);
assertTrue(validationError instanceof TooFewPoints);
TooFewPoints err = (TooFewPoints) validationError;
assertEquals("_Simple_BD.1_PG.6_LR.1", err.getLinearRingId());
}
@Test
void testReadingRingSelfIntersectionError()
throws ADEException, CityGMLBuilderException, CityGMLReadException, FileNotFoundException {
CityModel cityModel = readCityGml("src/test/resources/SimpleSolid_RingSelfIntersection.gml");
List<CityObjectMember> cityObjectMember = cityModel.getCityObjectMember();
CityObjectMember com = cityObjectMember.get(0);
AbstractCityObject aco = com.getCityObject();
Building b = (Building) aco;
List<ADEComponent> gen = b.getGenericApplicationPropertyOfCityObject();
ADEComponent resultComp = gen.get(0);
ValidationResult result = (ValidationResult) resultComp;
assertEquals(ResultType.ERROR, result.getResult());
assertFalse(result.getErrors().isEmpty());
List<ValidationError> errors = result.getErrors();
ValidationError validationError = errors.get(0);
assertTrue(validationError instanceof RingSelfIntersection);
RingSelfIntersection err = (RingSelfIntersection) validationError;
assertEquals("_Simple_BD.1_PG.6_LR.1", err.getLinearRingId());
assertEquals(RingSelfIntType.POINT_TOUCHES_EDGE, err.getType());
assertNull(err.getEdge2());
Edge edge1 = err.getEdge1();
assertEquals(10.0, edge1.getFrom().getValue().get(0), 0.000001);
assertEquals(11.0, edge1.getTo().getValue().get(0), 0.000001);
assertEquals(5.0, err.getVertex1().getValue().get(0));
assertNull(err.getVertex2());
}
@Test
void testReadingRingNotClosedError()
throws ADEException, CityGMLBuilderException, CityGMLReadException, FileNotFoundException {
CityModel cityModel = readCityGml("src/test/resources/SimpleSolid_RingNotClosed.gml");
List<CityObjectMember> cityObjectMember = cityModel.getCityObjectMember();
CityObjectMember com = cityObjectMember.get(0);
AbstractCityObject aco = com.getCityObject();
Building b = (Building) aco;
List<ADEComponent> gen = b.getGenericApplicationPropertyOfCityObject();
ADEComponent resultComp = gen.get(0);
ValidationResult result = (ValidationResult) resultComp;
assertEquals(ResultType.ERROR, result.getResult());
assertFalse(result.getErrors().isEmpty());
List<ValidationError> errors = result.getErrors();
ValidationError validationError = errors.get(0);
assertTrue(validationError instanceof RingNotClosed);
RingNotClosed err = (RingNotClosed) validationError;
assertEquals("_Simple_BD.1_PG.6_LR.1", err.getLinearRingId());
}
@Test
void testReadingInteriorDisconnectedError()
throws ADEException, CityGMLBuilderException, CityGMLReadException, FileNotFoundException {
CityModel cityModel = readCityGml("src/test/resources/SimpleSolid_InteriorDisconnected.gml");
List<CityObjectMember> cityObjectMember = cityModel.getCityObjectMember();
CityObjectMember com = cityObjectMember.get(0);
AbstractCityObject aco = com.getCityObject();
Building b = (Building) aco;
List<ADEComponent> gen = b.getGenericApplicationPropertyOfCityObject();
ADEComponent resultComp = gen.get(0);
ValidationResult result = (ValidationResult) resultComp;
assertEquals(ResultType.ERROR, result.getResult());
assertFalse(result.getErrors().isEmpty());
List<ValidationError> errors = result.getErrors();
ValidationError validationError = errors.get(0);
assertTrue(validationError instanceof InteriorDisconnected);
InteriorDisconnected err = (InteriorDisconnected) validationError;
assertEquals("_Simple_BD.1_PG.1", err.getPolygonId());
}
@Test
void testReadingIntersectingRingsError()
throws ADEException, CityGMLBuilderException, CityGMLReadException, FileNotFoundException {
CityModel cityModel = readCityGml("src/test/resources/SimpleSolid_IntersectingRings.gml");
List<CityObjectMember> cityObjectMember = cityModel.getCityObjectMember();
CityObjectMember com = cityObjectMember.get(0);
AbstractCityObject aco = com.getCityObject();
Building b = (Building) aco;
List<ADEComponent> gen = b.getGenericApplicationPropertyOfCityObject();
ADEComponent resultComp = gen.get(0);
ValidationResult result = (ValidationResult) resultComp;
assertEquals(ResultType.ERROR, result.getResult());
assertFalse(result.getErrors().isEmpty());
List<ValidationError> errors = result.getErrors();
ValidationError validationError = errors.get(0);
assertTrue(validationError instanceof IntersectingRings);
IntersectingRings err = (IntersectingRings) validationError;
assertEquals("_Simple_BD.1_PG.1", err.getPolygonId());
assertEquals("_Simple_BD.1_PG.1_Ring1", err.getLinearRingId1());
assertEquals("_Simple_BD.1_PG.1_Ring2", err.getLinearRingId2());
}
@Test
void testReadingNonPlanarPolygonDistancePlaneError()
throws ADEException, CityGMLBuilderException, CityGMLReadException, FileNotFoundException {
CityModel cityModel = readCityGml("src/test/resources/SimpleSolid_NonPlanarPolygonDistancePlane.gml");
List<CityObjectMember> cityObjectMember = cityModel.getCityObjectMember();
CityObjectMember com = cityObjectMember.get(0);
AbstractCityObject aco = com.getCityObject();
Building b = (Building) aco;
List<ADEComponent> gen = b.getGenericApplicationPropertyOfCityObject();
ADEComponent resultComp = gen.get(0);
ValidationResult result = (ValidationResult) resultComp;
assertEquals(ResultType.ERROR, result.getResult());
assertFalse(result.getErrors().isEmpty());
List<ValidationError> errors = result.getErrors();
ValidationError validationError = errors.get(0);
assertTrue(validationError instanceof NonPlanarDistancePlane);
NonPlanarDistancePlane err = (NonPlanarDistancePlane) validationError;
assertEquals("_Simple_BD.1_PG.1", err.getPolygonId());
assertEquals(1.0, err.getVertex().getValue().get(0), 0.000001);
assertEquals(0.001, err.getDistance().getValue(), 0.000001);
assertEquals("m", err.getDistance().getUom());
}
@Test
void testReadingInnerRingsNestedError()
throws ADEException, CityGMLBuilderException, CityGMLReadException, FileNotFoundException {
CityModel cityModel = readCityGml("src/test/resources/SimpleSolid_InnerRingNested.gml");
List<CityObjectMember> cityObjectMember = cityModel.getCityObjectMember();
CityObjectMember com = cityObjectMember.get(0);
AbstractCityObject aco = com.getCityObject();
Building b = (Building) aco;
List<ADEComponent> gen = b.getGenericApplicationPropertyOfCityObject();
ADEComponent resultComp = gen.get(0);
ValidationResult result = (ValidationResult) resultComp;
assertEquals(ResultType.ERROR, result.getResult());
assertFalse(result.getErrors().isEmpty());
List<ValidationError> errors = result.getErrors();
ValidationError validationError = errors.get(0);
assertTrue(validationError instanceof InnerRingsNested);
InnerRingsNested err = (InnerRingsNested) validationError;
assertEquals("_Simple_BD.1_PG.1", err.getPolygonId());
assertEquals("_Simple_BD.1_PG.1_Ring1", err.getLinearRingId1());
assertEquals("_Simple_BD.1_PG.1_Ring2", err.getLinearRingId2());
}
@Test
void testReadingHoleOutsideError()
throws ADEException, CityGMLBuilderException, CityGMLReadException, FileNotFoundException {
CityModel cityModel = readCityGml("src/test/resources/SimpleSolid_HoleOutside.gml");
List<CityObjectMember> cityObjectMember = cityModel.getCityObjectMember();
CityObjectMember com = cityObjectMember.get(0);
AbstractCityObject aco = com.getCityObject();
Building b = (Building) aco;
List<ADEComponent> gen = b.getGenericApplicationPropertyOfCityObject();
ADEComponent resultComp = gen.get(0);
ValidationResult result = (ValidationResult) resultComp;
assertEquals(ResultType.ERROR, result.getResult());
assertFalse(result.getErrors().isEmpty());
List<ValidationError> errors = result.getErrors();
ValidationError validationError = errors.get(0);
assertTrue(validationError instanceof HoleOutside);
HoleOutside err = (HoleOutside) validationError;
assertEquals("_Simple_BD.1_PG.1", err.getPolygonId());
assertEquals("_Simple_BD.1_PG.1_Ring1", err.getLinearRingId());
}
@Test
void testReadingNonPlanarNormalsDeviationError()
throws ADEException, CityGMLBuilderException, CityGMLReadException, FileNotFoundException {
CityModel cityModel = readCityGml("src/test/resources/SimpleSolid_NonPlanarPolygonNormalsDeviation.gml");
List<CityObjectMember> cityObjectMember = cityModel.getCityObjectMember();
CityObjectMember com = cityObjectMember.get(0);
AbstractCityObject aco = com.getCityObject();
Building b = (Building) aco;
List<ADEComponent> gen = b.getGenericApplicationPropertyOfCityObject();
ADEComponent resultComp = gen.get(0);
ValidationResult result = (ValidationResult) resultComp;
assertEquals(ResultType.ERROR, result.getResult());
assertFalse(result.getErrors().isEmpty());
List<ValidationError> errors = result.getErrors();
ValidationError validationError = errors.get(0);
assertTrue(validationError instanceof NonPlanarNormalsDeviation);
NonPlanarNormalsDeviation err = (NonPlanarNormalsDeviation) validationError;
assertEquals("_Simple_BD.1_PG.1", err.getPolygonId());
assertEquals(1.0, err.getDeviation().getValue());
assertEquals("deg", err.getDeviation().getUom());
}
@Test
void testReadingOrientationRingsSameError()
throws ADEException, CityGMLBuilderException, CityGMLReadException, FileNotFoundException {
CityModel cityModel = readCityGml("src/test/resources/SimpleSolid_OrientationRingsSame.gml");
List<CityObjectMember> cityObjectMember = cityModel.getCityObjectMember();
CityObjectMember com = cityObjectMember.get(0);
AbstractCityObject aco = com.getCityObject();
Building b = (Building) aco;
List<ADEComponent> gen = b.getGenericApplicationPropertyOfCityObject();
ADEComponent resultComp = gen.get(0);
ValidationResult result = (ValidationResult) resultComp;
assertEquals(ResultType.ERROR, result.getResult());
assertFalse(result.getErrors().isEmpty());
List<ValidationError> errors = result.getErrors();
ValidationError validationError = errors.get(0);
assertTrue(validationError instanceof OrientationRingsSame);
OrientationRingsSame err = (OrientationRingsSame) validationError;
assertEquals("_Simple_BD.1_PG.1", err.getPolygonId());
assertEquals("_Simple_BD.1_PG.1_Ring1", err.getLinearRingId());
}
@Test
void testReadingAllPolygonsWrongOrientationError()
throws ADEException, CityGMLBuilderException, CityGMLReadException, FileNotFoundException {
CityModel cityModel = readCityGml("src/test/resources/SimpleSolid_AllPolygonsWrongOrientation.gml");
List<CityObjectMember> cityObjectMember = cityModel.getCityObjectMember();
CityObjectMember com = cityObjectMember.get(0);
AbstractCityObject aco = com.getCityObject();
Building b = (Building) aco;
List<ADEComponent> gen = b.getGenericApplicationPropertyOfCityObject();
ADEComponent resultComp = gen.get(0);
ValidationResult result = (ValidationResult) resultComp;
assertEquals(ResultType.ERROR, result.getResult());
assertFalse(result.getErrors().isEmpty());
List<ValidationError> errors = result.getErrors();
ValidationError validationError = errors.get(0);
assertTrue(validationError instanceof AllPolygonsWrongOrientation);
AllPolygonsWrongOrientation err = (AllPolygonsWrongOrientation) validationError;
assertEquals("_Simple_BD.1_Geom1", err.getGeometryId());
}
@Test
void testReadingPolygonWrongOrientationError()
throws ADEException, CityGMLBuilderException, CityGMLReadException, FileNotFoundException {
CityModel cityModel = readCityGml("src/test/resources/SimpleSolid_PolygonWrongOrientation.gml");
List<CityObjectMember> cityObjectMember = cityModel.getCityObjectMember();
CityObjectMember com = cityObjectMember.get(0);
AbstractCityObject aco = com.getCityObject();
Building b = (Building) aco;
List<ADEComponent> gen = b.getGenericApplicationPropertyOfCityObject();
ADEComponent resultComp = gen.get(0);
ValidationResult result = (ValidationResult) resultComp;
assertEquals(ResultType.ERROR, result.getResult());
assertFalse(result.getErrors().isEmpty());
List<ValidationError> errors = result.getErrors();
ValidationError validationError = errors.get(0);
assertTrue(validationError instanceof PolygonWrongOrientation);
PolygonWrongOrientation err = (PolygonWrongOrientation) validationError;
assertEquals("_Simple_BD.1_Geom1", err.getGeometryId());
assertFalse(err.getEdges().isEmpty());
List<Edge> edges = err.getEdges();
Edge edge = edges.get(0);
DirectPosition from = edge.getFrom();
assertEquals(10.0, from.getValue().get(0), 0.000001);
assertEquals(11.0, edge.getTo().getValue().get(0), 0.000001);
}
@Test
void testReadingNonManifoldVertexError()
throws ADEException, CityGMLBuilderException, CityGMLReadException, FileNotFoundException {
CityModel cityModel = readCityGml("src/test/resources/SimpleSolid_NonManifoldVertex.gml");
List<CityObjectMember> cityObjectMember = cityModel.getCityObjectMember();
CityObjectMember com = cityObjectMember.get(0);
AbstractCityObject aco = com.getCityObject();
Building b = (Building) aco;
List<ADEComponent> gen = b.getGenericApplicationPropertyOfCityObject();
ADEComponent resultComp = gen.get(0);
ValidationResult result = (ValidationResult) resultComp;
assertEquals(ResultType.ERROR, result.getResult());
assertFalse(result.getErrors().isEmpty());
List<ValidationError> errors = result.getErrors();
ValidationError validationError = errors.get(0);
assertTrue(validationError instanceof NonManifoldVertex);
NonManifoldVertex err = (NonManifoldVertex) validationError;
assertEquals("_Simple_BD.1_Geom1", err.getGeometryId());
DirectPosition vertex = err.getVertex();
assertEquals(1.0, vertex.getValue().get(0), 0.000001);
}
@Test
void testReadingNonManifoldEdgeError()
throws ADEException, CityGMLBuilderException, CityGMLReadException, FileNotFoundException {
CityModel cityModel = readCityGml("src/test/resources/SimpleSolid_NonManifoldEdge.gml");
List<CityObjectMember> cityObjectMember = cityModel.getCityObjectMember();
CityObjectMember com = cityObjectMember.get(0);
AbstractCityObject aco = com.getCityObject();
Building b = (Building) aco;
List<ADEComponent> gen = b.getGenericApplicationPropertyOfCityObject();
ADEComponent resultComp = gen.get(0);
ValidationResult result = (ValidationResult) resultComp;
assertEquals(ResultType.ERROR, result.getResult());
assertFalse(result.getErrors().isEmpty());
List<ValidationError> errors = result.getErrors();
ValidationError validationError = errors.get(0);
assertTrue(validationError instanceof NonManifoldEdge);
NonManifoldEdge err = (NonManifoldEdge) validationError;
assertEquals("_Simple_BD.1_Geom1", err.getGeometryId());
assertFalse(err.getEdges().isEmpty());
List<Edge> edges = err.getEdges();
Edge edge = edges.get(0);
DirectPosition from = edge.getFrom();
assertEquals(10.0, from.getValue().get(0), 0.000001);
assertEquals(11.0, edge.getTo().getValue().get(0), 0.000001);
}
@Test
void testReadingSolidNotClosedError()
throws ADEException, CityGMLBuilderException, CityGMLReadException, FileNotFoundException {
CityModel cityModel = readCityGml("src/test/resources/SimpleSolid_SolidNotClosed.gml");
List<CityObjectMember> cityObjectMember = cityModel.getCityObjectMember();
CityObjectMember com = cityObjectMember.get(0);
AbstractCityObject aco = com.getCityObject();
Building b = (Building) aco;
List<ADEComponent> gen = b.getGenericApplicationPropertyOfCityObject();
ADEComponent resultComp = gen.get(0);
ValidationResult result = (ValidationResult) resultComp;
assertEquals(ResultType.ERROR, result.getResult());
assertFalse(result.getErrors().isEmpty());
List<ValidationError> errors = result.getErrors();
ValidationError validationError = errors.get(0);
assertTrue(validationError instanceof SolidNotClosed);
SolidNotClosed err = (SolidNotClosed) validationError;
assertEquals("_Simple_BD.1_Geom1", err.getGeometryId());
assertFalse(err.getEdges().isEmpty());
List<Edge> edges = err.getEdges();
Edge edge = edges.get(0);
DirectPosition from = edge.getFrom();
assertEquals(10.0, from.getValue().get(0), 0.000001);
assertEquals(11.0, edge.getTo().getValue().get(0), 0.000001);
}
@Test @Test
void testReadingTooFewPolygonsError() void testConsecutivePointsSameError() throws ADEException, CityGMLContextException, CityGMLWriteException, SAXException, IOException, SchemaHandlerException {
throws ADEException, CityGMLBuilderException, CityGMLReadException, FileNotFoundException { CityModel model = new CityModel();
CityModel cityModel = readCityGml("src/test/resources/SimpleSolid_TooFewPolygons.gml"); ValidationResult res = fillCityModel(model);
List<CityObjectMember> cityObjectMember = cityModel.getCityObjectMember(); ConsecutivePointsSameError err = new ConsecutivePointsSameError();
CityObjectMember com = cityObjectMember.get(0); err.setLinearRingId("ringId");
AbstractCityObject aco = com.getCityObject(); err.setVertex1(new DirectPosition(1, 2, 3));
Building b = (Building) aco; err.setVertex2(new DirectPosition(5, 6, 7));
res.getErrors().add(new AbstractErrorProperty(err));
List<ADEComponent> gen = b.getGenericApplicationPropertyOfCityObject();
ADEComponent resultComp = gen.get(0); byte[] buf = writeModel(model);
ValidationResult result = (ValidationResult) resultComp; assertTrue(validate(new ByteArrayInputStream(buf)));
assertEquals(ResultType.ERROR, result.getResult());
assertFalse(result.getErrors().isEmpty());
List<ValidationError> errors = result.getErrors();
ValidationError validationError = errors.get(0);
assertTrue(validationError instanceof TooFewPolygons);
TooFewPolygons err = (TooFewPolygons) validationError;
assertEquals("_Simple_BD.1_Geom1", err.getGeometryId());
}
@Test
void testReadingMultipleConnectedComponentsError()
throws ADEException, CityGMLBuilderException, CityGMLReadException, FileNotFoundException {
CityModel cityModel = readCityGml("src/test/resources/SimpleSolid_MultipleConnectedComponents.gml");
List<CityObjectMember> cityObjectMember = cityModel.getCityObjectMember();
CityObjectMember com = cityObjectMember.get(0);
AbstractCityObject aco = com.getCityObject();
Building b = (Building) aco;
List<ADEComponent> gen = b.getGenericApplicationPropertyOfCityObject();
ADEComponent resultComp = gen.get(0);
ValidationResult result = (ValidationResult) resultComp;
assertEquals(ResultType.ERROR, result.getResult());
assertFalse(result.getErrors().isEmpty());
List<ValidationError> errors = result.getErrors();
ValidationError validationError = errors.get(0);
assertTrue(validationError instanceof MultipleConnectedComponents);
MultipleConnectedComponents err = (MultipleConnectedComponents) validationError;
assertEquals("_Simple_BD.1_Geom1", err.getGeometryId());
assertEquals("_Simple_BD.1_PG.1", err.getComponents().get(0).getPolygonIds().get(0));
assertEquals("_Simple_BD.1_PG.2", err.getComponents().get(0).getPolygonIds().get(1));
assertEquals("_Simple_BD.1_PG.3", err.getComponents().get(1).getPolygonIds().get(0));
assertEquals("_Simple_BD.1_PG.4", err.getComponents().get(1).getPolygonIds().get(1));
}
@Test
void testWritingAttributeMissingError()
throws ADEException, CityGMLBuilderException, CityGMLWriteException, CityGMLReadException {
CityModel model = new CityModel();
Building b = new Building();
model.getCityObjectMember().add(new CityObjectMember(b));
ValidationResult result = new ValidationResult();
result.setResult(ResultType.ERROR);
b.addGenericApplicationPropertyOfCityObject(result);
AttributeMissing error = new AttributeMissing();
error.setAttributeName("TestName");
error.setChildId("TestId");
error.setGeneric(true);
result.getErrors().add(error);
byte[] gml = writeCityGml(model);
model = readCityGml(gml);
AbstractCityObject co = model.getCityObjectMember().get(0).getCityObject();
List<ADEComponent> ades = co.getGenericApplicationPropertyOfCityObject();
ADEComponent adeComponent = ades.get(0);
ValidationResult valRes = (ValidationResult) adeComponent;
assertEquals(ResultType.ERROR, valRes.getResult());
ValidationError valError = valRes.getErrors().get(0);
AttributeMissing error2 = (AttributeMissing) valError;
assertEquals(error.getAttributeName(), error2.getAttributeName());
assertEquals(error.getChildId(), error2.getChildId());
assertEquals(error.isGeneric(), error2.isGeneric());
} }
@Test @Test
void testWritingAttributeWrongValueError() void testHoleOutsideError() throws ADEException, CityGMLContextException, CityGMLWriteException, SAXException, IOException, SchemaHandlerException {
throws ADEException, CityGMLBuilderException, CityGMLWriteException, CityGMLReadException { CityModel model = new CityModel();
CityModel model = new CityModel(); ValidationResult res = fillCityModel(model);
Building b = new Building();
model.getCityObjectMember().add(new CityObjectMember(b)); HoleOutsideError err = new HoleOutsideError();
err.setLinearRingId("ringId");
ValidationResult result = new ValidationResult(); err.setPolygonId("polyId");
result.setResult(ResultType.ERROR); res.getErrors().add(new AbstractErrorProperty(err));
b.addGenericApplicationPropertyOfCityObject(result);
AttributeWrongValue error = new AttributeWrongValue(); byte[] buf = writeModel(model);
error.setAttributeName("TestName"); assertTrue(validate(new ByteArrayInputStream(buf)));
error.setChildId("TestId");
error.setGeneric(true);
result.getErrors().add(error);
byte[] gml = writeCityGml(model);
model = readCityGml(gml);
AbstractCityObject co = model.getCityObjectMember().get(0).getCityObject();
List<ADEComponent> ades = co.getGenericApplicationPropertyOfCityObject();
ADEComponent adeComponent = ades.get(0);
ValidationResult valRes = (ValidationResult) adeComponent;
assertEquals(ResultType.ERROR, valRes.getResult());
ValidationError valError = valRes.getErrors().get(0);
AttributeWrongValue error2 = (AttributeWrongValue) valError;
assertEquals(error.getAttributeName(), error2.getAttributeName());
assertEquals(error.getChildId(), error2.getChildId());
assertEquals(error.isGeneric(), error2.isGeneric());
} }
@Test @Test
void testWritingMultipleConnectedComponentsError() void testInnerRingsNestedError() throws ADEException, CityGMLContextException, CityGMLWriteException, SAXException, IOException, SchemaHandlerException {
throws ADEException, CityGMLBuilderException, CityGMLWriteException, CityGMLReadException { CityModel model = new CityModel();
CityModel model = new CityModel(); ValidationResult res = fillCityModel(model);
Building b = new Building();
model.getCityObjectMember().add(new CityObjectMember(b)); InnerRingsNestedError err = new InnerRingsNestedError();
err.setLinearRingId1("ringId1");
ValidationResult result = new ValidationResult(); err.setLinearRingId2("ringId2");
result.setResult(ResultType.ERROR); err.setPolygonId("polyId");
b.addGenericApplicationPropertyOfCityObject(result); res.getErrors().add(new AbstractErrorProperty(err));
MultipleConnectedComponents error = new MultipleConnectedComponents();
error.setGeometryId("TestGeometry"); byte[] buf = writeModel(model);
Component c1 = new Component(); assertTrue(validate(new ByteArrayInputStream(buf)));
c1.getPolygonIds().add("TestPoly");
error.getComponents().add(c1);
result.getErrors().add(error);
byte[] gml = writeCityGml(model);
model = readCityGml(gml);
AbstractCityObject co = model.getCityObjectMember().get(0).getCityObject();
List<ADEComponent> ades = co.getGenericApplicationPropertyOfCityObject();
ADEComponent adeComponent = ades.get(0);
ValidationResult valRes = (ValidationResult) adeComponent;
assertEquals(ResultType.ERROR, valRes.getResult());
ValidationError valError = valRes.getErrors().get(0);
MultipleConnectedComponents error2 = (MultipleConnectedComponents) valError;
assertEquals(error.getGeometryId(), error2.getGeometryId());
assertEquals(error.getComponents().get(0).getPolygonIds().get(0),
error2.getComponents().get(0).getPolygonIds().get(0));
} }
@Test @Test
void testWritingTooFewPolygonsError() void testInteriorDisconnectedError() throws ADEException, CityGMLContextException, CityGMLWriteException, SAXException, IOException, SchemaHandlerException {
throws ADEException, CityGMLBuilderException, CityGMLWriteException, CityGMLReadException { CityModel model = new CityModel();
CityModel model = new CityModel(); ValidationResult res = fillCityModel(model);
Building b = new Building();
model.getCityObjectMember().add(new CityObjectMember(b)); InteriorDisconnectedError err = new InteriorDisconnectedError();
err.setPolygonId("polyId");
ValidationResult result = new ValidationResult(); res.getErrors().add(new AbstractErrorProperty(err));
result.setResult(ResultType.ERROR);
b.addGenericApplicationPropertyOfCityObject(result); byte[] buf = writeModel(model);
TooFewPolygons error = new TooFewPolygons(); assertTrue(validate(new ByteArrayInputStream(buf)));
error.setGeometryId("TestGeometry");
result.getErrors().add(error);
byte[] gml = writeCityGml(model);
model = readCityGml(gml);
AbstractCityObject co = model.getCityObjectMember().get(0).getCityObject();
List<ADEComponent> ades = co.getGenericApplicationPropertyOfCityObject();
ADEComponent adeComponent = ades.get(0);
ValidationResult valRes = (ValidationResult) adeComponent;
assertEquals(ResultType.ERROR, valRes.getResult());
ValidationError valError = valRes.getErrors().get(0);
TooFewPolygons error2 = (TooFewPolygons) valError;
assertEquals(error.getGeometryId(), error2.getGeometryId());
} }
@Test @Test
void testWritingSolidNotClosedError() void testIntersectingRingsError() throws ADEException, CityGMLContextException, CityGMLWriteException, SAXException, IOException, SchemaHandlerException {
throws ADEException, CityGMLBuilderException, CityGMLWriteException, CityGMLReadException { CityModel model = new CityModel();
CityModel model = new CityModel(); ValidationResult res = fillCityModel(model);
Building b = new Building();
model.getCityObjectMember().add(new CityObjectMember(b)); IntersectingRingsError err = new IntersectingRingsError();
err.setLinearRingId1("ringId1");
ValidationResult result = new ValidationResult(); err.setLinearRingId2("ringId2");
result.setResult(ResultType.ERROR); err.setPolygonId("polyId");
b.addGenericApplicationPropertyOfCityObject(result); res.getErrors().add(new AbstractErrorProperty(err));
SolidNotClosed error = new SolidNotClosed();
error.setGeometryId("TestGeometry"); byte[] buf = writeModel(model);
DirectPosition from = new DirectPosition(); assertTrue(validate(new ByteArrayInputStream(buf)));
from.getValue().add(10.0);
DirectPosition to = new DirectPosition();
to.getValue().add(11.0);
Edge e = new Edge();
e.setFrom(from);
e.setTo(to);
error.getEdges().add(e);
result.getErrors().add(error);
byte[] gml = writeCityGml(model);
model = readCityGml(gml);
AbstractCityObject co = model.getCityObjectMember().get(0).getCityObject();
List<ADEComponent> ades = co.getGenericApplicationPropertyOfCityObject();
ADEComponent adeComponent = ades.get(0);
ValidationResult valRes = (ValidationResult) adeComponent;
assertEquals(ResultType.ERROR, valRes.getResult());
ValidationError valError = valRes.getErrors().get(0);
SolidNotClosed error2 = (SolidNotClosed) valError;
assertEquals(error.getGeometryId(), error2.getGeometryId());
Edge edge = error.getEdges().get(0);
assertEquals(edge.getFrom().getValue().get(0), e.getFrom().getValue().get(0), 0.00001);
assertEquals(edge.getTo().getValue().get(0), e.getTo().getValue().get(0), 0.00001);
} }
@Test @Test
void testWritingNonManifoldEdgeError() void testMultipleComponentsError() throws ADEException, CityGMLContextException, CityGMLWriteException, SAXException, IOException, SchemaHandlerException {
throws ADEException, CityGMLBuilderException, CityGMLWriteException, CityGMLReadException { CityModel model = new CityModel();
CityModel model = new CityModel(); ValidationResult res = fillCityModel(model);
Building b = new Building();
model.getCityObjectMember().add(new CityObjectMember(b)); MultipleComponentsError err = new MultipleComponentsError();
err.setGeometryId("geomId");
ValidationResult result = new ValidationResult(); ComponentList comp = new ComponentList();
result.setResult(ResultType.ERROR); PolygonIdList polygons = new PolygonIdList();
b.addGenericApplicationPropertyOfCityObject(result); polygons.getPolygonIds().add("test1");
NonManifoldEdge error = new NonManifoldEdge(); polygons.getPolygonIds().add("test2");
error.setGeometryId("TestGeometry"); comp.getComponents().add(new PolygonIdListProperty(polygons));
DirectPosition from = new DirectPosition();
from.getValue().add(10.0); err.getComponents().add(new ComponentListProperty(comp));
DirectPosition to = new DirectPosition();
to.getValue().add(11.0); res.getErrors().add(new AbstractErrorProperty(err));
Edge e = new Edge();
e.setFrom(from); byte[] buf = writeModel(model);
e.setTo(to); assertTrue(validate(new ByteArrayInputStream(buf)));
error.getEdges().add(e);
result.getErrors().add(error);
byte[] gml = writeCityGml(model);
model = readCityGml(gml);
AbstractCityObject co = model.getCityObjectMember().get(0).getCityObject();
List<ADEComponent> ades = co.getGenericApplicationPropertyOfCityObject();
ADEComponent adeComponent = ades.get(0);
ValidationResult valRes = (ValidationResult) adeComponent;
assertEquals(ResultType.ERROR, valRes.getResult());
ValidationError valError = valRes.getErrors().get(0);
NonManifoldEdge error2 = (NonManifoldEdge) valError;
assertEquals(error.getGeometryId(), error2.getGeometryId());
Edge edge = error.getEdges().get(0);
assertEquals(edge.getFrom().getValue().get(0), e.getFrom().getValue().get(0), 0.00001);
assertEquals(edge.getTo().getValue().get(0), e.getTo().getValue().get(0), 0.00001);
} }
@Test @Test
void testWritingNonManifoldVertexError() void testNonManifoldEdgeError() throws ADEException, CityGMLContextException, CityGMLWriteException, SAXException, IOException, SchemaHandlerException {
throws ADEException, CityGMLBuilderException, CityGMLWriteException, CityGMLReadException { CityModel model = new CityModel();
CityModel model = new CityModel(); ValidationResult res = fillCityModel(model);
Building b = new Building();
model.getCityObjectMember().add(new CityObjectMember(b)); NonManifoldEdgeError err = new NonManifoldEdgeError();
err.setGeometryId("geomId");
ValidationResult result = new ValidationResult(); EdgeList edges = new EdgeList();
result.setResult(ResultType.ERROR); Edge edge = new Edge();
b.addGenericApplicationPropertyOfCityObject(result); edge.setFrom(new DirectPosition(1, 2, 3));
NonManifoldVertex error = new NonManifoldVertex(); edge.setTo(new DirectPosition(5, 6, 7));
error.setGeometryId("TestGeometry"); edges.getEdges().add(new EdgeProperty(edge));
DirectPosition vertex = new DirectPosition(); err.setEdges(new EdgeListProperty(edges));
vertex.getValue().add(10.0);
error.setVertex(vertex); res.getErrors().add(new AbstractErrorProperty(err));
result.getErrors().add(error);
byte[] buf = writeModel(model);
byte[] gml = writeCityGml(model); assertTrue(validate(new ByteArrayInputStream(buf)));
model = readCityGml(gml);
AbstractCityObject co = model.getCityObjectMember().get(0).getCityObject();
List<ADEComponent> ades = co.getGenericApplicationPropertyOfCityObject();
ADEComponent adeComponent = ades.get(0);
ValidationResult valRes = (ValidationResult) adeComponent;
assertEquals(ResultType.ERROR, valRes.getResult());
ValidationError valError = valRes.getErrors().get(0);
NonManifoldVertex error2 = (NonManifoldVertex) valError;
assertEquals(error.getGeometryId(), error2.getGeometryId());
assertEquals(error.getVertex().getValue().get(0), error2.getVertex().getValue().get(0));
} }
@Test @Test
void testWritingPolygonWrongOrientationError() void testNonManifoldVertexError() throws ADEException, CityGMLContextException, CityGMLWriteException, SAXException, IOException, SchemaHandlerException {
throws ADEException, CityGMLBuilderException, CityGMLWriteException, CityGMLReadException { CityModel model = new CityModel();
CityModel model = new CityModel(); ValidationResult res = fillCityModel(model);
Building b = new Building();
model.getCityObjectMember().add(new CityObjectMember(b)); NonManifoldVertexError err = new NonManifoldVertexError();
err.setGeometryId("geomId");
ValidationResult result = new ValidationResult(); err.setVertex(new DirectPosition(1, 2, 3));
result.setResult(ResultType.ERROR); res.getErrors().add(new AbstractErrorProperty(err));
b.addGenericApplicationPropertyOfCityObject(result);
PolygonWrongOrientation error = new PolygonWrongOrientation(); byte[] buf = writeModel(model);
error.setGeometryId("TestGeometry"); assertTrue(validate(new ByteArrayInputStream(buf)));
DirectPosition from = new DirectPosition();
from.getValue().add(10.0);
DirectPosition to = new DirectPosition();
to.getValue().add(11.0);
Edge e = new Edge();
e.setFrom(from);
e.setTo(to);
error.getEdges().add(e);
result.getErrors().add(error);
byte[] gml = writeCityGml(model);
model = readCityGml(gml);
AbstractCityObject co = model.getCityObjectMember().get(0).getCityObject();
List<ADEComponent> ades = co.getGenericApplicationPropertyOfCityObject();
ADEComponent adeComponent = ades.get(0);
ValidationResult valRes = (ValidationResult) adeComponent;
assertEquals(ResultType.ERROR, valRes.getResult());
ValidationError valError = valRes.getErrors().get(0);
PolygonWrongOrientation error2 = (PolygonWrongOrientation) valError;
assertEquals(error.getGeometryId(), error2.getGeometryId());
Edge edge = error.getEdges().get(0);
assertEquals(edge.getFrom().getValue().get(0), e.getFrom().getValue().get(0), 0.00001);
assertEquals(edge.getTo().getValue().get(0), e.getTo().getValue().get(0), 0.00001);
} }
@Test @Test
void testWritingAllPolygonsWrongOrientationError() void testOrientationRingsSameError() throws ADEException, CityGMLContextException, CityGMLWriteException, SAXException, IOException, SchemaHandlerException {
throws ADEException, CityGMLBuilderException, CityGMLWriteException, CityGMLReadException { CityModel model = new CityModel();
CityModel model = new CityModel(); ValidationResult res = fillCityModel(model);
Building b = new Building();
model.getCityObjectMember().add(new CityObjectMember(b)); OrientationRingsSameError err = new OrientationRingsSameError();
err.setLinearRing("ring1");
ValidationResult result = new ValidationResult(); err.setPolygonId("polyId");
result.setResult(ResultType.ERROR); res.getErrors().add(new AbstractErrorProperty(err));
b.addGenericApplicationPropertyOfCityObject(result);
AllPolygonsWrongOrientation error = new AllPolygonsWrongOrientation(); byte[] buf = writeModel(model);
error.setGeometryId("TestGeometry"); assertTrue(validate(new ByteArrayInputStream(buf)));
result.getErrors().add(error);
byte[] gml = writeCityGml(model);
model = readCityGml(gml);
AbstractCityObject co = model.getCityObjectMember().get(0).getCityObject();
List<ADEComponent> ades = co.getGenericApplicationPropertyOfCityObject();
ADEComponent adeComponent = ades.get(0);
ValidationResult valRes = (ValidationResult) adeComponent;
assertEquals(ResultType.ERROR, valRes.getResult());
ValidationError valError = valRes.getErrors().get(0);
AllPolygonsWrongOrientation error2 = (AllPolygonsWrongOrientation) valError;
assertEquals(error.getGeometryId(), error2.getGeometryId());
} }
@Test @Test
void testWritingOrientationRingsSameError() void testPlanarDistancePlaneError() throws ADEException, CityGMLContextException, CityGMLWriteException, SAXException, IOException, SchemaHandlerException {
throws ADEException, CityGMLBuilderException, CityGMLWriteException, CityGMLReadException { CityModel model = new CityModel();
CityModel model = new CityModel(); ValidationResult res = fillCityModel(model);
Building b = new Building();
model.getCityObjectMember().add(new CityObjectMember(b)); PlanarDistancePlaneError err = new PlanarDistancePlaneError();
err.setPolygonId("polyId");
ValidationResult result = new ValidationResult(); err.setDistance(new Length(5d, "m"));
result.setResult(ResultType.ERROR); err.setVertex(new DirectPosition(1, 2, 3));
b.addGenericApplicationPropertyOfCityObject(result); res.getErrors().add(new AbstractErrorProperty(err));
OrientationRingsSame error = new OrientationRingsSame();
error.setPolygonId("TestPolygon"); byte[] buf = writeModel(model);
error.setLinearRingId("TestRing"); assertTrue(validate(new ByteArrayInputStream(buf)));
result.getErrors().add(error);
byte[] gml = writeCityGml(model);
model = readCityGml(gml);
AbstractCityObject co = model.getCityObjectMember().get(0).getCityObject();
List<ADEComponent> ades = co.getGenericApplicationPropertyOfCityObject();
ADEComponent adeComponent = ades.get(0);
ValidationResult valRes = (ValidationResult) adeComponent;
assertEquals(ResultType.ERROR, valRes.getResult());
ValidationError valError = valRes.getErrors().get(0);
OrientationRingsSame error2 = (OrientationRingsSame) valError;
assertEquals(error.getPolygonId(), error2.getPolygonId());
assertEquals(error.getLinearRingId(), error2.getLinearRingId());
} }
@Test @Test
void testWritingNonPlanarNormalsDeviationError() void testPlanarNormalsDeviationError() throws ADEException, CityGMLContextException, CityGMLWriteException, SAXException, IOException, SchemaHandlerException {
throws ADEException, CityGMLBuilderException, CityGMLWriteException, CityGMLReadException { CityModel model = new CityModel();
CityModel model = new CityModel(); ValidationResult res = fillCityModel(model);
Building b = new Building();
model.getCityObjectMember().add(new CityObjectMember(b)); PlanarNormalsDeviationError err = new PlanarNormalsDeviationError();
err.setPolygonId("polyId");
ValidationResult result = new ValidationResult(); err.setDeviation(new Angle(5d, "deg"));
result.setResult(ResultType.ERROR); res.getErrors().add(new AbstractErrorProperty(err));
b.addGenericApplicationPropertyOfCityObject(result);
NonPlanarNormalsDeviation error = new NonPlanarNormalsDeviation(); byte[] buf = writeModel(model);
error.setPolygonId("TestPolygon"); assertTrue(validate(new ByteArrayInputStream(buf)));
Angle deviation = new Angle();
deviation.setValue(1.0);
deviation.setUom("deg");
error.setDeviation(deviation);
result.getErrors().add(error);
byte[] gml = writeCityGml(model);
model = readCityGml(gml);
AbstractCityObject co = model.getCityObjectMember().get(0).getCityObject();
List<ADEComponent> ades = co.getGenericApplicationPropertyOfCityObject();
ADEComponent adeComponent = ades.get(0);
ValidationResult valRes = (ValidationResult) adeComponent;
assertEquals(ResultType.ERROR, valRes.getResult());
ValidationError valError = valRes.getErrors().get(0);
NonPlanarNormalsDeviation error2 = (NonPlanarNormalsDeviation) valError;
assertEquals(error.getPolygonId(), error2.getPolygonId());
assertEquals(error.getDeviation().getValue(), error2.getDeviation().getValue());
assertEquals(error.getDeviation().getUom(), error2.getDeviation().getUom());
} }
@Test @Test
void testWritingHoleOutsideError() void testPolygonWrongOrientationError() throws ADEException, CityGMLContextException, CityGMLWriteException, SAXException, IOException, SchemaHandlerException {
throws ADEException, CityGMLBuilderException, CityGMLWriteException, CityGMLReadException { CityModel model = new CityModel();
CityModel model = new CityModel(); ValidationResult res = fillCityModel(model);
Building b = new Building();
model.getCityObjectMember().add(new CityObjectMember(b)); PolygonWrongOrientationError err = new PolygonWrongOrientationError();
err.setGeometryId("geomId");
ValidationResult result = new ValidationResult(); EdgeList edges = new EdgeList();
result.setResult(ResultType.ERROR); Edge edge = new Edge();
b.addGenericApplicationPropertyOfCityObject(result); edge.setFrom(new DirectPosition(1, 2, 3));
HoleOutside error = new HoleOutside(); edge.setTo(new DirectPosition(5, 6, 7));
error.setPolygonId("TestPolygon"); edges.getEdges().add(new EdgeProperty(edge));
error.setLinearRingId("TestRing1"); err.setEdges(new EdgeListProperty(edges));
result.getErrors().add(error); res.getErrors().add(new AbstractErrorProperty(err));
byte[] gml = writeCityGml(model); byte[] buf = writeModel(model);
model = readCityGml(gml); assertTrue(validate(new ByteArrayInputStream(buf)));
AbstractCityObject co = model.getCityObjectMember().get(0).getCityObject();
List<ADEComponent> ades = co.getGenericApplicationPropertyOfCityObject();
ADEComponent adeComponent = ades.get(0);
ValidationResult valRes = (ValidationResult) adeComponent;
assertEquals(ResultType.ERROR, valRes.getResult());
ValidationError valError = valRes.getErrors().get(0);
HoleOutside error2 = (HoleOutside) valError;
assertEquals(error.getPolygonId(), error2.getPolygonId());
assertEquals(error.getLinearRingId(), error2.getLinearRingId());
} }
@Test @Test
void testWritingInnerRingsNestedError() void testRingNotClosedError() throws ADEException, CityGMLContextException, CityGMLWriteException, SAXException, IOException, SchemaHandlerException {
throws ADEException, CityGMLBuilderException, CityGMLWriteException, CityGMLReadException { CityModel model = new CityModel();
CityModel model = new CityModel(); ValidationResult res = fillCityModel(model);
Building b = new Building();
model.getCityObjectMember().add(new CityObjectMember(b)); RingNotClosedError err = new RingNotClosedError();
err.setLinearRingId("ringId");
ValidationResult result = new ValidationResult(); res.getErrors().add(new AbstractErrorProperty(err));
result.setResult(ResultType.ERROR);
b.addGenericApplicationPropertyOfCityObject(result); byte[] buf = writeModel(model);
InnerRingsNested error = new InnerRingsNested(); assertTrue(validate(new ByteArrayInputStream(buf)));
error.setPolygonId("TestPolygon");
error.setLinearRingId1("TestRing1");
error.setLinearRingId2("TestRing2");
result.getErrors().add(error);
byte[] gml = writeCityGml(model);
model = readCityGml(gml);
AbstractCityObject co = model.getCityObjectMember().get(0).getCityObject();
List<ADEComponent> ades = co.getGenericApplicationPropertyOfCityObject();
ADEComponent adeComponent = ades.get(0);
ValidationResult valRes = (ValidationResult) adeComponent;
assertEquals(ResultType.ERROR, valRes.getResult());
ValidationError valError = valRes.getErrors().get(0);
InnerRingsNested error2 = (InnerRingsNested) valError;
assertEquals(error.getPolygonId(), error2.getPolygonId());
assertEquals(error.getLinearRingId1(), error2.getLinearRingId1());
assertEquals(error.getLinearRingId2(), error2.getLinearRingId2());
} }
@Test @Test
void testWritingNonPlanarDistancePlaneError() void testRingSelfIntersectionError() throws ADEException, CityGMLContextException, CityGMLWriteException, SAXException, IOException, SchemaHandlerException {
throws ADEException, CityGMLBuilderException, CityGMLWriteException, CityGMLReadException { CityModel model = new CityModel();
CityModel model = new CityModel(); ValidationResult res = fillCityModel(model);
Building b = new Building();
model.getCityObjectMember().add(new CityObjectMember(b)); RingSelfIntersectionError err = new RingSelfIntersectionError();
err.setLinearRingId("ringId");
ValidationResult result = new ValidationResult(); Edge edge = new Edge();
result.setResult(ResultType.ERROR); edge.setFrom(new DirectPosition(1, 2, 3));
b.addGenericApplicationPropertyOfCityObject(result); edge.setTo(new DirectPosition(5, 6, 7));
NonPlanarDistancePlane error = new NonPlanarDistancePlane(); err.setEdge1(new EdgeProperty(edge));
error.setPolygonId("TestPolygon"); err.setEdge2(new EdgeProperty(edge));
DirectPosition vertex = new DirectPosition(); err.setType(RingSelfIntType.EDGE_INTERSECTS_EDGE);
vertex.getValue().add(1.0); err.setVertex1(new DirectPosition(1, 2, 3));
error.setVertex(vertex); res.getErrors().add(new AbstractErrorProperty(err));
Length distance = new Length(0.1);
distance.setUom("m"); byte[] buf = writeModel(model);
error.setDistance(distance); assertTrue(validate(new ByteArrayInputStream(buf)));
result.getErrors().add(error);
byte[] gml = writeCityGml(model);
model = readCityGml(gml);
AbstractCityObject co = model.getCityObjectMember().get(0).getCityObject();
List<ADEComponent> ades = co.getGenericApplicationPropertyOfCityObject();
ADEComponent adeComponent = ades.get(0);
ValidationResult valRes = (ValidationResult) adeComponent;
assertEquals(ResultType.ERROR, valRes.getResult());
ValidationError valError = valRes.getErrors().get(0);
NonPlanarDistancePlane error2 = (NonPlanarDistancePlane) valError;
assertEquals(error.getPolygonId(), error2.getPolygonId());
assertEquals(error.getVertex().getValue().get(0), error2.getVertex().getValue().get(0), 0.00001);
assertEquals(error.getDistance().getValue(), error2.getDistance().getValue(), 0.00001);
} }
@Test @Test
void testWritingIntersectingRingsError() void testRingTooFewPointsError() throws ADEException, CityGMLContextException, CityGMLWriteException, SAXException, IOException, SchemaHandlerException {
throws ADEException, CityGMLBuilderException, CityGMLWriteException, CityGMLReadException { CityModel model = new CityModel();
CityModel model = new CityModel(); ValidationResult res = fillCityModel(model);
Building b = new Building();
model.getCityObjectMember().add(new CityObjectMember(b)); RingTooFewPointsError err = new RingTooFewPointsError();
err.setLinearRingId("ringId");
ValidationResult result = new ValidationResult(); res.getErrors().add(new AbstractErrorProperty(err));
result.setResult(ResultType.ERROR);
b.addGenericApplicationPropertyOfCityObject(result); byte[] buf = writeModel(model);
IntersectingRings error = new IntersectingRings(); assertTrue(validate(new ByteArrayInputStream(buf)));
error.setPolygonId("TestPolygon");
error.setLinearRingId1("TestRing1");
error.setLinearRingId2("TestRing2");
result.getErrors().add(error);
byte[] gml = writeCityGml(model);
model = readCityGml(gml);
AbstractCityObject co = model.getCityObjectMember().get(0).getCityObject();
List<ADEComponent> ades = co.getGenericApplicationPropertyOfCityObject();
ADEComponent adeComponent = ades.get(0);
ValidationResult valRes = (ValidationResult) adeComponent;
assertEquals(ResultType.ERROR, valRes.getResult());
ValidationError valError = valRes.getErrors().get(0);
IntersectingRings error2 = (IntersectingRings) valError;
assertEquals(error.getPolygonId(), error2.getPolygonId());
assertEquals(error.getLinearRingId1(), error2.getLinearRingId1());
assertEquals(error.getLinearRingId2(), error2.getLinearRingId2());
} }
@Test @Test
void testWritingInteriorDisconnectedError() void testSemanticAttributeMissingError() throws ADEException, CityGMLContextException, CityGMLWriteException, SAXException, IOException, SchemaHandlerException {
throws ADEException, CityGMLBuilderException, CityGMLWriteException, CityGMLReadException { CityModel model = new CityModel();
CityModel model = new CityModel(); ValidationResult res = fillCityModel(model);
Building b = new Building();
model.getCityObjectMember().add(new CityObjectMember(b)); SemanticAttributeMissingError err = new SemanticAttributeMissingError();
err.setAttributeName("attribute");
ValidationResult result = new ValidationResult(); err.setChildId("child");
result.setResult(ResultType.ERROR); err.setGeneric(true);
b.addGenericApplicationPropertyOfCityObject(result); res.getErrors().add(new AbstractErrorProperty(err));
InteriorDisconnected error = new InteriorDisconnected();
error.setPolygonId("TestPolygon"); byte[] buf = writeModel(model);
result.getErrors().add(error); assertTrue(validate(new ByteArrayInputStream(buf)));
byte[] gml = writeCityGml(model);
model = readCityGml(gml);
AbstractCityObject co = model.getCityObjectMember().get(0).getCityObject();
List<ADEComponent> ades = co.getGenericApplicationPropertyOfCityObject();
ADEComponent adeComponent = ades.get(0);
ValidationResult valRes = (ValidationResult) adeComponent;
assertEquals(ResultType.ERROR, valRes.getResult());
ValidationError valError = valRes.getErrors().get(0);
InteriorDisconnected error2 = (InteriorDisconnected) valError;
assertEquals(error.getPolygonId(), error2.getPolygonId());
} }
@Test @Test
void testWritingRingNotClosedError() void testSemanticAttributeWrongValueError() throws ADEException, CityGMLContextException, CityGMLWriteException, SAXException, IOException, SchemaHandlerException {
throws ADEException, CityGMLBuilderException, CityGMLWriteException, CityGMLReadException { CityModel model = new CityModel();
CityModel model = new CityModel(); ValidationResult res = fillCityModel(model);
Building b = new Building();
model.getCityObjectMember().add(new CityObjectMember(b)); SemanticAttributeWrongValueError err = new SemanticAttributeWrongValueError();
err.setAttributeName("attribute");
ValidationResult result = new ValidationResult(); err.setChildId("child");
result.setResult(ResultType.ERROR); err.setGeneric(true);
b.addGenericApplicationPropertyOfCityObject(result); res.getErrors().add(new AbstractErrorProperty(err));
RingNotClosed error = new RingNotClosed();
error.setLinearRingId("TestRing"); byte[] buf = writeModel(model);
result.getErrors().add(error); assertTrue(validate(new ByteArrayInputStream(buf)));
byte[] gml = writeCityGml(model);
model = readCityGml(gml);
AbstractCityObject co = model.getCityObjectMember().get(0).getCityObject();
List<ADEComponent> ades = co.getGenericApplicationPropertyOfCityObject();
ADEComponent adeComponent = ades.get(0);
ValidationResult valRes = (ValidationResult) adeComponent;
assertEquals(ResultType.ERROR, valRes.getResult());
ValidationError valError = valRes.getErrors().get(0);
RingNotClosed error2 = (RingNotClosed) valError;
assertEquals(error.getLinearRingId(), error2.getLinearRingId());
} }
@Test @Test
void testWritingTooFewPointsError() void testSolidNotClosedError() throws ADEException, CityGMLContextException, CityGMLWriteException, SAXException, IOException, SchemaHandlerException {
throws ADEException, CityGMLBuilderException, CityGMLWriteException, CityGMLReadException { CityModel model = new CityModel();
CityModel model = new CityModel(); ValidationResult res = fillCityModel(model);
Building b = new Building();
model.getCityObjectMember().add(new CityObjectMember(b)); SolidNotClosedError err = new SolidNotClosedError();
err.setGeometryId("geomId");
ValidationResult result = new ValidationResult(); EdgeList edges = new EdgeList();
result.setResult(ResultType.ERROR); Edge edge = new Edge();
b.addGenericApplicationPropertyOfCityObject(result); edge.setFrom(new DirectPosition(1, 2, 3));
TooFewPoints error = new TooFewPoints(); edge.setTo(new DirectPosition(5, 6, 7));
error.setLinearRingId("TestRing"); edges.getEdges().add(new EdgeProperty(edge));
result.getErrors().add(error); err.setEdges(new EdgeListProperty(edges));
res.getErrors().add(new AbstractErrorProperty(err));
byte[] gml = writeCityGml(model);
model = readCityGml(gml); byte[] buf = writeModel(model);
assertTrue(validate(new ByteArrayInputStream(buf)));
AbstractCityObject co = model.getCityObjectMember().get(0).getCityObject();
List<ADEComponent> ades = co.getGenericApplicationPropertyOfCityObject();
ADEComponent adeComponent = ades.get(0);
ValidationResult valRes = (ValidationResult) adeComponent;
assertEquals(ResultType.ERROR, valRes.getResult());
ValidationError valError = valRes.getErrors().get(0);
TooFewPoints error2 = (TooFewPoints) valError;
assertEquals(error.getLinearRingId(), error2.getLinearRingId());
} }
@Test @Test
void testWritingConsecutiveSameError() void testSolidSelfIntersectionError() throws ADEException, CityGMLContextException, CityGMLWriteException, SAXException, IOException, SchemaHandlerException {
throws ADEException, CityGMLBuilderException, CityGMLWriteException, CityGMLReadException { CityModel model = new CityModel();
CityModel model = new CityModel(); ValidationResult res = fillCityModel(model);
Building b = new Building();
model.getCityObjectMember().add(new CityObjectMember(b)); SolidSelfIntersectionError err = new SolidSelfIntersectionError();
err.setGeometryId("geomId");
ValidationResult result = new ValidationResult(); err.setPolygonId1("poly1");
result.setResult(ResultType.ERROR); err.setPolygonId2("poly2");
b.addGenericApplicationPropertyOfCityObject(result); res.getErrors().add(new AbstractErrorProperty(err));
ConsecutivePointsSame error = new ConsecutivePointsSame(); byte[] buf = writeModel(model);
error.setLinearRingId("TestRing"); assertTrue(validate(new ByteArrayInputStream(buf)));
DirectPosition vertex1 = new DirectPosition();
vertex1.getValue().add(10.0);
vertex1.getValue().add(5.0);
vertex1.getValue().add(7.0);
error.setVertex1(vertex1);
DirectPosition vertex2 = new DirectPosition();
vertex2.getValue().add(15.0);
vertex2.getValue().add(55.0);
vertex2.getValue().add(71.0);
error.setVertex2(vertex2);
result.getErrors().add(error);
byte[] gml = writeCityGml(model);
model = readCityGml(gml);
AbstractCityObject co = model.getCityObjectMember().get(0).getCityObject();
List<ADEComponent> ades = co.getGenericApplicationPropertyOfCityObject();
ADEComponent adeComponent = ades.get(0);
ValidationResult valRes = (ValidationResult) adeComponent;
assertEquals(ResultType.ERROR, valRes.getResult());
ValidationError valError = valRes.getErrors().get(0);
ConsecutivePointsSame error2 = (ConsecutivePointsSame) valError;
assertEquals(error.getLinearRingId(), error2.getLinearRingId());
assertEquals(error.getVertex1().getValue().get(0), error2.getVertex1().getValue().get(0));
assertEquals(error.getVertex2().getValue().get(0), error2.getVertex2().getValue().get(0));
} }
@Test @Test
void testWritingRingSelfIntersection() void testSolidTooFewPolygonsError() throws ADEException, CityGMLContextException, CityGMLWriteException, SAXException, IOException, SchemaHandlerException {
throws ADEException, CityGMLBuilderException, CityGMLWriteException, CityGMLReadException { CityModel model = new CityModel();
CityModel model = new CityModel(); ValidationResult res = fillCityModel(model);
Building b = new Building();
model.getCityObjectMember().add(new CityObjectMember(b)); SolidTooFewPolygonsError err = new SolidTooFewPolygonsError();
err.setGeometryId("geomId");
ValidationResult result = new ValidationResult(); res.getErrors().add(new AbstractErrorProperty(err));
result.setResult(ResultType.ERROR);
b.addGenericApplicationPropertyOfCityObject(result); byte[] buf = writeModel(model);
assertTrue(validate(new ByteArrayInputStream(buf)));
RingSelfIntersection error = new RingSelfIntersection();
error.setType(RingSelfIntType.DUPLICATE_POINT);
error.setLinearRingId("TestRing");
DirectPosition vertex1 = new DirectPosition();
vertex1.getValue().add(10.0);
vertex1.getValue().add(5.0);
vertex1.getValue().add(7.0);
error.setVertex1(vertex1);
DirectPosition vertex2 = new DirectPosition();
vertex2.getValue().add(15.0);
vertex2.getValue().add(55.0);
vertex2.getValue().add(71.0);
error.setVertex2(vertex2);
result.getErrors().add(error);
byte[] gml = writeCityGml(model);
model = readCityGml(gml);
AbstractCityObject co = model.getCityObjectMember().get(0).getCityObject();
List<ADEComponent> ades = co.getGenericApplicationPropertyOfCityObject();
ADEComponent adeComponent = ades.get(0);
ValidationResult valRes = (ValidationResult) adeComponent;
assertEquals(ResultType.ERROR, valRes.getResult());
ValidationError valError = valRes.getErrors().get(0);
RingSelfIntersection error2 = (RingSelfIntersection) valError;
assertEquals(error.getLinearRingId(), error2.getLinearRingId());
assertEquals(error.getVertex1().getValue().get(0), error2.getVertex1().getValue().get(0));
assertEquals(error.getVertex2().getValue().get(0), error2.getVertex2().getValue().get(0));
} }
private boolean validate(InputStream stream) throws SAXException, IOException, CityGMLContextException, SchemaHandlerException {
@Test CityGMLContext context = CityGMLContext.newInstance();
void testWritingValidationPlan()
throws ADEException, CityGMLBuilderException, CityGMLWriteException, CityGMLReadException {
CityModel model = new CityModel();
Validation val = new Validation();
model.addGenericApplicationPropertyOfCityModel(val);
ZonedDateTime expectedDate = LocalDateTime.of(2002, 5, 30, 9, 0).atZone(ZoneId.systemDefault());
val.setValidationDate(expectedDate);
val.setValidationSoftware("CityDoctor2");
ValidationPlan plan = new ValidationPlan();
val.setValidationPlan(plan);
Parameter roundingParameter = new Parameter();
roundingParameter.setName("numberOfRoundingPlaces");
roundingParameter.setValue("8");
plan.getGlobalParameters().add(roundingParameter);
Parameter minVertexDistance = new Parameter();
minVertexDistance.setName("minVertexDistance");
minVertexDistance.setValue("0.0001");
minVertexDistance.setUom("m");
plan.getGlobalParameters().add(minVertexDistance);
Requirement rTooFewPoints = new Requirement();
rTooFewPoints.setEnabled(true);
rTooFewPoints.setName(RequirementId.R_GE_R_TOO_FEW_POINTS);
plan.getRequirements().add(rTooFewPoints);
Checking buildingChecking = new Checking();
buildingChecking.setValue(TopLevelFeatureType.BUILDING);
plan.getFilter().add(buildingChecking);
Statistics statistics = new Statistics();
val.setStatistics(statistics);
FeatureStatistics numErrorBridgeObjects = new FeatureStatistics();
numErrorBridgeObjects.setNumChecked(0);
numErrorBridgeObjects.setNumErrors(0);
statistics.setNumErrorBridgeObjects(numErrorBridgeObjects);
FeatureStatistics numErrorBuildings = new FeatureStatistics();
numErrorBuildings.setNumChecked(1);
numErrorBuildings.setNumErrors(1);
statistics.setNumErrorBuildings(numErrorBuildings);
FeatureStatistics numErrors = new FeatureStatistics();
statistics.setNumErrorLandObjects(numErrors);
statistics.setNumErrorTransportation(numErrors);
statistics.setNumErrorVegetation(numErrors);
statistics.setNumErrorWaterObjects(numErrors);
ErrorStatistics stats1 = new ErrorStatistics(); CityGMLSchemaHandler schemaHandler = context.getDefaultSchemaHandler();
stats1.setAmount(1); Source[] schemas = schemaHandler.getSchemas();
stats1.setName(ErrorId.GE_R_CONSECUTIVE_POINTS_SAME);
statistics.getErrorStatistics().add(stats1);
byte[] gml = writeCityGml(model); SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
model = readCityGml(gml); Schema schema = schemaFactory.newSchema(schemas);
testValidationPlan(model); Validator validator = schema.newValidator();
} boolean[] foundErrors = new boolean[1];
foundErrors[0] = false;
private CityModel readCityGml(InputStream input) validator.setErrorHandler(new ErrorHandler() {
throws ADEException, CityGMLBuilderException, CityGMLReadException { @Override
CityGMLContext context = CityGMLContext.getInstance(); public void error(SAXParseException exception) {
List<ADEContext> adeContexts = context.getADEContexts(); String message = "[" + exception.getLineNumber() + ", " + exception.getColumnNumber() + "] "
if (adeContexts.isEmpty()) { + exception.getMessage();
for (ADEContext adeContext : ServiceLoader.load(ADEContext.class)) { System.out.println(message);
context.registerADEContext(adeContext); foundErrors[0] = true;
}
} }
CityGMLBuilder builder = context.createCityGMLBuilder(); @Override
CityGMLInputFactory in = builder.createCityGMLInputFactory(); public void warning(SAXParseException exception) {
in.setProperty(CityGMLInputFactory.USE_VALIDATION, true); error(exception);
in.setProperty(CityGMLInputFactory.FEATURE_READ_MODE, FeatureReadMode.NO_SPLIT);
in.setValidationEventHandler(event -> {
System.out.print(
"[" + event.getLocator().getLineNumber() + "," + event.getLocator().getColumnNumber() + "] ");
System.out.println(event.getMessage());
throw new IllegalStateException(event.getLinkedException());
});
try (CityGMLReader reader = in.createCityGMLReader("?", input)) {
while (reader.hasNext()) {
CityGML nextFeature = reader.nextFeature();
if (nextFeature instanceof CityModel) {
return (CityModel) nextFeature;
}
} }
}
throw new IllegalStateException("No CityModel found in GML file");
}
private CityModel readCityGml(File f) @Override
throws FileNotFoundException, ADEException, CityGMLBuilderException, CityGMLReadException { public void fatalError(SAXParseException exception) {
return readCityGml(new FileInputStream(f)); error(exception);
} }
});
private CityModel readCityGml(String fileName) Path file = Paths.get("test.gml");
throws FileNotFoundException, ADEException, CityGMLBuilderException, CityGMLReadException {
return readCityGml(new File(fileName));
}
private CityModel readCityGml(byte[] bytes) throws ADEException, CityGMLBuilderException, CityGMLReadException { validator.validate(new StreamSource(file.toFile()));
return readCityGml(new ByteArrayInputStream(bytes)); return !foundErrors[0];
} }
private void testValidationPlan(CityModel cityModel) { private byte[] writeModel(CityModel model) throws ADEException, CityGMLContextException, CityGMLWriteException {
assertFalse(cityModel.getGenericApplicationPropertyOfCityModel().isEmpty());
List<ADEComponent> ades = cityModel.getGenericApplicationPropertyOfCityModel();
ADEComponent adeComponent = ades.get(0);
assertTrue(adeComponent instanceof Validation);
Validation val = (Validation) adeComponent;
ZonedDateTime expectedDate = LocalDateTime.of(2002, 5, 30, 9, 0).atZone(ZoneId.systemDefault());
assertTrue(expectedDate.isEqual(val.getValidationDate()));
assertEquals("CityDoctor2", val.getValidationSoftware());
assertNotNull(val.getValidationPlan());
ValidationPlan plan = val.getValidationPlan();
assertNotNull(plan.getGlobalParameters());
assertFalse(plan.getGlobalParameters().isEmpty());
List<Parameter> globalParameters = plan.getGlobalParameters();
Parameter roundingParameter = globalParameters.get(0);
assertEquals("numberOfRoundingPlaces", roundingParameter.getName());
assertEquals("8", roundingParameter.getValue());
assertNull(roundingParameter.getUom());
Parameter minVertexDistance = globalParameters.get(1);
assertEquals("minVertexDistance", minVertexDistance.getName());
assertEquals("0.0001", minVertexDistance.getValue());
assertEquals("m", minVertexDistance.getUom());
assertNotNull(plan.getRequirements());
assertFalse(plan.getRequirements().isEmpty());
List<Requirement> requirements = plan.getRequirements();
Requirement rTooFewPoints = requirements.get(0);
assertEquals(RequirementId.R_GE_R_TOO_FEW_POINTS, rTooFewPoints.getName());
assertTrue(rTooFewPoints.isEnabled());
assertNotNull(plan.getFilter());
assertFalse(plan.getFilter().isEmpty());
List<Checking> filter = plan.getFilter();
Checking buildingChecking = filter.get(0);
assertEquals(TopLevelFeatureType.BUILDING, buildingChecking.getValue());
Statistics statistics = val.getStatistics();
assertNotNull(statistics);
FeatureStatistics numErrorBridgeObjects = statistics.getNumErrorBridgeObjects();
assertNotNull(numErrorBridgeObjects);
assertEquals(0, numErrorBridgeObjects.getNumChecked());
assertEquals(0, numErrorBridgeObjects.getNumErrors());
FeatureStatistics numErrorBuildings = statistics.getNumErrorBuildings();
assertEquals(1, numErrorBuildings.getNumChecked());
assertEquals(1, numErrorBuildings.getNumErrors());
List<ErrorStatistics> errorStatistics = statistics.getErrorStatistics(); CityGMLContext context = CityGMLContext.newInstance();
assertNotNull(errorStatistics); CityGMLVersion version = CityGMLVersion.v2_0;
assertFalse(errorStatistics.isEmpty()); CityGMLOutputFactory out = context.createCityGMLOutputFactory(version);
ErrorStatistics stats1 = errorStatistics.get(0); ByteArrayOutputStream outStream = new ByteArrayOutputStream();
assertEquals(ErrorId.GE_R_CONSECUTIVE_POINTS_SAME, stats1.getName()); try (CityGMLWriter writer = out.createCityGMLWriter(outStream, StandardCharsets.UTF_8.name())) {
assertEquals(1, stats1.getAmount()); writer.withIndent(" ")
.withSchemaLocation(QualityADEModule.NAMESPACE_URI, getClass().getResource("/qualityAde.xsd").toString())
.withDefaultPrefixes()
.withDefaultNamespace(CoreModule.of(version).getNamespaceURI())
.write(model);
}
return outStream.toByteArray();
} }
private byte[] writeCityGml(CityModel model) throws ADEException, CityGMLBuilderException, CityGMLWriteException { private ValidationResult fillCityModel(CityModel model) {
CityGMLContext context = CityGMLContext.getInstance(); Validation v = new Validation();
List<ADEContext> adeContexts = context.getADEContexts(); v.setId("planId");
if (adeContexts == null || adeContexts.isEmpty()) { model.getFeatureMembers().add(new AbstractFeatureProperty(v));
for (ADEContext adeContext : ServiceLoader.load(ADEContext.class)) { v.setValidationSoftware("testSoftware");
context.registerADEContext(adeContext); v.setValidationDate(ZonedDateTime.now());
} ValidationPlan plan = new ValidationPlan();
}
Statistics stats = new Statistics();
FeatureStatistics fStats = new FeatureStatistics();
fStats.setNumChecked(5);
fStats.setNumErrors(2);
stats.setNumErrorBridgeObjects(new FeatureStatisticsProperty(fStats));
v.setStatistics(new StatisticsProperty(stats));
Requirement req = new Requirement();
req.setEnabled(true);
req.setRequirementType(RequirementId.R_GE_P_HOLE_OUTSIDE);
plan.getRequirements().add(new RequirementProperty(req));
CityGMLBuilder builder = context.createCityGMLBuilder(); Checking checking = new Checking();
checking.setFeatureType(TopLevelFeatureType.BRIDGE);
Filter filter = new Filter();
filter.getChecking().add(new CheckingProperty(checking));
plan.setFilter(new FilterProperty(filter));
CityGMLOutputFactory outputFactory = builder.createCityGMLOutputFactory(CityGMLVersion.DEFAULT); Parameter param = new Parameter();
ByteArrayOutputStream out = new ByteArrayOutputStream(); param.setName("test");
try (CityGMLWriter writer = outputFactory.createCityGMLWriter(out)) { param.setUom("uom");
writer.setIndentString(" "); param.setValue("5");
writer.setPrefixes(CityGMLVersion.DEFAULT); GlobalParameters globalParams = new GlobalParameters();
writer.setPrefix("qual", QualityADEModule.NAMESPACE_URI); globalParams.getParameters().add(new ParameterProperty(param));
writer.setSchemaLocation(QualityADEModule.NAMESPACE_URI, plan.setGlobalParameters(new GlobalParametersProperty(globalParams));
QualityADEModule.NAMESPACE_URI + "/qualityAdeOld.xsd");
writer.setSchemaLocations(CityGMLVersion.DEFAULT);
writer.write(model);
return out.toByteArray();
}
} */
v.setValidationPlan(new ValidationPlanProperty(plan));
Building b = new Building();
b.setId("testId");
model.getCityObjectMembers().add(new AbstractCityObjectProperty(b));
CityObjectProperties props = new CityObjectProperties();
b.addADEProperty(props);
ValidationResult res = new ValidationResult();
props.setValidationResult(new ValidationResultProperty(res));
res.setResultType(ResultType.ERROR);
res.setValidationPlanID(new Reference(v));
return res;
}
} }
<?xml version="1.0" encoding="utf-8"?>
<core:CityModel xmlns:core="http://www.opengis.net/citygml/2.0" xmlns:gen="http://www.opengis.net/citygml/generics/2.0" xmlns:bldg="http://www.opengis.net/citygml/building/2.0" xmlns:app="http://www.opengis.net/citygml/appearance/2.0" xmlns:dem="http://www.opengis.net/citygml/relief/2.0" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:qual="https://transfer.hft-stuttgart.de/pages/citydoctor/qualityade/0.1.3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/citygml/building/2.0 http://schemas.opengis.net/citygml/building/2.0/building.xsd http://www.opengis.net/citygml/appearance/2.0 http://schemas.opengis.net/citygml/appearance/2.0/appearance.xsd http://www.opengis.net/citygml/relief/2.0 http://schemas.opengis.net/citygml/relief/2.0/relief.xsd http://www.opengis.net/citygml/2.0 http://schemas.opengis.net/citygml/2.0/cityGMLBase.xsd http://www.opengis.net/citygml/generics/2.0 http://schemas.opengis.net/citygml/generics/2.0/generics.xsd https://transfer.hft-stuttgart.de/pages/citydoctor/qualityade/0.1.3 https://transfer.hft-stuttgart.de/pages/citydoctor/qualityade/0.1.3/qualityAde.xsd">
<!--
Einfaches Gebäude mit Grundriss 3m x 5m und Satteldach, Traufhöhe 3m, Firsthöhe 4,5m
Modelliert mit Begrenzungsflächen (eine Dachfläche, 4 Wandflächen, 1 Grundfläche),
die Gebäudegeometrie als Solid, der auf die Polygone der Begrenzungsflächen referenziert
CityGML 2.0
linear ring _Simple_BD.1_PG.6_LR.1 beinhaltet zwei aufeinander folgende Punkte, die identisch sind.
10.5.2017
Author: V. Coors, HFT Stuttgart
Lizenz:
-->
<core:cityObjectMember>
<bldg:Building gml:id="_Simple_BD.1">
<qual:validationResult result="ERROR">
<qual:GE_S_ALL_POLYGONS_WRONG_ORIENTATION>
<qual:geometryId>_Simple_BD.1_Geom1</qual:geometryId>
</qual:GE_S_ALL_POLYGONS_WRONG_ORIENTATION>
</qual:validationResult>
<bldg:lod2Solid>
<gml:Solid gml:id="_Simple_BD.1_Geom1">
<gml:exterior>
<gml:CompositeSurface>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.1"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.2"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.3"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.4"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.5"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.6"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.7"/>
</gml:CompositeSurface>
</gml:exterior>
</gml:Solid>
</bldg:lod2Solid>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.2">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.2_LR.1">
<gml:posList srsDimension="3">
13.0 15.0 0.0
13.0 15.0 3.0
13.0 10.0 3.0
13.0 10.0 0.0
13.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_2">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.3">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.3_LR.1">
<gml:posList srsDimension="3">
10.0 15.0 0.0
10.0 15.0 3.0
11.5 15.0 4.5
13.0 15.0 3.0
13.0 15.0 0.0
10.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_3">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.4">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.4_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 3.0
10.0 15.0 3.0
10.0 15.0 0.0
10.0 10.0 0.0
10.0 10.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_4">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.5">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.5_LR.1">
<gml:posList srsDimension="3">
13.0 10.0 0.0
13.0 10.0 3.0
11.5 10.0 4.5
10.0 10.0 3.0
10.0 10.0 0.0
13.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:RoofSurface gml:id="_Simple_BD.1_RoofSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.6">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.6_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 3.0
11.5 10.0 4.5
11.5 10.0 4.5
11.5 15.0 4.5
10.0 15.0 3.0
10.0 10.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.7">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.7_LR.1">
<gml:posList srsDimension="3">
11.5 10.0 4.5
13.0 10.0 3.0
13.0 15.0 3.0
11.5 15.0 4.5
11.5 10.0 4.5
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:RoofSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:GroundSurface gml:id="_Simple_BD.1_GroundSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.1">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.1_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 0.0
10.0 15.0 0.0
13.0 15.0 0.0
13.0 10.0 0.0
10.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:GroundSurface>
</bldg:boundedBy>
</bldg:Building>
</core:cityObjectMember>
<qual:validation>
<qual:validationDate>2002-05-30T09:00:00</qual:validationDate>
<qual:validationSoftware>CityDoctor2</qual:validationSoftware>
<qual:validationPlan>
<qual:globalParameters>
<qual:parameter name="numberOfRoundingPlaces">8</qual:parameter>
<qual:parameter name="minVertexDistance" uom="m">0.0001</qual:parameter>
<qual:parameter name="schematronFile"></qual:parameter>
</qual:globalParameters>
<qual:requirement name="R_GE_R_TOO_FEW_POINTS" enabled="true"/>
<qual:requirement name="R_GE_R_NOT_CLOSED" enabled="true"/>
<qual:requirement name="R_GE_R_CONSECUTIVE_POINTS_SAME" enabled="true"/>
<qual:requirement name="R_GE_R_SELF_INTERSECTION" enabled="true"/>
<qual:requirement name="R_GE_R_NOT_CLOSED" enabled="true"/>
<qual:requirement name="R_GE_P_NON_PLANAR" enabled="true">
<qual:parameter name="type">distance</qual:parameter>
<qual:parameter name="distanceTolerance" uom="m">0.01</qual:parameter>
<qual:parameter name="angleTolerance" uom="deg">1</qual:parameter>
<qual:parameter name="degeneratedPolygonTolerance" uom="m">0.0000</qual:parameter>
</qual:requirement>
<qual:requirement name="R_GE_P_INTERIOR_DISCONNECTED" enabled="true"/>
<qual:requirement name="R_GE_P_INTERSECTING_RINGS" enabled="true"/>
<qual:requirement name="R_GE_P_HOLE_OUTSIDE" enabled="true"/>
<qual:requirement name="R_GE_P_ORIENTATION_RINGS_SAME" enabled="true"/>
<qual:requirement name="R_GE_P_INNER_RINGS_NESTED" enabled="true"/>
<qual:requirement name="R_GE_S_TOO_FEW_POLYGONS" enabled="true"/>
<qual:requirement name="R_GE_S_NOT_CLOSED" enabled="true"/>
<qual:requirement name="R_GE_S_NON_MANIFOLD_EDGE" enabled="true"/>
<qual:requirement name="R_GE_S_POLYGON_WRONG_ORIENTATION" enabled="true"/>
<qual:requirement name="R_GE_S_ALL_POLYGONS_WRONG_ORIENTATION" enabled="true"/>
<qual:requirement name="R_GE_S_NON_MANIFOLD_VERTEX" enabled="true"/>
<qual:requirement name="R_GE_S_SELF_INTERSECTION" enabled="true"/>
<qual:requirement name="R_GE_S_MULTIPLE_CONNECTED_COMPONENTS" enabled="true"/>
<qual:filter>
<qual:checking>BUILDING</qual:checking>
<qual:checking>TRANSPORTATION</qual:checking>
<qual:checking>VEGETATION</qual:checking>
<qual:checking>BRIDGE</qual:checking>
<qual:checking>WATER</qual:checking>
<qual:checking>LAND</qual:checking>
</qual:filter>
</qual:validationPlan>
<qual:statistics>
<qual:numErrorBuildings numChecked="1">1</qual:numErrorBuildings>
<qual:numErrorVegetation numChecked="0">0</qual:numErrorVegetation>
<qual:numErrorLandObjects numChecked="0">0</qual:numErrorLandObjects>
<qual:numErrorBridgeObjects numChecked="0">0</qual:numErrorBridgeObjects>
<qual:numErrorWaterObjects numChecked="0">0</qual:numErrorWaterObjects>
<qual:numErrorTransportation numChecked="0">0</qual:numErrorTransportation>
<qual:errorStatistics>
<qual:error name="GE_R_CONSECUTIVE_POINTS_SAME">1</qual:error>
</qual:errorStatistics>
</qual:statistics>
</qual:validation>
</core:CityModel>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<core:CityModel xmlns:core="http://www.opengis.net/citygml/2.0" xmlns:gen="http://www.opengis.net/citygml/generics/2.0" xmlns:bldg="http://www.opengis.net/citygml/building/2.0" xmlns:app="http://www.opengis.net/citygml/appearance/2.0" xmlns:dem="http://www.opengis.net/citygml/relief/2.0" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:qual="https://transfer.hft-stuttgart.de/pages/citydoctor/qualityade/0.1.3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/citygml/building/2.0 http://schemas.opengis.net/citygml/building/2.0/building.xsd http://www.opengis.net/citygml/appearance/2.0 http://schemas.opengis.net/citygml/appearance/2.0/appearance.xsd http://www.opengis.net/citygml/relief/2.0 http://schemas.opengis.net/citygml/relief/2.0/relief.xsd http://www.opengis.net/citygml/2.0 http://schemas.opengis.net/citygml/2.0/cityGMLBase.xsd http://www.opengis.net/citygml/generics/2.0 http://schemas.opengis.net/citygml/generics/2.0/generics.xsd https://transfer.hft-stuttgart.de/pages/citydoctor/qualityade/0.1.3 https://transfer.hft-stuttgart.de/pages/citydoctor/qualityade/0.1.3/qualityAde.xsd">
<!--
Einfaches Gebäude mit Grundriss 3m x 5m und Satteldach, Traufhöhe 3m, Firsthöhe 4,5m
Modelliert mit Begrenzungsflächen (eine Dachfläche, 4 Wandflächen, 1 Grundfläche),
die Gebäudegeometrie als Solid, der auf die Polygone der Begrenzungsflächen referenziert
CityGML 2.0
linear ring _Simple_BD.1_PG.6_LR.1 beinhaltet zwei aufeinander folgende Punkte, die identisch sind.
10.5.2017
Author: V. Coors, HFT Stuttgart
Lizenz:
-->
<core:cityObjectMember>
<bldg:Building gml:id="_Simple_BD.1">
<qual:validationResult result="ERROR">
<qual:GE_P_HOLE_OUTSIDE>
<qual:polygonId>_Simple_BD.1_PG.1</qual:polygonId>
<qual:linearRingId>_Simple_BD.1_PG.1_Ring1</qual:linearRingId>
</qual:GE_P_HOLE_OUTSIDE>
</qual:validationResult>
<bldg:lod2Solid>
<gml:Solid>
<gml:exterior>
<gml:CompositeSurface>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.1"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.2"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.3"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.4"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.5"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.6"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.7"/>
</gml:CompositeSurface>
</gml:exterior>
</gml:Solid>
</bldg:lod2Solid>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.2">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.2_LR.1">
<gml:posList srsDimension="3">
13.0 15.0 0.0
13.0 15.0 3.0
13.0 10.0 3.0
13.0 10.0 0.0
13.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_2">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.3">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.3_LR.1">
<gml:posList srsDimension="3">
10.0 15.0 0.0
10.0 15.0 3.0
11.5 15.0 4.5
13.0 15.0 3.0
13.0 15.0 0.0
10.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_3">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.4">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.4_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 3.0
10.0 15.0 3.0
10.0 15.0 0.0
10.0 10.0 0.0
10.0 10.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_4">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.5">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.5_LR.1">
<gml:posList srsDimension="3">
13.0 10.0 0.0
13.0 10.0 3.0
11.5 10.0 4.5
10.0 10.0 3.0
10.0 10.0 0.0
13.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:RoofSurface gml:id="_Simple_BD.1_RoofSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.6">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.6_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 3.0
11.5 10.0 4.5
11.5 10.0 4.5
11.5 15.0 4.5
10.0 15.0 3.0
10.0 10.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.7">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.7_LR.1">
<gml:posList srsDimension="3">
11.5 10.0 4.5
13.0 10.0 3.0
13.0 15.0 3.0
11.5 15.0 4.5
11.5 10.0 4.5
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:RoofSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:GroundSurface gml:id="_Simple_BD.1_GroundSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.1">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.1_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 0.0
10.0 15.0 0.0
13.0 15.0 0.0
13.0 10.0 0.0
10.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:GroundSurface>
</bldg:boundedBy>
</bldg:Building>
</core:cityObjectMember>
<qual:validation>
<qual:validationDate>2002-05-30T09:00:00</qual:validationDate>
<qual:validationSoftware>CityDoctor2</qual:validationSoftware>
<qual:validationPlan>
<qual:globalParameters>
<qual:parameter name="numberOfRoundingPlaces">8</qual:parameter>
<qual:parameter name="minVertexDistance" uom="m">0.0001</qual:parameter>
<qual:parameter name="schematronFile"></qual:parameter>
</qual:globalParameters>
<qual:requirement name="R_GE_R_TOO_FEW_POINTS" enabled="true"/>
<qual:requirement name="R_GE_R_NOT_CLOSED" enabled="true"/>
<qual:requirement name="R_GE_R_CONSECUTIVE_POINTS_SAME" enabled="true"/>
<qual:requirement name="R_GE_R_SELF_INTERSECTION" enabled="true"/>
<qual:requirement name="R_GE_R_NOT_CLOSED" enabled="true"/>
<qual:requirement name="R_GE_P_NON_PLANAR" enabled="true">
<qual:parameter name="type">distance</qual:parameter>
<qual:parameter name="distanceTolerance" uom="m">0.01</qual:parameter>
<qual:parameter name="angleTolerance" uom="deg">1</qual:parameter>
<qual:parameter name="degeneratedPolygonTolerance" uom="m">0.0000</qual:parameter>
</qual:requirement>
<qual:requirement name="R_GE_P_INTERIOR_DISCONNECTED" enabled="true"/>
<qual:requirement name="R_GE_P_INTERSECTING_RINGS" enabled="true"/>
<qual:requirement name="R_GE_P_HOLE_OUTSIDE" enabled="true"/>
<qual:requirement name="R_GE_P_ORIENTATION_RINGS_SAME" enabled="true"/>
<qual:requirement name="R_GE_P_INNER_RINGS_NESTED" enabled="true"/>
<qual:requirement name="R_GE_S_TOO_FEW_POLYGONS" enabled="true"/>
<qual:requirement name="R_GE_S_NOT_CLOSED" enabled="true"/>
<qual:requirement name="R_GE_S_NON_MANIFOLD_EDGE" enabled="true"/>
<qual:requirement name="R_GE_S_POLYGON_WRONG_ORIENTATION" enabled="true"/>
<qual:requirement name="R_GE_S_ALL_POLYGONS_WRONG_ORIENTATION" enabled="true"/>
<qual:requirement name="R_GE_S_NON_MANIFOLD_VERTEX" enabled="true"/>
<qual:requirement name="R_GE_S_SELF_INTERSECTION" enabled="true"/>
<qual:requirement name="R_GE_S_MULTIPLE_CONNECTED_COMPONENTS" enabled="true"/>
<qual:filter>
<qual:checking>BUILDING</qual:checking>
<qual:checking>TRANSPORTATION</qual:checking>
<qual:checking>VEGETATION</qual:checking>
<qual:checking>BRIDGE</qual:checking>
<qual:checking>WATER</qual:checking>
<qual:checking>LAND</qual:checking>
</qual:filter>
</qual:validationPlan>
<qual:statistics>
<qual:numErrorBuildings numChecked="1">1</qual:numErrorBuildings>
<qual:numErrorVegetation numChecked="0">0</qual:numErrorVegetation>
<qual:numErrorLandObjects numChecked="0">0</qual:numErrorLandObjects>
<qual:numErrorBridgeObjects numChecked="0">0</qual:numErrorBridgeObjects>
<qual:numErrorWaterObjects numChecked="0">0</qual:numErrorWaterObjects>
<qual:numErrorTransportation numChecked="0">0</qual:numErrorTransportation>
<qual:errorStatistics>
<qual:error name="GE_R_CONSECUTIVE_POINTS_SAME">1</qual:error>
</qual:errorStatistics>
</qual:statistics>
</qual:validation>
</core:CityModel>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<core:CityModel xmlns:core="http://www.opengis.net/citygml/2.0" xmlns:gen="http://www.opengis.net/citygml/generics/2.0" xmlns:bldg="http://www.opengis.net/citygml/building/2.0" xmlns:app="http://www.opengis.net/citygml/appearance/2.0" xmlns:dem="http://www.opengis.net/citygml/relief/2.0" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:qual="https://transfer.hft-stuttgart.de/pages/citydoctor/qualityade/0.1.3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/citygml/building/2.0 http://schemas.opengis.net/citygml/building/2.0/building.xsd http://www.opengis.net/citygml/appearance/2.0 http://schemas.opengis.net/citygml/appearance/2.0/appearance.xsd http://www.opengis.net/citygml/relief/2.0 http://schemas.opengis.net/citygml/relief/2.0/relief.xsd http://www.opengis.net/citygml/2.0 http://schemas.opengis.net/citygml/2.0/cityGMLBase.xsd http://www.opengis.net/citygml/generics/2.0 http://schemas.opengis.net/citygml/generics/2.0/generics.xsd https://transfer.hft-stuttgart.de/pages/citydoctor/qualityade/0.1.3 https://transfer.hft-stuttgart.de/pages/citydoctor/qualityade/0.1.3/qualityAde.xsd">
<!--
Einfaches Gebäude mit Grundriss 3m x 5m und Satteldach, Traufhöhe 3m, Firsthöhe 4,5m
Modelliert mit Begrenzungsflächen (eine Dachfläche, 4 Wandflächen, 1 Grundfläche),
die Gebäudegeometrie als Solid, der auf die Polygone der Begrenzungsflächen referenziert
CityGML 2.0
linear ring _Simple_BD.1_PG.6_LR.1 beinhaltet zwei aufeinander folgende Punkte, die identisch sind.
10.5.2017
Author: V. Coors, HFT Stuttgart
Lizenz:
-->
<core:cityObjectMember>
<bldg:Building gml:id="_Simple_BD.1">
<qual:validationResult result="ERROR">
<qual:GE_P_INNER_RINGS_NESTED>
<qual:polygonId>_Simple_BD.1_PG.1</qual:polygonId>
<qual:linearRingId1>_Simple_BD.1_PG.1_Ring1</qual:linearRingId1>
<qual:linearRingId2>_Simple_BD.1_PG.1_Ring2</qual:linearRingId2>
</qual:GE_P_INNER_RINGS_NESTED>
</qual:validationResult>
<bldg:lod2Solid>
<gml:Solid>
<gml:exterior>
<gml:CompositeSurface>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.1"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.2"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.3"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.4"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.5"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.6"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.7"/>
</gml:CompositeSurface>
</gml:exterior>
</gml:Solid>
</bldg:lod2Solid>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.2">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.2_LR.1">
<gml:posList srsDimension="3">
13.0 15.0 0.0
13.0 15.0 3.0
13.0 10.0 3.0
13.0 10.0 0.0
13.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_2">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.3">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.3_LR.1">
<gml:posList srsDimension="3">
10.0 15.0 0.0
10.0 15.0 3.0
11.5 15.0 4.5
13.0 15.0 3.0
13.0 15.0 0.0
10.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_3">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.4">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.4_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 3.0
10.0 15.0 3.0
10.0 15.0 0.0
10.0 10.0 0.0
10.0 10.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_4">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.5">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.5_LR.1">
<gml:posList srsDimension="3">
13.0 10.0 0.0
13.0 10.0 3.0
11.5 10.0 4.5
10.0 10.0 3.0
10.0 10.0 0.0
13.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:RoofSurface gml:id="_Simple_BD.1_RoofSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.6">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.6_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 3.0
11.5 10.0 4.5
11.5 10.0 4.5
11.5 15.0 4.5
10.0 15.0 3.0
10.0 10.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.7">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.7_LR.1">
<gml:posList srsDimension="3">
11.5 10.0 4.5
13.0 10.0 3.0
13.0 15.0 3.0
11.5 15.0 4.5
11.5 10.0 4.5
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:RoofSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:GroundSurface gml:id="_Simple_BD.1_GroundSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.1">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.1_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 0.0
10.0 15.0 0.0
13.0 15.0 0.0
13.0 10.0 0.0
10.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:GroundSurface>
</bldg:boundedBy>
</bldg:Building>
</core:cityObjectMember>
<qual:validation>
<qual:validationDate>2002-05-30T09:00:00</qual:validationDate>
<qual:validationSoftware>CityDoctor2</qual:validationSoftware>
<qual:validationPlan>
<qual:globalParameters>
<qual:parameter name="numberOfRoundingPlaces">8</qual:parameter>
<qual:parameter name="minVertexDistance" uom="m">0.0001</qual:parameter>
<qual:parameter name="schematronFile"></qual:parameter>
</qual:globalParameters>
<qual:requirement name="R_GE_R_TOO_FEW_POINTS" enabled="true"/>
<qual:requirement name="R_GE_R_NOT_CLOSED" enabled="true"/>
<qual:requirement name="R_GE_R_CONSECUTIVE_POINTS_SAME" enabled="true"/>
<qual:requirement name="R_GE_R_SELF_INTERSECTION" enabled="true"/>
<qual:requirement name="R_GE_R_NOT_CLOSED" enabled="true"/>
<qual:requirement name="R_GE_P_NON_PLANAR" enabled="true">
<qual:parameter name="type">distance</qual:parameter>
<qual:parameter name="distanceTolerance" uom="m">0.01</qual:parameter>
<qual:parameter name="angleTolerance" uom="deg">1</qual:parameter>
<qual:parameter name="degeneratedPolygonTolerance" uom="m">0.0000</qual:parameter>
</qual:requirement>
<qual:requirement name="R_GE_P_INTERIOR_DISCONNECTED" enabled="true"/>
<qual:requirement name="R_GE_P_INTERSECTING_RINGS" enabled="true"/>
<qual:requirement name="R_GE_P_HOLE_OUTSIDE" enabled="true"/>
<qual:requirement name="R_GE_P_ORIENTATION_RINGS_SAME" enabled="true"/>
<qual:requirement name="R_GE_P_INNER_RINGS_NESTED" enabled="true"/>
<qual:requirement name="R_GE_S_TOO_FEW_POLYGONS" enabled="true"/>
<qual:requirement name="R_GE_S_NOT_CLOSED" enabled="true"/>
<qual:requirement name="R_GE_S_NON_MANIFOLD_EDGE" enabled="true"/>
<qual:requirement name="R_GE_S_POLYGON_WRONG_ORIENTATION" enabled="true"/>
<qual:requirement name="R_GE_S_ALL_POLYGONS_WRONG_ORIENTATION" enabled="true"/>
<qual:requirement name="R_GE_S_NON_MANIFOLD_VERTEX" enabled="true"/>
<qual:requirement name="R_GE_S_SELF_INTERSECTION" enabled="true"/>
<qual:requirement name="R_GE_S_MULTIPLE_CONNECTED_COMPONENTS" enabled="true"/>
<qual:filter>
<qual:checking>BUILDING</qual:checking>
<qual:checking>TRANSPORTATION</qual:checking>
<qual:checking>VEGETATION</qual:checking>
<qual:checking>BRIDGE</qual:checking>
<qual:checking>WATER</qual:checking>
<qual:checking>LAND</qual:checking>
</qual:filter>
</qual:validationPlan>
<qual:statistics>
<qual:numErrorBuildings numChecked="1">1</qual:numErrorBuildings>
<qual:numErrorVegetation numChecked="0">0</qual:numErrorVegetation>
<qual:numErrorLandObjects numChecked="0">0</qual:numErrorLandObjects>
<qual:numErrorBridgeObjects numChecked="0">0</qual:numErrorBridgeObjects>
<qual:numErrorWaterObjects numChecked="0">0</qual:numErrorWaterObjects>
<qual:numErrorTransportation numChecked="0">0</qual:numErrorTransportation>
<qual:errorStatistics>
<qual:error name="GE_R_CONSECUTIVE_POINTS_SAME">1</qual:error>
</qual:errorStatistics>
</qual:statistics>
</qual:validation>
</core:CityModel>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<core:CityModel xmlns:core="http://www.opengis.net/citygml/2.0" xmlns:gen="http://www.opengis.net/citygml/generics/2.0" xmlns:bldg="http://www.opengis.net/citygml/building/2.0" xmlns:app="http://www.opengis.net/citygml/appearance/2.0" xmlns:dem="http://www.opengis.net/citygml/relief/2.0" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:qual="https://transfer.hft-stuttgart.de/pages/citydoctor/qualityade/0.1.3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/citygml/building/2.0 http://schemas.opengis.net/citygml/building/2.0/building.xsd http://www.opengis.net/citygml/appearance/2.0 http://schemas.opengis.net/citygml/appearance/2.0/appearance.xsd http://www.opengis.net/citygml/relief/2.0 http://schemas.opengis.net/citygml/relief/2.0/relief.xsd http://www.opengis.net/citygml/2.0 http://schemas.opengis.net/citygml/2.0/cityGMLBase.xsd http://www.opengis.net/citygml/generics/2.0 http://schemas.opengis.net/citygml/generics/2.0/generics.xsd https://transfer.hft-stuttgart.de/pages/citydoctor/qualityade/0.1.3 https://transfer.hft-stuttgart.de/pages/citydoctor/qualityade/0.1.3/qualityAde.xsd">
<!--
Einfaches Gebäude mit Grundriss 3m x 5m und Satteldach, Traufhöhe 3m, Firsthöhe 4,5m
Modelliert mit Begrenzungsflächen (eine Dachfläche, 4 Wandflächen, 1 Grundfläche),
die Gebäudegeometrie als Solid, der auf die Polygone der Begrenzungsflächen referenziert
CityGML 2.0
linear ring _Simple_BD.1_PG.6_LR.1 beinhaltet zwei aufeinander folgende Punkte, die identisch sind.
10.5.2017
Author: V. Coors, HFT Stuttgart
Lizenz:
-->
<core:cityObjectMember>
<bldg:Building gml:id="_Simple_BD.1">
<qual:validationResult result="ERROR">
<qual:GE_P_INTERIOR_DISCONNECTED>
<qual:polygonId>_Simple_BD.1_PG.1</qual:polygonId>
</qual:GE_P_INTERIOR_DISCONNECTED>
</qual:validationResult>
<bldg:lod2Solid>
<gml:Solid>
<gml:exterior>
<gml:CompositeSurface>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.1"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.2"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.3"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.4"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.5"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.6"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.7"/>
</gml:CompositeSurface>
</gml:exterior>
</gml:Solid>
</bldg:lod2Solid>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.2">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.2_LR.1">
<gml:posList srsDimension="3">
13.0 15.0 0.0
13.0 15.0 3.0
13.0 10.0 3.0
13.0 10.0 0.0
13.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_2">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.3">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.3_LR.1">
<gml:posList srsDimension="3">
10.0 15.0 0.0
10.0 15.0 3.0
11.5 15.0 4.5
13.0 15.0 3.0
13.0 15.0 0.0
10.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_3">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.4">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.4_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 3.0
10.0 15.0 3.0
10.0 15.0 0.0
10.0 10.0 0.0
10.0 10.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_4">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.5">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.5_LR.1">
<gml:posList srsDimension="3">
13.0 10.0 0.0
13.0 10.0 3.0
11.5 10.0 4.5
10.0 10.0 3.0
10.0 10.0 0.0
13.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:RoofSurface gml:id="_Simple_BD.1_RoofSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.6">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.6_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 3.0
11.5 10.0 4.5
11.5 10.0 4.5
11.5 15.0 4.5
10.0 15.0 3.0
10.0 10.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.7">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.7_LR.1">
<gml:posList srsDimension="3">
11.5 10.0 4.5
13.0 10.0 3.0
13.0 15.0 3.0
11.5 15.0 4.5
11.5 10.0 4.5
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:RoofSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:GroundSurface gml:id="_Simple_BD.1_GroundSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.1">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.1_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 0.0
10.0 15.0 0.0
13.0 15.0 0.0
13.0 10.0 0.0
10.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:GroundSurface>
</bldg:boundedBy>
</bldg:Building>
</core:cityObjectMember>
<qual:validation>
<qual:validationDate>2002-05-30T09:00:00</qual:validationDate>
<qual:validationSoftware>CityDoctor2</qual:validationSoftware>
<qual:validationPlan>
<qual:globalParameters>
<qual:parameter name="numberOfRoundingPlaces">8</qual:parameter>
<qual:parameter name="minVertexDistance" uom="m">0.0001</qual:parameter>
<qual:parameter name="schematronFile"></qual:parameter>
</qual:globalParameters>
<qual:requirement name="R_GE_R_TOO_FEW_POINTS" enabled="true"/>
<qual:requirement name="R_GE_R_NOT_CLOSED" enabled="true"/>
<qual:requirement name="R_GE_R_CONSECUTIVE_POINTS_SAME" enabled="true"/>
<qual:requirement name="R_GE_R_SELF_INTERSECTION" enabled="true"/>
<qual:requirement name="R_GE_R_NOT_CLOSED" enabled="true"/>
<qual:requirement name="R_GE_P_NON_PLANAR" enabled="true">
<qual:parameter name="type">distance</qual:parameter>
<qual:parameter name="distanceTolerance" uom="m">0.01</qual:parameter>
<qual:parameter name="angleTolerance" uom="deg">1</qual:parameter>
<qual:parameter name="degeneratedPolygonTolerance" uom="m">0.0000</qual:parameter>
</qual:requirement>
<qual:requirement name="R_GE_P_INTERIOR_DISCONNECTED" enabled="true"/>
<qual:requirement name="R_GE_P_INTERSECTING_RINGS" enabled="true"/>
<qual:requirement name="R_GE_P_HOLE_OUTSIDE" enabled="true"/>
<qual:requirement name="R_GE_P_ORIENTATION_RINGS_SAME" enabled="true"/>
<qual:requirement name="R_GE_P_INNER_RINGS_NESTED" enabled="true"/>
<qual:requirement name="R_GE_S_TOO_FEW_POLYGONS" enabled="true"/>
<qual:requirement name="R_GE_S_NOT_CLOSED" enabled="true"/>
<qual:requirement name="R_GE_S_NON_MANIFOLD_EDGE" enabled="true"/>
<qual:requirement name="R_GE_S_POLYGON_WRONG_ORIENTATION" enabled="true"/>
<qual:requirement name="R_GE_S_ALL_POLYGONS_WRONG_ORIENTATION" enabled="true"/>
<qual:requirement name="R_GE_S_NON_MANIFOLD_VERTEX" enabled="true"/>
<qual:requirement name="R_GE_S_SELF_INTERSECTION" enabled="true"/>
<qual:requirement name="R_GE_S_MULTIPLE_CONNECTED_COMPONENTS" enabled="true"/>
<qual:filter>
<qual:checking>BUILDING</qual:checking>
<qual:checking>TRANSPORTATION</qual:checking>
<qual:checking>VEGETATION</qual:checking>
<qual:checking>BRIDGE</qual:checking>
<qual:checking>WATER</qual:checking>
<qual:checking>LAND</qual:checking>
</qual:filter>
</qual:validationPlan>
<qual:statistics>
<qual:numErrorBuildings numChecked="1">1</qual:numErrorBuildings>
<qual:numErrorVegetation numChecked="0">0</qual:numErrorVegetation>
<qual:numErrorLandObjects numChecked="0">0</qual:numErrorLandObjects>
<qual:numErrorBridgeObjects numChecked="0">0</qual:numErrorBridgeObjects>
<qual:numErrorWaterObjects numChecked="0">0</qual:numErrorWaterObjects>
<qual:numErrorTransportation numChecked="0">0</qual:numErrorTransportation>
<qual:errorStatistics>
<qual:error name="GE_R_CONSECUTIVE_POINTS_SAME">1</qual:error>
</qual:errorStatistics>
</qual:statistics>
</qual:validation>
</core:CityModel>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<core:CityModel xmlns:core="http://www.opengis.net/citygml/2.0" xmlns:gen="http://www.opengis.net/citygml/generics/2.0" xmlns:bldg="http://www.opengis.net/citygml/building/2.0" xmlns:app="http://www.opengis.net/citygml/appearance/2.0" xmlns:dem="http://www.opengis.net/citygml/relief/2.0" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:qual="https://transfer.hft-stuttgart.de/pages/citydoctor/qualityade/0.1.3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/citygml/building/2.0 http://schemas.opengis.net/citygml/building/2.0/building.xsd http://www.opengis.net/citygml/appearance/2.0 http://schemas.opengis.net/citygml/appearance/2.0/appearance.xsd http://www.opengis.net/citygml/relief/2.0 http://schemas.opengis.net/citygml/relief/2.0/relief.xsd http://www.opengis.net/citygml/2.0 http://schemas.opengis.net/citygml/2.0/cityGMLBase.xsd http://www.opengis.net/citygml/generics/2.0 http://schemas.opengis.net/citygml/generics/2.0/generics.xsd https://transfer.hft-stuttgart.de/pages/citydoctor/qualityade/0.1.3 https://transfer.hft-stuttgart.de/pages/citydoctor/qualityade/0.1.3/qualityAde.xsd">
<!--
Einfaches Gebäude mit Grundriss 3m x 5m und Satteldach, Traufhöhe 3m, Firsthöhe 4,5m
Modelliert mit Begrenzungsflächen (eine Dachfläche, 4 Wandflächen, 1 Grundfläche),
die Gebäudegeometrie als Solid, der auf die Polygone der Begrenzungsflächen referenziert
CityGML 2.0
linear ring _Simple_BD.1_PG.6_LR.1 beinhaltet zwei aufeinander folgende Punkte, die identisch sind.
10.5.2017
Author: V. Coors, HFT Stuttgart
Lizenz:
-->
<core:cityObjectMember>
<bldg:Building gml:id="_Simple_BD.1">
<qual:validationResult result="ERROR">
<qual:GE_P_INTERSECTING_RINGS>
<qual:polygonId>_Simple_BD.1_PG.1</qual:polygonId>
<qual:linearRingId1>_Simple_BD.1_PG.1_Ring1</qual:linearRingId1>
<qual:linearRingId2>_Simple_BD.1_PG.1_Ring2</qual:linearRingId2>
</qual:GE_P_INTERSECTING_RINGS>
</qual:validationResult>
<bldg:lod2Solid>
<gml:Solid>
<gml:exterior>
<gml:CompositeSurface>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.1"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.2"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.3"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.4"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.5"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.6"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.7"/>
</gml:CompositeSurface>
</gml:exterior>
</gml:Solid>
</bldg:lod2Solid>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.2">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.2_LR.1">
<gml:posList srsDimension="3">
13.0 15.0 0.0
13.0 15.0 3.0
13.0 10.0 3.0
13.0 10.0 0.0
13.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_2">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.3">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.3_LR.1">
<gml:posList srsDimension="3">
10.0 15.0 0.0
10.0 15.0 3.0
11.5 15.0 4.5
13.0 15.0 3.0
13.0 15.0 0.0
10.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_3">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.4">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.4_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 3.0
10.0 15.0 3.0
10.0 15.0 0.0
10.0 10.0 0.0
10.0 10.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_4">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.5">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.5_LR.1">
<gml:posList srsDimension="3">
13.0 10.0 0.0
13.0 10.0 3.0
11.5 10.0 4.5
10.0 10.0 3.0
10.0 10.0 0.0
13.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:RoofSurface gml:id="_Simple_BD.1_RoofSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.6">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.6_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 3.0
11.5 10.0 4.5
11.5 10.0 4.5
11.5 15.0 4.5
10.0 15.0 3.0
10.0 10.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.7">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.7_LR.1">
<gml:posList srsDimension="3">
11.5 10.0 4.5
13.0 10.0 3.0
13.0 15.0 3.0
11.5 15.0 4.5
11.5 10.0 4.5
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:RoofSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:GroundSurface gml:id="_Simple_BD.1_GroundSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.1">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.1_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 0.0
10.0 15.0 0.0
13.0 15.0 0.0
13.0 10.0 0.0
10.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:GroundSurface>
</bldg:boundedBy>
</bldg:Building>
</core:cityObjectMember>
<qual:validation>
<qual:validationDate>2002-05-30T09:00:00</qual:validationDate>
<qual:validationSoftware>CityDoctor2</qual:validationSoftware>
<qual:validationPlan>
<qual:globalParameters>
<qual:parameter name="numberOfRoundingPlaces">8</qual:parameter>
<qual:parameter name="minVertexDistance" uom="m">0.0001</qual:parameter>
<qual:parameter name="schematronFile"></qual:parameter>
</qual:globalParameters>
<qual:requirement name="R_GE_R_TOO_FEW_POINTS" enabled="true"/>
<qual:requirement name="R_GE_R_NOT_CLOSED" enabled="true"/>
<qual:requirement name="R_GE_R_CONSECUTIVE_POINTS_SAME" enabled="true"/>
<qual:requirement name="R_GE_R_SELF_INTERSECTION" enabled="true"/>
<qual:requirement name="R_GE_R_NOT_CLOSED" enabled="true"/>
<qual:requirement name="R_GE_P_NON_PLANAR" enabled="true">
<qual:parameter name="type">distance</qual:parameter>
<qual:parameter name="distanceTolerance" uom="m">0.01</qual:parameter>
<qual:parameter name="angleTolerance" uom="deg">1</qual:parameter>
<qual:parameter name="degeneratedPolygonTolerance" uom="m">0.0000</qual:parameter>
</qual:requirement>
<qual:requirement name="R_GE_P_INTERIOR_DISCONNECTED" enabled="true"/>
<qual:requirement name="R_GE_P_INTERSECTING_RINGS" enabled="true"/>
<qual:requirement name="R_GE_P_HOLE_OUTSIDE" enabled="true"/>
<qual:requirement name="R_GE_P_ORIENTATION_RINGS_SAME" enabled="true"/>
<qual:requirement name="R_GE_P_INNER_RINGS_NESTED" enabled="true"/>
<qual:requirement name="R_GE_S_TOO_FEW_POLYGONS" enabled="true"/>
<qual:requirement name="R_GE_S_NOT_CLOSED" enabled="true"/>
<qual:requirement name="R_GE_S_NON_MANIFOLD_EDGE" enabled="true"/>
<qual:requirement name="R_GE_S_POLYGON_WRONG_ORIENTATION" enabled="true"/>
<qual:requirement name="R_GE_S_ALL_POLYGONS_WRONG_ORIENTATION" enabled="true"/>
<qual:requirement name="R_GE_S_NON_MANIFOLD_VERTEX" enabled="true"/>
<qual:requirement name="R_GE_S_SELF_INTERSECTION" enabled="true"/>
<qual:requirement name="R_GE_S_MULTIPLE_CONNECTED_COMPONENTS" enabled="true"/>
<qual:filter>
<qual:checking>BUILDING</qual:checking>
<qual:checking>TRANSPORTATION</qual:checking>
<qual:checking>VEGETATION</qual:checking>
<qual:checking>BRIDGE</qual:checking>
<qual:checking>WATER</qual:checking>
<qual:checking>LAND</qual:checking>
</qual:filter>
</qual:validationPlan>
<qual:statistics>
<qual:numErrorBuildings numChecked="1">1</qual:numErrorBuildings>
<qual:numErrorVegetation numChecked="0">0</qual:numErrorVegetation>
<qual:numErrorLandObjects numChecked="0">0</qual:numErrorLandObjects>
<qual:numErrorBridgeObjects numChecked="0">0</qual:numErrorBridgeObjects>
<qual:numErrorWaterObjects numChecked="0">0</qual:numErrorWaterObjects>
<qual:numErrorTransportation numChecked="0">0</qual:numErrorTransportation>
<qual:errorStatistics>
<qual:error name="GE_R_CONSECUTIVE_POINTS_SAME">1</qual:error>
</qual:errorStatistics>
</qual:statistics>
</qual:validation>
</core:CityModel>
\ 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