how to draw open ended circle in open gl es android - android

I need to draw a open ended circle as shown in image attached below
http://i49.tinypic.com/254y5bs.png
In the image the length of M should be greater than N, and the starting points of lines M and N are the center of circle. How can I draw an arc from the end point of N to M such that the arc looks linear in shape.
i am drawing the circle using the following code
for (int nR = N_IN_DEGREE; nR < M_IN_DEGREE && nCount < 360; nR++)
{
float fX = (float) Math.sin((float) nR * (Math.PI / 180)) + nR * 0.0008f;
float fY = (float) Math.cos((float) nR * (Math.PI / 180));
stVertexArray[nCount * 2] = fX;
stVertexArray[nCount * 2 + 1] = fY;
nCount++;
}
I get the open end circle from the angles N_IN_DEGREE to M_IN_DEGREE..but as I am increasing the value of fX by a factor of nR * 0.0008f , the complete circle is drawn only with 350 degrees,but i want 360..please run the code and see..my requirement is that I need to draw 2 lines n(length 0.8) and line m(length=1) from a single point and draw a arc from end point of n to end point of m and fill the arc with a color as well..

I can't make your code run, as there is not enough information, and I have trouble following your code.
But here is the basic idea, implemented in python.
import math
def genc(r1, r2, t1, t2, n):
dr = (r2 - r1)/n
dt = (t2 - t1)/n
x = []
y = []
for k in range(n):
r = r1 + k*dr
t = t1 + k*dt
x.append(r*math.cos(t))
y.append(r*math.sin(t))
return [x, y]
This is the output (plotted using matplotlib)
In [43]: a = circ.genc(1.0, 0.8, math.pi/2, 2*math.pi, 60)
In [44]: plot(a[0], a[1],'ro')
Out[44]: [<matplotlib.lines.Line2D at 0xb9285d0>]

Related

How to draw watchface 'ticks' on a square watch?

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.

Color Image in the Google Tango Leibniz API

