Using vectors to find the line between two lines

I can do this (see sketch) with lerp(), but it cannot be the best way. Using lerp() and starting at the desired angle, one would have to use tan(), then solve two equations before knowing what value to give lerp(). Then I would need to lengthen the line. All doable, but inelegant.

I am guessing the cross formula is the way to go, but I could see further if I stood on the shoulders of giants.

lerp1

PVector a, b, c;
PVector middle;
float angle = 0.5;
float m;

void setup() {
  size(400, 400, P3D);

  a = new PVector(0, 0, 0);
  b = new PVector(100, 100, 0);
  c = new PVector(100, -100, 0);

  m = PVector.dist(a, b);
}

void draw() {
  background(255);
  strokeWeight(1);
  //noLoop();
  //println(mouseX);
  angle = 1-(mouseY/float(height));

  translate(width/2, height/2);  // move (0, 0, 0) to centre of window


  stroke(0, 0, 0);

  line(a.x, a.y, a.z, b.x, b.y, b.z);
  line(a.x, a.y, a.z, c.x, c.y, c.z);


  middle = PVector.lerp(b, c, angle);
  middle.normalize();
  middle.mult(m);
  stroke(0, 0, 127);
  line(a.x, a.y, a.z, middle.x, middle.y, middle.z);

  pushMatrix(); // move (0, 0, 0) back to centre of window
  translate(a.x, a.y, a.z);
  noFill();
  stroke(0);
  sphere(4);
  popMatrix();

  pushMatrix(); 
  translate(b.x, b.y, b.z);
  noFill();
  stroke(0);
  sphere(4);
  popMatrix();

  pushMatrix(); 
  translate(c.x, c.y, c.z);
  noFill();
  stroke(0);
  sphere(4);
  popMatrix();

  pushMatrix(); 
  translate(middle.x, middle.y, middle.z);
  noFill();
  stroke(127);
  sphere(4);
  popMatrix();
}
2 Likes

Hello @paulstgeorge,

This will display a line between two vectors but not return the vector:

//https://github.com/processing/processing4/blob/main/core/src/processing/core/PApplet.java#L12888

PVector a, b, c, ax, v;

float x, y, z;

void setup() 
 {
 size(400, 400, P3D);

 a = new PVector(0, 0, 0);
 b = new PVector(100, 100, 50);
 c = new PVector(100, -100, -50);
 ax = new PVector(0, 0, 0);
 v = new PVector(0, 0, 0);
 }

void draw() 
 {
 background(255);

 float angleBetween = PVector.angleBetween(b, c);
 float angle = map(mouseX, 0, width, 0, angleBetween);

 translate(width/2, height/2);  // move (0, 0, 0) to centre of window
 rotateY(frameCount%360*(TAU/360)); // This will mess with modelX below

 stroke(0);
 strokeWeight(2);

 line(a.x, a.y, a.z, b.x, b.y, b.z);
 line(a.x, a.y, a.z, c.x, c.y, c.z);
 
 ax = b.cross(c).normalize(); //normalize may not be needed

 // Rotates a line about an axis
 stroke(255, 128, 0);
 pushMatrix();
 rotV(angle, ax);
 line(a.x, a.y, a.z, b.x, b.y, b.z);
 popMatrix();
 }
 
void rotV(float angle, PVector axis) 
 {
 rotate(angle, axis.x, axis.y, axis.z);
 }

References:

This gem is not in the on-line references:
https://github.com/processing/processing4/blob/main/core/src/processing/core/PApplet.java#L12888

:)

A gem indeed. Well found @glv
I actually want the vector. This is currently rotating the display of line AB. Isn’t there one or two lines of code we can add to the sketch below to find the new vector?

PVector a, b, c, ax;

float x, y, z, angle;

void setup()
{
  size(400, 400, P3D);

  a = new PVector(0, 0, 0);
  b = new PVector(100, 100, 50);
  c = new PVector(100, -100, -50);
  ax = new PVector(0, 0, 0);
  angle = radians(60);
}

void draw()
{
  background(255);
  translate(width/2, height/2);  // move (0, 0, 0) to centre of window
  stroke(0);
  strokeWeight(2);

  line(a.x, a.y, a.z, b.x, b.y, b.z);  // static line ab
  line(a.x, a.y, a.z, c.x, c.y, c.z);  // static line ac

  //step 1
  ax = b.cross(c);
  
  // Rotates a line about an axis
  stroke(255, 128, 0);
  pushMatrix();
  rotV(angle, ax); //step 2
  line(a.x, a.y, a.z, b.x, b.y, b.z);  // the line ab rotated in display
  popMatrix();

  // a blob for identifying vector points
  pushMatrix();
  translate(a.x, a.y, a.z);
  noFill();
  stroke(127);
  //sphere(4);
  popMatrix();
}

void rotV(float angle, PVector axis)   //step 3
{
  rotate(angle, axis.x, axis.y, axis.z);
}

Hello again!

I do not have a simple solution… and very little time these days to explore.

A search revealed some possible solutions for consideration:

I have used your initial approach in the past for drawing arcs on a sphere.

:)

Hello again!

If you are using transformations you can use get the x, y, z coordinates with the modelX(), modelY(), modelZ() functions.
See references for details.

Example:

PVector a, b, c, ax;
float x, y, z, angle;

void setup()
  {
  size(400, 400, P3D);

  a = new PVector(0, 0, 0);
  b = new PVector(100, 100, 60);
  c = new PVector(100, -100, -60);
  ax = new PVector(0, 0, 0);
  angle = radians(60);
  }

