Class: GeoRuby::Shp4r::ShpFile

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/geo_ruby/shp4r/shp.rb

Overview

An interface to an ESRI shapefile (actually 3 files : shp, shx and dbf). Currently supports only the reading of geometries.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file) ⇒ ShpFile

Opens a SHP file. Both “abc.shp” and “abc” are accepted. The files “abc.shp”, “abc.shx” and “abc.dbf” must be present


34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/geo_ruby/shp4r/shp.rb', line 34

def initialize(file)
  # strip the shp out of the file if present
  @file_root = file.gsub(/.shp$/i, '')  # check existence of shp, dbf and shx files

  unless File.exist?(@file_root + '.shp') &&
         File.exist?(@file_root + '.dbf') &&
         File.exist?(@file_root + '.shx')
    fail MalformedShpException.new("Missing one of shp, dbf or shx for: #{@file}")
  end

  @dbf = Dbf::Reader.open(@file_root + '.dbf')
  @shx = File.open(@file_root + '.shx', 'rb')
  @shp = File.open(@file_root + '.shp', 'rb')
  read_index
end

Instance Attribute Details

#file_lengthObject (readonly)

Returns the value of attribute file_length


27
28
29
# File 'lib/geo_ruby/shp4r/shp.rb', line 27

def file_length
  @file_length
end

#file_rootObject (readonly)

Returns the value of attribute file_root


27
28
29
# File 'lib/geo_ruby/shp4r/shp.rb', line 27

def file_root
  @file_root
end

#mmaxObject (readonly)

Returns the value of attribute mmax


27
28
29
# File 'lib/geo_ruby/shp4r/shp.rb', line 27

def mmax
  @mmax
end

#mminObject (readonly)

Returns the value of attribute mmin


27
28
29
# File 'lib/geo_ruby/shp4r/shp.rb', line 27

def mmin
  @mmin
end

#record_countObject (readonly)

Returns the value of attribute record_count


27
28
29
# File 'lib/geo_ruby/shp4r/shp.rb', line 27

def record_count
  @record_count
end

#shp_typeObject (readonly)

Returns the value of attribute shp_type


27
28
29
# File 'lib/geo_ruby/shp4r/shp.rb', line 27

def shp_type
  @shp_type
end

#xmaxObject (readonly)

Returns the value of attribute xmax


27
28
29
# File 'lib/geo_ruby/shp4r/shp.rb', line 27

def xmax
  @xmax
end

#xminObject (readonly)

Returns the value of attribute xmin


27
28
29
# File 'lib/geo_ruby/shp4r/shp.rb', line 27

def xmin
  @xmin
end

#ymaxObject (readonly)

Returns the value of attribute ymax


27
28
29
# File 'lib/geo_ruby/shp4r/shp.rb', line 27

def ymax
  @ymax
end

#yminObject (readonly)

Returns the value of attribute ymin


27
28
29
# File 'lib/geo_ruby/shp4r/shp.rb', line 27

def ymin
  @ymin
end

#zmaxObject (readonly)

Returns the value of attribute zmax


27
28
29
# File 'lib/geo_ruby/shp4r/shp.rb', line 27

def zmax
  @zmax
end

#zminObject (readonly)

Returns the value of attribute zmin


27
28
29
# File 'lib/geo_ruby/shp4r/shp.rb', line 27

def zmin
  @zmin
end

Class Method Details

.create(file, shp_type, fields, &proc) ⇒ Object

create a new Shapefile of the specified shp type (see ShpType) and with the attribute specified in the fields array (see Dbf::Field). If a block is given, the ShpFile object newly created is passed to it.


72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/geo_ruby/shp4r/shp.rb', line 72

def self.create(file, shp_type, fields, &proc)
  file_root = file.gsub(/.shp$/i, '')
  shx_io = File.open(file_root + '.shx', 'wb')
  shp_io = File.open(file_root + '.shp', 'wb')
  dbf_io = File.open(file_root + '.dbf', 'wb')
  str = [9994, 0, 0, 0, 0, 0, 50, 1000, shp_type, 0, 0, 0, 0, 0, 0, 0, 0].pack('N7V2E8')
  shp_io << str
  shx_io << str
  rec_length = 1 + fields.reduce(0) { |s, f| s + f.length } #+1 for the prefixed space (active record marker)
  dbf_io << [3, 107, 7, 7, 0, 33 + 32 * fields.length, rec_length].pack('c4Vv2x20') # 32 bytes for first part of header
  fields.each do |field|
    dbf_io << [field.name, field.type, field.length, field.decimal].pack('a10xax4CCx14')
  end
  dbf_io << ['0d'].pack('H2')

  shx_io.close
  shp_io.close
  dbf_io.close

  open(file, &proc)
end

.open(file) ⇒ Object

opens a SHP “file”. If a block is given, the ShpFile object is yielded to it and is closed upon return. Else a call to open is equivalent to ShpFile.new(...).


59
60
61
62
63
64
65
66
67
# File 'lib/geo_ruby/shp4r/shp.rb', line 59

def self.open(file)
  shpfile = ShpFile.new(file)
  if block_given?
    yield shpfile
    shpfile.close
  else
    shpfile
  end
end

Instance Method Details

#[](i) ⇒ Object

Returns record i


136
137
138
# File 'lib/geo_ruby/shp4r/shp.rb', line 136

def [](i)
  get_record(i)
end

#closeObject

Closes a shapefile


95
96
97
98
99
# File 'lib/geo_ruby/shp4r/shp.rb', line 95

def close
  @dbf.close
  @shx.close
  @shp.close
end

#eachObject Also known as: each_record

Goes through each record


128
129
130
131
132
# File 'lib/geo_ruby/shp4r/shp.rb', line 128

def each
  (0...record_count).each do |i|
    yield get_record(i)
  end
end

#empty?Boolean

Tests if the file has no record

Returns:

  • (Boolean)

123
124
125
# File 'lib/geo_ruby/shp4r/shp.rb', line 123

def empty?
  record_count == 0
end

#fieldsObject

return the description of data fields


118
119
120
# File 'lib/geo_ruby/shp4r/shp.rb', line 118

def fields
  @dbf.fields
end

#recordsObject

Returns all the records


141
142
143
144
145
# File 'lib/geo_ruby/shp4r/shp.rb', line 141

def records
  Array.new(record_count) do |i|
    get_record(i)
  end
end

#reload!Object

force the reopening of the files compsing the shp. Close before calling this.


52
53
54
# File 'lib/geo_ruby/shp4r/shp.rb', line 52

def reload!
  initialize(@file_root)
end

#transactionObject

starts a transaction, to buffer physical file operations on the shapefile components.


103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/geo_ruby/shp4r/shp.rb', line 103

def transaction
  trs = ShpTransaction.new(self, @dbf)
  if block_given?
    answer = yield trs
    if answer == :rollback
      trs.rollback
    elsif !trs.rollbacked
      trs.commit
    end
  else
    trs
  end
end