ทดสอบคำนวณหาความสูงจีออยด์ TGM2017 ด้วยไลบรารี Proj.4

ไม่นานมานี้มีผมดาวน์โหลดไฟล์โปรแกรมและข้อมูลของ TGM2017 เรียกเต็มๆคือ Thailand Geoid Model 2017 ที่เป็นโครงการร่วมมือจากหลายๆฝ่ายของทางราชการ ผมยังไม่มีโอกาสได้นำไปใช้งาน โดยเฉพาะจะนำมาประยุกต์ใช้ในงานรังวัด GNSS ถือว่าเป็นสิ่งที่พวกเรารอคอยมานานที่จะได้มี local geoid model มาใช้งานกัน

โดยเฉพาะงานรังวัด GNSS เมื่อคำนวณแล้วจะได้ค่าพิกัดทางราบ และทางดิ่งจะได้ความสูง (h – Ellipsoid height) ที่เทียบกับทรงรี WGS84 ถ้าเรามีแบบจำลองความสูงจีออยด์สามารถคำนวณหาความสูง (H – Orthometric height) หรือระดับน้ำทะเลปานกลางได้ จากสูตร h = H + N โดยที่ไม่ต้องมีการเดินระดับไปหาจุดที่รังวัด GNSS แต่อย่างใด โดยที่โปรแกรมคำนวณหาค่าความสูงจีออยด์ (N – Geoid Height หรือ Geoid Separation) ที่ผมจะมาลองเขียนโปรแกรมเล็กๆเพื่อหาค่า N นี้ด้วยภาษาไพทอนในลำดับต่อไป

ในตอนนี้ผมจะใช้ไลบรารี Proj.4 เรียกไลบรารีในเวอร์ชั่นภาษาไพทอนนี้ว่า PyProj ตัวไลบรารี Proj.4 เองก็เพิ่งสนับสนุนการคำนวณ Vertical Datum ไปไม่นานนี้เอง สมมติว่าถ้าไม่ได้ใช้ไลบรารีตัวนี้เป็นตัวช่วยคงเป็นงานหนักหนาสาหัสเหมือนกัน

แปลงรูปแบบไฟล์ของแบบจำลองความสูงจีออยด์ TGM2017

ไฟล์แบบจำลองความสูงจีออยด์ TGM2017 ที่ผมดาวน์โหลดได้มานั้นเป็นแอสกี้ (Text file) ขนาดประมาณ 10.7 MB และมีโปรแกรมคำนวณมาด้วยชื่อไฟล์ execute คือ “TGM2017.EXE” สำหรับไฟล์แอสกี้ในคู่มือแสดงรายละเอียดดังนี้

  • ค่าละติจูด (Latitude) เริ่มต้น : 3 องศา
  • ค่าลองจิจูด (Longitude) เริ่มต้น : 95 องศา
  • ความละเอียดเชิงพื้นที่ : 1 ลิปดา
  • จานวนหลัก (Column) : 780 หลัก
  • จานวนแถว (Row) : 1200 แถว
TGM2017 layout

สำหรับไลบรารี PyProj นั้นถ้าต้องการคำนวณ Vertical Datum ต้องการไฟล์ในรูปแบบ gtx ที่กำหนดมาตรฐานโดย NOAA เพื่อให้การใช้งานมีประสิทธิภาพมาก ทางนี้แนะนำให้ใช้ไฟล์ไบนารีเพื่อประหยัดเมมโมรี สำหรับรูปแบบไฟล์ gtx นั้นไม่มีอะไรมาก กำหนดให้มีไฟล์ header เพื่อบอกจุดเริ่มต้นขอบเขตการใช้งาน ระยะห่างของละติจูดและลองจิจูดของแต่ละจุดในแนวตั้งและแนวนอน จำนวนแถวและจำนวนคอลัมน์ ที่เหลือจะเป็นความสูงจีออยด์ในแต่ละจุดมีขนาดเท่ากับ จำนวณแถวคูณจำนวนคอลัมน์ ตัวหัวไฟล์ผมสามารถเขียนได้ดังนี้

3.0 95.0 0.01666666666 0.01666666666 1200 780

อธิบาย : ละติจูดของมุมล่างซ้าย ลองจิจูดของมุมล่างซ้าย ระยะห่างของจุดในแนวละติจูด ระยะห่างของจุดในแนวลองจิจูด จำนวนแถว จำนวนคอลัมน์

ผมตรวจสอบไฟล์แอสกี้แล้วพบว่า ความสูงจีออยด์ถูกปูเรียงมาแล้วตามข้อกำหนดของ NOAA ดังนั้นผมจะอ่านไฟล์แอสกี้นี้แล้วแปลงเป็นไบนารี เพียงแต่เพิ่มส่วนหัวเข้าไป

