ก้าวต่อไปของโปรแกรมเขียนรูปตัดตามขวาง XSection Plot ในร่างใหม่พัฒนาด้วย Python + Qt

ลาก่อน XSection Plot รุ่น 3.25

  • โปรแกรมพล็อทรูปตัดตามขวาง XSection Plot เดิมๆนั้นผมเขียนด้วย Visual Basic 6 ใช้มาเป็นสิบๆปีแล้ว บัดนี้ถึงกาลเวลาที่จะต้องฝังในความทรงจำแล้ว เพราะฟอนต์ที่เคยแสดงผลได้ในวินโดส์ XP กลับกลายเป็นตัวประหลาดในวินโดส์ 7/8 ผมเข้าใจว่าฟอนต์ระบบที่เคยอยู่ในวินโดส์ XP น่าจะเป็นระบบแบบด็อทเมทริก น่าจะถูกถอดออกไปแล้วในวินโดส์ 7/8 จึงแสดงผลแบบอักขระประหลาดอย่างที่เห็นxsectionplot_old1
  • กลับมารื้อโค๊ดเดิมๆดูคร่าวๆ จำนวนบรรทัดหลายหมื่นบรรทัดทีเดียว ประกอบด้วยโมดูลและคลาสจำนวนมาก ออกอาการงงๆเหมือนกัน เพราะเขียนไว้นานแล้วภาษานี้ก็ไม่ได้เขียนนานแล้ว แต่ด้วยความง่ายของภาษา VB ใช้เวลาไม่นานก็รื้อฟื้น

แรงจูงใจในการนำมาพัฒนาใหม่

  • บอกตรงๆว่าทนเห็นโปรแกรมที่เคยใช้ได้ดีตอนอยู่วินโดส์ XP แต่มาล้มหายตายจากพอมาอยู่บนวินโดส์ 7/8 ไม่ได้ และความรู้สีกอยากช่วยผู้ที่ใช้งานโปรแกรมนี้ ในรุ่นเก่าแล้วต้องการย้ายงานมาบนวินโดส์ 7/8

เครื่องมือและสภาพแวดล้อมในการพัฒนา

  • ในตอนนี้ผมศึกษา Python อยู่ วิธีเดียวที่จะให้โปรแกรมมิงแตกฉาน คือลงมือเขียนโปรแกรม ก่อนหน้านี้ผมเริ่มเขียนด้วย Python เป็นเวอร์ชัน 2.7.5 แบบ 32 บิต ใช้ graphic user interface (GUI) ของ wxWidgets รวมๆเรียกว่า wxPython ตัวโปรแกรมที่ผมเขียนเป็นโปรแกรมด้าน GIS ใช้ Mapnik เป็นตัว  GIS Map Engine เขียนจนจบโปรแกรมนำมาใช้งานได้ดีพอสมควร  สำหรับผมแล้ว wxPython ก็โอเคในระดับหนึ่ง แต่ความรู้สึกส่วนตัวว่าค่อนข้างติดๆขัดๆไม่ลื่นไหล (ทัศนส่วนตัว)
  • ตอนหลังๆมาลองติดตั้ง Python 3.4 แล้วก็ลง Qt5 เรียกว่า PyQt5 แบบ 64 บิต ลองศึกษา Qt5 ควบคู่ไปด้วย ปรากฎว่าอันนี้ใช่เลย ตามสไตล์ของไพธ่อนครับ สั้น กระชับ ฉับไว ทรงพลัง ผมลงทุนไม่ดูโค๊ดเก่าที่เป็นวิชวลเบสิคเก่า ใช้เวลายามว่างๆ ลงมือเขียนใหม่ เกือบทั้งหมด
  • สภาพแวดล้อมในการพัฒนาใช้ Eclipse (ดั้งเดิมเป็น platform สำหรับพัฒนา Java) ในขณะที่เขียนอยู่เป็นรุน Luna ในส่วน Eclipse ติดตั้ง Plug-ins เพิ่มเติมคือตัว PyDev เพื่อให้สามารถใช้ Python บน Eclipse ได้ ทุกอย่างที่กล่าวมาฟรีหมดครับ

pydev_eclipse

XSection Plot โฉมใหม่ ไฉไลกว่าเดิม

  • มาดูหน้าตาโฉมใหม่ก็เรียบง่ายดังที่เห็น

xsectionplot_new1

xsectionplot_new2

ออกแบบไฟล์ข้อมูลใหม่ เป็น XML

  • ไฟล์ข้อมูลเดิมของ XSection Plot  รุ่นเก่าเป็นไฟล์ไบนารี ข้อเสีย คือมนุษย์อ่านไม่ออก ผู้ใช้ไม่สามารถเปิดไฟล์มาดูได้โดยตรง  ข้อเสียในแง่คนพัฒนาโปรแกรมคือ ขยายเพิ่มเติมข้อมูลลำบาก ก็เลยหันมามอง XML ที่เกิดมานมนานเป็นสิบๆปีแล้ว สนใจลองกดปุ่มบวกข้างล่างดูลักษณะไฟล์ข้อมูล แต่รุ่นจริงอาจจะมีการเปลี่ยนแปลง
