Month: November 2009

ปฐมบท “GDAL/OGR “ สุดยอดไลบรารีสำหรับการพัฒนาโปรแกรม GIS

200px-GDALLogoColor.svg

  • ตอนก่อนๆผมเคยแนะนำ GDAL (Geospatial Data Abstraction Library) เป็น Library แบบ opensource ใช้จัดการอ่านและเขียนภาพ (Raster) ที่อ้างอิงกับระบบพิกัดภูมิศาสตร์ ไลบรารีพัฒนาด้วยภาษา glibc/glibc++
  • ส่วน OGR ก็เช่นเดียวกันเป็นส่วนหนึ่งของ GDAL แต่ใช้กับจัดการกับไฟล์ Vector
  • GDAL/OGR เดิมที่ก่อนหน้าเวอร์ชั่น 1.3.2 พัฒนาโดย Frank Warmerdam ภายหลังโอนย้ายภาระกิจไปยังสมาคม GDAL/OGR Project Management ซึ่งอยู่ภายใต้ Open Source Geospatial Foundation ซึ่งมั่นใจได้ว่าโครงการนี้จะดำเนินการพัฒนาต่อไปเรื่อยๆ
  • ในฐานะนักพัฒนาโปรแกรมอื่นๆเช่น Perl, Python, Ruby, C#, Java สะดวกมากสามารถนำไลบรารีนี้ไปใช้ได้เลย โค๊ดของ glibc++ สามารถแปลหรือ การทำ Wrapper ไปหาภาษาเหล่านี้ได้ด้วย SWIG (Simplified Wrapper and Interface Generator) แค่ดาวน์โหลด sourcecode ของ GDAL/OGR ไปก็ใช้งานได้เลย
  • ส่วน Visual Basic 6 (แต่ยังไม่มี VB.Net) ก็มีคนทำ Wrapper ไปใช้งานซึ่งไม่ได้ทำผ่าน SWIG เพราะ SWIG ไม่ได้รองรับ VB เช่นเดียวกันกับ Delphi หรือ Lazarus ถ้าดาวน์โหลด sourcecode ก็จะได้ wrapper สำหรับ VB6 ไปใช้ การดาวน์โหลดถ้าผ่าน subversion ก็สะดวกเพราะจะได้เวอร์ชั่นที่ update ไปใช้งานได้ตลอด และตัว sourcecode ตัวนี้สามารถคอมไพล์ด้วย MS C++ เพื่อให้ได้ไลบรารี *.dll ไปใช้งาน แต่สำหรับผมแล้วไม่ได้ใช้ MS C++ จึงสะดวกที่จะดาวน์โหลดไลบรารีที่ผ่านการคอมไพล์เป็น .dll แล้วจาก website ไปใช้งาน
  • ในเบื้องต้นผมใช้ตัว wrapper ของ VB6 เป็นแนวทางของการทำ wrapper ด้วย Lazarus ภายหลังเพิ่มฟังก์ชั่นของ GDAL เข้าไปมากกว่าของ VB6 หลักการทำ wrapper คือเขียน class ขึ้นมาห่อฟังก์ชั่นที่เรียกใช้งานไลบรารีของ GDAL ทำให้สะดวกในการเรียกใช้งานเมื่อนำไปใช้พัฒนาโปรแกรม
  • GDAL ออกเสียงเรียกเป็น “จี ดอล” หรือ “กู ดอล” เนื่องจาก OGR เป็นส่วนหนึ่งของ GDAL ดังนั้นเมื่อเรียก GDAL ให้หมายถึง GDAL/OGR

การสนับสนุนฟอร์แมต

  • ผมจะยังไม่พูดถึง OGR ในตอนนี้ขอกล่าวถึงเฉพาะ GDAL (Raster) ก่อน ซึ่ง GDAL เองสนับสนุนฟอร์แมตของ Raster file มากถึง 75 ฟอร์แม็ต ซึ่งครอบคลุมฟอร์แม็ตที่สำคัญไว้ครบถ้วน เช่น GeoTIFF, Erdas Imagine, SDTS, ECW, MrSID, JPEG2000, DTED, NITF
  • รายละเอียดเต็มๆดูได้ที่นี่ http://www.gdal.org/formats_list.html

Download & Install

  • ผมจะขอพูดถึง platform เฉพาะของวินโดส์ก่อน ส่วนใน Linux ผมพยายามใช้ library (libgdal1.6.0.so) ของ GDAL แต่ยังไม่สำเร็จตอนทำ linking เกิด error ยังหาสาเหตุไม่พบ จึงขอข้ามไปก่อน ผมจะดาวน์โหลดที่เป็นไบนารีไฟล์ของ GDAL ไปก่อน ซึ่งที่จะดาวน์โหลดต่อไปนี้ จะรวม utility หลายๆตัวซึ่งเป็น execute file ไปใช้งานได้ด้วย แต่เป็น command line นะครับ ซึ่งผมใช้บ้างแต่ไม่บ่อย
  • เริ่มกันเลยไปดาวน์โหลดได้ที่ http://download.osgeo.org/gdal/win32/1.6/gdalwin32exe160.zip แล้วทำการติดตั้ง โปรแกรมติดตั้งจะเลือกติดตั้งที่รากของ Drive C ที่โฟลเดอร์ c:\gdalwin32-1.6 ตอนนี้เป็นเวอร์ชั่น 1.6 ดูรูปด้านล่างจะเห็นในโฟลเดอร์ย่อนคือ bin จะมี execute file (*.exe) ซึ่งเป็น command line และที่เหลือเป็นไลบรารี Dynamic Link Library (*.dll) ที่ผมจะทำ wrapper ด้วย Lazarus เพื่อดึงไลบรารีมาใช้งาน แต่ที่เราเรียกใช้จริงๆคือ gdal16.dll ซึ่งในไฟล์นี้จะรวม OGR (vertor) มาเรียบร้อยแล้ว

gdalbinfolder

การตั้ง Path ให้ Library

  • ถ้าต้องการใช้ execute file ซึ่งเป็น command line ให้ใช้งานได้สะดวกจะต้องตั้ง library path ให้วินโดส์ได้รับรู้ก่อน ซึ่งเป็นวิธีค่อนข้างโบราณตั้งแต่ DOS ไม่เป็นไร ไม่ใช่เรื่องลำบากนัก ที่ My Computer ของวินโดส์ คลิกขวาเลือก Properties คลิกไปที่แท็บ Advance แล้วคลิกต่อที่ Environment Variables ดูรูปด้านล่างประกอบ setpath01
  • จากนั้นคลิกไปที่บรรทัด Path แล้วคลิกที่ปุ่ม Edit

