1 | import {isArray, formatNum} from '../core/Util';
|
2 |
|
3 | /*
|
4 | * @class Point
|
5 | * @aka L.Point
|
6 | *
|
7 | * Represents a point with `x` and `y` coordinates in pixels.
|
8 | *
|
9 | * @example
|
10 | *
|
11 | * ```js
|
12 | * var point = L.point(200, 300);
|
13 | * ```
|
14 | *
|
15 | * All Leaflet methods and options that accept `Point` objects also accept them in a simple Array form (unless noted otherwise), so these lines are equivalent:
|
16 | *
|
17 | * ```js
|
18 | * map.panBy([200, 300]);
|
19 | * map.panBy(L.point(200, 300));
|
20 | * ```
|
21 | *
|
22 | * Note that `Point` does not inherit from Leaflet's `Class` object,
|
23 | * which means new classes can't inherit from it, and new methods
|
24 | * can't be added to it with the `include` function.
|
25 | */
|
26 |
|
27 | export function Point(x, y, round) {
|
28 | // @property x: Number; The `x` coordinate of the point
|
29 | this.x = (round ? Math.round(x) : x);
|
30 | // @property y: Number; The `y` coordinate of the point
|
31 | this.y = (round ? Math.round(y) : y);
|
32 | }
|
33 |
|
34 | var trunc = Math.trunc || function (v) {
|
35 | return v > 0 ? Math.floor(v) : Math.ceil(v);
|
36 | };
|
37 |
|
38 | Point.prototype = {
|
39 |
|
40 | // @method clone(): Point
|
41 | // Returns a copy of the current point.
|
42 | clone: function () {
|
43 | return new Point(this.x, this.y);
|
44 | },
|
45 |
|
46 | // @method add(otherPoint: Point): Point
|
47 | // Returns the result of addition of the current and the given points.
|
48 | add: function (point) {
|
49 | // non-destructive, returns a new point
|
50 | return this.clone()._add(toPoint(point));
|
51 | },
|
52 |
|
53 | _add: function (point) {
|
54 | // destructive, used directly for performance in situations where it's safe to modify existing point
|
55 | this.x += point.x;
|
56 | this.y += point.y;
|
57 | return this;
|
58 | },
|
59 |
|
60 | // @method subtract(otherPoint: Point): Point
|
61 | // Returns the result of subtraction of the given point from the current.
|
62 | subtract: function (point) {
|
63 | return this.clone()._subtract(toPoint(point));
|
64 | },
|
65 |
|
66 | _subtract: function (point) {
|
67 | this.x -= point.x;
|
68 | this.y -= point.y;
|
69 | return this;
|
70 | },
|
71 |
|
72 | // @method divideBy(num: Number): Point
|
73 | // Returns the result of division of the current point by the given number.
|
74 | divideBy: function (num) {
|
75 | return this.clone()._divideBy(num);
|
76 | },
|
77 |
|
78 | _divideBy: function (num) {
|
79 | this.x /= num;
|
80 | this.y /= num;
|
81 | return this;
|
82 | },
|
83 |
|
84 | // @method multiplyBy(num: Number): Point
|
85 | // Returns the result of multiplication of the current point by the given number.
|
86 | multiplyBy: function (num) {
|
87 | return this.clone()._multiplyBy(num);
|
88 | },
|
89 |
|
90 | _multiplyBy: function (num) {
|
91 | this.x *= num;
|
92 | this.y *= num;
|
93 | return this;
|
94 | },
|
95 |
|
96 | // @method scaleBy(scale: Point): Point
|
97 | // Multiply each coordinate of the current point by each coordinate of
|
98 | // `scale`. In linear algebra terms, multiply the point by the
|
99 | // [scaling matrix](https://en.wikipedia.org/wiki/Scaling_%28geometry%29#Matrix_representation)
|
100 | // defined by `scale`.
|
101 | scaleBy: function (point) {
|
102 | return new Point(this.x * point.x, this.y * point.y);
|
103 | },
|
104 |
|
105 | // @method unscaleBy(scale: Point): Point
|
106 | // Inverse of `scaleBy`. Divide each coordinate of the current point by
|
107 | // each coordinate of `scale`.
|
108 | unscaleBy: function (point) {
|
109 | return new Point(this.x / point.x, this.y / point.y);
|
110 | },
|
111 |
|
112 | // @method round(): Point
|
113 | // Returns a copy of the current point with rounded coordinates.
|
114 | round: function () {
|
115 | return this.clone()._round();
|
116 | },
|
117 |
|
118 | _round: function () {
|
119 | this.x = Math.round(this.x);
|
120 | this.y = Math.round(this.y);
|
121 | return this;
|
122 | },
|
123 |
|
124 | // @method floor(): Point
|
125 | // Returns a copy of the current point with floored coordinates (rounded down).
|
126 | floor: function () {
|
127 | return this.clone()._floor();
|
128 | },
|
129 |
|
130 | _floor: function () {
|
131 | this.x = Math.floor(this.x);
|
132 | this.y = Math.floor(this.y);
|
133 | return this;
|
134 | },
|
135 |
|
136 | // @method ceil(): Point
|
137 | // Returns a copy of the current point with ceiled coordinates (rounded up).
|
138 | ceil: function () {
|
139 | return this.clone()._ceil();
|
140 | },
|
141 |
|
142 | _ceil: function () {
|
143 | this.x = Math.ceil(this.x);
|
144 | this.y = Math.ceil(this.y);
|
145 | return this;
|
146 | },
|
147 |
|
148 | // @method trunc(): Point
|
149 | // Returns a copy of the current point with truncated coordinates (rounded towards zero).
|
150 | trunc: function () {
|
151 | return this.clone()._trunc();
|
152 | },
|
153 |
|
154 | _trunc: function () {
|
155 | this.x = trunc(this.x);
|
156 | this.y = trunc(this.y);
|
157 | return this;
|
158 | },
|
159 |
|
160 | // @method distanceTo(otherPoint: Point): Number
|
161 | // Returns the cartesian distance between the current and the given points.
|
162 | distanceTo: function (point) {
|
163 | point = toPoint(point);
|
164 |
|
165 | var x = point.x - this.x,
|
166 | y = point.y - this.y;
|
167 |
|
168 | return Math.sqrt(x * x + y * y);
|
169 | },
|
170 |
|
171 | // @method equals(otherPoint: Point): Boolean
|
172 | // Returns `true` if the given point has the same coordinates.
|
173 | equals: function (point) {
|
174 | point = toPoint(point);
|
175 |
|
176 | return point.x === this.x &&
|
177 | point.y === this.y;
|
178 | },
|
179 |
|
180 | // @method contains(otherPoint: Point): Boolean
|
181 | // Returns `true` if both coordinates of the given point are less than the corresponding current point coordinates (in absolute values).
|
182 | contains: function (point) {
|
183 | point = toPoint(point);
|
184 |
|
185 | return Math.abs(point.x) <= Math.abs(this.x) &&
|
186 | Math.abs(point.y) <= Math.abs(this.y);
|
187 | },
|
188 |
|
189 | // @method toString(): String
|
190 | // Returns a string representation of the point for debugging purposes.
|
191 | toString: function () {
|
192 | return 'Point(' +
|
193 | formatNum(this.x) + ', ' +
|
194 | formatNum(this.y) + ')';
|
195 | }
|
196 | };
|
197 |
|
198 | // @factory L.point(x: Number, y: Number, round?: Boolean)
|
199 | // Creates a Point object with the given `x` and `y` coordinates. If optional `round` is set to true, rounds the `x` and `y` values.
|
200 |
|
201 | // @alternative
|
202 | // @factory L.point(coords: Number[])
|
203 | // Expects an array of the form `[x, y]` instead.
|
204 |
|
205 | // @alternative
|
206 | // @factory L.point(coords: Object)
|
207 | // Expects a plain object of the form `{x: Number, y: Number}` instead.
|
208 | export function toPoint(x, y, round) {
|
209 | if (x instanceof Point) {
|
210 | return x;
|
211 | }
|
212 | if (isArray(x)) {
|
213 | return new Point(x[0], x[1]);
|
214 | }
|
215 | if (x === undefined || x === null) {
|
216 | return x;
|
217 | }
|
218 | if (typeof x === 'object' && 'x' in x && 'y' in x) {
|
219 | return new Point(x.x, x.y);
|
220 | }
|
221 | return new Point(x, y, round);
|
222 | }
|