Adding numbers to analog clock Processing - processing

make a 24 hour clock. What makes it 24 hour is the clock face will count up from zero hour to 23. But the clock face has only either the AM numbering of the hours or the PM numbering of the hours shown at any one time. The AM numbering is from 0 to 11. The PM is from 12 to 23
I need use the drawNum code and i can't get it to work,
this is the code i have so far...
float x[], y[];
float diam;
color c[];
int n; //number of balls
void setup()
{
size (500, 500);
colorMode(HSB);
background(0);
frameRate(1);
x = new float [n];
y = new float [n];
}
void draw()
{
float h, m, s;
float radius;
float cx, cy;
float clockface;
float hoursRadius, minutesRadius, hoursTick, secondsRadius, minutesTick;
radius = min(height/2.0, width/2.0);
cx = width/2.0;
cy = height/2.0;
clockface = radius * 0.9;
hoursRadius = radius * 0.5;
minutesRadius = radius * 0.65;
secondsRadius = radius * 0.72;
hoursTick = radius * 0.04;
minutesTick = hoursTick * 0.5;
// get time
s = second();
m = minute();
h = hour()%12 + m/60.0;
//draw clock face
fill(40);
noStroke();
ellipseMode(RADIUS);
ellipse(cx, cy, clockface, clockface);
//
drawHand(cx, cy, s*6.0, secondsRadius, 2);
drawHand(cx, cy, m*6.0, minutesRadius, 3);
drawHand(cx, cy, h*30.0, hoursRadius, 5);
for ( int i=0; i<60; i++) {
if (i%5==0) {
drawNum(cx, cy, i*6, secondsRadius, 10, 0);
} else {
drawNum(cx, cy, i*6, secondsRadius, 5, 23);
}
}
// draw the ticks
for ( int i=0; i<60; i++) {
if (i%5==0) {
drawTick(cx, cy, i*6, secondsRadius, 10);
} else {
drawTick(cx, cy, i*6, secondsRadius, 5);
}
}
}
void drawTick( float x, float y,
float angle, float len,
float weight) {
fill(angleToColor(angle));
noStroke();
rectMode(CENTER);
rect(x + cos(radians(angle-90))*len,
y + sin(radians(angle-90))*len,
weight, weight) ;
}
void drawHand( float x, float y,
float angle, float len,
float weight) {
strokeWeight(weight);
stroke(angleToColor(angle));
line(x, y,
x + cos(radians(angle-90))*len,
y + sin(radians(angle-90))*len);
}
color angleToColor(float angle) {
return color(map(angle, 0, 360, 0, 255), 255, 255);
}
void drawNum(float x,float y,
float angle, float len,
float tsize, int num) {
float i;
textSize(36);
fill(0);
noStroke();
for (num = 0; num < 12; num++) {
int hoursNum = (x + cos(radians(angle-90))*len,
y + sin(radians(angle-90))*len,
num, num)) ;;
}
}

You need to convert the number into a string (text) to display it. This is done with function str(arg) which returns a value of type String. The argument arg can be an int, float, char, byte or boolean type.
The function for drawing text is text( s, x, y ) where s is the string to display and x and y are the location.
EDIT:
The hour() function returns hours on a 24-hour clock, measured from 0-23 instead of 1-24. Right-click on the function in the Processing window and select "Find in Reference" to see the details. The code hour()%12 is taking the hour value modulo 12, which means when the value reached 12 it cycles back to zero, and values 12-23 are reported as 0-11.

Related

Why do the lines (muscles) not line up with part3 (blue)?

