Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenlib/tests/BLI_delaunay_2d_test.cc')
-rw-r--r--source/blender/blenlib/tests/BLI_delaunay_2d_test.cc372
1 files changed, 363 insertions, 9 deletions
diff --git a/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc b/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc
index d00e8bf55fd..59c4be6d952 100644
--- a/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc
+++ b/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc
@@ -17,6 +17,7 @@ extern "C" {
#define DO_CPP_TESTS 1
#define DO_C_TESTS 1
+#define DO_TEXT_TESTS 0
#define DO_RANDOM_TESTS 0
#include "BLI_array.hh"
@@ -267,7 +268,7 @@ template<typename T>
void graph_draw(const std::string &label,
const Array<vec2<T>> &verts,
const Array<std::pair<int, int>> &edges,
- const Array<Vector<int>> &UNUSED(faces))
+ const Array<Vector<int>> &faces)
{
/* Would like to use BKE_tempdir_base() here, but that brings in dependence on kernel library.
* This is just for developer debugging anyway, and should never be called in production Blender.
@@ -281,7 +282,7 @@ void graph_draw(const std::string &label,
constexpr int max_draw_height = 1000;
constexpr int thin_line = 1;
constexpr int vert_radius = 3;
- constexpr bool draw_vert_labels = true;
+ constexpr bool draw_vert_labels = false;
constexpr bool draw_edge_labels = false;
if (verts.size() == 0) {
@@ -339,6 +340,15 @@ void graph_draw(const std::string &label,
"xml:space=\"preserve\"\n"
<< "width=\"" << view_width << "\" height=\"" << view_height << "\">n";
+ for (const Vector<int> &fverts : faces) {
+ f << "<polygon fill=\"azure\" stroke=\"none\"\n points=\"";
+ for (int vi : fverts) {
+ const vec2<T> &co = verts[vi];
+ f << SX(co[0]) << "," << SY(co[1]) << " ";
+ }
+ f << "\"\n />\n";
+ }
+
for (const std::pair<int, int> &e : edges) {
const vec2<T> &uco = verts[e.first];
const vec2<T> &vco = verts[e.second];
@@ -642,6 +652,110 @@ template<typename T> void lineinsquare_test()
if (DO_DRAW) {
graph_draw<T>("LineInSquare - constraints", out2.vert, out2.edge, out2.face);
}
+ CDT_result<T> out3 = delaunay_2d_calc(in, CDT_INSIDE_WITH_HOLES);
+ EXPECT_EQ(out3.vert.size(), 6);
+ EXPECT_EQ(out3.face.size(), 6);
+ if (DO_DRAW) {
+ graph_draw<T>("LineInSquare - inside with holes", out3.vert, out3.edge, out3.face);
+ }
+ CDT_result<T> out4 = delaunay_2d_calc(in, CDT_CONSTRAINTS_VALID_BMESH_WITH_HOLES);
+ EXPECT_EQ(out4.vert.size(), 6);
+ EXPECT_EQ(out4.face.size(), 2);
+ if (DO_DRAW) {
+ graph_draw<T>("LineInSquare - valid bmesh with holes", out4.vert, out4.edge, out4.face);
+ }
+}
+
+template<typename T> void lineholeinsquare_test()
+{
+ const char *spec = R"(10 1 2
+ -0.5 -0.5
+ 0.5 -0.5
+ -0.5 0.5
+ 0.5 0.5
+ -0.25 0.0
+ 0.25 0.0
+ -0.4 -0.4
+ 0.4 -0.4
+ 0.4 -0.3
+ -0.4 -0.3
+ 4 5
+ 0 1 3 2
+ 6 7 8 9
+ )";
+
+ CDT_input<T> in = fill_input_from_string<T>(spec);
+ CDT_result<T> out = delaunay_2d_calc(in, CDT_FULL);
+ EXPECT_EQ(out.vert.size(), 10);
+ EXPECT_EQ(out.face.size(), 14);
+ if (DO_DRAW) {
+ graph_draw<T>("LineHoleInSquare - full", out.vert, out.edge, out.face);
+ }
+ CDT_result<T> out2 = delaunay_2d_calc(in, CDT_CONSTRAINTS);
+ EXPECT_EQ(out2.vert.size(), 10);
+ EXPECT_EQ(out2.face.size(), 2);
+ if (DO_DRAW) {
+ graph_draw<T>("LineHoleInSquare - constraints", out2.vert, out2.edge, out2.face);
+ }
+ CDT_result<T> out3 = delaunay_2d_calc(in, CDT_INSIDE_WITH_HOLES);
+ EXPECT_EQ(out3.vert.size(), 10);
+ EXPECT_EQ(out3.face.size(), 12);
+ if (DO_DRAW) {
+ graph_draw<T>("LineHoleInSquare - inside with holes", out3.vert, out3.edge, out3.face);
+ }
+ CDT_result<T> out4 = delaunay_2d_calc(in, CDT_CONSTRAINTS_VALID_BMESH_WITH_HOLES);
+ EXPECT_EQ(out4.vert.size(), 10);
+ EXPECT_EQ(out4.face.size(), 2);
+ if (DO_DRAW) {
+ graph_draw<T>("LineHoleInSquare - valid bmesh with holes", out4.vert, out4.edge, out4.face);
+ }
+}
+
+template<typename T> void nestedholes_test()
+{
+ const char *spec = R"(12 0 3
+ -0.5 -0.5
+ 0.5 -0.5
+ -0.5 0.5
+ 0.5 0.5
+ -0.4 -0.4
+ 0.4 -0.4
+ 0.4 0.4
+ -0.4 0.4
+ -0.2 -0.2
+ 0.2 -0.2
+ 0.2 0.2
+ -0.2 0.2
+ 0 1 3 2
+ 4 7 6 5
+ 8 9 10 11
+ )";
+
+ CDT_input<T> in = fill_input_from_string<T>(spec);
+ CDT_result<T> out = delaunay_2d_calc(in, CDT_FULL);
+ EXPECT_EQ(out.vert.size(), 12);
+ EXPECT_EQ(out.face.size(), 18);
+ if (DO_DRAW) {
+ graph_draw<T>("NestedHoles - full", out.vert, out.edge, out.face);
+ }
+ CDT_result<T> out2 = delaunay_2d_calc(in, CDT_CONSTRAINTS);
+ EXPECT_EQ(out2.vert.size(), 12);
+ EXPECT_EQ(out2.face.size(), 3);
+ if (DO_DRAW) {
+ graph_draw<T>("NestedHoles - constraints", out2.vert, out2.edge, out2.face);
+ }
+ CDT_result<T> out3 = delaunay_2d_calc(in, CDT_INSIDE_WITH_HOLES);
+ EXPECT_EQ(out3.vert.size(), 12);
+ EXPECT_EQ(out3.face.size(), 10);
+ if (DO_DRAW) {
+ graph_draw<T>("NestedHoles - inside with holes", out3.vert, out3.edge, out3.face);
+ }
+ CDT_result<T> out4 = delaunay_2d_calc(in, CDT_CONSTRAINTS_VALID_BMESH_WITH_HOLES);
+ EXPECT_EQ(out4.vert.size(), 12);
+ EXPECT_EQ(out4.face.size(), 3);
+ if (DO_DRAW) {
+ graph_draw<T>("NestedHoles - valid bmesh with holes", out4.vert, out4.edge, out4.face);
+ }
}
template<typename T> void crosssegs_test()
@@ -1025,16 +1139,28 @@ template<typename T> void overlapfaces_test()
graph_draw<T>("OverlapFaces - inside", out2.vert, out2.edge, out2.face);
}
- CDT_result<T> out3 = delaunay_2d_calc(in, CDT_CONSTRAINTS);
- EXPECT_EQ(out3.face.size(), 4);
+ CDT_result<T> out3 = delaunay_2d_calc(in, CDT_INSIDE_WITH_HOLES);
+ EXPECT_EQ(out3.face.size(), 14);
+ if (DO_DRAW) {
+ graph_draw<T>("OverlapFaces - inside with holes", out3.vert, out3.edge, out3.face);
+ }
+
+ CDT_result<T> out4 = delaunay_2d_calc(in, CDT_CONSTRAINTS);
+ EXPECT_EQ(out4.face.size(), 4);
if (DO_DRAW) {
- graph_draw<T>("OverlapFaces - constraints", out3.vert, out3.edge, out3.face);
+ graph_draw<T>("OverlapFaces - constraints", out4.vert, out4.edge, out4.face);
}
- CDT_result<T> out4 = delaunay_2d_calc(in, CDT_CONSTRAINTS_VALID_BMESH);
- EXPECT_EQ(out4.face.size(), 5);
+ CDT_result<T> out5 = delaunay_2d_calc(in, CDT_CONSTRAINTS_VALID_BMESH);
+ EXPECT_EQ(out5.face.size(), 5);
if (DO_DRAW) {
- graph_draw<T>("OverlapFaces - valid bmesh", out4.vert, out4.edge, out4.face);
+ graph_draw<T>("OverlapFaces - valid bmesh", out5.vert, out5.edge, out5.face);
+ }
+
+ CDT_result<T> out6 = delaunay_2d_calc(in, CDT_CONSTRAINTS_VALID_BMESH_WITH_HOLES);
+ EXPECT_EQ(out6.face.size(), 3);
+ if (DO_DRAW) {
+ graph_draw<T>("OverlapFaces - valid bmesh with holes", out6.vert, out6.edge, out6.face);
}
}
@@ -1246,6 +1372,34 @@ template<typename T> void repeattri_test()
}
}
+template<typename T> void square_o_test()
+{
+ const char *spec = R"(8 0 2
+ 0.0 0.0
+ 1.0 0.0
+ 1.0 1.0
+ 0.0 1.0
+ 0.2 0.2
+ 0.2 0.8
+ 0.8 0.8
+ 0.8 0.2
+ 0 1 2 3
+ 4 5 6 7
+ )";
+ CDT_input<T> in = fill_input_from_string<T>(spec);
+ CDT_result<T> out1 = delaunay_2d_calc(in, CDT_INSIDE_WITH_HOLES);
+ EXPECT_EQ(out1.face.size(), 8);
+ if (DO_DRAW) {
+ graph_draw<T>("Square O - inside with holes", out1.vert, out1.edge, out1.face);
+ }
+
+ CDT_result<T> out2 = delaunay_2d_calc(in, CDT_CONSTRAINTS_VALID_BMESH_WITH_HOLES);
+ EXPECT_EQ(out2.face.size(), 2);
+ if (DO_DRAW) {
+ graph_draw<T>("Square O - valid bmesh with holes", out2.vert, out2.edge, out2.face);
+ }
+}
+
TEST(delaunay_d, Empty)
{
empty_test<double>();
@@ -1301,6 +1455,16 @@ TEST(delaunay_d, LineInSquare)
lineinsquare_test<double>();
}
+TEST(delaunay_d, LineHoleInSquare)
+{
+ lineholeinsquare_test<double>();
+}
+
+TEST(delaunay_d, NestedHoles)
+{
+ nestedholes_test<double>();
+}
+
TEST(delaunay_d, CrossSegs)
{
crosssegs_test<double>();
@@ -1371,6 +1535,11 @@ TEST(delaunay_d, RepeatTri)
repeattri_test<double>();
}
+TEST(delaunay_d, SquareO)
+{
+ square_o_test<double>();
+}
+
# ifdef WITH_GMP
TEST(delaunay_m, Empty)
{
@@ -1426,6 +1595,16 @@ TEST(delaunay_m, LineInSquare)
lineinsquare_test<mpq_class>();
}
+TEST(delaunay_m, LineHoleInSquare)
+{
+ lineholeinsquare_test<mpq_class>();
+}
+
+TEST(delaunay_m, NestedHoles)
+{
+ nestedholes_test<mpq_class>();
+}
+
TEST(delaunay_m, CrossSegs)
{
crosssegs_test<mpq_class>();
@@ -1496,7 +1675,6 @@ TEST(delaunay_m, RepeatTri)
repeattri_test<mpq_class>();
}
# endif
-
#endif
#if DO_C_TESTS
@@ -1524,6 +1702,182 @@ TEST(delaunay_d, CintTwoFace)
}
#endif
+#if DO_TEXT_TESTS
+template<typename T>
+void text_test(int num_arc_points, int num_lets_per_line, int num_lines, CDT_output_type otype)
+{
+ constexpr bool print_timing = true;
+ /*
+ * Make something like a letter B:
+ *
+ * 4------------3
+ * | )
+ * | 12--11 )
+ * | | ) a3 ) a1
+ * | 9---10 )
+ * | )
+ * | 2
+ * | )
+ * | 8----7 )
+ * | | ) a2 ) a0
+ * | 5----6 )
+ * | )
+ * 0------------1
+ *
+ * Where the numbers are the first 13 vertices, and the rest of
+ * the vertices are in arcs a0, a1, a2, a3, each of which have
+ * num_arc_points per arc in them.
+ */
+
+ const char *b_before_arcs = R"(13 0 3
+ 0.0 0.0
+ 1.0 0.0
+ 1.0 1.5
+ 1.0 3.0
+ 0.0 3.0
+ 0.2 0.2
+ 0.6 0.2
+ 0.6 1.4
+ 0.2 1.4
+ 0.2 1.6
+ 0.6 1.6
+ 0.6 2.8
+ 0.2 2.8
+ 3 4 0 1 2
+ 6 5 8 7
+ 10 9 12 11
+ )";
+
+ CDT_input<T> b_before_arcs_in = fill_input_from_string<T>(b_before_arcs);
+ constexpr int narcs = 4;
+ int b_npts = b_before_arcs_in.vert.size() + narcs * num_arc_points;
+ constexpr int b_nfaces = 3;
+ Array<vec2<T>> b_vert(b_npts);
+ Array<Vector<int>> b_face(b_nfaces);
+ std::copy(b_before_arcs_in.vert.begin(), b_before_arcs_in.vert.end(), b_vert.begin());
+ std::copy(b_before_arcs_in.face.begin(), b_before_arcs_in.face.end(), b_face.begin());
+ if (num_arc_points > 0) {
+ b_face[0].pop_last(); // We'll add center point back between arcs for outer face.
+ for (int arc = 0; arc < narcs; ++arc) {
+ int arc_origin_vert;
+ int arc_terminal_vert;
+ bool ccw;
+ switch (arc) {
+ case 0:
+ arc_origin_vert = 1;
+ arc_terminal_vert = 2;
+ ccw = true;
+ break;
+ case 1:
+ arc_origin_vert = 2;
+ arc_terminal_vert = 3;
+ ccw = true;
+ break;
+ case 2:
+ arc_origin_vert = 7;
+ arc_terminal_vert = 6;
+ ccw = false;
+ break;
+ case 3:
+ arc_origin_vert = 11;
+ arc_terminal_vert = 10;
+ ccw = false;
+ break;
+ default:
+ BLI_assert(false);
+ }
+ vec2<T> start_co = b_vert[arc_origin_vert];
+ vec2<T> end_co = b_vert[arc_terminal_vert];
+ vec2<T> center_co = 0.5 * (start_co + end_co);
+ BLI_assert(start_co[0] == end_co[2]);
+ double radius = abs(math_to_double<T>(end_co[1] - center_co[1]));
+ double angle_delta = M_PI / (num_arc_points + 1);
+ int start_vert = b_before_arcs_in.vert.size() + arc * num_arc_points;
+ Vector<int> &face = b_face[(arc <= 1) ? 0 : arc - 1];
+ for (int i = 0; i < num_arc_points; ++i) {
+ vec2<T> delta;
+ float ang = ccw ? (-M_PI_2 + (i + 1) * angle_delta) : (M_PI_2 - (i + 1) * angle_delta);
+ delta[0] = T(radius * cos(ang));
+ delta[1] = T(radius * sin(ang));
+ b_vert[start_vert + i] = center_co + delta;
+ face.append(start_vert + i);
+ }
+ if (arc == 0) {
+ face.append(arc_terminal_vert);
+ }
+ }
+ }
+
+ CDT_input<T> in;
+ int tot_instances = num_lets_per_line * num_lines;
+ if (tot_instances == 1) {
+ in.vert = b_vert;
+ in.face = b_face;
+ }
+ else {
+ in.vert = Array<vec2<T>>(tot_instances * b_vert.size());
+ in.face = Array<Vector<int>>(tot_instances * b_face.size());
+ T cur_x = T(0);
+ T cur_y = T(0);
+ T delta_x = T(2);
+ T delta_y = T(3.25);
+ int instance = 0;
+ for (int line = 0; line < num_lines; ++line) {
+ for (int let = 0; let < num_lets_per_line; ++let) {
+ vec2<T> co_offset(cur_x, cur_y);
+ int in_v_offset = instance * b_vert.size();
+ for (int v = 0; v < b_vert.size(); ++v) {
+ in.vert[in_v_offset + v] = b_vert[v] + co_offset;
+ }
+ int in_f_offset = instance * b_face.size();
+ for (int f : b_face.index_range()) {
+ for (int fv : b_face[f]) {
+ in.face[in_f_offset + f].append(in_v_offset + fv);
+ }
+ }
+ cur_x += delta_x;
+ ++instance;
+ }
+ cur_y += delta_y;
+ cur_x = T(0);
+ }
+ }
+ in.epsilon = b_before_arcs_in.epsilon;
+ double tstart = PIL_check_seconds_timer();
+ CDT_result<T> out = delaunay_2d_calc(in, otype);
+ double tend = PIL_check_seconds_timer();
+ if (print_timing) {
+ std::cout << "time = " << tend - tstart << "\n";
+ }
+ if (DO_DRAW) {
+ std::string label = "Text arcpts=" + std::to_string(num_arc_points);
+ if (num_lets_per_line > 1) {
+ label += " linelen=" + std::to_string(num_lets_per_line);
+ }
+ if (num_lines > 1) {
+ label += " lines=" + std::to_string(num_lines);
+ }
+ graph_draw<T>(label, out.vert, out.edge, out.face);
+ }
+}
+
+TEST(delaunay_d, TextB10)
+{
+ text_test<double>(10, 1, 1, CDT_INSIDE_WITH_HOLES);
+}
+
+TEST(delaunay_d, TextB200)
+{
+ text_test<double>(200, 1, 1, CDT_INSIDE_WITH_HOLES);
+}
+
+TEST(delaunay_d, TextB10_10_10)
+{
+ text_test<double>(10, 10, 10, CDT_INSIDE_WITH_HOLES);
+}
+
+#endif
+
#if DO_RANDOM_TESTS
enum {