<root version="1.0">
  <!--Generated by XSection Plot-->
  <!--This data file is Existing ground section-->
  <Header>
    <AppName>XSection Plot</AppName>
    <Developer>Prajuab Riabroy</Developer>
    <Version>4.0.512</Version>
    <SectionType>Ground</SectionType>
    <DateCreated>2014-08-07 16:45:56.517701</DateCreated>
  </Header>
  <ProjectInfo>
    <ProjectName>KohKong Coal-Fired Power Plant</ProjectName>
    <ClientName>Harbour Department</ClientName>
    <ContractorName>Universal Construction Development PCL.</ContractorName>
    <DrawingTitle>Cross Section of Access Channel</DrawingTitle>
    <DrawnName>DRS</DrawnName>
    <ApprovedName>AS</ApprovedName>
    <ClientApprovedName>AD</ClientApprovedName>
    <CheckedName>PJ</CheckedName>
    <SurveyorName>SK</SurveyorName>
    <SurveyedDate>1-7/03/2010</SurveyedDate>
    <DrawingNo></DrawingNo>
    <SheetNo>1/</SheetNo>
    <DrawingDate>1-7/03/2010</DrawingDate>
    <Revision></Revision>
    <UseLocaleLanguage>False</UseLocaleLanguage>
    <MapTexts>
      <MapText Label="Client" Locale="เจ้าของโครงการ"/>
      <MapText Label="Contractor" Locale="ผู้รับเหมา"/>
      <MapText Label="Drawn" Locale="เขียน"/>
      <MapText Label="Design" Locale="ออกแบบ"/>
      <MapText Label="Surveyor" Locale="สำรวจ"/>
      <MapText Label="Surveyed date" Locale="วันที่สำรวจ"/>
      <MapText Label="Checked" Locale="ตรวจสอบ"/>
      <MapText Label="Approved" Locale="อนุมัติ"/>
      <MapText Label="Client approved" Locale="ผู้คุมงานอนุมัติ"/>
      <MapText Label="Drawing No." Locale="แบบเลขที่"/>
      <MapText Label="Drawing date" Locale="แบบวันที่"/>
      <MapText Label="Project title" Locale="โครงการ"/>
      <MapText Label="Drawing title" Locale="แผนที่แสดง"/>
      <MapText Label="Sheet No." Locale="แบบเลขที่"/>
      <MapText Label="Scale" Locale="มาตราส่วน"/>
      <MapText Label="Vertical" Locale="ทางดิ่ง"/>
      <MapText Label="Horizontal" Locale="ทางราบ"/>
      <MapText Label="Vertical scale" Locale="มาตราส่วนทางดิ่ง"/>
      <MapText Label="Horizontal scale" Locale="มาตราส่วนทางราบ"/>
      <MapText Label="Legend" Locale="สัญลักษณ์"/>
      <MapText Label="Notes" Locale="หมายเหตุ"/>
      <MapText Label="Geodetic Information" Locale="ข้อมูลทางยีออเดซี"/>
      <MapText Label="No" Locale="ครั้งที่"/>
      <MapText Label="Amendments" Locale="ความเห็น"/>
      <MapText Label="By" Locale="โดย"/>
      <MapText Label="Date" Locale="วันที่"/>
      <MapText Label="Revision" Locale="ครั้งที่แก้ไข"/>
    </MapTexts>
  </ProjectInfo>
  <SectionOptions>
    <VerticalScale>250.0</VerticalScale>
    <HorizontalScale>2500.0</HorizontalScale>
    <HozGridSpace>25.0</HozGridSpace>
    <VertGridSpace>2.0</VertGridSpace>
    <GridLineType>1</GridLineType>
    <CalcIntersection>-1</CalcIntersection>
    <CalcArea>-1</CalcArea>
    <TrimTypical>0</TrimTypical>
    <NumDecimalElev>3</NumDecimalElev>
    <NumDecimalDist>3</NumDecimalDist>
    <UseIntervalText>-1</UseIntervalText>
    <IntervalDist>25.0</IntervalDist>
    <PrefixText></PrefixText>
    <PostfixText></PostfixText>
    <UsePostPrefix>0</UsePostPrefix>
    <UseOffsetElevFormat>2</UseOffsetElevFormat>
    <CalcPlotAreaCut>0</CalcPlotAreaCut>
    <CalcPlotAreaFill>0</CalcPlotAreaFill>
    <NumVertCLLeft>18</NumVertCLLeft>
    <NumVertCLRight>18</NumVertCLRight>
    <NumHozTopBottom>8</NumHozTopBottom>
    <LeftSideText>LT.</LeftSideText>
    <RightSideText>RT.</RightSideText>
    <StationText>Km.</StationText>
    <SelectedTBlock>3</SelectedTBlock>
    <NumSectionRows>6</NumSectionRows>
    <NumSectionColumns>2</NumSectionColumns>
    <SurveyType>0</SurveyType>
    <PlotTBlock>-1</PlotTBlock>
    <SwapLeftAndRight>0</SwapLeftAndRight>
  </SectionOptions>
  <PageSetup>
    <PaperSize>A1</PaperSize>
    <PageWidth>-999</PageWidth>
    <PaperHeight>-999</PaperHeight>
  </PageSetup>
  <Sections>
    <NumSections>12</NumSections>
    <Section Name="2 + 000">
      <XPositionOnPaper>51.66</XPositionOnPaper>
      <YPositionOnPaper>21.18</YPositionOnPaper>
      <TopGridElev>0.0</TopGridElev>
      <NumPoints>37</NumPoints>
      <Points>
        <Point Elevation="-13.75" Offset="-450.0"/>
        <Point Elevation="-13.724" Offset="-444.229"/>
        <Point Elevation="-13.453" Offset="-394.64"/>
        <Point Elevation="-13.708" Offset="-357.293"/>
        <Point Elevation="-13.832" Offset="-340.678"/>
        <Point Elevation="-13.815" Offset="-321.128"/>
        <Point Elevation="-13.812" Offset="-303.689"/>
        <Point Elevation="-13.817" Offset="-263.4"/>
        <Point Elevation="-13.795" Offset="-256.48"/>
        <Point Elevation="-13.774" Offset="-237.844"/>
        <Point Elevation="-13.725" Offset="-215.868"/>
        <Point Elevation="-13.694" Offset="-179.238"/>
        <Point Elevation="-13.694" Offset="-146.471"/>
        <Point Elevation="-13.641" Offset="-126.792"/>
        <Point Elevation="-13.651" Offset="-77.938"/>
        <Point Elevation="-13.577" Offset="-68.628"/>
        <Point Elevation="-13.573" Offset="-67.035"/>
        <Point Elevation="-13.578" Offset="-57.508"/>
        <Point Elevation="-13.545" Offset="-14.98"/>
        <Point Elevation="-13.551" Offset="-2.388"/>
        <Point Elevation="-13.569" Offset="19.95"/>
        <Point Elevation="-13.553" Offset="64.032"/>
        <Point Elevation="-13.541" Offset="72.772"/>
        <Point Elevation="-13.516" Offset="81.096"/>
        <Point Elevation="-13.614" Offset="138.343"/>
        <Point Elevation="-13.629" Offset="150.271"/>
        <Point Elevation="-13.556" Offset="198.013"/>
        <Point Elevation="-13.557" Offset="211.934"/>
        <Point Elevation="-13.577" Offset="254.983"/>
        <Point Elevation="-13.624" Offset="269.121"/>
        <Point Elevation="-13.736" Offset="298.975"/>
        <Point Elevation="-13.717" Offset="339.278"/>
        <Point Elevation="-13.679" Offset="356.86"/>
        <Point Elevation="-13.497" Offset="383.249"/>
        <Point Elevation="-13.423" Offset="405.804"/>
        <Point Elevation="-13.548" Offset="442.413"/>
        <Point Elevation="-13.59" Offset="450.0"/>
      </Points>
    </Section>
    <Section Name="2 + 050">
      <XPositionOnPaper>42.78</XPositionOnPaper>
      <YPositionOnPaper>21.18</YPositionOnPaper>
      <TopGridElev>0.0</TopGridElev>
      <NumPoints>37</NumPoints>
      <Points>
        <Point Elevation="-13.587" Offset="-450.0"/>
        <Point Elevation="-13.564" Offset="-431.93"/>
        <Point Elevation="-13.389" Offset="-392.416"/>
        <Point Elevation="-13.59" Offset="-363.705"/>
        <Point Elevation="-13.714" Offset="-349.243"/>
        <Point Elevation="-13.648" Offset="-319.939"/>
        <Point Elevation="-13.613" Offset="-305.319"/>
        <Point Elevation="-13.836" Offset="-245.696"/>
        <Point Elevation="-13.833" Offset="-244.203"/>
        <Point Elevation="-13.656" Offset="-200.692"/>
        <Point Elevation="-13.608" Offset="-176.25"/>
        <Point Elevation="-13.525" Offset="-143.894"/>
        <Point Elevation="-13.552" Offset="-129.046"/>
        <Point Elevation="-13.527" Offset="-96.253"/>
        <Point Elevation="-13.656" Offset="-54.905"/>
        <Point Elevation="-13.654" Offset="-53.835"/>
        <Point Elevation="-13.566" Offset="-45.158"/>
        <Point Elevation="-13.591" Offset="-20.343"/>
        <Point Elevation="-13.567" Offset="-0.305"/>
        <Point Elevation="-13.438" Offset="26.667"/>
        <Point Elevation="-13.397" Offset="59.524"/>
        <Point Elevation="-13.375" Offset="70.237"/>
        <Point Elevation="-13.38" Offset="77.772"/>
        <Point Elevation="-13.49" Offset="115.256"/>
        <Point Elevation="-13.6" Offset="156.486"/>
        <Point Elevation="-13.475" Offset="180.904"/>
        <Point Elevation="-13.453" Offset="188.472"/>
        <Point Elevation="-13.454" Offset="203.878"/>
        <Point Elevation="-13.471" Offset="256.873"/>
        <Point Elevation="-13.554" Offset="276.218"/>
        <Point Elevation="-13.604" Offset="294.693"/>
        <Point Elevation="-13.63" Offset="328.866"/>
        <Point Elevation="-13.63" Offset="355.449"/>
        <Point Elevation="-13.502" Offset="374.332"/>
        <Point Elevation="-13.316" Offset="406.895"/>
        <Point Elevation="-13.486" Offset="441.986"/>
        <Point Elevation="-13.52" Offset="450.0"/>
      </Points>
    </Section>
    <Section Name="2 + 100">
      <XPositionOnPaper>33.89</XPositionOnPaper>
      <YPositionOnPaper>21.18</YPositionOnPaper>
      <TopGridElev>0.0</TopGridElev>
      <NumPoints>38</NumPoints>
      <Points>
        <Point Elevation="-13.478" Offset="-450.0"/>
        <Point Elevation="-13.468" Offset="-424.977"/>
        <Point Elevation="-13.401" Offset="-404.422"/>
        <Point Elevation="-13.463" Offset="-387.405"/>
        <Point Elevation="-13.633" Offset="-344.262"/>
        <Point Elevation="-13.608" Offset="-339.036"/>
        <Point Elevation="-13.494" Offset="-305.986"/>
        <Point Elevation="-13.552" Offset="-274.196"/>
        <Point Elevation="-13.555" Offset="-259.655"/>
        <Point Elevation="-13.555" Offset="-237.91"/>
        <Point Elevation="-13.486" Offset="-192.39"/>
        <Point Elevation="-13.35" Offset="-155.4"/>
        <Point Elevation="-13.323" Offset="-145.491"/>
        <Point Elevation="-13.288" Offset="-86.808"/>
        <Point Elevation="-13.275" Offset="-58.314"/>
        <Point Elevation="-13.286" Offset="-56.712"/>
        <Point Elevation="-13.511" Offset="-44.626"/>
        <Point Elevation="-13.477" Offset="-19.724"/>
        <Point Elevation="-13.435" Offset="-1.021"/>
        <Point Elevation="-13.385" Offset="20.078"/>
        <Point Elevation="-13.354" Offset="48.949"/>
        <Point Elevation="-13.322" Offset="58.859"/>
        <Point Elevation="-13.309" Offset="73.917"/>
        <Point Elevation="-13.431" Offset="135.063"/>
        <Point Elevation="-13.512" Offset="161.041"/>
        <Point Elevation="-13.36" Offset="170.629"/>
        <Point Elevation="-13.285" Offset="176.557"/>
        <Point Elevation="-13.303" Offset="252.984"/>
        <Point Elevation="-13.309" Offset="261.078"/>
        <Point Elevation="-13.349" Offset="269.352"/>
        <Point Elevation="-13.442" Offset="286.219"/>
        <Point Elevation="-13.451" Offset="289.018"/>
        <Point Elevation="-13.454" Offset="295.508"/>
        <Point Elevation="-13.381" Offset="357.63"/>
        <Point Elevation="-13.291" Offset="397.562"/>
        <Point Elevation="-13.265" Offset="410.885"/>
        <Point Elevation="-13.291" Offset="415.854"/>
        <Point Elevation="-13.436" Offset="450.0"/>
      </Points>
    </Section>
    <Section Name="2 + 150">
      <XPositionOnPaper>25.01</XPositionOnPaper>
      <YPositionOnPaper>21.18</YPositionOnPaper>
      <TopGridElev>0.0</TopGridElev>
      <NumPoints>36</NumPoints>
      <Points>
        <Point Elevation="-13.42" Offset="-450.0"/>
        <Point Elevation="-13.422" Offset="-448.815"/>
        <Point Elevation="-13.36" Offset="-407.76"/>
        <Point Elevation="-13.421" Offset="-383.018"/>
        <Point Elevation="-13.466" Offset="-343.431"/>
        <Point Elevation="-13.477" Offset="-330.434"/>
        <Point Elevation="-13.426" Offset="-308.725"/>
        <Point Elevation="-13.339" Offset="-248.217"/>
        <Point Elevation="-13.318" Offset="-227.42"/>
        <Point Elevation="-13.346" Offset="-185.203"/>
        <Point Elevation="-13.22" Offset="-153.307"/>
        <Point Elevation="-13.204" Offset="-149.805"/>
        <Point Elevation="-13.299" Offset="-109.743"/>
        <Point Elevation="-13.355" Offset="-76.976"/>
        <Point Elevation="-13.291" Offset="-70.628"/>
        <Point Elevation="-13.2" Offset="-57.454"/>
        <Point Elevation="-13.217" Offset="-40.497"/>
        <Point Elevation="-13.27" Offset="-5.497"/>
        <Point Elevation="-13.298" Offset="42.337"/>
        <Point Elevation="-13.313" Offset="57.83"/>
        <Point Elevation="-13.306" Offset="58.86"/>
        <Point Elevation="-13.119" Offset="66.396"/>
        <Point Elevation="-13.147" Offset="99.813"/>
        <Point Elevation="-13.307" Offset="160.186"/>
        <Point Elevation="-13.248" Offset="169.925"/>
        <Point Elevation="-13.135" Offset="176.817"/>
        <Point Elevation="-13.233" Offset="220.607"/>
        <Point Elevation="-13.302" Offset="256.981"/>
        <Point Elevation="-13.362" Offset="268.584"/>
        <Point Elevation="-13.398" Offset="285.574"/>
        <Point Elevation="-13.254" Offset="344.07"/>
        <Point Elevation="-13.228" Offset="357.109"/>
        <Point Elevation="-13.214" Offset="363.701"/>
        <Point Elevation="-13.071" Offset="408.839"/>
        <Point Elevation="-13.195" Offset="427.653"/>
        <Point Elevation="-13.336" Offset="450.0"/>
      </Points>
    </Section>
    <Section Name="2 + 200">
      <XPositionOnPaper>16.13</XPositionOnPaper>
      <YPositionOnPaper>21.18</YPositionOnPaper>
      <TopGridElev>0.0</TopGridElev>
      <NumPoints>34</NumPoints>
      <Points>
        <Point Elevation="-13.299" Offset="-450.0"/>
        <Point Elevation="-13.244" Offset="-436.225"/>
        <Point Elevation="-13.11" Offset="-404.037"/>
        <Point Elevation="-13.219" Offset="-363.07"/>
        <Point Elevation="-13.268" Offset="-346.98"/>
        <Point Elevation="-13.241" Offset="-317.712"/>
        <Point Elevation="-13.227" Offset="-310.438"/>
        <Point Elevation="-13.238" Offset="-280.224"/>
        <Point Elevation="-13.258" Offset="-255.553"/>
        <Point Elevation="-13.299" Offset="-211.447"/>
        <Point Elevation="-13.297" Offset="-203.957"/>
        <Point Elevation="-13.325" Offset="-143.444"/>
        <Point Elevation="-13.182" Offset="-96.867"/>
        <Point Elevation="-13.167" Offset="-71.842"/>
        <Point Elevation="-13.173" Offset="-66.961"/>
        <Point Elevation="-13.161" Offset="-63.511"/>
        <Point Elevation="-13.105" Offset="-25.008"/>
        <Point Elevation="-13.095" Offset="-1.821"/>
        <Point Elevation="-13.263" Offset="45.687"/>
        <Point Elevation="-13.267" Offset="49.066"/>
        <Point Elevation="-13.264" Offset="49.467"/>
        <Point Elevation="-13.074" Offset="66.884"/>
        <Point Elevation="-13.11" Offset="161.015"/>
        <Point Elevation="-13.061" Offset="165.896"/>
        <Point Elevation="-13.022" Offset="174.39"/>
        <Point Elevation="-13.136" Offset="236.021"/>
        <Point Elevation="-13.157" Offset="249.355"/>
        <Point Elevation="-13.194" Offset="259.713"/>
        <Point Elevation="-13.265" Offset="285.85"/>
        <Point Elevation="-13.251" Offset="296.83"/>
        <Point Elevation="-13.145" Offset="348.582"/>
        <Point Elevation="-13.023" Offset="386.699"/>
        <Point Elevation="-12.918" Offset="410.555"/>
        <Point Elevation="-13.122" Offset="450.0"/>
      </Points>
    </Section>
    <Section Name="2 + 250">
      <XPositionOnPaper>7.24</XPositionOnPaper>
      <YPositionOnPaper>21.18</YPositionOnPaper>
      <TopGridElev>0.0</TopGridElev>
      <NumPoints>35</NumPoints>
      <Points>
        <Point Elevation="-13.141" Offset="-450.0"/>
        <Point Elevation="-13.135" Offset="-427.089"/>
        <Point Elevation="-13.116" Offset="-408.612"/>
        <Point Elevation="-13.158" Offset="-378.649"/>
        <Point Elevation="-13.208" Offset="-347.778"/>
        <Point Elevation="-13.103" Offset="-300.077"/>
        <Point Elevation="-13.082" Offset="-258.336"/>
        <Point Elevation="-13.043" Offset="-232.005"/>
        <Point Elevation="-13.019" Offset="-212.37"/>
        <Point Elevation="-13.039" Offset="-193.983"/>
        <Point Elevation="-13.092" Offset="-151.651"/>
        <Point Elevation="-13.105" Offset="-143.345"/>
        <Point Elevation="-13.093" Offset="-121.002"/>
        <Point Elevation="-13.082" Offset="-74.012"/>
        <Point Elevation="-13.072" Offset="-70.704"/>
        <Point Elevation="-12.939" Offset="-61.159"/>
        <Point Elevation="-12.878" Offset="-54.908"/>
        <Point Elevation="-13.036" Offset="-16.297"/>
        <Point Elevation="-12.959" Offset="13.485"/>
        <Point Elevation="-13.014" Offset="34.515"/>
        <Point Elevation="-13.016" Offset="41.274"/>
        <Point Elevation="-12.881" Offset="73.456"/>
        <Point Elevation="-12.997" Offset="132.919"/>
        <Point Elevation="-13.083" Offset="160.722"/>
        <Point Elevation="-12.971" Offset="167.25"/>
        <Point Elevation="-12.897" Offset="174.705"/>
        <Point Elevation="-12.973" Offset="224.215"/>
        <Point Elevation="-13.039" Offset="247.5"/>
        <Point Elevation="-12.997" Offset="275.574"/>
        <Point Elevation="-12.965" Offset="306.485"/>
        <Point Elevation="-12.954" Offset="335.878"/>
        <Point Elevation="-12.932" Offset="347.275"/>
        <Point Elevation="-12.763" Offset="408.665"/>
        <Point Elevation="-12.844" Offset="430.348"/>
        <Point Elevation="-12.93" Offset="450.0"/>
      </Points>
    </Section>
    <Section Name="2 + 300">
      <XPositionOnPaper>51.66</XPositionOnPaper>
      <YPositionOnPaper>62.03</YPositionOnPaper>
      <TopGridElev>0.0</TopGridElev>
      <NumPoints>34</NumPoints>
      <Points>
        <Point Elevation="-13.074" Offset="-450.0"/>
        <Point Elevation="-12.945" Offset="-417.015"/>
        <Point Elevation="-12.941" Offset="-415.185"/>
        <Point Elevation="-13.024" Offset="-341.605"/>
        <Point Elevation="-13.123" Offset="-294.567"/>
        <Point Elevation="-13.107" Offset="-279.439"/>
        <Point Elevation="-13.068" Offset="-253.199"/>
        <Point Elevation="-13.027" Offset="-222.165"/>
        <Point Elevation="-13.007" Offset="-210.839"/>
        <Point Elevation="-12.978" Offset="-193.209"/>
        <Point Elevation="-12.874" Offset="-146.031"/>
        <Point Elevation="-12.947" Offset="-112.293"/>
        <Point Elevation="-12.994" Offset="-74.731"/>
        <Point Elevation="-12.951" Offset="-56.842"/>
        <Point Elevation="-12.941" Offset="-51.044"/>
        <Point Elevation="-12.928" Offset="-49.349"/>
        <Point Elevation="-12.919" Offset="-41.744"/>
        <Point Elevation="-12.857" Offset="-17.072"/>
        <Point Elevation="-12.849" Offset="-1.213"/>
        <Point Elevation="-12.937" Offset="29.996"/>
        <Point Elevation="-12.943" Offset="43.79"/>
        <Point Elevation="-12.822" Offset="75.413"/>
        <Point Elevation="-12.792" Offset="80.941"/>
        <Point Elevation="-12.826" Offset="90.04"/>
        <Point Elevation="-13.069" Offset="164.519"/>
        <Point Elevation="-12.837" Offset="183.079"/>
        <Point Elevation="-12.873" Offset="222.341"/>
        <Point Elevation="-12.893" Offset="250.522"/>
        <Point Elevation="-12.863" Offset="272.959"/>
        <Point Elevation="-12.84" Offset="289.627"/>
        <Point Elevation="-12.791" Offset="341.037"/>
        <Point Elevation="-12.791" Offset="375.553"/>
        <Point Elevation="-12.778" Offset="402.959"/>
        <Point Elevation="-12.782" Offset="450.0"/>
      </Points>
    </Section>
    <Section Name="2 + 350">
      <XPositionOnPaper>42.78</XPositionOnPaper>
      <YPositionOnPaper>62.03</YPositionOnPaper>
      <TopGridElev>0.0</TopGridElev>
      <NumPoints>35</NumPoints>
      <Points>
        <Point Elevation="-12.783" Offset="-450.0"/>
        <Point Elevation="-12.807" Offset="-423.664"/>
        <Point Elevation="-12.842" Offset="-402.422"/>
        <Point Elevation="-12.834" Offset="-393.811"/>
        <Point Elevation="-12.879" Offset="-350.323"/>
        <Point Elevation="-12.966" Offset="-318.938"/>
        <Point Elevation="-13.011" Offset="-304.688"/>
        <Point Elevation="-12.898" Offset="-262.751"/>
        <Point Elevation="-12.866" Offset="-244.765"/>
        <Point Elevation="-12.876" Offset="-206.942"/>
        <Point Elevation="-12.88" Offset="-204.564"/>
        <Point Elevation="-12.856" Offset="-158.672"/>
        <Point Elevation="-12.786" Offset="-141.587"/>
        <Point Elevation="-12.787" Offset="-103.149"/>
        <Point Elevation="-12.766" Offset="-91.41"/>
        <Point Elevation="-12.779" Offset="-82.894"/>
        <Point Elevation="-12.781" Offset="-78.804"/>
        <Point Elevation="-12.767" Offset="-58.384"/>
        <Point Elevation="-12.765" Offset="-39.14"/>
        <Point Elevation="-12.676" Offset="-10.552"/>
        <Point Elevation="-12.786" Offset="13.725"/>
        <Point Elevation="-12.924" Offset="42.861"/>
        <Point Elevation="-12.794" Offset="60.497"/>
        <Point Elevation="-12.654" Offset="81.948"/>
        <Point Elevation="-12.833" Offset="123.769"/>
        <Point Elevation="-12.916" Offset="163.182"/>
        <Point Elevation="-12.784" Offset="181.207"/>
        <Point Elevation="-12.765" Offset="188.92"/>
        <Point Elevation="-12.792" Offset="255.693"/>
        <Point Elevation="-12.815" Offset="295.177"/>
        <Point Elevation="-12.79" Offset="315.292"/>
        <Point Elevation="-12.749" Offset="345.204"/>
        <Point Elevation="-12.744" Offset="364.207"/>
        <Point Elevation="-12.753" Offset="396.564"/>
        <Point Elevation="-12.68" Offset="450.0"/>
      </Points>
    </Section>
    <Section Name="2 + 400">
      <XPositionOnPaper>33.89</XPositionOnPaper>
      <YPositionOnPaper>62.03</YPositionOnPaper>
      <TopGridElev>0.0</TopGridElev>
      <NumPoints>36</NumPoints>
      <Points>
        <Point Elevation="-12.776" Offset="-450.0"/>
        <Point Elevation="-12.779" Offset="-447.698"/>
        <Point Elevation="-12.774" Offset="-434.746"/>
        <Point Elevation="-12.716" Offset="-414.286"/>
        <Point Elevation="-12.81" Offset="-359.948"/>
        <Point Elevation="-12.835" Offset="-352.389"/>
        <Point Elevation="-12.834" Offset="-346.592"/>
        <Point Elevation="-12.907" Offset="-315.681"/>
        <Point Elevation="-12.863" Offset="-285.783"/>
        <Point Elevation="-12.746" Offset="-240.545"/>
        <Point Elevation="-12.748" Offset="-212.21"/>
        <Point Elevation="-12.82" Offset="-189.251"/>
        <Point Elevation="-12.715" Offset="-173.517"/>
        <Point Elevation="-12.632" Offset="-145.846"/>
        <Point Elevation="-12.591" Offset="-106.965"/>
        <Point Elevation="-12.571" Offset="-91.109"/>
        <Point Elevation="-12.571" Offset="-48.284"/>
        <Point Elevation="-12.577" Offset="-45.561"/>
        <Point Elevation="-12.599" Offset="-14.411"/>
        <Point Elevation="-12.787" Offset="15.841"/>
        <Point Elevation="-12.859" Offset="44.469"/>
        <Point Elevation="-12.629" Offset="73.752"/>
        <Point Elevation="-12.541" Offset="85.843"/>
        <Point Elevation="-12.606" Offset="127.261"/>
        <Point Elevation="-12.689" Offset="164.56"/>
        <Point Elevation="-12.777" Offset="188.004"/>
        <Point Elevation="-12.794" Offset="194.282"/>
        <Point Elevation="-12.765" Offset="220.036"/>
        <Point Elevation="-12.697" Offset="257.027"/>
        <Point Elevation="-12.742" Offset="298.261"/>
        <Point Elevation="-12.761" Offset="308.727"/>
        <Point Elevation="-12.739" Offset="317.584"/>
        <Point Elevation="-12.692" Offset="346.633"/>
        <Point Elevation="-12.663" Offset="389.2"/>
        <Point Elevation="-12.662" Offset="396.811"/>
        <Point Elevation="-12.622" Offset="450.0"/>
      </Points>
    </Section>
    <Section Name="2 + 450">
      <XPositionOnPaper>25.01</XPositionOnPaper>
      <YPositionOnPaper>62.03</YPositionOnPaper>
      <TopGridElev>0.0</TopGridElev>
      <NumPoints>35</NumPoints>
      <Points>
        <Point Elevation="-12.772" Offset="-450.0"/>
        <Point Elevation="-12.779" Offset="-447.895"/>
        <Point Elevation="-12.728" Offset="-435.359"/>
        <Point Elevation="-12.625" Offset="-419.964"/>
        <Point Elevation="-12.671" Offset="-361.947"/>
        <Point Elevation="-12.65" Offset="-349.652"/>
        <Point Elevation="-12.745" Offset="-323.285"/>
        <Point Elevation="-12.881" Offset="-302.461"/>
        <Point Elevation="-12.774" Offset="-273.658"/>
        <Point Elevation="-12.614" Offset="-241.564"/>
        <Point Elevation="-12.923" Offset="-198.167"/>
        <Point Elevation="-12.751" Offset="-169.044"/>
        <Point Elevation="-12.581" Offset="-144.88"/>
        <Point Elevation="-12.616" Offset="-115.712"/>
        <Point Elevation="-12.607" Offset="-103.85"/>
        <Point Elevation="-12.527" Offset="-58.007"/>
        <Point Elevation="-12.522" Offset="-49.404"/>
        <Point Elevation="-12.511" Offset="-40.605"/>
        <Point Elevation="-12.526" Offset="-7.582"/>
        <Point Elevation="-12.637" Offset="44.494"/>
        <Point Elevation="-12.638" Offset="46.028"/>
        <Point Elevation="-12.336" Offset="98.718"/>
        <Point Elevation="-12.345" Offset="101.193"/>
        <Point Elevation="-12.764" Offset="162.39"/>
        <Point Elevation="-12.66" Offset="204.444"/>
        <Point Elevation="-12.627" Offset="229.054"/>
        <Point Elevation="-12.548" Offset="258.494"/>
        <Point Elevation="-12.644" Offset="293.019"/>
        <Point Elevation="-12.669" Offset="307.749"/>
        <Point Elevation="-12.618" Offset="321.733"/>
        <Point Elevation="-12.477" Offset="351.792"/>
        <Point Elevation="-12.529" Offset="375.735"/>
        <Point Elevation="-12.545" Offset="385.798"/>
        <Point Elevation="-12.574" Offset="415.152"/>
        <Point Elevation="-12.621" Offset="450.0"/>
      </Points>
    </Section>
    <Section Name="2 + 500">
      <XPositionOnPaper>16.13</XPositionOnPaper>
      <YPositionOnPaper>62.03</YPositionOnPaper>
      <TopGridElev>0.0</TopGridElev>
      <NumPoints>37</NumPoints>
      <Points>
        <Point Elevation="-12.675" Offset="-450.0"/>
        <Point Elevation="-12.682" Offset="-448.083"/>
        <Point Elevation="-12.672" Offset="-428.342"/>
        <Point Elevation="-12.68" Offset="-425.205"/>
        <Point Elevation="-12.649" Offset="-408.657"/>
        <Point Elevation="-12.507" Offset="-340.077"/>
        <Point Elevation="-12.62" Offset="-320.546"/>
        <Point Elevation="-12.737" Offset="-293.581"/>
        <Point Elevation="-12.521" Offset="-251.753"/>
        <Point Elevation="-12.513" Offset="-249.937"/>
        <Point Elevation="-12.801" Offset="-216.359"/>
        <Point Elevation="-12.653" Offset="-174.972"/>
        <Point Elevation="-12.591" Offset="-158.425"/>
        <Point Elevation="-12.541" Offset="-144.303"/>
        <Point Elevation="-12.614" Offset="-115.444"/>
        <Point Elevation="-12.615" Offset="-111.726"/>
        <Point Elevation="-12.6" Offset="-104.058"/>
        <Point Elevation="-12.415" Offset="-42.364"/>
        <Point Elevation="-12.406" Offset="-28.724"/>
        <Point Elevation="-12.416" Offset="-1.475"/>
        <Point Elevation="-12.36" Offset="38.494"/>
        <Point Elevation="-12.353" Offset="52.28"/>
        <Point Elevation="-12.321" Offset="63.68"/>
        <Point Elevation="-12.198" Offset="112.168"/>
        <Point Elevation="-12.383" Offset="139.067"/>
        <Point Elevation="-12.577" Offset="161.059"/>
        <Point Elevation="-12.541" Offset="188.84"/>
        <Point Elevation="-12.454" Offset="213.082"/>
        <Point Elevation="-12.385" Offset="256.777"/>
        <Point Elevation="-12.375" Offset="261.779"/>
        <Point Elevation="-12.415" Offset="269.668"/>
        <Point Elevation="-12.639" Offset="309.342"/>
        <Point Elevation="-12.483" Offset="329.784"/>
        <Point Elevation="-12.337" Offset="352.33"/>
        <Point Elevation="-12.37" Offset="365.049"/>
        <Point Elevation="-12.507" Offset="423.352"/>
        <Point Elevation="-12.597" Offset="450.0"/>
      </Points>
    </Section>
    <Section Name="2 + 550">
      <XPositionOnPaper>7.24</XPositionOnPaper>
      <YPositionOnPaper>62.03</YPositionOnPaper>
      <TopGridElev>0.0</TopGridElev>
      <NumPoints>40</NumPoints>
      <Points>
        <Point Elevation="-12.351" Offset="-450.0"/>
        <Point Elevation="-12.346" Offset="-440.604"/>
        <Point Elevation="-12.456" Offset="-420.924"/>
        <Point Elevation="-12.422" Offset="-356.665"/>
        <Point Elevation="-12.436" Offset="-351.476"/>
        <Point Elevation="-12.433" Offset="-348.926"/>
        <Point Elevation="-12.599" Offset="-305.043"/>
        <Point Elevation="-12.617" Offset="-296.42"/>
        <Point Elevation="-12.516" Offset="-254.712"/>
        <Point Elevation="-12.489" Offset="-238.476"/>
        <Point Elevation="-12.648" Offset="-206.205"/>
        <Point Elevation="-12.563" Offset="-187.983"/>
        <Point Elevation="-12.407" Offset="-147.195"/>
        <Point Elevation="-12.453" Offset="-122.034"/>
        <Point Elevation="-12.46" Offset="-116.462"/>
        <Point Elevation="-12.465" Offset="-115.775"/>
        <Point Elevation="-12.453" Offset="-110.426"/>
        <Point Elevation="-12.39" Offset="-62.05"/>
        <Point Elevation="-12.294" Offset="-40.738"/>
        <Point Elevation="-12.318" Offset="-24.44"/>
        <Point Elevation="-12.277" Offset="-5.967"/>
        <Point Elevation="-12.467" Offset="31.391"/>
        <Point Elevation="-12.537" Offset="53.35"/>
        <Point Elevation="-12.432" Offset="77.607"/>
        <Point Elevation="-12.187" Offset="125.999"/>
        <Point Elevation="-12.356" Offset="151.552"/>
        <Point Elevation="-12.421" Offset="160.797"/>
        <Point Elevation="-12.325" Offset="199.432"/>
        <Point Elevation="-12.286" Offset="218.382"/>
        <Point Elevation="-12.281" Offset="225.988"/>
        <Point Elevation="-12.28" Offset="255.015"/>
        <Point Elevation="-12.398" Offset="283.83"/>
        <Point Elevation="-12.476" Offset="305.13"/>
        <Point Elevation="-12.396" Offset="329.028"/>
        <Point Elevation="-12.277" Offset="354.738"/>
        <Point Elevation="-12.291" Offset="372.85"/>
        <Point Elevation="-12.291" Offset="400.408"/>
        <Point Elevation="-12.334" Offset="421.647"/>
        <Point Elevation="-12.426" Offset="448.515"/>
        <Point Elevation="-12.419" Offset="450.0"/>
      </Points>
    </Section>
  </Sections>
