class Gdsii::Structure

Represents a GDSII Structure.

Public Class Methods

new(name=nil) { |self| ... } click to toggle source

Creates a Structure object. Various GDSII Elements are added to a structure such as a Boundary, Path, SRef, ARef, Text, Node, and Box.

str_sub = Structure.new('sub')
str_top = Structure.new('top')
str_top.add SRef.new(str_sub)
str_top.add Boundary.new(1, 0, [0,0, 0,10, 10,10, 10,0, 0,0])
Calls superclass method Gdsii::Group.new
# File lib/gdsii/structure.rb, line 45
def initialize(name=nil)
  # Create the record grouping
  super()
  @records[Elements] = Elements.new
  @records[GRT_ENDSTR] = Record.new(GRT_ENDSTR)

  # set the name
  self.name = name unless name.nil?

  # Set create/modify time to the current time
  now = Time.now
  self.create_time = now
  self.modify_time = now

  yield self if block_given?
end
read_each(file) { |read| ... } click to toggle source

Reads each Structure and its Elements from the given file handle. Each Structure is yielded after the entire Structure is read from the file. Compare this with Structure#read_each_header which might be more efficient, more streamlined, and consume less memory.

The Library#read_header method must be called as a prerequisite (the file handle must be at a BGNSTR record).

File.open(file_name, 'rb') do |file|
  Library.read_header(file) do |lib|
    Structure.read_each(file) do |struct|
      puts "#{struct.name} has #{struct.elements.length} elements"
    end
  end
end
# File lib/gdsii/structure.rb, line 203
def Structure.read_each(file)
  while (Record.peek(file).type == GRT_BGNSTR) do
    yield Structure.read(file)
  end
end
read_each_header(file) { |read_header| ... } click to toggle source

Reads the Structure header records from a file handle but without reading any Element records. The resulting Structure element is yielded. This is useful for using the high-level GDSII access methods as a stream file is being read in.

Prior to using this method, the file position must be at the first structure definition (i.e. after the Library header). The best method to do this is to call Library#read_header first.

Also, you MUST advance the file position to the next structure record header (BGNSTR) either with Structure#seek_next or Structure#read_each_element within the code block. Otherwise the file pointer will not be advanced properly and only the first Structure will be yielded.

File.open(file_name, 'rb') do |file|
  Library.read_header(file) do |lib|
    Structure.read_each_header(file) do |struct|
      if struct.name == 'TOP'
        # Show all elements in structure "TOP"
        puts "Processing structure #{struct.name}"
        Element.read_each(file) do |element|
          puts "--> Element: #{element.class}"
        end
      else
        # Skip past elements in other blocks
        puts "Ignoring structure #{struct.name}"
        Structure.seek_next(file)
      end
    end
  end
end
# File lib/gdsii/structure.rb, line 243
def Structure.read_each_header(file)
  while (Record.peek(file).type == GRT_BGNSTR) do
    yield Structure.read_header(file)
  end
end
read_header(file) { |struct| ... } click to toggle source

