experimental alternative isconvex
Bug: skia: Change-Id: I55175a95d37aad9a656cd211fc6c7238bdb7d674 Reviewed-on: https://skia-review.googlesource.com/c/173361 Commit-Queue: Mike Reed <reed@google.com> Reviewed-by: Mike Reed <reed@google.com>
This commit is contained in:
parent
9e55daa7ec
commit
64284e1482
@ -1691,3 +1691,116 @@ bool SkTriangulateSimplePolygon(const SkPoint* polygonVerts, uint16_t* indexMap,
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////
|
||||
|
||||
static double crs(SkVector a, SkVector b) {
|
||||
return a.fX * b.fY - a.fY * b.fX;
|
||||
}
|
||||
|
||||
static int sign(SkScalar v) {
|
||||
return v < 0 ? -1 : (v > 0);
|
||||
}
|
||||
|
||||
struct SignTracker {
|
||||
int fSign;
|
||||
int fSignChanges;
|
||||
|
||||
void reset() {
|
||||
fSign = 0;
|
||||
fSignChanges = 0;
|
||||
}
|
||||
|
||||
void init(int s) {
|
||||
SkASSERT(fSignChanges == 0);
|
||||
SkASSERT(s == 1 || s == -1 || s == 0);
|
||||
fSign = s;
|
||||
fSignChanges = 1;
|
||||
}
|
||||
|
||||
void update(int s) {
|
||||
if (s) {
|
||||
if (fSign != s) {
|
||||
fSignChanges += 1;
|
||||
fSign = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct ConvexTracker {
|
||||
SkVector fFirst, fPrev;
|
||||
SignTracker fDSign, fCSign;
|
||||
int fVecCounter;
|
||||
bool fIsConcave;
|
||||
|
||||
ConvexTracker() { this->reset(); }
|
||||
|
||||
void reset() {
|
||||
fPrev = {0, 0};
|
||||
fDSign.reset();
|
||||
fCSign.reset();
|
||||
fVecCounter = 0;
|
||||
fIsConcave = false;
|
||||
}
|
||||
|
||||
void addVec(SkPoint p1, SkPoint p0) {
|
||||
this->addVec(p1 - p0);
|
||||
}
|
||||
void addVec(SkVector v) {
|
||||
if (v.fX == 0 && v.fY == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
fVecCounter += 1;
|
||||
if (fVecCounter == 1) {
|
||||
fFirst = fPrev = v;
|
||||
fDSign.update(sign(v.fX));
|
||||
return;
|
||||
}
|
||||
|
||||
SkScalar d = v.fX;
|
||||
SkScalar c = crs(fPrev, v);
|
||||
int sign_c;
|
||||
if (c) {
|
||||
sign_c = sign(c);
|
||||
} else {
|
||||
if (d >= 0) {
|
||||
sign_c = fCSign.fSign;
|
||||
} else {
|
||||
sign_c = -fCSign.fSign;
|
||||
}
|
||||
}
|
||||
|
||||
fDSign.update(sign(d));
|
||||
fCSign.update(sign_c);
|
||||
fPrev = v;
|
||||
|
||||
if (fDSign.fSignChanges > 3 || fCSign.fSignChanges > 1) {
|
||||
fIsConcave = true;
|
||||
}
|
||||
}
|
||||
|
||||
void finalCross() {
|
||||
this->addVec(fFirst);
|
||||
}
|
||||
};
|
||||
|
||||
bool SkIsPolyConvex_experimental(const SkPoint pts[], int count) {
|
||||
if (count <= 3) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ConvexTracker tracker;
|
||||
|
||||
for (int i = 0; i < count - 1; ++i) {
|
||||
tracker.addVec(pts[i + 1], pts[i]);
|
||||
if (tracker.fIsConcave) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
tracker.addVec(pts[0], pts[count - 1]);
|
||||
tracker.finalCross();
|
||||
return !tracker.fIsConcave;
|
||||
}
|
||||
|
||||
|
@ -103,4 +103,7 @@ bool SkIsConvexPolygon(const SkPoint* polygonVerts, int polygonSize);
|
||||
bool SkTriangulateSimplePolygon(const SkPoint* polygonVerts, uint16_t* indexMap, int polygonSize,
|
||||
SkTDArray<uint16_t>* triangleIndices);
|
||||
|
||||
// Experiment: doesn't handle really big floats (returns false), always returns true for count <= 3
|
||||
bool SkIsPolyConvex_experimental(const SkPoint[], int count);
|
||||
|
||||
#endif
|
||||
|
@ -255,3 +255,37 @@ DEF_TEST(PolyUtils, reporter) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user