epsg_option.tcl 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. #=====================================================================================
  2. #
  3. # FILE: epsg_option.tcl
  4. #
  5. # DESCRIPTION: adds the utility to execute Netelers script to create a location
  6. # using the epsg codes
  7. #
  8. # NOTES: ---
  9. # AUTHOR: Antonello Andrea
  10. # EMAIL: antonell ing.unitn.it
  11. # COMPANY: Engineering, University of Trento / CUDAM
  12. # COPYRIGHT: Copyright (C) 2004 University of Trento / CUDAM, ITALY, GPL
  13. # VERSION: 1.2
  14. # CREATED: 04/01/2004
  15. # REVISION: 22/04/2006 (Michael Barton, Arizona State University)
  16. # CHANGELOG: 20/12/2006 - EPSG code search and epsgOpt::create_loc. Michael Barton.
  17. # 08/12/2006 - Fixed directory choosing dialogs. Maris Nartiss.
  18. #
  19. #=====================================================================================
  20. #
  21. #
  22. #
  23. # This library is free software; you can redistribute it and/or
  24. # modify it under the terms of the GNU Library General Public
  25. # License as published by the Free Software Foundation; either
  26. # version 2 of the License, or (at your option) any later version.
  27. #
  28. # This library is distributed in the hope that it will be useful,
  29. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  30. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  31. # Library General Public License for more details.
  32. #
  33. # You should have received a copy of the GNU Library General Public
  34. # License along with this library; if not, write to the Free
  35. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  36. # USA
  37. #
  38. #1. Redistributions of source code must retain the above copyright
  39. # notice, this list of conditions and the following disclaimer.
  40. #2. Redistributions in binary form must reproduce the above copyright
  41. # notice, this list of conditions and the following disclaimer in the
  42. # documentation and/or other materials provided with the distribution.
  43. #
  44. #############################################################################
  45. #
  46. # part regarding to the creation of a new location using proj and
  47. # the EPSG codes (routines epsgLocCom and infoEpsg)
  48. #
  49. #############################################################################
  50. namespace eval epsgOpt {
  51. variable browsedepsg ;#path to EPSG code file
  52. variable epsgLocation ;#name of new location to be created
  53. variable epsg_code ;#EPSG code number
  54. variable searchterm ;#text string searched in EPSG file
  55. variable dir
  56. variable start ;#starting index for searching EPSG text widget
  57. variable epsgtxt ;#text widget with EPSG definitions and codes
  58. variable dtnum ;#datum transformation number
  59. global env
  60. global database
  61. global refresh
  62. global mingw ;#test to see if we are running a windows version in mingw
  63. }
  64. # G_msg.tcl should be sourced first for internationalized strings.
  65. # the frame used to set EPSG parameters
  66. proc epsgOpt::epsgLocCom args {
  67. #Create main panel for setting location with EPSG code
  68. variable epsgLocation
  69. variable epsg_code
  70. variable browsedepsg
  71. variable searchterm
  72. variable dir
  73. variable start
  74. variable searchterm
  75. global database
  76. global env
  77. global mingw
  78. #initialize some variables
  79. set searchterm ""
  80. set dir "f"
  81. set start 1.0
  82. #Mac framework location for EPSG file
  83. #set env(/Library/Frameworks/PROJ.framework/Resources/proj) "/Library/Frameworks/PROJ.framework/Resources/proj"
  84. # NOTE: the epsg file is generated in GDAL for PROJ4
  85. # with gdal/pymod/epsg_tr.py
  86. if { [ catch { set epsgOpt::browsedepsg "$env(GRASS_PROJSHARE)/epsg" } ] } {
  87. DialogGen .wrnDlg [G_msg "WARNING: cant get enviromental variable"] warning \
  88. [format [G_msg "Warning: Unable to get enviromental variable GRASS_PROJSHARE. \nThis is a GRASS installation error. \nSet enviromental variable GRASS_PROJSHARE to point to directory with Proj4 EPSG file. "]] \
  89. 0 OK;
  90. return 0
  91. }
  92. set epsgOpt::epsgLocation "newLocation"
  93. set epsgOpt::epsg_code ""
  94. # creation of the parameter window
  95. set epsg_win [toplevel .optPopup]
  96. wm title $epsg_win [ G_msg "Define location using EPSG projection codes" ]
  97. # put it in the middle of the screen
  98. update idletasks
  99. set winWidth [winfo reqwidth $epsg_win]
  100. set winHeight [winfo reqheight $epsg_win]
  101. set scrnWidth [winfo screenwidth $epsg_win]
  102. set scrnHeight [winfo screenheight $epsg_win]
  103. set x [expr ($scrnWidth - $winWidth) / 2-250]
  104. set y [expr ($scrnHeight - $winHeight) / 2]
  105. wm geometry $epsg_win +$x+$y
  106. wm deiconify $epsg_win
  107. #create the form and buttons
  108. set row1 [frame $epsg_win.row1]
  109. set row2 [frame $epsg_win.row2]
  110. set row3 [frame $epsg_win.row3]
  111. set row4 [frame $epsg_win.row4]
  112. LabelEntry $row1.newloc -label [G_msg "Name of new location"] \
  113. -labeljustify right -labelanchor e -labelwidth 30 -wraplength 200 \
  114. -textvariable epsgOpt::epsgLocation -width 35 \
  115. -helptext [G_msg "Enter name for location to be created"]
  116. pack $row1.newloc -side left -expand 0 -fill x -padx 2
  117. LabelEntry $row2.epsgpath -label [G_msg "Path to the EPSG-codes file"] \
  118. -labeljustify right -labelanchor e -labelwidth 30 -wraplength 200 \
  119. -textvariable epsgOpt::browsedepsg -width 35 \
  120. -helptext [G_msg "Path to the EPSG-codes file"]
  121. #browse for epsg file
  122. Button $row2.browseepsgfile -justify center -padx 10 -bd 1 -text [G_msg "Browse..."] \
  123. -helptext [G_msg "Browse to locate EPSG file"] \
  124. -command "set epsgOpt::browsedepsg \[tk_getOpenFile -initialdir epsgOpt::browsedepsg -initialfile epsg \
  125. -parent .optPopup -title \[ G_msg \"Choose EPSG file\" \] -multiple false\]"
  126. pack $row2.epsgpath $row2.browseepsgfile -side left -expand 0 -fill x -padx 2
  127. #browse epsg codes in file
  128. LabelEntry $row3.code_entry -label [G_msg "EPSG code number of projection"] \
  129. -labeljustify right -labelanchor e -labelwidth 30 -wraplength 200 \
  130. -textvariable epsgOpt::epsg_code -width 35 \
  131. -helptext [G_msg "Enter EPSG code for selected projection"]
  132. Button $row3.codebutton -justify center -padx 10 -bd 1 -text [G_msg "Browse..."] \
  133. -helptext [G_msg "View EPSG codes and projection information."] \
  134. -command {
  135. if {[file exists $epsgOpt::browsedepsg]} {
  136. set epsgOpt::epsg_code ""
  137. epsgOpt::codesEpsg
  138. } else {
  139. DialogGen .wrnDlg [G_msg "WARNING: epsg-codes file not found"] warning \
  140. [G_msg "WARNING: The epsg-codes file was not found!"] \
  141. 0 OK
  142. return 0
  143. }
  144. }
  145. pack $row3.code_entry $row3.codebutton -side left -fill x -expand 0 -padx 2
  146. Button $row4.submit -padx 10 -text [G_msg "Define location"] \
  147. -command "epsgOpt::def_loc" -bd 1
  148. Button $row4.cancel -padx 10 -text [G_msg "Cancel"] \
  149. -command {destroy .optPopup} -bd 1
  150. pack $row4.submit -side left -fill x -expand 0
  151. pack $row4.cancel -side right -fill x -expand 0
  152. pack $row1 $row2 $row3 $row4 -side top -fill both -expand 1 -padx 3 -pady 3
  153. return 1
  154. }
  155. proc epsgOpt::def_loc { } {
  156. # define new location using EPSG code
  157. global refresh
  158. global database
  159. variable epsg_code
  160. variable epsgLocation
  161. if {$epsg_code==""} {return}
  162. if {![string is integer $epsg_code]} {
  163. DialogGen .wrnDlg [G_msg "Invalid EPSG Code!"] error \
  164. [format [G_msg "ERROR: Invalid EPSG code %s: should be an integer."] \
  165. $epsg_code] \
  166. 0 OK
  167. set epsg_code ""
  168. return
  169. }
  170. set epsgLocation [ string trim $epsgLocation ]
  171. if {[file exists ${database}/$epsgLocation]} {
  172. DialogGen .wrnDlg [G_msg "Location Exists!"] warning \
  173. [format [G_msg "WARNING: Location '%s' already exists: please try another name."] \
  174. $epsgLocation] 0 OK
  175. set epsgLocation ""
  176. return
  177. }
  178. if {[file exists $epsgLocation ]==0} {
  179. destroy .optPopup
  180. epsgOpt::create_loc
  181. set refresh 1
  182. return 1
  183. }
  184. }
  185. proc epsgOpt::create_loc { } {
  186. # Create a new location using g.proj
  187. # original bash code by M. Neteler
  188. # create new location from EPSG code
  189. epsgOpt::runproj
  190. return
  191. }
  192. proc epsgOpt::runproj {} {
  193. # first run g.proj to see if there are more than the default
  194. # parameters to choose from
  195. global location
  196. global mapset
  197. variable epsgLocation
  198. variable epsg_code
  199. set dtrans ""
  200. catch {set dtrans [exec g.proj --q -c location=$epsgLocation epsg=$epsg_code datumtrans=-1]} errMsg
  201. if {[lindex $::errorCode 0] eq "CHILDSTATUS"} {
  202. DialogGen .wrnDlg [G_msg "Error creating location!"] error \
  203. [format [G_msg "g.proj returned the following message:\n%s"] $errMsg] \
  204. 0 OK
  205. } elseif {$dtrans eq ""} {
  206. # if nothing written to stdout, there was no choice of
  207. # datum parameters and we need not do anything more
  208. if {$errMsg ne ""} {
  209. DialogGen .wrnDlg [G_msg "Informational output from g.proj"] info \
  210. [format [G_msg "g.proj returned the following informational message:\n%s"] $errMsg] \
  211. 0 OK
  212. }
  213. set location $epsgLocation
  214. set mapset "PERMANENT"
  215. } else {
  216. # user selects datum transform
  217. #create dialog that lists datum transforms, asks user to enter a number and press OK
  218. set paramset [epsgOpt::sel_dtrans $dtrans]
  219. # operation canceled
  220. if {$paramset == -9} {return}
  221. # create new location from epsg code
  222. catch {exec g.proj --q -c epsg=$epsg_code location=$epsgLocation datumtrans=$paramset} errMsg
  223. #catch any other errors
  224. if {[lindex $::errorCode 0] eq "CHILDSTATUS"} {
  225. DialogGen .wrnDlg [G_msg "Error creating location!"] warning \
  226. [format [G_msg "g.proj returned the following message:\n%s"] $errMsg] \
  227. 0 OK
  228. } else {
  229. if {$errMsg ne ""} {
  230. DialogGen .wrnDlg [G_msg "Informational output from g.proj"] info \
  231. [format [G_msg "g.proj returned the following informational message:\n%s"] $errMsg] \
  232. 0 OK
  233. }
  234. set location $epsgLocation
  235. set mapset "PERMANENT"
  236. }
  237. }
  238. }
  239. proc epsgOpt::sel_dtrans {dtrans} {
  240. # Dialog for selecting optional datum transform parameters
  241. # Argument is stdout from g.proj
  242. # default is not to specify datum transformation
  243. set epsgOpt::dtnum 0
  244. # Create a popup search dialog
  245. toplevel .dtrans_sel
  246. wm title .dtrans_sel [G_msg "Select datum transformation parameters:"]
  247. set row1 [frame .dtrans_sel.frame1]
  248. set row3 [frame .dtrans_sel.frame3]
  249. radiobutton $row1.0 -value 0 -variable epsgOpt::dtnum -wraplength 640 -justify left -text [G_msg "Continue without specifying parameters - if used when creating a location, other GRASS modules will use the \"default\" (likely non-optimum) parameters for this datum if necessary in the future."]
  250. pack $row1.0 -anchor w
  251. set dtrans [split $dtrans "\n"]
  252. for {set i 0} { $i < [llength $dtrans] } {incr i} {
  253. set thisnum [lindex $dtrans $i]
  254. if {$thisnum == "---"} {
  255. continue
  256. }
  257. set thisdesc $thisnum.
  258. while { [incr i] < [llength $dtrans] && [lindex $dtrans $i] != "---"} {
  259. set thisdesc ${thisdesc}\n[lindex $dtrans $i]
  260. }
  261. radiobutton $row1.$thisnum -variable epsgOpt::dtnum -value $thisnum -wraplength 640 -justify left -text $thisdesc
  262. pack $row1.$thisnum -anchor w
  263. }
  264. pack $row1
  265. Button $row3.ok -text [G_msg "OK"] -padx 10 -bd 1 \
  266. -command "destroy .dtrans_sel"
  267. pack $row3.ok -side left -padx 3
  268. button $row3.cancel -text [G_msg "Cancel"] -padx 10 -bd 1 \
  269. -command "set epsgOpt::dtnum -9; destroy .dtrans_sel"
  270. pack $row3.cancel -side left -padx 3
  271. pack $row3 -anchor center -pady 3
  272. tkwait window .dtrans_sel
  273. return $epsgOpt::dtnum
  274. }
  275. proc epsgOpt::codesEpsg args {
  276. # text widget for listing EPSG codes
  277. variable browsedepsg
  278. variable epsgtxt
  279. variable epsg_code
  280. toplevel .infoPopup
  281. wm title .infoPopup {EPSG-codes}
  282. update idletasks
  283. wm geometry .infoPopup +250+10
  284. wm deiconify .infoPopup
  285. set epsgfr [frame .infoPopup.fr]
  286. set titlefr [frame $epsgfr.top -relief groove -bd 2 -bg white]
  287. label $titlefr.title1 -text [G_msg "EPSG CODES (from file: $epsgOpt::browsedepsg)"] \
  288. -fg mediumblue -bg white
  289. label $titlefr.title2 -bg white \
  290. -text [G_msg "You can select EPSG code (in <braces>) and copy it for later use." ]
  291. pack $titlefr.title1 $titlefr.title2 -side top
  292. pack $titlefr -side top -fill x -expand 0
  293. frame $epsgfr.mid
  294. set epsgtxt [text $epsgfr.mid.text \
  295. -wrap word -exportselection 1 \
  296. -relief flat -selectbackground lightgreen \
  297. -yscrollcommand "$epsgfr.mid.vscroll set"]
  298. scrollbar $epsgfr.mid.vscroll \
  299. -relief sunken \
  300. -command "$epsgtxt yview"
  301. # tag configuration
  302. $epsgtxt tag configure underline -underline 1
  303. $epsgtxt tag configure title -relief sunken -borderwidth 2 \
  304. -background white -foreground "mediumblue" -justify center
  305. #$epsgtxt tag configure lefttitle -relief flat -background beige
  306. # Do not set background color for subtitle. It will override selection background color!
  307. $epsgtxt tag configure subtitle -relief flat
  308. # open the file
  309. set f [open $epsgOpt::browsedepsg "r"]
  310. set found ""
  311. while { [eof $f] == 0 } {
  312. set line [gets $f]
  313. set firstdash [string first # $line]
  314. set firstminor [string first < $line]
  315. if {$firstdash == "0"} {
  316. $epsgtxt insert end "\n$line\n" lefttitle
  317. set found "yes"
  318. }
  319. if {$firstminor == "0"} {
  320. $epsgtxt insert end "\n$line\n\n" subtitle
  321. }
  322. if {$firstminor != "0" && $firstdash != "0" && $found != "yes"} {
  323. $epsgtxt insert end [format "\n\n%s\n\n" [G_msg "GUESS THAT IS NOT THE EPSG FILE"]] title;
  324. break;
  325. }
  326. }
  327. set controls [frame .infoPopup.buttons]
  328. button $controls.search -text [G_msg "Search"] -padx 10 -bd 1 -command "epsgOpt::search_epsg $epsgtxt"
  329. Button $controls.grab -text [G_msg "Grab code"] -padx 10 -bd 1 \
  330. -command "epsgOpt::grabcode"
  331. pack $controls.search $controls.grab -side left -fill x -expand 0
  332. button $controls.close -padx 10 -text [G_msg "Close"] \
  333. -command {destroy .infoPopup} -bd 1
  334. pack $controls.close -side right -fill x -expand 0
  335. pack $controls -side bottom -fill x -expand 0 -padx 5 -pady 4
  336. pack $epsgtxt -side left -fill both -expand 1
  337. pack $epsgfr.mid.vscroll -side right -fill both -expand 0
  338. pack $epsgfr.mid -side top -fill both -expand 1
  339. pack $epsgfr -fill both -expand 1
  340. }
  341. proc epsgOpt::search_epsg { epsgtxt } {
  342. # Widget for searching EPSG file. Selects EPSG code associated with found search term.
  343. # Argument is text widget
  344. variable searchterm
  345. variable dir
  346. variable start
  347. # Create a popup search dialog
  348. toplevel .search_epsg
  349. wm title .search_epsg [G_msg "Search"]
  350. set row1 [frame .search_epsg.frame1]
  351. set row2 [frame .search_epsg.frame2]
  352. set row3 [frame .search_epsg.frame3]
  353. set row4 [frame .search_epsg.frame4]
  354. Label $row1.label -text [G_msg "Search text: "] \
  355. -helptext [G_msg "Search for entered text in EPSG file"]
  356. set searchentry [entry $row1.enter -relief sunken -textvariable epsgOpt::searchterm]
  357. pack $row1.label $row1.enter -side left -fill x -expand 0 -anchor w
  358. pack $row1 -side top -padx 3 -pady 4 -expand 1 -fill both
  359. radiobutton $row2.forward -text [G_msg "forward search"] -variable epsgOpt::dir -value "f"
  360. radiobutton $row2.backward -text [G_msg "backward search"] -variable epsgOpt::dir -value "b"
  361. $row2.forward select
  362. pack $row2.forward $row2.backward -side left \
  363. -anchor w -fill x -expand 0
  364. pack $row2 -side top -padx 3 -expand 1 -fill both
  365. Button $row4.search -text [G_msg "Search"] -padx 10 -bd 1 \
  366. -command "epsgOpt::textsearch"
  367. pack $row4.search -side left -fill x -expand 0
  368. button $row4.cancel -text [G_msg "Close"] -padx 10 -bd 1 -command "destroy .search_epsg"
  369. pack $row4.cancel -side right -fill x -expand 0
  370. pack $row4 -side top -pady 3 -expand 1 -fill both
  371. }
  372. proc epsgOpt::textsearch { } {
  373. # Search for text in EPSG text widget and return the EPSG code
  374. variable epsgtxt
  375. variable searchterm
  376. variable dir
  377. variable start
  378. variable epsg_code
  379. set strlength 0
  380. catch {$epsgtxt tag remove sel [lindex [$epsgtxt tag ranges sel] 0] [lindex [$epsgtxt tag ranges sel] 1]}
  381. if {$dir == "f"} {
  382. catch {set start [$epsgtxt search -forwards -nocase -count strlength -- $epsgOpt::searchterm $start]}
  383. catch {set newstart [$epsgtxt index "$start +[expr 1+$strlength] c"]}
  384. } else {
  385. catch {set start [$epsgtxt search -backwards -nocase -count strlength -- $epsgOpt::searchterm $start]}
  386. catch {set newstart [$epsgtxt index "$start -1 c"]}
  387. }
  388. update idletasks
  389. if {$start != 0 && $strlength !=0} {
  390. $epsgtxt tag add sel "$start"
  391. $epsgtxt see $start
  392. catch {set start $newstart}
  393. set currpos [$epsgtxt index sel.first]
  394. if { [$epsgtxt get "$currpos linestart"] == "<" } {
  395. set codestart [$epsgtxt index "$currpos linestart +1c"]
  396. set codeend [$epsgtxt index [$epsgtxt search -forwards -- {>} $codestart]]
  397. } else {
  398. set codestart [$epsgtxt index "[$epsgtxt search -forwards -- {<} $currpos] +1c"]
  399. set codeend [$epsgtxt index [$epsgtxt search -forwards -- {>} $codestart]]
  400. }
  401. $epsgtxt tag remove sel [$epsgtxt index sel.first]
  402. $epsgtxt tag add sel "$codestart" "$codeend"
  403. set epsg_code [$epsgtxt get $codestart $codeend]
  404. } else {
  405. set start 1.0
  406. return
  407. }
  408. }
  409. proc epsgOpt::grabcode { } {
  410. # put the code in the EPSG code entry and activate the define location button
  411. # Will grab the code of the entry where the insertion cursor is located if nothing found search
  412. variable epsgtxt
  413. variable searchterm
  414. variable dir
  415. variable start
  416. variable epsg_code
  417. if { $epsg_code == "" } {
  418. set currpos [$epsgtxt index insert]
  419. if { [$epsgtxt get "$currpos linestart"] == "<" } {
  420. set codestart [$epsgtxt index "$currpos linestart +1c"]
  421. set codeend [$epsgtxt index [$epsgtxt search -forwards -- {>} $codestart]]
  422. } else {
  423. set codestart [$epsgtxt index "[$epsgtxt search -forwards -- {<} $currpos] +1c"]
  424. set codeend [$epsgtxt index [$epsgtxt search -forwards -- {>} $codestart]]
  425. }
  426. $epsgtxt tag remove sel [$epsgtxt index insert]
  427. $epsgtxt tag add sel "$codestart" "$codeend"
  428. set epsg_code [$epsgtxt get $codestart $codeend]
  429. }
  430. destroy .infoPopup
  431. }