# # *********************************************************************
# # *  Copyright (c) 2008-2015, Natural Resources Canada
# # *  All rights reserved.
# # *
# # *  This library is free software; you can redistribute it and/or
# # *  modify it under the terms of the GNU Lesser General Public
# # *  License as published by the Free Software Foundation; either
# # *  version 2.1 of the License, or (at your option) any later version.
# # *
# # *  This library is distributed in the hope that it will be useful,
# # *  but WITHOUT ANY WARRANTY; without even the implied warranty of
# # *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# # *  Lesser General Public License for more details.
# # *
# # *  You should have received a copy of the GNU Lesser General Public
# # *  License along with this library; if not, write to the Free Software
# # *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
# # **********************************************************************/
#
#
#
# require "singleton"
#
#
# module BTAP
#   module EQuest
#     # Author::    Phylroy Lopez  (mailto:plopez@nrcan.gc.ca)
#     # Copyright:: Copyright (c) NRCan
#     # License::   GNU Public Licence
#     #This class contains encapsulates the generic interface for the DOE2.x command
#     #set. It stores the u type, commands, and keyword pairs for each command. It also
#     #stores the parent and child command relationships w.r.t. the building envelope
#     #and the hvac systems. I have attempted to make the underlying storage of data
#     #private so, if required, we could move to a database solution in the future
#     #if required for web development..
#
#     class DOECommand
#
#       # Contains the user specified name
#       attr_accessor :utype
#       #Contains the u-value
#       attr_accessor :uvalue
#       # Contains the DOE-2 command name.
#       attr_accessor :commandName
#       # Contains the Keyword Pairs.
#       attr_accessor :keywordPairs
#       # Lists all ancestors in increasing order.
#       attr_accessor :parents
#       # An Array of all the children of this command.
#       attr_accessor :children
#       # The command type.
#       attr_accessor :commandType
#       # Flag to see if this component is exempt.
#       attr_accessor :exempt
#       # Comments. To be added to the command.
#       attr_accessor :comments
#       # A list of all the non_utype_commands.
#       attr_accessor :non_utype_commands
#       # A list of all the one line commands (no keyword pairs)
#       attr_accessor :one_line_commands
#       # Pointer to the building obj.
#       attr_accessor :building
#
#
#
#
#       def remove()
#         #unlink children
#         self.children.each {|item| item.remove}
#         #unlink from parent.
#         self.get_parents[0].children.delete(self)
#         #remove from command array.
#         @building.commands.delete(self)
#         return self
#       end
#
#       def set_parent(parent)
#         @parents.clear
#         parent.get_parents().each {|parent| @parents << parent}
#         @parents << parent
#       end
#
#       #This method will return the value of the keyword pair if available.
#       #Example:
#       #If you object has this data in it...
#       #
#       #"EL1 West Perim Spc (G.W4)" = SPACE
#       #SHAPE            = POLYGON
#       #ZONE-TYPE        = CONDITIONED
#       #PEOPLE-SCHEDULE  = "EL1 Bldg Occup Sch"
#       #LIGHTING-SCHEDUL = ( "EL1 Bldg InsLt Sch" )
#       #EQUIP-SCHEDULE   = ( "EL1 Bldg Misc Sch" )
#       #
#       #
#       #then calling
#       #
#       #get_keyword_value("ZONE-TYPE")
#       #
#       #will return the string
#       #
#       #"CONDITIONED".
#       #
#       #if the keyword does not exist, it will return a nil object.
#       # Returns the value associated with the keyword.
#       def get_keyword_value(string)
#         return_string = String.new()
#         found = false
#         @keywordPairs.each do |pair|
#           if pair[0] == string
#             found = true
#             return_string = pair[1]
#           end
#         end
#         if found == false
#           raise "Error: In the command #{@utype}:#{@command_name} Attempted to get a Keyword pair #{string} present in the command\n Is this keyword missing? \n#{output}"
#         end
#         return return_string
#       end
#
#       # Sets the keyword value.
#       def set_keyword_value(keyword, value)
#         found = false
#         unless @keywordPairs.empty?
#           @keywordPairs.each do |pair|
#             if pair[0] == keyword
#               pair[1] = value
#               found = true
#             end
#           end
#           if (found == false)
#             @keywordPairs.push([keyword,value])
#           end
#         else
#           #First in the array...
#           add_keyword_pair(keyword,value)
#         end
#       end
#
#       # Removes the keyword pair.
#       def remove_keyword_pair(string)
#         return_string = String.new()
#         @keywordPairs.each do |pair|
#           if pair[0] == string
#             @keywordPairs.delete(pair)
#           end
#         end
#         return return_string
#       end
#
#       def initialize()
#         @utype = String.new()
#         @commandName= String.new()
#         @keywordPairs=Array.new()
#         @parents = Array.new()
#         @children = Array.new()
#         @commandType = String.new()
#         @exempt = false
#         #HVAC Hierarchry
#         @comments =Array.new()
#         @hvacLevel = Array.new()
#         @hvacLevel[0] =["SYSTEM"]
#         @hvacLevel[1] =["ZONE"]
#         #Envelope Hierachy
#         @envelopeLevel = Array.new()
#         @envelopeLevel[0] = ["FLOOR"]
#         @envelopeLevel[1] = ["SPACE"]
#
#         @envelopeLevel[2] = [
#           "EXTERIOR-WALL",
#           "INTERIOR-WALL",
#           "UNDERGROUND-WALL",
#           "ROOF"
#         ]
#
#         @envelopeLevel[3] = [
#           "WINDOW",
#           "DOOR"]
#
#         @non_utype_commands = Array.new()
#         @non_utype_commands = [
#           "TITLE",
#           "SITE-PARAMETERS",
#           "BUILD-PARAMETER",
#           "LOADS_REPORT",
#           "SYSTEMS-REPORT",
#           "MASTERS-METERS",
#           "ECONOMICS-REPORT",
#           "PLANT-REPORT",
#           "LOADS-REPORT",
#           "COMPLIANCE"
#         ]
#         @one_line_commands = Array.new()
#         @one_line_commands = ["INPUT","RUN-PERIOD","DIAGNOSTIC","ABORT", "END", "COMPUTE", "STOP", "PROJECT-DATA"]
#       end
#
#       # Determines the DOE scope, either envelope or hvac (Window, Wall, Space Floor) or (System->Plant)
#       # Hierarchy) this is required to determine parent/child relationships in the building.
#       def doe_scope
#         scope = "none"
#         @envelopeLevel.each_index do |index|
#           @envelopeLevel[index].each do |name|
#             if (@commandName == name )
#               scope = "envelope"
#             end
#           end
#         end
#
#         @hvacLevel.each_index do |index|
#           @hvacLevel[index].each do |name|
#             if (@commandName == name )
#               scope = "hvac"
#             end
#           end
#         end
#         return scope
#       end
#       # Determines the DOE scope depth (Window, Wall, Space Floor) or (System->Plant) Hierarchy)
#       def depth
#         level = 0
#         scopelist=[]
#         if (doe_scope == "hvac")
#           scopelist = @hvacLevel
#         else
#           scopelist = @envelopeLevel
#         end
#         scopelist.each_index do |index|
#           scopelist[index].each do |name|
#             if (@commandName == name )
#               level = index
#             end
#           end
#         end
#         return level
#       end
#
#       #Outputs the command in DOE 2.2 format.
#       def output
#         return basic_output()
#       end
#
#       #Outputs the command in DOE 2.2 format.
#       def basic_output()
#         temp_string = String.new()
#
#         if (@utype != "")
#           temp_string = temp_string + "#{@utype} = "
#         end
#         temp_string = temp_string + @commandName
#         temp_string = temp_string + "\n"
#         @keywordPairs.each {|array| temp_string = temp_string +  "\t#{array[0]} = #{array[1]}\n" }
#         temp_string = temp_string + "..\n"
#
#         temp_string = temp_string + "$Parents\n"
#         @parents.each do |array|
#           temp_string = temp_string +  "$\t#{array.utype} = #{array.commandName}\n"
#         end
#         temp_string = temp_string + "..\n"
#
#         temp_string = temp_string + "$Children\n"
#         @children.each {|array| temp_string = temp_string +  "$\t#{array.utype} = #{array.commandName}\n" }
#         temp_string = temp_string + "..\n"
#
#       end
#
#       # Creates the command informantion based on DOE 2.2 syntax.
#       def get_command_from_string(command_string)
#         #Split the command based on the equal '=' sign.
#         remove = ""
#         keyword=""
#         value=""
#
#         if (command_string != "")
#           #Get command and u-value
#           if ( command_string.match(/(^\s*(\".*?\")\s*\=\s*(\S+)\s*)/) )
#             @commandName=$3.strip
#             @utype = $2.strip
#             remove = Regexp.escape($1)
#
#           else
#             # if no u-value, get just the command.
#             command_string.match(/(^\s*(\S*)\s)/ )
#             remove = Regexp.escape($1)
#             @commandName=$2.strip
#           end
#           #Remove command from string.
#
#           command_string.sub!(/#{remove}/,"")
#           command_string.strip!
#
#
#           #Loop throught the keyword values.
#           while ( command_string.length > 0 )
#             #DOEMaterial, or SCHEDULES
#             if ( command_string.match(/(^\s*(MATERIAL|DAY-SCHEDULES|WEEK-SCHEDULES)\s*(\=?)\s*(.*)\s*)/))
#               #puts "Bracket"
#               keyword = $2.strip
#               value = $4.strip
#               remove = Regexp.escape($1)
#               #Stars
#             elsif ( command_string.match(/(^\s*(\S*)\s*(\=?)\s*(\*.*?\*)\s*)/))
#               #puts "Bracket"
#               keyword = $2.strip
#               value = $4.strip
#               remove = Regexp.escape($1)
#
#               #Brackets
#             elsif ( command_string.match(/(^\s*(\S*)\s*(\=?)\s*(\(.*?\))\s*)/))
#               #puts "Bracket"
#               keyword = $2.strip
#               value = $4.strip
#               remove = Regexp.escape($1)
#               #Quotes
#             elsif ( command_string.match(/(^\s*(\S*)\s*(\=?)\s*(".*?")\s*)/) )
#               #puts "Quotes"
#               keyword = $2
#               value = $4.strip
#               remove = Regexp.escape($1)
#               #single command
#             elsif command_string.match(/(^\s*(\S*)\s*(\=?)\s*(\S+)\s*)/)
#               #puts "Other"
#               keyword = $2
#               value = $4.strip
#               remove = Regexp.escape($1)
#             end
#             #puts "DOE22::DOECommand: #{command_string}"
#             #puts "K = #{keyword} V = #{value}\n"
#             if (keyword != "")
#               set_keyword_value(keyword,value)
#             end
#             command_string.sub!(/#{remove}/,"")
#           end
#           #puts "Keyword"
#           #puts keywordPairs
#         end
#       end
#
#       #Returns an array of the commands parents.
#       def get_parents
#         return @parents
#       end
#
#       #Returns an array of the commands children.
#       def get_children
#         return children
#       end
#
#       # Gets name.
#       def get_name()
#         return @utype
#       end
#
#       # Check if keyword exists.
#       def check_keyword?(keyword)
#         @keywordPairs.each do |pair|
#           if pair[0] == keyword
#             return true
#           end
#         end
#         return false
#       end
#
#       # Gets the parent of command...if any.
#       def get_parent(keyword)
#
#         get_parents().each do |findcommand|
#
#           if ( findcommand.commandName == keyword)
#             return findcommand
#           end
#         end
#         return nil
#
#       end
#
#       #Gets children of command, if any.
#       def get_children_of_command(keyword)
#         array = Array.new()
#         children.each do |findcommand|
#           if ( findcommand.commandName == keyword)
#             array.push(findcommand)
#           end
#         end
#         return array
#       end
#
#       def name()
#         return utype
#       end
#
#       private
#       def add_keyword_pair(keyword,pair)
#         array = [keyword,pair]
#         keywordPairs.push(array)
#       end
#     end
#     class DOEZone < BTAP::EQuest::DOECommand
#       attr_accessor :space
#       # a vector of spaces used when the declaration of space is "combined"
#       attr_accessor :space_uses
#       # a lighting object which stores the lighting characteristics of each zone
#       attr_accessor :lighting
#       #defines the thermal mass characteristics of the zone.
#       #could be a string object or a user defined object
#       attr_accessor :thermal_mass
#       # stores a constant floating value of the amount of air leakage,
#       #accoriding to rule #4.3.5.9.
#       attr_accessor :air_leakage
#       # this will be a vector consisting of heat transfer objects,
#       # which contains a pointer to the adjacent thermal block and a pointer
#       # to the wall in between them
#       attr_accessor :heat_transfers
#       def initialize
#         super()
#       end
#
#       def output
#
#         temp_string = basic_output()
#         if (@space == nil)
#           temp_string = temp_string + "$ No space found to match zone!\n"
#         else
#           temp_string = temp_string + "$Space\n"
#           temp_string = temp_string +  "$\t#{@space.utype} = #{@space.commandName}\n"
#         end
#         return temp_string
#       end
#
#       # This method finds all the exterior surfaces, ie. Exterior Wall and Roof
#       # Output => surfaces as an Array of commands
#       def get_exterior_surfaces()
#         surfaces = Array.new()
#         @space.get_children().each do |child|
#
#           if child.commandName == "EXTERIOR-WALL" ||
#               child.commandName == "ROOF"
#             surfaces.push(child)
#           end
#         end
#         return surfaces
#       end
#
#       # This method returns all the children of the space
#       def get_children()
#         return @space.get_children()
#       end
#
#
#
#       # This method returns the area of the space
#       def get_area()
#         @space.get_area()
#       end
#
#
#
#
#       def convert_to_openstudio(model,runner = nil)
#         if self.space.get_shape() == "NO-SHAPE"
#           BTAP::runner_register("Info", "Thermal Zone contains a NO-SHAPE space named. OS does not support no shape spaces.  Thermal Zone will not be created.",runner)
#         else
#           os_zone = OpenStudio::Model::ThermalZone.new(model)
#           os_zone.setName(self.name)
#           #set space to thermal zone
#           OpenStudio::Model::getSpaceByName(model,self.space.name).get.setThermalZone(os_zone)
#           BTAP::runner_register("Info", "\tThermalZone: " + self.name + " created",runner)
#         end
#       end
#     end
#
#
#     class DOESurface < DOECommand
#       attr_accessor :construction
#       attr_accessor :polygon
#
#       def initialize
#         super()
#         @polygon = nil
#       end
#
#       def get_azimuth()
#         #puts OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 0.0, 0.0), OpenStudio::Vector3d.new(1.0, 0.0, 0.0) ) )
#         if check_keyword?("LOCATION")
#           case get_keyword_value("LOCATION")
#           when /SPACE-\s*V\s*(.*)/
#             index = $1.strip.to_i - 1
#             point0 = self.get_parent("SPACE").polygon.point_list[index]
#             point1 = self.get_parent("SPACE").polygon.point_list[index + 1] ? get_parent("SPACE").polygon.point_list[index + 1] : get_parent("SPACE").polygon.point_list[0]
#             edge = point1-point0
#
#             sign = OpenStudio::Vector3d.new(1.0, 0.0, 0.0).dot(( edge )) > 0 ? 1 :-1
#             angle = OpenStudio::radToDeg( sign * OpenStudio::getAngle(OpenStudio::Vector3d.new(1.0, 0.0, 0.0), ( point1 - point0 ) ) )
#
#             #since get angle only get acute angles we need to get sign and completment for reflex angle
#             angle = angle + 180 if edge.y < 0
#             return angle
#           when "FRONT"
#             return  OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 1.0, 0.0), ( get_parent("SPACE").polygon.point_list[1] - get_parent("SPACE").polygon.point_list[0] ) ) )
#           when "RIGHT"
#             return OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 1.0, 0.0), ( get_parent("SPACE").polygon.point_list[2] - get_parent("SPACE").polygon.point_list[1] ) ) )
#           when "BACK"
#             return OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 1.0, 0.0), ( get_parent("SPACE").polygon.point_list[3] - get_parent("SPACE").polygon.point_list[2] ) ) )
#           when "LEFT"
#             return OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 1.0, 0.0), ( get_parent("SPACE").polygon.point_list[0] - get_parent("SPACE").polygon.point_list[3] ) ) )
#           end
#         end
#         return self.check_keyword?("AZIMUTH")? self.get_keyword_value("AZIMUTH").to_f : 0.0
#       end
#
#       def get_tilt()
#         #puts OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 0.0, 0.0), OpenStudio::Vector3d.new(1.0, 0.0, 0.0) ) )
#         if check_keyword?("LOCATION")
#           case get_keyword_value("LOCATION")
#           when "FRONT","BACK","LEFT","RIGHT",/SPACE-\s*V\s*(.*)/
#             return  90.0
#           when "TOP"
#             return 0.0
#           when "BOTTOM"
#             return 180.0
#           end
#         end
#         return self.check_keyword?("TILT")? self.get_keyword_value("TILT").to_f : 0.0
#       end
#
#
#
#
#       def get_origin()
#         space_xref = self.check_keyword?("X")? self.get_keyword_value("X").to_f : 0.0
#         space_yref = self.check_keyword?("Y")? self.get_keyword_value("Y").to_f : 0.0
#         space_zref = self.check_keyword?("Z")? self.get_keyword_value("Z").to_f : 0.0
#         return OpenStudio::Vector3d.new(space_xref,space_yref,space_zref)
#       end
#
#       def get_sub_surface_origin()
#         height = ""
#         BTAP::runner_register("Info", "geting origin",runner)
#         origin = ""
#         if self.check_keyword?("X") and self.check_keyword?("Y") and self.check_keyword?("Z")
#           BTAP::runner_register("Info", "XYZ definition",runner)
#           space_xref = self.get_keyword_value("X").to_f
#           space_yref = self.get_keyword_value("Y").to_f
#           space_zref = self.get_keyword_value("Z").to_f
#           return OpenStudio::Vector3d.new(space_xref,space_yref,space_zref)
#         end
#         BTAP::runner_register("Info", get_name(),runner)
#         array = Array.new()
#         origin = ""
#         floor = get_parent("FLOOR")
#         space = get_parent("SPACE")
#         case space.get_keyword_value("ZONE-TYPE")
#         when "PLENUM"
#           height = floor.get_keyword_value("FLOOR-HEIGHT").to_f  - floor.get_keyword_value("SPACE-HEIGHT").to_f
#         when "CONDITIONED","UNCONDITIONED"
#           height =  space.check_keyword?("HEIGHT") ? space.get_keyword_value("HEIGHT").to_f : floor.get_keyword_value("SPACE-HEIGHT").to_f
#
#         end
#         BTAP::runner_register("Info", "Space is #{space.get_shape}",runner)
#         case space.get_shape
#         when "BOX"
#           BTAP::runner_register("Info", "Box Space Detected....",runner)
#           #get height, width and depth of box.
#           height = space.check_keyword?("HEIGHT").to_f ? space.check_keyword?("HEIGHT") : height
#           width = space.get_keyword_value("WIDTH").to_f
#           depth = space.get_keyword_value("DEPTH").to_f
#
#           case get_keyword_value("LOCATION")
#           when "TOP"
#             BTAP::runner_register("Info", "Top of Box....",runner)
#             #counter clockwise
#             origin = OpenStudio::Point3d.new(0.0,0.0,height)
#
#           when "BOTTOM"
#             BTAP::runner_register("Info", "Bottom of Box....",runner)
#             #counter clockwise
#             origin = OpenStudio::Point3d.new( 0.0, 0.0, 0.0 )
#           when "FRONT"
#             BTAP::runner_register("Info", "Front of Box....",runner)
#             #counter clockwise
#             origin = OpenStudio::Point3d.new( 0.0, 0.0, 0.0 )
#           when "RIGHT"
#             BTAP::runner_register("Info", "Right of Box....",runner)
#             #counter clockwise
#             origin = OpenStudio::Point3d.new(width, 0.0, 0.0)
#           when "BACK"
#             BTAP::runner_register("Info", "Back of Box....",runner)
#             #counter clockwise
#             origin = OpenStudio::Point3d.new(width,depth,0.0)
#           when "LEFT"
#             BTAP::runner_register("Info", "Left of Box....",runner)
#             #counter clockwise
#             origin = OpenStudio::Point3d.new(0.0,depth,0.0)
#
#           end
#
#         when "POLYGON"
#           #puts "Polygon Space definition detected..."
#           if check_keyword?("LOCATION")
#             #puts "LOCATION surface definition detected..."
#             case get_keyword_value("LOCATION")
#             when "BOTTOM"
#               origin = OpenStudio::Vector3d.new(0.0,0.0, 0.0 )
#             when "TOP"
#               #puts "TOP surface definition detected..."
#               #need to move floor polygon up to space height for top. Using Transformation.translation matrix for this.
#
#               origin = OpenStudio::Vector3d.new(0.0,0.0, height ) #to-do!!!!!!!!!!!
#             when /SPACE-\s*V\s*(.*)/
#               #puts "SPACE-V#{$1} surface definition detected..."
#               index = $1.strip.to_i - 1
#               point0 = space.polygon.point_list[index]
#               #counter clockwise
#               origin = OpenStudio::Point3d.new( point0.x, point0.y, 0.0)
#
#             end
#           else
#             #puts "CATCH-ALL for surface definition.."
#             #nasty. The height is NOT defined if the height is the same as the space height...so gotta get it from it's parent space.
#             space_height =  space.check_keyword?("HEIGHT") ? space.get_keyword_value("HEIGHT").to_f : floor.get_keyword_value("SPACE-HEIGHT").to_f
#             height = self.check_keyword?("HEIGHT") ? self.get_keyword_value("HEIGHT").to_f : space_height
#             width =  self.get_keyword_value("WIDTH").to_f
#             #origin
#             origin = OpenStudio::Point3d.new(width,0.0,0.0)
#           end
#         when "NO-SHAPE"
#           raise("Using SHAPE = NO-SHAPE deifnition for space is not supported by open Studio")
#         end
#
#         origin =  OpenStudio::Vector3d.new(origin.x,origin.y,origin.z)
#         #puts "Surface origin vector is #{origin}"
#         return origin
#       end
#
#
#
#       def get_transformation_matrix
#         #Rotate points around z (azimuth) and x (Tilt)
#         translation = OpenStudio::createTranslation(self.get_origin)
#         e_a = OpenStudio::EulerAngles.new(	OpenStudio::degToRad( self.get_tilt ), 0.0, OpenStudio::degToRad( 180.0 - self.get_azimuth  ) )
#         rotations = OpenStudio::Transformation::rotation(e_a)
#         return  translation * rotations
#       end
#
#       def get_3d_polygon()
#         array = Array.new()
#         origin = ""
#         floor = get_parent("FLOOR")
#         space = get_parent("SPACE")
#         case space.get_keyword_value("ZONE-TYPE")
#         when "PLENUM"
#           height = floor.get_keyword_value("FLOOR-HEIGHT").to_f  - floor.get_keyword_value("SPACE-HEIGHT").to_f
#         when "CONDITIONED","UNCONDITIONED"
#           height =  space.check_keyword?("HEIGHT") ? space.get_keyword_value("HEIGHT").to_f : floor.get_keyword_value("SPACE-HEIGHT").to_f
#         end
#
#         #if the surface has been given a polygon. Then use it.
#         if check_keyword?("POLYGON")
#           #          puts "Polygon Surface Detected...Doing a local transform.."
#           #
#           #          puts "Point List"
#           #          puts self.polygon.point_list
#           #          puts "Origin"
#           #          puts self.get_origin
#           #          puts "azimuth"
#           #          puts self.get_azimuth
#           #          puts "tilt"
#           #          puts self.get_tilt
#
#
#
#           #all other methods below create points relative to the space. This method however, need to be transformed.
#           array = self.polygon.point_list
#
#
#           #if surfaces are defined by shape of space.
#         else
#           case space.get_shape
#           when "BOX"
#             BTAP::runner_register("Info", "Box Space Detected....",runner)
#             #get height, width and depth of box.
#             height = space.check_keyword?("HEIGHT").to_f ? space.check_keyword?("HEIGHT") : height
#             width = space.get_keyword_value("WIDTH").to_f
#             depth = space.get_keyword_value("DEPTH").to_f
#
#             case get_keyword_value("LOCATION")
#             when "TOP"
#               #puts "Top of Box...."
#               #counter clockwise
#               origin = OpenStudio::Point3d.new(0.0,0.0,height)
#               p2 = OpenStudio::Point3d.new(width,0.0,height)
#               p3 = OpenStudio::Point3d.new(width,depth,height)
#               p4 = OpenStudio::Point3d.new(0.0,depth,height)
#               array =  [origin,p2,p3,p4]
#             when "BOTTOM"
#               #puts "Bottom of Box...."
#               #counter clockwise
#               origin = OpenStudio::Point3d.new( 0.0, 0.0, 0.0 )
#               p2 = OpenStudio::Point3d.new( 0.0, depth, 0.0)
#               p3 = OpenStudio::Point3d.new( width, depth, 0.0)
#               p4 = OpenStudio::Point3d.new( width,0.0 ,0.0 )
#               array =  [origin,p2,p3,p4]
#             when "FRONT"
#               #puts "Front of Box...."
#               #counter clockwise
#               origin = OpenStudio::Point3d.new( 0.0, 0.0, 0.0 )
#               p2 = OpenStudio::Point3d.new( width,0.0 ,0.0 )
#               p3 = OpenStudio::Point3d.new( width, 0.0, height)
#               p4 = OpenStudio::Point3d.new( 0.0, 0.0, height)
#               array =  [origin,p2,p3,p4]
#             when "RIGHT"
#               #puts "Right of Box...."
#               #counter clockwise
#               origin = OpenStudio::Point3d.new(width, 0.0, 0.0)
#               p2 = OpenStudio::Point3d.new(width,depth, 0.0)
#               p3 = OpenStudio::Point3d.new(width,depth,height)
#               p4 = OpenStudio::Point3d.new(width,0.0,height)
#               array =  [origin,p2,p3,p4]
#             when "BACK"
#               #puts "Back of Box...."
#               #counter clockwise
#               origin = OpenStudio::Point3d.new(width,depth,0.0)
#               p2 = OpenStudio::Point3d.new(0.0,depth,0.0)
#               p3 = OpenStudio::Point3d.new(0.0,depth,height)
#               p4 = OpenStudio::Point3d.new(width,depth,height)
#               array =  [origin,p2,p3,p4]
#             when "LEFT"
#               #puts "Left of Box...."
#               #counter clockwise
#               origin = OpenStudio::Point3d.new(0.0,depth,0.0)
#               p2 = OpenStudio::Point3d.new( 0.0, 0.0, 0.0 )
#               p3 = OpenStudio::Point3d.new(0.0, 0.0,height)
#               p4 = OpenStudio::Point3d.new(0.0,depth,height)
#               array =  [origin,p2,p3,p4]
#             end
#
#           when "POLYGON"
#             #puts "Polygon Space definition detected..."
#             if check_keyword?("LOCATION")
#               #puts "LOCATION surface definition detected..."
#               case get_keyword_value("LOCATION")
#               when "BOTTOM"
#                 #puts "BOTTOM surface definition detected..."
#                 #reverse array
#                 array = space.polygon.point_list.dup
#                 first = array.pop
#                 array.insert(0,first).reverse!
#               when "TOP"
#                 #puts "TOP surface definition detected..."
#                 #need to move floor polygon up to space height for top. Using Transformation.translation matrix for this.
#                 array = OpenStudio::createTranslation(OpenStudio::Vector3d.new(0.0,0.0, height )) * space.polygon.point_list
#               when /SPACE-\s*V\s*(.*)/
#                 #puts "SPACE-V#{$1} surface definition detected..."
#                 index = $1.strip.to_i - 1
#                 point0 = space.polygon.point_list[index]
#                 point1 = space.polygon.point_list[index + 1] ? space.polygon.point_list[index + 1] : space.polygon.point_list[0]
#                 #counter clockwise
#                 origin = OpenStudio::Point3d.new( point0.x, point0.y, 0.0)
#                 p2 = OpenStudio::Point3d.new(     point1.x, point1.y, 0.0)
#                 p3 = OpenStudio::Point3d.new(     point1.x, point1.y, height )
#                 p4 = OpenStudio::Point3d.new(     point0.x, point0.y, height )
#                 array =  [origin,p2,p3,p4]
#               end
#             else
#               #puts "CATCH-ALL for surface definition.."
#               #nasty. The height is NOT defined if the height is the same as the space height...so gotta get it from it's parent space.
#               space_height =  space.check_keyword?("HEIGHT") ? space.get_keyword_value("HEIGHT").to_f : floor.get_keyword_value("SPACE-HEIGHT").to_f
#               height = self.check_keyword?("HEIGHT") ? self.get_keyword_value("HEIGHT").to_f : space_height
#               width =  self.get_keyword_value("WIDTH").to_f
#               #counter clockwise
#               origin = OpenStudio::Point3d.new(width,0.0,0.0)
#               p2 = OpenStudio::Point3d.new( 0.0,0.0,0.0 )
#               p3 = OpenStudio::Point3d.new(0.0,0.0,height)
#               p4 = OpenStudio::Point3d.new(width,0.0,height)
#               array = [p4, p3, p2, origin]
#
#
#
#             end
#           when "NO-SHAPE"
#             raise("Using SHAPE = NO-SHAPE deifnition for space is not supported...yet")
#           end
#         end
#         #        if self.check_keyword?("AZIMUTH") or self.check_keyword?("TILT")
#         #          puts "Did a transform"
#         #          return get_transformation_matrix * array
#         #        else
#         #          return array
#         #        end
#         return array
#       end
#
#
#       def get_windows()
#         return self.get_children_of_command("WINDOW")
#       end
#
#       def get_doors()
#         return self.get_children_of_command("DOOR")
#       end
#
#
#
#       # This method finds all the commands within the building that are "Construction"
#       # and if the utype matches, it gets the construction
#       def determine_user_defined_construction()
#         constructions = @building.find_all_commands("CONSTRUCTION")
#         constructions.each do |construction|
#           if ( construction.utype == get_keyword_value("CONSTRUCTION") )
#             @construction = construction
#           end
#         end
#         return @construction
#       end
#
#       #This method will try to convert a DOE inp file to an openstudio file..
#       def convert_to_openstudio(model,runner = nil)
#         #Get 3d polygon of surface and tranform the points based on space origin and the floor origin since they each may use their own co-ordinate base system.
#         total_transform = ""
#         if self.check_keyword?("AZIMUTH") or self.check_keyword?("TILT")
#           total_transform =  get_parent("FLOOR").get_transformation_matrix() * get_parent("SPACE").get_transformation_matrix() * get_transformation_matrix()
#         else
#           total_transform =  get_parent("FLOOR").get_transformation_matrix() * get_parent("SPACE").get_transformation_matrix()
#         end
#         surface_points = total_transform * self.get_3d_polygon()
#         #Add the surface to the new openstudio model.
#
#         os_surface = OpenStudio::Model::Surface.new(surface_points, model)
#         #set the name of the surface.
#         os_surface.setName(self.name)
#         case self.commandName
#           #Set the surface boundary condition if it is a ground surface.
#
#         when "UNDERGROUND-WALL"
#           BTAP::Geometry::Surfaces::set_surfaces_boundary_condition(model,os_surface, "Ground")
#         when "EXTERIOR-WALL","ROOF"
#           #this is needed since the surface constructor defaults to a Ground boundary and Floor Surface type
#           #when a horizontal surface is initialized.
#           if os_surface.outsideBoundaryCondition == "Ground" and os_surface.surfaceType == "Floor"
#             os_surface.setSurfaceType("RoofCeiling")
#           end
#           BTAP::Geometry::Surfaces::set_surfaces_boundary_condition(model,os_surface, "Outdoors")
#         when "INTERIOR-WALL"
#           BTAP::Geometry::Surfaces::set_surfaces_boundary_condition(model,os_surface, "Surface")
#         end
#
#         #Add to parent space that was already created.
#         os_surface.setSpace(OpenStudio::Model::getSpaceByName( model,get_parent("SPACE").name).get )
#         #output to console for debugging.
#         BTAP::runner_register("Info", "\tSurface: " + self.name + " created",runner)
#         #check if we need to create a mirror surface in another space.
#         if self.check_keyword?("NEXT-TO")
#           #reverse the points.
#           new_array = surface_points.dup
#           first = new_array.pop
#           new_array.insert(0,first).reverse!
#           #...then add the reverse surface to the model and assign the name with a mirror suffix.
#           os_surface_mirror = OpenStudio::Model::Surface.new(new_array, model)
#           os_surface_mirror.setName(self.name + "-mirror" )
#           #Assign the mirror surface to the parent space that is NEXT-TO
#           os_surface_mirror.setSpace(OpenStudio::Model::getSpaceByName(model,get_keyword_value("NEXT-TO")).get)
#           #output to console for debugging.
#           BTAP::runner_register("Info", "\tSurface: " + self.name + "-mirror"  + " created",runner)
#         end #if statement
#
#         #Some switches for debugging.
#         convert_sub_surfaces = true
#         convert_sub_surfaces_as_surfaces = false
#
#         #
#         if convert_sub_surfaces
#           #convert subsurfaces
#           self.get_children().each do |child|
#             #Get height and width of subsurface
#             height = child.get_keyword_value("HEIGHT").to_f
#             width = child.get_keyword_value("WIDTH").to_f
#
#
#             #Sum the origin of the surface and the translation of the window
#             x = os_surface.vertices.first().x + ( child.check_keyword?("X")?  child.get_keyword_value("X").to_f : 0.0 )
#             y = os_surface.vertices.first().y + ( child.check_keyword?("Y")?  child.get_keyword_value("Y").to_f : 0.0 )
#             z = os_surface.vertices.first().z
#
#             #counter clockwise
#             origin = OpenStudio::Point3d.new( x, y , z )
#             p2 = OpenStudio::Point3d.new(x + width , y, z )
#             p3 = OpenStudio::Point3d.new(x + width , y + height , z )
#             p4 = OpenStudio::Point3d.new(x, y + height, z )
#             polygon =  [origin,p2,p3,p4]
#
#             #get floot and space rotations
#             space_azi = 360.0 - get_parent("SPACE").get_azimuth()
#             floor_azi = 360.0 - get_parent("FLOOR").get_azimuth()
#
#
#             tilt_trans = OpenStudio::Transformation::rotation(os_surface.vertices.first(), OpenStudio::Vector3d.new(1.0,0.0,0.0), OpenStudio::degToRad( self.get_tilt ))
#             azi_trans = OpenStudio::Transformation::rotation(os_surface.vertices.first(), OpenStudio::Vector3d.new(0.0,0.0,1.0), OpenStudio::degToRad( 360.0 - self.get_azimuth + space_azi + floor_azi  ))
#             surface_points =  azi_trans  * tilt_trans * polygon
#             if convert_sub_surfaces_as_surfaces
#               #Debug subsurface
#               os_sub_surface = OpenStudio::Model::Surface.new(surface_points, model)
#               #set the name of the surface.
#               os_sub_surface.setName(child.name)
#               #Add to parent space that was already created.
#               os_sub_surface.setSpace(OpenStudio::Model::getSpaceByName( model,self.get_parent("SPACE").name).get )
#             else
#               #Add the subsurface to the new openstudio model.
#               os_sub_surface = OpenStudio::Model::SubSurface.new(surface_points, model)
#               #set the name of the surface.
#               os_sub_surface.setName(child.name)
#               #Add to parent space that was already created.
#               os_sub_surface.setSurface(os_surface)
#               #output to console for debugging.
#               BTAP::runner_register("Info", "\tSubSurface: " + child.name + " created",runner)
#               case child.commandName
#               when "WINDOW"
#                 #By default it is a window.
#               when "DOOR"
#                 os_sub_surface.setSubSurfaceType( "Door" )
#               end #end case.
#
#               # Add overhang for subsurface if required. Note this only supports overhangs of width the same as the window.
#               if child.check_keyword?("OVERHANG-D") == true
#                 offset = 0.0
#                 offset = child.get_keyword_value("OVERHANG-O").to_f if child.check_keyword?("OVERHANG-O")
#                 depth = 0.0
#                 depth = child.get_keyword_value("OVERHANG-D").to_f
#                 os_sub_surface.addOverhang(	depth , offset )
#               end
#
#             end
#           end
#         end
#       end
#
#     end
#
#     #This class allows to manipulate a subsurface (window/door) in inherits from surface.
#     class DOESubSurface < DOESurface
#
#       def initialize
#         #run the parent class initialization.
#         super()
#       end
#
#       # This method returns the area of the window
#       def get_area()
#         unless check_keyword?("HEIGHT")  and check_keyword?("WIDTH")
#           raise "Error: In the command #{@utype}:#{@command_name} the area could not be evaluated. Either the HEIGHT or WIDTH is invalid.\n #{output}"
#         end
#         return get_keyword_value("WIDTH").to_f * get_keyword_value("HEIGHT").to_f
#       end
#
#       #Return the widow polygon with an origin of zero
#       def get_3d_polygon()
#         height = get_keyword_value("HEIGHT").to_f
#         width = get_keyword_value("WIDTH").to_f
#         x = self.check_keyword?("X")?  self.get_keyword_value("X").to_f : 0.0
#         y = self.check_keyword?("Y")?  self.get_keyword_value("Y").to_f : 0.0
#         #counter clockwise
#         origin = OpenStudio::Point3d.new( x, y , 0.0 )
#         p2 = OpenStudio::Point3d.new(x + width , y,0.0 )
#         p3 = OpenStudio::Point3d.new(x + width , y + height , 0.0 )
#         p4 = OpenStudio::Point3d.new(x, y + height,0.0 )
#         return [origin,p2,p3,p4]
#       end
#
#       #Returns the origin relative to the parent surface.
#       def get_origin()
#         origin = get_parent_surface().get_sub_surface_origin()
#         return origin
#       end
#
#       #Gets azimuth, based on parent surface.
#       def get_azimuth()
#         get_parent_surface().get_azimuth()
#       end
#
#       #gets tilt based on parent surface.
#       def get_tilt()
#         get_parent_surface().get_tilt()
#       end
#
#       #return the parent surface of the subsurface.
#       def get_parent_surface()
#         get_parents().each do |findcommand|
#           [
#             "EXTERIOR-WALL",
#             "INTERIOR-WALL",
#             "UNDERGROUND-WALL",
#             "ROOF"
#           ].each do |type|
#
#             if ( findcommand.commandName == type)
#               return findcommand
#             end
#           end
#         end
#         raise("#no parent surface defined!")
#       end
#
#       #returns the translation matrix reletive to its parent ( the surface )
#       def get_transformation_matrix
#         return  self.get_rotation_matrix() * self.get_translation_matrix()
#       end
#
#       def get_rotation_matrix
#         #Rotate points around z (azimuth) and x (Tilt)
#         e_a = OpenStudio::EulerAngles.new(	OpenStudio::degToRad( self.get_tilt ), 0.0, OpenStudio::degToRad( 0.0  ) )
#         rotations = OpenStudio::Transformation::rotation(e_a)
#         return  rotations
#       end
#
#       def get_translation_matrix
#         #Rotate points around z (azimuth) and x (Tilt)
#         translation = OpenStudio::createTranslation(self.get_origin)
#         return  translation
#       end
#
#
#
#
#
#       # this will translate the subsurface to the openstudio model.
#       def convert_to_openstudio(model)
#       end
#     end
#
#     #an attempt to organize the BDLlibs...don't think it works well at all.
#     class DOEBDLlib
#
#       attr_accessor :db, :materials
#
#       include Singleton
#
#
#
#
#       # stores the name of the individual materials
#
#       attr_accessor :commandList
#       # stores the name of the individual layers
#
#
#       def initialize
#         @commandList = Array.new()
#         @db = Sequel.sqlite
#         @db.create_table :materials do # Create a new table
#           primary_key :id, :integer, :auto_increment => true
#           column :command_name, :text
#           column :name, :text
#           column :type, :text
#           column :thickness, :float
#           column :conductivity, :float
#           column :resistance, :float
#           column :density, :float
#           column :spec_heat, :float
#         end
#         @materials = @db[:materials] # Create a dataset
#
#         @db.create_table :layers do # Create a new table
#           primary_key :id, :integer, :auto_increment => true
#           column :command_name, :text
#           column :name, :text
#           column :material, :text
#           column :inside_film_res, :float
#         end
#         @layers = @db[:layers] # Create a dataset
#
#
#         store_material()
#       end
#
#
#
#       def find_material(utype)
#         posts =  @materials.filter(:name => utype)
#         record = posts.first()
#         #Create the new command object.
#         command = DOE2::DOECommand.new()
#         #Insert the collected information into the object.
#         command.commandName = "MATERIAL"
#         command.utype = record[:name]
#         command.set_keyword_value("TYPE", record[:type])
#         command.set_keyword_value("THICKNESS", record[:thickness])
#         command.set_keyword_value("CONDUCTIVITY", record[:conductivity])
#         command.set_keyword_value("DENSITY", record[:density])
#         command.set_keyword_value("SPECIFIC HEAT", record[:spec_heat])
#
#         return command
#       end
#
#
#       def find_layer(utype)
#         posts =  @layers.filter(:name => utype)
#         record = posts.first()
#         #Create the new command object.
#         command = DOE2::DOECommand.new()
#         #Insert the collected information into the object.
#         command.commandName = "LAYERS"
#         command.utype = record[:name]
#         command.set_keyword_value("MATERIAL", record[:material])
#         command.set_keyword_value("THICKNESS", record[:thickness])
#         command.set_keyword_value("CONDUCTIVITY", record[:conductivity])
#         command.set_keyword_value("DENSITY", record[:density])
#         command.set_keyword_value("SPECIFIC HEAT", record[:spec_heat])
#
#         return command
#       end
#
#
#
#
#
#       # stores the material information using keywordPairs into the command structure
#       # accessed using the find_command method
#       private
#       def store_material
#
#         begin
#           f = File.open("../Resources/DOE2_2/bdllib.dat")
#         rescue
#           f = File.open("Resources/DOE2_2/bdllib.dat")
#         end
#
#         lines = f.readlines
#         # Iterating through the file.
#         lines.each_index do |i|
#           command_string = ""
#           # If we find a material.
#           if lines[i].match(/\$LIBRARY-ENTRY\s(.{32})MAT .*/)
#             #Get the name strips the white space.
#             name = ("\""+$1.strip + "\"")
#
#             #Is this the last line?
#             command_string = get_data(command_string, i, lines)
#             #Extract data for material type PROPERTIES.
#             if (match = command_string.match(/^\s*TYPE\s*=\s*(\S*)\s*TH\s*=\s*(\S*)\s*COND\s*=\s*(\S*)\s*DENS\s*=\s*(\S*)\s*S-H\s*=\s*(\S*)\s*$/) )
#               #Create the new command object.
#               command = DOE2::DOECommand.new()
#               #Insert the collected information into the object.
#               command.commandName = "MATERIAL"
#               command.utype = name
#               command.set_keyword_value("TYPE", $1.strip)
#               command.set_keyword_value("THICKNESS", $2.strip.to_f.to_s)
#               command.set_keyword_value("CONDUCTIVITY", $3.strip.to_f.to_s)
#               command.set_keyword_value("DENSITY", $4.strip.to_f.to_s)
#               command.set_keyword_value("SPECIFIC HEAT", $5.strip.to_f.to_s)
#               #Push the object into the array for storage.
#               @commandList.push(command)
#               @materials << {:name => name,
#                 :command_name => 'MATERIAL',
#                 :type =>  $1.strip,
#                 :thickness =>  $2.strip.to_f.to_s,
#                 :conductivity =>  $3.strip.to_f.to_s,
#                 :density =>  $4.strip.to_f.to_s,
#                 :spec_heat =>  $5.strip.to_f.to_s}
#
#
#
#               #Extract data for material type RESISTANCE.
#             elsif (match = command_string.match(/^\s*TYPE\s*=\s*(\S*)\s*RES\s*=\s*(\S*)\s*$/) )
#               command = DOE2::DOECommand.new()
#               command.commandName = "MATERIAL"
#               command.utype = name
#               command.set_keyword_value("TYPE", $1.strip)
#               command.set_keyword_value("RESISTANCE", $2.strip.to_f.to_s)
#               #Push the object into the array for storage.
#               @materials << {:name => name,
#                 :command_name => 'MATERIAL',
#                 :type =>  $1.strip,
#                 :resistance =>  $2.strip.to_f.to_s}
#
#               @commandList.push(command)
#             else
#               raise("data not extracted")
#             end
#           end
#
#           if lines[i].match(/\$LIBRARY-ENTRY\s(.{32})LA .*/)
#             #Get the name
#             name = ("\""+$1.strip + "\"")
#             #Is this the last line?
#             command_string = get_data(command_string, i, lines)
#             #Extract data into the command.
#             if (match = command_string.match(/^\s*MAT\s*=\s*(.*?)\s*I-F-R\s*=\s*(\S*)\s*$/) )
#               command = DOE2::DOECommand.new()
#               command.commandName = "LAYERS"
#               command.utype = name
#               command.set_keyword_value("MATERIAL",$1)
#               #Push the object into the array for storage.
#               @layers << {:name => name,
#                 :command_name => 'LAYER',
#                 :material =>  $1.strip,
#                 :inside_film_res =>  $2.strip.to_f.to_s}
#               @commandList.push(command)
#             else
#               raise("data not extracted")
#             end
#           end
#         end
#       end
#
#       private
#       # This method will get all the
#       def get_data(command_string, i, lines)
#         #Do this while this is NOT the last line of data.
#         while (! lines[i].match(/^(.*?)\.\.\s*(.{6})?\s*?(\d*)?/) )
#           #Grab all the data in between.
#           if ( lines[i].match(/^\$.*$/) )
#           elsif ( myarray = lines[i].match(/^(.*?)\s*(.{6})?\s*?(\d*)?\s*$/) )
#             command_string = command_string + $1.strip
#           end
#           #Increment counter.
#           i = i + 1
#         end
#         #Get the last line
#         lines[i].match(/^(.*?)\.\.\s*(.{6})?\s*?(\d*)?/)
#         command_string = command_string + $1.strip
#         if command_string == ""
#           raise("error")
#         end
#         i  = i + 1
#         command_string
#       end
#     end
#
#     #class that
#     class DOEExteriorWall < DOESurface
#
#       def initialize
#         #call the parent class.
#         super()
#       end
#
#       # This method finds the area of the exterior wall
#       def get_area()
#         OpenStudio::getArea(self.get_3d_polygon())
#       end
#
#       #This method finds the floor parent
#       def get_floor()
#         get_parent("FLOOR")
#       end
#
#       #This method finds the space parent command
#       def get_space()
#         get_parent("SPACE")
#       end
#
#       #This method gets the construction command
#       def get_construction_name()
#         get_keyword_value("CONSTRUCTION")
#       end
#
#       #This method returns the window area
#       def get_window_area()
#         get_children_area("WINDOW")
#       end
#
#       #This method returns the door area
#       def get_door_area()
#         get_children_area("DOOR")
#       end
#
#       # This method returns the difference between the wall area and the window
#       # and door
#       def get_opaque_area()
#         get_area.to_f - get_window_area().to_f - get_door_area().to_f
#       end
#
#       # This method returns the fraction of the wall dominated by the window
#       def get_fwr()
#         get_window_area().to_f / get_area.to_f
#       end
#
#       # This method returns the area of the children classes based on the given
#       # commandname.
#       # Input => A command_name as a String
#       # Output => Total area as a float
#       def get_children_area(scommand_name)
#         area = 0.0
#         @children.each do |child|
#
#           if child.commandName == scommand_name
#             area = child.get_area() + area
#           end
#         end
#         return area
#       end
#
#       # This method checks if the construction only has a defined U-value
#       def just_u_value?()
#         @construction.check_keyword?("U-VALUE")
#       end
#
#
#     end
#
#
#
#
#
#
#     #The interface for the roof command.. same as parent.
#     class DOERoof < DOECommand
#       def initialize
#         super()
#       end
#
#       # This method finds the area of the roof
#       def get_area
#
#         # Finds the floor and space parents and assigns them to @floor and @space
#         # variables to be used later
#         parent = get_parents
#         parent.each do |findcommand|
#           if ( findcommand.commandName == "FLOOR" )
#             @floor = findcommand
#           end
#           if ( findcommand.commandName == "SPACE")
#             @space = findcommand
#           end
#         end
#
#         # Get the keyword value for location
#         begin
#           location = get_keyword_value("LOCATION")
#         rescue
#         end
#
#         # Get the keyword value for polygon
#         begin
#           polygon_id = get_keyword_value("POLYGON")
#         rescue
#         end
#
#         # if the polygon_id keyword value was nil and the location value was nil, then
#         # the height and width are directly defined within the "roof" command
#
#
#         if  ( location == "BOTTOM" || location == "TOP") && (@space.get_shape != "BOX")
#           return @space.polygon.get_area
#
#         elsif ( location == nil  && polygon_id == nil )
#           height = get_keyword_value("HEIGHT")
#           width = get_keyword_value("WIDTH")
#           height = height.to_f
#           width = width.to_f
#           return height * width
#         elsif ( location == nil && polygon_id != nil)
#           return @space.polygon.get_area
#
#
#           # if the location was defined as "SPACE...", it is immediately followed by a
#           # vertex, upon which lies the width of the roof
#         elsif location.match(/SPACE.*/)
#           location = location.sub( /^(.{6})/, "")
#           width = @space.polygon.get_length(location)
#           height = @floor.get_space_height
#           return width * height
#           # if the shape was a box, the width and height would be taken from the
#           # "SPACE" object
#         elsif ( @space.get_shape == "BOX" )
#           width = @space.get_width
#           height = @space.get_height
#           return width * height
#         else
#           raise "The area could not be evaluated"
#         end
#       end
#
#       #returns tilt of roof surface.
#       def get_tilt()
#         if check_keyword?("TILT") then return get_keyword_value("TILT").to_f
#         else
#           if check_keyword?("LOCATION")
#             location = get_keyword_value("LOCATION")
#             case location
#             when "TOP"
#               return 0.0
#             when "BOTTOM"
#               return 180.0
#             when "LEFT", "RIGHT", "BACK", "FRONT"
#               return 90.0
#             end
#           end
#           # If it is a polygon or not defined, set to DOE default = 0.0
#           return 0
#         end
#       end
#
#       # This method returns the Azimuth value as a FLOAT if it exists
#       # It first checks if the azimuth keyword value is present within the roof
#       # command itself. If it does not find this, then it checks for the location
#       # keyword and assigns the correct azimuth depending on the azimuth of the parent
#       # space. However, if the shape of the parent space is defined as a polygon, then it
#       # searches for the location of the roof and uses the polygon's get-azimuth for the vertex
#       # to return the azimuth of the roof
#
#       #NOTE: The FRONT is defined as 0, going clockwise, ie. RIGHT = 90 degrees
#
#       #OUTPUT: Azimuth between the parent SPACE and the ROOF
#       def get_azimuth()
#         space = get_parent("SPACE")
#         if check_keyword?("AZIMUTH") then return get_keyword_value("AZIMUTH").to_f
#         else
#           if check_keyword?("LOCATION")
#             location = get_keyword_value("LOCATION")
#
#             case location
#             when "TOP"
#               raise "Exception: Azimuth does not exist"
#             when "BOTTOM"
#               raise "Exception: Azimuth does not exist"
#             when "FRONT"
#               return 0.0 + space.get_azimuth
#             when "RIGHT"
#               return 90.0 + space.get_azimuth
#             when "BACK"
#               return 180.0 + space.get_azimuth
#             when "LEFT"
#               return 270.0 + space.get_azimuth
#             end
#           end
#           if space.get_keyword_value("SHAPE") == "POLYGON"
#             space_vertex = get_keyword_value("LOCATION")
#             space_vertex.match(/SPACE-(.*)/)
#             vertex = $1.strip
#             return space.polygon.get_azimuth(vertex)
#           end
#
#         end
#       end
#
#       # This method returns the Azimuth value as a FLOAT if it exists
#       # It first checks if the azimuth keyword value is present within the roof
#       # command itself. If it does not find this, then it checks for the location
#       # keyword and assigns the correct azimuth depending on the azimuth of the parent
#       # space. However, if the shape of the parent space is defined as a polygon, then it
#       # searches for the location of the roof and uses the polygon's get-azimuth for the vertex
#       # and adding it on to the overall azimuth to get the Absolute Azimuth from True North
#
#       #NOTE: The FRONT is defined as 0, going clockwise, ie. RIGHT = 90 degrees
#
#       #OUTPUT: Azimuth between ROOF and TRUE NORTH
#       def get_absolute_azimuth
#         space = get_parent("SPACE")
#         if check_keyword?("AZIMUTH")
#           azimuth = get_keyword_value("AZIMUTH").to_f
#           space_azimuth = space.get_absolute_azimuth
#           return azimuth + space_azimuth
#         else
#           if check_keyword?("LOCATION")
#             location = get_keyword_value("LOCATION")
#             case location
#             when "TOP"
#               raise "Exception: Azimuth does not exist"
#             when "BOTTOM"
#               raise "Exception: Azimuth does not exist"
#             when "FRONT"
#               return 0.0 + space.get_absolute_azimuth
#             when "RIGHT"
#               return 90.0 + space.get_absolute_azimuth
#             when "BACK"
#               return 180.0 + space.get_absolute_azimuth
#             when "LEFT"
#               return 270.0 + space.get_absolute_azimuth
#             end
#           end
#           if space.get_keyword_value("SHAPE") == "POLYGON"
#             space_vertex = get_keyword_value("LOCATION")
#             space_vertex.match(/SPACE-(.*)/)
#             vertex = $1.strip
#             return space.polygon.get_azimuth(vertex) + space.get_absolute_azimuth
#           end
#         end
#       end
#     end
#     #Interface for the DOESpace Command.
#     class DOESpace < DOECommand
#       attr_accessor :polygon
#       attr_accessor :zone
#       def initialize
#
#         super()
#       end
#
#       #this outputs the command to a string.
#       def output
#         temp_string = basic_output()
#         if @polygon != nil
#           temp_string = temp_string + "$Polygon\n"
#           temp_string = temp_string +  "$\t#{@polygon.utype} = #{@polygon.commandName}\n"
#         end
#         if @zone != nil
#           temp_string = temp_string + "$Zone\n"
#           temp_string = temp_string +  "$\t#{@zone.utype} = #{@zone.commandName}\n"
#         end
#         return temp_string
#       end
#
#       # This method finds the area of the space
#       def get_area
#
#         # get the keyword value of shape
#         shape = get_keyword_value("SHAPE")
#
#         # if the shape value is nil, or it is defined as "NO-SHAPE", the get_area value
#         # would be defined, and would represent the get_area of the space
#         if ( shape == nil || shape == "NO-SHAPE")
#           area = get_keyword_value("AREA")
#           area = area.to_f
#           return area
#
#           # if the shape value is "BOX", the height and width key values are given,
#           # and the get_area would be defined as their product
#         elsif ( shape == "BOX" )
#           height = get_keyword_value("HEIGHT")
#           width = get_keyword_value("WIDTH")
#           height = height.to_f
#           width = width.to_f
#           return height * width
#
#           # if the shape value is defined as a polygon , the get_area of the polygon would
#           # represent the get_area of the space
#         elsif ( shape == "POLYGON")
#           return @polygon.get_area
#         else
#           raise "Error: The area could not be evaluated. Please check inputs\n "
#
#         end
#       end
#
#       # This method finds the volume of the space
#       def get_volume
#
#         # get the keyword value of "SHAPE"
#         shape = get_keyword_value("SHAPE")
#
#         # if the shape value returns nil, or is defined as "NO-SHAPE", the volume is
#         # given directly
#         if ( shape == nil || shape == "NO-SHAPE")
#           volume = get_keyword_value("VOLUME")
#           volume = volume.to_f
#           return volume
#
#           # if the shape is defined as a "BOX", the values for height, width, and
#           # depth are given, from which you can get the volume
#         elsif ( shape == "BOX" )
#           height = get_keyword_value("HEIGHT")
#           width = get_keyword_value("WIDTH")
#           depth = get_keyword_value("DEPTH")
#           height = height.to_f
#           width = width.to_f
#           depth = depth.to_f
#           return height * width * depth
#
#           # if the shape is defined as a "POLYGON", the get_area is defined as the area
#           # of the polygon, and the height is given by the value of "HEIGHT"
#         elsif ( shape == "POLYGON")
#           height = getKeywordvalue("HEIGHT")
#           temp = get_keyword_value("POLYGON")
#           height = height.to_f
#           @polygon.utype = temp
#           return @polygon.get_area * height
#         else
#           raise "Error: The volume could not be evaluated. Please check inputs\n "
#
#         end
#
#       end
#
#       def get_height()
#         if check_keyword?("HEIGHT") then return get_keyword_value("HEIGHT").to_f end
#         return get_floor.get_keyword_value("SPACE-HEIGHT").to_f
#       end
#
#       def get_width
#         width = get_keyword_value("WIDTH")
#         width = width.to_f
#         return width
#       end
#
#       def get_depth
#         depth = get_keyword_value("DEPTH")
#         depth = depth.to_f
#         return depth
#       end
#
#       def get_shape
#         return "NO-SHAPE" unless check_keyword?("SHAPE")
#         return get_keyword_value("SHAPE")
#       end
#
#       def get_floor
#         get_parent("FLOOR")
#       end
#
#
#       def get_origin()
#         space_origin = nil
#         if check_keyword?("LOCATION") and ( not self.check_keyword?("X") or not self.check_keyword?("Y") or not self.check_keyword?("Z") )
#           zero = OpenStudio::Point3d.new( 0.0, 0.0, 0.0 )
#           case get_keyword_value("LOCATION")
#           when /FLOOR-\s*V\s*(.*)/
#             index = $1.strip.to_i - 1
#             surf_vector =  get_parent("FLOOR").polygon.point_list[index] - zero
#           when "FRONT"
#             surf_vector =  get_parent("FLOOR").polygon.point_list[0] - zero
#           when "RIGHT"
#             surf_vector =  get_parent("FLOOR").polygon.point_list[1] - zero
#           when "BACK"
#             surf_vector =  get_parent("FLOOR").polygon.point_list[2] - zero
#           when "LEFT"
#             surf_vector =  get_parent("FLOOR").polygon.point_list[3] - zero
#           end
#           space_xref = self.check_keyword?("X")? self.get_keyword_value("X").to_f : 0.0
#           space_yref = self.check_keyword?("Y")? self.get_keyword_value("Y").to_f : 0.0
#           space_zref = self.check_keyword?("Z")? self.get_keyword_value("Z").to_f : 0.0
#           space_origin = OpenStudio::Vector3d.new(space_xref,space_yref,space_zref)
#           space_origin = surf_vector + space_origin
#         else
#           space_xref = self.check_keyword?("X")? self.get_keyword_value("X").to_f : 0.0
#           space_yref = self.check_keyword?("Y")? self.get_keyword_value("Y").to_f : 0.0
#           space_zref = self.check_keyword?("Z")? self.get_keyword_value("Z").to_f : 0.0
#           space_origin = OpenStudio::Vector3d.new(space_xref,space_yref,space_zref)
#         end
#         return space_origin
#       end
#
#       def get_azimuth()
#         angle = 0.0
#         #puts OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 0.0, 0.0), OpenStudio::Vector3d.new(1.0, 0.0, 0.0) ) )
#         if check_keyword?("LOCATION") and not check_keyword?("AZIMUTH")
#           case get_keyword_value("LOCATION")
#           when /FLOOR-\s*V\s*(.*)/
#             index = $1.strip.to_i - 1
#             point0 = self.get_parent("FLOOR").polygon.point_list[index]
#             point1 = self.get_parent("FLOOR").polygon.point_list[index + 1] ? get_parent("FLOOR").polygon.point_list[index + 1] : get_parent("FLOOR").polygon.point_list[0]
#             edge = point1-point0
#
#
#             sign = 1.0# OpenStudio::Vector3d.new(1.0, 0.0, 0.0).dot(( edge )) > 0 ? 1 :-1
#             angle = OpenStudio::radToDeg( sign * OpenStudio::getAngle(OpenStudio::Vector3d.new(1.0, 0.0, 0.0), ( point1 - point0 ) ) )
#
#             #since get angle only get acute angles we need to get sign and completment for reflex angle
#             if edge.y > 0.0
#               angle = -1.0 * angle
#             end
#
#           when "FRONT"
#             angle = OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 1.0, 0.0), ( get_parent("FLOOR").polygon.point_list[1] - get_parent("FLOOR").polygon.point_list[0] ) ) )
#           when "RIGHT"
#             angle = OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 1.0, 0.0), ( get_parent("FLOOR").polygon.point_list[2] - get_parent("FLOOR").polygon.point_list[1] ) ) )
#           when "BACK"
#             angle = OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 1.0, 0.0), ( get_parent("FLOOR").polygon.point_list[3] - get_parent("FLOOR").polygon.point_list[2] ) ) )
#           when "LEFT"
#             angle = OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 1.0, 0.0), ( get_parent("FLOOR").polygon.point_list[0] - get_parent("FLOOR").polygon.point_list[3] ) ) )
#           end
#         else
#           angle =  self.check_keyword?("AZIMUTH")? self.get_keyword_value("AZIMUTH").to_f : 0.0
#         end
#         return angle
#       end
#
#
#       def get_transformation_matrix()
#         #This will transform the space vertices to normal space co-ordinates using Sketchup/OS convention
#         return OpenStudio::createTranslation(self.get_origin) * OpenStudio::Transformation::rotation(OpenStudio::Vector3d.new(0.0, 0.0, 1.0), OpenStudio::degToRad(360.0 - self.get_azimuth()))
#       end
#
#       def get_rotation_matrix()
#         return OpenStudio::Transformation::rotation(OpenStudio::Vector3d.new(0.0, 0.0, 1.0), OpenStudio::degToRad(360.0 - self.get_azimuth()))
#       end
#
#       def convert_to_openstudio(model,runner = nil)
#         if self.get_keyword_value("SHAPE") == "NO-SHAPE"
#           BTAP::runner_register("Info", "OpenStudio does not support NO-SHAPE SPACE definitions currently. Not importing the space #{self.name}.",runner)
#         else
#           os_space = OpenStudio::Model::Space.new(model)
#           os_space.setName(self.name)
#           #set floor
#           os_space.setBuildingStory(OpenStudio::Model::getBuildingStoryByName(model,self.get_parent("FLOOR").name).get)
#           BTAP::runner_register("Info", "\tSpace: " + self.name + " created",runner)
#           #puts "\t\t Azimuth:#{self.get_azimuth}"
#           #puts "\t\t Azimuth:#{self.get_origin}"
#         end
#       end
#
#     end
#     class DOEFloor < DOESurface
#       attr_accessor :polygon
#       # a string object which defines the type of roof (e.g. attic)
#       attr_accessor :type
#       # The absorptance of the exterior surface of the floor
#       # (see rule #4.3.5.3.(6)
#       attr_accessor :absorptance
#       # thermal insulation of floors
#       attr_accessor :thermal_insulation
#
#       def initialize
#         super()
#       end
#
#       #This method returns the floor area
#       def get_area
#
#         # get the keyword for the shape of the floor
#         case get_keyword_value("SHAPE")
#
#           # if the keyword value is "BOX", the width and depth values are defined
#         when "BOX"
#           return get_keyword_value("WIDTH").to_f * get_keyword_value("DEPTH").to_f
#
#           # if the keyword value is "POLYGON", the get_area is defined as the area of the
#           # given polygon
#         when "POLYGON"
#           return @polygon.get_area
#
#           # if the keyword value of the floor is "No-SHAPE", the get_area is given as the
#           # get_area keyword value
#         when "NO-SHAPE"
#           return get_keyword_value("AREA").to_f
#         else
#           raise "Error: The area could not be evaluated. Please check inputs\n "
#         end
#       end
#
#       # This method returns the volume of the floor space
#       def get_volume
#         return get_floor_height.to_f * get_area.to_f
#       end
#
#       # gets the height of the floor
#       def get_height
#         return get_keyword_value("FLOOR-HEIGHT").to_f
#       end
#
#       # gets the space height
#       def get_space_height
#         return get_keyword_value("SPACE-HEIGHT").to_f
#       end
#
#       def get_origin()
#         space_xref = self.check_keyword?("X")? self.get_keyword_value("X").to_f : 0.0
#         space_yref = self.check_keyword?("Y")? self.get_keyword_value("Y").to_f : 0.0
#         space_zref = self.check_keyword?("Z")? self.get_keyword_value("Z").to_f : 0.0
#         return OpenStudio::Vector3d.new(space_xref,space_yref,space_zref)
#       end
#
#       def get_azimuth()
#         return self.check_keyword?("AZIMUTH")? self.get_keyword_value("AZIMUTH").to_f : 0.0
#       end
#
#       def get_transformation_matrix()
#         return OpenStudio::createTranslation(self.get_origin) * OpenStudio::Transformation::rotation(OpenStudio::Vector3d.new(0.0, 0.0, 1.0), OpenStudio::degToRad(360.0 - self.get_azimuth()))
#       end
#
#       def get_rotation_matrix()
#         return OpenStudio::Transformation::rotation(OpenStudio::Vector3d.new(0.0, 0.0, 1.0), OpenStudio::degToRad(360.0 - self.get_azimuth()))
#       end
#
#       def convert_to_openstudio(model,runner = nil)
#         floor = OpenStudio::Model::BuildingStory.new(model)
#         floor.setName(self.name)
#         BTAP::runner_register("Info", "\tBuildingStory: " + self.name + " created",runner)
#       end
#
#     end
#     #This class makes it easier to deal with DOE Polygons.
#     class DOEPolygon < DOECommand
#
#       attr_accessor :point_list
#
#       #The constructor.
#       def initialize
#         super()
#         @point_list = Array.new()
#         #Convert Keywork Pairs to points.
#
#       end
#
#       def create_point_list()
#
#         #Convert Keywork Pairs to points.
#         @point_list.clear
#         @keywordPairs.each do |array|
#
#           array[1].match(/\(\s*(\-?\d*\.?\d*)\s*\,\s*(\-?\d*\.?\d*)\s*\)/)
#           #puts array[1]
#
#           point = OpenStudio::Point3d.new($1.to_f,$2.to_f,0.0)
#           @point_list.push(point)
#         end
#         #      @point_list.each do |p|
#         #        puts p.x.to_s + " " + p.y.to_s + " " + p.z.to_s + " "
#         #      end
#       end
#
#       # This method returns the area of the polygon.
#       def get_area
#         openstudio::getArea(@points_list)
#       end
#
#
#       # This method must determine the length of the given point to the next point
#       # in the polygon list. If the point is the last point, then it will be the
#       # distance from the last point to the first.
#       # point_name is the string named keyword in the keyword pair list.
#       # Example:
#       # "DOEPolygon 2" = POLYGON
#       #   V1               = ( 0, 0 )
#       #   V2               = ( 0, 1 )
#       #   V3               = ( 2, 1 )
#       #   V4               = ( 2 ,0 )
#       # get_length(3) should return "2"
#       # get_length(2) should return "1"
#
#       def get_length(point_index)
#         if @points_list.size < pointindex + 2
#           return OpenStudio::getDistance(@point_list[0],@point_list.last)
#         else
#           return OpenStudio::getDistance(@point_list[point_index],@point_list[point_index + 1] )
#         end
#       end
#
#
#       def get_azimuth(point_index)
#         if @points_list.size < pointindex + 2
#           return OpenStudio::radToDeg(OpenStudio::getAngle(@point_list.last - @point_list[0] , openstudio::Vector3d( 1.0, 0.0, 0.0)))
#         else
#           return OpenStudio::radToDeg(OpenStudio::getAngle(@point_list[point_index + 1] - @point_list[point_index] , openstudio::Vector3d( 1.0, 0.0, 0.0)))
#         end
#       end
#
#     end
#     class DOELayer < DOECommand
#       # type of material (see rule #4.3.5.2.(3))
#       attr_accessor :material
#       # the thickness of the material (see rule #4.3.5.2.(3))
#       attr_accessor :thickness
#       def initialize
#         super()
#       end
#     end
#     class DOEMaterial < DOECommand
#       # characteristics of the materials
#       attr_accessor :density
#       attr_accessor :specific_heat
#       attr_accessor :thermal_conductivity
#       def initialize
#         super()
#       end
#     end
#     class DOEConstruction < DOECommand
#
#       def initialize
#         super()
#       end
#
#       def get_materials()
#         bdllib = DOE2::DOEBDLlib.instance
#         materials = Array.new
#
#         case self.get_keyword_value("TYPE")
#         when "LAYERS"
#           # finds the command associated with the layers keyword
#           layers_command = building.find_command_with_utype( self.get_keyword_value("LAYERS") )
#
#           #if Layres command cannot be found in the inp file... find it in the bdl database.
#           layers_command = bdllib.find_layer(self.get_keyword_value("LAYERS")) unless layers_command.length == 1
#
#           # if there ends up to be more than one command with the layers keyword
#           # raise an exception
#           raise "Layers was defined more than once " + self.get_keyword_value("LAYERS").to_s if layers_command.length > 1
#
#           # get all the materials, separate it by the quotation marks and push it
#           # onto the materials array
#           layers_command[0].get_keyword_value("MATERIAL").scan(/(\".*?\")/).each do |material|
#             material_command = ""
#
#             #Try to find material in doe model.
#             material_command_array = building.find_command_with_utype(material.to_s.strip)
#
#             # if there ends up to be more than one, raise an exception
#             raise "Material was defined more than once #{material}" if material_command_array.length > 1
#
#             # if the material cannot be found within the model, find it within the doe2 database
#             material_command = bdllib.find_material(material) if material_command_array.length < 1
#
#             #If material was found then set it.
#             material_command = material_command_array[0] if material_command_array.length == 1
#
#             materials.push(material_command)
#           end
#           return materials
#         when "U-VALUE"
#           return nil
#         end
#       end
#
#       # This method finds the u-value of the given construction
#       # Output => total conductivity as a float
#       def get_u_value()
#         total_conductivity = 0.0
#         case self.get_keyword_value("TYPE")
#         when "LAYERS"
#           self.get_materials().each do |material_command|
#             case material_command.get_keyword_value("TYPE")
#             when  "RESISTANCE"
#               conductivity = 1 / material_command.get_keyword_value("RESISTANCE").to_f
#             when "PROPERTIES"
#               conductivity = material_command.get_keyword_value("CONDUCTIVITY").to_f
#             else
#               raise "Error in material properties"
#             end
#             total_conductivity = total_conductivity + conductivity
#           end
#           return total_conductivity
#         when "U-VALUE"
#           return self.get_keyword_value("U-VALUE").to_f
#         end
#       end
#
#
#     end
#     class DOECommandFactory
#       def initialize
#
#       end
#
#       def DOECommandFactory.command_factory(command_string, building)
#
#         command = ""
#         command_name = ""
#         if (command_string != "")
#           #Get command and u-value
#           if ( command_string.match(/(^\s*(\".*?\")\s*\=\s*(\S+)\s*)/) )
#             command_name=$3.strip
#           else
#             # if no u-value, get just the command.
#             command_string.match(/(^\s*(\S*)\s)/ )
#             @command_name=$2.strip
#
#           end
#         end
#         case command_name
#         when  "ZONE" then
#           command = DOEZone.new()
#         when  "FLOOR" then
#           command = DOEFloor.new()
#         when  "SPACE" then
#           command = DOESpace.new()
#         when  "EXTERIOR-WALL" then
#           command = DOEExteriorWall.new()
#         when  "INTERIOR-WALL" then
#           command = DOESurface.new()
#         when  "UNDERGROUND-WALL" then
#           command = DOESurface.new()
#         when  "ROOF" then
#           command = DOERoof.new()
#         when "WINDOW" then
#           command = DOESubSurface.new()
#         when "DOOR" then
#           command = DOESubSurface.new()
#         when "POLYGON" then
#           command = DOEPolygon.new()
#         when "LAYER" then
#           command = DOELayer.new()
#         when "MATERIAL" then
#           command = DOEMaterial.new()
#         when "CONSTRUCTION" then
#           command = DOEConstruction.new()
#         else
#           command = DOECommand.new()
#         end
#
#         command.get_command_from_string(command_string)
#         command.building = building
#         return command
#       end
#     end
#
#     # This is the main interface dealing with DOE inp files. You can load, save
#     # manipulate doe files with this interface at a command level.
#     class DOEBuilding
#
#       #An array to contain all the DOE
#       attr_accessor  :commands
#       #An array to contain the current parent when reading in the input files.
#       attr_accessor  :parents
#
#
#       # This method makes a deep copy of the building object.
#       def clone
#         return Marshal::load(Marshal.dump(self))
#       end
#
#       # The Constructor.
#       def initialize
#
#         @commands=[]
#         @parents=[]
#         @commandList = Array.new()
#
#       end
#
#       # This method will find all Commands given the command name string.
#       # Example
#       # def find_all_Command("ZONE")  will return an array of all the ZONE commands
#       # used in the building.
#       def find_all_commands (sCOMMAND)
#         array = Array.new()
#         @commands.each do |command|
#           if (command.commandName == sCOMMAND)
#             array.push(command)
#           end
#         end
#         return array
#       end
#
#       # This method will find all Commands given the command name string.
#       # Example
#       # def find_all_Command("Default Construction")  will return an array of all
#       # the commands with "Default Construction" as the u-type used in the building.
#       def find_command_with_utype (utype)
#         array = Array.new()
#         @commands.each do |command|
#           if (command.utype == utype)
#             array.push(command)
#           end
#         end
#         return array
#       end
#
#
#       # Same as find_all_commands except you can use regular expressions.
#       def find_all_regex(sCOMMAND)
#         array = Array.new()
#         search =/#{sCOMMAND}/
#         @commands.each do |command|
#           if (command.commandName.match(search) )
#             array.push(command)
#           end
#
#         end
#         return array
#       end
#
#       # Find a matching keyword value pair in from an array of commands.
#       # Example:
#       # find_keyword_value(building.commands, "TYPE", "CONDITIONED")  will return
#       # all the commands that have the
#       # TYPE = CONDITIONED"
#       # Keyword pair.
#       def search_by_keyword_value( keyword, value)
#         returnarray = Array.new()
#         @commands.each do |command|
#           if ( command.keywordPairs[keyword] == value )
#             returnarray.push(command)
#           end
#         end
#         return returnarray
#       end
#
#
#       # Will read an input file into memory and store all the commands into the
#       # commands array.
#       # param filename
#       # param runner
#       def load_inp(filename,runner = nil)
#         BTAP::runner_register("Info", "loading file:" + filename, runner)
#         #Open the file.
#         #puts filename
#         iter = 0
#
#
#         File.exist?(filename)
#         f = File.open(filename, "r")
#
#
#
#
#         #Read the file into an array, line by line.
#         lines = f.readlines
#         #Set up the temp string.
#         command_string =""
#
#         lines.each do|line|
#           iter = iter.next
#           #line.forced_encoding("US-ASCII")
#           #Ignore comments (To do!...strip from file as well as in-line comments.
#           if (!line.match(/\$.*/) )
#
#             if (myarray = line.match(/(.*?)\.\./) )
#               #Add the last part of the command to the newline...may be blank."
#               command_string = command_string + myarray[1]
#               #Determine correct command class to create, then populates it."
#               command = DOECommandFactory.command_factory(command_string, self)
#               #Push the command into the command array."
#               @commands.push(command)
#               command_string = ""
#             else
#               myarray = line.match(/(.*)/)
#               command_string = command_string + myarray[1]
#             end
#           end
#         end
#
#         organize_data()
#         BTAP::runner_register("Info","INP model contains:", runner)
#         #report number of things read in.
#         ["SPACE","ZONE","EXTERIOR-WALL","ROOF","INTERIOR-WALL","UNDERGROUND-WALL","WINDOW","DOOR","MATERIAL","CONSTRUCTION"].each do |item|
#           items = self.find_all_commands(item)
#           message = "\t#{item} = #{items.size}"
#           BTAP::runner_register("Info",message, runner)
#         end
#         BTAP::runner_register("Info", "\tFinished Loading File:" + filename,runner)
#       end
#
#
#
#       # This will right a clean output file, meaning no comments. Good for doing
#       # diffs
#       def save_inp(string)
#         array = @commands
#         w = File.open(string, 'w')
#         array.each { |command| w.print command.output }
#         w.close
#       end
#
#
#
#
#
#       #This routine organizes the hierarchy of the space <-> zones and the polygon
#       # associations that are not formally identified by the sequential relationship
#       # like the floor, walls, windows. It would seem that zones and spaces are 1 to
#       # one relationships.  So each zone will have a reference to its space and vice versa.
#       # If there is a polygon command in the space or floor definition, a reference to the
#       # polygon class will be set.
#       def organize_data()
#         # set_envelope_hierarchy
#         # This method determines the current parents of the current command.
#         def determine_current_parents(new_command)
#           if @last_command.nil?
#             @last_command = new_command
#           end
#           #Check to see if scope (HVAC versus Envelope) has changed or the parent depth is undefined "0"
#           if (!@parents.empty? and (new_command.doe_scope != @parents.last.doe_scope or new_command.depth == 0 ))
#             @parents.clear
#           end
#           #no change in parent.
#           if ( (new_command.depth  == @last_command.depth))
#             #no change
#             @last_command = new_command
#             #puts "#{new_command.commandName}"
#           end
#           #Parent depth added
#           if ( new_command.depth  > @last_command.depth)
#             @parents.push(@last_command)
#             #puts "Added parent#{@last_command.commandName}"
#             @last_command = new_command
#           end
#           #parent depth removed.
#           if ( new_command.depth  < @last_command.depth)
#             parent = @parents.pop
#             #puts "Removed parent #{parent}"
#             @last_command = new_command
#           end
#           array = Array.new(@parents)
#           return array
#         end
#
#
#         @commands.each do |command|
#           if command.doe_scope() == "envelope"
#             #Sets parents of command.
#             parents = determine_current_parents(command)
#             if (!parents.empty?)
#               command.parents = parents
#             end
#             #inserts current command into the parent's children.
#             if (!command.parents.empty?)
#               command.parents.last.children.push(command)
#             end
#           end
#         end
#         # Associating the polygons with the FLoor and spaces.
#         polygons =  find_all_commands("POLYGON")
#         spaces = find_all_commands("SPACE")
#         floors = find_all_commands("FLOOR")
#         zones = find_all_commands("ZONE")
#         ext_walls = find_all_commands("EXTERIOR-WALL")
#         roof = find_all_commands("ROOF")
#         door = find_all_commands("DOOR")
#         int_walls = find_all_commands("INTERIOR-WALL")
#         underground_walls = find_all_commands("UNDERGROUND-WALL")
#         underground_floors = find_all_commands("UNDERGROUND-FLOOR")
#         constructions =find_all_commands("CONSTRUCTION")
#         surface_lists = [ ext_walls, roof, door, int_walls, underground_walls, underground_floors]
#
#
#         #Organize surface data.
#         surface_lists.each do |surfaces|
#           surfaces.each do |surface|
#             #Assign constructions to surface objects
#             constructions.each do |construction|
#               if ( construction.utype == surface.get_keyword_value("CONSTRUCTION") )
#                 surface.construction = construction
#               end
#             end
#             #Find Polygons associated with surface.
#             polygons.each do |polygon|
#               if ( surface.check_keyword?("POLYGON") and polygon.utype == surface.get_keyword_value("POLYGON")  )
#                 surface.polygon = polygon
#               end
#             end
#           end
#         end
#
#
#
#         #Organize polygon data for space and floors.
#         polygons.each do |polygon|
#           #set up point list in polygon objects
#           polygon.create_point_list()
#           #Find Polygons associated with  floor and and reference to floor.
#           floors.each do |floor|
#             if ( polygon.utype == floor.get_keyword_value("POLYGON") )
#               floor.polygon = polygon
#             end
#           end
#           #Find Polygons for space and add reference to the space.
#           spaces.sort.each do |space|
#             if space.check_keyword?("POLYGON")
#               if ( polygon.utype == space.get_keyword_value("POLYGON") )
#                 space.polygon = polygon
#               end
#             end
#           end
#         end
#
#
#
#         #    Find spaces that belong to the zone.
#         zones.each do |zone|
#           spaces.sort.each do |space|
#             if ( space.utype ==  zone.get_keyword_value("SPACE") )
#               space.zone = zone
#               zone.space = space
#             end
#           end
#         end
#       end
#
#
#
#       def get_building_transformation_matrix()
#         build_params = self.find_all_commands("BUILD-PARAMETERS")[0]
#         building_xref = build_params.check_keyword?("X-REF")? build_params.get_keyword?("X-REF") : 0.0
#         building_yref = build_params.check_keyword?("Y-REF")? build_params.get_keyword?("Y-REF") : 0.0
#         building_origin = OpenStudio::Vector3d.new(building_xref,building_yref,0.0)
#         building_azimuth = build_params.check_keyword?("AZIMUTH")? build_params.get_keyword?("AZIMUTH") : 0.0
#         return  OpenStudio::Transformation::rotation(OpenStudio::Vector3d(0.0, 0.0, 1.0), openstudio::degToRad(building_azimuth)) * OpenStudio::Transformation::translation(building_origin)
#       end
#
#
#
#
#       #this method will convert a DOE inp file to the OSM file.. This will return
#       # and openstudio model object.
#       def create_openstudio_model_new(runner = nil)
#         beginning_time = Time.now
#
#         end_time = Time.now
#         BTAP::runner_register("Info", "Time elapsed #{(end_time - beginning_time)*1000} milliseconds",runner)
#         model = OpenStudio::Model::Model.new()
#         #add All Materials
#         #    find_all_commands( "Materials" ).each do |doe_material|
#         #    end
#         #
#         #    find_all_commands( "Constructions" ).each do |doe_cons|
#         #    end
#
#         #this block will create OS story objects in the OS model.
#         BTAP::runner_register("Info", "Exporting DOE FLOORS to OS",runner)
#         find_all_commands("FLOOR").each do |doe_floor|
#           doe_floor.convert_to_openstudio(model)
#         end
#         BTAP::runner_register("Info", OpenStudio::Model::getBuildingStorys(model).size.to_s + " floors created",runner)
#
#         #this block will create OS space objects in the OS model.
#         BTAP::runner_register("Info", "Exporting DOE SPACES to OS",runner)
#         find_all_commands("SPACE").each do |doe_space|
#           doe_space.convert_to_openstudio(model)
#         end
#         BTAP::runner_register("Info", OpenStudio::Model::getSpaces(model).size.to_s + " spaces created",runner)
#
#         #this block will create OS space objects in the OS model.
#         BTAP::runner_register("Info", "Exporting DOE ZONES to OS",runner)
#         find_all_commands("ZONE").each do |doe_zone|
#           doe_zone.convert_to_openstudio(model)
#         end
#         BTAP::runner_register("Info", OpenStudio::Model::getThermalZones(model).size.to_s + " zones created",runner)
#
#         #this block will create OS surface objects in the OS model.
#         BTAP::runner_register("Info", "Exporting DOE Surfaces to OS",runner)
#         all_surfaces = Array.new()
#         @commands.each do |command|
#           case command.commandName
#           when "EXTERIOR-WALL","INTERIOR-WALL","UNDERGROUND-WALL","ROOF"
#             all_surfaces.push(command)
#           end
#         end
#         all_surfaces.each do |doe_surface|
#           doe_surface.convert_to_openstudio(model)
#         end
#         BTAP::runner_register("Info", OpenStudio::Model::getSurfaces(model).size.to_s + " surfaces created",runner)
#         BTAP::runner_register("Info", OpenStudio::Model::getSubSurfaces(model).size.to_s + " sub_surfaces created",runner)
#         BTAP::runner_register("Info", "Setting Boundary Conditions for surfaces",runner)
#         BTAP::Geometry::match_surfaces(model)
#
#         x_scale = y_scale = z_scale = 0.3048
#         BTAP::runner_register("Info", "scaling model from feet to meters",runner)
#         model.getPlanarSurfaces.sort.each do |surface|
#           new_vertices = OpenStudio::Point3dVector.new
#           surface.vertices.each do |vertex|
#             new_vertices << OpenStudio::Point3d.new(vertex.x * x_scale, vertex.y * y_scale, vertex.z * z_scale)
#           end
#           surface.setVertices(new_vertices)
#         end
#
#         model.getPlanarSurfaceGroups.sort.each do |surface_group|
#           transformation = surface_group.transformation
#           translation = transformation.translation
#           euler_angles = transformation.eulerAngles
#           new_translation = OpenStudio::Vector3d.new(translation.x * x_scale, translation.y * y_scale, translation.z * z_scale)
#           #TODO these might be in the wrong order
#           new_transformation = OpenStudio::createRotation(euler_angles) * OpenStudio::createTranslation(new_translation)
#           surface_group.setTransformation(new_transformation)
#         end
#         BTAP::runner_register("Info", "DOE2.2 -> OS Geometry Conversion Complete",runner)
#         BTAP::runner_register("Info", "Summary of Conversion",runner)
#         BTAP::runner_register("Info", OpenStudio::Model::getBuildingStorys(model).size.to_s + " floors created",runner)
#         BTAP::runner_register("Info", OpenStudio::Model::getSpaces(model).size.to_s + " spaces created",runner)
#         BTAP::runner_register("Info", OpenStudio::Model::getThermalZones(model).size.to_s + " thermal zones created",runner)
#         BTAP::runner_register("Info", OpenStudio::Model::getSurfaces(model).size.to_s + " surfaces created",runner)
#         BTAP::runner_register("Info", OpenStudio::Model::getSubSurfaces(model).size.to_s + " sub_surfaces created",runner)
#         BTAP::runner_register("Info", "No Contruction were converted.",runner)
#         BTAP::runner_register("Info", "No Materials were converted",runner)
#         BTAP::runner_register("Info", "No HVAC components were converted",runner)
#         BTAP::runner_register("Info", "No Environment or Simulation setting were converted.",runner)
#
#         end_time = Time.now
#         BTAP::runner_register("Info", "Time elapsed #{(end_time - beginning_time)} seconds",runner)
#         return model
#       end
#
#
#
#
#
#       def get_materials()
#         BTAP::runner_register("Info", "Spaces",runner)
#         find_all_commands("SPACE").each do |space|
#           BTAP::runner_register("Info", space.get_azimuth(),runner)
#         end
#         BTAP::runner_register("Info", "Materials",runner)
#         find_all_commands("MATERIAL").each do |materials|
#           BTAP::runner_register("Info", materials.get_name(),runner)
#         end
#         BTAP::runner_register("Info", "Layers",runner)
#         find_all_commands("LAYERS").each do |materials|
#           BTAP::runner_register("Info", materials.get_name(),runner)
#         end
#         BTAP::runner_register("Info", "Constructions",runner)
#         find_all_commands("CONSTRUCTION").each do |materials|
#           BTAP::runner_register("Info", materials.get_name(),runner)
#         end
#
#       end
#
#
#     end
#     # This class will manage all the layer information of the Reference components.
#     class LayerManager
#       include Singleton
#       class Layer
#
#         attr_accessor :name
#         attr_accessor :thickness
#         attr_accessor :conductivity
#         attr_accessor :density
#         attr_accessor :specific_heat
#         attr_accessor :air_space
#         attr_accessor :resistance
#         def initialize
#           @air_space = false
#         end
#
#         def set( thickness, conductivity, density, specific_heat)
#           @thickness, @conductivity, @density, @specific_heat =  thickness, conductivity, density, specific_heat
#           @airspace = false
#         end
#
#         def set_air_space(thickness, resistance)
#           @thickness, @resistance = thickness, resistance
#           @air_space = true
#         end
#
#         def output
#           string = "Airspace = #{@air_space}\nThickness = #{@thickness}\nConductivity = #{@conductivity}\nResistance = #{@resistance}\nDensity = #{@density}\nSpecificHeat = #{@specific_heat}\n"
#         end
#       end
#       # Array of all the layers
#       attr_accessor :layers
#       def initialize
#         @layers = Array.new()
#       end
#
#       #Add a layer. If the layer already exists. It will return the exi
#       def add_layer(new_layer)
#         #first determine if the layer already exists.
#         @layers.each do  |current_layer|
#           if new_layer == current_layer
#             return current_layer
#           end
#         end
#         @layers.push(new_layer)
#         return @layers.last()
#       end
#
#       private
#
#       def clear()
#         @layers.clear()
#       end
#     end
#     #This class manages all of the constructions that are used in the simulation. It
#     #should remove any constructions that are doubly defined in the project.
#     class ConstructionManager
#       # An array containing all the constructions.
#       attr_accessor :constructions
#
#       # The layer manager all the constructions.
#       attr_accessor :layer_manager
#       class Construction
#
#         #The unique name for the construction.
#         attr_accessor :name
#         #The array which contains the material layers of the construction.
#         attr_accessor :layers
#
#         def initialize
#           #Set up the array for the layers.
#           @layers = Array.new()
#         end
#
#         #Adds a layer object to the construction.
#         # Must pass a Layer object as an arg.
#         def add_layer_object( object )
#           layers.push( object )
#         end
#
#         #Adds a layer based on the physical properties list.
#         #All units are based on the simulators input.
#         def add_layer(thickness, conductivity, density, specific_heat)
#           layer = Layer.new()
#           # Make sure all the values are > 0.
#           layer.set(thickness, conductivity, density, specific_heat)
#           @layers.push(layer)
#         end
#
#         # Adds an airspace to the construction based on the thickness and Resistances.
#         #All units are based on the simulators input.
#         def add_air_space(thickness, resistance )
#           layer = Layer.new()
#           layer.set_air_space(thickness, resistance)
#           @layers.push(layer)
#         end
#
#         def output()
#           soutput = ""
#           @layers.each do|layer|
#             soutput = soutput + layer.output() + "\n"
#           end
#           soutput
#         end
#       end
#
#
#       def initialize
#         @constructions = Array.new()
#         @layer_manager = LayerManager.instance()
#       end
#
#
#       #Adds a new construction to the construction array.
#       #Arg must be a construction object.
#       def add_construction(new_construction)
#         #first determine if the layer already exists.
#         @constructions.each do  |current_construction|
#           if new_construction == current_construction
#             return current_construction
#           end
#         end
#         new_construction.layers.each do |new_layer|
#           #If the new layer already exists...use the old one instead.
#           # it is the layerManager's job to decide this.
#           new_layer = @layer_manager.add_layer(new_layer)
#         end
#         @constructions.push(new_construction)
#         return @constructions.last()
#       end
#
#       def clear()
#         @constructions.clear()
#         @layer_manager.clear()
#       end
#
#     end
#   end
# end
#