git-svn-id: http://skia.googlecode.com/svn/trunk@4006 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
caryclark@google.com 2012-05-18 20:50:33 +00:00
Родитель a611c3ea53
Коммит b45a1b46ee
29 изменённых файлов: 1455 добавлений и 548 удалений

Просмотреть файл

@ -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',