How to get (x,y) of circle surface? - java

I'm trying to draw line over all circle surface, my current shape look like:
My wrong attempt:
for (int i = 0; i < 24; i++) {
g.drawLine(xCenter - clockRadius + i , yCenter - clockRadius + i, xCenter - clockRadius + i + 5,
yCenter - clockRadius + i + 5);
}
I'm trying to draw a full clock :

You are looking for cosinus and sinus.
Your clock is a circle, and you can easily translate your steps into degrees on that circle. If you want to have 24 steps, 12 would be 180° (or π) and 24 would be 360°, or 2π. So to get the correct angles for each index, just devide 2π (360°) by 24 and multiply it by the current index. Then feed that resulting angle to the cos and sin functions, which give you the x and y coordinates respectively:
double x = Math.cos(2 * Math.PI / 24 * i);
double y = Math.sin(2 * Math.PI / 24 * i);
Of course you can optimize the 2 and the 24 into one constant that you define somewhere and then use in your code.

I suspect that you want to draw small segments - ticks, centered at circumference and directed from the circle center. In this case use trigonometry alike hour hands drawing.
for (int i = 0; i < 24; i++) {
double ang = i * Math.Pi / 12;
g.drawLine((int) (xCenter + (clockRadius - 5) * Math.Cos(ang)),
(int) (yCenter + (clockRadius - 5) * Math.Sin(ang)),
(int) (xCenter + (clockRadius + 5) * Math.Cos(ang)),
(int) (yCenter + (clockRadius + 5) * Math.Sin(ang)));
}

You need to calculate points over 360 degree not just 24, so you have the radius and angel rotation (angel rotation from 0 to 360) to get the proper point of (x,y) we need to multiply sin or cos of angel with radius.
for (int i = 0; i < 360; i++) {
int x = (int) (clockRadius * Math.cos(i)) + xCenter;
int y = (int) (clockRadius * Math.sin(i)) + yCenter;
g.drawLine(x, y, x + 5, y + 5);
}
Note: for better result you may need to develop two loops, one for right (180) part and another for left (180) part.
Edit: to get the right direction you need to check for angel e.g:
int xV = 0, yV = 0;
if (i <= 90){
xV = 5;
yV = 5;
}

Related

How do I apply a mathematical equation to each number in a for loop?

I've done some searching around and tried some solutions I've found, but a lot of them result in the same problem I am having. I'd like to apply a mathematical equation to each number of a for loop. The problem I am having is that the equation only occurs on the last number in that for loop. For example:
for (int i = 3; i <= 5; i++)
{
radius = i;
area = (Math.PI * (radius * radius));
System.out.println (radius)
}
My code is much more extensive than this, but this is the part I am having issues with. It prints:
3
4
5
Radius: 5
Area: 78.53981633974483
I tried using for each loop, while loop, putting the numbers in a variable to pull from, I'm kind of at my wits end on what to try myself without asking. I'd like the for loop to look like:
3
Radius: 3
Area: //... the area with radius 3...
4
Radius: 4
Area: //... the area with radius 4...
5
Radius: 5
Area: //...area with radius 5...
How would I go about going through each iteration of the for loop and apply the mathematical equation to it?
You did not post the full code, but from your output one can guess you have something like this:
int radius = 0;
double area = 0.0;
for (int i = 3; i <= 5; i++)
{
radius = i;
area = (Math.PI * (radius * radius));
System.out.println (radius)
}
System.out.println("Radius: " + radius);
System.out.println("Area: " + area);
With that your program loops over i = 3, 4, 5; for each i it calculates the area and prints the radius.
Only when the loop is over it prints radius and area - and exactly that is what you see in the output.
Change your code as commented by Federico to look like this:
int radius = 0;
double area = 0.0;
for (int i = 3; i <= 5; i++)
{
radius = i;
area = (Math.PI * (radius * radius));
System.out.println("Radius: " + radius);
System.out.println("Area: " + area);
}
Then it will loop over the same values, and for each perform the calculation and print the result.
Assuming you are using java 8, take advantage of it.
IntStream
.range(3, 6)
.forEach(radius -> {
float area = (float) (Math.PI * (radius * radius));
System.out.println("Radius: " + radius);
System.out.println("Area: " + area);
});

Draw cylinder from point X to point Y in Processing

