Limit Scrolling on offline maps, in Android - android

I got these piece of codes or patches from osmdroid, and I decided to ask for your help guys because i don't have the enough knowledge to combine these codes to come up with on a solution on my problem, Scrolling limit on an offline map. I searched across the web, and modified tutorials. Honestly I tried to modify these codes but i have not found any progress. Basically I have an offline map from mapnik, and a few overlays. I don't know where to properly place these set of codes. Your ideas and modification will be a great help and also helps me keep going with my project and I guess your answers will definitely help others with the same problem as mine in the future. I know this is to much. Thank you sirs for your time, and God Bless.
public void onCreate(Bundle savedInstanceState) {
...
...
m_mapView = (MapView) findViewById(R.id.mapview);
m_mapView.setTileSource(TileSourceFactory.MAPNIK);
}
First: BoundingBox
BoundingBoxE6 bbox = new BoundingBoxE6(9.37398, 123.33761, 9.23948, 123.25035);
this.setScrollableAreaLimit(bbox);
Second: LimitScrollToGeographicArea.patch
Index: MapView.java
===================================================================
--- MapView.java (revision 944)
+++ MapView.java (working copy)
## -103,6 +103,8 ##
protected MapListener mListener;
+ protected Rect mScrollableAreaLimit;
+
// for speed (avoiding allocations)
private final Matrix mMatrix = new Matrix();
private final MapTileProviderBase mTileProvider;
## -505,6 +507,36 ##
mMapOverlay.setUseDataConnection(aMode);
}
+ /**
+ * Set the map to limit it's scrollable view to the specified BoundingBoxE6. Note that, like
+ * North/South bounds limiting, this allows an overscroll of half the screen size. This means
+ * each border can be scrolled to the center of the screen.
+ *
+ * #param boundingBox
+ * A lat/long bounding box to limit scrolling to, or null to remove any scrolling
+ * limitations
+ */
+ public void setScrollableAreaLimit(BoundingBoxE6 boundingBox) {
+ final int worldSize_2 = TileSystem.MapSize(MapViewConstants.MAXIMUM_ZOOMLEVEL) / 2;
+
+ // Clear scrollable area limit if null passed.
+ if (boundingBox == null) {
+ mScrollableAreaLimit = null;
+ return;
+ }
+
+ // Get NW/upper-left
+ final Point upperLeft = TileSystem.LatLongToPixelXY(boundingBox.getLatNorthE6() / 1E6,
+ boundingBox.getLonWestE6() / 1E6, MapViewConstants.MAXIMUM_ZOOMLEVEL, null);
+ upperLeft.offset(-worldSize_2, -worldSize_2);
+
+ // Get SE/lower-right
+ final Point lowerRight = TileSystem.LatLongToPixelXY(boundingBox.getLatSouthE6() / 1E6,
+ boundingBox.getLonEastE6() / 1E6, MapViewConstants.MAXIMUM_ZOOMLEVEL, null);
+ lowerRight.offset(-worldSize_2, -worldSize_2);
+ mScrollableAreaLimit = new Rect(upperLeft.x, upperLeft.y, lowerRight.x, lowerRight.y);
+ }
+
// ===========================================================
// Methods from SuperClass/Interfaces
// ===========================================================
## -772,10 +804,26 ##
//I am confused with these codes below, where should I declare it? Int x, y in the onCreate method?
x += (worldSize_2 * 2);
while (x > worldSize_2)
x -= (worldSize_2 * 2);
- while (y < -worldSize_2)
- y += (worldSize_2 * 2);
- while (y > worldSize_2)
- y -= (worldSize_2 * 2);
+ if (y < -worldSize_2)
+ y = -worldSize_2;
+ if (y > worldSize_2)
+ y = worldSize_2;
+
+ if (mScrollableAreaLimit != null) {
+ final int zoomDiff = MapViewConstants.MAXIMUM_ZOOMLEVEL - getZoomLevel();
+ final int minX = mScrollableAreaLimit.left >> zoomDiff;
+ final int minY = mScrollableAreaLimit.top >> zoomDiff;
+ final int maxX = mScrollableAreaLimit.right >> zoomDiff;
+ final int maxY = mScrollableAreaLimit.bottom >> zoomDiff;
+ if (x < minX)
+ x = minX;
+ else if (x > maxX)
+ x = maxX;
+ if (y < minY)
+ y = minY;
+ else if (y > maxY)
+ y = maxY;
+ }
super.scrollTo(x, y);
// do callback on listener
Another one:
scrollToMethod
public void scrollTo(int x, int y) {
int curZoomLevel = mZoomLevel;
final int worldSize_2 = TileSystem.MapSize(curZoomLevel) / 2;
Log.v("HELP", "Scrolling to X=" + x + " Y=" + y + " ZL=" + curZoomLevel + " - WW="+worldSize_2);
while (x < -worldSize_2)
x += (worldSize_2 * 2);
while (x > worldSize_2)
x -= (worldSize_2 * 2);
if (y < -worldSize_2)
y = -worldSize_2;
if (y > worldSize_2)
y = worldSize_2;
if (mScrollableAreaLimit != null) {
int targetZoomLevel = getZoomLevel();
final int zoomDiff = MapViewConstants.MAXIMUM_ZOOMLEVEL - targetZoomLevel;
//final int zoomDiff = MapViewConstants.MAXIMUM_ZOOMLEVEL - mZoomLevel;
final int minX = mScrollableAreaLimit.left >> zoomDiff;
final int minY = mScrollableAreaLimit.top >> zoomDiff;
final int maxX = mScrollableAreaLimit.right >> zoomDiff;
final int maxY = mScrollableAreaLimit.bottom >> zoomDiff;
Log.v("HELP", "Limit: minX=" + minX + " maxX=" + maxX + " minY=" + minY + " maxY=" + maxY + " ZL=" + curZoomLevel + " ZLTarget="+ targetZoomLevel + " ZD="+zoomDiff);
if (x < minX) {
Log.v("HELP", "!!! X=" + x + " minX=" + minX + " CORRECTION:" + (minX-x));
x = minX;
} else if (x > maxX) {
Log.v("HELP", "!!! X=" + x + " maxX=" + maxX + " CORRECTION:" + (maxX-x));
x = maxX;
}
if (y < minY) {
Log.v("HELP", "!!! Y=" + y + " minY=" + minY + " CORRECTION:" + (minY-y));
y = minY;
} else if (y > maxY) {
Log.v("HELP", "!!! Y=" + y + " maxY=" + maxY + " CORRECTION:" + (maxY-y));
y = maxY;
}
}
super.scrollTo(x, y);
// do callback on listener
if (mListener != null) {
final ScrollEvent event = new ScrollEvent(this, x, y);
mListener.onScroll(event);
}
}

