Question-and-Answer Resource for the Building Energy Modeling Community
Get s tarted with the Help page

# Best practice for determining if two Surfaces intersect?

Hi all,

I'm looking to find the best way to use the OpenStudio SDK to check if two surfaces intersect. Rather than write my own code to do this, I assumed there's likely something packaged into the SDK to help me do this.

Ideally, the code would look something like.

#Made up function 'intersectsWith'
surfaces_intersect = surface1.intersectsWith(surface2)

if surfaces_intersect
#DO SOMETHING
end


Where

• surface1,surface2 are OpenStudio::Model::Surface
• surfaces_intersect = a boolean that determines if surface1 and surface2 intersect

I've looked into the computeIntersection for Surface found here but am unsure if this is path would be the most elegant way to do this.

For context, I'm trying to dynamically determine the perimeter of a floor surface exposed to ambient to set them for a FFactorGroundFloorConstruction. I haven't seen any way to easily do this in OpenStudio. Here is my approach:

1. Identify if floor with outside boundary condition equal to Ground. If so, flag as a floor requiring a FFactorGroundFloorConstruction
2. Identify all walls in this floor's space. If the wall's outside boundary condition is Outdoors AND it intersects the floor of interest, find it's projection on the x, y plane (i.e. the length of floor that is exposed to perimeter along this wall). NOTE: This assumes a wall only touches 1 floor; this might not always be true.
3. Add these perimeters for the floor to ultimately arrive at the exposed perimeter.

I cannot complete step two as I do not have a way to determine if a wall intersects a floor surface.

Any ideas? Thanks!

edit retag close merge delete

1

My solution to the ground-exposed perimeter problem is to find the spaces with floor BCs of "Ground", loop through that space's "Outdoor"-exposed walls, find the two vertices with minimum z coordinates and calculate the distance between those two coordinates (and sum for all such surfaces). Probably not the most general or foolproof method, but works for most of my geometry.

( 2020-04-06 15:45:48 -0600 )edit

Thanks Eric! That's not a bad idea. The issue I ran into recently was when a building had "stacked" walls on the same plane. Since I didn't check whether each wall intersected with the floor surface, I ended up double counting perimeters. If I implemented something similar to what you suggested but then also did a check that the "z" coordinate was along the same plane as the floor, I bet it would work. I'm hoping to find a more elegant "OpenStudio" way of doing it, but so far finding nothing.

( 2020-04-06 15:53:35 -0600 )edit
2

Yeah or you could always store the global min-Z for all surfaces and compare against that. Which would fail if you had different ground elevations, but that's a pretty special case. BTW it looks like computeIntersection would fail if the surfaces are not coplanar.

( 2020-04-06 16:02:41 -0600 )edit

Sort by » oldest newest most voted

Hi all,

I ended up writing my own script for calculating a wall and floor intersection. It comes with some caveats (found in the comments) but it can be found here:

https://github.com/NREL/openstudio-st...

It's how I ended up solving this issue. It's not super generalized, but works for calculating most cases of walls and floors. Any feedback on it would be greatly appreciated.

Thanks!

EDIT: Updated URL

more

@jugonzal07 the link is not available anymore.

( 2020-10-16 09:33:17 -0600 )edit

Thanks for catching that. I have updated the link.

( 2020-10-16 11:32:15 -0600 )edit

@jugonzal07 I think by intersect here you are referring to two surfaces which share a common edge, as opposed to intersect surfaces related to surface matching, where you have to split a surface into two more elements to be able to match it to the adjacent zone.

We have a method to calculate building perimeter by story that works very much as you describe. It does have some limitations but it works in most cases. It creates an array of edges in a space and then store surfaces that use that edge. It finds an edge which has an exterior wall, and also has a ground or interior exposed floor. It then adds these together. This is in the openstudio-extension gem which is included with OpenStudio much like the openstudio-standardsgem. https://github.com/NREL/openstudio-ex...

An alternative approach I have played with is using method in OpenStudio that merges multiple polygons into a single polygon. Then you can just sum the length of the edges. I have used this method to create a geojson footprint from an OpenStudio model. There were some issues with this so it was not stable enough for me to want to use to calculate perimeter yet but if you want to explore that I can find a link to it.

more

This looks super interesting. I will play around with the calculate_perimeter method.

( 2020-04-06 18:31:01 -0600 )edit

Thanks David, I ended up using a similar idea to what you had. You can find it in my answer above.

( 2020-07-01 12:52:29 -0600 )edit

Based on this, I wrote the following function that I've just shared.

  def self.get_length(vertices_a, vertices_b)
length = 0.0

vertices_a.each_with_index do |vertex_a, index_a|
prev_a = vertices_a[index_a-1]
vertices_b.each_with_index do |vertex_b, index_b|
prev_b = vertices_b[index_b-1]

p1 = prev_a
p2 = vertex_a
p3 = prev_b
p4 = vertex_b

p12 = p2-p1
p34 = p4-p3

next unless p12.cross(p34).length < 1e-6

p13 = p3-p1

next unless p12.cross(p13).length < 1e-6

p14 = p4-p1

k2 = p12.dot(p12)
k3 = p12.dot(p13)
k4 = p12.dot(p14)

table = [
[0.0, p14.length, p12.length],
[p13.length, p34.length, (p3-p2).length],
[p12.length, (p4-p2).length, 0.0]
]

row = if k3 < 1e-6 then
0
elsif k3 < k2 then
1
else
2
end

col = if k4 < 1e-6 then
0
elsif k4 < k2 then
1
else
2
end

length += table[row][col]
end
end
length /= 2 if vertices_a.length.eql?(2)
length /= 2 if vertices_b.length.eql?(2)

return length
end

more

## Stats

Seen: 198 times

Last updated: Oct 16 '20