Create vtm-jts module, closes #53
This commit is contained in:
parent
e74052c164
commit
37ace257cf
@ -1,5 +1,6 @@
|
||||
rootProject.name = 'vtm-parent'
|
||||
include ':vtm'
|
||||
include ':vtm-jts'
|
||||
include ':vtm-tests'
|
||||
include ':vtm-extras'
|
||||
include ':vtm-android'
|
||||
|
@ -4,6 +4,7 @@ dependencies {
|
||||
compile project(':vtm-android')
|
||||
compile project(':vtm-extras')
|
||||
compile project(':vtm-jeo')
|
||||
compile project(':vtm-jts')
|
||||
compile project(':vtm-themes')
|
||||
compile 'com.android.support:support-v4:24.0.0'
|
||||
compile 'com.android.support:appcompat-v7:24.0.0'
|
||||
|
@ -24,7 +24,7 @@ import java.util.ArrayList;
|
||||
import org.oscim.backend.canvas.Color;
|
||||
import org.oscim.core.MapPosition;
|
||||
import org.oscim.event.Event;
|
||||
import org.oscim.layers.PathLayer;
|
||||
import org.oscim.layers.JtsPathLayer;
|
||||
import org.oscim.map.Map.UpdateListener;
|
||||
|
||||
import android.os.Bundle;
|
||||
@ -47,7 +47,7 @@ public class PathOverlayActivity extends BitmapTileMapActivity {
|
||||
mMap.setMapPosition(0, 0, 1 << 2);
|
||||
for (double lat = -90; lat <= 90; lat += 5) {
|
||||
int c = Color.fade(Color.rainbow((float) (lat + 90) / 180), 0.5f);
|
||||
PathLayer pathLayer = new PathLayer(mMap, c, 6);
|
||||
JtsPathLayer pathLayer = new JtsPathLayer(mMap, c, 6);
|
||||
mMap.layers().add(pathLayer);
|
||||
mPathLayers.add(pathLayer);
|
||||
}
|
||||
@ -74,7 +74,7 @@ public class PathOverlayActivity extends BitmapTileMapActivity {
|
||||
mMap.setMapPosition(0, 0, 1 << 2);
|
||||
}
|
||||
|
||||
ArrayList<PathLayer> mPathLayers = new ArrayList<PathLayer>();
|
||||
ArrayList<JtsPathLayer> mPathLayers = new ArrayList<JtsPathLayer>();
|
||||
|
||||
void createLayers(float pos) {
|
||||
|
||||
|
18
vtm-jts/build.gradle
Normal file
18
vtm-jts/build.gradle
Normal file
@ -0,0 +1,18 @@
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'maven'
|
||||
|
||||
dependencies {
|
||||
compile project(':vtm')
|
||||
compile 'com.vividsolutions:jts:1.13'
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs = ['src']
|
||||
}
|
||||
|
||||
// Automated Gradle project deployment to Sonatype OSSRH
|
||||
if (isReleaseVersion && project.hasProperty("SONATYPE_USERNAME")) {
|
||||
afterEvaluate {
|
||||
project.apply from: "${rootProject.projectDir}/deploy.gradle"
|
||||
}
|
||||
}
|
204
vtm-jts/src/org/oscim/layers/JtsPathLayer.java
Normal file
204
vtm-jts/src/org/oscim/layers/JtsPathLayer.java
Normal file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright 2012 osmdroid authors: Viesturs Zarins, Martin Pearman
|
||||
* Copyright 2012 Hannes Janetzek
|
||||
*
|
||||
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oscim.layers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.oscim.core.GeoPoint;
|
||||
import org.oscim.layers.vector.VectorLayer;
|
||||
import org.oscim.layers.vector.geometries.LineDrawable;
|
||||
import org.oscim.layers.vector.geometries.Style;
|
||||
import org.oscim.map.Map;
|
||||
import org.oscim.utils.geom.GeomBuilder;
|
||||
|
||||
import com.vividsolutions.jts.geom.LineString;
|
||||
|
||||
/** This class draws a path line in given color. */
|
||||
public class JtsPathLayer extends VectorLayer {
|
||||
|
||||
protected final ArrayList<GeoPoint> mPoints;
|
||||
|
||||
protected Style mStyle;
|
||||
protected LineDrawable mDrawable;
|
||||
|
||||
public JtsPathLayer(Map map, int lineColor, float lineWidth) {
|
||||
super(map);
|
||||
mStyle = Style.builder()
|
||||
.strokeColor(lineColor)
|
||||
.strokeWidth(lineWidth)
|
||||
.build();
|
||||
|
||||
mPoints = new ArrayList<GeoPoint>();
|
||||
}
|
||||
|
||||
public JtsPathLayer(Map map, int lineColor) {
|
||||
this(map, lineColor, 2);
|
||||
}
|
||||
|
||||
public void setStyle(int lineColor, float lineWidth) {
|
||||
mStyle = Style.builder()
|
||||
.strokeColor(lineColor)
|
||||
.strokeWidth(lineWidth)
|
||||
.build();
|
||||
}
|
||||
|
||||
public void clearPath() {
|
||||
if (!mPoints.isEmpty())
|
||||
mPoints.clear();
|
||||
|
||||
updatePoints();
|
||||
}
|
||||
|
||||
public void setPoints(List<GeoPoint> pts) {
|
||||
mPoints.clear();
|
||||
mPoints.addAll(pts);
|
||||
updatePoints();
|
||||
}
|
||||
|
||||
public void addPoint(GeoPoint pt) {
|
||||
mPoints.add(pt);
|
||||
updatePoints();
|
||||
}
|
||||
|
||||
public void addPoint(int latitudeE6, int longitudeE6) {
|
||||
mPoints.add(new GeoPoint(latitudeE6, longitudeE6));
|
||||
updatePoints();
|
||||
}
|
||||
|
||||
private void updatePoints() {
|
||||
synchronized (this) {
|
||||
|
||||
if (mDrawable != null) {
|
||||
remove(mDrawable);
|
||||
mDrawable = null;
|
||||
}
|
||||
|
||||
if (!mPoints.isEmpty()) {
|
||||
mDrawable = new LineDrawable(mPoints, mStyle);
|
||||
if (mDrawable.getGeometry() == null)
|
||||
mDrawable = null;
|
||||
else
|
||||
add(mDrawable);
|
||||
}
|
||||
}
|
||||
mWorker.submit(0);
|
||||
}
|
||||
|
||||
public List<GeoPoint> getPoints() {
|
||||
return mPoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a great circle. Calculate a point for every 100km along the path.
|
||||
*
|
||||
* @param startPoint
|
||||
* start point of the great circle
|
||||
* @param endPoint
|
||||
* end point of the great circle
|
||||
*/
|
||||
public void addGreatCircle(GeoPoint startPoint, GeoPoint endPoint) {
|
||||
synchronized (mPoints) {
|
||||
|
||||
/* get the great circle path length in meters */
|
||||
double length = startPoint.distanceTo(endPoint);
|
||||
|
||||
/* add one point for every 100kms of the great circle path */
|
||||
int numberOfPoints = (int) (length / 100000);
|
||||
|
||||
addGreatCircle(startPoint, endPoint, numberOfPoints);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a great circle.
|
||||
*
|
||||
* @param startPoint
|
||||
* start point of the great circle
|
||||
* @param endPoint
|
||||
* end point of the great circle
|
||||
* @param numberOfPoints
|
||||
* number of points to calculate along the path
|
||||
*/
|
||||
public void addGreatCircle(GeoPoint startPoint, GeoPoint endPoint,
|
||||
final int numberOfPoints) {
|
||||
/* adapted from page
|
||||
* http://compastic.blogspot.co.uk/2011/07/how-to-draw-great-circle-on-map
|
||||
* -in.html
|
||||
* which was adapted from page http://maps.forum.nu/gm_flight_path.html */
|
||||
|
||||
GeomBuilder gb = new GeomBuilder();
|
||||
|
||||
/* convert to radians */
|
||||
double lat1 = startPoint.getLatitude() * Math.PI / 180;
|
||||
double lon1 = startPoint.getLongitude() * Math.PI / 180;
|
||||
double lat2 = endPoint.getLatitude() * Math.PI / 180;
|
||||
double lon2 = endPoint.getLongitude() * Math.PI / 180;
|
||||
|
||||
double d = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin((lat1 - lat2) / 2), 2)
|
||||
+ Math.cos(lat1) * Math.cos(lat2)
|
||||
* Math.pow(Math.sin((lon1 - lon2) / 2), 2)));
|
||||
double bearing = Math.atan2(
|
||||
Math.sin(lon1 - lon2) * Math.cos(lat2),
|
||||
Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
|
||||
* Math.cos(lat2)
|
||||
* Math.cos(lon1 - lon2))
|
||||
/ -(Math.PI / 180);
|
||||
bearing = bearing < 0 ? 360 + bearing : bearing;
|
||||
|
||||
for (int i = 0, j = numberOfPoints + 1; i < j; i++) {
|
||||
double f = 1.0 / numberOfPoints * i;
|
||||
double A = Math.sin((1 - f) * d) / Math.sin(d);
|
||||
double B = Math.sin(f * d) / Math.sin(d);
|
||||
double x = A * Math.cos(lat1) * Math.cos(lon1) + B * Math.cos(lat2)
|
||||
* Math.cos(lon2);
|
||||
double y = A * Math.cos(lat1) * Math.sin(lon1) + B * Math.cos(lat2)
|
||||
* Math.sin(lon2);
|
||||
double z = A * Math.sin(lat1) + B * Math.sin(lat2);
|
||||
|
||||
double latN = Math.atan2(z, Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)));
|
||||
double lonN = Math.atan2(y, x);
|
||||
|
||||
gb.point(latN / (Math.PI / 180), lonN / (Math.PI / 180));
|
||||
}
|
||||
|
||||
setLineString(gb.toLineString());
|
||||
}
|
||||
|
||||
public void setLineString(LineString path) {
|
||||
synchronized (this) {
|
||||
if (mDrawable != null)
|
||||
remove(mDrawable);
|
||||
mDrawable = new LineDrawable(path, mStyle);
|
||||
add(mDrawable);
|
||||
}
|
||||
mWorker.submit(0);
|
||||
}
|
||||
|
||||
public void setLineString(double[] lonLat) {
|
||||
synchronized (this) {
|
||||
if (mDrawable != null)
|
||||
remove(mDrawable);
|
||||
mDrawable = new LineDrawable(lonLat, mStyle);
|
||||
add(mDrawable);
|
||||
}
|
||||
mWorker.submit(0);
|
||||
}
|
||||
|
||||
}
|
@ -5,6 +5,7 @@ dependencies {
|
||||
compile project(':vtm-desktop')
|
||||
compile project(':vtm-extras')
|
||||
compile project(':vtm-jeo')
|
||||
compile project(':vtm-jts')
|
||||
runtime 'com.squareup.okhttp:okhttp:1.5.2'
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ import org.oscim.core.GeoPoint;
|
||||
import org.oscim.core.MapPosition;
|
||||
import org.oscim.event.Event;
|
||||
import org.oscim.gdx.GdxMapApp;
|
||||
import org.oscim.layers.PathLayer;
|
||||
import org.oscim.layers.JtsPathLayer;
|
||||
import org.oscim.map.Map;
|
||||
import org.oscim.map.Map.UpdateListener;
|
||||
|
||||
@ -33,7 +33,7 @@ public class PathLayerTest extends GdxMapApp {
|
||||
});
|
||||
}
|
||||
|
||||
ArrayList<PathLayer> mPathLayers = new ArrayList<PathLayer>();
|
||||
ArrayList<JtsPathLayer> mPathLayers = new ArrayList<JtsPathLayer>();
|
||||
|
||||
void createLayers(float pos, boolean init) {
|
||||
|
||||
@ -61,10 +61,10 @@ public class PathLayerTest extends GdxMapApp {
|
||||
|
||||
pts.add(new GeoPoint(latitude, longitude));
|
||||
}
|
||||
PathLayer pathLayer;
|
||||
JtsPathLayer pathLayer;
|
||||
if (init) {
|
||||
int c = Color.fade(Color.rainbow((float) (lat + 90) / 180), 0.5f);
|
||||
pathLayer = new PathLayer(mMap, c, 6);
|
||||
pathLayer = new JtsPathLayer(mMap, c, 6);
|
||||
mMap.layers().add(pathLayer);
|
||||
mPathLayers.add(pathLayer);
|
||||
} else {
|
||||
|
@ -4,7 +4,6 @@ apply plugin: 'maven'
|
||||
configurations { providedCompile }
|
||||
|
||||
dependencies {
|
||||
compile 'com.vividsolutions:jts:1.13'
|
||||
compile 'org.slf4j:slf4j-api:1.7.21'
|
||||
providedCompile 'com.google.code.findbugs:annotations:2.0.1'
|
||||
providedCompile 'com.squareup.okhttp:okhttp:1.5.2'
|
||||
|
@ -21,30 +21,39 @@ package org.oscim.layers;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.oscim.backend.canvas.Paint.Cap;
|
||||
import org.oscim.core.GeoPoint;
|
||||
import org.oscim.layers.vector.VectorLayer;
|
||||
import org.oscim.layers.vector.geometries.LineDrawable;
|
||||
import org.oscim.layers.vector.geometries.Style;
|
||||
import org.oscim.core.GeometryBuffer;
|
||||
import org.oscim.core.MapPosition;
|
||||
import org.oscim.core.MercatorProjection;
|
||||
import org.oscim.core.Tile;
|
||||
import org.oscim.map.Map;
|
||||
import org.oscim.utils.geom.GeomBuilder;
|
||||
|
||||
import com.vividsolutions.jts.geom.LineString;
|
||||
import org.oscim.renderer.BucketRenderer;
|
||||
import org.oscim.renderer.GLViewport;
|
||||
import org.oscim.renderer.bucket.LineBucket;
|
||||
import org.oscim.renderer.bucket.RenderBuckets;
|
||||
import org.oscim.theme.styles.LineStyle;
|
||||
import org.oscim.utils.FastMath;
|
||||
import org.oscim.utils.async.SimpleWorker;
|
||||
import org.oscim.utils.geom.LineClipper;
|
||||
|
||||
/** This class draws a path line in given color. */
|
||||
public class PathLayer extends VectorLayer {
|
||||
public class PathLayer extends Layer {
|
||||
|
||||
/** Stores points, converted to the map projection. */
|
||||
protected final ArrayList<GeoPoint> mPoints;
|
||||
protected boolean mUpdatePoints;
|
||||
|
||||
protected Style mStyle;
|
||||
protected LineDrawable mDrawable;
|
||||
/** Line style */
|
||||
LineStyle mLineStyle;
|
||||
|
||||
final Worker mWorker;
|
||||
|
||||
public PathLayer(Map map, int lineColor, float lineWidth) {
|
||||
super(map);
|
||||
mStyle = Style.builder()
|
||||
.strokeColor(lineColor)
|
||||
.strokeWidth(lineWidth)
|
||||
.build();
|
||||
|
||||
mWorker = new Worker(map);
|
||||
mLineStyle = new LineStyle(lineColor, lineWidth, Cap.BUTT);
|
||||
mRenderer = new RenderPath();
|
||||
mPoints = new ArrayList<GeoPoint>();
|
||||
}
|
||||
|
||||
@ -52,62 +61,63 @@ public class PathLayer extends VectorLayer {
|
||||
this(map, lineColor, 2);
|
||||
}
|
||||
|
||||
public void setStyle(int lineColor, float lineWidth) {
|
||||
mStyle = Style.builder()
|
||||
.strokeColor(lineColor)
|
||||
.strokeWidth(lineWidth)
|
||||
.build();
|
||||
}
|
||||
|
||||
public void clearPath() {
|
||||
if (!mPoints.isEmpty())
|
||||
mPoints.clear();
|
||||
if (mPoints.isEmpty())
|
||||
return;
|
||||
|
||||
synchronized (mPoints) {
|
||||
mPoints.clear();
|
||||
}
|
||||
updatePoints();
|
||||
}
|
||||
|
||||
public void setPoints(List<GeoPoint> pts) {
|
||||
mPoints.clear();
|
||||
mPoints.addAll(pts);
|
||||
synchronized (mPoints) {
|
||||
mPoints.clear();
|
||||
mPoints.addAll(pts);
|
||||
}
|
||||
updatePoints();
|
||||
}
|
||||
|
||||
public void addPoint(GeoPoint pt) {
|
||||
mPoints.add(pt);
|
||||
synchronized (mPoints) {
|
||||
mPoints.add(pt);
|
||||
}
|
||||
updatePoints();
|
||||
}
|
||||
|
||||
public void addPoint(int latitudeE6, int longitudeE6) {
|
||||
mPoints.add(new GeoPoint(latitudeE6, longitudeE6));
|
||||
synchronized (mPoints) {
|
||||
mPoints.add(new GeoPoint(latitudeE6, longitudeE6));
|
||||
}
|
||||
updatePoints();
|
||||
}
|
||||
|
||||
private void updatePoints() {
|
||||
synchronized (this) {
|
||||
|
||||
if (mDrawable != null) {
|
||||
remove(mDrawable);
|
||||
mDrawable = null;
|
||||
}
|
||||
|
||||
if (!mPoints.isEmpty()) {
|
||||
mDrawable = new LineDrawable(mPoints, mStyle);
|
||||
if (mDrawable.getGeometry() == null)
|
||||
mDrawable = null;
|
||||
else
|
||||
add(mDrawable);
|
||||
}
|
||||
}
|
||||
mWorker.submit(0);
|
||||
mWorker.submit(10);
|
||||
mUpdatePoints = true;
|
||||
}
|
||||
|
||||
public List<GeoPoint> getPoints() {
|
||||
return mPoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* FIXME To be removed
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
*/
|
||||
public void setGeom(GeometryBuffer geom) {
|
||||
mGeom = geom;
|
||||
mWorker.submit(10);
|
||||
}
|
||||
|
||||
GeometryBuffer mGeom;
|
||||
|
||||
/**
|
||||
* Draw a great circle. Calculate a point for every 100km along the path.
|
||||
*
|
||||
*
|
||||
* @param startPoint
|
||||
* start point of the great circle
|
||||
* @param endPoint
|
||||
@ -128,7 +138,7 @@ public class PathLayer extends VectorLayer {
|
||||
|
||||
/**
|
||||
* Draw a great circle.
|
||||
*
|
||||
*
|
||||
* @param startPoint
|
||||
* start point of the great circle
|
||||
* @param endPoint
|
||||
@ -137,29 +147,26 @@ public class PathLayer extends VectorLayer {
|
||||
* number of points to calculate along the path
|
||||
*/
|
||||
public void addGreatCircle(GeoPoint startPoint, GeoPoint endPoint,
|
||||
final int numberOfPoints) {
|
||||
/* adapted from page
|
||||
* http://compastic.blogspot.co.uk/2011/07/how-to-draw-great-circle-on-map
|
||||
* -in.html
|
||||
* which was adapted from page http://maps.forum.nu/gm_flight_path.html */
|
||||
final int numberOfPoints) {
|
||||
// adapted from page
|
||||
// http://compastic.blogspot.co.uk/2011/07/how-to-draw-great-circle-on-map-in.html
|
||||
// which was adapted from page http://maps.forum.nu/gm_flight_path.html
|
||||
|
||||
GeomBuilder gb = new GeomBuilder();
|
||||
|
||||
/* convert to radians */
|
||||
// convert to radians
|
||||
double lat1 = startPoint.getLatitude() * Math.PI / 180;
|
||||
double lon1 = startPoint.getLongitude() * Math.PI / 180;
|
||||
double lat2 = endPoint.getLatitude() * Math.PI / 180;
|
||||
double lon2 = endPoint.getLongitude() * Math.PI / 180;
|
||||
|
||||
double d = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin((lat1 - lat2) / 2), 2)
|
||||
+ Math.cos(lat1) * Math.cos(lat2)
|
||||
* Math.pow(Math.sin((lon1 - lon2) / 2), 2)));
|
||||
+ Math.cos(lat1) * Math.cos(lat2)
|
||||
* Math.pow(Math.sin((lon1 - lon2) / 2), 2)));
|
||||
double bearing = Math.atan2(
|
||||
Math.sin(lon1 - lon2) * Math.cos(lat2),
|
||||
Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
|
||||
* Math.cos(lat2)
|
||||
* Math.cos(lon1 - lon2))
|
||||
/ -(Math.PI / 180);
|
||||
Math.sin(lon1 - lon2) * Math.cos(lat2),
|
||||
Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
|
||||
* Math.cos(lat2)
|
||||
* Math.cos(lon1 - lon2))
|
||||
/ -(Math.PI / 180);
|
||||
bearing = bearing < 0 ? 360 + bearing : bearing;
|
||||
|
||||
for (int i = 0, j = numberOfPoints + 1; i < j; i++) {
|
||||
@ -167,38 +174,237 @@ public class PathLayer extends VectorLayer {
|
||||
double A = Math.sin((1 - f) * d) / Math.sin(d);
|
||||
double B = Math.sin(f * d) / Math.sin(d);
|
||||
double x = A * Math.cos(lat1) * Math.cos(lon1) + B * Math.cos(lat2)
|
||||
* Math.cos(lon2);
|
||||
* Math.cos(lon2);
|
||||
double y = A * Math.cos(lat1) * Math.sin(lon1) + B * Math.cos(lat2)
|
||||
* Math.sin(lon2);
|
||||
* Math.sin(lon2);
|
||||
double z = A * Math.sin(lat1) + B * Math.sin(lat2);
|
||||
|
||||
double latN = Math.atan2(z, Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)));
|
||||
double lonN = Math.atan2(y, x);
|
||||
|
||||
gb.point(latN / (Math.PI / 180), lonN / (Math.PI / 180));
|
||||
addPoint((int) (latN / (Math.PI / 180) * 1E6), (int) (lonN / (Math.PI / 180) * 1E6));
|
||||
}
|
||||
|
||||
setLineString(gb.toLineString());
|
||||
}
|
||||
|
||||
public void setLineString(LineString path) {
|
||||
synchronized (this) {
|
||||
if (mDrawable != null)
|
||||
remove(mDrawable);
|
||||
mDrawable = new LineDrawable(path, mStyle);
|
||||
add(mDrawable);
|
||||
/***
|
||||
* everything below runs on GL- and Worker-Thread
|
||||
***/
|
||||
final class RenderPath extends BucketRenderer {
|
||||
|
||||
public RenderPath() {
|
||||
|
||||
buckets.addLineBucket(0, mLineStyle);
|
||||
}
|
||||
|
||||
private int mCurX = -1;
|
||||
private int mCurY = -1;
|
||||
private int mCurZ = -1;
|
||||
|
||||
@Override
|
||||
public synchronized void update(GLViewport v) {
|
||||
int tz = 1 << v.pos.zoomLevel;
|
||||
int tx = (int) (v.pos.x * tz);
|
||||
int ty = (int) (v.pos.y * tz);
|
||||
|
||||
// update layers when map moved by at least one tile
|
||||
if ((tx != mCurX || ty != mCurY || tz != mCurZ)) {
|
||||
mWorker.submit(100);
|
||||
mCurX = tx;
|
||||
mCurY = ty;
|
||||
mCurZ = tz;
|
||||
}
|
||||
|
||||
Task t = mWorker.poll();
|
||||
if (t == null)
|
||||
return;
|
||||
|
||||
// keep position to render relative to current state
|
||||
mMapPosition.copy(t.pos);
|
||||
|
||||
// compile new layers
|
||||
buckets.set(t.bucket.get());
|
||||
compile();
|
||||
}
|
||||
mWorker.submit(0);
|
||||
}
|
||||
|
||||
public void setLineString(double[] lonLat) {
|
||||
synchronized (this) {
|
||||
if (mDrawable != null)
|
||||
remove(mDrawable);
|
||||
mDrawable = new LineDrawable(lonLat, mStyle);
|
||||
add(mDrawable);
|
||||
}
|
||||
mWorker.submit(0);
|
||||
final static class Task {
|
||||
RenderBuckets bucket = new RenderBuckets();
|
||||
MapPosition pos = new MapPosition();
|
||||
}
|
||||
|
||||
final class Worker extends SimpleWorker<Task> {
|
||||
|
||||
// limit coords
|
||||
private final int max = 2048;
|
||||
|
||||
public Worker(Map map) {
|
||||
super(map, 0, new Task(), new Task());
|
||||
mClipper = new LineClipper(-max, -max, max, max);
|
||||
mPPoints = new float[0];
|
||||
}
|
||||
|
||||
private static final int MIN_DIST = 3;
|
||||
|
||||
// pre-projected points
|
||||
private double[] mPreprojected = new double[2];
|
||||
|
||||
// projected points
|
||||
private float[] mPPoints;
|
||||
private final LineClipper mClipper;
|
||||
private int mNumPoints;
|
||||
|
||||
@Override
|
||||
public boolean doWork(Task task) {
|
||||
|
||||
int size = mNumPoints;
|
||||
|
||||
if (mUpdatePoints) {
|
||||
synchronized (mPoints) {
|
||||
mUpdatePoints = false;
|
||||
mNumPoints = size = mPoints.size();
|
||||
|
||||
ArrayList<GeoPoint> geopoints = mPoints;
|
||||
double[] points = mPreprojected;
|
||||
|
||||
if (size * 2 >= points.length) {
|
||||
points = mPreprojected = new double[size * 2];
|
||||
mPPoints = new float[size * 2];
|
||||
}
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
MercatorProjection.project(geopoints.get(i), points, i);
|
||||
}
|
||||
|
||||
} else if (mGeom != null) {
|
||||
GeometryBuffer geom = mGeom;
|
||||
mGeom = null;
|
||||
size = geom.index[0];
|
||||
|
||||
double[] points = mPreprojected;
|
||||
|
||||
if (size > points.length) {
|
||||
points = mPreprojected = new double[size * 2];
|
||||
mPPoints = new float[size * 2];
|
||||
}
|
||||
|
||||
for (int i = 0; i < size; i += 2)
|
||||
MercatorProjection.project(geom.points[i + 1],
|
||||
geom.points[i], points,
|
||||
i >> 1);
|
||||
mNumPoints = size = size >> 1;
|
||||
|
||||
}
|
||||
if (size == 0) {
|
||||
if (task.bucket.get() != null) {
|
||||
task.bucket.clear();
|
||||
mMap.render();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
RenderBuckets layers = task.bucket;
|
||||
|
||||
LineBucket ll = layers.getLineBucket(0);
|
||||
ll.line = mLineStyle;
|
||||
ll.scale = ll.line.width;
|
||||
|
||||
mMap.getMapPosition(task.pos);
|
||||
|
||||
int zoomlevel = task.pos.zoomLevel;
|
||||
task.pos.scale = 1 << zoomlevel;
|
||||
|
||||
double mx = task.pos.x;
|
||||
double my = task.pos.y;
|
||||
double scale = Tile.SIZE * task.pos.scale;
|
||||
|
||||
// flip around dateline
|
||||
int flip = 0;
|
||||
int maxx = Tile.SIZE << (zoomlevel - 1);
|
||||
|
||||
int x = (int) ((mPreprojected[0] - mx) * scale);
|
||||
int y = (int) ((mPreprojected[1] - my) * scale);
|
||||
|
||||
if (x > maxx) {
|
||||
x -= (maxx * 2);
|
||||
flip = -1;
|
||||
} else if (x < -maxx) {
|
||||
x += (maxx * 2);
|
||||
flip = 1;
|
||||
}
|
||||
|
||||
mClipper.clipStart(x, y);
|
||||
|
||||
float[] projected = mPPoints;
|
||||
int i = addPoint(projected, 0, x, y);
|
||||
|
||||
float prevX = x;
|
||||
float prevY = y;
|
||||
|
||||
float[] segment = null;
|
||||
|
||||
for (int j = 2; j < size * 2; j += 2) {
|
||||
x = (int) ((mPreprojected[j + 0] - mx) * scale);
|
||||
y = (int) ((mPreprojected[j + 1] - my) * scale);
|
||||
|
||||
int flipDirection = 0;
|
||||
if (x > maxx) {
|
||||
x -= maxx * 2;
|
||||
flipDirection = -1;
|
||||
} else if (x < -maxx) {
|
||||
x += maxx * 2;
|
||||
flipDirection = 1;
|
||||
}
|
||||
|
||||
if (flip != flipDirection) {
|
||||
flip = flipDirection;
|
||||
if (i > 2)
|
||||
ll.addLine(projected, i, false);
|
||||
|
||||
mClipper.clipStart(x, y);
|
||||
i = addPoint(projected, 0, x, y);
|
||||
continue;
|
||||
}
|
||||
|
||||
int clip = mClipper.clipNext(x, y);
|
||||
if (clip < 1) {
|
||||
if (i > 2)
|
||||
ll.addLine(projected, i, false);
|
||||
|
||||
if (clip < 0) {
|
||||
/* add line segment */
|
||||
segment = mClipper.getLine(segment, 0);
|
||||
ll.addLine(segment, 4, false);
|
||||
prevX = mClipper.outX2;
|
||||
prevY = mClipper.outY2;
|
||||
}
|
||||
i = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
float dx = x - prevX;
|
||||
float dy = y - prevY;
|
||||
if ((i == 0) || FastMath.absMaxCmp(dx, dy, MIN_DIST)) {
|
||||
projected[i++] = prevX = x;
|
||||
projected[i++] = prevY = y;
|
||||
}
|
||||
}
|
||||
if (i > 2)
|
||||
ll.addLine(projected, i, false);
|
||||
|
||||
// trigger redraw to let renderer fetch the result.
|
||||
mMap.render();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup(Task task) {
|
||||
task.bucket.clear();
|
||||
}
|
||||
|
||||
private int addPoint(float[] points, int i, int x, int y) {
|
||||
points[i++] = x;
|
||||
points[i++] = y;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user