-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Autogenerate skylight wells (redux) #17
Conversation
box | ||
end | ||
|
||
## | ||
# Generates a bounded box within a polygon. Returns a ULC sequence if original | ||
# points are counterclockwise. | ||
# Generates a BLC bounded box within a polygon. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a bounding box (in blue) circumscribes a set of vertices (e.g. the irregular polygon in white), the latter's bounded box is the largest rectangular polygon (in green) that fits within it.
The method is not fully optimized, yet yields satisfactory results for the following purposes:
- (a more intuitive) re-alignment of irregular horizontal surfaces (e.g. floors, ceilings)
- delineating a regular 2D drawing board (within a surface) for adding subsurfaces, skylight well arrays, etc.
h = height(pts) | ||
d = h > w ? h : w | ||
sgs = {} | ||
box = boundedBox(pts) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The solution rests on the boundedBox method, a means to re-align a flat (or pre-flattened) surface (e.g. via OpenStudio::Transformation.alignFace). The goal is to go from an aligned surface (e.g. SEB roof):
...which would yield the following skylight insertion (far from great):
... to a more "natural" or "intuitive" (?) alignment along its bounded box:
# conflicts). Valid leader line anchors (set key :ld) need to be generated | ||
# prior to calling the method (see genAnchors). By default, the method seeks | ||
# to link leader line anchors to set :vtx (key) vertices (users can select | ||
# another collection of vertices, e.g. tag == :box). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bulk = bulk.get | ||
fine = fine.get | ||
|
||
# No overhangs/attics. Calculation of roof area for SRR% is more intuitive. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Models without plenums/attics (e.g. warehouses) are far easier to process (no wells).
Here, the addSkylights method is instructed to:
- alter only the "Bulk Storage" roof on the left (ignoring the "Fine Storage" roof on the right)
- purge pre-existing skylight subsurfaces of the "Bulk Storage" roof
- ... leaving the "Fine Storage" skylights as is
- meet a 4% skylight-to-roof ratio (SRR%)
- use 8' x 8' (industrial) skylights as a template
The solution first analyses the geometry of the candidate space(s) to toplight (e.g. convexity, aspect ratios) to determine the most suitable skylight distribution pattern (users can be picky and restrict candidate patterns). Here, the solution has determined that the "Bulk Storage" is deep/wide enough to accommodate a 2D array skylight distribution, whose parameters (e.g. number of rows and columns, skylight spacing) reflect general recommendations articulated here, often the basis of known codes and standards. The pattern would have been different for more geometrically-constrained spaces.
Once the rows and columns of skylights is established, the solution does a final adjustment of skylight width/depth (usually a contraction) to exactly meet the request 4% SRR%.
|
||
t = OpenStudio::Transformation.alignFace(p1) | ||
|
||
if v < 340 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OSut's overlap
relies on the OpenStudio.intersect function to extract a potential overlapping area (i.e. a polygon) shared between 2 intersecting polygons. TBD relies on OSut's overlap
to detect conflicts when dealing with fenestrated subsurfaces with Frame & Divider frames (where widths are often fairly narrow, e.g. 3cm to 6cm). I'm unable to isolate why (maybe linked to this fix), but OpenStudio.intersect
fails for intersection widths < 5cm for versions v3.2.1 through v3.3.0. It works fine for versions > v3.3.0 (in fact, it works for v3.0.0 as well). So here, I'm simply relaxing the test for v3.2.1 and v3.3.0, as I have no intention in developing a backwards-compatible workaround for something like 3cm frame widths (for older SDK versions) ... so user beware :]
@@ -3099,7 +3099,7 @@ def getNonCollinears(pts = nil, n = 0) | |||
p3 = pts[i3] | |||
v13 = p3 - p1 | |||
v12 = p2 - p1 | |||
next if v12.cross(v13).length < TOL | |||
next if v12.cross(v13).length < TOL2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is one of maybe several tweaks to ensure OSut doesn't red-flag surfaces that EnergyPlus would ultimately tolerate. The latter would accept/process surfaces having a width/length of my thumb (definitely not good, but hey). More to come, maybe.
srr = 0.04 | ||
|
||
# The method returns the GRA, calculated BEFORE adding skylights/wells. | ||
rm2 = mod1.addSkyLights(model.getSpaces, {srr: srr}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lib/osut/utils.rb
Outdated
@@ -264,6 +264,7 @@ def genConstruction(model = nil, specs = {}) | |||
a[:clad][:d ] = d | |||
a[:clad][:id ] = "OSut|#{mt}|#{format('%03d', d*1000)[-3..-1]}" | |||
|
|||
# TO DO: replace sheathing by mineral below a certain Uo factor. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A single sheathing material (between 2x drywall layers) is a proxy for an uninsulated stud wall cavity. This won't do however when the partition must be insulated. So a switch is needed (e.g. from sheathing to mineral insulation) for lower Uo factors. If not, CTF calculations will fail.
@@mats = { | ||
material: {}, # generic, e.g. lightweight cladding over furring, fibreboard |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A generic (default) material is retained to cover all lightweight cladding and sheathing needs. When assemblies are adequately insulated, there's no point dragging multiple fibre-based materials with subtle differences in properties.
d = 0.015 | ||
d = 0.100 if specs[:frame] == :medium | ||
d = 0.200 if specs[:frame] == :heavy | ||
d = 0.100 if u |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This allows one to switch from un/insulated partitions, massive 1x layer construction, etc.
# Typical uninsulated, framed cavity wall, suitable for light interzone | ||
# assemblies (i.e. symmetrical, 3-layer construction). | ||
specs = {type: :partition} | ||
surface = cls1.genConstruction(model, specs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One of many (minimally-) commented genConstruction
calls.
Long overdue follow-up to an earlier (draft) PR on autogenerating skylight wells, e.g. through (unenclosed/unconditioned) attics or (indirectly-conditioned) plenums.
There are many more roof/ceiling geometry combinations to test, areas in the code to refactor/optimize, etc. Yet tempus fugit; this will have to do for now ...