Построение правильного многоугольника без тригонометрических функций
См. функцию poly :
<!DOCTYPE html> <canvas id=c width=600 height=600 style='outline:1px solid'></canvas> <script> 'use strict'; const cx=c.getContext('2d'), {PI,sin,cos,round}=Math, pi2=PI*2, ra=PI/180, // 1 радиан ra90=90*ra, line=(x1,y1,x2,y2)=>(cx.beginPath(),cx.moveTo(x1,y1),cx.lineTo(x2,y2),cx.stroke(),line), cross=(x,y,d=20)=>(line(x-(d/=2),y,x+d,y)(x,y-d,x,y+d),cross), circle=(x,y,d=20)=>(cx.beginPath(),cx.arc(x,y,d/2,0,pi2),cx.stroke(),circle), poly=(x,y,d=20,n=4,a=-ra90)=>{ // a - первая вершина будет сверху холста if(n>2){ d/=2; cx.beginPath(); for(let b=pi2/n++; n--; cx.lineTo( x+d*cos(a+=b), y+d*sin(a) )); cx.stroke() } }; poly(300,300,400,8); // 400 - диаметр описанной окружности, 8 - количество вершин cross(300,300); // центр правильного многоугольника cx.strokeStyle='red'; // первая вершина circle(300,100); cx.strokeStyle='blue'; circle(300,300,400); </script> Возможно ли избавиться от sin и cos при построении многоугольника, если знать диаметр описанной окружности, количество вершин многоугольника? Может здесь поможет векторная алгебра, всякие скалярные и векторные произведения. Или как-то найти соотношение длины дуги описанной коружности к хорде, которая будет стороной многоугольника. Получить равнобедренный треугольник и зная хорду и 2 стороны, равные диаметру, найти координаты вершин. В общем я запутался, есть чувство, что можно обойтись без тригонометрии, хотя бы в цикле. Одной из причин, которая сподвигла задать вопрос, был просмотр мною видео об истории числа ПИ, которые нашли разбиением окружности на сегменты. И чем больше сегментов, тем точнее ПИ. И спрашивается можно ли вообще без него обойтись при построении правильного многоугольника и почему я должен разбивать окружность на 360 частей, если надо например только на 8, или скажем на 1000. И вообще, возможно было бы удобно, представить длину окружности за единицу (нормализовать) и иметь дело с соотношениями сторон, координатами. Также мне очень понравились статьи с хабра про векторную алгебру: Избегаем тригонометрии : https://habr.com/ru/post/462539/ Когда не нужна тригонометрия : https://habr.com/ru/post/105882/ Надеюсь получится улучшить функцию poly и сделать её настолько быстрой, насколько возможно, ведь так здорово когда всё работает быстро и без извращений ))) |
Цитата:
а эти твои синусы вычисляются очень быстро. |
Можно попробовать поэкспериментировать с трансформацией
https://developer.mozilla.org/ru/doc...tions#rotating по идее, если вращать вокруг центра фигуры, то можно будет рисовать одну и ту же хорду. Хотя не факт, что это позволит ускориться. |
Пи - это иррациональное число. Иррациональные числа невозможно соизмерять с единицей (рациональными числами) это и есть их основное свойство.
Очень странным выглядит попытка вычисления углов с попыткой игнорирования науки о вычислении углов. Для меня все это выглядит как изобретение велосипеда. т.е. переизобретение тригонометрии. В общем даже древние греки знали что Пифагоровы штаны во все стороны ровны. теорема Пифагора поможет тебе с помощью умножения и деления описать тригонометрические функции но библиотечные реализации sin cos работают быстрее и оптимальнее. |
Цитата:
Разработка CAD-приложения. В API нет функций setTransform, rotate, translate, там вообще ничего нет, кроме рисования прямых линий и треугольников - соответственно окружность будет правильным многоугольником, хоть треугольником )) И чтобы облегчить разработку, я использую обычный Canvas API, отрабатываю алгоритмы и уже потом имея логику, постараюсь засунуть в WebGPU. Просто бросается в глаза простота процесса отрисовки - использовать одинаковое угловое приращение и прям так вылезает на поверхность вопрос - зачем высчитывать синусы и косинусы если угол приращения одинаковый, всё равномерно )) Цитата:
|
Мне непонятна твоя логика и на мой скромный взгляд в ней куча элементарных ошибок и заблуждений.
![]() Ну может пригодится простейший пример рисование правильного многоугольника шейдерной программкой (кнопочка SHOW CODE ну и раскомменчивать построчно). со смещением и вращением глобальных координат матрицей трансформации. https://glslsandbox.com/e#78075.1 |
Цитата:
А затем, надеясь на векторную алгебру, которую что-то не могу осилить )), а также помощь форума, решить задачу. Я ещё поколдую )) Хотя другая часть меня говорит: Ты занимаешься фигнёй )) |
Вложений: 1
Ну если не совсем произвольный многоугольник, а последовательно переходить удваивая количество вершин. Например, от квадрата перейти к правильному восьмиугольнику, потом к правильному 16-ти угольнику, то можно строить эти вершины без синусов и косинусов. Правда квадратный корень извлекать придется
Надо находить точку на окружности между двумя вершинами треугольника Вроде так можно (см рисунок) Есть Треугольник O(Xo,Yo), A(Xa,Ya) B(Xb, Yb), O - центр окружности радиуса R Найти точку C(Xc,Yc), чтобы OC "делила треугольник на равные части" Найдем P(Xp, Yp) Xp = (Xa+Xb)/2; Yp = (Ya+Yb)/2; Длина OP d = Sqrt((Xp-Xo)^2 + (Yp-Yo)^2) Отсюда Xc = Xo + (Xp-Xo)*R/d; Yc = Yo + (Yp-Yo)*R/d |
Небольшой тест на svg
<body> <button id="p2">Удвоить</button> <br> <svg width="410" height="410" version="1.1" xmlns="http://www.w3.org/2000/svg"> <circle cx="205" cy="205" r="200" stroke="black" fill="transparent" stroke-width="1"/> <polygon id="mnog" stroke="red" fill="transparent" stroke-width="1"/> </svg> <script> const O =[205,205]; const R = 200; let mnog = [[205, 5], [405, 205], [205, 405], [5, 205]]; const draw = (mnog) =>{ const pol = mnog.flat() document.getElementById('mnog').setAttribute('points', pol) } const sredn = ([xo, yo], [xa, ya], [xb, yb], R) => { const xp = (xa+xb)/2; const yp= (ya+yb)/2 const d = Math.sqrt((xp-xo)**2 + (yp-yo)**2) return [xo+(xp-xo)*R/d, yo+(yp-yo)*R/d] } const doublm = (mnog) => { const sred = [] for (let i=0; i<mnog.length; i++) sred.push(sredn(O, mnog[i], mnog[i === mnog.length-1? 0: i+1], R)) const res = [] for (let i=0; i<mnog.length; i++) res.push(mnog[i], sred[i]) return res } document.getElementById('p2').addEventListener('click', () => { mnog = doublm(mnog) draw(mnog) }) draw(mnog); </script> </body> |
voraa,
хитро )) Тогда можно в принципе, на входе функции проверить чётность количества переданных вершин и в зависимости от чётности выполнять блок построения квдаратов, восьмиугольников, ... А если нечётно, то блок отрисовки треугольников, пятиугольников. Хотя если взять шестиугольник, то можно ли будет построить его по вашему алгоритму? |
Часовой пояс GMT +3, время: 10:13. |