Вы выбираете один угол прямоугольника в качестве источника. Два соединенных с ним ребра будут основой (u
и v
, которые должны быть перпендикулярны друг другу). Сначала вам нужно их нормализовать.
Вычтите начало координат из координат и вычислите скалярное произведение с вектором масштабирования (u
) и другим вектором (v
). Это даст вам, сколько u
и v
вносит вклад в координату.
Затем вы масштабируете компонент, который хотите. Чтобы получить окончательную координату, вы просто умножаете (теперь масштабированные) компоненты на соответствующий вектор и складываете их вместе.
Например:
Points: p1 = (3,5) and p2 = (6,4)
Selection corners: (0,2),(8,0),(9,4),(1,6)
selected origin = (8,0)
u = ((0,2)-(8,0))/|(0,2)-(8,0)| = <-0.970, 0.242>
v = <-0.242, -0.970>
(v
- это u
, но с перевернутыми координатами, и одна из них отрицается)
p1´ = p1 - origin = (-5, 5)
p2´ = p2 - origin = (-2, 4)
p1_u = p1´ . u = -0.970 * (-5) + 0.242 * 5 = 6.063
p1_v = p1´ . v = -0.242 * (-5) - 0.970 * 5 = -3.638
Scale p1_u by 0.5: 3.038
p1_u * u + p1_v * v + origin = <5.941, 4.265>
Same for p2: <7.412, 3.647>
Как вы, возможно, можете видеть, они сместились к линии (8,0)
- (9,4)
, так как мы масштабировали до 0,5, с (0,8)
в качестве источника.
Редактировать: Это оказалось немного сложнее объяснить, чем я ожидал.
В коде Python это может выглядеть примерно так:
def scale(points, origin, u, scale):
# normalize
len_u = (u[0]**2 + u[1]**2) ** 0.5
u = (u[0]/len_u, u[1]/len_u)
# create v
v = (-u[1],u[0])
ret = []
for x,y in points:
# subtract origin
x, y = x - origin[0], y - origin[1]
# calculate dot product
pu = x * u[0] + y * u[1]
pv = x * v[0] + y * v[1]
# scale
pu = pu * scale
# transform back to normal space
x = pu * u[0] + pv * v[0] + origin[0]
y = pu * u[1] + pv * v[1] + origin[1]
ret.append((x,y))
return ret
>>> scale([(3,5),(6,4)],(8,0),(-8,2),0.5)
[(5.9411764705882355, 4.2647058823529411), (7.4117647058823533, 3.6470588235294117)]