I am trying to capture the image data in the onFrameAvailable method from a Google Tango. I am using the Leibniz release. In the header file it is said that the buffer contains HAL_PIXEL_FORMAT_YV12 pixel data. In the release notes they say the buffer contains YUV420SP. But in the documentation it is said the pixels are RGBA8888 format (). I am a little confused and additionally. I don't really get image data but a lot of magenta and green. Right now I am trying to convert from YUV to RGB similar to this one. I guess there is something wrong with the stride, too. Here eís the code of the onFrameAvailable method:
int size = (int)(buffer->width * buffer->height);
for (int i = 0; i < buffer->height; ++i)
{
for (int j = 0; j < buffer->width; ++j)
{
float y = buffer->data[i * buffer->stride + j];
float v = buffer->data[(i / 2) * (buffer->stride / 2) + (j / 2) + size];
float u = buffer->data[(i / 2) * (buffer->stride / 2) + (j / 2) + size + (size / 4)];
const float Umax = 0.436f;
const float Vmax = 0.615f;
y = y / 255.0f;
u = (u / 255.0f - 0.5f) ;
v = (v / 255.0f - 0.5f) ;
TangoData::GetInstance().color_buffer[3*(i*width+j)]=y;
TangoData::GetInstance().color_buffer[3*(i*width+j)+1]=u;
TangoData::GetInstance().color_buffer[3*(i*width+j)+2]=v;
}
}
I am doing the yuv to rgb conversion in the fragment shader.
Has anyone ever obtained an RGB image for the Google Tango Leibniz release? Or had someone similar problems when converting from YUV to RGB?
YUV420SP (aka NV21) is correct for the time being. An explanation is here. In this format you have a width x height array where each element is a Y byte, followed by a width/2 x height/2 array where each element is a V byte and a U byte. Your code is implementing YV21, which has separate arrays for V and U instead of interleaving them in one array.
You mention that you are doing YUV to RGB conversion in a fragment shader. If all you want to do with the camera images is draw then you can use TangoService_connectTextureId() and TangoService_updateTexture() instead of TangoService_connectOnFrameAvailable(). This approach delivers the camera image to you already in an OpenGL texture that gives your fragment shader RGB values without bothering with the pixel format details. You will need to bind to GL_TEXTURE_EXTERNAL_OES (instead of GL_TEXTURE_2D), and your fragment shader would look something like this:
#extension GL_OES_EGL_image_external : require
precision mediump float;
varying vec4 v_t;
uniform samplerExternalOES colorTexture;
void main() {
gl_FragColor = texture2D(colorTexture, v_t.xy);
}
If you really do want to pass YUV data to a fragment shader for some reason, you can do so without preprocessing it into floats. In fact, you don't need to unpack it at all - for NV21 just define a 1-byte texture for Y and a 2-byte texture for VU, and load the data as-is. Your fragment shader will use the same texture coordinates for both.
By the way, if someone experienced problems with capturing the image data on the Leibniz release, too: One of the developers told me that there is a bug concerning the camera and that it should be fixed with the Nash release.
The bug caused my buffer to be null but when I used the Nash update I got data again. However, right now the problem is that the data I am using doesn't make sense. I guess/hope the cause is that the Tablet didn't get the OTA update yet (there can be a gap between the actual release date and the OTA software update).
Just try code following:
//C#
public bool YV12ToPhoto(byte[] data, int width, int height, out Texture2D photo)
{
photo = new Texture2D(width, height);
int uv_buffer_offset = width * height;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
int x_index = j;
if (j % 2 != 0)
{
x_index = j - 1;
}
// Get the YUV color for this pixel.
int yValue = data[(i * width) + j];
int uValue = data[uv_buffer_offset + ((i / 2) * width) + x_index + 1];
int vValue = data[uv_buffer_offset + ((i / 2) * width) + x_index];
// Convert the YUV value to RGB.
float r = yValue + (1.370705f * (vValue - 128));
float g = yValue - (0.689001f * (vValue - 128)) - (0.337633f * (uValue - 128));
float b = yValue + (1.732446f * (uValue - 128));
Color co = new Color();
co.b = b < 0 ? 0 : (b > 255 ? 1 : b / 255.0f);
co.g = g < 0 ? 0 : (g > 255 ? 1 : g / 255.0f);
co.r = r < 0 ? 0 : (r > 255 ? 1 : r / 255.0f);
co.a = 1.0f;
photo.SetPixel(width - j - 1, height - i - 1, co);
}
}
return true;
}
I have succeeded.

android Dividing circle into N equal parts and know the coordinates of each dividing point

