Wanted to show you something
Here you have a curve with a plane.
When you drag the 4 red points you can change the curve
You can place the anchors (aka start/stop) OUTSIDE the canvas and move the control points
like with this example:
[ 1417.0, 181.0, 0.0 ]
[ -108.0, -4.0, 0.0 ]
[ 1509.0, 531.0, 0.0 ]
[ 376.0, -107.0, 0.0 ]
or here
[ 272.0, -19.0, 0.0 ]
[ -126.0, 255.0, 0.0 ]
[ 1793.0, 861.0, 0.0 ]
[ -2.0, -31.0, 0.0 ]
Remark
This Sketch can be seen as an curve editor, that printlns curve data that you then use in your main program
Full Sketch
// https://discourse.processing.org/t/align-the-arrows-with-the-route-or-how-to-follow-a-path-planes/41188
int index=-1;
float i_Plane;
PVector[] pvListDef = {
new PVector(340, 80),
new PVector(40, 40),
new PVector(360, 360),
new PVector( 60, 320)
};
PVector[] pvList = {
new PVector(340, 80),
new PVector(40, 40),
new PVector(360, 360),
new PVector( 60, 320)
};
//-------------------------------------------------------------------------------------
void setup() {
size(1400, 1400);
}
void draw() {
background(111);
noFill();
// show curve
bezier(pvList[0].x, pvList[0].y,
pvList[1].x, pvList[1].y,
pvList[2].x, pvList[2].y,
pvList[3].x, pvList[3].y);
// show points on curve
fill(255);
int steps = 100;
for (int i = 0; i <= steps; i++) {
float t = i / float(steps);
float x = bezierPoint(pvList[0].x, pvList[1].x, pvList[2].x, pvList[3].x, t);
float y = bezierPoint(pvList[0].y, pvList[1].y, pvList[2].y, pvList[3].y, t);
ellipse(x, y, 10, 10);
}
// PLANE
PVector posPlane=new PVector(0, 0),
facingPlane=new PVector(0, 0);
float t2 = i_Plane / float(steps);
float x2 = bezierPoint(pvList[0].x, pvList[1].x, pvList[2].x, pvList[3].x, t2);
float y2 = bezierPoint(pvList[0].y, pvList[1].y, pvList[2].y, pvList[3].y, t2);
posPlane=new PVector(x2, y2);
float t3 = (i_Plane+1) / float(steps);
float x3 = bezierPoint(pvList[0].x, pvList[1].x, pvList[2].x, pvList[3].x, t3);
float y3 = bezierPoint(pvList[0].y, pvList[1].y, pvList[2].y, pvList[3].y, t3);
// Start and end of our path
PVector v0 = new PVector(x2, y2);
PVector v1 = new PVector(x3, y3);
facingPlane = PVector.sub(v1, v0); // direction of travel / facing direction
fill(0, 255, 0);
drawPlane(posPlane, facingPlane);
i_Plane++;
if (i_Plane > steps)
i_Plane=0;
// show 4 RED points
int i=0;
for (PVector pv : pvList) {
fill(255, 0, 0);
ellipse(pv.x, pv.y, 16, 16);
if (i==0||i==3) {
fill(255);
text("anchor", pv.x, pv.y-10);
}
if (i==1||i==2) {
fill(255);
text("control", pv.x, pv.y-10);
}
i++;
}
fill(255);
// Allow drag
if (index>-1) {
fill(255);
text("Hit ESC to leave drag mode", 19, 19);
pvList[index].x=mouseX;
pvList[index].y=mouseY;
} else {
fill(255);
text("click RED points to drag ", 19, 19);
}
}//draw
//-------------------------------------------------------------------------------------
// Inputs
void keyPressed() {
index=-1;
key=0;
}
void mousePressed() {
// search point
int i=0;
index=-1;
for (PVector pv : pvList) {
if (dist(pv.x, pv.y, mouseX, mouseY)<19) {
index=i;
return;
}
i++;
}
}
void mouseReleased () {
// reset
index=-1;
// dump
for (PVector pv : pvList) {
println(pv);
}
}
//-------------------------------------------------------------------------------------
// Misc
void drawPlane(PVector pos, PVector facing) {
push(); // save current drawing attributes
float angle = atan2(facing.y, facing.x); // path angle
translate(pos.x, pos.y);
rotate(angle);
stroke(0, 0, 200);
//fill(255, 255, 0);
triangle(-5, -4, -5, 4, 8, 0);
pop(); // restore previous drawing attributes
}
//