#Topic Point
#Alias Points
#Alias Point_Reference

#Subtopic Overview
    #Subtopic Subtopics
    #Populate
    ##
##

#Struct SkPoint

#Subtopic Constructors
#Populate
##

#Subtopic Operators
#Populate
##

#Subtopic Member_Functions
#Populate
##

#Subtopic Members
#Populate

#Member SkScalar  fX
#Line # x-axis value ##
x-axis value used by both Point and Vector. May contain any value, including
infinities and NaN.
##

#Member SkScalar  fY
#Line # y-axis value ##
y-axis value used by both Point and Vector. May contain any value, including
infinities and NaN.
##

#Subtopic Members ##

# ------------------------------------------------------------------------------

#Method static constexpr SkPoint Make(SkScalar x, SkScalar y)

#Line # constructs from SkScalar inputs ##
Sets fX to x, fY to y. Used both to set Point and Vector.

#Param x  SkScalar x-axis value of constructed Point or Vector ##
#Param y  SkScalar y-axis value of constructed Point or Vector ##

#Return Point (x, y) ##

#Example
SkPoint pt1 = {45, 66};
SkPoint pt2 = SkPoint::Make(45, 66);
SkVector v1 = {45, 66};
SkVector v2 = SkPoint::Make(45, 66);
SkDebugf("all %s" "equal\n", pt1 == pt2 && pt2 == v1 && v1 == v2 ? "" : "not ");
#StdOut
all equal
##
##

#SeeAlso set() iset() SkIPoint::Make

#Method ##

# ------------------------------------------------------------------------------

#Method SkScalar x() const

#Line # returns fX ##
Returns x-axis value of Point or Vector.

#Return fX ##

#Example
SkPoint pt1 = {45, 66};
SkDebugf("pt1.fX %c= pt1.x()\n", pt1.fX == pt1.x() ? '=' : '!');
#StdOut
pt1.fX == pt1.x()
##
##

#SeeAlso y() SkIPoint::x()

#Method ##

# ------------------------------------------------------------------------------

#Method SkScalar y() const

#Line # returns fY ##
Returns y-axis value of Point or Vector.

#Return fY ##

#Example
SkPoint pt1 = {45, 66};
SkDebugf("pt1.fY %c= pt1.y()\n", pt1.fY == pt1.y() ? '=' : '!');
#StdOut
pt1.fY == pt1.y()
##
##

#SeeAlso x() SkIPoint::y()

#Method ##

# ------------------------------------------------------------------------------

#Method bool isZero() const

#Line # returns true if both members equal zero ##
Returns true if fX and fY are both zero.

#Return true if fX is zero and fY is zero ##

#Example
SkPoint pt = { 0.f, -0.f};
SkDebugf("pt.fX=%c%g pt.fY=%c%g\n", std::signbit(pt.fX) ? '-' : '+', fabsf(pt.fX),
                                    std::signbit(pt.fY) ? '-' : '+', fabsf(pt.fY));
SkDebugf("pt.isZero() == %s\n", pt.isZero() ? "true" : "false");
#StdOut
pt.fX=+0 pt.fY=-0
pt.isZero() == true
##
##

#SeeAlso isFinite SkIPoint::isZero

#Method ##

# ------------------------------------------------------------------------------

#Method void set(SkScalar x, SkScalar y)

#Line # sets to SkScalar input ##
Sets fX to x and fY to y.

#Param x  new value for fX ##
#Param y  new value for fY ##

#Example
SkPoint pt1, pt2 = { SK_ScalarPI, SK_ScalarSqrt2 };
pt1.set(SK_ScalarPI, SK_ScalarSqrt2);
SkDebugf("pt1 %c= pt2\n", pt1 == pt2 ? '=' : '!');
#StdOut
pt1 == pt2
##
##

#SeeAlso iset() Make

#Method ##

# ------------------------------------------------------------------------------

#Method void iset(int32_t x, int32_t y)

#Line # sets to integer input ##
Sets fX to x and fY to y, promoting integers to SkScalar values.

Assigning a large integer value directly to fX or fY may cause a compiler 
error, triggered by narrowing conversion of int to SkScalar. This safely
casts x and y to avoid the error. 

#Param x  new value for fX ##
#Param y  new value for fY ##

#Example
SkPoint pt1, pt2 = { SK_MinS16, SK_MaxS16 };
pt1.iset(SK_MinS16, SK_MaxS16);
SkDebugf("pt1 %c= pt2\n", pt1 == pt2 ? '=' : '!');
##

#SeeAlso set Make SkIPoint::set

#Method ##

# ------------------------------------------------------------------------------

#Method void iset(const SkIPoint& p)

Sets fX to p.fX and fY to p.fY, promoting integers to SkScalar values.

Assigning an IPoint containing a large integer value directly to fX or fY may
cause a compiler error, triggered by narrowing conversion of int to SkScalar.
This safely casts p.fX and p.fY to avoid the error. 

#Param p  IPoint members promoted to SkScalar ##

