BLI_polyfill_2d_test.cc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  1. /* Apache License, Version 2.0 */
  2. #include "testing/testing.h"
  3. /* Use to write out OBJ files, handy for checking output */
  4. // #define USE_OBJ_PREVIEW
  5. /* test every possible offset and reverse */
  6. #define USE_COMBINATIONS_ALL
  7. #define USE_BEAUTIFY
  8. extern "C" {
  9. #include "BLI_utildefines.h"
  10. #include "BLI_array_utils.h"
  11. #include "BLI_polyfill_2d.h"
  12. #include "BLI_edgehash.h"
  13. #include "BLI_math.h"
  14. #include "MEM_guardedalloc.h"
  15. #ifdef USE_OBJ_PREVIEW
  16. # include "BLI_string.h"
  17. #endif
  18. #ifdef USE_BEAUTIFY
  19. # include "BLI_polyfill_2d_beautify.h"
  20. # include "BLI_memarena.h"
  21. # include "BLI_heap.h"
  22. #endif
  23. }
  24. #include "stubs/bf_intern_eigen_stubs.h"
  25. static void polyfill_to_obj(const char *id,
  26. const float poly[][2],
  27. const unsigned int poly_tot,
  28. const unsigned int tris[][3],
  29. const unsigned int tris_tot);
  30. /* -------------------------------------------------------------------- */
  31. /* test utility functions */
  32. #define TRI_ERROR_VALUE (unsigned int)-1
  33. static void test_valid_polyfill_prepare(unsigned int tris[][3], unsigned int tris_tot)
  34. {
  35. unsigned int i;
  36. for (i = 0; i < tris_tot; i++) {
  37. unsigned int j;
  38. for (j = 0; j < 3; j++) {
  39. tris[i][j] = TRI_ERROR_VALUE;
  40. }
  41. }
  42. }
  43. /**
  44. * Basic check for face index values:
  45. *
  46. * - no duplicates.
  47. * - all tris set.
  48. * - all verts used at least once.
  49. */
  50. static void test_polyfill_simple(const float poly[][2],
  51. const unsigned int poly_tot,
  52. const unsigned int tris[][3],
  53. const unsigned int tris_tot)
  54. {
  55. unsigned int i;
  56. int *tot_used = (int *)MEM_callocN(poly_tot * sizeof(int), __func__);
  57. for (i = 0; i < tris_tot; i++) {
  58. unsigned int j;
  59. for (j = 0; j < 3; j++) {
  60. EXPECT_NE(TRI_ERROR_VALUE, tris[i][j]);
  61. tot_used[tris[i][j]] += 1;
  62. }
  63. EXPECT_NE(tris[i][0], tris[i][1]);
  64. EXPECT_NE(tris[i][1], tris[i][2]);
  65. EXPECT_NE(tris[i][2], tris[i][0]);
  66. }
  67. for (i = 0; i < poly_tot; i++) {
  68. EXPECT_NE(0, tot_used[i]);
  69. }
  70. MEM_freeN(tot_used);
  71. }
  72. static void test_polyfill_topology(const float poly[][2],
  73. const unsigned int poly_tot,
  74. const unsigned int tris[][3],
  75. const unsigned int tris_tot)
  76. {
  77. EdgeHash *edgehash = BLI_edgehash_new(__func__);
  78. EdgeHashIterator *ehi;
  79. unsigned int i;
  80. for (i = 0; i < tris_tot; i++) {
  81. unsigned int j;
  82. for (j = 0; j < 3; j++) {
  83. const unsigned int v1 = tris[i][j];
  84. const unsigned int v2 = tris[i][(j + 1) % 3];
  85. void **p = BLI_edgehash_lookup_p(edgehash, v1, v2);
  86. if (p) {
  87. *p = (void *)((intptr_t)*p + (intptr_t)1);
  88. }
  89. else {
  90. BLI_edgehash_insert(edgehash, v1, v2, (void *)(intptr_t)1);
  91. }
  92. }
  93. }
  94. EXPECT_EQ(BLI_edgehash_len(edgehash), poly_tot + (poly_tot - 3));
  95. for (i = 0; i < poly_tot; i++) {
  96. const unsigned int v1 = i;
  97. const unsigned int v2 = (i + 1) % poly_tot;
  98. void **p = BLI_edgehash_lookup_p(edgehash, v1, v2);
  99. EXPECT_EQ((void *)p != NULL, 1);
  100. EXPECT_EQ((intptr_t)*p, 1);
  101. }
  102. for (ehi = BLI_edgehashIterator_new(edgehash), i = 0; BLI_edgehashIterator_isDone(ehi) == false;
  103. BLI_edgehashIterator_step(ehi), i++) {
  104. void **p = BLI_edgehashIterator_getValue_p(ehi);
  105. EXPECT_TRUE(ELEM((intptr_t)*p, 1, 2));
  106. }
  107. BLI_edgehashIterator_free(ehi);
  108. BLI_edgehash_free(edgehash, NULL);
  109. }
  110. /**
  111. * Check all faces are flipped the same way
  112. */
  113. static void test_polyfill_winding(const float poly[][2],
  114. const unsigned int poly_tot,
  115. const unsigned int tris[][3],
  116. const unsigned int tris_tot)
  117. {
  118. unsigned int i;
  119. unsigned int count[2] = {0, 0};
  120. for (i = 0; i < tris_tot; i++) {
  121. float winding_test = cross_tri_v2(poly[tris[i][0]], poly[tris[i][1]], poly[tris[i][2]]);
  122. if (fabsf(winding_test) > FLT_EPSILON) {
  123. count[winding_test < 0.0f] += 1;
  124. }
  125. }
  126. EXPECT_TRUE(ELEM(0, count[0], count[1]));
  127. }
  128. /**
  129. * Check the accumulated triangle area is close to the original area.
  130. */
  131. static void test_polyfill_area(const float poly[][2],
  132. const unsigned int poly_tot,
  133. const unsigned int tris[][3],
  134. const unsigned int tris_tot)
  135. {
  136. unsigned int i;
  137. const float area_tot = area_poly_v2(poly, poly_tot);
  138. float area_tot_tris = 0.0f;
  139. const float eps_abs = 0.00001f;
  140. const float eps = area_tot > 1.0f ? (area_tot * eps_abs) : eps_abs;
  141. for (i = 0; i < tris_tot; i++) {
  142. area_tot_tris += area_tri_v2(poly[tris[i][0]], poly[tris[i][1]], poly[tris[i][2]]);
  143. }
  144. EXPECT_NEAR(area_tot, area_tot_tris, eps);
  145. }
  146. /* -------------------------------------------------------------------- */
  147. /* Macro and helpers to manage checking */
  148. /**
  149. * Main template for polyfill testing.
  150. */
  151. static void test_polyfill_template_check(const char *id,
  152. bool is_degenerate,
  153. const float poly[][2],
  154. const unsigned int poly_tot,
  155. const unsigned int tris[][3],
  156. const unsigned int tris_tot)
  157. {
  158. test_polyfill_simple(poly, poly_tot, tris, tris_tot);
  159. test_polyfill_topology(poly, poly_tot, tris, tris_tot);
  160. if (!is_degenerate) {
  161. test_polyfill_winding(poly, poly_tot, tris, tris_tot);
  162. test_polyfill_area(poly, poly_tot, tris, tris_tot);
  163. }
  164. polyfill_to_obj(id, poly, poly_tot, tris, tris_tot);
  165. }
  166. static void test_polyfill_template(const char *id,
  167. bool is_degenerate,
  168. const float poly[][2],
  169. const unsigned int poly_tot,
  170. unsigned int tris[][3],
  171. const unsigned int tris_tot)
  172. {
  173. test_valid_polyfill_prepare(tris, tris_tot);
  174. BLI_polyfill_calc(poly, poly_tot, 0, tris);
  175. /* check all went well */
  176. test_polyfill_template_check(id, is_degenerate, poly, poly_tot, tris, tris_tot);
  177. #ifdef USE_BEAUTIFY
  178. /* check beautify gives good results too */
  179. {
  180. MemArena *pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
  181. Heap *pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE);
  182. BLI_polyfill_beautify(poly, poly_tot, tris, pf_arena, pf_heap);
  183. test_polyfill_template_check(id, is_degenerate, poly, poly_tot, tris, tris_tot);
  184. BLI_memarena_free(pf_arena);
  185. BLI_heap_free(pf_heap, NULL);
  186. }
  187. #endif
  188. }
  189. static void test_polyfill_template_flip_sign(const char *id,
  190. bool is_degenerate,
  191. const float poly[][2],
  192. const unsigned int poly_tot,
  193. unsigned int tris[][3],
  194. const unsigned int tris_tot)
  195. {
  196. float(*poly_copy)[2] = (float(*)[2])MEM_mallocN(sizeof(float[2]) * poly_tot, id);
  197. for (int flip_x = 0; flip_x < 2; flip_x++) {
  198. for (int flip_y = 0; flip_y < 2; flip_y++) {
  199. float sign_x = flip_x ? -1.0f : 1.0f;
  200. float sign_y = flip_y ? -1.0f : 1.0f;
  201. for (int i = 0; i < poly_tot; i++) {
  202. poly_copy[i][0] = poly[i][0] * sign_x;
  203. poly_copy[i][1] = poly[i][1] * sign_y;
  204. }
  205. test_polyfill_template(id, is_degenerate, poly_copy, poly_tot, tris, tris_tot);
  206. }
  207. }
  208. MEM_freeN(poly_copy);
  209. }
  210. #ifdef USE_COMBINATIONS_ALL
  211. static void test_polyfill_template_main(const char *id,
  212. bool is_degenerate,
  213. const float poly[][2],
  214. const unsigned int poly_tot,
  215. unsigned int tris[][3],
  216. const unsigned int tris_tot)
  217. {
  218. /* overkill? - try at _every_ offset & reverse */
  219. unsigned int poly_reverse;
  220. float(*poly_copy)[2] = (float(*)[2])MEM_mallocN(sizeof(float[2]) * poly_tot, id);
  221. float tmp[2];
  222. memcpy(poly_copy, poly, sizeof(float[2]) * poly_tot);
  223. for (poly_reverse = 0; poly_reverse < 2; poly_reverse++) {
  224. unsigned int poly_cycle;
  225. if (poly_reverse) {
  226. BLI_array_reverse(poly_copy, poly_tot);
  227. }
  228. for (poly_cycle = 0; poly_cycle < poly_tot; poly_cycle++) {
  229. // printf("polytest %s ofs=%d, reverse=%d\n", id, poly_cycle, poly_reverse);
  230. test_polyfill_template_flip_sign(id, is_degenerate, poly, poly_tot, tris, tris_tot);
  231. /* cycle */
  232. copy_v2_v2(tmp, poly_copy[0]);
  233. memmove(&poly_copy[0], &poly_copy[1], (poly_tot - 1) * sizeof(float[2]));
  234. copy_v2_v2(poly_copy[poly_tot - 1], tmp);
  235. }
  236. }
  237. MEM_freeN(poly_copy);
  238. }
  239. #else /* USE_COMBINATIONS_ALL */
  240. static void test_polyfill_template_main(const char *id,
  241. bool is_degenerate,
  242. const float poly[][2],
  243. const unsigned int poly_tot,
  244. unsigned int tris[][3],
  245. const unsigned int tris_tot)
  246. {
  247. test_polyfill_template_flip_sign(id, is_degenerate, poly, poly_tot, tris, tris_tot);
  248. }
  249. #endif /* USE_COMBINATIONS_ALL */
  250. #define TEST_POLYFILL_TEMPLATE_STATIC(poly, is_degenerate) \
  251. { \
  252. unsigned int tris[POLY_TRI_COUNT(ARRAY_SIZE(poly))][3]; \
  253. const unsigned int poly_tot = ARRAY_SIZE(poly); \
  254. const unsigned int tris_tot = ARRAY_SIZE(tris); \
  255. const char *id = typeid(*this).name(); \
  256. \
  257. test_polyfill_template_main(id, is_degenerate, poly, poly_tot, tris, tris_tot); \
  258. } \
  259. (void)0
  260. /* -------------------------------------------------------------------- */
  261. /* visualisation functions (not needed for testing) */
  262. #ifdef USE_OBJ_PREVIEW
  263. static void polyfill_to_obj(const char *id,
  264. const float poly[][2],
  265. const unsigned int poly_tot,
  266. const unsigned int tris[][3],
  267. const unsigned int tris_tot)
  268. {
  269. char path[1024];
  270. FILE *f;
  271. unsigned int i;
  272. BLI_snprintf(path, sizeof(path), "%s.obj", id);
  273. f = fopen(path, "w");
  274. if (!f) {
  275. return;
  276. }
  277. for (i = 0; i < poly_tot; i++) {
  278. fprintf(f, "v %f %f 0.0\n", UNPACK2(poly[i]));
  279. }
  280. for (i = 0; i < tris_tot; i++) {
  281. fprintf(f, "f %u %u %u\n", UNPACK3_EX(1 +, tris[i], ));
  282. }
  283. fclose(f);
  284. }
  285. #else
  286. static void polyfill_to_obj(const char *id,
  287. const float poly[][2],
  288. const unsigned int poly_tot,
  289. const unsigned int tris[][3],
  290. const unsigned int tris_tot)
  291. {
  292. (void)id;
  293. (void)poly, (void)poly_tot;
  294. (void)tris, (void)tris_tot;
  295. }
  296. #endif /* USE_OBJ_PREVIEW */
  297. /* -------------------------------------------------------------------- */
  298. /* tests */
  299. /**
  300. * Script to generate the data below:
  301. *
  302. * \code{.py}
  303. * # This example assumes we have a mesh object in edit-mode
  304. *
  305. * import bpy
  306. * import bmesh
  307. *
  308. * obj = bpy.context.edit_object
  309. * me = obj.data
  310. * bm = bmesh.from_edit_mesh(me)
  311. *
  312. * def clean_float(num):
  313. * if int(num) == num:
  314. * return str(int(num))
  315. * prec = 1
  316. * while True:
  317. * text = f"{num:.{prec}f}"
  318. * if float(text) == num:
  319. * return text
  320. * prec += 1
  321. *
  322. * for f in bm.faces:
  323. * if f.select:
  324. * print(f"\t// data for face: {f.index}")
  325. * print("\tconst float poly[][2] = {", end="")
  326. * coords = [[clean_float(num) for num in l.vert.co[0:2]] for l in f.loops]
  327. * print("\t ", end="")
  328. * for i, (x, y) in enumerate(coords):
  329. * if (i % 2) == 0:
  330. * print("\n\t ", end="")
  331. * print(f"{{{x}, {y}}}", end=",")
  332. * print("\n\t};")
  333. * \endcode
  334. */
  335. #define POLY_TRI_COUNT(len) ((len)-2)
  336. /* A counterclockwise triangle */
  337. TEST(polyfill2d, TriangleCCW)
  338. {
  339. const float poly[][2] = {{0, 0}, {0, 1}, {1, 0}};
  340. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  341. }
  342. /* A counterclockwise square */
  343. TEST(polyfill2d, SquareCCW)
  344. {
  345. const float poly[][2] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}};
  346. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  347. }
  348. /* A clockwise square */
  349. TEST(polyfill2d, SquareCW)
  350. {
  351. const float poly[][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
  352. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  353. }
  354. /* Starfleet insigna */
  355. TEST(polyfill2d, Starfleet)
  356. {
  357. const float poly[][2] = {{0, 0}, {0.6f, 0.4f}, {1, 0}, {0.5f, 1}};
  358. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  359. }
  360. /* Starfleet insigna with repeated point */
  361. TEST(polyfill2d, StarfleetDegenerate)
  362. {
  363. const float poly[][2] = {{0, 0}, {0.6f, 0.4f}, {0.6f, 0.4f}, {1, 0}, {0.5f, 1}};
  364. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  365. }
  366. /* Three collinear points */
  367. TEST(polyfill2d, 3Colinear)
  368. {
  369. const float poly[][2] = {{0, 0}, {1, 0}, {2, 0}};
  370. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  371. }
  372. /* Four collinear points */
  373. TEST(polyfill2d, 4Colinear)
  374. {
  375. const float poly[][2] = {{0, 0}, {1, 0}, {2, 0}, {3, 0}};
  376. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  377. }
  378. /* Non-consecutive collinear points */
  379. TEST(polyfill2d, UnorderedColinear)
  380. {
  381. const float poly[][2] = {{0, 0}, {1, 1}, {2, 0}, {3, 1}, {4, 0}};
  382. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  383. }
  384. /* Plus shape */
  385. TEST(polyfill2d, PlusShape)
  386. {
  387. const float poly[][2] = {
  388. {1, 0},
  389. {2, 0},
  390. {2, 1},
  391. {3, 1},
  392. {3, 2},
  393. {2, 2},
  394. {2, 3},
  395. {1, 3},
  396. {1, 2},
  397. {0, 2},
  398. {0, 1},
  399. {1, 1},
  400. };
  401. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  402. }
  403. /* Star shape */
  404. TEST(polyfill2d, StarShape)
  405. {
  406. const float poly[][2] = {{4, 0}, {5, 3}, {8, 4}, {5, 5}, {4, 8}, {3, 5}, {0, 4}, {3, 3}};
  407. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  408. }
  409. /* U shape */
  410. TEST(polyfill2d, UShape)
  411. {
  412. const float poly[][2] = {
  413. {1, 0}, {2, 0}, {3, 1}, {3, 3}, {2, 3}, {2, 1}, {1, 1}, {1, 3}, {0, 3}, {0, 1}};
  414. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  415. }
  416. /* Spiral */
  417. TEST(polyfill2d, Spiral)
  418. {
  419. const float poly[][2] = {
  420. {1, 0},
  421. {4, 0},
  422. {5, 1},
  423. {5, 4},
  424. {4, 5},
  425. {1, 5},
  426. {0, 4},
  427. {0, 3},
  428. {1, 2},
  429. {2, 2},
  430. {3, 3},
  431. {1, 3},
  432. {1, 4},
  433. {4, 4},
  434. {4, 1},
  435. {0, 1},
  436. };
  437. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  438. }
  439. /* Test case from http:# www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml */
  440. TEST(polyfill2d, TestFlipCode)
  441. {
  442. const float poly[][2] = {
  443. {0, 6},
  444. {0, 0},
  445. {3, 0},
  446. {4, 1},
  447. {6, 1},
  448. {8, 0},
  449. {12, 0},
  450. {13, 2},
  451. {8, 2},
  452. {8, 4},
  453. {11, 4},
  454. {11, 6},
  455. {6, 6},
  456. {4, 3},
  457. {2, 6},
  458. };
  459. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  460. }
  461. /* Self-intersection */
  462. TEST(polyfill2d, SelfIntersect)
  463. {
  464. const float poly[][2] = {{0, 0}, {1, 1}, {2, -1}, {3, 1}, {4, 0}};
  465. TEST_POLYFILL_TEMPLATE_STATIC(poly, true);
  466. }
  467. /* Self-touching */
  468. TEST(polyfill2d, SelfTouch)
  469. {
  470. const float poly[][2] = {
  471. {0, 0},
  472. {4, 0},
  473. {4, 4},
  474. {2, 4},
  475. {2, 3},
  476. {3, 3},
  477. {3, 1},
  478. {1, 1},
  479. {1, 3},
  480. {2, 3},
  481. {2, 4},
  482. {0, 4},
  483. };
  484. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  485. }
  486. /* Self-overlapping */
  487. TEST(polyfill2d, SelfOverlap)
  488. {
  489. const float poly[][2] = {
  490. {0, 0},
  491. {4, 0},
  492. {4, 4},
  493. {1, 4},
  494. {1, 3},
  495. {3, 3},
  496. {3, 1},
  497. {1, 1},
  498. {1, 3},
  499. {3, 3},
  500. {3, 4},
  501. {0, 4},
  502. };
  503. TEST_POLYFILL_TEMPLATE_STATIC(poly, true);
  504. }
  505. /* Test case from http:# www.davdata.nl/math/polygons.html */
  506. TEST(polyfill2d, TestDavData)
  507. {
  508. const float poly[][2] = {
  509. {190, 480}, {140, 180}, {310, 100}, {330, 390}, {290, 390}, {280, 260}, {220, 260},
  510. {220, 430}, {370, 430}, {350, 30}, {50, 30}, {160, 560}, {730, 510}, {710, 20},
  511. {410, 30}, {470, 440}, {640, 410}, {630, 140}, {590, 140}, {580, 360}, {510, 370},
  512. {510, 60}, {650, 70}, {660, 450}, {190, 480},
  513. };
  514. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  515. }
  516. /* Issue 815, http:# code.google.com/p/libgdx/issues/detail?id=815 */
  517. TEST(polyfill2d, Issue815)
  518. {
  519. const float poly[][2] = {
  520. {-2.0f, 0.0f},
  521. {-2.0f, 0.5f},
  522. {0.0f, 1.0f},
  523. {0.5f, 2.875f},
  524. {1.0f, 0.5f},
  525. {1.5f, 1.0f},
  526. {2.0f, 1.0f},
  527. {2.0f, 0.0f},
  528. };
  529. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  530. }
  531. /* Issue 207, comment #1, http:# code.google.com/p/libgdx/issues/detail?id=207#c1 */
  532. TEST(polyfill2d, Issue207_1)
  533. {
  534. const float poly[][2] = {
  535. {72.42465f, 197.07095f},
  536. {78.485535f, 189.92776f},
  537. {86.12059f, 180.92929f},
  538. {99.68253f, 164.94557f},
  539. {105.24325f, 165.79604f},
  540. {107.21862f, 166.09814f},
  541. {112.41958f, 162.78253f},
  542. {113.73238f, 161.94562f},
  543. {123.29477f, 167.93805f},
  544. {126.70667f, 170.07617f},
  545. {73.22717f, 199.51062f},
  546. };
  547. TEST_POLYFILL_TEMPLATE_STATIC(poly, true);
  548. }
  549. /* Issue 207, comment #11, http:# code.google.com/p/libgdx/issues/detail?id=207#c11 */
  550. /* Also on issue 1081, http:# code.google.com/p/libgdx/issues/detail?id=1081 */
  551. TEST(polyfill2d, Issue207_11)
  552. {
  553. const float poly[][2] = {
  554. {2400.0f, 480.0f}, {2400.0f, 176.0f}, {1920.0f, 480.0f},
  555. {1920.0459f, 484.22314f}, {1920.1797f, 487.91016f}, {1920.3955f, 491.0874f},
  556. {1920.6875f, 493.78125f}, {1921.0498f, 496.01807f}, {1921.4766f, 497.82422f},
  557. {1921.9619f, 499.22607f}, {1922.5f, 500.25f}, {1923.085f, 500.92236f},
  558. {1923.7109f, 501.26953f}, {1924.3721f, 501.31787f}, {1925.0625f, 501.09375f},
  559. {1925.7764f, 500.62354f}, {1926.5078f, 499.9336f}, {1927.251f, 499.0503f},
  560. {1928.0f, 498.0f}, {1928.749f, 496.80908f}, {1929.4922f, 495.5039f},
  561. {1930.2236f, 494.11084f}, {1930.9375f, 492.65625f}, {1931.6279f, 491.1665f},
  562. {1932.2891f, 489.66797f}, {1932.915f, 488.187f}, {1933.5f, 486.75f},
  563. {1934.0381f, 485.3833f}, {1934.5234f, 484.11328f}, {1934.9502f, 482.9663f},
  564. {1935.3125f, 481.96875f}, {1935.6045f, 481.14697f}, {1935.8203f, 480.52734f},
  565. {1935.9541f, 480.13623f}, {1936.0f, 480.0f}};
  566. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  567. }
  568. /* Issue 1407, http:# code.google.com/p/libgdx/issues/detail?id=1407 */
  569. TEST(polyfill2d, Issue1407)
  570. {
  571. const float poly[][2] = {
  572. {3.914329f, 1.9008259f},
  573. {4.414321f, 1.903619f},
  574. {4.8973203f, 1.9063174f},
  575. {5.4979978f, 1.9096732f},
  576. };
  577. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  578. }
  579. /* Issue 1407, http:# code.google.com/p/libgdx/issues/detail?id=1407, */
  580. /* with an additional point to show what is happening. */
  581. TEST(polyfill2d, Issue1407_pt)
  582. {
  583. const float poly[][2] = {
  584. {3.914329f, 1.9008259f},
  585. {4.414321f, 1.903619f},
  586. {4.8973203f, 1.9063174f},
  587. {5.4979978f, 1.9096732f},
  588. {4, 4},
  589. };
  590. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  591. }
  592. /* Simplified from Blender bug T40777 */
  593. TEST(polyfill2d, IssueT40777_colinear)
  594. {
  595. const float poly[][2] = {
  596. {0.7, 0.37}, {0.7, 0}, {0.76, 0}, {0.76, 0.4}, {0.83, 0.4}, {0.83, 0}, {0.88, 0},
  597. {0.88, 0.4}, {0.94, 0.4}, {0.94, 0}, {1, 0}, {1, 0.4}, {0.03, 0.62}, {0.03, 0.89},
  598. {0.59, 0.89}, {0.03, 1}, {0, 1}, {0, 0}, {0.03, 0}, {0.03, 0.37},
  599. };
  600. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  601. }
  602. /* Blender bug T41986 */
  603. TEST(polyfill2d, IssueT41986_axis_align)
  604. {
  605. const float poly[][2] = {
  606. {-0.25, -0.07}, {-0.25, 0.27}, {-1.19, 0.14}, {-0.06, 0.73}, {0.17, 1.25},
  607. {-0.25, 1.07}, {-0.38, 1.02}, {-0.25, 0.94}, {-0.40, 0.90}, {-0.41, 0.86},
  608. {-0.34, 0.83}, {-0.25, 0.82}, {-0.66, 0.73}, {-0.56, 1.09}, {-0.25, 1.10},
  609. {0.00, 1.31}, {-0.03, 1.47}, {-0.25, 1.53}, {0.12, 1.62}, {0.36, 1.07},
  610. {0.12, 0.67}, {0.29, 0.57}, {0.44, 0.45}, {0.57, 0.29}, {0.66, 0.12},
  611. {0.68, 0.06}, {0.57, -0.36}, {-0.25, -0.37}, {0.49, -0.74}, {-0.59, -1.21},
  612. {-0.25, -0.15}, {-0.46, -0.52}, {-1.08, -0.83}, {-1.45, -0.33}, {-1.25, -0.04}};
  613. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  614. }
  615. /* Blender bug T52834 */
  616. TEST(polyfill2d, IssueT52834_axis_align_co_linear)
  617. {
  618. const float poly[][2] = {
  619. {40, 0}, {36, 0}, {36, 5}, {35, 5}, {35, 0}, {30, 0}, {30, 5}, {29, 5},
  620. {29, 0}, {24, 0}, {24, 3}, {23, 4}, {23, 0}, {18, 0}, {18, 5}, {17, 5},
  621. {17, 0}, {12, 0}, {12, 5}, {11, 5}, {11, 0}, {6, 0}, {6, 5}, {5, 5},
  622. {5, 0}, {0, 0}, {0, 5}, {-1, 5}, {-1, 0}, {-6, 0}, {-9, -3}, {-6, -3},
  623. {-6, -2}, {-1, -2}, {0, -2}, {5, -2}, {6, -2}, {11, -2}, {12, -2}, {17, -2},
  624. {18, -2}, {23, -2}, {24, -2}, {29, -2}, {30, -2}, {35, -2}, {36, -2}, {40, -2},
  625. };
  626. TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
  627. }