#################################
### COPYRIGHT: Anders Lyhagen ###
#################################

module CAUL_FAQS
class EdgeHash

  def initialize(bb)
    @divX = @divY = @divZ = 10.0
    @bbMin = bb.min.offset([-1, -1, -1])  
    @bbMax = bb.max.offset([1, 1, 1])

    @dxInv = 1.0 / ((@bbMax.x - @bbMin.x) / @divX)
    @dyInv = 1.0 / ((@bbMax.y - @bbMin.y) / @divY)
    @dzInv = 1.0 / ((@bbMax.z - @bbMin.z) / @divZ)
    
    @hash = []
    (0..@divX - 1).each { |i| @hash << []
      (0..@divY - 1).each { |j| @hash[i] << []
        (0..@divZ - 1).each { |k| @hash[i][j] << []
    }}}
  end
  
  def addVertex(v)
    x_ind, y_ind, z_ind = getBox(v.position)
    return if x_ind == nil
    @hash[x_ind][y_ind][z_ind] << v
  end
  
  def getEdge(p0, p1)
    x_ind, y_ind, z_ind = getBox(p0)
    return nil if x_ind == nil
    v = @hash[x_ind][y_ind][z_ind].find { |v| v.position == p0 }
    return nil if v == nil
    return v.edges.find { |e| e.other_vertex(v).position == p1 }
  end
  
  def getBox(p)
    x = ((p.x - @bbMin.x) * @dxInv).floor
    y = ((p.y - @bbMin.y) * @dyInv).floor
    z = ((p.z - @bbMin.z) * @dzInv).floor 
    return [nil, nil, nil] if x < 0 || y < 0 || z < 0 || x >= @divX || y >= @divY || z >= @divZ
    return [x, y, z]
  end
  
  def self.getBB(vs)
    bb = Geom::BoundingBox.new
    vs.each { |v| bb.add(v) }
    return bb
  end
  
  #####################
  ##### DEBUG #########
  #####################
  def self.main
  
    mod = Sketchup.active_model # Open model
    ent = mod.entities # All entities in model
    sel = mod.selection # Current selection
    
    gs = sel.grep(Sketchup::Group)
    return nil if gs.length != 1
    g = gs[0]
    
    
    t0 = Time.now
    vs = g.entities.grep(Sketchup::Edge).map { |e| e.vertices }.flatten!.uniq!
    bb = getBB(vs)
    
    eh = CAUL_EdgeHash.new(bb)
    
    vs.each { |v| eh.addVertex(v) }
    
    t1 = Time.now
    es = g.entities.grep(Sketchup::Edge)
    count = 0
    es.each { |e|
      p0 = e.start.position
      p1 = e.end.position
      e2 = eh.getEdge(p0, p1)
      if e2 == nil
        puts 'noooo'
      else
        count += 1
      end
    }
    t2 = Time.now
    puts (t1 - t0).to_s+' s'
    puts (t2 - t1).to_s+' s'
    puts (t2 - t0).to_s+' s'
    puts count.to_s
  end
  
end
end