https://imgur.com/a/hDRx3SI
The lines (muscles) start out in the center as I want. (This video starts out a second or two into the sketch.) Why do the muscles not line up with the center of part3 (Blue circle)? Is it simply a trigonometric issue where I'm trying to force them into an impossible position given the constraints?
Part part1;
Part part2;
Part part3;
Muscle muscle1;
Muscle muscle2;
Muscle muscle3;
void setup() {
size (800, 800);
frameRate(1);
part1 = new Part(width/2, height/2, 50, color(255, 0, 0));
part2 = new Part(width/2 + 100, height/2, 50, color(0, 255, 0));
part3 = new Part(width/2 + 50, height/2 - 75, 50, color(0, 0, 255));
muscle1 = new Muscle(part1.x, part1.y, part2.x, part2.y, dist(part1.x, part1.y, part2.x,part2.y), color(0, 255, 0));
muscle2 = new Muscle(part1.x, part1.y, part3.x, part3.y, dist(part1.x, part1.y, part3.x, part3.y), color(0, 255, 0));
muscle3 = new Muscle(part2.x, part2.y, part3.x, part3.y, dist(part2.x, part2.y, part3.x, part3.y), color(0, 255, 0));
}
void draw() {
background(255);
part1.drawpart();
part2.drawpart();
part3.drawpart();
muscle1.drawmuscle(part1, part2);
muscle2.drawmuscle(part1, part3);
muscle3.drawmuscle(part2, part3);
part2.movepart();
}
class Muscle{
float leftx;
float lefty;
float rightx;
float righty;
float size = 100;
int musclecolor;
Muscle(float leftpositionx, float leftpositiony, float rightpositionx, float rightpositiony, float musclesize, int musclemusclecolor) {
leftx = leftpositionx;
lefty = leftpositiony;
rightx = rightpositionx;
righty = rightpositiony;
size = musclesize;
musclecolor = musclemusclecolor;
}
void drawmuscle(Part obj1, Part obj2) {
strokeWeight(5);
float dx = obj2.x - obj1.x;
float dy = obj2.y - obj1.y;
float angle = atan2(dy, dx);
obj2.x = obj1.x + cos(angle) * size;
obj2.y = obj1.y + sin(angle) * size;
line(obj1.x, obj1.y, obj2.x, obj2.y);
}
}
class Part{
float x;
float y;
float size;
int partcolor;
Part(float positionx, float positiony, float partsize, int partpartcolor) {
x = positionx;
y = positiony;
size = partsize;
partcolor = partpartcolor;
}
void drawpart() {
fill(partcolor);
strokeWeight(1);
ellipseMode(CENTER);
ellipse(x, y, size, size);
}
void movepart() {
y += 10;
}
}
There are two different problems here which interacts with one another, which is why this is hard to solve. You'll be happy to notice, though, that your math are irreproachable.
First issue is in the drawmuscle() method. You modify coordinates while drawing them, which isn't necessarily an issue. The problem is that you're doing this in cascade for 3 different parts, which depend on each other to be calculated. The variables all end up all right - so mathematically it works - but as you draw some parts before others have been calculated, they end up with unexpected coordinates that are neither the old ones nor the new ones.
To fix this, I modified the drawmuscle() method so it only draws the muscles, and I added a new method to update the muscles/parts coordinates. It's still all your code, just displaced into different containers. Then I modified the draw() method to reflect this change: the coordinates have to be calculated first, then the parts can be drawn.
Now, the blue circle was still misplaced. That's also because of a matter of order in the draw() method: as the circles were drawn before their coordinates were updated, they were subject to be misdrawn. Again, at the end of every frame, your calculations were correct, but in the way the operations to get there were applied and drawn they would appear off.
As a rule of thumb, I would say that you need to remember from this project the following rule: calculate first, draw last.
So here are the changes I made to your methods:
void draw() {
background(255);
// calculating new positions
muscle1.moveMuscle(part1, part2);
muscle2.moveMuscle(part1, part3);
muscle3.moveMuscle(part2, part3);
// drawing
part1.drawpart();
part2.drawpart();
part3.drawpart();
muscle1.drawmuscle(part1, part2);
muscle2.drawmuscle(part1, part3);
muscle3.drawmuscle(part2, part3);
muscle1.growmuscle(part1, part2);
}
void drawmuscle(Part obj1, Part obj2) {
// no calculations here
strokeWeight(5);
line(obj1.x, obj1.y, obj2.x, obj2.y);
}
void moveMuscle(Part obj1, Part obj2) {
// every calculations here
float dx = obj2.x - obj1.x;
float dy = obj2.y - obj1.y;
float angle = atan2(dy, dx);
obj2.x = obj1.x + cos(angle) * size;
obj2.y = obj1.y + sin(angle) * size;
rightx = obj2.x;
righty = obj2.y;
}
I hope this will help. Have fun!