I have to points in 3D space that I want to draw a cylinder between. I currently have this code:
applet.pushMatrix();
applet.stroke(0);
applet.fill(0);
applet.line(this.start.x, this.start.y, this.start.z, this.end.x, this.end.y, this.end.z); //debug, shows where the cylinder should be
applet.translate(this.start.x, this.start.y);
applet.beginShape(PConstants.TRIANGLE_STRIP);
float xdif = this.end.x - this.start.x;
float ydif = this.end.y - this.start.y;
float zdif = this.end.z - this.start.z;
float rx = (float)Math.atan(ydif / xdif);
float ry = (float)Math.atan(zdif / xdif);
float rz = (float)Math.atan(zdif == 0 ? 0 : ydif / zdif);
applet.rotateZ((float) (rx - Math.PI / 2));
applet.rotateY((float) (ry - Math.PI / 2));
applet.rotateX((float) (rz - Math.PI / 2));
float r = 20;
float len = HelperFunctions.distance(this.start, this.end) / 2;
boolean w = false;
for (int i = 0; i < 2; i += 1) {
for (float j = 0; j < Math.PI * 2 + 0.2; j += 0.4) {
w = !w;
float z = (i + (w ? 0 : 1)) * len;
float x = (float)(r * Math.cos(j));
float y = (float)(r * Math.sin(j));
applet.vertex(y, x, z);
}
}
applet.endShape();
applet.popMatrix();
The cylinder does draw correctly, however, it doesn't rotate correctly. I'm trying to use trig to determine the rotation angles, however, I'm not sure I've done it correctly. How would I get the correct angles to rotate around such that it is drawn from Vector start to Vector end?
Vector is a custom class with just a float x, y, z, and HelperFunctions.distance takes two Vectors and calculates the distance (pythagoras).
Thanks in advance.

Making a circle in an array (Tile based game light map)

