Rotate circle drawn on canvas to point marked by touchHow to calculate an angle from three points?Draw transparent lines on bitmap via touch inputProblems with touch eventRectangle Coordinates With Respect To The Rotation AngleHow to rotate an image in circular manner with respect to its center on touch in androidGlow Effect on a Bitmap set as Background of a custom view in androidBest way to determine screen dimensions for signature capture stroke width?Moving an image after rotating does not behave correctly in androidHow to detect finger touched point on the circle drawn on canvas in android?Undo/Redo not working in android CanvasHow to slide indicator image on a semi circle Path
Create a list of snaking numbers under 50,000
What is the following VRP?
What is this "opened" cube called?
Can copper pour be used as an alternative to large traces?
In Endgame, wouldn't Stark have remembered Hulk busting out of the stairwell?
Printing a list as "a, b, c." using Python
Who declared the Last Alliance to be the "last" and why?
Rapid change in character
How do I keep my animals from eating my people food?
Storing milk for long periods of time
Can UV radiation be safe for the skin?
Sum and average calculator
Strange behavior of std::initializer_list of std::strings
'spazieren' - walking in a silly and affected manner?
I was given someone else's visa, stamped in my passport
Did the Apollo Guidance Computer really use 60% of the world's ICs in 1963?
When is it a good idea to capture the fianchettoed bishop?
Unexpected behavior after assignment of function object to function wrapper
How do I get my neighbour to stop disturbing with loud music?
Terminology of atomic spectroscopy: Difference Among Term, States and Level
What is the practical impact of using System.Random which is not cryptographically random?
Was it illegal to blaspheme God in Antioch in 360.-410.?
Does the telecom provider need physical access to the SIM card to clone it?
What am I looking at here at Google Sky?
Rotate circle drawn on canvas to point marked by touch
How to calculate an angle from three points?Draw transparent lines on bitmap via touch inputProblems with touch eventRectangle Coordinates With Respect To The Rotation AngleHow to rotate an image in circular manner with respect to its center on touch in androidGlow Effect on a Bitmap set as Background of a custom view in androidBest way to determine screen dimensions for signature capture stroke width?Moving an image after rotating does not behave correctly in androidHow to detect finger touched point on the circle drawn on canvas in android?Undo/Redo not working in android CanvasHow to slide indicator image on a semi circle Path
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
I'm trying to get my app to display a circle that the user can rotate to a certain degree by touching and dragging the circle. Say the maximum the circle can be rotated is 60 degrees, either way.
I've extended the View class to create my custom View.
I've drawn a circle on my canvas with the drawCircle() method.
To rotate it, I know I'd have to do a canvas.rotate(), but I'm not sure what to fix the center as.
How do I measure this angle?
What do I rotate about?
public class DrawingView extends View
Paint paint;
Canvas canvas;
int originalX = 100;
int originalY = 50;
int radius = 75;
// ... some code ...
// paint, canvas initialised in constructors
@Override
protected void onDraw(Canvas canvas)
canvas.drawCircle(originalX, originalY, radius, paint);
// some more code ...
@Override
public boolean onTouchEvent(MotionEvent event)
int x = (int)event.getX();
int y = (int)event.getY();
case MotionEvent.ACTION_DOWN:
// Detect if touch in my circle
break;
case MotionEvent.ACTION_MOVE:
double tx = x - originalX;
double ty = y - originalY;
double tlength = Math.sqrt(tx*tx + ty*ty);
double angle = Math.acos(radius/tlength);
double degrees = (angle * 180)/Math.PI;
System.out.println("Degrees " + (angle*180)/Math.PI);
break;
The code I've displayed doesn't seem to give me a correct value.
Like, if I touch and drag all the way to the end of the screen, it gives me a value around 70 degrees. I don't think I'm calculating the angle right, but I have no idea how to either.
I followed the selected answer's way of finding the angle.
I then used canvas.rotate() before drawing the circle.
java
add a comment |
I'm trying to get my app to display a circle that the user can rotate to a certain degree by touching and dragging the circle. Say the maximum the circle can be rotated is 60 degrees, either way.
I've extended the View class to create my custom View.
I've drawn a circle on my canvas with the drawCircle() method.
To rotate it, I know I'd have to do a canvas.rotate(), but I'm not sure what to fix the center as.
How do I measure this angle?
What do I rotate about?
public class DrawingView extends View
Paint paint;
Canvas canvas;
int originalX = 100;
int originalY = 50;
int radius = 75;
// ... some code ...
// paint, canvas initialised in constructors
@Override
protected void onDraw(Canvas canvas)
canvas.drawCircle(originalX, originalY, radius, paint);
// some more code ...
@Override
public boolean onTouchEvent(MotionEvent event)
int x = (int)event.getX();
int y = (int)event.getY();
case MotionEvent.ACTION_DOWN:
// Detect if touch in my circle
break;
case MotionEvent.ACTION_MOVE:
double tx = x - originalX;
double ty = y - originalY;
double tlength = Math.sqrt(tx*tx + ty*ty);
double angle = Math.acos(radius/tlength);
double degrees = (angle * 180)/Math.PI;
System.out.println("Degrees " + (angle*180)/Math.PI);
break;
The code I've displayed doesn't seem to give me a correct value.
Like, if I touch and drag all the way to the end of the screen, it gives me a value around 70 degrees. I don't think I'm calculating the angle right, but I have no idea how to either.
I followed the selected answer's way of finding the angle.
I then used canvas.rotate() before drawing the circle.
java
1
The problem is that tx and ty don't necessarily fall on the circle and may be inside or outside of it, so your Math.acos() calculation is off. I think this is what you need. (But don't read the comments.)
– Cheticamp
Mar 28 at 1:25
This seems to work too. But the math's a little complicated for me. Thanks though!
– user7999116
Mar 28 at 2:18
add a comment |
I'm trying to get my app to display a circle that the user can rotate to a certain degree by touching and dragging the circle. Say the maximum the circle can be rotated is 60 degrees, either way.
I've extended the View class to create my custom View.
I've drawn a circle on my canvas with the drawCircle() method.
To rotate it, I know I'd have to do a canvas.rotate(), but I'm not sure what to fix the center as.
How do I measure this angle?
What do I rotate about?
public class DrawingView extends View
Paint paint;
Canvas canvas;
int originalX = 100;
int originalY = 50;
int radius = 75;
// ... some code ...
// paint, canvas initialised in constructors
@Override
protected void onDraw(Canvas canvas)
canvas.drawCircle(originalX, originalY, radius, paint);
// some more code ...
@Override
public boolean onTouchEvent(MotionEvent event)
int x = (int)event.getX();
int y = (int)event.getY();
case MotionEvent.ACTION_DOWN:
// Detect if touch in my circle
break;
case MotionEvent.ACTION_MOVE:
double tx = x - originalX;
double ty = y - originalY;
double tlength = Math.sqrt(tx*tx + ty*ty);
double angle = Math.acos(radius/tlength);
double degrees = (angle * 180)/Math.PI;
System.out.println("Degrees " + (angle*180)/Math.PI);
break;
The code I've displayed doesn't seem to give me a correct value.
Like, if I touch and drag all the way to the end of the screen, it gives me a value around 70 degrees. I don't think I'm calculating the angle right, but I have no idea how to either.
I followed the selected answer's way of finding the angle.
I then used canvas.rotate() before drawing the circle.
java
I'm trying to get my app to display a circle that the user can rotate to a certain degree by touching and dragging the circle. Say the maximum the circle can be rotated is 60 degrees, either way.
I've extended the View class to create my custom View.
I've drawn a circle on my canvas with the drawCircle() method.
To rotate it, I know I'd have to do a canvas.rotate(), but I'm not sure what to fix the center as.
How do I measure this angle?
What do I rotate about?
public class DrawingView extends View
Paint paint;
Canvas canvas;
int originalX = 100;
int originalY = 50;
int radius = 75;
// ... some code ...
// paint, canvas initialised in constructors
@Override
protected void onDraw(Canvas canvas)
canvas.drawCircle(originalX, originalY, radius, paint);
// some more code ...
@Override
public boolean onTouchEvent(MotionEvent event)
int x = (int)event.getX();
int y = (int)event.getY();
case MotionEvent.ACTION_DOWN:
// Detect if touch in my circle
break;
case MotionEvent.ACTION_MOVE:
double tx = x - originalX;
double ty = y - originalY;
double tlength = Math.sqrt(tx*tx + ty*ty);
double angle = Math.acos(radius/tlength);
double degrees = (angle * 180)/Math.PI;
System.out.println("Degrees " + (angle*180)/Math.PI);
break;
The code I've displayed doesn't seem to give me a correct value.
Like, if I touch and drag all the way to the end of the screen, it gives me a value around 70 degrees. I don't think I'm calculating the angle right, but I have no idea how to either.
I followed the selected answer's way of finding the angle.
I then used canvas.rotate() before drawing the circle.
java
java
edited Mar 28 at 2:54
user7999116
asked Mar 27 at 22:55
user7999116user7999116
518 bronze badges
518 bronze badges
1
The problem is that tx and ty don't necessarily fall on the circle and may be inside or outside of it, so your Math.acos() calculation is off. I think this is what you need. (But don't read the comments.)
– Cheticamp
Mar 28 at 1:25
This seems to work too. But the math's a little complicated for me. Thanks though!
– user7999116
Mar 28 at 2:18
add a comment |
1
The problem is that tx and ty don't necessarily fall on the circle and may be inside or outside of it, so your Math.acos() calculation is off. I think this is what you need. (But don't read the comments.)
– Cheticamp
Mar 28 at 1:25
This seems to work too. But the math's a little complicated for me. Thanks though!
– user7999116
Mar 28 at 2:18
1
1
The problem is that tx and ty don't necessarily fall on the circle and may be inside or outside of it, so your Math.acos() calculation is off. I think this is what you need. (But don't read the comments.)
– Cheticamp
Mar 28 at 1:25
The problem is that tx and ty don't necessarily fall on the circle and may be inside or outside of it, so your Math.acos() calculation is off. I think this is what you need. (But don't read the comments.)
– Cheticamp
Mar 28 at 1:25
This seems to work too. But the math's a little complicated for me. Thanks though!
– user7999116
Mar 28 at 2:18
This seems to work too. But the math's a little complicated for me. Thanks though!
– user7999116
Mar 28 at 2:18
add a comment |
1 Answer
1
active
oldest
votes
I'm not sure I have your idea of how this should work down right. But the geometry there is certainly weird. tlength is the radius from the circle center to the fingerpress and you're doing an acos on it. But, that's wrong. acos is which values gives you the cos of that value. In theory that'll be a cosine wave of different angles. Which might be interesting but doesn't sound like what you want. It sounds like you want to call distance from center of 0 to be rotate by -60 degrees and radius rotate by 0 degrees and 2*radius as rotate +60 degrees. So just do that. You linearly interpolate the distance (60° * (distance/radius)) - 60° or whatever.
Though really it seems from a UI standpoint you'd be better off just letting the user change the actual angle on the circle by moving their finger to that angle. Then throw those values in an atan2() and limit it if it's beyond the permitted bounds.
There's many ways to do this. You can calculate the angle based on finger presses. So you can use the known points like center point and current polar coord. So if you have a current angle at distance of r the point at the other end is cos(x)*r, sin(y)*r if you have x and y of the where you want that end point then the distance from the center is sqrt(dx*dx + dy*dy) and the angle it's at is atan2(dy, dx). So you can go from polar to Cartesian with a bit of trig. If you want to call the difference between the center and the radius an angle you can linearly interpolate that.
Here's a quick rendering of a view that does it like that. There are other UI choices that could be done instead like not doing the actual angle but doing the change of the angle, so you're moving the circle like it's a knob or something.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class RotateCircleView extends View
static final double TAU = Math.PI * 2;
Paint paint;
double angle = 0;
double radius = 0;
double ix = Double.NaN, iy = Double.NaN;
public RotateCircleView(Context context)
super(context);
init();
public RotateCircleView(Context context, @Nullable AttributeSet attrs)
super(context, attrs);
init();
public RotateCircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr)
super(context, attrs, defStyleAttr);
init();
public void init()
paint = new Paint();
paint.setAlpha(100);
paint.setStrokeWidth(20);
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
super.onSizeChanged(w, h, oldw, oldh);
ix = w / 2.0;
iy = h / 2.0;
radius = Math.min(ix, iy) / 2.0;
invalidate();
@Override
protected void onDraw(Canvas canvas)
if (Double.isNaN(ix)) return;
super.onDraw(canvas);
canvas.save();
canvas.rotate((float) ((TAU * -angle) / 360.0), (float) ix, (float) iy);
canvas.drawCircle((float) ix, (float) iy, (float) radius, paint);
double limit = TAU / 6.0;
if (angle > limit) angle = limit;
if (angle < -limit) angle = -limit;
double tx = ix + Math.cos(angle) * radius;
double ty = iy + Math.sin(angle) * radius;
canvas.drawLine((float) ix, (float) iy, (float) tx, (float) ty, paint);
canvas.restore();
public boolean onTouchEvent(MotionEvent event)
double mx = event.getX();
double my = event.getY();
double dx = mx - ix;
double dy = my - iy;
switch (event.getAction())
case MotionEvent.ACTION_MOVE:
//radius = Math.sqrt(dx * dx + dy * dy);
angle = Math.atan2(dy, dx);
invalidate();
break;
return true;
How do I get the user to decide the angle, that is, how do I rotate to the point they put their finger on? And how do I check if this angle falls in my range [-60, 60]?
– user7999116
Mar 28 at 1:47
There's multiple ways to do the UI there. The math depends a bit which way you're going to do it. If you want the angle changed based on the distance from the center of the circle that's a different set of math. If you want the angle to be whatever their fingerpress is at you do atan2(dy, dx) and say that that is the angle.
– Tatarize
Mar 28 at 1:56
If a,b is the center of my circle and x,y the co-ordinates of the finger press, is dy = y-b, dx = x-a?
– user7999116
Mar 28 at 2:00
1
public static double angleR(double a, double b, double x, double y) return Math.atan2(y - a, x - b);
– Tatarize
Mar 28 at 2:04
The main thing to grasp is that when you have two points, one for the center of the circle and another one, you can solve for the angle between them, the distance between them, and if you have a set radius etc. you can mess with the numbers. The angle between those points is Math.atan2(y-a,x-b) the distance is sqrt(dx * dx, dy * dy). If you have the angle and distance it's x = cos(angle)*distance and y = sin(angle)*distance so you can jump between the systems pretty easily. Even doing things like finding the new position on the radius at the angle found by applying delta-angle.
– Tatarize
Mar 28 at 2:38
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55387714%2frotate-circle-drawn-on-canvas-to-point-marked-by-touch%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I'm not sure I have your idea of how this should work down right. But the geometry there is certainly weird. tlength is the radius from the circle center to the fingerpress and you're doing an acos on it. But, that's wrong. acos is which values gives you the cos of that value. In theory that'll be a cosine wave of different angles. Which might be interesting but doesn't sound like what you want. It sounds like you want to call distance from center of 0 to be rotate by -60 degrees and radius rotate by 0 degrees and 2*radius as rotate +60 degrees. So just do that. You linearly interpolate the distance (60° * (distance/radius)) - 60° or whatever.
Though really it seems from a UI standpoint you'd be better off just letting the user change the actual angle on the circle by moving their finger to that angle. Then throw those values in an atan2() and limit it if it's beyond the permitted bounds.
There's many ways to do this. You can calculate the angle based on finger presses. So you can use the known points like center point and current polar coord. So if you have a current angle at distance of r the point at the other end is cos(x)*r, sin(y)*r if you have x and y of the where you want that end point then the distance from the center is sqrt(dx*dx + dy*dy) and the angle it's at is atan2(dy, dx). So you can go from polar to Cartesian with a bit of trig. If you want to call the difference between the center and the radius an angle you can linearly interpolate that.
Here's a quick rendering of a view that does it like that. There are other UI choices that could be done instead like not doing the actual angle but doing the change of the angle, so you're moving the circle like it's a knob or something.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class RotateCircleView extends View
static final double TAU = Math.PI * 2;
Paint paint;
double angle = 0;
double radius = 0;
double ix = Double.NaN, iy = Double.NaN;
public RotateCircleView(Context context)
super(context);
init();
public RotateCircleView(Context context, @Nullable AttributeSet attrs)
super(context, attrs);
init();
public RotateCircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr)
super(context, attrs, defStyleAttr);
init();
public void init()
paint = new Paint();
paint.setAlpha(100);
paint.setStrokeWidth(20);
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
super.onSizeChanged(w, h, oldw, oldh);
ix = w / 2.0;
iy = h / 2.0;
radius = Math.min(ix, iy) / 2.0;
invalidate();
@Override
protected void onDraw(Canvas canvas)
if (Double.isNaN(ix)) return;
super.onDraw(canvas);
canvas.save();
canvas.rotate((float) ((TAU * -angle) / 360.0), (float) ix, (float) iy);
canvas.drawCircle((float) ix, (float) iy, (float) radius, paint);
double limit = TAU / 6.0;
if (angle > limit) angle = limit;
if (angle < -limit) angle = -limit;
double tx = ix + Math.cos(angle) * radius;
double ty = iy + Math.sin(angle) * radius;
canvas.drawLine((float) ix, (float) iy, (float) tx, (float) ty, paint);
canvas.restore();
public boolean onTouchEvent(MotionEvent event)
double mx = event.getX();
double my = event.getY();
double dx = mx - ix;
double dy = my - iy;
switch (event.getAction())
case MotionEvent.ACTION_MOVE:
//radius = Math.sqrt(dx * dx + dy * dy);
angle = Math.atan2(dy, dx);
invalidate();
break;
return true;
How do I get the user to decide the angle, that is, how do I rotate to the point they put their finger on? And how do I check if this angle falls in my range [-60, 60]?
– user7999116
Mar 28 at 1:47
There's multiple ways to do the UI there. The math depends a bit which way you're going to do it. If you want the angle changed based on the distance from the center of the circle that's a different set of math. If you want the angle to be whatever their fingerpress is at you do atan2(dy, dx) and say that that is the angle.
– Tatarize
Mar 28 at 1:56
If a,b is the center of my circle and x,y the co-ordinates of the finger press, is dy = y-b, dx = x-a?
– user7999116
Mar 28 at 2:00
1
public static double angleR(double a, double b, double x, double y) return Math.atan2(y - a, x - b);
– Tatarize
Mar 28 at 2:04
The main thing to grasp is that when you have two points, one for the center of the circle and another one, you can solve for the angle between them, the distance between them, and if you have a set radius etc. you can mess with the numbers. The angle between those points is Math.atan2(y-a,x-b) the distance is sqrt(dx * dx, dy * dy). If you have the angle and distance it's x = cos(angle)*distance and y = sin(angle)*distance so you can jump between the systems pretty easily. Even doing things like finding the new position on the radius at the angle found by applying delta-angle.
– Tatarize
Mar 28 at 2:38
add a comment |
I'm not sure I have your idea of how this should work down right. But the geometry there is certainly weird. tlength is the radius from the circle center to the fingerpress and you're doing an acos on it. But, that's wrong. acos is which values gives you the cos of that value. In theory that'll be a cosine wave of different angles. Which might be interesting but doesn't sound like what you want. It sounds like you want to call distance from center of 0 to be rotate by -60 degrees and radius rotate by 0 degrees and 2*radius as rotate +60 degrees. So just do that. You linearly interpolate the distance (60° * (distance/radius)) - 60° or whatever.
Though really it seems from a UI standpoint you'd be better off just letting the user change the actual angle on the circle by moving their finger to that angle. Then throw those values in an atan2() and limit it if it's beyond the permitted bounds.
There's many ways to do this. You can calculate the angle based on finger presses. So you can use the known points like center point and current polar coord. So if you have a current angle at distance of r the point at the other end is cos(x)*r, sin(y)*r if you have x and y of the where you want that end point then the distance from the center is sqrt(dx*dx + dy*dy) and the angle it's at is atan2(dy, dx). So you can go from polar to Cartesian with a bit of trig. If you want to call the difference between the center and the radius an angle you can linearly interpolate that.
Here's a quick rendering of a view that does it like that. There are other UI choices that could be done instead like not doing the actual angle but doing the change of the angle, so you're moving the circle like it's a knob or something.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class RotateCircleView extends View
static final double TAU = Math.PI * 2;
Paint paint;
double angle = 0;
double radius = 0;
double ix = Double.NaN, iy = Double.NaN;
public RotateCircleView(Context context)
super(context);
init();
public RotateCircleView(Context context, @Nullable AttributeSet attrs)
super(context, attrs);
init();
public RotateCircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr)
super(context, attrs, defStyleAttr);
init();
public void init()
paint = new Paint();
paint.setAlpha(100);
paint.setStrokeWidth(20);
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
super.onSizeChanged(w, h, oldw, oldh);
ix = w / 2.0;
iy = h / 2.0;
radius = Math.min(ix, iy) / 2.0;
invalidate();
@Override
protected void onDraw(Canvas canvas)
if (Double.isNaN(ix)) return;
super.onDraw(canvas);
canvas.save();
canvas.rotate((float) ((TAU * -angle) / 360.0), (float) ix, (float) iy);
canvas.drawCircle((float) ix, (float) iy, (float) radius, paint);
double limit = TAU / 6.0;
if (angle > limit) angle = limit;
if (angle < -limit) angle = -limit;
double tx = ix + Math.cos(angle) * radius;
double ty = iy + Math.sin(angle) * radius;
canvas.drawLine((float) ix, (float) iy, (float) tx, (float) ty, paint);
canvas.restore();
public boolean onTouchEvent(MotionEvent event)
double mx = event.getX();
double my = event.getY();
double dx = mx - ix;
double dy = my - iy;
switch (event.getAction())
case MotionEvent.ACTION_MOVE:
//radius = Math.sqrt(dx * dx + dy * dy);
angle = Math.atan2(dy, dx);
invalidate();
break;
return true;
How do I get the user to decide the angle, that is, how do I rotate to the point they put their finger on? And how do I check if this angle falls in my range [-60, 60]?
– user7999116
Mar 28 at 1:47
There's multiple ways to do the UI there. The math depends a bit which way you're going to do it. If you want the angle changed based on the distance from the center of the circle that's a different set of math. If you want the angle to be whatever their fingerpress is at you do atan2(dy, dx) and say that that is the angle.
– Tatarize
Mar 28 at 1:56
If a,b is the center of my circle and x,y the co-ordinates of the finger press, is dy = y-b, dx = x-a?
– user7999116
Mar 28 at 2:00
1
public static double angleR(double a, double b, double x, double y) return Math.atan2(y - a, x - b);
– Tatarize
Mar 28 at 2:04
The main thing to grasp is that when you have two points, one for the center of the circle and another one, you can solve for the angle between them, the distance between them, and if you have a set radius etc. you can mess with the numbers. The angle between those points is Math.atan2(y-a,x-b) the distance is sqrt(dx * dx, dy * dy). If you have the angle and distance it's x = cos(angle)*distance and y = sin(angle)*distance so you can jump between the systems pretty easily. Even doing things like finding the new position on the radius at the angle found by applying delta-angle.
– Tatarize
Mar 28 at 2:38
add a comment |
I'm not sure I have your idea of how this should work down right. But the geometry there is certainly weird. tlength is the radius from the circle center to the fingerpress and you're doing an acos on it. But, that's wrong. acos is which values gives you the cos of that value. In theory that'll be a cosine wave of different angles. Which might be interesting but doesn't sound like what you want. It sounds like you want to call distance from center of 0 to be rotate by -60 degrees and radius rotate by 0 degrees and 2*radius as rotate +60 degrees. So just do that. You linearly interpolate the distance (60° * (distance/radius)) - 60° or whatever.
Though really it seems from a UI standpoint you'd be better off just letting the user change the actual angle on the circle by moving their finger to that angle. Then throw those values in an atan2() and limit it if it's beyond the permitted bounds.
There's many ways to do this. You can calculate the angle based on finger presses. So you can use the known points like center point and current polar coord. So if you have a current angle at distance of r the point at the other end is cos(x)*r, sin(y)*r if you have x and y of the where you want that end point then the distance from the center is sqrt(dx*dx + dy*dy) and the angle it's at is atan2(dy, dx). So you can go from polar to Cartesian with a bit of trig. If you want to call the difference between the center and the radius an angle you can linearly interpolate that.
Here's a quick rendering of a view that does it like that. There are other UI choices that could be done instead like not doing the actual angle but doing the change of the angle, so you're moving the circle like it's a knob or something.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class RotateCircleView extends View
static final double TAU = Math.PI * 2;
Paint paint;
double angle = 0;
double radius = 0;
double ix = Double.NaN, iy = Double.NaN;
public RotateCircleView(Context context)
super(context);
init();
public RotateCircleView(Context context, @Nullable AttributeSet attrs)
super(context, attrs);
init();
public RotateCircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr)
super(context, attrs, defStyleAttr);
init();
public void init()
paint = new Paint();
paint.setAlpha(100);
paint.setStrokeWidth(20);
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
super.onSizeChanged(w, h, oldw, oldh);
ix = w / 2.0;
iy = h / 2.0;
radius = Math.min(ix, iy) / 2.0;
invalidate();
@Override
protected void onDraw(Canvas canvas)
if (Double.isNaN(ix)) return;
super.onDraw(canvas);
canvas.save();
canvas.rotate((float) ((TAU * -angle) / 360.0), (float) ix, (float) iy);
canvas.drawCircle((float) ix, (float) iy, (float) radius, paint);
double limit = TAU / 6.0;
if (angle > limit) angle = limit;
if (angle < -limit) angle = -limit;
double tx = ix + Math.cos(angle) * radius;
double ty = iy + Math.sin(angle) * radius;
canvas.drawLine((float) ix, (float) iy, (float) tx, (float) ty, paint);
canvas.restore();
public boolean onTouchEvent(MotionEvent event)
double mx = event.getX();
double my = event.getY();
double dx = mx - ix;
double dy = my - iy;
switch (event.getAction())
case MotionEvent.ACTION_MOVE:
//radius = Math.sqrt(dx * dx + dy * dy);
angle = Math.atan2(dy, dx);
invalidate();
break;
return true;
I'm not sure I have your idea of how this should work down right. But the geometry there is certainly weird. tlength is the radius from the circle center to the fingerpress and you're doing an acos on it. But, that's wrong. acos is which values gives you the cos of that value. In theory that'll be a cosine wave of different angles. Which might be interesting but doesn't sound like what you want. It sounds like you want to call distance from center of 0 to be rotate by -60 degrees and radius rotate by 0 degrees and 2*radius as rotate +60 degrees. So just do that. You linearly interpolate the distance (60° * (distance/radius)) - 60° or whatever.
Though really it seems from a UI standpoint you'd be better off just letting the user change the actual angle on the circle by moving their finger to that angle. Then throw those values in an atan2() and limit it if it's beyond the permitted bounds.
There's many ways to do this. You can calculate the angle based on finger presses. So you can use the known points like center point and current polar coord. So if you have a current angle at distance of r the point at the other end is cos(x)*r, sin(y)*r if you have x and y of the where you want that end point then the distance from the center is sqrt(dx*dx + dy*dy) and the angle it's at is atan2(dy, dx). So you can go from polar to Cartesian with a bit of trig. If you want to call the difference between the center and the radius an angle you can linearly interpolate that.
Here's a quick rendering of a view that does it like that. There are other UI choices that could be done instead like not doing the actual angle but doing the change of the angle, so you're moving the circle like it's a knob or something.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class RotateCircleView extends View
static final double TAU = Math.PI * 2;
Paint paint;
double angle = 0;
double radius = 0;
double ix = Double.NaN, iy = Double.NaN;
public RotateCircleView(Context context)
super(context);
init();
public RotateCircleView(Context context, @Nullable AttributeSet attrs)
super(context, attrs);
init();
public RotateCircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr)
super(context, attrs, defStyleAttr);
init();
public void init()
paint = new Paint();
paint.setAlpha(100);
paint.setStrokeWidth(20);
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
super.onSizeChanged(w, h, oldw, oldh);
ix = w / 2.0;
iy = h / 2.0;
radius = Math.min(ix, iy) / 2.0;
invalidate();
@Override
protected void onDraw(Canvas canvas)
if (Double.isNaN(ix)) return;
super.onDraw(canvas);
canvas.save();
canvas.rotate((float) ((TAU * -angle) / 360.0), (float) ix, (float) iy);
canvas.drawCircle((float) ix, (float) iy, (float) radius, paint);
double limit = TAU / 6.0;
if (angle > limit) angle = limit;
if (angle < -limit) angle = -limit;
double tx = ix + Math.cos(angle) * radius;
double ty = iy + Math.sin(angle) * radius;
canvas.drawLine((float) ix, (float) iy, (float) tx, (float) ty, paint);
canvas.restore();
public boolean onTouchEvent(MotionEvent event)
double mx = event.getX();
double my = event.getY();
double dx = mx - ix;
double dy = my - iy;
switch (event.getAction())
case MotionEvent.ACTION_MOVE:
//radius = Math.sqrt(dx * dx + dy * dy);
angle = Math.atan2(dy, dx);
invalidate();
break;
return true;
edited Mar 28 at 4:07
answered Mar 28 at 0:19
TatarizeTatarize
7,0373 gold badges39 silver badges46 bronze badges
7,0373 gold badges39 silver badges46 bronze badges
How do I get the user to decide the angle, that is, how do I rotate to the point they put their finger on? And how do I check if this angle falls in my range [-60, 60]?
– user7999116
Mar 28 at 1:47
There's multiple ways to do the UI there. The math depends a bit which way you're going to do it. If you want the angle changed based on the distance from the center of the circle that's a different set of math. If you want the angle to be whatever their fingerpress is at you do atan2(dy, dx) and say that that is the angle.
– Tatarize
Mar 28 at 1:56
If a,b is the center of my circle and x,y the co-ordinates of the finger press, is dy = y-b, dx = x-a?
– user7999116
Mar 28 at 2:00
1
public static double angleR(double a, double b, double x, double y) return Math.atan2(y - a, x - b);
– Tatarize
Mar 28 at 2:04
The main thing to grasp is that when you have two points, one for the center of the circle and another one, you can solve for the angle between them, the distance between them, and if you have a set radius etc. you can mess with the numbers. The angle between those points is Math.atan2(y-a,x-b) the distance is sqrt(dx * dx, dy * dy). If you have the angle and distance it's x = cos(angle)*distance and y = sin(angle)*distance so you can jump between the systems pretty easily. Even doing things like finding the new position on the radius at the angle found by applying delta-angle.
– Tatarize
Mar 28 at 2:38
add a comment |
How do I get the user to decide the angle, that is, how do I rotate to the point they put their finger on? And how do I check if this angle falls in my range [-60, 60]?
– user7999116
Mar 28 at 1:47
There's multiple ways to do the UI there. The math depends a bit which way you're going to do it. If you want the angle changed based on the distance from the center of the circle that's a different set of math. If you want the angle to be whatever their fingerpress is at you do atan2(dy, dx) and say that that is the angle.
– Tatarize
Mar 28 at 1:56
If a,b is the center of my circle and x,y the co-ordinates of the finger press, is dy = y-b, dx = x-a?
– user7999116
Mar 28 at 2:00
1
public static double angleR(double a, double b, double x, double y) return Math.atan2(y - a, x - b);
– Tatarize
Mar 28 at 2:04
The main thing to grasp is that when you have two points, one for the center of the circle and another one, you can solve for the angle between them, the distance between them, and if you have a set radius etc. you can mess with the numbers. The angle between those points is Math.atan2(y-a,x-b) the distance is sqrt(dx * dx, dy * dy). If you have the angle and distance it's x = cos(angle)*distance and y = sin(angle)*distance so you can jump between the systems pretty easily. Even doing things like finding the new position on the radius at the angle found by applying delta-angle.
– Tatarize
Mar 28 at 2:38
How do I get the user to decide the angle, that is, how do I rotate to the point they put their finger on? And how do I check if this angle falls in my range [-60, 60]?
– user7999116
Mar 28 at 1:47
How do I get the user to decide the angle, that is, how do I rotate to the point they put their finger on? And how do I check if this angle falls in my range [-60, 60]?
– user7999116
Mar 28 at 1:47
There's multiple ways to do the UI there. The math depends a bit which way you're going to do it. If you want the angle changed based on the distance from the center of the circle that's a different set of math. If you want the angle to be whatever their fingerpress is at you do atan2(dy, dx) and say that that is the angle.
– Tatarize
Mar 28 at 1:56
There's multiple ways to do the UI there. The math depends a bit which way you're going to do it. If you want the angle changed based on the distance from the center of the circle that's a different set of math. If you want the angle to be whatever their fingerpress is at you do atan2(dy, dx) and say that that is the angle.
– Tatarize
Mar 28 at 1:56
If a,b is the center of my circle and x,y the co-ordinates of the finger press, is dy = y-b, dx = x-a?
– user7999116
Mar 28 at 2:00
If a,b is the center of my circle and x,y the co-ordinates of the finger press, is dy = y-b, dx = x-a?
– user7999116
Mar 28 at 2:00
1
1
public static double angleR(double a, double b, double x, double y) return Math.atan2(y - a, x - b);
– Tatarize
Mar 28 at 2:04
public static double angleR(double a, double b, double x, double y) return Math.atan2(y - a, x - b);
– Tatarize
Mar 28 at 2:04
The main thing to grasp is that when you have two points, one for the center of the circle and another one, you can solve for the angle between them, the distance between them, and if you have a set radius etc. you can mess with the numbers. The angle between those points is Math.atan2(y-a,x-b) the distance is sqrt(dx * dx, dy * dy). If you have the angle and distance it's x = cos(angle)*distance and y = sin(angle)*distance so you can jump between the systems pretty easily. Even doing things like finding the new position on the radius at the angle found by applying delta-angle.
– Tatarize
Mar 28 at 2:38
The main thing to grasp is that when you have two points, one for the center of the circle and another one, you can solve for the angle between them, the distance between them, and if you have a set radius etc. you can mess with the numbers. The angle between those points is Math.atan2(y-a,x-b) the distance is sqrt(dx * dx, dy * dy). If you have the angle and distance it's x = cos(angle)*distance and y = sin(angle)*distance so you can jump between the systems pretty easily. Even doing things like finding the new position on the radius at the angle found by applying delta-angle.
– Tatarize
Mar 28 at 2:38
add a comment |
Got a question that you can’t ask on public Stack Overflow? Learn more about sharing private information with Stack Overflow for Teams.
Got a question that you can’t ask on public Stack Overflow? Learn more about sharing private information with Stack Overflow for Teams.
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55387714%2frotate-circle-drawn-on-canvas-to-point-marked-by-touch%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
The problem is that tx and ty don't necessarily fall on the circle and may be inside or outside of it, so your Math.acos() calculation is off. I think this is what you need. (But don't read the comments.)
– Cheticamp
Mar 28 at 1:25
This seems to work too. But the math's a little complicated for me. Thanks though!
– user7999116
Mar 28 at 2:18