【问题标题】:How to extend a line segment in both directions如何在两个方向上延伸线段
【发布时间】:2015-03-03 06:30:36
【问题描述】:

我被这个烦人的问题困扰了好久。我正在尝试编写代码,以便我可以缩放线段,这意味着如果我要缩放的量(例如)是 2 并且线的当前长度是 33,它将把整个长度增加到 67。我在开头加一半,在结尾加一半…… new front ---a--------b--- new back... 但是我在将其转换为代码时遇到了麻烦。这是代码示例。端点方法应以元组形式返回端点,例如 (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)

这些测试无法正常工作,但以上是.. 我得到 a(5.0, 5.0) 和 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 

【问题讨论】:

  • 你的 Line 类中的方法scale 不包含?请告诉我们你到目前为止做了什么
  • 我不认为你们明白我的要求。我想将点 a(5,5) 的线改为点 (20,35) 并将其向外缩放 2。这意味着我想将点 a 变成 (-2.5, -10) 点 b进入 (27.5, 50)。在长度上,我想分别把33.54变成67.08,但我不想只扩展b,我也想扩展a。
  • 嗯,就是这样,我的答案就是这样......
  • 您能用数学术语还是用我的代码来解释?

标签: python math line


【解决方案1】:

不确定我是否正确,但是

  1. 使用线性插值(参数线方程)

    您得到了由端点p0,p1 以向量形式定义的线,因此其上的任何点都定义为:

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

    其中p(t) 是点(向量),t 是范围内的标量参数

    t=<0.0,1.0>
    

    如果您不知道向量数学,则将其重写为标量

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

    所以如果t=0 那么你得到了p0 的观点,如果t=1 那么你得到了p1 的观点

  2. 现在只需重新调整t 范围

    所以你有规模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
    

    所以新的端点是

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

[edit1] 我是这样看的

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)

请记住,我不会在 python 中编写代码,所以要带着偏见来处理......

【讨论】:

  • 我不认为你们明白我的要求。我想将点 a(5,5) 的线改为点 (20,35) 并将其向外缩放 2。这意味着我想将点 a 变为 (-2.5, -10) 点和点 b进入 (27.5, 50)。在长度方面,我想分别把33.54变成67.08,但我不想只扩展b,我也想扩展a。
  • @Crunch 如果您尝试计算示例的值,那么您将看到您得到的正是您想要的。 s=2 , t0=-0.5 , t1=+1.5 ... so x0=5+(20-5)*(-0.5)=2.5 .... t 是 [线长] 中从起点开始的长度
  • 这会反过来吗?因为似乎当数字小于 1 点时,a(5,5) 缩放 2 后为 (-2.5, -10) 变为 (8.75, 12.5) 缩放 0.5
  • @Crunch 我在之前的评论中遗漏了负号(结果是粗略的 -2.5 :))如果您按 2 缩放,那么反向比例也应该起作用,那么长度是两倍,所以反向比例应该是 @987654338 @ ...
  • 我刚刚在我的帖子中编辑了我解释的内容。你能帮我纠正一下吗?
【解决方案2】:

对于比例因子s,新点的坐标由下式给出

Xa' = Xa (1+s)/2 + Xb (1-s)/2
Ya' = Ya (1+s)/2 + Yb (1-s)/2


Xb' = Xb (1+s)/2 + Xa (1-s)/2
Yb' = Yb (1+s)/2 + Ya (1-s)/2

【讨论】:

    【解决方案3】:

    使用通用度量,您只需要单独调整每个维度。

    我重写了部分代码,使其更适合the usual Python style

    您可能想解决您不熟悉的事情,以便将来节省大量时间。

    class Line:
        def __init__(self, point_one, point_two):
            self.point_one = point_one
            self.point_two = point_two
    
        def __str__(self):
            return 'Line(p1:{},p2:{})'.format(self.point_one, self.point_two)
    
        @property
        def points(self):
            return self.point_one, self.point_two
    
        @property
        def length(self):
            return ((self.point_one.x - self.point_two.x)**2 + (self.point_one.y - self.point_two.y)**2)**0.5
    
        def scale(self, factor):
            self.point_one.x, self.point_two.x = Line.scale_dimension(self.point_one.x, self.point_two.x, factor)
            self.point_one.y, self.point_two.y = Line.scale_dimension(self.point_one.y, self.point_two.y, factor)
    
        @staticmethod
        def scale_dimension(dim1, dim2, factor):
            base_length = dim2 - dim1
            ret1 = dim1 - (base_length * (factor-1) / 2)
            ret2 = dim2 + (base_length * (factor-1) / 2)
            return ret1, ret2
    
    
    class Point:
        def __init__(self, x=0, y=0):
            self.x = x
            self.y = y
    
        def __str__(self):
            return 'Point(x={},y={})'.format(self.x, self.y)
    
        def __eq__(self, other):
            return self.x == other.x and self.y == other.y
    
    
    if __name__ == "__main__":
        p1 = Point(5, 5)
        p2 = Point(20, 35)
        l1 = Line(p1, p2)
        print(l1)
        print(l1.length)
        l1.scale(2)
        print(l1)
        print(l1.length)
        p5 = Point(-2.5, -10)
        p6 = Point(27.5, 50)
        assert l1.points == (p5, p6)
    

    注意,缩放方法会修改原始线和点。如果要换行,方法应该是:

    def scale(self, factor):
        x1, x2 = Line.scale_dimension(self.point_one.x, self.point_two.x, factor)
        y1, y2 = Line.scale_dimension(self.point_one.y, self.point_two.y, factor)
        return Line(Point(x1, y1), Point(x2, y2))
    

    【讨论】:

    • 我不认为你们明白我的要求。我想将点 a(5,5) 的线改为点 (20,35) 并将其向外缩放 2。这意味着我想将点 a 变为 (-2.5, -10) 点和点 b进入 (27.5, 50)。在长度方面,我想分别把33.54变成67.08,但我不想只扩展b,我也想扩展a。
    • 你试过这个代码吗?断言通过,点就是那些,你想要的,长度适合。
    • 好的,谢谢这个工作,但是当我在 print(str(l1)) 上尝试它时 #p5 = Point(8.75,12.5) #p6 = Point(16.25,27.5) #assert l1.getEndPoints() == (p5,p6) 或 l1.getEndPoints() == (p6,p5)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-15
    • 2021-10-25
    • 1970-01-01
    • 2010-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多