Android how to rotate canvas - android

I'am doing a simple app which displays compas rose + two arrows which represents current and mean wind direction.
What I want is to rotate compas rose + two arrows after they are drawed on canvas.
Here is my example:
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
//compass rose
canvas.drawBitmap(broza, crozax, crozay, null);
// Draw current wind arrow + rotate for currentwinddirection from json
matrix.reset();
matrix.setRotate(180 + (float) currentWindDirection, bkazalec.getWidth() / 2, bkazalec.getHeight() / 2);
matrix.postTranslate(ckazalecx, ckazalecy);
canvas.drawBitmap(bkazalec, matrix, mPaint);
//Draw mean wind arrow + rotate for meanwinddirection from json
matrix.reset();
matrix.setRotate(180 + (float) meanWindDirection, bkazalecmean.getWidth() / 2, bkazalecmean.getHeight() / 2);
matrix.postTranslate(mkazalecx, mkazalecy);
canvas.drawBitmap(bkazalecmean, matrix, mPaint);
//here I want to rotate canvas (compas rose + two arrows) for certain degree number which I obtain from sensor.
.
.
//after this I must "draw" some text for certain datas
canvas.drawText(getResources().getString(R.string.pod_smer_vetra) + getCurrentWindDirection() + "°", x, y, mPaint);
y += mPaint.getFontSpacing();
canvas.drawText(getResources().getString(R.string.pod_hitrost_vetra) + getCurrentWindSpeed() + " m/s", x, y, mPaint);
y += mPaint.getFontSpacing();
canvas.drawText(getResources().getString(R.string.pod_povp_smer_vetra) + getMeanWindDirection() + "°", x, y, mPaint);
y += mPaint.getFontSpacing();
canvas.drawText(getResources().getString(R.string.pod_pov_hitrost_vetra) + getMeanWindSpeed() + " m/s", x, y, mPaint);
y += mPaint.getFontSpacing();
canvas.drawText(getResources().getString(R.string.pod_beaufort) + getMeanWindBeaufort(), x, y, mPaint);
y += mPaint.getFontSpacing();
canvas.drawText(getResources().getString(R.string.pod_temp_povrsina_voda) + getTemperatureSeaSurface() + "°C", x, y, mPaint);
y += mPaint.getFontSpacing();
canvas.drawText(getResources().getString(R.string.pod_temp_zraka) + getTemperatureAir() + "°C", x, y, mPaint);
}

int saveCount = canvas.save(); // save canvas state
try { // just for case if some exceptions
canvas.rotate(angle, centerX, centerY);
if (needScale) canvas.scale(scaleX, scaleY, centerX, centerY);
// draw here what you want
} finally {
canvas.restoreToCount(saveCount); // restore previous state, further draw is unrotated
}

Related

Canvas.drawTextOnPath doesn't scales text along with canvas scale

I am trying to draw a text on curved path. But when I scale up the canvas, text gets blurred.
Here's the code I've tried
public void draw(Canvas canvas) {
float midX = (maxX + minX) / 2;
float midY = (maxY + minY) / 2;
canvas.save();
canvas.translate(minX, minY);
canvas.scale(this.scaleX, this.scaleY);
if (curvingAngle != 0) {
drawCurveText(canvas, 0f, 0f, 1f);
} else
canvas.drawText(text, mOrigin[0], mOrigin[1], textPaint);
canvas.restore();
}
private void drawCurveText(Canvas canvas,float offsetX, float offsetY, float scale) {
// Path Calculation
Path textPath;
canvas.drawTextOnPath(text, this.textPath, hOffset, 0.0f, this.getPaint());
}
It gives following results
Before Scale
After Scale
The same code without curvingAngle (canvas.drawText) works perfectly with scaling.
Any help would be appreciated...

Draw circle on start and end point of an Arc

