Search code examples
pythonmathline

How to extend a line segment in both directions


I've been stuck on this annoying problems for eons. I'm trying to write code so that I can scale a line segment meaning if the amount that I was to scale by(for example) is 2 and the current length of the line is 33 it will increase the entire length to 67. Meaning I add half to the beginning and half to the end... new front ---a--------b--- new back... But I'm having trouble translating it into code. Here is an example of the code.. The endpoints method should return the endpoints in a tuple such as (p1, p2)

from point import Point
import math

class Line:
def __init__(self,aPoint=Point(), bPoint=Point()):
    self.firstPoint = aPoint
    self.secondPoint = bPoint

def getEndPoints(self):
    return (self.firstPoint, self.secondPoint)

def scale(self,factor):
    if factor < 1:
       x1 = self.firstPoint.x +(self.secondPoint.x - self.firstPoint.x) * (factor)
       x2 = self.secondPoint.x +(self.firstPoint.x  - self.secondPoint.x) * (factor)
       print(str(x1))
       y1 = self.firstPoint.y +(self.secondPoint.y - self.firstPoint.y) * (factor)
       y2 = self.secondPoint.y +(self.firstPoint.y  - self.secondPoint.y) * (factor)
    else:
       x1 = -(self.firstPoint.x +(self.secondPoint.x - self.firstPoint.x) * (factor))
       x2 = -(self.secondPoint.x +(self.firstPoint.x  - self.secondPoint.x) * (factor))
       y1 = self.firstPoint.y +(self.secondPoint.y - self.firstPoint.y) * (factor)
       y2  = self.secondPoint.y +(self.firstPoint.y  - self.secondPoint.y) * (factor)
    self.firstPoint = Point(x1, y1)
    self.secondPoint = Point(x2, y2)

if __name__ == "__main__":
    p1 = Point(5,5)
    p2 = Point(20,35)
    l1 = Line(p1,p2)
    l1.scale(2)
    p5 = Point(-2.5,-10)
    p6 = Point(27.5,50)
    assert l1.getEndPoints() == (p5,p6)

These tests are not working correctly but the above are.. I'm getting a(5.0, 5.0) and b(20.0, 35.0)


    l1.scale(0.5)

    p5 = Point(8.75,12.5)
    p6 = Point(16.25,27.5)

class Point:
'''Point class represents and manipulates
x,y coordinates.'''

def __init__(self,x=0,y=0):
    '''Create a new point with default
    x,y coordinates at 0,0.'''
    self.x = x
    self.y = y

def distanceTo(self,aPoint):
    return ((self.x-aPoint.x) ** 2 + (self.y-aPoint.y) ** 2)** .5 

Solution

  • not sure if I get it right but

    1. use linear interpolation (parametric line equation)

      You got line defined by endpoints p0,p1 in form of vectors so any point on it is defined as:

      p(t)=p0+(p1-p0)*t
      

      where p(t) is the point (vector) and t is scalar parameter in range

      t=<0.0,1.0>
      

      if you do not know the vector math then rewrite it to scalars

      x(t)=x0+(x1-x0)*t
      y(t)=y0+(y1-y0)*t
      

      so if t=0 then you get the point p0 and if t=1 then you get the point p1

    2. Now just rescale the t range

      so you have scale s

      t0=0.5-(0.5*s)` ... move from half of line by scale towards p0
      t1=0.5+(0.5*s)` ... move from half of line by scale towards p1
      

      so new endpoints are

      q0=p0+(p1-p0)*t0
      q1=p0+(p1-p0)*t1
      

    [edit1] I see it like this

    def scale(self,factor):
     t0=0.5*(1.0-factor)
     t1=0.5*(1.0+factor)
     x1 = self.firstPoint.x +(self.secondPoint.x - self.firstPoint.x) * t0
     y1 = self.firstPoint.y +(self.secondPoint.y - self.firstPoint.y) * t0
     x2 = self.firstPoint.x +(self.secondPoint.x - self.firstPoint.x) * t1
     y2 = self.firstPoint.y +(self.secondPoint.y - self.firstPoint.y) * t1
     self.firstPoint = Point(x1, y1)
     self.secondPoint = Point(x2, y2)
    

    Take in mind I do not code in python so handle with prejudice ...