#Example
SkIPoint iPt = { SK_MinS32, SK_MaxS32 };
SkPoint fPt;
fPt.iset(iPt);
SkDebugf("iPt: %d, %d\n", iPt.fX, iPt.fY);
SkDebugf("fPt: %g, %g\n", fPt.fX, fPt.fY);
#StdOut
iPt: -2147483647, 2147483647
fPt: -2.14748e+09, 2.14748e+09
##
##

#SeeAlso set Make SkIPoint::set

#Method ##

# ------------------------------------------------------------------------------

#Method void setAbs(const SkPoint& pt)

#Line # sets sign of both members to positive ##
Sets fX to absolute value of pt.fX; and fY to absolute value of pt.fY.

#Param pt  members providing magnitude for fX and fY ##

#Example
SkPoint test[] = { {0.f, -0.f}, {-1, -2},
                   { SK_ScalarInfinity, SK_ScalarNegativeInfinity },
                   { SK_ScalarNaN, -SK_ScalarNaN } };
for (const SkPoint& pt : test) {
    SkPoint absPt;
    absPt.setAbs(pt);
    SkDebugf("pt: %g, %g  abs: %g, %g\n", pt.fX, pt.fY, absPt.fX, absPt.fY);
}
#StdOut
pt: 0, -0  abs: 0, 0
pt: -1, -2  abs: 1, 2
pt: inf, -inf  abs: inf, inf
pt: nan, -nan  abs: nan, nan
##
##

#SeeAlso set Make negate 

#Method ##

# ------------------------------------------------------------------------------

#Method static void Offset(SkPoint points[], int count, const SkVector& offset)

#Line # translates Point array ##
Adds offset to each Point in points array with count entries.

#Param points  Point array ##
#Param count  entries in array ##
#Param offset  Vector added to points ##

#Example
    SkPaint paint;
    paint.setAntiAlias(true);
    SkPoint points[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
                         { 6, 4 }, { 7, 5 }, { 5, 7 },
                         { 4, 6 }, { 3, 7 }, { 1, 5 },
                         { 2, 4 }, { 1, 3 }, { 3, 1 } };
    canvas->scale(30, 15);
    paint.setStyle(SkPaint::kStroke_Style);
    canvas->drawPoints(SkCanvas::kPolygon_PointMode, SK_ARRAY_COUNT(points), points, paint);
    SkPoint::Offset(points, SK_ARRAY_COUNT(points), { 1, 9 } );
    canvas->drawPoints(SkCanvas::kPolygon_PointMode, SK_ARRAY_COUNT(points), points, paint);
##

#SeeAlso offset operator+=(const SkVector& v)

#Method ##

# ------------------------------------------------------------------------------

#Method static void Offset(SkPoint points[], int count, SkScalar dx, SkScalar dy)

Adds offset (dx, dy) to each Point in points array of length count.

#Param points  Point array ##
#Param count  entries in array ##
#Param dx  added to fX in points ##
#Param dy  added to fY in points ##

#Example
    SkPaint paint;
    paint.setAntiAlias(true);
    SkPoint points[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
                         { 6, 4 }, { 7, 5 }, { 5, 7 },
                         { 4, 6 }, { 3, 7 }, { 1, 5 },
                         { 2, 4 }, { 1, 3 }, { 3, 1 } };
    canvas->scale(30, 15);
    paint.setStyle(SkPaint::kStroke_Style);
    canvas->drawPoints(SkCanvas::kPolygon_PointMode, SK_ARRAY_COUNT(points), points, paint);
    SkPoint::Offset(points, SK_ARRAY_COUNT(points), 1, 9);
    canvas->drawPoints(SkCanvas::kPolygon_PointMode, SK_ARRAY_COUNT(points), points, paint);
##

#SeeAlso offset operator+=(const SkVector& v)

#Method ##

# ------------------------------------------------------------------------------

#Method void offset(SkScalar dx, SkScalar dy)

#Line # translates Point ##
Adds offset (dx, dy) to Point.

#Param dx  added to fX ##
#Param dy  added to fY ##

#Example
#Height 128
    SkPaint paint;
    paint.setAntiAlias(true);
    SkPoint points[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
                         { 6, 4 }, { 7, 5 }, { 5, 7 },
                         { 4, 6 }, { 3, 7 }, { 1, 5 },
                         { 2, 4 }, { 1, 3 }, { 3, 1 } };
    canvas->scale(30, 15);
    paint.setStyle(SkPaint::kStroke_Style);
    canvas->drawPoints(SkCanvas::kPolygon_PointMode, SK_ARRAY_COUNT(points), points, paint);
    points[1].offset(1, 1);
    paint.setColor(SK_ColorRED);
    canvas->drawPoints(SkCanvas::kPolygon_PointMode, SK_ARRAY_COUNT(points), points, paint);
##

#SeeAlso Offset operator+=(const SkVector& v)

#Method ##

# ------------------------------------------------------------------------------

#Method SkScalar length() const

#Line # returns straight-line distance to origin ##
Returns the Euclidean_Distance from origin, computed as:
#Code
#Literal
sqrt(fX * fX + fY * fY)
##
.

#Return straight-line distance to origin ##

