Friday, August 23, 2013

Insert coordinates from text file into Smallworld database

I recently received a query from a reader asking if I could show him how to insert coordinates from a text file into Smallworld database.  I have put together a gist that shows how to do this.  I started off by using a LWT approach but then remembered that the recommended approach is to use the record transaction APIs.  So the gist includes both styles of database writing.


_package sw
$
_global coordinate_importer <<
_proc@coordinate_importer(filename)
## coordinate_importer(STRING filename) : unset
##
## parses FILENAME and inserts records into database
## assumes the format...
## x|y|description
## with the first line being the header line
## and x=Longitude (decimal degrees)
## and y=Latitude (decimal degrees)
# the x/y values we get from the coordinate file are in
# lat/long so we need to set the !current_coordinate_system!
# value here so that those lat/long values automagikally get
# transformed into whatever the current database coordinate
# system is.
_dynamic !current_coordinate_system! << coordinate_system.new_proj_long_lat(:wgs84,:degree)
_constant DELIMITER << "|"
_local str , line , values , x , y , description
_local v << gis_program_manager.cached_dataset(:gis)
# set the !current_dsview! and !current_world!
_dynamic !current_dsview! << v
_dynamic !current_world! << v.world
_local coll << v.collections[:town]
_local ok? << _false
v.start_lwt()
_protect
str << external_text_input_stream.new(filename)
str.get_line() # skip the header line
_loop
_if (line << str.get_line()) _is _unset
_then
_leave
_endif
values << line.split_by(DELIMITER)
_local ndr << coll.new_detached_record()
ndr.name << values[3] # description
ndr.class << "City"
_local rec << coll.insert(ndr)
_local coord << coordinate(values[1].as_number(),values[2].as_number())
rec.make_geometry(:location,coord)
rec.make_geometry(:annotation,coord,rec.name)
_endloop
ok? << _true
_protection
v.end_lwt(ok?)
_if str _isnt _unset
_then
str.close()
_endif
_endprotect
_endproc
$
# MagikSF> coordinate_importer("C:\Users\Alfred\Desktop\coordinates.txt")
# $
_package sw
$
_global coordinate_importer <<
_proc@coordinate_importer(filename)
## coordinate_importer(STRING filename) : unset
##
## parses FILENAME and inserts records into database
## assumes the format...
## x|y|description
## with the first line being the header line
## and x=Longitude (decimal degrees)
## and y=Latitude (decimal degrees)
# the x/y values we get from the coordinate file are in
# lat/long so we need to set the !current_coordinate_system!
# value here so that those lat/long values automagikally get
# transformed into whatever the current database coordinate
# system is.
_dynamic !current_coordinate_system! << coordinate_system.new_proj_long_lat(:wgs84,:degree)
_constant DELIMITER << "|"
_local str , line , values , x , y , description
_local v << gis_program_manager.cached_dataset(:gis)
_local coll << v.collections[:town]
_protect
str << external_text_input_stream.new(filename)
str.get_line() # skip the header line
_loop
_if (line << str.get_line()) _is _unset
_then
_leave
_endif
values << line.split_by(DELIMITER)
_local name << values[3] # description
_local coord << coordinate(values[1].as_number(),values[2].as_number())
_local location << pseudo_point.new(coord)
_local annotation << pseudo_text.new(coord,name)
_local properties << property_list.new_with(:name,name,
:class,"City",
:location,location,
:annotation,annotation)
_local t << record_transaction.new_insert(coll,
properties,
"Insert Town")
t.run()
_endloop
_protection
_if str _isnt _unset
_then
str.close()
_endif
_endprotect
_endproc
$
# MagikSF> coordinate_importer("C:\Users\Alfred\Desktop\coordinates.txt")
# $
x|y|description
-0.1271|51.51|London, UK
-2.249|53.48|Manchester, UK
-1.260|51.76|Oxford, UK
-0.1341|50.83|Brighton, UK
-6.248|53.35|Dublin, Ireland
view raw coordinates.txt hosted with ❤ by GitHub