plotboilerplate 1.28.1 → 1.29.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.
Files changed (66) hide show
  1. package/README.md +8 -0
  2. package/dist/index.esm.js +335 -39
  3. package/dist/index.esm.js.map +1 -1
  4. package/dist/index.esm.min.js +1 -1
  5. package/dist/index.esm.min.js.map +1 -1
  6. package/dist/plotboilerplate.browser.min.js +1 -1
  7. package/dist/plotboilerplate.browser.min.js.map +1 -1
  8. package/dist/plotboilerplate.js +335 -37
  9. package/dist/plotboilerplate.min.js +1 -1
  10. package/package.json +1 -1
  11. package/src/cjs/Circle.d.ts +70 -3
  12. package/src/cjs/Circle.js +159 -4
  13. package/src/cjs/Circle.js.map +1 -1
  14. package/src/cjs/Triangle.d.ts +40 -4
  15. package/src/cjs/Triangle.js +127 -31
  16. package/src/cjs/Triangle.js.map +1 -1
  17. package/src/cjs/VertTuple.d.ts +4 -1
  18. package/src/cjs/VertTuple.js +6 -1
  19. package/src/cjs/VertTuple.js.map +1 -1
  20. package/src/cjs/Vertex.d.ts +25 -2
  21. package/src/cjs/Vertex.js +43 -1
  22. package/src/cjs/Vertex.js.map +1 -1
  23. package/src/cjs/utils/algorithms/minimalContainingCircleFromPoints.d.ts +21 -0
  24. package/src/cjs/utils/algorithms/minimalContainingCircleFromPoints.js +73 -0
  25. package/src/cjs/utils/algorithms/minimalContainingCircleFromPoints.js.map +1 -0
  26. package/src/cjs/utils/algorithms/minimalEnclosingCircleFromPoints.d.ts +21 -0
  27. package/src/cjs/utils/algorithms/minimalEnclosingCircleFromPoints.js +73 -0
  28. package/src/cjs/utils/algorithms/minimalEnclosingCircleFromPoints.js.map +1 -0
  29. package/src/cjs/utils/algorithms/pointsMinimalContainingCircle.d.ts +21 -0
  30. package/src/cjs/utils/algorithms/pointsMinimalContainingCircle.js +73 -0
  31. package/src/cjs/utils/algorithms/pointsMinimalContainingCircle.js.map +1 -0
  32. package/src/cjs/utils/algorithms/solveApollonius3.d.ts +69 -0
  33. package/src/cjs/utils/algorithms/solveApollonius3.js +118 -0
  34. package/src/cjs/utils/algorithms/solveApollonius3.js.map +1 -0
  35. package/src/esm/Circle.d.ts +70 -3
  36. package/src/esm/Circle.js +159 -4
  37. package/src/esm/Circle.js.map +1 -1
  38. package/src/esm/Triangle.d.ts +40 -4
  39. package/src/esm/Triangle.js +128 -32
  40. package/src/esm/Triangle.js.map +1 -1
  41. package/src/esm/VertTuple.d.ts +4 -1
  42. package/src/esm/VertTuple.js +6 -1
  43. package/src/esm/VertTuple.js.map +1 -1
  44. package/src/esm/Vertex.d.ts +25 -2
  45. package/src/esm/Vertex.js +44 -2
  46. package/src/esm/Vertex.js.map +1 -1
  47. package/src/esm/utils/algorithms/minimalContainingCircleFromPoints.d.ts +21 -0
  48. package/src/esm/utils/algorithms/minimalContainingCircleFromPoints.js +69 -0
  49. package/src/esm/utils/algorithms/minimalContainingCircleFromPoints.js.map +1 -0
  50. package/src/esm/utils/algorithms/minimalEnclosingCircleFromPoints.d.ts +21 -0
  51. package/src/esm/utils/algorithms/minimalEnclosingCircleFromPoints.js +69 -0
  52. package/src/esm/utils/algorithms/minimalEnclosingCircleFromPoints.js.map +1 -0
  53. package/src/esm/utils/algorithms/pointsMinimalContainingCircle.d.ts +21 -0
  54. package/src/esm/utils/algorithms/pointsMinimalContainingCircle.js +69 -0
  55. package/src/esm/utils/algorithms/pointsMinimalContainingCircle.js.map +1 -0
  56. package/src/esm/utils/algorithms/solveApollonius3.d.ts +69 -0
  57. package/src/esm/utils/algorithms/solveApollonius3.js +114 -0
  58. package/src/esm/utils/algorithms/solveApollonius3.js.map +1 -0
  59. package/src/index-gl.js +5 -2
  60. package/src/index.js +25 -17
  61. package/src/ts/Circle.ts +178 -5
  62. package/src/ts/Triangle.ts +148 -41
  63. package/src/ts/VertTuple.ts +14 -1
  64. package/src/ts/Vertex.ts +44 -2
  65. package/src/ts/utils/algorithms/minimalEnclosingCircleFromPoints.ts +69 -0
  66. package/src/ts/utils/algorithms/solveApollonius3.ts +132 -0
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ /**
3
+ * Calculate the minimal containing circle from a set of points.
4
+ *
5
+ * The number of points must be at least 2. Otherwise the function returns null.
6
+ *
7
+ * Inspired by https://github.com/rowanwins/smallest-enclosing-circle.
8
+ *
9
+ * @param {XYCoords[]} points
10
+ * @returns
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.minimalEnclosingCircleFromPoints = void 0;
14
+ var Circle_1 = require("../../Circle");
15
+ var Triangle_1 = require("../../Triangle");
16
+ var VertTuple_1 = require("../../VertTuple");
17
+ var Vertex_1 = require("../../Vertex");
18
+ /**
19
+ * Calculate the minimal containing circle from a set of points.
20
+ *
21
+ * The number of points must be at least 2. Otherwise the function returns null.
22
+ *
23
+ * @param {XYCoords[]} points
24
+ * @returns {Circle | null} The minimal containing circle or null if the point count is lower than 2.
25
+ */
26
+ var minimalEnclosingCircleFromPoints = function (points) {
27
+ if (points.length <= 1) {
28
+ return null;
29
+ }
30
+ var circleObject = wetzlsAlgorithm(points);
31
+ return new Circle_1.Circle(new Vertex_1.Vertex(circleObject.center.x, circleObject.center.y), circleObject.radius);
32
+ };
33
+ exports.minimalEnclosingCircleFromPoints = minimalEnclosingCircleFromPoints;
34
+ /**
35
+ * This initiates the actual algorithm but return a shallow circle representation.
36
+ *
37
+ * @param points
38
+ * @returns
39
+ */
40
+ var wetzlsAlgorithm = function (points) {
41
+ return minimumContainingCircle(points, points.length, [], 0);
42
+ };
43
+ /**
44
+ * Pre: points.length >= 2
45
+ * @param {Vertex[]} points
46
+ * @param n
47
+ * @param boundary
48
+ * @param boundaryLength
49
+ * @returns
50
+ */
51
+ var minimumContainingCircle = function (points, n, boundary, boundaryLength) {
52
+ if (boundaryLength === 3) {
53
+ return Triangle_1.Triangle.utils.calcCircumcircle(boundary[0], boundary[1], boundary[2]);
54
+ }
55
+ else if (n === 1 && boundaryLength === 0) {
56
+ return { center: { x: points[0].x, y: points[0].y }, radius: 0 };
57
+ }
58
+ else if (n === 0 && boundaryLength === 2) {
59
+ return VertTuple_1.VertTuple.vtutils.calcCircumcircle(boundary[0], boundary[1]);
60
+ }
61
+ else if (n === 1 && boundaryLength === 1) {
62
+ return VertTuple_1.VertTuple.vtutils.calcCircumcircle(boundary[0], points[0]);
63
+ }
64
+ else {
65
+ var localCircle = minimumContainingCircle(points, n - 1, boundary, boundaryLength);
66
+ if (!Circle_1.Circle.circleUtils.containsPoint(localCircle.center, localCircle.radius, points[n - 1])) {
67
+ boundary[boundaryLength++] = points[n - 1];
68
+ return minimumContainingCircle(points, n - 1, boundary, boundaryLength);
69
+ }
70
+ return localCircle;
71
+ }
72
+ };
73
+ //# sourceMappingURL=minimalEnclosingCircleFromPoints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"minimalEnclosingCircleFromPoints.js","sourceRoot":"","sources":["../../../ts/utils/algorithms/minimalEnclosingCircleFromPoints.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AAEH,uCAA+C;AAC/C,2CAA0C;AAC1C,6CAA4C;AAC5C,uCAAsC;AAGtC;;;;;;;GAOG;AACI,IAAM,gCAAgC,GAAG,UAAC,MAAkB;IACjE,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAC7C,OAAO,IAAI,eAAM,CAAC,IAAI,eAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;AACnG,CAAC,CAAC;AANW,QAAA,gCAAgC,oCAM3C;AAEF;;;;;GAKG;AACH,IAAM,eAAe,GAAG,UAAC,MAAkB;IACzC,OAAO,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AAC/D,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,IAAM,uBAAuB,GAAG,UAAC,MAAkB,EAAE,CAAS,EAAE,QAAoB,EAAE,cAAsB;IAC1G,IAAI,cAAc,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,mBAAQ,CAAC,KAAK,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAChF,CAAC;SAAM,IAAI,CAAC,KAAK,CAAC,IAAI,cAAc,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IACnE,CAAC;SAAM,IAAI,CAAC,KAAK,CAAC,IAAI,cAAc,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO,qBAAS,CAAC,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACtE,CAAC;SAAM,IAAI,CAAC,KAAK,CAAC,IAAI,cAAc,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO,qBAAS,CAAC,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACpE,CAAC;SAAM,CAAC;QACN,IAAM,WAAW,GAAY,uBAAuB,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;QAC9F,IAAI,CAAC,eAAM,CAAC,WAAW,CAAC,aAAa,CAAC,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7F,QAAQ,CAAC,cAAc,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC3C,OAAO,uBAAuB,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;QAC1E,CAAC;QACD,OAAO,WAAW,CAAC;IACrB,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Calculate the minimal containing circle from a set of points.
3
+ *
4
+ * The number of points must be at least 2. Otherwise the function returns null.
5
+ *
6
+ * Inspired by https://github.com/rowanwins/smallest-enclosing-circle.
7
+ *
8
+ * @param {XYCoords[]} points
9
+ * @returns
10
+ */
11
+ import { Circle } from "../../Circle";
12
+ import { XYCoords } from "../../interfaces";
13
+ /**
14
+ * Calculate the minimal containing circle from a set of points.
15
+ *
16
+ * The number of points must be at least 2. Otherwise the function returns null.
17
+ *
18
+ * @param {XYCoords[]} points
19
+ * @returns {Circle | null} The minimal containing circle or null if the point count is lower than 2.
20
+ */
21
+ export declare const pointsMinimalContainingCircle: (points: XYCoords[]) => Circle | null;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ /**
3
+ * Calculate the minimal containing circle from a set of points.
4
+ *
5
+ * The number of points must be at least 2. Otherwise the function returns null.
6
+ *
7
+ * Inspired by https://github.com/rowanwins/smallest-enclosing-circle.
8
+ *
9
+ * @param {XYCoords[]} points
10
+ * @returns
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.pointsMinimalContainingCircle = void 0;
14
+ var Circle_1 = require("../../Circle");
15
+ var Triangle_1 = require("../../Triangle");
16
+ var VertTuple_1 = require("../../VertTuple");
17
+ var Vertex_1 = require("../../Vertex");
18
+ /**
19
+ * Calculate the minimal containing circle from a set of points.
20
+ *
21
+ * The number of points must be at least 2. Otherwise the function returns null.
22
+ *
23
+ * @param {XYCoords[]} points
24
+ * @returns {Circle | null} The minimal containing circle or null if the point count is lower than 2.
25
+ */
26
+ var pointsMinimalContainingCircle = function (points) {
27
+ if (points.length <= 1) {
28
+ return null;
29
+ }
30
+ var circleObject = wetzlsAlgorithm(points);
31
+ return new Circle_1.Circle(new Vertex_1.Vertex(circleObject.center.x, circleObject.center.y), circleObject.radius);
32
+ };
33
+ exports.pointsMinimalContainingCircle = pointsMinimalContainingCircle;
34
+ /**
35
+ * This initiates the actual algorithm but return a shallow circle representation.
36
+ *
37
+ * @param points
38
+ * @returns
39
+ */
40
+ var wetzlsAlgorithm = function (points) {
41
+ return minimumContainingCircle(points, points.length, [], 0);
42
+ };
43
+ /**
44
+ * Pre: points.length >= 2
45
+ * @param {Vertex[]} points
46
+ * @param n
47
+ * @param boundary
48
+ * @param boundaryLength
49
+ * @returns
50
+ */
51
+ var minimumContainingCircle = function (points, n, boundary, boundaryLength) {
52
+ if (boundaryLength === 3) {
53
+ return Triangle_1.Triangle.utils.calcCircumcircle(boundary[0], boundary[1], boundary[2]);
54
+ }
55
+ else if (n === 1 && boundaryLength === 0) {
56
+ return { center: { x: points[0].x, y: points[0].y }, radius: 0 };
57
+ }
58
+ else if (n === 0 && boundaryLength === 2) {
59
+ return VertTuple_1.VertTuple.vtutils.calcCircumcircle(boundary[0], boundary[1]);
60
+ }
61
+ else if (n === 1 && boundaryLength === 1) {
62
+ return VertTuple_1.VertTuple.vtutils.calcCircumcircle(boundary[0], points[0]);
63
+ }
64
+ else {
65
+ var localCircle = minimumContainingCircle(points, n - 1, boundary, boundaryLength);
66
+ if (!Circle_1.Circle.circleUtils.containsPoint(points[n - 1], localCircle)) {
67
+ boundary[boundaryLength++] = points[n - 1];
68
+ return minimumContainingCircle(points, n - 1, boundary, boundaryLength);
69
+ }
70
+ return localCircle;
71
+ }
72
+ };
73
+ //# sourceMappingURL=pointsMinimalContainingCircle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pointsMinimalContainingCircle.js","sourceRoot":"","sources":["../../../ts/utils/algorithms/pointsMinimalContainingCircle.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AAEH,uCAA+C;AAC/C,2CAA0C;AAC1C,6CAA4C;AAC5C,uCAAsC;AAGtC;;;;;;;GAOG;AACI,IAAM,6BAA6B,GAAG,UAAC,MAAkB;IAC9D,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAC7C,OAAO,IAAI,eAAM,CAAC,IAAI,eAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;AACnG,CAAC,CAAC;AANW,QAAA,6BAA6B,iCAMxC;AAEF;;;;;GAKG;AACH,IAAM,eAAe,GAAG,UAAC,MAAkB;IACzC,OAAO,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AAC/D,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,IAAM,uBAAuB,GAAG,UAAC,MAAkB,EAAE,CAAS,EAAE,QAAoB,EAAE,cAAsB;IAC1G,IAAI,cAAc,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,mBAAQ,CAAC,KAAK,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAChF,CAAC;SAAM,IAAI,CAAC,KAAK,CAAC,IAAI,cAAc,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IACnE,CAAC;SAAM,IAAI,CAAC,KAAK,CAAC,IAAI,cAAc,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO,qBAAS,CAAC,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACtE,CAAC;SAAM,IAAI,CAAC,KAAK,CAAC,IAAI,cAAc,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO,qBAAS,CAAC,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACpE,CAAC;SAAM,CAAC;QACN,IAAM,WAAW,GAAY,uBAAuB,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;QAC9F,IAAI,CAAC,eAAM,CAAC,WAAW,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,EAAE,CAAC;YAClE,QAAQ,CAAC,cAAc,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC3C,OAAO,uBAAuB,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;QAC1E,CAAC;QACD,OAAO,WAAW,CAAC;IACrB,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * A solver for the Apollonian circle problem:
3
+ * find the circle that touches three other circles in extactly one point (each).
4
+ * The solution is not necesarily unique.
5
+ *
6
+ * For each of the three circles a boolean attribute can be passed that determines if the
7
+ * resultint circle should touch the input circle should be touched on the inside or outside.
8
+ *
9
+ * Not that there can be condition when the circle cannot be calculated (e.g. all circles
10
+ * have the same size and are colinear).
11
+ *
12
+ * Found at
13
+ * https://stackoverflow.com/questions/79281573/algorithm-for-finding-enclosing-circles-for-3-other-circles
14
+ *
15
+ * solveApollonius(Coord c1, Coord c2, Coord c3, int s1, int s2, int s3) {
16
+ // https://github.com/DIKU-Steiner/ProGAL/blob/master/src/ProGAL/geom2d/ApolloniusSolver.java
17
+
18
+ var x1 = c1.x;
19
+ var y1 = c1.y;
20
+ var r1 = c1.z;
21
+ var x2 = c2.x;
22
+ var y2 = c2.y;
23
+ var r2 = c2.z;
24
+ var x3 = c3.x;
25
+ var y3 = c3.y;
26
+ var r3 = c3.z;
27
+
28
+ // Currently optimized for fewest multiplications.
29
+ var v11 = 2 * x2 - 2 * x1;
30
+ var v12 = 2 * y2 - 2 * y1;
31
+ var v13 = x1 * x1 - x2 * x2 + y1 * y1 - y2 * y2 - r1 * r1 + r2 * r2;
32
+ var v14 = 2 * s2 * r2 - 2 * s1 * r1;
33
+
34
+ var v21 = 2 * x3 - 2 * x2;
35
+ var v22 = 2 * y3 - 2 * y2;
36
+ var v23 = x2 * x2 - x3 * x3 + y2 * y2 - y3 * y3 - r2 * r2 + r3 * r3;
37
+ var v24 = 2 * s3 * r3 - 2 * s2 * r2;
38
+
39
+ var w12 = v12 / v11;
40
+ var w13 = v13 / v11;
41
+ var w14 = v14 / v11;
42
+
43
+ var w22 = v22 / v21 - w12;
44
+ var w23 = v23 / v21 - w13;
45
+ var w24 = v24 / v21 - w14;
46
+
47
+ var P = -w23 / w22;
48
+ var Q = w24 / w22;
49
+ var M = -w12 * P - w13;
50
+ var N = w14 - w12 * Q;
51
+
52
+ var a = N * N + Q * Q - 1;
53
+ var b = 2 * M * N - 2 * N * x1 + 2 * P * Q - 2 * Q * y1 + 2 * s1 * r1;
54
+ var c = x1 * x1 + M * M - 2 * M * x1 + P * P + y1 * y1 - 2 * P * y1 - r1 * r1;
55
+
56
+ // Find a root of a quadratic equation. This requires the circle centers not
57
+ // to be e.g. colinear
58
+ var D = b * b - 4 * a * c;
59
+ var rs = (-b - Math.sqrt(D)) / (2 * a);
60
+ var xs = M + N * rs;
61
+ var ys = P + Q * rs;
62
+
63
+ return (xs, ys, rs);
64
+ }
65
+ *
66
+ * @date 2026-07-03
67
+ */
68
+ import { Circle, ICircle } from "../../Circle";
69
+ export declare const solveApollonius3: (c1: ICircle, c2: ICircle, c3: ICircle, circle1Inside?: boolean, circle2Inside?: boolean, circle3Inside?: boolean) => Circle;
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ /**
3
+ * A solver for the Apollonian circle problem:
4
+ * find the circle that touches three other circles in extactly one point (each).
5
+ * The solution is not necesarily unique.
6
+ *
7
+ * For each of the three circles a boolean attribute can be passed that determines if the
8
+ * resultint circle should touch the input circle should be touched on the inside or outside.
9
+ *
10
+ * Not that there can be condition when the circle cannot be calculated (e.g. all circles
11
+ * have the same size and are colinear).
12
+ *
13
+ * Found at
14
+ * https://stackoverflow.com/questions/79281573/algorithm-for-finding-enclosing-circles-for-3-other-circles
15
+ *
16
+ * solveApollonius(Coord c1, Coord c2, Coord c3, int s1, int s2, int s3) {
17
+ // https://github.com/DIKU-Steiner/ProGAL/blob/master/src/ProGAL/geom2d/ApolloniusSolver.java
18
+
19
+ var x1 = c1.x;
20
+ var y1 = c1.y;
21
+ var r1 = c1.z;
22
+ var x2 = c2.x;
23
+ var y2 = c2.y;
24
+ var r2 = c2.z;
25
+ var x3 = c3.x;
26
+ var y3 = c3.y;
27
+ var r3 = c3.z;
28
+
29
+ // Currently optimized for fewest multiplications.
30
+ var v11 = 2 * x2 - 2 * x1;
31
+ var v12 = 2 * y2 - 2 * y1;
32
+ var v13 = x1 * x1 - x2 * x2 + y1 * y1 - y2 * y2 - r1 * r1 + r2 * r2;
33
+ var v14 = 2 * s2 * r2 - 2 * s1 * r1;
34
+
35
+ var v21 = 2 * x3 - 2 * x2;
36
+ var v22 = 2 * y3 - 2 * y2;
37
+ var v23 = x2 * x2 - x3 * x3 + y2 * y2 - y3 * y3 - r2 * r2 + r3 * r3;
38
+ var v24 = 2 * s3 * r3 - 2 * s2 * r2;
39
+
40
+ var w12 = v12 / v11;
41
+ var w13 = v13 / v11;
42
+ var w14 = v14 / v11;
43
+
44
+ var w22 = v22 / v21 - w12;
45
+ var w23 = v23 / v21 - w13;
46
+ var w24 = v24 / v21 - w14;
47
+
48
+ var P = -w23 / w22;
49
+ var Q = w24 / w22;
50
+ var M = -w12 * P - w13;
51
+ var N = w14 - w12 * Q;
52
+
53
+ var a = N * N + Q * Q - 1;
54
+ var b = 2 * M * N - 2 * N * x1 + 2 * P * Q - 2 * Q * y1 + 2 * s1 * r1;
55
+ var c = x1 * x1 + M * M - 2 * M * x1 + P * P + y1 * y1 - 2 * P * y1 - r1 * r1;
56
+
57
+ // Find a root of a quadratic equation. This requires the circle centers not
58
+ // to be e.g. colinear
59
+ var D = b * b - 4 * a * c;
60
+ var rs = (-b - Math.sqrt(D)) / (2 * a);
61
+ var xs = M + N * rs;
62
+ var ys = P + Q * rs;
63
+
64
+ return (xs, ys, rs);
65
+ }
66
+ *
67
+ * @date 2026-07-03
68
+ */
69
+ Object.defineProperty(exports, "__esModule", { value: true });
70
+ exports.solveApollonius3 = void 0;
71
+ var Circle_1 = require("../../Circle");
72
+ var Vertex_1 = require("../../Vertex");
73
+ var solveApollonius3 = function (c1, c2, c3, circle1Inside, circle2Inside, circle3Inside) {
74
+ // https://github.com/DIKU-Steiner/ProGAL/blob/master/src/ProGAL/geom2d/ApolloniusSolver.java
75
+ var x1 = c1.center.x;
76
+ var y1 = c1.center.y;
77
+ var r1 = c1.radius;
78
+ var x2 = c2.center.x;
79
+ var y2 = c2.center.y;
80
+ var r2 = c2.radius;
81
+ var x3 = c3.center.x;
82
+ var y3 = c3.center.y;
83
+ var r3 = c3.radius;
84
+ var s1 = Boolean(circle1Inside) ? 1 : -1;
85
+ var s2 = Boolean(circle2Inside) ? 1 : -1;
86
+ var s3 = Boolean(circle3Inside) ? 1 : -1;
87
+ // Currently optimized for fewest multiplications.
88
+ var v11 = 2 * x2 - 2 * x1;
89
+ var v12 = 2 * y2 - 2 * y1;
90
+ var v13 = x1 * x1 - x2 * x2 + y1 * y1 - y2 * y2 - r1 * r1 + r2 * r2;
91
+ var v14 = 2 * s2 * r2 - 2 * s1 * r1;
92
+ var v21 = 2 * x3 - 2 * x2;
93
+ var v22 = 2 * y3 - 2 * y2;
94
+ var v23 = x2 * x2 - x3 * x3 + y2 * y2 - y3 * y3 - r2 * r2 + r3 * r3;
95
+ var v24 = 2 * s3 * r3 - 2 * s2 * r2;
96
+ var w12 = v12 / v11;
97
+ var w13 = v13 / v11;
98
+ var w14 = v14 / v11;
99
+ var w22 = v22 / v21 - w12;
100
+ var w23 = v23 / v21 - w13;
101
+ var w24 = v24 / v21 - w14;
102
+ var P = -w23 / w22;
103
+ var Q = w24 / w22;
104
+ var M = -w12 * P - w13;
105
+ var N = w14 - w12 * Q;
106
+ var a = N * N + Q * Q - 1;
107
+ var b = 2 * M * N - 2 * N * x1 + 2 * P * Q - 2 * Q * y1 + 2 * s1 * r1;
108
+ var c = x1 * x1 + M * M - 2 * M * x1 + P * P + y1 * y1 - 2 * P * y1 - r1 * r1;
109
+ // Find a root of a quadratic equation. This requires the circle centers not
110
+ // to be e.g. colinear
111
+ var D = b * b - 4 * a * c;
112
+ var rs = (-b - Math.sqrt(D)) / (2 * a);
113
+ var xs = M + N * rs;
114
+ var ys = P + Q * rs;
115
+ return new Circle_1.Circle(new Vertex_1.Vertex(xs, ys), Math.abs(rs));
116
+ };
117
+ exports.solveApollonius3 = solveApollonius3;
118
+ //# sourceMappingURL=solveApollonius3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solveApollonius3.js","sourceRoot":"","sources":["../../../ts/utils/algorithms/solveApollonius3.ts"],"names":[],"mappings":"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"}
@@ -14,7 +14,15 @@
14
14
  * @modified 2022-08-23 Added the `closestPoint` function.
