un cercle de Bresenham à Scala (35)
L'algorithme de Bresenham a 2 points principaux:
- fonctionne sans péché / cosinus.
- vous ne calculez que ¼ * ½ cercle, les autres points sont trouvés en miroir.
Comment faire:
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 pi x B 3 pi
CC
DE ED
FF
GJ JG
IJ JI
GFE EFG
DCBABCD
2'1 '
- Nous calculons uniquement les nombres de A dans le zénit à I.
- Le point I est à 45 °, défini par x == y.
- Le zéro du sol est l'endroit où se trouve le +.
- Le A dans le zénit est le point (x = 0, y = r), r = rayon.
- Pour dessiner un cercle fermé, nous nous déplaçons dans le sens des aiguilles d'une montre (++ x), ce qui est à droite (x + = 1) ou au point suivant, (y- = 1).
- chaque point (x, y) du cercle est r éloigné du centre. Pythagore dit, r² = x² + y².
- Cela sent la racine carrée et les équations avec 2 solutions, mais attention!
- nous commençons en A et voulons savoir si nous peignons ensuite le point en dessous ou le point en dessous à droite.
- nous calculons pour les deux points (x² + y²) et construisons pour les deux la différence à r² (qui reste bien sûr constante).
- puisque la différence peut être négative, on en retire les abdos.
- on regarde ensuite quel point est le plus proche du résultat (r²), eo ipso plus petit.
- en fonction de cela, nous dessinons le voisin droit ou inférieur.
- le point ainsi trouvé
- 1 x, y se reflète
- 2 -x, y à gauche
- 3 y, x en diagonale
- 4-y, x de là vers la gauche
- tous ces points se reflètent à nouveau au sud
- 1 'x, -y
- 2 '-x, -y
- 3 'y, -x
- 4 '-y, -x terminé.
Ce n'est pas du golf de code, mais tous ces chiffres en haut des solutions existantes m'ont fait penser que c'était le cas, alors j'ai passé un temps inutile à jouer au golf avec ma solution. J'ai donc ajouté un numéro inutile en haut aussi. C'est 11 fois Pi arrondi.
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"))
}
La question de police est décidée par le serveur Web des sites et les paramètres de votre navigateur. Maintenant que je regarde c'est
'Droid Sans Mono',Consolas,Menlo,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace,serif
La taille de la police est de 12 pixels. Des informations assez inutiles, si vous me demandez, mais qui le fait?
Bonus: ellipses et exemple de sortie:
L'invocation est
scala BresenhamCircle SIZE RATIO
par exemple
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
J'ai restreint le paramètre ratio pour Int pour qu'il reste simple, mais il peut facilement être élargi pour autoriser les flottants.