коло Брезенем у Скалі (35)
Алгоритм Брезхема має 2 основні моменти:
- працює без гріха / косинуса.
- ви обчислюєте лише ¼ * ½ кола, інші точки знаходимо за допомогою дзеркального відображення.
Як це зробити:
2 1
DCBABCD
GFE | EFG
IJ y | ---- JI
GJ | / Дж
Ж | / | Ж
DE | р / | ЕД
C | / | С
Б 4 | / | Б 3
A + ------- A
B 4 'x B 3'
КК
DE ED
ФФ
GJ JG
IJ JI
GFE EFG
DCBABCD
2'1 '
- Ми обчислюємо лише числа від A в зеніті до I.
- Точка I знаходиться під 45 °, визначена x == y.
- Нуль землі - це місце, де є +.
- A в зеніті - точка (x = 0, y = r), r = радіус.
- Щоб намалювати замкнене коло, рухаємося за годинниковою стрілкою (++ x), що знаходиться праворуч (x + = 1) або вниз до наступної точки, (y- = 1).
- кожна точка (x, y) на колі знаходиться r від центру. Піфагор каже, r² = x² + y².
- Це пахне квадратними коренями та рівняннями з двома рішеннями, але будьте обережні!
- ми починаємо з А і хочемо знати, чи малюємо ми наступну точку внизу або точку внизу праворуч.
- ми обчислюємо обидві точки (x² + y²) і будуємо для обох різницю до r² (що залишається, звичайно, постійним).
- оскільки різниця може бути негативною, ми беремо з неї абс.
- тоді ми дивимося, яка точка ближче до результату (r²), eo ipso менша.
- залежно від того, що ми намалюємо правого або нижнього сусіда.
- так знайдений пункт
- 1 x, y отримує дзеркальне відображення
- 2 -x, y зліва
- 3 y, x по діагоналі
- 4 -y, x звідти ліворуч
- всі ці точки знову віддзеркалюються на південь
- 1 'х, -я
- 2 '-х, -я
- 3 'у, -х
- 4 '-y, -x зроблено.
Це не код гольфу, але всі ці цифри у верхній частині існуючих рішень змусили мене подумати, що це так, тому я витратив марний час на гольф на своє рішення. Тому я додав також марну цифру вгорі. Це 11 разів Пі округлений.
object BresenhamCircle extends App {
var count = 0
val r = args(0).toInt
// ratio > 1 means expansion in horizontal direction
val ratio = args(1).toInt
val field = ((0 to 2 * r).map (i=> (0 to 2 * r * ratio).map (j=> ' ').toArray)).toArray
def square (x: Int, y: Int): Int = x * x + y * y
def setPoint (x: Int, y: Int) {
field (x)(y*ratio) = "Bresenham"(count)
field (y)(x*ratio) = "Bresenham"(count)
}
def points (x: Int, y: Int)
{
setPoint (r + x, r + y)
setPoint (r - x, r + y)
setPoint (r + x, r - y)
setPoint (r - x, r - y)
}
def bresenwalk () {
var x = 0;
var y = r;
val rxr = r * r
points (x, y);
do
{
val (dx, dy) = { if (math.abs (rxr - square ((x+1), y)) < math.abs (rxr - square (x, (y-1))))
(1, 0)
else
(0, -1)
}
count = (count + 1) % "Bresenham".length
x += dx
y += dy
points (x, y)
}while ((x <= y))
}
bresenwalk ()
println (field.map (_.mkString ("")).mkString ("\n"))
}
Питання про шрифт вирішують веб-сервер веб-сайтів та налаштування вашого браузера. Тепер, коли я дивлюсь, це так
'Droid Sans Mono',Consolas,Menlo,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace,serif
Розмір шрифту - 12 пікселів. Досить непотрібна інформація, якщо ви запитаєте мене, але хто це робить?
Бонус: еліпси та вихідний зразок:
Виклик є
scala BresenhamCircle SIZE RATIO
наприклад
scala BresenhamCircle 10 2
s e r B r e s
h n e e n h
e m a a m e
e r r e
m m
h a a h
n n
s e e s
e e
r r
B B
r r
e e
s e e s
n n
h a a h
m m
e r r e
e m a a m e
h n e e n h
s e r B r e s
A ratio of 2 will print a circular shape for most fonts which happen to be about twice as tall than wide. To compensate for that, we widen by 2.
# As smaller value than 2 only 1 is available:
scala BresenhamCircle 6 1
erBre
aes sea
ah ha
e e
es se
r r
B B
r r
es se
e e
ah ha
aes sea
erBre
# widening it has more freedom:
scala BresenhamCircle 12 5
s e r B r e s
a h n e e n h a
B m m B
e r r e
e s s e
B r r B
a m m a
h h
n n
s e e s
e e
r r
B B
r r
e e
s e e s
n n
h h
a m m a
B r r B
e s s e
e r r e
B m m B
a h n e e n h a
s e r B r e s
Я обмежив параметр співвідношення для Int, щоб він був простим, але його можна легко розширити, щоб дозволити поплавці.