Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2018 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 #include "Test.h"
      8 #include "SkPolyUtils.h"
      9 
     10 DEF_TEST(PolyUtils, reporter) {
     11 
     12     SkTDArray<SkPoint> poly;
     13     // init simple index map
     14     uint16_t indexMap[1024];
     15     for (int i = 0; i < 1024; ++i) {
     16         indexMap[i] = i;
     17     }
     18     SkTDArray<uint16_t> triangleIndices;
     19 
     20     // skinny triangle
     21     *poly.push() = SkPoint::Make(-100, 55);
     22     *poly.push() = SkPoint::Make(100, 55);
     23     *poly.push() = SkPoint::Make(102.5f, 54.330127f);
     24     REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) < 0);
     25     REPORTER_ASSERT(reporter, SkIsConvexPolygon(poly.begin(), poly.count()));
     26     REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
     27     REPORTER_ASSERT(reporter, SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
     28                                                          &triangleIndices));
     29 
     30     // switch winding
     31     poly[2].set(102.5f, 55.330127f);
     32     REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) > 0);
     33     REPORTER_ASSERT(reporter, SkIsConvexPolygon(poly.begin(), poly.count()));
     34     REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
     35     triangleIndices.rewind();
     36     REPORTER_ASSERT(reporter, SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
     37                                                          &triangleIndices));
     38 
     39     // make degenerate
     40     poly[2].set(100 + 2.5f, 55);
     41     REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) == 0);
     42     // TODO: should these fail?
     43     REPORTER_ASSERT(reporter, SkIsConvexPolygon(poly.begin(), poly.count()));
     44     REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
     45     triangleIndices.rewind();
     46     REPORTER_ASSERT(reporter, !SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
     47                                                           &triangleIndices));
     48 
     49     // giant triangle
     50     poly[0].set(-1.0e+37f, 1.0e+37f);
     51     poly[1].set(1.0e+37f, 1.0e+37f);
     52     poly[2].set(-1.0e+37f, -1.0e+37f);
     53     REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) < 0);
     54     REPORTER_ASSERT(reporter, SkIsConvexPolygon(poly.begin(), poly.count()));
     55     REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
     56     triangleIndices.rewind();
     57     REPORTER_ASSERT(reporter, SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
     58                                                          &triangleIndices));
     59 
     60     // teeny triangle
     61     poly[0].set(-1.0e-38f, 1.0e-38f);
     62     poly[1].set(-1.0e-38f, -1.0e-38f);
     63     poly[2].set(1.0e-38f, 1.0e-38f);
     64     REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) == 0);
     65     // TODO: should these fail?
     66     REPORTER_ASSERT(reporter, SkIsConvexPolygon(poly.begin(), poly.count()));
     67     REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
     68     triangleIndices.rewind();
     69     REPORTER_ASSERT(reporter, !SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
     70                                                           &triangleIndices));
     71 
     72     // triangle way off in space (relative to size so we don't completely obliterate values)
     73     poly[0].set(-100 + 1.0e+9f, 55 - 1.0e+9f);
     74     poly[1].set(100 + 1.0e+9f, 55 - 1.0e+9f);
     75     poly[2].set(150 + 1.0e+9f, 100 - 1.0e+9f);
     76     REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) > 0);
     77     REPORTER_ASSERT(reporter, SkIsConvexPolygon(poly.begin(), poly.count()));
     78     REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
     79     triangleIndices.rewind();
     80     REPORTER_ASSERT(reporter, SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
     81                                                          &triangleIndices));
     82 
     83     ///////////////////////////////////////////////////////////////////////
     84     // round rect
     85     poly.rewind();
     86     *poly.push() = SkPoint::Make(-100, 55);
     87     *poly.push() = SkPoint::Make(100, 55);
     88     *poly.push() = SkPoint::Make(100 + 2.5f, 50 + 4.330127f);
     89     *poly.push() = SkPoint::Make(100 + 3.535534f, 50 + 3.535534f);
     90     *poly.push() = SkPoint::Make(100 + 4.330127f, 50 + 2.5f);
     91     *poly.push() = SkPoint::Make(105, 50);
     92     *poly.push() = SkPoint::Make(105, -50);
     93     *poly.push() = SkPoint::Make(100 + 4.330127f, -50 - 2.5f);
     94     *poly.push() = SkPoint::Make(100 + 3.535534f, -50 - 3.535534f);
     95     *poly.push() = SkPoint::Make(100 + 2.5f, -50 - 4.330127f);
     96     *poly.push() = SkPoint::Make(100, -55);
     97     *poly.push() = SkPoint::Make(-100, -55);
     98     *poly.push() = SkPoint::Make(-100 - 2.5f, -50 - 4.330127f);
     99     *poly.push() = SkPoint::Make(-100 - 3.535534f, -50 - 3.535534f);
    100     *poly.push() = SkPoint::Make(-100 - 4.330127f, -50 - 2.5f);
    101     *poly.push() = SkPoint::Make(-105, -50);
    102     *poly.push() = SkPoint::Make(-105, 50);
    103     *poly.push() = SkPoint::Make(-100 - 4.330127f, 50 + 2.5f);
    104     *poly.push() = SkPoint::Make(-100 - 3.535534f, 50 + 3.535534f);
    105     *poly.push() = SkPoint::Make(-100 - 2.5f, 50 + 4.330127f);
    106     REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) < 0);
    107     REPORTER_ASSERT(reporter, SkIsConvexPolygon(poly.begin(), poly.count()));
    108     REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
    109     triangleIndices.rewind();
    110     REPORTER_ASSERT(reporter, SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
    111                                                          &triangleIndices));
    112 
    113     // translate far enough to obliterate some low bits
    114     for (int i = 0; i < poly.count(); ++i) {
    115         poly[i].offset(1.0e+7f, 1.0e+7f);
    116     }
    117     REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) < 0);
    118     // Due to floating point error it's no longer convex
    119     REPORTER_ASSERT(reporter, !SkIsConvexPolygon(poly.begin(), poly.count()));
    120     REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
    121     triangleIndices.rewind();
    122     REPORTER_ASSERT(reporter, SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
    123                                                           &triangleIndices));
    124 
    125     // translate a little farther to create some coincident vertices
    126     for (int i = 0; i < poly.count(); ++i) {
    127         poly[i].offset(4.0e+7f, 4.0e+7f);
    128     }
    129     REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) < 0);
    130     REPORTER_ASSERT(reporter, SkIsConvexPolygon(poly.begin(), poly.count()));
    131     REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
    132     // This can't handle coincident vertices
    133     triangleIndices.rewind();
    134     REPORTER_ASSERT(reporter, !SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
    135                                                           &triangleIndices));
    136 
    137     // troublesome case -- clipped roundrect
    138     poly.rewind();
    139     *poly.push() = SkPoint::Make(335.928101f, 428.219055f);
    140     *poly.push() = SkPoint::Make(330.414459f, 423.034912f);
    141     *poly.push() = SkPoint::Make(325.749084f, 417.395508f);
    142     *poly.push() = SkPoint::Make(321.931946f, 411.300842f);
    143     *poly.push() = SkPoint::Make(318.963074f, 404.750977f);
    144     *poly.push() = SkPoint::Make(316.842468f, 397.745850f);
    145     *poly.push() = SkPoint::Make(315.570068f, 390.285522f);
    146     *poly.push() = SkPoint::Make(315.145966f, 382.369965f);
    147     *poly.push() = SkPoint::Make(315.570068f, 374.454346f);
    148     *poly.push() = SkPoint::Make(316.842468f, 366.994019f);
    149     *poly.push() = SkPoint::Make(318.963074f, 359.988892f);
    150     *poly.push() = SkPoint::Make(321.931946f, 353.439056f);
    151     *poly.push() = SkPoint::Make(325.749084f, 347.344421f);
    152     *poly.push() = SkPoint::Make(330.414459f, 341.705017f);
    153     *poly.push() = SkPoint::Make(335.928101f, 336.520813f);
    154     *poly.push() = SkPoint::Make(342.289948f, 331.791901f);
    155     *poly.push() = SkPoint::Make(377.312134f, 331.791901f);
    156     *poly.push() = SkPoint::Make(381.195313f, 332.532593f);
    157     *poly.push() = SkPoint::Make(384.464935f, 334.754700f);
    158     *poly.push() = SkPoint::Make(386.687042f, 338.024292f);
    159     *poly.push() = SkPoint::Make(387.427765f, 341.907532f);
    160     *poly.push() = SkPoint::Make(387.427765f, 422.832367f);
    161     *poly.push() = SkPoint::Make(386.687042f, 426.715576f);
    162     *poly.push() = SkPoint::Make(384.464935f, 429.985168f);
    163     *poly.push() = SkPoint::Make(381.195313f, 432.207275f);
    164     *poly.push() = SkPoint::Make(377.312134f, 432.947998f);
    165     *poly.push() = SkPoint::Make(342.289948f, 432.947998f);
    166     REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) > 0);
    167     REPORTER_ASSERT(reporter, SkIsConvexPolygon(poly.begin(), poly.count()));
    168     REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
    169     triangleIndices.rewind();
    170     REPORTER_ASSERT(reporter, SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
    171                                                          &triangleIndices));
    172 
    173     // a star is born
    174     poly.rewind();
    175     *poly.push() = SkPoint::Make(0.0f, -50.0f);
    176     *poly.push() = SkPoint::Make(14.43f, -25.0f);
    177     *poly.push() = SkPoint::Make(43.30f, -25.0f);
    178     *poly.push() = SkPoint::Make(28.86f, 0.0f);
    179     *poly.push() = SkPoint::Make(43.30f, 25.0f);
    180     *poly.push() = SkPoint::Make(14.43f, 25.0f);
    181     *poly.push() = SkPoint::Make(0.0f, 50.0f);
    182     *poly.push() = SkPoint::Make(-14.43f, 25.0f);
    183     *poly.push() = SkPoint::Make(-43.30f, 25.0f);
    184     *poly.push() = SkPoint::Make(-28.86f, 0.0f);
    185     *poly.push() = SkPoint::Make(-43.30f, -25.0f);
    186     *poly.push() = SkPoint::Make(-14.43f, -25.0f);
    187     REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) > 0);
    188     REPORTER_ASSERT(reporter, !SkIsConvexPolygon(poly.begin(), poly.count()));
    189     REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
    190     triangleIndices.rewind();
    191     REPORTER_ASSERT(reporter, SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
    192                                                          &triangleIndices));
    193 
    194     // many spiked star
    195     {
    196         const SkScalar c = SkIntToScalar(45);
    197         const SkScalar r1 = SkIntToScalar(20);
    198         const SkScalar r2 = SkIntToScalar(3);
    199         const int n = 500;
    200         poly.rewind();
    201         SkScalar rad = 0;
    202         const SkScalar drad = SK_ScalarPI / n;
    203         for (int i = 0; i < n; i++) {
    204             SkScalar cosV, sinV = SkScalarSinCos(rad, &cosV);
    205             *poly.push() = SkPoint::Make(c + cosV * r1, c + sinV * r1);
    206             rad += drad;
    207             sinV = SkScalarSinCos(rad, &cosV);
    208             *poly.push() = SkPoint::Make(c + cosV * r2, c + sinV * r2);
    209             rad += drad;
    210         }
    211         REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) > 0);
    212         REPORTER_ASSERT(reporter, !SkIsConvexPolygon(poly.begin(), poly.count()));
    213         REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
    214         triangleIndices.rewind();
    215         REPORTER_ASSERT(reporter, SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
    216                                                              &triangleIndices));
    217     }
    218 
    219     // self-intersecting polygon
    220     poly.rewind();
    221     *poly.push() = SkPoint::Make(0.0f, -50.0f);
    222     *poly.push() = SkPoint::Make(14.43f, -25.0f);
    223     *poly.push() = SkPoint::Make(43.30f, -25.0f);
    224     *poly.push() = SkPoint::Make(-28.86f, 0.0f);
    225     *poly.push() = SkPoint::Make(43.30f, 25.0f);
    226     *poly.push() = SkPoint::Make(14.43f, 25.0f);
    227     *poly.push() = SkPoint::Make(0.0f, 50.0f);
    228     *poly.push() = SkPoint::Make(-14.43f, 25.0f);
    229     *poly.push() = SkPoint::Make(-43.30f, 25.0f);
    230     *poly.push() = SkPoint::Make(28.86f, 0.0f);
    231     *poly.push() = SkPoint::Make(-43.30f, -25.0f);
    232     *poly.push() = SkPoint::Make(-14.43f, -25.0f);
    233     REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) > 0);
    234     REPORTER_ASSERT(reporter, !SkIsConvexPolygon(poly.begin(), poly.count()));
    235     REPORTER_ASSERT(reporter, !SkIsSimplePolygon(poly.begin(), poly.count()));
    236     triangleIndices.rewind();
    237     // running this just to make sure it doesn't crash
    238     // the fact that it succeeds doesn't mean anything since the input is not simple
    239     REPORTER_ASSERT(reporter, SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
    240                                                          &triangleIndices));
    241 
    242     // self-intersecting polygon with coincident point
    243     poly.rewind();
    244     *poly.push() = SkPoint::Make(0.0f, 0.0f);
    245     *poly.push() = SkPoint::Make(-50, -50);
    246     *poly.push() = SkPoint::Make(50, -50);
    247     *poly.push() = SkPoint::Make(0.00000001f, -0.00000001f);
    248     *poly.push() = SkPoint::Make(-50, 50);
    249     *poly.push() = SkPoint::Make(50, 50);
    250     REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) == 0);
    251     REPORTER_ASSERT(reporter, !SkIsConvexPolygon(poly.begin(), poly.count()));
    252     REPORTER_ASSERT(reporter, !SkIsSimplePolygon(poly.begin(), poly.count()));
    253     triangleIndices.rewind();
    254     // running this just to make sure it doesn't crash
    255     REPORTER_ASSERT(reporter, !SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
    256                                                           &triangleIndices));
    257 }
    258 
    259 struct PtSet {
    260     const SkPoint*  fPts;
    261     int             fN;
    262 };
    263 
    264 DEF_TEST(IsPolyConvex_experimental, r) {
    265     #define PTSET(array)    {array, SK_ARRAY_COUNT(array)}
    266 
    267     const SkPoint g0[] = { {0, 0}, {10, 0}, {10, 10}, {0, 10} };
    268     const PtSet convex[] = { PTSET(g0) };
    269     for (auto& set : convex) {
    270         REPORTER_ASSERT(r, SkIsPolyConvex_experimental(set.fPts, set.fN));
    271     }
    272 
    273     const SkPoint b0[] = { {0, 0}, {10, 0}, {0, 10}, {10, 10} };
    274     const SkPoint b1[] = {
    275         {24.8219f, 8.05052f},
    276         {26.0616f, 24.4895f}, {8.49582f, 16.815f},
    277         {27.3047f, 7.75211f},
    278         {21.927f, 27.2051f},
    279     };
    280     const SkPoint b2[] = {
    281         {20, 20}, {20, 50}, {80, 50}, {20, 50}, {20, 80},
    282     };
    283     const PtSet concave[] = { PTSET(b0), PTSET(b1), PTSET(b2) };
    284     for (auto& set : concave) {
    285         if (SkIsPolyConvex_experimental(set.fPts, set.fN)) {
    286             REPORTER_ASSERT(r, !SkIsPolyConvex_experimental(set.fPts, set.fN));
    287         }
    288     }
    289 
    290 }
    291 
    292