Hi im having difficulties on drawing dots on arc's both ends (start and end)
Although I can draw arc on canvas. Heres my sample code for drawing arc.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float width = (float) getWidth();
float height = (float) getHeight();
float radius;
if (width > height) {
radius = height / 4;
} else {
radius = width / 4;
}
float center_x, center_y;
final RectF oval = new RectF();
center_x = width / 2;
center_y = height / 2;
oval.set(center_x - radius,
center_y - radius,
center_x + radius,
center_y + radius);
float percent = 25;
float arcRadius = 360;
float angle = arcRadius * (percent/100);
canvas.drawArc(oval, 270, 360, false, trackpaint);
canvas.drawArc(oval, 270, angle, false, arcPaint);
}
the only missing is putting circles on start and end points of the arc. I've tried this link but it doest work Calculate Arc Center Point, Knowing It's Start and End Degrees. Any help will be much appreciated. Thank you
the coordinate of the start point is:
double startX = Math.cos(Math.toRadians(270)) * radius + center_x;
double startY = Math.sin(Math.toRadians(270)) * radius + center_y;
the coordinate of the end point is:
double endX = Math.cos(Math.toRadians(270 + angle)) * radius + center_x;
double endY = Math.sin(Math.toRadians(270 + angle)) * radius + center_y;
and then you can draw circle using the start point and end point:
canvas.drawCircle(startX, startY, 10, paint);
canvas.drawCircle(endX, endY, 10, paint);
Get path from the ARC
Use PathMeasure class to retrieve Path length and path TAN, using starting or Ending X and Y coordinates of the ARC
Use this X and Y coordinates to draw circle.
Example for circle at the start of the ARC:
final Path mPath = new Path();
mPath.addArc(oval, startAngle, sweepAngle);
PathMeasure pm = new PathMeasure(mPath, false);
float[] xyCoordinate = { arcStarting.x , arcStarting.y };
float pathLength = pm.getLength();
pm.getPosTan(0, xyCoordinate, null);//"0 for starting point"
PointF point = new PointF(xyCoordinate[0], xyCoordinate[1]);
canvas.drawCircle(point.x, point.y, 10, YourPaintHere)

how to rotate different part of canvas separately in android

i have custom view that contains many rectangles and ovals and ..... i can rotate my whole canvas(rect and ovals and ....) by using canvas.Rotate(degree,cneterX,centerY)
but in bottom of the my view i want to have a something like menu that doesn't rotate when i use canvas.rotate() . it means that i want to rotate these rectangles and ovals but don't wanna rotate my menu that will be create with same canvas.
#Override
protected void onDraw(Canvas canvas) {
float ringWidth = textHeight + 4;
int height = getMeasuredHeight();
int width =getMeasuredWidth();
int px = width;
int py = height/2;
Point center = new Point(px,py );
int radius = Math.max(px, py)-2;
int UpperSide = center.y;
RectF boundingBox = new RectF(center.x - radius, center.y - radius, center.x + radius, center.y + radius);
RectF innerBoundingBox = new RectF(center.x - radius , center.y - radius , center.x + radius, center.y + radius );
RectF GroundSectionBox = new RectF(center.x - radius,UpperSide ,center.x + radius,center.y + radius);
RectF RightPanel = new RectF(center.x + width -(width/4), center.y - (radius/2)+10, center.x+radius- ringWidth, center.y + (radius/2)-10);
RectF LeftPanel = new RectF(center.x - radius + ringWidth ,center.y - (radius/2)+10, center.x - width + (width/4), center.y + (radius/2)-10);
RectF RightBlack = new RectF(center.x + width -(width/4),center.y-(radius/10),center.x+radius- ringWidth,center.y + (radius/10));
RectF leftBlack = new RectF(center.x - radius + ringWidth ,center.y - (radius/10), center.x - width + (width/4), center.y + (radius/10));
.
.
canvas.drawRect(innerBoundingBox, groundPaint);
canvas.drawPath(skyPath, skyPaint);
canvas.drawRect(GroundSectionBox, skyPaint);
canvas.drawPath(skyPath, markerPaint);
canvas.drawRect(RightBlack, sideBlack);
canvas.drawRect(leftBlack, sideBlack);
canvas.drawRect(RightPanel, RightPanelup);
canvas.drawRect(LeftPanel, LeftPanelUp);
.
.
}
You cans use the save and restore methods on Canvas to draw stuff in transformations, then restore back to the original state. Here's an example:
protected void onDraw(Canvas canvas)
{
canvas.save(); // Canvas is in original state. Save it before anything
// Perform any transformations you want here (like rotate)
// Draw while your transformations are in place (like ovals)
canvas.restore(); // Canvas state returned to what it was when you called save
// Draw things that need to be drawn without any transformations
}
Hope this helps :)

How to rotate a rectangle drawn on canvas in Android?

