ladybug-tools / honeybee-openstudio-gem

:honeybee: :gem: Library and measures for translating between Honeybee JSON schema and OpenStudio Model schema (OSM)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Get the measure to automatically convert to upper-left vertices

chriswmackey opened this issue ยท comments

While we are currently able to take care of ensuring all vertices are counter-clockwise on our Python end before we export the schema, we don't check to be sure that the vertices start in the upper-left corner. This is something we will probably need to do in the measure if we want to support the specification of holes in faces (since upper-left vertices would have to be recalculated after merging the boundary of the Face with the holes).

I have some code here in Python that I use to find the upper-left vertex and reset the order of the list:
https://github.com/ladybug-tools/ladybug-geometry/blob/master/ladybug_geometry/geometry3d/face.py#L492-L515

Alternatively, if the OpenStudio SDK takes care of this, that would be ideal. Do you know if such code exists in the OpenStudio SDK @DavidGoldwasser ?

@chriswmackey I'll look around, but I'm not aware of any code in OpenStudio to do this. I don't think it is a requirement of a planer surface in OpenStudio or EnergyPlus to start in the upper left. clockwise/counter clockwise is important, but starting vertex shouldn't me. Are you seeing cases where this is creating problems? The OpenStudio/EnergyPlus geometry doesn't have any way to define a hole. The closest to that is the sub-surface hosted by a base surface, but that does not always result hole (such as a door) or when out of plane with the base surface.

Thank you very much @macumber and @DavidGoldwasser .

That OpenStudio::reorderULC method will save us several extra lines of code and it looks like that is what we should use in the measure.

Thank you also for the info about OpenStudio::subtract but I think the method is a little different than what we need since our inputs are in 3D space (not always 2D polygons) and the direction of the holes doesn't always align with the direction of the boundary (though the boundary is always counter-clockwise and it dictates the orientation of the face). I have ~100 lines of Python that can convert from a shape with holes over to a single list of counter-clockwise vertices that I made a note of here:
#47
I don't think it will be to much effort to convert this code from Python to Ruby in order to make use of it in the measure.

While we're on the subject of geometry, though, does OpenStudio have any code to triangulate fenestration surfaces with more than 4 vertices? We have code to do this on the Python end but it's several hundred lines of code and I don't think it's worth translating it to Ruby for the measure (we would just run it before exporting to the JSON for the measure). If there's a way to do triangulation in OpenStudio SDK, though, we will use it.

@chriswmackey not exactly what you are looking for but our SetWWR measure has been updated to triangulate non-rectangular base surfaces. It can then create inset triangular fenestration.
https://github.com/NREL/OpenStudio-measures/blob/develop/nrel_published/SetWindowToWallRatioByFacade/measure.rb#L383

note, variable name is confusing, I'll fix that next time I work on it, while it is named ss it is base surface and not sub-surface.

This method provides a transformation from 3D coordinates to 2D (each face is planar), all the intersection code works in 2D, then you can translate back to 3D:
https://github.com/NREL/OpenStudio/blob/2c4dd5c9d790d1e1a019b328ca06957660733478/src/utilities/geometry/Transformation.hpp#L85

There is also a triangulation method:
https://github.com/NREL/OpenStudio/blob/2c4dd5c9d790d1e1a019b328ca06957660733478/src/utilities/geometry/Geometry.hpp#L99

This repo is an overview of how to do geometry stuff in OpenStudio:
https://github.com/macumber/coordinate-system-tutorial

It's internal but the removeHoles method uses PolyPartition which gives a nicer partitioning than naive triangulation

https://github.com/NREL/OpenStudio/blob/2c4dd5c9d790d1e1a019b328ca06957660733478/src/utilities/geometry/Intersection.cpp#L83

Thank you for all of the info, Dan.

This is all very helpful and I think I'll need some time to go through what documentation exists and probably also run some tests to see if it's giving us what we expect since I can't find any documentation about what exactly the subtract method returns. I'd assume that we can get a single list of vertices from it that winds inward to cut out the holes of a parent shape like what I describe here but I'm not sure.

I can see from the Polypartition github that it does ear clipping triangulation like what we use on the Python end so this should allow the measure to accept a wider range of fenestration surface input and not force us to always do triangulation in Python (definitely a big help!). I also see that Polypartition has some fancier subdivision methods as you mentioned but a lot of them seemed aimed at sub-diving to convex polygons and not shapes with <= 4 vertices, which I know is what we need for E+ fenestration. If there's a particular method that you typically use for fenestration, we can definitely use that. Otherwise, I know ear clipping will get the job done.

Subtract returns a vector of polygons. If the holes are all inside the polygon, then the result will be a vector of size 1 which is the original polygon with windings around all the holes. If the holes completely cut through the first polygon you can get out multiple polygons. It's based on boost::geometry::difference, we have used this in the radiance translator in the past to make holes for windows.

I don't think we ever really cared to make "nice" triangulation of the holes/windows themselves, just triangulated them if they were > 4 vertices. Typically we would just tag all the triangles with some id so we can associate them back to the original window.

We can add more functionality to the API based on methods in boost geometry or polypartition.

Dan,
I just wanted to say thanks again for all of the advice and explanations. I have opened a separate issue for the triangulation of sub-faces and pasted in all of your advice about it. This way, we can track it separately from the sorting of vertices to get the upper-left corner.

@tanushree04 ,
Looking at the OpenStudio::reorderULC method that Dan linked to, it seems that implementing automatic sorting of points on all the geometry translated by the measure should be pretty straightforward. Would you be able to add this in while I look into addressing the cases of geometry with holes and cases requiring triangulation?

@chriswmackey Yes, I can work on implementing this in the measure.

๐ŸŽ‰ This issue has been resolved in version 1.0.0 ๐ŸŽ‰

The release is available on GitHub release

Your semantic-release bot ๐Ÿ“ฆ๐Ÿš€