</root>

ระยะเวลาในการพัฒนา

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

Geoid Height Calculator v1.05 สำหรับ Mac OS X

Geoid Height Calculator v1.05 รุ่นสำหรับแมคโอเอส

  • คล้อยหลังที่ปล่อยรุ่นสำหรับวินโดส์ไปแล้ว ผมมานั่งคอมไพล์โปรแกรมสำหรับ Mac ซึ่งก็แก้ไขโค๊ดไปบ้าง แต่ไม่ได้หนักหนาอะไร ทำ installer ด้วย dmgCreator  ฟรี ข้อเสียในรุ่นแมคเทียบกับวินโดส์ก็คือ ขนาดเมื่อบีบอัดแล้วยังปาไปถึง 218 MB ส่วนรุ่นวินโดส์ประมาณ 95 MB เอง

ดาวน์โหลดและติดตั้ง

  • ดาวน์โหลดโปรแกรมได้ที่ GeoidHeightV105.dmg แล้วดับเบิ้ลคลิกแมคจะทำการเมาท์อิมเมจมาให้จากนั้นลาก icon โปรแกรมเข้าโฟลเดอร์ Applications เป็นอันเสร็จ โปรแกรมไม่มีเรียกใช้เฟรมเวิร์ค  (Framework) ใดๆทั้งสิ้นครับ ดังนั้นผมคิดว่านำไปติดตั้งเครื่องไหนน่าจะรันได้ไม่มีปัญหา

