Skip to content

Commit 12b9494

Browse files
authored
Fix the zebra polygon (#832)
* add Zebra polygon stress test * fixed Zebra polygon - 4 bugs * fix MSVC build * try MSVC fix
1 parent 0577aab commit 12b9494

File tree

7 files changed

+63260
-16
lines changed

7 files changed

+63260
-16
lines changed

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ if(CMAKE_EXPORT_COMPILE_COMMANDS AND NOT EMSCRIPTEN)
8383
endif()
8484

8585
if (MSVC)
86-
set(MANIFOLD_FLAGS ${MANIFOLD_FLAGS} /DNOMINMAX)
86+
set(MANIFOLD_FLAGS ${MANIFOLD_FLAGS} /DNOMINMAX /bigobj)
8787
else()
8888
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
8989
set(WARNING_FLAGS -Werror -Wall -Wno-sign-compare -Wno-unused -Wno-array-bounds

src/polygon/src/polygon.cpp

+27-7
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,13 @@ class EarClip {
344344
// it finds a clear geometric result. In the vast majority of cases the loop
345345
// will only need one or two iterations.
346346
bool IsConvex(float precision) const {
347+
const int convexity = CCW(left->pos, pos, right->pos, precision);
348+
if (convexity != 0) {
349+
return convexity > 0;
350+
}
351+
if (glm::dot(left->pos - pos, right->pos - pos) <= 0) {
352+
return true;
353+
}
347354
return left->InsideEdge(left->right, precision, true);
348355
}
349356

@@ -363,8 +370,8 @@ class EarClip {
363370
const auto none = std::make_pair(left, false);
364371
if (pos.y < start.y && right->pos.y >= start.y) {
365372
return std::make_pair(left->right, true);
366-
} else if (pos.x > start.x - precision && pos.y > start.y - precision &&
367-
pos.y < start.y + precision &&
373+
} else if (onTop != 0 && pos.x > start.x - precision &&
374+
pos.y > start.y - precision && pos.y < start.y + precision &&
368375
Interior(start, precision) >= 0) {
369376
if (onTop > 0 && left->pos.x < pos.x &&
370377
left->pos.y > start.y - precision) {
@@ -433,7 +440,7 @@ class EarClip {
433440
float totalCost = glm::dot(left->rightDir, rightDir) - 1 - precision;
434441
if (CCW(pos, left->pos, right->pos, precision) == 0) {
435442
// Clip folded ears first
436-
return totalCost < -1 ? kBest : 0;
443+
return totalCost;
437444
}
438445

439446
Vec<Box> earBox;
@@ -611,7 +618,7 @@ class EarClip {
611618
areaCompensation += (area - t1) + area1;
612619
area = t1;
613620

614-
if (!v->IsConvex(precision_) && v->pos.x > maxX) {
621+
if (v->pos.x > maxX) {
615622
maxX = v->pos.x;
616623
start = v;
617624
}
@@ -754,6 +761,8 @@ class EarClip {
754761
} else if (v->IsConvex(precision_)) {
755762
v->cost = v->EarCost(precision_, collider);
756763
v->ear = earsQueue_.insert(v);
764+
} else {
765+
v->cost = 1; // not used, but marks reflex verts for debug
757766
}
758767
}
759768

@@ -852,6 +861,15 @@ class EarClip {
852861
std::cout << " [" << v->pos.x << ", " << v->pos.y << "],# " << v->mesh_idx
853862
<< std::endl;
854863
std::cout << "]))" << std::endl;
864+
865+
v = start;
866+
std::cout << "polys.push_back({" << std::setprecision(9) << std::endl;
867+
do {
868+
std::cout << " {" << v->pos.x << ", " << v->pos.y << "}, //"
869+
<< std::endl;
870+
v = v->right;
871+
} while (v != start);
872+
std::cout << "});" << std::endl;
855873
#endif
856874
}
857875
};
@@ -875,23 +893,25 @@ namespace manifold {
875893
std::vector<glm::ivec3> TriangulateIdx(const PolygonsIdx &polys,
876894
float precision) {
877895
std::vector<glm::ivec3> triangles;
896+
float updatedPrecision = precision;
878897
try {
879898
EarClip triangulator(polys, precision);
899+
updatedPrecision = triangulator.GetPrecision();
880900
triangles = triangulator.Triangulate();
881901
#ifdef MANIFOLD_DEBUG
882902
if (params.intermediateChecks) {
883903
CheckTopology(triangles, polys);
884904
if (!params.processOverlaps) {
885-
CheckGeometry(triangles, polys, 2 * triangulator.GetPrecision());
905+
CheckGeometry(triangles, polys, 2 * updatedPrecision);
886906
}
887907
}
888908
} catch (const geometryErr &e) {
889909
if (!params.suppressErrors) {
890-
PrintFailure(e, polys, triangles, precision);
910+
PrintFailure(e, polys, triangles, updatedPrecision);
891911
}
892912
throw;
893913
} catch (const std::exception &e) {
894-
PrintFailure(e, polys, triangles, precision);
914+
PrintFailure(e, polys, triangles, updatedPrecision);
895915
throw;
896916
#else
897917
} catch (const std::exception &e) {

test/polygon_corpus.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ TEST(Polygon, Ugly) {
570570
{2289.28784, 13251.1582}, //
571571
{2379.03027, 13010.5566}, //
572572
});
573-
TestPoly(polys, 32);
573+
TestPoly(polys, 36);
574574
};
575575

576576
TEST(Polygon, Sponge4a) {

test/polygon_test.cpp

+8-5
Original file line numberDiff line numberDiff line change
@@ -56,21 +56,24 @@ Polygons Duplicate(Polygons polys) {
5656
}
5757

5858
void TestPoly(const Polygons &polys, int expectedNumTri,
59-
float precision = -1.0f) {
59+
float precision = -1.0f, bool onlyBasic = false) {
6060
PolygonParams().verbose = options.params.verbose;
6161

6262
std::vector<glm::ivec3> triangles;
6363
EXPECT_NO_THROW(triangles = Triangulate(polys, precision));
6464
EXPECT_EQ(triangles.size(), expectedNumTri) << "Basic";
6565

66-
EXPECT_NO_THROW(triangles = Triangulate(Turn180(polys), precision));
67-
EXPECT_EQ(triangles.size(), expectedNumTri) << "Turn 180";
66+
if (!onlyBasic) {
67+
EXPECT_NO_THROW(triangles = Triangulate(Turn180(polys), precision));
68+
EXPECT_EQ(triangles.size(), expectedNumTri) << "Turn 180";
6869

69-
EXPECT_NO_THROW(triangles = Triangulate(Duplicate(polys), precision));
70-
EXPECT_EQ(triangles.size(), 2 * expectedNumTri) << "Duplicate";
70+
EXPECT_NO_THROW(triangles = Triangulate(Duplicate(polys), precision));
71+
EXPECT_EQ(triangles.size(), 2 * expectedNumTri) << "Duplicate";
72+
}
7173

7274
PolygonParams().verbose = false;
7375
}
7476
} // namespace
7577

7678
#include "polygon_corpus.cpp"
79+
#include "zebra.cpp"

test/sdf_test.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ TEST(SDF, SineSurface) {
116116
Mesh surface(LevelSet(
117117
[](glm::vec3 p) {
118118
float mid = glm::sin(p.x) + glm::sin(p.y);
119-
return (p.z > mid - 0.5 && p.z < mid + 0.5) ? 1 : 0;
119+
return (p.z > mid - 0.5 && p.z < mid + 0.5) ? 1.0f : 0.0f;
120120
},
121121
{glm::vec3(-4 * glm::pi<float>()), glm::vec3(4 * glm::pi<float>())}, 1));
122122
Manifold smoothed = Manifold::Smooth(surface).Refine(2);

test/smooth_test.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ TEST(Smooth, SineSurface) {
323323
MeshGL surface = LevelSet(
324324
[](glm::vec3 p) {
325325
float mid = glm::sin(p.x) + glm::sin(p.y);
326-
return (p.z > mid - 0.5 && p.z < mid + 0.5) ? 1 : -1;
326+
return (p.z > mid - 0.5 && p.z < mid + 0.5) ? 1.0f : -1.0f;
327327
},
328328
{glm::vec3(-2 * glm::pi<float>() + 0.2),
329329
glm::vec3(0 * glm::pi<float>() - 0.2)},

0 commit comments

Comments
 (0)