代码之家  ›  专栏  ›  技术社区  ›  Steven Sproat

使用鼠标缩放二维多边形

  •  2
  • Steven Sproat  · 技术社区  · 15 年前

    我开发了一个基于Python的绘图程序Whyteboard( https://launchpad.net/whyteboard

    我正在开发允许用户旋转和缩放他们绘制的多边形的功能。我的问题是:

    我有一个问题:我需要弄清楚如何计算一个调整大小的“比例”来应用于多边形。例如,(在按住鼠标的情况下),用户将鼠标移离形状应该是一个“增长”动作,而将鼠标移向形状应该会使其收缩。

    def rescale(self, x, y):
        """ 
        x and y are the current mouse positions. the center and "original" mouse 
        coords are calculated below
        """
        if not self.center:
            a = sum([x for x, y in self.points]) / len(self.points)
            b = sum([y for x, y in self.points]) / len(self.points)
            self.center = (a, b)
        if not self.orig_click:  # where the user first clicked on
            self.orig_click = (x, y)
        if not self.original_points:  # the points before applying any scaling
            self.original_points = list(self.points)
    
    
        orig_click = self.orig_click
        original_distance = math.sqrt((orig_click[0] - self.center[0]) ** 2 + (orig_click[1] - self.center[1]) ** 2)
    
        current_distance = (math.sqrt((x - self.center[0]) ** 2 + 
                           (y - self.center[1]) ** 2))
        self.scale_factor = current_distance / original_distance        
    
        for count, point in enumerate(self.original_points): 
            dist = (point[0] - self.center[0], point[1] - self.center[1]) 
            self.points[count] = (self.scale_factor * dist[0] + self.center[0], self.scale_factor * dist[1] + self.center[1]) 
    

    目前,这段代码似乎可以快速地将多边形缩小到零,并且再多的鼠标移动也不会使它变大。有时它会做相反的事情,并迅速成长;但不要退缩。

    3 回复  |  直到 15 年前
        1
  •  6
  •   Mark Ransom    15 年前

    首先,让我们更正您的缩放代码:

    for count, point in enumerate(self.points): 
        dist = (point[0] - self.center[0], point[1] - self.center[1]) 
        self.points[count] = (self.scale_factor * dist[0] + self.center[0], self.scale_factor * dist[1] + self.center[1]) 
    

    我希望您的点保持在浮点形式,因为整数截断错误将很快累积。最好有两个点的副本,一个缩放,一个未缩放。

    要确定比例因子,请获取从原始单击到中心的距离与当前鼠标位置到中心的距离之比。

    original_distance = sqrt((click[0] - self.center[0])**2 + (click[1] - self.center[1])**2)
    current_distance = sqrt((current_position[0] - self.center[0])**2 + (current_position[1] - self.center[1])**2)
    self.scale_factor = current_distance / original_distance
    

    编辑:

    对于你的评论,不,你不必重新计算中心。中心不应该移动。

    编辑2: 从…起 一号 另一个尺寸。如果不断重新缩放,则有两种选择:将形状的一个副本保持为其原始大小,或使比例因子相对于形状的最后一个大小而不是原始大小。我更喜欢双拷贝方法,因为否则即使使用浮点,错误也很容易累积;这也更容易得到正确的逻辑。

        2
  •  1
  •   moonshadow    15 年前

        3
  •  1
  •   knight666    15 年前

    我不精通Python,所以我将尝试用伪代码回答。

    center = (point1 + point2 + point3) / 3
    

    你想根据鼠标缩放它,对吗?这总是很棘手,但应该是这样的:

    scale = lengthof(mouse - center) / MAGIC_NUMBER
    

    relative_point1 = point1 - center
    relative_point2 = point2 - center
    relative_point3 = point3 - center
    

    然后按比例缩放相对点:

    relative_point1 *= scale
    relative_point2 *= scale
    relative_point3 *= scale
    

    point1 = center + relative_point1
    point2 = center + relative_point2
    point3 = center + relative_point3
    

    为了避免舍入错误,您可能希望保留原始点,直到用户完成缩放。