geoidheight_mac_01

ลองใช้งาน

  • ติดตั้งแล้วโปรแกรมจะอยู่ที่ Applications พร้อมใช้งาน

myapplications

  • ลองรันดู หน้าตาก็เหมือนรุ่นบนวินโดส์

geoidheight_mac_02

  • ป้อนค่าพิกัดแลตติจูด ลองจิจูดแล้วคลิกคำนวณ (Compute)

geoidheight_mac_03

  • ข้อมูลไฟล์ทดสอบ ผมใส่ไฟล์ข้อมูลตัวอย่าง  bundle ไปในโปรแกรมด้วยวิธีเปิดใช้ Finder ไปที่ Applications หาไอคอนโปรแกรม แล้วคลิกขวาเลือก “Show Package Contents”  คลิกไปที่ Contents/Resources/data จากนั้น copy ไฟล์ไปไว้ที่ใช้งานได้สะดวก

geoidheight_mac_05

  • ลองเปิดไฟล์ดูแล้วรัน

geoidheight_mac_06

  • นี่นับว่าเป็นโปรแกรมแรกของผมที่เขียนใช้บนแมค หลังๆมาผมใช้แมคมากกว่าลีนุกซ์ ส่วนวินโดส์ก็ยังใช้เป็นปกติ แต่ยังไงๆก็ใช้น้อยลงกว่าแต่ก่อน เพราะใช้สมาร์ทโฟนกับแท็ปเล็ตมากขึ้น ก็ยังเป็นที่สงสัยโลกยุคหลังพีซี จะเป็นอย่างไร CPU ตระกูล ARM จะสามารถยึดตลาดได้เบ็ดเสร็จ เหมือน x86 ของอินเทลเคยทำได้เหมือนแต่ก่อนไหม
  • สำหรับโปรแกรมเวอร์ชั่นหน้าตรงแผนที่โลก แสดงสเปคตรัมความสูงจีออยด์ ผมอาจจะเปลี่ยนมาเป็น ลูกโลก 3D ให้ดูน่าสนใจมากขึ้น ผมเตรียมลูกโลกไว้แล้วสำหรับเวอร์ชั่นหน้า

geoidheight_mac_07

Categories: 3D, GIS, GPS, Lazarus, Programming, Surveying ป้ายกำกับ:, , , , , , , , ,

แนะนำโปรแกรมคำนวณความสูงจีออยด์ (Geoid Height Calculator) บน EGM96 และ EGM2008 (แจกให้ใช้ฟรี)

ทำไมต้องคำนวณความสูงจีออยด์

  • เป็นที่ทราบกันว่าความสูงเมื่อวัดด้วย GPS จะเป็นความสูงที่อยู่บนทรงรีของ WGS84 เรียกว่า Ellipsoidal Height แต่ในชีวิตจริงของคนเราความสูงที่เราต้องการคือความสูงที่เทียบกับระดับน้ำทะเลปานกลาง (Mean Sea Level)  โดยเฉลี่ยแล้วพื้นผิวจีออยด์จะทับกันสนิทได้กับระดับน้ำทะเลปานกลาง ดังนั้นถ้าทราบความสูงจีออยด์ในตำแหน่งนั้น เราก็สามารถคำนวณหาความสูงจาก GPS เทียบกับระดับน้ำทะเลปานกลางได้ และความสูงเมื่อเทียบกับระดับน้ำทะเลปานกลาง เรียกอีกอย่างได้ว่า Orthometric Height

geoid2_lg

geoid undulation

Geoid Height Calculator

  • ตั้งแต่ปี 2008 รูปทรงของสนามแรงดึงดูดของโลก (Earth Gravitational Model)  เรียกชื่อว่า EGM2008 ได้ถูกเปิดตัวโดย NGA  (National Geospatial Intelligence Agency) และก็ได้ปรับปรุงมาหลายรุ่นแล้ว ปัจจุบัน นำมาใช้งานแทนที่ EGM96 กันมากแล้ว ผมใช้เวลาว่างๆ เขียนโปรแกรมมาคำนวณความสูงจีออยด์ จากที่เขียนเล่นๆในตอนแรก หลังๆมาเพิ่มนู่นนิดเพิ่มนี่หน่อย ก็กลายมาอย่างที่เห็น

geoid height calculator

ส่วนประกอบของโปรแกรม

  • ถ้าติดตั้งโปรแกรมจะเห็นโฟลเดอร์ย่อยชื่อ geoids จะมีไฟล์ “corrcoef” และ “egm96″ สองไฟล์นี้เป็นไฟล์ ascii สำหรับคำนวณความสูงจีออยด์บนโมเดล EGM96 ส่วนอีกไฟล์ที่ขนาดใหญ่ประมาณ 150 MB เป็นไฟล์ไบนารี ชื่อไฟล์ “Und_min2.5×2.5_egm2008_WGS84_TideFree_reformatted” สำหรับคำนวณความสูงจีออยด์บน EGM2008 ในที่นี้จะขอเน้นเฉพาะ EGM2008
  • ไฟล์ “Und_min2.5×2.5_egm2008_WGS84_TideFree_reformatted” ไม่ใช่ไฟล์ต้นฉบับ แต่เป็นไฟล์ที่ถูกรีฟอร์แม็ต เปลี่ยนรูปใหม่สำหรับโปรแกรมเปิดโค๊ด Geotrans ในไฟล์นี้บรรจุความสูงจีออยด์ทุกๆที่ของโลกนี้ ลักษณะไฟล์เป็นกริด แต่ละกริดมีขนาด 2.5’x2.5′ หรือประมาณ 4.5 กม. x 4.5 กม.
  • ถ้าใช้โปรแกรมจำพวก Hex editor มาเปิดปรับโหมดเป็น Big Endian ปรับให้ดูเป็นเลขฐานสิบจะเห็น ตัวเลข 4321 (ไบต์ที่ 5-8) และตัวเลข 8640 (ไบต์ที่ 9-12) ตัวเลขนี้แสดงขนาดของกริด= 4321×8640 จำนวนคอลัมน์(แกน x หรือตามแกนของ longitude) คือ 8640 จำนวนแถว (แกน y หรือตามแกนของ latitude) คือ 4321und_geoid_file_hex
  • ปรับโปรแกรมให้ดูเป็นเลขฐาน 16 ถัดไปไบต์ที่ 13-20 ขนาด 8 ไบต์เป็นขนาด double แสดงระยะห่างระหว่างจุดของกริดในแนวแกน x อ่านมาได้ 3fa55555 55555555 แปลงเป็นตัวเลขได้ 0.04166666666 หน่วยเป็นองศา คูณด้วย 60 เข้าไปเป็น ลิปดาก็ได้ 2.5′ (ตรงกับที่ระบุไว้ตั้งแต่แรกว่าขนาดของแต่ละกริด 2.5’x2.5′)und_geoid_file_hex_griddist
  • ถัดไปไบต์ที่ 21-28 เป็นระยะห่างระหว่างจุดของกริดในแนวแกน y ซึ่งก็เท่ากัน
  • ต่อไปทุกๆ 4 ไบต์จะเป็นตัวเลขลักษณะเป็น float แสดงความสูงของจีออยด์ลักษณะเป็นจุดๆ จนครบทั้งหมด 4321×8640 จุด

