1 |
jan |
2389 |
# Copyright (C) 2003, 2004 by Intevation GmbH |
2 |
jan |
1721 |
# Authors: |
3 |
jan |
2389 |
# Jan-Oliver Wagner <[email protected]> (2003, 2004) |
4 |
jan |
1721 |
# |
5 |
|
|
# This program is free software under the GPL (>=v2) |
6 |
|
|
# Read the file COPYING coming with Thuban for details. |
7 |
|
|
|
8 |
|
|
""" |
9 |
|
|
Extend thuban with a gns2shp converter. |
10 |
|
|
|
11 |
|
|
This module also works without Thuban on the command line |
12 |
|
|
if the shapelib and dbflib python wrappers can be found via the |
13 |
|
|
PYTHONPATH (e.g. via including directory 'Lib' of thuban directory). |
14 |
|
|
|
15 |
|
|
The GUI should eventually be extended to allow pre-selection |
16 |
|
|
of the points to import in order to reduce immense quantities |
17 |
|
|
of some country files. |
18 |
|
|
""" |
19 |
|
|
|
20 |
|
|
__version__ = '$Revision$' |
21 |
jan |
2203 |
# $Source$ |
22 |
|
|
# $Id$ |
23 |
jan |
1721 |
|
24 |
|
|
import os, sys |
25 |
|
|
|
26 |
jan |
2356 |
# only import GUI and register when not called as command line tool |
27 |
jan |
1721 |
if __name__ != '__main__': |
28 |
dpinte |
2721 |
import wx |
29 |
jan |
1721 |
|
30 |
|
|
from Thuban.UI.command import registry, Command |
31 |
jan |
2203 |
from Thuban.UI.mainwindow import main_menu |
32 |
jan |
1721 |
from Thuban import _ |
33 |
|
|
from Thuban.Model.layer import Layer |
34 |
|
|
|
35 |
|
|
import shapelib |
36 |
|
|
import dbflib |
37 |
|
|
|
38 |
|
|
def gns2shp(src_fname, dest_fname): |
39 |
|
|
"""Convert a file from gns textformat into a Shapefile. |
40 |
|
|
|
41 |
|
|
The GNS text format is described on |
42 |
jan |
2486 |
http://www.nima.mil/gns/html/gis.html |
43 |
jan |
1721 |
|
44 |
|
|
src_fname -- Filename of the GNS standard textfile (including suffix '.txt) |
45 |
|
|
dest_fname -- Filename where to write the Shapefile components (name |
46 |
|
|
without suffix). After successful completion there |
47 |
|
|
will be files "dest_fname".shp, "dest_fname".shx and |
48 |
|
|
"dest_fname.dbf". |
49 |
|
|
|
50 |
|
|
Return: Number of sucessfully converted entries |
51 |
|
|
""" |
52 |
|
|
gns_filename = src_fname |
53 |
|
|
shp_filename = dest_fname + '.shp' |
54 |
|
|
dbf_filename = dest_fname + '.dbf' |
55 |
|
|
|
56 |
|
|
gns = open(gns_filename, 'r').readlines() |
57 |
|
|
|
58 |
|
|
shp = shapelib.create(shp_filename, shapelib.SHPT_POINT) |
59 |
|
|
dbf = dbflib.create(dbf_filename) |
60 |
|
|
dbf.add_field('RC', dbflib.FTInteger, 1, 0) |
61 |
|
|
dbf.add_field('UFI', dbflib.FTInteger, 10, 0) |
62 |
|
|
dbf.add_field('UNI', dbflib.FTInteger, 10, 0) |
63 |
|
|
dbf.add_field('UTM', dbflib.FTString, 4, 0) |
64 |
|
|
dbf.add_field('JOG', dbflib.FTString, 7, 0) |
65 |
|
|
dbf.add_field('FC', dbflib.FTString, 1, 0) |
66 |
|
|
dbf.add_field('DSG', dbflib.FTString, 5, 0) |
67 |
jan |
2486 |
dbf.add_field('PC', dbflib.FTInteger, 1, 0) |
68 |
jan |
1721 |
dbf.add_field('CC1', dbflib.FTString, 2, 0) |
69 |
|
|
dbf.add_field('ADM1', dbflib.FTString, 2, 0) |
70 |
jan |
2486 |
dbf.add_field('ADM2', dbflib.FTString, 200, 0) |
71 |
jan |
1721 |
dbf.add_field('DIM', dbflib.FTInteger, 10, 0) |
72 |
|
|
dbf.add_field('CC2', dbflib.FTString, 2, 0) |
73 |
|
|
dbf.add_field('NT', dbflib.FTString, 1, 0) |
74 |
|
|
dbf.add_field('LC', dbflib.FTString, 2, 0) |
75 |
jan |
2486 |
dbf.add_field('SHORT_FORM', dbflib.FTString, 128, 0) |
76 |
|
|
dbf.add_field('GENERIC', dbflib.FTString, 128, 0) |
77 |
|
|
dbf.add_field('SORT_NAME', dbflib.FTString, 200, 0) |
78 |
|
|
dbf.add_field('FULL_NAME', dbflib.FTString, 200, 0) |
79 |
|
|
dbf.add_field('FULL_ND', dbflib.FTString, 200, 0) # FULL_NAME_ND |
80 |
jan |
2216 |
dbf.add_field('MODIFY_DATE', dbflib.FTString, 11, 0) |
81 |
jan |
1721 |
del dbf |
82 |
|
|
dbf = dbflib.open(dbf_filename, 'r+b') |
83 |
|
|
|
84 |
|
|
gns.pop(0) # drop the header line |
85 |
|
|
|
86 |
|
|
i = 0 |
87 |
|
|
for line in gns: |
88 |
|
|
if line[0] == '#': continue |
89 |
|
|
RC, UFI, UNI, DD_LAT, DD_LONG, DMS_LAT, DMS_LONG, UTM, \ |
90 |
|
|
JOG, FC, DSG, PC, CC1, ADM1, ADM2, DIM, CC2, NT, LC, \ |
91 |
|
|
SHORT_FORM, GENERIC, SORT_NAME, FULL_NAME, FULL_NAME_ND, \ |
92 |
|
|
MODIFY_DATE = line.split('\t') |
93 |
|
|
RC = int(RC) |
94 |
|
|
UFI = int(UFI) |
95 |
|
|
UNI = int(UNI) |
96 |
|
|
DD_LAT = float(DD_LAT) |
97 |
|
|
DD_LONG = float(DD_LONG) |
98 |
|
|
try: PC = int(PC) |
99 |
|
|
except: PC = None |
100 |
|
|
try: DIM = int(DIM) |
101 |
|
|
except: DIM = None |
102 |
jan |
2486 |
MODIFY_DATE = MODIFY_DATE[0:10] # kill trailing "\n" or "\r\n" |
103 |
jan |
1721 |
obj = shapelib.SHPObject(shapelib.SHPT_POINT, i, [[(DD_LONG, DD_LAT)]]) |
104 |
|
|
shp.write_object(-1, obj) |
105 |
|
|
dbf.write_record(i, { 'RC': RC, 'UFI': UFI, 'UNI': UNI, 'UTM': UTM, |
106 |
|
|
'JOG': JOG, 'FC': FC, 'DSG': DSG, 'PC': PC, |
107 |
|
|
'CC1': CC1, 'ADM1': ADM1, 'ADM2': ADM2, |
108 |
|
|
'DIM': DIM, 'CC2': CC2, 'NT': NT, 'LC': LC, |
109 |
|
|
'SHORT_FORM': SHORT_FORM, 'GENERIC': GENERIC, |
110 |
|
|
'SORT_NAME': SORT_NAME, 'FULL_NAME': FULL_NAME, |
111 |
|
|
'FULL_ND': FULL_NAME_ND, |
112 |
|
|
'MODIFY_DAT': MODIFY_DATE}) |
113 |
|
|
i += 1 |
114 |
|
|
|
115 |
|
|
del shp |
116 |
|
|
del dbf |
117 |
|
|
|
118 |
|
|
return i |
119 |
|
|
|
120 |
|
|
def gns2shp_dialog(context): |
121 |
|
|
"""Request filename from user, run conversion and add |
122 |
|
|
resulting shapefile to the current map. |
123 |
|
|
|
124 |
|
|
context -- The Thuban context. |
125 |
|
|
""" |
126 |
dpinte |
2721 |
dlg = wx.FileDialog(context.mainwindow, |
127 |
jan |
1721 |
_('Select GNS file'), '.', '', |
128 |
|
|
_('Generate Files (*.txt)|*.txt|') + |
129 |
|
|
_('All Files (*.*)|*.*'), |
130 |
dpinte |
2721 |
wx.OPEN|wx.OVERWRITE_PROMPT) |
131 |
|
|
if dlg.ShowModal() == wx.ID_OK: |
132 |
jan |
1721 |
gns_filename = dlg.GetPath() |
133 |
|
|
dlg.Destroy() |
134 |
|
|
else: |
135 |
|
|
return |
136 |
|
|
|
137 |
|
|
no = gns2shp(gns_filename, gns_filename[:-4]) |
138 |
|
|
if no <= 0: |
139 |
|
|
context.mainwindow.RunMessageBox(_('gns2shp'), _('Conversion failed')) |
140 |
|
|
return |
141 |
|
|
else: |
142 |
|
|
context.mainwindow.RunMessageBox(_('gns2shp %s') % __version__, |
143 |
|
|
_('%d locations converted' % no)) |
144 |
|
|
|
145 |
|
|
# Now load the newly created shapefile |
146 |
|
|
filename = gns_filename[:-4] + '.shp' |
147 |
|
|
title = os.path.splitext(os.path.basename(filename))[0] |
148 |
|
|
map = context.mainwindow.canvas.Map() |
149 |
|
|
has_layers = map.HasLayers() |
150 |
|
|
try: |
151 |
|
|
store = context.session.OpenShapefile(filename) |
152 |
|
|
except IOError: |
153 |
|
|
# the layer couldn't be opened |
154 |
|
|
context.mainwindow.RunMessageBox(_('Add GNS Layer'), |
155 |
|
|
_("Can't open the file '%s'.") % filename) |
156 |
|
|
else: |
157 |
|
|
layer = Layer(title, store) |
158 |
|
|
map.AddLayer(layer) |
159 |
|
|
if not has_layers: |
160 |
|
|
# if we're adding a layer to an empty map, fit the |
161 |
|
|
# new map to the window |
162 |
|
|
context.mainwindow.canvas.FitMapToWindow() |
163 |
|
|
|
164 |
|
|
if __name__ == '__main__': # gns2shp executed as a command line tool |
165 |
|
|
print 'gns2shp.py %s' % __version__ |
166 |
|
|
if len(sys.argv) == 3: |
167 |
|
|
no = gns2shp(sys.argv[1], sys.argv[2][:-4]) |
168 |
|
|
print '%d locations converted' % no |
169 |
|
|
sys.exit(0) |
170 |
|
|
else: |
171 |
|
|
print 'usage: gns2shp.py GNS-file Shapefile' |
172 |
|
|
sys.exit(1) |
173 |
|
|
|
174 |
|
|
|
175 |
|
|
# gns2shp executed as an extension to Thuban |
176 |
|
|
|
177 |
|
|
# register the new command |
178 |
|
|
registry.Add(Command('gns2shp', _('gns2shp...'), gns2shp_dialog, |
179 |
|
|
helptext = _('Convert GNS-file into a shapefile'))) |
180 |
|
|
|
181 |
|
|
# find the extensions menu (create it anew if not found) |
182 |
jan |
2203 |
extensions_menu = main_menu.FindOrInsertMenu('extensions', _('E&xtensions')) |
183 |
jan |
1721 |
|
184 |
|
|
# finally add the new entry to the extensions menu |
185 |
|
|
extensions_menu.InsertItem('gns2shp') |