#Example
#Height 192
    SkPaint paint;
    paint.setAntiAlias(true);
    const SkPoint points[] = { { 90, 30 }, { 120, 150 }, { 150, 30 }, { 210, 90 } };
    const SkPoint origin = {30, 140};
    for (auto point : points) {
        canvas->drawLine(origin, point, paint);
        SkAutoCanvasRestore acr(canvas, true);
        SkScalar angle = SkScalarATan2((point.fY - origin.fY), point.fX - origin.fX);
        canvas->rotate(angle * 180 / SK_ScalarPI, origin.fX, origin.fY);
        SkString length("length = ");
        length.appendScalar(point.length());
        canvas->drawString(length, origin.fX + 25, origin.fY - 4, paint);
    }
##

#SeeAlso distanceToOrigin Length setLength Distance

#Method ##

# ------------------------------------------------------------------------------

#Method SkScalar distanceToOrigin() const

#Line # returns straight-line distance to origin ##
Returns the Euclidean_Distance from origin, computed as:
#Code
#Literal
sqrt(fX * fX + fY * fY)
##
.

#Return straight-line distance to origin ##

#Example
#Height 192
    SkPaint paint;
    paint.setAntiAlias(true);
    const SkPoint points[] = { { 60, -110 }, { 90, 10 }, { 120, -110 }, { 180, -50 } };
    const SkPoint origin = {0, 0};
    canvas->translate(30, 140);
    for (auto point : points) {
        canvas->drawLine(origin, point, paint);
        SkAutoCanvasRestore acr(canvas, true);
        SkScalar angle = SkScalarATan2((point.fY - origin.fY), point.fX - origin.fX);
        canvas->rotate(angle * 180 / SK_ScalarPI, origin.fX, origin.fY);
        SkString distance("distance = ");
        distance.appendScalar(point.distanceToOrigin());
        canvas->drawString(distance, origin.fX + 25, origin.fY - 4, paint);
    }
##

#SeeAlso length Length setLength Distance

#Method ##

# ------------------------------------------------------------------------------

#Method bool normalize()

#Line # sets length to one, preserving direction ##
Scales (fX, fY) so that length() returns one, while preserving ratio of fX to fY,
if possible. If prior length is nearly zero, sets Vector to (0, 0) and returns
false; otherwise returns true.

#Return true if former length is not zero or nearly zero ##

#Example
    SkPaint paint;
    paint.setAntiAlias(true);
    const SkPoint lines[][2] = { {{  30, 110 }, { 190,  30 }},
                                 {{ 120, 140 }, {  30, 220 }}};
    for (auto line : lines) {
        canvas->drawLine(line[0], line[1], paint);
        SkVector vector = line[1] - line[0];
        if (vector.normalize()) {
            SkVector rotate90 = { -vector.fY, vector.fX };
            rotate90 *= 10.f;
            canvas->drawLine(line[0] - rotate90, line[0] + rotate90, paint);
            canvas->drawLine(line[1] - rotate90, line[1] + rotate90, paint);
        }
    }
##

#SeeAlso Normalize setLength length Length

#Method ##

# ------------------------------------------------------------------------------

#Method bool setNormalize(SkScalar x, SkScalar y)

#Line # sets length to one, in direction of (x, y) ##
Sets Vector to (x, y) scaled so length() returns one, and so that
(fX, fY) is proportional to (x, y).  If (x, y) length is nearly zero,
sets Vector to (0, 0) and returns false; otherwise returns true.

#Param x  proportional value for fX ##
#Param y  proportional value for fY ##

#Return true if (x, y) length is not zero or nearly zero ##

#Example
    SkPaint paint;
    paint.setAntiAlias(true);
    const SkPoint points[] = { { 60, -110 }, { 90, 10 }, { 120, -110 }, { 180, -50 } };
    const SkPoint origin = {0, 0};
    canvas->translate(30, 140);
    for (auto point : points) {
        paint.setStrokeWidth(1);
        paint.setColor(SK_ColorBLACK);
        canvas->drawLine(origin, point, paint);
        SkVector normal;
        normal.setNormalize(point.fX, point.fY);
        normal *= 100;
        paint.setStrokeWidth(10);
        paint.setColor(0x3f4512bf);
        canvas->drawLine(origin, normal, paint);
    }
##

#SeeAlso normalize setLength

#Method ##

# ------------------------------------------------------------------------------

#Method bool setLength(SkScalar length)

#Line # sets straight-line distance to origin ##
Scales Vector so that distanceToOrigin returns length, if possible. If former
length is nearly zero, sets Vector to (0, 0) and return false; otherwise returns
true.

#Param length  straight-line distance to origin ##

#Return true if former length is not zero or nearly zero  ##

#Example
#Height 160
    SkPaint paint;
    paint.setAntiAlias(true);
    const SkPoint points[] = { { 60, -110 }, { 90, 10 }, { 120, -110 }, { 180, -50 } };
    const SkPoint origin = {0, 0};
    canvas->translate(30, 140);
    for (auto point : points) {
        paint.setStrokeWidth(1);
        paint.setColor(SK_ColorBLACK);
        canvas->drawLine(origin, point, paint);
        SkVector normal = point;
        normal.setLength(100);
        paint.setStrokeWidth(10);
        paint.setColor(0x3f45bf12);
        canvas->drawLine(origin, normal, paint);
    }