ตัวอย่างโปรแกรมไพทอนสำหรับแปลงไฟล์แบบจำลองความสูงจีออยด์

ผมเขียนสคริปต์ภาษาไพทอน เผื่อมีใครสนใจ ผมตึ้งชื่อไฟล์ว่า “rtsd2gtx.py” โปรแกรมมีขนาดเล็กมากๆ ไม่กี่บรรทัด หลักการคืออ่านไฟล์แอสกี้ “tgm2017.asc” มาแล้วเขียนไฟล์ไบนารีในรูปแบบ gtx ข้อควรระวังคือไฟล์ไบนารี ต้องเป็นแบบ Big Endian ในโมดูล struct ผมจึงใส่เครื่องหมาย “>” ไปด้วย

ตัวอย่างเขียนขนิดข้อมูลเป็น double ใช้คำสั่ง f.write(struct.pack(“>d”, 3.0))
เขียนข้อมูลเป็น integer ใช้คำสั่ง f.write(struct.pack(“>i”, 1200))

<import struct
def readRTSDAsciiFile():
    geoid = []
    with open('tgm2017.asc', 'r') as f:
        geoid = [[float(n) for n in line.split()] for line in f] #2D list, one list contain one row.
    #TGM2017 was organized already from lowest row (min latitude) to highest row (max latitude).
    #No need to reverse.	
    return geoid

def writeGTXBinaryFile(geoid):
    with open('tgm2017.gtx', 'wb') as f:
        # pack with ">" for big endian.
		# write Header of file
        f.write(struct.pack(">d", 3.0))  #lower left Latitude
        f.write(struct.pack(">d", 95.0)) #lower left Longtitude		
        f.write(struct.pack(">d", 1.0/60.0)) #delta Latitude = 1 second
        f.write(struct.pack(">d", 1.0/60.0)) #delta Longitude = 1 second	
        f.write(struct.pack(">i", 1200)) #number of rows
        f.write(struct.pack(">i", 780))	#number of columns
		# write height values.
        for row in geoid:
            for c in row:
                f.write(struct.pack(">f", c))

# main program	
g = readRTSDAsciiFile()
writeGTXBinaryFile(g)

ณ ตอนนี้ผมสร้างโฟลเดอร์ เอาไฟล์ tgm2017.asc มาวางไว้ และมีโปรแกรมสคริปต์ “rtsd2gtx.py” อยู่ในโฟลเดอร์เดียวกัน

โฟลเดอร์ที่เก็บไฟล์

จากนั้นทำการรันโปรแกรมด้วยคำสั่งที่คอมมานด์ไลน์ python rtsd2gtx.py รอแป๊ปหนึ่งไฟล์ gtx ที่เก็บแบบจำลองความสูงจีออยด์จะถูกสร้าง และมีขนาดเล็กลงจากไฟล์แอสกี้ดั้งเดิมประมาณ 3 เท่า

ไฟล์ tgm2017.gtx ขนาดประมาณ 3.57 MB

ตัวอย่างโปรแกรมไพทอนสำหรับคำนวณหาความสูงจีออยด์

ต่อไปโปรแกรมไพทอนที่จะนำมาทดสอบคำนวณหาความสูงจีออยด์ ผมตั้งชื่อง่ายๆว่า “test.py” ถ้าจะลองรันโปรแกรมนี้เพื่อทดสอบต้องติดตั้งไลบรารี pyproj ให้เรียบร้อยก่อน

โค้ดโปรแกรมเริ่มต้นจากสร้าง projection ต้นทาง (ตัวแปร wgs84 egm) โดยที่กำหนด +geoidgrids=tgm2017.gtx และสร้าง projection ปลายทาง (ตัวแปร wgs84) โดยที่เว้นไม่ใส่แบบจำลองความสูงจีออยด์

import pyproj # Import the pyproj module
# Define source coordinate system with TGM2017.
wgs84egm = pyproj.Proj("+init=EPSG:4326 +geoidgrids=tgm2017.gtx") 
# Define target coordinate system without geoid model.
wgs84 = pyproj.Proj("+init=EPSG:4326")

lat, lon = 18.3353398540, 99.371215293000
x, y, z = pyproj.transform(wgs84egm, wgs84, lon, lat, 0.0)
print("1) Latitude = %.8f, Longitude = %.8f, Geoid Height = %.5f" % (y, x, z))

lat, lon = 7.75906518100, 98.303594340000
x, y, z = pyproj.transform(wgs84egm, wgs84, lon, lat, 0.0)
print("2) Latitude = %.8f, Longitude = %.8f, Geoid Height = %.5f" % (y, x, z))

lat, lon = 9.18558870000, 99.843706600000
x, y, z = pyproj.transform(wgs84egm, wgs84, lon, lat, 0.0)
print("3) Latitude = %.8f, Longitude = %.8f, Geoid Height = %.5f" % (y, x, z))

