Skip to content

Commit

Permalink
Add translation support (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickackermann authored Nov 19, 2024
2 parents 33e38e3 + 241d401 commit 5ed5f17
Show file tree
Hide file tree
Showing 23 changed files with 3,114 additions and 185 deletions.
5 changes: 5 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# By default text files use native line endings for the platform
* text=auto

*.ili text eol=crlf
*.dxf text eol=lf
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ repositories {

dependencies {
implementation 'ch.interlis:iox-ili:1.23.1'
implementation 'ch.interlis:ili2c-tool:5.5.4'
implementation 'ch.interlis:ili2c-core:5.5.4'

implementation 'commons-cli:commons-cli:1.9.0'
Expand All @@ -40,4 +41,5 @@ jar {

test {
useJUnitPlatform()
testLogging.showStandardStreams = true
}
4 changes: 3 additions & 1 deletion config/checkstyle/checkstyle.xml
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,9 @@
<!-- Checks for Size Violations. -->
<!-- See https://checkstyle.org/checks/sizes/index.html -->
<module name="MethodLength"/>
<module name="ParameterNumber"/>
<module name="ParameterNumber">
<property name="max" value="8"/>
</module>

<!-- Checks for whitespace -->
<!-- See https://checkstyle.org/checks/whitespace/index.html -->
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/ch/geowerkstatt/lk2dxf/DxfWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -273,13 +273,13 @@ public void writeBlockInsert(String layerName, String blockName, double rotation
* @param position The position of the text.
* @see <a href="https://help.autodesk.com/view/OARX/2024/ENU/?guid=GUID-62E5383D-8A14-47B4-BFC4-35824CAE8363">TEXT (DXF Reference)</a>
*/
public void writeText(String layerName, String textStyle, String text, String hAlignment, String vAlignment, double orientation, IomObject position) throws IOException {
var hAlignmentValue = switch (hAlignment.toLowerCase(Locale.ROOT)) {
public void writeText(String layerName, String textStyle, String text, String hAlignment, String vAlignment, double orientation, double size, IomObject position) throws IOException {
var hAlignmentValue = switch (Objects.requireNonNullElse(hAlignment, "").toLowerCase(Locale.ROOT)) {
case "right" -> 2;
case "center" -> 1;
default -> 0; // Left
};
var vAlignmentValue = switch (vAlignment.toLowerCase(Locale.ROOT)) {
var vAlignmentValue = switch (Objects.requireNonNullElse(vAlignment, "").toLowerCase(Locale.ROOT)) {
case "top", "cap" -> 3;
case "half" -> 2;
case "bottom" -> 1;
Expand All @@ -297,7 +297,7 @@ public void writeText(String layerName, String textStyle, String text, String hA
writeElement(7, textStyle);
writeElement(10, isDefaultAlignment ? Double.parseDouble(position.getattrvalue("C1")) : 0.0);
writeElement(20, isDefaultAlignment ? Double.parseDouble(position.getattrvalue("C2")) : 0.0);
writeElement(40, 1.25); // text height
writeElement(40, size); // text height
writeElement(1, text);
if (hAlignmentValue != 0) {
writeElement(72, hAlignmentValue);
Expand Down
37 changes: 2 additions & 35 deletions src/main/java/ch/geowerkstatt/lk2dxf/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import java.io.File;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;

public final class Main {
Expand Down Expand Up @@ -55,50 +54,18 @@ public static void main(String[] args) {

private static void processFiles(LK2DxfOptions options) {
Optional<Geometry> perimeter = options.parsePerimeter();
AtomicInteger counter = new AtomicInteger();

try (var dxfWriter = new DxfWriter(options.dxfFile(), 3, ObjectMapper.getLayerMappings(), "lk2dxf " + Main.VERSION)) {
for (String xtfFile : options.xtfFiles()) {
try (LKMapXtfReader reader = new LKMapXtfReader(new File(xtfFile))) {
try (XtfStreamReader reader = new XtfStreamReader(new File(xtfFile))) {
ObjectMapper mapper = new ObjectMapper();
Stream<MappedObject> objects = mapper.mapObjects(reader.readObjects());

if (perimeter.isPresent()) {
objects = objects.filter(o -> perimeter.get().intersects(o.geometry()));
}

objects.forEach(o -> {
try {
switch (o.layerMapping().objectClass()) {
case "LKFlaeche" ->
dxfWriter.writeHatch(o.layerMapping().layer(), o.iomObject().getattrobj(o.layerMapping().geometry(), 0));
case "LKLinie" ->
dxfWriter.writeLwPolyline(o.layerMapping().layer(), o.iomObject().getattrobj(o.layerMapping().geometry(), 0));
case "LKPunkt" -> dxfWriter.writeBlockInsert(
o.layerMapping().layer(),
o.layerMapping().symbol(),
Optional.ofNullable(o.iomObject().getattrvalue(o.layerMapping().orientation())).map(Double::parseDouble).orElse(90.0),
o.iomObject().getattrobj(o.layerMapping().geometry(), 0));
case "LKObjekt_Text" -> dxfWriter.writeText(
o.layerMapping().layer(),
o.layerMapping().font(),
o.iomObject().getattrvalue(o.layerMapping().text()),
o.iomObject().getattrvalue(o.layerMapping().hAlign()),
o.iomObject().getattrvalue(o.layerMapping().vAlign()),
Double.parseDouble(o.iomObject().getattrvalue(o.layerMapping().orientation())),
o.iomObject().getattrobj(o.layerMapping().geometry(), 0));

default -> System.out.println("Unsupported geometry type: " + o.layerMapping().geometryType());
//throw new IllegalArgumentException("Unsupported geometry type: " + o.layerMapping().geometryType());
}

System.out.println(counter.incrementAndGet() + ": " + o.iomObject().getobjectoid() + " -> " + o.layerMapping().layer());
} catch (Exception e) {
System.err.println("Failed to process object: " + o.iomObject().getobjectoid());
e.printStackTrace();
return;
}
});
objects.forEach(o -> o.writeToDxf(dxfWriter));
} catch (Exception e) {
System.err.println("Failed to process file: " + xtfFile);
e.printStackTrace();
Expand Down
67 changes: 42 additions & 25 deletions src/main/java/ch/geowerkstatt/lk2dxf/MappedObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,59 @@
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;

public record MappedObject(Geometry geometry, IomObject iomObject, LayerMapping layerMapping) {
public record MappedObject(
String oid,
Geometry geometry,
IomObject iomGeometry,
double orientation,
String vAlign,
String hAlign,
String text,
LayerMapping layerMapping) {
private static final GeometryFactory GEOMETRY_FACTORY = new JtsextGeometryFactory();

/**
* Creates a new geometry object from the given {@link IomObject}.
* @param iomObject The {@link IomObject} to create the geometry object from.
* @return A geometry object containing the {@link IomObject} and its extracted {@link Geometry}.
* @throws IllegalArgumentException If the object tag is not supported.
* Creates a new {@link MappedObject} that contains all information to process the object further.
*
* @throws RuntimeException If an error occurs while extracting the geometry.
*/
public static MappedObject create(IomObject iomObject, LayerMapping layerMapping) {
public MappedObject(String oid, IomObject iomGeometry, Double orientation, String vAlign, String hAlign, String text, LayerMapping layerMapping) {
this(oid, constructGeometry(iomGeometry, layerMapping.output(), oid), iomGeometry, orientation == null ? 90 : orientation, vAlign, hAlign, text, layerMapping);
}

private static Geometry constructGeometry(IomObject iomGeometry, LayerMapping.OutputType outputType, String oid) {
try {
Geometry geometry = switch (layerMapping.geometryType()) {
case "Point" -> readPoint(iomObject, layerMapping.geometry());
case "Line" -> readLine(iomObject, layerMapping.geometry());
case "Surface" -> readSurface(iomObject, layerMapping.geometry());
default -> throw new IllegalArgumentException("Unsupported object tag: " + iomObject.getobjecttag());
return switch (outputType) {
case TEXT, POINT -> GEOMETRY_FACTORY.createPoint(Iox2jtsext.coord2JTS(iomGeometry));
case LINE -> Iox2jtsext.polyline2JTS(iomGeometry, false, 0.0);
case SURFACE -> Iox2jtsext.surface2JTS(iomGeometry, 0.0);
};
return new MappedObject(geometry, iomObject, layerMapping);
} catch (IoxException e) {
throw new RuntimeException("Error creating geometry for object with id \"" + iomObject.getobjectoid() + "\".", e);
throw new RuntimeException("Error creating geometry for object with id \"" + oid + "\".", e);
}
}

private static Geometry readPoint(IomObject iomObject, String attributeName) throws IoxException {
IomObject position = iomObject.getattrobj(attributeName, 0);
return GEOMETRY_FACTORY.createPoint(Iox2jtsext.coord2JTS(position));
}

private static Geometry readLine(IomObject iomObject, String attributeName) throws IoxException {
IomObject line = iomObject.getattrobj(attributeName, 0);
return Iox2jtsext.polyline2JTS(line, false, 0.0);
}
/**
* Writes the object to a DXF file using the provided {@link DxfWriter}.
*/
public void writeToDxf(DxfWriter dxfWriter) {
try {
if (iomGeometry == null) {
throw new IllegalStateException("Cannot write object to dxf without geometry.");
}

private static Geometry readSurface(IomObject iomObject, String attributeName) throws IoxException {
IomObject surface = iomObject.getattrobj(attributeName, 0);
return Iox2jtsext.surface2JTS(surface, 0.0);
switch (layerMapping().output()) {
case SURFACE -> dxfWriter.writeHatch(layerMapping().layer(), iomGeometry);
case LINE -> dxfWriter.writeLwPolyline(layerMapping().layer(), iomGeometry);
case POINT ->
dxfWriter.writeBlockInsert(layerMapping().layer(), layerMapping().symbol(), orientation, iomGeometry);
case TEXT ->
dxfWriter.writeText(layerMapping().layer(), layerMapping().font(), text, hAlign, vAlign, orientation, layerMapping().textsize(), iomGeometry);
default -> throw new AssertionError("Unknown output type: " + layerMapping().output());
}
} catch (Exception e) {
System.err.println("Failed to write object: " + oid() + " to dxf.");
e.printStackTrace();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@
import java.util.stream.StreamSupport;

/**
* A reader for LKMap INTERLIS transfer files.
* A reader for INTERLIS transfer files.
*/
public final class LKMapXtfReader implements AutoCloseable {
private static final String BASKET_NAME = "SIA405_LKMap_2015_LV95.SIA405_LKMap";
public final class XtfStreamReader implements AutoCloseable {
private static final ReaderFactory READER_FACTORY = new ReaderFactory();

private final IoxReader reader;
Expand All @@ -34,7 +33,7 @@ public final class LKMapXtfReader implements AutoCloseable {
* @param xtfFile The file to read from.
* @throws IoxException If an error occurs while creating the transfer file reader.
*/
public LKMapXtfReader(File xtfFile) throws IoxException {
public XtfStreamReader(File xtfFile) throws IoxException {
LogEventFactory logEventFactory = new LogEventFactory();
Settings settings = new Settings();
this.reader = READER_FACTORY.createReader(xtfFile, logEventFactory, settings);
Expand Down Expand Up @@ -68,7 +67,7 @@ private enum LKMapXtfReaderState {
}

/**
* A sequential spliterator for reading objects from the surrounding {@link LKMapXtfReader}.
* A sequential spliterator for reading objects from the surrounding {@link XtfStreamReader}.
* Advancing the spliterator will read from the xtf reader and may throw an exception when reading invalid data.
*/
private class XtfReaderSpliterator implements Spliterator<IomObject> {
Expand All @@ -89,9 +88,6 @@ public boolean tryAdvance(Consumer<? super IomObject> action) {
if (state != LKMapXtfReaderState.TRANSFER) {
throw new IllegalStateException("Unexpected start basket event in state: " + state);
}
if (!BASKET_NAME.equals(startBasketEvent.getType())) {
throw new IllegalStateException("Invalid basket type: " + startBasketEvent.getType());
}
state = LKMapXtfReaderState.BASKET;
System.out.println("Start basket \"" + startBasketEvent.getBid() + "\"");
}
Expand Down
28 changes: 26 additions & 2 deletions src/main/java/ch/geowerkstatt/lk2dxf/mapping/LayerMapping.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

import java.util.Collection;
import java.util.List;
import java.util.Map;

public record LayerMapping(
String layer,
String objectClass,
String geometryType,
@JsonDeserialize(converter = ObjectClassConverter.class)
Collection<String> objectClass,
OutputType output,
String geometry,
int color,
String orientation,
Expand All @@ -22,4 +24,26 @@ public record LayerMapping(
String font,
@JsonDeserialize(converter = MappingConverter.class)
Map<String, List<String>> mapping) {

public enum OutputType {
/**
* The object has a surface and is exported as a filled polygon.
*/
SURFACE,

/**
* The object has a line geometry.
*/
LINE,

/**
* The object represents text with font, alignment and orientation.
*/
TEXT,

/**
* The object has a point geometry that gets marked with a symbol.
*/
POINT,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,15 @@
import java.io.InputStream;
import java.util.List;

/**
* Read and interpret the layer mapping configuration.
*/
public final class MappingReader {
private static final String MAPPING_RESOURCE = "/mappings.csv";
private static final CsvMapper MAPPER = CsvMapper
.builder()
.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS)
.build();

private MappingReader() { }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package ch.geowerkstatt.lk2dxf.mapping;

import com.fasterxml.jackson.databind.util.StdConverter;

import java.util.*;
import java.util.regex.Pattern;

public final class ObjectClassConverter extends StdConverter<String, Collection<String>> {
private static final Pattern VALUE_SEPARATOR = Pattern.compile("\\|");

@Override
public Collection<String> convert(String s) {
return new HashSet<>(Arrays.asList(VALUE_SEPARATOR.split(s)));
}
}
Loading

0 comments on commit 5ed5f17

Please sign in to comment.