ข้างนอกมันมืดเหรอ? วาดแผนที่ดวงอาทิตย์!


71

ดาวที่อยู่ใกล้ที่สุดของเราคือดวงอาทิตย์ค่อนข้างงุนงง เวลาที่มันเพิ่มขึ้นและชุดขึ้นอยู่กับว่าคุณอยู่ที่ไหนและไม่ว่าจะเป็นฤดูหนาวหรือไม่

เราต้องการที่จะสามารถอนุมานได้หากดวงอาทิตย์ส่องแสงด้านนอกโดยไม่ต้องออกจากห้องใต้ดินของเรา - นี่คือเหตุผลที่เราต้องการแผนที่ดวงอาทิตย์ที่ทันสมัย ​​(แผนที่กลางวันหรือที่รู้จัก) คุณเป็นคนหนึ่งที่เขียนโปรแกรมที่สร้างขึ้นมา!

กฎ:โปรแกรมของคุณควรแสดงภาพ (ในรูปแบบที่รู้จัก) หรือการแสดงภาพ ASCII ของดาวเคราะห์ของเราโดยแสดง (ประมาณ) ส่วนใดที่สว่างจากดวงอาทิตย์ โปรแกรมของคุณจะต้องเป็นต้นฉบับและอยู่ในตัวเอง : คุณไม่ได้รับอนุญาตให้คัดลอกใช้รวมหรือโทรรหัสใด ๆ ยกเว้นห้องสมุดมาตรฐานของภาษาโปรแกรม

หากคุณยังไม่มีเงื่อนงำสิ่งที่ฉันกำลังพูดถึงนี่เป็นตัวอย่างจาก Wikipedia:

ตัวอย่างแผนที่ดวงอาทิตย์

นี่คือการประกวดความนิยม คุณควรสังเกตคำตอบของคุณว่าคุณกำลังพยายามทำสิ่งต่อไปนี้ (มีหลายทางเลือก):

  • ความถูกต้อง โปรดทราบว่ากฎบอกว่า 'การประมาณ' - ยิ่งการประมาณของคุณดีขึ้นเท่าไหร่คะแนนในหมวดหมู่นี้ก็จะยิ่งมากขึ้นเท่านั้น คุณสามารถตรวจสอบการดำเนินงานของคุณกับWolfram Alpha ของ , เวลาและวันที่ของหรือdie.net ของ

  • ฟังก์ชั่น ตัวอย่างเช่นสิ่งที่เกี่ยวกับการโต้ตอบ? ทำเครื่องหมายสถานที่เฉพาะหรือไม่ ทำแผนที่ดาวเคราะห์ดวงอื่น?

  • สุนทรียศาสตร์ การวาดทวีป คะแนนโบนัส ทวีปพื้นผิว? คะแนนโบนัส บนโลก 3 มิติ? มีเมฆไหม ดาว? ดาวที่ถูกต้อง ? คะแนนโบนัสจำนวนมาก และอื่น ๆ

  • ใช้เทคโนโลยีที่ผิดธรรมดาเก่าหรือผิดธรรมดา แน่นอนว่าคุณสามารถชนะสิ่งนี้ใน Mathematica แต่คุณคิดว่าจะใช้m4หรือไม่? SQL? ออกมา? การประกอบ x86

  • สนุก. ต้องการใช้แผนที่ฉาย Dymaxionหรือไม่ ไปข้างหน้า!

  • รหัสย่อ นี่คือ Code Golf SE หลังจากทั้งหมด

มีความสุข!


3
@PeterTaylor น่าจะเป็น! ฉันคิดว่าคุณไม่จำเป็นต้องทำแสงสว่าง: คุณสามารถวาดโลก 3 มิติและหมุนเพื่อให้ส่วนแสง (และไม่มีอะไรอื่น) หันหน้าไปทางผู้ชม มันจะไม่แสดงตอนกลางคืนของโลก แต่ก็ไม่จำเป็น
Wander Nauta

30
อีกทางเลือกหนึ่งคือติดตั้ง windows (ในห้องใต้ดินฉันหมายถึง.)
คลื่นไส้ ossifrage

2
@qwr ฉันจะประกอบ x86 m4ทุกวันในสัปดาห์สำหรับงานนี้ ...
Wander Nauta

3
นอกจากนี้: "ดวงอาทิตย์ค่อนข้างงุนงงเพราะมันขึ้นและตกตามเวลาต่างกัน" ความผิดของดวงอาทิตย์อย่างแน่นอน: P
qwr

2
@qwr เคยคิดเกี่ยวกับการคำนวณเวลา / วันที่ง่ายแค่ไหนถ้าเรามี 10 ชั่วโมง 10 วัน 10 สัปดาห์ 10 เดือนและ 10 เดือนปีและดวงอาทิตย์อยู่ระหว่าง t = 0 และ t = 5? แต่ไม่ดวงอาทิตย์ต้องไปแสดงหน้าน่าเกลียดในสถานที่ต่าง ๆ ในเวลาต่าง ๆ และใช้เวลานานเกินไปในการเดินทางรอบโลก ไม่มีส่วนร้องเรียนใด ๆ น่าสะอิดสะเอียน
Wander Nauta

คำตอบ:


89

Haskell - รหัสคุณภาพต่ำ

ฉันเหนื่อยมากเมื่อฉันเขียนสิ่งนี้

ฉันอาจไปไกลเกินไปกับความคิดในการฉายภาพต่อไปนี่คือภาพที่โปรแกรมใช้ โดยพื้นฐานแล้วชอบฉายโลกลงบนลูกบาศก์แล้วคลี่มันออก นอกจากนี้ในการฉายภาพนี้เงาทำจากเส้นตรง
โปรแกรมใช้วันที่ / เวลาปัจจุบันและส่งออกไฟล์ PPM บน stdout

import Data.Time.Clock
import Data.Time.Calendar
import Control.Applicative
import Data.Fixed
import Data.Maybe