First of all use this command on your terminal:
svn checkout http://osmdroid.googlecode.com/svn/branches/release_3_0_5
It will download a stable version
Then follow this to import contents of the folder you downloaded:
In Eclipse, right-click on the Package area, and select the following:
click on Import...
select General -> Existing Projects into Workspace
click Next
click Browse...
select the checked out projects' directories
osmdroid-android (import as a java project)
OSMMapTilePackager (import as a java project)
OpenStreetMapViewer (mport as an android project)
click OK
click Finish
Now open this java file-->
osmdroid-android/src/org/osmdroid/view/MapView.java
Now as stated in this patch file, modify MapView.java ( add
code wherever + , remove code wherever -)
Also modify computeScroll() in MapView.java as stated here
Now, to use this modified .java file, you need to create a new jar
file that you can include in your project
Here is a step by step process to create jar
Add this newly created jar file to your project's build path and you
are ready to use your modified jar
Now use this in your activity class:
BoundingBoxE6 bbox = new BoundingBoxE6(limit north, limit east, limit south, limit west);
mapView.setScrollableAreaLimit(bbox);

Related

Crop YUV byte[] based on a rectangle without any convertion

I have tried to use the logic and pictorial representation from this SO. I am though confused with the images since one of them follow 4:1:1 whereas the later one does 4:2:2 nomenclature for YUV image (NV21).
Right now the issue is that i get an image (converted to Bitmap/PNG) with YUV component all over, essentially an unusable image.
Any recommendation to fix this?
private byte[] cropImage(byte[] data, Rect cropRect) {
int dataHeight = 480;
int dataWidth = 640;
int totalWH = dataWidth * dataHeight;
// make rect points even, currently the width & height is even number
// adjust x coordinates to make them
if (cropRect.left % 2 != 0 || cropRect.right % 2 != 0) {
cropRect.left -= 1;
cropRect.right -= 1;
}
// adjust y coordinates to make them even
if (cropRect.top % 2 != 0 || cropRect.bottom % 2 != 0) {
cropRect.top -= 1;
cropRect.bottom -= 1;
}
int area = cropRect.width() * cropRect.height() * 3/2;
Logger.getLogger().d("Size of byte array " + data.length + " Size of alloc area " + area);
byte[] pixels = new byte[area];//the size of the array is the dimensions of the sub-photo
// size.total = size.width * size.height;
// y = yuv[position.y * size.width + position.x];
// u = yuv[(position.y / 2) * (size.width / 2) + (position.x / 2) + size.total];
// v = yuv[(position.y / 2) * (size.width / 2) + (position.x / 2) + size.total + (size.total / 4)];
try {
// copy Y plane first
int srcOffset = cropRect.top * dataWidth;
int destOffset = 0;
int lengthToCopy = cropRect.width();
int y = 0;
for (; y < cropRect.height(); y++, srcOffset += dataWidth, destOffset += cropRect.width()) {
// Logger.getLogger().d("IO " + srcOffset + cropRect.left + " oO " + destOffset + " LTC " + lengthToCopy);
System.arraycopy(data, srcOffset + cropRect.left, pixels, destOffset, lengthToCopy);
}
Logger.getLogger().d("Completed Y copy");
// U and V components are not-interleaved, hence their size is just 1/4th the original size
// copy U plane
int nonYPlanerHeight = dataHeight / 4;
int nonYPlanerWidth = dataWidth / 4;
srcOffset = totalWH + (cropRect.top / 4 * nonYPlanerWidth);
for (y = 0; y < cropRect.height();
y++, srcOffset += nonYPlanerWidth, destOffset += cropRect.width() / 4) {
System.arraycopy(data, srcOffset + cropRect.left / 4, pixels, destOffset, cropRect.width() / 4);
}
Logger.getLogger().d("Completed U copy " + y + " destOffset=" + destOffset);
// copy V plane
srcOffset = totalWH + totalWH / 4 + (cropRect.top / 4 * nonYPlanerWidth);
for (y = 0; y < cropRect.height();
y++, srcOffset += nonYPlanerWidth, destOffset += cropRect.width() / 4) {
System.arraycopy(data, srcOffset + cropRect.left / 4, pixels, destOffset, cropRect.width() / 4);
}
Logger.getLogger().d("Completed V copy " + y + " destOffset=" + destOffset);
} catch (ArrayIndexOutOfBoundsException ae) {
// do nothing
Logger.getLogger().e("Exception " + ae.getLocalizedMessage());
}
return pixels;
}