I am drawing a text on android canvas using the following piece of code
Rect rect = new Rect();
paint.getTextBounds(text, 0, text.length(), rect);
canvas.translate(xPosition + position.getX(), yPosition + position.getY());
paint.setColor(Color.BLUE);
paint.setStyle(Style.STROKE);
canvas.drawRect(rect, paint);
paint.setStyle(Style.FILL);
paint.setColor(text_color);
canvas.translate(-(xPosition + position.getX()), -(yPosition + position.getY()));
canvas.rotate(getDegreesFromRadians(angle), xPosition + position.getX() + rect.exactCenterX(), yPosition + position.getY() + rect.exactCenterY());
canvas.drawText(text, xPosition + position.getX(), yPosition + position.getY(), paint);
This code takes care of the rotation of the text and it works fine. I am drawing a blue rectangle around the text using the above code. Now my problem is that the rectangle is not rotating along with the text. It still remains the same. Is there any way to rotate the rectangle drawn in android canvas?
please use
canvas.save();
canvas.rotate();
//stuff to draw that should be rotated
canvas.restore();
else you have to compensate for every rotation afterwards
I found my own answer. I used the following code
Rect rect = new Rect();
paint.setColor(text_color);
paint.setStyle(Style.FILL);
paint.getTextBounds(text, 0, text.length(), rect);
canvas.translate(xPosition + position.getX(), yPosition + position.getY());
canvas.translate(-(xPosition + position.getX()), -(yPosition + position.getY()));
canvas.rotate(getDegreesFromRadians(angle), xPosition + position.getX() + rect.exactCenterX(), yPosition + position.getY() + rect.exactCenterY());
canvas.drawText(text, xPosition + position.getX(), yPosition + position.getY(), paint);
paint.getTextBounds(text, 0, text.length(), rect);
canvas.translate(xPosition + position.getX(), yPosition + position.getY());
paint.setColor(Color.BLUE);
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(4);
rect = new Rect(rect.left - 10, rect.top - 10, rect.right + 10, rect.bottom + 10);
canvas.drawRect(rect, paint);
The thing is the whole canvas is being rotated for rotating the text. So i just need to draw the rectangle after the rotation of the canvas.

Make an equilateral triangle inscribed in a circle, knowing a vertex or a side

I'm learning Android and now I'm experimenting with the Canvas class.
I would like to draw a regular (equilateral) triangle inscribed into a known circle.
I think there must be a easier way to do it than getting into trigonomery, pythagoras,...
Doing the trig is the most straightforward method that I've found. Below is a function for drawing an equilateral triangle in the normal, "pointing upward" orientation. I've posted a more sophisticated implementation here that also handles rotating the triangle.
private void drawCircumscribedTriangle(Canvas canvas, float circleCenterX, float circleCenterY, float radius, Paint paint) {
float xOffsetFromCenter = FloatMath.cos((float)Math.PI/6) * radius;
float yOffsetFromCenter = FloatMath.sin((float)Math.PI/6) * radius;
canvas.drawLine(circleCenterX, circleCenterY - radius, circleCenterX + xOffsetFromCenter, circleCenterY + yOffsetFromCenter, paint);
canvas.drawLine(circleCenterX + xOffsetFromCenter, circleCenterY + yOffsetFromCenter, circleCenterX - xOffsetFromCenter, circleCenterY + yOffsetFromCenter, paint);
canvas.drawLine(circleCenterX - xOffsetFromCenter, circleCenterY + yOffsetFromCenter, circleCenterX, circleCenterY - radius, paint);
}
Thanks to Acj, I got it, But it wasn't exactly what I wanted, because I wanted it to be filled (It's my fault because I didn't specify it).
Anyway, I adapted Acj's code to my needs, and here it is:
private void drawCircumscribedTriangle(Canvas canvas, float circleCenterX, float circleCenterY, float radius, Paint paint) {
float xOffsetFromCenter = FloatMath.cos((float)Math.PI/6) * radius;
float yOffsetFromCenter = FloatMath.sin((float)Math.PI/6) * radius;
Path path = new Path();
path.setFillType(Path.FillType.EVEN_ODD);
path.moveTo(circleCenterX, circleCenterY - radius);
path.lineTo(circleCenterX + xOffsetFromCenter, circleCenterY + yOffsetFromCenter);
path.lineTo(circleCenterX - xOffsetFromCenter, circleCenterY + yOffsetFromCenter);
path.lineTo(circleCenterX, circleCenterY - radius);
path.lineTo(circleCenterX, circleCenterY - radius);
canvas.drawPath(path, paint);
}
Once more, all the merit is for Acj
As FloatMath.cos(float) is deprecated since API 23, this answer to a tricky equilateral question needs the following lines of its code updating to
float xOffsetFromCenter = ((float)Math.PI/6) * radius;
float yOffsetFromCenter = ((float)Math.PI/6) * radius;

Categories

Resources