Surface matching and intersecting adds unnecessary surfaces
Hi all,
We've hit a bug in our code base that will randomly add unnecessary edges/surfaces when doing surface matching. It's surprisingly inconsistent and I haven't been able to pin down why it happens.
Below is a screenshot before and after performing intersect surfaces and match surfaces. I have a ceiling plenum space touching a set zones for a perimeter and core layout. For some reason, two extra lines are added:
I created a minimum working example with the old legacy code we use for surface matching and intersecting. The original author has long since left the project but it seems fairly simple to grasp. The code and example for regenerating this problem can be found on github here. The script you'd want to run is titled surface_matching.rb
. The one edit you'd need to make is on line 48 for the path to the before_matching.osm
file.
require 'openstudio'
# Helper to load a model in one line
def osload(path)
translator = OpenStudio::OSVersion::VersionTranslator.new
ospath = OpenStudio::Path.new(path)
model = translator.loadModel(ospath)
if model.empty?
raise "Path '#{path}' is not a valid path to an OpenStudio Model"
else
model = model.get
end
return model
end
def match_blocks(model)
spaces = model.getSpaces
outside_spaces = []
spaces.each do |space|
space.surfaces.each do |surface|
if (surface.outsideBoundaryCondition == "Outdoors" ||
surface.outsideBoundaryCondition == "Ground")
outside_spaces << space
break
end
end
end
n = outside_spaces.size
boundingBoxes = []
(0...n).each do |i|
boundingBoxes[i] = outside_spaces[i].transformation * outside_spaces[i].boundingBox
end
(0...n).each do |i|
(i+1...n).each do |j|
next if not boundingBoxes[i].intersects(boundingBoxes[j])
outside_spaces[i].intersectSurfaces(outside_spaces[j])
outside_spaces[i].matchSurfaces(outside_spaces[j])
end #j
end #i
end
#----- Main testing starts here
osm_path = 'C:/git/stack_overflow_questions/unmet_hours/surface_matching/before_matching.osm'
model = osload(osm_path)
# Match and intersect surfaces
match_blocks(model)
File.open("after_matching.osm", 'w') {|f| f.write(model)}
Any thoughts on what's causing this?
Thanks!
Hey Juan, these bugs are very hard to track down. One suggestion would be to sort surfaces by area or spaces by some criteria to try to intersect larger surfaces before smaller ones. At least sorting should make the result repeatable.
@macumber, I could be wrong, but just looking at it, if the first surfaces to intersect were the third story core floor with the single surface whole story zone ceiling of the second story, it would have created the long diagonals to avoid the new surface from being a sub-surface.
@jugonzal07 as a test if you first try to manually split the second story roof at new footprint boundary it may go away. I have written code in past to create footprint polygon from collection of floors.
Maybe we can come up with a way to pre-intersect all surfaces against these footprints, it wouldn't catch all cases but might catch a lot. I've also had code that looks for floor surfaces that share an edge with an exterior wall. Could group those together and intersect them before surfaces that don't share an edge with an exterior surface.
Another thought I had was pre-sorting surfaces to be intersected, not by name, but by min or max z values, then y, then x.Working way across in this way might avoid some of these issues.
Thanks all for the responses. I'll give some of these a try! I agree that sorting the surfaces, at the very least, will give consistent results that I can learn from. I will report back with my findings. I think it makes sense to work in some post processing checks/tests to flag buildings with odd surfaces. While I'm not positive it would catch all cases, if I check for triangular surfaces I bet I could catch most of them-- at least for this project.