##

#SeeAlso length Length setNormalize setAbs

#Method ##

# ------------------------------------------------------------------------------

#Method bool setLength(SkScalar x, SkScalar y, SkScalar length)

Sets Vector to (x, y) scaled to length, if possible. If former
length is nearly zero, sets Vector to (0, 0) and return false; otherwise returns
true.

#Param x  proportional value for fX ##
#Param y  proportional value for fY ##
#Param length  straight-line distance to origin ##

#Return true if (x, y) length is not zero or nearly zero ##

#Example
#Height 160
    SkPaint paint;
    paint.setAntiAlias(true);
    const SkPoint points[] = { { 60, -110 }, { 90, 10 }, { 120, -110 }, { 180, -50 } };
    const SkPoint origin = {0, 0};
    canvas->translate(30, 140);
    for (auto point : points) {
        paint.setStrokeWidth(1);
        paint.setColor(SK_ColorBLACK);
        canvas->drawLine(origin, point, paint);
        SkVector normal;
        normal.setLength(point.fX, point.fY, 100);
        paint.setStrokeWidth(10);
        paint.setColor(0x3fbf4512);
        canvas->drawLine(origin, normal, paint);
    }
##

#SeeAlso length Length setNormalize setAbs

#Method ##

# ------------------------------------------------------------------------------

#Method void scale(SkScalar scale, SkPoint* dst) const

#Line # multiplies Point by scale factor ##
Sets dst to Point times scale. dst may be Point to modify Point in place.

#Param scale  factor to multiply Point by ##
#Param dst  storage for scaled Point ##

#Example
    SkPaint paint;
    paint.setAntiAlias(true);
    SkPoint point = {40, -15}, scaled;
    SkPoint origin = {30, 110};
    for (auto scale : {1, 2, 3, 5}) {
        paint.setStrokeWidth(scale * 5);
        paint.setARGB(0x7f, 0x9f, 0xbf, 0x33 * scale);
        point.scale(scale, &scaled);
        canvas->drawLine(origin, origin + scaled, paint);
    }
##

#SeeAlso operator*(SkScalar scale)_const operator*=(SkScalar scale) setLength

#Method ##

# ------------------------------------------------------------------------------

#Method void scale(SkScalar value)

Scales Point in place by scale.

#Param value  factor to multiply Point by ##

#Example
    SkPaint paint;
    paint.setAntiAlias(true);
    SkPoint point = {40, -15};
    SkPoint origin = {30, 110};
    for (auto scale : {1, 2, 3, 5}) {
        paint.setStrokeWidth(scale * 5);
        paint.setARGB(0x7f, 0x9f, 0xbf, 0x33 * scale);
        point.scale(scale);
        canvas->drawLine(origin, origin + point, paint);
    }
##

#SeeAlso operator*(SkScalar scale)_const operator*=(SkScalar scale) setLength

#Method ##

# ------------------------------------------------------------------------------

#Method void negate()

#Line # reverses the sign of both members ##
Changes the sign of fX and fY.

#Example
SkPoint test[] = { {0.f, -0.f}, {-1, -2},
                   { SK_ScalarInfinity, SK_ScalarNegativeInfinity },
                   { SK_ScalarNaN, -SK_ScalarNaN } };
for (const SkPoint& pt : test) {
    SkPoint negPt = pt;
    negPt.negate();
    SkDebugf("pt: %g, %g  negate: %g, %g\n", pt.fX, pt.fY, negPt.fX, negPt.fY);
}
#StdOut
pt: 0, -0  negate: -0, 0
pt: -1, -2  negate: 1, 2
pt: inf, -inf  negate: -inf, inf
pt: nan, -nan  negate: -nan, nan
##
##

#SeeAlso operator-()_const setAbs

#Method ##

# ------------------------------------------------------------------------------

#Method SkPoint operator-()_const

#Line # reverses sign of Point ##
Returns Point changing the signs of fX and fY.

#Return Point as (-fX, -fY) ##

#Example
SkPoint test[] = { {0.f, -0.f}, {-1, -2},
                   { SK_ScalarInfinity, SK_ScalarNegativeInfinity },
                   { SK_ScalarNaN, -SK_ScalarNaN } };
for (const SkPoint& pt : test) {
    SkPoint negPt = -pt;
    SkDebugf("pt: %g, %g  negate: %g, %g\n", pt.fX, pt.fY, negPt.fX, negPt.fY);
}
#StdOut
pt: 0, -0  negate: -0, 0
pt: -1, -2  negate: 1, 2
pt: inf, -inf  negate: -inf, inf
pt: nan, -nan  negate: -nan, nan
##
##

#SeeAlso negate operator-(const SkPoint& a, const SkPoint& b) operator-=(const SkVector& v) SkIPoint::operator-()_const

#Method ##

# ------------------------------------------------------------------------------

#Method void operator+=(const SkVector& v)

#Line # adds Vector to Point ##
Adds Vector v to Point. Sets Point to:
#Formula
(fX + v.fX, fY + v.fY)
##
.

#Param v  Vector to add ##

