I have a stroke circle path and a little fill circle path and i want to move the little circle along the stroke circle path with touch, the little circle should not be outside the stroke circle. How can i do this ? Please help me
Your touch might be slighty outside of your circle path. To provide object position at the circle, you can make the next:
find position of touch against circle center
dx = touch.x - center.x
dy = touch.y - center.y
find distance from the center
dist = sqrt(dx*dx +dy*dy)
make new position at the same disraction form center but at circle radius distance
newx = center.x + radius * dx / dist
newy = center.y + radius * dy / dist
Related
According to official documents of Android on Matrix.
XXRotate(float degrees) --
process the matrix to rotate about (0,0) by the specified number of degrees.
XXRotate(float degrees, float px, float py) --
process the matrix to rotate by the specified number of degrees, with a pivot point at (px, py).
XX set, post or pre as per needed.
for example : XXRotate(90, center_point_x_of_view, center_point_y_of_view)
Does it take some translate regarding the pivot points while specifying some pivot points ?
what are the changes in origin coordinates points on views after first rotation?
As an example, let's take a square with a width and height of 10. The upper left corner is at the origin of (0,0) which puts the lower right corner at (10,10).
If we transform that square with matrix.setRotate(180F) we would expect that the origin point — being the pivot point — won't move, while the lower right corner is moved to (-10, -10).
Now let's say we transform the square with matrix.setRotate(180F, 5F, 5F). We have put the pivot point at the center of the square, so we expect that the origin moves to (10, 10) and the lower right corner moves to (0, 0).
So after you look at all the math, it turns out that
matrix.setRotate(theta, pivotX, pivotY);
is really just a shorter version of
matrix.setRotate(theta);
matrix.preTranslate(-pivotX, -pivotY);
matrix.postTranslate(pivotX, pivotY);
If you want to know the changes of the points, for the rotation the X changes by the cosine of the angle and the y changes by the sine of the angle.
So simple rotation:
float thetaR = theta * Math.PI / 180F; // convert degrees to radians
int x2 = Math.round(x * (float) Math.cos(thetaR));
int y2 = Math.round(y * (float) Math.sin(thetaR));
And putting it all together, you have
float thetaR = theta * Math.PI / 180F; // convert degrees to radians
int x2 = Math.round((x - pivotX) * (float) Math.cos(thetaR) + pivotX);
int y2 = Math.round((y - pivotY) * (float) Math.sin(thetaR) + pivotY);
I currently have this snippet generating the ticks around the outside of and android wear watchface
float innerMainTickRadius = mCenterX - 35;
for(int tickIndex = 0; tickIndex < 12; tickIndex++) {
float tickRot = (float) (tickIndex * Math.PI * 2 / 12);
float innerX = (float) Math.sin(tickRot) * innerMainTickRadius;
float innerY = (float) -Math.cos(tickRot) * innerMainTickRadius;
float outerX = (float) Math.sin(tickRot) * mCenterX;
float outerY = (float) -Math.cos(tickRot) * mCenterX;
canvas.drawLine(mCenterX + innerX, mCenterY + innerY, mCenterX + outerX, mCenterY + outerY, mTickPaint);
}
Which generates the ticks well on a round watchface but on a square it turns out like this:
but I'd like them to not be circular, but instead fit the shape a bit more suitably, e.g:
Is there a standard way to do this? I'm guessing I can't use trig again...
Of course you use geometry and trig. For example any line you put on the clock face you want to point to the center so one part will be the given (x,y) and the other will be arctan2(cy-y,cx-x) giving you the angle from the point you have towards the center (cx,cy) then simply draw the line in the direction of the center of a given length r, by drawing the line from x,y to cos(angle) * r, sin(angle) * r.
However, given your sample image you might want to draw the line from x,y to x+r,y then rotate the canvas by angle so that you can draw those numbers tweaked like that. Be sure to do canvas.save() before tweaking the canvas' matrix and canvas.restore() after the tweak.
This leaves the math of whatever shape you want to draw your ticks from and the positions thereto. You can do this within a Path. So define the path for a rounded rectangle and then use the PathMeasure class to get the getPosTan() and then ignore the tangent and just use the position it gives you to find your position around a rounded rectangle. That or simply calculate those positions as the positions through either a line segment or a bezier section depending on the decided shape.
For example:
static final int TICKS = 12;
static final float TICKLENGTH = 20;
In the draw routine,
float left = cx - 50;
float top = cy - 50;
float right = cx + 50;
float bottom = cy + 50;
float ry = 20;
float rx = 20;
float width = right-left;
float height = bottom-top;
Path path = new Path();
path.moveTo(right, top + ry);
path.rQuadTo(0, -ry, -rx, -ry);
path.rLineTo(-(width - (2 * rx)), 0);
path.rQuadTo(-rx, 0, -rx, ry);
path.rLineTo(0, (height - (2 * ry)));
path.rQuadTo(0, ry, rx, ry);
path.rLineTo((width - (2 * rx)), 0);
path.rQuadTo(rx, 0, rx, -ry);
path.rLineTo(0, -(height - (2 * ry)));
path.close();
PathMeasure pathMeasure = new PathMeasure();
pathMeasure.setPath(path,true);
float length = pathMeasure.getLength();
float[] pos = new float[2];
float r = TICKLENGTH;
for (int i = 0; i < TICKS; i++) {
pathMeasure.getPosTan(i * (length/TICKS),pos,null);
double angle = Math.atan2(cy - pos[1], cx - pos[0]); //yes, y then x.
double cos = Math.cos(angle);
double sin = Math.sin(angle);
canvas.drawLine(pos[0], pos[1], (float)(pos[0] + cos * r), (float)(pos[1] + sin * r), paint);
}
Admittedly it looks like:
So it would take a lot more work to get it looking like your image. But, it's totally doable. The path measure trick thing will work for any shape. I avoided using path.addRoundRect because of the Lollipop+ restriction. You can see my answer to that question here. And the other answers which are plenty fine to how to draw a rounded rectangle-esque shape. You can, if you would like to write an envelope function simply scale your current picture to the envelope of the rectangle according to the factor t, as it goes around the clock.
The angle is a function of the position now. I'm not immediately seeing the trick for getting a closed form in this case. But in the most general case, you could end up just storing the position of each tickmark, then you're just drawing the line that goes through that point and the center. so the angle at second i is just
theta(i)=arctan(y_pos(i) / x_pos(i))
assuming the center has coordinates (0,0). In this case, you only need to store the positions for 8 consecutive ticks because the face is periodic every 90 degrees and symmetric about the diagonals as well.
I have Circle X,Y and radius for drawing a circle, now I want to calculate the rectangle co-ordinates from this circle x,y, radius of the circle. I need help from this.
Thanks In Advance...
topx = X - radius
topy = Y - radius
bottomx = X + radius
bottomy = Y + radius
As you mention X and Y are center cordinates of circle then:-
topx = X - radius
topy = Y - radius
bottomx = X + radius
bottomy = Y + radius
I am facing problem in getting the touch point of the circle for the game i was developing
I tried to solve this by getting the points as below
public Actor hit(float x, float y, boolean touchable){
if(!this.isVisible() || this.getTouchable() == Touchable.disabled)
return null;
// Get center-point of bounding circle, also known as the center of the Rect
float centerX = _texture.getRegionWidth() / 2;
float centerY = _texture.getRegionHeight() / 2;
// Calculate radius of circle
float radius = (float) (Math.sqrt(centerX * centerX + centerY * centerY))-5f;
// And distance of point from the center of the circle
float distance = (float) Math.sqrt(((centerX - x) * (centerX - x))
+ ((centerY - y) * (centerY - y)));
// If the distance is less than the circle radius, it's a hit
if(distance <= radius) return this;
// Otherwise, it isn't
return null;}
I am getting hit positions inside circle but also the points around it near black spots, i only need the touch points near circle.
Would some body suggest the approach for achieving this.
Im guessing that you are comparing local rect coordinates (ie centerX, centerY) with screen coordinates x,y parameters that you are feeding to the function.
So you probably want to subtract the rect's x,y position from the parameters x,y so your parameters are in local coordinates.
So:
float lLocalX = x-rectX (assuming this is the rects x position on the screen)
float lLocalY = y-rectY (assuming this is the rects y position on the screen)
now you can compare them!
float distance = (float) Math.sqrt(((centerX - lLocalX ) * (centerX - lLocalX ))
+ ((centerY - lLocalY ) * (centerY - lLocalY )));
You can have a Circle object in your Actor: http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/Circle.html
Then check if the circle contains that point using the circle.contains(float x, float y) function.
Basically it'll look something like this:
public Actor hit(float x, float y, boolean touchable){
if(!this.isVisible() || this.getTouchable() == Touchable.disabled)
return null;
if (circle.contains(x,y)) return this;
return null;
}
Of course the downside is that if this is a dynamic object and it moves around a lot, then you'd have to constantly update the circles position. Hope this helps :)
Question:
How can I taken into account the rectangular shape of the screen to ensure that circles are drawn exactly to the padded boundary?
The following works for a 'round' area, but not a rectangular one...
dx = abs(center.x - place.x);
dy = abs(center.y - place.y);
dh = Math.sqrt((dx * dx) + (dy * dy));
radius = dh - padding;
Halo Design:
If the problem doesn't seem apparent, the following image represents the current approach which i'm using. Depending on where the place is effects how far it protrudes into the screen space.
I think this should work. Not tested.
dx = abs(placeLocationPixels.x - ourLocationPixels.x)
dy = abs(placeLocationPixels.y - ourLocationPixels.y)
ox = dx - ((screenSize.x / 2) - padding);
oy = dy - ((screenSize.y / 2) - padding);
if (ox < 0) ox = 0;
if (oy < 0) oy = 0;
radius = sqrt((ox*ox) + (oy*oy));
edit: this is not in any particular language.
I'm not sure but maybe you can calculate the convex hull, and then circumscribe it into a rectangle, then you will have the scale of your map to ensure that every circle is shown on the screen.
here: you can find information about the convex hull: http://en.wikipedia.org/wiki/Convex_hull