Processing Square Stacking loop

This is my first time writing here so i'll be direct, i've been trying to recreate this image:
and so far all the code i've got is:
void setup() {
size(500, 500);
}
void draw() {
rectMode(CENTER);
recta();
}
void recta() {
noFill();
int a = 10;
int y = 250;
for (int x = 0; x<20; x++) {
pushMatrix();
translate(y, y);
rect(0, 0, a, a);
popMatrix();
rotate(radians(2.0*PI));
stroke(0, 0, 0);
a= a - 20;
}
}
And i have no idea what to do next since this is what i get from it:
So i'd like to ask for help on how to get the same result as the image.
You are so close !
You're absolutely on the right track using pushMatrix()/popMatrix() to isolate coordinate systems, however you might have accidentally placed the rotation after popMatrix() which defeats the purpose. You probably meant to for each square to have an independent rotation from each other and not accumulate 2 * PI to the global rotation.
The other catch is that you're rotating by the same angle (2 * PI) for each iteration in your for loop and that rotation is 360 degrees so even if you fix rotation like this:
pushMatrix();
translate(y, y);
rotate(radians(2.0*PI));
rect(0, 0, a, a);
popMatrix();
you'll get a scaling effect:
(Minor note 2.0 * PI already exists in Processing as the TWO_PI constant)
To get that spiral looking effect is to increment the angle for each iteration (e.g. x = 0, rotation = 0, x = 1, rotation = 5, x = 2, rotation = 10, etc.). The angle increment is totally up to you: depending on how you map the x increment to a rotation angle angle you'll get a tighter or looser spiral.
Speaking of mapping, Processing has a map() function which makes it super easy to map from one range of numbers (let's say x from 0 to 19) to another (let's say 0 radians to PI radians):
for (int x = 0; x < 20; x++) {
pushMatrix();
translate(y, y);
rotate(map(x, 0, 19, 0, PI));
rect(0, 0, a, a);
popMatrix();
a = a - 20;
}
Here's a basic sketch based on your code:
int a = 10;
int y = 250;
void setup() {
size(500, 500);
rectMode(CENTER);
noFill();
background(255);
recta();
}
void recta() {
for (int x = 0; x < 20; x++) {
pushMatrix();
translate(y, y);
rotate(map(x, 0, 19, 0, PI));
rect(0, 0, a, a);
popMatrix();
a = a - 20;
}
}
I've removed draw() because it was rendering the same frame without any change: drawing once in setup() achieves the same visual effect using less CPU/power.
You can use draw(), but might as add some interactivity or animation to explore shapes. Here's a tweaked version of the above with comments:
int y = 250;
void setup() {
size(500, 500);
rectMode(CENTER);
noFill();
}
void draw(){
background(255);
recta();
}
void recta() {
// map mouse X position to -180 to 180 degrees (as radians)
float maxAngle = map(mouseX, 0, width, -PI, PI);
// reset square size
int a = 10;
// for each square
for (int x = 0; x < 20; x++) {
// isolate coordinate space
pushMatrix();
// translate first
translate(y, y);
// then rotate: order matters
// map x value to mouse mapped maximum rotation angle
rotate(map(x, 0, 19, 0, maxAngle));
// render the square
rect(0, 0, a, a);
popMatrix();
// decrease square size
a = a - 20;
}
}
Remember transformation order matters (e.g. translate() then rotate() would produce different effects compared to rotate() then translate()). Have fun!

How do I change values,which are already used in a while loop?

I am trying to write a program that displays spheres with a fixed spacing "d=19" in a rectangle. I only got it to work in the x and y axis direction or in the diagonal axis but not on the full area of the rectangle. I know the solution should be fairly easy but i cant seem to get it.
void setup() {
size(600, 500);
background(255);
}
void draw() {
int x = 50;
int y = 100;
int r = 5;
int d = 19;
background(255);
rect(x, y, mouseX-x, mouseY-y);
while (y <= mouseY) {
ellipse(x, y, 2*r, 2*r);
while (x <= mouseX) {
ellipse(x, y, 2*r, 2*r);
x = x+d;
}
y = y+d;
}
}
You've to reset the x coordinate before the inner loop of the nested loops. The circles have to be started in each row in the 1st column:
void draw() {
int x=50;
int y=100;
int r =5;
int d =19;
background(255);
rect(x, y, mouseX-x, mouseY-y);
while (y <= mouseY) {
x = 50; // <--- start at the begin in each row
while (x <= mouseX) {
ellipse(x, y, 2*r, 2*r);
x=x+d;
}
y=y+d;
}
}
Note, to draw the objects in a 2 dimensional grid, 2 nested loops are sufficient.