setpath02

  • พิมพ์ path ของไลบรารีของ GDAL เข้าไปดังรูป (อย่าลืมปิดท้ายด้วยเครื่องหมาย 😉 เท่านี้ก็เรียบร้อย เวลาเราใช้ Lazarus ตอน compile & linking โปรแกรมที่เราพัฒนา Lazarus จะได้หาไฟล์ gdal16.dll มา link ได้ถูกต้อง

setpath03

Tools ที่ต้องการมาช่วยการ Export ไลบรารี

  • แต่ละฟังก์ชั่นที่เราจะดึงมาใช้เช่นดูโค๊ดของ c++ มี export name เป็นอย่างไร
CPLErr GDALSetMetadataItem (GDALMajorObjectH hObject, const char *pszName,
                            const char *pszValue, const char *pszDomain)
  • ใน website ของ GDAL ไม่ได้แสดงไว้ให้เราดู ต้องการ tools ซึ่งผมจะแนะนำต่อไป มาดูโค๊ดทีของ Lazarus ที่เรียกใช้ฟังก์ชั่นนี้ จะเห็นฟังก์ชั่นมี export name เป็น ‘_GDALSetMetadataItem@16’ ซึ่งถ้าชื่อตรงนี้ไม่ถูก Lazarus ไม่สามารถ link ได้
function GDALSetMetadataItem (const Handle : TGDALMajorObjectH;
                              const Name : PCHAR;
                              const Value : PCHAR;
                              const Domain : PCHAR
                              ) : longint; stdcall;
                              external External_Lib name '_GDALSetMetadataItem@16';
  • ดูโค๊ดด้านบนจะเห็น External_Lib เป็นตัวแปร string constant ผมให้เก็บ ‘gdal16.dll’ ถ้าฝั่ง Linux เปลี่ยนเป็น ‘libgdal1.6.0.so’  อะไรประมาณนี้

Download โปรแกรม Dllexp (Dll Export Viewer 1.36)

  • tool ตัวนี้มีขนาดเล็กมากๆ แค่ 44 KB เองแต่เก่งมาก สิ่งที่ต้องการมีครบหมด ไปดาวน์โหลดได้ที่ http://www.download3k.com/Install-DLL-Export-Viewer.html ได้ zip file มาก็ unzip ไปวางไว้ที่โฟลเดอร์ตรงไหนก็ได้แล้วทำ shortcut ก็เรียกใช้ได้เลย มาลองดู tool ตัวนี้ผมลองรันดังรูปด้านล่าง

dllexp01

  • จากรูปด้านบน เราคลิกไปที่ browse เพื่อเลือกไลบรารีดังรูป คลิกที่ OK เพื่อดูชื่อ export function

dllexp02

  • ที่ผมทำลูกศรชี้ไว้ด้านบนเป็น tools ที่เราใช้บ่อย ตัวซ้ายมือเป็น property ของฟังก์ชั่นที่เราเลือก ตัวขวามือเป็นเครื่องค้นหาชื่อฟังก์ชั่น ส่วนลูกศรด้านล่างเป็นฟังก์ชั่นที่ผมกล่าวไปแล้วคือ _GDALSetMetadataItem@16 ชื่อที่เราเห็นใน sourcecode คือ GDALSetMetadataItem ลองคลิก property ที่ toolbar ดู

dllexp03

  • ส่วน toolbar ค้นหาผมจะใช้ชื่อฟังก์ชั่นภาษาซี มาป้อนแล้วค้นหาเมื่อพบฟังก์ชั่นแล้วเราจะ copy ชื่อ function name นี้ไปวางที่ฟังก์ชั่น wrap ด้วย Lazarus หลัง external library name (‘gdal16.dll’)
  • ถ้าเราดูโค๊ดของ GDAL มีฟังก์ชั่นเป็นจำนวนมากไม่ได้ export แต่โปรแกรม Dllexp ช่วยเราได้ในตรงจุดนี้ ตัวอย่างเช่นฟังก์ชั่นสร้าง memory คือ CPLMalloc() ไปดูใน DllExp เห็น ไม่มีปัญหาใช้งานได้ แต่ฟังก์ชั่นตัวคืน momery คือ CPLFree() กลังไม่พบใน gdal16.dll ซึ่งแปลกมากให้สร้างแต่ไม่ export ฟังก์ชั่นคืน memory ให้ใช้

ปัญหาความแตกต่างของตัวแปรระหว่าง C/C++ และ Lazarus

  • ปัญหาการรับส่งตัวแปรในฟังก์ชั่นของ C++ จะเห็นว่าเต็มไปด้วย Pointer ซึ่งในภาษาซีการใช้ pointer เป็นเรื่องปกติ แต่ถ้าเป็น Lazarus จะยุ่งยากในการใช้ตัวแปรเพื่อให้ compatible กับ C++ แต่ผมดูแล้ว Lazarus คงเล็งเห็นปัญหาในจุดนี้เตรียม Type ของตัวแปรมาให้ค่อนข้างดี (ผมว่าดีกว่า Delphi ที่ผมใช้เมื่อก่อนเสียอีก) ดูตัวอย่างโค๊ดของภาษาซีด้านล่าง
    CPLErr GDALSetRasterCategoryNames(GDALRasterBandH hBand, char **papszNames)
  • ตัว CPLErr เป็น Type ข้อมูลแบบ enumerate ใน Lazarus ผม declare ให้เทียบเท่าเป็น
TCPLErr = (CE_None = 0, CE_Debug = 1,
           CE_Warning = 2, CE_Failure = 3,
           CE_Fatal = 4);
  • ส่วนในโค๊ดภาษาซี ตัวถัดไปคือ GDALRasterBandH เป็น pointer (เก็บ handle ของ object) ใน Lazarus เรา declare ได้ง่ายๆเป็น

TGDALMajorObjectH = POINTER;

  • โค๊ดถัดไปของฟังก์ชั่นภาษาซีตัวต่อไป คือ char **papszNames (Pointer to pointer of char) จะเทียบเท่ากับ Lazarus อย่างไร ใน VB6 ใช้ variant แทนแต่ Lazarus ใช้ variant ไม่ได้ แต่โชคดี Lazarus เตรียมตัวแปรแบบนี้มาให้พร้อมคือ PPCHAR ผมหลงไปตั้งนาน เมื่อมารู้ว่า Lazarus เตรียมมาให้แล้ว งานก็ดูง่ายขึ้นเป็นอันมาก ฟังก์ชั่นใน Lazarus ก็ declare ได้ดังนี้
function GDALSetRasterCategoryNames(hBand : TGDALRasterBandH;
                                    papszNames : PPCHAR
                                    ) : TCPLErr; stdcall;
                                   external External_Lib name '_GDALSetRasterCategoryNames@8';

Pointer to Array

  • ดูโค๊ดของภาษาซีตรง double *padfTransform ตัวแปร padfTransform จะเป็นตัวแปร pointer ชี้ไปที่ array ของตัวแปรแบบ double
    CPLErr GDALSetGeoTransform(GDALDatasetH hDS,double *padfTransform)
  • ใน Lazarus เปลี่ยนชื่อตัวแปรให้สอดคล้อง และ pointer to array  แทนด้วย PDOUBLE ซึ่ง Lazarus ก็เตรียมมาให้เช่นเดียวกันคือ PDOUBLE ฟังก์ชั่นของ Lazarus จึงเขียนได้ดังนี้
function GDALSetGeoTransform (const Handle : TGDALDatasetH;
                              Geotransform : PDOUBLE) : TCPLErr;
                              stdcall; external External_Lib name '_GDALSetGeoTransform@8';
 

Pointer to Function

  • ในฟังก์ชั่นไลบรารีของ GDAL จะมีตัวแปร pointer to function ด้วย ดูโค๊ดของภาษาซีด้านล่าง จะเห็นตัวแปร GDALProgressFunc pfnProgress
CPLErr GDALBuildOverviews(GDALDatasetH hDataset,
                          const char *pszResampling,
                          int  nOverviews,
                          int *panOverviewList,
                          int  nListBands,
                          int *panBandList,
                          GDALProgressFunc pfnProgress,
                          void *  pProgressData)
  • ใน Lazarus เรา declare  type และฟังก์ชั่นดังนี้
TGDALProgressFunc = function(dfComplete : double; const pszMessage : PCHAR;
function GDALBuildOverviews(hDataset : TGDALDatasetH;
                            const pszResampling : PCHAR;
                            nOverviews : longint;
                            panOverviewList : PINTEGER;
                            nListBands : longint;
                            panBandList : PINTEGER;
                            pfnProgress : TGDALProgressFunc;
                            pProgressData : POINTER
                           ) : TCPLErr; stdcall; external External_Lib name '_GDALBuildOverviews@32';
  • ส่วนตัวแปร void *pProgressData ใน Lazarus แทนด้วย pProgressData : POINTER

ตัวแปร 16 bit, 32 bit และ 64 bit

  • เนื่องจากฟอร์แม็ตไฟล์ข้อมูลจำพวก Raster จะหลากหลายมากบางฟอร์แม็ตข้อมูลแต่ละ pixel ใช้ Byte บ้าง ใช้ integer  16 bit แบบ signed และ unsigned บ้าง ดังนั้น type ตัวแปรที่จะอ่านเขียน pixel ต้องสอดคล้องกัน ดูโค๊ดของภาษาซี ที่ declare ชนิดข้อมูลของ pixel ใน web
enum  GDALDataType {GDT_Unknown = 0, GDT_Byte = 1, GDT_UInt16 = 2,
                    GDT_Int16 = 3, GDT_UInt32 = 4, GDT_Int32 = 5,
                    GDT_Float32 = 6, GDT_Float64 = 7, GDT_CInt16 = 8,
                    GDT_CInt32 = 9, GDT_CFloat32 = 10, GDT_CFloat64 = 11,
                    GDT_TypeCount = 12
                   }
  • ใน website อธิบายตัวแปรแบบ enumerate ชื่อ GDALDataType

enum GDALDataType

Pixel data types

Enumerator:

GDT_Unknown – Unknown or unspecified type

GDT_Byte – Eight bit unsigned integer

GDT_UInt16 – Sixteen bit unsigned integer

GDT_Int16 – Sixteen bit signed integer

GDT_UInt32 – Thirty two bit unsigned integer

GDT_Int32 – Thirty two bit signed integer

GDT_Float32 –  Thirty two bit floating point

GDT_Float64  – Sixty four bit floating point

GDT_CInt16  – Complex Int16

GDT_CInt32  – Complex Int32

GDT_CFloat32  – Complex Float32

GDT_CFloat64  – Complex Float64

  • ใน Lazarus เรา declare ดังนี้
type
  GInt32   = longint;
  GUInt32  = longword;
  GInt16   = shortInt;
  GUInt16  = word;
  GByte    = byte;
  GBool    = boolean;
  GFloat32 = single;
  GFloat64 = double;
  TGDALDataType = (GDT_Unknown = 0, GDT_Byte = 1, GDT_UInt16 = 2,
                   GDT_Int16 = 3, GDT_UInt32 = 4, GDT_Int32 = 5,
                   GDT_Float32 = 6, GDT_Float64 = 7, GDT_CInt16 = 8,
                   GDT_CInt32 = 9, GDT_CFloat32 = 10, GDT_CFloat64 = 11,
                   GDT_TypeCount = 12);

โครงสร้างของ Model ของ GDAL

  • โครงสร้าง Class ของไลบรารี GDAL เป็นไปดังรูปด้านล่างผมพยายาม wrapper เป็น class ให้สอดคล้องกับ model ของ GDAL เช่นเดียวกัน ต่อไปผมจะอธิบายแต่ละ class พอเป็นสังเขป

  • จากรูป model ด้านบน จะมี classs “GDALMajorObject” ซึ่งลักษณะเป็น abstract class หรือ class ต้นแบบ ส่วนใน Lazarus ผม declare เป็น TGDALMajorObject (อยู่ในยูนิตไฟล์ gdalcore.pas)
  • class “GDALDataset” จะเกี่ยวข้องกับ Raster band ทั้งหมดรวมทั้งข้อมูลบางอย่างของ raster file เช่นขนาดของรูปเป็น pixel และจัดเก็บ Metadata พร้อมทั้งระบบพิกัดภูมิศาสตร์ รวมทั้งการแปลงค่าพิกัดจากระบบหนึ่งไปอีกระบบหนึ่ง ใน Lazarus ผม declare เป็น TGDALDataset (อยู่ในยูนิตไฟล์ gdaldataset.pas)
  • class “GDALDriverManager” เกี่ยวข้องกับฟอร์แม็ตข้อมูล ทาง GDAL จะเรียกเป็น driver สามารถหาจำนวนฟอร์แม็ตที่สนับสนุน ค้นหา รวมทั้งสามารถ register ฟอร์แม็ตข้อมูลก็ได้ ใน Lazarus ผม declare เป็น TGDALDriverManager อยู่ในยูนิต gdaldrivermanager.pas)
  • class “GDALDriver” เกี่ยวข้องกับ Dataset แต่จะเป็นลักษณะการสร้าง เปลี่ยนชื่อ การ copy และลบไฟล์ข้อมูล ใน Lazarus คือ TGDALDriver (อยู่ในยูนิตไฟล์ gdaldriver.pas)
  • class “GDALRasterBand” เกี่ยวข้องกับ raster band เพียงแค่หนึ่งแบนด์เท่านั้น เช่นในไฟล์หนึ่งๆอาจจะมี 3 แบนด์ (แดง เขียว น้ำเงิน) สามารถอ่านและเขียนในระดับ pixel หรือ อ่านและเขียนเป็น block ได้ สามารถอ่าน Color table ได้ผ่าน class “GDALColorTable” ใน Lazarus คือ TGDALRasterBand (อยู่ในยูนิตไฟล์ gdalrasterband.pas) และ TGDALColorTable (อยู่ในยูนิตไฟล์ gdalcolortable.pas) ตามลำดับ
  • และต่อไปเป็นคลาสที่ไม่ได้อยู่ใน model แต่ก็ถูกใช้เมื่ออ้างอิงถึงระบบพิกัด ได้แก่ class “OGRSpatialReference” และ class “ogrcoordinatetransformation” ให้บริการเรื่องระบบพิกัดทั้งเส้นโครงแผนที่และพื้นหลักฐาน(Projections&Datums) ใน Lazarus เป็น class “TOGRSpatialReference” (ogrspatialreference.pas) และ class “TOGRCoordinateTransformation” (ogrcoordinatetransformation.pas)
  • และที่เพิ่มเติมสำหรับโค๊ดของ Lazarus คือยูนิตไฟล์ gdal.pas เก็บ constant และ data type และอีกไฟล์คือ gdalcore.pas สำหรับเก็บ export function จาก GDAL library

TOGRSpatialReference และ TOGRCoordinateTransformation งานยังไม่จบ

  • สำหรับสอง class ข้างต้นมีฟังก์ชั่นมากเกี่ยวกับเส้นโครงแผนที่และพื้นหลักฐาน การแปลงพิกัด ผมยัง port เข้าหา Lazarus ยังไม่เสร็จต้องใช้เวลาอีกมากแต่ก็มีฟังก์ชั่นที่สำคัญเอาไปใช้งานก่อน ความจริงที่ผมเขียนโปรแกรมเกี่ยวกับด้านการแปลงพิกัดตอนก่อน เราสามารถใช้ GDAL มาทำแทนได้เลยเพียงแต่ต้องศึกษาก่อนว่าอะไรเป็นอะไร จะลดงานลงไปได้มาก (สองคลาสนี้ในเบื้องต้นผู้พัฒนา GDAL ได้ port โค๊ดมาจากโครงการ Proj4 ที่จริงผู้พัฒนา Proj4 ก็คือ Frank Warmerdam คนๆเดียวกันที่พัฒนา GDAL) ยุคนี้ไม่ใช่ยุคแต่ก่อนที่โปรแกรมเมอร์ต้องโค๊ดโปรแกรมด้วยตัวเองทั้งหมด ถ้าพัฒนาโปรแกรมด้าน GIS จะได้มีเวลาและพุ่งโฟกัสไปที่จุดมุ่งหมาย ไม่ต้องห่วงเรื่องการอ่านไฟล์ raster & vector เพราะ GDAL ทำให้แล้ว ไม่ต้องห่วงเรื่องระบบพิกัดเพราะ GDAL ทำให้แล้วเช่นเดียวกัน ถ้าสามารถหา component เก่งๆที่ช่วยเรื่องระบบกราฟฟิคได้ก็ดีมาก จะลดงานไปอีกได้มาก
  • โชคดียุคนี้เป็นยุคของ opensource เป็นโลกของการแบ่งปันและร่วมกันพัฒนา จึงมีอะไรดีๆอีกมากในโลกของอินเทอร์เน็ต ถ้าหาให้เจอแค่นั้นเอง ที่ผมเขียน blog ส่วนหนึ่งเพราะต้องการแบ่งปันประสบการณ์ และก็มีความสุขครับ
  • ตอนหน้าจะมาดูเรื่องโปรแกรมมิ่งด้วย Lazarus ในเบื้องต้น ส่วน sourcecode ของ GDAL library ผมหาที่ฝากได้แล้ว ผู้อ่านสามารถจะ download ไปลองรันดูได้

GeoViewer และ ER Viewer สองสุดยอดเครื่องมือดูไฟล์รูปขนาดใหญ่

  • บางครั้งบางโอกาส เวลาได้รับภาพถ่ายดาวเทียมที่มีขนาดใหญ่ระดับ 500 Megabyte ขึ้นไปต้องการโปรแกรมเล็กๆอะไรสักอย่างที่สามารถเปิดไฟล์ได้อย่างรวดเร็ว ผมขอแนะนำสองโปรแกรมคือ GeoViewer ของ LizardTech และ ER Viewer ของ Erdas เรามาลองวัดดูว่าสองโปรแกรมนี้ใครจะแน่กว่ากัน

Download and Install

  • ER Viewer ขณะที่เขียนอยู่นี้เป็นเวอร์ชั่น 7.2 สามารถดาวน์โหลดได้ที่นี่ http://www.erdas.com/LinkClick.aspx?fileticket=GepwjNjtpmE%3d&tabid=84&mid=401 แต่จะดาวน์โหลดได้ต้อง register ก่อนซึ่งก็ไม่หนักหนาอะไรแค่ป้อนข้อความไม่กี่อย่าง ขนาดดาวน์โหลดประมาณ 17 เมกะไบต์ แล้วทำการติดตั้งได้ง่ายๆ
  • GeoViewer ขณะที่เขียนอยู่นี้เวอร์ชั่น 4.0 ดาวน์โหลดเวอร์ชั่นสำหรับวินโดส์ 32 bit ได้ที่นี่ http://www.lizardtech.com/download/dl_download.php?detail=GeoViewer32 ถ้าเป็นวินโดส์ 64 bit ดาวน์โหลดได้ที่ http://www.lizardtech.com/download/dl_download.php?detail=GeoViewer64 สำหรับ GeoViewer ไม่ต้องลงทะเบียนก็ดาวน์โหลดได้ ตอนแรกจะดาวน์โหลดไฟล์ setup.exe เมื่อทำการคลิกติดตั้งโปรแกรม setup จะดาวน์โหลดโปรแกรมตัวจริงมา ซึ่งมีขนาดประมาณ 20 กว่าเมกกะไบต์
  • ปัญหาของ Geoviewer เมื่อทำการรันครั้งแรกบางเครื่องเช่นเครื่องคอมพิวเตอร์ผมจะเตือนว่า

After installing GeoViewer4 or updating GeoViewer3 to version 4 the client receives the following error box.
“The following exception was thrown while initializing DirectX; a frequent cause is unsupported hardware, drivers, or OS configuration.The 3D view will now be disabled.Exception message: Unable to load DLL ‘LidarRenderer.dll’: The specified module could not be found. (Exception from HRESULT: 0x8007007E)”

GeoViewer

  • มาดูหน้าตาของ Geoviewer ก่อน จะเห็นว่าค่อนข้างเรียบง่าย ก่อนจะใช้งานก็เข้าไปที่เมนู Options ลองตั้งค่าให้ตรงกับความต้องการ
GeoViewer Version 4.0
  • ผมจะทดสอบอ่านไฟล์ satelite image ของ landsat7 รูปแบบ Jpeg ขนาดประมาณ 500 MB ด้วยเมนู File > Add layer > Local layer… ใช้เวลาตั้งแต่อ่านไฟล์เพื่อเปิดภาพจนกระทั่งแสดงผลใช้เวลา 1 นาที 40 วินาที ความรู้สึกผมว่าใช้เวลามากไปหน่อย

 

 

  • ข้อดีของ GeoViewer คือสามารถอ่านข้อมูลเป็น Shape file หรือ Lidar (*.las) ได้ ถึงจะ support ชนิดข้อมูลไม่มากนัก ข้อดีอีกอย่างคือสามารถ Export ภาพเป็นฟอร์แม็ต GeoTiff, PNG, Jpeg เลือก resolution ได้ วิธีการคือคลิกที่เมนู Tools > Export…

 

 

  • ข้อดีที่ผมชอบก็คือแสดง metadata ได้ละเอียดดี ที่เมนูเลือก Tools > View layer metadata…

 

 

  • การแสดงผล 3D ถ้าใช้ข้อมูล Lidar เสียดายผมไม่มีข้อมูลดูรูปจาก Help ของ GeoViewer ไปก่อน
เปิดไฟล์ Lidar (ภาพจาก help ของ GeoViewer)

ER Viewer

  • บอกชื่อของผู้พัฒนาคือ Erdas ก็รับประกันความผิดหวังได้ เมื่อติดตั้งแล้วมาดูหน้าตาของ ER Viewer
ER Viewer version 7.2
  • ลองเปิดไฟล์เดียวกันที่ใช้ GeoViewer เปิด ใช้เวลา 20 วินาที ว้าว…….เร็วมาก แต่ข้อเสียก็มีบ้างแต่ไม่ใช่สาระ เพราะชื่อก็บอกอยู่แล้วว่าเป็น Viewer คือเอาไว้ดูอย่างเดียว ข้อเสียที่ว่าคือไม่สนับสนุน vector file ไม่มี metadata ให้ดูก็ไม่เป็นไร
ER Viewer เปิดภาพไฟล์ขนาดใหญ่
  • สรุปแล้วผมชอบสองโปรแกรมนี้ทั้งคู่ครับ GeoViewer ช้ากว่าแต่ก็มี feature มากกว่าเล็กน้อย

การผสมสี (Band Combination) ภาพถ่ายดาวเทียมด้วยโปรแกรม HighView

  • สำหรับการผสมสี (Band combination) ภาพถ่ายดาวเทียมในตอนนี้ ถือเป็นกรณีศึกษา (case study) ก็แล้วกัน คือภาพถ่ายดาวเทียมแต่ละดวงเช่น Landsat,  Alos, Quickbird, Ikonos, Spot-5 ภาพดั้งเดิมจะแยกเป็น Band กัน ที่เราเห็นส่วนใหญ่จะถูกผสมมาให้เรียบร้อยแล้ว
  • ผมจะขอใช้ภาพถ่ายดาวเทียม Landsat 7 ก็แล้วกันเพราะฟรี ถึงแม้ไม่ค่อยละเอียดนัก การ Download ภาพแบบ Online ด้วยโปรแกรม Global Mapper สะดวกแต่เป็นภาพที่ผสมมาเรียบร้อยแล้ว Band ของภาพถ่ายดาวเทียมเช่น Landsat 7 มีมากถึง 8 Band ภาพถ่ายสีแบบธรรมชาติที่เราเห็นจะใช้ Band 1 (สีน้ำเงิน), Band 2 (สีเขียว) และ Band 3 (สีแดง) มาผสมกัน
  • ผมขอแนะนะ website ที่พูดเรื่องนี้ ดูได้ที่ http://web.pdx.edu/~emch/ip1/bandcombinations.html ตัวอย่างถ้าจะศึกษาเรื่องน้ำ ให้เอา Band 1,4 และ 7 มาผสมกันเป็นต้น
  • ขอแนะนำโปรแกรมตัวเล็กๆคือ Highview ที่เป็นเวอร์ชั่นฟรี สามารถนำมาทำ Band combination ได้เป็นอย่างดี ข้อดีคือใช้งานง่าย ดาวน์โหลดได้ที่ http://www.geosage.com/highview/download/HighView2.5.3.T_GUI.zip โปรแกรมสามารถทำ Pan Sharpening ได้ด้วยแต่ตอนนี้ยังไม่พูดถึง

การ Download ภาพ Landsat 7

  • สามารถดาวน์โหลดได้หลายที่ แต่ที่สะดวกมากที่สุดอยู่ที่ http://glcfapp.umiacs.umd.edu:8080/esdi/index.jsp เปิดเข้าไปจะเห็นทางเลือกการดาวน์โหลดอยู่ 3 แบบเลือกแบบแรกคือ Map search
  • ครั้งแรกจะเห็นแผนที่ทั้งโลกใช้ tool ตัว zoom คลิกที่ประเทศไทยจะได้ภาพขยายตามต้องการ ที่ panel ด้านซ้ายคลิกเลือก ETM+ ที่ด้านล่างภาพเลือกวันที่เดือนปี ที่ต้องการ และอย่าลืมตรงตรง Require เลือก GeoTiff ดีที่สุด
  • ใช้ tool ที่เป็นรูปลูกศรเครื่องหมายบวกเพื่อเลือกภาพโดยการคลิกเข้าไปที่แผนที่ ถ้าบริเวณนั้นมีภาพตามเงื่อนไขที่เราตั้งก็จะปรากฎสีแดง จากนั้นคลิกที่ Preview&Download เพื่อทำการเลือกภาพอีกครั้ง ถ้าบริเวณนั้นมีภาพตรงกับเงื่อนไขซ้อนกันอยู่หลายภาพ
เลือกภาพถ่ายที่ต้องการ
  • จากรูปด้านบนผมเลือกปี 2002 ส่วนภาพปี 2004 ของ USGS พบว่าภาพบริเวณนี้มีปัญหาคือภาพเป็นริ้วๆที่ขอบ
เลือกไฟล์เพื่อดาวน์โหลดขั้นตอนสุดท้าย
  • คลิกตรงไฟล์ตาม Band ที่ต้องการ ชื่อไฟล์จะนำหน้าด้วย path และ row เช่น p130r051_7t20020421_z47_nn10.tif.gz หมายถึง path = 130 row = 51 ตรงกลางชื่อไฟล์แสดงปีคศ. Z47 หมายถึงเป็นภาพ UTM Zone 47 (แน่นอนอยู่บน datum WGS84) ส่วนคำหลัง nn10 จะหมายถึง Band 1
  • การดาวน์โหลดควรใช้โปรแกรมดาวน์โหลดมาช่วยเช่น Flashget, Bitcomet เพราะไฟล์มีขนาดใหญ่ ตอนนี้เราจะดาวน์โหลดมาแค่ 4 ไฟล์ 4 Band ดังรูปด้านบน ส่วน Band 8 เป็นภาพ Panchromatic ซึ่งมีความละเอียดมากกว่าแต่ตอนนี้ ดาวน์โหลดมาก่อนแต่ยังไม่ได้ใช้ จะนำมาใช้อีกครั้งเรื่องการทำ Pan Sharpening เมื่อดาวน์โหลดมาได้เรียบร้อยแล้วทำการ unzip ให้อยู่ในรูปฟอร์แม็ตของ GeoTiff

โปรแกรม HighView

  • ผมชอบเพราะโปรแกรมมีขนาดเล็กๆ ถึงแม้ไม่เป็น opensource แต่ก็ฟรี เมื่อดาวน์โหลดมาแล้วทำการติดตั้งแล้วรันดูจะเห็นหน้าตาที่เรียบง่าย ดังรูปด้านล่าง สังเกตที่เมนูจะเห็นเมนู Band Combination เราจะใช้เมนูนี้เพื่อทำการผสมสี คลิกที่เมนู Band Combination > Landsat ETM+
HighView ของ GeoSage
  • จะเห็น dialog คลิกเลือกไฟล์ตาม Band ดังรูป
เลือกไฟล์ตาม Band เริ่มจาก Band 1, Band 2 และ Band 3 ตามลำดับ
  • จากรูปด้านบนเลือกไฟล์ให้ตรงกับ Band ที่โปรแกรมต้องการเรียงจาก Band 1 Band 2 และ Band 3 อย่าลืมคลิกที่ ที่ผมเน้นไว้เพื่อสร้างไฟล์ GeoTiff ถ้าไม่เลือกโปรแกรมจะผสมภาพให้เป็นภาพ .BMP (ไม่รู้สร้างไฟล์ฟอร์แม็ตนี้มาให้ทำไม ผมเข้าใจว่าเป็นฟอร์แม็ตที่โลกลืมแล้ว) เข้าไปที่ windows explorer แล้วเข้าไปแก้ไขชื่อไฟล์ GeoTiff  ตัวอย่างเช่นโปรแกรมสร้างชื่อให้เป็น p130r051_7t20020421_z47_nn10_Composite.tif ผมแก้ไขเป็น p130r051.tiff ขนาดไฟล์ประมาณ 191 MB ลองเปิดไฟล์ GeoTiff นี้ด้วยโปรแกรม tools ด้าน GIS เช่น Global Mapper จะเห็นสีค่อนข้างทึมๆ ไม่สวย
ไฟล์ GeoTiff เมื่อเปิดดูด้วย Global Mapper
  • จะทำการปรับโทนสีใหม่ให้ดูสดใส ผมเลือกใช้ Gimp เปิดไฟล์ tiff นี้ ต้องระวังหน่อยโปรแกรมจำพวกนี้เช่น Photoshop เมื่อทำการเซฟไฟล์ ความเป็น Georeferencee จะหาย วิธีแก้ไขก็ใช้ Global Mapper ทำการ export เพื่อ Backup ไว้โฟลเดอร์อื่นแล้วอย่าลืม คลิกเลือก Generate TFW (World file) เพื่อสร้าง world file ไว้ เมื่อใช้โปรแกรม Gimp ทำการแก้ไขสี ผมใช้เมนู สี >  levels… ปรับให้สวยแล้วเซฟเป็นไฟล์ใหม่ Gimp จะถามว่าให้จัดเก็บแบบบีบขนาดหรือไม่ ตอบเป็น LZW
  • จากนั้นให้ไป copy world file ที่เรา backup ไว้ด้วย Global Mapper กลับมาที่โฟลเดอร์ไฟล์ที่เราเพิ่งทำการแก้ไขด้วย Gimp ลองเปิดด้วย Global Mapper อีกครั้ง จะสังเกตความเป็น GeoTiff หายไป โปรแกรมจะถามให้เลือก datum เลือก Zone เป็น 47 N เลือก datum เป็น WGS84 หน่วยเป็นเมตร จะเห็น Global Mapper แสดงภาพถ่ายดาวเทียม Landsat 7 ได้สวยงามดังรูปด้านล่าง
ภาพ Geotiff ที่ผ่านการปรับสีแล้ว
  • พูดถึงเรื่องปรับสี แล้วขอเล่าประสบการณ์หน่อย การปรับสีด้วย Gimp หรือ Photoshop (ซึ่งผมเลิกใช้ไปนานแล้ว) ถ้าเป็นภาพใหญ่ๆ ขนาด 1 GB ขึ้นไป ผมมีภาพใหญ่ขนาด 1.4 GB ใช้ Gimp ไม่ประสบความสำเร็จคือจะ hang ไปเลย ส่วน Photoshop เมื่อไปลองที่เครื่องน้องที่สำนักงาน ผ่านครับแต่ก็ช้าพอสมควร ผมว่า Gimp น่าจะมีอะไรปรับปรุงเรื่องอัลกอริทึ่มบ้าง ให้สามารถจัดการภาพไฟล์ขนาดใหญ่นี้ได้ แหมทำเอาผมขายหน้าไปเลย วันนี้เอาแค่นี้ก่อน พบกันตอนหน้าครับ

การใช้ฐานข้อมูล SQLite กับ Lazarus ในเบื้องต้น (ตอนที่ 2)

  • ตอนที่แล้วผม post ตัวโค๊ดทั้งหมด มาดูคำอธิบายตรงสาระที่สำคัญ

Declare ตัวแปรสำหรับ SQLite

  • ที่ class ของ TfrmSetEllipsoid จะ declare เพื่อจัดการกับฐานข้อมูล SQLite ผม declare ทีส่วน private
{ TfrmSetEllipsoid }
TfrmSetEllipsoid = class(TForm)
cmdDelete: TButton;
cmdNew: TButton;
cmdApply: TButton;
cmdOK: TButton;
cmdCancel: TButton;
dbtxtFlattening: TDBEdit;
dbtxtSemiMajorAxis: TDBEdit;
dbtxtEllipsoidCode: TDBEdit;
DBNavigator1: TDBNavigator;
dbcboEllipsoidName: TDBComboBox;
GroupBox1: TGroupBox;
Image1: TImage;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;

procedure cmdApplyClick(Sender: TObject);
procedure cmdCancelClick(Sender: TObject);
procedure cmdDeleteClick(Sender: TObject);
procedure cmdNewClick(Sender: TObject);
procedure cmdOKClick(Sender: TObject);
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ private declarations }
FDBCon : TSQLite3Connection;
FTrans : TSQLTransaction;
FSql : TSQLQuery;
FDatasource : TDatasource;
FDatabaseFile : string;
FNewRecordState : boolean;
public
{ public declarations }
end;
  • มีตัวแปร FDBCon, FSql, FTrans เป็นตัวแปรในระดับ Dataset ตัวแปร FDBCon อยู่ล่างสุดทำหน้าที่ชี้ไปยัง Database ส่วน FTrans ทำหน้าที่เรื่อง Transaction ส่วน FSql เป็น Dataset ที่ทำหน้าที่ Query ข้อมูลจากฐานข้อมูลตามเงื่อนไขมาเก็บไว้ ส่วน FDatasource อยู่สูงขึ้นมาอีกเป็นตัวกลางระหว่าง Dataset กับวัตถุจำพวก data-aware ที่ทำหน้าที่แสดงฟิลด์ของข้อมูล ดังไดอะแกรมที่ผมแสดงไว้ตอนที่ 1 ความสัมพันธ์ระหว่างตัวแปรนี้เป็นไปดัง event ของ FormCreate
