Math 使用鼠标缩放二维多边形

Math 使用鼠标缩放二维多边形,math,polygon,draw,rescale,Math,Polygon,Draw,Rescale,我开发了一个基于Python的绘图程序Whyteboard 我正在开发允许用户旋转和缩放他们绘制的多边形的功能。我的问题是: 我有一个多边形类,它包含所有点的列表,在末尾关闭。用户可以在我的程序中选择绘制的形状,该程序会高亮显示它们,并在每个点上绘制选择手柄。可以抓住这些点来更改其位置,并更改多边形的形状 我有一个问题:我需要找出如何计算一个调整大小的比例,以适用于多边形。例如,在按住鼠标的情况下,用户将鼠标移离形状应该是一个增长动作,而将鼠标移向形状应该会使其收缩 我有代码来执行缩放,我相信这

我开发了一个基于Python的绘图程序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]) 

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

最直观的比例因子是从当前鼠标位置到多边形中心的距离与拖动开始时从鼠标位置到多边形中心的距离之比-因此,单击多边形中的一个点并将其拖动到距离中心两倍于原来距离的位置,将使多边形的大小增加一倍。

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

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

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

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

这里的幻数是多少?我是说,一个值。00-1.00,1-100,或者什么?这是个神奇的数字!这取决于什么看起来最好。先试试10。实际上,不需要幻数。单击鼠标时,测量lengthofmouse center并将其存储为原始文件。然后,新的比例就是lengthofmouse center/original。如果原始值为零,请小心!谢谢我想这就是我在第一篇文章中编辑的代码中所做的,但它仍然有点不可靠。在浮动上的想法很好,我没有想到——我已经转换了。我是否一直在重新计算代码中的中心?我已经编辑了我的原始帖子来添加我的代码,但是效果不太好-多边形的大小调整似乎太快了。嗨,很抱歉继续这样。我不确定我是否遵循-当前点仅用于计算中心,一次?如果你能帮忙的话,我不确定两套衣服在哪里合适。谢谢对谢谢你,马克!我终于把一切都做好了。你的帮助是无价的。现在,让你看看你帮了我什么:-无刻度-做得更小-更大的欢呼声!