Skip to content

Commit

Permalink
Merge pull request #6 from kionell/master
Browse files Browse the repository at this point in the history
Bring back Node.js 8.3 support
  • Loading branch information
Itsyuka authored Oct 17, 2020
2 parents 207f38b + 5e4d1d1 commit 9d398f2
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 69 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ These instructions will get you a copy of the project up and running on your loc

### Prerequisites

- Node.js 8+
- Node.js 8.3.0+

### Installing

Expand Down Expand Up @@ -58,4 +58,4 @@ request.get('https://osu.ppy.sh/osu/1262832').then(osu => {

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
{
"name": "osu-bpdpc",
"version": "0.2.2",
"version": "0.2.3",
"description": "Osu beatmap parser, difficulty and performance calculator",
"main": "index.js",
"engines": {
"node": ">=8.3.0",
"npm": ">=5.3.0"
},
"scripts": {
"test": "mocha src/**/*.spec.js",
"lint": "eslint **/*.{js,ts} && tsc"
Expand Down
52 changes: 26 additions & 26 deletions src/Utils/PathApproximator.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
const Vector2 = require('./Vector2');

const bezier_tolerance = Math.fround(0.25);
const circular_arc_tolerance = Math.fround(0.1);

/**
* The amount of pieces to calculate for each control point quadruplet.
*/
const catmull_detail = 50;

/**
* Helper methods to approximate a path by interpolating a sequence of control points.
*/
class PathApproximator
{
static #bezier_tolerance = Math.fround(0.25);
static #circular_arc_tolerance = Math.fround(0.1);

/**
* The amount of pieces to calculate for each control point quadruplet.
*/
static #catmull_detail = 50;

/**
* Creates a piecewise-linear approximation of a bezier curve, by adaptively repeatedly subdividing
* the control points until their approximation error vanishes below a given threshold.
Expand All @@ -38,12 +38,12 @@ class PathApproximator
while (toFlatten.length > 0) {
let parent = toFlatten.pop();

if (PathApproximator.#bezierIsFlatEnough(parent)) {
if (PathApproximator._bezierIsFlatEnough(parent)) {
// If the control points we currently operate on are sufficiently "flat", we use
// an extension to De Casteljau's algorithm to obtain a piecewise-linear approximation
// of the bezier curve represented by our control points, consisting of the same amount
// of points as there are control points.
PathApproximator.#bezierApproximate(parent, output, subdivisionBuffer1, subdivisionBuffer2, count);
PathApproximator._bezierApproximate(parent, output, subdivisionBuffer1, subdivisionBuffer2, count);

freeBuffers.push(parent);
continue;
Expand All @@ -53,7 +53,7 @@ class PathApproximator
// subdividing the curve we are currently operating on.
let rightChild = freeBuffers.length > 0 ? freeBuffers.pop() : [];

PathApproximator.#bezierSubdivide(parent, leftChild, rightChild, subdivisionBuffer1, count);
PathApproximator._bezierSubdivide(parent, leftChild, rightChild, subdivisionBuffer1, count);

// We re-use the buffer of the parent for one of the children, so that we save one allocation per iteration.
for (let i = 0; i < count; ++i) {
Expand Down Expand Up @@ -84,9 +84,9 @@ class PathApproximator
let v3 = i < controlPointsLength - 1 ? controlPoints[i + 1] : v2.add(v2).subtract(v1);
let v4 = i < controlPointsLength - 2 ? controlPoints[i + 2] : v3.add(v3).subtract(v2);

for (let c = 0; c < PathApproximator.#catmull_detail; c++) {
result.push(PathApproximator.#catmullFindPoint(v1, v2, v3, v4, Math.fround(c) / PathApproximator.#catmull_detail));
result.push(PathApproximator.#catmullFindPoint(v1, v2, v3, v4, Math.fround(c + 1) / PathApproximator.#catmull_detail));
for (let c = 0; c < catmull_detail; c++) {
result.push(PathApproximator._catmullFindPoint(v1, v2, v3, v4, Math.fround(c) / catmull_detail));
result.push(PathApproximator._catmullFindPoint(v1, v2, v3, v4, Math.fround(c + 1) / catmull_detail));
}
}

Expand Down Expand Up @@ -157,8 +157,8 @@ class PathApproximator
// is: 2 * Math.Acos(1 - TOLERANCE / r)
// The special case is required for extremely short sliders where the radius is smaller than
// the tolerance. This is a pathological rather than a realistic case.
let amountPoints = 2 * r <= PathApproximator.#circular_arc_tolerance ? 2
: Math.max(2, Math.ceil(thetaRange / (2 * Math.acos(1 - PathApproximator.#circular_arc_tolerance / r))));
let amountPoints = 2 * r <= circular_arc_tolerance ? 2
: Math.max(2, Math.ceil(thetaRange / (2 * Math.acos(1 - circular_arc_tolerance / r))));

let output = [];
let fract, theta, o;
Expand Down Expand Up @@ -196,7 +196,7 @@ class PathApproximator

let result = [];

let weights = PathApproximator.#barycentricWeights(controlPoints);
let weights = PathApproximator._barycentricWeights(controlPoints);

let minX = controlPoints[0].x;
let maxX = controlPoints[0].x;
Expand All @@ -210,7 +210,7 @@ class PathApproximator

for (let i = 0; i < num_steps; i++) {
let x = minX + dx / (num_steps - 1) * i;
let y = Math.fround(PathApproximator.#barycentricLagrange(controlPoints, weights, x));
let y = Math.fround(PathApproximator._barycentricLagrange(controlPoints, weights, x));

result.push(new Vector2(x, y));
}
Expand All @@ -223,7 +223,7 @@ class PathApproximator
* Can be used as a helper function to compute a Lagrange polynomial repeatedly.
* @param points An array of coordinates. No two x should be the same.
*/
static #barycentricWeights(points)
static _barycentricWeights(points)
{
let n = points.length;
let w = [];
Expand All @@ -249,7 +249,7 @@ class PathApproximator
* @param weights An array of precomputed barycentric weights.
* @param time The x coordinate to calculate the basis polynomial for.
*/
static #barycentricLagrange(points, weights, time)
static _barycentricLagrange(points, weights, time)
{
if (points === null || points.Length === 0) {
throw new Error("points must contain at least one point");
Expand Down Expand Up @@ -285,7 +285,7 @@ class PathApproximator
* @param controlPoints The control points to check for flatness.
* @returns Whether the control points are flat enough.
*/
static #bezierIsFlatEnough(controlPoints)
static _bezierIsFlatEnough(controlPoints)
{
let sub, sum, scale;

Expand All @@ -294,7 +294,7 @@ class PathApproximator
sub = controlPoints[i - 1].subtract(scale);
sum = sub.add(controlPoints[i + 1]);

if (sum.length() ** 2 > PathApproximator.#bezier_tolerance ** 2 * 4) {
if (sum.length() ** 2 > bezier_tolerance ** 2 * 4) {
return false;
}
}
Expand All @@ -312,7 +312,7 @@ class PathApproximator
* @param subdivisionBuffer The first buffer containing the current subdivision state.
* @param count The number of control points in the original list.
*/
static #bezierSubdivide(controlPoints, l, r, subdivisionBuffer, count)
static _bezierSubdivide(controlPoints, l, r, subdivisionBuffer, count)
{
let midpoints = subdivisionBuffer;

Expand All @@ -339,12 +339,12 @@ class PathApproximator
* @param subdivisionBuffer1 The first buffer containing the current subdivision state.
* @param subdivisionBuffer2 The second buffer containing the current subdivision state.
*/
static #bezierApproximate(controlPoints, output, subdivisionBuffer1, subdivisionBuffer2, count)
static _bezierApproximate(controlPoints, output, subdivisionBuffer1, subdivisionBuffer2, count)
{
let l = subdivisionBuffer2;
let r = subdivisionBuffer1;

PathApproximator.#bezierSubdivide(controlPoints, l, r, subdivisionBuffer1, count);
PathApproximator._bezierSubdivide(controlPoints, l, r, subdivisionBuffer1, count);

for (let i = 0; i < count - 1; ++i) {
l[count + i] = r[i + 1];
Expand All @@ -369,7 +369,7 @@ class PathApproximator
* @param t The parameter at which to find the point on the spline, in the range [0, 1].
* @returns The point on the spline at t.
*/
static #catmullFindPoint(vec1, vec2, vec3, vec4, t)
static _catmullFindPoint(vec1, vec2, vec3, vec4, t)
{
let t2 = Math.fround(t * t);
let t3 = Math.fround(t * t2);
Expand Down
72 changes: 32 additions & 40 deletions src/Utils/SliderPath.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,18 @@ const Vector2 = require('./Vector2');

class SliderPath
{
/**
* The user-set distance of the path. If non-null, <see cref="Distance"/> will match this value,
* and the path will be shortened/lengthened to match this length.
*/
expectedDistance;

/**
* The control points of the path.
*/
controlPoints;

calculatedPath;
cumulativeLength;
#pathCache;

calculatedLength;

constructor(controlPoints, expectedDistance = null)
{
/**
* The control points of the path.
*/
this.controlPoints = controlPoints.slice();

/**
* The user-set distance of the path. If non-null, <see cref="Distance"/> will match this value,
* and the path will be shortened/lengthened to match this length.
*/
this.expectedDistance = expectedDistance;
}

Expand All @@ -31,7 +23,7 @@ class SliderPath
*/
get distance()
{
this.#ensureValid();
this._ensureValid();

return this.cumulativeLength.length === 0
? 0 : this.cumulativeLength[this.cumulativeLength.length - 1];
Expand All @@ -42,7 +34,7 @@ class SliderPath
*/
get calculatedDistance()
{
this.#ensureValid();
this._ensureValid();

return this.calculatedLength;
}
Expand All @@ -56,22 +48,22 @@ class SliderPath
*/
getPathToProgress(path, p0, p1)
{
this.#ensureValid();
this._ensureValid();

let d0 = this.#progressToDistance(p0);
let d1 = this.#progressToDistance(p1);
let d0 = this._progressToDistance(p0);
let d1 = this._progressToDistance(p1);

let i = 0;

while (i < this.calculatedPath.length && this.cumulativeLength[i++] < d0);

path = [this.#interpolateVertices(i, d0)];
path = [this._interpolateVertices(i, d0)];

while (i < this.calculatedPath.length && this.cumulativeLength[i++] <= d1) {
path.push(this.calculatedPath[i]);
}

path.push(this.#interpolateVertices(i, d1));
path.push(this._interpolateVertices(i, d1));
}

/**
Expand All @@ -81,26 +73,26 @@ class SliderPath
*/
positionAt(progress)
{
this.#ensureValid();
this._ensureValid();

let d = this.#progressToDistance(progress);
let d = this._progressToDistance(progress);

return this.#interpolateVertices(this.#indexOfDistance(d), d);
return this._interpolateVertices(this._indexOfDistance(d), d);
}

#ensureValid()
_ensureValid()
{
if (this.#pathCache) {
if (this._pathCache) {
return;
}

this.#calculatePath();
this.#calculateLength();
this._calculatePath();
this._calculateLength();

this.#pathCache = true;
this._pathCache = true;
}

#calculatePath()
_calculatePath()
{
let controlPointsLength = this.controlPoints.length;

Expand All @@ -127,7 +119,7 @@ class SliderPath
let segmentVertices = vertices.slice(start, i + 1);
let segmentType = this.controlPoints[start].type || 'L';

for (let t of this.#calculateSubPath(segmentVertices, segmentType)) {
for (let t of this._calculateSubPath(segmentVertices, segmentType)) {
if (this.calculatedPath.length === 0
|| this.calculatedPath[this.calculatedPath.length - 1] != t) {
this.calculatedPath.push(t);
Expand All @@ -139,7 +131,7 @@ class SliderPath
}
}

#calculateSubPath(subControlPoints, type)
_calculateSubPath(subControlPoints, type)
{
switch (type) {
case 'L':
Expand Down Expand Up @@ -167,7 +159,7 @@ class SliderPath
return PathApproximator.approximateBezier(subControlPoints);
}

#calculateLength()
_calculateLength()
{
this.calculatedLength = 0;
this.cumulativeLength = [0];
Expand Down Expand Up @@ -212,16 +204,16 @@ class SliderPath
}
}

#indexOfDistance(d)
_indexOfDistance(d)
{
let i = this.#binarySearch(this.cumulativeLength, d);
let i = this._binarySearch(this.cumulativeLength, d);

if (i < 0) i = ~i;

return i;
}

#binarySearch(arr, x)
_binarySearch(arr, x)
{
let start = 0, mid, end = arr.length - 1;

Expand All @@ -242,12 +234,12 @@ class SliderPath
return Math.floor((start + end) / 2);
}

#progressToDistance(progress)
_progressToDistance(progress)
{
return Math.min(Math.max(progress, 0), 1) * this.distance;
}

#interpolateVertices(i, d)
_interpolateVertices(i, d)
{
if (this.calculatedPath.length === 0)
return new Vector2(0, 0);
Expand Down

0 comments on commit 9d398f2

Please sign in to comment.