I have requirement that a circle should be divided into N equal parts based on number(2,3...n. But I want the coordinates of dividing points.
I have a circle whose centre(x,y) and radius(150) are known.
Question:
Is there any formula which gives me the coordinates of dividing points as shown in figure. Can anyone please tell me the formula. I want to implement it in Java.
Circle image for refrence:
I have already accepted answer... the formula works perfectly.
Here is the solution coded in Java. It will help other developers.
private int x[]; // Class variable
private int y[]; // Class variable
private void getPoints(int x0,int y0,int r,int noOfDividingPoints)
{
double angle = 0;
x = new int[noOfDividingPoints];
y = new int[noOfDividingPoints];
for(int i = 0 ; i < noOfDividingPoints ;i++)
{
angle = i * (360/noOfDividingPoints);
x[i] = (int) (x0 + r * Math.cos(Math.toRadians(angle)));
y[i] = (int) (y0 + r * Math.sin(Math.toRadians(angle)));
}
for(int i = 0 ; i < noOfDividingPoints ;i++)
{
Log.v("x",""+i+": "+x[i]);
Log.v("y",""+i+": "+y[i]);
}
}
Where x0 and y0 are co ordinates of circle's centre.and r is radius.
In my case:
Input x0 = 0 , y0 = 0 and r = 150 , noOfDividingPoints = 5
output
point1: (150,0)
point2: (46,142)
point3: (-121,88)
point4: (-121,-88)
point5: (46,-142)
You need to convert between polar and Cartesian coordinates. The angle you need is the angle between the (imaginary) vertical line that splits the circle in half and the line that connects the center with the circle's boundary. With this formula you can calculate the X and Y offsets from the center.
In your example image the first angle is 0, and the second one is 360/n. Each next is i*(360/n) where i is the index of the current line you need to draw. Applying this will give you the X and Y offsets in a clockwise order (and you can just add them to the X and Y coordinates of the center to find the coordinates of each point)
EDIT: some kind of pseudo-code:
//x0, y0 - center's coordinates
for(i = 1 to n)
{
angle = i * (360/n);
point.x = x0 + r * cos(angle);
point.y = y0 + r * sin(angle);
}

Drawing an arrow head in android

I am trying to draw an arrow to point to objects in am image. I have been able to write code to draw the line but cant seem to be able to find a way to draw the arrowhead.The code I wrote to draw a dragabble line is as follows.I need to draw an arrowhead on ACTION_UP event to the direction in which the line is pointing
if(event.getAction() ==MotionEvent.ACTION_DOWN) {
if (count==1){
x1 = event.getX();
y1 = event.getY();
System.out.println(count+"count of value a;skd");
Toast.makeText(getApplicationContext(), ""+(radius+count), Toast.LENGTH_LONG).show();
Log.i(TAG, "coordinate x1 : "+String.valueOf(x1)+" y1 : "+String.valueOf(y1));
}
}
else if(event.getAction() ==MotionEvent.ACTION_MOVE){
imageView.setImageBitmap(bmp2);
x2 = event.getX();
y2 = event.getY();
posX=(float)(x1+x2)/2;
posY=(float)(y1+y2)/2;
radius=(float) Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2))/2;
onDraw();
Toast.makeText(getApplicationContext(), ""+radius, Toast.LENGTH_LONG).show();
}
Hi, for anyone still needing help .This is how I did it in the end
float h=(float) 30.0;
float phi = (float) Math.atan2(y2 - y1, x2 - x1);
float angle1 = (float) (phi - Math.PI / 6);
float angle2 = (float) (phi + Math.PI / 6);
float x3 = (float) (x2 - h * Math.cos(angle1));
float x4 = (float) (x2 - h * Math.cos(angle2));
float y3 = (float) (y2 - h * Math.sin(angle1));
float y4 = (float) (y2 - h * Math.sin(angle2));
c.drawLine(x1, y1,x2,y2 ,pnt);
c.drawLine(x2, y2,x3,y3 ,pnt);
c.drawLine(x2, y2,x4,y4 ,pnt);
I got help from the accepted answer and ios section in stackoverflow
How I would do this is to find the slope of the line, which is drawn between two points(start and end). The slope would be (dy/dx), and that would be a good start point for your arrow. Assuming you want the base of the arrowhead to be perpendicular to the line of the arrow, to find the slope of the base you would find the opposite reciprocal of the slope of the line. for example, lets say that your line has a slope of 2. The slope for the base of your triangle would be (-1/2), because you do (1/(oldslope)) and multiply by -1. I don't know android very well, but if I remember correctly, in Java, you would use a drawPolygon method, and you would have to specify 4 points(3 unique and 1 the same as the first to close it). Given the slope of the base of the tip, we can get our first two points and our final point. You should know before you start the dimensions of the arrowhead you wish to draw, so in this case b will be the length of your baseline. If you take ϴ=arctan(dy/dx), that will give you an angle between the x axis and your baseline. With that ϴ value, you can do ydif = b*sin(ϴ) to get the difference in y value between the two base corners of your arrow. Doing the same thing but with xdif = b*cos(ϴ) gives you the difference in the x value between the two base points. If the location of the final point of the line that the user drew is, say, (x1, y1), then the locations of the basepoints of the triangle would be (x1-(xdif/2), y1-(ydif/2)) and (x1+(xdif/2), y1+(ydif/2)). These two points, p1 and p2, are the first, second, and fourth points in the draw polygon method. To find the third point, we need to find the angle of the original line, by doing ϴ=arctan(dy/dx), this time using your original dy/dx. with that angle. Before we finish the actual calculation of the point, you first have to know how far from the end of your line the tip of the arrow should actually be, in my case, I will use the var h and h = 10. To get the cordinate, (x,y), assuming the cordinate for the line tip is (x1, y1)you would do (x1+hcosϴ, y1+hsinϴ). Use that for the third value in drawPolygon(), and you should be done. sorry if I kind of rushed at the end, I got kind of tired of typing, comment if you need help.
If you managed to draw a line from the input event, you might additionally draw a triangle on its end indicating the direction.
On another project I drew a square everytime a magnetic point on a grid was touched (as you can see here) Sorry I can not provide you any sample code right now. But if that's a suitable approach for you, I might post it later.
Here is a good code, its not mine, It was a Java Graphics2D code that I converted to Canvas. All credit go to the original guy/lady who wrote it
private void drawArrowHead(Canvas canvas, Point tip, Point tail)
{
double dy = tip.y - tail.y;
double dx = tip.x - tail.x;
double theta = Math.atan2(dy, dx);
int tempX = tip.x ,tempY = tip.y;
//make arrow touch the circle
if(tip.x>tail.x && tip.y==tail.y)
{
tempX = (tip.x-10);
}
else if(tip.x<tail.x && tip.y==tail.y)
{
tempX = (tip.x+10);
}
else if(tip.y>tail.y && tip.x==tail.x)
{
tempY = (tip.y-10);
}
else if(tip.y<tail.y && tip.x==tail.x)
{
tempY = (tip.y+10);
}
else if(tip.x>tail.x || tip.x<tail.x)
{
int rCosTheta = (int) ((10)*Math.cos(theta)) ;
int xx = tip.x - rCosTheta;
int yy = (int) ((xx-tip.x)*(dy/dx) + tip.y);
tempX = xx;
tempY = yy;
}
double x, y, rho = theta + phi;
for(int j = 0; j < 2; j++)
{
x = tempX - arrowLength * Math.cos(rho);
y = tempY - arrowLength * Math.sin(rho);
canvas.drawLine(tempX,tempY,(int)x,(int)y,this.paint);
rho = theta - phi;
}
}
Just call this for both sides of your line and it will draw an arrow at each side!

