def iterate dim
@cells[dim].each_key do |cell| yield cell end
end
def add (lower,data = nil, inverted = false)
begin
lower.each do |lowCell|
if (!lowCell.is_a?(Cell) || !member?(lowCell))
raise "object #{lowCell} is not a cell"
end
end
if (lower != [])
ld = lower[0].dim
exit if ld >= @dim
lower.each do |lowCell|
if (lowCell.dim != ld)
raise "boundary cells have different dimension"
end
end
end
cellDim = (lower.empty? ? 0 : lower[0].dim+1 )
cell = @cellCreate.call(self, cellDim, data)
@lower[cell] = lower
@upper[cell] = Array.new
@cells[cellDim][cell] = true
@inverted[cell] = inverted
lower.each do |lowCell|
@lower[lowCell].each do |lowestCell|
matches = @upper[lowestCell] & lower
if (matches.length > 2)
raise "diamond property violation"
end
if (matches.length == 2)
@switchH[[lowestCell,matches[1],cell]] = matches[0]
@switchH[[lowestCell,matches[0],cell]] = matches[1]
end
end
@upper[lowCell].push(cell)
end
if (cellDim == 1)
if lower.length > 2
raise "diamond property violation"
end
if (lower.length == 2)
@switchH[[nil,lower[0],cell]] = lower[1]
@switchH[[nil,lower[1],cell]] = lower[0]
else
@switchH[[nil,lower[0],cell]] = lower[0]
end
end
if (cell.dim == @dim)
lower.each do |lowCell|
upper = @upper[lowCell]
if upper.length > 2
raise "diamond property violation"
end
if (upper.length == 2)
@switchH[[lowCell,upper[0],nil]] = upper[1]
@switchH[[lowCell,upper[1],nil]] = upper[0]
end
end
end
return cell
rescue
raise $!
end
end
def switch(k, tuple)
raise "nil Tuple given to switch" if tuple == nil
raise "non-Tuple given to switch" if !tuple.is_a? CellTuple
raise "bad call to switch" if k<0 || k>tuple.dim
raise "bad tuple given to switch" if !tuple.dim.is_a? Integer
triple = [tuple[k-1], tuple[k], tuple[k+1]]
otherCell = @switchH[triple]
if (otherCell == nil)
return nil
else
newTupArr = Array.new
for j in 0..tuple.dim
newTupArr[j] = tuple[j]
end
newTupArr[k] = otherCell
return CellTuple.new(newTupArr)
end
end
def delete cell
upper = @upper[cell].clone
upper.each do |upCell| delete upCell end
@lower[cell].each do |lowCell|
@lower[lowCell].each do |lowestCell|
otherCell = @switchH[[lowestCell,lowCell,cell]]
if (otherCell != nil)
@switchH[[lowestCell,lowCell,cell]] = nil
@switchH[[lowestCell,otherCell,cell]] = nil
end
end
if (cell.dim == @dim)
otherCell = @switchH[[lowCell, cell, nil]]
if otherCell != nil
@switchH[[lowCell, cell, nil]] = nil
@switchH[[lowCell, otherCell, nil]] = nil
end
end
@upper[lowCell].delete(cell)
end
@cells[cell.dim].delete(cell)
@lower[cell] = nil
@upper[cell] = nil
@inverted[cell] = nil
end
def member? cell
return @cells[cell.dim].member?(cell)
end
def down(cell,offset=1)
return [cell] if (offset == 0)
lower = Array.new
@lower[cell].each do |lowCell|
lower |= self.down(lowCell,offset-1)
end
return lower
end
def up(cell,offset=1)
return [cell] if (offset == 0)
upper = Array.new
return [] if @upper[cell] == nil
@upper[cell].each do |upCell|
upper |= self.up(upCell,offset-1)
end
return upper
end
def rotate(k, tuple)
index = k - 1
nextCell = cell = tuple[index]
nextTuple = tuple
begin
yield nextCell
oldTuple = nextTuple
nextTuple = switch(index, nextTuple)
index = (index == k) ? k - 1 : k
nextCell = nextTuple[index] if nextTuple != nil
end until (nextCell == cell || nextTuple == nil)
if (nextTuple == nil)
yield oldTuple[k-1]
end
end
def getTuple(cell)
begin
tuple = []
k = cell.dim
if dim < 0 || dim > @dim
raise "cell has dimesion #{dim} and complex has dimension #{@dim}"
end
c = cell
while k >= 0 do
tuple[k] = c
lowC = @lower[c]
c = (lowC == nil) ? nil : lowC[0]
if c == nil && k > 0
raise "non-vertex cell has no boundary elements #{k} #{cell}"
end
k -= 1
end
ctuple = CellTuple.new(tuple)
ctuple = switch(0, ctuple) if @inverted[ctuple[@dim]]
return ctuple
rescue => exc
print "CellComplex.getTuple: ", $!
puts exc.backtrace
exit
end
end
def getFullTuple v
e = up(v)[0]
t = up(e)[0]
CellTuple.new(v, e, t)
end
def getOTuple(ed,tri = nil)
puts "Warning" if ed==nil
tri = up(ed)[0] if (tri==nil)
if tri==nil
puts "Cell Complex is not properly constructed. This should not be."
puts ed
puts up(ed)
puts down(ed)
end
tup = getTuple(tri)
while (tup[1] != ed)
tup = switch(1,switch(0,tup))
end
return tup
end
def getOTupleV(v,tri = nil)
t1 = up(up(v)[0])[0]
tup = getTuple(t1)
while (tup[0] != v)
tup = switch(0,switch(1,tup))
end
return tup
end
def show
@cells.each do |dCells|
dCells.each_key do |cell|
puts "Cell: #{cell} #{cell.data}"
puts "Upper:"
@upper[cell].each do |upCell|
puts "#{upCell}"
end
puts "Lower:"
@lower[cell].each do |lowCell|
puts "#{lowCell}"
end
end
end
end
def import otherComplex
@switchH.update(otherComplex.switchH)
@cells.each_index {|i| @cells[i].update(otherComplex.cells[i]) }
@lower.update(otherComplex.lower)
@upper.update(otherComplex.upper)
@inverted.update(otherComplex.inverted)
end
attr_reader :dim
attr_reader :cells,:switchH,:lower,:upper,:inverted
end