Scala'da bir Bresenham dairesi (35)
Bresenham algoritmasının 2 ana noktası vardır:
- günah / cosin olmadan çalışır
- sadece ¼ * ½ daireyi hesaplarsanız, diğer noktalar yansıtma ile bulunur.
Nasıl yapılır:
2 1
DCBABCD
GFE | EFG
IJ y | ---- JI
GJ | / JG
F | / | F
DE | r / | ED
C | / | C
B 4 | / | B 3
A + ------- A
B 4 'x B 3'
CC
DE ED
FF
GJ JG
IJ JI
GFE EFG
DCBABCD
2'1'
- Sadece zenit'teki A'dan I'ye kadar olan sayıları hesaplıyoruz.
- I noktası 45 ° 'dir, x == y ile tanımlanır.
- Sıfır noktası + işaretinin bulunduğu yerdir.
- Zenit içindeki A noktası (x = 0, y = r), r = yarıçaptır.
- Kapalı bir daire çizmek için sağa (x + = 1) veya bir sonraki noktaya (y- = 1) doğru saat yönünde (++ x) hareket ederiz.
- çember üzerindeki her nokta (x, y) merkezden r. Pisagor diyor ki, r² = x² + y².
- Bu karekök ve 2 çözüm ile eşitlik gibi kokuyor, ama dikkat!
- A'dan başlıyoruz ve aşağıdaki noktayı mı yoksa sağdaki noktayı mı boyadığımızı bilmek istiyoruz.
- her iki noktayı (x² + y²) hesaplıyoruz ve her ikisi de r² (elbette sabit kalır) farkı için inşa ediyoruz.
- fark negatif olabileceğinden, abs'i ondan alırız.
- o zaman sonuca (r²) daha yakın, eo ipso daha küçük görünüyoruz.
- buna bağlı olarak sağ veya alt komşuyu çiziyoruz.
- Bulunan nokta
- 1 x, y yansıtılır
- 2 -x, y sola
- Çaprazda 3 y, x
- 4 -y, x oradan sola
- tüm bu noktalar tekrar güneye yansıtılır
- 1 'x, -y
- 2 '-x, -y
- 3 'y, -x
- 4 '-y, -x bitti.
Bu kod golf değil, ama mevcut çözümlerin üstündeki tüm bu sayılar bana öyle olduğunu düşündürdü, bu yüzden çözümümü golf yapmak için gereksiz zaman geçirdim. Bu yüzden üstüne de işe yaramaz bir sayı ekledim. Pi yuvarlanmasının 11 katı.
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"))
}
Yazı tipi sorusu, siteler web sunucusu ve tarayıcı ayarlarınız tarafından belirlenir. Şimdi, bakıyorum ki
'Droid Sans Mono',Consolas,Menlo,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace,serif
Yazı tipi boyutu 12 pikseldir. Bana sorarsanız oldukça işe yaramaz bilgi, ama kim yapar?
Bonus: elipsler ve örnek çıktı:
Çağrı
scala BresenhamCircle SIZE RATIO
Örneğin
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 için oran parametresini basit tutmak için kısıtladım, ancak şamandıralara izin vermek için kolayca genişletilebilir.