Skip to content

Commit

Permalink
Merge pull request #5003 from macumber/fix_5002
Browse files Browse the repository at this point in the history
Allow edges to have same surface on both sides
  • Loading branch information
jmarrec authored Oct 30, 2023
2 parents 6fb3ded + d746a33 commit b36c283
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/cli/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ int main(int argc, char* argv[]) {
->add_option_function<LogLevel>(
"-l,--loglevel",
[](const LogLevel& level) {
fmt::print("Setting Log Level to {} ({})\n", logLevelStrs[static_cast<size_t>(level) - static_cast<size_t>(LogLevel::Trace)], level);
fmt::print("Setting Log Level to {} ({})\n", logLevelStrs[static_cast<size_t>(level) - static_cast<size_t>(LogLevel::Trace)], std::to_string(level));
openstudio::Logger::instance().standardOutLogger().setLogLevel(level);
},
"LogLevel settings: One of {Trace, Debug, Info, Warn, Error, Fatal} [Default: Warn]")
Expand Down
24 changes: 20 additions & 4 deletions src/utilities/geometry/Polyhedron.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ std::ostream& operator<<(std::ostream& os, const Surface3dEdge& edge) {

Surface3d::Surface3d(std::vector<Point3d> t_vertices, std::string t_name, size_t t_surfNum)
: vertices(std::move(t_vertices)), name(std::move(t_name)), surfNum(t_surfNum) {

edges.reserve(vertices.size());
for (auto it = vertices.begin(); it != vertices.end(); ++it) {

auto itnext = std::next(it);
Expand Down Expand Up @@ -240,11 +242,9 @@ void Polyhedron::performEdgeMatching() {

m_hasAnySurfaceWithIncorrectOrientation = false;

// We use **Combinations** (rather than Permutations) to avoid traversing unnecessarily
for (size_t i = 0; i < m_surfaces.size(); ++i) {
for (size_t j = 0; j < m_surfaces.size(); ++j) {
if (i == j) {
continue;
}
for (size_t j = i + 1; j < m_surfaces.size(); ++j) {
auto& surface1 = m_surfaces[i];
auto& surface2 = m_surfaces[j];
for (Surface3dEdge& edge1 : surface1.edges) {
Expand All @@ -268,6 +268,22 @@ void Polyhedron::performEdgeMatching() {
}
}
}

// #5002 - special case to find edges that are used to "cut" in to a surface to remove an interior hole
// we allow these edges to double count the first surface since they bound the same surface on two sides
for (auto& surface : m_surfaces) {
auto& edges = surface.edges;
for (size_t i = 0; i < edges.size(); ++i) {
for (size_t j = i + 1; j < edges.size(); ++j) {
if ((edges[i].count() == 1) && (edges[j].count() == 1) && (edges[i] == edges[j]) && edges[i].reverseEqual(edges[j])) {
// appendSurface will allow use to check edge.count() later to check if count == 2.
// All edges must be count == 2 in an Enclosed Polyhedron
edges[i].appendSurface(surface);
edges[j].appendSurface(surface);
}
}
}
}
}

void Polyhedron::resetEdgeMatching() {
Expand Down
50 changes: 50 additions & 0 deletions src/utilities/geometry/Test/Polyhedron_GTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,56 @@ TEST_F(GeometryFixture, Polyhedron_Titled_Roof) {
EXPECT_DOUBLE_EQ(volume, zonePoly.calcDivergenceTheoremVolume());
}

TEST_F(GeometryFixture, Polyhedron_Box_With_Hole) {

// This is a 10x10x1 box, with a 5x5x1 hole cut in the middle

// We put extra vertices here to skew the calculate that Space::volume does
const Surface3d roof(
{{+10.0, +0.0, +1.0}, {+10.0, +10.0, +1.0}, {+0.0, +10.0, +1.0}, {+0.0, +0.0, +1.0},
{+2.50, +2.5, +1.0}, {+2.50, +7.50, +1.0}, {+7.5, +7.50, +1.0}, {+7.5, +2.5, +1.0}, {+2.50, +2.5, +1.0}, {+0.0, +0.0, +1.0}}, "ROOF", 1);
EXPECT_FALSE(roof.isConvex());

const Surface3d east1({{+10.0, +0.0, +1.0}, {+10.0, +0.0, +0.0}, {+10.0, +10.0, +0.0}, {+10.0, +10.0, +1.0}}, "EAST1", 2);
EXPECT_TRUE(east1.isConvex());

const Surface3d east2({{+7.50, +7.50, +1.0}, {+7.50, +7.50, +0.0}, {+7.50, +2.5, +0.0},{+7.50, +2.5, +1.0}}, "EAST2", 7);
EXPECT_TRUE(east2.isConvex());

const Surface3d north1({{+10.0, +10.0, +1.0}, {+10.0, +10.0, +0.0}, {+0.0, +10.0, +0.0}, {+0.0, +10.0, +1.0}}, "NORTH1", 3);
EXPECT_TRUE(north1.isConvex());

const Surface3d north2({{+2.5, +7.50, +1.0}, {+2.5, +7.50, +0.0}, {+7.50, +7.50, +0.0}, {+7.50, +7.50, +1.0}}, "NORTH2", 8);
EXPECT_TRUE(north2.isConvex());

const Surface3d west1({{+0.0, +10.0, +1.0}, {+0.0, +10.0, +0.0}, {+0.0, +0.0, +0.0}, {+0.0, +0.0, +1.0}}, "WEST1", 4);
EXPECT_TRUE(west1.isConvex());

const Surface3d west2({{+2.5, +2.5, +1.0}, {+2.5, +2.5, +0.0}, {+2.5, +7.50, +0.0}, {+2.5, +7.50, +1.0}}, "WEST2", 9);
EXPECT_TRUE(west2.isConvex());

const Surface3d south1({{+0.0, +0.0, +1.0}, {+0.0, +0.0, +0.0}, {+10.0, +0.0, +0.0}, {+10.0, +0.0, +1.0}}, "SOUTH1", 5);
EXPECT_TRUE(south1.isConvex());

const Surface3d south2({{+7.5, +2.5, +1.0}, {+7.5, +2.5, +0.0}, {+2.5, +2.5, +0.0}, {+2.5, +2.5, +1.0}}, "SOUTH2", 10);
EXPECT_TRUE(south2.isConvex());

const Surface3d floor(
{{+0.0, +10.0, +0.0}, {+10.0, +10.0, +0.0}, {+10.0, +0.0, +0.0}, {+0.0, +0.0, +0.0},
{+2.50, +2.5, +0.0}, {+7.50, +2.50, +0.0}, {+7.50, +7.5, +0.0}, {+2.50, +7.50, +0.0}, {+2.50, +2.5, +0.0}, {+0.0, +0.0, +0.0}}, "FLOOR", 6);
EXPECT_FALSE(floor.isConvex());

const Polyhedron zonePoly({south1, north1, east1, west1, roof, floor, south2, north2, east2, west2});

EXPECT_TRUE(zonePoly.isEnclosedVolume());
EXPECT_TRUE(zonePoly.edgesNotTwo().empty());
EXPECT_FALSE(zonePoly.hasAnySurfaceWithIncorrectOrientation());

constexpr double volume = 10.0 * 10.0 * 1.0 - 5.0 * 5.0 * 1.0;
EXPECT_DOUBLE_EQ(volume, zonePoly.polyhedronVolume());
EXPECT_DOUBLE_EQ(volume, zonePoly.calcDivergenceTheoremVolume());
}

TEST_F(GeometryFixture, Surface3d_Convexity) {
const Point3d p0{};
for (size_t i = 3; i <= 16; ++i) {
Expand Down

0 comments on commit b36c283

Please sign in to comment.