Resize a path in android canvas - java

I have drawn an path in my canvas. On Single tap I want to resize the path. Say I want to make it double the original size.
I have tried path.transform but it shifts the path to a different location in canvass. This is the code I used for that
Matrix translateMatrix = new Matrix();
translateMatrix.setTranslate(100,0);
p.transform(translateMatrix);
How can I resize a path in android?

I have tried the solution provided by smitalm. Still the path was shifting its location. I have tried this way and it worked for me.
Matrix scaleMatrix = new Matrix();
RectF rectF = new RectF();
path.computeBounds(rectF, true);
scaleMatrix.setScale(1.25f, 1.25f,rectF.centerX(),rectF.centerY());
path.transform(scaleMatrix);

Havent done this by myself, but you should probably use
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(sx,sy, px, py);
p.transform(scaleMatrix);
where sx,sy should be 2,2 in your case, if you want double size
and px,py should probably be 0.5,0.5 in your case

RectF bounds = new RectF();
path.computeBounds(bounds, true);
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(scale_pathSX, scale_pathSY,
bounds.centerX(),bounds.centerY());
path.transform(scaleMatrix);
The Bound.centerx and center Y will help you to scale the path to its center position, scale_pathSX and scale_pathSY is for how much you want to scale your path,
FOR SCALE LARGE
scale_pathSX and scalepathSy = 1.001; FOR SCALE SMALL scale_pathSX and scalepathSy = 0.999;

Related

android - How to add satellte image in osmdroid

