blob: 045b1b4d46a72ad12fe47e93cde7662c99afdc27 [file] [log] [blame]
/*
* 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 "SkPathOpsTypes.h"
#include "SkPoint.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, fY;
friend SkDPoint operator+(const SkDPoint& a, const SkDVector& b);
void operator+=(const SkDVector& v) {
fX += v.fX;
fY += v.fY;
}
void operator-=(const SkDVector& v) {
fX -= v.fX;
fY -= v.fY;
}
void operator/=(const double s) {
fX /= s;
fY /= s;
}
void operator*=(const double s) {
fX *= s;
fY *= s;
}
SkVector asSkVector() const {
SkVector v = {SkDoubleToScalar(fX), SkDoubleToScalar(fY)};
return v;
}
double cross(const SkDVector& a) const {
return fX * a.fY - fY * a.fX;
}
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;
}
};
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);
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;
}
void operator+=(const SkDVector& v) {
fX += v.fX;
fY += v.fY;
}
void operator-=(const SkDVector& v) {
fX -= v.fX;
fY -= v.fY;
}
// 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
bool approximatelyEqual(const SkDPoint& a) const {
double denom = SkTMax(fabs(fX), SkTMax(fabs(fY),
SkTMax(fabs(a.fX), fabs(a.fY))));
if (precisely_zero(denom)) {
return true;
}
double inv = 1 / denom;
return approximately_equal(fX * inv, a.fX * inv)
&& approximately_equal(fY * inv, a.fY * inv);
}
bool approximatelyEqual(const SkPoint& a) const {
return AlmostEqualUlps(SkDoubleToScalar(fX), a.fX)
&& AlmostEqualUlps(SkDoubleToScalar(fY), a.fY);
}
bool approximatelyEqualHalf(const SkDPoint& a) const {
double denom = SkTMax(fabs(fX), SkTMax(fabs(fY),
SkTMax(fabs(a.fX), fabs(a.fY))));
if (denom == 0) {
return true;
}
double inv = 1 / denom;
return approximately_equal_half(fX * inv, a.fX * inv)
&& approximately_equal_half(fY * inv, a.fY * inv);
}
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;
}
double moreRoughlyEqual(const SkDPoint& a) const {
return more_roughly_equal(a.fY, fY) && more_roughly_equal(a.fX, fX);
}
double roughlyEqual(const SkDPoint& a) const {
return roughly_equal(a.fY, fY) && roughly_equal(a.fX, fX);
}
};
#endif