plotboilerplate 1.29.0 → 1.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.esm.js +194 -16
- package/dist/index.esm.js.map +1 -1
- package/dist/index.esm.min.js +1 -1
- package/dist/index.esm.min.js.map +1 -1
- package/dist/plotboilerplate.browser.min.js +1 -1
- package/dist/plotboilerplate.browser.min.js.map +1 -1
- package/dist/plotboilerplate.js +195 -16
- package/dist/plotboilerplate.min.js +1 -1
- package/package.json +1 -1
- package/src/cjs/Circle.d.ts +17 -1
- package/src/cjs/Circle.js +21 -1
- package/src/cjs/Circle.js.map +1 -1
- package/src/cjs/CubicBezierCurve.d.ts +34 -3
- package/src/cjs/CubicBezierCurve.js +79 -12
- package/src/cjs/CubicBezierCurve.js.map +1 -1
- package/src/cjs/Line.d.ts +46 -1
- package/src/cjs/Line.js +80 -1
- package/src/cjs/Line.js.map +1 -1
- package/src/cjs/VertTuple.d.ts +13 -2
- package/src/cjs/VertTuple.js +15 -2
- package/src/cjs/VertTuple.js.map +1 -1
- package/src/esm/Circle.d.ts +17 -1
- package/src/esm/Circle.js +21 -1
- package/src/esm/Circle.js.map +1 -1
- package/src/esm/CubicBezierCurve.d.ts +34 -3
- package/src/esm/CubicBezierCurve.js +79 -12
- package/src/esm/CubicBezierCurve.js.map +1 -1
- package/src/esm/Line.d.ts +46 -1
- package/src/esm/Line.js +80 -1
- package/src/esm/Line.js.map +1 -1
- package/src/esm/VertTuple.d.ts +13 -2
- package/src/esm/VertTuple.js +15 -2
- package/src/esm/VertTuple.js.map +1 -1
- package/src/index-gl.js +1 -2
- package/src/ts/Circle.ts +23 -1
- package/src/ts/CubicBezierCurve.ts +133 -48
- package/src/ts/Line.ts +84 -1
- package/src/ts/VertTuple.ts +16 -2
package/dist/plotboilerplate.js
CHANGED
|
@@ -1750,7 +1750,8 @@ exports.Bounds = Bounds;
|
|
|
1750
1750
|
* @modified 2026-07-08 Adding the `Circle.setRadius` method (for chaining).
|
|
1751
1751
|
* @mofified 2026-07-31 Adding the `radicalAxis(Circle)` method. Added the `Circle.circleUtils.createRadicalAxisHelperCircle` and `.circleDistance` helper methods.
|
|
1752
1752
|
* @modified 2026-08-03 Adding `Circle.tangentsFromPoint`.
|
|
1753
|
-
* @
|
|
1753
|
+
* @modified 2026-08-16 Adding the `Circle.sectorAngleByArcLength` method and the `Circle.circleUtils.sectorAngleByArcLength` helper method.
|
|
1754
|
+
* @version 1.8.0
|
|
1754
1755
|
**/
|
|
1755
1756
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1756
1757
|
exports.Circle = void 0;
|
|
@@ -2136,6 +2137,15 @@ var Circle = /** @class */ (function () {
|
|
|
2136
2137
|
}
|
|
2137
2138
|
return [new Vector_1.Vector(intersection.a, vert), new Vector_1.Vector(intersection.b, vert)];
|
|
2138
2139
|
};
|
|
2140
|
+
/**
|
|
2141
|
+
* Calculate inner sector angle for this circle and a given circle arc length.
|
|
2142
|
+
*
|
|
2143
|
+
* @param {number} sectorArcLength - The desired arc length (in units).
|
|
2144
|
+
* @returns The sector's inner angle (in radians).
|
|
2145
|
+
*/
|
|
2146
|
+
Circle.prototype.sectorAngleByArcLength = function (sectorArcLength) {
|
|
2147
|
+
return Circle.circleUtils.sectorAngleByArcLength(sectorArcLength, this.radius);
|
|
2148
|
+
};
|
|
2139
2149
|
/**
|
|
2140
2150
|
* Create a deep copy of this circle.
|
|
2141
2151
|
*
|
|
@@ -2213,6 +2223,16 @@ var Circle = /** @class */ (function () {
|
|
|
2213
2223
|
*/
|
|
2214
2224
|
circleDistance: function (circleA, circleB) {
|
|
2215
2225
|
return circleA.center.distance(circleB.center) - circleA.radius - circleB.radius;
|
|
2226
|
+
},
|
|
2227
|
+
/**
|
|
2228
|
+
* Calculate the inner sector angle for a given circle arc length and radius.
|
|
2229
|
+
*
|
|
2230
|
+
* @param {number} sectorArcLength - The desired arc length.
|
|
2231
|
+
* @param {number} circleRadius - The circle's radius.
|
|
2232
|
+
* @returns The sector angle in radians.
|
|
2233
|
+
*/
|
|
2234
|
+
sectorAngleByArcLength: function (sectorArcLength, circleRadius) {
|
|
2235
|
+
return sectorArcLength / circleRadius;
|
|
2216
2236
|
}
|
|
2217
2237
|
};
|
|
2218
2238
|
return Circle;
|
|
@@ -8278,12 +8298,14 @@ exports["default"] = PlotBoilerplate;
|
|
|
8278
8298
|
* @modified 2025-04-15 Changed param of `VertTuple.moveTo` method from `Vertex` to `XYCoords`.
|
|
8279
8299
|
* @modified 2025-04-15 Added method `VertTuple.move` method.
|
|
8280
8300
|
* @modified 2026-06-10 Adding helper function `VertTuple.utils.calcCircumcircle`.
|
|
8281
|
-
* @
|
|
8301
|
+
* @modified 2026-06-17 Adding method `VertTuple.asLine` for converting Vector to Line instances.
|
|
8302
|
+
* @version 1.6.0
|
|
8282
8303
|
*/
|
|
8283
8304
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
8284
8305
|
exports.VertTuple = void 0;
|
|
8285
8306
|
var Vertex_1 = __webpack_require__(787);
|
|
8286
8307
|
var UIDGenerator_1 = __webpack_require__(938);
|
|
8308
|
+
var Line_1 = __webpack_require__(939);
|
|
8287
8309
|
/**
|
|
8288
8310
|
* @classdesc An abstract base classes for vertex tuple constructs, like Lines or Vectors.
|
|
8289
8311
|
* @abstract
|
|
@@ -8566,7 +8588,7 @@ var VertTuple = /** @class */ (function () {
|
|
|
8566
8588
|
/**
|
|
8567
8589
|
* Create a deep clone of this instance.
|
|
8568
8590
|
*
|
|
8569
|
-
* @method
|
|
8591
|
+
* @method clone
|
|
8570
8592
|
* @return {T} A type safe clone if this instance.
|
|
8571
8593
|
* @instance
|
|
8572
8594
|
* @memberof VertTuple
|
|
@@ -8574,6 +8596,17 @@ var VertTuple = /** @class */ (function () {
|
|
|
8574
8596
|
VertTuple.prototype.clone = function () {
|
|
8575
8597
|
return this.factory(this.a.clone(), this.b.clone());
|
|
8576
8598
|
};
|
|
8599
|
+
/**
|
|
8600
|
+
* Converts this `Vector` to a `Line` (segment).
|
|
8601
|
+
*
|
|
8602
|
+
* @method asLine
|
|
8603
|
+
* @return {T} A type safe clone if this instance.
|
|
8604
|
+
* @instance
|
|
8605
|
+
* @memberof VertTuple
|
|
8606
|
+
**/
|
|
8607
|
+
VertTuple.prototype.asLine = function () {
|
|
8608
|
+
return new Line_1.Line(this.a, this.b);
|
|
8609
|
+
};
|
|
8577
8610
|
/**
|
|
8578
8611
|
* Create a string representation of this line.
|
|
8579
8612
|
*
|
|
@@ -14364,7 +14397,8 @@ exports.UIDGenerator = UIDGenerator;
|
|
|
14364
14397
|
* @modified 2023-09-25 Changed param type of `intersection()` from Line to VertTuple.
|
|
14365
14398
|
* @modified 2025-04-15 Class `Line` now implements interface `Intersectable`.
|
|
14366
14399
|
* @modified 2025-04-16 Class `Line` now implements interface `IBounded`.
|
|
14367
|
-
* @
|
|
14400
|
+
* @modified 2026-08-16 Adding methods `Line.trimStart` and `Line.trimEnd`. Adding methods `Line.trimStartAt` and `Line.trimEndAt`.
|
|
14401
|
+
* @version 2.5.0
|
|
14368
14402
|
*
|
|
14369
14403
|
* @file Line
|
|
14370
14404
|
* @public
|
|
@@ -14514,6 +14548,84 @@ var Line = /** @class */ (function (_super) {
|
|
|
14514
14548
|
return this;
|
|
14515
14549
|
};
|
|
14516
14550
|
//--- END Implement PathSegment ---
|
|
14551
|
+
/**
|
|
14552
|
+
* Trim this line segment from the start point by the given amount.
|
|
14553
|
+
* The amount must be positive and should be withing the segment's length. If the amount exceeds the segment's length
|
|
14554
|
+
* then the length of the resulting line will be zero (0.0).
|
|
14555
|
+
*
|
|
14556
|
+
* @method trimStart
|
|
14557
|
+
* @memberof Line
|
|
14558
|
+
* @param {number} amount - The positive amount to trim the line from the start point `a`.
|
|
14559
|
+
* @returns {Line} This for chaining, with updated point `a`.
|
|
14560
|
+
*/
|
|
14561
|
+
Line.prototype.trimStart = function (amount) {
|
|
14562
|
+
// Calculate the relative position `t` on this line.
|
|
14563
|
+
var t = amount / this.length();
|
|
14564
|
+
// `t` should be inside 0..1 – otherwise the amount was too large or negative.
|
|
14565
|
+
if (t < 0.0) {
|
|
14566
|
+
return this;
|
|
14567
|
+
}
|
|
14568
|
+
if (t > 1.0) {
|
|
14569
|
+
// Set the line to length zero (endpoint only)
|
|
14570
|
+
this.a = this.b.clone();
|
|
14571
|
+
return this;
|
|
14572
|
+
}
|
|
14573
|
+
this.a = this.vertAt(t);
|
|
14574
|
+
return this;
|
|
14575
|
+
};
|
|
14576
|
+
/**
|
|
14577
|
+
* Trim this line segment from the start point by the given relative amount.
|
|
14578
|
+
* The amount must be positive and should be within 0.0 and 1.0. If the amount exceeds the segment's length
|
|
14579
|
+
* then the length of the resulting line will be zero (0.0).
|
|
14580
|
+
*
|
|
14581
|
+
* @method trimStartAt
|
|
14582
|
+
* @memberof Line
|
|
14583
|
+
* @param {number} amount - The positive amount to trim the line from the start point `a`.
|
|
14584
|
+
* @returns {Line} This for chaining, with updated point `a`.
|
|
14585
|
+
*/
|
|
14586
|
+
Line.prototype.trimStartAt = function (relativeAmount) {
|
|
14587
|
+
// Calculate the relative position `t` on this line.
|
|
14588
|
+
return this.trimStart(relativeAmount * this.length());
|
|
14589
|
+
};
|
|
14590
|
+
/**
|
|
14591
|
+
* Trim this line segment from the end point by the given amount.
|
|
14592
|
+
* The amount must be positive and should be withing the segment's length. If the amount exceeds the segment's length
|
|
14593
|
+
* then the length of the resulting line will be zero (0.0).
|
|
14594
|
+
*
|
|
14595
|
+
* @method trimEnd
|
|
14596
|
+
* @memberof Line
|
|
14597
|
+
* @param {number} amount - The positive amount to trim the line from the end point `b`.
|
|
14598
|
+
* @returns {Line} This for chaining, with updated point `b`.
|
|
14599
|
+
*/
|
|
14600
|
+
Line.prototype.trimEnd = function (amount) {
|
|
14601
|
+
// Calculate the relative position `t` on this line.
|
|
14602
|
+
var t = 1.0 - amount / this.length();
|
|
14603
|
+
// `t` should be inside 0..1 – otherwise the amount was too large or negative.
|
|
14604
|
+
if (t < 0.0) {
|
|
14605
|
+
return this;
|
|
14606
|
+
}
|
|
14607
|
+
if (t > 1.0) {
|
|
14608
|
+
// Set the line to length zero (endpoint only)
|
|
14609
|
+
this.b = this.a.clone();
|
|
14610
|
+
return this;
|
|
14611
|
+
}
|
|
14612
|
+
this.b = this.vertAt(t);
|
|
14613
|
+
return this;
|
|
14614
|
+
};
|
|
14615
|
+
/**
|
|
14616
|
+
* Trim this line segment from the end point by the given relative amount.
|
|
14617
|
+
* The amount must be positive and should be within 0.0 and 1.0. If the amount exceeds the segment's length
|
|
14618
|
+
* then the length of the resulting line will be zero (0.0).
|
|
14619
|
+
*
|
|
14620
|
+
* @method trimEndAt
|
|
14621
|
+
* @memberof Line
|
|
14622
|
+
* @param {number} amount - The positive amount to trim the line from the start point `a`.
|
|
14623
|
+
* @returns {Line} This for chaining, with updated point `a`.
|
|
14624
|
+
*/
|
|
14625
|
+
Line.prototype.trimEndAt = function (relativeAmount) {
|
|
14626
|
+
// Calculate the relative position `t` on this line.
|
|
14627
|
+
return this.trimEnd(relativeAmount * this.length());
|
|
14628
|
+
};
|
|
14517
14629
|
//--- BEGIN --- Implement interface `Intersectable`
|
|
14518
14630
|
/**
|
|
14519
14631
|
* Get all line intersections with this polygon.
|
|
@@ -14604,8 +14716,9 @@ exports.Line = Line;
|
|
|
14604
14716
|
* @modified 2025-04-18 Added evaluation method for cubic Bézier curves `CubicBezierCurve.utils.evaluateT`.
|
|
14605
14717
|
* @modified 2025-04-18 Refactored method `CubicBezierCurve.getPointAt` to use `evaluateT`.
|
|
14606
14718
|
* @modified 2025-04-18 Fixed the `CubicBezierCurve.getBounds` method: now returning the real bounding box. Before it was an approximated one.
|
|
14607
|
-
* @modified 2025
|
|
14608
|
-
* @
|
|
14719
|
+
* @modified 2025-04-18 Added helper methods for bounding box calculation `CubucBezierCurve.util.cubicPolyMinMax` and `cubicPoly`.
|
|
14720
|
+
* @modified 2026-09-09 Adding methods `CubicBezierCurve.trimStartEnd` and `CubicBezierCurve.trimStartEndAt`.
|
|
14721
|
+
* @version 2.10.0
|
|
14609
14722
|
*
|
|
14610
14723
|
* @file CubicBezierCurve
|
|
14611
14724
|
* @public
|
|
@@ -15060,6 +15173,7 @@ var CubicBezierCurve = /** @class */ (function () {
|
|
|
15060
15173
|
this.endControlPoint.set(subCurbePoints[3]);
|
|
15061
15174
|
this.updateArcLengths();
|
|
15062
15175
|
return this;
|
|
15176
|
+
// return this.trimStartEndAt(t, null);
|
|
15063
15177
|
};
|
|
15064
15178
|
/**
|
|
15065
15179
|
* Trim off the end of this curve. The position parameter `uValue` is the absolute position on the
|
|
@@ -15095,7 +15209,79 @@ var CubicBezierCurve = /** @class */ (function () {
|
|
|
15095
15209
|
this.endControlPoint.set(subCurbePoints[3]);
|
|
15096
15210
|
this.updateArcLengths();
|
|
15097
15211
|
return this;
|
|
15212
|
+
// return this.trimStartEndAt(null, t);
|
|
15213
|
+
};
|
|
15214
|
+
/**
|
|
15215
|
+
* Trim off a start and end section of this curve. The position parameters `uStart` and `uEnd` are the absolute positions in [0..arcLength].
|
|
15216
|
+
* The remaining curve will be the one in the bounds `[uStart,uEnd]` (so `[0.0,uStart]` and `[uEnd,1.0]` are cut off).
|
|
15217
|
+
*
|
|
15218
|
+
* Parameters out of bounds (< 0.0 or > arcLength) are ignored.
|
|
15219
|
+
* If `uEnd` is smaller than `uStart` then a curve with length zero (0) at `uStart` is returned.
|
|
15220
|
+
*
|
|
15221
|
+
* @method trimStartEndAt
|
|
15222
|
+
* @instance
|
|
15223
|
+
* @memberof CubicBezierCurve
|
|
15224
|
+
* @param {number} tStart - The relative position parameter where to cut off the head curve.
|
|
15225
|
+
* @param {number} tEnd - The relative position parameter where to cut off the tail curve.
|
|
15226
|
+
* @returns {CubicBezierCurve} `this` for chanining.
|
|
15227
|
+
*/
|
|
15228
|
+
CubicBezierCurve.prototype.trimStartEnd = function (uStart, uEnd) {
|
|
15229
|
+
return this.trimStartEndAt(this.convertU2T(uStart), this.convertU2T(uEnd));
|
|
15230
|
+
};
|
|
15231
|
+
/**
|
|
15232
|
+
* Trim off a start and end section of this curve. The position parameters `tStart` and `tEnd` are the relative positions in [0..1].
|
|
15233
|
+
* The remaining curve will be the one in the bounds `[tStart,tEnd]` (so `[0.0,tStart]` and `[tEnd,1.0]` are cut off).
|
|
15234
|
+
*
|
|
15235
|
+
* Parameters out of bounds (< 0.0 or > 1.0) are ignored.
|
|
15236
|
+
* If `tEnd` is smaller than `tStart` then a curve with length zero (0) at `tStart` is returned.
|
|
15237
|
+
*
|
|
15238
|
+
* @method trimStartEndAt
|
|
15239
|
+
* @instance
|
|
15240
|
+
* @memberof CubicBezierCurve
|
|
15241
|
+
* @param {number} tStart - The relative position parameter where to cut off the head curve.
|
|
15242
|
+
* @param {number} tEnd - The relative position parameter where to cut off the tail curve.
|
|
15243
|
+
* @returns {CubicBezierCurve} `this` for chanining.
|
|
15244
|
+
*/
|
|
15245
|
+
CubicBezierCurve.prototype.trimStartEndAt = function (tStart, tEnd) {
|
|
15246
|
+
var cleanTrimStart = Math.min(Math.max(0.0, tStart), 1.0);
|
|
15247
|
+
var cleanTrimEnd = Math.min(Math.max(cleanTrimStart, tEnd), 1.0);
|
|
15248
|
+
this.trimStartAt(cleanTrimStart);
|
|
15249
|
+
var relativeTrimEnd = (cleanTrimEnd - cleanTrimStart) / (1.0 - cleanTrimStart);
|
|
15250
|
+
this.trimEndAt(relativeTrimEnd);
|
|
15251
|
+
return this;
|
|
15098
15252
|
};
|
|
15253
|
+
// __trimStartEndAt(tStart: number, tEnd: number): CubicBezierCurve {
|
|
15254
|
+
// var finalCurvePoints = [
|
|
15255
|
+
// this.startPoint.clone(),
|
|
15256
|
+
// this.endPoint.clone(),
|
|
15257
|
+
// this.startControlPoint.clone(),
|
|
15258
|
+
// this.endControlPoint.clone()
|
|
15259
|
+
// ];
|
|
15260
|
+
// if (typeof tStart === "number" && !Number.isNaN(tStart)) {
|
|
15261
|
+
// const subCurvePointsStart = CubicBezierCurve.utils.getSubCurvePointsAt(this, tStart, 1.0);
|
|
15262
|
+
// finalCurvePoints[0].set(subCurvePointsStart[0]);
|
|
15263
|
+
// finalCurvePoints[2].set(subCurvePointsStart[2]);
|
|
15264
|
+
// // this.startPoint.set(subCurvePointsStart[0]);
|
|
15265
|
+
// // this.startControlPoint.set(subCurvePointsStart[2]);
|
|
15266
|
+
// // this.endPoint.set(subCurvePointsStart[1]);
|
|
15267
|
+
// // this.endControlPoint.set(subCurvePointsStart[3]);
|
|
15268
|
+
// }
|
|
15269
|
+
// if (typeof tEnd === "number" && !Number.isNaN(tEnd)) {
|
|
15270
|
+
// const subCurvePointsEnd = CubicBezierCurve.utils.getSubCurvePointsAt(this, 0.0, tEnd);
|
|
15271
|
+
// // this.startPoint.set(subCurvePointsEnd[0]);
|
|
15272
|
+
// // this.startControlPoint.set(subCurvePointsEnd[2]);
|
|
15273
|
+
// // this.endPoint.set(subCurvePointsEnd[1]);
|
|
15274
|
+
// // this.endControlPoint.set(subCurvePointsEnd[3]);
|
|
15275
|
+
// finalCurvePoints[1].set(subCurvePointsEnd[1]);
|
|
15276
|
+
// finalCurvePoints[3].set(subCurvePointsEnd[3]);
|
|
15277
|
+
// }
|
|
15278
|
+
// this.startPoint.set(finalCurvePoints[0]);
|
|
15279
|
+
// this.endPoint.set(finalCurvePoints[1]);
|
|
15280
|
+
// this.startControlPoint.set(finalCurvePoints[2]);
|
|
15281
|
+
// this.endControlPoint.set(finalCurvePoints[3]);
|
|
15282
|
+
// this.updateArcLengths();
|
|
15283
|
+
// return this;
|
|
15284
|
+
// }
|
|
15099
15285
|
/**
|
|
15100
15286
|
* Get a sub curve at the given start end end positions (values on the curve's length, between 0 and curve.arcLength).
|
|
15101
15287
|
*
|
|
@@ -15450,10 +15636,7 @@ var CubicBezierCurve = /** @class */ (function () {
|
|
|
15450
15636
|
*/
|
|
15451
15637
|
CubicBezierCurve.utils = {
|
|
15452
15638
|
evaluateT: function (p0, p1, p2, p3, t) {
|
|
15453
|
-
return p0 * Math.pow(1.0 - t, 3) +
|
|
15454
|
-
p1 * 3 * t * Math.pow(1.0 - t, 2) +
|
|
15455
|
-
p2 * 3 * Math.pow(t, 2) * (1.0 - t) +
|
|
15456
|
-
p3 * Math.pow(t, 3);
|
|
15639
|
+
return (p0 * Math.pow(1.0 - t, 3) + p1 * 3 * t * Math.pow(1.0 - t, 2) + p2 * 3 * Math.pow(t, 2) * (1.0 - t) + p3 * Math.pow(t, 3));
|
|
15457
15640
|
},
|
|
15458
15641
|
cubicPolyMinMax: function (p0, p1, p2, p3) {
|
|
15459
15642
|
// var polyX = CubicBezierCurve.utils.cubicPoly2(
|
|
@@ -15525,7 +15708,7 @@ var CubicBezierCurve = /** @class */ (function () {
|
|
|
15525
15708
|
* @param {number} tEnd – The end offset if the desired cub curve (must be in [0..1]).
|
|
15526
15709
|
* @instance
|
|
15527
15710
|
* @memberof CubicBezierCurve
|
|
15528
|
-
* @return {
|
|
15711
|
+
* @return {[Vertex, Vertex, Vertex, Vertex]} The sub curve as curve vertices.
|
|
15529
15712
|
**/
|
|
15530
15713
|
getSubCurvePointsAt: function (curve, tStart, tEnd) {
|
|
15531
15714
|
var startVec = new Vector_1.Vector(curve.getPointAt(tStart), curve.getTangentAt(tStart));
|
|
@@ -15614,11 +15797,7 @@ var CubicBezierCurve = /** @class */ (function () {
|
|
|
15614
15797
|
* @returns {[number,number,number]}
|
|
15615
15798
|
*/
|
|
15616
15799
|
cubicPoly: function (p0, p1, p2, p3) {
|
|
15617
|
-
return [
|
|
15618
|
-
3 * p3 - 9 * p2 + 9 * p1 - 3 * p0,
|
|
15619
|
-
6 * p0 - 12 * p1 + 6 * p2,
|
|
15620
|
-
3 * p1 - 3 * p0
|
|
15621
|
-
];
|
|
15800
|
+
return [3 * p3 - 9 * p2 + 9 * p1 - 3 * p0, 6 * p0 - 12 * p1 + 6 * p2, 3 * p1 - 3 * p0];
|
|
15622
15801
|
},
|
|
15623
15802
|
/**
|
|
15624
15803
|
* sign of number, but is division safe: no zero returned :)
|