procedure TfrmSetEllipsoid.FormCreate(Sender: TObject);
begin
//เปลี่ยน path ที่อยู่ของฐานข้อมูลให้ตรงกับโฟลเดอร์ที่เก็บ
FDatabaseFile := 'e:\sourcecodes\lazarus\sqliteproj2\datums.s3db';

FDBCon := TSQLite3Connection.Create(NIL);
FTrans := TSQLTransaction.Create(NIL);
FSql := TSQLQuery.Create(NIL);
FDatasource := TDatasource.Create(NIL);

FDBCon.DatabaseName := FDatabaseFile;
FDBCon.Transaction := FTrans;
FTrans.DataBase := FDBCon;
FSql.DataBase := FDBCon;
FSql.Transaction := FTrans;
FDBCon.Connected := true;
FTrans.Active := true;
FDatasource.Dataset := FSql;
FDatasource.AutoEdit := true;

FSql.Close;
FSql.SQL.Clear;
FSql.SQL.Text := 'SELECT * FROM ELLIPSOIDS';
FSql.Open;
//FTrans.CommitRetaining; {This line does not work in win32. But OK in linux???}

dbcboEllipsoidName.DataSource := FDatasource;
dbcboEllipsoidName.DataField := 'NAME';
dbtxtEllipsoidCode.DataSource := FDatasource;
dbtxtEllipsoidCode.DataField := 'CODE';
dbtxtSemiMajorAxis.DataSource := FDatasource;
dbtxtSemiMajorAxis.DataField := 'A';
dbtxtFlattening.DataSource := FDatasource;
dbtxtFlattening.DataField := 'INV_F';
DBNavigator1.DataSource := FDatasource;

