add vtm-jeo
This commit is contained in:
parent
05b977be70
commit
9109da9784
80
vtm-jeo/src/org/oscim/layers/JeoMapLayer.java
Normal file
80
vtm-jeo/src/org/oscim/layers/JeoMapLayer.java
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package org.oscim.layers;
|
||||||
|
|
||||||
|
import org.jeo.data.Dataset;
|
||||||
|
import org.jeo.map.Style;
|
||||||
|
import org.oscim.core.MapPosition;
|
||||||
|
import org.oscim.layers.JeoMapLoader.Task;
|
||||||
|
import org.oscim.map.Map;
|
||||||
|
import org.oscim.map.Map.UpdateListener;
|
||||||
|
import org.oscim.renderer.ElementRenderer;
|
||||||
|
import org.oscim.renderer.MapRenderer.Matrices;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class JeoMapLayer extends Layer implements UpdateListener {
|
||||||
|
|
||||||
|
public static final Logger log = LoggerFactory.getLogger(JeoMapLayer.class);
|
||||||
|
|
||||||
|
final org.jeo.map.View view;
|
||||||
|
private final org.jeo.map.Map mJeoMap;
|
||||||
|
|
||||||
|
private final JeoMapLoader mWorker;
|
||||||
|
|
||||||
|
public JeoMapLayer(Map map, Dataset data, Style style) {
|
||||||
|
super(map);
|
||||||
|
|
||||||
|
mJeoMap = org.jeo.map.Map.build().layer(data).style(style).map();
|
||||||
|
view = mJeoMap.getView();
|
||||||
|
|
||||||
|
mRenderer = new ElementRenderer() {
|
||||||
|
@Override
|
||||||
|
protected synchronized void update(MapPosition position, boolean changed,
|
||||||
|
Matrices matrices) {
|
||||||
|
|
||||||
|
if (mNewLayers != null) {
|
||||||
|
mMapPosition.copy(mNewLayers);
|
||||||
|
|
||||||
|
this.layers.clear();
|
||||||
|
this.layers.baseLayers = mNewLayers.layers;
|
||||||
|
mNewLayers = null;
|
||||||
|
|
||||||
|
compile();
|
||||||
|
log.debug("is ready " + isReady() + " " + layers.getSize());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mWorker = new JeoMapLoader(this);
|
||||||
|
mWorker.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDetach() {
|
||||||
|
super.onDetach();
|
||||||
|
|
||||||
|
mWorker.awaitPausing();
|
||||||
|
try {
|
||||||
|
mWorker.join();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMapUpdate(MapPosition pos, boolean changed, boolean clear) {
|
||||||
|
if (changed) {
|
||||||
|
log.debug("go");
|
||||||
|
mWorker.go();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Task mNewLayers;
|
||||||
|
|
||||||
|
void setLayers(Task newLayers) {
|
||||||
|
synchronized (mRenderer) {
|
||||||
|
mNewLayers = newLayers;
|
||||||
|
}
|
||||||
|
mMap.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
346
vtm-jeo/src/org/oscim/layers/JeoMapLoader.java
Normal file
346
vtm-jeo/src/org/oscim/layers/JeoMapLoader.java
Normal file
@ -0,0 +1,346 @@
|
|||||||
|
package org.oscim.layers;
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
// Apache License 2.0
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.jeo.data.Dataset;
|
||||||
|
import org.jeo.data.Query;
|
||||||
|
import org.jeo.data.VectorDataset;
|
||||||
|
import org.jeo.feature.Feature;
|
||||||
|
import org.jeo.geom.CoordinatePath;
|
||||||
|
import org.jeo.geom.Envelopes;
|
||||||
|
import org.jeo.geom.Geom;
|
||||||
|
import org.jeo.map.CartoCSS;
|
||||||
|
import org.jeo.map.Map;
|
||||||
|
import org.jeo.map.RGB;
|
||||||
|
import org.jeo.map.Rule;
|
||||||
|
import org.jeo.map.RuleList;
|
||||||
|
import org.jeo.map.View;
|
||||||
|
import org.oscim.core.BoundingBox;
|
||||||
|
import org.oscim.core.GeometryBuffer;
|
||||||
|
import org.oscim.core.MapPosition;
|
||||||
|
import org.oscim.core.MercatorProjection;
|
||||||
|
import org.oscim.core.Tile;
|
||||||
|
import org.oscim.renderer.elements.ElementLayers;
|
||||||
|
import org.oscim.renderer.elements.LineLayer;
|
||||||
|
import org.oscim.renderer.elements.MeshLayer;
|
||||||
|
import org.oscim.renderer.elements.RenderElement;
|
||||||
|
import org.oscim.theme.renderinstruction.Line;
|
||||||
|
import org.oscim.utils.PausableThread;
|
||||||
|
import org.oscim.utils.TileClipper;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.vividsolutions.jts.geom.Coordinate;
|
||||||
|
import com.vividsolutions.jts.geom.Envelope;
|
||||||
|
import com.vividsolutions.jts.geom.Geometry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the work of actually rendering the map, outside of the ui thread.
|
||||||
|
*
|
||||||
|
* @author Justin Deoliveira, OpenGeo
|
||||||
|
* @author Hannes Janetzek, OpenScienceMap
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class JeoMapLoader extends PausableThread {
|
||||||
|
|
||||||
|
static final Logger log = LoggerFactory.getLogger(JeoMapLoader.class);
|
||||||
|
|
||||||
|
private final JeoMapLayer mMapLayer;
|
||||||
|
|
||||||
|
public JeoMapLoader(JeoMapLayer mapLayer) {
|
||||||
|
mMapLayer = mapLayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ElementLayers layers;
|
||||||
|
private final GeometryBuffer mGeom = new GeometryBuffer(128, 4);
|
||||||
|
|
||||||
|
private Task mCurrentTask;
|
||||||
|
|
||||||
|
private double mMinX;
|
||||||
|
private double mMinY;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doWork() throws InterruptedException {
|
||||||
|
log.debug("start");
|
||||||
|
mWork = false;
|
||||||
|
Envelope env = new Envelope();
|
||||||
|
BoundingBox bbox = mMapLayer.mMap.getViewport().getViewBox();
|
||||||
|
|
||||||
|
env.init(bbox.getMinLongitude(), bbox.getMaxLongitude(),
|
||||||
|
bbox.getMinLatitude(), bbox.getMaxLatitude());
|
||||||
|
int w = mMapLayer.mMap.getWidth();
|
||||||
|
int h = mMapLayer.mMap.getHeight();
|
||||||
|
mMapLayer.view.setWidth(w);
|
||||||
|
mMapLayer.view.setHeight(h);
|
||||||
|
|
||||||
|
mClipper.setRect(-w, -h, w, h);
|
||||||
|
|
||||||
|
mMapLayer.view.zoomto(env);
|
||||||
|
|
||||||
|
Task task = new Task();
|
||||||
|
task.view = mMapLayer.view.clone();
|
||||||
|
|
||||||
|
mMapLayer.mMap.getMapPosition(task);
|
||||||
|
|
||||||
|
mCurrentTask = task;
|
||||||
|
layers = new ElementLayers();
|
||||||
|
|
||||||
|
Envelope b = task.view.getBounds();
|
||||||
|
|
||||||
|
// reduce lines points min distance
|
||||||
|
mMinX = ((b.getMaxX() - b.getMinX()) / task.view.getWidth()) * 2;
|
||||||
|
mMinY = ((b.getMaxY() - b.getMinY()) / task.view.getHeight()) * 2;
|
||||||
|
|
||||||
|
Map map = mMapLayer.view.getMap();
|
||||||
|
|
||||||
|
for (org.jeo.map.Layer l : map.getLayers()) {
|
||||||
|
|
||||||
|
if (!l.isVisible())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Dataset data = l.getData();
|
||||||
|
|
||||||
|
RuleList rules =
|
||||||
|
map.getStyle().getRules().selectById(l.getName(), true).flatten();
|
||||||
|
|
||||||
|
log.debug("data {}", data);
|
||||||
|
|
||||||
|
if (data instanceof VectorDataset) {
|
||||||
|
for (RuleList ruleList : rules.zgroup()) {
|
||||||
|
render(task.view, (VectorDataset) data, ruleList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layers.baseLayers != null) {
|
||||||
|
mCurrentTask.layers = layers.baseLayers;
|
||||||
|
|
||||||
|
//layers.baseLayers = null;
|
||||||
|
//layers.clear();
|
||||||
|
|
||||||
|
mMapLayer.setLayers(mCurrentTask);
|
||||||
|
}
|
||||||
|
layers = null;
|
||||||
|
mCurrentTask = null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void render(View view, VectorDataset data, RuleList rules) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Query q = new Query().bounds(view.getBounds());
|
||||||
|
log.debug("query {}", q);
|
||||||
|
|
||||||
|
// reproject
|
||||||
|
// if (data.getCRS() != null) {
|
||||||
|
// if (!Proj.equal(view.getCRS(), data.getCRS())) {
|
||||||
|
// q.reproject(view.getCRS());
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//else {
|
||||||
|
// log.debug("Layer " + data.getName()
|
||||||
|
// + " specifies no projection, assuming map projection");
|
||||||
|
//}
|
||||||
|
|
||||||
|
for (Feature f : data.cursor(q)) {
|
||||||
|
|
||||||
|
RuleList rs = rules.match(f);
|
||||||
|
if (rs.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rule r = rules.match(f).collapse();
|
||||||
|
if (r == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
draw(view, f, r);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Error querying layer " + data.getName() + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Geometry clipGeometry(View view, Geometry g) {
|
||||||
|
// TODO: doing a full intersection is sub-optimal,
|
||||||
|
// look at a more efficient clipping
|
||||||
|
// algorithm, like cohen-sutherland
|
||||||
|
return g.intersection(Envelopes.toPolygon(view.getBounds()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw(View view, Feature f, Rule rule) {
|
||||||
|
Geometry g = f.geometry();
|
||||||
|
if (g == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// g = clipGeometry(view, g);
|
||||||
|
// if (g.isEmpty()) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
switch (Geom.Type.from(g)) {
|
||||||
|
case POINT:
|
||||||
|
case MULTIPOINT:
|
||||||
|
//log.debug("draw point");
|
||||||
|
//drawPoint(f, rule);
|
||||||
|
return;
|
||||||
|
case LINESTRING:
|
||||||
|
case MULTILINESTRING:
|
||||||
|
//log.debug("draw line");
|
||||||
|
drawLine(f, rule, g);
|
||||||
|
return;
|
||||||
|
case POLYGON:
|
||||||
|
//Polygon p = (Polygon) g;
|
||||||
|
//p.reverse();
|
||||||
|
//log.debug("draw polygon");
|
||||||
|
drawPolygon(f, rule, g);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case MULTIPOLYGON:
|
||||||
|
//log.debug("draw polygon");
|
||||||
|
for (int i = 0, n = g.getNumGeometries(); i < n; i++)
|
||||||
|
drawPolygon(f, rule, g.getGeometryN(i));
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawLine(Feature f, Rule rule, Geometry g) {
|
||||||
|
|
||||||
|
LineLayer ll = layers.getLineLayer(0);
|
||||||
|
|
||||||
|
if (ll.line == null) {
|
||||||
|
RGB color = rule.color(f, CartoCSS.LINE_COLOR, RGB.black);
|
||||||
|
float width = rule.number(f, CartoCSS.LINE_WIDTH, 1.2f);
|
||||||
|
ll.line = new Line(0, color(color), width);
|
||||||
|
ll.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
mGeom.clear();
|
||||||
|
mGeom.startLine();
|
||||||
|
|
||||||
|
CoordinatePath p = CoordinatePath.create(g);
|
||||||
|
path(mGeom, p);
|
||||||
|
|
||||||
|
//log.debug( ll.width + " add line " + mGeom.pointPos + " " + Arrays.toString(mGeom.points));
|
||||||
|
|
||||||
|
ll.addLine(mGeom);
|
||||||
|
}
|
||||||
|
|
||||||
|
TileClipper mClipper = new TileClipper(0, 0, 0, 0);
|
||||||
|
|
||||||
|
private void drawPolygon(Feature f, Rule rule, Geometry g) {
|
||||||
|
|
||||||
|
LineLayer ll = layers.getLineLayer(3);
|
||||||
|
|
||||||
|
if (ll.line == null) {
|
||||||
|
RGB color = rule.color(f, CartoCSS.POLYGON_FILL, RGB.red);
|
||||||
|
float width = rule.number(f, CartoCSS.LINE_WIDTH, 1.2f);
|
||||||
|
ll.line = new Line(2, color(color), width);
|
||||||
|
ll.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
//PolygonLayer pl = layers.getPolygonLayer(1);
|
||||||
|
//
|
||||||
|
//if (pl.area == null) {
|
||||||
|
// RGB color = rule.color(f, CartoCSS.POLYGON_FILL, RGB.red);
|
||||||
|
// pl.area = new Area(1, color(color));
|
||||||
|
//}
|
||||||
|
|
||||||
|
MeshLayer mesh = layers.getMeshLayer(2);
|
||||||
|
|
||||||
|
mGeom.clear();
|
||||||
|
mGeom.startPolygon();
|
||||||
|
//mGeom.startLine();
|
||||||
|
|
||||||
|
CoordinatePath p = CoordinatePath.create(g).generalize(mMinX, mMinY);
|
||||||
|
if (path(mGeom, p) < 3)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!mClipper.clip(mGeom))
|
||||||
|
return;
|
||||||
|
|
||||||
|
//log.debug(ll.width + " add poly " + mGeom.pointPos + " " + Arrays.toString(mGeom.points));
|
||||||
|
mesh.addMesh(mGeom);
|
||||||
|
|
||||||
|
ll.addLine(mGeom);
|
||||||
|
//pl.addPolygon(mGeom.points, mGeom.index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int color(RGB rgb) {
|
||||||
|
return rgb.getAlpha() << 24
|
||||||
|
| rgb.getRed() << 16
|
||||||
|
| rgb.getGreen() << 8
|
||||||
|
| rgb.getBlue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int path(GeometryBuffer g, CoordinatePath path) {
|
||||||
|
|
||||||
|
MapPosition pos = mCurrentTask;
|
||||||
|
double scale = pos.scale * Tile.SIZE;
|
||||||
|
int cnt = 0;
|
||||||
|
O: while (path.hasNext()) {
|
||||||
|
Coordinate c = path.next();
|
||||||
|
float x = (float) ((MercatorProjection.longitudeToX(c.x) - pos.x) * scale);
|
||||||
|
float y = (float) ((MercatorProjection.latitudeToY(c.y) - pos.y) * scale);
|
||||||
|
|
||||||
|
switch (path.getStep()) {
|
||||||
|
case MOVE_TO:
|
||||||
|
if (g.isPoly())
|
||||||
|
g.startPolygon();
|
||||||
|
else if (g.isLine())
|
||||||
|
g.startLine();
|
||||||
|
|
||||||
|
cnt++;
|
||||||
|
g.addPoint(x, y);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LINE_TO:
|
||||||
|
cnt++;
|
||||||
|
g.addPoint(x, y);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CLOSE:
|
||||||
|
//g.addPoint(x, y);
|
||||||
|
|
||||||
|
//if (g.type == GeometryType.POLY)
|
||||||
|
break;
|
||||||
|
case STOP:
|
||||||
|
break O;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getThreadName() {
|
||||||
|
return "JeoMapLayer";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean hasWork() {
|
||||||
|
return mWork;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean mWork;
|
||||||
|
|
||||||
|
public void go() {
|
||||||
|
if (hasWork())
|
||||||
|
return;
|
||||||
|
|
||||||
|
mWork = true;
|
||||||
|
|
||||||
|
synchronized (this) {
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Task extends MapPosition {
|
||||||
|
View view;
|
||||||
|
RenderElement layers;
|
||||||
|
}
|
||||||
|
}
|
128
vtm-jeo/src/org/oscim/layers/JeoTestData.java
Normal file
128
vtm-jeo/src/org/oscim/layers/JeoTestData.java
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
package org.oscim.layers;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.jeo.carto.Carto;
|
||||||
|
import org.jeo.data.Dataset;
|
||||||
|
import org.jeo.data.Query;
|
||||||
|
import org.jeo.data.mem.MemVector;
|
||||||
|
import org.jeo.data.mem.MemWorkspace;
|
||||||
|
import org.jeo.feature.Feature;
|
||||||
|
import org.jeo.feature.Features;
|
||||||
|
import org.jeo.feature.Schema;
|
||||||
|
import org.jeo.feature.SchemaBuilder;
|
||||||
|
import org.jeo.geojson.GeoJSONDataset;
|
||||||
|
import org.jeo.geom.GeomBuilder;
|
||||||
|
import org.jeo.map.Style;
|
||||||
|
|
||||||
|
import com.vividsolutions.jts.geom.Geometry;
|
||||||
|
|
||||||
|
public class JeoTestData {
|
||||||
|
|
||||||
|
public static Style getStyle() {
|
||||||
|
Style style = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
style = Carto.parse("" +
|
||||||
|
"#things {" +
|
||||||
|
" line-color: #c80;" +
|
||||||
|
" polygon-fill: #00a;" +
|
||||||
|
"}" +
|
||||||
|
"#states {" +
|
||||||
|
" polygon-fill: #0dc;" +
|
||||||
|
"}"
|
||||||
|
);
|
||||||
|
|
||||||
|
return style;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dataset getJsonData(String file, boolean memory) {
|
||||||
|
GeoJSONDataset data = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
data = new GeoJSONDataset(new File(file));
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memory) {
|
||||||
|
MemWorkspace mem = new MemWorkspace();
|
||||||
|
|
||||||
|
//mem.put("layer", data);
|
||||||
|
try {
|
||||||
|
|
||||||
|
Schema s = data.schema();
|
||||||
|
Query q = new Query();
|
||||||
|
|
||||||
|
MemVector memData = mem.create(s);
|
||||||
|
|
||||||
|
for (Feature f : data.cursor(q)) {
|
||||||
|
memData.add(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
//return mem.get("layer");
|
||||||
|
return memData;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dataset getMemWorkspace(String layer) {
|
||||||
|
GeomBuilder gb = new GeomBuilder(4326);
|
||||||
|
|
||||||
|
MemWorkspace mem = new MemWorkspace();
|
||||||
|
Schema schema = new SchemaBuilder(layer)
|
||||||
|
.field("geometry", Geometry.class)
|
||||||
|
.field("id", Integer.class)
|
||||||
|
.field("name", String.class)
|
||||||
|
.field("cost", Double.class).schema();
|
||||||
|
|
||||||
|
MemVector data;
|
||||||
|
try {
|
||||||
|
data = mem.create(schema);
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
} catch (IOException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Geometry g = gb.point(0, 0).toPoint();
|
||||||
|
//g.setSRID(4326);
|
||||||
|
|
||||||
|
data.add(Features.create(null, data.schema(),
|
||||||
|
g, 1, "anvil",
|
||||||
|
10.99));
|
||||||
|
|
||||||
|
data.add(Features.create(null, data.schema(),
|
||||||
|
gb.points(10, 10, 20, 20).toLineString(),
|
||||||
|
2, "bomb", 11.99));
|
||||||
|
|
||||||
|
data.add(Features.create(null, data.schema(),
|
||||||
|
gb.point(100, 10).toPoint().buffer(10),
|
||||||
|
3, "dynamite", 12.99));
|
||||||
|
|
||||||
|
//Dataset jsonData = new GeoJSONDataset(new File("states.json"));
|
||||||
|
//mem.put("states", jsonData);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return mem.get(layer);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
74
vtm-jeo/src/org/oscim/theme/carto/MatcherFeature.java
Normal file
74
vtm-jeo/src/org/oscim/theme/carto/MatcherFeature.java
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
package org.oscim.theme.carto;
|
||||||
|
|
||||||
|
import static java.lang.System.out;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jeo.feature.BasicFeature;
|
||||||
|
import org.oscim.core.Tag;
|
||||||
|
import org.oscim.core.TagSet;
|
||||||
|
|
||||||
|
//imitate Feature behaviour for tags and zoom-level
|
||||||
|
class MatcherFeature extends BasicFeature {
|
||||||
|
TagSet mTags;
|
||||||
|
Integer mZoom;
|
||||||
|
|
||||||
|
void setTags(TagSet tags) {
|
||||||
|
mTags = tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setZoom(int zoom) {
|
||||||
|
mZoom = Integer.valueOf(zoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MatcherFeature() {
|
||||||
|
super("");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object get(String key) {
|
||||||
|
//out.println("get(" + key + ")");
|
||||||
|
|
||||||
|
if (key.equals("zoom"))
|
||||||
|
return mZoom;
|
||||||
|
|
||||||
|
Tag t = mTags.get(key.intern());
|
||||||
|
if (t == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
//out.println("value: " + t.value);
|
||||||
|
|
||||||
|
return t.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void put(String key, Object val) {
|
||||||
|
out.println("EEEK put()");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Object> list() {
|
||||||
|
out.println("EEEK list()");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> map() {
|
||||||
|
out.println("EEEK map()");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object get(int arg0) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(int arg0, Object arg1) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
266
vtm-jeo/src/org/oscim/theme/carto/RenderTheme.java
Normal file
266
vtm-jeo/src/org/oscim/theme/carto/RenderTheme.java
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
package org.oscim.theme.carto;
|
||||||
|
|
||||||
|
import static java.lang.System.out;
|
||||||
|
import static org.jeo.map.CartoCSS.BACKGROUND_COLOR;
|
||||||
|
import static org.jeo.map.CartoCSS.OPACITY;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jeo.carto.Carto;
|
||||||
|
import org.jeo.map.CartoCSS;
|
||||||
|
import org.jeo.map.RGB;
|
||||||
|
import org.jeo.map.Rule;
|
||||||
|
import org.jeo.map.RuleList;
|
||||||
|
import org.jeo.map.Selector;
|
||||||
|
import org.jeo.map.Style;
|
||||||
|
import org.oscim.core.GeometryBuffer.GeometryType;
|
||||||
|
import org.oscim.core.MapElement;
|
||||||
|
import org.oscim.core.Tag;
|
||||||
|
import org.oscim.core.TagSet;
|
||||||
|
import org.oscim.theme.IRenderTheme;
|
||||||
|
import org.oscim.theme.renderinstruction.Area;
|
||||||
|
import org.oscim.theme.renderinstruction.Line;
|
||||||
|
import org.oscim.theme.renderinstruction.RenderInstruction;
|
||||||
|
|
||||||
|
public class RenderTheme implements IRenderTheme {
|
||||||
|
|
||||||
|
final String STYLE = "" +
|
||||||
|
|
||||||
|
"[building = 'yes'] {" +
|
||||||
|
" z: 1;" +
|
||||||
|
" polygon-fill: #eee;" +
|
||||||
|
" [zoom >= 16] {" +
|
||||||
|
" polygon-fill: #c00;" +
|
||||||
|
" }" +
|
||||||
|
"}" +
|
||||||
|
|
||||||
|
"[admin_level = '2'] {" +
|
||||||
|
" line-color: #000;" +
|
||||||
|
" line-width: 1;" +
|
||||||
|
" z: 1;" +
|
||||||
|
"}" +
|
||||||
|
|
||||||
|
"[admin_level = '2'] {" +
|
||||||
|
" line-color: #000;" +
|
||||||
|
" line-width: 1;" +
|
||||||
|
" z: 1;" +
|
||||||
|
"}" +
|
||||||
|
|
||||||
|
"[admin_level = '4'] {" +
|
||||||
|
" line-color: #aaa;" +
|
||||||
|
" line-width: 1;" +
|
||||||
|
" z: 2;" +
|
||||||
|
"}" +
|
||||||
|
|
||||||
|
"[highway = 'motorway'] {" +
|
||||||
|
" line-color: #a00;" +
|
||||||
|
" z: 10;" +
|
||||||
|
"}" +
|
||||||
|
|
||||||
|
"[highway = 'primary'] {" +
|
||||||
|
" line-color: #aa0;" +
|
||||||
|
" z: 11;" +
|
||||||
|
"}" +
|
||||||
|
|
||||||
|
"[highway = 'residential'],[highway = 'road'],[highway = 'secondary'] {" +
|
||||||
|
" line-color: #fff;" +
|
||||||
|
" z: 12;" +
|
||||||
|
"}" +
|
||||||
|
|
||||||
|
" [landuse = 'forest'] {" +
|
||||||
|
" polygon-fill: #0a0;" +
|
||||||
|
" z: 2;" +
|
||||||
|
"}" +
|
||||||
|
|
||||||
|
"[natural = 'water'] {" +
|
||||||
|
" polygon-fill: #00a;" +
|
||||||
|
" z: 3;" +
|
||||||
|
"}";
|
||||||
|
|
||||||
|
private Style mStyle;
|
||||||
|
private RuleList mRules;
|
||||||
|
|
||||||
|
MatcherFeature mMatchFeature = new MatcherFeature();
|
||||||
|
private int mBackground;
|
||||||
|
|
||||||
|
public RenderTheme() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
mStyle = loadStyle();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
// get map background
|
||||||
|
RuleList rules = mStyle.getRules().selectByName("Map", false);
|
||||||
|
if (!rules.isEmpty()) {
|
||||||
|
Rule rule = rules.collapse();
|
||||||
|
RGB bgColor = rule.color(null, BACKGROUND_COLOR, null);
|
||||||
|
if (bgColor != null) {
|
||||||
|
bgColor = bgColor.alpha(rule.number(null, OPACITY, 1f));
|
||||||
|
mBackground = color(bgColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mRules = mStyle.getRules();
|
||||||
|
|
||||||
|
//out.println(mRules);
|
||||||
|
//out.println();
|
||||||
|
if (mRules.get(1).equals(mRules.get(2)))
|
||||||
|
out.println("ok");
|
||||||
|
|
||||||
|
for (Rule r : mRules)
|
||||||
|
out.println(formatRule(r, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
class StyleSet {
|
||||||
|
int level;
|
||||||
|
RenderInstruction[] ri = new RenderInstruction[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<Rule, StyleSet> mStyleSets = new HashMap<Rule, StyleSet>();
|
||||||
|
int mCurLevel = 0;
|
||||||
|
|
||||||
|
public String formatRule(Rule r, int indent) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
String pad = "";
|
||||||
|
for (int i = 0; i < indent; i++)
|
||||||
|
pad += " ";
|
||||||
|
|
||||||
|
sb.append(pad);
|
||||||
|
|
||||||
|
for (Selector s : r.getSelectors()) {
|
||||||
|
sb.append(RuleDebug.formatSelector(s));
|
||||||
|
sb.append(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sb.length() > 0)
|
||||||
|
sb.setLength(sb.length() - 1);
|
||||||
|
|
||||||
|
sb.append(pad).append(" {").append("\n");
|
||||||
|
|
||||||
|
StyleSet s = new StyleSet();
|
||||||
|
RGB l = null;
|
||||||
|
RGB p = null;
|
||||||
|
if (r.properties().containsKey(CartoCSS.LINE_COLOR)) {
|
||||||
|
l = r.color(null, CartoCSS.LINE_COLOR, RGB.black);
|
||||||
|
}
|
||||||
|
if (r.properties().containsKey(CartoCSS.POLYGON_FILL)) {
|
||||||
|
p = r.color(null, CartoCSS.POLYGON_FILL, RGB.black);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p != null) {
|
||||||
|
s.ri[0] = new Area(mCurLevel++, color(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l != null) {
|
||||||
|
s.ri[1] = new Line(mCurLevel++, color(l), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p != null || l != null) {
|
||||||
|
mStyleSets.put(r, s);
|
||||||
|
out.println("put " + s.ri[0] + s.ri[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map.Entry<String, Object> e : r.properties().entrySet()) {
|
||||||
|
sb.append(pad).append(" ").append(e.getKey()).append(": ").append(e.getValue())
|
||||||
|
.append(";\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Rule nested : r.nested()) {
|
||||||
|
sb.append(formatRule(nested, indent + 2)).append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(pad).append("}");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
Style loadStyle() throws IOException {
|
||||||
|
return Carto.parse(STYLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized RenderInstruction[] matchElement(GeometryType type, TagSet tags,
|
||||||
|
int zoomLevel) {
|
||||||
|
MatcherFeature f = mMatchFeature;
|
||||||
|
|
||||||
|
f.setTags(tags);
|
||||||
|
f.setZoom(zoomLevel);
|
||||||
|
|
||||||
|
RuleList rules = mRules.match(f);
|
||||||
|
|
||||||
|
Rule r = rules.collapse();
|
||||||
|
|
||||||
|
//out.println(r);
|
||||||
|
if (rules.isEmpty())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
int z = r.number(f, "z", 0f).intValue();
|
||||||
|
|
||||||
|
if (type == GeometryType.POLY) {
|
||||||
|
RGB c = r.color(f, CartoCSS.POLYGON_FILL, RGB.black);
|
||||||
|
out.println(z + " " + c);
|
||||||
|
return new RenderInstruction[] {
|
||||||
|
new Area(z, color(c))
|
||||||
|
};
|
||||||
|
|
||||||
|
} else if (type == GeometryType.LINE) {
|
||||||
|
RGB c = r.color(f, CartoCSS.LINE_COLOR, RGB.black);
|
||||||
|
float width = r.number(f, CartoCSS.LINE_WIDTH, 2f);
|
||||||
|
//out.println(z + " " + c);
|
||||||
|
|
||||||
|
return new RenderInstruction[] {
|
||||||
|
new Line(100 + z, color(c), width)
|
||||||
|
};
|
||||||
|
|
||||||
|
} else if (type == GeometryType.POINT) {
|
||||||
|
//RGB c = r.color(f, CartoCSS.MARKER_FILL, RGB.black);
|
||||||
|
//out.println(c);
|
||||||
|
//return new RenderInstruction[] {
|
||||||
|
// new Caption(color(c), width)
|
||||||
|
//};
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int color(RGB rgb) {
|
||||||
|
return rgb.getAlpha() << 24
|
||||||
|
| rgb.getRed() << 16
|
||||||
|
| rgb.getGreen() << 8
|
||||||
|
| rgb.getBlue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLevels() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMapBackground() {
|
||||||
|
return mBackground;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void scaleTextSize(float scaleFactor) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
RenderTheme t = new RenderTheme();
|
||||||
|
|
||||||
|
MapElement e = new MapElement();
|
||||||
|
e.startPolygon();
|
||||||
|
e.tags.add(new Tag("building", "yes"));
|
||||||
|
|
||||||
|
t.matchElement(GeometryType.POLY, e.tags, 16);
|
||||||
|
t.matchElement(GeometryType.POLY, e.tags, 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
74
vtm-jeo/src/org/oscim/theme/carto/RuleDebug.java
Normal file
74
vtm-jeo/src/org/oscim/theme/carto/RuleDebug.java
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
package org.oscim.theme.carto;
|
||||||
|
|
||||||
|
import static java.lang.System.out;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jeo.filter.Filter;
|
||||||
|
import org.jeo.map.Rule;
|
||||||
|
import org.jeo.map.Selector;
|
||||||
|
|
||||||
|
public class RuleDebug {
|
||||||
|
|
||||||
|
static void printRule(Rule r, int level) {
|
||||||
|
|
||||||
|
out.println("> " + level + " >");
|
||||||
|
out.println(formatRule(r, level));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String formatRule(Rule r, int indent) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
String pad = "";
|
||||||
|
for (int i = 0; i < indent; i++) {
|
||||||
|
pad += " ";
|
||||||
|
};
|
||||||
|
|
||||||
|
sb.append(pad);
|
||||||
|
for (Selector s : r.getSelectors()) {
|
||||||
|
sb.append(formatSelector(s));
|
||||||
|
sb.append(",");
|
||||||
|
}
|
||||||
|
if (sb.length() > 0) {
|
||||||
|
sb.setLength(sb.length() - 1);
|
||||||
|
}
|
||||||
|
sb.append(pad).append(" {").append("\n");
|
||||||
|
|
||||||
|
for (Map.Entry<String, Object> e : r.properties().entrySet()) {
|
||||||
|
sb.append(pad).append(" ").append(e.getKey()).append(": ").append(e.getValue())
|
||||||
|
.append(";\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Rule nested : r.nested()) {
|
||||||
|
sb.append(nested.toString(indent + 2)).append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(pad).append("}");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String formatSelector(Selector s) {
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
|
||||||
|
if (s.getName() != null) {
|
||||||
|
sb.append(s.getName());
|
||||||
|
}
|
||||||
|
if (s.getId() != null) {
|
||||||
|
sb.append("#").append(s.getId());
|
||||||
|
}
|
||||||
|
for (String c : s.getClasses()) {
|
||||||
|
sb.append(".").append(c);
|
||||||
|
}
|
||||||
|
if (s.getFilter() != null && s.getFilter() != Filter.TRUE) {
|
||||||
|
sb.append("[").append(s.getFilter()).append("]");
|
||||||
|
}
|
||||||
|
if (s.getAttachment() != null) {
|
||||||
|
sb.append("::").append(s.getAttachment());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s.isWildcard()) {
|
||||||
|
sb.append("*");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user