A 'quick and dirty' method to find and correct surfaces that have incorrect orientations Checks the surface against the space bounding box If the surface is at or near the upper bound of the bounding box it should be a Roof/Ceiling If the surface is at or near the lower bound of the bounding box it should be a Floor Works only for spaces with 3D shapes that are prisms in the sense that they have o
| 342 | // Works only for spaces with 3D shapes that are prisms in the sense that they have only two |
| 343 | // levels where there are horizontal surfaces. |
| 344 | void ReverseTranslator::validateSpaceSurfaces(openstudio::model::Model& model) { |
| 345 | |
| 346 | double tol = 0.001; |
| 347 | |
| 348 | const auto& spaces = model.getConcreteModelObjects<openstudio::model::Space>(); |
| 349 | for (const auto& space : spaces) { |
| 350 | std::string spaceName = space.name().value(); |
| 351 | |
| 352 | const auto& bounds = space.boundingBox(); |
| 353 | auto surfaces = space.surfaces(); |
| 354 | for (auto& surface : surfaces) { |
| 355 | std::string surfType = surface.surfaceType(); |
| 356 | std::string surfName = surface.name().value(); |
| 357 | |
| 358 | // Look for Roof or Floor surfaces that have adjacent surface (if there's no adjacwent surface |
| 359 | // then the spaces cannot be in the wrong order and the orientation would have already been fixed) |
| 360 | boost::optional<openstudio::model::Surface> adjacentSurf = surface.adjacentSurface(); |
| 361 | if ((surfType == "RoofCeiling" || surfType == "Floor") && adjacentSurf) { |
| 362 | auto vertices = surface.vertices(); |
| 363 | |
| 364 | if (std::abs(vertices[0].z() - bounds.maxZ().value()) > tol && std::abs(vertices[0].z() - bounds.minZ().value()) > tol) { |
| 365 | |
| 366 | // Log this because we cant do a face orientation check because the space |
| 367 | // isnt a prism (it has > 2 levels of horizontal surfaces) |
| 368 | LOG(Warn, "Skipping surface " << surfName << " of type " << surfType << " because it is not a prism"); |
| 369 | continue; |
| 370 | } |
| 371 | |
| 372 | if (std::abs(vertices[0].z() - bounds.maxZ().value()) <= tol) { |
| 373 | |
| 374 | // Surface is at the top of the space bounding box so it should be a roof/ceiling |
| 375 | // and the normal should be up (z should be > 0) |
| 376 | auto surfType = surface.surfaceType(); |
| 377 | if (surfType != "RoofCeiling") { |
| 378 | // Log changing surface type |
| 379 | LOG(Warn, "Changing surface type from " << surfType << " to RoofCeiling. Surface vertices elevation is above the space."); |
| 380 | surface.setSurfaceType("RoofCeiling"); |
| 381 | } |
| 382 | const auto& normal = surface.outwardNormal(); |
| 383 | if (normal.z() < 0) { |
| 384 | // Log reversing surface |
| 385 | LOG(Warn, "Reversing surface orientation because surface is a RoofCeiling but the surface is oriented down."); |
| 386 | std::reverse(vertices.begin(), vertices.end()); |
| 387 | surface.setVertices(vertices); |
| 388 | } |
| 389 | } else if (std::abs(vertices[0].z() - bounds.minZ().value()) <= tol) { |
| 390 | |
| 391 | // Surface is at the bottom of the space's bounding box and so should be a floor |
| 392 | // and the normal shuld be down (z < 0) |
| 393 | auto surfType = surface.surfaceType(); |
| 394 | if (surfType != "Floor") { |
| 395 | // Log changing surface type |
| 396 | surface.setSurfaceType("Floor"); |
| 397 | } |
| 398 | const auto& normal = surface.outwardNormal(); |
| 399 | if (normal.z() > 0) { |
| 400 | // Log reversing surface |
| 401 | LOG(Warn, "Reversing surface orientation because surface is a Floor but the surface is oriented up."); |
nothing calls this directly
no test coverage detected