FNewRecordState := false;
end;
  • เมื่อปิดโปรแกรมตรง event FormDestroy อย่าลืม Free ให้กับตัวแปรที่เรา Declare ไว้ เพื่อคืนความจำให้ระบบ
procedure TfrmSetEllipsoid.FormDestroy(Sender: TObject);
begin
FTrans.Free;
FSql.Free;
FDatasource.Free;
//Make sure TSQLite3Connection is the last.
FDBCon.Free;
end;

ลบ Record

  • การเลื่อน Record ทำได้โดยการลิกที่ปุ่มลูกศร ซ้ายและขวา
  • มาดูการลบ record ที่ปุ่ม (button) “Delete…” สร้าง Event procedure ชี้ไปที่ cmdDeleteClick(Sender: TObject);
procedure TfrmSetEllipsoid.cmdDeleteClick(Sender: TObject);
var
szECode : string;
sql : TSQLQuery;

begin
try
sql := TSQLQuery.Create(nil);
sql.Database := FDBCon;
sql.Transaction := FTrans;
szECode := dbtxtEllipsoidCode.Text;

if (MessageDlg ('คำเตือน','ยืนยันว่าต้องการลบทรงรี', mtConfirmation,
[mbOK, mbCancel],0) = mrOK) then
begin
sql.Close;
sql.SQL.Text := 'DELETE FROM ELLIPSOIDS WHERE CODE = :CODE';
sql.Params.ParamByName('CODE').AsString := szECode;
sql.ExecSQL;
FSql.ApplyUpdates;
FTrans.CommitRetaining;
FSql.Close;
FSql.SQL.Clear;
FSql.SQL.Text := 'SELECT * FROM ELLIPSOIDS';
FSql.Open;
FTrans.CommitRetaining;
end;

finally
sql.Free;
end;
end;
  • จากโค๊ดด้านบน เนื่องจากเราไม่ได้ใช้ DBNavigator เราจะำทำการลบด้วยการดึงชื่อโค๊ดของทรงรีเข้าตัวแปร szECode  เพื่อมาใช้ Query “DELETE” ได้ถูก ก่อนจะลบให้ผู้ใช้ยีนยันด้วย MessageDlg

เพิ่มและแก้ไข Record

  • การแก้ไขฟิลด์ของ record ที่มีอยู่แล้วใช้ SQL syntax “UPDATE” แต่การลบ record ใช้ “DELETE” จึงมีตัวแปร FNewRecordState คอยตรวจว่าเป็นการแก้ไขหรือการลบ record มาดูการเพิ่ม record ที่ event “cmdNewClick” ไม่มีอะไรมากสำหรับแค่เตรียมตัว data-aware ให้ว่างและจัดสถานะให้พร้อม พร้อมที่ผู้ใช้โปรแกรมป้อนค่าทรงรีรูปทรงใหม่เข้าไป การจะจัดเก็บเข้า Database ให้ผู้ใช้คลิกที่ปุ่ม “Apply” เพื่อยืนยัน
procedure TfrmSetEllipsoid.cmdNewClick(Sender: TObject);
begin
//Make its to ready for editable.
dbcboEllipsoidName.ReadOnly := false;
dbtxtSemiMajorAxis.ReadOnly := false;
dbtxtflattening.ReadOnly := false;
dbtxtEllipsoidCode.ReadOnly := false;
dbcboEllipsoidName.Text := '';
dbtxtSemiMajorAxis.Text := '';
dbtxtFlattening.Text := '';
dbtxtEllipsoidCode.Text := '';
cmdApply.Enabled := true;
cmdNew.Enabled := false;
DBNavigator1.BtnClick(nbInsert);
FNewRecordState := true;
end;

UPDATE หรือ INSERT

  • การ update ด้วยโปรแกรม demo ของผมได้แก่การแก้ไขค่าสัณฐานทรงรีเช่นชื่อของทรงรี, ค่า a, ค่า 1/f ยกเว้นไม่ให้แก้ไขคือค่าโค๊ดของทรงรี (CODE) ถ้าเพิ่มรูปทรงรีสามารถทำได้อิสระ เพียงแต่ค่า CODE ของทรงรีต้องไม่ซ้ำกับค่าที่มีอยู่แล้ว
  • เมื่อคลิกปุ่ม “New…” ทำการป้อนรูปทรงรีใหม่เข้าไป หรือแก้ไขค่าทรงรีเดิม ฐานข้อมูลจะไม่มีการเปลี่ยนแปลงจนกระทั่ง ผู้ใช้โปรแกรมคลิกที่ปุ่ม “Apply” โปรแกรมจะทำตรวจสอบว่าผู้ใช้เพิ่ม record จากตัวแปร FNewRecordState ถ้าเป็นการ Update ก็สวิตท์ if clause ไปที่ else if
  • โปรแกรมมีเงื่อนไขอีกนิดว่าค่า a ต้องมากกว่า 6377000 เมตร และค่า 1/f ต้องมากกว่า  293 ถ้าไม่ได้ให้รอป้อนจนป้อนค่าถูก
procedure TfrmSetEllipsoid.cmdApplyClick(Sender: TObject);
var
szEName, szECode : string;
dA, dB, dF : extended;
f1, f2 : boolean;
sql : TSQLQuery;
begin
try
sql := TSQLQuery.Create(nil);
sql.Database := FDBCon;
sql.Transaction := FTrans;
szEName := trim(dbcboEllipsoidName.Text);
szECode := trim(dbtxtEllipsoidCode.Text);
if (szEName <> '') and (szECode <> '') then
begin
szECode := Trim(dbtxtEllipsoidCode.Text);
f1 := trystrtofloat(dbtxtSemiMajorAxis.Text, dA);
f2 := trystrtofloat(dbtxtFlattening.Text, dF);
dB := dA - dA * 1 / dF;
if (FNewRecordState) then
begin
if (f1 and (dA > 6377000)) and (f2 and (df > 293)) then
begin
sql.Close;
sql.SQL.Clear;
sql.SQL.Text := 'INSERT INTO ELLIPSOIDS (NAME,CODE,A,B,INV_F)'
+ ' VALUES (:NAME,:CODE,:A,:B,:INV_F)';
sql.Params.ParamByName('NAME').AsString := szEName;
sql.Params.ParamByName('CODE').AsString := szECode;
sql.Params.ParamByName('A').AsFloat := dA;
sql.Params.ParamByName('B').AsFloat := dB;
sql.Params.ParamByName('INV_F').AsFloat := dF;

sql.ExecSQL;
cmdApply.Enabled := False;
cmdNew.Enabled := true;
FTrans.CommitRetaining;
FNewRecordState := false;
end
else if not(f1 and (dA > 6377000)) then
begin
MessageDlg ('Warning', 'Semi-major axis must be the number and its value must > 6,377,000 m.?', mtConfirmation,
[mbOK],0);
dbtxtSemiMajorAxis.SetFocus;
end
else if not (f2 and (df > 297)) then
begin
MessageDlg ('Warning', 'Flattening must be the number and its value must > 297 m.?', mtConfirmation,
[mbOK],0);
dbtxtFlattening.SetFocus;
end;
end
else
begin
sql.Close;
sql.SQL.Clear;
sql.SQL.Text := 'UPDATE ELLIPSOIDS SET NAME=:NAME,'
+ 'A=:A,B=:B,INV_F=:INV_F WHERE CODE=:CODE';
sql.Params.ParamByName('NAME').AsString := szEName;
sql.Params.ParamByName('CODE').AsString := szECode;
sql.Params.ParamByName('A').AsFloat := dA;
sql.Params.ParamByName('B').AsFloat := dB;
sql.Params.ParamByName('INV_F').AsFloat := dF;

sql.ExecSQL;
cmdApply.Enabled := False;
FTrans.CommitRetaining;

end;
end;
finally
sql.Free;
end;
end;
  • มาลองรันโปรแกรม ลองคลิกไปที่ลูกศรขวาจนถึงรูปทรงรี “WGS 72” ลองคลิกที่ปุ่ม “Delete…”  โปรแกรมจะถามยืนยันตอบ OK
ลองทดสอบลบทรงรี WGS 72
  • เมื่อลบเสร็จโปรแกรมจะเลื่อนไปที่ record แรกอัตโนมัติ ลองเลื่อนลูกศรไปดูว่า WGS 72 ยังอยู่หรือไม่ จะไม่เห็น ต่อไปลองมาแก้ไขค่ารูปทรงรีดู
แก้ไขค่ารูปทรงรี
  • ลองปิดโปรแกรมแล้วรันอีกครั้งทดสอบว่าฐานข้อมูล update ไปตามต้องการแล้วหรือยัง ช่วงทดสอบโปรแกรมผมจะ backup ฐานข้อมูลไว้อีกชุดหนึ่ง ในความเป็นจริงรูปทรงรีที่เป็นมาตรฐาน บางโปรแกรมจะไม่ให้ทำการแกัไข ที่จะแก้ไขได้แก่รูปทรงรีที่ผู้ใช้เพิ่มเข้าไป (user defined) ฉะนั้นเวลาโปรแกรมกันจริงๆ ฐานข้อมูลเราจะเพิ่มฟิลด์ READONLY ไปอีกฟิลด์หนึ่ง ถ้าเป็นรูปทรงรีมาตรฐาน READONLY จะเป็น TRUE
  • ฐานข้อมูลที่ทดสอบเป็นไปอย่างง่ายมีแค่ Table เดียว ถ้ามีหลาย Table เช่นการเขียนโปรแกรมแปลงค่าพิกัดที่ support หลายๆเส้นโครงแผนที่ (Map projection) ในฐานข้อมูลนี้จะจัดเก็บ datum ไว้อีก Table หนึ่งต่างหาก  ซึ่งจะมีค่าพารามิเตอร์ เช่น Translation แกน X, Y, Z และค่า Rotation แกน X, Y, Z และมึค่า Scale รวมแล้วเป็นเจ็ดพารามิเตอร์

Download sourcecode

  • sourcecode ของ post ตอนนี้สามารถ download ได้ที่ SQLiteProj2.zip

ทิ้งท้ายก่อนจาก

  • เป็นธรรมเนียมก่อนจะจบ post แต่ละตอนจะมีอะไรมาพูดคุยก่อนจะจาก ตอนที่แล้วผมพูดถึงไลบรารี ด้าน GIS คือ GDAL/OGR ที่ website จะเห็นมีตัว wrapper ด้วยภาษาอื่นๆที่ไม่ใช่ภาษา C++ เช่น Python, Ruby, Java, Perl และ C#/.Net การจะ wrapper ส่วนใหญ่จะตามมาตรฐานที่เรียกว่า SWIG (Simplified Wrapper and Interface Generator) มีกลุ่มโปรแกรมเมอร์ที่ตั้งมาตรฐานในการเขียนโปรแกรมเพื่อ interface กับ Library ที่เขียนด้วย C++ ด้วยภาษาอื่นๆที่ผมกล่าวมาแล้ว จะเห็นว่าขาด Delphi หรือ Lazarus และ VB (อีกแล้ว)
  • มีโปรแกรมเมอร์ชื่อ Stefano Moratto เขียน interface GDAL ด้วย SWIG ที่เขาเขียนด้วยตัวเขาเอง แต่ปรากฎว่าตั้งแต่ปี 2008 คุณ Frank Warmerdam ยังตามตัว Stefano Moratto ไม่เจอ แหมน่าเสียดายมาก ถ้ามี SWIG ของ GDAL ด้วย Delphi ก็วิเศษเลย จะเป็นประโยชน์แก่โปรแกรมเมอร์ Delphi อีกมากรวมทั้ง Lazarus ด้วย ไม่เป็นไรตัว wrapper ที่เขียนด้วย VB ที่ผมแปลงโค๊ดเป็น Lazarus ก็พอไหว ตอนนี้แค่นี้ก่อนครับ

การใช้ฐานข้อมูล SQLite กับ Lazarus ในเบื้องต้น (ตอนที่ 1)

  • ตอนก่อนหน้านี้ผมพูดเรื่อง SQLite พร้อมทั้ง tools สำหรับ admin ที่หาได้ในวินโดส์ พร้อมทั้งการ Pump ข้อมูลจากไฟล์ CSV เข้าฐานข้อมูล ต่อไปนี้จะมาดูลึกเข้าไปอีกนิด จะมาเขียนโปรแกรมเพื่อติดต่อกับฐานข้อมูล ด้วย Lazarus
  • ปัญหาของการพัฒนาโปรแกรมฐานข้อมูล SQLite ด้วย Lazarus ก็คือถ้าใช้ object จำพวก Data-aware(แทนฟิลด์)  เช่น  DBNavigator, DBEdit, DBGrid เป็นต้นพวกนี้อิงอยู่กับ Datasource และ Datasource อ้างอิงไปที่ชุด Dataset เช่น Table, Query, StoreProc และสุดท้าย Dataset อ้างอิงไปยัง Database ดูรูปโมเดลด้านล่างแสดงความสัมพันธ์