#Example
#Height 128
    SkPaint paint;
    paint.setAntiAlias(true);
    SkPoint points[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
                         { 6, 4 }, { 7, 5 }, { 5, 7 },
                         { 4, 6 }, { 3, 7 }, { 1, 5 },
                         { 2, 4 }, { 1, 3 }, { 3, 1 } };
    canvas->scale(30, 15);
    paint.setStyle(SkPaint::kStroke_Style);
    canvas->drawPoints(SkCanvas::kPolygon_PointMode, SK_ARRAY_COUNT(points), points, paint);
    points[1] += {1, 1};
    points[2] += {-1, -1};
    paint.setColor(SK_ColorRED);
    canvas->drawPoints(SkCanvas::kPolygon_PointMode, SK_ARRAY_COUNT(points), points, paint);
##

#SeeAlso offset() operator+(const SkPoint& a, const SkVector& b) SkIPoint::operator+=(const SkIVector& v)

#Method ##

# ------------------------------------------------------------------------------

#Method void operator-=(const SkVector& v)

#Line # subtracts Vector from Point ##
Subtracts Vector v from Point. Sets Point to:
#Formula
(fX - v.fX, fY - v.fY)
##
.

#Param v  Vector to subtract ##

#Example
#Height 128
    SkPaint paint;
    paint.setAntiAlias(true);
    SkPoint points[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
                         { 6, 4 }, { 7, 5 }, { 5, 7 },
                         { 4, 6 }, { 3, 7 }, { 1, 5 },
                         { 2, 4 }, { 1, 3 }, { 3, 1 } };
    canvas->scale(30, 15);
    paint.setStyle(SkPaint::kStroke_Style);
    canvas->drawPoints(SkCanvas::kPolygon_PointMode, SK_ARRAY_COUNT(points), points, paint);
    points[1] -= {1, 1};
    points[2] -= {-1, -1};
    paint.setColor(SK_ColorRED);
    canvas->drawPoints(SkCanvas::kPolygon_PointMode, SK_ARRAY_COUNT(points), points, paint);
##

#SeeAlso offset() operator-(const SkPoint& a, const SkPoint& b) SkIPoint::operator-=(const SkIVector& v)

#Method ##

# ------------------------------------------------------------------------------

#Method SkPoint operator*(SkScalar scale)_const

#Line # returns Point multiplied by scale ##
Returns Point multiplied by scale.

#Param scale  Scalar to multiply by ##

#Return Point as (fX * scale, fY * scale) ##

#Example
#Height 128
    SkPaint paint;
    paint.setAntiAlias(true);
    SkPoint points[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
                         { 6, 4 }, { 7, 5 }, { 5, 7 },
                         { 4, 6 }, { 3, 7 }, { 1, 5 },
                         { 2, 4 }, { 1, 3 }, { 3, 1 } };
    canvas->scale(15, 10);
    paint.setStyle(SkPaint::kStroke_Style);
    canvas->drawPoints(SkCanvas::kPolygon_PointMode, SK_ARRAY_COUNT(points), points, paint);
    for (auto& point : points) {
        point = point * 1.5f;
    }
    paint.setColor(SK_ColorRED);
    canvas->drawPoints(SkCanvas::kPolygon_PointMode, SK_ARRAY_COUNT(points), points, paint);
##

#SeeAlso operator*=(SkScalar scale) scale() setLength setNormalize

#Method ##

# ------------------------------------------------------------------------------

#Method SkPoint& operator*=(SkScalar scale)

#Line # multiplies Point by scale factor ##
Multiplies Point by scale. Sets Point to:
#Formula
(fX * scale, fY * scale)
##

#Param scale  Scalar to multiply by ##

#Return reference to Point ##

#Example
#Height 128
    SkPaint paint;
    paint.setAntiAlias(true);
    SkPoint points[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
                         { 6, 4 }, { 7, 5 }, { 5, 7 },
                         { 4, 6 }, { 3, 7 }, { 1, 5 },
                         { 2, 4 }, { 1, 3 }, { 3, 1 } };
    canvas->scale(15, 10);
    paint.setStyle(SkPaint::kStroke_Style);
    canvas->drawPoints(SkCanvas::kPolygon_PointMode, SK_ARRAY_COUNT(points), points, paint);
    for (auto& point : points) {
        point *= 2;
    }
    paint.setColor(SK_ColorRED);
    canvas->drawPoints(SkCanvas::kPolygon_PointMode, SK_ARRAY_COUNT(points), points, paint);
##

#SeeAlso operator*(SkScalar scale)_const scale() setLength setNormalize

#Method ##

# ------------------------------------------------------------------------------

#Method bool isFinite() const

#Line # returns true if no member is infinite or NaN ##
Returns true if both fX and fY are measurable values.

#Return true for values other than infinities and NaN ##

#Example
SkPoint test[] = { {0, -0.f}, {-1, -2}, {SK_ScalarInfinity, 1}, {SK_ScalarNaN, -1} };
for (const SkPoint& pt : test) {
    SkDebugf("pt: %g, %g  finite: %s\n", pt.fX, pt.fY, pt.isFinite() ? "true" : "false");
}
#StdOut
pt: 0, -0  finite: true
pt: -1, -2  finite: true
pt: inf, 1  finite: false
pt: nan, -1  finite: false
##
##

