What kind of connection exists between innerRadiusRatio and thicknessRatio from GradientDrawable class? - android

Let's supposed we've got a ring with inner radius R2 and outer radius R1. According documentation:
Inner radius of the ring expressed as a ratio of the ring's width.For instance, if innerRadiusRatio=9, then the inner radius equals the ring's width divided by 9
As I understand this means that innerRadiusRatio = 2*R1 / R2.
About thicknessRatio there is that:
Thickness of the ring expressed as a ratio of the ring's width. For instance, if thicknessRatio=3, then the thickness equals the ring's width divided by 3. So thicknessRatio = 2*R1 / (R1 - R2).
From this two equationÑ– we can get this one: thicknessRatio*(1-2/innerRadiusRatio)=2 which means that there is a connection between thicknessRatio and innerRadiusRatio. But there is nothing about this connection in GradientDrawable class documentation. And it doesn't seem that there is any connections between them as I can set thicknessRatio and innerRadiusRatio which doesn't satisfying last equation.
So tell me please where I'm wrong in my consideration or what are this parameters really responsible for?

I know this is pretty late, but it may help others looking for this.
In the documentation it says:
Inner radius of the ring expressed as a ratio of the ring's width.
The ring's width is not the Radius of the ring, it is the width of the view containing the ring. I draw this for an easier explanation:
That's the scheme of a view with a ring inside. The letters mean:
W: Width
P: Padding
Th: Thickness
Ir: Inner Radius.
And I will add:
R: Radius.
IRR: InnerRadiusRatio.
THR: ThicknesRatio.
The documentation actually describes the following relationship:
Ir = W/IRR
Th = W/THR
So you can actually calculate the Radius.
R = Ir + Th = W (1/IRR + 1/THR).
You can prove this by creating a view with a Ring that has:
InnerRadiusRatio="4"
ThicknessRatio="4".
This will create a ring that has exactly the same width as the view.
Note: All of the previous formulas are calculated with no padding. If there is padding on the View, you should replace every W with (W - P).

Ratios are a comparison of two numbers, so the above two equations can be rewritten as
Ratio1 = InnerRadius : Ring Width (where Ratio1 = InnerRadiusRatio)
Ratio2 = Thickness : Ring Width (where Ratio2 = ThicknessRatio)
Which means...
Ring Width = Ratio1 x Inner Radius = Ratio2 x Thickness
The "2" appeared since you added it into your equation. The only common denominator in all equation is "Ring Width". Trying it out with real numbers helps too.

Related

Projection and Translation in OpenGL ES 2

I have a question regarding transformations in OpenGL ES 2. I'm currently drawing a rectangle using triangle fans as depicted in the image below. The origin is located in its center, while its width and height are 0.6 and 2 respectively. I assume that these sizes are related to the model space. However, in order to maintain the ratio of height and width on a tablet or phone one has to do a projection that considers the proportion of the device lengths (again width and height). This is why I call orthoM(projectionMatrix, 0, -aspectRatio, aspectRatio, -1f, 1f, -1f, 1f);and the aspectRatio is given by float aspectRatio = (float) width / (float) height. This finally leads to the rectangle shown in the image below. Now, I would like to move the rectangle along the x-axis to the border of the screen. However, I was not able to come up with the correct calculation to do so, either I moved it too little or too much. So how would the calculation look like? Furtermore, I'm a little bit confused about the sizes given in the model space. What are the max and min values that can be achieved there?
Thanks a lot!
Vertex position of the rectangle are in world space. A way to do this it could be get the screen coordinates you want to move to and then transform them into world space.
For example:
If the screen is 300 x 200 and you are in the center 0,0 in world space (or 150, 100) in screen space). You want to translate to 300.
So the transformation should be screen_position to normalized device coordiantes and then multiply by inverseOf(projection matrix * view matrix) and divided by the w component.
Here it is explained for mouse that it is finally the same, just that you know the z because it is the one you used for your rectangle already (if it is on the plane x,y): OpenGL Math - Projecting Screen space to World space coords.

how to make custom view dial drawing numbers with trigonometry

Im trying to create an custom view that displays a dial with the numbers 1-10 around it. Im using trigonometry to find the X and Y positions for the numbers of the dial. I have no problems to find the positions around the circle but im unable to align them further in towards center of the dial. Look at number 6 for example, i just want it to be placed slightly above the thick white tick mark.
I have tried versions of "shortening the radius".
val diameter = Math.min(width, height)
val radius = diameter / 2
val distance = radius * 0.20f //20% of radius
And then deduct 'distance' from radius to find the X and Y positions there and then add the numbers on those positions with no luck.
Below is the code that calculates the X and Y positions and adds the numbers displayed in the dial screenshot.
for (i in 1..10) {
canvas?.drawText(i.toString(),cx.toFloat() +
(Math.cos(Math.toRadians(degrees.getInt(feetNumber,0).toDouble())).toFloat()) *
radius - (paint.measureText(i.toString()) / 2),
cy.toFloat() +
(Math.sin(Math.toRadians(degrees.getInt(feetNumber,0).toDouble())).toFloat()) *
radius + (paint.measureText(i.toString()) / 2), paint)
feetNumber++;
}
I have added the degrees in a array resource file.
<resources>
<array
name="degrees">
<item>270</item>
<item>306</item>
<item>342</item>
<item>18</item>
<item>54</item>
<item>90</item>
<item>126</item>
<item>162</item>
<item>198</item>
<item>234</item>
</array>
</resources>
I would be very grateful if any one can help me to understand how to draw the numbers a short space after the thick tick marks where you usually find the numbers in a dial.
I have found a solution to my problem. The problem was that i cant calulate the radius in the canvas?.drawText() so i needed to privide pre-calculated value.
val radius = diameter / 2
val mark = radius * 0.30f
val shorterRadius = radius - mark
and then use the shorterRadius inside canvas?.drawText() along with the rest of the calculations.
Then my dial look like the attached picture.