Database components model.
  • แต่ปัญหาของ SQLite  บน Lazarus นั้นเท่าที่พบใน Lazarus คือใช้ data-aware เช่น วาง DBNavigator, DBEdit, DBGrid ลงบนฟอร์ม วาง Datasource และวาง Dataset คือ TSQLite3Dataset ป้อนชื่อไฟล์ฐานข้อมูลให้กับ TSQLite3Dataset เมื่อทำการแก้ไขเช่นแก้ไขค่าในฟิลด์ ลบ record ทำการ Post ด้วย DBNavigator แต่เมื่อเปิดโปรแกรมมาใหม่ ข้อมูลจะไม่ update ยังเหมือนเดิม อืม………..ผมยังไม่รู้ว่าเป็นที่ Components ติดต่อฐานข้อมูลของ Lazarus หรือว่าเป็นที่ Library ของ SQLite แต่ความคิดผมน่าจะเป็นที่ Lazarus วิธีนี้ไม่ work
  • เอาใหม่วิธีนี้ต้องเขียน code มากขึ้น แต่ถ้าเข้าใจจะเป็นวิธีที่มีประสิทธิภาพมากที่สุด คือสามารถควบคุม บริหารฐานข้อมูลได้ลึกซึ้งกว่า และถ้าเปลี่ยนฐานข้อมูลจาก SQLite ไปเป็นฐานข้อมูลอื่นๆ จะแก้ code น้อยมาก เพราะโ้ค้ดทั้งหมดจะเป็นภาษา SQL ผมเขียนหัวข้อว่าเบื้องต้น แต่ในความเป็นจริงก็ไม่ยากเพราะภาษา SQL เป็นภาษามาตรฐานและง่ายต่อการเรียนรู้

เตรียมฐานข้อมูล SQLite

  • ตอนก่อนหน้านี้ ที่ผมแนะนำ tools ไปแล้วคือ SQLite Administrator เราสร้างไฟล์ฐานข้อมูล ผมตั้งชื่อว่า datums.s3db ตอนนี้มี table อยู่ 1 table คือ Ellipsoidas อนาคตเราจะสร้าง table เพิ่มคือ เส้นโครงแผนที่ (Map Projection) เข้ามาอยู่ด้วยกัน ดูรูปด้านล่าง
SQLite Administrator จัดการฐานข้อมูล

สร้าง New Project

  • เปิด Lazarus คลิกที่เมนู Project > New Project… เลือก Application วาง object เช่น ปุ่ม New…, Delelte…, Apply เป็นต้น ต่อจากนั้น  เราจะวางวัตถุจำพวก data-aware ตามปกติเช่น DBCombobox, DBText, DBEdit แล้ววาง DBNavigator ดูรูปด้านล่างประกอบ
วาง object เช่น controls data-aware ตั้งชื่อดังรูป
  • ตั้งชื่อ unit เป็น main ตั้งชื่อฟอร์มว่า frmSetEllipsoid แล้วแก้ไข uses ดังโค๊ดด้านล่าง อย่าลืมติดตั้งสอง component ที่ผมเคยกล่าวไปแล้วคือ sqlitedb.lpk กับ sqlitelaz.lpk ด้วยเมนูหลักคือ Package > Open package file (*.lpk) ซึ่งสอง component นี้อยู่ในโฟลเดอร์ c:\lazarus\components\sqldb และ c:\lazarus\components\sqlite ตามลำดับ
unit main;

{$mode objfpc}{$H+}

interface

uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
StdCtrls, ExtCtrls, sqldb, DbCtrls, db, SQLite3Conn;

จุดประสงค์ของโปรแกรม

  • ต้องการอ่านฐานข้อมูล SQLite ที่เตรียมไว้มาแสดงบน data-aware ต่างๆ เช่น DBCombobox, DBEdit แล้วทำการ Edit ข้อมูลเช่นเพิ่ม record ลบ record ด้วยการเขียนโค๊ดคุมเป็นหลัก ต่อไปผมจะ post โค๊ดทั้งหมดที่อยู่บนยูนิต main (main.pas)
unit main;

{$mode objfpc}{$H+}

interface

uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
StdCtrls, ExtCtrls, sqldb, DbCtrls, db, SQLite3Conn;

type

{ TfrmSetEllipsoid }

TfrmSetEllipsoid = class(TForm)
cmdDelete: TButton;
cmdNew: TButton;
cmdApply: TButton;
cmdOK: TButton;
cmdCancel: TButton;
dbtxtFlattening: TDBEdit;
dbtxtSemiMajorAxis: TDBEdit;
dbtxtEllipsoidCode: TDBEdit;
DBNavigator1: TDBNavigator;
dbcboEllipsoidName: TDBComboBox;
GroupBox1: TGroupBox;
Image1: TImage;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;

procedure cmdApplyClick(Sender: TObject);
procedure cmdCancelClick(Sender: TObject);
procedure cmdDeleteClick(Sender: TObject);
procedure cmdNewClick(Sender: TObject);
procedure cmdOKClick(Sender: TObject);
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ private declarations }
FDBCon : TSQLite3Connection;
FTrans : TSQLTransaction;
FSql : TSQLQuery;
FDatasource : TDatasource;
FDatabaseFile : string;
FNewRecordState : boolean;
public
{ public declarations }
end;

var
frmSetEllipsoid: TfrmSetEllipsoid;

implementation

{ TfrmSetEllipsoid }

procedure TfrmSetEllipsoid.cmdOKClick(Sender: TObject);
begin
FSql.Close;
FDBCon.Close;
FTrans.EndTransaction;
Close;
end;

procedure TfrmSetEllipsoid.FormClose(Sender: TObject;
var CloseAction: TCloseAction);
begin
FTrans.EndTransaction;
FSql.Close;
FDBCon.Close;
end;

procedure TfrmSetEllipsoid.FormCreate(Sender: TObject);
begin
//เปลี่ยน path ที่อยู่ของฐานข้อมูลให้ตรงกับโฟลเดอร์ที่เก็บ
FDatabaseFile := 'e:\sourcecodes\lazarus\sqliteproj2\datums.s3db';

FDBCon := TSQLite3Connection.Create(NIL);
FTrans := TSQLTransaction.Create(NIL);
FSql := TSQLQuery.Create(NIL);
FDatasource := TDatasource.Create(NIL);

FDBCon.DatabaseName := FDatabaseFile;
FDBCon.Transaction := FTrans;
FTrans.DataBase := FDBCon;
FSql.DataBase := FDBCon;
FSql.Transaction := FTrans;
FDBCon.Connected := true;
FTrans.Active := true;
FDatasource.Dataset := FSql;
FDatasource.AutoEdit := true;

FSql.Close;
FSql.SQL.Clear;
FSql.SQL.Text := 'SELECT * FROM ELLIPSOIDS';
FSql.Open;
//FTrans.CommitRetaining; {This line does not work in win32. But OK in linux???}

dbcboEllipsoidName.DataSource := FDatasource;
dbcboEllipsoidName.DataField := 'NAME';
dbtxtEllipsoidCode.DataSource := FDatasource;
dbtxtEllipsoidCode.DataField := 'CODE';
dbtxtSemiMajorAxis.DataSource := FDatasource;
dbtxtSemiMajorAxis.DataField := 'A';
dbtxtFlattening.DataSource := FDatasource;
dbtxtFlattening.DataField := 'INV_F';
DBNavigator1.DataSource := FDatasource;

FNewRecordState := false;
end;

procedure TfrmSetEllipsoid.FormDestroy(Sender: TObject);
begin
FTrans.Free;
FSql.Free;
FDatasource.Free;
//Make sure TSQLite3Connection is the last.
FDBCon.Free;
end;

procedure TfrmSetEllipsoid.cmdCancelClick(Sender: TObject);
begin
Close;
end;

procedure TfrmSetEllipsoid.cmdDeleteClick(Sender: TObject);
var
szECode : string;
sql : TSQLQuery;

begin
try
sql := TSQLQuery.Create(nil);
sql.Database := FDBCon;
sql.Transaction := FTrans;
szECode := dbtxtEllipsoidCode.Text;

if (MessageDlg ('คำเตือน','ยืนยันว่าต้องการลบทรงรี', mtConfirmation,
[mbOK, mbCancel],0) = mrOK) then
begin
sql.Close;
sql.SQL.Text := 'DELETE FROM ELLIPSOIDS WHERE CODE = :CODE';
sql.Params.ParamByName('CODE').AsString := szECode;
sql.ExecSQL;
FSql.ApplyUpdates;
FTrans.CommitRetaining;
FSql.Close;
FSql.SQL.Clear;
FSql.SQL.Text := 'SELECT * FROM ELLIPSOIDS';
FSql.Open;
FTrans.CommitRetaining;
end;

finally
sql.Free;
end;
end;

procedure TfrmSetEllipsoid.cmdNewClick(Sender: TObject);
begin
//Make its to ready for editable.
dbcboEllipsoidName.ReadOnly := false;
dbtxtSemiMajorAxis.ReadOnly := false;
dbtxtflattening.ReadOnly := false;
dbtxtEllipsoidCode.ReadOnly := false;
dbcboEllipsoidName.Text := '';
dbtxtSemiMajorAxis.Text := '';
dbtxtFlattening.Text := '';
dbtxtEllipsoidCode.Text := '';
cmdApply.Enabled := true;
cmdNew.Enabled := false;
DBNavigator1.BtnClick(nbInsert);
FNewRecordState := true;
end;

//The big problem that DBNavigator1.Post method doesn't work.
//using query to solve the problem with ExeSql method.
procedure TfrmSetEllipsoid.cmdApplyClick(Sender: TObject);
var
szEName, szECode : string;
dA, dB, dF : extended;
f1, f2 : boolean;
sql : TSQLQuery;
begin
try
sql := TSQLQuery.Create(nil);
sql.Database := FDBCon;
sql.Transaction := FTrans;
szEName := trim(dbcboEllipsoidName.Text);
szECode := trim(dbtxtEllipsoidCode.Text);
if (szEName <> '') and (szECode <> '') then
begin
szECode := Trim(dbtxtEllipsoidCode.Text);
f1 := trystrtofloat(dbtxtSemiMajorAxis.Text, dA);
f2 := trystrtofloat(dbtxtFlattening.Text, dF);
dB := dA - dA * 1 / dF;
if (FNewRecordState) then
begin
if (f1 and (dA > 6377000)) and (f2 and (df > 293)) then
begin
sql.Close;
sql.SQL.Clear;
sql.SQL.Text := 'INSERT INTO ELLIPSOIDS (NAME,CODE,A,B,INV_F)'
+ ' VALUES (:NAME,:CODE,:A,:B,:INV_F)';
sql.Params.ParamByName('NAME').AsString := szEName;
sql.Params.ParamByName('CODE').AsString := szECode;
sql.Params.ParamByName('A').AsFloat := dA;
sql.Params.ParamByName('B').AsFloat := dB;
sql.Params.ParamByName('INV_F').AsFloat := dF;

sql.ExecSQL;
cmdApply.Enabled := False;
cmdNew.Enabled := true;
FTrans.CommitRetaining;
FNewRecordState := false;
end
else if not(f1 and (dA > 6377000)) then
begin
MessageDlg ('Warning', 'Semi-major axis must be the number and its value must > 6,377,000 m.?', mtConfirmation,
[mbOK],0);
dbtxtSemiMajorAxis.SetFocus;
end
else if not (f2 and (df > 297)) then
begin
MessageDlg ('Warning', 'Flattening must be the number and its value must > 297 m.?', mtConfirmation,
[mbOK],0);
dbtxtFlattening.SetFocus;
end;
end
else
begin
sql.Close;
sql.SQL.Clear;
sql.SQL.Text := 'UPDATE ELLIPSOIDS SET NAME=:NAME,'
+ 'A=:A,B=:B,INV_F=:INV_F WHERE CODE=:CODE';
sql.Params.ParamByName('NAME').AsString := szEName;
sql.Params.ParamByName('CODE').AsString := szECode;
sql.Params.ParamByName('A').AsFloat := dA;
sql.Params.ParamByName('B').AsFloat := dB;
sql.Params.ParamByName('INV_F').AsFloat := dF;

sql.ExecSQL;
cmdApply.Enabled := False;
FTrans.CommitRetaining;

end;
end;
finally
sql.Free;
end;
end;

initialization
{$I main.lrs}

end.

  • ติดตามตอนหน้าผมจะอธิบายโค๊ดที่สำคัญ เราจะทดลองเพิ่มและลบ record ที่อยู่ในฐานข้อมูลดู

ทิ้งท้ายก่อนจากกัน

  • ที่ผ่านมาผมเขียนถึงเรื่อง GIS Components ที่จะหานำมาพัฒนาโปรแกรม Desktop application ด้าน GIS สุดท้ายมาพบกับ Quantum GIS แต่มีปัญหาว่าโค๊ดเป็นภาษา C++ ซึ่งการแปลง header file ของ C++ ไม่ใช่เรื่องง่ายสำหรับผมซึ๋งไม่กระดิก C++ เลย และจำนวนไฟล์ header ก็มีมาก เลยลดเกรดลงมาดูจำพวก library ทีี่เกี่ยวข้องกับด้าน GIS ที่ดังๆ ก็คือ GDAL/OGR ชื่อเต็มๆก็คือ Geospatial Data Abstraction Library ที่จริงรู้จักตั้งนานแล้วแต่ไม่ใช่ในฐานะโปรแกรมมิ่ง GDAL/OGR ถูกนำไปใช้ด้วยโปรแกรมดังๆมากมาย เช่น ArcGIS, Google Earth, Minisota Mapserver, MapWindow, FWTools,QGIS และอื่นๆอีกหลายโปรแกรม เป็น library ที่นำมาจัดการกับพวก Raster file (GDAL) และ Vector file (OGR) ผมดูใน website ของ GDAL พบว่ามีคนเขียนด้วย VB6 ด้วยการ wrap ขึ้นเป็น class ผมนำมาแปลงเป็นโค๊ดของ Lazarus ช่วงนี้อยู่ระหว่างการทดสอบ แต่ก็ผ่านไปแล้วประมาณ 80% ว่างๆจะนำมาแนะนำกัน
  • คือในโลกของ Opensource เป็นโลกแห่งการ share กัน และร่วมพัฒนาต่อยอดขึ้นไปอีก GDAL/OGR ทีมพัฒนานำโดยคุณ Frank Warmerdam เป็นคนที่มีชื่อเสียงมาก ผมลองค้นคำว่า Frank Warmerdam GDAL บน Google พบจำนวน record ทั้งหมดประมาณ 75,000 ไม่ธรรมดาเลย ต่อไปลองไปดู plunins ของ Quantum GIS ที่ใช้ไลบรารีของ GDAL/OGR ที่ผมเปิดให้ดูเป็น OGR ใช้แปลง vector file ผมลองแปลงจาก Shape file ไปเป็น Sqlite แล้วเปิดด้วย QGIS ก็สามารถเปิดได้ ดูรูปด้านล่าง