earth :: [[Int]]
earth = [[256],[256],[256],[256],[64,1,1,2,1,5,14,16,152],[56,19,3,27,1,6,50,1,2,1,90],[53,6,1,11,2,36,26,1,2,1,16,2,1,1,2,1,24,4,66],[47,2,5,14,4,35,22,7,54,2,1,3,60],[38,1,2,2,3,1,6,1,2,1,2,7,6,1,1,33,24,3,3,1,56,2,60],[34,2,1,4,2,1,3,1,1,3,3,2,15,3,3,29,57,5,19,1,2,11,17,1,1,1,34],[40,3,10,2,1,8,16,27,54,3,18,19,18,1,36],[33,6,5,3,2,3,1,3,2,2,1,5,16,21,1,2,53,2,10,1,6,19,1,7,4,3,9,2,33],[32,4,1,7,1,2,3,2,1,1,3,11,14,23,53,2,10,3,1,4,2,33,7,7,29],[8,5,25,10,5,3,2,14,10,2,1,18,1,2,31,6,18,1,7,4,1,60,22],[5,18,2,12,3,5,1,3,2,2,1,3,4,2,3,8,11,18,30,13,9,2,7,3,2,72,1,6,8],[4,36,2,1,1,4,3,7,1,4,3,9,8,15,34,18,2,2,2,17,1,78,4],[4,1,1,27,3,1,1,24,6,3,1,1,1,3,6,13,13,1,20,15,1,4,1,104,1],[3,31,1,24,1,2,4,8,10,9,12,6,18,7,3,7,1,1,2,99,3,2,2],[7,50,2,2,2,1,2,1,3,2,1,2,10,7,15,1,20,7,2,111,7,1],[4,35,1,15,9,1,1,3,4,1,12,5,34,8,3,110,10],[4,9,1,2,1,37,12,6,16,3,34,8,3,96,5,6,13],[6,6,1,1,8,32,12,6,3,1,49,9,4,2,1,86,1,3,4,2,19],[9,2,1,1,11,31,11,11,40,1,8,1,2,4,5,83,12,3,20],[8,1,16,33,9,11,39,2,8,1,2,3,3,83,13,5,19],[28,33,5,12,40,2,7,3,6,62,1,19,13,5,20],[27,36,2,15,34,3,2,2,6,71,1,22,11,2,22],[30,21,1,11,2,16,33,3,1,4,2,72,1,24,1,1,9,1,23],[31,21,1,26,39,4,1,98,1,1,33],[31,42,7,1,40,100,1,1,33],[33,25,2,15,4,4,35,102,36],[33,23,2,1,2,14,8,1,36,27,1,9,1,61,3,1,33],[33,26,5,14,42,10,1,11,2,2,2,7,3,5,1,9,1,44,38],[33,26,1,2,1,9,2,1,45,7,1,2,2,9,8,6,2,6,1,53,4,2,33],[33,26,1,4,1,6,44,8,6,2,3,7,9,5,3,56,1,1,4,3,33],[33,37,45,8,7,2,3,6,2,4,3,6,4,53,43],[33,36,46,6,6,1,4,1,2,2,3,16,3,47,1,5,8,2,34],[34,34,46,7,11,1,3,2,2,16,3,45,6,2,8,1,35],[34,33,48,5,11,1,4,1,4,16,2,49,3,2,6,2,35],[35,32,54,8,17,60,5,2,4,4,35],[36,30,50,12,18,60,8,2,1,1,38],[38,27,50,15,16,61,6,2,41],[38,25,51,18,3,4,6,62,6,1,42],[39,1,1,17,2,3,51,93,49],[40,1,1,11,9,2,49,31,1,10,2,50,49],[40,1,2,9,10,2,48,33,1,10,2,49,49],[41,1,2,8,11,1,47,34,2,10,5,44,50],[42,1,2,7,58,36,1,11,2,1,8,36,51],[46,6,58,36,2,15,7,34,2,1,49],[46,6,12,2,43,38,2,14,7,2,1,12,1,15,55],[46,6,5,2,7,2,41,38,2,14,10,10,4,10,59],[47,6,3,3,10,3,38,37,3,12,11,8,6,9,2,1,57],[49,10,51,38,3,9,13,7,8,9,9,2,48],[51,7,51,40,2,7,15,6,9,1,1,8,8,2,48],[55,7,47,41,1,6,17,4,12,8,8,1,49],[57,5,47,42,1,2,20,4,13,8,9,1,47],[59,3,8,1,38,43,22,4,13,1,2,4,10,2,46],[60,2,6,5,38,41,1,4,18,3,17,3,10,2,46],[61,2,1,1,2,3,1,7,34,45,18,2,18,1,60],[63,1,2,13,33,44,22,1,12,1,16,3,45],[66,14,33,43,22,1,13,1,14,1,1,1,46],[66,18,30,4,1,1,5,30,34,1,2,2,9,3,50],[66,19,43,27,34,2,2,1,7,3,52],[65,20,43,26,36,2,1,2,5,5,51],[65,21,42,24,39,3,4,7,2,1,1,1,1,1,44],[56,1,7,23,41,16,1,6,41,2,4,6,7,1,44],[64,25,39,16,1,5,42,3,4,5,2,1,8,1,2,1,37],[64,29,35,22,43,3,1,1,2,3,2,1,1,1,2,1,1,2,1,7,6,1,27],[63,31,35,20,45,2,11,1,9,7,4,2,26],[64,32,34,19,67,1,2,6,1,2,28],[65,31,34,12,1,6,48,4,18,6,31],[65,31,34,19,54,2,1,2,2,1,10,2,2,1,30],[66,29,36,14,1,3,57,1,19,2,28],[66,29,36,14,1,4,63,1,42],[67,27,36,15,1,4,63,5,3,2,33],[67,26,37,20,5,2,53,2,1,4,4,2,33],[68,25,37,20,4,3,52,9,3,3,32],[70,23,36,20,3,4,53,11,1,4,31],[71,22,37,17,5,4,51,18,31],[71,22,37,16,7,3,50,20,30],[71,21,39,15,6,3,5,1,42,24,29],[71,20,40,15,6,3,47,26,28],[71,17,43,15,6,3,46,28,27],[71,16,45,13,8,1,48,27,27],[71,16,45,12,58,28,26],[71,16,45,12,58,28,26],[70,16,47,10,59,28,26],[70,15,49,9,60,27,26],[70,14,50,7,62,7,6,13,27],[70,13,51,6,63,6,8,1,1,9,28],[70,10,138,10,28],[69,12,139,7,29],[69,11,141,5,19,3,8],[69,8,167,3,9],[69,8,166,1,1,1,10],[70,5,149,2,16,2,12],[69,6,166,3,12],[68,6,166,2,14],[68,5,166,3,14],[68,6,182],[67,6,183],[68,4,184],[68,4,6,2,176],[69,4,183],[70,5,20,1,160],[256],[256],[256],[256],[256],[256],[78,1,1,1,109,1,65],[75,2,115,1,23,1,39],[72,3,80,1,1,5,20,42,32],[74,1,70,1,4,21,5,52,2,1,25],[67,1,2,2,1,4,64,28,4,62,21],[69,9,34,1,1,1,1,1,1,1,2,48,3,69,15],[50,1,5,1,16,5,34,130,14],[32,1,1,2,4,1,3,1,4,29,32,128,18],[20,1,1,54,32,128,20],[17,49,34,137,19],[9,1,2,54,20,4,6,143,17],[16,51,18,5,10,135,21],[11,1,4,54,25,140,21],[12,66,4,155,19],[12,231,13],[0,6,9,5,2,234],[0,256],[0,256]]
main = do
    header
    mapM_ line [0..299]
    where
        header = do
            putStrLn "P3"
            putStrLn "# Some PPM readers expect a comment here"
            putStrLn "400 300"
            putStrLn "2"
        line y = mapM_ (\x -> pixel x y >>= draw) [0..399]
            where
                draw (r, g, b) = putStrLn $ (show r) ++ " " ++ (show g) ++ " " ++ (show b)
                pixel x y = fromMaybe (return (1, 1, 1)) $
                    mapRegion (\x y -> (50, -x, y)) (x - 50) (y - 50)
                    <|> mapRegion (\x y -> (-x, -50, y)) (x - 150) (y - 50)
                    <|> mapRegion (\x y -> (-x, y, 50)) (x - 150) (y - 150)
                    <|> mapRegion (\x y -> (-50, y, -x)) (x - 250) (y - 150)
                    <|> mapRegion (\x y -> (y, 50, -x)) (x - 250) (y - 250)
                    <|> mapRegion (\x y -> (y, -x, -50)) (x - 350) (y - 250)
                    where
                        mapRegion f x y = if x >= -50 && y >= -50 && x < 50 && y < 50 then
                            Just $ fmap (worldMap . shade) getCurrentTime
                            else Nothing
                                where
                                    t (x, y, z) = (atan2 y z) / pi
                                    p (x, y, z) = asin (x / (sqrt $ x*x+y*y+z*z)) / pi * 2
                                    rotate o (x, y, z) = (x, y * cos o + z * sin o, z * cos o - y * sin o)
                                    tilt o (x, y, z) = (x * cos o - y * sin o, x * sin o + y * cos o, z)
                                    shade c = ((t $ rotate yearAngle $ tilt 0.366 $ rotate (dayAngle - yearAngle) $ f x y)) `mod'` 2 > 1
                                        where
                                            dayAngle = fromIntegral (fromEnum $ utctDayTime c) / 43200000000000000 * pi + pi / 2
                                            yearAngle = (fromIntegral $ toModifiedJulianDay $ utctDay c) / 182.624 * pi + 2.5311
                                    worldMap c = case (c, index (t $ f x y) (p $ f x y)) of
                                            (False, False) -> (0, 0, 0)
                                            (False, True) -> (0, 0, 1)
                                            (True, False) -> (2, 1, 0)
                                            (True, True) -> (0, 1, 2)
                                            where
                                                index x y = index' (earth !! (floor $ (y + 1) * 63)) (floor $ (x + 1) * 127) True
                                                    where
                                                        index' [] _ p = False
                                                        index' (x:d) n p
                                                            | n < x = p
                                                            | otherwise = index' d (n - x) (not p)