libgdx - find the coordinates different from the point of origin?

I 'd like someone to advise me a way to find the coordinates of a point on a sprite in libgdx .
As you can see from the image I have set the sprite with the point of origin on the red dot , and I can not change it.
I would leave the red dot as the source and find the coordinates of the green on the same sprite .
Thanks for your help.
EDIT
#Override
public void create () {
img = new Texture("rocket.png");
font = new BitmapFont();
font.setColor(Color.BLUE);
MyInputProcessor inputProcessor = new MyInputProcessor();
Gdx.input.setInputProcessor(inputProcessor);
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
sprite = new Sprite(img);
spacesprite = new Sprite(new Texture(Gdx.files.internal("space.jpg")));
spacesprite.setPosition(0,0);
spacesprite.setSize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
point = new Sprite(new Texture(Gdx.files.internal("point.png")));
batch = new SpriteBatch();
}
#Override
public void render () {
sprite.setPosition(Gdx.graphics.getWidth() / 2 - sprite.getWidth()/2, Gdx.graphics.getHeight() / 2 - sprite.getHeight()/2);
sprite.setOrigin(sprite.getWidth()/2, sprite.getHeight()/2);
point.setPosition(sprite.getX() + sprite.getWidth()/2 - point.getWidth()/2, sprite.getY() + sprite.getHeight()/2);
point.setOrigin(point.getWidth()/2, 0);
if(Gdx.input.isButtonPressed(Input.Buttons.LEFT)){
//sprite.setPosition(Gdx.input.getX() - sprite.getWidth()/2, Gdx.graphics.getHeight() - Gdx.input.getY() - sprite.getHeight()/2);
if(Gdx.input.getX() < Gdx.graphics.getWidth() / 2)
{
//System.out.println("x: " + Gdx.input.getX() + " - y: " + Gdx.input.getY());
sprite.setRotation(rotation++);
point.setRotation(rotation++);
System.out.println("Sprite: X" + sprite.getX() + " - Y:" + sprite.getY());
}
else
{
//System.out.println("x: " + Gdx.input.getX() + " - y: " + Gdx.input.getY());
sprite.setRotation(rotation--);
point.setRotation(rotation--);
System.out.println("Sprite: X" + sprite.getX() + " - Y:" + sprite.getY());
}
}
batch.begin();
spacesprite.draw(batch);
sprite.draw(batch);
point.draw(batch);
batch.end();
}
someone can adapt the code , when I rotate I'd get the position , but they are insecure about my implementation .
if you're looking for a middle point on the rectangular sprite, try something like this:
float x = obj.getOriginX() + obj.getHeight();
float y = obj.getOriginY() + obj.getWidth() / 2;
Either use Gonio, matrix or quaternions to calculate the rotated coordinates.
For a few simple calculations I'd use gonio, something like:
float angle_rad = sprite.getRotation() / 180.0f * PI;
float rotated_x = Math.sin(angle_rad) * y + Math.cos(angle_rad) * x;
float rotated_y = Math.sin(angle_rad) * x + Math.cos(angle_rad) * y;
If you have to do this more often look into matrices or quaternions, matrices are a little easier though: http://en.wikipedia.org/wiki/Rotation_matrix