การแปลง vector file ด้วยการใช้ plugins ของ GDAL/OGR บน QGIS
  • ตอนต่อๆไปผมจะำนำไลบรารี GDAL/OGR มารันด้วย Lazarus และจะลองเขียนโปรแกรมแปลงฟอร์แม็ตของ Raster/Vector ดู ด้วยการใช้สุดยอดไลบรารีตัวนี้ครับ

การสร้าง 3D Anaglyph ด้วย MicroDem

  • ตอนที่แล้วผม post การทำ animation (flyby) ด้วย 3Dem ซึ่งโปรแกรมได้หยุดพัฒนาไปแล้ว มาดู Tools ที่ฟรีตัวต่อไป ที่นำมาใช้งานด้าน GIS เป็นโปรแกรมรุ่นเก่าเหมือนกัน แต่ตัวนี้ยังพัฒนาต่อเนื่อง และ MicroDem นี้มี feature ที่แฝงอยู่เป็นจำนวนมาก แต่ข้อเสียของโปรแกรมนี้คือ ใช้งานยาก ถ้าไม่รู้ว่าอะไรอยู่ตรงไหน เวลาใช้งานครั้งแรกๆ จะหงุดหงิด พาลเลิกไปเลย คือมี icon ของฟังก์ชั่น เยอะไปหมด พอคลิกดูที่น่าใช่กลับไม่ใช่ คือวิจารณ์ข้อเสียของ software ส่องกระจกดูก็เป็นข้อเสียของผมสะท้อนกลับมาเหมือนกัน คือนิสัยเสียไม่ค่อยอยากอ่านคู่มือ ใช้วิธีแกะวิธีใช้จากการลองผิดลองถูก แต่ถ้าเป็น User Interface ที่เรียบง่ายคือออกแบบได้อย่างที่เรียกว่า User friendly อย่าง Global Mapper นี่แทบไม่เคยอ่านคู่มือเลย
  • อย่างที่ผมจะเขียนเรื่องการทำ 3D Anaglyph คือเป็นภาพสามมิติ ที่ต้องใช้แว่นตา แดง/น้ำเงิน (ที่ใช้ดูหนัง 3D บนทีวีหรือโรงหนังก็ได้) มาส่องดูถึงจะเห็นเป็นภาพสามมิติ ถ้าเอาไปขึ้นจอ projector ก็เป็น idea ที่ไม่เลว แต่ต้องเตรียมแว่นตา ไว้หลายๆอันหน่อย ถูกๆหน่อยก็ที่ทำด้วยกระดาษ ถ้าใครที่ใช้โปรแกรมด้าน GIS อยู่บ่อยๆ จะเข้าใจเลยว่าถ้าพูดถึงภาพ 3D Anaglyph ต้องมีอะไรบ้าง หนึ่งคือ tools ที่ใช้สร้างภาพ Anaglyph อย่างง่าย สองต้องมี DEM  สามที่ต้องไม่ลืมคือแว่นตา แดง/น้ำเงิน
  • เมื่อเปิด DEM แล้ว ทำการ Map shading ซึ่งมีให้เลือก 4-5 อย่าง ต่อจากนั้นสั่งให้โปรแกรม render เป็น 3D Anaglyph แล้วใส่แว่นตาดู โปรแกรมถ้าใช้งานง่าย concept ก็ควรจะเป็นอย่างที่ผมกล่าว ที่นี้มาดูว่า MicroDem ใช้งานยากที่ร่ำลือเป็นอย่างไรกัน
MicroDem01
การสวมภาพ Map Shading จาก MicroDem เข้า Google Earth โดยตรง(แค่คลิกเมาส์สองคลิก) ทำให้ 3D ของ MicroDem ไปโผล่ใน Google Earth ดูสวยแปลกตา

ความเป็นมาของ MicroDem

  • เป็นโปรแกรม Freeware ด้าน GIS ที่ดูประวัติแล้วเริ่มต้นจากทีมงานของหน่วยทหารช่างของอเมริกา คือ US Naval Academy ที่เริ่มต้นครั้งแรกปี 1985 พยายามครั้งแรกบนเครื่อง Apple II แต่มาประสบความสำเร็จบนเครื่อง PC. ปี 1987 หัวหน้าทีมพัฒนาโปรแกรมก็คือ ศาตราจารย์ Peter Guth ครั้งแรกถูกพัฒนาด้วย Turbo Pascal เวอร์ชั่นบน DOS ถูก port เป็น Borland Delphi ในปี 1995 และถูกพัฒนาด้วย Delphi ตลอดมา
  • MicroDem สนับสนุนฟอร์แม็ตได้หลายๆตัวที่สำคัญๆ เช่น GeoTiff, Shape file, SRTM DEM, MrSid
  • ที่ผมสนใจโปรแกรมตัวนี้เป็นพิเศษเพราะว่าพัฒนาด้วย Delphi ถือว่าเป็น compiler ต้นธารของผมเลย คือมีความผูกพันธ์กับ compiler ตัวนี้ถึงแม้ผู้สร้างคือ Borland จะล้มหายตายจากไปแล้วก็ตาม

เตรียม Resource ให้ MicroDem

  • ผมขอใช้ resource เดียวกันกับตอนที่แล้ว ที่ใช้ 3DEM มี DEM อยู่หนึ่งไฟล์ พื้นที่เป็นแหลมเมืองทวาย พม่า DEM ที่วัดได้จากกระบวนการภาพถ่ายทางอากาศ เพื่อสร้างแผนที่ 1:50000 ของพม่า มีความละเอียดมากกว่า SRTM DEM อยู่พอสมควร คือ resource ของพื้นที่บริเวณนี้ได้มาเป็นจุด DTM ในรูป DWG แล้วนำมา export เป็น 3D Points นำเข้า Global Mapper แล้วสร้างเป็น GeoTiff DEM มีขนาด pixel 15mx15m (ทึ่จริงขนาด 30mx30m ก็ได้)

ปรับแต่ง Configuration ของ MicroDem ก่อนใช้งาน

  • ผู้ใช้บางท่านอาจจะมีข้อมูลที่อ้างอิงกับ Indian 1975 datum อยู่แต่พารามิเตอร์ที่โปรแกรมตั้งมายังไม่ถูกต้อง กับพารามิเตอร์ของกรมแผนที่ทหาร ดังนั้นถ้านำข้อมูลที่อ้างอิงกับ Indian 1975 มาใช้งานจะไม่ถูกต้อง
  • ตอนติดตั้งโปรแกรม MicroDem จะเลือกติดตั้งที่ C:\MicroDem จะมีไฟล์กำหนดรูปทรงรี คือ  GT_Ellip.dat และไฟล์กำหนด datum คือ GT_datum.dat ไฟล์กำหนดรูปทรงรีไม่ต้องสนใจเพราะถูกต้องแล้ว แต่จะำทำการแก้ไข GT_datum.dat ให้ถูกต้องตามพารามิเตอร์ของกรมแผนที่ทหาร ผมใช้ Notepad++ หรือจะใช้  Notepad ที่ติดมากับ windows ก็ได้

microdem02

  • ทำการแก้ไขให้ถูกต้องดังรูปด้านล่าง แล้ว save
microdem03
แก้ใขค่าพารามิเตอร์ของการ Transformation ใหตรงกับของกรมแผนที่ทหาร
  • รันโปรแกรม MicroDem ที่เมนูหลักของ MicroDem คลิกที่ Options แล้วแท็ปไปที่ Datum ตั้งค่าที่ UTM zone ตั้งเป็น 47 ซึ่งเป็นพื้นที่ส่วนใหญ่ของไทย ถ้าใช้งานอยู่แถว Zone 48 ก็ตั้งค่าเป็น 48 Hemisphere เลือกเป็น North เพราะไทยเราอยู่เหนือเส้นศูนย์สูตร Primary Datum เลือกเป็น WGS84 ส่วน Secondary Datum ผมเลือกเป็น INDIAN 1975, Thailand (ที่เราเพิ่งแก้ค่าพารามิเตอร์ไป) ก็เลือกตามรูปด้านล่าง แต่อย่าลืมติ๊กเครื่องหมาย Verify datums เวลาเปิดรูป เปิด DEM โปรแกรม MicroDem จะถามเพื่อ confirm
microdem04
ตั้งค่า configuration ที่ datum

นำเข้า DEM

  • ที่เมนูหลักของ MicroDem คลิกที่ File > Open > Open DEM เลือกไฟล์ DEM ที่เราเตรีียมไว้ จากนั้นโปรแกรมจะถาม Datum ตั้งค่าให้ตรงกับ DEM ของเราดังรูปด้านล่าง

microdem05

  • จะเห็น DEM แสดงผลในลักษณะ Map Shaded ซึ่งภายหลังเราสามารถปรับได้หลายอย่าง (มากกว่าโปรแกรม 3DEM)

microdem06

  • ที่กรอบการแสดงผลของ DEM สังเกต icon ที่เป็นรูปสี่เหลี่ยมมีลูกศรชี้เข้าหา (icon ที่ 5 จากซ้ายมือ คลิกเพื่อขยายรูป) เลือกพื้นที่ที่ต้องการขยาย
  • microdem08ต่อไปเราจะตั้ง Map shading options ซึ่ง MicroDem เตรียมรูปแบบมาให้แตกต่างกัน 3-4 อย่าง ที่รูป DEM คลิกขวาเพื่อเลือก options แล้วคลิกที่ Map Shading Options ดังรูปด้านล่าง

microdem09

การทำ Map Shading

  • จะเห็นเงื่อนไขหรือทางเลือก DEM color merge อยู่ 4 อย่างคือ Elevation, Slope, Reflectance, Terrain Shading
    • ถ้าเลือก Elevation การไล่เฉดสีจะเป็นไปตามค่าระดับของพื้นที่
    • ถ้าเลือก Slope การไล่เฉดสีเป็นไปตามความชัันของพื้นที่ เช่นความชันน้อยๆเป็นสีอ่อน ถ้าชันมากก็เป็นสีเข้ม ซึ่งผู้ใช้สามารถเลือกตั้งค่าได้
    • ถ้าเลือก Reflectance ผมคิดว่าดูดีที่สุดเป็นธรรมชาติคือสามารถตั้งแสงเงาและทิศทางได้ด้วย
    • ถ้าเลือก Terrain Shadings คล้ายกับ Reflectance มาก แต่เหมือนจะใส่การ blending เข้าไปมากจะทำให้ภาพดูมืดมากกว่า แต่ความคมชัดมากกว่า Reflectance
  • ลองเลือกดูตามใจชอบ ส่วนผมชอบ Refectance มากที่สุด
microdem10
ตั้งค่าสำหรับ DEM Color merge ลองเลือก Elevation
microdem11
เมื่อเลือก DEM Color Merge เป็น Elevation
  • ดูที่กรอบหน้าต่างแสดงผล DEM สามารถ pan ได้ด้วยการคลิกที่เครื่องหมายลูกศร UI ยังโบราณมาก ความจริงถ้าให้คลิกเมาส์ปุ่มกลางกดค้างแล้วลากจะสะดวกมากกว่า ลองเลือกเป็น reflectance ดู
microdem12
เลือก DEM Color merge เป็น Reflectance

การส่งภาพไปแสดงผลที่ Google Earth

  • นี่เป็น feature ที่เด็ดที่สุดของ MicroDem สามารถยิงไปออกที่ Google Earth ได้เลย ในแง่โปรแกรมมิ่ง เทคนิคนี้เป็นไม่ใช่เทคนิคใหม่ เรียกอะไรจำไม่ได้แล้ว คือ Google Earth ต้องให้ Type Library มา ถึงจะเขียนโปรแกรมติดต่อได้ ที่ผมใช้อยู่ประจำคือ Autocad และ Microsoft Excel สามารถเขียนแบบด้วยโค๊ดแล้วส่งเข้าไปแสดงผลใน Autocad หรือ Excel ได้เลย ถึงจะเป็นเทคนิคเก่าแต่สะดวกมาก (แต่ที่โปรแกรมเมอร์ไม่ค่อยอยากเขียนเท่าไหร่เพราะคุมไม่ได้เช่น Type library สำหรับ Google Earth version 5 แต่พอถึง version  7 อาจจะเปลี่ยนการ interface ใหม่ ทำหให้โปรแกรมที่เขียนติดต่อกับ Google Earth ที่ยังอิงกับ Type library version เก่าก็ใช้ไม่ได้) ไม่ต้องหาโปรแกรมมาแปลงเป็น KML/KMZ คลิกเมาส์แล้วส่งออกไปเลย มาดูกันครับ ที่ภาพของ DEM คลิกขวาเลือก Load > Google Earth overlay

microdem13

  • ลองดูผลลัพธ์ ภาพที่ overlay เข้าโดยมีฟอร์แม็ต PNG ที่สามารถทำ transparency กับ ภาพของ Google Earth ลองดูรูปด้านล่าง
microdem14
ภาพที่ส่งเข้ามาจาก MicroDem
  • ดูภาพด้านบน สวยงามมาก ที่จริงเป็นภาพอะไรก็ได้ที่อ้างอิงกับ Georeference ที่สามารถอ่านด้วย MicroDem ก็สามารถส่งเข้ายัง Google Earth ได้เสมอ

3D Anaglyph

  • สุดท้ายที่เราตั้งเป้าไว้คือการแสดงผลแบบ 3D Anaglyph ที่หน้าต่างแสดง DEM คลิกขวาเลือก 3D Map  Options ตั้งค่า ที่ stereo mode ตั้งเป็น Anaglyph คลิกที่ OK เพื่อ Render ใหม่