How can i draw a cylinder in OpenGL-es on Android?

Can any one help me to draw a cylinder in OpenGL-es android. Whatever i draw its look like a rectangle.
I would appreciate any tips or link.
Here is the code i've tried:
int VERTICES=180; // more than needed
float coords[] = new float[VERTICES * 3];
float theta = 0;
for (int i = 0; i < VERTICES * 3; i += 3) {
coords[i + 0] = (float) Math.cos(theta);
coords[i + 1] = (float) Math.sin(theta);
coords[i + 2] = 0;
_vertexBuffer.put(coords[i + 0]);
_vertexBuffer.put(coords[i + 1]);
_vertexBuffer.put(coords[i + 2]);
theta += Math.PI / 90;
}
This will only draw a circle. A cylinder is more complicated as you will need to define vertices in a translated z plane. And define them with correct normals (either facing in as if you were inside the cylinder -ie a tunnel or out as in looking at a pipe) which is the trickier part.
I'm currently doing this now (which is what brought me here) and have the cylinder drawn but pretty sure my normals are incorrect as my lighting looks a bit off. I'll post some code when I figure it out.
Edit : realized the code also doesn't actually draw a circle. Here is how to do that (in 2D) :
R = Radius
NUM_VERTICES = Number of vertices you want to use in circle
delta = (Math.PI / 180) * (360 / NUM_VERTICES); //get delta in radians between vertex definition
for i = 0 ; i < NUM_VERTICES ; i ++
x = R * cos(Delta * i)
y = R * sin(Delta * i))
vertices[i] = x; vertices[i+1] = y; vertices[i+2] = 0;
end for
//note may need to redefine the original vertex to complete the circle depending on which GL draw type you are using. If so just take the arg to sin / cos to be 0 to complete the loop
Last Edit* : just realized I was overcomplicating the normals by re-using some calculate normal from triangle code I had. Instead I realized how simple the normal calculation is for a cylinder if you consider the the origin 0,0 to be the center of each circular strip. The normal will be = vertex position scaled to length 1. for normals facing in on a cylinder (ie tunnel) the x,y values would be inverted (this is a assuming you are looking down the -z axis).

Categories

Resources