15
15
  * @modified 2025-04-09 Added the `Circle.move(amount: XYCoords)` method.
16
16
  * @modified 2025-04-16 Class `Circle` now implements interface `Intersectable`.
17
- * @version 1.5.0
17
+ * @modified 2026-06-10 Adding the utility function `Circle.circleUtils.containsPoint`.
18
+ * @modified 2026-06-10 Adding the `Circle.clone` method.
19
+ * @modified 2026-01-13 Adding helper function `Circle.circleUtils.containsPoint` and refactored the member method `containsPoint`.
20
+ * @modified 2026-07-03 Adding the optional `epsilon` parameter to the `Circle.containsCircle` method.
21
+ * @modified 2026-07-03 Fixing the `Circle.clone` method; the center had not been cloned at all, this was fixed.
22
+ * @modified 2026-07-08 Adding the `Circle.setRadius` method (for chaining).
23
+ * @mofified 2026-07-31 Adding the `radicalAxis(Circle)` method. Added the `Circle.circleUtils.createRadicalAxisHelperCircle` and `.circleDistance` helper methods.
24
+ * @modified 2026-08-03 Adding `Circle.tangentsFromPoint`.
25
+ * @version 1.7.0
18
26
  **/
19
27
  import { Bounds } from "./Bounds";
