|
2D-программирование Вопросы, касающиеся двумерного программирования |
04.10.2015, 02:58
|
#1
|
Разработчик
Регистрация: 08.08.2011
Сообщений: 505
Написано 191 полезных сообщений (для 369 пользователей)
|
Пунктирная окружность
Приветствую, форумчане!
Появилась необходимость рисовать пунктирную окружность. При этом она должна состоять не из точек, а из линий длиной 4 пикселя и промежуток между ними 2 пикселя.
Поиск ничего не дал. Четыре часа ломал голову, вспоминал формулы окружности. Либо я туплю, либо что-то не учитываю, но если просто рисовать точками (а потом разделить их на отрезки) по функции y = +-Sqr (r^2-x^2), то при y, приближающемся к нулю, точки почему-то не все прорисовываются. В итоге пришлось разбить окружность на 4 части и рисовать по-отдельности. Второй момент: длина окружности ведь 2*Пи*r, если разделить на 4 части и еще на 2 (отрицательные и положительные значения), то цикл должен выглядеть так: For x = -Пи*r/4 To Пи*r/4. То есть получаем Пи/4 = 0,7854*r. Но при таком значении части окружности почему-то накладываются друг на друга. Подобрал экспериментально число 0.7067. Откуда оно взялось непонятно. В математике такого нет.
В общем, вот то, на что меня хватило:
Проблемы следующие:
1) вроде делаю шаг 4 пикселя (целочисленное деление), а получаются линии по 8 пикселей. Промежуток 5 пикселей (хотя при 8 должен быть 4, если в 2 раза меньше).
2) при радиусе 100 вроде окружность выглядит нормально, а вот при радиусе 200 и более стыки между четырьмя её частями сливаются.
Может кто подскажет решение попроще и поэлегантнее?
Ну или может кто заметит косяк, а то я совсем запутался, уже на бумаге всё разрисовал, а в коде не получается
Graphics 800,600,32, 2
Dim kr_x (1) Dim kr_y (1)
While Not KeyHit(1) Color 255, 255, 255 If KeyHit (57) Then dotted_circle (400, 300, 100) Wend
Function dotted_circle (dx, dy, r) For x = -0.7067*r To 0.7067*r y = Sqr (r^2 - x^2) If x Mod 4 = 0 Then rf = rf + 1 EndIf Next
Dim kr_x (rf) Dim kr_y (rf)
For x = -0.7067*r To 0.7067*r y = Sqr (r^2 - x^2) If x Mod 4 = 0 Then kr_x (i) = x kr_y (i) = y i = i + 1 EndIf Next
For i = 0 To rf Step 4 Line kr_x (i) + dx, kr_y (i) + dy, kr_x (i+2) + dx, kr_y (i+2) + dy Line kr_x (i) + dx, -kr_y (i) + dy, kr_x (i+2) + dx, -kr_y (i+2) + dy Line kr_y (i) + dx, kr_x (i) + dy, kr_y (i+2) + dx, kr_x (i+2) + dy Line -kr_y (i) + dx, kr_x (i) + dy, -kr_y (i+2) + dx, kr_x (i+2) + dy Next
rf = 0: i = 0
End Function
|
(Offline)
|
|
04.10.2015, 03:10
|
#2
|
Зануда с интернетом
Регистрация: 04.09.2005
Сообщений: 14,014
Написано 6,798 полезных сообщений (для 20,935 пользователей)
|
Ответ: Пунктирная окружность
y=r*sin(q)
x=r*cos(q)
При известном r оцениваешь значение шага для q. Генерируешь набор точек. Соединяешь линиями. всё
Блитца под рукой нет
__________________
http://nabatchikov.com
Мир нужно делать лучше и чище. Иначе, зачем мы живем? tormoz
А я растила сына на преданьях
о принцах, троллях, потайных свиданьях,
погонях, похищениях невест.
Да кто же знал, что сказка душу съест?
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
04.10.2015, 03:27
|
#3
|
Разработчик
Регистрация: 08.08.2011
Сообщений: 505
Написано 191 полезных сообщений (для 369 пользователей)
|
Ответ: Пунктирная окружность
Спасибо! Проверил, работает.
Всё проще, оказывается. Обидно, что 4 часа провозился с разбиением окружности на части.
Хреново, когда не помнишь геометрию. Я даже не подумал про синусы косинусы, потому что их графики мне представляются в виде волны, а не окружности.
Graphics 800,600,32, 2
While Not KeyHit(1) Color 255, 255, 255 For q = 1 To 1000 Step 4 Plot 400+200*Cos(q), 300+200*Sin(q) Next Wend
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
04.10.2015, 07:02
|
#4
|
ПроЭктировщик
Регистрация: 17.07.2009
Сообщений: 182
Написано 51 полезных сообщений (для 71 пользователей)
|
Ответ: Пунктирная окружность
Кстати , если кому надо , то ...
Функция Пунктирная линия с регулируемым шагом
- - - - - - - - - - - - - - - - - - - - - - - - -
шаг задаёт переменная offsete
Код под спойлером :
Function Interpolate#(stepInterpolate#, Pt_1#, Pt_2#)
Return ((1.0-stepInterpolate)*Pt_1 + stepInterpolate *Pt_2)
End Function
Function StepLine#(sPt_x# ,sPt_y#, ePt_x# ,ePt_y# , R_ = 255,G_ = 255,B_ = 255 , offsete = 4)
offsete = Int(offsete )
If offsete <1 Then offsete =1
step_line# = 1.0 /((sPt_x- ePt_x)*(sPt_x- ePt_x) + (sPt_y- ePt_y)*(sPt_y- ePt_y))^0.5 *offsete
local_step_line# = 0.0
local_step_line_2# = local_step_line# - step_line
While local_step_line<1.0
local_x# = Interpolate#(local_step_line, sPt_x, ePt_x)
local_y# = Interpolate#(local_step_line, sPt_y, ePt_y)
local_step_line_2 = local_step_line + step_line
If local_step_line_2 < 0.0 local_step_line_2 = local_step_line
local_x2# = Interpolate#(local_step_line_2, sPt_x, ePt_x)
local_y2# = Interpolate#(local_step_line_2, sPt_y, ePt_y)
switch = Not switch
If switch
Color R_ ,G_ ,B_
Line local_x , local_y ,local_x2 , local_y2
EndIf
local_step_line = local_step_line + step_line
Wend
End Function
__________________
Мой проект здесь
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
04.10.2015, 23:42
|
#5
|
Зануда с интернетом
Регистрация: 04.09.2005
Сообщений: 14,014
Написано 6,798 полезных сообщений (для 20,935 пользователей)
|
Ответ: Пунктирная окружность
Сообщение от DarkInside
Спасибо! Проверил, работает.
|
Пожалуйста. Зашёл в тред - думал будет не довольный коммент про лапидарность моего ответа. Уже думал набросать код именно с линиями (т.е. аппроксимацию окружности отрезками, а не кривыми [образованными точками] как сейчас) - а тут оказывается уже всё решилось. Обращайся.
По коду:
For q = 1 To 360 Step 4
upd: правомочное уравнение r^2=x^2+y^2 (упомянутое тобой) удобно использовать для определения принадлежности заданной точки указанной кривой (окружности). Само по себе оно корректно, просто, для данной задачи неудобно. Надо будет перебрать значения от 0 до r => получить два y => отражением получить из каждого ещё по точке -т.о. получить 4 точки. Проблема в том, что двигаться по х надо неравномерно (т.к. производная от sin, по которой изменяется прирост y - cos, а не прямая) если тебе нужно выдерживать постоянную длину штриха.
__________________
http://nabatchikov.com
Мир нужно делать лучше и чище. Иначе, зачем мы живем? tormoz
А я растила сына на преданьях
о принцах, троллях, потайных свиданьях,
погонях, похищениях невест.
Да кто же знал, что сказка душу съест?
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
05.10.2015, 06:03
|
#6
|
ПроЭктировщик
Регистрация: 17.07.2009
Сообщений: 182
Написано 51 полезных сообщений (для 71 пользователей)
|
Ответ: Пунктирная окружность
Функция окружность пунктиром с регулируемым шагом .
DarkInside , если у тебя не получилось , то посмотри этот
Код под спойлером :
Function StepCircle(Point_X# ,Point_Y# ,Radius# = 1,Offset = 4 , rr% = 255 ,gg% = 255 ,bb% = 255)
Local angle = 0 , trigger
If Offset < 1 Offset = 1
While angle < 360
If trigger
For thisAngle# = angle To angle +Offset Step 0.1
x# = Radius * Cos (thisAngle) + Point_X#
y# = Radius * Sin (thisAngle) + Point_Y#
WritePixel x,y, (rr*$10000+gg*$100+bb)
Next
EndIf
angle = angle + Offset
trigger = Not trigger
Wend
End Function
__________________
Мой проект здесь
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
06.10.2015, 10:17
|
#7
|
Разработчик
Регистрация: 08.08.2011
Сообщений: 505
Написано 191 полезных сообщений (для 369 пользователей)
|
Ответ: Пунктирная окружность
polopok, да я уже вроде как написал самопальную функцию. Но спасибо, посмотрю.
|
(Offline)
|
|
06.10.2015, 23:22
|
#8
|
.
Регистрация: 05.08.2006
Сообщений: 10,429
Написано 3,454 полезных сообщений (для 6,863 пользователей)
|
Ответ: Пунктирная окружность
Вот смотри, код доступен, рендер есть (ничего не нужно запускать, 1 клик по ссылке), кто хочет сейчас может код обновить и выложить ссылку на его ввариант. Удобно же!
Пунктирная окружность с регулируемым градусом дуги:
http://jsfiddle.net/bq6vvqch/
И еще версия с гарантированной последовательностью отступ > дуга, и чтобы не было где-то одного мелкого/большого отступа.
Также анимировано: http://jsfiddle.net/o8xkde88/1/
Можно еще сделать чтобы дуга могла удлиняться/укорачиваться, но гарантированно иметь одной длины отступы и другой единой длины дуги. Таким образом переход между разным числом дуг будет более плавный.
var canvas = document.getElementById('render'); var ctx = canvas.getContext('2d');
// step of 15 degrees in radians var step = 5 / (180 / Math.PI);
for(var i = 0; i < Math.PI * 2 / step; i += 2) { var a = i * step; ctx.beginPath(); ctx.arc(canvas.width / 2, canvas.height / 2, canvas.width / 2 - 8, a, a + step, false); ctx.stroke(); }
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
07.10.2015, 04:30
|
#9
|
ПроЭктировщик
Регистрация: 17.07.2009
Сообщений: 182
Написано 51 полезных сообщений (для 71 пользователей)
|
Ответ: Пунктирная окружность
ага ,нормально ...
Да ,вот что, в приведённой мною функции ,переменную offset проверить ,что она меньше длины круга (2 * Pi * Radius ).
__________________
Мой проект здесь
|
(Offline)
|
|
07.10.2015, 10:41
|
#10
|
Разработчик
Регистрация: 08.08.2011
Сообщений: 505
Написано 191 полезных сообщений (для 369 пользователей)
|
Ответ: Пунктирная окружность
Всем спасибо за примеры. За ссылку на сервис отдельное спасибо, удобная вещь.
Если бы сегодня у меня канвас не тормозил в хроме, было бы еще лучше. Хром вообще своей жизнью живет, сегодня вот канвас тормозит, на прошлой неделе элементы с одних сайтов переносились на другие (на скриншоте сам сайт уже закрыт, а подсказки с него остались на других сайтах).
Последний раз редактировалось DarkInside, 12.10.2015 в 18:45.
|
(Offline)
|
|
Ваши права в разделе
|
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 10:18.
|