Orthogonal projection of a point onto a line?

edited March 2016 in How To...

I have a line segment and a circle in my processing sketch. I want the center of the circle, point q, to find the closest point, p, on the line segment and the circle will move towards it. I'm not quite sure how to code this, so any suggestions would be great! Thanks!

Tagged:

Answers

  • Draw us a picture

  • Answer ✓
    float x1,y1,x2,y2;
    float cx,cy;
    float x4,y4;
    
    void setup()
    {
       size(600,600);
    }
    
    void init()
    {
       x1 = (int)random(100,500);
       y1 = (int)random(100,500);
       x2 = (int)random(100,500);
       y2 = (int)random(100,500);
       cx = (int)random(100,500);
       cy = (int)random(100,500);   
    }   
    
    void draw()
    {
      background(60);
      init();
      stroke(220);
      line(x1,y1,x2,y2);
      noFill();
      ellipse(cx,cy,50,50);
      noStroke();
      fill(220,20,20);
      ellipse(cx,cy,8,8);
      // calculate the point
      float k = ((y2-y1) * (cx-x1) - (x2-x1) * (cy-y1)) / ((y2-y1)*(y2-y1) + (x2-x1)*(x2-x1));
      float x4 = cx - k * (y2-y1);
      float y4 = cy + k * (x2-x1);
      fill(20,20,220);
      ellipse(x4,y4, 8,8);
      stroke(0);
      line(cx,cy,x4,y4);
      noLoop();
    }
    
    void keyPressed() { loop(); }  
    

    Two hints:
    1) the calculated point can be outside the line
    2) check division by zero

  • Have a look at pages 7 & 8 of my Geometry Cookbook. It provides the code to solve this problem and many others to boot :)

  • that book has a lot of great examples in there, thanks!

  • Would anyone have any suggestions of how we could show the circle moving towards that point on the line segment?

  • Ceaser, what do you mean?

    I pushed the projection code here - https://openprocessing.org/sketch/413945.

  • edited March 2017

    @cameo your solution is very good
    I'we made a function zoning on on the closest point along a "line spline" by O(log n) comparisons of dot products.
    I think ill make it break the loop and do your calculation when the closest segment is found.

    @causar

    float x1,y1,x2,y2;
    float cx,cy, ccx,ccy;
    float x4,y4;
    boolean snap=false;
    void setup()
    {
       size(600,600);
       init();
    }
    void init()
    {
      x1 = (int)random(100,500);
      y1 = (int)random(100,500);
      x2 = (int)random(100,500);
      y2 = (int)random(100,500);
      ccx = cx = (int)random(100,500);
      ccy = cy = (int)random(100,500); 
       // calculate the point
      float k = ((y2-y1) * (cx-x1) - (x2-x1) * (cy-y1)) / ((y2-y1)*(y2-y1) + (x2-x1)*(x2-x1));
      x4 = cx - k * (y2-y1);
      y4 = cy + k * (x2-x1);
      if(snap){
      x4=constrain(x4,min(x1,x2),max(x1,x2));
      y4=constrain(y4,min(y1,y2),max(y1,y2)); 
      }
    }   
    void draw()
    {
      background(60);
      stroke(220);
      line(x1,y1,x2,y2);
      noFill();
      ccx=lerp(cx,x4,(frameCount%100)/100.0);
      ccy=lerp(cy,y4,(frameCount%100)/100.0);
      ellipse(ccx,ccy,50,50);
      noStroke();
      fill(220,20,20);
      ellipse(cx,cy,8,8);
      fill(20,220,20);
      ellipse(ccx,ccy,8,8);
      fill(20,20,220);
      ellipse(x4,y4, 8,8);
      stroke(0);
      line(cx,cy,x4,y4);
    }
    void keyPressed() { init(); }  
    
Sign In or Register to comment.