3 недели назад Я задал вопрос, как сохранить соотношение кривой Безье при изменении точек X. «MBo» мне помогает, но возникла проблема и он посоветовал мне создать новую тему.
Проблема в том, что P0.Y и P2.Y могут быть разными, и поэтому кривая выглядит как «булочка».
Теперь у меня есть это, и при изменении P0.X и P2.X я хочу сохранить соотношение, которое работает нормально:
https://www.w3schools.com/code/tryit.asp?filename=FXDIZMBCCYNA
Например, при изменении P0.Y это выглядит как «бестия» (P1.X не совсем посередине):
https://www.w3schools.com/code/tryit.asp?filename=FXDJ733KQZM4
Хорошо, я пытаюсь объяснить это поподробнее.
У меня есть четыре точки (X1, Y1, X2, Y2), и мне нужна кривая Безье, основанная на этих точках, поэтому: P0.X находится на X1, P1.X между X1 и X2, а P2.X на X2. P0.Y находится на Y1, а P2.Y - на Y2.
Когда у меня теперь есть это:
ctx.moveTo(0, 50);
ctx.quadraticCurveTo(100, 25, 200, 50);
И измените положение x1 и x2. Я сохраняю соотношение сверху:
ctx.moveTo(0, 50);
ctx.quadraticCurveTo(25, 44, 50, 50);
Хорошо, пока эта часть работает нормально. Теперь моя проблема в том, что когда я меняю Y1 или Y2, это выглядит как «бестолковая», а кривая не круглая, как выше, потому что P1.X не совсем посередине.
ctx.moveTo(0, 250);
ctx.quadraticCurveTo(100, 25, 200, 50);
Где должно так:
Это настолько расплывчато, что может означать что угодно ... если вы меняете контрольные точки, вы активно меняете форму и размер кривой, так что именно вы хотите? найти интервал, в котором кривая образует заданное соотношение сторон? или пропорционально масштабировать / позиционировать кривую, чтобы она соответствовала некоторому BBOX? или что? как вы можете видеть, это все еще неясно ... Вы должны отредактировать новую информацию ... в свой вопрос Также вы должны добавить саму кривую (точки изгиба и тип кривой ...) MCVE был бы даже лучше, чем многие из нас ленивы кодировать его с нуля Кстати, четко описывая проблему, некоторые обычно находили решение
И чем этот вопрос отличается от связанного вопроса? Если они такие же, не публикуйте дубликаты, вместо этого добавьте новую информацию в свой исходный вопрос и прокомментируйте там других, чтобы уведомить их о новой информации ...
У вас есть 4 вопроса с ответами, но вы не отметили ни один из них как решенный.
Кстати, вопрос снова не ясен. Пожалуйста, постарайтесь составить более подробное описание.
@JCss ну, это все еще нуждается в некоторой настройке ... например, для квадратичной кривой нужно 3 точки, а не 2 ... в тексте вы пишете около 4, а в скобках у вас есть 2, в коде у вас есть 2 и один в moveto, так что черт возьми?
Я предполагаю, что moveTo - это первая контрольная точка, а quadraticCurveTo - следующие две .. теперь вы изменили последние 2 контрольные точки, и форма и соотношение сторон изменились? как вы хотите сохранить соотношение сторон ... или какие значения вы хотите вычислить? мы не знаем, почему вы меняете координаты x и y, а также то, что является фоном, поэтому мы не знаем, какие значения мы можем изменить безопасно и как ... единственное, что я могу порекомендовать, - это сохранять пропорциональные изменения между x и y ...
Вы хотите повернуть кривую? Чтобы повернуть с некоторым масштабированием? (при сдвиге y2 расстояние p0-p2 меняется)
@MBo хе ротация вообще не пришла мне в голову :)
@MBo Да, это как вращение с масштабированием. Мне просто нужна кривая между двумя точками (x1, y1) и (x2, y2).



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я это вижу так:
Итак, вы получили около 3 баллов (P0(x0,y0),P1(x1,y1),P2(x2,y2)). Теперь то, что вы хотите сделать, это все еще неясно, но я предполагаю, что вы просто хотите изменить размер кривой по оси x и сохранить форму также по оси y ...
Итак, вам нужно изменить все, что угодно ... так что поддерживайте это:
(x1-x0) / (x2-x0) = (x1'-x0') / (x2'-x0')
(y1-y0) / (y2-y0) = (y1'-y0') / (y2'-y0')
(x1-x0) / (x1'-x0') = c
(y1-y0) / (y1'-y0') = c
(x2-x0) / (x2'-x0') = c
(y2-y0) / (y2'-y0') = c
(x2-x1) / (x2'-x1') = c
(y2-y1) / (y2'-y1') = c
где x,y - исходные точки, а x',y' - измененные
для вашего примера:
P0=( 0,50)
P1=(100,25)
P2=(200,50)
x2'=50
вам нужно пересчитать оставшееся начало с масштабом:
c = (x2-x0) / (x2'-x0') = (200-0)/(50-0) = 200/50 = 4
затем просто пересчитайте то, чего не хватает:
(x1-x0) / c = (x1'-x0') // x0=0, x0'=0
x1 / c = x1'
x1' = 100/4 = 25
(y1'-y0') = (y1-y0) / c // y0' = y0
y1' = (y1-y0) / c + y0
y1' = (25-50) / 4 + 50
y1' = 43.75
(y2'-y0') = (y2-y0) / c // y0' = y0
y1' = (y2-y0) / c + y0
y1' = (50-50) / 4 + 50
y1' = 50
То же самое и с заменой y ... как только вы замените какой-либо y, вам нужно будет пересчитать оставшийся x,y, затронутый таким же образом ...
Спасибо Спектре. Я попробую это скоро, потому что мне нужно время, чтобы понять это :)
@JCss, дело в том, чтобы поддерживать одинаковое соотношение между контрольной точкой, поэтому, когда вы меняете любую координату, вы должны пересчитывать другие, чтобы соответствовать ... Если вы хотите повернуть вместо изменения размера, вам нужно повернуть все точки на один и тот же угол вокруг тот же центр вместо
Когда кривая Безье подвергается некоторому аффинному преобразованию, то же преобразование применяется к их контрольным точкам.
В вашем случае преобразование - это вращение и масштабирование вокруг первой точки (P0) кривой.
Угол поворота составляет
fi = arctan((P2'.Y - P2.Y) / (P2.X - P0.X))
Коэффициент масштабирования
Cf = Sqrt(1 + (P2'.Y - P2.Y)^2/(P2.X - P0.X)^2)
Итак, новые координаты для контрольных точек
xx = P1.X - P0.X
yy = P1.Y - P0.Y
nx = xx * Cos(fi) - yy * Sin(fi)
ny = xx * Sin(fi) + yy * Cos(fi)
P1'.X = P0.X + nx * Cf
P1'.Y = P0.Y + ny * Cf
Спасибо MBo. На выходных протестирую и отвечу им.
Так работать отлично. Спасибо!
Я забыл добавить ссылку: stackoverflow.com/questions/53329826/… Вопрос в том, как я могу сохранить соотношение, как на первом изображении, при изменении точек X и Y, чтобы оно не выглядело «скучно», как на втором изображении.