20
28
  import { Line } from "./Line";
@@ -22,6 +30,11 @@ import { Vector } from "./Vector";
22
30
  import { VertTuple } from "./VertTuple";
23
31
  import { Vertex } from "./Vertex";
24
32
  import { IBounded, Intersectable, SVGSerializable, UID, XYCoords } from "./interfaces";
33
+ export interface ICircle {
34
+ center: XYCoords;
35
+ radius: number;
36
+ radius_squared?: number;
37
+ }
25
38
  /**
26
39
  * @classdesc A simple circle: center point and radius.
27
40
  *
@@ -33,7 +46,7 @@ import { IBounded, Intersectable, SVGSerializable, UID, XYCoords } from "./inter
33
46
  * @requires UID
34
47
  * @requires UIDGenerator
35
48
  **/
36
- export declare class Circle implements IBounded, Intersectable, SVGSerializable {
49
+ export declare class Circle implements IBounded, ICircle, Intersectable, SVGSerializable {
37
50
  /**
38
51
  * Required to generate proper CSS classes and other class related IDs.
39
52
  **/
@@ -75,6 +88,17 @@ export declare class Circle implements IBounded, Intersectable, SVGSerializable
75
88
  * @param {number} radius - The radius of the circle.
76
89
  */
77
90
  constructor(center: Vertex, radius: number);
91
+ /**
92
+ * Set the radius of this circle.
93
+ * The method is meant for chaining, you may also alter the `radius` attribute directly.
94
+ *
95
+ * @method setRadius
96
+ * @param {number} radius - The amount to move.
97
+ * @instance
98
+ * @memberof Circle
99
+ * @return {Circle} this for chaining
100
+ **/
101
+ setRadius(radius: number): Circle;
78
102
  /**
79
103
  * Move the circle by the given amount.
80
104
  *
@@ -104,7 +128,7 @@ export declare class Circle implements IBounded, Intersectable, SVGSerializable
104
128
  * @memberof Circle
105
129
  * @return {boolean} `true` if any only if the given circle is completely inside this circle.
106
130
  */
107
- containsCircle(circle: Circle): boolean;
131
+ containsCircle(circle: Circle, epsilon?: number): boolean;
108
132
  /**
109
133
  * Calculate the distance from this circle to the given line.
110
134
  *
@@ -192,6 +216,20 @@ export declare class Circle implements IBounded, Intersectable, SVGSerializable
192
216
  * @returns
193
217
  */
194
218
  lineIntersectionTangents(line: VertTuple<any>, inVectorBoundsOnly?: boolean): Array<Vector>;
219
+ /**
220
+ * Calculate the radical axis of this and a different circle.
221
+ * The two circles must not be co-centric.
222
+ *
223
+ * See this article for details:
224
+ * https://www.cut-the-knot.org/Curriculum/Geometry/GeoGebra/RadicalAxes.shtml
225
+ *
226
+ * @method radicalAxis
227
+ * @instance
228
+ * @memberof Circle
229
+ * @param {Circle} circleB - The second circle to calculated the radical axis for.
230
+ * @return {Line} A line defining the radical axis of the two circles.
231
+ **/
232
+ radicalAxis(circleB: Circle): Line;
195
233
  /**
196
234
  * Calculate the closest point on the outline of this circle to the given point.
197
235
  *
@@ -202,6 +240,27 @@ export declare class Circle implements IBounded, Intersectable, SVGSerializable
202
240
  * @return {Vertex} The closest point on this circle.
203
241
  **/
204
242
  closestPoint(vert: XYCoords): Vertex;
243
+ /**
244
+ * Get the two tangent vectors for the given point.
245
+ * If the point is on or in the circle then null is returned.
246
+ *
247
+ * @method tangentsFromPoint
248
+ * @instance
249
+ * @memberof Circle
250
+ * @param {Vertex} vert - The point to find the two tangents for.
251
+ * @return {[Vector,Vector]} The two tangent vector
252
+ **/
253
+ tangentsFromPoint(vert: Vertex): [Vector, Vector];
254
+ /**
255
+ * Create a deep copy of this circle.
256
+ *
257
+ * @method clone
258
+ * @return {Circle} A new circle, an exact copy of this one.
259
+ * @instance
260
+ * @memberof Circle
261
+ **/
262
+ clone(): Circle;
263
+ static fromICircle(obj: ICircle): Circle;
205
264
  /**
206
265
  * This function should invalidate any installed listeners and invalidate this object.
207
266
  * After calling this function the object might not hold valid data any more and
@@ -210,5 +269,13 @@ export declare class Circle implements IBounded, Intersectable, SVGSerializable
210
269
  destroy(): void;
211
270
  static circleUtils: {
212
271
  vertAt: (angle: number, radius: number) => Vertex;
272
+ containsPoint: (circleCenter: XYCoords, circleRadius: number, point: XYCoords) => boolean;
273
+ createRadicalAxisHelperCircle: (circleA: Circle, circleB: Circle) => Circle;
274
+ /**
275
+ * Calculate the outer distance between two circles. If the circles touch then the
276
+ * distance is 0.0.
277
+ * If the circles intersect then the distance in negative.
278
+ */
279
+ circleDistance: (circleA: Circle, circleB: Circle) => number;
213
280
  };
214
281
  }