ถูกต้องแล้ว - whereรหัสสามเหลี่ยม, ซ้อนกันcase, การใช้งาน IO ที่ไม่ถูกต้อง


นั่นเป็นงานของอัจฉริยะบิด ข้อเสนอแนะหนึ่งfromIntegral (fromEnum $ utctDayTime c)คือ neater (realToFrac $ utctDayTime c)เป็น (ฉันเพิ่งเรียนรู้สิ่งนี้ในขณะที่เขียนคำตอบของฉัน)
bazzargh

8
ฉันสามารถดู. gif ได้ทั้งวัน
MikeTheLiar

mnlip ฉันเห็นด้วยกับ @mikeTheLiar คุณควรฝัง gif นั้นไว้ที่ด้านบนสุดของคำตอบคุณจะได้รับคะแนนทั้งหมด
bazzargh

1
ฉันโหวตให้กับ gif สุดป่วน นั่นเป็นเพียงวิธีบิดดูโลก
อัลเลนกูล

trippy เล็กน้อยเลยทีเดียว
Pharap

61

Haskell ในหมวดหมู่ 'เพราะมีอยู่'

ฉันอยากรู้อยากเห็นดังนั้นฉันจึงเขียน สูตรมีความแม่นยำพอสมควร [1] แต่หลังจากนั้นฉันไปและใช้งาน ascii art แทนแผนที่ Plate Carréeที่เหมาะสมเพราะดูดีกว่า (วิธีที่ฉันแปลงพิกเซลเป็น lat / long ใช้งานได้อย่างถูกต้องสำหรับ Plate Carrée)

import Data.Time
d=pi/180
tau=2*pi
m0=UTCTime(fromGregorian 2000 1 1)(secondsToDiffTime(12*60*60))
dark lat long now =
  let
    time=(realToFrac$diffUTCTime now m0)/(60*60*24)
    hour=(realToFrac$utctDayTime now)/(60*60)
    mnlong=280.460+0.9856474*time
    mnanom=(357.528+0.9856003*time)*d
    eclong=(mnlong+1.915*sin(mnanom)+0.020*sin(2*mnanom))*d
    oblqec=(23.439-0.0000004*time)*d
    ra=let num=cos(oblqec)*sin(eclong)
           den=cos(eclong) in
       if den<0 then atan(num/den)+pi else atan(num/den)
    dec=asin(sin(oblqec)*sin(eclong))
    gmst =6.697375+0.0657098242*time+hour
    lmst=(gmst*15*d)+long
    ha=(lmst-ra)
    el=asin(sin(dec)*sin(lat)+cos(dec)*cos(lat)*cos(ha))
  in
  el<=0

td x = fromIntegral x :: Double
keep="NSEW"++['0'..'9']
pixel p dk=if dk && p`notElem`keep then if p==' ' then '#' else '%' else p
showMap t= do
  let w=length(worldmap!!0)
      h=length worldmap
  putStrLn (worldmap!!0)
  putStrLn (worldmap!!1)
  mapM_(\y->do
           mapM_(\x->let
                    lat=(0.5-td y/td h)*pi
                    long=(0.5-td x/td w)*tau
                    in
                     putStr [pixel ((worldmap!!(y+2))!!x) (dark lat long t)]) [0..(w-1)]
           putStrLn "") [0..(h-4)]
  putStrLn (last worldmap)

main = do {t<-getCurrentTime; showMap t}

worldmap=[
 "180 150W  120W  90W   60W   30W  000   30E   60E   90E   120E  150E 180",
 "|    |     |     |     |     |    |     |     |     |     |     |     |",
 "+90N-+-----+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+",
 "|          . _..::__:  ,-\"-\"._       |7       ,     _,.__             |",
 "|  _.___ _ _<_>`!(._`.`-.    /        _._     `_ ,_/  '  '-._.---.-.__|",
 "|.{     \" \" `-==,',._\\{  \\  / {)     / _ \">_,-' `                mt-2_|",
 "+ \\_.:--.       `._ )`^-. \"'      , [_/(                       __,/-' +",
 "|'\"'     \\         \"    _L       oD_,--'                )     /. (|   |",
 "|         |           ,'         _)_.\\\\._<> 6              _,' /  '   |",
 "|         `.         /          [_/_'` `\"(                <'}  )      |",
 "+30N       \\\\    .-. )          /   `-'\"..' `:._          _)  '       +",
 "|   `        \\  (  `(          /         `:\\  > \\  ,-^.  /' '         |",
 "|             `._,   \"\"        |           \\`'   \\|   ?_)  {\\         |",
 "|                `=.---.       `._._       ,'     \"`  |' ,- '.        |",
 "+000               |    `-._        |     /          `:`<_|h--._      +",
 "|                  (        >       .     | ,          `=.__.`-'\\     |",
 "|                   `.     /        |     |{|              ,-.,\\     .|",
 "|                    |   ,'          \\   / `'            ,\"     \\     |",
 "+30S                 |  /             |_'                |  __  /     +",
 "|                    | |                                 '-'  `-'   \\.|",
 "|                    |/                                        \"    / |",
 "|                    \\.                                            '  |",
 "+60S                                                                  +",
 "|                     ,/           ______._.--._ _..---.---------._   |",
 "|    ,-----\"-..?----_/ )      _,-'\"             \"                  (  |",
 "|.._(                  `-----'                                      `-|",
 "+90S-+-----+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+",
 "Map 1998 Matthew Thomas. Freely usable as long as this line is included"]

ตัวอย่างผลลัพธ์จากช่วงเวลาที่น่าสนใจของปี (เราอยู่ใกล้ Equinox ดังนั้น Blobs รูปสี่เหลี่ยมผืนผ้าของ Wander Nauta นั้นมีความแม่นยำอย่างเป็นธรรม :)) - นี่สำหรับ Jan 16 13:55:51 UTC 2014:

180 150W  120W  90W   60W   30W  000   30E   60E   90E   120E  150E 180
|    |     |     |     |     |    |     |     |     |     |     |     |
%90N%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%##########%#%%%%%%%%##%%%%%%%#######%7#######%#####%%%%%#############%
%##%%%%%#%#%%%%%%%%%%%%%%####%########%%%#####%%#%%%##%##%%%%%%%%%%%%%%
%%%#####%#%#%%%%%%%%%%%##%##%#%%#####%#%#%%%%%%#%################%%%2%%
%#%%%%%%%#######%%%#%%%%%#%%######, [_/(         ##############%%%%%%#%
%%%%#####%#########%####%%#####  oD_,--'            ####%#####%%#%%###%
%#########%###########%%#####    _)_.\\._<> 6        ######%%%#%##%###%
%#########%%#########%######    [_/_'` `"(             ###%%%##%######%
%30N#######%%####%%%#%#####     /   `-'"..' `:._       ###%%##%#######%
%###%########%##%##%%#####     /         `:\  > \  ,-^. #%%#%#########%
%#############%%%%###%%###     |           \`'   \|   ?_)##%%#########%
%################%%%%%%%#      `._._       ,'     "`  |' %%#%%########%
%000###############%####`-._        |     /          `:`<_%%%%%%######%
%##################%####    >       .     | ,          `=.%%%%%%%#####%
%###################%%#    /        |     |{|              %%%%%#####%%
%####################%#  ,'          \   / `'            ,"#####%#####%
%30S#################%  /             |_'                |  %%##%#####%
%####################% |                                 '-'##%%%###%%%
%####################|/                                      ##%####%#%
%####################\.                                       #####%##%
%60S################                                          ########%
%##################   ,/           ______._.--._ _..---.-------%%%%###%
%####%%%%%%%%%%%%%--_/ )      _,-'"             "                ##%##%
%%%%%###########       `-----'                                    ##%%%
%90S%%%%%%%%%----+-----+-----+----+-----+-----+-----+-----+-----+----%%
Map 1998 Matthew Thomas. Freely usable as long as this line is included

