Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public int parseSRID(String identifier) throws SrsException {
throw UncheckedException.wrap(e);
}
});
} catch (RuntimeException e) {
} catch (Exception e) {
throw UncheckedException.unwrap(e, SrsException.class);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
import org.citydb.model.common.Name;
import org.citygml4j.core.ade.ADEException;
import org.citygml4j.core.ade.ADERegistry;
import org.citygml4j.xml.CityGMLContext;
import org.citygml4j.xml.CityGMLContextException;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
Expand All @@ -28,26 +26,20 @@
import java.util.concurrent.ConcurrentHashMap;

public class CityGMLAdapterContext {
private final CityGMLContext context;
private final Map<String, BuilderInfo> builders = new ConcurrentHashMap<>();
private final Map<String, Map<String, SerializerInfo>> serializers = new ConcurrentHashMap<>();

CityGMLAdapterContext(ClassLoader loader) throws IOAdapterException {
try {
ADERegistry.getInstance().loadADEs(loader);
context = CityGMLContext.newInstance(loader);
} catch (ADEException | CityGMLContextException e) {
} catch (ADEException e) {
throw new IOAdapterException("Failed to create CityGML context.", e);
}

loadBuilders(loader);
loadSerializers(loader);
}

public CityGMLContext getCityGMLContext() {
return context;
}

@SuppressWarnings("unchecked")
public <T, R extends Child> ModelBuilder<T, R> getBuilder(Class<T> sourceType, Class<R> targetType) {
BuilderInfo info = builders.get(sourceType.getName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
import org.citydb.io.writer.FeatureWriter;
import org.citydb.io.writer.WriteException;
import org.citydb.io.writer.WriteOptions;
import org.citygml4j.cityjson.CityJSONContext;
import org.citygml4j.cityjson.CityJSONContextException;

import java.io.InputStream;
import java.nio.charset.Charset;
Expand All @@ -32,17 +30,11 @@
mediaType = "application/city+json",
fileExtensions = {".json", ".jsonl"})
public class CityJSONAdapter implements IOAdapter {
private CityGMLAdapterContext adapterContext;
private CityJSONContext cityJSONContext;
private CityGMLAdapterContext context;

@Override
public void initialize(ClassLoader loader) throws IOAdapterException {
adapterContext = new CityGMLAdapterContext(loader);
try {
cityJSONContext = CityJSONContext.newInstance(loader);
} catch (CityJSONContextException e) {
throw new IOAdapterException("Failed to create CityJSON context.", e);
}
context = new CityGMLAdapterContext(loader);
}

@Override
Expand All @@ -67,12 +59,12 @@ public boolean canRead(InputFile file) {

@Override
public FeatureReader createReader(InputFile file, ReadOptions options) throws ReadException {
return new CityJSONReader(file, options, adapterContext, cityJSONContext);
return new CityJSONReader(file, options, context);
}

@Override
public FeatureWriter createWriter(OutputFile file, WriteOptions options) throws WriteException {
return new CityJSONWriter(file, options, adapterContext, cityJSONContext);
return new CityJSONWriter(file, options, context);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public void build(org.citygml4j.core.model.appearance.Appearance source, Appeara
if (property != null) {
if (property.isSetInlineObject()) {
AbstractSurfaceData object = property.getObject();
if (helper.lookupAndPut(object)) {
if (appearanceHelper.lookupAndPut(object)) {
target.getSurfaceData().add(SurfaceDataProperty.of(object.getId()));
} else {
SurfaceDataAdapter<SurfaceData<?>, AbstractSurfaceData> builder = helper.getContext()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public class AppearanceHelper {
private final Map<AbstractSurfaceData, SurfaceData<?>> surfaceData = new IdentityHashMap<>();
private final Map<GMLObject, List<TargetContext<Surface<?>>>> surfaces = new IdentityHashMap<>();
private final Map<GMLObject, List<TargetContext<LinearRing>>> rings = new IdentityHashMap<>();
private final Set<String> surfaceDataIdCache = new HashSet<>();
private boolean processAppearances = true;
private Set<String> themes;

Expand All @@ -59,6 +60,10 @@ public AppearanceHelper initialize(FormatOptions<?> formatOptions) {
return this;
}

public boolean lookupAndPut(AbstractSurfaceData surfaceData) {
return surfaceData.getId() != null && !surfaceDataIdCache.add(surfaceData.getId());
}

public org.citydb.model.appearance.Appearance getAppearance(AbstractAppearance source) throws ModelBuildException {
if (processAppearances
&& source instanceof Appearance appearance
Expand Down Expand Up @@ -89,10 +94,10 @@ public void addTarget(LinearRing ring, AbstractGeometry source, GeometryProperty
}
}

public void processTargets(AbstractFeature feature) {
public void processTargets(VisitableObject object) {
if (processAppearances && !surfaceData.isEmpty()) {
AppearanceCollector collector = new AppearanceCollector();
for (AppearanceCollector.Context context : collector.collect(feature)) {
for (AppearanceCollector.Context context : collector.collect(object)) {
for (Appearance appearance : context.appearances) {
processor.process(appearance, context.properties);
}
Expand All @@ -104,13 +109,14 @@ public void reset() {
surfaceData.clear();
surfaces.clear();
rings.clear();
surfaceDataIdCache.clear();
}

private static class AppearanceCollector extends ObjectWalker {
private final Map<VisitableObject, Context> contexts = new IdentityHashMap<>();

Collection<Context> collect(AbstractFeature feature) {
feature.accept(this);
Collection<Context> collect(VisitableObject object) {
object.accept(this);
return contexts.values();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,21 @@ public abstract class AbstractFeatureAdapter<T extends AbstractFeature> extends
@Override
public void build(T source, Feature target, ModelBuilderHelper helper) throws ModelBuildException {
super.build(source, target, helper);
boolean isTopLevel = source.getParent() == null;

if (helper.isComputeEnvelopes()
boolean computeEnvelope = (isTopLevel && helper.isComputeEnvelopes())
|| source.getBoundedBy() == null
|| !source.getBoundedBy().isSetEnvelope()) {
|| !source.getBoundedBy().isSetEnvelope();
if (computeEnvelope) {
source.computeEnvelope(EnvelopeOptions.defaults().setEnvelopeOnFeatures(true));
} else {
// make sure implicit geometries are included in envelope
}

// make sure implicit geometries are included in envelope
if (!computeEnvelope || helper.hasImplicitGeometries()) {
source.accept(new ObjectWalker() {
@Override
public void visit(ImplicitGeometry implicitGeometry) {
source.getBoundedBy().getEnvelope().include(implicitGeometry.computeEnvelope());
source.getBoundedBy().getEnvelope().include(helper.computeEnvelope(implicitGeometry));
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
import org.citydb.io.citygml.serializer.ModelSerializeException;
import org.citydb.io.citygml.serializer.ModelSerializer;
import org.citydb.io.citygml.writer.ModelSerializerHelper;
import org.citydb.model.common.Name;
import org.citydb.model.common.Namespaces;
import org.citydb.model.geometry.ImplicitGeometry;
import org.citydb.model.geometry.Point;
import org.citydb.model.property.AppearanceProperty;
Expand All @@ -33,13 +31,6 @@ public void build(org.citygml4j.core.model.core.ImplicitGeometry source, Implici
if (source.getReferencePoint() != null) {
target.setReferencePoint(helper.getPointGeometry(source.getReferencePoint().getObject(), Point.class));
}

ImplicitGeometry implicitGeometry = target.getObject().orElse(null);
if (implicitGeometry != null && source.isSetAppearances()) {
for (AbstractAppearanceProperty property : source.getAppearances()) {
helper.addAppearance(Name.of("appearance", Namespaces.CORE), property, implicitGeometry);
}
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,10 @@
import org.citydb.io.citygml.adapter.appearance.builder.AppearanceHelper;
import org.citydb.io.citygml.builder.ModelBuildException;
import org.citydb.io.citygml.reader.ModelBuilderHelper;
import org.citydb.model.common.ExternalFile;
import org.citydb.model.common.Name;
import org.citydb.model.geometry.Geometry;
import org.citydb.model.geometry.ImplicitGeometry;
import org.citydb.model.property.ImplicitGeometryProperty;
import org.slf4j.event.Level;
import org.xmlobjects.gml.model.geometry.AbstractGeometry;
import org.xmlobjects.gml.model.geometry.GeometryProperty;

import java.io.IOException;

public class GeometryHelper {
private final ModelBuilderHelper helper;
private final PointGeometryBuilder pointGeometryBuilder;
Expand Down Expand Up @@ -127,42 +120,4 @@ private Geometry<?> buildGeometry(AbstractGeometry source, boolean force2D, Geom

return null;
}

public ImplicitGeometryProperty getImplicitGeometry(org.citygml4j.core.model.core.ImplicitGeometry source, Name name, boolean force2D) throws ModelBuildException {
if (source != null) {
if (source.getRelativeGeometry() != null) {
if (source.getRelativeGeometry().getObject() != null) {
AbstractGeometry template = source.getRelativeGeometry().getObject();
if (helper.lookupAndPut(template)) {
return ImplicitGeometryProperty.of(name, template.getId());
} else {
Geometry<?> geometry = getGeometry(template, force2D);
if (geometry != null) {
return ImplicitGeometryProperty.of(name, ImplicitGeometry.of(geometry
.setSrsIdentifier(template.getSrsName())));
}
}
} else if (source.getRelativeGeometry().getHref() != null) {
return ImplicitGeometryProperty.of(name,
helper.getIdFromReference(source.getRelativeGeometry().getHref()));
}
} else if (source.getLibraryObject() != null) {
try {
ExternalFile libraryObject = helper.getExternalFile(source.getLibraryObject());
return helper.lookupAndPut(libraryObject) ?
ImplicitGeometryProperty.of(name, libraryObject.getOrCreateObjectId()) :
ImplicitGeometryProperty.of(name, ImplicitGeometry.of(libraryObject));
} catch (IOException e) {
helper.logOrThrow(Level.ERROR, helper.formatMessage(source, "Failed to read library object file " +
source.getLibraryObject() + "."), e);
}
}
}

return null;
}

public ImplicitGeometryProperty getImplicitGeometry(org.citygml4j.core.model.core.ImplicitGeometryProperty source, Name name, boolean force2D) throws ModelBuildException {
return source != null ? getImplicitGeometry(source.getObject(), name, force2D) : null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright virtualcitysystems GmbH <https://vc.systems>
*/

package org.citydb.io.citygml.adapter.geometry.builder;

import org.citydb.io.citygml.adapter.appearance.builder.AppearanceHelper;
import org.citydb.io.citygml.builder.ModelBuildException;
import org.citydb.io.citygml.reader.ModelBuilderHelper;
import org.citydb.io.citygml.reader.preprocess.ImplicitGeometryResolver;
import org.citydb.io.citygml.reader.util.FeatureHelper;
import org.citydb.model.appearance.Appearance;
import org.citydb.model.common.ExternalFile;
import org.citydb.model.common.Name;
import org.citydb.model.common.Namespaces;
import org.citydb.model.geometry.Geometry;
import org.citydb.model.geometry.ImplicitGeometry;
import org.citydb.model.property.AppearanceProperty;
import org.citydb.model.property.ImplicitGeometryProperty;
import org.citygml4j.core.model.core.AbstractAppearanceProperty;
import org.slf4j.event.Level;
import org.xmlobjects.gml.model.geometry.AbstractGeometry;
import org.xmlobjects.gml.model.geometry.Envelope;

import java.io.IOException;

public class ImplicitGeometryHelper {
private final ImplicitGeometryResolver resolver;
private final ModelBuilderHelper helper;

public ImplicitGeometryHelper(ImplicitGeometryResolver resolver, ModelBuilderHelper helper) {
this.resolver = resolver;
this.helper = helper;
}

public boolean hasImplicitGeometries() {
return resolver.hasImplicitGeometries();
}

public Envelope computeEnvelope(org.citygml4j.core.model.core.ImplicitGeometry implicitGeometry) {
return resolver.computeEnvelope(implicitGeometry);
}

public ImplicitGeometryProperty getImplicitGeometry(Name name, org.citygml4j.core.model.core.ImplicitGeometry source, boolean force2D) throws ModelBuildException {
if (source != null) {
if (source.getRelativeGeometry() != null) {
if (source.getRelativeGeometry().getHref() != null) {
String objectId = FeatureHelper.getIdFromReference(source.getRelativeGeometry().getHref());
if (helper.lookupAndPut(source.getRelativeGeometry())) {
return ImplicitGeometryProperty.of(name, objectId);
} else {
ImplicitGeometry target = resolver.getOrConvert(objectId,
implicitGeometry -> buildImplicitGeometry(implicitGeometry, force2D));
if (target != null) {
return ImplicitGeometryProperty.of(name, target);
}
}
} else {
ImplicitGeometry target = buildImplicitGeometry(source, force2D);
if (target != null) {
return ImplicitGeometryProperty.of(name, target);
}
}
} else if (source.getLibraryObject() != null) {
try {
ExternalFile libraryObject = helper.getExternalFile(source.getLibraryObject());
return helper.lookupAndPut(libraryObject) ?
ImplicitGeometryProperty.of(name, libraryObject.getOrCreateObjectId()) :
ImplicitGeometryProperty.of(name, ImplicitGeometry.of(libraryObject));
} catch (IOException e) {
helper.logOrThrow(Level.ERROR, helper.formatMessage(source, "Failed to read library object file " +
source.getLibraryObject() + "."), e);
}
}
}

return null;
}

private ImplicitGeometry buildImplicitGeometry(org.citygml4j.core.model.core.ImplicitGeometry source, boolean force2D) throws ModelBuildException {
if (source.getRelativeGeometry() != null && source.getRelativeGeometry().getObject() != null) {
AbstractGeometry template = source.getRelativeGeometry().getObject();
AppearanceHelper appearanceHelper = new AppearanceHelper(helper);
GeometryHelper geometryHelper = new GeometryHelper(appearanceHelper, helper);

Geometry<?> geometry = geometryHelper.getGeometry(template, force2D);
if (geometry != null) {
ImplicitGeometry target = ImplicitGeometry.of(geometry.setSrsIdentifier(template.getSrsName()));
if (source.isSetAppearances()) {
for (AbstractAppearanceProperty property : source.getAppearances()) {
if (property != null && property.getObject() != null) {
Appearance appearance = appearanceHelper.getAppearance(property.getObject());
if (appearance != null) {
target.addAppearance(AppearanceProperty.of(
Name.of("appearance", Namespaces.CORE), appearance));
}
}
}

if (target.hasAppearances()) {
appearanceHelper.processTargets(source);
}
}

return target;
}
}

return null;
}
}
Loading
Loading