und_geoid_file_hex_float

  • โปรแกรมของผมก็จะอ่านไฟล์นี้ในลักษณะนี้มาทั้งหมดมาเก็บเป็น array เรียกว่า Cahce All ซึ่งโปรแกรมจะกินเมมโมรีพอสมควรประมาณ 500 MB ซึ่งเครื่องพีซีหรือโน๊ตบุ๊คสมัยปัจจุบัน คงไม่ใช่เรื่องเหลือบ่ากว่าแรง

ดาวน์โหลดและติดตั้ง

  • โปรแกรมเขียนด้วย FPC/Lazarus ทำไฟล์ติดตั้งด้วย Inno Setup ดาวน์โหลดโปรแกรมแบบ 64 บิตได้ที่ GeoidHeightV106Setup64.zip และดาวน์โหลดโปรแกรมแบบ 32 บิตได้ที่ GeoidHeightV106Setup32.zip
  • ทำการติดตั้ง ผมทดสอบติดตั้งบนวินโดส์ 7/8 รันแล้วไม่มีปัญหา เมื่อเปิดโปรแกรมจะเห็นหน้าตาแรกเข้าดังรูปด้านล่าง ลักษณะ user inteface ก็เน้นเรียบง่าย มีอยู่หน้าเดียว เลือกโมเดลได้ว่าจะใช้ EGM96 หรือ EGM2008 2.5’x2.5′ ถัดไปจะเป็นช่องให้ป้อนพิกัด Latitude/Longitude ในระบบพิกัด WGS84 ถ้ามีความสูงที่ได้จาก GPS หรือรังวัดจาก GPS ก็ป้อนที่ Ellipsoidal Height ได้
  • เมื่อป้อน latitude/longitude แล้วก็คลิก “Compute” โปรแกรมจะคำนวณนำไปเขียนให้ที่ช่าง Geoid Height หรือถ้าป้อนความสูง Ellipsoidal Heigtht  มาด้วยโปรแกรมจะทำการคำนวณ Orthometric Height มาให้ด้วย

geoidheight-first

  • ถัดลงมาด้านซ้ายเป็นตารางกริด จะถูกใช้เมื่อเปิดไฟล์ที่เก็บค่า Latitude/Longitude หลายๆจุด ในกรณีที่ต้องการคำนวณเยอะๆ ส่วนด้านขวาที่ประกอบด้วยแผนที่โลกอย่างง่ายๆ มีเส้น Latitude/Longitude ในแนวตั้งแนวนอน ทุกๆ 45 องศา ส่วนที่เป็นสีๆเป็นสเปคตรัม ได้จากการอ่านไฟล์ที่ผมกล่าวไปแล้วแล้วนำความสูงจีออยด์มาแมพกับสี โดยที่ด้านสีน้ำเงินเข้มแทนความสูงจีออยด์ -107 เมตร จะไปถึงโทนสีแดงเข้มแทนความสูงจีออยด์ที่มากสุด 87 เมตร
  • ด้านล่างเขียนสเกลมีตัวเลขกำกับให้ดูง่ายด้วย ใต้แผนที่โลกจีออยด์จะมีทูลส์บาร์เล็กๆ สำหรับการซูมเข้าออก การเลื่อนแผนที่ให้ใช้งานได้สะดวกด้วย
  • การเลื่อนเมาส์ โปรแกรมจะทำการคำนวณค่าความสุงจีออยด์ให้แบบเรียลไทม์ แสดงค่าพิกัดและความสูงจีออยด์ที่ status bar ด้านล่างด้านขวา

วิธีใช้งาน

  • มุม latitude/longitude สามารถป้อนได้สามแบบ แบบแรกเป็นดีกรีเช่น 12.2325215 แบบที่สองทศนิยมที่ลิปดาเช่น 12 35.25322 และแบบสุดท้ายคือแบบแยก 12 40 21.4512 ใส่เครื่องหมายลบได้กรณี latitude อยู่ต่ำกว่าเส้นศูนย์สูตร
  • ช่วงของ latitude ที่คำนวณได้อยู่ในช่วง -90…90 ส่วน longitude ป้อนค่าได้ตั้งแต่ -180..180
  • มาทดสอบกันเลย ผมลองป้อนค่าเข้าดังรูปด้านล่าง คลิกคำนวณจะได้ผลลัพธ์และ เขียนกากบาทให้ที่แผนที่โลกด้วย ตรงตำแหน่งพิกัดที่ป้อนไป ลองซูมแผนที่โลกมาดู

geoidheight-manualinput

การคำนวณผ่านไฟล์ coordinates

  • เมื่อติดตั้งโปรแกรมแล้วจะมีโฟลเดอร์ย่อยชื่อ “data” ผมจะเก็บไฟล์ coordinates ของ latitude/longitude เอาไว้ทดสอบ ไฟล์เหล่านี้สามารถเป็นตัวคั่นด้วยคอมมาได้ (csv) หรือกั้นด้วยช่องว่างได้ คลิกที่ทุลส์บาร์ด้านเปิด ทำการเปิดไฟล์ชื่อ NE2000.csv มีจุด coordinates ทั้งหมด 2000 จุด ได้จาก randomsample_data
  • ต่อไปโปรแกรมจะถามรูปแบบ ไฟล์นี้เก็บค่า lattitude/longitude เท่านั้น เลือกแบบ “N E” จากนั้นคลิก import

seelct_format

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

geoidheight-openneทดสอบกับไฟล์ 3000 จุด แบบมีความสูง

  • ลองเปิดไฟล์ PNEZ3000.csv ไฟล์นี้มีความสูง Ellipsoidal Height ติดมาด้วย แต่เหมือนเดิมคือค่าความสูงได้จากการ random

format_pnez

  • ทำการคำนวณ เนื่องจากไฟล์นี้มีความสูง Ellipsoidal Height มาด้วยโปรแกรมจะคำนวณหา Orthometric Height มาให้ด้วยเช่นกัน geoidheight-pnez
  • ถ้าต้องการเซฟไฟล์ที่คำนวณแล้วสามารถคลิกที่ทูลส์บาร์ด้านบนรูปดิสเก็ตได้

ที่มาไฟล์ทดสอบ

  • ไฟล์ทดสอบชื่อ GeoidHeights.dat (credits Charles F. F. Karney ผู้พัฒนา GeographicLib) ผมดาวน์โหลดมาเป็นไว้อ้างอิง ไม่เปิดไฟล์นี้มาคำนวณนะครับ ในไฟล์ประกอบด้วยค่าพิกัด latitude/longitude ความสูงจีออยด์บน EGM84 EGM96 EGM2008 ตามลำดับ จำนวนจุดทั้งหมด 500, 000 จุด ค่าพิกัดได้จากการ random ผมนำไฟล์นี้มาตัดแบ่งเพื่อนำมาคำนวณด้วยโปรแกรมของผม เพื่อทดสอบว่าค่าความสุงจีออยด์ที่คำนวณมาได้ตรงกันไหม ค่าที่ได้จะแตกต่างกันระดับเศษของมิลลิเมตร

geoidheights-testdata

การคำนวณ Interpolation และเครดิต

  • ใช้แบบ Bi cubic interpolation ส่วนในแผนที่ในโปรแกรมเวลาผู้ใช้ลากเมาส์ ความสูงจีออยด์ที่คำนวณแบบเรียลไทม์ ใช้แบบ Bi linear interpolation
  • ก็ขอยกเครดิตให้กับโปรแกรมเปิดโค๊ด Geotrans ผมศึกษาและเรียบเรียงการคำนวณ EGM2008 จากโค๊ดภาษา c/c++ ได้ ที่นี่
  • ยกเครดิตคำนวณความสูงจีออยด์บน EGM96 ผมศึกษาและเรียบเรียงจากโค๊ดภาษา c ได้ ที่นี่ (credits ineiev) ซึ่งเจ้าของโค๊ดเขาเรียบเรียงจากภาษาฟอร์แทรนของ NGA แต่สำหรับผมก็ไปศึกษาฟอร์แทรนจากโค๊ดของ NGA เหมือนกันแต่ไม่สำเร็จ ทั้งๆตอนปี 2 อยู่มหาวิทยาลัยก็ร่ำเรียนภาษานี้จากเครื่องเมนเฟรมมาเหมือนกัน ผ่านไปหลายสิบปี กลายเป็นคนแปลกหน้า

ทิ้งท้าย

  • เนื่องจากโปรแกรมยังเป็นรุ่นแรกๆ คาดว่าบั๊กคงจะมีพอสมควร การ zoom in หรือ zoom out ใช้เวลา 4-5 วินาที โปรแกรมใช้เวลาในการเขียนแผนที่โลก ที่ใช้เวลามาก เนื่องจากไม่ได้ใช้เอนจิ้นแผนที่่ใดๆมาช่วยเลย เขียนบน canvas แบบดิบๆ
  • ก็ขอฝากโปรแกรม Geoid Height Calculator ประดับวงการสำรวจไว้อีกโปรแกรมหนึ่งครับ

เขียนโปรแกรมเปลี่ยนภาษาบนวินโดส์ด้วย AutoIT

Grave Accent (`) ผิดตรงไหน

  • ผมเชื่อว่าคนใช้วินโดส์ส่วนใหญ่เวลาตั้งปุ่มภาษา จะใช้คีย์ Grave Accent (`) แทนที่จะเป็น Alt + Shift หรือ Ctrl + Shift สำหรับผมแล้วเนื่องจากใช้แมคด้วย จึงคุ้นเคยกับการใช้คีย์ Alt + Space จนติดเป็นนิสัย เวลาใช้ลีนุกซ์ จึงตั้งคีย์เปลี่ยนภาษาเป็น Alt + Space ตามแมค ซึ่งในลีนุกซ์การตั้งค่าก็ไม่ใช่เรื่องยากเย็น การใช้ Grave Accent ผมว่าก็ไม่ได้ผิดตรงไหน แล้วแต่ความคุ้นเคย
  • แต่ในวินโดส์การตั้งคีย์ Alt + Space กลับเป็นเรื่องใหญ่เพราะ OS ไม่สนับสนุนคีย์นี้ แต่ในวินโดส์แปด กลับสามารถใช้คีย์ Win + Space ได้ แต่ไม่ถนัดเท่าเพราะ Alt + Space เวลากดใช้หัวแม่มือซ้ายกด Alt หัวแม่มือขวากด Space จะสะดวกมากกว่า ผมเคยค้นหาในอินเทอร์เน็ต  ดาวน์โหลดมาใช้งาน เมื่อล้างลงวินโดส์ใหม่ โปรแกรมหาย ไปค้นหาอีกครั้งไม่เจอแล้ว

