title: Calculate a point along the line A-B at a given distance from A
body: <p>I'm going quite mad trying to calculate the point along the given line A-B, at a given distance from A, so that I can &quot;draw&quot; the line between two given points. It sounded simple enough at the outset, but I can't seem to get it right. Worse still, I don't understand where I've gone wrong. Geometry (and math in general) is NOT my strong suite.</p>
  <p>I have read similar questions and there answers on SO. In fact I lifted my current implementation of CalculatePoint function directly from <em>Mads Elvheim</em>'s answer to: <a href="https://stackoverflow.com/questions/1800138/given-a-start-and-end-point-and-a-distance-calculate-a-point-along-a-line">Given a start and end point, and a distance, calculate a point along a line</a> (plus a correction in a later comment - if I understand him correctly) because my indepedent attempts to solve the problem were getting me nowhere, except a first class express ticket frusterpationland.</p>
  <p>Here's my <strong>UPDATED</strong> code (please see the EDIT notes a bottom of post):</p>
  <pre><code>using System;
  using System.Drawing;
  using System.Windows.Forms;
  
  namespace DrawLines
  {
      public class MainForm : Form
      {
          // =====================================================================
          // Here's the part I'm having trouble with. I don't really understand
          // how this is suposed to work, so I can't seem to get it right!
          // ---------------------------------------------------------------------
  
          // A &quot;local indirector&quot; - Just so I don't have go down and edit the 
          // actual call everytime this bluddy thing changes names.
          private Point CalculatePoint(Point a, Point b, int distance) {
              return CalculatePoint_ByAgentFire(a, b, distance);
          }
  
          #region CalculatePoint_ByAgentFire
          //AgentFire: Better approach (you can rename the struct if you need):
          struct Vector2
          {
              public readonly double X;
              public readonly double Y;
              public Vector2(double x, double y) {
                  this.X = x;
                  this.Y = y;
              }
              public static Vector2 operator -(Vector2 a, Vector2 b) {
                  return new Vector2(b.X - a.X, b.Y - a.Y);
              }
              public static Vector2 operator *(Vector2 a, double d) {
                  return new Vector2(a.X * d, a.Y * d);
              }
              public override string ToString() {
                  return string.Format(&quot;[{0}, {1}]&quot;, X, Y);
              }
          }
          // For getting the midpoint you just need to do the (a - b) * d action:
          //static void Main(string[] args)
          //{
          //    Vector2 a = new Vector2(1, 1);
          //    Vector2 b = new Vector2(3, 1);
          //    float distance = 0.5f; // From 0.0 to 1.0.
          //    Vector2 c = (a - b) * distance;
          //    Console.WriteLine(c);
          //}
          private Point CalculatePoint_ByAgentFire(Point a, Point b, int distance) {
              var vA = new Vector2(a.X, a.Y);
              var vB = new Vector2(b.X, b.Y);
              double lengthOfHypotenuse = LengthOfHypotenuseAsDouble(a,b);
              double portionOfDistanceFromAtoB = distance / lengthOfHypotenuse;
              var vC = (vA - vB) * portionOfDistanceFromAtoB;
              Console.WriteLine(&quot;vC=&quot;+vC);
              return new Point((int)(vC.X+0.5), (int)(vC.Y+0.5));
          }
          // Returns the length of the hypotenuse rounded to an integer, using
          // Pythagoras' Theorem for right angle triangles: The length of the
          // hypotenuse equals the sum of the square of the other two sides.
          // Ergo: h = Sqrt(a*a + b*b)
          private double LengthOfHypotenuseAsDouble(Point a, Point b) {
              double aSq = Math.Pow(Math.Abs(a.X - b.X), 2); // horizontal length squared
              double bSq = Math.Pow(Math.Abs(b.Y - b.Y), 2); // vertical length  squared
              return Math.Sqrt(aSq + bSq); // length of the hypotenuse
          }
  
          #endregion
  
          //dbaseman: I thought something looked strange about the formula ... the question 
          //you linked was how to get the point at a distance after B, whereas you want the
          //distance after A. This should give you the right answer, the start point plus 
          //distance in the vector direction.
          //
          // Didn't work as per: http://s1264.photobucket.com/albums/jj496/corlettk/?action=view&amp;current=DrawLinesAB-broken_zps069161e9.jpg
          //
          private Point CalculatePoint_ByDbaseman(Point a, Point b, int distance) {
              // a. calculate the vector from a to b:
              double vectorX = b.X - a.X;
              double vectorY = b.Y - a.Y;
              // b. calculate the length:
              double magnitude = Math.Sqrt(vectorX * vectorX + vectorY * vectorY);
              // c. normalize the vector to unit length:
              vectorX /= magnitude;
              vectorY /= magnitude;
              // d. calculate and Draw the new vector, which is x1y1 + vxvy * (mag + distance).
              return new Point(
                  (int)((double)a.X + vectorX * distance)     // x = col
                , (int)((double)a.Y + vectorY * distance)     // y = row
              );
          }
  
          // MBo: Try to remove 'magnitude' term in the parentheses both for X and for Y expressions.
          //
          // Didn't work as per: http://s1264.photobucket.com/albums/jj496/corlettk/?action=view&amp;current=DrawLinesAB-broken_zps069161e9.jpg
          //
          //private Point CalculatePoint_ByMBo(Point a, Point b, int distance) {
          //    // a. calculate the vector from a to b:
          //    double vectorX = b.X - a.X;
          //    double vectorY = b.Y - a.Y;
          //    // b. calculate the length:
          //    double magnitude = Math.Sqrt(vectorX * vectorX + vectorY * vectorY);
          //    // c. normalize the vector to unit length:
          //    vectorX /= magnitude;
          //    vectorY /= magnitude;
          //    // d. calculate and Draw the new vector, which is x1y1 + vxvy * (mag + distance).
          //    return new Point(
          //        (int)(  ((double)a.X + vectorX * distance)  +  0.5  )
          //      , (int)(  ((double)a.X + vectorX * distance)  +  0.5  )
          //    );
          //}
  
          // Didn't work
          //private Point CalculatePoint_ByUser1556110(Point a, Point b, int distance) {
          //    Double magnitude = Math.Sqrt(Math.Pow(b.Y - a.Y, 2) + Math.Pow(b.X - a.X, 2));
          //    return new Point(
          //        (int)(a.X + distance * (b.X - a.X) / magnitude + 0.5)
          //      , (int)(a.Y + distance * (b.Y - a.Y) / magnitude + 0.5)
          //    );
          //}
  
          // didn't work
          //private static Point CalculatePoint_ByCadairIdris(Point a, Point b, int distance) {
          //    // a. calculate the vector from a to b:
          //    double vectorX = b.X - a.X;
          //    double vectorY = b.Y - a.Y;
          //    // b. calculate the proportion of hypotenuse
          //    double factor = distance / Math.Sqrt(vectorX*vectorX + vectorY*vectorY);
          //    // c. factor the lengths
          //    vectorX *= factor;
          //    vectorY *= factor;
          //    // d. calculate and Draw the new vector,
          //    return new Point((int)(a.X + vectorX), (int)(a.Y + vectorY));
          //}
  
          // Returns a point along the line A-B at the given distance from A
          // based on Mads Elvheim's answer to:
          // https://stackoverflow.com/questions/1800138/given-a-start-and-end-point-and-a-distance-calculate-a-point-along-a-line
          private Point MyCalculatePoint(Point a, Point b, int distance) {
              // a. calculate the vector from o to g:
              double vectorX = b.X - a.X;
              double vectorY = b.Y - a.Y;
              // b. calculate the length:
              double magnitude = Math.Sqrt(vectorX * vectorX + vectorY * vectorY);
              // c. normalize the vector to unit length:
              vectorX /= magnitude;
              vectorY /= magnitude;
              // d. calculate and Draw the new vector, which is x1y1 + vxvy * (mag + distance).
              return new Point(
                  (int)(((double)a.X + vectorX * (magnitude + distance)) + 0.5) // x = col
                , (int)(((double)a.Y + vectorY * (magnitude + distance)) + 0.5) // y = row
              );
          }
  
          // =====================================================================
  
          private const int CELL_SIZE = 4; // width and height of each &quot;cell&quot; in the bitmap.
  
          private readonly Bitmap _bitmap; // to draw on (displayed in picBox1).
          private readonly Graphics _graphics; // to draw with.
  
          // actual points on _theLineString are painted red.
          private static readonly SolidBrush _thePointBrush = new SolidBrush(Color.Red);
          // ... and are labeled in Red, Courier New, 12 point, Bold
          private static readonly SolidBrush _theLabelBrush = new SolidBrush(Color.Red);
          private static readonly Font _theLabelFont = new Font(&quot;Courier New&quot;, 12, FontStyle.Bold);
  
          // the interveening calculated cells on the lines between actaul points are painted Black.
          private static readonly SolidBrush _theLineBrush = new SolidBrush(Color.Black);
  
          // the points in my line-string.
          private static readonly Point[] _theLineString = new Point[] {
              //          x,   y
              new Point(170,  85), // A
              new Point( 85,  70), // B
              //new Point(209,  66), // C
              //new Point( 98, 120), // D
              //new Point(158,  19), // E
              //new Point(  2,  61), // F
              //new Point( 42, 177), // G
              //new Point(191, 146), // H
              //new Point( 25, 128), // I
              //new Point( 95,  24)  // J
          };
  
          public MainForm() {
              InitializeComponent();
              // initialise &quot;the graphics system&quot;.
              _bitmap = new Bitmap(picBox1.Width, picBox1.Height);
              _graphics = Graphics.FromImage(_bitmap);
              picBox1.Image = _bitmap;
          }
  
          #region actual drawing on the Grpahics
  
          private void DrawCell(int x, int y, Brush brush) {
              _graphics.FillRectangle(
                  brush
                , x * CELL_SIZE, y * CELL_SIZE    // x, y
                , CELL_SIZE, CELL_SIZE        // width, heigth
              );
          }
  
          private void DrawLabel(int x, int y, char c) {
              string s = c.ToString();
              _graphics.DrawString(
                  s, _theLabelFont, _theLabelBrush
                , x * CELL_SIZE + 5   // x
                , y * CELL_SIZE - 8   // y
              );
          }
  
          // ... there should be no mention of _graphics or CELL_SIZE below here ...
  
          #endregion
  
          #region draw points on form load
  
          private void MainForm_Load(object sender, EventArgs e) {
              DrawPoints();
          }
  
          // draws and labels each point in _theLineString
          private void DrawPoints() {
              char c = 'A'; // label text, as a char so we can increment it for each point.
              foreach ( Point p in _theLineString ) {
                  DrawCell(p.X, p.Y, _thePointBrush);
                  DrawLabel(p.X, p.Y, c++);
              }
          }
  
          #endregion
  
          #region DrawLines on button click
  
          private void btnDrawLines_Click(object sender, EventArgs e) {
              DrawLinesBetweenPointsInTheString();
          }
  
          // Draws &quot;the lines&quot; between the points in _theLineString.
          private void DrawLinesBetweenPointsInTheString() {
              int n = _theLineString.Length - 1; // one less line-segment than points
              for ( int i = 0; i &lt; n; ++i )
                  Draw(_theLineString[i], _theLineString[i + 1]);
              picBox1.Invalidate(); // tell the graphics system that the picture box needs to be repainted.
          }
  
          // Draws all the cells along the line from Point &quot;a&quot; to Point &quot;b&quot;.
          private void Draw(Point a, Point b) {
              int maxDistance = LengthOfHypotenuse(a, b);
              for ( int distance = 1; distance &lt; maxDistance; ++distance ) {
                  var point = CalculatePoint(a, b, distance);
                  DrawCell(point.X, point.X, _theLineBrush);
              }
          }
  
          // Returns the length of the hypotenuse rounded to an integer, using
          // Pythagoras' Theorem for right angle triangles: The length of the
          // hypotenuse equals the sum of the square of the other two sides.
          // Ergo: h = Sqrt(a*a + b*b)
          private int LengthOfHypotenuse(Point a, Point b) {
              double aSq = Math.Pow(Math.Abs(a.X - b.X), 2); // horizontal length squared
              double bSq = Math.Pow(Math.Abs(b.Y - b.Y), 2); // vertical length  squared
              return (int)(Math.Sqrt(aSq + bSq) + 0.5); // length of the hypotenuse
          }
  
          #endregion
  
          #region Windows Form Designer generated code
          /// &lt;summary&gt;
          /// Required method for Designer support - do not modify
          /// the contents of this method with the code editor.
          /// &lt;/summary&gt;
          private void InitializeComponent() {
              this.picBox1 = new System.Windows.Forms.PictureBox();
              this.btnDrawLines = new System.Windows.Forms.Button();
              ((System.ComponentModel.ISupportInitialize)(this.picBox1)).BeginInit();
              this.SuspendLayout();
              // 
              // picBox1
              // 
              this.picBox1.Dock = System.Windows.Forms.DockStyle.Fill;
              this.picBox1.Location = new System.Drawing.Point(0, 0);
              this.picBox1.Name = &quot;picBox1&quot;;
              this.picBox1.Size = new System.Drawing.Size(1000, 719);
              this.picBox1.TabIndex = 0;
              this.picBox1.TabStop = false;
              // 
              // btnDrawLines
              // 
              this.btnDrawLines.Location = new System.Drawing.Point(23, 24);
              this.btnDrawLines.Name = &quot;btnDrawLines&quot;;
              this.btnDrawLines.Size = new System.Drawing.Size(77, 23);
              this.btnDrawLines.TabIndex = 1;
              this.btnDrawLines.Text = &quot;Draw Lines&quot;;
              this.btnDrawLines.UseVisualStyleBackColor = true;
              this.btnDrawLines.Click += new System.EventHandler(this.btnDrawLines_Click);
              // 
              // MainForm
              // 
              this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
              this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
              this.ClientSize = new System.Drawing.Size(1000, 719);
              this.Controls.Add(this.btnDrawLines);
              this.Controls.Add(this.picBox1);
              this.Location = new System.Drawing.Point(10, 10);
              this.MinimumSize = new System.Drawing.Size(1016, 755);
              this.Name = &quot;MainForm&quot;;
              this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
              this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
              this.Text = &quot;Draw Lines on a Matrix.&quot;;
              this.Load += new System.EventHandler(this.MainForm_Load);
              ((System.ComponentModel.ISupportInitialize)(this.picBox1)).EndInit();
              this.ResumeLayout(false);
          }
  
          private System.Windows.Forms.PictureBox picBox1;
          private System.Windows.Forms.Button btnDrawLines;
          #endregion
      }
  
  }
  </code></pre>
  <p>Sorry if it's a bit long, but this an is <a href="http://sscce.org/" rel="nofollow noreferrer" title="SSCCE">SSCCE</a> exhumed from my real project, which is an implementation of the <a href="http://en.wikipedia.org/wiki/A*_search_algorithm" rel="nofollow noreferrer">A* shortest route algorithm</a> to run the <a href="http://cplus.about.com/od/programmingchallenges/a/challenge12.htm" rel="nofollow noreferrer">MazeOfBolton</a>... i.e. a maze runner.</p>
  <p>What I actually want to do is pre-calculate a &quot;fence&quot; (i.e. a buffered <a href="http://en.wikipedia.org/wiki/Minimum_bounding_rectangle" rel="nofollow noreferrer">MBR</a>) around two given points (origin and goal) in the maze (a matrix), such that all points within the &quot;fence&quot; are within a given distance from &quot;the straight line between the two points&quot;, in order to quickly eliminate the hundreds-of-thousands of possible paths which are heading away from the goal.</p>
  <p>Note that this programming challenge closed years ago, so there's no issue with &quot;competitive plagerism&quot; here. No this is not homework, in fact I'm a professional programmer... I'm just WAAAAY out of my comfort zone here, even with relatively simple geometry. Sigh.</p>
  <p>So... Please can anyone give me any pointers to help me get the CalculatePoint function to <strong>correctly</strong>: <em>Calculate a point along the line A-B at the given distance from A?</em></p>
  <p>Thanks in advance for your generosity... even in reading this far.</p>
  <p>Cheers. Keith.</p>
  <hr />
  <p><strong>EDIT:</strong> I just updated the posted source code becuase:</p>
  <p>(1) I just realised that it wasn't self contained. I forgot about the seperate MainForm.<strong>Designer</strong>.cs file, which I've appended to the bottom of the posted code.</p>
  <p>(2) The latest version includes what I've tried so far, with a photobucket link to a picture of what each failure looks like... and they're all the same. Huy? WTF?</p>
  <p>I suppose my problem may be elsewhere, like some funky windows form setting that was previously missed by everyone else because I forgot to post the designer-generated code... Except everythingelse (in my actual project) paints exactly where I expect it to, so why should a calculated point be any different. I don't know!?!?!? I'm pretty frustrated and I'm getting cranky, so I think I'll leave this for another day ;-)</p>
  <p>Goes to show how much we routinely underestimate how much effort it'll take to make a computer do ANYthing... even just draw a simple line... it's not even a curve, let alone a great circle or a transverse mercator or anything fancy... just a simple bluddy line!?!?!? ;-)</p>
  <h2>A BIG Thank You to everyone who posted!</h2>
  <p>Cheers again. Keith.</p>