Search code examples
javageometryawtlinejava-2d

How to create a line whose head is some distance from its end - java / awt


I have points

A(x1, y1)

B(x2, y2)

I need to draw the arrow head of this line but not on the end. It must be some distance from the end. What way would this thing do?

I have:

    ---------------------->

I need:

    ----------------->-----

See image:

And this is with angle:

Result:

Thank you guys for helping. This is for another.

Let's create main function and draw a line and arrowhead:

   private void drawLineWithArrowHead(Point from, Point to, Graphics2D graphics){
       Polygon arrowHead = new Polygon();
       arrowHead.addPoint( 0,6);
       arrowHead.addPoint( -6, -6);
       arrowHead.addPoint( 6,-6);int y1,y2,x1,x2;
       x1=from.getPosX();
       y1=from.getPosY();
       x2=to.getPosX();
       y2=to.getPosY();
       Line2D.Double line = new Line2D.Double(x1,y1,x2,y2);
       graphics.draw(line);

Lets load old affine transform and get new from line:

   AffineTransform tx, old_tx = graphics.getTransform();
   tx = calcAffineTransformation(line);

Some math:

   double dx = (x2-x1), dy = (y2-y1);
   double len = Math.sqrt(dx*dx + dy*dy);
   double udx = dx/len, udy = dy/len;
   double cordx = x2  - (size-5) * udx, cordy = y2  - (size-5) * udy;
   double r_cordx = x2  - (size+3) * udx, r_cordy = y2  - (size+3) * udy;

And now place that arrowhead:

   tx.setToIdentity(); // null transform to origin
   double angle = Math.atan2(line.y2 - line.y1, line.x2 - line.x1);
   !! important !! must firstly translate secondly rotate
   tx.translate( cordx,  cordy ); // setup of cord of arrowhead
   tx.rotate((angle - Math.PI / 2d)); // head rotate
   graphics.setTransform(tx); // set transform for graphics
   graphics.fill(arrowHead);
   graphics.setTransform(old_tx); // get original transform back

CalcAffineTransformation function to get line position and rotate:

   private AffineTransform calcAffineTransformation(Line2D.Double line) {
       AffineTransform transformation = new AffineTransform();
       transformation.setToIdentity();
       double angle = Math.atan2(line.y2 - line.y1, line.x2 - line.x1);
       transformation.translate(line.x2, line.y2);
       transformation.rotate((angle - Math.PI / 2d));
       return transformation;
   }

Thats all. And this is what code do:


Solution

  • Your line has direction vector

     dx, dy = (x2 - x1), (y2 - y1)
    

    It's length is

     len = sqrt(dx*dx + dy*dy)
    

    Unit direction vector is

    udx, udy = dx/len, dy/len
    

    Point at distance D from the end (this is head point of arrow, as I understand):

    x3, y3 = x2 - D * udx, y2 - D * udy
    

    do you need something else to build arrow?