Question-and-Answer Resource for the Building Energy Modeling Community
Get started with the Help page
Ask Your Question

Revision history [back]

to expand on Dan's answer (code was roo long for comment) here is method I use to calculate perimeter for building. You could adjust this for multiple possible boundary conditions and also for an individual space or surface.

As is it has a single counter for all edges common to an exterior wall and a floor with ground boundary condition.

  # currently takes in model and checks for edges shared by a ground exposed floor and exterior exposed wall. Later could be updated for a specific story independent of floor boundary condition.

def OsLib_Geometry.calculate_perimeter(model)

perimeter = 0
model.getSpaces.each do |space|
  # counter to use later
  edge_hash = {}
  edge_counter = 0
  space.surfaces.each do |surface|
    # get vertices
    vertex_hash = {}
    vertex_counter = 0
    surface.vertices.each do |vertex|
      vertex_counter += 1
      vertex_hash[vertex_counter] = [vertex.x,vertex.y,vertex.z]
    end
    # make edges
    counter = 0
    vertex_hash.each do |k,v|
      edge_counter += 1
      counter += 1
      if vertex_hash.size != counter
        edge_hash[edge_counter] = [v,vertex_hash[counter+1],surface,surface.outsideBoundaryCondition,surface.surfaceType]
      else # different code for wrap around vertex
        edge_hash[edge_counter] = [v,vertex_hash[1],surface,surface.outsideBoundaryCondition,surface.surfaceType]
      end
    end
  end

  # check edges for matches (need opposite vertices and proper boundary conditions)
  edge_hash.each do |k1,v1|
    next if v1[3] != "Ground" # skip if not ground exposed floor
    next if v1[4] != "Floor"
    edge_hash.each do |k2,v2|
      next if v2[3] != "Outdoors" # skip if not exterior exposed wall (todo - update to handle basement)
      next if v2[4] != "Wall"
      # see if edges have same geometry
      next if not v1[0] == v2[1] # next if not same geometry reversed
      next if not v1[1] == v2[0]
      point_one = OpenStudio::Point3d.new(v1[0][0],v1[0][1],v1[0][2])
      point_two = OpenStudio::Point3d.new(v1[1][0],v1[1][1],v1[1][2])
      length = OpenStudio::Vector3d.new(point_one - point_two).length
      perimeter += length
    end
  end
end

return perimeter

end

to expand on Dan's answer (code was roo long for comment) here is method I use to calculate perimeter for building. You could adjust this for multiple possible boundary conditions and also for an individual space or surface.

As is it has a single counter for all edges common to an exterior wall and a floor with ground boundary condition.

  # currently takes in model and checks for edges shared by a ground exposed floor and exterior exposed wall. Later could be updated for a specific story independent of floor boundary condition.

def OsLib_Geometry.calculate_perimeter(model)

OsLib_Geometry.calculate_perimeter(model)    
  perimeter = 0
 model.getSpaces.each do |space|
   # counter to use later
   edge_hash = {}
   edge_counter = 0
   space.surfaces.each do |surface|
     # get vertices
     vertex_hash = {}
     vertex_counter = 0
     surface.vertices.each do |vertex|
       vertex_counter += 1
       vertex_hash[vertex_counter] = [vertex.x,vertex.y,vertex.z]
    end
  end
      # make edges
     counter = 0
     vertex_hash.each do |k,v|
       edge_counter += 1
       counter += 1
       if vertex_hash.size != counter
         edge_hash[edge_counter] = [v,vertex_hash[counter+1],surface,surface.outsideBoundaryCondition,surface.surfaceType]
       else # different code for wrap around vertex
         edge_hash[edge_counter] = [v,vertex_hash[1],surface,surface.outsideBoundaryCondition,surface.surfaceType]
      end
    end
  end

  end
      end
    end

    # check edges for matches (need opposite vertices and proper boundary conditions)
   edge_hash.each do |k1,v1|
     next if v1[3] != "Ground" # skip if not ground exposed floor
     next if v1[4] != "Floor"
     edge_hash.each do |k2,v2|
       next if v2[3] != "Outdoors" # skip if not exterior exposed wall (todo - update to handle basement)
       next if v2[4] != "Wall"
       # see if edges have same geometry
       next if not v1[0] == v2[1] # next if not same geometry reversed
       next if not v1[1] == v2[0]
       point_one = OpenStudio::Point3d.new(v1[0][0],v1[0][1],v1[0][2])
       point_two = OpenStudio::Point3d.new(v1[1][0],v1[1][1],v1[1][2])
       length = OpenStudio::Vector3d.new(point_one - point_two).length
       perimeter += length
    end
  end
end

  end
    end
  end

  return perimeter
end

end