void draw()
  {
  background(255);
  translate(width/2, height/2);  // move (0, 0, 0) to center of window
  
  ax = b.cross(c);
 
 // Just for fun! Can uncomment these to animate!
  //float aY = (frameCount%360)*(TAU/360); // One degree per frame
  //rotateY(aY);
  //angle = PVector.angleBetween(b, c)/2*sin(aY) + PVector.angleBetween(b, c)/2;
  
  stroke(0);
  strokeWeight(3);
  line(a.x, a.y, a.z, b.x, b.y, b.z);  // static line ab
  line(a.x, a.y, a.z, c.x, c.y, c.z);  // static line ac
  
  // Rotates a line about an axis and returns PVector
 pushMatrix();
  resetMatrix(); //otherwise this includes the transformations above
  rotV(angle, ax);
  PVector v = new PVector(modelX(b.x, b.y, b.z), 
                          modelY(b.x, b.y, b.z), 
                          modelZ(b.x, b.y, b.z));
  println(v);
 popMatrix();
  
  stroke(255, 0, 0);
  line(a.x, a.y, a.z, v.x, v.y, v.z);  // the line ab rotated in display
  }

void rotV(float angle, PVector axis)
  {
  rotate(angle, axis.x, axis.y, axis.z);
  }

@paulstgeorge Consider refactoring into a single function to rotate PVector and return PVector.

:)

1 Like

Maybe I’m misunderstanding the question, but it sounds like you want to do vector addition.

In your example a is at the origin right, so you’d just be adding b and c

1 Like

Yes @corvanessen , ‘addition’ works very well.

but it bisects the angle

How do I use ‘add’ to choose the ratio of division between the two lines?

so, for example if there were 90° between AC and AB how would I find the line AM that is 30° from AC and 60° from AD.

Adding the two vectors gives me 45° in this example.

1 Like

Solved! I just add the two vectors, but I do not give them equal weight. First multiply each of the two vectors according to the desired ratio. The full sketch is below, here is the pertinent detail:

  b2 = b.copy();
  b2.mult(sin(angle));
  c2 = c.copy();
  c2.mult(cos(angle));

  v3 = PVector.add(b2, c2);
  v3.normalize();
  v3.mult(m);

Sketch:

PVector a, b, c, b2, c2, v3;

float m, dangle, angle;


void setup() {
  size(800, 800, P3D);

  a = new PVector(0, 0, 0);
  b = new PVector(100, 100, 0);
  c = new PVector(100, -100, 0);

  m = PVector.dist(a, b);
}

void draw() {
  background(255);
  strokeWeight(1);

  textSize(64);

  dangle = 90 * (mouseY/float(height)); // 0.0 at top, 90.0 at bottom
  angle = dangle * PI /180; // radians


  translate(width/2, height/2);  // move (0, 0, 0) to centre of window

  stroke(0, 0, 0);

  line(a.x, a.y, a.z, b.x, b.y, b.z);
  line(a.x, a.y, a.z, c.x, c.y, c.z);

  b2 = b.copy();
  b2.mult(sin(angle));
  c2 = c.copy();
  c2.mult(cos(angle));

  v3 = PVector.add(b2, c2);
  v3.normalize();
  v3.mult(m);

  line(a.x, a.y, a.z, v3.x, v3.y, v3.z);

  pushMatrix();
  translate(v3.x, v3.y, v3.z);
  noFill();
  stroke(127, 0, 0);
  sphere(4);
  popMatrix();

  pushMatrix(); // move (0, 0, 0) back to centre of window
  translate(a.x, a.y, a.z);
  noFill();
  stroke(0);
  sphere(4);
  popMatrix();

  pushMatrix();
  translate(b.x, b.y, b.z);
  noFill();
  stroke(0);
  sphere(4);
  popMatrix();

  pushMatrix();
  translate(c.x, c.y, c.z);
  noFill();
  stroke(0);
  sphere(4);
  popMatrix();

  fill(0, 408, 612, 204);
  text(int(dangle), 40, 360);
}
2 Likes

This topic was engaging!

Another twist on this that was inspired by the discussions:

PVector a, b, c, b2, c2, v3;

float m, dangle, angle;

void setup() 
  {
  size(500, 500, P3D);

  a = new PVector(0, 0, 0);
  b = new PVector(100, 140, 50);
  c = new PVector(100, -100, -50);

  m = PVector.dist(a, b);
  textSize(64);
  }

void draw() 
  {
  background(0);

  float ratio = float(mouseY)/height; 
  println(ratio);
 push();
  translate(width/2, height/2);  // move (0, 0, 0) to centre of window
  rotateY((frameCount%360)*(TAU/360));

  stroke(128);
  strokeWeight(2);
  line(a.x, a.y, a.z, b.x, b.y, b.z);
  line(a.x, a.y, a.z, c.x, c.y, c.z);

  //b2 = b.copy();
  //b2.mult(sin(angle));
  //c2 = c.copy();
  //c2.mult(cos(angle));
  
  //Replaces above
  b2 = b.copy();
  b2.mult(ratio);
  c2 = c.copy();
  c2.mult(1-ratio);
  println(b2, c2);
  
  strokeWeight(5);
  stroke(255, 0, 0);
  line(a.x, a.y, a.z, b2.x, b2.y, b2.z);
  stroke(0, 255, 0);
  line(a.x, a.y, a.z, c2.x, c2.y, c2.z);

  v3 = PVector.add(b2, c2);
  //v3.normalize();
  //v3.mult(m);
  
  stroke(255, 255, 0);
  line(a.x, a.y, a.z, v3.x, v3.y, v3.z);
 pop();

  fill(0, 408, 612, 204);
  text( (int) degrees(PVector.angleBetween(b2, v3)), 40, height-40 );
  }

:)

1 Like

@glv I realise that it is not solved. As @corvanessen points out, the solution only works when a is at the origin.

I have been trying and failing to make the solution more general. Can you help?

Everything the same, still 90° between the two lines but the point a can be anywhere.