Module: BTAP::Geometry::Surfaces
- Defined in:
- lib/openstudio-standards/btap/geometry.rb
Class Method Summary collapse
- .create_surface(model, name, os_point3d_array, boundary_condition = "", construction = "") ⇒ Object
-
.filter_by_azimuth_and_tilt(surfaces, azimuth_from, azimuth_to, tilt_from, tilt_to, tolerance = 1.0) ⇒ Object
Azimuth start from Y axis, Tilts starts from Z-axis.
- .filter_by_boundary_condition(surfaces, boundary_conditions) ⇒ Object
- .filter_by_interzonal_surface(surfaces) ⇒ Object
- .filter_by_non_defaulted_surfaces(surfaces) ⇒ Object
- .filter_by_surface_types(surfaces, surfaceTypes) ⇒ Object
-
.filter_subsurfaces_by_types(subsurfaces, subSurfaceTypes) ⇒ Object
[“FixedWindow” , “OperableWindow” , “Door” , “GlassDoor”, “OverheadDoor” , “Skylight”, “TubularDaylightDiffuser”,“TubularDaylightDome”].
-
.get_overlapping_segments(overlap_segs:, index:, point_a1:, point_a2:) ⇒ Object
This method takes the y projections of a bunch of overlapping line segments and sorts them to determines which are unique and, if they are not unique, which is closest to the current, upwardly pointing, line.
- .get_sub_surface_net_area(subsurface) ⇒ Object
- .get_subsurfaces_from_surfaces(surface_array) ⇒ Object
-
.get_surface_construction_conductance(surface) ⇒ Object
This method creates a new construction based on the current, changes the rsi and assign the construction to the current surface.
-
.get_surface_construction_shgc(surface) ⇒ Object
This method gets the shgc for a surface.
-
.get_surface_construction_tvis(surface) ⇒ Object
This method gets the tvis for the surface.
- .get_surface_net_area(surface) ⇒ Object
- .get_surfaces_from_building_stories(model, story_array) ⇒ Object
- .get_surfaces_from_spaces(spaces_array) ⇒ Object
- .get_surfaces_from_thermal_zones(thermal_zone_array) ⇒ Object
- .get_total_ext_fenestration_area(model) ⇒ Object
- .get_total_ext_floor_area(model) ⇒ Object
- .get_total_ext_roof_area(model) ⇒ Object
-
.get_total_ext_wall_area(model) ⇒ Object
get total exterior surface area of building.
-
.get_weighted_average_surface_conductance(surfaces) ⇒ Object
determine average conductance on set of surfaces or subsurfaces.
-
.get_weighted_average_surface_shgc(surfaces) ⇒ Object
determine average conductance on set of surfaces or subsurfaces.
-
.get_weighted_average_surface_tvis(surfaces) ⇒ Object
determine average conductance on set of surfaces or subsurfaces.
-
.getSurfaceAreafromVertices(vertices:) ⇒ Object
This method calculates the surface area of a 2-D polygon from an array of OpenStudio vertices.
- .hide(surfaces) ⇒ Object
-
.line_segment_overlap_x_coord(y_check:, point_b1:, point_b2:) ⇒ Object
This method determines the x coordinate of where a given y coordinate crosses a given line.
-
.line_segment_overlap_y?(point_a1:, point_a2:, point_b1:, point_b2:) ⇒ Boolean
This method determines if the y component of 2 lines overlap.
-
.make_convex_surfaces(surface:, tol: 12) ⇒ Object
2018-09-27 Chris Kirney This method takes a surface in the x-y plane (z coordinates are ignored) with an upwardly pointing normal and turns it into convex quadrialaterals.
-
.remove_all_subsurfaces(surfaces) ⇒ OpenStudio::Model::Model
This Method removes all the subsurfaces in a model (Windows, Doors ).
-
.rotate_tilt_translate_surfaces(planar_surfaces, azimuth_degrees, tilt_degrees = 0.0, translation_vector = OpenStudio::Vector3d.new(0.0, 0.0, 0.0)) ⇒ OpenStudio::Model::Model
This method will rotate a surface.
- .set_fenestration_to_wall_ratio(surfaces, ratio, offset = 0, height_offset_from_floor = true, floor = "all") ⇒ Object
-
.set_surfaces_boundary_condition(model, surfaces, boundaryCondition) ⇒ Object
This method sets the boundary condition for a surface and it’s matching surface.
- .set_surfaces_construction(surfaces, construction) ⇒ Object
-
.set_surfaces_construction_conductance(surfaces, conductance) ⇒ Object
This method creates a new construction based on the current, changes the rsi and assign the construction to the current surface.
- .show(surfaces) ⇒ Object
-
.subdivide_overlaps(overlap_segs:) ⇒ Object
This method was originally written to work with the ‘make_concave_surfaces’ method above.
-
.surf_centroid(surf:) ⇒ Object
This method finds the centroid of a surface using the point averaging method.
Class Method Details
.create_surface(model, name, os_point3d_array, boundary_condition = "", construction = "") ⇒ Object
2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2635 def self.create_surface(model, name, os_point3d_array, boundary_condition = "", construction = "") os_surface = OpenStudio::Model::Surface.new(os_point3d_array, model) os_surface.setName(name) if OpenStudio::Model::Surface::validOutsideBoundaryConditionValues.include?(boundary_condition) self.set_surfaces_boundary_condition([os_surface], boundary_condition) else puts "boundary condition not set for #{name}" end self.set_surfaces_construction([os_surface], construction) return os_surface end |
.filter_by_azimuth_and_tilt(surfaces, azimuth_from, azimuth_to, tilt_from, tilt_to, tolerance = 1.0) ⇒ Object
Azimuth start from Y axis, Tilts starts from Z-axis
2981 2982 2983 2984 2985 2986 2987 2988 2989 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2981 def self.filter_by_azimuth_and_tilt(surfaces, azimuth_from, azimuth_to, tilt_from, tilt_to, tolerance = 1.0) return_surfaces = [] surfaces.each do |surface| unless OpenStudio::Model::PlanarSurface::findPlanarSurfaces([surface], OpenStudio::OptionalDouble.new(azimuth_from), OpenStudio::OptionalDouble.new(azimuth_to), OpenStudio::OptionalDouble.new(tilt_from), OpenStudio::OptionalDouble.new(tilt_to), tolerance).empty? return_surfaces << surface end end return return_surfaces end |
.filter_by_boundary_condition(surfaces, boundary_conditions) ⇒ Object
2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2912 def self.filter_by_boundary_condition(surfaces, boundary_conditions) #check to see if a string or an array was passed. if boundary_conditions.kind_of?(String) temp = boundary_conditions boundary_conditions = Array.new() boundary_conditions.push(temp) end #ensure boundary conditions are valid boundary_conditions.each do |boundary_condition| unless OpenStudio::Model::Surface::validOutsideBoundaryConditionValues.include?(boundary_condition) raise "ERROR: Invalid Boundary Condition = " + boundary_condition + "Correct Values are:" + OpenStudio::Model::Surface::validOutsideBoundaryConditionValues.to_s end end #create return array. return_array = Array.new() if boundary_conditions.size == 0 or boundary_conditions[0].upcase == "All".upcase return_array = surfaces else surfaces.each do |surface| boundary_conditions.each do |condition| if surface.outsideBoundaryCondition == condition return_array.push(surface) end end end end return return_array end |
.filter_by_interzonal_surface(surfaces) ⇒ Object
2970 2971 2972 2973 2974 2975 2976 2977 2978 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2970 def self.filter_by_interzonal_surface(surfaces) return_array = Array.new() surfaces.each do |surface| unless surface.adjacentSurface().empty? return_array.push(surface) end return return_array end end |
.filter_by_non_defaulted_surfaces(surfaces) ⇒ Object
2905 2906 2907 2908 2909 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2905 def self.filter_by_non_defaulted_surfaces(surfaces) non_defaulted_surfaces = Array.new() surfaces.each {|surface| non_defaulted_surfaces << surface unless surface.isConstructionDefaulted} return non_defaulted_surfaces end |
.filter_by_surface_types(surfaces, surfaceTypes) ⇒ Object
2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2942 def self.filter_by_surface_types(surfaces, surfaceTypes) #check to see if a string or an array was passed. if surfaceTypes.kind_of?(String) temp = surfaceTypes surfaceTypes = Array.new() surfaceTypes.push(temp) end surfaceTypes.each do |surfaceType| unless OpenStudio::Model::Surface::validSurfaceTypeValues.include?(surfaceType) raise("ERROR: Invalid surface type = #{surfaceType} Correct Values are: #{OpenStudio::Model::Surface::validSurfaceTypeValues}") end end return_array = Array.new() if surfaceTypes.size == 0 or surfaceTypes[0].upcase == "All".upcase return_array = self else surfaces.each do |surface| surfaceTypes.each do |surfaceType| if surface.surfaceType == surfaceType return_array.push(surface) end end end end return return_array end |
.filter_subsurfaces_by_types(subsurfaces, subSurfaceTypes) ⇒ Object
- “FixedWindow” , “OperableWindow” , “Door” , “GlassDoor”, “OverheadDoor” , “Skylight”, “TubularDaylightDiffuser”,“TubularDaylightDome”
2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2790 def self.filter_subsurfaces_by_types(subsurfaces, subSurfaceTypes) #check to see if a string or an array was passed. if subSurfaceTypes.kind_of?(String) temp = subSurfaceTypes subSurfaceTypes = Array.new() subSurfaceTypes.push(temp) end subSurfaceTypes.each do |subSurfaceType| unless OpenStudio::Model::SubSurface::validSubSurfaceTypeValues.include?(subSurfaceType) raise("ERROR: Invalid surface type = #{subSurfaceType} Correct Values are: #{OpenStudio::Model::SubSurface::validSubSurfaceTypeValues}") end end return_array = Array.new() if subSurfaceTypes.size == 0 or subSurfaceTypes[0].upcase == "All".upcase return_array = self else subsurfaces.each do |subsurface| subSurfaceTypes.each do |subSurfaceType| if subsurface.subSurfaceType == subSurfaceType return_array.push(subsurface) end end end end return return_array end |
.get_overlapping_segments(overlap_segs:, index:, point_a1:, point_a2:) ⇒ Object
This method takes the y projections of a bunch of overlapping line segments and sorts them to determines which are unique and, if they are not unique, which is closest to the current, upwardly pointing, line. If several overlapping segments belong to the same line they are put together (after the ‘subdivide_overlaps’ method broke them apart). The end result is the method returns the closet point downward pointing line segments closest to the given upward pointing line segment.
overlap_segs: This is an array of hashes that looks like:
overlap_seg = {
index_a1: i,
index_a2: i-1,
index_b1: j,
index_b2: j-1,
point_b1: surf_verts[j],
point_b2: surf_verts[j-1],
overlap_y: overlap_y
}
index_a1: The index of the array of points that cooresponds with the top of line a (points up) index_a1: The index of the array of points that cooresponds with the bottom of line a (points up) index_b1: The index of the array of points that cooresponds with the bottom of line b (points down) index_b1: The index of the array of points that cooresponds with the top of line b (points down) point_b1: The coordinates of the bottom of line b point_b2: The coordinates of the top of line b
overlap_y: A hash that contains the coordinates of the top and bottom of the y projection of the overlapping lines (line a and line b)
overlap_y = {
overlap_start: overlap_start,
overlap_end: overlap_end
}
overlap_start: The y coordinate of the top of the overlap overlap_end: The y coordinate of the bottom of the overlap
index: The index of the array of points that cooresponds with the top of of the current upward pointing line.
point_a1: The coordinates of the top of the first line point_a2: The coordinates of the bottom of the first line This naming convention was chosen because this method was originally designed to work with the ‘make_concave_surfaces’ method (see above). That method choses lines that point up and then sees where they overlap with lines pointing down. The point_1 of each line is the end of the line. In this case a lines point up and b lines point down.
3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 3226 def self.get_overlapping_segments(overlap_segs:, index:, point_a1:, point_a2:) closest_overlaps = [] linea_overlaps = [] # This goes through all the line segments and determines which correspond to the current upward pointing line # segment(line a). It also determines the x coordinate distance between the top and bottom of the overlapping # portions of the line segments. curr_overlap_segs = overlap_segs.select { |seg| (seg[:index_a1] == index) && (seg[:index_a2] == (index - 1)) } curr_overlap_segs.each do |overlap_seg| line_a_x_top = line_segment_overlap_x_coord(y_check: overlap_seg[:overlap_y][:overlap_start], point_b1: point_a1, point_b2: point_a2) line_a_x_bottom = line_segment_overlap_x_coord(y_check: overlap_seg[:overlap_y][:overlap_end], point_b1: point_a1, point_b2: point_a2) line_b_x_top = line_segment_overlap_x_coord(y_check: overlap_seg[:overlap_y][:overlap_start], point_b1: overlap_seg[:point_b1], point_b2: overlap_seg[:point_b2]) line_b_x_bottom = line_segment_overlap_x_coord(y_check: overlap_seg[:overlap_y][:overlap_end], point_b1: overlap_seg[:point_b1], point_b2: overlap_seg[:point_b2]) x_distance_top = line_a_x_top - line_b_x_top x_distance_bottom = line_a_x_bottom - line_b_x_bottom linea_overlap = { dx_top: x_distance_top, dx_bottom: x_distance_bottom, overlap: overlap_seg } linea_overlaps << linea_overlap end # This sorts through the overlapping downward pointing line segments corresponding to the current upward pointing # line a. The overlapping downward pointing line segments closest to the current upward pointing line segment # are kept. The other are discarded. Unique overlapping line segments are kept as well. There should only be # unuique overlapping line segments or overlapping line segments that precisely match one another because of # the 'subdivide_overlaps' method which this method is supposed to work with. linea_overlaps.each do |line_a_overlap| overlaps = linea_overlaps.select { |seg| seg[:overlap][:overlap_y] == line_a_overlap[:overlap][:overlap_y]} if overlaps.size > 1 redundant_overlap = closest_overlaps.select { |dup_seg| dup_seg[:overlap_y] == overlaps[0][:overlap][:overlap_y] } closest_overlaps << (overlaps.min_by { |dup_seg| dup_seg[:dx_top] })[:overlap] if redundant_overlap.empty? elsif overlaps.size == 1 closest_overlaps << overlaps[0][:overlap] end end # This combines the line segments that belong together. These were broken apart because of the # 'subdivide_overlaps' method. overlap_exts = [closest_overlaps[0]] for j in 0..(closest_overlaps.length - 1) index = 0 found = false for l in 0..(overlap_exts.length - 1) if overlap_exts[l][:index_b1] == closest_overlaps[j][:index_b1] && overlap_exts[l][:index_b2] == closest_overlaps[j][:index_b2] index = l found = true break end end if found == false overlap_exts << closest_overlaps[j] index = overlap_exts.length - 1 end for k in 0..(closest_overlaps.length - 1) if (closest_overlaps[j][:index_b1] == closest_overlaps[k][:index_b1]) && (closest_overlaps[j][:index_b2] == closest_overlaps[k][:index_b2]) if closest_overlaps[k][:overlap_y][:overlap_start] >= overlap_exts[index][:overlap_y][:overlap_start] overlap_exts[index][:overlap_y][:overlap_start] = closest_overlaps[k][:overlap_y][:overlap_start] end if closest_overlaps[k][:overlap_y][:overlap_end] <= overlap_exts[index][:overlap_y][:overlap_end] overlap_exts[index][:overlap_y][:overlap_end] = closest_overlaps[k][:overlap_y][:overlap_end] end end end end return overlap_exts end |
.get_sub_surface_net_area(subsurface) ⇒ Object
2863 2864 2865 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2863 def self.get_sub_surface_net_area(subsurface) return subsurface.netArea() end |
.get_subsurfaces_from_surfaces(surface_array) ⇒ Object
2717 2718 2719 2720 2721 2722 2723 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2717 def self.get_subsurfaces_from_surfaces(surface_array) subsurfaces = Array.new() surface_array.each do |surface| subsurfaces.concat(surface.subSurfaces) end return subsurfaces end |
.get_surface_construction_conductance(surface) ⇒ Object
This method creates a new construction based on the current, changes the rsi and assign the construction to the current surface. Most of the meat of this method is in the construction class. Testing is done there.
2835 2836 2837 2838 2839 2840 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2835 def self.get_surface_construction_conductance(surface) #a bit of acrobatics to get the construction object from the ConstrustionBase object's name. construction = OpenStudio::Model::getConstructionByName(surface.model, surface.construction.get.name.to_s).get #create a new construction with the requested RSI value based on the current construction. return BTAP::Resources::Envelope::Constructions::get_conductance(construction) end |
.get_surface_construction_shgc(surface) ⇒ Object
This method gets the shgc for a surface
2843 2844 2845 2846 2847 2848 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2843 def self.get_surface_construction_shgc(surface) #a bit of acrobatics to get the construction object from the ConstrustionBase object's name. construction = OpenStudio::Model::getConstructionByName(surface.model, surface.construction.get.name.to_s).get #create a new construction with the requested RSI value based on the current construction. return BTAP::Resources::Envelope::Constructions::get_shgc(surface.model,construction) end |
.get_surface_construction_tvis(surface) ⇒ Object
This method gets the tvis for the surface
2851 2852 2853 2854 2855 2856 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2851 def self.get_surface_construction_tvis(surface) #a bit of acrobatics to get the construction object from the ConstrustionBase object's name. construction = OpenStudio::Model::getConstructionByName(surface.model, surface.construction.get.name.to_s).get #create a new construction with the requested RSI value based on the current construction. return BTAP::Resources::Envelope::Constructions::get_tvis(model,construction) end |
.get_surface_net_area(surface) ⇒ Object
2859 2860 2861 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2859 def self.get_surface_net_area(surface) return surface.netArea() end |
.get_surfaces_from_building_stories(model, story_array) ⇒ Object
2699 2700 2701 2702 2703 2704 2705 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2699 def self.get_surfaces_from_building_stories(model, story_array) surfaces = Array.new() BTAP::Geometry::Spaces::get_spaces_from_storeys(model, story_array).each do |space| surfaces.concat(space.surfaces()) end return surfaces end |
.get_surfaces_from_spaces(spaces_array) ⇒ Object
2691 2692 2693 2694 2695 2696 2697 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2691 def self.get_surfaces_from_spaces(spaces_array) surfaces = Array.new() spaces_array.each do |space| surfaces.concat(space.surfaces()) end return surfaces end |
.get_surfaces_from_thermal_zones(thermal_zone_array) ⇒ Object
2707 2708 2709 2710 2711 2712 2713 2714 2715 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2707 def self.get_surfaces_from_thermal_zones(thermal_zone_array) surfaces = Array.new() thermal_zone_array.each do |thermal_zone| thermal_zone.spaces.sort.each do |space| surfaces.concat(space.surfaces()) end return surfaces end end |
.get_total_ext_fenestration_area(model) ⇒ Object
2779 2780 2781 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2779 def self.get_total_ext_fenestration_area(model) end |
.get_total_ext_floor_area(model) ⇒ Object
2774 2775 2776 2777 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2774 def self.get_total_ext_floor_area(model) outdoor_floors = BTAP::Geometry::Surfaces::filter_by_surface_types(outdoor_surfaces, "Floor") end |
.get_total_ext_roof_area(model) ⇒ Object
2783 2784 2785 2786 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2783 def self.get_total_ext_roof_area(model) outdoor_roofs = BTAP::Geometry::Surfaces::filter_by_surface_types(outdoor_surfaces, "RoofCeiling") end |
.get_total_ext_wall_area(model) ⇒ Object
get total exterior surface area of building.
2767 2768 2769 2770 2771 2772 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2767 def self.get_total_ext_wall_area(model) outdoor_surfaces = BTAP::Geometry::Surfaces::filter_by_boundary_condition(model.getSurfaces(), "Outdoors") outdoor_walls = BTAP::Geometry::Surfaces::filter_by_surface_types(outdoor_surfaces, "Wall") end |
.get_weighted_average_surface_conductance(surfaces) ⇒ Object
determine average conductance on set of surfaces or subsurfaces.
2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2727 def self.get_weighted_average_surface_conductance(surfaces) total_area = 0.0 temp = 0.0 surfaces.each do |surface| temp = temp + BTAP::Geometry::Surfaces::get_surface_net_area(surface) * BTAP::Geometry::Surfaces::get_surface_construction_conductance(surface) total_area = total_area + BTAP::Geometry::Surfaces::get_surface_net_area(surface) end average_conductance = "NA" average_conductance = temp / total_area unless total_area == 0.0 return average_conductance end |
.get_weighted_average_surface_shgc(surfaces) ⇒ Object
determine average conductance on set of surfaces or subsurfaces.
2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2740 def self.get_weighted_average_surface_shgc(surfaces) total_area = 0.0 temp = 0.0 surfaces.each do |surface| temp = temp + BTAP::Geometry::Surfaces::get_surface_net_area(surface) * BTAP::Geometry::Surfaces::get_surface_construction_shgc(surface) total_area = total_area + BTAP::Geometry::Surfaces::get_surface_net_area(surface) end ave_shgc = "NA" ave_shgc = temp / total_area unless total_area == 0.0 return ave_shgc end |
.get_weighted_average_surface_tvis(surfaces) ⇒ Object
determine average conductance on set of surfaces or subsurfaces.
2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2753 def self.get_weighted_average_surface_tvis(surfaces) total_area = 0.0 temp = 0.0 surfaces.each do |surface| temp = temp + BTAP::Geometry::Surfaces::get_surface_net_area(surface) * BTAP::Geometry::Surfaces::get_surface_construction_tvis(surface) total_area = total_area + BTAP::Geometry::Surfaces::get_surface_net_area(surface) end ave_tvis = "NA" ave_tvis = temp / total_area unless total_area == 0.0 return ave_tvis end |
.getSurfaceAreafromVertices(vertices:) ⇒ Object
This method calculates the surface area of a 2-D polygon from an array of OpenStudio vertices. It ignores any z vertices. This method assumes that the polygon is complete, has no holes, does not cross itself, and that the vertices are provided in counter-clockwise order. This method is used in cases when you want to find the area of something before creating an OpenStudio surface/subsurface.
Input arguments: vetices: Array of openstudio vertices.
Output: Area: Float, area of polygot represented by the vertices.
3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 3796 def self.getSurfaceAreafromVertices(vertices:) area = 0.0 numberVertices = vertices.size # Check that a polygon is actually provided and not just a line or point. Return 0 if the vertices are a line # or point. return 0.0 if numberVertices < 3 # Go through the vertices and get the cross product. This adopted from: # https://web.archive.org/web/20100405070507/http://valis.cs.uiuc.edu/~sariel/research/CG/compgeom/msg00831.html vertices.each_with_index do |vertex, i| j = (i + 1) % numberVertices area += vertex.x.to_f * vertices[j].y.to_f area -= vertex.y.to_f * vertices[j].x.to_f end return area end |
.hide(surfaces) ⇒ Object
3002 3003 3004 3005 3006 3007 3008 3009 3010 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 3002 def self.hide(surfaces) surfaces.each do |surface| if drawing_interface = surface.drawing_interface if entity = drawing_interface.entity entity.visible = false end end end end |
.line_segment_overlap_x_coord(y_check:, point_b1:, point_b2:) ⇒ Object
This method determines the x coordinate of where a given y coordinate crosses a given line. y_check: The y coordinate that you want to determine the x coordinate for on a line point_b1: The coordinates of the bottom of the line point_b2: The coordinates of the top of the line
3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 3750 def self.line_segment_overlap_x_coord(y_check:, point_b1:, point_b2:) # If the line is vertical then all x coordinates are the same if point_b1[:x] == point_b2[:x] xcross = point_b2[:x] # If the line is horizontal you cannot find the y intercept elsif (point_b1[:y] == point_b2[:y]) raise("This line is horizontal so no y intercept can be found.") # Otherwise determine the line coefficients and get the intercept else a = (point_b1[:y] - point_b2[:y]) / (point_b1[:x] - point_b2[:x]) b = point_b1[:y] - a * point_b1[:x] xcross = (y_check - b) / a end return xcross end |
.line_segment_overlap_y?(point_a1:, point_a2:, point_b1:, point_b2:) ⇒ Boolean
This method determines if the y component of 2 lines overlap. point_a1: The top of the first line point_a2: The bottom of the first line point_b1: The bottom of the second line point_b2: The top of the second line. This naming convention was chosen because this method was originally designed to work with the ‘make_concave_surfaces’ method (see above). That method choses lines that point up and then sees where they overlap with lines pointing down. The point_1 of each line is the end of the line. In this case a lines point up and b lines point down.
3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 3712 def self.line_segment_overlap_y?(point_a1:, point_a2:, point_b1:, point_b2:) overlap_start = nil overlap_end = nil # If line a overlaps with the bottom of line b do this: if (point_a1 >= point_b1) && (point_a2 <= point_b1) overlap_start = point_a1 overlap_end = point_b1 # This checks if all of line b is overlapped by line a if point_a1 >= point_b2 overlap_start = point_b2 end # If line a overlaps with the top of line b do this: elsif (point_a1 >= point_b2) && (point_a2 <= point_b2) overlap_start = point_b2 overlap_end = point_a2 # This checks if all of line b is overlapped by line a if point_a2 <= point_b1 overlap_end = point_b1 end # This checks if all of line a fits in line b elsif (point_a1 <= point_b2) && (point_a2 >= point_b1) overlap_start = point_a1 overlap_end = point_a2 end # Overlap vectors always point down. Thus overlap_start is the y location of the top of the overlap vector and # overlap_end is the y location of the bottom of the overlap vector. The overlap vector will later be constructed # using point_b1 and point_b2 and checking which overlaps are closest (and not obstructed) by other overlaps. overlap_y = { overlap_start: overlap_start, overlap_end: overlap_end } return overlap_y end |
.make_convex_surfaces(surface:, tol: 12) ⇒ Object
2018-09-27 Chris Kirney This method takes a surface in the x-y plane (z coordinates are ignored) with an upwardly pointing normal and turns it into convex quadrialaterals. If the original surface is already a convex quadrilateral then this method will go to a lot of trouble to return the same thing (only with the coordinates of the points rounded). If the surface is already a concave surface then this method will return it broken into a bunch of quadrilaters (maybe a triangle here and there). Neither of the above are especially useful. However, the point of this method is if you pass this a concave surface it will return convex surfaces that you can then use with other methods that only apply to convex surfaces (such as a method which fits skylights into a roof). Note that surfaces per say are not returned. Rather, an array containing 4 points arranged in counter clockwise order is returned. These points are also in the x-y plane with an upwardly pointing normal. No z coordinate is returned.
The method works by first looking for upward pointing lines. It then looks for cooresponding downward pointing lines. Since all of the surfaces are closed there should always be enough upward and downward pointing lines. Horizontal lines are ignored. It then checks to see which y projections of the upward and downward pointing lines overlap. It then sees which of these overlaping lines overlap. Ultimately you wind up with a whole bunch of overlapping y projections that coorespond with different upward pointing lines. These overlapping y projects are either unique, or they precisely match other overlapping y projections. The point is that, in the case of a convex shape, an upward pointing line may overlap with some lines close, and some far away, with some lines in between. The method then sorts through the overlapping y projections to see which are closest to a given upward pointing line. It keeps the unique ones, and the ones that are closest. The end result should be downward pointing line segments that correspond to an upward pointing line segment with no intervening lines. The last part of the method assembles the quadrilaterals from the remaining downward pointing line segments which correspond with a given upward pointing line segment.
3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 3035 def self.make_convex_surfaces(surface:, tol: 12) # Note that points on surfaces are given counterclockwise when looking at the surface from the opposite direction as # the outward normal (i.e. the outward normal is pointing at you). I use point_a1, point_a2, point_b1 and point b2 # lots. For this, point_a refers to vectors pointing up. In this case point_a1 is at the top of the vector and # point_a2 is at the bottom of the vector. Contrarily, point_b refers to vectors pointing down. In this case # point_b1 is at the bottom of the vector and point_b2 is at the top. All of this comes about because I cycle # through the points starting at the 2nd point and and going to the last point. I count vectors as starting from # the last point and going toward the current point. # See following where P1 through P4 are the points. When cycling through a is where you start and b is where you # end. the o is the tip of the outward normal pointing at you. # P2b------------aP1 # a b # | | # | o | # | | # b a # P3a-----------bP4 surf_verts = [] # Get the vertices from the surface, keep the x and y coordinates, and turn the vertices from OpenStudio's # data structure to a differet one which is a little easier to deal with. Also, round them to the given # tolerance. This is done because some numbers that should match don't because of tiny errors. surface.vertices.each do |vert| surf_vert = { x: vert.x.to_f.round(tol), y: vert.y.to_f.round(tol), z: vert.z.to_f } surf_verts << surf_vert end # If the surface is a triangle or less then do nothing and return it. return surf_verts if surf_verts.length <= 3 # Adding the first vertex to the end so that it is accounted for. surf_verts << surf_verts[0] # Following we go through the points, look for upward pointing lines, then look for downward pointing lines to # their left (only to the left because everything goes counter-clockwise). If there is a line find how much the # current upward pointing line overlaps with it in the y direction. overlap_segs = [] new_surfs = [] for i in 1..(surf_verts.length - 1) # Is this line segment pointing up? If no, then ignore it and go to the next line segment. if surf_verts[i][:y] > surf_verts[i - 1][:y] # Go through each line segment for j in 1..(surf_verts.length - 1) # Is the line segment to the left of the current (index i) line segment? If no, then ignore it and go to the next one. # I revised this to check if the start or end of the current (index i) line segment is to the left of the # line segment being checked. #if surf_verts[j][:x] < surf_verts[i][:x] and surf_verts[j - 1][:x] < surf_verts[i - 1][:x] if surf_verts[j][:x] < surf_verts[i][:x] || surf_verts[j - 1][:x] < surf_verts[i - 1][:x] # Is the line segment pointing down? If no, then ignore it and go to the next line segment. if surf_verts[j][:y] < surf_verts[j - 1][:y] # Do the y coordinates of the line segment overlap with the current (index i) line segment? If no # then ignore it and go to the next line segment. overlap_y = line_segment_overlap_y?(point_a1: surf_verts[i][:y], point_a2: surf_verts[i - 1][:y], point_b1: surf_verts[j][:y], point_b2: surf_verts[j - 1][:y]) unless overlap_y[:overlap_start].nil? || overlap_y[:overlap_end].nil? unless overlap_y[:overlap_start] == overlap_y[:overlap_end] overlap_seg = { index_a1: i, index_a2: i - 1, index_b1: j, index_b2: j - 1, point_b1: surf_verts[j], point_b2: surf_verts[j - 1], overlap_y: overlap_y } overlap_segs << overlap_seg end end end end end end end # This part: # 1. Subdivides the overlapping segments found above into either unique overlaps between the upward and downward # pointing lines or overlapping segments that exactly match one another. # 2. Goes through each upward pointing line and finds the closest overlapping downward pointing line segments (if # these downward pointing segments belong together they are re-attached). # 3. Makes quadrilaterals (or triangles as the case may be) out of each upward pointing line and the closest # downward pointing line segment. if overlap_segs.length > 1 # Subdivide the overlapping segments found above into either unique overlaps between the upward and downward # pointing lines or overlapping segments that exactly match one another. overlap_segs = subdivide_overlaps(overlap_segs: overlap_segs) # Remove redundant overlapping segments recheck = true while recheck recheck = false # Go through each overlapping segment and look for duplicate segments overlap_segs.each_with_index do |ind_overlap_seg, seg_index| # Find duplicate overlapping segments redundant_segs = overlap_segs.select { |check_seg| check_seg == ind_overlap_seg} # Remove the first one and then restart the while loop to recompile the seg_index if redundant_segs.size > 1 overlap_segs.delete_at(seg_index) recheck = true end end end for i in 1..(surf_verts.length - 1) # Does the line point up? No then ignore and go on to the next one. if surf_verts[i][:y] > surf_verts[i - 1][:y] # Finds the closest overlapping downward pointing line segments that correspond to this upward pointing # line (if some of these downward pointing segments belong together then re-attached them). closest_overlaps = get_overlapping_segments(overlap_segs: overlap_segs, index: i, point_a1: surf_verts[i], point_a2: surf_verts[i - 1]) closest_overlaps = closest_overlaps.sort_by {|closest_overlap| closest_overlap[:overlap_y][:overlap_start]} # Create the quadrilaterals out of the downward pointing line segments closest to the current upward # pointing line. for j in 0..(closest_overlaps.length - 1) new_surf = [] z_loc = surf_verts[closest_overlaps[j][:index_a1]][:z] y_loc = closest_overlaps[j][:overlap_y][:overlap_start] x_loc = line_segment_overlap_x_coord(y_check: y_loc, point_b1: surf_verts[closest_overlaps[j][:index_a1]], point_b2: surf_verts[closest_overlaps[j][:index_a2]]) new_surf << {x: x_loc.to_f.round(tol), y: y_loc.to_f.round(tol), z: z_loc.to_f.round(tol)} x_loc = line_segment_overlap_x_coord(y_check: y_loc, point_b1: closest_overlaps[j][:point_b1], point_b2: closest_overlaps[j][:point_b2]) z_loc = surf_verts[closest_overlaps[j][:index_b2]][:z] new_surf << {x: x_loc.to_f.round(tol), y: y_loc.to_f.round(tol), z: z_loc.to_f.round(tol)} y_loc = closest_overlaps[j][:overlap_y][:overlap_end] x_loc = line_segment_overlap_x_coord(y_check: y_loc, point_b1: closest_overlaps[j][:point_b1], point_b2: closest_overlaps[j][:point_b2]) z_loc = surf_verts[closest_overlaps[j][:index_b1]][:z] new_surf << {x: x_loc.to_f.round(tol), y: y_loc.to_f.round(tol), z: z_loc.to_f.round(tol)} x_loc = line_segment_overlap_x_coord(y_check: y_loc, point_b1: surf_verts[closest_overlaps[j][:index_a1]], point_b2: surf_verts[closest_overlaps[j][:index_a2]]) z_loc = surf_verts[closest_overlaps[j][:index_a2]][:z] new_surf << {x: x_loc.to_f.round(tol), y: y_loc.to_f.round(tol), z: z_loc.to_f.round(tol)} # Check if this should be a triangle. for k in 0..(new_surf.length - 1) break_now = false for l in 0..(new_surf.length - 1) next if k == l if (new_surf[k][:x] == new_surf[l][:x]) && (new_surf[k][:y] == new_surf[l][:y]) new_surf.delete_at(l) break_now = true break end end if break_now == true break end end new_surfs << new_surf end end end elsif overlap_segs.length == 1 # There is only one overlapping downward line, thus this is a quadrilateral already so just return it. # Remove the last vertex as we had artificially added it at the start. surf_verts.pop new_surfs << surf_verts end return new_surfs end |
.remove_all_subsurfaces(surfaces) ⇒ OpenStudio::Model::Model
This Method removes all the subsurfaces in a model (Windows, Doors )
2684 2685 2686 2687 2688 2689 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2684 def self.remove_all_subsurfaces(surfaces) surfaces.each do |subsurface| subsurface.remove end return surfaces end |
.rotate_tilt_translate_surfaces(planar_surfaces, azimuth_degrees, tilt_degrees = 0.0, translation_vector = OpenStudio::Vector3d.new(0.0, 0.0, 0.0)) ⇒ OpenStudio::Model::Model
This method will rotate a surface
2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2653 def self.rotate_tilt_translate_surfaces(planar_surfaces, azimuth_degrees, tilt_degrees = 0.0, translation_vector = OpenStudio::Vector3d.new(0.0, 0.0, 0.0)) # Identity matrix for setting space origins azimuth_matrix = OpenStudio::Transformation::rotation(OpenStudio::Vector3d.new(0, 0, 1), azimuth_degrees * Math::PI / 180) tilt_matrix = OpenStudio::Transformation::rotation(OpenStudio::Vector3d.new(0, 0, 1), tilt_degrees * Math::PI / 180) translation_matrix = OpenStudio::createTranslation(translation_vector) planar_surfaces.each do |surface| surface.changeTransformation(azimuth_matrix) surface.changeTransformation(tilt_matrix) surface.changeTransformation(translation_matrix) end return planar_surfaces end |
.set_fenestration_to_wall_ratio(surfaces, ratio, offset = 0, height_offset_from_floor = true, floor = "all") ⇒ Object
2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2666 def self.set_fenestration_to_wall_ratio(surfaces, ratio, offset = 0, height_offset_from_floor = true, floor = "all") surfaces.each do |surface| result = surface.setWindowToWallRatio(ratio, offset, height_offset_from_floor) raise("Unable to set FWR for surface " + surface.name.get.to_s + " . Possible reasons are if the surface is not a wall, if the surface is not rectangular in face coordinates, if requested ratio is too large (window area ~= surface area) or too small (min dimension of window < 1 foot), or if the window clips any remaining sub surfaces. Otherwise, removes all existing windows and adds new window to meet requested ratio.") unless result end return surfaces end |
.set_surfaces_boundary_condition(model, surfaces, boundaryCondition) ⇒ Object
This method sets the boundary condition for a surface and it’s matching surface.
If set to adiabatic, it will remove all subsurfaces since E+ cannot have adiabatic sub surfaces.
2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2877 def self.set_surfaces_boundary_condition(model, surfaces, boundaryCondition) surfaces = BTAP::Common::validate_array(model, surfaces, "Surface") if OpenStudio::Model::Surface::validOutsideBoundaryConditionValues.include?(boundaryCondition) surfaces.each do |surface| if boundaryCondition == "Adiabatic" #need to remove subsurface as you cannot have a adiabatic surface with a #subsurface. surface.subSurfaces.each do |subsurface| subsurface.remove end #A bug with adiabatic surfaces. They do not hold the default contruction. surface.setConstruction(surface.construction.get()) if surface.isConstructionDefaulted end surface.setOutsideBoundaryCondition(boundaryCondition) adj_surface = surface.adjacentSurface unless adj_surface.empty? adj_surface.get.setOutsideBoundaryCondition(boundaryCondition) end end else puts "ERROR: Invalid Boundary Condition = " + boundary_condition puts "Correct Values are:" puts OpenStudio::Model::Surface::validOutsideBoundaryConditionValues end end |
.set_surfaces_construction(surfaces, construction) ⇒ Object
2868 2869 2870 2871 2872 2873 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2868 def self.set_surfaces_construction(surfaces, construction) surfaces.each do |surface| surface.setConstruction(construction) end return true end |
.set_surfaces_construction_conductance(surfaces, conductance) ⇒ Object
This method creates a new construction based on the current, changes the rsi and assign the construction to the current surface. Most of the meat of this method is in the construction class. Testing is done there.
2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2821 def self.set_surfaces_construction_conductance(surfaces, conductance) surfaces.each do |surface| #a bit of acrobatics to get the construction object from the ConstrustionBase object's name. construction = OpenStudio::Model::getConstructionByName(surface.model, surface.construction.get.name.to_s).get #create a new construction with the requested conductance value based on the current construction. new_construction = BTAP::Resources::Envelope::Constructions::customize_opaque_construction(surface.model, construction, conductance) surface.setConstruction(new_construction) end return surfaces end |
.show(surfaces) ⇒ Object
2992 2993 2994 2995 2996 2997 2998 2999 3000 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 2992 def self.show(surfaces) surfaces.each do |surface| if drawing_interface = surface.drawing_interface if entity = drawing_interface.entity entity.visible = false end end end end |
.subdivide_overlaps(overlap_segs:) ⇒ Object
This method was originally written to work with the ‘make_concave_surfaces’ method above. It takes the y-components of a bunch of line segemnts and cuts them up until they either are unique (no other overlapping components) or they match the y-components of other line segments. overlap_segs: This is an array of hashes that looks like:
overlap_seg = {
index_a1: i,
index_a2: i-1,
index_b1: j,
index_b2: j-1,
point_b1: surf_verts[j],
point_b2: surf_verts[j-1],
overlap_y: overlap_y
}
index_a1: The index of the array of points that cooresponds with the top of line a (points up) index_a1: The index of the array of points that cooresponds with the bottom of line a (points up) index_b1: The index of the array of points that cooresponds with the bottom of line b (points down) index_b1: The index of the array of points that cooresponds with the top of line b (points down) point_b1: The coordinates of the bottom of line b point_b2: The coordinates of the top of line b
overlap_y: A hash that contains the coordinates of the top and bottom of the y projection of the overlapping lines (line a and line b)
overlap_y = {
overlap_start: overlap_start,
overlap_end: overlap_end
}
overlap_start: The y coordinate of the top of the overlap overlap_end: The y coordinate of the bottom of the overlap
3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 3322 def self.subdivide_overlaps(overlap_segs:) restart = true # Keep doing this until the y projections of the lines are either unique or the match the y projections of other # lines. while restart == true restart = false overlap_segs.each_with_index do |overlap_seg, curr_seg_index| for j in 0..(overlap_segs.length - 1) # Skip this y projection if it is the same as that in overlap_seg if overlap_seg == overlap_segs[j] next end # Check to see if the y projection of line a overlaps with the y projection of line b overlap_segs_overlap = line_segment_overlap_y?(point_a1: overlap_seg[:overlap_y][:overlap_start], point_a2: overlap_seg[:overlap_y][:overlap_end], point_b1: overlap_segs[j][:overlap_y][:overlap_end], point_b2: overlap_segs[j][:overlap_y][:overlap_start]) # If the y projections of the two lines overlap then the components of overlap_segs_overlap should not be # nil. unless ((overlap_segs_overlap[:overlap_start].nil?) || (overlap_segs_overlap[:overlap_end].nil?)) # If the two overlaping segments start and end at the same point then do nothing and go to the next segment. if (overlap_seg[:overlap_y][:overlap_start] == overlap_segs[j][:overlap_y][:overlap_start]) && (overlap_seg[:overlap_y][:overlap_end] == overlap_segs[j][:overlap_y][:overlap_end]) next # If the start point of one overlapping segment shares the end point of the other overlapping segment then # they are not really overlapping. Ignore and go to the next point. elsif overlap_segs_overlap[:overlap_start] == overlap_segs_overlap[:overlap_end] next # If the overlap_seg segment covers beyond the overlap_segs[j] segment then break overlap_seg into three smaller pieces: # -One piece for where overlap_seg starts to where overlap_segs[j] starts; # -One piece to cover overlap_segs[j] (the middle part); and # -One piece for where overlap_segs[j] ends to where overlap_seg ends (the bottom part). # The overlap_segs[j] remains as it is associated with another upward pointing line segment. # If overlap_seg starts at the same point as overlap_segs[j] or ends at the same point as overlap_segs[j] # then overlap_seg is broken into two pieces (no mid piece). elsif (overlap_seg[:overlap_y][:overlap_start] >= overlap_segs[j][:overlap_y][:overlap_start]) && (overlap_seg[:overlap_y][:overlap_end] <= overlap_segs[j][:overlap_y][:overlap_end]) # If the overlap_seg and overlap_segs[j] start at the same point replace overlap_seg with two segments ( # one top and one bottom). if overlap_seg[:overlap_y][:overlap_start] == overlap_segs[j][:overlap_y][:overlap_start] overlap_top = { index_a1: overlap_seg[:index_a1], index_a2: overlap_seg[:index_a2], index_b1: overlap_seg[:index_b1], index_b2: overlap_seg[:index_b2], point_b1: overlap_seg[:point_b1], point_b2: overlap_seg[:point_b2], overlap_y: overlap_segs_overlap } overlap_bottom_over = { overlap_start: overlap_segs_overlap[:overlap_end], overlap_end: overlap_seg[:overlap_y][:overlap_end] } overlap_bottom = { index_a1: overlap_seg[:index_a1], index_a2: overlap_seg[:index_a2], index_b1: overlap_seg[:index_b1], index_b2: overlap_seg[:index_b2], point_b1: overlap_seg[:point_b1], point_b2: overlap_seg[:point_b2], overlap_y: overlap_bottom_over } # delete the existing y projection overlaps and replace it with the ones we just made. overlap_segs.delete_at(curr_seg_index) overlap_segs << overlap_top overlap_segs << overlap_bottom elsif overlap_seg[:overlap_y][:overlap_end] == overlap_segs[j][:overlap_y][:overlap_end] # If the overlap_seg and overlap_segs[j] end at the same point replace overlap_seg with two segments ( # one top and one bottom). overlap_top_over = { overlap_start: overlap_seg[:overlap_y][:overlap_start], overlap_end: overlap_segs_overlap[:overlap_start] } overlap_top = { index_a1: overlap_seg[:index_a1], index_a2: overlap_seg[:index_a2], index_b1: overlap_seg[:index_b1], index_b2: overlap_seg[:index_b2], point_b1: overlap_seg[:point_b1], point_b2: overlap_seg[:point_b2], overlap_y: overlap_top_over } overlap_bottom = { index_a1: overlap_seg[:index_a1], index_a2: overlap_seg[:index_a2], index_b1: overlap_seg[:index_b1], index_b2: overlap_seg[:index_b2], point_b1: overlap_seg[:point_b1], point_b2: overlap_seg[:point_b2], overlap_y: overlap_segs_overlap } # delete the existing y projection overlaps and replace it with the ones we just made. overlap_segs.delete_at(curr_seg_index) overlap_segs << overlap_top overlap_segs << overlap_bottom elsif (overlap_seg[:overlap_y][:overlap_start] > overlap_segs[j][:overlap_y][:overlap_start]) && (overlap_seg[:overlap_y][:overlap_end] < overlap_segs[j][:overlap_y][:overlap_end]) # If the overlap_seg stretches above and below overlap_segs[j] then break overlap_seg into three pieces # (one top, one middle, one bottom). overlap_top_over = { overlap_start: overlap_seg[:overlap_y][:overlap_start], overlap_end: overlap_segs_overlap[:overlap_start] } overlap_top = { index_a1: overlap_seg[:index_a1], index_a2: overlap_seg[:index_a2], index_b1: overlap_seg[:index_b1], index_b2: overlap_seg[:index_b2], point_b1: overlap_seg[:point_b1], point_b2: overlap_seg[:point_b2], overlap_y: overlap_top_over } overlap_mid = { index_a1: overlap_seg[:index_a1], index_a2: overlap_seg[:index_a2], index_b1: overlap_seg[:index_b1], index_b2: overlap_seg[:index_b2], point_b1: overlap_seg[:point_b1], point_b2: overlap_seg[:point_b2], overlap_y: overlap_segs_overlap } overlap_bottom_over = { overlap_start: overlap_segs_overlap[:overlap_end], overlap_end: overlap_seg[:overlap_y][:overlap_end] } overlap_bottom = { index_a1: overlap_seg[:index_a1], index_a2: overlap_seg[:index_a2], index_b1: overlap_seg[:index_b1], index_b2: overlap_seg[:index_b2], point_b1: overlap_seg[:point_b1], point_b2: overlap_seg[:point_b2], overlap_y: overlap_bottom_over } # delete the existing y projection overlaps and replace it with the ones we just made. overlap_segs.delete_at(curr_seg_index) overlap_segs << overlap_top overlap_segs << overlap_mid overlap_segs << overlap_bottom end restart = true break # If the overlap_segs[j] segment covers beyond the overlap_seg segment then break overlap_segs[j] into three smaller pieces: # -One piece for where overlap_segs[j] starts to where overlap_seg starts; # -One piece to cover overlap_seg (the middle part); and # -One piece for where overlap_seg ends to where overlap_segs[j] ends (the bottom part). # The overlap_seg remains as it is associated with another upward pointing line segment. # If overlap_segs[j] starts at the same point as overlap_seg or ends at the same point as overlap_seg # then overlap_segs[j] is broken into two pieces (no mid piece). elsif overlap_seg[:overlap_y][:overlap_start] <= overlap_segs[j][:overlap_y][:overlap_start] && overlap_seg[:overlap_y][:overlap_end] >= overlap_segs[j][:overlap_y][:overlap_end] # If the overlap_seg and overlap_segs[j] start at the same point replace overlap_segs[j] with two segments ( # one top and one bottom). if overlap_seg[:overlap_y][:overlap_start] == overlap_segs[j][:overlap_y][:overlap_start] overlap_top = { index_a1: overlap_segs[j][:index_a1], index_a2: overlap_segs[j][:index_a2], index_b1: overlap_segs[j][:index_b1], index_b2: overlap_segs[j][:index_b2], point_b1: overlap_segs[j][:point_b1], point_b2: overlap_segs[j][:point_b2], overlap_y: overlap_segs_overlap } overlap_bottom_over = { overlap_start: overlap_segs_overlap[:overlap_end], overlap_end: overlap_segs[j][:overlap_y][:overlap_end] } overlap_bottom = { index_a1: overlap_segs[j][:index_a1], index_a2: overlap_segs[j][:index_a2], index_b1: overlap_segs[j][:index_b1], index_b2: overlap_segs[j][:index_b2], point_b1: overlap_segs[j][:point_b1], point_b2: overlap_segs[j][:point_b2], overlap_y: overlap_bottom_over } # delete the existing y projection overlaps and replace it with the ones we just made. overlap_segs.delete_at(j) overlap_segs << overlap_top overlap_segs << overlap_bottom elsif overlap_seg[:overlap_y][:overlap_end] == overlap_segs[j][:overlap_y][:overlap_end] # If the overlap_seg and overlap_segs[j] end at the same point replace overlap_segs[j] with two segments ( # one top and one bottom). overlap_top_over = { overlap_start: overlap_segs[j][:overlap_y][:overlap_start], overlap_end: overlap_segs_overlap[:overlap_start] } overlap_top = { index_a1: overlap_segs[j][:index_a1], index_a2: overlap_segs[j][:index_a2], index_b1: overlap_segs[j][:index_b1], index_b2: overlap_segs[j][:index_b2], point_b1: overlap_segs[j][:point_b1], point_b2: overlap_segs[j][:point_b2], overlap_y: overlap_top_over } overlap_bottom = { index_a1: overlap_segs[j][:index_a1], index_a2: overlap_segs[j][:index_a2], index_b1: overlap_segs[j][:index_b1], index_b2: overlap_segs[j][:index_b2], point_b1: overlap_segs[j][:point_b1], point_b2: overlap_segs[j][:point_b2], overlap_y: overlap_segs_overlap } # delete the existing y projection overlaps and replace it with the ones we just made. overlap_segs.delete_at(j) overlap_segs << overlap_top overlap_segs << overlap_bottom elsif overlap_seg[:overlap_y][:overlap_start] < overlap_segs[j][:overlap_y][:overlap_start] && overlap_seg[:overlap_y][:overlap_end] > overlap_segs[j][:overlap_y][:overlap_end] # If the overlap_segs[j] stretches above and below overlap_seg then break overlap_segs[j] into three pieces # (one top, one middle, one bottom). overlap_top_over = { overlap_start: overlap_segs[j][:overlap_y][:overlap_start], overlap_end: overlap_segs_overlap[:overlap_start] } overlap_top = { index_a1: overlap_segs[j][:index_a1], index_a2: overlap_segs[j][:index_a2], index_b1: overlap_segs[j][:index_b1], index_b2: overlap_segs[j][:index_b2], point_b1: overlap_segs[j][:point_b1], point_b2: overlap_segs[j][:point_b2], overlap_y: overlap_top_over } overlap_mid = { index_a1: overlap_segs[j][:index_a1], index_a2: overlap_segs[j][:index_a2], index_b1: overlap_segs[j][:index_b1], index_b2: overlap_segs[j][:index_b2], point_b1: overlap_segs[j][:point_b1], point_b2: overlap_segs[j][:point_b2], overlap_y: overlap_segs_overlap } overlap_bottom_over = { overlap_start: overlap_segs_overlap[:overlap_end], overlap_end: overlap_segs[j][:overlap_y][:overlap_end] } overlap_bottom = { index_a1: overlap_segs[j][:index_a1], index_a2: overlap_segs[j][:index_a2], index_b1: overlap_segs[j][:index_b1], index_b2: overlap_segs[j][:index_b2], point_b1: overlap_segs[j][:point_b1], point_b2: overlap_segs[j][:point_b2], overlap_y: overlap_bottom_over } # delete the existing y projection overlaps and replace it with the ones we just made. overlap_segs.delete_at(j) overlap_segs << overlap_top overlap_segs << overlap_mid overlap_segs << overlap_bottom end restart = true break # if overlap_seg covers the top of overlap_segs[j] then break overlap_seg into a top and an overlap portion # ond break overlap_segs[j] into an overlap portion and a bottom portion. elsif (overlap_seg[:overlap_y][:overlap_start] >= overlap_segs[j][:overlap_y][:overlap_start]) && (overlap_seg[:overlap_y][:overlap_end] <= overlap_segs[j][:overlap_y][:overlap_start]) && (overlap_seg[:overlap_y][:overlap_end] > overlap_segs[j][:overlap_y][:overlap_end]) overlap_top_over = { overlap_start: overlap_seg[:overlap_y][:overlap_start], overlap_end: overlap_segs_overlap[:overlap_start] } overlap_top = { index_a1: overlap_seg[:index_a1], index_a2: overlap_seg[:index_a2], index_b1: overlap_seg[:index_b1], index_b2: overlap_seg[:index_b2], point_b1: overlap_seg[:point_b1], point_b2: overlap_seg[:point_b2], overlap_y: overlap_top_over } overlap_mid_seg = { index_a1: overlap_seg[:index_a1], index_a2: overlap_seg[:index_a2], index_b1: overlap_seg[:index_b1], index_b2: overlap_seg[:index_b2], point_b1: overlap_seg[:point_b1], point_b2: overlap_seg[:point_b2], overlap_y: overlap_segs_overlap } overlap_mid_segs = { index_a1: overlap_segs[j][:index_a1], index_a2: overlap_segs[j][:index_a2], index_b1: overlap_segs[j][:index_b1], index_b2: overlap_segs[j][:index_b2], point_b1: overlap_segs[j][:point_b1], point_b2: overlap_segs[j][:point_b2], overlap_y: overlap_segs_overlap } overlap_bottom_over = { overlap_start: overlap_segs_overlap[:overlap_end], overlap_end: overlap_segs[j][:overlap_y][:overlap_end] } overlap_bottom = { index_a1: overlap_segs[j][:index_a1], index_a2: overlap_segs[j][:index_a2], index_b1: overlap_segs[j][:index_b1], index_b2: overlap_segs[j][:index_b2], point_b1: overlap_segs[j][:point_b1], point_b2: overlap_segs[j][:point_b2], overlap_y: overlap_bottom_over } # delete the existing y projection overlaps and replace it with the ones we just made. if curr_seg_index > j overlap_segs.delete_at(curr_seg_index) overlap_segs.delete_at(j) else overlap_segs.delete_at(j) overlap_segs.delete_at(curr_seg_index) end overlap_segs << overlap_top overlap_segs << overlap_mid_seg overlap_segs << overlap_mid_segs overlap_segs << overlap_bottom restart = true break elsif (overlap_seg[:overlap_y][:overlap_start] >= overlap_segs[j][:overlap_y][:overlap_end]) && (overlap_seg[:overlap_end] < overlap_segs[j][:overlap_end]) && (overlap_seg[:overlap_y][:overlap_start] <= overlap_segs[j][:overlap_y][:overlap_start]) # if overlap_seg covers the bottom of overlap_segs[j] then break overlap_segs[j] into a top and an overlap portion # ond break overlap_seg into an overlap portion and a bottom portion. overlap_top_over = { overlap_start: overlap_segs[j][:overlap_y][:overlap_start], overlap_end: overlap_segs_overlap[:overlap_start] } overlap_top = { index_a1: overlap_segs[j][:index_a1], index_a2: overlap_segs[j][:index_a2], index_b1: overlap_segs[j][:index_b1], index_b2: overlap_segs[j][:index_b2], point_b1: overlap_segs[j][:point_b1], point_b2: overlap_segs[j][:point_b2], overlap_y: overlap_top_over } overlap_mid_seg = { index_a1: overlap_seg[:index_a1], index_a2: overlap_seg[:index_a2], index_b1: overlap_seg[:index_b1], index_b2: overlap_seg[:index_b2], point_b1: overlap_seg[:point_b1], point_b2: overlap_seg[:point_b2], overlap_y: overlap_segs_overlap } overlap_mid_segs = { index_a1: overlap_segs[j][:index_a1], index_a2: overlap_segs[j][:index_a2], index_b1: overlap_segs[j][:index_b1], index_b2: overlap_segs[j][:index_b2], point_b1: overlap_segs[j][:point_b1], point_b2: overlap_segs[j][:point_b2], overlap_y: overlap_segs_overlap } overlap_bottom_over = { overlap_start: overlap_segs_overlap[:overlap_end], overlap_end: overlap_seg[:overlap_y][:overlap_end] } overlap_bottom = { index_a1: overlap_seg[:index_a1], index_a2: overlap_seg[:index_a2], index_b1: overlap_seg[:index_b1], index_b2: overlap_seg[:index_b2], point_b1: overlap_seg[:point_b1], point_b2: overlap_seg[:point_b2], overlap_y: overlap_bottom_over } # delete the existing y projection overlaps and replace it with the ones we just made. if curr_seg_index > j overlap_segs.delete_at(curr_seg_index) overlap_segs.delete_at(j) else overlap_segs.delete_at(j) overlap_segs.delete_at(curr_seg_index) end overlap_segs << overlap_top overlap_segs << overlap_mid_seg overlap_segs << overlap_mid_segs overlap_segs << overlap_bottom restart = true break end end end if restart == true break end end end return overlap_segs end |
.surf_centroid(surf:) ⇒ Object
This method finds the centroid of a surface using the point averaging method. OpenStudio already has something which does this but you have to turn something into a special OpenStudio surface first which you may not want to do.
3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 |
# File 'lib/openstudio-standards/btap/geometry.rb', line 3769 def self.surf_centroid(surf:) new_surf_cent = { x: 0, y: 0, z: 0 } surf.each do |surf_vert| new_surf_cent[:x] += surf_vert[:x] new_surf_cent[:y] += surf_vert[:y] new_surf_cent[:z] += surf_vert[:z] end new_surf_cent[:x] /= surf.length new_surf_cent[:y] /= surf.length new_surf_cent[:z] /= surf.length return new_surf_cent end |