Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 23.12.2021, 12:29
Профессор
Отправить личное сообщение для Teamur Посмотреть профиль Найти все сообщения от Teamur
 
Регистрация: 08.06.2015
Сообщений: 206

Построение правильного многоугольника без тригонометрических функций
См. функцию 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 и сделать её настолько быстрой, насколько возможно,
ведь так здорово когда всё работает быстро и без извращений )))

Последний раз редактировалось Teamur, 23.12.2021 в 12:31.
Ответить с цитированием
  #2 (permalink)  
Старый 23.12.2021, 13:14
Аватар для Alexandroppolus
Профессор
Отправить личное сообщение для Alexandroppolus Посмотреть профиль Найти все сообщения от Alexandroppolus
 
Регистрация: 25.10.2016
Сообщений: 1,012

Сообщение от Teamur
Надеюсь получится улучшить функцию poly и сделать её настолько быстрой, насколько возможно
там самая медленная часть - рисование.
а эти твои синусы вычисляются очень быстро.
Ответить с цитированием
  #3 (permalink)  
Старый 23.12.2021, 13:35
Аватар для Alexandroppolus
Профессор
Отправить личное сообщение для Alexandroppolus Посмотреть профиль Найти все сообщения от Alexandroppolus
 
Регистрация: 25.10.2016
Сообщений: 1,012

Можно попробовать поэкспериментировать с трансформацией
https://developer.mozilla.org/ru/doc...tions#rotating
по идее, если вращать вокруг центра фигуры, то можно будет рисовать одну и ту же хорду. Хотя не факт, что это позволит ускориться.
Ответить с цитированием
  #4 (permalink)  
Старый 23.12.2021, 14:27
Аватар для MallSerg
Профессор
Отправить личное сообщение для MallSerg Посмотреть профиль Найти все сообщения от MallSerg
 
Регистрация: 07.03.2011
Сообщений: 1,138

Пи - это иррациональное число. Иррациональные числа невозможно соизмерять с единицей (рациональными числами) это и есть их основное свойство.
Очень странным выглядит попытка вычисления углов с попыткой игнорирования науки о вычислении углов. Для меня все это выглядит как изобретение велосипеда. т.е. переизобретение тригонометрии.
В общем даже древние греки знали что
Пифагоровы штаны во все стороны ровны.
теорема Пифагора поможет тебе с помощью умножения и деления описать тригонометрические функции но библиотечные реализации sin cos работают быстрее и оптимальнее.
Ответить с цитированием
  #5 (permalink)  
Старый 23.12.2021, 14:51
Профессор
Отправить личное сообщение для Teamur Посмотреть профиль Найти все сообщения от Teamur
 
Регистрация: 08.06.2015
Сообщений: 206

Сообщение от Alexandroppolus
Можно попробовать поэкспериментировать с трансформацией
Я планирую переписать код для использования в WebGPU ( WGSL ) API.
Разработка CAD-приложения. В API нет функций setTransform, rotate, translate, там вообще ничего нет, кроме рисования прямых линий и треугольников - соответственно окружность будет правильным многоугольником, хоть треугольником ))
И чтобы облегчить разработку, я использую обычный Canvas API, отрабатываю алгоритмы и уже потом имея логику, постараюсь засунуть в WebGPU.
Просто бросается в глаза простота процесса отрисовки - использовать одинаковое угловое приращение и прям так вылезает на поверхность вопрос - зачем высчитывать синусы и косинусы если угол приращения одинаковый, всё равномерно ))

Сообщение от MallSerg
библиотечные реализации sin cos работают быстрее и оптимальнее
Это хорошо, но мне важно знать - принципиально это как-то возможно, обойтись без тригонометрии, чисто координатами, длинами сторон, диаметрами, теорией по треугольникам?
Ответить с цитированием
  #6 (permalink)  
Старый 23.12.2021, 17:01
Аватар для MallSerg
Профессор
Отправить личное сообщение для MallSerg Посмотреть профиль Найти все сообщения от MallSerg
 
Регистрация: 07.03.2011
Сообщений: 1,138

Мне непонятна твоя логика и на мой скромный взгляд в ней куча элементарных ошибок и заблуждений.


Ну может пригодится простейший пример рисование правильного многоугольника шейдерной программкой (кнопочка SHOW CODE ну и раскомменчивать построчно).
со смещением и вращением глобальных координат матрицей трансформации.
https://glslsandbox.com/e#78075.1
Ответить с цитированием
  #7 (permalink)  
Старый 23.12.2021, 21:58
Профессор
Отправить личное сообщение для Teamur Посмотреть профиль Найти все сообщения от Teamur
 
Регистрация: 08.06.2015
Сообщений: 206

Сообщение от MallSerg
Мне непонятна твоя логика и на мой скромный взгляд в ней куча элементарных ошибок и заблуждений
Потому что, я был уверен, что можно как-то исхитриться и задействовать Пифагора, а синусы и косинусы представить в виде отношений катетов к гипотенузе, которая была бы радиусом от центра окружности до вершины многоугольника.
А затем, надеясь на векторную алгебру, которую что-то не могу осилить )), а также помощь форума, решить задачу.
Я ещё поколдую )) Хотя другая часть меня говорит: Ты занимаешься фигнёй ))
Ответить с цитированием
  #8 (permalink)  
Старый 23.12.2021, 23:29
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,745

Ну если не совсем произвольный многоугольник, а последовательно переходить удваивая количество вершин. Например, от квадрата перейти к правильному восьмиугольнику, потом к правильному 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
Изображения:
Тип файла: jpg tr.jpg (7.3 Кб, 4 просмотров)
Ответить с цитированием
  #9 (permalink)  
Старый 24.12.2021, 00:28
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,745

Небольшой тест на 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>
Ответить с цитированием
  #10 (permalink)  
Старый 24.12.2021, 15:31
Профессор
Отправить личное сообщение для Teamur Посмотреть профиль Найти все сообщения от Teamur
 
Регистрация: 08.06.2015
Сообщений: 206

voraa,
хитро ))
Тогда можно в принципе, на входе функции проверить чётность количества переданных вершин и в зависимости от чётности выполнять блок построения квдаратов, восьмиугольников, ... А если нечётно, то блок отрисовки треугольников, пятиугольников.
Хотя если взять шестиугольник, то можно ли будет построить его по вашему алгоритму?
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Тест на js: чтобы без правильного ответа не было возможно перейти к след. вопросу. Globus Общие вопросы Javascript 8 02.11.2021 13:19
Построение сколемовских функций Opositt Работа 1 10.01.2019 13:25
Порядок выполнения функций с Promise и без. Даниленко Денис Общие вопросы Javascript 0 29.04.2017 12:33
Сумма чисел фиббоначи без использования функций и массивов. mariaanina Общие вопросы Javascript 4 03.06.2014 17:22