un círculo de Bresenham en Scala (35)
El algoritmo de Bresenham tiene 2 puntos principales:
- trabaja sin pecado / cosin.
- solo calcula ¼ * ½ círculo, los otros puntos se encuentran reflejando.
Cómo hacerlo:
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
ESCRITURA
FF
GJ JG
IJ JI
GFE EFG
DCBABCD
2'1 '
- Solo calculamos los números de A en el cenit a I.
- El punto I está a 45 °, definido por x == y.
- La zona cero es donde está el +.
- La A en el cenit es el punto (x = 0, y = r), r = radio.
- Para dibujar un círculo cerrado, nos movemos en el sentido de las agujas del reloj (++ x), que está a la derecha (x + = 1) o hacia abajo al siguiente punto, (y- = 1).
- cada punto (x, y) en el círculo está r alejado del centro. Pitágoras dice: r² = x² + y².
- Esto huele a raíz cuadrada y ecuaciones con 2 soluciones, ¡pero cuidado!
- comenzamos en A y queremos saber si pintamos a continuación el punto de abajo o el punto de abajo a la derecha.
- calculamos para ambos puntos (x² + y²) y construimos para ambos la diferencia a r² (que por supuesto permanece constante).
- Como la diferencia puede ser negativa, le quitamos los abdominales.
- luego miramos qué punto está más cerca del resultado (r²), eo ipso más pequeño.
- dependiendo de eso dibujamos el vecino derecho o inferior.
- el punto tan encontrado
- 1 x, y se refleja
- 2 -x, y a la izquierda
- 3 y, x en la diagonal
- 4 -y, x desde allí a la izquierda
- todos esos puntos se reflejan nuevamente hacia el sur
- 1 'x, -y
- 2 '-x, -y
- 3 'y, -x
- 4 '-y, -x hecho.
Este no es el código de golf, pero todos esos números en la parte superior de las soluciones existentes me hicieron pensar que sí, así que pasé un tiempo inútil en jugar golf en mi solución. Por lo tanto, agregué un número inútil en la parte superior también. Es 11 veces que Pi se redondea.
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 pregunta sobre la fuente es decidida por el servidor web de los sitios y la configuración de su navegador. Ahora que estoy mirando es
'Droid Sans Mono',Consolas,Menlo,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace,serif
El tamaño de fuente es 12px. Información bastante inútil, si me preguntas, pero ¿quién lo hace?
Bonus: puntos suspensivos y salida de muestra:
La invocación es
scala BresenhamCircle SIZE RATIO
por ejemplo
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
Restringí el parámetro de relación para Int para que sea simple, pero se puede ampliar fácilmente para permitir flotantes.