Очень большой неточный круг в HTML5 - PullRequest
6 голосов
/ 03 января 2012

Я разрабатываю приложение, в котором пользователи рисуют евклидовы конструкции на холсте HTML5.Поэтому я не могу ограничить размер определенных фигур.При исследовании очень больших кругов, нарисованных на экране, я заметил, что очень большие круги не имеют постоянного радиуса.

Точнее говоря, круг, определяемый двумя точками, центральной точкой и одной, указывающей радиусбольше не проходит через точку радиуса!

Large circle with radius point

Постепенно большие круги.Предполагается, что все они проходят через точку E.

Larger circles

Ошибка не возникает при кратных 45 градусам = PI / 4.Между этими коэффициентами самая большая ошибка (например, PI / 8)

Вот jsfiddle, содержащий первый пример выше:

http://jsfiddle.net/D28J2/2/

Мои вопросы: Почему это происходит?и есть ли способ (эффективно) обойти это?

Ответы [ 4 ]

3 голосов
/ 06 февраля 2012

Способ, которым я полностью обошел эту проблему, заключался в том, чтобы применить собственную реализацию аппроксимации рисования окружностей с помощью кривых Безье.Статья, подробно описывающая реализацию, может быть найдена здесь http://www.tinaja.com/glib/ellipse4.pdf.

function magic_circle(ctx, x, y, r){
  m = 0.551784

  ctx.save()
  ctx.translate(x, y)
  ctx.scale(r, r)

  ctx.beginPath()
  ctx.moveTo(1, 0)
  ctx.bezierCurveTo(1,  -m,  m, -1,  0, -1)
  ctx.bezierCurveTo(-m, -1, -1, -m, -1,  0)
  ctx.bezierCurveTo(-1,  m, -m,  1,  0,  1)
  ctx.bezierCurveTo( m,  1,  1,  m,  1,  0)
  ctx.closePath()
  ctx.restore()
}

Только с этими четырьмя сегментами я смог приблизить окружность намного лучше, чем сборка в реализации Google Chrome Canvas.

2 голосов
/ 05 января 2012

Вероятно, это ошибка с плавающей запятой. Возможно, потому что синус и косинус не дают совершенно точных значений. Вы можете обойти это (по крайней мере в Chrome), вращая холст вместо дуги.

ctx.save();          // Save the canvas so we can rotate back.
ctx.translate(x, y); // Translate to the origin point.
ctx.rotate(alpha);   // Rotate the proper angle.

ctx.arc(0, 0, 3, 0, Math.PI*2); // Draw the small circle at the origin.
ctx.fill();

ctx.arc(r, 0, r, 0, Math.PI*2); // Create a big with the origin 1 radius away.
ctx.restore();                  // Restore the canvas to the original orientation
                                // before drawing.  Otherwise the circle looks bad.
ctx.strokeStyle = "black";
ctx.stroke();                   // Draw!

Я большой поклонник манипулирования холстом вместо фигур. Это дает вам более логичную область для работы. Смотри http://jsfiddle.net/D28J2/10/

1 голос
/ 09 сентября 2016

Просто добавлю это, но может ли это быть проблемой без указания достаточного количества цифр PI?Всякий раз, когда я делаю что-то подобное, я склоняюсь к тому, чтобы идти немного за борт и использовать около 10 цифр ПИ.

0 голосов
/ 03 января 2012

В Google Chrome я могу повторить проблему, но в IE 9 и IE 10 все в порядке.

Так что я предполагаю, что реализация в Chrome неверна.Это может быть ошибка округления, или они использовали метод интерполяции, чтобы избежать греха и кос, которые не очень точны.

Смотрите также здесь: Дуги HTML5 canvas не корректно отображаются в Google Chrome

Единственная работа, которую я могу себе представить, это нарисовать круг с помощью собственного кода или использовать плагин (jQuery?), Который сделает это за вас.

...