วงกลม Bresenham ใน Scala (35)
Bresenham - อัลกอริทึมมี 2 ประเด็นสำคัญ:
- ทำงานโดยไม่บาป / โคไซน์
- คุณคำนวณเฉพาะวงกลม¼ * ½จุดอื่น ๆ จะพบได้โดยการมิเรอร์
ทำอย่างไร:
2 1
DCBABCD
GFE | EFG
IJ y | ---- JI
GJ | / JG
F | / | F
DE | r / | ED
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'
- เราคำนวณเฉพาะตัวเลขจาก A ใน zenit ถึง I
- จุดฉันอยู่ที่ 45 °กำหนดโดย x == y
- Ground zero คือเครื่องหมาย +
- A ในซีนิทคือจุด (x = 0, y = r), r = รัศมี
- ในการวาดวงกลมปิดเราเลื่อนตามเข็มนาฬิกา (++ x) ซึ่งอยู่ทางขวา (x + = 1) หรือลงไปที่จุดถัดไป (y- = 1)
- ทุกจุด (x, y) บนวงกลมนั้นอยู่ห่างจากศูนย์กลาง Pythagoras พูดว่า, r² = x² + y²
- มีกลิ่นเหมือนรากที่สองและสมการด้วย 2 วิธีแก้ไข แต่ระวัง!
- เราเริ่มต้นที่ A และต้องการทราบไม่ว่าเราจะวาดจุดถัดไปด้านล่างหรือจุดที่อยู่ด้านขวา
- เราคำนวณทั้งสองจุด (x² + y²) และสร้างทั้งความแตกต่างเป็นr² (ซึ่งคงที่แน่นอน)
- เนื่องจากความแตกต่างอาจเป็นค่าลบเราจึงนำเอบีเอสจากมัน
- จากนั้นเราดูว่าจุดใดอยู่ใกล้กับผลลัพธ์มากขึ้น (r²) eo ipso เล็กลง
- ขึ้นอยู่กับว่าเราวาดเพื่อนบ้านขวาหรือล่าง
- จุดที่พบดังนั้น
- 1 x, y ถูกมิร์เรอร์
- 2 -x, y ไปทางซ้าย
- 3 y, x ที่เส้นทแยงมุม
- 4 -y, x จากที่นั่นไปทางซ้าย
- คะแนนทั้งหมดเหล่านั้นสะท้อนกลับไปทางทิศใต้อีกครั้ง
- 1 'x, -y
- 2 '-x, -y
- 3 'y, -x
- 4 '-y, -x เสร็จแล้ว
นี่ไม่ใช่โค้ดกอล์ฟ แต่ตัวเลขทั้งหมดที่อยู่ด้านบนของโซลูชันที่มีอยู่ทำให้ฉันคิดว่าเป็นดังนั้นฉันจึงใช้เวลาอย่างไร้ประโยชน์ในการเล่นกอล์ฟโซลูชันของฉัน ดังนั้นฉันจึงเพิ่มหมายเลขที่ไร้ประโยชน์ที่ด้านบนด้วย มันคือ 11 คูณ Pi
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
ขนาดตัวอักษรคือ 12px ข้อมูลที่ไร้ประโยชน์ถ้าคุณถามฉัน แต่ใครทำ
โบนัส: วงรีและเอาต์พุตตัวอย่าง:
การภาวนาคือ
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 เพื่อให้ง่าย แต่สามารถขยายได้อย่างง่ายดายเพื่อให้มีการลอย