#SeeAlso SkRect::isFinite SkPath::isFinite

#Method ##

# ------------------------------------------------------------------------------

#Method bool equals(SkScalar x, SkScalar y) const

#Line # returns true if Points are equal ##
Returns true if Point is equivalent to Point constructed from (x, y).

#Param x  value compared with fX ##
#Param y  value compared with fY ##

#Return true if Point equals (x, y) ##

#Example
SkPoint test[] = { {0, -0.f}, {-1, -2}, {SK_ScalarInfinity, 1}, {SK_ScalarNaN, -1} };
for (const SkPoint& pt : test) {
    SkDebugf("pt: %g, %g  %c= pt\n", pt.fX, pt.fY, pt.equals(pt.fX, pt.fY) ? '=' : '!');
}
#StdOut
pt: 0, -0  == pt
pt: -1, -2  == pt
pt: inf, 1  == pt
pt: nan, -1  != pt
##
##

#SeeAlso operator==(const SkPoint& a, const SkPoint& b)

#Method ##

# ------------------------------------------------------------------------------

#Method bool operator==(const SkPoint& a, const SkPoint& b)

#Line # returns true if Point are equal ##
Returns true if a is equivalent to b.

#Param a  Point to compare ##
#Param b  Point to compare ##

#Return true if a.fX == b.fX and a.fY == b.fY ##

#Example
SkPoint test[] = { {0, -0.f}, {-1, -2}, {SK_ScalarInfinity, 1}, {SK_ScalarNaN, -1} };
for (const SkPoint& pt : test) {
    SkDebugf("pt: %g, %g  %c= pt\n", pt.fX, pt.fY, pt == pt ? '=' : '!');
}
#StdOut
pt: 0, -0  == pt
pt: -1, -2  == pt
pt: inf, 1  == pt
pt: nan, -1  != pt
##
##

#SeeAlso equals() operator!=(const SkPoint& a, const SkPoint& b)

#Method ##

# ------------------------------------------------------------------------------

#Method bool operator!=(const SkPoint& a, const SkPoint& b)

#Line # returns true if Point are unequal ##
Returns true if a is not equivalent to b.

#Param a  Point to compare ##
#Param b  Point to compare ##

#Return true if a.fX != b.fX or a.fY != b.fY ##

#Example
SkPoint test[] = { {0, -0.f}, {-1, -2}, {SK_ScalarInfinity, 1}, {SK_ScalarNaN, -1} };
for (const SkPoint& pt : test) {
    SkDebugf("pt: %g, %g  %c= pt\n", pt.fX, pt.fY, pt != pt ? '!' : '=');
}
#StdOut
pt: 0, -0  == pt
pt: -1, -2  == pt
pt: inf, 1  == pt
pt: nan, -1  != pt
##
##

#SeeAlso operator==(const SkPoint& a, const SkPoint& b) equals()

#Method ##

# ------------------------------------------------------------------------------

#Method SkVector operator-(const SkPoint& a, const SkPoint& b)

#Line # returns Vector between Points ##
Returns Vector from b to a, computed as
#Formula
(a.fX - b.fX, a.fY - b.fY)
##
.

Can also be used to subtract Vector from Point, returning Point.
Can also be used to subtract Vector from Vector, returning Vector.

#Param a  Point to subtract from ##
#Param b  Point to subtract ##

#Return Vector from b to a ##

#Example
    SkPaint paint;
    paint.setAntiAlias(true);
    SkPoint points[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
                         { 6, 4 }, { 7, 5 }, { 5, 7 },
                         { 4, 6 }, { 3, 7 }, { 1, 5 },
                         { 2, 4 }, { 1, 3 }, { 3, 1 } };
    canvas->scale(30, 15);
    paint.setStyle(SkPaint::kStroke_Style);
    canvas->drawPoints(SkCanvas::kPolygon_PointMode, SK_ARRAY_COUNT(points), points, paint);
    points[1] += points[0] - points[2];
    points[2] -= points[3] - points[5];
    paint.setColor(SK_ColorRED);
    canvas->drawPoints(SkCanvas::kPolygon_PointMode, SK_ARRAY_COUNT(points), points, paint);
##

#SeeAlso operator-=(const SkVector& v) offset()

#Method ##

# ------------------------------------------------------------------------------

#Method SkPoint operator+(const SkPoint& a, const SkVector& b)

#Line # returns Point offset by Vector ##
Returns Point resulting from Point a offset by Vector b, computed as:
#Formula
(a.fX + b.fX, a.fY + b.fY)
##
.

Can also be used to offset Point b by Vector a, returning Point.
Can also be used to add Vector to Vector, returning Vector.

#Param a  Point or Vector to add to ##
#Param b  Point or Vector to add ##

#Return Point equal to a offset by b ##