AutoIt Script Language

  • ในที่สุดมาเจอโปรแกรมที่เป็นภาษาสคริปต์ ชื่อ AutoIT ไปดาวน์โหลดมาใช้ได้ฟรี ขนาดไม่ใหญ่ ใช้เวลาอ่านคู่มือประมาณครึ่งชั่วโมง ผมดาวน์โหลดโปรแกรมสคริปต์เปลี่ยนคีย์บอร์ดจากไหนจำไม่ได้แล้ว แล้วมาทำการแก้ไข จากโค๊ดด้านล่างไม่กี่บรรทัด ฟังก์ชั่น HotKeySet เมื่อผู้ใช้กด Alt และ Space พร้อมกันให้เรียกฟังก์ชั่น Change แล้วทำการแปลงคีย์เป็น Alt + Shift
;^ = Ctrl
;! = Alt
;# = WinKey (Meta)
;+ = Shift</code>

HotKeySet("!{Space}", "change") ;Registers Alt + Space

;Main loop
While 1
  Sleep(100)
WEnd

;At Input language settings on windows
;Please select Alt + Shift
;Changes Keyboard Layout

Func change()
  Send ("{ALTDOWN}") ;Hold down Alt
  Sleep(50) ;Wait 100 milliseconds
  Send("{LSHIFT}{ALTUP}") ;Press Left-Shift and release Alt
EndFunc

ตั้งคีย์บนวินโดส์ก่อน

  • ผมตั้งค่าการเปลี่ยนคีย์เป็น Alt + Shift ด้านซ้าย เราจะให้โปรแกรมสคริปย์ดักจับ Alt + Space เมื่อผู้ใช้กดแล้วเปลี่ยนเป็นคีย์ Alt + Shift ส่งต่อให้วินโดส์

switch_win

ติดตั้ง AutoIt และใช้งาน

  • ในชุดของ AutoIt จะมี SciTe Script Editor เปิดมาแล้วลอกโค๊ดด้านบนใส่

scite

  • ที่จริงสามารถรันโค๊ดได้จากเมนู Tools ถ้า build จะได้ไฟล์ exe ออกมา แต่จะไม่มีไอคอน การยัดไอคอนเข้าไปใน execute file ให้ใช้ Auto2Exe ที่มาด้วยกัน ผมเตรียมไฟล์ไอคอนด้วย เป็นรูปธงชาติไทย คลิก Convert จะได้โปรแกรม exe ที่มีไอคอนมาเรียบร้อย

auto2exe

พร้อมใช้งาน

  • ถ้าเป็นวินโดส์ 7 ทำการ copy โปรแกรมไฟล์ exe มาวางที่ “C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup” เมื่อวินโดส์บู๊ตมาอีกรอบก็พร้อมใช้งานครับ

notifications

ดาวน์โหลดโปรแกรม

  • ไม่อยากโปรแกรม สามารถดาวน์โหลดไปใช้งานได้ iSwitcher2.zip (4shared.com) หรือ iSwitcher2.zip (Hightail.com)

Traverse Pro รุ่นใหม่ version 2.50 (มาตามสัญญา)

 นานเหลือเกินที่จากกันไกล

  • หยุดไปนานจนทิ้งบล็อกให้ร้าง เนื่องจากภารกิจการงานในปัจจุบันยุ่งเหยิงเหลือเกิน ที่ผ่านมาไม่นานนี้พอมีเวลาว่าง จึงเอาโปรแกรม Traverse Pro ที่ทิ้งโครงการไว้เสียนานมาปัดฝุ่นต่อ ให้สามารถนำมาติดตั้งบนวินโดส์ 7 หรือ 8 ได้ ปรับปรุงหน้าตา user interface ให้ดูดีขึ้น แตกเวอร์ชั่นออกเป็นรุ่น 32 บิตและ 64 บิต สำหรับวินโดส์ 32 บิต ผมว่าก็น่าจะมีคนใช้อยู่พอสมควร ในอนาคตไม่นานวินโดส์ 64 บิตก็น่าจะเป็นรุ่นหลัก เพราะมองเห็นและใช้ทรัพยากรของเครื่องได้หมด ตัวอย่างเช่นแรมที่เห็นเกิน 3 GB อาจจะมีคนใช้ Windows XP อยู่บ้างประปราย เนื่องจากโปรแกรมถูกพัฒนาบนวินโดส์  7 ไม่ทราบว่าเอาไปติดตั้งบนวินโดส์ XP ได้หรือปล่าว

traversepro_about32

หยุดพัฒนาไปนานเพราะติดกัปดักตัวเอง

  • บอกกันตรงๆ Traverse Pro รุ่นเดิมเขียนด้วย Delphi ตอนนี้ผมพอร์ตขึ้นมาเขียนด้วย Free pascal compiler(FPC) & Lazarus ที่ติดปัญหาร้ายแรงคือไฟล์ข้อมูลบางส่วนที่เป็นไบนารีไฟล์ รุ่นเดิมเขียนตัวเลขทศนิยมด้วยชนิดข้อมูลที่เรียกว่า Extended เดิมบนวินโวส์ 32 บิต มันเป็นเลขทศนิยมขนาด 10 byte (80 bit) แต่บนวินโดส์ 64 บิต ทาง Dephi และ  FPC พร้อมใจกันมาลดขนาดลงเป็น 8 Byte (64 bit) ทำให้การอ่านข้อมูลจากไฟล์รุ่นเก่าได้ข้อมูลมาไม่ถูก ยุ่งจริงๆ ผมทิ้งปัญหานี้ไว้นานมาก จนมานั่งแกะเขียนกันใหม่จากเดิมอ่านข้อมูลไฟล์เป็นก้อนๆ (record) แต่ตอนนี้อ่านสตรีมจากไฟล์ออกมาเป็น Byte (หรือ array of byte) แล้วมาทำการนับบิตหั่นข้อมูลออกมาเป็นส่วนๆ ก็สามารถแก้ปัญหานี้ได้แบบทุลักทุเล
  • สรุปแล้วที่พลาดตอนแรกออกแบบไฟล์ข้อมูลเขียนข้อมูลทศนิยมเป็น Extended ที่กล่าวไปแล้ว ซึ่งเกินความจำเป็นจริงๆ ตัวเลขไม่ได้ละเอียดที่จะต้องเขียนด้วยข้อมูลประเภทนี้

ส่วนที่ปรับปรุงใหม่

  • เขียนข้อมูลเก็บลงไฟล์เป็น Unicode ทำให้เรื่องภาษาไทย ไม่ต้องกังวลเหมือนแต่ก่อน ก่อนหน้านี้เวลาเขียนเครื่องหมาย degree เช่นเขียนลง excel ฝั่ง excel จะเห็นเป็นฐอฐาน (ฐ) วุ่นจริงๆ พอมาเป็นยูนิโค๊ด ก็หมดปัญหา
  • User interface ปรับให้ดูเรียบง่ายขึ้น รายการคำนวณก็ปรับใหม่ให้ดูเนียนขึ้น เมื่อป้อนข้อมูลวงรอบแล้ว ทำการคำนวณ ตรงรายการคำนวณผมจัดทำใหม่ให้ดูง่ายขึ้น

traversepro_computed_clicked

รายการคำนวณที่ดูง่ายขึ้น

traversepro_output

  • เมื่อคำนวณวงรอบแล้ว คลิกที่ toolbar ดังรูป  โปรแกรมจะส่งข้อมูลออกที่โปรแกรม Microsoft Excel เครื่องหมายองศาดีกรี ไม่มีปัญหาเป็น ฐอฐาน เหมือนรุ่นเก่า ทำให้เวลาเขียนมุม อ่านได้ง่าย

traversepro_excel_clicked

จะได้ผลลัพธ์ดังรูป

traversepro_excel

  • ส่วนพล๊อทรูปวงรอบ (Plot  Traverse) ปรับปรุงใหม่  แสดงผลให้ดูเรียบง่ายกว่าเดิม สามารถ Zoom, Pan ได้ตามต้องการ

traversepro_plot_clicked

จะเห็นรูปร่างวงรอบที่ถูกคำนวณปรับแก้แล้ว

traversepro_plotraverse

สามารถเซฟเป็น Autocad DXF ที่ทูลบาร์ดังรูปด้านล่าง

traversepro_plottraverse_toolbarเสร็จแล้วนำไปเปิดด้วย Autocad ต่อไป

traversepro_autocad

ของแถมอีกเล็กน้อยสามารถ Copy เป็นรูปได้เข้าคลิปบอร์ด

traversepro_plottraverse_copy_clickedแล้วไปเปิดโปรแกรมด้านตบแต่งรูปภาพจะได้ผลลัพธ์

traversepro_painted

แก้ไขปัญหาฟอนต์จิ๋วบนวินโดส์ 8

  • ใครที่ดาวน์โหลดโปรแกรมช่วงเดือนธันวาคม 56 อาจจะประสบปัญหาฟอนต์ตารางป้อนข้อมูลมีขนาดเล็กกว่าที่รันในวินโดส์ 7 ทรมานสายตาผู้สูงวัยเป็นอย่างยิ่ง

tpro001

  • แก้ไขแล้ว ขอให้ผู้ใช้งานบนวินโดส์ 8 ดาวน์โหลดมา แล้วติดตั้งอีกครั้ง

tpro002

ดาวน์โหลดโปรแกรม (Download)

ก่อนจากกัน

  • ในส่วนคู่มือมีน้องๆอยู่คน ตอนนี้ไม่ประสงค์จะออกนามครับ ได้รับอาสาไปจัดทำ ก็รอ user manual เสร็จเมื่อไหร่ค่อยมาใส่ลิีงค์ให้ดาวน์โหลดกัน
  • ที่ผ่านมาได้มีโอกาสศึกษาเขียนโปรแกรมด้วย Python เนื่องจากอายุมากค่อนข้างใช้เวลาพอสมควร ไพธ่อนเป็นภาษาที่เขียนได้กระชับไม่เยิ่นเย้อเหมือนปาสคาลหรือ Visual basic ทรงพลัง ที่สำคัญคือมีไลบรารีมากมายมหาศาล แต่ใช้เวลาเรียนรู้ไปสองสามเดือนเหมือนกันครับ นับว่า Learning curve ค่อนข้างชัน ไม่ได้ยากมาก แต่เป็นที่วัยไม่เอื้ออำนวย สมองไม่ปราดเปรียวเหมือนตอนวัยรุ่นๆแล้ว
  • ผมเอา Mapnik มาเรียกใช้ด้วย Python ช่วยด้าน GIS ตัวนี้ก็ทรงพลังมาก แต่คนส่วนใหญ่เอาไปใช้ในฝั่งเซิฟเวอร์กันเป็นส่วนมาก ส่วนผมเอามาใช้ในฐานะบน Desktop ก็ไม่ผิดหวัง อนาคตอาจมีโปรเจคที่เขียนด้วยไพธ่อนมาฝากกัน ถ้ายังไม่หมดแรงเสียก่อนครับ

traversepro_about64bit

ขั้นตอนการติดตั้ง PostGIS/Postgresql บน Ubuntu Server

ความเป็นมา

  • Postgresql อ่านออกเสียงว่า โพสเกรส เป็นระบบจัดการฐานข้อมูล RDBMS ซึ่งพัฒนาโดย PostgreSQL Global Development Group ในปี 2550 ลักษณะเป็น opensource มีลิขสิทธิ์แบบ BSD เป็นซอฟท์แวร์แบบ cross-platform ใช้ได้ทั้ง Windows, Free BSD, Solaris, Linux และก็ Mac OS
  • ย้อนหลังไปก่อนหน้านั้น ประวัติดั้งเดิม Postgresql พัฒนาต่อจากฐานข้อมูลชื่อ Ingres จึงเรียกว่า Post-Ingres (แปลง่ายๆว่า อินเกรสในตอนหลัง) ตอนหลังชื่อกลายเป็น Postgresql โครงการนี้สานต่อจากฐานข้อมูล Ingres ที่ยังมีปัญหา การพัฒนาเริ่มต้นในปี 2528 โดย Michael Stonebraker ที่ University of California, Berkeley

