2

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

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

我有一个 Polygon 类,其中包含所有点的列表,最后是“关闭”的。用户可以在我的程序中选择绘制的形状,“突出显示”它们,在每个点绘制选择句柄。这些点可以被“抓取”以改变其位置,并改变多边形的形状。

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

我有代码来执行缩放(我相信这是正确的),但我无法创建一个“好的”缩放因子。下面的代码是我根据答案提出的

/edit - 这是解决的代码。

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]) 

目前,这段代码似乎可以迅速将我的多边形缩小到零,并且没有多少鼠标移动会使它重新长出来。有时它会适得其反,迅速成长;但不退缩。

4

3 回答 3

6

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

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:当您缩放时,您正在一种尺寸缩放另一种尺寸。如果您不断地重新缩放,您有两个选择:将形状的一个副本保留为其原始大小,或者使您的比例因子相对于形状的最后一个大小,而不是原始大小。我更喜欢两次复制方法,因为否则即使您使用浮点数也很容易累积错误;使逻辑正确也更容易。

于 2010-01-06T17:56:17.607 回答
1

我不精通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

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

于 2010-01-06T18:06:57.413 回答
1

最直观的比例因子是(从当前鼠标位置到多边形中心的距离)与(从拖动开始时的鼠标位置到多边形中心的距离)的比率 - 这样单击多边形中的一个点并拖动它两次离中心越远,多边形的大小就加倍。

于 2010-01-06T17:32:13.583 回答