#Example
    SkPaint paint;
    paint.setAntiAlias(true);
    SkPoint points[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
                         { 6, 4 }, { 7, 5 }, { 5, 7 },
                         { 4, 6 }, { 3, 7 }, { 1, 5 },
                         { 2, 4 }, { 1, 3 }, { 3, 1 } };
    canvas->scale(30, 15);
    paint.setStyle(SkPaint::kStroke_Style);
    canvas->drawPoints(SkCanvas::kPolygon_PointMode, SK_ARRAY_COUNT(points), points, paint);
    SkVector mod = {1, 1};
    for (auto& point : points) {
        point = point + mod;
        mod.fX *= 1.1f;
        mod.fY += .2f;
    }
    paint.setColor(SK_ColorRED);
    canvas->drawPoints(SkCanvas::kPolygon_PointMode, SK_ARRAY_COUNT(points), points, paint);
##

#SeeAlso operator+=(const SkVector& v) offset()

#Method ##

# ------------------------------------------------------------------------------

#Method static SkScalar Length(SkScalar x, SkScalar y)

#Line # returns straight-line distance to origin ##
Returns the Euclidean_Distance from origin, computed as:
#Code
#Literal
sqrt(x * x + y * y)
##
.

#Param x  component of length ##
#Param y  component of length ##

#Return straight-line distance to origin ##

#Example
#Height 192
    SkPaint paint;
    paint.setAntiAlias(true);
    const SkPoint points[] = { { 90, 30 }, { 120, 150 }, { 150, 30 }, { 210, 90 } };
    const SkPoint origin = {30, 140};
    for (auto point : points) {
        canvas->drawLine(origin, point, paint);
        SkAutoCanvasRestore acr(canvas, true);
        SkScalar angle = SkScalarATan2((point.fY - origin.fY), point.fX - origin.fX);
        canvas->rotate(angle * 180 / SK_ScalarPI, origin.fX, origin.fY);
        SkString length("length = ");
        length.appendScalar(SkPoint::Length(point.fX, point.fY));
        canvas->drawString(length, origin.fX + 25, origin.fY - 4, paint);
    }
##

#SeeAlso length() Distance setLength

#Method ##

# ------------------------------------------------------------------------------

#Method static SkScalar Normalize(SkVector* vec)

#Line # sets length to one, and returns prior length ##
Scales (vec->fX, vec->fY) so that length() returns one, while preserving ratio of vec->fX to vec->fY,
if possible. If original length is nearly zero, sets vec to (0, 0) and returns zero;
otherwise, returns length of vec before vec is scaled.

Returned prior length may be SK_ScalarInfinity if it can not be represented by SkScalar.

Note that normalize() is faster if prior length is not required.

#Param vec  normalized to unit length ##

#Return original vec length ##

#Example
    SkPaint paint;
    paint.setAntiAlias(true);
    const SkPoint lines[][2] = { {{  30, 110 }, { 190,  30 }},
                                 {{  30, 220 }, { 120, 140 }}};
    for (auto line : lines) {
        canvas->drawLine(line[0], line[1], paint);
        SkVector vector = line[1] - line[0];
        SkScalar priorLength = SkPoint::Normalize(&vector);
        SkVector rotate90 = { -vector.fY, vector.fX };
        rotate90 *= 10.f;
        canvas->drawLine(line[0] - rotate90, line[0] + rotate90, paint);
        canvas->drawLine(line[1] - rotate90, line[1] + rotate90, paint);
        SkString length("length = ");
        length.appendScalar(priorLength);
        canvas->drawString(length, line[0].fX + 25, line[0].fY - 4, paint);
    }
##

#SeeAlso normalize() setLength Length

#Method ##

# ------------------------------------------------------------------------------

#Method static SkScalar Distance(const SkPoint& a, const SkPoint& b)

#Line # returns straight-line distance between points ##
Returns the Euclidean_Distance between a and b.

#Param a  line end point ##
#Param b  line end point ##

#Return straight-line distance from a to b ##

#Example
#Height 192
    SkPaint paint;
    paint.setAntiAlias(true);
    const SkPoint lines[][2] = {{{-10, -10}, {90, 30}}, {{0, 0}, {150, 30}}, {{10, 25}, {120, 150}}};
    const SkPoint origin = {30, 160};
    for (auto line : lines) {
        SkPoint a = origin + line[0];
        const SkPoint& b = line[1];
        canvas->drawLine(a, b, paint);
        SkAutoCanvasRestore acr(canvas, true);
        SkScalar angle = SkScalarATan2((b.fY - a.fY), b.fX - a.fX);
        canvas->rotate(angle * 180 / SK_ScalarPI, a.fX, a.fY);
        SkString distance("distance = ");
        distance.appendScalar(SkPoint::Distance(a, b));
        canvas->drawString(distance, a.fX + 25, a.fY - 4, paint);
    }
##

#SeeAlso length() setLength

#Method ##

# ------------------------------------------------------------------------------

#Method static SkScalar DotProduct(const SkVector& a, const SkVector& b)

#Line # returns dot product ##
Returns the dot product of Vector a and Vector b.

#Param a  left side of dot product ##
#Param b  right side of dot product ##

#Return product of input magnitudes and cosine of the angle between them ##

