133 lines
3.1 KiB
Plaintext
133 lines
3.1 KiB
Plaintext
final float pointRadius = 5;
|
|
final int pointAmount = 6;
|
|
|
|
ArrayList<PVector> points = new ArrayList<PVector>();
|
|
boolean dragging = false, showNormals = true, showHelp = true;
|
|
int dragIndex = -1;
|
|
int increment = 100;
|
|
|
|
void setup() {
|
|
fullScreen();
|
|
|
|
for (int i = 0; i < pointAmount; i++) {
|
|
points.add(
|
|
new PVector(
|
|
((i + 1) * width) / (pointAmount + 1),
|
|
height / 2
|
|
)
|
|
);
|
|
}
|
|
|
|
textSize(height / 32);
|
|
}
|
|
|
|
void draw() {
|
|
background(0);
|
|
if (showHelp) {
|
|
fill(255);
|
|
text("Press 's' to show the Green Point-Connections.\nPress 'a' to decrease the calculated intervals of the red line.\nPress 'd' to increase the calculated intervals of the red line.\nPress 'h' to display this message.",0,height / 32);
|
|
}
|
|
|
|
if (dragging && dragIndex != -1) {
|
|
points.set(dragIndex, new PVector(mouseX, mouseY));
|
|
}
|
|
|
|
if (showNormals) {
|
|
fill(255);
|
|
for (int i = 0; i < points.size(); i++) {
|
|
final PVector current = points.get(i).copy();
|
|
stroke(255);
|
|
circle(current.x, current.y, pointRadius);
|
|
if (i > 0) {
|
|
final PVector previous = points.get(i - 1).copy();
|
|
stroke(0, 255, 0);
|
|
line(current.x, current.y, previous.x, previous.y);
|
|
}
|
|
}
|
|
}
|
|
|
|
noFill();
|
|
stroke(255, 0, 0);
|
|
PVector p = bezierCurve(0);
|
|
final float inc = (float)1 / increment;
|
|
for (float i = inc; i <= 1; i += inc) {
|
|
PVector n = bezierCurve(i);
|
|
line(p.x, p.y, n.x, n.y);
|
|
p = n.copy();
|
|
}
|
|
final PVector last = points.get(points.size()-1).copy();
|
|
line(p.x, p.y, last.x, last.y);
|
|
}
|
|
|
|
PVector bezierCurve(float t) {
|
|
final int n = points.size() - 1;
|
|
PVector newPoint = PVector.mult(points.get(0).copy(), pow(1 - t, n));
|
|
|
|
for (int i = 1; i <= n; i++) {
|
|
final float factor = binomialCoefficient(n, i) * pow(1 - t, n - i) * pow(t, i);
|
|
final PVector nextPoint = PVector.mult(points.get(i).copy(), factor);
|
|
newPoint.add(nextPoint);
|
|
}
|
|
|
|
return newPoint;
|
|
}
|
|
|
|
void mousePressed() {
|
|
dragging = true;
|
|
final PVector mouseVector = new PVector(mouseX, mouseY);
|
|
|
|
int recordIndex = 0;
|
|
float recordDistance = PVector.dist(mouseVector, points.get(recordIndex));
|
|
for (int i = 1; i < points.size(); i++) {
|
|
final float distance = PVector.dist(mouseVector, points.get(i));
|
|
if (distance < recordDistance) {
|
|
recordIndex = i;
|
|
recordDistance = distance;
|
|
}
|
|
}
|
|
|
|
if (recordDistance <= pointRadius * 4) {
|
|
dragIndex = recordIndex;
|
|
}
|
|
}
|
|
|
|
void mouseReleased() {
|
|
dragging = false;
|
|
dragIndex = -1;
|
|
}
|
|
|
|
void keyPressed() {
|
|
final char lk = lowerCaseChar(key);
|
|
if (lk == 's') {
|
|
showNormals = !showNormals;
|
|
} else if (lk == 'a' && increment > 0) {
|
|
increment -= 5;
|
|
} else if (lk == 'd' && increment < 100) {
|
|
increment += 5;
|
|
} else if (lk == 'h') {
|
|
showHelp = !showHelp;
|
|
}
|
|
}
|
|
|
|
char lowerCaseChar(char c) {
|
|
return str(c).toLowerCase().charAt(0);
|
|
}
|
|
|
|
float binomialCoefficient(int n, int k) {
|
|
return factorial(n) / (factorial(k) * factorial(n - k));
|
|
}
|
|
|
|
int factorial(int n) {
|
|
if (n == 0 || n == 1) {
|
|
return 1;
|
|
}
|
|
|
|
int o = 2;
|
|
|
|
for (int i = 3; i < n + 1; i++) {
|
|
o *= i;
|
|
}
|
|
|
|
return o;
|
|
}
|