Class: Shapefile

Inherits:
Object
  • Object
show all
Defined in:
lib/shapefile.rb

Defined Under Namespace

Classes: Shape

Constant Summary collapse

HEADER_BYTES =
100

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(shp, shx = nil, dbf = nil) ⇒ Shapefile

Returns a new instance of Shapefile.



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/shapefile.rb', line 8

def initialize(shp, shx = nil, dbf = nil)
  # Open files.
  @shp = File.open(shp)
  @dbf = DBF::Table.new(dbf) if dbf
   # Read and verify the header.
  hdr = @shp.read(HEADER_BYTES).unpack("NNNNNNNVVEEEEEEEE")
  unless hdr[0] == 9994
    raise RuntimeError, "#{shp} isn't a shapefile"
  end
  unless hdr[7] == 1000
    raise RuntimeError, "#{shp} isn't a supported version of shapefile"
  end
  unless @shape_class = Shape.class_for_code(hdr[8])
    raise RuntimeError, "#{shp} is composed of an unsupported shape type"
  end
end

Instance Attribute Details

#shape_classObject (readonly)

Returns the value of attribute shape_class.



6
7
8
# File 'lib/shapefile.rb', line 6

def shape_class
  @shape_class
end

Class Method Details

.open(shp, shx = nil, dbf = nil) ⇒ Object



25
26
27
# File 'lib/shapefile.rb', line 25

def self.open(shp, shx = nil, dbf = nil)
  new(shp, shx, dbf)
end

Instance Method Details

#attribute_namesObject



57
58
59
60
61
62
63
# File 'lib/shapefile.rb', line 57

def attribute_names
  if @dbf
    @dbf.columns.collect {|c| c.name.downcase}
  else
    nil
  end
end

#each_shape(&block) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/shapefile.rb', line 35

def each_shape(&block)
  @shp.seek(HEADER_BYTES, IO::SEEK_SET)
  until @shp.eof?
    # Read the next shape record.
    nbr, len, shp_type = @shp.read(12).unpack("NNV")
    record = @shp.read(len * 2 - 4)
    next if shp_type == Shape::Null.code
    shape = @shape_class.new(nbr, record)
    # Load the shape's attributes. DBF's record method is ridiculously slow
    # (it rereads every single row each time you call it), so we cheat a bit
    # and use some of its private methods.
    if @dbf
      @dbf.send(:seek_to_record, nbr - 1)
      unless @dbf.send(:deleted_record?)
        shape.attributes = DBF::Record.new(@dbf).attributes
      end
    end
    # Run the shape through the block.
    block.call(shape)
  end
end

#shapesObject



29
30
31
32
33
# File 'lib/shapefile.rb', line 29

def shapes
  result = []
  each_shape {|shape| result << shape}
  result
end