[1] เหมือนกันกับที่คุณพบที่อื่นยกเว้นไม่มีงานพิเศษที่จะรักษาองศาระหว่าง 0 และ 360, ชั่วโมงระหว่าง 0 ถึง 24 และเรเดียนระหว่าง 0 ถึง 2pi ฉันคิดว่าสิ่งเหล่านี้เป็นของสะสมจากวันที่เราใช้กฎสไลด์ ฟังก์ชั่นตรีโกณมิติทำงานได้ดีนอกช่วงเหล่านั้น ...


7
ยอดเยี่ยม! ฉันชอบที่คุณยังสามารถดูแผนที่ผ่านทาง 'มืด' นอกจากนี้คณิตศาสตร์ก็ดูแข็งแรงเช่นกัน คุณสามารถเพิ่มวันที่ที่คุณใช้เป็นตัวอย่างเพื่อให้คนอื่นสามารถเปรียบเทียบการแก้ปัญหาของพวกเขากับคุณ?
Wander Nauta

ฉันเห็นว่าคุณได้เพิ่มวันที่แล้วขอบคุณ!
Wander Nauta

1
อ๋อ ฉันชอบที่ในภาพคุณสามารถเห็นได้อย่างชัดเจนว่าเป็นฤดูหนาวในซีกโลกเหนือทำให้ง่ายต่อการเชื่อในวันนั้น! ฉันดีใจที่คุณโพสต์คำตอบก่อนหน้าฉันช่วยฉันไม่รู้จบที่พยายามทำเวอร์ชันกอล์ฟไม่มีทางที่ฉันจะเอาชนะคุณได้
bazzargh

39

นิเมชั่น

.

Bash, 882 * ตัวละคร

นี้เป็นรายการที่สองของฉันเวลานี้ในสุนทรียศาสตร์ , เทคโนโลยีแปลก , สนุกและรหัสสั้นประเภท มันได้แรงบันดาลใจจากการเข้าร่วมของ Ram Narasimhan และความคิดเห็นของ Peter Taylor

สคริปต์จะสร้างพื้นผิวที่มีความละเอียดต่ำของโลกเป็นครั้งแรกซึ่งรวมเป็นข้อมูลที่เข้ารหัสด้วย base64 จากนั้นจะสร้างฉาก PovRay 24 ฉากที่มีทรงกลมที่มีพื้นผิวนั้นแต่ละฉากหมุนไปที่ 'เผชิญหน้ากับดวงอาทิตย์' ในที่สุดเฟรมจะรวมกันเป็นภาพเคลื่อนไหว GIF โดยใช้ ImageMagick ซึ่งหมายความว่าคุณจะต้องติดตั้ง PovRay และ ImageMagick เพื่อให้สคริปต์ทำงานได้ - อย่าลังเลที่จะเพิกเฉยต่อรายการนี้หากคุณคิดว่าควรตัดสิทธิ์รายการนี้

เช่นเดียวกับรายการของ Ram และรายการแรกของฉันนี่ไม่ได้หมายถึงการเปลี่ยนแปลงตามฤดูกาลซึ่งหมายความว่ามันไม่แม่นยำมากนัก อย่างไรก็ตามมันสั้นกว่าสวยกว่าและแม่นยำกว่ารายการแรกของฉันและไม่เหมือนกับรายการของ Ram ข้อมูลแผนที่และรหัสสำหรับสร้างภาพเคลื่อนไหว GIF นั้นรวมอยู่ด้วย

                               echo '
                    iVBO  Rw0KGgoAAAA       NS
              UhE  U g      AAAEgAAAA                     kAQMAAAAQFe4lAAAABlB
    MVEUAFFwAbxKgAD63 AAAA   AWJLR0                  QAiAUdSAAAAAlwSFlzAAALEwAACx
 MB AJqcGAAAAAd0SU1FB9  4DE  hUWI   op      Fp5MAAADDSURBVBhXrcYhTsNQGADgr3ShE4Qi
    h4BeYQFBgqAJN8Lh    +r                jBb rArIJHPobgAgkzgeSQkVHT7MWThAHzq44
           /j/jezy6jSH  M6fB           gd  9T Nbxdl99R4Q+XpdNRISj4dlFRCz
            oI11FxIpup4uIRDe5           fokp0Y2W25jQFDfrGNGsDNsoqBaGj34D2
             bA7TcAwnmRoDZM             5tLkePUJb6uIT2rEq7hKaUhUHCXWpv7Q
             PqEv1rsuoc7X              RbV Bn2d   kGTYKMQ3C7H8z2+wc/eMd S
              QW39v8kAAA               AA      SUVOR K5CYII='|base64 \
               -di>t;for                X in     {0..23};do R=$((90-(\
                $X*15)                )); echo "camera{location <0,
                 0,                   -5> angle 38 }    light_source{
                  <0,0,               -1000> rgb < 2,2,   2>} sphere
                    {<0              ,0,0> 1 pigment      {
                      /**/            image_map{\"t\"        map_type
                        1}}                rotate           <0,$R,0>
                        }">s               ;povray             +Is +H300\
                        +Of$X.png          +W400
                        mogrify            -fill                     white    \
                        -annotate           +0+10                    "$X:00" \
                         -gravity           south                    f$X.png
                         done;              convert                -delay     \
                         100                -loop                 0 $(ls f*  \
                         |sort               -V)                  ani.gif
                        exit;

เป็นโบนัสนี่คือ GIF ที่ใช้อิมเมจ Blue Marble ของ NASA แทนที่จะเป็นพื้นผิวแบบ 1 บิตที่ประหยัดพื้นที่นั่นคือผลลัพธ์ที่ได้จะดูเหมือนเป็นอย่างไรโดยไม่มีการ จำกัด ขนาด: http://i.imgur.com/AnahEIu.gif

*: 882 ตัวอักษรไม่นับพื้นที่ว่างตกแต่งรวม 1872 ตัวอักษร


5
+1 ที่ทำให้ทุกอย่างอยู่ในตัวเอง และสำหรับการสร้างรหัสอ้างอิงตนเองซึ่งดูเหมือนว่าแผนที่โลก ทำได้ดีมาก
Ram Narasimhan

1
โอ๊ะ! หลายรายการ ตอนนี้ฉันไม่มีข้อแก้ตัวที่จะไม่ทำคนบ้า ...
bazzargh

1
ไม่สบาย! รักมัน
pandubear

เฮ้ฉันรู้แล้วว่าตอนนี้ฉันสามารถใช้การจัดรูปแบบของรหัสเองเป็นแหล่งที่มาสำหรับแผนที่โลก (พร้อมช่องว่าง = มหาสมุทรทุกอย่างอื่น = พื้นดิน) และได้รับการแก้ไขที่ดีขึ้นโดยใช้ตัวอักษรน้อยลง ดี ...
พเนจร Nauta

2
ดูเหมือนว่า Minecraft
Kaz Wolfe

25

ฉันตัดสินใจที่จะเริ่มการแข่งขันด้วยการเข้าร่วมของตัวเองในรหัสย่อหมวดมีความยาวอักขระ 923 ตัวไม่นับบรรทัดใหม่

C: 923 ตัวอักษร

นี่คือรหัส:

