Loading...
Logo
Processing Forum
I'm trying to draw an arrow from the edge of a circle to the edge of another circle.
 
The only data I store is the coordinates of the two circles, and using the line function to join them up, and triangle to draw the arrow head. 

But I can't find a way to start the line at the edge of the circle and get it to stop at the edge of the other node, and be able to drag the circles round without the arrows going wrong.

Replies(6)

Might not work so well if the circles are close (intersecting)...

Copy code
  1. int cx, cy, cr, kx, ky, kr;

  2. void setup() {
  3.   size(400, 400);
  4.   cx = width/4;
  5.   cy = height/4;
  6.   cr = 20;
  7.   kx = 3 * width/4;
  8.   ky = 3 * height/4;
  9.   kr = 30;
  10.   smooth();
  11.   noFill();
  12. }

  13. void draw() {
  14.   background(0);
  15.   if ( mousePressed ) {
  16.     cx = mouseX;
  17.     cy = mouseY;
  18.   }
  19.   if ( keyPressed ) {
  20.     kx = mouseX;
  21.     ky = mouseY;
  22.   }
  23.   stroke(255, 0, 0);
  24.   ellipse(cx, cy, 2*cr, 2*cr);
  25.   stroke(0, 0, 255);
  26.   ellipse(kx, ky, 2*kr, 2*kr);
  27.   PVector p = new PVector( kx-cx, ky-cy, 0);
  28.   PVector q = new PVector( kx-cx, ky-cy, 0);
  29.   p.limit(cr);
  30.   q.limit(dist(cx, cy, kx, ky)-kr);
  31.   stroke(0, 255, 255);
  32.   line(cx+p.x, cy+p.y, cx+q.x, cy+q.y );
  33.   pushMatrix();
  34.   translate( cx+q.x, cy+q.y );
  35.   stroke(255);
  36.   p.limit(20);
  37.   rotate(radians(30));
  38.   line(0, 0, -p.x, -p.y);
  39.   rotate(radians(-60));
  40.   line(0, 0, -p.x, -p.y);
  41.   popMatrix();
  42. }
Could you explain what's going on here, so I know which lines are doing what?

Thanks.
1: Define the six variables used to track the two circles.
5-10: Give them initial values.
17-20: Move the first circle to the mouse's position if a mouse button is pressed.
21-24: Move the second circle to the mouse's position if a keyboard key is pressed.
25-26: Draw the first circle.
27-28: Draw the second circle.
29-30: Define two similar vectors that point from the center of the first circle to the center of the second circle.
31: Limit the length of the first of these vectors to the radius of the first circle, so that, if placed at the center of the first circle, it ends at a point on the first circle that is between the two centers of the circles.
31: Limit the length of the second vector to it's own length, minus the radius of the second circle, so that, if placed at the center of the first circle, it ends at a point on the second circle that is between the two centers of the circles.
33-34: placing both vectors at the center of the first circle, draw a line between their two end points.
Now we just need to draw the two lines for the arrow head.
36: Recenter the coordinate system around the point on the second circle.
The vector p points from the first circle to the second, so -p points from the second to the first.
38: Limit p to a fixed length of 20 pixels.
39: Rotate the coordinate system a bits so that p now only sort of points from one circle to the other.
40: Use p to draw one of the arrow head lines.
41: Rotate the coordinate system a bits in the other direction so that p now only sort of points from one circle to the other, but in the other direction.
42: Use p to draw the other one of the arrow head lines.
The code draws the arrow you want and the code is fairly self-explantory. I leave it to you to drag the circle.

Copy code
    Copy code
    1. float x0, y0, r0;
    2. float x1, y1, r1;
    3. int fc0, fc1;
    4. int sc0, sc1;
    5. float th;
    6. int arrowCol;

    7. public void setup() {
    8.   size(300, 300);
    9.   ellipseMode(CENTER);
    10.   // Circle 0 posuition and size
    11.   x0 = 50;
    12.   y0 = 90;
    13.   r0 = 30;
    14.   // Circle 0 colors
    15.   fc0 = color(255, 128, 128);
    16.   sc0 = color(200, 64, 64);
    17.   // Circle 1 posuition and size
    18.   x1 = 220;
    19.   y1 = 190;
    20.   r1 = 50;
    21.   // Circle 0 colors
    22.   fc1 = color(128, 128, 255);
    23.   sc1 = color(64, 64, 200);
    24.   th = 2.0;
    25.   arrowCol = color(0, 64, 0);
    26. }

    27. public void draw() {
    28.   background(230);
    29.   drawCircle(x0, y0, r0, fc0, sc0);
    30.   drawCircle(x1, y1, r1, fc1, sc1);
    31.   drawArrow(x0, y0, r0, x1, y1, r1, th, arrowCol);
    32. }

    33. public void drawCircle(float cx, float cy, float rad, int fc, int sc) {
    34.   fill(fc);
    35.   stroke(sc);
    36.   strokeWeight(2);
    37.   ellipse(cx, cy, 2*rad, 2*rad);
    38. }

    39. public void drawArrow(float cx0, float cy0, float rad0, float cx1, float cy1, float rad1, float thickness, int ac) {
    40.   // These will be the points on the circles circumference
    41.   float px0, py0, px1, py1;
    42.   // the angle of the line joining centre of circle c0 to c1
    43.   float angle = atan2(cy1-cy0, cx1-cx0);
    44.   px0 = cx0 + rad0 * cos(angle);
    45.   py0 = cy0 + rad0 * sin(angle);
    46.   px1 = cx1 + rad1 * cos(angle + PI);
    47.   py1 = cy1 + rad1 * sin(angle + PI);
    48.   // Calculate the arrow length and head size
    49.   float arrowLength = sqrt((px1-px0)*(px1-px0) +(py1-py0)*(py1-py0));
    50.   float arrowSize = 2.5 * th;
    51.   // Setup arrow colours and thickness
    52.   strokeWeight(th);
    53.   stroke(ac);
    54.   fill(ac);
    55.   // Set the drawing matrix as if the arrow starts
    56.   // at the origin and is along the x-axis
    57.   pushMatrix();
    58.   translate(px0, py0);
    59.   rotate(angle);
    60.   // Draw the arrow shafte
    61.   line(0, 0, arrowLength, 0);
    62.   //  draw the arrowhead
    63.   beginShape(TRIANGLES);
    64.   vertex(arrowLength, 0); // point
    65.   vertex(arrowLength - arrowSize, -arrowSize);
    66.   vertex(arrowLength - arrowSize, arrowSize);
    67.   endShape();
    68.   popMatrix();
    69. }

    This code doesn't work.

    You're putting the x co-ordinate as both the x and y co-ordinate when running the drawCircle and drawArrow functions. Even when the y-coord is fixed it doesn't put the arrows in the correct place.

    When I add the option to move the co-ordinates of the circles, the arrow looks even weirder, I think it's just that angle that it seems to work properly.
    Sorry about that - just demonstartes the problem of copy and pasting code and then not testing it properly.

    I have corrected and tested the code - the arrow is solved too.