"Mirroring" a PShape object (rotation / translation issue) with Processing

I would like to "mirror" a PShape object like in the picture below:
I know how to display multiple shapes and how to invert them (screenshot below) but things get complicated when I have to rotate them (and probably translating them) so as they "stick" to the preceding shapes (first picture).
I've been trying to compute an angle with the first 2 vertices of the original shape (irregular quadrilateral) and the atan2() function but to no avail.
I would really appreciate if someone could help figuring how to solve this problem.
int W = 20;
int H = 20;
int D = 20;
PShape object;
void setup(){
size(600, 600, P2D);
smooth();
}
void draw(){
background(255);
pushMatrix();
translate(width/2, height/1.3);
int td = -1;
for (int i = 0; i < 6; i++){
translate(0, td*H*2);
scale(-1, 1);
rotate(PI);
object();
td *= -1;
}
popMatrix();
}
void object() {
beginShape(QUADS);
vertex(-20, 20);
vertex(20, 0);
vertex(20, -20);
vertex(-20, -20);
endShape();
}
To do what you want you have to create a shape by 2 given angles for the top and the bottom of the shape angleT and `angleBĀ“. The origin (0,0) is in the center of the shape. This causes that the pivots for the rotations are in the middle of the slopes of the shape :
int W = 40;
int H = 40;
float angleT = -PI/18;
float angleB = PI/15;
PShape object;
void object() {
float H1 = -H/2 + W*tan(angleB);
float H2 = H/2 + W*tan(angleT);
beginShape(QUADS);
vertex(-W/2, -H/2);
vertex(W/2, H1);
vertex(W/2, H2);
vertex(-W/2, H/2);
endShape();
}
When you draw the parts, then you should distinguish between even and odd parts. The parts have to be flipped horizontal by inverting the y axis (scale(1, -1)). The even parts have to be rotated by the double of angleB and the odd parts have to be rotated by the doubled of angleT. For the rotation, the center of the slopes (pivots) have to be translated to the origin:
void setup(){
size(600, 600, P2D);
smooth();
}
void draw(){
background(255);
translate(width/2, height/2);
float HC1 = -H/2 + W*tan(angleB)/2;
float HC2 = H/2 + W*tan(angleT)/2;
for (int i = 0; i < 15; i++){
float angle = (i % 2 == 0) ? -angleB : -angleT;
float HC = (i % 2 == 0) ? HC1 : HC2;
translate(0, -HC);
rotate(angle*2);
translate(0, -HC);
object();
scale(1, -1);
}
}
The algorithm works for any angle, positive and negative including 0.
This algorithm can be further improved. Let's assume you have a quad, defined by 4 points (p0, p1, p2, p3):
float[] p0 = {10, 0};
float[] p1 = {40, 10};
float[] p2 = {60, 45};
float[] p3 = {0, 60};
PShape object;
void object() {
beginShape(QUADS);
vertex(p0[0], p0[1]);
vertex(p1[0], p1[1]);
vertex(p2[0], p2[1]);
vertex(p3[0], p3[1]);
endShape();
}
Calculate the the minimum, maximum, centerpoint, pivots and angles:
float minX = min( min(p0[0], p1[0]), min(p2[0], p3[0]) );
float maxX = max( max(p0[0], p1[0]), max(p2[0], p3[0]) );
float minY = min( min(p0[1], p1[1]), min(p2[1], p3[1]) );
float maxY = max( max(p0[1], p1[1]), max(p2[1], p3[1]) );
float cptX = (minX+maxX)/2;
float cptY = (minY+maxY)/2;
float angleB = atan2(p1[1]-p0[1], p1[0]-p0[0]);
float angleT = atan2(p2[1]-p3[1], p2[0]-p3[0]);
float HC1 = p0[1] + (p1[1]-p0[1])*(cptX-p0[0])/(p1[0]-p0[0]);
float HC2 = p3[1] + (p2[1]-p3[1])*(cptX-p3[0])/(p2[0]-p3[0]);
Draw the shape like before:
for (int i = 0; i < 6; i++){
float angle = (i % 2 == 0) ? -angleB : -angleT;
float HC = (i % 2 == 0) ? HC1 : HC2;
translate(cptX, -HC);
rotate(angle*2);
translate(-cptX, -HC);
object();
scale(1, -1);
}
Another approach would be to stack the shape on both sides:
For this you have to know the heights of the pivots (HC1, HC2) and the angles (angleB, angleT). So this can be implemented based on both of the above approaches.
Define the pivot points and the directions of the top and bottom edge:
PVector dir1 = new PVector(cos(angleB), sin(angleB));
PVector dir2 = new PVector(cos(angleT), sin(angleT));
PVector pv1 = new PVector(0, HC1); // or PVector(cptX, HC1)
PVector pv2 = new PVector(0, HC2); // or PVector(cptX, HC2)
Calculate the intersection point (X) of the both edges. Of course this will work only if the
edges are not parallel:
PVector v12 = pv2.copy().sub(pv1);
PVector nDir = new PVector(dir2.y, -dir2.x);
float d = v12.dot(nDir) / dir1.dot(nDir);
PVector X = pv1.copy().add( dir1.copy().mult(d) );
The stack algorithm works as follows:
for (int i = 0; i < 8; i++){
float fullAngle = angleT-angleB;
float angle = fullAngle * floor(i/2);
if ((i/2) % 2 != 0)
angle += fullAngle;
if (i % 2 != 0)
angle = -angle;
float flip = 1.0;
if (i % 2 != 0)
flip *= -1.0;
if ((i/2) % 2 != 0)
flip *= -1.0;
pushMatrix();
translate(X.x, X.y);
rotate(angle);
scale(1, flip);
rotate(-angleB);
translate(-X.x, -X.y);
object();
popMatrix();
}

Rotate some elements in an ellipse path

I am trying to make some objects, say 12, to rotate in an ellipse path continuously in Processing. I got a sketch which does rotation in a circle and I want to make it to rotate in a ellipse. I have some pointer from processing forum but the code from the pointer is different from the code that I posted and I couldn't understand yet (weak in trigonometry).
I googled a bit and found a post trying to achieve this with this algorithm:
You need to define your ellipse with a few parameters:
x, y: center of the ellipse
a, b: semimajor and semiminor axes
If you want to move on the elipses this means that you change the
angle between the major axes and your position on the ellipse. Lets
call this angle alpha.
Your position (X,Y) is:
X = x + (a * Math.cos(alpha));
Y = y + (b * Math.sin(alpha));
In order to move left or right you need to increase/decrease alpha and
then recalculate your position. Source:
http://answers.unity3d.com/questions/27620/move-object-allong-an-ellipsoid-path.html
How do I integrate it into my sketch? Thank you.
Here's my sketch:
void setup()
{
size(1024, 768);
textFont(createFont("Arial", 30));
}
void draw()
{
background(0);
stroke(255);
int cx = 500;
int cy = 350;
int r = 300; //radius of the circle
float t = millis()/4000.0f; //increase to slow down the movement
ellipse(cx, cy, 5, 5);
for (int i = 1 ; i <= 12; i++) {
t = t + 100;
int x = (int)(cx + r * cos(t));
int y = (int)(cy + r * sin(t));
line(cx, cy, x, y);
textSize(30);
text(i, x, y);
if (i == 10) {
textSize(15);
text("x: " + x + " y: " + y, x - 50, y - 20);
}
}
}
Replace
int r = 300; //radius of the circle
with
int a = 350; // major axis of ellipse
int b = 250; // minor axis of ellipse
and replace
int x = (int)(cx + r * cos(t));
int y = (int)(cy + r * sin(t));
with
int x = (int)(cx + a * cos(t));
int y = (int)(cy + b * sin(t));

Resources