i;j;w=160;f=40;t;b;p;s;e;k;d=86400;q=599;
char* m="M('+z EDz :!#\"!*!8S$[\"!$!#\"\")\"!3R)V$'!!()1M./!F)\"!!!!)'/GE5@\"\"!&%.3&,Y$D\"!!%$)5i\"\"\"F\"%&&6%!e'A#!#!!#&$5&!f&A'$*\"5&!c-#'3''8\"$!!#\"U'\"=5$'8#$$\"S(#=7!*5\"!\"#['!A@6#!^H=!#6bH;!!!\"6_!!I;<&!&\"!!$\"F\"!I8;&\"#\"$&#\"C#\"I7<%#!\"/\"BP5=$*,\"=#\"$!L4A%&\"\"G\"\"\"#M1@)*F\"%P/@,!N#!S(E;!@W'E=!!!<Y&D7!&!\"$7\\$D8!)$4_$C8!('&#&!!a&@9!&(%$&g$>9!$*#(%h\">:!!-\"(%&!b!$&5:!\"+\"(!!#$!!!c+5<-!'!'!#!e)5:.!(!&!\"\"e,:25!!!\"!\"\"h-;07#\"$h.9/:\"\"$!!#\"a17-;'!\"$!!\"$!X46,<\"%\"&$\\45,>#&!$$#!W45,C!!!'!\"!$!V26,H\"#!$!\"!\"!S17-#!A!!#\"!_07,\"#A&!\"`.7+#\"A*.!Q.7*$\">/^-9)$\"=0^*<)$!>1]*<(D1])>&E2\\)>&F&!)\\)@#G$%(\\'w%]'x#,\"P%z .\"P%z .!R$z -\"S$z b#z c#z d#z 3";
main(){
t=(time(0)%d*160)/d;
printf("P2\n%d 62\n5\n",w);
for(;i<q;i++){
for(j=m[i]-' ';j>0;j--){
p=k%w,s=(t-f),e=(t+f);
printf("%c ","1324"[b*2+((p>s&&p<e)||(p>s+w&&p<e+w)||(p>s-w&&p<e-w))]);
k++;
}
b=!b;
}
}

นี่คือวิธีการทำงาน:

บิตแมปที่หยาบของโลก*ถูกเข้ารหัสความยาวรันเป็นสตริง อักขระทุกตัวในสตริงแสดงถึงการวิ่งของพิกเซลที่ดินหรือพิกเซลทะเล ทะเลที่ทอดยาวจะถูกแบ่งออกเป็นทะเลจากนั้นตามด้วย 0 พิกเซลของแผ่นดินและทะเลอื่น ๆ เพื่อหลีกเลี่ยงการรวมอักขระที่ไม่สามารถพิมพ์ได้ในสตริง สคริปต์ Python ที่ฉันเขียนเพื่อแปลงไฟล์ PBM เป็นรูปแบบนี้อยู่ที่นี่ที่นี่

จากนั้นฉันใช้ time () เพื่อดูว่ามีกี่วินาทีที่ผ่านมาใน Greenwich ตั้งแต่เที่ยงคืนวันที่ 1 มกราคม 1970 ฉันโมดูโล่ที่จะค้นหาว่ามีกี่วินาทีที่ผ่านไปในวันนี้โดยใช้ข้อมูลนั้นเพื่อวางตำแหน่งส่วนแสงของแผนที่เพิ่มเติม - หรือน้อยกว่านั้น (ฉันหวังว่า)

ความถูกต้องเป็นเรื่องตลก ไม่มีคณิตศาสตร์เลย รหัสสมมติว่าโลกเป็นรูปทรงกระบอก (กลางวัน - กลางคืน) ที่ดวงอาทิตย์อยู่เหนือเส้นศูนย์สูตร (ไม่มีฤดูร้อน / ฤดูหนาว) และคุณชอบสีเทา (ไม่มีสี)

ในด้านบวกฉันวาดทวีป

ผลลัพธ์อยู่ในรูปแบบ Portable Graymap (PGM) ซึ่งสามารถแปลงเป็น PNG ด้วยบางอย่างเช่น ImageMagick หรือ GIMP

นี่เป็นตัวอย่างเอาต์พุตแปลงเป็น PNG ( เวอร์ชั่นที่ใหญ่กว่า ):

ตัวอย่างผลลัพธ์

*: ทั้งโลกยกเว้นแอนตาร์กติกา แต่ใครจะอยู่ที่นั่น ...


1
การส่งออกที่ดีมันจะดีกว่าถ้าพื้นที่มืดโค้งแม้ว่า
qwr

1
อ้อ! การที่เอาท์พุทเป็นโค้งหมายความว่าคุณจะต้องทำตรีโกณมิติสักหน่อยซึ่งจะทำให้นานขึ้น (หรือฉันเดาว่าคุณสามารถปัดเศษมุมที่ถูกต้องเพื่อทำให้มันดูถูกต้อง ... )
Wander Nauta

1
@WanderNauta จะมีนกเพนกวินโกรธจำนวนมากที่จะรู้สึกโกงว่าคุณไม่ได้คำนึงถึงพวกเขา ...
WallyWest

@WallyWest หากคุณอาศัยอยู่บนเสาเหมือนเพนกวินของคุณคุณไม่จำเป็นต้องใช้โปรแกรมนี้ - ดวงอาทิตย์เที่ยงคืนและทั้งหมด
Wander Nauta

22

Haskell - ถึงเวลาค้อนแล้ว

ป้อนคำอธิบายรูปภาพที่นี่

ฉันทำอีกอันหนึ่ง ดัดแปลงมาจากรุ่นก่อนหน้าของฉันชิ้นนี้ใช้การฉายภาพเฉียง เพื่อแสดงเสาทั้งสองในเวลาเดียวกัน (อันที่จริงคุณเห็นทั่วโลกในแต่ละเฟรม) เพื่อเพิ่มความแปลกประหลาดแทนที่จะใช้บิตแมปโดยตรงฉันสุ่มตัวอย่างโลกตามเกลียวเพื่อให้ครอบคลุมพื้นที่โดยประมาณ นี่คือสิ่งที่ช่วยให้ฉันบิดเบือนโลกและหมุนได้อย่างง่ายดาย การฉายภาพของ Hammer นั้นมีพื้นที่เท่ากัน ความคิดของฉันคือการจับคู่สองสิ่งนี้จะนำไปสู่การบิดเบือนน้อยลงเมื่อฉันเติมในช่องว่าง ฉันแสดง graticule บนเครื่องฉายด้วยเช่นกันโดยใช้อัลกอริทึมของ Bresenhamเพื่อวาดเส้น เส้นโลกและจุดสิ้นสุดทั้งคู่เคลื่อนตัวไปตามเส้นทางของวัน

แก้ไขเพื่อเปลี่ยนภาพให้เป็นความละเอียดที่สูงขึ้น แต่บิตแมปพื้นฐานที่หยาบ (จงใจ) เพื่อให้คุณสามารถเห็นผลของเกลียว สิ่งนี้ใช้ 5,000 คะแนน (สุ่มจาก~ 260000 ) เทียบเท่ากับบิตแมป 50x100 แต่ให้ความละเอียดกับเส้นศูนย์สูตรมากกว่าเสา

ในการใช้รหัสให้คอมไพล์ด้วย ghc ให้รันด้วยพารามิเตอร์ตัวเลขซึ่งเป็นทางเลือกซึ่งเป็นออฟเซ็ตชั่วโมง ไฟล์ถูกสร้างเช่น 'earth0.pgm', 'earth1.pgm'

import System.Environment
import Data.List (intercalate,unfoldr)
import qualified Data.Set as Set
import Data.List.Split
import Data.List
import Data.Maybe (catMaybes)
import qualified Data.Map as Map
import Data.Time
import Debug.Trace
d=pi/180
tau=2*pi
m0=UTCTime(fromGregorian 2000 1 1)(secondsToDiffTime(12*60*60))
dark::Double->Double->UTCTime->Bool
dark lat long now =
  let
    time=(realToFrac$diffUTCTime now m0)/(60*60*24)
    hour=(realToFrac$utctDayTime now)/(60*60)
    mnlong=280.460+0.9856474*time
    mnanom=(357.528+0.9856003*time)*d
    eclong=(mnlong+1.915*sin(mnanom)+0.020*sin(2*mnanom))*d
    oblqec=(23.439-0.0000004*time)*d
    ra=let num=cos(oblqec)*sin(eclong)
           den=cos(eclong) in
       if den<0 then atan(num/den)+pi else atan(num/den)
    dec=asin(sin(oblqec)*sin(eclong))
    gmst =6.697375+0.0657098242*time+hour
    lmst=(gmst*15*d)+long
    ha=(lmst-ra)
    el=asin(sin(dec)*sin(lat)+cos(dec)*cos(lat)*cos(ha))
  in
  el<=0