lat, lon = 6.96243169, 99.77398865
x, y, z = pyproj.transform(wgs84egm, wgs84, lon, lat, 0.0)
print("4) Latitude = %.8f, Longitude = %.8f, Geoid Height = %.5f" % (y, x, z))

lat, lon = 7.20852844, 99.72353542
x, y, z = pyproj.transform(wgs84egm, wgs84, lon, lat, 0.0)
print("5) Latitude = %.8f, Longitude = %.8f, Geoid Height = %.5f" % (y, x, z))

lat, lon = 7.35631365, 100.12797020
x, y, z = pyproj.transform(wgs84egm, wgs84, lon, lat, 0.0)
print("6) Latitude = %.8f, Longitude = %.8f, Geoid Height = %.5f" % (y, x, z))

lat, lon = 7.23806984, 100.55255020
x, y, z = pyproj.transform(wgs84egm, wgs84, lon, lat, 0.0)
print("7) Latitude = %.8f, Longitude = %.8f, Geoid Height = %.5f" % (y, x, z))

lat, lon = 7.09316728, 100.56368280
x, y, z = pyproj.transform(wgs84egm, wgs84, lon, lat, 0.0)
print("8) Latitude = %.8f, Longitude = %.8f, Geoid Height = %.5f" % (y, x, z))

lat, lon = 6.99643503, 100.43034140
x, y, z = pyproj.transform(wgs84egm, wgs84, lon, lat, 0.0)
print("9) Latitude = %.8f, Longitude = %.8f, Geoid Height = %.5f" % (y, x, z))

lat, lon = 13.0+42.0/60+38.64/3600, 100+29.0/60+13.02/3600
x, y, z = pyproj.transform(wgs84egm, wgs84, lon, lat, 0.0)
print("10) Latitude = %.8f, Longitude = %.8f, Geoid Height = %.5f" % (y, x, z))

เมื่อจัดเก็บไฟล์เรียบร้อย ในตอนนี้ ถ้าดูที่โฟล์เดอร์จะเห็นไฟล์ดังนี้

จุดทดสอบ

ถ้าดูในโค้ดจะเห็นจุดทดสอบทั้งหมด 10 จุด โดยที่ 9 จุดแรกผมนำมาจากไฟล์ INPUT.DAT ที่ติดมากับโปรแกรม TGM2017.EXE ถ้าเปิดดูด้วย Notepad จะเห็นดังนี้

จุดทดสอบ

ส่วนจุดที่ 10 ได้มาจากสไลด์ ชื่อ BM11SP Latitude = 13° 42′ 38.64″ N Longitude = 100° 29′ 13.02″E

คำนวณ

จากนั้นทำการรันโปรแกรมบนคอมมานด์ไลน์ ใช้้คำสั่ง python test.py จะได้ผลลัพธ์ดังนี้

คำนวณหาความสูงจีออยด์

ผมนำผลลัพธ์มาเปรียบเทียบกับที่คำนวณด้วย TGM2017.EXE พบว่ามีความต่างกันเล็กน้อยที่หลักมิลลิเมตร สาเหตุน่าจะเกิดตอน interpolation โดยการนำจุดรอบๆจากแบบจำลองความสูงจีออยด์ ซึ่งโปรแกรมอาจจะเลือกใช้แบบ BiCubic หรือ BiLinear ผมไม่แน่ใจว่า Proj.4 ใช้แบบไหน ตอนนี้ยังไม่มีโอกาสไปดูโค้ดต้นฉบับ

เปรียบเทียบผลลัพธ์การคำนวณ

การพัฒนาโปรแกรมสำหรับการใช้งานในอนาคต

ผมวางแผนว่าจะนำแบบจำลองความสูงจีออยด์ TGM2017 ไปคำนวณในโปรแกรมรวมเครื่องมือฉบับกระเปาสำหรับช่างสำรวจ Surveyor Pocket Tools ได้แก่การคำนวณความสูงจีออยด์ การคำนวณหาสเกลแฟคเตอร์

สรุป

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

4 thoughts on “ทดสอบคำนวณหาความสูงจีออยด์ TGM2017 ด้วยไลบรารี Proj.4”

  1. ช่างสามารถทำ TGM2017 ให้อยู่ในรูปแบบนามสกุล .ggf เพื่อใช้กับโปรแกรม TBC ได้ไหมครับ

    1. ขอบคุณครับที่ทักทายกันมา ผมลองแปลงรูปแบบเป็น GGF ไปลองใช้ใน Trimble Business Center สามารถใช้งานได้ ไปอ่านได้ในบล็อกตามลิ๊งค์นี้ ไฟล์ไปดาวน์โหลดได้ตามลี๊งค์นี้

Leave a Reply

Your email address will not be published. Required fields are marked *