PostGIS

  • PostGIS คือส่วนขยายเพิ่มเติมที่ทำให้ฐานข้อมูล Postgresql  สามารถรองรับข้อมูลด้านสารสนเทศรูมิศาสตร์ (GIS) คือสนับสนุนข้อมูลที่สัมพันธ์เชิงพื้นที่ (Spatial)  ในตอนที่เขียนอยู่เป็นรุ่น 1.5 ยังไม่สนับสนุนงานด้าน Raster ต้องรอรุ่น 2.0
  • ผมจะเน้นเขียนถึงด้านนี้เพราะทีมงานของผมนำไปประยุกต์ใช้ควบคู่กับโปรแกรม GIS Desktop คือ Quantum GIS ซึ่งจะเป็นโปรแกรมที่เรียกใช้ฐานข้อมูล PostGIS จากเครื่อง Ubuntu Server ที่ลง PostGIS/Postgresql ไว้

  • สำหรับฐานข้อมูลระดับใหญ่ที่ support ข้อมูลแบบสัมพันธ์กับเชิงพื้นที่ (Spatial) มี Oracle, Microsoft SQL ServerInformix Dynamic Server และก็ Postgresql ผ่านทางส่วนขยาย PostGIS ที่กล่าวไปแล้ว

ความนิยม

  • ตอนนี้มีคนหันมาใช้ Postgresql กันมากขึ้น เพราะ MySQL ฐานข้อมูลยอดนิยมตอนแรกถูก Sun ซื้อไปคนยังไม่ตระหนกตกใจเท่าไหร่ แต่พอ Oracle ไปซื้อ Sun แล้วได้ MySQL มาด้วย ผู้ใช้ก็เกิดอาการอกสั่นขวัญแขวนว่า MySQL จะฟรีหรือเสียเงินต่อด้วยความไม่มั่นใจใน Oracle ผู้ใช้ตามองค์กรก็ย้ายจาก MySQL ไป Postgresql กันมากขึ้น
  • Postgresql ที่เราใช้ฟรีกันทั่วไปพัฒนาโดยชุมชนที่ผมกล่าวไปแล้ว ถ้าเป็นรุ่น Enterprize ที่เทียบเคียงกับ Oracle, DB2, MS SQL Server พัฒนาโดย EnterprizeDB โดยการพัฒนาต่อยอดจาก Postgresql แต่เป็นโค๊ดปิด
  • ตัวอย่างก็คือ Redhat ที่กระโดดเข้าไปลงทุนใน EnterprizeDB ทั้งที่ก่อนหน้านี้โซลูชั่นของ Redhat ก็ผูกอยู่กับ MySQL แต่มีความเสี่ยงสูงเพราะ Oracle เป็นคู่แข่งโดยตรงกับ Redhat และที่ไม่ลืมคือ IBM เข้าไปลงทุนกับ EnterprizeDB ก่อน Redhat ซะอีก (ทั้งที่ IBM ก็มี DB2 อยู่แล้ว)

ขั้นตอนการติดตั้ง

  • สำหรับ Ubuntu Server ที่ใช้อยู่เป็น  64 บิต ตามธรรมเนียมของเซิฟเวอร์ดั้งเดิมคือไม่มีระบบ Desktop คำสั่งที่ใช้เป็น command line ทั้งหมด แต่หลังๆก็เห็น Centos Server ทำเป็น Desktop แต่ดูๆแล้วกราฟฟิคค่อนข้างเรียบง่าย เบาๆ ไม่กินแรมมาก เพราะต้องสงวนแรมให้กับ service/process ของเซิฟเวอร์
  • สำหรับ server ก็ยังเป็นเดี่ยวๆไม่มี cluster เพราะ user ยังไม่มาก ไม่เกิน 20 คน ตัว server รับงานได้ลื่นไหล

ติดตั้ง PostGIS/Postgresql

  • ใช้ putty ล็อกอิน เข้าไป server หรือไปนั่งหน้า server แล้วก็บรรเลงเลยครับ ตอนนี้เมเจอร์เวอร์ชั่นออก 9,1 แล้วแต่ใน Ubuntu Server ยังเป็น 8.4 อยู่
$sudo apt-get install postgresql-8.4 postgresql-contrib-8.4 postgresql-8.4-postgis
  • แก้ไขไฟล์ config ชื่อ pg_hba.conf
$sudo nano /etc/postgresql/8.4/main/pg_hba.conf
  • ระบุว่า IP Address สามารถเข้ามาใช้งาน server ได้ เพิ่มบรรทัดนี้เข้าไปโดยที่หมายเลข IP Address แก้ไขให้ตรงกับที่ใช้

host  all  postgres  192.168.5.0/24  md5

  • แก้ไขไฟล์ config ชื่อ postgresql.conf เพื่อให้การ remote จากเครื่องอื่นที่ใช้เช่น pgAdmin เข้าไปใช้ server ได้
$sudo nano /etc/postgresql/8.4/main/postgresql.conf
  • แก้ไขบรรทัดโดยการยกเลิก comment ที่บรรทัด  listen_address = ‘localhost’ ให้เป็น
listen_address = '*'
  • ทำการ restart service ของ postgresql
$sudo /etc/init.d/postgresql restart
  • หลังจากติดตั้ง postgresql แล้วจะมี user และ group ชื่อ postgres ขึ้นมาซึ่งจะเป็น user ผู้ดูแลระบบของ linux ที่มีสิทธิ์ในการแก้ไข database ทำการเปลี่ยน password ของ user ชื่อ postgres ให้กับ Ubuntu ก่อน โดยป้อนรหัสของไปสองครั้ง สมมติว่าเป็น ‘mypostgres143′
$sudo passwd postgres
  • เปลี่ยน user เป็น postgres เพื่อจะทำการแก้ไข password เพื่อให้สามารถล็อกอินไปแก้ไข database ได้ password ที่ใส่เข้าไปต้องให้ตรงกับ Ubuntu คือ ‘mypostgres143′
$sudo su postgres
$psql -c"ALTER user postgres WITH PASSWORD 'mypostgres143'"
  • สร้างเท็มเพลตของฐานข้อมูลที่เป็นต้นแบบสำหรับงาน GIS (ยังใช้ user ชื่อ postgres อยู่)

$createdb postgistemplate

  • ตอนนี้ฐานข้อมูลชือ postgistemplate ยังเป็นฐานข้อมูลต้นแบบสำหรับ postgresql ทั่วๆไปต่อไปจะปรับโครงสร้างให้รองรับงาน GIS
$createlang -d postgistemplate plpgsql
$psql -q -d postgistemplate -f /usr/share/postgresql/8.4/contrib/postgis-1.5/postgis.sql
$psql -d postgistemplate -f /usr/share/postgresql/8.4/contrib/postgis-1.5/spatial_ref_sys.sql
  • สร้าง Group role แล้วค่อยมอบสิทธิ์ให้ user ต่อไปพิมพ์คำว่า psql ตรงคอมมานด์ไลน์ เพื่อจะใช้ภาษา sql ได้เต็มๆ ตรงพร็อมต์จะกลายเป็น postgres# ผมสร้าง group role ที่ชื่อ gisgroup ขึ้นมา จำกัดสิทธิ์ให้สร้าง Database ได้เท่านั้น
#CREATE ROLE gisgroup NOSUPERUSER NOINHERIT CREATEDB NOCREATEROLE;
  • สร้าง user ชื่อ gis ด้วยพาสเวิร์ด ‘mypuppet’
#CREATE ROLE gis LOGIN PASSWORD 'mypuppet' NOINHERIT;
  • แล้วมอบอาญาสิทธิ์หรือบทบาทจาก gisgroup ให้ด้วยคำสั่ง GRANT ออกจากโหมด sql ด้วยคำสั่ง \q
#GRANT gisgroup TO gis;
#\q

มอบสิทธ์ 2 ตารางข้อมูล spatial ให้แก่ผู้ใช้ที่กำหนด

  • สองตารางข้อมูลที่สนันสนุนเรื่อง spatial ที่สร้างมาด้วยตัวส่วนขยาย PostGIS คือ geometry_columns และ spatial_ref_sys เราจะมอบสิทธิ์เต็มแก่ผู้ใช้ชื่อ gis (ไม่ลืมที่จะเปลี่ยน user อื่นเป็น postgres)
$psql -d postgistemplate -c "ALTER TABLE geometry_columns OWNER TO gis;"
$psql -d postgistemplate -c "ALTER TABLE spatial_ref_sys OWNER TO gis;"

สร้างฐานข้อมูลสำหรับใช้งานจริง

  • ใช้คำสั่งสร้างฐานข้อมูลจาก template ที่เราสร้างไว้แล้วชื่อ postgistemplate ฐานข้อมูลที่จะสร้างใหม่ชื่อ cpendb ให้สิทธิ์ผุ้ใช้ชื่อ gis

$createdb -T postgistemplate cpendb -O gis

ติดตั้งทูลส์สำหรับ Postgresql

  • ต่อไปเครื่องมือสำหรับรีโมตเข้าไปบริหารฐานข้อมูล Postgresql จากเครื่องคอมพิวเตอร์ของเรามีให้เลือกใช้แบบ stand alone หรือรันบนอินเทอร์เน็ต เบราเซอร์ก็มี เป็นของฟรี ตัวแรกก็ pgAdmin3 นั้นแจ๋วที่สุดมีให้ใช้ทั้งบนลีนุกซ์หรือทางฝั่งวินโดส์ หรือจะไปใช้ phpPgAdmin บน internet browser ก็ได้แล้วแต่ความชอบ
  • ถ้าเราใช้ ubuntu หรือ ลีนุกซ์ Mint เป็น desktop ติดตั้งง่ายๆด้วย $sudo apt-get install pgadmin3 ติดตั้งแล้วมาดูว่าจะเข้าไป access ฐานข้อมูล cpdb ที่ติดตั้งเข้าไปแล้วอย่างไร เปิดโปรแกรม pgAdmin3 ใช้เมนู File > Add Server…

pgAdmin3 สำหรับบริหารฐานข้อมูล Postgresql (บนวินโดส์)

  • สำหรับผู้ใช้ pgAdmin3 ส่วนใหญ่จะเป็นสิทธิ์ Admin กันอยู่แล้ว ดังนั้น Username ที่ใช้จะเป็น ‘postgres‘ ซึ่งมีสิทธิ์สูงสุด ใส่ password เป็น ‘mypostgres143‘ ส่วน Name เป็นชื่อ Server (ตั้งอะไรก็ได้ในสื่อความหมาย) ส่วน Host เป็นเลข IP ของเซิฟเวอร์ในวงแลนของเราอย่างของผมเป็น 192.168.5.111 เสร็จแค่นี้ถ้าไม่มีอะไรผิดพลาดจะเห็นฐานข้อมูล cpendb ที่เราสร้างไว้ก่อนแล้ว

pgAdmin3 เปิดเซิฟเวอร์ดูไฟล์ที่สร้างไว้แล้ว (บนลีนุกซ์)

ใช้ปลั๊กอินของ Quantum GIS แปลง shape file เข้าไปเก็บในฐานข้อมูล

  • การปั๊ม shape file เข้าไปเก็บในฐานข้อมูล PostGIS ใช้ SPIT ซึ่งเป็นปลั๊กอินของ Quantum GIS นั้นง่ายที่สุด เมื่อเปิด QGIS แล้วคลิกที่เมนู Database > SPIT > Import Shapefile to PostgreSQL ขั้นแรกสร้าง connection ไปที่ฐานข้อมูลPostGIS ก่อน ด้วยการคลิกที่ New

สร้าง connection ไปยังฐานข้อมูล PostGIS บน Server

  • ขั้นต่อไปให้พารามิเตอร์ที่จะติดต่อกับ Server ตั้งชื่อ Host ให้ตรงกับ IP Address ส่วนฐานข้อมูลคือ ‘cpendb’ ที่เราเพิ่งสร้างไป และ Username ‘gis’ Password ‘mypuppet’