Reads records related to a Structure header from the given file handle. It is assumed that the file position is already at BGNSTR (likely after Library#read_header). The structure is yielded (if desired) and returned. The iterative version of this method is likely preferable in most cases (Structure#read_each_header).

# File lib/gdsii/structure.rb, line 179
def Structure.read_header(file)
  Structure.read(file, nil, nil, :before_group) {|struct|
    yield struct if block_given?
    break struct
  }
end
seek_next(file) click to toggle source

Reads from the given file handle until a ENDSTR record is met (presumably to a BGNSTR or ENDLIB record. This effectively “skips” past all elements within a structure and prepares the file handle to read the next structure in the file (or ENDLIB if at the end of the GDSII library). See Structure#read_each_header for an example. The new file position is returned.

Compare this with Element#read_each which accomplishes the same thing but instead yields each element as it is read from the file.

# File lib/gdsii/structure.rb, line 260
def Structure.seek_next(file)
  Record.read_each(file) do |record|
    break file.pos if record.is_endstr?
  end
  nil
end

Public Instance Methods

add(*args) click to toggle source

Shortcut for Gdsii::Access::EnumerableGroup#add. For example, instead of:

struct = Structure.new('test')
struct.elements.add Text(1, 0, [0,0], 'hello')

It could be simply:

struct.add Text(1, 0, [0,0], 'hello')
# File lib/gdsii/structure.rb, line 77
def add(*args); elements.add(*args); end
bgnstr() click to toggle source

Get the bgnstr number (returns Fixnum). This holds the create/modify time stamp for the structure. It is probably easier to not access this directly but to use create_time and modify_time instead.

# File lib/gdsii/structure.rb, line 132
def bgnstr() @records.get_data(GRT_BGNSTR); end
bgnstr=(val) click to toggle source

Set the bgnstr number. The value is a Fixnum representation of the create/modify time stamp for the structure. It is probably easier to not access this directly but to use create_time= and modify_time= instead.

# File lib/gdsii/structure.rb, line 140
def bgnstr=(val) @records.set(GRT_BGNSTR, val); end
bgnstr_record() click to toggle source

Get the bgnstr record (returns Record).

# File lib/gdsii/structure.rb, line 125
def bgnstr_record() @records.get(GRT_BGNSTR); end
create_time() click to toggle source

Returns the create time for this structure (returns Time)

# File lib/gdsii/structure.rb, line 155
def create_time(); @create_time; end
create_time=(time) click to toggle source

Accepts a Time object and sets the create time for the structure.

struct.create_time = Time.now
# File lib/gdsii/structure.rb, line 147
def create_time=(time)
  @create_time = time
  update_times
end
elements() click to toggle source

Access to the Elements object. See Elements for a listing of methods.

# File lib/gdsii/structure.rb, line 65
def elements(); @records.get(Elements); end
modify_time() click to toggle source

Returns the modify time for this structure (returns Time)

# File lib/gdsii/structure.rb, line 170
def modify_time(); @modify_time; end
modify_time=(time) click to toggle source

Accepts a Time object and sets the modify time for the structure.

struct.modify_time = Time.now
# File lib/gdsii/structure.rb, line 162
def modify_time=(time)
  @modify_time = time
  update_times
end
name() click to toggle source

Get the Structure name (returns String).

# File lib/gdsii/structure.rb, line 98
def name() @records.get_data(GRT_STRNAME); end
name=(val) click to toggle source

Set the Structure name.

# File lib/gdsii/structure.rb, line 103
def name=(val) @records.set(GRT_STRNAME, val); end
name_record() click to toggle source

Get the Structure STRNAME record (returns Record).

# File lib/gdsii/structure.rb, line 93
def name_record() @records.get(GRT_STRNAME); end
remove(*args) click to toggle source

Shortcut for Gdsii::Access::EnumerableGroup#remove. For example, instead of:

struct.elements.remove {|e| e.class == Gdsii::Text}

It could be simply:

struct.remove {|e| e.class == Gdsii::Text}
# File lib/gdsii/structure.rb, line 88
def remove(*args); elements.remove(*args); end
strclass() click to toggle source

Get the strclass bitarray number (returns Fixnum).

# File lib/gdsii/structure.rb, line 113
def strclass() @records.get_data(GRT_STRCLASS); end
strclass=(val) click to toggle source

Set the strclass bitarray number. According to the GDSII specification, this is only to be used by Calma - otherwise it should be omitted or set to 0. It is probably a good idea to not touch this property.

# File lib/gdsii/structure.rb, line 120
def strclass=(val) @records.set(GRT_STRCLASS, val); end
strclass_record() click to toggle source

Get the strclass record (returns Record).

# File lib/gdsii/structure.rb, line 108
def strclass_record() @records.get(GRT_STRCLASS); end
write_header(file) { || ... } click to toggle source

Writes only the header portion of the Structure to a file (no elements). This is useful when streamlined writing is desired (for better performance or when writing GDSII as another GDSII is being read). Be sure to either:

  1. Call write_footer after writing the header and any Element

objects. Also be sure to wrap this around Gdsii::Library#write_header and Gdsii::Library#write_footer; Or

  1. Pass a block whereupon the footer will automatically be added after

the block is processed.

See Gdsii::Library#write_header for an example.

# File lib/gdsii/structure.rb, line 281
def write_header(file)
  # alter the BNF to exclude Elements and ENDSTR; then write to file
  # according to the modified BNF
  alt_bnf = BnfSpec.new(*Structure.bnf_spec.bnf_items[0..-3])
  self.write(file, alt_bnf)

  # if block is given, then yield to that block and then write the
  # footer afterwards
  if block_given?
    yield
    self.write_footer(file)
  end
end

Private Instance Methods

update_times() click to toggle source

Used by create_time and modify_time

# File lib/gdsii/structure.rb, line 310
def update_times()
  if create_time and modify_time
    self.bgnstr = build_time(create_time) + build_time(modify_time)
  else
    self.bgnstr = nil
  end
end