infill(open, known)= 
  if null open then known else infill gen
  where
    neighbours (x,y)=catMaybes $ map ((flip Map.lookup) known) [(x+1,y),(x-1,y),(x,y+1),(x,y-1),(x+1,y+1),(x-1,y+1),(x-1,y-1),(x-1,y-1)] 
    vote a= if null a then Nothing
             else Just ((sum a)`div`(length a))
    fill x (open',  known')=
      case vote (neighbours x) of
        Nothing->(x:open',known')
        Just c->(open',(x,c):known')
    gen=(\(o,k)->(o,Map.fromList k))$foldr fill ([], Map.toList known) open
mpoint (a,b)=case a of Nothing->Nothing;Just c->Just(c,b)
grid w h n g lut= map (\y->map (\x->if Set.member (x,y) g then 3 else case Map.lookup (x,y) lut of Nothing->7;Just c->c) [1..w]) [1..h]
unknowns w h lut=concatMap (\y->concatMap (\x->let z=1-(2*x//w-1)^2-(2*y//h-1)^2 in case Map.lookup (x,y) lut of Nothing->if z<0 then [] else [(x,y)];_->[]) [1..w]) [1..h]
main=do
  args <- getArgs
  let off = if null args then 0 else read(args!!0)
  actual <- getCurrentTime
  let now=((fromIntegral off)*60*60) `addUTCTime` actual
  let tod=realToFrac(utctDayTime now)/86400+0.4
  let s=5000
  let w=800
  let h=400
  let n=6
  -- pbm <- readFile "earth.pbm"
  -- let bits=ungrid s$parsepbm pbm
  let bits=[0,23,4,9,1,3,1,2,6,10,1,10,4,1,3,7,10,7,4,2,2,1,2,6,12,1,1,2,1,5,4,1,8,1,3,
            1,21,7,2,2,35,1,4,3,2,2,2,2,16,1,25,1,2,8,1,4,1,2,13,3,2,1,26,1,1,10,3,3,8,
            2,3,6,1,3,25,2,1,10,15,5,1,6,2,3,30,10,15,19,32,11,16,20,35,11,1,2,14,22,27,
            1,8,14,16,22,2,1,22,1,1,2,1,1,2,1,2,1,3,16,14,25,1,2,21,1,6,1,2,1,1,2,3,17,
            14,26,1,2,1,1,26,1,1,3,3,1,1,19,13,28,4,1,26,6,6,21,11,35,40,21,11,37,41,20,
            2,4,4,1,1,39,19,1,6,1,16,19,2,4,5,40,18,2,7,1,17,19,1,1,1,1,1,2,3,46,7,1,5,
            4,25,16,3,1,1,3,5,44,1,4,5,4,3,6,4,1,19,22,5,46,2,3,4,6,2,9,22,22,2,50,1,5,
            2,1,1,6,1,8,24,15,5,1,2,51,2,5,1,1,1,5,1,10,23,14,9,55,1,4,2,17,16,1,4,14,9,
            57,4,1,3,17,13,20,11,54,2,1,3,1,2,20,12,18,13,47,4,3,8,21,10,17,15,44,5,1,1,
            4,1,3,2,22,10,15,16,46,4,3,1,2,2,25,9,17,15,47,1,1,3,30,9,18,13,46,2,1,4,25,
            2,1,11,16,13,46,8,24,2,2,9,16,11,45,12,22,1,3,7,17,10,45,12,21,1,3,7,19,8,
            43,12,25,6,19,8,41,12,25,5,20,7,40,11,25,4,20,6,40,5,3,2,48,6,38,3,54,4,30,
            1,6,2,55,2,29,1,5,1,53,3,28,1,55,3,49,1,30,2,76,1,284,3,4,1,15,1,17,10,1,9,
            7,1,13,21,4,4,1,2,6,17,2,8,3,63]
  let t(phi,lambda)=unitsphere$rx (-pi/4)$rz (-tod*4*pi)$sphereunit(phi, lambda)
  let hmr=(fmap (\(x,y)->(floor((fl w)*(x+4)/8),floor((fl h)*(y+2)/4)))).hammer.t
  let g=graticule hmr n
  let lut = Map.fromList$ catMaybes $map mpoint$map (\((lat,long),bit)->(hmr(lat,long),bit*4+2-if dark lat long now then 2 else 0))  $zip (spiral s) (rld bits)
  -- let lut = Map.fromList$ catMaybes $map mpoint$map (\((lat,long),bit)->(hmr(lat,long),bit))$zip (spiral s) (rld bits)
  let lut' = infill ((unknowns w h lut), lut)
  let pgm = "P2\n"++((show w)++" "++(show h)++" 7\n")++(intercalate "\n" $ map (intercalate " ")$chunksOf 35 $ map show(concat$grid w h n g lut'))++"\n"
  writeFile ("earth"++(show off)++".pgm") pgm

fl=fromIntegral
spiral::Int->[(Double,Double)]
spiral n=map (\k-> let phi=acos(((2*(fl k))-1)/(fl n)-1) in rerange(pi/2-phi,sqrt((fl n)*pi)*phi)) [1..n]
rld::[Int]->[Int]
rld bits=concat$rld' (head bits) (tail bits)
  where
   rld' bit []=[]
   rld' bit (run:xs) = (replicate run bit):(rld' (case bit of 1->0;_->1) xs)
rle::[Int]->[Int]
rle bits=(head bits):(map length$group bits)
sample::Int->Int->Int->[(Int,Int)]
sample n w h = map (\(phi, theta)->((floor((fl h)*((phi-(pi/2))/pi)))`mod`h, (floor((fl w)*(theta-pi)/(tau)))`mod`w )) $ spiral n
ungrid::Int->[[Int]]->[Int]
ungrid n g = rle $ map (\(y, x)->(g!!y)!!x) (sample n w h)
  where w = length$head g
        h = length g
parsepbm::[Char]->[[Int]]
parsepbm pbm=
    let header = lines pbm
        format = head header
        [width, height] = map read$words (head$drop 1 header)
        rest = drop 2 header
        d = ((map read).concat.(map words)) rest
    in chunksOf width d
rerange(phi,lambda)
 | abs(phi)>pi = rerange(phi - signum(phi)*tau, lambda)
 | abs(phi)>pi/2 = rerange(phi-signum(phi)*pi, lambda+pi)
 | abs(lambda)>pi = rerange(phi, lambda - signum(lambda)*tau)
 | otherwise = (phi, lambda)
laea(phi,lambda)=if isInfinite(z) then Nothing else Just (z*cos(phi)*sin(lambda),z*sin(phi)) where z=4/sqrt(1+cos(phi)*cos(lambda))
hammer(phi,lambda)=case laea(phi, lambda/2) of Nothing->Nothing; Just(x,y)->Just (x, y/2)
bresenham :: (Int, Int)->(Int, Int)->[(Int, Int)]
bresenham p0@(x0,y0) p1@(x1,y1)
  | abs(dx)>50||abs(dy)>50=[]
  | x0>x1 = map h$ bresenham (h p0) (h p1)
  | y0>y1 = map v$ bresenham (v p0) (v p1)
  | (x1-x0) < (y1-y0) = map f$ bresenham (f p0) (f p1)
  | otherwise = unfoldr (\(x,y,d)->if x>x1 then Nothing else Just((x,y),(if 2*(d+dy)<dx then(x+1,y,d+dy)else(x+1,y+1,d+dy-dx)))) (x0,y0,0)
      where 
        h(x,y)=(-x,y)
        v(x,y)=(x,-y)
        f(x,y)=(y,x)
        dx=x1-x0
        dy=y1-y0
globe n k= 
  (concatMap (\m->map (meridian m) [k*(1-n)..k*(n-1)]) [k*(1-2*n),k*(2-2*n)..k*2*n])
  ++(concatMap (\p->map (parallel p) [k*(-2*n)..k*2*n]) [k*(1-n),k*(2-n)..k*(n-1)])
  where
  meridian m p=(radians(p,m),radians(p+1,m))
  parallel p m=(radians(p,m),radians(p,m+1))
  radians(p,m)=rerange((p//(k*n))*pi/2,(m//(k*n))*pi/2)
graticule f n=Set.fromList $ concatMap (\(a,b)->case (f a,f b) of (Nothing,_)->[];(_,Nothing)->[];(Just c,Just d)->bresenham c d) (globe n 4)
rx theta (x,y,z) = (x, y*(cos theta)-z*(sin theta), y*(sin theta)+z*(cos theta))
ry theta (x,y,z) = (z*(sin theta)+x*(cos theta), y, z*(cos theta)-x*(sin theta))
rz theta (x,y,z) = (x*(cos theta)-y*(sin theta), x*(sin theta)+y*(cos theta), z)
sphereunit (phi, theta) = (rz theta (ry (-phi) (1,0,0)))
unitsphere (x,y,z) = (asin z, atan2 y x)
x//y=(fromIntegral x)/(fromIntegral y)    

3
นี่คือความบ้า. บ้าแน่นอน ฉันรักมัน.
Wander Nauta

1
ฉันใช้เวลานานมากที่จะได้รับการเปลี่ยนแปลงในอันนี้ บิตแมปเกลียวเพียงอย่างเดียวคือเฮฮา
bazzargh

อีกครั้ง "มันขยายขนาดได้ค่อนข้างดี" - คุณหมายถึงคุณสามารถสร้าง GIF ที่มีความละเอียดสูงได้อย่างง่ายดายหรือไม่?
Wander Nauta

ใช่. ค่อนข้างใหญ่กว่ามาก ฉันเอารหัสนั้นออกไปสักพักหนึ่งในขณะที่ฉันยุ่งกับ graticule เมื่อฉันได้เวลาสักครู่หลังจากนั้นฉันจะใส่กลับเข้าไปในนั้นและอัปโหลดภาพที่ดีกว่า
bazzargh

1
คุณจะไป - ภาพใหญ่ที่ดีของ crazytown
bazzargh

21

C ใช้ภาพ pnm

คำตอบล่าช้าโดยมุ่งเน้นไปที่ความถูกต้องและความสวยงามความงามเอาท์พุทคือการผสมผสานของสองภาพอินพุต (day.pnm และ night.pnm) รวมถึงแถบโพล้เพล้ ฉันใช้ภาพจากหินอ่อนสีน้ำเงินของ NASAs ที่นี่

รหัสใช้ img.h ของฉันเองเพื่อความชัดเจน (แค่คิดว่ามันรวมคำต่อคำใน. c สำหรับการปฏิบัติตามกฎที่เข้มงวด ... ) ทุกอย่างในนั้นถูกใช้งานผ่านมาโคร C ภาพเคลื่อนไหวถูกสร้างขึ้นด้วย imagemagicks แปลงจากหลายเฟรม - ตัวโปรแกรมเองจะส่งออกภาพนิ่งเท่านั้น รหัสด้านล่าง

ตอนนี้: (13 สิงหาคม ~ 13:00 CEST)

เอาท์พุต

วันหนึ่ง: (1 มกราคม)

วันหนึ่ง

หนึ่งปี: (12:00 UTC)

หนึ่งปี

sun.c

  #include <math.h>
  #include <time.h>

  #include "img.h"

  #ifndef M_PI
  #define M_PI 3.14159265359
  #endif

  double deg2rad(double x) {return x / 180.0 * M_PI;}
  double rad2deg(double x) {return x * 180.0 / M_PI;}

  double  sind(double x) {return  sin(deg2rad(x));}
  double  cosd(double x) {return  cos(deg2rad(x));}
  double asind(double x) {return rad2deg(asin(x));}

  double elevation(double latitude, double longitude, int yday, int hour, int min, int sec)
  {
     double fd = (hour + (min + sec / 60.0) / 60.0) / 24.0;
     double fyd = 360.0 * (yday + fd) / 366.0;

     double m = fyd - 3.943;
     double ta = -1.914 * sind(m) + 2.468 * sind(2 * m + 205.6);
     double hourangle = (fd - 0.5) * 360.0 + longitude + ta;
     double decl = 0.396 - 22.913 * cosd(fyd) + 4.025 * sind(fyd) - 0.387 * cosd(2 * fyd) + 0.052 * sind(2 * fyd) - 0.155 * cosd(3 * fyd) + 0.085 * sind(3 * fyd);

     return asind(cosd(hourangle) * cosd(decl) * cosd(latitude) + sind(decl) * sind(latitude));
  }

  int main(int argc, char* argv[])
  {
     Image day, night, out;
     int x, y;
     time_t t = time(0);
     struct tm* utc = gmtime(&t);
     int yday = utc->tm_yday, hour = utc->tm_hour, min = utc->tm_min, sec = utc->tm_sec;

     imgLoad(day, "day.pnm");
     imgLoad(night, "night.pnm");
     imgLoad(out, "day.pnm");
     for(y = 0; y < day.height; ++y)
     {
        double latitude = 90.0 - 180.0 * (y + 0.5) / day.height;
        for(x = 0; x < day.width; ++x)
        {
           double longitude = -180.0 + 360.0 * (x + 0.5) / day.width;
           double elev = elevation(latitude, longitude, yday, hour, min, sec);
           double nf = elev > -0.8 ? 0.0 : elev > -6.0 ? 0.5 : 1.0;
           double df = 1.0 - nf;
           Color dc = imgGetColor(day, x, y);
           Color nc = imgGetColor(night, x, y);
           imgDotC3(out, x, y, df * dc.r + nf * nc.r, df * dc.g + nf * nc.g, df * dc.b + nf * nc.b);
        }
     }
     imgSave(out, "out.pnm");
  }

img.h

  #include <stdlib.h>
  #include <stdio.h>
  #include <string.h>

  typedef struct
  {
     unsigned char r;
     unsigned char g;
     unsigned char b;
  } Color;

  typedef struct
  {
     Color* data;
     int width;
     int height;
     Color c;
  } Image;

  #define imgCreate(img, w, h)           {\
                                            int length;\
                                            (img).width = (w);\
                                            (img).height = (h);\
                                            length = (img).width * (img).height * sizeof(Color);\
                                            (img).data = malloc(length);\
                                            memset((img).data, 0, length);\
                                            (img).c.r = (img).c.g = (img).c.b = 0;\
                                         }

  #define imgDestroy(img)                {\
                                            free((img).data);\
                                            (img).width = 0;\
                                            (img).height = 0;\
                                            (img).c.r = (img).c.g = (img).c.b = 0;\
                                         }

  #define imgSetColor(img, ur, ug, ub)   {\
                                            (img).c.r = (ur);\
                                            (img).c.g = (ug);\
                                            (img).c.b = (ub);\
                                         }

  #define imgDot(img, x, y)              {\
                                            (img).data[(int)(x) + (int)(y) * (img).width] = (img).c;\
                                         }

  #define imgDotC3(img, x, y, ur, ug, ub) {\
                                            (img).data[(int)(x) + (int)(y) * (img).width].r = (ur);\
                                            (img).data[(int)(x) + (int)(y) * (img).width].g = (ug);\
                                            (img).data[(int)(x) + (int)(y) * (img).width].b = (ub);\
                                         }

  #define imgDotC(img, x, y, c)          {\
                                            (img).data[(int)(x) + (int)(y) * (img).width] = (c);\
                                         }

  #define imgGetColor(img, x, y)         ((img).data[(int)(x) + (int)(y) * (img).width])

  #define imgLine(img, x, y, xx, yy)     {\
                                            int x0 = (x), y0 = (y), x1 = (xx), y1 = (yy);\
                                            int dx =  abs(x1 - x0), sx = x0 < x1 ? 1 : -1;\
                                            int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1;\
                                            int err = dx + dy, e2;\
                                            \
                                            for(;;)\
                                            {\
                                               imgDot((img), x0, y0);\
                                               if (x0 == x1 && y0 == y1) break;\
                                               e2 = 2 * err;\
                                               if (e2 >= dy) {err += dy; x0 += sx;}\
                                               if (e2 <= dx) {err += dx; y0 += sy;}\
                                            }\
                                         }

  #define imgSave(img, fname)            {\
                                            FILE* f = fopen((fname), "wb");\
                                            fprintf(f, "P6 %d %d 255\n", (img).width, (img).height);\
                                            fwrite((img).data, sizeof(Color), (img).width * (img).height, f);\
                                            fclose(f);\
                                         }

  #define imgLoad(img, fname)            {\
                                            FILE* f = fopen((fname), "rb");\
                                            char buffer[16];\
                                            int index = 0;\
                                            int field = 0;\
                                            int isP5 = 0;\
                                            unsigned char c = ' ';\
                                            while(field < 4)\
                                            {\
                                               do\
                                               {\
                                                  if(c == '#') while(c = fgetc(f), c != '\n');\
                                               } while(c = fgetc(f), isspace(c) || c == '#');\
                                               index = 0;\
                                               do\
                                               {\
                                                  buffer[index++] = c;\
                                               } while(c = fgetc(f), !isspace(c) && c != '#' && index < 16);\
                                               buffer[index] = 0;\
                                               switch(field)\
                                               {\
                                                  case 0:\
                                                     if (strcmp(buffer, "P5") == 0) isP5 = 1;\
                                                     else if (strcmp(buffer, "P6") == 0) isP5 = 0;\
                                                     else fprintf(stderr, "image format \"%s\" unsupported (not P5 or P6)\n", buffer), exit(1);\
                                                     break;\
                                                  case 1:\
                                                     (img).width = atoi(buffer);\
                                                     break;\
                                                  case 2:\
                                                     (img).height = atoi(buffer);\
                                                     break;\
                                                  case 3:\
                                                     index = atoi(buffer);\
                                                     if (index != 255) fprintf(stderr, "image format unsupported (not 255 values per channel)\n"), exit(1);\
                                                     break;\
                                               }\
                                               field++;\
                                            }\
                                            imgCreate((img), (img).width, (img).height);\
                                            if (isP5)\
                                            {\
                                               int length = (img).width * (img).height;\
                                               for(index = 0; index < length; ++index)\
                                               {\
                                                  (img).data[index].r = (img).data[index].g = (img).data[index].b = fgetc(f);\
                                               }\
                                            }\
                                            else\
                                            {\
                                               fread((img).data, sizeof(Color), (img).width * (img).height, f);\
                                            }\
                                            fclose(f);\
                                         }

