Question-and-Answer Resource for the Building Energy Modeling Community
Get started with the Help page
Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

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 of 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 = 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!

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 of 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 = 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!