Android GestureOverlayView parameters

I started experimenting with Custom Gestures and the GestureOverlayView and noticed a few variables where I am not sure what they are for and what range of values can and should be assigned, the docs seem to be somewhat vague on those:
//Minimum curve angle a stroke must contain before it is recognized as a gesture.
android:gestureStrokeAngleThreshold
I assumed this is in degrees and when I add "25" here, a sharp edge must be contained in the gesture, but actually it still is detected ifI draw a circle or a perfect square.
//Minimum length of a stroke before it is recognized as a gesture.
android:gestureStrokeLengthThreshold
Is this in dp ? Because it seems like on smaller screens it is harder to trigger the gesture...
//Squareness threshold of a stroke before it is recognized as a gesture.
android:gestureStrokeSquarenessThreshold
what is this?
EDIT:
Ok I just realized that every prediction has a score value, which should be used to find out if the gesture performed actually meets the requirements, so I added a check if the prediction's score is greater than 1.
Still I am curious what those variables in GestureOverlayView are doing, so enlighten me :)
gestureStrokeLengthThreshold definitely is not density independent but apparently uses pixels. If you want to set a density independent threshold you can calculate the gestureStrokeLengthThreshold at runtime, like that:
DisplayMetrics metrics = getResources().getDisplayMetrics();
float normalizedScreenSize = (metrics.heightPixels + metrics.widthPixels) / 2.0f;
return normalizedScreenSize * GESTURE_LENGTH_THRESHOLD;
GESTURE_LENGTH_THRESHOLD would be a value representing how long the gesture should be. A value of 1.0 would roughly be the size of the screen (averaged from screen width and height)
Still I am interested in what those other variables in GestureOverlayView do, so if you know more - enlighten me :)

Movement along circle around a given point 2D

I want to move an object on a circle around a given point. I am using OpenGL on Android and my viewport is the screen resolution in landscape mode (1280 * 800). The point I want to rotate an object around is e.g (500, 300) and this is where the user pressed. I also have the radius of the desired circle r.
To sum it up, I've the center of the circle, the radius, and the angle (amount I want to move the object with each iteration of the game loop)
So far I tried this:
this.setPosX(((float)Math.cos(angle)*radius + center.x) * width);
this.setPosY(((float)Math.sin(angle)*radius + center.y) * height);
This will create a movement along an ellipsis, not a circle...
Can anyone please help me?
It produces an ellipse cause circles DON'T have heights. Try this instead
this.setPosX(((float)Math.cos(angle)*radius ) + center.x);
this.setPosY(((float)Math.sin(angle)*radius ) +center.y);
Just remove the width and height factors at the end. If you want a circle you cannot multiply the coordinates with different factors.
The formula is not correct because you are multiplying the correct value for a point around a circle by other different values which are not meaningful.
Think about the fact that you have c(x,y) which is the center and you need to move around by a value which is given by r(cos(angle)*radius, sin(angle)*radius).
What you obtain is p(x + cos(angle)*radius, y + sin(angle)*radius).
If you multiply these two coordinates by two other values (width and height in your formula) you are changing the factor either for the circle either for the center so you end up with not only an ellipse but an ellipse which changes its center.
So:
circle: p(c.x + cos(angle)*r, y + sin(angle)*r)
ellipse: p(c.x + cos(angle)*w, y + sin(angle)*h)
your formula: p((c.x + cos(angle)*r)*w, (c.y + sin(angle)*r)*h) (which makes no sense)

Android: Convert points to pixels

I have been using the pt unit in XML files. Now I need to set the width of an element at runtime. How can I set the width by points so that it is the same unit I have been using everywhere else. I assume I will need to multiply by resolution and dpi. A code sample would be best.
First you should really read the following in-depth article from the Android Developer Documentation :
http://developer.android.com/guide/practices/screens_support.html
Right in the middle you'll find the following under the title :
Do not use hard-coded pixel values in your code
// Convert the dps to pixels
final float scale = getContext().getResources().getDisplayMetrics().density;
mGestureThreshold = (int) (GESTURE_THRESHOLD_DP * scale + 0.5f);
You can use dip instead of pt

Categories

Resources