// License: GPL. For details, see LICENSE file.
package pdfimport;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.awt.Color;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.data.osm.Relation;
import org.openstreetmap.josm.data.osm.RelationMember;
import org.openstreetmap.josm.data.osm.Way;
import org.openstreetmap.josm.gui.progress.ProgressMonitor;
public class OsmBuilder {
enum Mode { Draft, Final, Debug }
private final FilePlacement placement;
private String layerName;
private String fillName;
private String lineName;
private Mode mode;
private ProgressMonitor monitor;
private int monitorPos;
private int monitorTotal;
public OsmBuilder(FilePlacement placement) {
this.placement = placement;
}
public DataSet build(List<LayerContents> data, Mode mode, ProgressMonitor monitor) {
this.monitor = monitor;
this.monitorPos = 0;
this.mode = mode;
DataSet result = new DataSet();
//count total items for progress monitor.
this.monitorTotal = 0;
for (LayerContents layer: data) {
this.monitorTotal += layer.paths.size();
for (PdfMultiPath mp: layer.multiPaths) {
this.monitorTotal += mp.paths.size();
}
}
monitor.beginTask(tr("Building JOSM layer."), this.monitorTotal);
for (LayerContents layer: data) {
this.addLayer(result, layer);
}
monitor.finishTask();
return result;
}
private void addLayer(DataSet target, LayerContents layer) {
Map<Point2D, Node> point2Node = new HashMap<>();
this.fillName = this.printColor(layer.info.fill);
this.lineName = this.printColor(layer.info.stroke);
this.layerName = "" + layer.info.nr;
//insert nodes
for (Point2D pt: layer.points) {
Node node = new Node();
node.setCoor(this.placement.tranformCoords(pt));
target.addPrimitive(node);
point2Node.put(pt, node);
}
//insert ways
Map<PdfPath, Way> path2Way = new HashMap<>();
for (PdfPath path: layer.paths) {
Way w = this.insertWay(path, point2Node, -1, false);
target.addPrimitive(w);
path2Way.put(path, w);
}
int pathId = 0;
for (PdfMultiPath mpath: layer.multiPaths) {
for (PdfPath path: mpath.paths) {
Way w = this.insertWay(path, point2Node, pathId, true);
target.addPrimitive(w);
path2Way.put(path, w);
}
pathId++;
}
if (this.mode != Mode.Draft) {
//insert relations
for (PdfMultiPath mpath: layer.multiPaths) {
Relation rel = new Relation();
Map<String, String> keys = new HashMap<>();
keys.put("type", "multipolygon");
keys.put("area", "yes");
rel.setKeys(keys);
for (PdfPath path: mpath.paths) {
Way w = path2Way.get(path);
rel.addMember(new RelationMember("", w));
}
target.addPrimitive(rel);
}
}
}
private Way insertWay(PdfPath path, Map<Point2D, Node> point2Node, int multipathId, boolean multipolygon) {
if (this.monitorPos % 100 == 0) {
monitor.setExtraText(tr(" "+this.monitorPos+"/"+this.monitorTotal));
monitor.setTicks(this.monitorPos);
}
this.monitorPos++;
List<Node> nodes = new ArrayList<>(path.points.size());
for (Point2D point: path.points) {
Node node = point2Node.get(point);
if (node == null) {
throw new RuntimeException();
}
nodes.add(node);
}
Map<String, String> keys = new HashMap<>();
if (this.mode != Mode.Draft) {
keys.put("PDF_nr", "" + path.nr);
keys.put("PDF_layer", this.layerName);
if (path.isClosed()) {
keys.put("PDF_closed", "yes");
}
if (this.fillName != null) {
keys.put("PDF_fillColor", this.fillName);
}
if (this.lineName != null) {
keys.put("PDF_lineColor", this.lineName);
}
if (multipathId != -1) {
keys.put("PDF_multipath", ""+ multipathId);
} else if (path.layer.info.fill != null && !multipolygon) {
keys.put("area", "yes");
}
}
if (this.mode == Mode.Debug) {
keys.put("PDF_pathLayer", ""+path.layer.info.nr);
keys.put("PDF_lineWidth", ""+path.layer.info.width);
keys.put("PDF_lineDash", ""+path.layer.info.dash);
keys.put("PDF_layerHash", ""+path.layer.info.hashCode());
keys.put("PDF_layerDivider", ""+path.layer.info.divider);
}
Way newWay = new Way();
newWay.setNodes(nodes);
newWay.setKeys(keys);
return newWay;
}
private String printColor(Color col) {
if (col == null) {
return null;
}
String s = Integer.toHexString(col.getRGB() & 0xffffff);
while (s.length() < 6) {
s = "0" + s;
}
return "#" + s;
}
}