microdem15
ตึ้งค่า 3D Anaglyph
  • เตรียมแว่นตา 3D ดูได้เลย
microdem16
ภาพ 3D Anaglyph

ข้อดีและข้อด้อยของ MicroDem

  • ในขณะใช้ MicroDem ทำ render ภาพ 3D ถ้าเกิดภาพหายไปดื้อๆ ไม่ต้องตกใจ เป็นเรื่องปกติ ปิดหน้าต่างแล้วเปิด DEM มาใหม่ มี  bug  บางส่วนไม่ได้รับการแก้ไขอยู่อีกหลายจุด
  • การ pan การ zoom ไม่เคยปรับปรุงมานานแล้ว ใช้งานยาก การเพิ่มโค๊ดเพื่อการ pan และ zoom แบบ real time ก็ไม่ใช่เรื่องหนักหนาสาหัสอะไรในทางโปรแกรมมิ่ง
  • ส่วนที่น่าสนใจมากของโปรแกรมนี้คือสนับสนุนเรื่อง Geology ซึ่งผู้พัฒนาโปรแกรมแต่ละคนก็ขนาดศาสตราจารย์ทั้งนั้น และทำงานให้แผนก Geology โปรแกรมจึง support ด้านนี้ สามารถนำภาพที่ได้จากการสำรวจ side scan sonar, sub-bottom profiler (เป็นงานสำรวจที่ทีมงานผมทำอยู่เหมือนกัน) เข้าไปซ้อนเป็นชั้นข้อมูลกับ DEM ได้ หรือสามารถนำข้อมูลชั้นดินมารวมกับชั้นข้อมูลอื่นๆ ได้ ฟีเจอร์หลายๆอย่างน่าสนใจ ถ้าถามว่าทำไมโปรแกรมใช้งานยาก หนึ่งคือไม่ใช่โปรแกรมเพื่อการค้า สองดูที่ผู้พัฒนาโปรแกรมระดับศาสตราจารย์ทั้งนั้น (เหตุผลข้อหลังไม่ขยายความต่อนะครับ) ถึงแม้จะใช้งานยาก แต่ก็ไม่เกินความพยายามของเรา เพราะเป็นของฟรี และความสามารถของโปรแกรมก็มีอะไรดีที่คาดไม่ถึงอยู่อีกมากครับ
  • ความคิดของผมเมื่อโปรแกรมมาถึงในจุดที่ทำต่อไปไม่ไหวก็เปิดเป็น opensource มี library หลายตัวของ MicroDem ที่น่าสนใจสามารถนำมาทำเป็น GIS Component ได้สบายๆ

การจำลองภาพเคลื่อนไหวมุมสูง (Flyby) 3D ด้วย Tools ฉบับกระเป๋า 3DEM

3Dem

  • เป็นโปรแกรมขนาดเล็กมาก จะเรียกว่าฉบับกระเป๋าก็ได้ เขียนโดย Richard Horne ตอนนี้หยุดพัฒนาไปแล้วครับ ถึงจะหยุดพัฒนาไปแล้วแต่ก็ยังหา download ได้หลาย website เช่นที่นี่  3dem_setup.exe โปรแกรม 3DEM เมื่อออกมาใหม่ๆเป็นที่กล่าวขานพอสมควร คือออกมานานมากตั้งแต่ Windows 95 นู่นครับ ใช้ OpenGL เป็น engine ในการ render เป็น 3D และแน่นอนสามารถจำลองเป็นภาพเคลื่อนไหว สามารถจัดเก็บเป็นฟอร์แม็ต avi และ mpg
  • น้องๆที่เป็นนักศึกษาที่ศึกษาด้าน GIS และคงจะมีหลายๆคนที่ศึกษาด้านโปรแกรมมิ่งด้วย โปรแกรม 3DEM นี้ก็เป็นโปรแกรมตัวอย่างที่ดี ที่ทำใ้ห้ผู้พัฒนาเป็นที่รู้จัก ถึงแม้คุณ Richard Horne จะไม่เอาดีด้านการค้า แต่ก็เขาก็ฝากชื่อไว้ให้เป็นที่รู้จัก

3Dem

  • รูปด้านบนนี่เป็นภาพจาก website ของ 3DEM ซึ่งปิดตัวไปแล้ว หลักการจำลองภาพ 3D แบบนี้เรียกว่าการ Drape ถ้าแปลตรงๆก็คือการสวม หลักการก็คือต้องมี DEM ก่อนแล้วหาไฟล์ที่เป็นภาพถ่ายทางอากาศสวมทับลงไป ยิ่งเป็นภาพถ่ายทางอากาศที่ละเีอียดก็ยิ่งสวย ภาพถ่ายอาจจะเป็นภาพถ่ายดาวเทียม(satelite image) หรือภาพถ่ายจากเครื่องบิน (aerial image) ที่สำคัญคือภาพถ่ายทางอากาศต้องมีลักษณะที่อ้างอิงกับค่าพิกัดภูมิศาสตร์จริง (Georeference) ส่วน DEM ถ้าเป็นประเทศไทยมี DEM (ขนาด pixel 30mx30m) ของกรมแผนที่ทหาร หรือจะใช้ของ SRTM DEM (ขนาด pixel 90mx90m) ที่แนะนำวิธีการ Download ได้จาก blog ของผมตอนก่อนๆ

เตรียมของให้ 3DEM

  • download ภาพถ่าย Landsat 7 ด้วย Global Mapper เป็นวิธีที่ง่ายที่สุด แต่เวลา save ไฟล์ออกมา จะเสียเวลาหน่อย ยิ่งเป็นไฟล์ใหญ่ก็ใช้เวลามากขึ้น
ภาพถ่ายดาวเทียม Landsat 7
ภาพถ่ายดาวเทียม Landsat 7
  • download SRTM DEM พื้นที่เีดียวกันกับภาพถ่ายดาวเทียม ใช้วิธี download ผ่าน Google Earth ที่ผมเขียนไปแล้วก็ง่ายสะดวกดี DEM ที่ผมจะใช้เป็นตัวอย่างได้จาก link ของ Google Earth srtm_56_10.zip ขนาดของ DEM ไฟล์นี้ค่อนข้างใหญ่ ผมใช้ Global Mapper ทำการ Crop ให้ DEM มีขนาดใกล้เคียงกับภาพถ่ายดาวเทียม Landsat แล้ว save เป็นฟอร์แม็ต GeoTiff

เริ่มใช้ 3DEM

  • หลังจาก download โปรแกรม 3DEM มาแล้วทำการติดตั้งแล้วก็รัน เมื่อเปิดโปรแำกรมมา จะถามหาไฟล์ DEM เลือกไฟล์ที่เราเซฟไว้
3DEM01
เลือก GeoTiff สำหรับ DEM
  • ข้อสังเกต ฟอร์แม็ตที่ 3DEM อ่านได้ยังถือว่าน้อยไปแต่ก็ไม่เป็นไร เมื่อเปิด DEM มาแล้วจะเห็นภาพของ DEM ที่ทำการ Shaded reliedf แล้ว ก็สวยงามดี
3DEM02
3DEM แสดง SRTM DEM บริเวณแหลมทวาย พม่า

การ Drape

  • ต่อไปจะโหลดภาพถ่ายดาวเทียมแล้วสวม (drape) ลงไป ที่เมนูหลัก คลิกที่ Operation > F4 Apply/Remove Map Overlay เลือกไฟล์ภาพถ่ายดาวเทียม Landsat 7
3DEM04
เปิดภาพถ่ายดาวเทียม Landsat 7
  • เมื่อ Drape ลงไปจะเห็นโปรแกรม 3DEM แสดงภาพถ่ายดาวเทียม Landsat 7 บน DEM
3DEM05
สวมภาพถ่ายลงบน DEM
  • จากรูปด้านบนจะเห็นกรอบสีดำอยู่ด้านล่าง กรอบนี้คือบริเวณที่โปรแกรมจะแสดงภาพ 3D

3D View

  • ต่อไปจะเปิดโหมดการแสดงผล 3D ที่เมนูหลักคลิกที่ Operation > F2 3D Scene หรือกด F2 ที่คีย์บอร์ดก็ได้ จะเห็น Dialog ให้ตั้งค่าดังรูปด้านล่าง
3DEM06
ตั้งค่าการแสดงผล 3D
  • 3DEM จะเปิดหน้าต่าง 3D Scene มาแสดงผลภาพ 3D
3DEM07
3D View
  • ภาพ 3D ก็พอดูได้ ข้อเสียถึงแม้เรามี DEM ขนาดใหญ่แต่ 3DEM พยายาม render ให้เฉพาะกรอบสีดำที่ผมกล่าวไปข้างต้น จึงทำให้ภาพ 3D จึงดูขาดๆ ค้านกับความเป็นจริง แต่รวมๆก็ OK นะครับสำหรับเป็น case study ที่เมนู 3D Scene สามารถ save เป็นฟอร์แม็ต 3D VRML ได้ด้วย

3D VRML

  • ถ้าสนใจ VRML มีโปรแกรมที่เป็น plug in ของ browser ชื่อ Cortona 3D สามารถดาวน์โหลดและติดตั้งได้ที่ download แล้วใช้เมนูของ browser (ผมใช้ Firefox) คลิกที่เมนู File > Open file… เปิดไฟล์ 3D VRML (.wrl) จะเห็นภาพ 3D ที่พร้อมจะทำ animate ดังรูปด้านล่าง
Cortona3D
Cortona 3D บน Firefox

3D Flyby

 

  • มาดูความสามารถของ 3DEM ที่ทำ Flyby จะเห็นหน้าต่าง 3D Scene อีกครั้ง ถ้าต้องการดูภาพเคลื่อนไหวก็ดูได้ แต่ถ้าต้องการเซฟเป็นไฟล์ วีดีโอ ต้องปิดหน้าต่าง 3D Scene นี้ก่อน การจะ flyby เราต้องมีเส้นทาง (fly path) ให้โปรแกรม 3DEM ซึ่งสามารถใช้เมาส์คลิกเป็นจุดๆต่อเนื่องตามความพอใจ ที่เมนูหลัก เลือก GPS > Enter GPS Points by mouse จัดการคลิกเพื่อสร้างจุดต่อเนื่องเป็นเส้นทางการบิน ที่รูปด้านล่างสังเกตดูเส้นสีแดงที่ผมสร้างไว้
3DEM09
สร้างเส้นทางการบินจำลอง
  • ที่เมนูหลักคลิกที่ Operation > Animate Flyby ตั้งค่าให้ตรงกับความต้องการ
3DEM08
ตั้งค่าสำหรับ Flyby
  • เมื่อคลิก OK แล้วป้อนชื่อไฟล์ เลือกชนิดไฟล์วีดีโอเป็น mpg จากนั้นจะมี dialog ถามเกี่ยว codec และ frame rate ตั้งค่าตามค่าปริยาย คลิก OK แล้วหน้าต่าง 3D Scene จะขึ้นมาอีกครั้งและแสดงภาพเคลื่อนไหวบินจำลอง รอจนกระทั่งสิ้นสุด fly path ลองเปิดไฟล์วีดีโอด้วยโปรแกรมพวก Media player
3DEM10
3D Flyby animation
  • เมื่อนำไฟล์มาเล่นด้วยโปรแกรมจำพวก Media player ดูแล้ว smooth มากน่าประทับใจไม่แพ้สร้างใน Google Earth

แนะนำการใช้งาน Global Mapper สุดยอด Tools ด้าน GIS

  • เขียนถึง Global Mappler หลายครั้งแล้ว ย้อนรอยกลับมาตั้งต้นอีกครั้งสำหรับคนที่สนใจ tool ตัวนี้ ผมจะรีวิวให้เห็นความสามารถ ข้อดีและข้อด้อยเท่าที่ผมใช้งานมา
  • Global Mapper เดิมทีผู้พัฒนาโปรแกรมวางตัวโปรแกรมให้เป็น Utility ในตอนนี้โปรแกรมได้พัฒนามาไกลเกินกว่าจะเป็นแค่ utility ธรรมดา ถ้าจะมองเป็น utility ก็น่าจะเป็น Power utility ที่ผมชอบตั้งแต่แรกใช้ Global Mapper ก็ตรงที่สนับสนุน format ข้อมูล Vector และ Raster & Elevation data ได้หลากหลายมาก
  • มาดูว่า Global Mapper สนับสนุนฟอร์แม็ตอะไรบ้าง

ข้อมูลเชิงเส้น(Vector Data)

  • Arc Ungenerate format
  • AutoCAD DXF format
  • CDF format
  • CSV format
  • Delft3D (LDB) format
  • DeLorme Text/Drawing format
  • DGN format
  • DWG format
  • ESRI Shapefile format
  • Garmin PCX5 TRK and WPT formats
  • GeoPDF format
  • GPX (GPS eXchange Format)
  • KML/KMZ (Google Earth) formats
  • InRoads ASCII format
  • Landmark Graphics format
  • Lidar LAS format
  • Lowrance LCM format
  • Lowrance USR format
  • MapGen format
  • MapInfo MIF/MID format
  • MapInfo TAB/MAP format
  • MatLab format
  • MOSS format
  • NIMA ASC format
  • Platte River ASCII Digitizer format
  • PLS CADD XYZ Grid format
  • Polish MP (cGPSMapper) format
  • SEGP1 format
  • Simple ASCII Text format
  • Surfer BLN format
  • SVG (Scalable Vector Graphic) format
  • TomTom OV2 (point database) format
  • Tsunami OVR format
  • UKOOA P/190 format
  • USGS DLG-O format
  • WAsP .MAP format
  • ZMap Plus XYSegId format

ข้อมูลเชิงภาพ(Raster Data)

  • BIL/BIP/BSQ formats
  • BMP
  • ECW format
  • Erdas Imagine format
  • GeoPDF
  • GeoTIFF format
  • KML/KMZ raster format (including super overlay support)
  • Idrisi format
  • JPG format
  • JPG2000 format
  • NITF format
  • PNG format

