lib/openstudio-standards/geometry/modify.rb in openstudio-standards-0.5.0 vs lib/openstudio-standards/geometry/modify.rb in openstudio-standards-0.6.0.rc1

- old
+ new

@@ -1,48 +1,156 @@ -# Methods to modify geometry module OpenstudioStandards + # This Module provides methods to create, modify, and get information about model geometry module Geometry - # @!group Modify + # Methods to modify geometry - # lower z value of vertices with starting value above z_value_target to z_value_target + # @!group Modify:SubSurface + + # Reduce the area of the subsurface by shrinking it toward the centroid + # @author Julien Marrec # - # @param surfaces [Array<OpenStudio::Model::Surface>] array of Surface objects - # @param z_value_target [Double] - # @return [Array] array of z values in meters - def self.surfaces_lower_z_values(surfaces, z_value_target) - count = 0 + # @param sub_surface [OpenStudio::Model::SubSurface] OpenStudio SubSurface object + # @param percent_reduction [Double] the fractional amount to reduce the area + # @return [Boolean] returns true if successful, false if not + def self.sub_surface_reduce_area_by_percent_by_shrinking_toward_centroid(sub_surface, percent_reduction) + # if percent_reduction > 1=> percent increase instead of reduction + mult = percent_reduction <= 1 ? 1 - percent_reduction : percent_reduction + scale_factor = mult**0.5 - # loop over all surfaces - surfaces.each do |surface| - # create a new set of vertices - new_vertices = OpenStudio::Point3dVector.new + # Get the centroid (Point3d) + g = sub_surface.centroid - # get the existing vertices for this interior partition - vertices = surface.vertices - flag = false - vertices.each do |vertex| - # initialize new vertex to old vertex - x = vertex.x - y = vertex.y - z = vertex.z + # Create an array to collect the new vertices + new_vertices = [] - # if this z vertex is not on the z = 0 plane - if z > z_value_target - z = z_value_target - flag = true - end + # Loop on vertices (Point3ds) + sub_surface.vertices.each do |vertex| + # Point3d - Point3d = Vector3d + # Vector from centroid to vertex (GA, GB, GC, etc) + centroid_vector = vertex - g - # add point to new vertices - new_vertices << OpenStudio::Point3d.new(x, y, z) + # Resize the vector (done in place) according to scale_factor + centroid_vector.setLength(centroid_vector.length * scale_factor) + + # Move the vertex toward the centroid + vertex = g + centroid_vector + + new_vertices << vertex + end + + # Assign the new vertices to the self + sub_surface.setVertices(new_vertices) + + return true + end + + # Reduce the area of the subsurface by raising the sill height + # + # @param sub_surface [OpenStudio::Model::SubSurface] OpenStudio SubSurface object + # @param percent_reduction [Double] the fractional amount to reduce the area + # @return [Boolean] returns true if successful, false if not + def self.sub_surface_reduce_area_by_percent_by_raising_sill(sub_surface, percent_reduction) + # Find the min and max z values + min_z_val = 99_999 + max_z_val = -99_999 + sub_surface.vertices.each do |vertex| + # Min z value + if vertex.z < min_z_val + min_z_val = vertex.z end + # Max z value + if vertex.z > max_z_val + max_z_val = vertex.z + end + end - # set vertices to new vertices - # @todo check if this was made, and issue warning if it was not. Could happen if resulting surface not planer. - surface.setVertices(new_vertices) + # Calculate the window height + height = max_z_val - min_z_val - count += 1 if flag + # Calculate the new sill height + z_delta = height * percent_reduction + + # Reset the z value of the lowest points within a certain threshold + new_vertices = [] + sub_surface.vertices.each do |vertex| + if (vertex.z - min_z_val).abs < 0.025 + new_vertices << vertex + OpenStudio::Vector3d.new(0.0, 0.0, z_delta) + else + new_vertices << vertex + end end - return count + # Reset the vertices + sub_surface.setVertices(new_vertices) + + return true end + + # @!endgroup Modify:SubSurface + + # @!group Modify:Model + + # Assign each space in the model to a building story based on common z (height) values. + # If no story object is found for a particular height, create a new one and assign it to the space. + # Does not assign a story to plenum spaces. + # + # @param model [OpenStudio::Model::Model] OpenStudio model object + # @return [Boolean] returns true if successful, false if not + def self.model_assign_spaces_to_building_stories(model) + # Make hash of spaces and min z values + sorted_spaces = {} + model.getSpaces.sort.each do |space| + # Skip plenum spaces + next if OpenstudioStandards::Space.space_plenum?(space) + + # loop through space surfaces to find min z value + z_points = [] + space.surfaces.each do |surface| + surface.vertices.each do |vertex| + z_points << vertex.z + end + end + min_z = z_points.min + space.zOrigin + sorted_spaces[space] = min_z + end + + # Pre-sort spaces + sorted_spaces = sorted_spaces.sort_by { |a| a[1] } + + # Take the sorted list and assign/make stories + sorted_spaces.each do |space| + space_obj = space[0] + space_min_z = space[1] + if space_obj.buildingStory.empty? + tolerance = 0.3 + story = OpenstudioStandards::Geometry.model_get_building_story_for_nominal_height(model, space_min_z, tolerance: tolerance) + if story.nil? + story = OpenStudio::Model::BuildingStory.new(model) + story.setNominalZCoordinate(space_min_z) + story.setName("Building Story #{space_min_z.round(1)}m") + OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Model', "No story with a min z value of #{space_min_z.round(2)} m +/- #{tolerance} m was found, so a new story called #{story.name} was created.") + end + space_obj.setBuildingStory(story) + OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Model', "Space #{space[0].name} was not assigned to a story by the user. It has been assigned to #{story.name}.") + end + end + + return true + end + + # Set the model's north axis (degrees from true North) + # + # @param model [OpenStudio::Model::Model] OpenStudio Model object + # @param north_axis [Float] Degrees from true North + # @return [Boolean] Returns true if successful, false otherwise + def self.model_set_building_north_axis(model, north_axis) + return false if north_axis.nil? + + building = model.getBuilding + building.setNorthAxis(north_axis) + + return true + end + + # @!endgroup Modify:Model end end