I get a .png from my server that represents a satellite image and I would put this image like a layer over the OpenStreetMap so I can see the street (under the satellite image) and the aerial photo on the same map.
I use this method
Drawable d = new BitmapDrawable(getResources(), bitmap);
bb = map.getBoundingBox();
Location SO = new Location(LocationManager.GPS_PROVIDER);
SO.setLatitude(bb.getLonWest());
SO.setLongitude(bb.getLatSouth());
Location NO = new Location(LocationManager.GPS_PROVIDER);
NO.setLatitude( bb.getLonWest());
NO.setLongitude(bb.getLatNorth());
Location NE = new Location(LocationManager.GPS_PROVIDER);
NE.setLatitude(bb.getLonEast());
NE.setLongitude(bb.getLatNorth());
float height = SO.distanceTo(NO);
float width = NE.distanceTo(NO);
Projection projection = map.getProjection();
int y = map.getHeight() / 2;
int x = map.getWidth() / 2;
GeoPoint geoPoint = (GeoPoint) projection.fromPixels(x, y);
deleteLayers(GroundOverlay.class);
GroundOverlay myGroundOverlay = new GroundOverlay();
myGroundOverlay.setImage(d);
myGroundOverlay.setPosition(geoPoint);
myGroundOverlay.setDimensions(width*0.94f, height*1.06f);
map.getOverlays().add(myGroundOverlay);
map.invalidate();
the problem is that the image always is stretch. my png cover only a part of my map (and it's ok beacuse our png is this way). When i move in the map the image stretching in all map but and it cover a part of map that it not rappresent.
Also, the image is not in the right place (look the red arrow).
How can i fix it?
Assuming your satellite image is limited to a portion of map you can use osmbonuspack GroundOverlay.
Probably this issue: https://github.com/MKergall/osmbonuspack/issues/273
Look at the hint about corrective coefficients.

Set Bitmap to specific size inside imageview

Trying to resize a bitmap and set to a specific part of an imageview. The imageview is square and I wish to have the bitmap in the bottom right corner. Width to be 10% of imageview and height to be 30%.
int w = imageview.getWidth();
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.vertical_bar_green);
imageview.setImageBitmap(Bitmap.createScaledBitmap(bm, w/10, w*30/100, false));
imageview.setScaleType(ScaleType.FIT_END);
The result is the bitmap is the full height of the imageview and the width is much larger.
How can I set specific points to place the bitmap?
From the documentation for END (the matrix used by FIT_END).
Compute a scale that will maintain the original src aspect ratio, but
will also ensure that src fits entirely inside dst. At least one axis
(X or Y) will fit exactly. END aligns the result to the right and
bottom edges of dst.
You will probable want to use a custom matrix for this, probably built with setRectToRect().
For example:
Matrix matrix = new Matrix();
RectF from = new RectF(0, 0, bm.getIntrinsicWidth(), bm.getIntrinsicHeight());
RectF to = new RectF(view.getWidth() * 0.9, view.getHeight() * 0.7, view.getWidth(), view.getHeight());
matrix.setRectToRect(from, to, Matrix.ScaleToFit.FILL);
view.setScaleType(ScaleType.MATRIX);
view.setImageMatrix(matrix);
(I'm not sure if you wanted to keep the original proportions or not, if you want it then use FIT_END for setRectToRect()).

3D Picking OpenGL ES 2.0 after model matrix translation

Hey all I'm trying to implement 3D picking into my program, and it works perfectly if I don't move from the origin. It is perfectly accurate. But if I move the model matrix away from the origin (the viewmatrix eye is still at 0,0,0) the picking vectors are still drawn from the original location. It should still be drawing from the view matrix eye (0,0,0) but it isn't. Here's some of my code to see if you can find out why..
Vector3d near = unProject(x, y, 0, mMVPMatrix, this.width, this.height);
Vector3d far = unProject(x, y, 1, mMVPMatrix, this.width, this.height);
Vector3d pickingRay = far.subtract(near);
//pickingRay.z *= -1;
Vector3d normal = new Vector3d(0,0,1);
if (normal.dot(pickingRay) != 0 && pickingRay.z < 0)
{
float t = (-5f-normal.dot(mCamera.eye))/(normal.dot(pickingRay));
pickingRay = mCamera.eye.add(pickingRay.scale(t));
addObject(pickingRay.x, pickingRay.y, pickingRay.z+.5f, Shape.BOX);
//a line for the picking vector for debugging
PrimProperties a = new PrimProperties(); //new prim properties for size and center
Prim result = null;
result = new Line(a, mCamera.eye, far);//new line object for seeing look at vector
result.createVertices();
objects.add(result);
}
public static Vector3d unProject(
float winx, float winy, float winz,
float[] resultantMatrix,
float width, float height)
{
winy = height-winy;
float[] m = new float[16],
in = new float[4],
out = new float[4];
Matrix.invertM(m, 0, resultantMatrix, 0);
in[0] = (winx / width) * 2 - 1;
in[1] = (winy / height) * 2 - 1;
in[2] = 2 * winz - 1;
in[3] = 1;
Matrix.multiplyMV(out, 0, m, 0, in, 0);
if (out[3]==0)
return null;
out[3] = 1/out[3];
return new Vector3d(out[0] * out[3], out[1] * out[3], out[2] * out[3]);
}
Matrix.translateM(mModelMatrix, 0, this.diffX, this.diffY, 0); //i use this to move the model matrix based on pinch zooming stuff.
Any help would be greatly appreciated! Thanks.
I wonder which algorithm you have implemented. Is it a ray casting approach to the problem?
I didn't focus much on the code itself but this looks a way too simple implementation to be a fully operational ray casting solution.
In my humble experience, i would like to suggest you, depending on the complexity of your final project (which I don't know), to adopt a color picking solution.
This solution is usually the most flexible and the easiest to be implemented.
It consist in the rendering of the objects in your scene with unique flat colors (usually you disable lighting as well in your shaders) to a backbuffer...a texture, then you acquire the coordinates of the click (touch) and you read the color of the pixel in that specific coordinates.
Having the color of the pixel and the tables of the colors of the different objects you rendered, makes possible for you to understand what the user clicked from a logical perspective.
There are other approaches to the object picking problem, this is probably universally recognized as the fastest one.
Cheers
Maurizio

Rotate image without shrinking on Android

I need to create a compass on an app i am working on. So i tried to create a new view called CompassView which basically extends imageview, shows a bitmap that has east west north south pointed on it, uses sensors to find the degrees the phone is pointed at, and rotate the image accordingly so that it would create an actual compass. But the problem is if i try to rotate the image to some angles like 45 degrees, it shrinks down. Here are some images to explain it better.
As you can see, the second image is shrinked down when i try to rotate around 45. What i want it to do is this:
Here is the code i am currently using:
Bitmap bMap = BitmapFactory.decodeResource(getResources(),
R.drawable.compass);
Matrix xMatrix = new Matrix();
xMatrix.reset();
xMatrix.postRotate(360-mValue, 75, 75); //This is 75 because 150 is the image width
Bitmap bMapRotate = Bitmap.createBitmap(bMap, 0, 0,
bMap.getWidth(), bMap.getHeight(), xMatrix, true);
setImageBitmap(bMapRotate);
Any help would be appreciated. THanks
EDIT: (SOLUTION)
I finally got it working thanks to the accepted answer. Here is the code i am using for anyone who wants to know how it worked:
RotateAnimation rAnimAntiClockWise = new RotateAnimation(
360 - mValue, 360 - event.values[0],
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
//mValue is the angle in degrees and i subtracted it from 360 to make it anticlockwise, and event.values[0] is the same thing as mValue
rAnimAntiClockWise.setFillAfter(true);
rAnimAntiClockWise.setInterpolator(new LinearInterpolator());
rAnimAntiClockWise.setDuration(0);
startAnimation(rAnimAntiClockWise);
You can use a alternative trick which will work like same as rotate and doesn't resize the image. I actually rotate the image with 45 degree angle and remain changes after animation.
rAnimAntiClockWise = new RotateAnimation(0.0f, 45.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
rAnimAntiClockWise.setFillAfter(true);
rAnimAntiClockWise.setInterpolator(new LinearInterpolator());
bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.rotate);
rAnimAntiClockWise.setDuration(100);
img_rotate.startAnimation(rAnimAntiClockWise);
The issue is that your new image is actually larger, due to the corners of the source "sticking out", and so the view is scaling it down to fit.
A few possible approaches:
After the above code, call Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height), copying the center region of the correct size. Easy given the code you have, but creates a useless intermediate bitmap.
Instead of giving the transform and source image to createBitmap, just create a mutable Bitmap of the correct size , wrap it in a Canvas , and tell the Canvas to render the rotated image .
bMapRotate = Bitmap.createBitmap(
bMap.getWidth(), bMap.getHeight(), bMap.getConfig());
Canvas canvasRotate = new Canvas(bMap);
canvasRotate.drawBitmap(bMap, xMatrix, paint); // any opaque Paint should do
Keep the code you have, but tell the view to crop rather than scale when rendering.

Android Rotatable ImageView

I am trying to create a Rotatable an ImageView to which I will specify certain angle and pivot point and see it rotated around that pivot point. I tried something like this:
Matrix matrix = new Matrix();
matrix.postRotate(45, imageView.getWidth(), imageView.getHeight());
imageView.setScaleType(ScaleType.MATRIX);
imageView.setImageMatrix(matrix);
but the parameters of postRotate method (the second and third - the pivot points) make NO CHANGE at all. even if they are 0, 0 - it's the same thing.
So I wanna create a ImageView that would be rotated by certain angle when initialized. In this example 45 degrees. I tried setting the bounds and staff.. no help.
How do I do that? :/
You can rotate a ImageView by using setRotation(int);
// rotate imageView 45 around center pivot point
imageView.setPivotX(imageView.getWidth()/2);
imageView.setPivotY(imageView.getHeight()/2);
imageView.setRotation(45);
Reference: http://goo.gl/WhhGM
Edit: I had to shorten the link because of a ) in the url, some browsers don't like that.
This is how I use view.setRotation(float angle) in my apps, hope it will be helpful:
//to make rotation use next code
imageView.setPivotX(imageView.getWidth() / 2);
imageView.setPivotY(imageView.getHeight() / 2);
imageView.setRotation(45);
//to reset rotate state to initial position
imageView.setPivotX(imageView.getWidth() / 2);
imageView.setPivotY(imageView.getHeight() / 2);
imageView.setRotation(0);
Based on answer from Spencer
This function works for me.
public static Bitmap rotateImage (Bitmap srcBitmap, int width, int height, int rotation)
{
// create rotated image
Matrix matrix = new Matrix();
rotation = (rotation +1 ) % 3;
rotation = rotation * 90;
matrix.postRotate( rotation,
width,
height );
Bitmap rotatedBmp = Bitmap.createBitmap( srcBitmap,
0,
0,
srcBitmap.getWidth(),
srcBitmap.getHeight(),
matrix,
false );
return rotatedBmp;
}

Categories