I am making a tiled based game in java and I want to make a light map.
I am having some issues. I have the lightmap array that has lights placed on it that affect the array. Lights emit in a circle shape. It seems ok so far but its not exactly what I wanted.
Here is my code so far:
for(float i = 0; i < strength + 1; i++){
for(double u = 0.0f; u < 360; u += 0.5){
double angle = u * Math.PI / 180;
int x2 = (int)(x + i * Math.cos(angle));
int y2 = (int)(y + i * Math.sin(angle));
if(map[y2][x2] > 1 - 1 / i)
map[y2][x2] = 1 - 1 / i;
}
}
Result:
As you can see in the result, it seems as though the light is expanding too much on the bottom left side (red x's). How do I fix this?
Background info:
Strength:
The radius of how far the light reaches. This also
determines how bright the light will be at each tile of the array.
The Array "map" is a 2D float array. The engine I am using uses float
values for the alpha channel. The range is 0 (completely transparent)
to 1 (completely opaque).
Solution (Thanks to Gene):
for(int x2 = -strength; x2 <= strength; x2++){
for (int y2 = -strength; y2 <= strength; y2++) {
double r = Math.sqrt(x2 * x2 + y2 * y2);
double inv_rad = r <= strength + 1 ? 1 / r : 0;
if(map[y + y2][x + x2] > 1 - (float) inv_rad)
map[y + y2][x + x2] = 1 - (float) inv_rad;
}
}
Your algorithm suffers from integer truncation of the map indicies. Try it the other away around. Compute the distance from each pixel in a square surrounding the center to the center. From this distance calculate what the intensity ought to be. It will be something like this:
for (x = -R; x <= R; x++)
for (y = -R; y <= R; y++) {
double r = Math.sqrt(x * x + y * y);
double inv_rad = r <= R ? 1 / r : 0; // truncate outside radius R
map[yc + y][xc + x] = 1 - inv_rad;
}
Here xc and yc are the integer center coordinates. R is the half-size of the box around the center.
when i try to add this to my project i only get o.o back
the values i entered where 500, 500,50
private float map[][] = new float[1000][1000];
public void test(int x, int y, float strength){
public void addLight(int x,int y,int strength ){
for(int x2 = -strength; x2 <= strength; x2++){
for (int y2 = -strength; y2 <= strength; y2++) {
double r = Math.sqrt(x2 * x2 + y2 * y2);
double inv_rad = r <= strength + 1 ? 1 / r : 0;
if(map[y + y2][x + x2] > 1 - (float) inv_rad)
map[y + y2][x + x2] = 1 - (float) inv_rad;
System.out.println(map[y + y2][x + x2]);
}
}
}

OpenGL: two spheres in single vertex buffer

(Question is at bottom)Im learning opengl(using lwjgl) and done some drawing of flat shape through sending buffers. Now I need to draw many spheres in single buffer. In my last question, I was advised to use geometry instancing but I dont know how to use any shader language in java yet so I'm trying to make multiple objects in single buffer just like in the examples.
What I tried to generate two spheres by QUAD_STRIP style(using lwjgl's own GLU.Sphere() function to fill the buffers):
n=c1*(c2+1);
float rr=(float) Math.random();
float gg=(float) Math.random();
float bb=(float) Math.random();
float aa=(float) Math.random();
positions = new float[c1 * (c2+1) * 3*2 *2];
normals = new float[c1 * (c2+1) * 3*2 *2];
colors = new float[c1 * (c2+1) * 4*2 *2];
int counter=0;
float drho = 3.141593F / 32.0f;
float dtheta = 6.283186F / 32.0f;
float ds = 1.0F / 32.0f;
float dt = 1.0F / 32.0f;
float t = 1.0F;
/*first sphere*/
for (int i = 0; i < 32; i++) {
float rho = i * drho;
float s = 0.0F;
for (int j = 0; j <= 32; j++) {
float theta = j == 32 ? 0.0F : j * dtheta;
float x = (float) (-Math.sin(theta) * Math.sin(rho));
float y = (float) (Math.cos(theta) * Math.sin(rho));
float z = (float) (1.0f * Math.cos(rho));
normals[counter*3+0]=x*1.0f;normals[counter*3+1]=y*1.0f;normalscounter*3+2]=z*1.0f;
colors[counter*4+0]=rr;colors[counter*4+1]=gg;colors[counter*4+2]=bb;colors[counter*4+3]=1.0f/*aa*/;
positions[counter*3+0]=x*r;positions[counter*3+1]=y*r;positions[counter*3+2]=z*r;
counter++;
x = (float) (-Math.sin(theta) * Math.sin(rho + drho));
y = (float) (Math.cos(theta) * Math.sin(rho + drho));
z = (float) (1.0f * Math.cos(rho + drho));
normals[counter*3+0]=x*1.0f;normals[counter*3+1]=y*1.0f;normals[counter*3+2]=z*1.0f;
colors[counter*4+0]=rr;colors[counter*4+1]=gg;colors[counter*4+2]=bb;colors[counter*4+3]=1.0f/*aa*/;
positions[counter*3+0]=x*r;positions[counter*3+1]=y*r;positions[counter*3+2]=z*r;
counter++;
s += ds;
}
t -= dt;
}
/* first sphere end */
/* second sphere generation */
{
drho = 3.141593F / 32.0f;
dtheta = 6.283186F / 32.0f;
ds = 1.0F / 32.0f;
dt = 1.0F / 32.0f;
t = 1.0F;
for (int i = 0; i < 32; i++) {
float rho = i * drho;
float s = 0.0F;
for (int j = 0; j <= 32; j++) {
float theta = j == 32 ? 0.0F : j * dtheta;
float x = (float) (-Math.sin(theta) * Math.sin(rho));
float y = (float) (Math.cos(theta) * Math.sin(rho));
float z = (float) (1.0f * Math.cos(rho));
normals[counter*3+0]=x*1.0f;normals[counter*3+1]=y*1.0f;normals[counter*3+2]=z*1.0f;
colors[counter*4+0]=rr;colors[counter*4+1]=gg;colors[counter*4+2]=bb;colors[counter*4+3]=1.0f/*aa*/;
positions[counter*3+0]=x*r+1.0f;positions[counter*3+1]=y*r+1.0f;positions[counter*3+2]=z*r+1.0f;
counter++;
x = (float) (-Math.sin(theta) * Math.sin(rho + drho));
y = (float) (Math.cos(theta) * Math.sin(rho + drho));
z = (float) (1.0f * Math.cos(rho + drho));
normals[counter*3+0]=x*1.0f;normals[counter*3+1]=y*1.0f;normals[counter*3+2]=z*1.0f;
colors[counter*4+0]=rr;colors[counter*4+1]=gg;colors[counter*4+2]=bb;colors[counter*4+3]=1.0f/*aa*/;
positions[counter*3+0]=x*r+1.0f;positions[counter*3+1]=y*r+1.0f;positions[counter*3+2]=z*r+1.0f;
counter++;
s += ds;
}
t -= dt;
}
}
/*second sphere end*/
positionsBuf=BufferUtils.createFloatBuffer(c1 * (c2+1) * 3*2 *2);
positionsBuf.put(positions);
positionsBuf.rewind();
colorsBuf=BufferUtils.createFloatBuffer(c1 * (c2+1) * 4*2 *2);
colorsBuf.put(colors);
colorsBuf.rewind();
normalsBuf=BufferUtils.createFloatBuffer(c1 * (c2+1) * 3*2 *2);
normalsBuf.put(normals);
normalsBuf.rewind();
As you can see, below image shows how two spheres are drawn. There is an unwanted link between two.
Most probably the rope is caused by the last point of first sphere and first point of second sphere. Is there some kind of delimiter/drawing-hint to separate two drawings in the same buffer?
Here is how they are drawn:
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER,sphereBufferCol.get(0));
GL11.glColorPointer(4, GL11.GL_FLOAT, 0, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, sphereBufferPos.get(0));
GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, sphereBufferNormal.get(0));
GL11.glNormalPointer(GL11.GL_FLOAT, 0, 0);
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);
GL11.glEnableClientState(GL11.GL_NORMAL_ARRAY);
//Each sphere is generated 32 by 32 quadstriparray and each having two sets of two points and there are two spheres
GL11.glDrawArrays(GL11.GL_QUAD_STRIP, 0, 32*33*2 *2);
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glDisableClientState(GL11.GL_COLOR_ARRAY);
GL11.glDisableClientState(GL11.GL_NORMAL_ARRAY);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
Question: How can I make that rope-like thing disappear without decreasing performance? Maybe putting zero to last and first points' alpha value can make it invisible but wouldnt that cause two holes on each sphere and decrease performance because of many lines on the screen?
All vertex values will be altered by opencl interoperability so single drawing call is needed to draw whole 10000+ spheres.
There seem to be a number of options:
use multiple buffers
use quads instead of quad strips
use primitive restart
use degenerate triangles, i.e. add the last vertex twice
use [instanced rendering] (http://www.opengl.org/wiki/Vertex_Rendering#Instancing)
If you are on newer hardware and want to use quad strips, I'd prefer using primitive restart.
Please note that this is just the result of a quick assessment and anchecked (I personally don't use quad strips or even tri strips that often ;) ).

Changing rotational point

I am having an issue with my program; currently it rotates around a set point, and can rotate models around it. Of course, this is a problem as I want it to be a first-person perspective, and currently, it rotates around a point in front of the viewer, instead of the perspective of the viewer. Here is the trigonometric calculations:
protected void drawWireframe(Graphics g) {
double theta = Math.PI * -azimuth / 180.0D;
double phi = Math.PI * elevation / 180.0D;
float cosT = (float) Math.cos(theta);
float sinT = (float) Math.sin(theta);
float cosP = (float) Math.cos(phi);
float sinP = (float) Math.sin(phi);
float cosTcosP = cosT * cosP;
float cosTsinP = cosT * sinP;
float sinTcosP = sinT * cosP;
float sinTsinP = sinT * sinP;
float near = 6.0F;
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
for (int i = 0; i < tiles.size(); i++) {
Point[] points = new Point[vertices.length];
for (int j = 0; j < points.length; j++) {
float x0 = -(tiles.get(i).getX() + xmod + vertices[j]
.getX());
float y0 = (tiles.get(i).getY() + ymod + vertices[j].getY());
float z0 = -(tiles.get(i).getZ() + zmod + vertices[j]
.getZ());
float x1 = cosT * x0 + sinT * z0;
float y1 = -sinTsinP * x0 + cosP * y0 + cosTsinP * z0;
float z1 = cosTcosP * z0 - sinTcosP * x0 - sinP * y0;
if (z1 + near > 0) {
x1 = x1 * near / (z1 + near);
y1 = y1 * near / (z1 + near);
points[j] = new Point((int) (Math.max(getWidth(),
getHeight()) / 2 - (Math.max(getWidth(),
getHeight()) / near) * x1), (int) (Math.max(
getWidth(), getHeight()) / 2 - (Math.max(
getWidth(), getHeight()) / near) * y1));
}
}
}
}
How would I go about moving the rotational point without actually modifying the xmod, ymod and zmod (these are used for movements like jumping, walking, running, crouching... etc)
I know how to figure out how to get the new x, y and z positions, I just don't know how to apply them; if I add them to the mods, it creates a weird loop-d-loop. If I add them to the x1, y1, z1's it doesn't cover the z not rotating from the perspective.
To change the rotation point, you effectively need three transforms:
Translate the coordinate system so that the rotation point becomes the origin.
Perform a rotation around the origin
Translate the coordinate system back again.
This can be factored a number of ways, but that's the basic priniciple: translate->rotate->translate.
The way you "move the rotation point" of an object is by translating the object so that the rotation point is at the origin; do the rotation; then translate the object back. All of this is done in memory, between frames - the user never actually sees the object moving to the origin and back.
By the way, all this stuff is significantly easier if you understand vectors and matrix transformations - as you've seen yourself, without them the code can get out of hand.
Using vectors/matrices, all your code above could be reduced to only a few lines.

Categories

Resources