สวยมาก! ฉันชอบมัน.
Wander Nauta

18

R: การใช้ ggplot2 และ Map projection

ป้อนคำอธิบายรูปภาพที่นี่

แรงบันดาลใจจากโพสต์ของ @ mniip ฉันตัดสินใจลองใช้แพ็กเกจ mapproj ของ R ซึ่งเราสามารถปรับทิศทางโลกได้โดยระบุตำแหน่งที่ขั้วโลกเหนือควรอยู่เมื่อคำนวณภาพ

ตามเวลา GMT ปัจจุบันฉันคำนวณลองจิจูดตอนนี้เป็นเวลาเที่ยงและทำให้จุดนั้นเป็นศูนย์กลางของแผนที่ เรากำลังมองโลกจาก "มุมมองของดวงอาทิตย์" ดังนั้นสิ่งที่มองเห็นได้คือในเวลากลางวัน

รหัสส่วนใหญ่เป็นเพียงความสวยงาม ส่วนเดียวที่ฉันต้องคิดก็คือการคำนวณ "เที่ยงลองจิจูด" นั่นคือค่าลองจิจูดที่เป็นเวลาเที่ยงที่ได้รับเวลา GMT

library(ggplot2);library(maps);library(ggmap)
world <- map_data("world")# a lat-long dataframe from the maps package
worldmap <- ggplot(world, aes(x=long, y=lat, group=group)) + 
  geom_path(color="orange") + 
  theme(panel.background= element_rect("black"),  
        axis.text.y=element_blank(),
        axis.ticks=element_blank(),
        axis.title.x=element_blank(),
        axis.title.y=element_blank(),
        panel.grid.major = element_line(colour="blue", size=0.75),
        panel.grid.minor = element_line(colour="blue")
  )  