Google Map API making lines smoother when bending

I am using Google Map API to get lines on the map in my application. I am loading the nodes of the lines from a database using following code:
// Add polyline "walks voda"
List<WalkLine> dbwalknodes = dbclass.queryWalksFromDatabase(this); // list of latlng
for (int i = 0; i < dbwalknodes.size() - 1 ; i++) {
WalkLine source = dbwalknodes.get(i);
WalkLine destination = dbwalknodes.get(i+1);
Polyline line = mMap.addPolyline(new PolylineOptions()
.add(new LatLng(source.getLat(), source.getLon()),
new LatLng(destination.getLat(), destination.getLon()))
.width(16)
.color(Color.parseColor("#1b9e77"))
.geodesic(true));
line.setZIndex(1000);
}
Do you have any idea how to create the lines smoother while it bends than on the picture bellow? Is it possible?
https://www.dropbox.com/s/6waic988mj90kdk/2014-10-22%2012.48.04.png?dl=0
You should not create a polyline for each two points, it should be a connected polyline with mulitple points, something like this:
public void drawRoute(List<LatLng> location) {
polylineOptions = new PolylineOptions().width(MAPS_PATH_WIDTH).color(routeColor).addAll(location);
polyLine = map.addPolyline(destinationRoutePolyLineOptions);
polyLine.setPoints(location);
}
This will make it much smoother.
Use the following code based on bSpline algorithm, it worked for me on Android.
public List<LatLng> bspline(List<LatLng> poly) {
if (poly.get(0).latitude != poly.get(poly.size()-1).latitude || poly.get(0).longitude != poly.get(poly.size()-1).longitude){
poly.add(new LatLng(poly.get(0).latitude,poly.get(0).longitude));
}
else{
poly.remove(poly.size()-1);
}
poly.add(0,new LatLng(poly.get(poly.size()-1).latitude,poly.get(poly.size()-1).longitude));
poly.add(new LatLng(poly.get(1).latitude,poly.get(1).longitude));
Double[] lats = new Double[poly.size()];
Double[] lons = new Double[poly.size()];
for (int i=0;i<poly.size();i++){
lats[i] = poly.get(i).latitude;
lons[i] = poly.get(i).longitude;
}
double ax, ay, bx, by, cx, cy, dx, dy, lat, lon;
float t;
int i;
List<LatLng> points = new ArrayList<>();
// For every point
for (i = 2; i < lats.length - 2; i++) {
for (t = 0; t < 1; t += 0.2) {
ax = (-lats[i - 2] + 3 * lats[i - 1] - 3 * lats[i] + lats[i + 1]) / 6;
ay = (-lons[i - 2] + 3 * lons[i - 1] - 3 * lons[i] + lons[i + 1]) / 6;
bx = (lats[i - 2] - 2 * lats[i - 1] + lats[i]) / 2;
by = (lons[i - 2] - 2 * lons[i - 1] + lons[i]) / 2;
cx = (-lats[i - 2] + lats[i]) / 2;
cy = (-lons[i - 2] + lons[i]) / 2;
dx = (lats[i - 2] + 4 * lats[i - 1] + lats[i]) / 6;
dy = (lons[i - 2] + 4 * lons[i - 1] + lons[i]) / 6;
lat = ax * Math.pow(t + 0.1, 3) + bx * Math.pow(t + 0.1, 2) + cx * (t + 0.1) + dx;
lon = ay * Math.pow(t + 0.1, 3) + by * Math.pow(t + 0.1, 2) + cy * (t + 0.1) + dy;
points.add(new LatLng(lat, lon));
}
}
return points;
}

