我开发了一个基于Python的绘图程序,Whyteboard(https://launchpad.net/whyteboard)
我正在开发功能,允许用户旋转和缩放他们绘制的多边形。这是我的问题:
我有一个Polygon类,其中包含所有点的列表,最后是“关闭”。用户可以在我的程序中选择绘制的形状,“高亮”它们,在每个点绘制选择手柄。可以“抓住”这些点来改变它的位置,并改变多边形的形状。
我遇到了一个问题:我需要弄清楚如何计算应用于多边形的调整大小“scale”。例如,(在按住鼠标的情况下),用户将鼠标移离形状应该是“成长”动作,将鼠标移向形状应该缩小它。
我有代码来执行比例(我认为这是正确的),但我不能创建一个“好”的比例因子。以下代码是我根据答案
提出的/ 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])
目前,这段代码似乎可以将我的多边形缩小到没有任何速度,并且鼠标移动量不会增加。有时它会做相反的事情,并迅速成长;但不退缩。
答案 0 :(得分: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])
我希望你的点保持浮点状态,因为整数截断错误会很快累积。拥有两个点的副本可能会更好,一个是缩放的,一个是非缩放的。
要确定比例因子,请选择从原始点击到中心的距离与当前鼠标位置到中心的比率。
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 :缩放时,您将从一个尺寸缩放到另一个尺寸。如果您经常重新缩放,则有两种选择:将形状的一个副本保留为原始大小,或者使比例因子相对于形状的最后大小而不是原始大小。我更喜欢两种复制方法,因为否则即使你使用浮点,也很容易积累错误;它也更容易使逻辑正确。
答案 1 :(得分:1)
最直观的比例因子是(从当前鼠标位置到多边形中心的距离)与(从拖动开始时的鼠标位置到多边形中心的距离)的比率 - 以便点击多边形中的点并且将它拖离中心两倍,因为它是多边形的两倍。
答案 2 :(得分: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
为避免舍入错误,您可能希望保留原始点,直到用户完成缩放。