Surface matching and intersecting adds unnecessary surfaces

asked 2020-06-30 12:20:41 -0500

jugonzal07 gravatar image

updated 2020-06-30 16:07:15 -0500

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:

image description

image description

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 =
    ospath =
    model = translator.loadModel(ospath)
    if model.empty?
        raise "Path '#{path}' is not a valid path to an OpenStudio Model"
        model = model.get
    return model

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

    n = outside_spaces.size

    boundingBoxes = []
    (0...n).each do |i|
        boundingBoxes[i] = outside_spaces[i].transformation * outside_spaces[i].boundingBox

    (0...n).each do |i|
        (i+1...n).each do |j|
            next if not boundingBoxes[i].intersects(boundingBoxes[j])
        end #j
    end #i

#----- 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)"after_matching.osm", 'w') {|f| f.write(model)}

Any thoughts on what's causing this?


edit retag flag offensive close merge delete



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 gravatar imagemacumber ( 2020-06-30 20:26:33 -0500 )edit

@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.

David Goldwasser gravatar imageDavid Goldwasser ( 2020-07-01 11:58:22 -0500 )edit

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.

David Goldwasser gravatar imageDavid Goldwasser ( 2020-07-01 12:06:57 -0500 )edit

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.

David Goldwasser gravatar imageDavid Goldwasser ( 2020-07-02 10:13:12 -0500 )edit

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.

jugonzal07 gravatar imagejugonzal07 ( 2020-07-02 10:36:47 -0500 )edit