#Example
    SkPaint paint;
    paint.setAntiAlias(true);
    SkVector vectors[][2] = {{{50, 2}, {-14, 20}}, {{0, 50}, {-50, 0}}, {{-20, 25}, {25, -20}},
                             {{-20, -24}, {-24, -20}}};
    SkPoint center[] = {{32, 32}, {160, 32}, {32, 160}, {160, 160}};
    paint.setStrokeWidth(2);
    for (size_t i = 0; i < 4; ++i) {
        canvas->drawLine(center[i], center[i] + vectors[i][0], paint);
        canvas->drawLine(center[i], center[i] + vectors[i][1], paint);
        SkString str;
        str.printf("dot = %g", SkPoint::DotProduct(vectors[i][0], vectors[i][1]));
        canvas->drawString(str, center[i].fX, center[i].fY, paint);
    }
##

#SeeAlso dot CrossProduct

#Method ##

# ------------------------------------------------------------------------------

#Method static SkScalar CrossProduct(const SkVector& a, const SkVector& b)

#Line # returns cross product ##
Returns the cross product of Vector a and Vector b.

a and b form three-dimensional vectors with z equal to zero. The cross product
is a three-dimensional vector with x and y equal to zero. The cross product z
term equals the returned value.

#Param a  left side of cross product ##
#Param b  right side of cross product ##

#Return area spanned by Vectors signed by angle direction ##

#Example
    SkPaint paint;
    paint.setAntiAlias(true);
    SkVector vectors[][2] = {{{50, 2}, {-14, 20}}, {{0, 50}, {-50, 0}}, {{-20, 25}, {25, -20}},
                             {{-20, -24}, {-24, -20}}};
    SkPoint center[] = {{32, 32}, {160, 32}, {32, 160}, {160, 160}};
    paint.setStrokeWidth(2);
    for (size_t i = 0; i < 4; ++i) {
        paint.setColor(SK_ColorRED);
        canvas->drawLine(center[i], center[i] + vectors[i][0], paint);
        paint.setColor(SK_ColorBLUE);
        canvas->drawLine(center[i], center[i] + vectors[i][1], paint);
        SkString str;
        SkScalar cross = SkPoint::CrossProduct(vectors[i][1], vectors[i][0]);
        str.printf("cross = %g", cross);
        paint.setColor(cross >= 0 ? SK_ColorRED : SK_ColorBLUE);
        canvas->drawString(str, center[i].fX, center[i].fY, paint);
    }
##

#SeeAlso cross DotProduct

#Method ##

# ------------------------------------------------------------------------------

#Method SkScalar cross(const SkVector& vec) const

#Line # returns cross product ##
Returns the cross product of Vector and vec.

Vector and vec form three-dimensional vectors with z equal to zero. The
cross product is a three-dimensional vector with x and y equal to zero.
The cross product z term equals the returned value.

#Param vec  right side of cross product ##

#Return area spanned by Vectors signed by angle direction ##

#Example
    SkPaint paint;
    paint.setAntiAlias(true);
    SkVector vectors[][2] = {{{50, 2}, {-14, 20}}, {{0, 50}, {-50, 0}}, {{-20, 25}, {25, -20}},
                             {{-20, -24}, {-24, -20}}};
    SkPoint center[] = {{32, 32}, {160, 32}, {32, 160}, {160, 160}};
    paint.setStrokeWidth(2);
    for (size_t i = 0; i < 4; ++i) {
        paint.setColor(SK_ColorRED);
        canvas->drawLine(center[i], center[i] + vectors[i][0], paint);
        paint.setColor(SK_ColorBLUE);
        canvas->drawLine(center[i], center[i] + vectors[i][1], paint);
        SkString str;
        SkScalar cross = vectors[i][0].cross(vectors[i][1]);
        str.printf("cross = %g", cross);
        paint.setColor(cross >= 0 ? SK_ColorRED : SK_ColorBLUE);
        canvas->drawString(str, center[i].fX, center[i].fY, paint);
    }
##

#SeeAlso CrossProduct dot

#Method ##

# ------------------------------------------------------------------------------

#Method SkScalar dot(const SkVector& vec) const

#Line # returns dot product ##
Returns the dot product of Vector and Vector vec.

#Param vec  right side of dot product ##

#Return product of input magnitudes and cosine of the angle between them ##

#Example
    SkPaint paint;
    paint.setAntiAlias(true);
    SkVector vectors[][2] = {{{50, 2}, {-14, 20}}, {{0, 50}, {-50, 0}}, {{-20, 25}, {25, -20}},
                             {{-20, -24}, {-24, -20}}};
    SkPoint center[] = {{32, 32}, {160, 32}, {32, 160}, {160, 160}};
    paint.setStrokeWidth(2);
    for (size_t i = 0; i < 4; ++i) {
        canvas->drawLine(center[i], center[i] + vectors[i][0], paint);
        canvas->drawLine(center[i], center[i] + vectors[i][1], paint);
        SkString str;
        str.printf("dot = %g", vectors[i][0].dot(vectors[i][1]));
        canvas->drawString(str, center[i].fX, center[i].fY, paint);
    }
##

#SeeAlso DotProduct cross

#Method ##

#Struct SkPoint ##

#Topic Point ##

# ------------------------------------------------------------------------------

#Topic Vector
    #Alias Vectors
    #Typedef SkPoint SkVector
    #Typedef ##
##