Sunday, 11 November 2007

extending a line

This post is more of a math post really. I have to admit, my maths is not that great! I even bought the book "Mathmatics and Physics for Programmers" to help me out. When I used to work with Derek I had it easy with the maths really. The team had several good math brains with Matthew "Bayesian" Bayes probably topping the list of reputable mathematicians in the group. I was given the math on a plate and just had to code it up, most of the time. When I moved on from there found very little need for math, from GIS programming to server side Java my math usage went from daily to less than monthly at a guess.

So I was coding something on a little side project of mine and realised I had a need to "extend a line". Usually I would email my old colleague and friend David Waters, but decided to try and work this one out for myself. I had a flick through my math book I mentioned above and didn't find a direct solution to my problem. However, I did have a good read through the section on Vectors.

Given I had two points and a distance I needed to extend one of those points by, I realised that I needed the following components:
  • a vector (subtract point 1 from point 2)
  • the magnitude of the vector (i.e. the distance between two points, either my starting points or the origin and the vector)
Once I had the magnitude, I worked out what the difference was between the starting line length and the existing line length and worked out what percentage this was of the original line length. This gave me a value which I used to multiply the vector with. Once I had done that I simply added point 1 back on to my newly scaled up vector in order to give me my new end point.

The code looks like this:

/**
*
* @param p1
* the start of the line
* @param p2
* the end of the line to extend
* @param distance
* how far to extend the line by
* @return the line object
*/
private Line2D createAndExtendLine(Point2D p1, Point2D p2, int distance) {

double length = p1.distance(p2);

Point2D vec = new Point2D.Double(p2.getX() - p1.getX(), p2.getY()
- p1.getY());

double multiplier = (length + distance) / length;

Point2D p3 = new Point2D.Double((vec.getX() * multiplier) + p1.getX(),
(vec.getY() * multiplier) + p1.getY());

return new Line2D.Double(p1, p3);
}
It appears to work in my test cases, so I'm happy with it, but of course I'd love to hear from the math wizards if it could be better or simpler!

No comments: