We are about to switch to a new forum software. Until then we have removed the registration on this forum.
I am modeling this robotic arm and it looks great.
I am also trying to display each angle next to each point of inflexion. In the case of the elbow, I am trying to move the text with the elbow position along with the inflexion point. That works, but I cant find a method to keep the writing horisontal. It rotates with the first segment angle...
here is my function
thanks
void ArmDepiction()
{ ///////////////////////////Base orientation
fill(201, 0, 211); // magenta //text("Y:", LS, spaceDown*3 ); text( (nf(degrees(BaseAngRad), 0, 1)), 630, 1050); //text( "0", 85, 0);
strokeWeight(10); stroke(238,242, 0); noFill ();
// Form: arc(x, y, width, height, start, stop, type); arc(550, 1000, 100, 100, (PI/2), (BaseAngRad+(PI/2)), PIE); //stroke(#71B28F); //arc(100, 1000, 175, 175, 0, 2*PI, 0);
//drawArrow(100,160,50,130);
///////////////////////Arm Depiction strokeWeight(40); stroke(255, 160); strokeCap(ROUND);
float x, y;
x = 550; y = 800;
pushMatrix(); strokeWeight(40); segment(x, y, PI+ShoAngRad); strokeWeight(30); segment1(segLength, 0, PI+ElbowAngRad); // 120 is the starting point segment3(segLength, 0, (2*PI)+ElbowAngRad-0.58); // 100 is the segment length popMatrix();
translate(x, y); strokeWeight(10); strokeJoin(ROUND); beginShape(); vertex(-40, 0);
vertex(-65, segLength); vertex(65, segLength);
vertex(40, 0); endShape(CLOSE);
DisplayElAngle(x, y);
}
void segment(float x, float y, float a) { translate(x, y); fill(201, 0, 211); // magenta //text("Y:", LS, spaceDown*3 ); text( (nf(degrees(ShoAngRad), 0, 1)), 30, 0); //text( "0", 85, 0); noFill ();
rotate(a); line(0, 0, segLength, 0); // 100 is the segment length
}
void DisplayElAngle(float x, float y) { translate(x, y); rotate(2PI); fill(201, 0, 211); // magenta //text("Y:", LS, spaceDown3 ); text( (nf(degrees(ElbowAngRad), 0, 1)), 20, -10); noFill (); //
} void segment1(float x, float y, float a) { translate(x, y); fill(201, 0, 211); // magenta //text("Y:", LS, spaceDown*3 ); text( (nf(degrees(ElbowAngRad), 0, 1)), 20, -10); noFill (); rotate(a); line(0, 0, segLength, 0); // 100 is the segment length // rotate(a);
}
void segment3(float x, float y, float a) { translate(x, y); rotate(a); line(0, 0, (segLength/5), 0); // 100 is the segment length
}
[Code below] Further down is my preferred solution, written in native JS, but applicable to p5. It's not the solution I wanted, but I think it's the most readable one so far.
For those who haven't seen this before, this is called "easing"(?), and it's is a way of achieving smooth animations. (I just call it "damping", because that's what I know from vvvv.)
For most cases, this technique looks far better than instant movements or linearly increasing variables.
Basically, each time the damping function is called, x.damped gets 5% closer to x.target.
In this example, x.target is changed from 0 to 100. x.damped then gets incremented by 5% of what's remaining to the target, each frame:
(0): 0.000 (+5.000)
(1): 5.000 (+4.750)
(2): 9.750 (+4.513)
(3): 14.262 (+4.287)
(4): 18.549 (+4.073)
(5): 22.622 (+3.869)
(6): 26.491 (+3.675)
(7): 30.166 (+3.492)
(8): 33.658 (+3.317)
(9): 36.975 (+3.151)
(10): 40.126 (+2.994)
(11): 43.120 (+2.844)
(12): 45.964 (+2.702)
(13): 48.666 (+2.567)
(14): 51.233 (+2.438)
(15): 53.671 (+2.316)
(16): 55.987 (+2.201)
(17): 58.188 (+2.091)
(18): 60.279 (+1.986)
(19): 62.265 (+1.887)
(20): 64.151 (+1.792)
(21): 65.944 (+1.703)
(22): 67.647 (+1.618)
(23): 69.264 (+1.537)
(24): 70.801 (+1.460)
(25): 72.261 (+1.387)
(26): 73.648 (+1.318)
(27): 74.966 (+1.252)
(28): 76.217 (+1.189)
(29): 77.406 (+1.130)
(30): 78.536 (+1.073)
(31): 79.609 (+1.020)
(32): 80.629 (+0.969)
(33): 81.597 (+0.920)
(34): 82.518 (+0.874)
(35): 83.392 (+0.830)
(36): 84.222 (+0.789)
(37): 85.011 (+0.749)
(38): 85.760 (+0.712)
(39): 86.472 (+0.676)
(40): 87.149 (+0.643)
(41): 87.791 (+0.610)
(42): 88.402 (+0.580)
(43): 88.982 (+0.551)
(44): 89.533 (+0.523)
(45): 90.056 (+0.497)
(46): 90.553 (+0.472)
(47): 91.026 (+0.449)
(48): 91.474 (+0.426)
(49): 91.901 (+0.405)
(50): 92.306 (+0.385)
(51): 92.690 (+0.365)
(52): 93.056 (+0.347)
(53): 93.403 (+0.330)
(54): 93.733 (+0.313)
(55): 94.046 (+0.298)
(56): 94.344 (+0.283)
(57): 94.627 (+0.269)
(58): 94.895 (+0.255)
(59): 95.151 (+0.242)
(60): 95.393 (+0.230)
etc.
Paste into .html file:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
* {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<canvas></canvas>
<script>
const canvas = document.querySelector("canvas");
const c = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let mouseX = {target: 0, damped: 0};
let mouseY = {target: 0, damped: 0};
let radius = {target: 20, damped: 20};
let hue = {target: 0, damped: 0};
let frameCount = 0;
let bigCircle = false;
let circleSize = 100;
canvas.addEventListener("mousemove", event => {
mouseX.target = event.layerX;
mouseY.target = event.layerY;
});
addEventListener("click", () => {
bigCircle = !bigCircle;
if (bigCircle) {
radius.target = 100;
} else {
radius.target = 20;
}
});
(function draw() {
damping();
changeHueEverySecond();
background();
cursor();
requestAnimationFrame(draw);
})();
function damping() {
mouseX.damped += 0.05 * (mouseX.target - mouseX.damped);
mouseY.damped += 0.05 * (mouseY.target - mouseY.damped);
radius.damped += 0.05 * (radius.target - radius.damped);
hue.damped += 0.05 * (hue.target - hue.damped);
}
function changeHueEverySecond() {
frameCount++;
if (frameCount % 60 === 0) {
hue.target = frameCount;
}
}
function background() {
c.fillStyle = "#ffa";
c.fillRect(0, 0, canvas.width, canvas.height);
c.fill();
}
function cursor() {
c.fillStyle = `hsl(${hue.damped}, 50%, 50%)`;
c.beginPath();
c.arc(mouseX.damped, mouseY.damped, radius.damped, 0, Math.PI * 2);
c.closePath();
c.fill();
}
</script>
</body>
</html>
A possible improvement would be to loop over an array or an object in the damping function, but I like being able to use x.damped instead of dampArray[2].damped or dampObject.x.damped for example.
// translate(xPos, yPos); //CHANGED
rotate(delta * i);
fill(0);
text(i + "--------------------", 200, 0); //CHANGED
Full working example below.
Kf
float dyna; //dynamic angle
void setup() {
size(800, 800,P2D);
}
//________________________________________________________________________________________________________________________________
void draw() {
background(255, 193, 37);
drawArcs();
}
//________________________________________________________________________________________________________________________________
void drawArcs() {
float startAngle = 0;
float lastAngle = 0;
pushMatrix();
translate(width/2, height/2);
for (int i = 0; i < 6; i++) {
fill(0+i*255/6);
stroke(0);
strokeWeight(0);
arc(0, 0, 300, 300, lastAngle, lastAngle+radians(360.0/6));
lastAngle += radians(360.0/6);
startAngle = startAngle + lastAngle;
float delta = TWO_PI / 6;
float xPos = 200 * cos(i* delta);
float yPos = 200 * sin(i* delta);
pushMatrix();
rotate(delta * i+dyna);
//translate(xPos, yPos);
fill(0);
text(i + "--------------------", 200,0);
popMatrix();
}//for
popMatrix();
if (frameCount%5==0) {
dyna+=0.01;
if (dyna>0.5) dyna=0;
}
}
Here we go, apologies once again.
I basically want to rotate it so that the writing just moves clockwise! around the circle so that it lies in the middle of each segment. So in the screen shot, the red lines are where I want the text to be. I also want to make it so that the text will remain in the middle of each segment no matter how many arcs I add to that circle. (6 are added in the code below but this number will be changing in my larger script)
Below is only the relevant code. I hope I mad more sense this time.
void setup() {
size(800, 800);
}
//________________________________________________________________________________________________________________________________
void draw() {
background(255, 193, 37);
drawArcs();
}
//________________________________________________________________________________________________________________________________
void drawArcs(){
float startAngle = 0;
float lastAngle = 0;
pushMatrix();
translate(width/2, height/2);
for (int i = 0; i < 6; i++) {
fill(0+i*255/6);
stroke(0);
strokeWeight(0);
arc(0, 0, 300, 300, lastAngle, lastAngle+radians(360.0/6));
lastAngle += radians(360.0/6);
startAngle = startAngle + lastAngle;
float delta = TWO_PI / 6;
float xPos = 200 * cos(i* delta);
float yPos = 200 * sin(i* delta);
pushMatrix();
translate(xPos, yPos);
rotate(delta * i);
fill(0);
text(i + "--------------------", 0, 0);
popMatrix();
}//for
popMatrix();
}
Sorry, @Niels. Here's the full code. The code above is contains from the lines 208 to 217. Thank you :)
import ddf.minim.*;
import ddf.minim.effects.*;
AudioPlayer[] mplayer;
Minim minim;
String[] songs={"train1.wav", "train2.wav"};
int idx=0;
import controlP5.*;
import java.util.*;
ControlP5 cp5;
String urlStationInfo = "http://" + "api.irishrail.ie/realtime/realtime.asmx/getStationsFilterXML?StationText=";
XML xmlA;
XML[] childrenA;
XML xmlS;
XML[] childrenS;
//String[] arrayStationIDs;
//String[] arrayStationIDS = new String[childrenS.length]; // Array to store x-coordinates
String[] storedID;
String[] storedName;
StringList arrayOrigin;
StringList arrayDestination;
FloatList arrayDueTimes;
IntList arrayLateTimes;
StringList arrayID;
StringList stationID;
int index;
int angle=0;
int scaler = 8;
Timer timer = new Timer(30000);
//________________________________________________________________________________________________________________________________
void setup() {
size(800, 800);
minim = new Minim(this);
mplayer=new AudioPlayer[2];
for (int i=0; i<songs.length; i++) {
mplayer[i] = minim.loadFile(songs[i]);
mplayer[i].play();
mplayer[i].pause();
}
cp5 = new ControlP5(this);
requestStationData();
requestArrayData();
timer.start();
for (int i = 0; i < childrenS.length; i++) {
cp5.addScrollableList("dropdown")
.setPosition(10, 10)
.setSize(100, 200)
.setBarHeight(20)
.setItemHeight(20)
.addItems(storedName)
.setType(ScrollableList.LIST) // currently supported DROPDOWN and LIST
;
}
}
//________________________________________________________________________________________________________________________________
void draw() {
background(255, 193, 37);
if (timer.isFinished()) { // Every one second, make a new request.
println("Timer is finished: Requesting values and restarting");
requestStationData();
requestArrayData();
timer.start(); // And restart the timer.
}
drawArcs();
}
//________________________________________________________________________________________________________________________________
void dropdown(int n) {
/* request the selected item based on index n */
println(n, cp5.get(ScrollableList.class, "dropdown").getItem(n));
index = n;
requestStationData();
requestArrayData();
timer.start();
mplayer[idx].pause();
idx=(int)random(songs.length);
mplayer[idx].rewind();
mplayer[idx].shiftGain(-80.0, 0, 5000);
mplayer[idx].play();
println("Randomly chosen sample is "+idx);
CColor c = new CColor();
c.setBackground(color(255,0,0));
cp5.get(ScrollableList.class, "dropdown").getItem(n).put("color", c);
}
//________________________________________________________________________________________________________________________________
void requestStationData() {
xmlS = loadXML(urlStationInfo);
childrenS = xmlS.getChildren("objStationFilter");
storedID = new String[childrenS.length]; // Array to store x-coordinates
storedName = new String[childrenS.length]; // Array to store x-coordinates
stationID = new StringList();
for (int i = 0; i < childrenS.length; i++) {
XML sIDElement = childrenS[i].getChild("StationCode");
String sID = sIDElement.getContent();
storedID[i] = sID;
stationID.append(sID);
XML sNameElement = childrenS[i].getChild("StationDesc");
String sName = sNameElement.getContent();
storedName[i] = sName;
//stationName.append(sName);
}
}
//________________________________________________________________________________________________________________________________
void requestArrayData() {
arrayID = new StringList();
arrayOrigin = new StringList();
arrayDestination = new StringList();
arrayDueTimes = new FloatList();
arrayLateTimes = new IntList();
//xmlA = loadXML("stationData.xml");
for (int i = 0; i < childrenS.length; i++) {
//String myString = stationID.get(i);
String myString = stationID.get(index);
//xmlA = loadXML("stationData.xml");
xmlA = loadXML("http://api.irishrail.ie/realtime/realtime.asmx/getStationDataByCodeXML?StationCode=" + myString);
childrenA = xmlA.getChildren("objStationData");
//println(childrenA.length);
for (int j = 0; j < childrenA.length; j++) {
XML originElement = childrenA[j].getChild("Origin");
String origin = originElement.getContent();
arrayOrigin.append(origin);
XML destinationElement = childrenA[j].getChild("Destination");
String destination = destinationElement.getContent();
arrayDestination.append(destination);
XML dueElement = childrenA[j].getChild("Duein");
int due = dueElement.getIntContent();
arrayDueTimes.append(due);
XML lateElement = childrenA[j].getChild("Late");
int late = lateElement.getIntContent();
arrayLateTimes.append(late);
//println(" Station: " + fullName + ". Next Train: " + origin + " to " + destination + " is due in " + due + "minutes.");
}
}
}
//________________________________________________________________________________________________________________________________
void drawArcs(){
float startAngle = 0;
float lastAngle = 0;
float radian = 360.0/childrenA.length;
pushMatrix();
translate(width/2, height/2);
for (int i = 0; i < childrenA.length; i++) {
// This collection of arcs is printed to screen. Each arc will protude by the pixel amount in minutes that its corresponding train is overdue
fill(255,0,0);
stroke(0);
strokeWeight(0);
arc(0, 0, scaler*abs(arrayDueTimes.get(i))+arrayLateTimes.get(i), scaler*abs(arrayDueTimes.get(i))+arrayLateTimes.get(i), lastAngle, lastAngle+radians(radian));
fill(0+i*255/childrenA.length);
stroke(0);
strokeWeight(0);
arc(0, 0, scaler*(arrayDueTimes.get(i)), scaler*(arrayDueTimes.get(i)), lastAngle, lastAngle+radians(radian));
lastAngle += radians(radian);
startAngle = startAngle + lastAngle;
float delta = TWO_PI / childrenA.length;
float xPos = 0+scaler/2*arrayDueTimes.get(i) * cos(i* delta);
float yPos = 0+scaler/2*arrayDueTimes.get(i) * sin(i* delta);
pushMatrix();
translate(xPos, yPos);
rotate(delta * i);
fill(0);
text(i + "--------------------", 0, 0);
popMatrix();
}//for
popMatrix();
}
//________________________________________________________________________________________________________________________________
class Timer {
int savedTime;
boolean running = false;
int totalTime;
Timer(int tempTotalTime) {
totalTime = tempTotalTime;
}
void start() {
running = true;
savedTime = millis();
}
boolean isFinished() {
int passedTime = millis() - savedTime;
if (running && passedTime > totalTime) {
running = false;
return true;
} else {
return false;
}
}
}
In case this is of use... before I tried to put the arcs into a class, it worked fine with the following code:
String urlStationInfo = "http://" + "api.irishrail.ie/realtime/realtime.asmx/getStationsFilterXML?StationText=";
XML xmlA;
XML xmlS;
XML[] childrenA;
XML[] childrenS;
FloatList arrayDueTimes;
IntList arrayLateTimes;
StringList arrayID;
StringList stationID;
int angle=0;
int scaler = 10;
Timer timer = new Timer(10000);
//________________________________________________________________________________________________________________________________
void setup() {
size(800, 800, P2D);
requestStationData();
requestArrayData();
timer.start();
}
//________________________________________________________________________________________________________________________________
void draw() {
background(255, 193, 37);
if (timer.isFinished()) { // Every one second, make a new request.
println("Timer is finished: Requesting values and restarting");
requestStationData();
requestArrayData();
timer.start(); // And restart the timer.
}
drawArcs();
}
//________________________________________________________________________________________________________________________________
void drawArcs(){
float startAngle = 0;
float lastAngle = 0;
float radian = 360.0/arrayDueTimes.size();
for (int i = 0; i < arrayDueTimes.size(); i++) {
fill(255);
stroke(0);
strokeWeight(0);
arc(width/2, height/2, scaler*(arrayDueTimes.get(i)), scaler*(arrayDueTimes.get(i)), lastAngle, lastAngle+radians(radian));
lastAngle += radians(radian);
startAngle = startAngle + lastAngle;
}//for
}
//________________________________________________________________________________________________________________________________
void requestStationData() {
xmlS = loadXML(urlStationInfo);
childrenS = xmlS.getChildren("objStationFilter");
stationID = new StringList();
for (int i = 0; i < childrenS.length; i++) {
XML sIDElement = childrenS[i].getChild("StationCode");
String sID = sIDElement.getContent();
stationID.append(sID);
}
}
//________________________________________________________________________________________________________________________________
void requestArrayData() {
arrayID = new StringList();
arrayDueTimes = new FloatList();
arrayLateTimes = new IntList();
//xmlA = loadXML("stationData.xml");
for (int i = 0; i < childrenS.length; i++) {
String myString = stationID.get(i);
//xmlA = loadXML("stationData.xml");
xmlA = loadXML("http://api.irishrail.ie/realtime/realtime.asmx/getStationDataByCodeXML?StationCode=" + myString);
childrenA = xmlA.getChildren("objStationData");
for (int j = 0; j < childrenA.length; j++) {
//println(childrenA.length);
XML originElement = childrenA[j].getChild("Origin");
String origin = originElement.getContent();
XML destinationElement = childrenA[j].getChild("Destination");
String destination = destinationElement.getContent();
XML dueElement = childrenA[j].getChild("Duein");
int due = dueElement.getIntContent();
arrayDueTimes.append(due);
XML fullNameElement= childrenA[j].getChild("Stationfullname");
String fullName = fullNameElement.getContent();
arrayID.append(fullName);
XML lateElement = childrenA[j].getChild("Late");
int late = lateElement.getIntContent();
arrayLateTimes.append(late);
println(" Station: " + fullName + ". Next Train: " + origin + " to " + destination + " is due in " + due + "minutes.");
}
}
}
//________________________________________________________________________________________________________________________________
class Timer {
int savedTime;
boolean running = false;
int totalTime;
Timer(int tempTotalTime) {
totalTime = tempTotalTime;
}
void start() {
running = true;
savedTime = millis();
}
boolean isFinished() {
int passedTime = millis() - savedTime;
if (running && passedTime > totalTime) {
running = false;
return true;
} else {
return false;
}
}
}
Okay, sorry koogs. I shall continue in this one.
So I adjusted my class according to the advice from TfGuy44 and revisiting some of Daniel Schiffman's arrays/objects tutorials. This is where I'm at. I'm confused about where to loop: should I loop inside the display of the class or in draw()? :(
String urlStationInfo = "http://" + "api.irishrail.ie/realtime/realtime.asmx/getStationsFilterXML?StationText=";
Arc[] arcs;
XML xmlA;
XML xmlS;
XML[] childrenA;
XML[] childrenS;
FloatList arrayDueTimes;
IntList arrayLateTimes;
StringList arrayID;
StringList stationID;
int angle=0;
int scaler = 10;
Timer timer = new Timer(10000);
//________________________________________________________________________________________________________________________________
void setup() {
size(800, 800, P2D);
requestStationData();
requestArrayData();
arcs = new Arc[arrayDueTimes.size()];
for (int i = 0; i < arrayDueTimes.size(); i++) {
arcs[i] = new Arc(360.0/arrayDueTimes.size(), i);
}
timer.start();
}
//________________________________________________________________________________________________________________________________
void draw() {
background(255, 193, 37);
if (timer.isFinished()) { // Every one second, make a new request.
println("Timer is finished: Requesting values and restarting");
requestStationData();
requestArrayData();
timer.start(); // And restart the timer.
}
for (int i = 0; i < arrayDueTimes.size(); i ++ ) {
arcs[i].display(i);
}
}
//________________________________________________________________________________________________________________________________
class Arc {
float radian;
int noOfArcs;
Arc(float tempRadian, int tempNoOfArcs) {
radian = tempRadian;
noOfArcs = tempNoOfArcs;
}
void display(int i) {
float startAngle = 0;
float lastAngle = 0;
fill(0);
stroke(0);
strokeWeight(1);
arc(width/2, height/2, scaler*abs(arrayDueTimes.get(i)), scaler*abs(arrayDueTimes.get(i)), lastAngle, lastAngle+radians(radian));
lastAngle += radians(radian);
startAngle = startAngle + lastAngle;
}
}
//________________________________________________________________________________________________________________________________
void requestStationData() {
xmlS = loadXML(urlStationInfo);
childrenS = xmlS.getChildren("objStationFilter");
stationID = new StringList();
for (int i = 0; i < childrenS.length; i++) {
XML sIDElement = childrenS[i].getChild("StationCode");
String sID = sIDElement.getContent();
stationID.append(sID);
}
}
//________________________________________________________________________________________________________________________________
class Timer {
int savedTime;
boolean running = false;
int totalTime;
Timer(int tempTotalTime) {
totalTime = tempTotalTime;
}
void start() {
running = true;
savedTime = millis();
}
boolean isFinished() {
int passedTime = millis() - savedTime;
if (running && passedTime > totalTime) {
running = false;
return true;
} else {
return false;
}
}
}
//________________________________________________________________________________________________________________________________
void requestArrayData() {
arrayID = new StringList();
arrayDueTimes = new FloatList();
arrayLateTimes = new IntList();
//xmlA = loadXML("stationData.xml");
for (int i = 0; i < childrenS.length; i++) {
String myString = stationID.get(i);
//xmlA = loadXML("stationData.xml");
xmlA = loadXML("http://api.irishrail.ie/realtime/realtime.asmx/getStationDataByCodeXML?StationCode=" + myString);
childrenA = xmlA.getChildren("objStationData");
for (int j = 0; j < childrenA.length; j++) {
//println(childrenA.length);
XML originElement = childrenA[j].getChild("Origin");
String origin = originElement.getContent();
XML destinationElement = childrenA[j].getChild("Destination");
String destination = destinationElement.getContent();
XML dueElement = childrenA[j].getChild("Duein");
int due = dueElement.getIntContent();
arrayDueTimes.append(due);
XML fullNameElement= childrenA[j].getChild("Stationfullname");
String fullName = fullNameElement.getContent();
arrayID.append(fullName);
XML lateElement = childrenA[j].getChild("Late");
int late = lateElement.getIntContent();
arrayLateTimes.append(late);
//println(" Station: " + fullName + ". Next Train: " + origin + " to " + destination + " is due in " + due + "minutes.");
}
}
}
I (kind of) solved it using the following code, though I'm currently troubleshooting the reason that this particular code runs very slowly.
String urlStationInfo = "http://" + "api.irishrail.ie/realtime/realtime.asmx/getStationsFilterXML?StationText=";
Arc[] arcs;
XML xmlA;
XML xmlS;
XML[] childrenA;
XML[] childrenS;
IntList arrayDueTimes;
IntList arrayLateTimes;
StringList arrayID;
StringList stationID;
int angle=0;
int scaler = 10;
Timer timer = new Timer(10000);
//________________________________________________________________________________________________________________________________
void setup() {
size(800, 800, P2D);
requestStationData();
requestArrayData();
arcs = new Arc[arrayDueTimes.size()];
for (int i = 0; i < arrayDueTimes.size(); i++) {
arcs[i] = new Arc(360/arrayDueTimes.size(), i);
}
timer.start();
}
//________________________________________________________________________________________________________________________________
void draw() {
background(255, 193, 37);
if (timer.isFinished()) { // Every one second, make a new request.
println("Timer is finished: Requesting values and restarting");
requestStationData();
requestArrayData();
timer.start(); // And restart the timer.
}
for (Arc a : arcs) {
a.display();
}
}
//________________________________________________________________________________________________________________________________
class Arc {
float radian;
int noOfArcs;
Arc(float tempRadian, int tempNoOfArcs) {
radian = tempRadian;
noOfArcs = tempNoOfArcs;
}
void display() {
float startAngle = 0;
float lastAngle = 0;
for (int i=0; i<arrayDueTimes.size(); i++) {
fill(255,0,0);
stroke(0);
strokeWeight(0);
arc(width/2, height/2, scaler*abs(arrayDueTimes.get(i))+arrayLateTimes.get(i), scaler*abs(arrayDueTimes.get(i))+arrayLateTimes.get(i), lastAngle, lastAngle+radians(radian));
fill(0+i*1);
stroke(0);
strokeWeight(0);
arc(width/2, height/2, scaler*abs(arrayDueTimes.get(i)), scaler*abs(arrayDueTimes.get(i)), lastAngle, lastAngle+radians(radian));
lastAngle += radians(radian);
startAngle = startAngle + lastAngle;
}
}
}
//________________________________________________________________________________________________________________________________
class Timer {
int savedTime;
boolean running = false;
int totalTime;
Timer(int tempTotalTime) {
totalTime = tempTotalTime;
}
void start() {
running = true;
savedTime = millis();
}
boolean isFinished() {
int passedTime = millis() - savedTime;
if (running && passedTime > totalTime) {
running = false;
return true;
} else {
return false;
}
}
}
//________________________________________________________________________________________________________________________________
void requestStationData() {
xmlS = loadXML(urlStationInfo);
childrenS = xmlS.getChildren("objStationFilter");
stationID = new StringList();
for (int i = 0; i < childrenS.length; i++) {
XML sIDElement = childrenS[i].getChild("StationCode");
String sID = sIDElement.getContent();
stationID.append(sID);
}
}
//________________________________________________________________________________________________________________________________
void requestArrayData() {
arrayID = new StringList();
arrayDueTimes = new IntList();
arrayLateTimes = new IntList();
//xmlA = loadXML("stationData.xml");
for (int i = 0; i < childrenS.length; i++) {
String myString = stationID.get(i);
xmlA = loadXML("http://api.irishrail.ie/realtime/realtime.asmx/getStationDataByCodeXML?StationCode=" + myString);
childrenA = xmlA.getChildren("objStationData");
for (int j = 0; j < childrenA.length; j++) {
//println(childrenA.length);
XML originElement = childrenA[j].getChild("Origin");
String origin = originElement.getContent();
XML destinationElement = childrenA[j].getChild("Destination");
String destination = destinationElement.getContent();
XML dueElement = childrenA[j].getChild("Duein");
int due = dueElement.getIntContent();
arrayDueTimes.append(due);
XML fullNameElement= childrenA[j].getChild("Stationfullname");
String fullName = fullNameElement.getContent();
arrayID.append(fullName);
XML lateElement = childrenA[j].getChild("Late");
int late = lateElement.getIntContent();
arrayLateTimes.append(late);
println(" Station: " + fullName + ". Next Train: " + origin + " to " + destination + " due in " + due + "mins / Running " + late + " mins late." );
}
}
}
I wanted to make a class for an array of arcs, and somehow this seems to be draining CPU. I've gone through it again and again deleting bits of code and running. I can't figure out which part is causing this but I'm pretty sure it's the 'class Arc' on line 53.
Any tips would be much appreciated:)
String urlStationInfo = "http://" + "api.irishrail.ie/realtime/realtime.asmx/getStationsFilterXML?StationText=";
Arc[] arcs;
XML xmlA;
XML xmlS;
XML[] childrenA;
XML[] childrenS;
IntList arrayDueTimes;
IntList arrayLateTimes;
StringList arrayID;
StringList stationID;
int angle=0;
int scaler = 10;
Timer timer = new Timer(10000);
//________________________________________________________________________________________________________________________________
void setup() {
size(800, 800, P2D);
requestStationData();
requestArrayData();
arcs = new Arc[arrayDueTimes.size()];
for (int i = 0; i < arrayDueTimes.size(); i++) {
arcs[i] = new Arc(360/arrayDueTimes.size(), i);
}
timer.start();
}
//________________________________________________________________________________________________________________________________
void draw() {
background(255, 193, 37);
if (timer.isFinished()) { // Every one second, make a new request.
println("Timer is finished: Requesting values and restarting");
requestStationData();
requestArrayData();
timer.start(); // And restart the timer.
}
for (Arc a : arcs) {
a.display();
}
}
//________________________________________________________________________________________________________________________________
class Arc {
float radian;
int noOfArcs;
Arc(float tempRadian, int tempNoOfArcs) {
radian = tempRadian;
noOfArcs = tempNoOfArcs;
}
void display() {
float startAngle = 0;
float lastAngle = 0;
for (int i=0; i<arrayDueTimes.size(); i++) {
fill(255,0,0);
stroke(0);
strokeWeight(0);
arc(width/2, height/2, scaler*abs(arrayDueTimes.get(i))+arrayLateTimes.get(i), scaler*abs(arrayDueTimes.get(i))+arrayLateTimes.get(i), lastAngle, lastAngle+radians(radian));
fill(0+i*1);
stroke(0);
strokeWeight(0);
arc(width/2, height/2, scaler*abs(arrayDueTimes.get(i)), scaler*abs(arrayDueTimes.get(i)), lastAngle, lastAngle+radians(radian));
lastAngle += radians(radian);
startAngle = startAngle + lastAngle;
}
}
}
//________________________________________________________________________________________________________________________________
class Timer {
int savedTime;
boolean running = false;
int totalTime;
Timer(int tempTotalTime) {
totalTime = tempTotalTime;
}
void start() {
running = true;
savedTime = millis();
}
boolean isFinished() {
int passedTime = millis() - savedTime;
if (running && passedTime > totalTime) {
running = false;
return true;
} else {
return false;
}
}
}
//________________________________________________________________________________________________________________________________
void requestStationData() {
xmlS = loadXML(urlStationInfo);
childrenS = xmlS.getChildren("objStationFilter");
stationID = new StringList();
for (int i = 0; i < childrenS.length; i++) {
XML sIDElement = childrenS[i].getChild("StationCode");
String sID = sIDElement.getContent();
stationID.append(sID);
}
}
//________________________________________________________________________________________________________________________________
void requestArrayData() {
arrayID = new StringList();
arrayDueTimes = new IntList();
arrayLateTimes = new IntList();
//xmlA = loadXML("stationData.xml");
for (int i = 0; i < childrenS.length; i++) {
String myString = stationID.get(i);
xmlA = loadXML("http://"+"api.irishrail.ie/realtime/realtime.asmx/getStationDataByCodeXML?StationCode=" + myString);
childrenA = xmlA.getChildren("objStationData");
for (int j = 0; j < childrenA.length; j++) {
//println(childrenA.length);
XML originElement = childrenA[j].getChild("Origin");
String origin = originElement.getContent();
XML destinationElement = childrenA[j].getChild("Destination");
String destination = destinationElement.getContent();
XML dueElement = childrenA[j].getChild("Duein");
int due = dueElement.getIntContent();
arrayDueTimes.append(due);
XML fullNameElement= childrenA[j].getChild("Stationfullname");
String fullName = fullNameElement.getContent();
arrayID.append(fullName);
XML lateElement = childrenA[j].getChild("Late");
int late = lateElement.getIntContent();
arrayLateTimes.append(late);
println(" Station: " + fullName + ". Next Train: " + origin + " to " + destination + " due in " + due + "mins / Running " + late + " mins late." );
}
}
}
size(1600, 900);
colorMode(HSB, 255);
background(0);
for (int i = 0; i < 10; i++) {
// set color
fill(25*i, 255, 255);
// show arc
stroke(0);
arc(width/2, height/2,
350, 350,
TWO_PI/10.0*i, TWO_PI/10.0*(i+1) );
// show rects with text
rect(1420, 20+30*i, 20, 20);
fill(255);
textAlign(LEFT);
text("Section " + i, 1450, 36 + 30*i);
// text at arcs
float halfAngle = TWO_PI/10.0/3;
float x1=width/2 + 210* cos(TWO_PI/10.0*i+halfAngle);
float y1=height/2 + 210* sin(TWO_PI/10.0*i+halfAngle);
textAlign(CENTER);
text("Section " + i,
x1, y1);
//
}//for
The code you posted does not run. It is missing user-defined classes, and probably your data.
Here is an example of a pie-chart with a label instead. Make sure you understand how this is drawn, and then use that understanding to draw your own pie chart and label.
size(600,400);
colorMode(HSB,255);
background(0);
for(int i = 0; i < 10; i++){
fill(25*i,255,255);
stroke(0);
arc(200,200,350,350,TWO_PI/10.0*i,TWO_PI/10.0*(i+1) );
rect(420,20+30*i,20,20);
fill(255);
text("Section " + i, 450, 36 + 30*i);
}
Hi, i hope somebody could help me because i should do the Project for my work. I created a pie Chart but i dont know how i can place the Label.
In the middle of the arc (outside the Circle) there should be the Label.
for (Rohtipps g : myRohtipp) {
//PVector c = randomVector(mapped);
//draw ellipse
PVector loc = g.getLocation();
float dia = g.getDiameter();
//noFill();
float[] data={g.getColdlead(), g.getWarmlead(), g.getHotlead()};
//float[] data={50.0, 50.0, 50.0, 50.0};
float sumdata=0;
for (int i=0; i<data.length; i++) {
sumdata+=data[i];
}
//println(sumdata);
sumdata = 360/sumdata;
for (int i=0; i<data.length; i++) {
data[i] = sumdata*data[i];
}
float lastAngle=0;
for (int i=0; i<data.length; i++) {
float col=map(i, 0, data.length, 20, 255);
fill(55, 150, col, col+100);
noStroke();
arc(loc.x, loc.y, dia, dia, lastAngle, lastAngle+radians(data[i]));
lastAngle +=radians(data[i]);
}
//println(g.getKampagne()+" "+g.getColdlead()+" "+g.getWarmlead()+" "+g.getHotlead());
//pieChart(dia, loc.x, loc.y, data);
//ellipse(loc.x, loc.y, dia, dia);
fill(40, 40, 40);
//label positionieren
textSize(11);
float tw=(textWidth(g.getKampagne()))/2;
text(g.getKampagne(), loc.x-tw, loc.y+30);
//println(g.getAnzahl());
ts=ts-2;
textSize(ts);
fill(30, 30, 30);
text(g.getKampagne()+" "+g.getAnzahl(), 1400, g.getPositionText());
textSize(24);
//println(g.getColdlead());
}
Thanks Theresa
Hey, thanks for the comment !
Here the code :
final float diameter = 700; //the diameter of the circle
color[] digitColor = new color[10]; //The color of each digit
float[] currentDigitAngle = new float[10]; //Keep track of the last angle used for each digit (each time a line goes to the digit, the line is offset)
float[] digitAngleStep = new float[10]; //Store the step to add every time the line goes to a digit
int pos; //Keep track of the current digits beeing displayed if the draw function is used
int[] digit; //All the digit of PI
void setup() {
size(1920, 1080);
background(0);
translate(width/2, height/2);
noFill();
stroke(255);
textAlign(CENTER, CENTER);
strokeWeight(5);
//Variables
String dataString; //all the PI number as string
int[] digitCount = new int[10]; //The amount of each deach from 0 to 9
float[] digitWeight = new float[10]; //The proportion of each digit from 0 to 9
final float angleGap = 0.03; //The gap between each arc
float[] digitAngleSize = new float[10]; //The size of each digit arc
float currentAngle; //Use to keep track of the last arc drawn on screen in order the draw the next one after
PFont myFont; //The font used for the text
//Initialize variables
myFont = createFont("data/Comfortaa-Regular.ttf", 40);
textFont(myFont);
textSize(diameter / 10);
text("π", -5, -10);
textSize(diameter / 30);
pos = 0;
digitColor[0] = color(236, 166, 15);
digitColor[1] = color(232, 125, 27);
digitColor[2] = color(227, 45, 42);
digitColor[3] = color(210, 0, 64);
digitColor[4] = color(168, 11, 95);
digitColor[5] = color(135, 46, 134);
digitColor[6] = color(91, 77, 163);
digitColor[7] = color(46, 116, 157);
digitColor[8] = color(30, 154, 119);
digitColor[9] = color(91, 176, 90);
//Load data from string
dataString = loadStrings("Data/PI_10000_digits.txt")[0];
//Transform data to integer and get count
digit = new int[dataString.length()];
for (int i = 0; i < dataString.length(); i++) {
digit[i] = Character.getNumericValue(dataString.charAt(i));
digitCount[digit[i]]++;
}
//Find weight and angle
for (int i = 0; i < 10; i++) {
digitWeight[i] = (float)digitCount[i] / digit.length;
digitAngleSize[i] = digitWeight[i] * (TWO_PI - (10 * angleGap));
if (digitCount[i] == 1) {
digitAngleStep[i] = 0;
} else {
digitAngleStep[i] = digitAngleSize[i] / (digitCount[i] - 1);
}
}
//Draw arcs and text
currentAngle = (3 * PI / 2) - (digitAngleSize[0] / 2);
for (int i = 0; i < 10; i++) {
//Arcs
stroke(red(digitColor[i]), green(digitColor[i]), blue(digitColor[i]));
noFill();
arc(0, 0, diameter, diameter, currentAngle, currentAngle+digitAngleSize[i]);
currentDigitAngle[i] = currentAngle;
//Text
fill(red(digitColor[i]), green(digitColor[i]), blue(digitColor[i]));
text(i, 1.1 * (diameter / 2) * cos((2*currentAngle+digitAngleSize[i])/2), 1.1 * (diameter/2) * sin((2*currentAngle+digitAngleSize[i])/2));
currentAngle = currentAngle + digitAngleSize[i] + angleGap;
}
//*******
//COMMENT THOSE LINES IF YOU USE THE DRAW FUNCTION
//*******
//Draw bezier curves
for (int i = 0; i < digit.length - 1; i++) {
drawBezier(currentDigitAngle[digit[i]], currentDigitAngle[digit[i+1]], digitColor[digit[i]]);
currentDigitAngle[digit[i]] += digitAngleStep[digit[i]];
}
//*******
}
void draw() {
//*******
//UNCOMMENT THOSE LINES TO SEE THE DRAWING PROCESS
//*******
//translate(width/2, height/2);
//for (int i = 0; i < 10; i++) {
// if (pos < digit.length - 1) {
// drawBezier(currentDigitAngle[digit[pos]], currentDigitAngle[digit[pos+1]], digitColor[digit[pos]]);
// currentDigitAngle[digit[pos]] += digitAngleStep[digit[pos]];
// pos++;
// }
//}
}
// Function called to draw the bezier curves between two points
// angle1 is the angle of the first point
// angle2 is the angle od the second point
// Stroke color is the color used for the line
void drawBezier(float angle1, float angle2, color strokeColor) {
float x1, y1, x2, y2, r, controlAngle1, controlAngle2, controlR;
r = (diameter / 2) - 6;
x1 = r * cos(angle1);
y1 = r * sin(angle1);
x2 = r * cos(angle2);
y2 = r * sin(angle2);
noFill();
stroke(red(strokeColor), green(strokeColor), blue(strokeColor), 5);
strokeWeight(2);
//Different method is used in order to avoid line in the middle section
if (angleDiff(x1, y1, x2, y2, 0, 0) < 0.3) {
controlAngle1 = getAngle(x1, y1, 0, 0) + 0.5;
controlAngle2 = getAngle(x2, y2, 0, 0) - 0.5;
controlR = 0.9 * dist(x1, y1, 0, 0);
bezier(x1, y1, x1 + controlR * cos(controlAngle1), y1 + controlR * sin(controlAngle1), x2 + controlR * cos(controlAngle2), y2 + controlR * sin(controlAngle2), x2, y2);
} else {
bezier(x1, y1, x1/2, y1/2, x2/2, y2/2, x2, y2);
}
}
//Get angle from point 1 to point 2
float getAngle(float x1, float y1, float x2, float y2) {
float angle;
if (x2==x1) {
if (y1>y2) {
return HALF_PI;
} else {
return -HALF_PI;
}
}
angle = atan((y2-y1)/(x2-x1));
if (x1 > x2) {
return angle + PI;
} else {
return angle;
}
}
//Angle difference between pt1-2 and p1-3
float angleDiff(float x1, float y1, float x2, float y2, float x3, float y3) {
float a1, a2, aDiff;
a1 = getAngle(x1, y1, x2, y2);
a2 = getAngle(x1, y1, x3, y3);
aDiff = abs(a1 - a2);
if (aDiff > PI) {
if (a1>a2) {
while (a1>a2) {
a1 = a1 - TWO_PI;
}
} else {
while (a1<a2) {
a1 = a1 + TWO_PI;
}
}
}
aDiff = abs(a1 - a2);
return aDiff;
}
float x;
float y;
float d;
float progress=9;
void setup() {
size(300, 300);
x = width/2;
y = height/2;
d = width * 0.8;
smooth();
background(14, 18, 30);
}
void draw() {
background(14, 18, 30);
// show full circles
ellipseMode(CENTER);
fill(#26221A);
ellipse(x, y, d, d);//yellow1
fill(#1C2420);
ellipse(x, y, d-30, d-30);//green1
fill(#101E24);
ellipse(x, y, d-60, d-60);//blue1
showArcs();
// -----------------
if (keyPressed&&key=='+')
progress++;
if (keyPressed&&key=='-')
progress--;
fill(255); // white
text(progress
+", use + and - ", 18, 18);
}
//---------------------------------------------------------------
void showArcs() {
fill(#B77C08); // !!!!!!!!!!!!!!!!!!!!!!!!!
arc(x, y, d, d, PI+HALF_PI, map(progress, 0, 100, PI+HALF_PI, PI+HALF_PI+PI+HALF_PI));//yellow !!!!!!!!!!!!!!!
fill(#657D31);
arc(x, y, d-30, d-30, PI+HALF_PI, TWO_PI);//green
fill(#1E624C);
arc(x, y, d-60, d-60, PI+HALF_PI, TWO_PI+QUARTER_PI);//blue
fill(14, 18, 30);
arc(x, y, d-90, d-90, 0, TWO_PI);//center
}
//
Hi,thank you for your precious reply...,This is my arc effect progress bar code ,Next, how can I change it by clicking on the keyboard? waiting for your suggestions and trying my best for this...
regards ...>
void setup(){
size(300,300);
smooth();
background(14,18,30);
}
void draw(){
float x = width/2;
float y = height/2;
float d = width * 0.8;
ellipseMode(CENTER);
fill(#26221A);
ellipse(x,y,d, d);//yellow1
fill(#1C2420);
ellipse(x,y,d-30, d-30);//green1
fill(#101E24);
ellipse(x,y,d-60, d-60);//blue1
fill(#B77C08);
arc(x,y,d, d,PI+HALF_PI, PI+HALF_PI+QUARTER_PI);//yellow
fill(#657D31);
//noStroke();
arc(x, y, d-30, d-30, PI+HALF_PI,TWO_PI);//green
fill(#1E624C);
arc(x, y, d-60, d-60, PI+HALF_PI,TWO_PI+QUARTER_PI);//blue
fill(14,18,30);
arc(x, y, d-90, d-90, 0,TWO_PI);//center
}
Your idea is good, just read the arc()
reference again
I think you need to know the thickness of your petal ring (distance inner line and outer line)
Concentrate on one ring please (for a start)
okay well lets learn, I'm having trouble understanding what the translate, and push matrix command do. I tried to remove the translate by just drawing everything in the center.
int outerPetalNum;
int innerPetalNum =7;
int centX,centY;
void setup() {
size(600, 600);
}
void draw() {
background(255);
for (outerPetalNum = 15; outerPetalNum >= innerPetalNum; outerPetalNum-=2) {
rotate(outerPetalNum);
for ( int i = 0; i < outerPetalNum; i++) {
petal(color(250, map(outerPetalNum,4,20,255,100), 250),
TWO_PI/float(2*outerPetalNum), 20*outerPetalNum-70);
rotate(TWO_PI/float(outerPetalNum));
}
}
fill(250,200,50);
ellipse(0,0,70,70);
}
void petal(color c, float a, float r) {
fill(c);
pushMatrix();
translate(20, 0);
centX = width/2;
centY = height/2;
arc(centX, centY, 2*r, 2*r, -a, a);
line(centX, centY, r*cos(-a), r*sin(-a));
line(centX,centY, r*cos(a), r*sin(a));
popMatrix();
}
Here are my adjustments, can you explain how I could make it work using this idea instead of the translate command?
To your question: let’s say your progress runs from 0 to 1000 then you can say
progressToDisplay=map(progress, 0, 1000, 0, TWO_PI);
and use this for arc(.....
Hi Chrisir, thank you for your precious reply...,but(Use radians() or map() to convert this value for the arc() command)I am not quite sure and how to command this variable?
Look at arc
please
It’s a command in the reference
Make a full arc (with less opacity) and your progress bar with full opacity - see command fill()
Now make several arcs all with the same center but different radius
For each arc you need a progress variable (the stop angle) how far the arc is painted
With keyPressed
and key=='+'
you can change this variable (stopProgressVar1++;
)
Use radians() or map() to convert this value for the arc() command
Show your entire code then
Chrisir