ป้อนค่าพารามิเตอร์

  • ก่อนจะเพิ่ม Shape fiel คลิกที่ปุ่ม Connect ดูถ้าสำเร็จก็คลิกที่ Add เพื่อเพิ่ม Shape file เข้าไปเก็บในฐานข้อมูล PostGIS ที่เครื่อง Server สามารถ Add ได้ทีละหลายไฟล์ จากนั้นจะเป็นกระบวนการปั๊มข้อมูลเข้า server ถ้าข้อมูลไม่ใหญ่ก็ไม่ต้องรอนานมาก

เพิ่ม Shape file เข้าฐานข้อมูล

  • หลังการเพิ่ม Shape file ไปที่ฐานข้อมูล PostGIS แล้วเราจะไม่เห็นอะไรเพิ่มมาที่ Map ให้ไปคลิกที่ไอคอนของ QGIS คือ Add PostGIS Layer เลือกตารางที่ต้องการด้วยการ

เลือก Add Table จากฐานข้อมูล PostGIs

  • จะเห็นตารางข้อมูลที่เลือกเพิ่มมาแสดงบน Map ของ QGIS

Quantum GIS แสดงตารางข้อมูลของ PostGIS จาก Server

สรุปการใช้งาน PostGIS

  • เมื่อฐานข้อมูลถูกย้ายมาที่ PostGIS แล้ว ข้อดีคือสามารถให้ user หลายๆคนเข้ามา access ฐานข้อมูลเพื่อแก้ไข update Attribute หรือแม้กระทั่งใช้ทูลส์เช่น QGIS เข้ามาแก้รุปร่าง Vector ได้พร้อมๆกัน
  • เพียงแต่ต้องมีการจำกัดสิทธิ์ user สำหรับผู้ใช้บางคน ซึ่งการให้สิทธิ์ผู้ใช้บางคนมีสิทธิ์แก้ไขได้เฉพาะบางฟิลด์ ไม่มีสิทธิ์เพิ่มหรือลบ record ได้ เป็นเรื่องปลีกย่อยที่ผู้อ่านต้องไปศึกษาต่อครับ
  • สำหรับ PostGIS รุ่น 2.0 ที่จะออกในวันข้างหน้าก็จะสนับสนุนเรื่อง Geo Raster ก็เป็นรุ่นที่รอคอยครับว่าจะทำได้ดีขนาดไหน
Categories: GIS, Lazarus, Windows ป้ายกำกับ:, , , , , ,

การนำเข้าข้อมูลจากไฟล์ CSV เป็นลายเส้น Polygon ใน QGIS

การนำเข้าข้อมูลจากไฟล์ CSV เป็นลายเส้น Polygon

  • ก็ถือว่าเป็นทิปและทริคเล็กๆน้อยๆ ในกรณีสร้าง Vector ที่เป็นรูป Polygon จากข้อมูลดั้งเดิมที่เป็นไฟล์ Excel แล้วแปลงเป็น CSV นำมาสร้างเป็นรูป Vector ใน Quantum GIS ซึ่งโปรแกรมด้าน GIS ที่ฟรีและเปิดโค๊ด cross-platform ในแวดวง GIS คงรู้จักกันดี ข้อมูลในเบื้องต้นที่จะนำมาทดสอบเป็นตัวอย่างคือ
  1. ไฟล์รูปแปลงที่ดิน งานสำรวจในภาคสนามจะได้มาเป็นค่าพิำกัด UTM และมี ID สำหรับรูปแปลงที่ดินไว้ด้วย ส่วนใหญ่แล้วเมื่อได้ค่าพิกัดแปลงที่ดินจากสนามแล้ว Draftman จะทำการสร้างรูปใน Autocad เพื่อตรวจสอบรูปร่าง ซึ่งการนำไฟล์ CAD แปลงเป็นฟอร์แม็ต้าน GIS ทำได้หลายโปรแกรมเช่นเปิดไฟล์ CAD ด้วย Global Mapper ทำการสร้าง attribute เพื่อเก็บ ID รูปแปลงที่ดิน แต่ในกรณีผมขอย้อนไปจุดเริ่มว่าถ้ามีไฟล์แบบ CSV และเก็บรูปแปลงเป็นค่าพิกัดเรียงไปตามลำดับจะทำอย่างไร?
  2. ไฟล์Attribute เก็บ Parcel_ID แปลงที่ดินพร้อมคุณสมบัติต่างเช่น ชื่อแปลงที่ดิน, ชื่อกลุ่มแปลงที่ดิน

ไฟล์ที่เก็บรูปแปลงที่ดินแยกตาม Parcel_ID

ความต้องการขั้นต้นใน QGIS

    1. ต้องการ Plug-in ชื่อ “Add Delimited Text Layer” เป็นปลั๊กอินที่มากับ QGIS ตั้งแต่ติดตั้งเสร็จตอนแรกไม่แสดง ต้องทำการเลือกก่อนผ่านเมนู Plugins > Manage Plugins… ทำเครื่องหมายเลือกให้กับ “Add Delimited Text Layer” เท่านี้ก็ใช้ได้
    2. ต้องการ Plug-in ชื่อ “Points2One” ปลั๊กอินตัวนี้ไม่ได้มาแต่แรก ต้องติดตั้งเพิ่มผ่านทางเมนู Plugins > Fetch Python Plugins…  ต้องอินเทอร์เน็ตด้วยจึงจะดาวน์โหลดแล้วติดตั้งได้
    3. ต้องการ Plug-in ชื่อ “MMQGIS”เหมือนกับตัวบนคือต้องติดตั้งเพิ่ม
    4. Plug-in ชื่อ “fTools” มากับ QGIS ตั้งแต่แรกแล้ว

      Plugins ที่ต้องติดตั้งเพิ่มเติม

ขั้นตอนการทำงาน

  • รวมไฟล์แปลงที่ดินเป็นไฟล์เดียว ถ้าไฟล์แปลงที่ดินเก็บแยกไฟล์กันให้นำมารวมเป็นไฟล์ CSV ไฟล์เดียวจะสะดวกมาก แต่ละวงของ polygon จะต่างกันที่ Parcel_ID

นำเข้าไฟล์ CSV

  • ใช้ปลั๊กอิน “Add Delimited Text Layer” ทำการอ่านไฟล์ CSV ของเรา ผลลัพธ์จะอยู่ในรูปจุด (Point) แต่ละจุดจะมี Parcel_ID ที่ต่างกัน และในกลุ่มจุดที่ Parcel_ID เดียวกัน QGIS จะสร้าง feather_id ให้ตามลำดับการนำเข้า

ใช้ปลั๊กอิน Add Delimited Text Layer นำไฟล์ CSV เข้ามาในรูปจุด

นำเข้ามาแล้วจะได้จุด (point) ที่มี Parcel_ID ที่แตกต่างกัน

แปลงข้อมูลจุด (Point) เป็นลายเส้น (Polygon)

ใช้ปลั๊กอิน “Points2One” ทำการรวมจุดที่มี Parcel_ID เดียวกันเป็น Polygon สืบจากข้อ 2 ปลั๊กอินนี้จะมองหา Parcel_ID เดียวกันแล้วลำดับ feather_id เริ่มลากเส้นจาก feather_id เท่ากับ 1 จนไปสิ้นสุดตัวสุดท้ายแล้วทำการปิดรูปให้

ใช้ปลั๊กอิน Point2One แปลงจากจุดเป็น Polygon

polygon ที่ได้จากปลั๊กอิน Point2One

Join Attribute

  • เตรียมไฟล์ Attribute ของเดิมอาจจะเป็น Export ทำการ Export เป็น CSV ที่สำคัญคือต้องมีคอลัมน์ใดคอลัมน์หนึ่งที่มีเลข Parcel_IDเป็นหมายเลขแปลงที่ดิน ตัวอย่างชื่อคอลัมน์คือ Par_ID ทึ่จะเชื่อมโยงไปยังรูป polygon แปลงที่ดิน

    แสดงไฟล์ attribute ที่จะนำมา Join

  • ใช้ปลั๊กอิน “MMQGIS” ทำการ Joint Attribute ด้วยเมนู Plugins > mmgis > Attributes Join from CSV File… จากไดอะล็อกเลือกไฟล์ (Input CSV File) แล้วกำหนด ID ของไฟล์ที่ CSV File Field ในที่นี้เป็น Par_IDเลือก layer ที่จะนำมา join (Join Layer) ในที่นี้เป็น Polygon_Parcels เลือก Join Layer Attribute ในที่นี้เป็น Parcel_ID เลือก Output Shape File เพื่อเก็บไฟล์ที่ Join Attribute กันแล้ว ส่วน Parcel_ID ไหนหาตัว join ไม่ได้เก็บไว้ในไฟล์ notfound.csv ซึ่งทำให้สามารถตรวจสอบได้ว่า Parcel_ID ที่ไม่สามารถหาคู่กันเจอ

    ใช้ปลั๊กอิน MMQGIS เพื่อ Join Attribute

  • หลังจาก Join แล้วลองปรับการแสดงผลดูได้ดังรูป

    QGIS แสดงผล layer ที่ได้จากการ join แล้ว

  • ลองเปิด table ของ layer ที่ join แล้วดู

    แสดง Table ที่ได้จากการ join แล้ว

การประมวลผลในเบื้องต้น

  • มาลองใช้ปลั๊กอินในการประมวลผลดู ปลั๋กอินตัวนี้ชื่อ fTools มาพร้อมกับ QGIS แต่ต้อง enable ก่อนถึงจะใช้งานได้ สำหรับ GIS แล้วการทำ processing เพื่อประมวลผลหาผลลัพธ์ที่ต้องการคือหัวใจของงาน GIS เมื่อได้ผลลัพธ์แล้วต่อไปก็คือการทำ Report และแสดง map สำหรับผลลัพธ์นั้นๆ
  • โจทย์ก็มีว่าถ้ามีแนวถนนกว้างเท่ากับ 100 เมตร (จริงแล้วคือเขตถนนหรือ right of way) ผ่านเข้าไปในแปลงที่ดิน ให้ประมวลผลว่าเข้าไปในแปลงไหนพร้อมแสดงเป็น map
  • ข้อมูล (layer) ที่จะนำมาประมวลผลสมมติว่ามี polyline (เส้นเดี่ยวไม่มีความกว้าง) ที่แทนแนวถนนตัดผ่านแปลงที่ดิ ผมนำเข้าถนนเข้าดังรูป

layer ถนน ที่เพิิ่มเข้าไป

  • ต่อไปจะขยายถนนให้ได้ขนาดกว้าง 100 เมตรด้วยการทำ Buffer ด้วยปลั๊กอืน fTools ใช้เมนู Vector > Geoprocessing Tools > Buffer ป้อนค่าใส่ไดอะล็อกดังรูป

ทำ Buffer ให้ได้ขนาดความกว้าง 100 เมตร

ความกว้างถนน 100 เมตร

  • ต่อไปจะหา polygon แปลงที่ดินที่ถูกตัดด้วยขอบเขตถนน 100 เมตรที่ตัดผ่าน ที่เมนู Vector > Geoprocessing > Intersect ใส่ค่าไปตาม dialog ดังรูปด้านล่าง

การทำ intersect ระหว่างขอบเขตถนนที่ได้จาก buffer กับ polygon ของแปลงที่ดิน

ผลลัพธ์ที่ได้

ผลจากการ intersect

  • ลองเปิดดู Attribute table ของ layer ที่ได้จากการ intersect

Attribute table ของเลเยอร์ถนนที่ตัดกับแปลงที่ดิน

สรุป

  • สำหรับผมแล้วใช้ QGIS เป็นหลักเพราะไม่ได้ใช้ฟังก์ชั่นการวิเคราะห์ที่ลึกซึ้งนัก ความเร็วของ QGIS ก็ไม่เลวเปิดรูปประมาณ 3 กิกะไบต์ก็ยังไปได้ แต่ขาดเรื่องการจัดปรินต์ Layout ที่ยังไม่ดีพอ อีกอย่างคือการ label ยังไม่เก่ง แต่ฟีเจอร์ต่างๆทางทีมผู้พัฒนาก็ปรับปรุงไปเรื่อยๆครับ
Categories: GIS, Linux, Windows ป้ายกำกับ:, , , , , , , , , ,
ติดตาม

Get every new post delivered to your Inbox.

Join 51 other followers