使用鼠标缩放2D多边形

Ste*_*oat 2 math polygon draw rescale

我开发了一个基于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]) 
Run Code Online (Sandbox Code Playgroud)

目前,这段代码似乎可以将我的多边形缩小到很快,并且没有任何鼠标移动会使其恢复.有时它会做相反的事情,并迅速成长; 但不退缩.

Mar*_*som 5

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

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]) 
Run Code Online (Sandbox Code Playgroud)

我希望你的点保持浮点,因为整数截断错误会很快积累.拥有两个点的副本可能会更好,一个是缩放的,一个是非缩放的.

要确定比例因子,请选择从原始点击到中心的距离与当前鼠标位置到中心的比率.

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
Run Code Online (Sandbox Code Playgroud)

编辑:您的最新问题强调了拥有两组原点和缩放点的重要性.由于比例因子是相对于形状的原始大小,因此每次缩放时都需要从形状的原始点开始.当用户完成鼠标播放时,您可以将其合并为一组.

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

编辑2:缩放时,您将从一种尺寸缩放另一种尺寸.如果您经常重新缩放,则有两种选择:将形状的一个副本保留为原始大小,或者使比例因子相对于形状的最后大小而不是原始大小.我更喜欢两种复制方法,因为否则即使你使用浮点,也很容易积累错误; 它也更容易获得正确的逻辑.