Elevation Data

  • Arc ASCII Grid format
  • BIL format
  • BT (Binary Terrain) format
  • DTED format
  • DXF (3D-point, 3D-mesh, and 3D-face) formats
  • Erdas Imagine format
  • Float/Grid file format
  • Geosoft Grid format
  • GeoTIFF DEM format
  • Gravsoft Grid format
  • Idrisi format
  • Leveller Heightfield format
  • Lidar LAS format
  • MapMaker Terrain file format
  • Optimi Terrain file format
  • PGM Grayscale Grid file format
  • PLS CADD XYZ Grid file format
  • RockWorks Grid format
  • STL format
  • Surfer Grid (ASCII and binary) formats
  • Terragen Terrain file format
  • USGS DEM format
  • Vertical Mapper (MapInfo) Grid
  • VRML format
  • Vulcan3D Triangulation format
  • XYZ ASCII Grid format
  • Zmap Plus Grid format

คุณสมบัติและความสามารถของโปรแกรม

การแปลงฟอร์แมตของไฟล์ (Import & Export)

  • เป็นความสามารถที่หา tools ตัวอื่นจับยาก ไม่ว่าแปลงจาก Raster ไป Raster อีกฟอร์แม็ตเช่นจาก Geotiff => Erdas Imagine หรือจาก Mrsid => Geotiff เป็นต้น
  • แปลงจาก Vector ไป Vector ฟอร์แม็ตอื่น เช่นจาก Autocad DWG => Google Earth (KML) หรือจาก ESRI Shape file => Microstation (DGN) หรือเวลา Tracking ด้วยเครื่อง GPS ตระกูล garmin เมื่อดาวน์โหลด track จากเครื่อง ด้วย Garmin Mapsource แล้ว save เป็นฟอร์แมต GPX ก็สามารถนำมาเปิดได้ พร้อมจะแปลงเป็นฟอร์แมตอื่นเช่นแปลงเป็น KML เพื่อไปเปิดใน Google Earth หรือถ้าดาวน์โหลด track จากเครื่อง gps ด้วย Oziexplorer เซฟเป็นฟอร์แม็ต PCX5 (.trk และ .wpt) ก็สามารถมาเปิดได้ง่ายเช่นเดียวกัน
  • แปลงจาก Elevation ฟอร์แม็ตหนึ่ง ไป Elevation ฟอร์แม็ตอื่น สะดวกมากกับการแปลงฟอร์แม็ตของ DEM เช่นจาก SRTM DEM => GeoTiff DEM
  • ข้อเสียที่ผมเห็นคือไม่สนับสนุนฟอร์แม็ตของ Terramodel (.pro) หวังว่า version หน้าๆน่าจะสนับสนุน เพราะ Terramodel เป็นโปรแกรมที่สร้างเส้น contour สวยที่สุดเท่าที่ผมเคยเห็นมา รองลงมาได้แก่ Eagle point (plug in ของ Autocad R14 ที่ไม่ทราบว่าล้มหายตายจากแล้วยัง) คนที่ใช้ Erdas Imagine โหมดสร้าง DEM (Create surface) จะเห็นว่าสนับสนุนฟอร์แมตของ Terramodel ด้วย แต่เนื่องจาก Terramodel เป็นโปรแกรมสำหรับงาน infrastructure คือรองรับพื้นที่ไม่ใหญ่มาก ผมมี point อยู่ประมาณ 1.4 ล้านจุดขึ้นรูป contour นี่นิ่งสนิทเลย เกิด error ฟ้องว่า memory ไม่พอ ไม่สามารถ export เส้น contour ออกมาเป็น DWG หรือ Shape file ได้เลย

การสร้าง DEM จาก DTM (3D Points)

  • สามารถสร้าง DEM ได้อย่างง่ายๆ จาก DTM  รายละเอียดผมเขียนถึงไปแล้ว หาอ่านได้ใน blog ของผมตอนก่อนๆ

การ Reproject

  • ในบางสถานการณ์เราอาจได้ข้อมูลที่เป็นไฟล์ใน datum และ projection เช่น UTM บนหลักฐาน Indian 1975 แต่เวลานำไปใช้ต้องการเป็น UTM บนหลักฐาน WGS84 การ reproject จึงเป็นคำตอบ ผมลองดูแล้วใช้งานไม่ยากและก็เร็วด้วย

การสร้างเส้นชั้นความสูง (Generate Contours)

  • อา …..จะพูดยังไงดี ความจริง Global Mapper วางตัวเองตามชื่อ Global น่าจะรองรับอะไรที่มันใหญ่ๆเช่น DEM ที่มีขนาดใหญ่ๆมาก แต่ DEM ไม่ใช่ปัญหา ขนาด DEM ของประเทศไทย (pixel 30m x 30m) ขนาดประมาณ 3 GB ก็ยังเอาอยู่ แต่ถ้านำมาสร้างเส้นชั้นความสูง โอกาสแป๊กสูง ผมเข้าใจว่าในทางโปรแกรมมิ่งการเก็บวัตถุเป็นเส้น (line หรือ polyline) ที่นำมาต่อกันเป็นเส้นชั้นความสูง จะใช้ memory และพื้นที่จัดเก็บมาก ยิ่งพื้นที่ที่มีความลาดชันมาก เส้น contour จะถี่ยิบ ตัวอย่างข้างต้นที่ผมกล่าวไปแล้วคือ Terramodel จะแป๊กที่จำนวนจุด 1.4 ล้านจุด ซึ่งเป็นพื้นที่ที่แม่น้ำตัดผ่านภูเขาที่สูงชันมาก แต่ผมไม่แปลกใจเพราะ Terramodel ยังใช้ algorithms รุ่นเก่า แต่ที่คาดหวังกับ Global Mapper ที่สามารถสนับสนุนฟอร์แม็ต Lidar Las format น่าจะทำได้ดีกว่านี้
  • แต่โดยทั่วๆไปก็ใช้งานได้ดี ถ้าไม่เจอ case แบบที่ผมว่า contour ก็ดูดี สามารถปรับความสวยได้ แต่ต้องแลกมากับขนาดไฟล์ของ contour ที่จะใหญ่ขึ้นหน่อย

การสร้างเส้นชั้นความสูง ใช้ interval contour = 20m

การ Download ข้อมูล Online

  • แนวโน้มของโปรแกรมด้าน GIS ต้องมีฟีเจอร์นี้ สำหรับคนที่อยู่อเมริกา แคนาดา หรือยุโรป จะมีบริการให้ดาวน์โหลดภาพถ่ายดาวเทียม,  Topographic map, DEM ความละเอียดสูงฟรี แต่บ้านเราไม่มีบริการด้านนี้จึงต้องหาจาก source อื่น แต่บ้านเราเมื่อเทียบกับเพื่อนบ้านเช่นกัมพูชา ลาว พม่า ก็ยังดีกว่ามากเรามีแผนที่ 1:50000 ใช้ตั้งนานแล้วตอนนี้ก็มี 1:4000 ส่วนพม่า 1:50000 ยังอยู่ในช่วงผลิต บางส่วนก็ออกมาใช้งานแล้ว ส่วนกัมพูชา ลาว เท่าที่ผมทราบยังไม่มีใช้
  • งานผมบางครั้งเกี่ยวข้องกับประเทศเพื่อนบ้าน หาแผนที่มาใช้งานลำบากก็ต้องอาศัยข้อมูล Online ที่นี้แหละครับมาถูๆไถๆ เช่นภาพถ่าย Landsat 7 และ SRTM DEM (ขนาด pixel 90m x 90m)
  • ใช้ Global Mapperr จะสะดวกมากแค่มีพื้นที่ (Area) ที่ต้องการข้อมูล อาจจะ import เป็น shape file หรือ DWG เข้ามา ทำการ zoom พื้นที่แล้วสั่ง Download มาได้เลย ทั้งภาพถ่ายดาวเทียม landsat 7 และ SRTM DEM เสร็จแล้วก็ export เป็น raster และ vector ตามที่ต้องการ

globalmapper3

การ Crop และการแก้ไข DEM

  • การ crop DEM เพื่อให้ได้ขนาดเล็กและพื้นที่ตรงกับที่ต้องการ Global Mapper ก็เตรียมมาให้ เพียงแต่ถ้าจะ crop DEM ต้องอาศัยตอน export DEM ไปยังไฟล์ใหม่ นี่คือข้อเสียอย่างหนึ่งที่ไม่สะดวก น่าจะ crop ได้ตอนเปิดไฟล์มาแล้ว  ส่วนการแก้ไข DEM สามารถระบุค่าระดับต่ำสุดและสูงสุดที่ต้องการได้  หรือแทนที่ค่าระดับที่ไม่อยู่ในช่วงที่ต้องการแทนที่ด้วยค่าระดับอื่น ว่างๆ ผมจะเขียนเรื่องนี้ให้ละเอียดอีกครั้ง
globalmapper4
ตั้งค่าเพื่อเลือก DEM ที่ไม่ต้องการทิ้ง

การทำ Raster Blending

  • ในบางครั้งระหว่าง Raster จำนวน 2 ไฟล์ขึ้นไป เมื่อมาวางซ้อนกันอยู่ จะมองเห็นเฉพาะ layer ด้านบนสุดเท่านั้น ด้วยเหตุผลนี้จึงต้องทำการ blending เพื่อให้สามารถเห็นภาพทั้งสอง layer ได้ นอกจากการ blending แล้วการทำให้โปร่งแสง ก็ยังถูกนำมารวมกับการ blending

globalmapper4

  • จากรูปด้านบน ตัวเลเยอร์  DEM จะอยู่ล่างสุด เลเยอร์ด้านบนจะเป็นภาพของ landsat7 แต่ตอนนี้ถูกปิดอยู่ ถ้าเปิดปกติจะมองไม่เห็น DEM อยู่ด้านล่าง ผมเอาภาพ Landsat7 มาทำ Blending ดูผลลัพธ์จะเห็นแม่น้ำถูก blending เข้ากับ DEM จากเดิมเรามอง DEM ภาพของแม่น้ำจะไม่เห็นเด่นชัด แต่การ blending จะทำให้เห็นภาพซ้อนและเห็นได้ชัดขึ้น พร้อมจะนำไปวิเคราะห์และศึกษาต่อได้

globalmapper5

การคำนวณหา Line of sight และ Cut/Fill Volumes

  • Feature ตัวนี้ค่อนข้างหน่อมแน้ม ถ้าจะใช้เป็นเรื่องเป็นราวไปใช้โปรแกรมอื่นๆดีกว่า เช่น Terramodel, Autodesk Civil 3D หรือ Geopak บน Microstation ไปเลย แต่ถ้าจะใช้งานเพื่อเป็น guide line ก็พอได้เช่นการตัดถนนผ่านภูเขาสามารถลองเส้น profile แล้วสั่งให้แสดง profile ได้ ดูรูปด้านล่างประกอบ

globalmapper6

การวิเคราะห์ View shed

  • เป็นฟังก์ชั่นพื้นฐานสำหรับด้าน GIS เพื่อวิเคราะห์การส่งสัญญาณเช่นการตั้งเสาวิทยุสื่อสาร การตั้งเสาโทรศัพท์มือถือ ยิ่งเราสามารถตั้งได้ในที่สูงๆเช่น เนินเขา ภูเขาก็ยิ่งดี ทำให้พื้นที่ในการรับสัญญาณมากขึ้น มองด้านต้นทุนก็คือตั้งเสาส่งให้น้อยลง แต่ครอบคลุมพื้นที่มากขึ้น ทำให้เสียค่าต้นทุนน้อยลง feature ตัวนี้ใช้ได้ดีครับ ดูรูปด้านล่างประกอบ จะเห็นบางส่วนที่ถูก hatch ด้วยสีแดง คือพื้นที่ที่สามารถรับสัญญาณได้

globalmapper7

การแสดง 3D View

  • การ Drape ข้อมูลที่เป็น Raster หรือ Vector บน DEM ตัว Global Mapper ก็ทำได้สวยพอใช้ได้ ดูรูปด้านล่างประกอบ แต่ที่พออวดได้ก็คือในภาพสามมิติสามารถใช้เมาส์ ซูม หมุน หรือเลื่อนได้แบบ Real time แต่ถ้าไปเทียบเจ้าพ่ออย่าง Google Earth ตัว Global Mapper คงต้องหลบไปก่อน

globalmapper8

  • ส่วน feature อื่นๆเช่นการแสดงสีของน้ำเมื่อกำหนดค่าระดับให้ก็ทำได้สวยงามมาก การทำ GPS Tracking ก็ทำได้ดีทีเดียว ที่สำคัญคือเสร็จจาก tracking สามารถ export ไปฟอร์แม็ตอื่นได้ทันที
  • ส่วนข้อด้อยที่ค่อนข้างร้ายแรงคือการเลือก (selection) vector data จะไม่สามารถเลือกเป็นกลุ่มหรือหลายๆตัวได้ การเลือกด้วยเมนู Search ก็พอทำได้แต่ไม่สะดวก ตัวอย่างเช่นต้องการลบจุดที่ไม่ต้องการ 10 จุดมาคลิกเพื่อเลือกแล้วลบทั้งหมด 10 ครั้ง มันก็ไม่ใช่ จะบอกว่าถ้าต้องการ edit vector data พวกนี้ก็หันไปใช้ ArcGIS แทน มันก็ไม่ได้เช่นกันขนาดและราคา software คนละเรื่อง จึงอยากจะได้อะไรที่มันเล็กๆเร็วๆ ในความคิดผมการเพิ่ม feature เหล่านี้มันก็ไม่ได้หนักหนาอะไรในเชิงโปรแกรมมิ่ง

สรุป

  • โดยภาพรวม Global Mapper สมกับเป็น Power Tools สำหรับงาน GIS ถึงจะมีข้อด้อยไปบ้างบางจุด แต่ก็ไม่ทำให้คุณค่าของโปรแกรมด้อยลงไปแต่อย่างใด โอกาสหน้าอาจจะเอา Manifold System V.8 มารีวิว ก็ขอจบแต่เพียงเท่านี้ครับ