skia2/tests/PolyUtilsTest.cpp
Brian Osman 4428f2c39f Remove SkScalarSinCos
This differed from the separate versions in that it snapped to zero.
It was also strictly worse than calling the two separate versions.
Most clients don't need the snapping, so just call the two existing
functions. For clients that need the snapping, call new variants of
each that do snap.

Change-Id: Ia4e09fd9651932fe15caeab1399df7f6281bdc17
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/205303
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Reed <reed@google.com>
2019-04-02 15:46:57 +00:00

290 lines
14 KiB
C++

/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "Test.h"
#include "SkPolyUtils.h"
DEF_TEST(PolyUtils, reporter) {
SkTDArray<SkPoint> poly;
// init simple index map
uint16_t indexMap[1024];
for (int i = 0; i < 1024; ++i) {
indexMap[i] = i;
}
SkTDArray<uint16_t> triangleIndices;
// skinny triangle
*poly.push() = SkPoint::Make(-100, 55);
*poly.push() = SkPoint::Make(100, 55);
*poly.push() = SkPoint::Make(102.5f, 54.330127f);
REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) < 0);
REPORTER_ASSERT(reporter, SkIsConvexPolygon(poly.begin(), poly.count()));
REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
REPORTER_ASSERT(reporter, SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
&triangleIndices));
// switch winding
poly[2].set(102.5f, 55.330127f);
REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) > 0);
REPORTER_ASSERT(reporter, SkIsConvexPolygon(poly.begin(), poly.count()));
REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
triangleIndices.rewind();
REPORTER_ASSERT(reporter, SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
&triangleIndices));
// make degenerate
poly[2].set(100 + 2.5f, 55);
REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) == 0);
// TODO: should these fail?
REPORTER_ASSERT(reporter, SkIsConvexPolygon(poly.begin(), poly.count()));
REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
triangleIndices.rewind();
REPORTER_ASSERT(reporter, !SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
&triangleIndices));
// giant triangle
poly[0].set(-1.0e+37f, 1.0e+37f);
poly[1].set(1.0e+37f, 1.0e+37f);
poly[2].set(-1.0e+37f, -1.0e+37f);
REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) < 0);
REPORTER_ASSERT(reporter, SkIsConvexPolygon(poly.begin(), poly.count()));
REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
triangleIndices.rewind();
REPORTER_ASSERT(reporter, SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
&triangleIndices));
// teeny triangle
poly[0].set(-1.0e-38f, 1.0e-38f);
poly[1].set(-1.0e-38f, -1.0e-38f);
poly[2].set(1.0e-38f, 1.0e-38f);
REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) == 0);
// TODO: should these fail?
REPORTER_ASSERT(reporter, SkIsConvexPolygon(poly.begin(), poly.count()));
REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
triangleIndices.rewind();
REPORTER_ASSERT(reporter, !SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
&triangleIndices));
// triangle way off in space (relative to size so we don't completely obliterate values)
poly[0].set(-100 + 1.0e+9f, 55 - 1.0e+9f);
poly[1].set(100 + 1.0e+9f, 55 - 1.0e+9f);
poly[2].set(150 + 1.0e+9f, 100 - 1.0e+9f);
REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) > 0);
REPORTER_ASSERT(reporter, SkIsConvexPolygon(poly.begin(), poly.count()));
REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
triangleIndices.rewind();
REPORTER_ASSERT(reporter, SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
&triangleIndices));
///////////////////////////////////////////////////////////////////////
// round rect
poly.rewind();
*poly.push() = SkPoint::Make(-100, 55);
*poly.push() = SkPoint::Make(100, 55);
*poly.push() = SkPoint::Make(100 + 2.5f, 50 + 4.330127f);
*poly.push() = SkPoint::Make(100 + 3.535534f, 50 + 3.535534f);
*poly.push() = SkPoint::Make(100 + 4.330127f, 50 + 2.5f);
*poly.push() = SkPoint::Make(105, 50);
*poly.push() = SkPoint::Make(105, -50);
*poly.push() = SkPoint::Make(100 + 4.330127f, -50 - 2.5f);
*poly.push() = SkPoint::Make(100 + 3.535534f, -50 - 3.535534f);
*poly.push() = SkPoint::Make(100 + 2.5f, -50 - 4.330127f);
*poly.push() = SkPoint::Make(100, -55);
*poly.push() = SkPoint::Make(-100, -55);
*poly.push() = SkPoint::Make(-100 - 2.5f, -50 - 4.330127f);
*poly.push() = SkPoint::Make(-100 - 3.535534f, -50 - 3.535534f);
*poly.push() = SkPoint::Make(-100 - 4.330127f, -50 - 2.5f);
*poly.push() = SkPoint::Make(-105, -50);
*poly.push() = SkPoint::Make(-105, 50);
*poly.push() = SkPoint::Make(-100 - 4.330127f, 50 + 2.5f);
*poly.push() = SkPoint::Make(-100 - 3.535534f, 50 + 3.535534f);
*poly.push() = SkPoint::Make(-100 - 2.5f, 50 + 4.330127f);
REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) < 0);
REPORTER_ASSERT(reporter, SkIsConvexPolygon(poly.begin(), poly.count()));
REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
triangleIndices.rewind();
REPORTER_ASSERT(reporter, SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
&triangleIndices));
// translate far enough to obliterate some low bits
for (int i = 0; i < poly.count(); ++i) {
poly[i].offset(1.0e+7f, 1.0e+7f);
}
REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) < 0);
// Due to floating point error it's no longer convex
REPORTER_ASSERT(reporter, !SkIsConvexPolygon(poly.begin(), poly.count()));
REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
triangleIndices.rewind();
REPORTER_ASSERT(reporter, SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
&triangleIndices));
// translate a little farther to create some coincident vertices
for (int i = 0; i < poly.count(); ++i) {
poly[i].offset(4.0e+7f, 4.0e+7f);
}
REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) < 0);
REPORTER_ASSERT(reporter, SkIsConvexPolygon(poly.begin(), poly.count()));
REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
// This can't handle coincident vertices
triangleIndices.rewind();
REPORTER_ASSERT(reporter, !SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
&triangleIndices));
// troublesome case -- clipped roundrect
poly.rewind();
*poly.push() = SkPoint::Make(335.928101f, 428.219055f);
*poly.push() = SkPoint::Make(330.414459f, 423.034912f);
*poly.push() = SkPoint::Make(325.749084f, 417.395508f);
*poly.push() = SkPoint::Make(321.931946f, 411.300842f);
*poly.push() = SkPoint::Make(318.963074f, 404.750977f);
*poly.push() = SkPoint::Make(316.842468f, 397.745850f);
*poly.push() = SkPoint::Make(315.570068f, 390.285522f);
*poly.push() = SkPoint::Make(315.145966f, 382.369965f);
*poly.push() = SkPoint::Make(315.570068f, 374.454346f);
*poly.push() = SkPoint::Make(316.842468f, 366.994019f);
*poly.push() = SkPoint::Make(318.963074f, 359.988892f);
*poly.push() = SkPoint::Make(321.931946f, 353.439056f);
*poly.push() = SkPoint::Make(325.749084f, 347.344421f);
*poly.push() = SkPoint::Make(330.414459f, 341.705017f);
*poly.push() = SkPoint::Make(335.928101f, 336.520813f);
*poly.push() = SkPoint::Make(342.289948f, 331.791901f);
*poly.push() = SkPoint::Make(377.312134f, 331.791901f);
*poly.push() = SkPoint::Make(381.195313f, 332.532593f);
*poly.push() = SkPoint::Make(384.464935f, 334.754700f);
*poly.push() = SkPoint::Make(386.687042f, 338.024292f);
*poly.push() = SkPoint::Make(387.427765f, 341.907532f);
*poly.push() = SkPoint::Make(387.427765f, 422.832367f);
*poly.push() = SkPoint::Make(386.687042f, 426.715576f);
*poly.push() = SkPoint::Make(384.464935f, 429.985168f);
*poly.push() = SkPoint::Make(381.195313f, 432.207275f);
*poly.push() = SkPoint::Make(377.312134f, 432.947998f);
*poly.push() = SkPoint::Make(342.289948f, 432.947998f);
REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) > 0);
REPORTER_ASSERT(reporter, SkIsConvexPolygon(poly.begin(), poly.count()));
REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
triangleIndices.rewind();
REPORTER_ASSERT(reporter, SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
&triangleIndices));
// a star is born
poly.rewind();
*poly.push() = SkPoint::Make(0.0f, -50.0f);
*poly.push() = SkPoint::Make(14.43f, -25.0f);
*poly.push() = SkPoint::Make(43.30f, -25.0f);
*poly.push() = SkPoint::Make(28.86f, 0.0f);
*poly.push() = SkPoint::Make(43.30f, 25.0f);
*poly.push() = SkPoint::Make(14.43f, 25.0f);
*poly.push() = SkPoint::Make(0.0f, 50.0f);
*poly.push() = SkPoint::Make(-14.43f, 25.0f);
*poly.push() = SkPoint::Make(-43.30f, 25.0f);
*poly.push() = SkPoint::Make(-28.86f, 0.0f);
*poly.push() = SkPoint::Make(-43.30f, -25.0f);
*poly.push() = SkPoint::Make(-14.43f, -25.0f);
REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) > 0);
REPORTER_ASSERT(reporter, !SkIsConvexPolygon(poly.begin(), poly.count()));
REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
triangleIndices.rewind();
REPORTER_ASSERT(reporter, SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
&triangleIndices));
// many spiked star
{
const SkScalar c = SkIntToScalar(45);
const SkScalar r1 = SkIntToScalar(20);
const SkScalar r2 = SkIntToScalar(3);
const int n = 500;
poly.rewind();
SkScalar rad = 0;
const SkScalar drad = SK_ScalarPI / n;
for (int i = 0; i < n; i++) {
*poly.push() = SkPoint::Make(c + SkScalarCos(rad) * r1, c + SkScalarSin(rad) * r1);
rad += drad;
*poly.push() = SkPoint::Make(c + SkScalarCos(rad) * r2, c + SkScalarSin(rad) * r2);
rad += drad;
}
REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) > 0);
REPORTER_ASSERT(reporter, !SkIsConvexPolygon(poly.begin(), poly.count()));
REPORTER_ASSERT(reporter, SkIsSimplePolygon(poly.begin(), poly.count()));
triangleIndices.rewind();
REPORTER_ASSERT(reporter, SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
&triangleIndices));
}
// self-intersecting polygon
poly.rewind();
*poly.push() = SkPoint::Make(0.0f, -50.0f);
*poly.push() = SkPoint::Make(14.43f, -25.0f);
*poly.push() = SkPoint::Make(43.30f, -25.0f);
*poly.push() = SkPoint::Make(-28.86f, 0.0f);
*poly.push() = SkPoint::Make(43.30f, 25.0f);
*poly.push() = SkPoint::Make(14.43f, 25.0f);
*poly.push() = SkPoint::Make(0.0f, 50.0f);
*poly.push() = SkPoint::Make(-14.43f, 25.0f);
*poly.push() = SkPoint::Make(-43.30f, 25.0f);
*poly.push() = SkPoint::Make(28.86f, 0.0f);
*poly.push() = SkPoint::Make(-43.30f, -25.0f);
*poly.push() = SkPoint::Make(-14.43f, -25.0f);
REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) > 0);
REPORTER_ASSERT(reporter, !SkIsConvexPolygon(poly.begin(), poly.count()));
REPORTER_ASSERT(reporter, !SkIsSimplePolygon(poly.begin(), poly.count()));
triangleIndices.rewind();
// running this just to make sure it doesn't crash
// the fact that it succeeds doesn't mean anything since the input is not simple
REPORTER_ASSERT(reporter, SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
&triangleIndices));
// self-intersecting polygon with coincident point
poly.rewind();
*poly.push() = SkPoint::Make(0.0f, 0.0f);
*poly.push() = SkPoint::Make(-50, -50);
*poly.push() = SkPoint::Make(50, -50);
*poly.push() = SkPoint::Make(0.00000001f, -0.00000001f);
*poly.push() = SkPoint::Make(-50, 50);
*poly.push() = SkPoint::Make(50, 50);
REPORTER_ASSERT(reporter, SkGetPolygonWinding(poly.begin(), poly.count()) == 0);
REPORTER_ASSERT(reporter, !SkIsConvexPolygon(poly.begin(), poly.count()));
REPORTER_ASSERT(reporter, !SkIsSimplePolygon(poly.begin(), poly.count()));
triangleIndices.rewind();
// running this just to make sure it doesn't crash
REPORTER_ASSERT(reporter, !SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
&triangleIndices));
}
struct PtSet {
const SkPoint* fPts;
int fN;
};
DEF_TEST(IsPolyConvex_experimental, r) {
#define PTSET(array) {array, SK_ARRAY_COUNT(array)}
const SkPoint g0[] = { {0, 0}, {10, 0}, {10, 10}, {0, 10} };
const PtSet convex[] = { PTSET(g0) };
for (auto& set : convex) {
REPORTER_ASSERT(r, SkIsPolyConvex_experimental(set.fPts, set.fN));
}
const SkPoint b0[] = { {0, 0}, {10, 0}, {0, 10}, {10, 10} };
const SkPoint b1[] = {
{24.8219f, 8.05052f},
{26.0616f, 24.4895f}, {8.49582f, 16.815f},
{27.3047f, 7.75211f},
{21.927f, 27.2051f},
};
const SkPoint b2[] = {
{20, 20}, {20, 50}, {80, 50}, {20, 50}, {20, 80},
};
const PtSet concave[] = { PTSET(b0), PTSET(b1), PTSET(b2) };
for (auto& set : concave) {
if (SkIsPolyConvex_experimental(set.fPts, set.fN)) {
REPORTER_ASSERT(r, !SkIsPolyConvex_experimental(set.fPts, set.fN));
}
}
}