#Create a function that takes in the current GMT time
print_3d_coordmap <- function (current_gmt_time) {
  curr_gmt_mins <- as.POSIXlt(current_gmt_time)$hour*60 + as.POSIXlt(current_gmt_time)$min
  noon_longitude <- 180 - (curr_gmt_mins * 360/1440)
  #centered at wherever longitude where it is Noon now on (lat:equator)  
  worldmap + coord_map("ortho", orientation=c(0, noon_longitude, 0))
}

#test it out
print_3d_coordmap(Sys.time() + 7*60*60) # my location is 7 hours behind UTC

จากนั้นฉันใช้แพ็คเกจภาพเคลื่อนไหว Rเพื่อสร้างภาพ 24 ภาพและต่อเข้าเป็นหนึ่ง GIF


ดูดี! มันจัดการกับฤดูร้อนและฤดูหนาวได้อย่างถูกต้องหรือไม่? ฉันไม่ทราบว่าอาร์ดี แต่ดูเหมือนว่าเส้นศูนย์สูตรของคุณมักจะเป็นศูนย์กลางของภาพ
Wander Nauta

ใช่คุณถูกต้อง. ฉันทำการติดตั้งที่รวดเร็วและสกปรกโดยใช้เส้นศูนย์สูตรเป็นละติจูดเท่านั้น (เน้นที่ภาพเคลื่อนไหวแทน) โครงการมีคุณสมบัติมากมายที่ฉันไม่ได้ใช้ หากมีการอ้างอิงที่แสดงวิธีการที่แตกต่างละติจูดกับฤดูกาลฉันจะมีความสุขที่จะลอง
Ram Narasimhan

นี่คือการอ้างอิงใน R, Ram - อันที่จริงนี่คือที่ที่ฉันแปลสูตรในรายการของฉันจากstackoverflow.com/questions/8708048/…
bazzargh

@bazzargh ขอบคุณ! ดูเหมือนว่าฉันได้เรียนรู้มากมายเกี่ยวกับมุมแอซิมัท
Ram Narasimhan

9

JavaScript - โดย Martin Kleppe ( http://aem1k.com/ )

ฉันต้องการเน้นว่านี่ไม่ใช่งานของฉัน แต่เป็นงานของ Martin Kleppe ฉันแค่คิดว่ามันลงตัวอย่างสมบูรณ์แบบที่ไม่ควรพลาดที่นี่:

การสาธิตออนไลน์ (หรือวางลงในคอนโซล)

eval(z='p="<"+"pre>"/*        ######## */;for(y in n="zw24l6k\
4e3t4jnt4qj24xh2 x/*    *############### */42kty24wrt413n243n\
9h243pdxt41csb yz/*  #################### */43iyb6k43pk7243nm\
r24".split(4)){/*     *#################*   */for(a in t=pars\
eInt(n[y],36)+/*          ###############*   */(e=x=r=[]))for\
(r=!r,i=0;t[a/*               ############*   */]>i;i+=.05)wi\
th(Math)x-= /*                #############    */.05,0<cos(o=\
new Date/1e3/*                #########*       */-x/PI)&&(e[~\
~(32*sin(o)*/*                     ####*       */sin(.5+y/7))\
+60] =-~ r);/*                         *###    */for(x=0;122>\
x;)p+="   *#"/*                        #####  */[e[x++]+e[x++\
]]||(S=("eval"/*                      *##### */+"(z=\'"+z.spl\
it(B = "\\\\")./*      ###*           ####  */join(B+B).split\
(Q="\'").join(B+Q/*                  ###* */)+Q+")//m1k")[x/2\
+61*y-1]).fontcolor/*               ##   */(/\\w/.test(S)&&"#\
03B");document.body.innerHTML=p+=B+"\\n"}setTimeout(z)')//m1k\

2
หากไม่ใช่งานของคุณคุณควรเปลี่ยนคำตอบเป็นวิกิชุมชน
Kyle Kanos

1
ขอบคุณสำหรับเคล็ดลับไม่เคยสังเกตเห็นช่องทำเครื่องหมายก่อน ทำ!
Ingo Bürk
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.