I'd like to calculate a point on a quadratic curve. To use it with the canvas element of HTML5.
When I use the quadraticCurveTo() function in JavaScript, I have a source point, a target point and a control point.
How can I calculate a point on the created quadratic curve at let's say t=0.5 with "only" knowing this three points?
Use the quadratic Bézier formula, found, for instance, on the Wikipedia page for Bézier Curves:
In pseudo-code, that's
t = 0.5; // given example value
x = (1 - t) * (1 - t) * p[0].x + 2 * (1 - t) * t * p[1].x + t * t * p[2].x;
y = (1 - t) * (1 - t) * p[0].y + 2 * (1 - t) * t * p[1].y + t * t * p[2].y;
p[0] is the start point, p[1] is the control point, and p[2] is the end point. t is the parameter, which goes from 0 to 1.
In case somebody needs the cubic form:
//B(t) = (1-t)**3 p0 + 3(1 - t)**2 t P1 + 3(1-t)t**2 P2 + t**3 P3
x = (1-t)*(1-t)*(1-t)*p0x + 3*(1-t)*(1-t)*t*p1x + 3*(1-t)*t*t*p2x + t*t*t*p3x;
y = (1-t)*(1-t)*(1-t)*p0y + 3*(1-t)*(1-t)*t*p1y + 3*(1-t)*t*t*p2y + t*t*t*p3y;
I created this demo :
// x = a * (1-t)³ + b * 3 * (1-t)²t + c * 3 * (1-t)t² + d * t³
//------------------------------------------------------------
// x = a - 3at + 3at² - at³
// + 3bt - 6bt² + 3bt³
// + 3ct² - 3ct³
// + dt³
//--------------------------------
// x = - at³ + 3bt³ - 3ct³ + dt³
// + 3at² - 6bt² + 3ct²
// - 3at + 3bt
// + a
//--------------------------------
// 0 = t³ (-a+3b-3c+d) + => A
// t² (3a-6b+3c) + => B
// t (-3a+3b) + => c
// a - x => D
//--------------------------------
var A = d - 3*c + 3*b - a,
B = 3*c - 6*b + 3*a,
C = 3*b - 3*a,
D = a-x;
// So we need to solve At³ + Bt² + Ct + D = 0
Full example here
may help someone.
I edited talkhabis answer (cubic curve) so the curve is displayed with the right coordinates. (Couldn't comment)
The Y-coordinates needed to be changed (-p[].y+150). (A new variable for that might be a nicer and more efficient solution, but you get the idea)
// Apply points to SVG and create the curve and controllers :
var path = document.getElementById('path'),
ctrl1 = document.getElementById('ctrl1'),
ctrl2 = document.getElementById('ctrl2'),
D = 'M ' + p0.x + ' ' + (-p0.y+150) +
'C ' + c0.x + ' ' + (-c0.y+150) +', ' + c1.x + ' ' + (-c1.y+150) + ', ' + p1.x + ' ' + (-p1.y+150);
path.setAttribute('d',D);
ctrl1.setAttribute('d','M'+p0.x+','+(-p0.y+150)+'L'+c0.x+','+(-c0.y+150));
ctrl2.setAttribute('d','M'+p1.x+','+(-p1.y+150)+'L'+c1.x+','+(-c1.y+150));
// Lets test the "Bezier Function"
var t = 0, point = document.getElementById('point');
setInterval(function(){
var p = Bezier(p0,c0,c1,p1,t);
point.setAttribute('cx',p.x);
point.setAttribute('cy',-p.y+150);
t += 0.01;
if(t>=1) t=0;
},50);
// OK ... Now tring to get "y" on cruve based on mouse "x" :
var svg = document.getElementById('svg'),
point2 = document.getElementById('point2');
svg.onmousemove = function(e){
var x = (e.pageX - 50)/2,
y = (e.pageY - 50)/2;
// "-50" because of "50px margin" on the left side
// and "/2" because the svg width is 300 units and 600 px => 300 = 600/2
// Get the x,y by mouse x
var p = YBX(p0,c0,c1,p1,x);
point2.setAttribute('cx',p.x);
point2.setAttribute('cy',-p.y+150);
}
http://jsfiddle.net/u214gco8/1/
I also created some C-Code to test the results for the cubic curve. Just enter the X and Y coordinates in the main function.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void bezierCurve(int x[] , int y[])
{
double xu = 0.0 , yu = 0.0 , u = 0.0 ;
int i = 0 ;
for(u = 0.0 ; u <= 1.0 ; u += 0.05)
{
xu = pow(1-u,3)*x[0]+3*u*pow(1-u,2)*x[1]+3*pow(u,2)*(1-u)*x[2]
+pow(u,3)*x[3];
yu = pow(1-u,3)*y[0]+3*u*pow(1-u,2)*y[1]+3*pow(u,2)*(1-u)*y[2]
+pow(u,3)*y[3];
printf("X: %i Y: %i \n" , (int)xu , (int)yu) ;
}
}
int main(void) {
int x[] = {0,75,50,300};
int y[] = {0,2,140,100};
bezierCurve(x,y);
return 0;
}
https://ideone.com/glLXcB
Just a note: If you are using the usual formulas presented here then don't expect t = 0.5 to return the point at half of the curve's length.. In most cases it won't.
More on this here under "§23 — Tracing a curve at fixed distance intervals" and here.
Related
I have point A, B and width of CD (A' = A). If user will move point B to B'how I can know coordinates of points C' D'. I would be very grateful if someone write method in java with 3 input parameters (A, B, and width of CD) which output coordinates of C' and D'. As reward I can pay 50$ via Paypal.
The background:
First, if I understand correctly, the task actually is "given the coordinates of A and B, find coordinates of C and D if we know that AB and CD are perpendicular, and we know the length of CD"
To calculate the coordinates, we use 3 basic math equations:
Line from 2 points A, B: y = (x - B.x)* (A.y - B.y)/(A.x - B.x) + B.y
If we set m = (A.y - B.y)/(A.x - B.x)
The equation from 2 points A, B will be: y = m * (x - B.x) + B.y
Line which is perpendicular with the line above (CD): y = (-1/m) * x + y0
Since CD goes through A, the equation can be written as: y = (-1/m) * (x - A.x) + A.y
The length (d) between 2 points A, C: d * d = (C.x - A.x) * (C.x - A.x) + (C.y - A.y) * (C.y - A.y)
From the equation of CD, we know C.y = (-1/m)*(C.x - A.x) + A.y
Therefore:
d*d = (C.x - A.x)*(C.x - A.x) + (1/(m*m))*(C.x - A.x)* (C.x - A.x)
Easily find out that C.x - A.x = (+|-) (m*d)/Math.sqrt(m*m + 1)
In java, I guess you can write the function as
public Point[] findCD(Point A, Point B, int widthCD) {
if (A.x == B.x) {
return [new Point(A.x - widthCD/2, A.y), new Point(A.x + widthCD/2, A.y)]
}
if (A.y == B.y) {
return [new Point(A.x, A.y - widthCD/2), new Point(A.x, A.y + widthCD/2)]
}
var m = (A.y - B.y)/(A.x - B.x);
var xC = A.x - m*widthCD/(2 * Math.sqrt(m*m + 1));
var xD = A.x + m*widthCD/(2 * Math.sqrt(m*m + 1));
var yC = (A.x - xC) / m + A.y;
var yD = (A.x - xD) / m + A.y;
return [new Point(xC, yC), new Point(xD, yD)];
}
Note: I don't have java, please correct if I write the pointer or array wrong
I have a circle and a polyline and I want to know the coordination of the intersection point
user3591040 its quite tricky....
I hope that you have data related to circle and line.
equations and all polylines
You want to find this point
**
Consider this image
We will try to detect any collision
**
Collision Detection Algorithm:try to implement this algorithm
Taking
E is the starting point of the ray,
L is the end point of the ray,
C is the center of sphere you're testing against
r is the radius of that sphere
Compute:
d = L - E ( Direction vector of ray, from start to end )
f = E - C ( Vector from center sphere to ray start )
Then the intersection is found by..
Plugging:
P = E + t * d
This is a parametric equation:
Px = Ex + tdx
Py = Ey + tdy
into
(x - h)2 + (y - k)2 = r2
(h,k) = center of circle.
Note: We've simplified the problem to 2D here, the solution we get applies also in 3D
to get:
Expand
x2 - 2xh + h2 + y2 - 2yk + k2 - r2 = 0
Plug
x = ex + tdx
y = ey + tdy
( ex + tdx )2 - 2( ex + tdx )h + h2 + ( ey + tdy )2 - 2( ey + tdy )k + k2 - r2 = 0
Explode
ex2 + 2extdx + t2dx2 - 2exh - 2tdxh + h2 + ey2 + 2eytdy + t2dy2 - 2eyk - 2tdyk + k2 - r2 = 0
Group
t2( dx2 + dy2 ) + 2t( exdx + eydy - dxh - dyk ) + ex2 + ey2 - 2exh - 2eyk + h2 + k2 - r2 = 0
Finally,
t2( _d * _d ) + 2t( _e * _d - _d * _c ) + _e * _e - 2( _e*_c ) + _c * _c - r2 = 0
*Where _d is the vector d and * is the dot product.*
And then,
t2( _d * _d ) + 2t( _d * ( _e - _c ) ) + ( _e - _c ) * ( _e - _c ) - r2 = 0
Letting _f = _e - _c
t2( _d * _d ) + 2t( _d * _f ) + _f * _f - r2 = 0
So we get:
t2 * (d DOT d) + 2t*( f DOT d ) + ( f DOT f - r2 ) = 0
So solving the quadratic equation:
float a = d.Dot( d ) ;
float b = 2*f.Dot( d ) ;
float c = f.Dot( f ) - r*r ;
float discriminant = b*b-4*a*c;
if( discriminant < 0 )
{
// no intersection
}
else
{
// ray didn't totally miss sphere,
// so there is a solution to
// the equation.
discriminant = sqrt( discriminant );
// either solution may be on or off the ray so need to test both
// t1 is always the smaller value, because BOTH discriminant and
// a are nonnegative.
float t1 = (-b - discriminant)/(2*a);
float t2 = (-b + discriminant)/(2*a);
// 3x HIT cases:
// -o-> --|--> | | --|->
// Impale(t1 hit,t2 hit), Poke(t1 hit,t2>1), ExitWound(t1<0, t2 hit),
// 3x MISS cases:
// -> o o -> | -> |
// FallShort (t1>1,t2>1), Past (t1<0,t2<0), CompletelyInside(t1<0, t2>1)
if( t1 >= 0 && t1 <= 1 )
{
// t1 is the intersection, and it's closer than t2
// (since t1 uses -b - discriminant)
// Impale, Poke
return true ;
}
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
I need to animate the drawing of a line graph. I'll receive an array of values (probably between 0 and 10) and that has to go on a graph over time. I want the line graph to be drawn, and the drawing should be visible; animated.
I've looked at Anders Ericsson's tutorial here: http://www.jayway.com/2012/08/29/creating-custom-android-views-part-3-animating-your-custom-views-smoothly/#comment-105813
The code here: https://github.com/andersericsson/ViewTutorialPart3
But I can't seem to swing it to work my way.
Is there another solution out there?
The solution I ended up using involved some algebra in the class where I extended View.
The function gets the array of scores (values between 0 and 10) from the activity and uses the values two-by-two as start and end points to a line (note that the end point of one line is the start point of the next line).
It calculates the length of the line and how many segments will be in the line; also how far to move in the x direction and how for to move in the y direction.
Then it calculates the x and y values of the end of the first segment in the line and draws that segment.
Then the xDirection and yDirection is added to the x and y points respectively and the line is drawn again, which now includes the first and second segment of the line. This is done for every segment in the line, and then the final line from point A to point B is drawn.
But it's not complete - the entire for loop in the setData function should be placed in a recursive function, because postInvalidateDelayed() doesn't pause the for loop from executing.
However, nothing is drawn on the canvas at all, hence the link to my other question currently on SO: Why are no lines drawn on my (custom View) canvas?
But for this question, I think that the solution I ended up using is probably not so bad. Comments?
public void setData(float[] scorePoints, float max, int totalScores){
Log.d(TAG, "Get stuff from activity");
scores = scorePoints;
numberOfScores = totalScores;
Log.d(TAG, "Number of scores = " + numberOfScores);
maxScore = max;
Log.d(TAG, "Max score = " + maxScore);
segmentToDraw = (float) 10;
//get the width of the area to draw
width = Math.abs(getWidth() - getPaddingLeft() - getPaddingRight());
//get the height of the area to draw
height = getHeight() - getPaddingTop() - getPaddingBottom();
Log.d(TAG, "Drawable area in view = " + width + " x " + height);
/*
* Now we start filling an array of points.
* The onDraw function will drawLines of groupings of four points in a given array.
*
* For the first segment, we'll draw from the x and y of the first point (which will be in the 1st and 2nd spots in our array)
* to the x and y of the first segment (which will be in the 3rd and 4th spots in our array).
* And then the 3rd and 4th spots in our array will be replaced by a new x and y
* marking the end of the second segment to be drawn from our first point.
*
* This will happen until the x and y is not smaller than the x and y of the final point of the line, any more.
* Then the 3rd and 4th spots in our array will be replaced by the x and y of the final point of the line.
*
* If there are more points to draw, the 5th and 6th spots in our array will also be created and filled with
* the x and y of the final point of the line because it'll be the first two values (x and y) for drawing the next line.
*
* So, yes, there will be duplicates in our array of points to draw, but a grouping of four spots will be used to draw one line,
* and the end point of the first line is the starting point of the second line, so we need it twice.
*/
points.add(getXPos(scores[0]));
points.add(getYPos(scores[0]));
points.add((float) 0);
points.add((float) 0);
x = points.get(0);
y = points.get(1);
startPoint = scores[0];
endPoint = scores[1];
for(int i=0; i<scores.length-1; i++){
String thePoints = "";
if(i>0){
startPoint = scores[i];
endPoint = scores[i+1];
x = points.get(i*4);
y = points.get((i*4) + 1);
}
startPointX = getXPos(startPoint);
startPointY = getYPos(startPoint);
endPointX = getXPos(endPoint);
endPointY = getYPos(endPoint);
distanceOfLine = (float) Math.sqrt(Math.pow((endPointX - startPointX), 2) + Math.pow((endPointY - startPointY), 2));
Log.d(TAG, "Distance of line = " + distanceOfLine);
//get number of segments in line
numberOfSegmentsInLine = (int) (distanceOfLine/segmentToDraw);
Log.d(TAG, "Number of segments in line = " + numberOfSegmentsInLine);
//get distance to move in Y direction
yDirection = (float) ((endPointY - startPointY)/ (float) numberOfSegmentsInLine);
Log.d(TAG, "Move " + yDirection + " in Y direction");
//get distance to move in X direction
xDirection = (float) ((endPointX - startPointX)/ (float) numberOfSegmentsInLine);
Log.d(TAG, "Move " + xDirection + " in X direction");
//loop for each segment
for(int j=0; j<numberOfSegmentsInLine; j++){
x += xDirection;
y += yDirection;
points.set(points.size()-2, Float.valueOf(x));
points.set(points.size()-1, Float.valueOf(y));
Log.d(TAG, "Line : " + (i+1) + " Segment : " + j);
Log.d(TAG, "X = "+ (x+xDirection) + " Y = " + (y+yDirection));
Log.d(TAG, "Call invalidate now!");
//invalidate();
//postInvalidateDelayed(delayMilliseconds);
}
//draw final line
points.set(points.size()-2, endPointX);
points.set(points.size()-1, endPointY);
invalidate();
//postInvalidateDelayed(delayMilliseconds);
if(i<scores.length-2){
points.add(endPointX);
points.add(endPointY);
points.add((float) 0);
points.add((float) 0);
}
for(int k =0; k<points.size(); k++){
thePoints = thePoints + " : " + points.get(k);
}
Log.d(TAG, "Points array = " + thePoints);
}
}
#Override
public void onDraw(Canvas canvas){
//setWillNotDraw(true);
Log.d(TAG, "DRAW DAMNIT!!!");
Log.d(TAG, "Width = " + (int) width + " Height = " + (int)height);
paint = new Paint();
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(4);
paint.setColor(Color.RED);
//paint.setAntiAlias(true);
//paint.setShadowLayer(4, 2, 2, 0x81000000);
Bitmap bitmap = Bitmap.createBitmap((int)width, (int)height, Bitmap.Config.ARGB_8888);
canvas = new Canvas(bitmap);
String drawPointsGo = "";
float[] drawPoints = new float[points.size()];
for(int i=0; i<points.size(); i++){
Float f = points.get(i);
drawPoints[i] = (float) (f != null ? f : 0.0);
drawPointsGo = drawPointsGo + " : " + drawPoints[i];
}
Log.d(TAG, "Draw Points: " + drawPointsGo);
canvas.drawLines(drawPoints, paint);
}
Try looking into CountDownTimer or Runnable so that onTick() or when it's time to post you can update your line by drawing a few more pixels. This would let you draw one line after the other but would give the effect of animation.
Here is the general direction to try:
Make sure you are comfortable with Canvas drawing.
Then you will want to create a new View (subclass it) and override the onDraw method.
This method should only draw the graph partially, based on the elapsed time since the start of the animation.
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);