Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #4831 - Platform dependent results for joinAll #4848

Merged
merged 3 commits into from
Apr 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/utilities/geometry/Intersection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
# pragma warning(pop)
#endif

#include <algorithm>
#include <cmath>
#include <iterator>

Expand Down Expand Up @@ -784,7 +785,9 @@ std::vector<std::vector<Point3d>> joinAll(const std::vector<std::vector<Point3d>
const std::vector<std::vector<unsigned>> connectedComponents = findConnectedComponents(A);
for (const std::vector<unsigned>& component : connectedComponents) {
std::vector<unsigned> orderedComponent(component);
std::sort(orderedComponent.begin(), orderedComponent.end(), [&polygonAreas](int ia, int ib) { return polygonAreas[ia] > polygonAreas[ib]; });
// #4831 - Use a stable_sort to produce consistent results between Windows and Unix in case you have polygons with the same area
std::stable_sort(orderedComponent.begin(), orderedComponent.end(),
[&polygonAreas](int ia, int ib) { return polygonAreas[ia] > polygonAreas[ib]; });

std::vector<Point3d> points;
std::set<unsigned> joinedComponents;
Expand Down Expand Up @@ -1437,7 +1440,9 @@ std::vector<Polygon3d> joinAll(const std::vector<Polygon3d>& polygons, double /*
for (const std::vector<unsigned>& component : connectedComponents) {

std::vector<unsigned> orderedComponent(component);
std::sort(orderedComponent.begin(), orderedComponent.end(), [&polygonAreas](int ia, int ib) { return polygonAreas[ia] > polygonAreas[ib]; });
// #4831 - Use a stable_sort to produce consistent results between Windows and Unix in case you have polygons with the same area
std::stable_sort(orderedComponent.begin(), orderedComponent.end(),
[&polygonAreas](int ia, int ib) { return polygonAreas[ia] > polygonAreas[ib]; });

Polygon3d polygon;
std::set<unsigned> joinedComponents;
Expand Down
287 changes: 286 additions & 1 deletion src/utilities/geometry/Test/Intersection_GTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,17 @@
***********************************************************************************************************************/

#include <gtest/gtest.h>
#include "../Intersection.hpp"
#include "GeometryFixture.hpp"

#include "../Intersection.hpp"

#include "../Geometry.hpp"
#include "../PointLatLon.hpp"
#include "../Vector3d.hpp"

#include "../../core/StringStreamLogSink.hpp"
#include "../../core/LogMessage.hpp"

#undef BOOST_UBLAS_TYPE_CHECK
#if defined(_MSC_VER)
# pragma warning(push)
Expand Down Expand Up @@ -2406,3 +2412,282 @@ TEST_F(GeometryFixture, Issue_3982) {
ASSERT_EQ(4, intersection2->newPolygons1()[4].size());
ASSERT_EQ(0, intersection1->newPolygons2().size());
}

TEST_F(GeometryFixture, Intersection_Stability) {
// Test for #4831

std::vector<std::vector<Point3d>> toplit_polygons = {
// Polygon 0
{
{-3.2099999999999995, -3.3206999999999995, 0.0},
{-3.2099999999999995, 9.0985, 0.0},
{9.209999999999999, 9.0985, 0.0},
{9.209999999999999, -3.3206999999999995, 0.0},
},
// Polygon 1
{
{2.790000000000001, 8.2348, 0.0},
{2.790000000000001, 20.654, 0.0},
{15.209999999999999, 20.654, 0.0},
{15.209999999999999, 8.2348, 0.0},
},
// Polygon 2
{
{8.790000000000001, 8.2348, 0.0},
{8.790000000000001, 20.654, 0.0},
{21.21, 20.654, 0.0},
{21.21, 8.2348, 0.0},
},
// Polygon 3
{
{14.790000000000001, 8.2348, 0.0},
{14.790000000000001, 20.654, 0.0},
{27.21, 20.654, 0.0},
{27.21, 8.2348, 0.0},
},
// Polygon 4
{
{-3.2099999999999995, 14.0126, 0.0},
{-3.2099999999999995, 26.431800000000003, 0.0},
{9.209999999999999, 26.431800000000003, 0.0},
{9.209999999999999, 14.0126, 0.0},
},
// Polygon 5
{
{2.790000000000001, 14.0126, 0.0},
{2.790000000000001, 26.431800000000003, 0.0},
{15.209999999999999, 26.431800000000003, 0.0},
{15.209999999999999, 14.0126, 0.0},
},
// Polygon 6
{
{8.790000000000001, 14.0126, 0.0},
{8.790000000000001, 26.431800000000003, 0.0},
{21.21, 26.431800000000003, 0.0},
{21.21, 14.0126, 0.0},
},
// Polygon 7
{
{14.790000000000001, 14.0126, 0.0},
{14.790000000000001, 26.431800000000003, 0.0},
{27.21, 26.431800000000003, 0.0},
{27.21, 14.0126, 0.0},
},
// Polygon 8
{
{-3.2099999999999995, 19.790399999999998, 0.0},
{-3.2099999999999995, 32.2096, 0.0},
{9.209999999999999, 32.2096, 0.0},
{9.209999999999999, 19.790399999999998, 0.0},
},
// Polygon 9
{
{2.790000000000001, 19.790399999999998, 0.0},
{2.790000000000001, 32.2096, 0.0},
{15.209999999999999, 32.2096, 0.0},
{15.209999999999999, 19.790399999999998, 0.0},
},
// Polygon 10
{
{8.790000000000001, 19.790399999999998, 0.0},
{8.790000000000001, 32.2096, 0.0},
{21.21, 32.2096, 0.0},
{21.21, 19.790399999999998, 0.0},
},
// Polygon 11
{
{2.790000000000001, -3.3206999999999995, 0.0},
{2.790000000000001, 9.0985, 0.0},
{15.209999999999999, 9.0985, 0.0},
{15.209999999999999, -3.3206999999999995, 0.0},
},
// Polygon 12
{
{14.790000000000001, 19.790399999999998, 0.0},
{14.790000000000001, 32.2096, 0.0},
{27.21, 32.2096, 0.0},
{27.21, 19.790399999999998, 0.0},
},
// Polygon 13
{
{-3.2099999999999995, 25.568199999999997, 0.0},
{-3.2099999999999995, 37.9874, 0.0},
{9.209999999999999, 37.9874, 0.0},
{9.209999999999999, 25.568199999999997, 0.0},
},
// Polygon 14
{
{2.790000000000001, 25.568199999999997, 0.0},
{2.790000000000001, 37.9874, 0.0},
{15.209999999999999, 37.9874, 0.0},
{15.209999999999999, 25.568199999999997, 0.0},
},
// Polygon 15
{
{8.790000000000001, 25.568199999999997, 0.0},
{8.790000000000001, 37.9874, 0.0},
{21.21, 37.9874, 0.0},
{21.21, 25.568199999999997, 0.0},
},
// Polygon 16
{
{14.790000000000001, 25.568199999999997, 0.0},
{14.790000000000001, 37.9874, 0.0},
{27.21, 37.9874, 0.0},
{27.21, 25.568199999999997, 0.0},
},
// Polygon 17
{
{-3.2099999999999995, 31.345999999999997, 0.0},
{-3.2099999999999995, 43.7652, 0.0},
{9.209999999999999, 43.7652, 0.0},
{9.209999999999999, 31.345999999999997, 0.0},
},
// Polygon 18
{
{2.790000000000001, 31.345999999999997, 0.0},
{2.790000000000001, 43.7652, 0.0},
{15.209999999999999, 43.7652, 0.0},
{15.209999999999999, 31.345999999999997, 0.0},
},
// Polygon 19
{
{8.790000000000001, 31.345999999999997, 0.0},
{8.790000000000001, 43.7652, 0.0},
{21.21, 43.7652, 0.0},
{21.21, 31.345999999999997, 0.0},
},
// Polygon 20
{
{14.790000000000001, 31.345999999999997, 0.0},
{14.790000000000001, 43.7652, 0.0},
{27.21, 43.7652, 0.0},
{27.21, 31.345999999999997, 0.0},
},
// Polygon 21
{
{-3.2099999999999995, 37.1237, 0.0},
{-3.2099999999999995, 49.5429, 0.0},
{9.209999999999999, 49.5429, 0.0},
{9.209999999999999, 37.1237, 0.0},
},
// Polygon 22
{
{8.790000000000001, -3.3206999999999995, 0.0},
{8.790000000000001, 9.0985, 0.0},
{21.21, 9.0985, 0.0},
{21.21, -3.3206999999999995, 0.0},
},
// Polygon 23
{
{2.790000000000001, 37.1237, 0.0},
{2.790000000000001, 49.5429, 0.0},
{15.209999999999999, 49.5429, 0.0},
{15.209999999999999, 37.1237, 0.0},
},
// Polygon 24
{
{8.790000000000001, 37.1237, 0.0},
{8.790000000000001, 49.5429, 0.0},
{21.21, 49.5429, 0.0},
{21.21, 37.1237, 0.0},
},
// Polygon 25
{
{14.790000000000001, 37.1237, 0.0},
{14.790000000000001, 49.5429, 0.0},
{27.21, 49.5429, 0.0},
{27.21, 37.1237, 0.0},
},
// Polygon 26
{
{-3.2099999999999995, 42.9015, 0.0},
{-3.2099999999999995, 55.3207, 0.0},
{9.209999999999999, 55.3207, 0.0},
{9.209999999999999, 42.9015, 0.0},
},
// Polygon 27
{
{2.790000000000001, 42.9015, 0.0},
{2.790000000000001, 55.3207, 0.0},
{15.209999999999999, 55.3207, 0.0},
{15.209999999999999, 42.9015, 0.0},
},
// Polygon 28
{
{8.790000000000001, 42.9015, 0.0},
{8.790000000000001, 55.3207, 0.0},
{21.21, 55.3207, 0.0},
{21.21, 42.9015, 0.0},
},
// Polygon 29
{
{14.790000000000001, 42.9015, 0.0},
{14.790000000000001, 55.3207, 0.0},
{27.21, 55.3207, 0.0},
{27.21, 42.9015, 0.0},
},
// Polygon 30
{
{14.790000000000001, -3.3206999999999995, 0.0},
{14.790000000000001, 9.0985, 0.0},
{27.21, 9.0985, 0.0},
{27.21, -3.3206999999999995, 0.0},
},
// Polygon 31
{
{-3.2099999999999995, 2.4571000000000005, 0.0},
{-3.2099999999999995, 14.8763, 0.0},
{9.209999999999999, 14.8763, 0.0},
{9.209999999999999, 2.4571000000000005, 0.0},
},
// Polygon 32
{
{2.790000000000001, 2.4571000000000005, 0.0},
{2.790000000000001, 14.8763, 0.0},
{15.209999999999999, 14.8763, 0.0},
{15.209999999999999, 2.4571000000000005, 0.0},
},
// Polygon 33
{
{8.790000000000001, 2.4571000000000005, 0.0},
{8.790000000000001, 14.8763, 0.0},
{21.21, 14.8763, 0.0},
{21.21, 2.4571000000000005, 0.0},
},
// Polygon 34
{
{14.790000000000001, 2.4571000000000005, 0.0},
{14.790000000000001, 14.8763, 0.0},
{27.21, 14.8763, 0.0},
{27.21, 2.4571000000000005, 0.0},
},
// Polygon 35
{
{-3.2099999999999995, 8.2348, 0.0},
{-3.2099999999999995, 20.654, 0.0},
{9.209999999999999, 20.654, 0.0},
{9.209999999999999, 8.2348, 0.0},
},
};

constexpr double tol = 0.01;

StringStreamLogSink sink;
sink.setLogLevel(Error);

auto combinedPolygons = openstudio::joinAll(toplit_polygons, tol);
EXPECT_TRUE(sink.logMessages().empty());
ASSERT_EQ(1, combinedPolygons.size());
auto& polygon = combinedPolygons.front();
std::vector<Point3d> expectedPolygon{
{27.21, 55.3207, 0.0},
{27.21, -3.3207, 0},
{-3.21, -3.3207, 0},
{-3.21, 55.3207, 0},
};
EXPECT_EQ(4, polygon.size());
for (size_t i = 0; const auto& pt : polygon) {
EXPECT_TRUE(openstudio::isAlmostEqual3dPt(expectedPolygon[i++], pt, 0.001));
}
}