It turns out that just using floor for the minutes does work after all.
I did try that, it gets janky when changing directions. There might be a way to make that work but it becomes unnecessarily clunky as far as I can see.
I was able to get this idea to work, too, but it doesn’t seem to work differently than just using floor for what I’m trying to do right now.
I might try something with this but its not what I was trying to solve at the moment.
Thanks for the help, it seems like this is pretty much working the way I wanted now.
// clock face
PVector c, c2;
float r, r2;
int divisions;
// mouse
PVector m, pm, mo, po;
float offset = -HALF_PI, heading, cross;
boolean cwDrag, ccwDrag, measuring, measureBegan;
// math
float snapAngle, dragAngle, dragAngleSnap;
float startAngleOffset, startAngleSnap;
float accDragAngle, accAngleSnap, accMinAngle;
int startSec, endSec, accSec, accMin;
PFont mono, sans;
void setup() {
size(400, 600);
mono = createFont("Monospaced", 18);
sans = createFont("Helvetica", 18);
//pixelDensity(2);
ellipseMode(RADIUS);
r = width/2 - 70;
c = new PVector(width/2, height - r - 70);
c2 = new PVector(50, height-50);
r2 = 30;
m = new PVector();
pm = new PVector();
divisions = 12;
snapAngle = TWO_PI/divisions;
}
void draw() {
background(127);
checkMouse();
dragAngle = heading;
dragAngleSnap = snapRound(dragAngle);
if (mousePressed && !measureBegan) {
measureBegan = true;
startAngleSnap = dragAngleSnap;
startAngleOffset = startAngleSnap - dragAngle;
startSec = round(startAngleSnap/snapAngle);
startSec *= 60/divisions;
endSec = startSec;
accDragAngle = 0;
accDragAngle -= startAngleOffset;
accAngleSnap = 0;
accSec = 0;
accMin = 0;
}
if (measuring) {
endSec = round(dragAngleSnap/snapAngle);
endSec *= 60/divisions;
accDragAngle += calcDragAngleDiff();
accAngleSnap = snapRound(accDragAngle);
accSec = round(accAngleSnap/snapAngle);
accSec *= 60/divisions;
accMin = floor(accSec/60);
accMinAngle = accMin*TWO_PI/60;
}
showNeedles();
showFace(c, r);
showFace(c2, r2);
showTextLeft();
showTextRight();
}
void mouseDragged() {
measuring = true;
}
void showTextLeft() {
String startAngleSnapStr = nfs(startAngleSnap, 3, 2) + " " + "startAngleSnap";
String dragAngleStr = nfs(dragAngle, 3, 2) + " " + "dragAngle";
String dragAngleSnapStr = nfs(dragAngleSnap, 3, 2) + " " + "dragAngleSnap";
String accDragAngleStr = nfs(accDragAngle, 3, 2) + " " + "accDragAngle";
String accAngleSnapStr = nfs(accAngleSnap, 3, 2) + " " + "accAngleSnap";
String accMinAngleStr = nfs(accMinAngle, 3, 2) + " " + "accMinAngle";
String[] strings = {
startAngleSnapStr,
dragAngleStr,
dragAngleSnapStr,
accDragAngleStr,
accAngleSnapStr,
accMinAngleStr
};
float textH = 18;
textFont(mono);
textSize(textH);
textAlign(LEFT, TOP);
fill(0);
for (int i=0; i<strings.length; i++) {
text(strings[i], 5, 5+i*textH);
}
}
void showTextRight() {
String newLine = "";
String startSecStr = "startSec" + " " + nfs(startSec, 2);
String endSecStr = "endSec" + " " + nfs(endSec, 2);
String accSecStr = "accSec" + " " + nfs(accSec, 2);
String accMinStr = "accMin" + " " + nfs(accMin, 2);
String accTimeSign = accMin<0 || accSec<0 ? "-" : " ";
String accTimeStr = "accTime" + " " + accTimeSign + nf(abs(accMin), 2) + ":" + nf(abs(accSec%60), 2);
String[] strings = {
startSecStr,
newLine,
endSecStr,
newLine,
accSecStr,
accMinStr,
newLine,
accTimeStr
};
float textH = 18;
textFont(mono);
textSize(textH);
textAlign(RIGHT, TOP);
fill(0);
for (int i=0; i<strings.length; i++) {
text(strings[i], width-5, 5+i*textH);
}
}
float calcDragAngleDiff() {
float diff = PVector.angleBetween(mo, po);
if (ccwDrag) diff = -diff;
return diff;
}
float snapRound(float a) {
a /= snapAngle;
a = round(a);
a *= snapAngle;
return a;
}
void checkMouse() {
m.set(mouseX, mouseY);
mo = PVector.sub(m, c);
mo.rotate(-offset);
pm.set(pmouseX, pmouseY);
po = PVector.sub(pm, c);
po.rotate(-offset);
cross = mo.cross(po).z;
cwDrag = cross < 0;
ccwDrag = cross > 0;
heading = mo.heading();
heading = (heading > 0) ? heading : heading + TWO_PI;
if (!mousePressed) {
measuring = false;
measureBegan = false;
}
}
void showNeedles() {
showNeedle(c, r, dragAngle, color(255), 7);
showNeedle(c, r, startAngleSnap, color(50, 200, 65), 5);
showNeedle(c, r, dragAngleSnap, color(200, 35, 40), 3);
showNeedle(c2, r2, accMinAngle, color(0), 3);
showNeedle(c2, r2, dragAngleSnap, color(200, 35, 40), 3);
}
void showNeedle(PVector loc, float radius, float angle, color needleColor, int needleSize) {
strokeWeight(needleSize);
stroke(needleColor);
angle += offset;
lineStartRA(loc, radius+radius/5.5, angle);
}
void circleCR(PVector loc, float radius) {
ellipse(loc.x, loc.y, radius, radius);
}
void lineStartRA(PVector start, float r, float a) {
PVector end = new PVector(cos(a), sin(a));
end.mult(r);
end.add(start);
linePts(start, end);
}
void linePts(PVector start, PVector end) {
line(start.x, start.y, end.x, end.y);
}
void showFace(PVector loc, float radius) {
PVector tickLoc = new PVector();
PVector textLoc = new PVector();
strokeWeight(1);
noStroke();
fill(127, 200);
circleCR(loc, radius);
for (int i=0; i<divisions; i++) {
float inc = TWO_PI/divisions;
float angle = i*inc;
angle += offset;
float x = cos(angle);
float y = sin(angle);
tickLoc.set(x, y);
tickLoc.mult(radius);
tickLoc.add(loc);
stroke(0);
noFill();
circleCR(tickLoc, radius/40);
textLoc.set(x, y);
textLoc.mult(radius+radius/3);
textLoc.add(loc);
int numVal = (i+divisions-1)%divisions+1;
numVal *= 60/divisions;
String numTextStr = nf(numVal, 1);
fill(0);
textFont(sans);
textSize(radius/5.5);
textAlign(CENTER, CENTER);
text(numTextStr, textLoc.x, textLoc.y);
}
}