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;








2















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.










share|improve this question





















  • 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

















2















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.










share|improve this question





















  • 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













2












2








2


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.










share|improve this question
















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 android






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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












  • 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












1 Answer
1






active

oldest

votes


















0















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;







share|improve this answer



























  • 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










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
);



);













draft saved

draft discarded


















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









0















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;







share|improve this answer



























  • 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















0















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;







share|improve this answer



























  • 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













0














0










0









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;







share|improve this answer















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;








share|improve this answer














share|improve this answer



share|improve this answer








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

















  • 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






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.



















draft saved

draft discarded
















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

SQL error code 1064 with creating Laravel foreign keysForeign key constraints: When to use ON UPDATE and ON DELETEDropping column with foreign key Laravel error: General error: 1025 Error on renameLaravel SQL Can't create tableLaravel Migration foreign key errorLaravel php artisan migrate:refresh giving a syntax errorSQLSTATE[42S01]: Base table or view already exists or Base table or view already exists: 1050 Tableerror in migrating laravel file to xampp serverSyntax error or access violation: 1064:syntax to use near 'unsigned not null, modelName varchar(191) not null, title varchar(191) not nLaravel cannot create new table field in mysqlLaravel 5.7:Last migration creates table but is not registered in the migration table

용인 삼성생명 블루밍스 목차 통계 역대 감독 선수단 응원단 경기장 같이 보기 외부 링크 둘러보기 메뉴samsungblueminx.comeh선수 명단용인 삼성생명 블루밍스용인 삼성생명 블루밍스ehsamsungblueminx.comeheheheh

155 수학 과학 기타 둘러보기 메뉴eh추가해eh문서를 완성해