123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- /*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #ifndef SkPathOpsPoint_DEFINED
- #define SkPathOpsPoint_DEFINED
- #include "include/core/SkPoint.h"
- #include "src/pathops/SkPathOpsTypes.h"
- inline bool AlmostEqualUlps(const SkPoint& pt1, const SkPoint& pt2) {
- return AlmostEqualUlps(pt1.fX, pt2.fX) && AlmostEqualUlps(pt1.fY, pt2.fY);
- }
- struct SkDVector {
- double fX;
- double fY;
- SkDVector& set(const SkVector& pt) {
- fX = pt.fX;
- fY = pt.fY;
- return *this;
- }
- // only used by testing
- void operator+=(const SkDVector& v) {
- fX += v.fX;
- fY += v.fY;
- }
- // only called by nearestT, which is currently only used by testing
- void operator-=(const SkDVector& v) {
- fX -= v.fX;
- fY -= v.fY;
- }
- // only used by testing
- void operator/=(const double s) {
- fX /= s;
- fY /= s;
- }
- // only used by testing
- void operator*=(const double s) {
- fX *= s;
- fY *= s;
- }
- SkVector asSkVector() const {
- SkVector v = {SkDoubleToScalar(fX), SkDoubleToScalar(fY)};
- return v;
- }
- // only used by testing
- double cross(const SkDVector& a) const {
- return fX * a.fY - fY * a.fX;
- }
- // similar to cross, this bastardization considers nearly coincident to be zero
- // uses ulps epsilon == 16
- double crossCheck(const SkDVector& a) const {
- double xy = fX * a.fY;
- double yx = fY * a.fX;
- return AlmostEqualUlps(xy, yx) ? 0 : xy - yx;
- }
- // allow tinier numbers
- double crossNoNormalCheck(const SkDVector& a) const {
- double xy = fX * a.fY;
- double yx = fY * a.fX;
- return AlmostEqualUlpsNoNormalCheck(xy, yx) ? 0 : xy - yx;
- }
- double dot(const SkDVector& a) const {
- return fX * a.fX + fY * a.fY;
- }
- double length() const {
- return sqrt(lengthSquared());
- }
- double lengthSquared() const {
- return fX * fX + fY * fY;
- }
- SkDVector& normalize() {
- double inverseLength = sk_ieee_double_divide(1, this->length());
- fX *= inverseLength;
- fY *= inverseLength;
- return *this;
- }
- bool isFinite() const {
- return std::isfinite(fX) && std::isfinite(fY);
- }
- };
- struct SkDPoint {
- double fX;
- double fY;
- void set(const SkPoint& pt) {
- fX = pt.fX;
- fY = pt.fY;
- }
- friend SkDVector operator-(const SkDPoint& a, const SkDPoint& b) {
- return { a.fX - b.fX, a.fY - b.fY };
- }
- friend bool operator==(const SkDPoint& a, const SkDPoint& b) {
- return a.fX == b.fX && a.fY == b.fY;
- }
- friend bool operator!=(const SkDPoint& a, const SkDPoint& b) {
- return a.fX != b.fX || a.fY != b.fY;
- }
- void operator=(const SkPoint& pt) {
- fX = pt.fX;
- fY = pt.fY;
- }
- // only used by testing
- void operator+=(const SkDVector& v) {
- fX += v.fX;
- fY += v.fY;
- }
- // only used by testing
- void operator-=(const SkDVector& v) {
- fX -= v.fX;
- fY -= v.fY;
- }
- // only used by testing
- SkDPoint operator+(const SkDVector& v) {
- SkDPoint result = *this;
- result += v;
- return result;
- }
- // only used by testing
- SkDPoint operator-(const SkDVector& v) {
- SkDPoint result = *this;
- result -= v;
- return result;
- }
- // note: this can not be implemented with
- // return approximately_equal(a.fY, fY) && approximately_equal(a.fX, fX);
- // because that will not take the magnitude of the values into account
- bool approximatelyDEqual(const SkDPoint& a) const {
- if (approximately_equal(fX, a.fX) && approximately_equal(fY, a.fY)) {
- return true;
- }
- if (!RoughlyEqualUlps(fX, a.fX) || !RoughlyEqualUlps(fY, a.fY)) {
- return false;
- }
- double dist = distance(a); // OPTIMIZATION: can we compare against distSq instead ?
- double tiniest = SkTMin(SkTMin(SkTMin(fX, a.fX), fY), a.fY);
- double largest = SkTMax(SkTMax(SkTMax(fX, a.fX), fY), a.fY);
- largest = SkTMax(largest, -tiniest);
- return AlmostDequalUlps(largest, largest + dist); // is the dist within ULPS tolerance?
- }
- bool approximatelyDEqual(const SkPoint& a) const {
- SkDPoint dA;
- dA.set(a);
- return approximatelyDEqual(dA);
- }
- bool approximatelyEqual(const SkDPoint& a) const {
- if (approximately_equal(fX, a.fX) && approximately_equal(fY, a.fY)) {
- return true;
- }
- if (!RoughlyEqualUlps(fX, a.fX) || !RoughlyEqualUlps(fY, a.fY)) {
- return false;
- }
- double dist = distance(a); // OPTIMIZATION: can we compare against distSq instead ?
- double tiniest = SkTMin(SkTMin(SkTMin(fX, a.fX), fY), a.fY);
- double largest = SkTMax(SkTMax(SkTMax(fX, a.fX), fY), a.fY);
- largest = SkTMax(largest, -tiniest);
- return AlmostPequalUlps(largest, largest + dist); // is the dist within ULPS tolerance?
- }
- bool approximatelyEqual(const SkPoint& a) const {
- SkDPoint dA;
- dA.set(a);
- return approximatelyEqual(dA);
- }
- static bool ApproximatelyEqual(const SkPoint& a, const SkPoint& b) {
- if (approximately_equal(a.fX, b.fX) && approximately_equal(a.fY, b.fY)) {
- return true;
- }
- if (!RoughlyEqualUlps(a.fX, b.fX) || !RoughlyEqualUlps(a.fY, b.fY)) {
- return false;
- }
- SkDPoint dA, dB;
- dA.set(a);
- dB.set(b);
- double dist = dA.distance(dB); // OPTIMIZATION: can we compare against distSq instead ?
- float tiniest = SkTMin(SkTMin(SkTMin(a.fX, b.fX), a.fY), b.fY);
- float largest = SkTMax(SkTMax(SkTMax(a.fX, b.fX), a.fY), b.fY);
- largest = SkTMax(largest, -tiniest);
- return AlmostDequalUlps((double) largest, largest + dist); // is dist within ULPS tolerance?
- }
- // only used by testing
- bool approximatelyZero() const {
- return approximately_zero(fX) && approximately_zero(fY);
- }
- SkPoint asSkPoint() const {
- SkPoint pt = {SkDoubleToScalar(fX), SkDoubleToScalar(fY)};
- return pt;
- }
- double distance(const SkDPoint& a) const {
- SkDVector temp = *this - a;
- return temp.length();
- }
- double distanceSquared(const SkDPoint& a) const {
- SkDVector temp = *this - a;
- return temp.lengthSquared();
- }
- static SkDPoint Mid(const SkDPoint& a, const SkDPoint& b) {
- SkDPoint result;
- result.fX = (a.fX + b.fX) / 2;
- result.fY = (a.fY + b.fY) / 2;
- return result;
- }
- bool roughlyEqual(const SkDPoint& a) const {
- if (roughly_equal(fX, a.fX) && roughly_equal(fY, a.fY)) {
- return true;
- }
- double dist = distance(a); // OPTIMIZATION: can we compare against distSq instead ?
- double tiniest = SkTMin(SkTMin(SkTMin(fX, a.fX), fY), a.fY);
- double largest = SkTMax(SkTMax(SkTMax(fX, a.fX), fY), a.fY);
- largest = SkTMax(largest, -tiniest);
- return RoughlyEqualUlps(largest, largest + dist); // is the dist within ULPS tolerance?
- }
- static bool RoughlyEqual(const SkPoint& a, const SkPoint& b) {
- if (!RoughlyEqualUlps(a.fX, b.fX) && !RoughlyEqualUlps(a.fY, b.fY)) {
- return false;
- }
- SkDPoint dA, dB;
- dA.set(a);
- dB.set(b);
- double dist = dA.distance(dB); // OPTIMIZATION: can we compare against distSq instead ?
- float tiniest = SkTMin(SkTMin(SkTMin(a.fX, b.fX), a.fY), b.fY);
- float largest = SkTMax(SkTMax(SkTMax(a.fX, b.fX), a.fY), b.fY);
- largest = SkTMax(largest, -tiniest);
- return RoughlyEqualUlps((double) largest, largest + dist); // is dist within ULPS tolerance?
- }
- // very light weight check, should only be used for inequality check
- static bool WayRoughlyEqual(const SkPoint& a, const SkPoint& b) {
- float largestNumber = SkTMax(SkTAbs(a.fX), SkTMax(SkTAbs(a.fY),
- SkTMax(SkTAbs(b.fX), SkTAbs(b.fY))));
- SkVector diffs = a - b;
- float largestDiff = SkTMax(diffs.fX, diffs.fY);
- return roughly_zero_when_compared_to(largestDiff, largestNumber);
- }
- // utilities callable by the user from the debugger when the implementation code is linked in
- void dump() const;
- static void Dump(const SkPoint& pt);
- static void DumpHex(const SkPoint& pt);
- };
- #endif
|