зеркало из https://github.com/mozilla/moz-skia.git
shape ops work in progress
git-svn-id: http://skia.googlecode.com/svn/trunk@4006 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
a611c3ea53
Коммит
b45a1b46ee
|
@ -25,24 +25,24 @@ SkPoint leftRight[][4] = {
|
|||
{{10, 0}, {10, 50}, {20, 10}, {20, 50}},
|
||||
{{10, 0}, {10, 50}, {10, 10}, {20, 50}},
|
||||
{{10, 0}, {10, 50}, {20, 10}, {10, 50}},
|
||||
{{10, 0}, {10, 50}, {20, 10}, {10 + 0.000001, 40}},
|
||||
{{10, 0}, {10, 50}, {20, 10}, {10 + 0.000001f, 40}},
|
||||
// left top lower
|
||||
{{10, 20}, {10, 50}, {20, 10}, {20, 50}},
|
||||
{{10, 20}, {10, 50}, {10, 10}, {20, 50}},
|
||||
{{10, 20}, {10, 50}, {20, 10}, {10, 50}},
|
||||
{{10, 20}, {10, 50}, {20, 10}, {10 + 0.000001, 40}},
|
||||
{{10, 20}, {10, 50}, {20, 10}, {10 + 0.000001f, 40}},
|
||||
{{10, 20}, {10, 50}, { 0, 0}, {50, 50}},
|
||||
// left bottom higher
|
||||
{{10, 10}, {10, 40}, {20, 10}, {20, 50}},
|
||||
{{10, 10}, {10, 40}, {10, 10}, {20, 50}},
|
||||
{{10, 10}, {10, 40}, {20, 10}, {10, 50}},
|
||||
{{10, 10}, {10, 40}, {20, 10}, { 0 + 0.000001, 70}},
|
||||
{{10, 10}, {10, 40}, {20, 10}, { 0 + 0.000001f, 70}},
|
||||
// left bottom lower
|
||||
{{10, 10}, {10, 60}, {20, 10}, {20, 50}},
|
||||
{{10, 10}, {10, 60}, {10, 10}, {20, 50}},
|
||||
{{10, 10}, {10, 60}, {20, 10}, {10 + 0.000001, 50}},
|
||||
{{10, 10}, {10, 60}, {20, 10}, {10 + 0.000001, 40}},
|
||||
{{10, 10}, {10, 60}, { 0, 0}, {20 + 0.000001, 20}},
|
||||
{{10, 10}, {10, 60}, {20, 10}, {10 + 0.000001f, 50}},
|
||||
{{10, 10}, {10, 60}, {20, 10}, {10 + 0.000001f, 40}},
|
||||
{{10, 10}, {10, 60}, { 0, 0}, {20 + 0.000001f, 20}},
|
||||
};
|
||||
|
||||
size_t leftRightCount = sizeof(leftRight) / sizeof(leftRight[0]);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#define IN_TEST 1
|
||||
#include "CubicIntersection_TestData.h"
|
||||
#include <limits>
|
||||
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
#if !defined(IN_TEST)
|
||||
#define IN_TEST 1
|
||||
#endif
|
||||
|
||||
#include "DataTypes.h"
|
||||
|
||||
extern const Cubic pointDegenerates[];
|
||||
|
|
|
@ -150,12 +150,12 @@ bool isLinear(const Cubic& cubic, int startIndex, int endIndex) {
|
|||
int inner1 = startIndex ^ mask;
|
||||
int inner2 = endIndex ^ mask;
|
||||
lineParameters.controlPtDistance(cubic, inner1, inner2, distance);
|
||||
double limit = normalSquared * SquaredEpsilon;
|
||||
double limit = normalSquared;
|
||||
int index;
|
||||
for (index = 0; index < 2; ++index) {
|
||||
double distSq = distance[index];
|
||||
distSq *= distSq;
|
||||
if (distSq > limit) {
|
||||
if (approximately_greater(distSq, limit)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,8 +14,12 @@ void *memcpy(void *, const void *, size_t);
|
|||
#endif
|
||||
|
||||
|
||||
#if USE_EPSILON
|
||||
const double PointEpsilon = 0.000001;
|
||||
const double SquaredEpsilon = PointEpsilon * PointEpsilon;
|
||||
#endif
|
||||
|
||||
const int UlpsEpsilon = 16;
|
||||
|
||||
bool rotate(const Cubic& cubic, int zero, int index, Cubic& rotPath) {
|
||||
double dy = cubic[index].y - cubic[zero].y;
|
||||
|
|
|
@ -12,6 +12,13 @@
|
|||
#include <strings.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
bool AlmostEqualUlps(float A, float B, int maxUlpsDiff);
|
||||
int UlpsDiff(float A, float B);
|
||||
int FloatAsInt(float A);
|
||||
|
||||
#define USE_EPSILON 0
|
||||
|
||||
#if USE_EPSILON
|
||||
extern const double PointEpsilon;
|
||||
extern const double SquaredEpsilon;
|
||||
|
||||
|
@ -42,6 +49,48 @@ inline bool approximately_zero_squared(double x) {
|
|||
inline bool approximately_negative(double x) {
|
||||
return x < PointEpsilon;
|
||||
}
|
||||
#else
|
||||
extern const int UlpsEpsilon;
|
||||
|
||||
#if defined(IN_TEST)
|
||||
// FIXME: move to test-only header
|
||||
const double PointEpsilon = 0.000001;
|
||||
const double SquaredEpsilon = PointEpsilon * PointEpsilon;
|
||||
#endif
|
||||
|
||||
inline bool approximately_zero(double x) {
|
||||
|
||||
return fabs(x) < FLT_EPSILON;
|
||||
}
|
||||
|
||||
inline bool approximately_equal(double x, double y) {
|
||||
if (approximately_zero(x - y)) {
|
||||
return true;
|
||||
}
|
||||
return AlmostEqualUlps((float) x, (float) y, UlpsEpsilon);
|
||||
}
|
||||
|
||||
inline bool approximately_equal_squared(double x, double y) {
|
||||
return approximately_equal(x, y);
|
||||
}
|
||||
|
||||
inline bool approximately_greater(double x, double y) {
|
||||
return approximately_equal(x, y) ? false : x > y;
|
||||
}
|
||||
|
||||
inline bool approximately_lesser(double x, double y) {
|
||||
return approximately_equal(x, y) ? false : x < y;
|
||||
}
|
||||
|
||||
inline bool approximately_zero_squared(double x) {
|
||||
return approximately_zero(x);
|
||||
}
|
||||
|
||||
inline bool approximately_negative(double x) {
|
||||
return x < FLT_EPSILON;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct _Point {
|
||||
double x;
|
||||
|
@ -134,8 +183,5 @@ void xy_at_t(const Cubic& , double t, double& x, double& y);
|
|||
void xy_at_t(const _Line& , double t, double& x, double& y);
|
||||
void xy_at_t(const Quadratic& , double t, double& x, double& y);
|
||||
|
||||
bool AlmostEqualUlps(float A, float B, int maxUlpsDiff);
|
||||
int UlpsDiff(float A, float B);
|
||||
int FloatAsInt(float A);
|
||||
|
||||
#endif // __DataTypes_h__
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
/*
|
||||
* EdgeMain.cpp
|
||||
* shapeops_edge
|
||||
*
|
||||
* Created by Cary Clark on 3/26/12.
|
||||
* Copyright 2012 __MyCompanyName__. All rights reserved.
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "EdgeMain.h"
|
||||
#include "Intersection_Tests.h"
|
||||
|
||||
int main(int argc, char* argv) {
|
||||
Intersection_Tests();
|
||||
return 0;
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
#include "Intersection_Tests.h"
|
||||
|
||||
int main(int argc, char* argv) {
|
||||
Intersection_Tests();
|
||||
return 0;
|
||||
}
|
|
@ -767,6 +767,7 @@ public:
|
|||
fTs = src.fTs;
|
||||
fTopIntercepts = src.fTopIntercepts;
|
||||
fBottomIntercepts = src.fBottomIntercepts;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// OPTIMIZATION: remove this function if it's never called
|
||||
|
@ -1409,7 +1410,8 @@ public:
|
|||
curve[1] = &rh.fTangent;
|
||||
curve[2] = &rh.fBelow;
|
||||
}
|
||||
|
||||
// FIXME: code has been abandoned, incomplete....
|
||||
return false;
|
||||
}
|
||||
|
||||
bool abCompare(const SkPoint& a1, const SkPoint& a2, const SkPoint& b1,
|
||||
|
@ -1727,9 +1729,9 @@ public:
|
|||
b2 = edge->fTangent.fX;
|
||||
}
|
||||
if (fabs(t1 - t2) > fabs(b1 - b2)) {
|
||||
ulps = UlpsDiff(t1, t2);
|
||||
ulps = UlpsDiff((float) t1, (float) t2);
|
||||
} else {
|
||||
ulps = UlpsDiff(b1, b2);
|
||||
ulps = UlpsDiff((float) b1, (float) b2);
|
||||
}
|
||||
#if DEBUG_ADJUST_COINCIDENT
|
||||
SkDebugf("%s this=%d edge=%d ulps=%d\n", __FUNCTION__, ID(), edge->ID(),
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
/*
|
||||
* EdgeWalkerPolygons_Mismatches.h
|
||||
* edge
|
||||
*
|
||||
* Created by Cary Clark on 3/6/12.
|
||||
* Copyright 2012 __MyCompanyName__. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
|
@ -367,7 +367,7 @@ static void testPathTriangleRendering() {
|
|||
one.lineTo(0, 3);
|
||||
one.lineTo(1, 2);
|
||||
one.close();
|
||||
for (float x = .1f; x <= 2.9f; x += .1f) {
|
||||
for (float x = .1f; x <= 2.9ff; x += .1f) {
|
||||
SkDebugf("%s x=%g\n", __FUNCTION__, x);
|
||||
two.moveTo(0, 0);
|
||||
two.lineTo(x, x);
|
||||
|
@ -412,25 +412,25 @@ static void testSimplifySkinnyTriangle1() {
|
|||
static void testSimplifySkinnyTriangle2() {
|
||||
SkPath path, out;
|
||||
#if 01
|
||||
path.moveTo(591.091064, 627.534851);
|
||||
path.lineTo(541.088135, 560.707642);
|
||||
path.lineTo(491.085175, 493.880310);
|
||||
path.lineTo(441.082214, 427.053101);
|
||||
//path.lineTo(591.091064, 627.534851);
|
||||
path.moveTo(591.091064f, 627.534851f);
|
||||
path.lineTo(541.088135f, 560.707642f);
|
||||
path.lineTo(491.085175f, 493.880310f);
|
||||
path.lineTo(441.082214f, 427.053101f);
|
||||
//path.lineTo(591.091064f, 627.534851f);
|
||||
path.close();
|
||||
#endif
|
||||
path.moveTo(317.093445, 592.013306);
|
||||
path.lineTo(366.316162, 542.986572);
|
||||
path.lineTo(416.051514, 486.978577);
|
||||
path.lineTo(465.786865, 430.970581);
|
||||
//path.lineTo(317.093445, 592.013306);
|
||||
path.moveTo(317.093445f, 592.013306f);
|
||||
path.lineTo(366.316162f, 542.986572f);
|
||||
path.lineTo(416.051514f, 486.978577f);
|
||||
path.lineTo(465.786865f, 430.970581f);
|
||||
//path.lineTo(317.093445f, 592.013306f);
|
||||
path.close();
|
||||
#if 0
|
||||
path.moveTo(289.392517, 517.138489);
|
||||
path.lineTo(249.886078, 508.598022);
|
||||
path.lineTo(217.110916, 450.916443);
|
||||
path.lineTo(196.621033, 394.917633);
|
||||
//path.lineTo(289.392517, 517.138489);
|
||||
path.moveTo(289.392517f, 517.138489f);
|
||||
path.lineTo(249.886078f, 508.598022f);
|
||||
path.lineTo(217.110916f, 450.916443f);
|
||||
path.lineTo(196.621033f, 394.917633f);
|
||||
//path.lineTo(289.392517f, 517.138489f);
|
||||
path.close();
|
||||
#endif
|
||||
simplify(__FUNCTION__, path, true, out);
|
||||
|
@ -438,84 +438,84 @@ path.close();
|
|||
|
||||
static void testSimplifySkinnyTriangle3() {
|
||||
SkPath path, out;
|
||||
path.moveTo(591, 627.534851);
|
||||
path.lineTo(541, 560.707642);
|
||||
path.lineTo(491, 493.880310);
|
||||
path.lineTo(441, 427.053101);
|
||||
path.moveTo(591, 627.534851f);
|
||||
path.lineTo(541, 560.707642f);
|
||||
path.lineTo(491, 493.880310f);
|
||||
path.lineTo(441, 427.053101f);
|
||||
path.close();
|
||||
path.moveTo(317, 592.013306);
|
||||
path.lineTo(366, 542.986572);
|
||||
path.lineTo(416, 486.978577);
|
||||
path.lineTo(465, 430.970581);
|
||||
path.moveTo(317, 592.013306f);
|
||||
path.lineTo(366, 542.986572f);
|
||||
path.lineTo(416, 486.978577f);
|
||||
path.lineTo(465, 430.970581f);
|
||||
path.close();
|
||||
simplify(__FUNCTION__, path, true, out);
|
||||
}
|
||||
|
||||
static void testSimplifySkinnyTriangle4() {
|
||||
SkPath path, out;
|
||||
path.moveTo(572.655212, 614.959961);
|
||||
path.lineTo(524.618896, 549.339600);
|
||||
path.lineTo(476.582581, 483.719269);
|
||||
path.lineTo(428.546265, 418.098938);
|
||||
path.lineTo(572.655212, 614.959961);
|
||||
path.moveTo(572.655212f, 614.959961f);
|
||||
path.lineTo(524.618896f, 549.339600f);
|
||||
path.lineTo(476.582581f, 483.719269f);
|
||||
path.lineTo(428.546265f, 418.098938f);
|
||||
path.lineTo(572.655212f, 614.959961f);
|
||||
path.close();
|
||||
path.moveTo(312.166382, 583.723083);
|
||||
path.lineTo(361.047791, 529.824219);
|
||||
path.lineTo(409.929230, 475.925354);
|
||||
path.lineTo(458.810669, 422.026520);
|
||||
path.lineTo(312.166382, 583.723083);
|
||||
path.moveTo(312.166382f, 583.723083f);
|
||||
path.lineTo(361.047791f, 529.824219f);
|
||||
path.lineTo(409.929230f, 475.925354f);
|
||||
path.lineTo(458.810669f, 422.026520f);
|
||||
path.lineTo(312.166382f, 583.723083f);
|
||||
path.close();
|
||||
path.moveTo(278.742737, 508.065643);
|
||||
path.lineTo(241.475800, 493.465118);
|
||||
path.lineTo(210.344177, 437.315125);
|
||||
path.lineTo(197.019455, 383.794556);
|
||||
path.lineTo(278.742737, 508.065643);
|
||||
path.moveTo(278.742737f, 508.065643f);
|
||||
path.lineTo(241.475800f, 493.465118f);
|
||||
path.lineTo(210.344177f, 437.315125f);
|
||||
path.lineTo(197.019455f, 383.794556f);
|
||||
path.lineTo(278.742737f, 508.065643f);
|
||||
path.close();
|
||||
simplify(__FUNCTION__, path, true, out);
|
||||
}
|
||||
|
||||
static void testSimplifySkinnyTriangle5() {
|
||||
SkPath path, out;
|
||||
path.moveTo(554.690613, 602.286072);
|
||||
path.lineTo(508.590057, 537.906250);
|
||||
path.lineTo(462.489441, 473.526520);
|
||||
path.lineTo(416.388855, 409.146729);
|
||||
path.lineTo(554.690613, 602.286072);
|
||||
path.moveTo(554.690613f, 602.286072f);
|
||||
path.lineTo(508.590057f, 537.906250f);
|
||||
path.lineTo(462.489441f, 473.526520f);
|
||||
path.lineTo(416.388855f, 409.146729f);
|
||||
path.lineTo(554.690613f, 602.286072f);
|
||||
path.close();
|
||||
path.moveTo(307.216949, 575.189270);
|
||||
path.lineTo(355.826965, 516.804688);
|
||||
path.lineTo(403.815918, 464.990753);
|
||||
path.lineTo(451.804871, 413.176819);
|
||||
path.lineTo(307.216949, 575.189270);
|
||||
path.moveTo(307.216949f, 575.189270f);
|
||||
path.lineTo(355.826965f, 516.804688f);
|
||||
path.lineTo(403.815918f, 464.990753f);
|
||||
path.lineTo(451.804871f, 413.176819f);
|
||||
path.lineTo(307.216949f, 575.189270f);
|
||||
path.close();
|
||||
path.moveTo(271.998901, 521.301025);
|
||||
path.lineTo(234.619705, 499.687683);
|
||||
path.lineTo(203.059692, 441.332336);
|
||||
path.lineTo(195.994370, 386.856506);
|
||||
path.lineTo(271.998901, 521.301025);
|
||||
path.moveTo(271.998901f, 521.301025f);
|
||||
path.lineTo(234.619705f, 499.687683f);
|
||||
path.lineTo(203.059692f, 441.332336f);
|
||||
path.lineTo(195.994370f, 386.856506f);
|
||||
path.lineTo(271.998901f, 521.301025f);
|
||||
path.close();
|
||||
simplify(__FUNCTION__, path, true, out);
|
||||
}
|
||||
|
||||
static void testSimplifySkinnyTriangle6() {
|
||||
SkPath path, out;
|
||||
path.moveTo(591.091064, 627.534851);
|
||||
path.lineTo(541.088135, 560.707642);
|
||||
path.lineTo(491.085175, 493.880310);
|
||||
path.lineTo(441.082214, 427.053101);
|
||||
path.lineTo(591.091064, 627.534851);
|
||||
path.moveTo(591.091064f, 627.534851f);
|
||||
path.lineTo(541.088135f, 560.707642f);
|
||||
path.lineTo(491.085175f, 493.880310f);
|
||||
path.lineTo(441.082214f, 427.053101f);
|
||||
path.lineTo(591.091064f, 627.534851f);
|
||||
path.close();
|
||||
path.moveTo(317.093445, 592.013306);
|
||||
path.lineTo(366.316162, 542.986572);
|
||||
path.lineTo(416.051514, 486.978577);
|
||||
path.lineTo(465.786865, 430.970581);
|
||||
path.lineTo(317.093445, 592.013306);
|
||||
path.moveTo(317.093445f, 592.013306f);
|
||||
path.lineTo(366.316162f, 542.986572f);
|
||||
path.lineTo(416.051514f, 486.978577f);
|
||||
path.lineTo(465.786865f, 430.970581f);
|
||||
path.lineTo(317.093445f, 592.013306f);
|
||||
path.close();
|
||||
path.moveTo(289.392517, 517.138489);
|
||||
path.lineTo(249.886078, 508.598022);
|
||||
path.lineTo(217.110916, 450.916443);
|
||||
path.lineTo(196.621033, 394.917633);
|
||||
path.lineTo(289.392517, 517.138489);
|
||||
path.moveTo(289.392517f, 517.138489f);
|
||||
path.lineTo(249.886078f, 508.598022f);
|
||||
path.lineTo(217.110916f, 450.916443f);
|
||||
path.lineTo(196.621033f, 394.917633f);
|
||||
path.lineTo(289.392517f, 517.138489f);
|
||||
path.close();
|
||||
simplify(__FUNCTION__, path, true, out);
|
||||
}
|
||||
|
@ -561,69 +561,69 @@ static void testSimplifyTriangle24() {
|
|||
|
||||
static void testSimplifySkinnyTriangle7() {
|
||||
SkPath path, out;
|
||||
path.moveTo(487.502319, 550.811279);
|
||||
path.lineTo(448.826050, 491.720123);
|
||||
path.lineTo(410.149780, 432.628967);
|
||||
path.lineTo(371.473572, 373.537781);
|
||||
path.lineTo(487.502319, 550.811279);
|
||||
path.moveTo(487.502319f, 550.811279f);
|
||||
path.lineTo(448.826050f, 491.720123f);
|
||||
path.lineTo(410.149780f, 432.628967f);
|
||||
path.lineTo(371.473572f, 373.537781f);
|
||||
path.lineTo(487.502319f, 550.811279f);
|
||||
path.close();
|
||||
path.moveTo(295.817108, 532.655579);
|
||||
path.lineTo(342.896271, 485.912292);
|
||||
path.lineTo(389.975433, 439.169006);
|
||||
path.lineTo(437.054596, 392.425781);
|
||||
path.lineTo(295.817108, 532.655579);
|
||||
path.moveTo(295.817108f, 532.655579f);
|
||||
path.lineTo(342.896271f, 485.912292f);
|
||||
path.lineTo(389.975433f, 439.169006f);
|
||||
path.lineTo(437.054596f, 392.425781f);
|
||||
path.lineTo(295.817108f, 532.655579f);
|
||||
path.close();
|
||||
path.moveTo(239.726822, 575.025269);
|
||||
path.lineTo(204.117569, 521.429688);
|
||||
path.lineTo(171.275452, 454.110382);
|
||||
path.lineTo(193.328583, 397.859497);
|
||||
path.lineTo(239.726822, 575.025269);
|
||||
path.moveTo(239.726822f, 575.025269f);
|
||||
path.lineTo(204.117569f, 521.429688f);
|
||||
path.lineTo(171.275452f, 454.110382f);
|
||||
path.lineTo(193.328583f, 397.859497f);
|
||||
path.lineTo(239.726822f, 575.025269f);
|
||||
path.close();
|
||||
simplify(__FUNCTION__, path, true, out);
|
||||
}
|
||||
|
||||
static void testSimplifySkinnyTriangle8() {
|
||||
SkPath path, out;
|
||||
path.moveTo(441.943115, 511.678040);
|
||||
path.lineTo(408.487549, 456.880920);
|
||||
path.lineTo(375.031952, 402.083801);
|
||||
path.lineTo(341.576385, 347.286682);
|
||||
path.lineTo(441.943115, 511.678040);
|
||||
path.moveTo(441.943115f, 511.678040f);
|
||||
path.lineTo(408.487549f, 456.880920f);
|
||||
path.lineTo(375.031952f, 402.083801f);
|
||||
path.lineTo(341.576385f, 347.286682f);
|
||||
path.lineTo(441.943115f, 511.678040f);
|
||||
path.close();
|
||||
path.moveTo(297.548492, 557.246704);
|
||||
path.lineTo(350.768494, 507.627014);
|
||||
path.lineTo(403.988525, 458.007385);
|
||||
path.lineTo(457.208527, 408.387695);
|
||||
path.lineTo(297.548492, 557.246704);
|
||||
path.moveTo(297.548492f, 557.246704f);
|
||||
path.lineTo(350.768494f, 507.627014f);
|
||||
path.lineTo(403.988525f, 458.007385f);
|
||||
path.lineTo(457.208527f, 408.387695f);
|
||||
path.lineTo(297.548492f, 557.246704f);
|
||||
path.close();
|
||||
path.moveTo(209.857895, 615.802979);
|
||||
path.lineTo(178.249481, 534.230347);
|
||||
path.lineTo(144.905640, 460.056824);
|
||||
path.lineTo(192.953125, 404.972900);
|
||||
path.lineTo(209.857895, 615.802979);
|
||||
path.moveTo(209.857895f, 615.802979f);
|
||||
path.lineTo(178.249481f, 534.230347f);
|
||||
path.lineTo(144.905640f, 460.056824f);
|
||||
path.lineTo(192.953125f, 404.972900f);
|
||||
path.lineTo(209.857895f, 615.802979f);
|
||||
path.close();
|
||||
simplify(__FUNCTION__, path, true, out);
|
||||
}
|
||||
|
||||
static void testSimplifySkinnyTriangle9() {
|
||||
SkPath path, out;
|
||||
path.moveTo(439.867065, 528.291931);
|
||||
path.lineTo(405.413025, 469.107178);
|
||||
path.lineTo(370.958954, 409.922363);
|
||||
path.lineTo(336.504883, 350.737610);
|
||||
path.lineTo(439.867065, 528.291931);
|
||||
path.moveTo(439.867065f, 528.291931f);
|
||||
path.lineTo(405.413025f, 469.107178f);
|
||||
path.lineTo(370.958954f, 409.922363f);
|
||||
path.lineTo(336.504883f, 350.737610f);
|
||||
path.lineTo(439.867065f, 528.291931f);
|
||||
path.close();
|
||||
path.moveTo(298.922455, 573.251953);
|
||||
path.lineTo(356.360962, 521.905090);
|
||||
path.lineTo(413.799438, 470.558228);
|
||||
path.lineTo(471.237915, 419.211365);
|
||||
path.lineTo(298.922455, 573.251953);
|
||||
path.moveTo(298.922455f, 573.251953f);
|
||||
path.lineTo(356.360962f, 521.905090f);
|
||||
path.lineTo(413.799438f, 470.558228f);
|
||||
path.lineTo(471.237915f, 419.211365f);
|
||||
path.lineTo(298.922455f, 573.251953f);
|
||||
path.close();
|
||||
path.moveTo(187.200775, 643.035156);
|
||||
path.lineTo(159.713165, 540.993774);
|
||||
path.lineTo(126.257164, 462.198517);
|
||||
path.lineTo(193.534012, 409.266235);
|
||||
path.lineTo(187.200775, 643.035156);
|
||||
path.moveTo(187.200775f, 643.035156f);
|
||||
path.lineTo(159.713165f, 540.993774f);
|
||||
path.lineTo(126.257164f, 462.198517f);
|
||||
path.lineTo(193.534012f, 409.266235f);
|
||||
path.lineTo(187.200775f, 643.035156f);
|
||||
path.close();
|
||||
path.close();
|
||||
simplify(__FUNCTION__, path, true, out);
|
||||
|
@ -632,87 +632,87 @@ path.close();
|
|||
static void testSimplifySkinnyTriangle10() {
|
||||
SkPath path, out;
|
||||
#if 0
|
||||
path.moveTo(99.270325, 239.365234);
|
||||
path.lineTo(105.967056, 173.361206);
|
||||
path.lineTo(148.821381, 141.309891);
|
||||
path.lineTo(159.101013, 189.235138);
|
||||
path.lineTo(99.270325, 239.365234);
|
||||
path.moveTo(99.270325f, 239.365234f);
|
||||
path.lineTo(105.967056f, 173.361206f);
|
||||
path.lineTo(148.821381f, 141.309891f);
|
||||
path.lineTo(159.101013f, 189.235138f);
|
||||
path.lineTo(99.270325f, 239.365234f);
|
||||
path.close();
|
||||
#endif
|
||||
path.moveTo(213.673737, 413.292938);
|
||||
path.lineTo(225.200134, 343.616821);
|
||||
path.lineTo(236.726532, 273.940704);
|
||||
path.lineTo(219.386414, 231.373322);
|
||||
path.lineTo(213.673737, 413.292938);
|
||||
path.moveTo(213.673737f, 413.292938f);
|
||||
path.lineTo(225.200134f, 343.616821f);
|
||||
path.lineTo(236.726532f, 273.940704f);
|
||||
path.lineTo(219.386414f, 231.373322f);
|
||||
path.lineTo(213.673737f, 413.292938f);
|
||||
path.close();
|
||||
path.moveTo(43.485352, 308.984497);
|
||||
path.lineTo(122.610657, 305.950134);
|
||||
path.lineTo(201.735962, 302.915802);
|
||||
path.lineTo(280.861267, 299.881470);
|
||||
path.lineTo(43.485352, 308.984497);
|
||||
path.moveTo(43.485352f, 308.984497f);
|
||||
path.lineTo(122.610657f, 305.950134f);
|
||||
path.lineTo(201.735962f, 302.915802f);
|
||||
path.lineTo(280.861267f, 299.881470f);
|
||||
path.lineTo(43.485352f, 308.984497f);
|
||||
path.close();
|
||||
simplify(__FUNCTION__, path, true, out);
|
||||
}
|
||||
|
||||
static void testSimplifySkinnyTriangle11() {
|
||||
SkPath path, out;
|
||||
path.moveTo(-177.878387, 265.368988);
|
||||
path.lineTo(-254.415771, 303.709961);
|
||||
path.lineTo(-317.465363, 271.325562);
|
||||
path.lineTo(-374.520386, 207.507660);
|
||||
path.lineTo(-177.878387, 265.368988);
|
||||
path.moveTo(-177.878387f, 265.368988f);
|
||||
path.lineTo(-254.415771f, 303.709961f);
|
||||
path.lineTo(-317.465363f, 271.325562f);
|
||||
path.lineTo(-374.520386f, 207.507660f);
|
||||
path.lineTo(-177.878387f, 265.368988f);
|
||||
path.close();
|
||||
path.moveTo(-63.582489, -3.679123);
|
||||
path.lineTo(-134.496841, 26.434566);
|
||||
path.lineTo(-205.411209, 56.548256);
|
||||
path.lineTo(-276.325562, 86.661942);
|
||||
path.lineTo(-63.582489, -3.679123);
|
||||
path.moveTo(-63.582489f, -3.679123f);
|
||||
path.lineTo(-134.496841f, 26.434566f);
|
||||
path.lineTo(-205.411209f, 56.548256f);
|
||||
path.lineTo(-276.325562f, 86.661942f);
|
||||
path.lineTo(-63.582489f, -3.679123f);
|
||||
path.close();
|
||||
path.moveTo(-57.078423, 162.633453);
|
||||
path.lineTo(-95.963928, 106.261139);
|
||||
path.lineTo(-134.849457, 49.888824);
|
||||
path.lineTo(-173.734955, -6.483480);
|
||||
path.lineTo(-57.078423, 162.633453);
|
||||
path.moveTo(-57.078423f, 162.633453f);
|
||||
path.lineTo(-95.963928f, 106.261139f);
|
||||
path.lineTo(-134.849457f, 49.888824f);
|
||||
path.lineTo(-173.734955f, -6.483480f);
|
||||
path.lineTo(-57.078423f, 162.633453f);
|
||||
path.close();
|
||||
simplify(__FUNCTION__, path, true, out);
|
||||
}
|
||||
|
||||
static void testSimplifySkinnyTriangle12() {
|
||||
SkPath path, out;
|
||||
path.moveTo(98.666489, -94.295059);
|
||||
path.lineTo(156.584320, -61.939133);
|
||||
path.lineTo(174.672974, -12.343765);
|
||||
path.lineTo(158.622345, 52.028267);
|
||||
path.lineTo(98.666489, -94.295059);
|
||||
path.moveTo(98.666489f, -94.295059f);
|
||||
path.lineTo(156.584320f, -61.939133f);
|
||||
path.lineTo(174.672974f, -12.343765f);
|
||||
path.lineTo(158.622345f, 52.028267f);
|
||||
path.lineTo(98.666489f, -94.295059f);
|
||||
path.close();
|
||||
path.moveTo(-133.225616, -48.622055);
|
||||
path.lineTo(-73.855499, -10.375397);
|
||||
path.lineTo(-14.485367, 27.871277);
|
||||
path.lineTo(44.884750, 66.117935);
|
||||
path.lineTo(-133.225616, -48.622055);
|
||||
path.moveTo(-133.225616f, -48.622055f);
|
||||
path.lineTo(-73.855499f, -10.375397f);
|
||||
path.lineTo(-14.485367f, 27.871277f);
|
||||
path.lineTo(44.884750f, 66.117935f);
|
||||
path.lineTo(-133.225616f, -48.622055f);
|
||||
path.close();
|
||||
path.moveTo( 9.030045, -163.413132);
|
||||
path.lineTo(-19.605331, -89.588760);
|
||||
path.lineTo(-48.240707, -15.764404);
|
||||
path.lineTo(-76.876053, 58.059944);
|
||||
path.lineTo( 9.030045, -163.413132);
|
||||
path.moveTo( 9.030045f, -163.413132f);
|
||||
path.lineTo(-19.605331f, -89.588760f);
|
||||
path.lineTo(-48.240707f, -15.764404f);
|
||||
path.lineTo(-76.876053f, 58.059944f);
|
||||
path.lineTo( 9.030045f, -163.413132f);
|
||||
path.close();
|
||||
simplify(__FUNCTION__, path, true, out);
|
||||
}
|
||||
|
||||
static void testSimplifySkinnyTriangle13() {
|
||||
SkPath path, out;
|
||||
path.moveTo(340.41568, -170.97171);
|
||||
path.lineTo(418.846893, -142.428329);
|
||||
path.lineTo(497.278107, -113.884933);
|
||||
path.lineTo(449.18222, -45.6723022);
|
||||
path.lineTo(340.41568, -170.97171);
|
||||
path.moveTo(340.41568f, -170.97171f);
|
||||
path.lineTo(418.846893f, -142.428329f);
|
||||
path.lineTo(497.278107f, -113.884933f);
|
||||
path.lineTo(449.18222f, -45.6723022f);
|
||||
path.lineTo(340.41568f, -170.97171f);
|
||||
path.close();
|
||||
path.moveTo(326.610535, 34.0393639);
|
||||
path.lineTo(371.334595, -14.9620667);
|
||||
path.lineTo(416.058624, -63.9634857);
|
||||
path.lineTo(460.782654, -112.96492);
|
||||
path.lineTo(326.610535, 34.0393639);
|
||||
path.moveTo(326.610535f, 34.0393639f);
|
||||
path.lineTo(371.334595f, -14.9620667f);
|
||||
path.lineTo(416.058624f, -63.9634857f);
|
||||
path.lineTo(460.782654f, -112.96492f);
|
||||
path.lineTo(326.610535f, 34.0393639f);
|
||||
path.close();
|
||||
simplify(__FUNCTION__, path, true, out);
|
||||
}
|
||||
|
|
|
@ -7,8 +7,13 @@ void testSimplify();
|
|||
#define TEST_QUADS_FIRST 0
|
||||
|
||||
void Intersection_Tests() {
|
||||
SimplifyFindTop_Test();
|
||||
SimplifyAngle_Test();
|
||||
QuadraticReduceOrder_Test();
|
||||
QuadraticBezierClip_Test();
|
||||
QuadraticIntersection_Test();
|
||||
SimplifyAddIntersectingTs_Test();
|
||||
|
||||
|
||||
cubecode_test(1);
|
||||
convert_testx();
|
||||
// tests are in dependency / complexity order
|
||||
|
@ -39,8 +44,6 @@ void Intersection_Tests() {
|
|||
#endif
|
||||
|
||||
QuadraticCoincidence_Test();
|
||||
QuadraticReduceOrder_Test();
|
||||
QuadraticBezierClip_Test();
|
||||
QuadraticIntersection_Test();
|
||||
|
||||
CubicParameterization_Test();
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
#if !defined(IN_TEST)
|
||||
#define IN_TEST 1
|
||||
#endif
|
||||
|
||||
void ActiveEdge_Test();
|
||||
void ConvexHull_Test();
|
||||
void ConvexHull_X_Test();
|
||||
|
@ -13,6 +17,9 @@ void LineIntersection_Test();
|
|||
void LineParameter_Test();
|
||||
void LineQuadraticIntersection_Test();
|
||||
void SimplifyAddIntersectingTs_Test();
|
||||
void SimplifyAngle_Test();
|
||||
void SimplifyFindNext_Test();
|
||||
void SimplifyFindTop_Test();
|
||||
void SimplifyDegenerate4x4TrianglesThreaded_Test();
|
||||
void SimplifyNondegenerate4x4TrianglesThreaded_Test();
|
||||
void SimplifyPolygonPaths_Test();
|
||||
|
|
|
@ -4,6 +4,15 @@
|
|||
// computer-aided design - volume 22 number 9 november 1990 pp 538 - 549
|
||||
// online at http://cagd.cs.byu.edu/~tom/papers/bezclip.pdf
|
||||
|
||||
// This turns a line segment into a parameterized line, of the form
|
||||
// ax + by + c = 0
|
||||
// When a^2 + b^2 == 1, the line is normalized.
|
||||
// The distance to the line for (x, y) is d(x,y) = ax + by + c
|
||||
//
|
||||
// Note that the distances below are not necessarily normalized. To get the true
|
||||
// distance, it's necessary to either call normalize() after xxxEndPoints(), or
|
||||
// divide the result of xxxDistance() by sqrt(normalSquared())
|
||||
|
||||
class LineParameters {
|
||||
public:
|
||||
void cubicEndPoints(const Cubic& pts) {
|
||||
|
@ -42,7 +51,7 @@ public:
|
|||
|
||||
bool normalize() {
|
||||
double normal = sqrt(normalSquared());
|
||||
if (normal < SquaredEpsilon) {
|
||||
if (approximately_zero_squared(normal)) {
|
||||
a = b = c = 0;
|
||||
return false;
|
||||
}
|
||||
|
@ -87,6 +96,7 @@ public:
|
|||
double pointDistance(const _Point& pt) {
|
||||
return a * pt.x + b * pt.y + c;
|
||||
}
|
||||
|
||||
private:
|
||||
double a;
|
||||
double b;
|
||||
|
|
|
@ -2,7 +2,24 @@
|
|||
#include "Intersection_Tests.h"
|
||||
#include "QuadraticIntersection_TestData.h"
|
||||
|
||||
void QuadraticBezierClip_Test() {
|
||||
static const Quadratic testSet[] = {
|
||||
{{8.0000000000000071, 8.0000000000000071},
|
||||
{8.7289570079366854, 8.7289570079366889},
|
||||
{9.3914917259458743, 9.0593802763083691}},
|
||||
{{8.0000000000000142, 8.0000000000000142},
|
||||
{8.1250000000000107, 8.1250000000000071},
|
||||
{8.2500000000000071, 8.2187500000000053}}
|
||||
};
|
||||
|
||||
static void oneOffTest() {
|
||||
const Quadratic& quad1 = testSet[0];
|
||||
const Quadratic& quad2 = testSet[1];
|
||||
double minT = 0;
|
||||
double maxT = 1;
|
||||
bezier_clip(quad1, quad2, minT, maxT);
|
||||
}
|
||||
|
||||
void standardTestCases() {
|
||||
for (size_t index = 0; index < quadraticTests_count; ++index) {
|
||||
const Quadratic& quad1 = quadraticTests[index][0];
|
||||
const Quadratic& quad2 = quadraticTests[index][1];
|
||||
|
@ -22,3 +39,8 @@ void QuadraticBezierClip_Test() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QuadraticBezierClip_Test() {
|
||||
oneOffTest();
|
||||
standardTestCases();
|
||||
}
|
||||
|
|
|
@ -3,10 +3,11 @@
|
|||
#include "Intersections.h"
|
||||
#include "QuadraticIntersection_TestData.h"
|
||||
#include "TestUtilities.h"
|
||||
#include "SkTypes.h"
|
||||
|
||||
const int firstQuadIntersectionTest = 9;
|
||||
|
||||
void QuadraticIntersection_Test() {
|
||||
static void standardTestCases() {
|
||||
for (size_t index = firstQuadIntersectionTest; index < quadraticTests_count; ++index) {
|
||||
const Quadratic& quad1 = quadraticTests[index][0];
|
||||
const Quadratic& quad2 = quadraticTests[index][1];
|
||||
|
@ -44,3 +45,49 @@ void QuadraticIntersection_Test() {
|
|||
}
|
||||
}
|
||||
|
||||
static const Quadratic testSet[] = {
|
||||
{{8, 8}, {10, 10}, {8, -10}},
|
||||
{{8, 8}, {12, 12}, {14, 4}},
|
||||
{{8, 8}, {9, 9}, {10, 8}}
|
||||
};
|
||||
|
||||
const size_t testSetCount = sizeof(testSet) / sizeof(testSet[0]);
|
||||
|
||||
static void oneOffTest() {
|
||||
for (int outer = 0; outer < testSetCount - 1; ++outer) {
|
||||
for (int inner = outer + 1; inner < testSetCount; ++inner) {
|
||||
const Quadratic& quad1 = testSet[outer];
|
||||
const Quadratic& quad2 = testSet[inner];
|
||||
Intersections intersections;
|
||||
intersect(quad1, quad2, intersections);
|
||||
if (!intersections.intersected()) {
|
||||
SkDebugf("%s no intersection!\n", __FUNCTION__);
|
||||
}
|
||||
for (int pt = 0; pt < intersections.used(); ++pt) {
|
||||
double tt1 = intersections.fT[0][pt];
|
||||
double tx1, ty1;
|
||||
xy_at_t(quad1, tt1, tx1, ty1);
|
||||
double tt2 = intersections.fT[1][pt];
|
||||
double tx2, ty2;
|
||||
xy_at_t(quad2, tt2, tx2, ty2);
|
||||
if (!approximately_equal(tx1, tx2)) {
|
||||
SkDebugf("%s [%d,%d] x!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
|
||||
__FUNCTION__, (int)index, pt, tt1, tx1, ty1, tt2, tx2, ty2);
|
||||
SkASSERT(0);
|
||||
}
|
||||
if (!approximately_equal(ty1, ty2)) {
|
||||
SkDebugf("%s [%d,%d] y!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
|
||||
__FUNCTION__, (int)index, pt, tt1, tx1, ty1, tt2, tx2, ty2);
|
||||
SkASSERT(0);
|
||||
}
|
||||
SkDebugf("%s [%d][%d] t1=%1.9g (%1.9g, %1.9g) t2=%1.9g\n", __FUNCTION__,
|
||||
outer, inner, tt1, tx1, tx2, tt2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QuadraticIntersection_Test() {
|
||||
oneOffTest();
|
||||
standardTestCases();
|
||||
}
|
|
@ -1,10 +1,8 @@
|
|||
/*
|
||||
* QuadraticIntersection_TestData.cpp
|
||||
* edge
|
||||
*
|
||||
* Created by Cary Clark on 1/10/12.
|
||||
* Copyright 2012 __MyCompanyName__. All rights reserved.
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "QuadraticIntersection_TestData.h"
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
#if !defined(IN_TEST)
|
||||
#define IN_TEST 1
|
||||
#endif
|
||||
|
||||
#include "DataTypes.h"
|
||||
|
||||
extern const Quadratic quadraticLines[];
|
||||
|
|
|
@ -110,11 +110,10 @@ static int check_linear(const Quadratic& quad, Quadratic& reduction,
|
|||
bool isLinear(const Quadratic& quad, int startIndex, int endIndex) {
|
||||
LineParameters lineParameters;
|
||||
lineParameters.quadEndPoints(quad, startIndex, endIndex);
|
||||
double normalSquared = lineParameters.normalSquared();
|
||||
double distance = lineParameters.controlPtDistance(quad); // not normalized
|
||||
double limit = normalSquared * SquaredEpsilon;
|
||||
double distSq = distance * distance;
|
||||
return distSq <= limit;
|
||||
// FIXME: maybe it's possible to avoid this and compare non-normalized
|
||||
lineParameters.normalize();
|
||||
double distance = lineParameters.controlPtDistance(quad);
|
||||
return approximately_zero(distance);
|
||||
}
|
||||
|
||||
// reduce to a quadratic or smaller
|
||||
|
|
|
@ -2,8 +2,27 @@
|
|||
#include "Intersection_Tests.h"
|
||||
#include "QuadraticIntersection_TestData.h"
|
||||
#include "TestUtilities.h"
|
||||
#include "SkTypes.h"
|
||||
|
||||
void QuadraticReduceOrder_Test() {
|
||||
static const Quadratic testSet[] = {
|
||||
{{1, 1}, {2, 2}, {1, 1.000003}},
|
||||
{{1, 0}, {2, 6}, {3, 0}}
|
||||
};
|
||||
|
||||
static const size_t testSetCount = sizeof(testSet) / sizeof(testSet[0]);
|
||||
|
||||
|
||||
static void oneOffTest() {
|
||||
SkDebugf("%s FLT_EPSILON=%1.9g\n", __FUNCTION__, FLT_EPSILON);
|
||||
for (int index = 0; index < testSetCount; ++index) {
|
||||
const Quadratic& quad = testSet[index];
|
||||
Quadratic reduce;
|
||||
int order = reduceOrder(quad, reduce);
|
||||
SkASSERT(order == 3);
|
||||
}
|
||||
}
|
||||
|
||||
static void standardTestCases() {
|
||||
size_t index;
|
||||
Quadratic reduce;
|
||||
int order;
|
||||
|
@ -36,3 +55,8 @@ void QuadraticReduceOrder_Test() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QuadraticReduceOrder_Test() {
|
||||
oneOffTest();
|
||||
standardTestCases();
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#include "CurveIntersection.h"
|
||||
#include "Intersections.h"
|
||||
#include "LineIntersection.h"
|
||||
#include "LineParameters.h"
|
||||
#include "SkPath.h"
|
||||
#include "SkRect.h"
|
||||
#include "SkTArray.h"
|
||||
#include "SkTDArray.h"
|
||||
#include "ShapeOps.h"
|
||||
#include "TSearch.h"
|
||||
#include <algorithm> // used for std::min
|
||||
|
|
@ -1,13 +1,10 @@
|
|||
#include "CurveIntersection.h"
|
||||
#include "Intersections.h"
|
||||
#include "LineIntersection.h"
|
||||
#include "SkPath.h"
|
||||
#include "SkRect.h"
|
||||
#include "SkTArray.h"
|
||||
#include "SkTDArray.h"
|
||||
#include "ShapeOps.h"
|
||||
#include "TSearch.h"
|
||||
#include <algorithm> // used for std::min
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#include "Simplify.h"
|
||||
|
||||
namespace SimplifyAddIntersectingTsTest {
|
||||
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "Simplify.h"
|
||||
|
||||
namespace SimplifyAngleTest {
|
||||
|
||||
#include "Simplify.cpp"
|
||||
|
||||
} // end of SimplifyAngleTest namespace
|
||||
|
||||
#include "Intersection_Tests.h"
|
||||
|
||||
static const SkPoint lines[][2] = {
|
||||
{ { 10, 10}, { 10, 20} },
|
||||
{ { 10, 10}, { 20, 10} },
|
||||
{ { 10, 10}, {-20, 10} },
|
||||
{ { 10, 10}, { 10, -20} },
|
||||
{ { 10, 10}, { 20, 20} },
|
||||
{ { 10, 10}, {-20, -20} },
|
||||
{ { 10, 10}, {-20, 40} },
|
||||
{ { 10, 10}, { 40, -20} }
|
||||
};
|
||||
|
||||
static const size_t lineCount = sizeof(lines) / sizeof(lines[0]);
|
||||
|
||||
static const SkPoint quads[][3] = {
|
||||
{{ 1, 1}, { 2, 2}, { 1, 3}}, // 0
|
||||
{{ 1, 1}, { 3, 3}, { 1, 5}}, // 1
|
||||
{{ 1, 1}, { 4, 4}, { 1, 7}}, // 2
|
||||
{{ 1, 1}, { 5, 5}, { 9, 9}}, // 3
|
||||
{{ 1, 1}, { 4, 4}, { 7, 1}}, // 4
|
||||
{{ 1, 1}, { 3, 3}, { 5, 1}}, // 5
|
||||
{{ 1, 1}, { 2, 2}, { 3, 1}}, // 6
|
||||
};
|
||||
|
||||
static const size_t quadCount = sizeof(quads) / sizeof(quads[0]);
|
||||
|
||||
static const SkPoint cubics[][4] = {
|
||||
{{ 1, 1}, { 2, 2}, { 2, 3}, { 1, 4}},
|
||||
{{ 1, 1}, { 3, 3}, { 3, 5}, { 1, 7}},
|
||||
{{ 1, 1}, { 4, 4}, { 4, 7}, { 1, 10}},
|
||||
{{ 1, 1}, { 5, 5}, { 8, 8}, { 9, 9}},
|
||||
{{ 1, 1}, { 4, 4}, { 7, 4}, { 10, 1}},
|
||||
{{ 1, 1}, { 3, 3}, { 5, 3}, { 7, 1}},
|
||||
{{ 1, 1}, { 2, 2}, { 3, 2}, { 4, 1}},
|
||||
};
|
||||
|
||||
static const size_t cubicCount = sizeof(cubics) / sizeof(cubics[0]);
|
||||
|
||||
static void testLines(bool testFlat) {
|
||||
// create angles in a circle
|
||||
SkTDArray<SimplifyAngleTest::Angle> angles;
|
||||
SkTDArray<SimplifyAngleTest::Angle* > angleList;
|
||||
SkTDArray<double> arcTans;
|
||||
size_t x;
|
||||
for (x = 0; x < lineCount; ++x) {
|
||||
SimplifyAngleTest::Angle* angle = angles.append();
|
||||
if (testFlat) {
|
||||
angle->setFlat(lines[x], SkPath::kLine_Verb, 0, x, x + 1, false);
|
||||
} else {
|
||||
angle->set(lines[x], SkPath::kLine_Verb, 0, x, x + 1, false);
|
||||
}
|
||||
double arcTan = atan2(lines[x][0].fX - lines[x][1].fX,
|
||||
lines[x][0].fY - lines[x][1].fY);
|
||||
arcTans.push(arcTan);
|
||||
}
|
||||
for (x = 0; x < lineCount; ++x) {
|
||||
angleList.push(&angles[x]);
|
||||
}
|
||||
QSort<SimplifyAngleTest::Angle>(angleList.begin(), angleList.end() - 1);
|
||||
bool first = true;
|
||||
bool wrap = false;
|
||||
double base, last;
|
||||
for (size_t x = 0; x < lineCount; ++x) {
|
||||
const SimplifyAngleTest::Angle* angle = angleList[x];
|
||||
int span = angle->start();
|
||||
// SkDebugf("%s [%d] %1.9g (%1.9g,%1.9g %1.9g,%1.9g)\n", __FUNCTION__,
|
||||
// span, arcTans[span], lines[span][0].fX, lines[span][0].fY,
|
||||
// lines[span][1].fX, lines[span][1].fY);
|
||||
if (first) {
|
||||
base = last = arcTans[span];
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
if (last < arcTans[span]) {
|
||||
last = arcTans[span];
|
||||
continue;
|
||||
}
|
||||
if (!wrap) {
|
||||
if (base < arcTans[span]) {
|
||||
SkDebugf("%s !wrap [%d] %g\n", __FUNCTION__, span, arcTans[span]);
|
||||
SkASSERT(0);
|
||||
}
|
||||
last = arcTans[span];
|
||||
wrap = true;
|
||||
continue;
|
||||
}
|
||||
SkDebugf("%s wrap [%d] %g\n", __FUNCTION__, span, arcTans[span]);
|
||||
SkASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void testQuads(bool testFlat) {
|
||||
SkTDArray<SimplifyAngleTest::Angle> angles;
|
||||
SkTDArray<SimplifyAngleTest::Angle* > angleList;
|
||||
size_t x;
|
||||
for (x = 0; x < quadCount; ++x) {
|
||||
SimplifyAngleTest::Angle* angle = angles.append();
|
||||
if (testFlat) {
|
||||
angle->setFlat(quads[x], SkPath::kQuad_Verb, 0, x, x + 1, false);
|
||||
} else {
|
||||
angle->set(quads[x], SkPath::kQuad_Verb, 0, x, x + 1, false);
|
||||
}
|
||||
}
|
||||
for (x = 0; x < quadCount; ++x) {
|
||||
angleList.push(&angles[x]);
|
||||
}
|
||||
QSort<SimplifyAngleTest::Angle>(angleList.begin(), angleList.end() - 1);
|
||||
for (size_t x = 0; x < quadCount; ++x) {
|
||||
*angleList[x] < *angleList[x + 1];
|
||||
SkASSERT(x == quadCount - 1 || *angleList[x] < *angleList[x + 1]);
|
||||
const SimplifyAngleTest::Angle* angle = angleList[x];
|
||||
if (x != angle->start()) {
|
||||
SkDebugf("%s [%d] [%d]\n", __FUNCTION__, x, angle->start());
|
||||
SkASSERT(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testCubics(bool testFlat) {
|
||||
SkTDArray<SimplifyAngleTest::Angle> angles;
|
||||
SkTDArray<SimplifyAngleTest::Angle* > angleList;
|
||||
for (size_t x = 0; x < cubicCount; ++x) {
|
||||
SimplifyAngleTest::Angle* angle = angles.append();
|
||||
if (testFlat) {
|
||||
angle->setFlat(cubics[x], SkPath::kCubic_Verb, 0, x, x + 1, false);
|
||||
} else {
|
||||
angle->set(cubics[x], SkPath::kCubic_Verb, 0, x, x + 1, false);
|
||||
}
|
||||
angleList.push(angle);
|
||||
}
|
||||
QSort<SimplifyAngleTest::Angle>(angleList.begin(), angleList.end() - 1);
|
||||
for (size_t x = 0; x < cubicCount; ++x) {
|
||||
const SimplifyAngleTest::Angle* angle = angleList[x];
|
||||
if (x != angle->start()) {
|
||||
SkDebugf("%s [%d] [%d]\n", __FUNCTION__, x, angle->start());
|
||||
SkASSERT(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void (*tests[])(bool) = {
|
||||
testLines,
|
||||
testQuads,
|
||||
testCubics
|
||||
};
|
||||
|
||||
static const size_t testCount = sizeof(tests) / sizeof(tests[0]);
|
||||
|
||||
static void (*firstTest)(bool) = 0;
|
||||
static bool skipAll = false;
|
||||
|
||||
void SimplifyAngle_Test() {
|
||||
if (skipAll) {
|
||||
return;
|
||||
}
|
||||
size_t index = 0;
|
||||
if (firstTest) {
|
||||
while (index < testCount && tests[index] != firstTest) {
|
||||
++index;
|
||||
}
|
||||
}
|
||||
bool firstTestComplete = false;
|
||||
for ( ; index < testCount; ++index) {
|
||||
(*tests[index])(true);
|
||||
firstTestComplete = true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "Simplify.h"
|
||||
|
||||
namespace SimplifyFindNextTest {
|
||||
|
||||
#include "Simplify.cpp"
|
||||
|
||||
} // end of SimplifyFindNextTest namespace
|
||||
|
||||
#include "Intersection_Tests.h"
|
||||
|
||||
static const SimplifyFindNextTest::Segment* testCommon(
|
||||
int start, int winding, int step,
|
||||
SkTArray<SimplifyFindNextTest::Contour>& contours,
|
||||
SimplifyFindNextTest::EdgeBuilder& builder, const SkPath& path) {
|
||||
SkTDArray<SimplifyFindNextTest::Contour*> contourList;
|
||||
SimplifyFindNextTest::Contour sentinel;
|
||||
sentinel.reset();
|
||||
makeContourList(contours, sentinel, contourList);
|
||||
addIntersectTs(contourList[0], contourList[0], -1);
|
||||
if (contours.count() > 1) {
|
||||
SkASSERT(contours.count() == 2);
|
||||
addIntersectTs(contourList[0], contourList[1], -1);
|
||||
addIntersectTs(contourList[1], contourList[1], -1);
|
||||
}
|
||||
fixOtherTIndex(contourList);
|
||||
SimplifyFindNextTest::Segment& segment = contours[0].fSegments[0];
|
||||
int spanIndex;
|
||||
SimplifyFindNextTest::Segment* next = segment.findNext(start, winding,
|
||||
step, spanIndex);
|
||||
SkASSERT(spanIndex == 1);
|
||||
return next;
|
||||
}
|
||||
|
||||
static void test(const SkPath& path) {
|
||||
SkTArray<SimplifyFindNextTest::Contour> contours;
|
||||
SimplifyFindNextTest::EdgeBuilder builder(path, contours);
|
||||
int start = 0;
|
||||
int winding = 0;
|
||||
int step = 1;
|
||||
testCommon(start, winding, step, contours, builder, path);
|
||||
}
|
||||
|
||||
static void testLine1() {
|
||||
SkPath path;
|
||||
path.moveTo(2,0);
|
||||
path.lineTo(1,1);
|
||||
path.lineTo(0,0);
|
||||
path.close();
|
||||
test(path);
|
||||
}
|
||||
|
||||
static void (*tests[])() = {
|
||||
testLine1,
|
||||
};
|
||||
|
||||
static const size_t testCount = sizeof(tests) / sizeof(tests[0]);
|
||||
|
||||
static void (*firstTest)() = 0;
|
||||
static bool skipAll = false;
|
||||
|
||||
void SimplifyFindNext_Test() {
|
||||
if (skipAll) {
|
||||
return;
|
||||
}
|
||||
size_t index = 0;
|
||||
if (firstTest) {
|
||||
while (index < testCount && tests[index] != firstTest) {
|
||||
++index;
|
||||
}
|
||||
}
|
||||
bool firstTestComplete = false;
|
||||
for ( ; index < testCount; ++index) {
|
||||
(*tests[index])();
|
||||
firstTestComplete = true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "Simplify.h"
|
||||
|
||||
namespace SimplifyFindTopTest {
|
||||
|
||||
#include "Simplify.cpp"
|
||||
|
||||
} // end of SimplifyFindTopTest namespace
|
||||
|
||||
#include "Intersection_Tests.h"
|
||||
|
||||
static const SimplifyFindTopTest::Segment* testCommon(
|
||||
SkTArray<SimplifyFindTopTest::Contour>& contours,
|
||||
SimplifyFindTopTest::EdgeBuilder& builder, const SkPath& path) {
|
||||
SkTDArray<SimplifyFindTopTest::Contour*> contourList;
|
||||
SimplifyFindTopTest::Contour sentinel;
|
||||
sentinel.reset();
|
||||
makeContourList(contours, sentinel, contourList);
|
||||
addIntersectTs(contourList[0], contourList[0], -1);
|
||||
if (contours.count() > 1) {
|
||||
SkASSERT(contours.count() == 2);
|
||||
addIntersectTs(contourList[0], contourList[1], -1);
|
||||
addIntersectTs(contourList[1], contourList[1], -1);
|
||||
}
|
||||
fixOtherTIndex(contourList);
|
||||
SimplifyFindTopTest::Segment* topStart = findTopContour(contourList,
|
||||
contourList.count());
|
||||
int index, direction;
|
||||
const SimplifyFindTopTest::Segment* topSegment = topStart->findTop(index,
|
||||
direction);
|
||||
SkASSERT(direction == 1);
|
||||
return topSegment;
|
||||
}
|
||||
|
||||
static void test(const SkPath& path) {
|
||||
SkTArray<SimplifyFindTopTest::Contour> contours;
|
||||
SimplifyFindTopTest::EdgeBuilder builder(path, contours);
|
||||
testCommon(contours, builder, path);
|
||||
}
|
||||
|
||||
static void test(const SkPath& path, SkScalar x1, SkScalar y1,
|
||||
SkScalar x2, SkScalar y2) {
|
||||
SkTArray<SimplifyFindTopTest::Contour> contours;
|
||||
SimplifyFindTopTest::EdgeBuilder builder(path, contours);
|
||||
const SimplifyFindTopTest::Segment* topSegment =
|
||||
testCommon(contours, builder, path);
|
||||
const SkPoint* pts = topSegment->pts();
|
||||
SkPoint top = pts[0];
|
||||
SkPoint bottom = pts[1];
|
||||
if (top.fY > bottom.fY) {
|
||||
SkTSwap<SkPoint>(top, bottom);
|
||||
}
|
||||
SkASSERT(top.fX == x1);
|
||||
SkASSERT(top.fY == y1);
|
||||
SkASSERT(bottom.fX == x2);
|
||||
SkASSERT(bottom.fY == y2);
|
||||
}
|
||||
|
||||
static void testLine1() {
|
||||
SkPath path;
|
||||
path.moveTo(2,0);
|
||||
path.lineTo(1,1);
|
||||
path.lineTo(0,0);
|
||||
path.close();
|
||||
test(path);
|
||||
}
|
||||
|
||||
static void addInnerCWTriangle(SkPath& path) {
|
||||
path.moveTo(3,0);
|
||||
path.lineTo(4,1);
|
||||
path.lineTo(2,1);
|
||||
path.close();
|
||||
}
|
||||
|
||||
static void addInnerCCWTriangle(SkPath& path) {
|
||||
path.moveTo(3,0);
|
||||
path.lineTo(2,1);
|
||||
path.lineTo(4,1);
|
||||
path.close();
|
||||
}
|
||||
|
||||
static void addOuterCWTriangle(SkPath& path) {
|
||||
path.moveTo(3,0);
|
||||
path.lineTo(6,2);
|
||||
path.lineTo(0,2);
|
||||
path.close();
|
||||
}
|
||||
|
||||
static void addOuterCCWTriangle(SkPath& path) {
|
||||
path.moveTo(3,0);
|
||||
path.lineTo(0,2);
|
||||
path.lineTo(6,2);
|
||||
path.close();
|
||||
}
|
||||
|
||||
static void testLine2() {
|
||||
SkPath path;
|
||||
addInnerCWTriangle(path);
|
||||
addOuterCWTriangle(path);
|
||||
test(path, 3, 0, 0, 2);
|
||||
}
|
||||
|
||||
static void testLine3() {
|
||||
SkPath path;
|
||||
addOuterCWTriangle(path);
|
||||
addInnerCWTriangle(path);
|
||||
test(path, 3, 0, 0, 2);
|
||||
}
|
||||
|
||||
static void testLine4() {
|
||||
SkPath path;
|
||||
addInnerCCWTriangle(path);
|
||||
addOuterCWTriangle(path);
|
||||
test(path, 3, 0, 0, 2);
|
||||
}
|
||||
|
||||
static void testLine5() {
|
||||
SkPath path;
|
||||
addOuterCWTriangle(path);
|
||||
addInnerCCWTriangle(path);
|
||||
test(path, 3, 0, 0, 2);
|
||||
}
|
||||
|
||||
static void testLine6() {
|
||||
SkPath path;
|
||||
addInnerCWTriangle(path);
|
||||
addOuterCCWTriangle(path);
|
||||
test(path, 3, 0, 0, 2);
|
||||
}
|
||||
|
||||
static void testLine7() {
|
||||
SkPath path;
|
||||
addOuterCCWTriangle(path);
|
||||
addInnerCWTriangle(path);
|
||||
test(path, 3, 0, 0, 2);
|
||||
}
|
||||
|
||||
static void testLine8() {
|
||||
SkPath path;
|
||||
addInnerCCWTriangle(path);
|
||||
addOuterCCWTriangle(path);
|
||||
test(path, 3, 0, 0, 2);
|
||||
}
|
||||
|
||||
static void testLine9() {
|
||||
SkPath path;
|
||||
addOuterCCWTriangle(path);
|
||||
addInnerCCWTriangle(path);
|
||||
test(path, 3, 0, 0, 2);
|
||||
}
|
||||
|
||||
static void testQuads() {
|
||||
SkPath path;
|
||||
path.moveTo(2,0);
|
||||
path.quadTo(1,1, 0,0);
|
||||
path.close();
|
||||
test(path);
|
||||
}
|
||||
|
||||
static void testCubics() {
|
||||
SkPath path;
|
||||
path.moveTo(2,0);
|
||||
path.cubicTo(2,3, 1,1, 0,0);
|
||||
path.close();
|
||||
test(path);
|
||||
}
|
||||
|
||||
static void (*tests[])() = {
|
||||
testLine1,
|
||||
testLine2,
|
||||
testLine3,
|
||||
testLine4,
|
||||
testLine5,
|
||||
testLine6,
|
||||
testLine7,
|
||||
testLine8,
|
||||
testLine9,
|
||||
testQuads,
|
||||
testCubics
|
||||
};
|
||||
|
||||
static const size_t testCount = sizeof(tests) / sizeof(tests[0]);
|
||||
|
||||
static void (*firstTest)() = 0;
|
||||
static bool skipAll = false;
|
||||
|
||||
void SimplifyFindTop_Test() {
|
||||
if (skipAll) {
|
||||
return;
|
||||
}
|
||||
size_t index = 0;
|
||||
if (firstTest) {
|
||||
while (index < testCount && tests[index] != firstTest) {
|
||||
++index;
|
||||
}
|
||||
}
|
||||
bool firstTestComplete = false;
|
||||
for ( ; index < testCount; ++index) {
|
||||
(*tests[index])();
|
||||
firstTestComplete = true;
|
||||
}
|
||||
}
|
|
@ -234,24 +234,37 @@ path.close();
|
|||
|
||||
<div id="testSimplifyQuadratic17">
|
||||
SkPath path, out;
|
||||
path.moveTo(0, 0);
|
||||
path.quadTo(0, 0, 0, 0);
|
||||
path.lineTo(2, 2);
|
||||
path.moveTo(8, 8);
|
||||
path.quadTo(10, 10, 8, -10);
|
||||
path.close();
|
||||
path.moveTo(0, 1);
|
||||
path.lineTo(0, 1);
|
||||
path.quadTo(2, 1, 3, 3);
|
||||
path.moveTo(8, 8);
|
||||
path.quadTo(12, 12, 14, 4);
|
||||
path.close();
|
||||
path.moveTo(8, 8);
|
||||
path.quadTo(9, 9, 10, 8);
|
||||
path.close();
|
||||
testSimplify(path, true, out, bitmap);
|
||||
drawAsciiPaths(path, out, true);
|
||||
}
|
||||
</div>
|
||||
|
||||
<div id="testSimplifyQuadratic18">
|
||||
SkPath path, out;
|
||||
path.moveTo(8.0000000000000071, 8.0000000000000071);
|
||||
path.quadTo(8.7289570079366854, 8.7289570079366889, 9.3914917259458743, 9.0593802763083691);
|
||||
path.close();
|
||||
path.moveTo(8.0000000000000142, 8.0000000000000142);
|
||||
path.quadTo(8.1250000000000107, 8.1250000000000071, 8.2500000000000071, 8.2187500000000053);
|
||||
path.close();
|
||||
testSimplify(path, true, out, bitmap);
|
||||
drawAsciiPaths(path, out, true);
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var testDivs = [
|
||||
testSimplifyQuadratic18,
|
||||
testSimplifyQuadratic17,
|
||||
testSimplifyQuadratic16,
|
||||
testSimplifyQuadratic15,
|
||||
|
@ -332,10 +345,12 @@ function init(test) {
|
|||
for (var verbs in contour) {
|
||||
var verb = contour[verbs];
|
||||
var last = verb.length;
|
||||
xmin = Math.min(xmin, verb[0]);
|
||||
ymin = Math.min(ymin, verb[1]);
|
||||
xmax = Math.max(xmax, verb[last - 2]);
|
||||
ymax = Math.max(ymax, verb[last - 1]);
|
||||
for (var idx = 0; idx < last; idx += 2) {
|
||||
xmin = Math.min(xmin, verb[idx]);
|
||||
xmax = Math.max(xmax, verb[idx]);
|
||||
ymin = Math.min(ymin, verb[idx + 1]);
|
||||
ymax = Math.max(ymax, verb[idx + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
var subscale = 1;
|
||||
|
|
|
@ -139,3 +139,28 @@ continue tracing the touched segments with reversed outside/inside sense
|
|||
once the edges are exhausted, remaining must be disjoint contours
|
||||
send a ray from a disjoint point through all other contours
|
||||
count the crossings, determine if disjoint is inside or outside, then continue
|
||||
|
||||
===
|
||||
|
||||
On Quadratic (and Cubic) Intersections
|
||||
|
||||
Currently, if only the end points touch, QuadracticIntersections does a lot of
|
||||
work to figure that out. Can I test for that up front, then short circuit the
|
||||
recursive search for the end points?
|
||||
|
||||
Or, is there something defective in the current approach that makes the end
|
||||
point recursion go so deep? I'm seeing 56 stack frames (about 28 divides, but
|
||||
thankfully, no splits) to find one matching endpoint.
|
||||
|
||||
|
||||
Bezier curve focus may allow more quickly determining that end points with
|
||||
identical tangents are practically coicident for some range of T, but I don't
|
||||
understand the math yet to know.
|
||||
|
||||
Another approach is to determine how flat the curve is to make good guesses
|
||||
about how far to move away in T before doing the intersection for the remainder
|
||||
and/or to determine whether one curve is to the inside or outside of another.
|
||||
According to Mike/Rob, the flatness for quadratics increases by 4 for each
|
||||
subdivision, and a crude guess of the curvature can be had by comparing P1 to
|
||||
(P0+P2)/2. By looking at the ULPS of the numbers, I can guess what value of
|
||||
T may be far enough that the curves diverge but don't cross.
|
|
@ -69,14 +69,15 @@
|
|||
'../experimental/Intersection/RectUtilities.cpp',
|
||||
'../experimental/Intersection/Simplify.cpp',
|
||||
'../experimental/Intersection/SimplifyAddIntersectingTs_Test.cpp',
|
||||
'../experimental/Intersection/SimplifyAngle_Test.cpp',
|
||||
'../experimental/Intersection/SimplifyFindNext_Test.cpp',
|
||||
'../experimental/Intersection/SimplifyFindTop_Test.cpp',
|
||||
'../experimental/Intersection/TestUtilities.cpp',
|
||||
'../experimental/Intersection/CubicIntersection_TestData.h',
|
||||
'../experimental/Intersection/CubicUtilities.h',
|
||||
'../experimental/Intersection/CurveIntersection.h',
|
||||
'../experimental/Intersection/DataTypes.h',
|
||||
'../experimental/Intersection/EdgeMain.h',
|
||||
'../experimental/Intersection/EdgeWalker_Test.h',
|
||||
'../experimental/Intersection/EdgeWalkerPolygons_Mismatches.h',
|
||||
'../experimental/Intersection/Extrema.h',
|
||||
'../experimental/Intersection/Intersection_Tests.h',
|
||||
'../experimental/Intersection/Intersections.h',
|
||||
|
@ -88,6 +89,7 @@
|
|||
'../experimental/Intersection/QuadraticIntersection_TestData.h',
|
||||
'../experimental/Intersection/QuadraticUtilities.h',
|
||||
'../experimental/Intersection/ShapeOps.h',
|
||||
'../experimental/Intersection/Simplify.h',
|
||||
'../experimental/Intersection/TestUtilities.h',
|
||||
'../experimental/Intersection/TSearch.h',
|
||||
'../experimental/Intersection/thingsToDo.txt',
|
||||
|
|
Загрузка…
Ссылка в новой задаче