Custom Onlayout not working

Can anybody tell me how to change data dynamically in onLayout().i want to display first 8 values and after rotation complete another 8 values until it display array limit.here is my code-
if (position < conversion.length) {
if (!childRotate) {
child.setAngle(angle);
child.setPosition(i);
position = i;
child.setImageResource(conversion[position]);
Float an = angle;
Log.i("prj,=angle", an.toString() + ",i=" + i.toString()
+ ",onlayout,position=" + position.toString());
position++;
} else {
child.setAngle(angle);
child.setPosition(i);
child.setImageResource(conversion[position]);
Float an = angle;
Log.i("prj,angle=", an.toString() + ",i=" + i.toString()
+ ",onlayout,position=" + position.toString());
position++;
// childRotate = false;
}
}
left = Math
.round((float) (((layoutWidth / 2) - childWidth / 2) + radius
* Math.cos(Math.toRadians(angle))));
top = Math
.round((float) (((layoutHeight / 2) - childHeight / 2) + radius
* Math.sin(Math.toRadians(angle))));
child.layout(left, top, left + childWidth, top + childHeight);
angle += angleDelay;

Android OpenGL 2.0 : Object Picking (seeing if you hit a object with a ray)

So I am trying to get object picking working in OpenGL 2, in OpenGK 1 I used the glpixelColor which was pretty straight forward.
I have the following code to give me the start and end point of my ray??
Log.i("My POSITION", "x:" + mRenderer.eye.x + " y:" + mRenderer.eye.y + " z:" + mRenderer.eye.z);
float xyzw[] = unproject(x, mRenderer.screenHeight - y, -1.0f);
Log.i("Start of ray", "x:" + xyzw[0] + " y:" + xyzw[1] + " z:" + xyzw[2]);
xyzw = unproject(x, mRenderer.screenHeight - y, 1.0f);
Log.i("End of Ray", "x:" + xyzw[0] + " y:" + xyzw[1] + " z:" + xyzw[2]);
I use the following function
public float[] unproject(float rx, float ry, float rz) {
float[] xyzw = {0, 0, 0, 0};
int[] viewport = { 0, 0, mRenderer.screenWidth, mRenderer.screenHeight};
android.opengl.GLU.gluUnProject(rx, ry, rz, mRenderer.mViewMatrix, 0, mRenderer.mProjectionMatrix, 0, viewport, 0, xyzw, 0);
xyzw[0] /= xyzw[3];
xyzw[1] /= xyzw[3];
xyzw[2] /= xyzw[3];
xyzw[3] = 1;
return xyzw;
}
I get the following output
My POSITION: x:-1.857801 y:0.0 z:-8.655011
04-21
Start of ray: x:-1.8198236 y:-0.005848203 z:-8.688532
04-21
End of Ray: x:758.43915 y:-117.07846 z:-679.7136
Question
How do I work out if I have tapped on a cube at a position? Say the cube is at 1,1,1
I have tried this and it kinda works
float xDif = (xyzw2[0] - xyzw[0]) / 1000;
float yDif = (xyzw2[1] - xyzw[1]) / 1000;
float zDif = (xyzw2[2] - xyzw[2]) / 1000;
for (int i = 0; i < 1000; i ++)
{
if ((xyzw[0] + (xDif * i)) > mRenderer.cube.position.x - 1.0 && (xyzw[0] + (xDif * i)) < mRenderer.cube.position.x + 1.0 &&
(xyzw[1] + (yDif * i)) > mRenderer.cube.position.y - 1.0 && (xyzw[1] + (yDif * i)) < mRenderer.cube.position.y + 1.0 &&
(xyzw[2] + (zDif * i)) > mRenderer.cube.position.z - 1.0 && (xyzw[2] + (zDif * i)) < mRenderer.cube.position.z + 1.0)
{
Log.i("Hit cube", "HIT");
break;
}
}

Categories

Resources