cubing 0.35.18 → 0.36.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 (85) hide show
  1. package/dist/esm/alg/index.js +1 -1
  2. package/dist/esm/bluetooth/index.js +53 -5
  3. package/dist/esm/bluetooth/index.js.map +2 -2
  4. package/dist/esm/{chunk-Z6WT2ASL.js → chunk-6OUID4YZ.js} +6 -3
  5. package/dist/esm/{chunk-Z6WT2ASL.js.map → chunk-6OUID4YZ.js.map} +1 -1
  6. package/dist/esm/{chunk-YU62MHVH.js → chunk-7C5DKKWG.js} +35 -3
  7. package/dist/esm/chunk-7C5DKKWG.js.map +7 -0
  8. package/dist/esm/{chunk-TZLV35JV.js → chunk-7LQBLROH.js} +11 -7
  9. package/dist/esm/chunk-7LQBLROH.js.map +7 -0
  10. package/dist/esm/{chunk-UDX76B24.js → chunk-BI4IALY5.js} +99 -6
  11. package/dist/esm/{chunk-UDX76B24.js.map → chunk-BI4IALY5.js.map} +1 -1
  12. package/dist/esm/{chunk-HVZKPYTG.js → chunk-CFNRQVBC.js} +186 -2
  13. package/dist/esm/chunk-CFNRQVBC.js.map +7 -0
  14. package/dist/esm/{chunk-JVS2MAXS.js → chunk-EXWFZEJA.js} +6 -3
  15. package/dist/esm/{chunk-JVS2MAXS.js.map → chunk-EXWFZEJA.js.map} +1 -1
  16. package/dist/esm/{chunk-AA7SSE6X.js → chunk-IBLLQ5L6.js} +2 -2
  17. package/dist/esm/{chunk-AA7SSE6X.js.map → chunk-IBLLQ5L6.js.map} +1 -1
  18. package/dist/esm/{chunk-6KPOQHQA.js → chunk-LCARNWZG.js} +23 -16
  19. package/dist/esm/chunk-LCARNWZG.js.map +7 -0
  20. package/dist/esm/{chunk-LFMH7YXT.js → chunk-OZ7BVDDY.js} +32 -3
  21. package/dist/esm/{chunk-LFMH7YXT.js.map → chunk-OZ7BVDDY.js.map} +2 -2
  22. package/dist/esm/{chunk-FVWUXED6.js → chunk-RCFH7AT2.js} +3 -3
  23. package/dist/esm/{chunk-FVWUXED6.js.map → chunk-RCFH7AT2.js.map} +1 -1
  24. package/dist/esm/{chunk-6FGST3DR.js → chunk-TF2GO5ZC.js} +43 -14
  25. package/dist/esm/chunk-TF2GO5ZC.js.map +7 -0
  26. package/dist/esm/{chunk-LZTD2XRZ.js → chunk-UOAT7IN5.js} +16 -2
  27. package/dist/esm/{chunk-LZTD2XRZ.js.map → chunk-UOAT7IN5.js.map} +1 -1
  28. package/dist/esm/{chunk-EV25IJFC.js → chunk-ZYCJIZDN.js} +2 -1
  29. package/dist/esm/{chunk-EV25IJFC.js.map → chunk-ZYCJIZDN.js.map} +1 -1
  30. package/dist/esm/kpuzzle/index.js +2 -2
  31. package/dist/esm/notation/index.js +4 -4
  32. package/dist/esm/protocol/index.js +4 -4
  33. package/dist/esm/puzzle-geometry/index.js +116 -1
  34. package/dist/esm/puzzle-geometry/index.js.map +2 -2
  35. package/dist/esm/puzzles/index.js +4 -4
  36. package/dist/esm/{puzzles-dynamic-side-events-TEAE45HA.js → puzzles-dynamic-side-events-SRPR4BEO.js} +8 -1
  37. package/dist/esm/{puzzles-dynamic-side-events-TEAE45HA.js.map → puzzles-dynamic-side-events-SRPR4BEO.js.map} +1 -1
  38. package/dist/esm/scramble/index.js +9 -9
  39. package/dist/esm/search/index.js +9 -9
  40. package/dist/esm/{search-dynamic-sgs-side-events-T2RBUDFD.js → search-dynamic-sgs-side-events-QD7TLXPV.js} +6 -6
  41. package/dist/esm/search-dynamic-sgs-side-events-QD7TLXPV.js.map +7 -0
  42. package/dist/esm/{search-dynamic-sgs-unofficial-TJXF7BKM.js → search-dynamic-sgs-unofficial-UEIZW7YS.js} +6 -6
  43. package/dist/esm/search-dynamic-sgs-unofficial-UEIZW7YS.js.map +7 -0
  44. package/dist/esm/{search-dynamic-solve-3x3x3-VY7R3CDP.js → search-dynamic-solve-3x3x3-FJI2OWOW.js} +1 -1
  45. package/dist/esm/{search-dynamic-solve-3x3x3-VY7R3CDP.js.map → search-dynamic-solve-3x3x3-FJI2OWOW.js.map} +1 -1
  46. package/dist/esm/{search-dynamic-solve-4x4x4-I77ZF4Z5.js → search-dynamic-solve-4x4x4-USNQSEDX.js} +6 -6
  47. package/dist/esm/{search-dynamic-solve-4x4x4-I77ZF4Z5.js.map → search-dynamic-solve-4x4x4-USNQSEDX.js.map} +1 -1
  48. package/dist/esm/{search-dynamic-solve-fto-JJ32OJVM.js → search-dynamic-solve-fto-IDE3JR5R.js} +36 -1
  49. package/dist/esm/{search-dynamic-solve-fto-JJ32OJVM.js.map → search-dynamic-solve-fto-IDE3JR5R.js.map} +1 -1
  50. package/dist/esm/{search-dynamic-solve-kilominx-F22YIQDX.js → search-dynamic-solve-kilominx-DUXFWYAF.js} +2 -2
  51. package/dist/esm/{search-dynamic-solve-kilominx-F22YIQDX.js.map → search-dynamic-solve-kilominx-DUXFWYAF.js.map} +1 -1
  52. package/dist/esm/{search-dynamic-solve-master_tetraminx-UF5FKJW6.js → search-dynamic-solve-master_tetraminx-N2NAFS2P.js} +2 -1
  53. package/dist/esm/{search-dynamic-solve-master_tetraminx-UF5FKJW6.js.map → search-dynamic-solve-master_tetraminx-N2NAFS2P.js.map} +1 -1
  54. package/dist/esm/{search-dynamic-solve-sq1-S6V3FTO2.js → search-dynamic-solve-sq1-OKRDTBN4.js} +1 -1
  55. package/dist/esm/{search-dynamic-solve-sq1-S6V3FTO2.js.map → search-dynamic-solve-sq1-OKRDTBN4.js.map} +1 -1
  56. package/dist/esm/{search-worker-inside-generated-string-2SRY6LLB.js → search-worker-inside-generated-string-BOLAH6BY.js} +45 -36
  57. package/dist/esm/search-worker-inside-generated-string-BOLAH6BY.js.map +7 -0
  58. package/dist/esm/search-worker-js-entry-XBNFXQ5S.js +17 -0
  59. package/dist/esm/{search-worker-ts-entry-D3F64FG2.js → search-worker-ts-entry-ERCMEK5N.js} +4 -4
  60. package/dist/esm/{search-worker-ts-entry-D3F64FG2.js.map → search-worker-ts-entry-ERCMEK5N.js.map} +1 -1
  61. package/dist/esm/stream/index.js +1 -1
  62. package/dist/esm/twisty/index.js +179 -34
  63. package/dist/esm/twisty/index.js.map +3 -3
  64. package/dist/esm/{twisty-dynamic-3d-2TN37YPE.js → twisty-dynamic-3d-GJKWHMDR.js} +40 -6
  65. package/dist/esm/twisty-dynamic-3d-GJKWHMDR.js.map +7 -0
  66. package/dist/esm/{twsearch-BDAXZGZU-WI6J7JNA.js → twsearch-BDAXZGZU-4Y6SSRS3.js} +1 -1
  67. package/dist/esm/{twsearch-BDAXZGZU-WI6J7JNA.js.map → twsearch-BDAXZGZU-4Y6SSRS3.js.map} +1 -1
  68. package/dist/esm/{twsearch-DGXZZNDD.js → twsearch-GXY4U67H.js} +3 -3
  69. package/dist/esm/{twsearch-DGXZZNDD.js.map → twsearch-GXY4U67H.js.map} +1 -1
  70. package/dist/types/{TwizzleLink-9f92123d.d.ts → TwizzleLink-f8f2c814.d.ts} +17 -17
  71. package/dist/types/notation/index.d.ts +1 -1
  72. package/dist/types/puzzles/index.d.ts +2 -2
  73. package/dist/types/twisty/index.d.ts +2 -2
  74. package/package.json +17 -17
  75. package/dist/esm/chunk-6FGST3DR.js.map +0 -7
  76. package/dist/esm/chunk-6KPOQHQA.js.map +0 -7
  77. package/dist/esm/chunk-HVZKPYTG.js.map +0 -7
  78. package/dist/esm/chunk-TZLV35JV.js.map +0 -7
  79. package/dist/esm/chunk-YU62MHVH.js.map +0 -7
  80. package/dist/esm/search-dynamic-sgs-side-events-T2RBUDFD.js.map +0 -7
  81. package/dist/esm/search-dynamic-sgs-unofficial-TJXF7BKM.js.map +0 -7
  82. package/dist/esm/search-worker-inside-generated-string-2SRY6LLB.js.map +0 -7
  83. package/dist/esm/search-worker-js-entry-CLLXI4HB.js +0 -17
  84. package/dist/esm/twisty-dynamic-3d-2TN37YPE.js.map +0 -7
  85. /package/dist/esm/{search-worker-js-entry-CLLXI4HB.js.map → search-worker-js-entry-XBNFXQ5S.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  Move,
3
3
  QuantumMove
4
- } from "../chunk-HVZKPYTG.js";
4
+ } from "../chunk-CFNRQVBC.js";
5
5
 
6
6
  // src/cubing/puzzle-geometry/FaceNameSwizzler.ts
7
7
  var FaceNameSwizzler = class {
@@ -23,6 +23,8 @@ var FaceNameSwizzler = class {
23
23
  setGripNames(names) {
24
24
  this.gripnames = names;
25
25
  }
26
+ // split a string into face names and return a list of
27
+ // indices.
26
28
  splitByFaceNames(s) {
27
29
  const r = [];
28
30
  let at = 0;
@@ -45,6 +47,7 @@ var FaceNameSwizzler = class {
45
47
  }
46
48
  return r;
47
49
  }
50
+ // cons a grip from an array of numbers.
48
51
  joinByFaceIndices(list) {
49
52
  let sep = "";
50
53
  const r = [];
@@ -57,6 +60,34 @@ var FaceNameSwizzler = class {
57
60
  }
58
61
  return r.join("");
59
62
  }
63
+ /*
64
+ * Try to match something the user gave us with some geometric
65
+ * feature. We used to have strict requirements:
66
+ *
67
+ * a) The set of face names are prefix free
68
+ * b) When specifying a corner, all coincident planes were
69
+ * specified
70
+ *
71
+ * But, to allow megaminx to have more reasonable and
72
+ * conventional names, and to permit shorter canonical
73
+ * names, we are relaxing these requirements and adding
74
+ * new syntax. Now:
75
+ *
76
+ * a) Face names need not be syntax free.
77
+ * b) When parsing a geometric name, we use greedy
78
+ * matching, so the longest name that matches the
79
+ * user string at the current position is the one
80
+ * assumed to match.
81
+ * c) Underscores are permitted to separate face names
82
+ * (both in user input and in geometric
83
+ * descriptions).
84
+ * d) Default names of corner moves where corners have
85
+ * more than three corners, need only include three
86
+ * of the corners.
87
+ *
88
+ * This code is not performance-sensitive so we can do it a
89
+ * slow and simple way.
90
+ */
60
91
  spinmatch(userinput, longname) {
61
92
  if (userinput === longname) {
62
93
  return true;
@@ -89,6 +120,7 @@ var FaceNameSwizzler = class {
89
120
  return false;
90
121
  }
91
122
  }
123
+ /* same as above, but permit both to have v's on the end. */
92
124
  spinmatchv(userinput, longname) {
93
125
  if (userinput.endsWith("v") && longname.endsWith("v")) {
94
126
  return this.spinmatch(
@@ -141,6 +173,7 @@ var FTONotationMapper = class {
141
173
  return r;
142
174
  }
143
175
  }
176
+ // we never rewrite click moves to these moves.
144
177
  notationToExternal(move) {
145
178
  let fam = move.family;
146
179
  if (fam.length > 0 && fam[fam.length - 1] === "v") {
@@ -162,6 +195,7 @@ var FaceRenamingMapper = class {
162
195
  this.internalNames = internalNames;
163
196
  this.externalNames = externalNames;
164
197
  }
198
+ // TODO: consider putting a cache in front of this
165
199
  convertString(grip, a, b) {
166
200
  let suffix = "";
167
201
  if ((grip.endsWith("v") || grip.endsWith("v")) && grip <= "_") {
@@ -233,6 +267,7 @@ var MegaminxScramblingNotationMapper = class {
233
267
  }
234
268
  return this.child.notationToInternal(move);
235
269
  }
270
+ // we never rewrite click moves to these moves.
236
271
  notationToExternal(move) {
237
272
  if (move.family === "DRRv" && Math.abs(move.amount) === 1) {
238
273
  return new Move(
@@ -313,6 +348,7 @@ var NxNxNCubeMapper = class {
313
348
  }
314
349
  return move;
315
350
  }
351
+ // do we want to map slice moves to E/M/S instead of 2U/etc.?
316
352
  notationToExternal(move) {
317
353
  const grip = move.family;
318
354
  if (!(move.innerLayer || move.outerLayer)) {
@@ -411,6 +447,7 @@ var PyraminxNotationMapper = class {
411
447
  return null;
412
448
  }
413
449
  }
450
+ // we never rewrite click moves to these moves.
414
451
  notationToExternal(move) {
415
452
  if (this.wcaHack && move.innerLayer === 2 && move.outerLayer === null) {
416
453
  for (const [external, internal] of Object.entries(pyraminxFamilyMapWCA)) {
@@ -499,6 +536,7 @@ var SkewbNotationMapper = class {
499
536
  }
500
537
  return null;
501
538
  }
539
+ // we never rewrite click moves to these moves.
502
540
  notationToExternal(move) {
503
541
  for (const [external, internal] of Object.entries(skewbFamilyMap)) {
504
542
  if (this.child.spinmatchv(move.family, internal)) {
@@ -581,25 +619,46 @@ function parseOptions(argv) {
581
619
  return { puzzleDescription, options };
582
620
  }
583
621
  var PuzzleGeometryFullOptions = class {
622
+ // scramble?
584
623
  constructor(options = {}) {
585
624
  this.verbosity = 0;
625
+ // verbosity (console.log)
586
626
  this.allMoves = false;
627
+ // generate outer block moves
587
628
  this.vertexMoves = false;
629
+ // generate vertex moves
588
630
  this.addRotations = false;
631
+ // add symmetry information to ksolve output
589
632
  this.moveList = null;
633
+ // move list to generate
590
634
  this.fixedOrientation = false;
635
+ // eliminate any orientations
591
636
  this.fixedPieceType = null;
637
+ // fix a piece?
592
638
  this.orientCenters = false;
639
+ // orient centers?
640
+ // TODO: Group these into a single object?
593
641
  this.includeCornerOrbits = true;
642
+ // include corner orbits
594
643
  this.includeCenterOrbits = true;
644
+ // include center orbits
595
645
  this.includeEdgeOrbits = true;
646
+ // include edge orbits
647
+ // Overrides the previous options.
596
648
  this.excludeOrbits = [];
649
+ // exclude these orbits
597
650
  this.optimizeOrbits = false;
651
+ // optimize PermOri
598
652
  this.grayCorners = false;
653
+ // make corner sets gray
599
654
  this.grayCenters = false;
655
+ // make center sets gray
600
656
  this.grayEdges = false;
657
+ // make edge sets gray
601
658
  this.puzzleOrientation = null;
659
+ // single puzzle orientation from options
602
660
  this.puzzleOrientations = null;
661
+ // puzzle orientation override object from options // TODO: is this needed?
603
662
  this.scrambleAmount = 0;
604
663
  Object.assign(this, options);
605
664
  }
@@ -656,6 +715,7 @@ function lcm(a, b) {
656
715
  return a / gcd(a, b) * b;
657
716
  }
658
717
  var Perm = class {
718
+ // The permutation itself
659
719
  constructor(a) {
660
720
  this.n = a.length;
661
721
  this.p = a;
@@ -845,6 +905,7 @@ var PGOrbitsDef = class {
845
905
  }
846
906
  return result;
847
907
  }
908
+ // TODO: return type.
848
909
  toKPuzzleDefinition(includemoves) {
849
910
  const orbits = {};
850
911
  const start = {};
@@ -993,9 +1054,13 @@ var PGOrbitsDef = class {
993
1054
  this.forcenames
994
1055
  );
995
1056
  }
1057
+ // replace the solved state with a new scrambled state.
996
1058
  scramble(n) {
997
1059
  this.solved = this.solved.mul(this.getScrambleTransformation(n));
998
1060
  }
1061
+ // generate a new "random" position based on an entropy pool
1062
+ // this should be significantly faster and more random than just
1063
+ // doing a large number of random moves, especially on big puzzles.
999
1064
  getScrambleTransformation(n) {
1000
1065
  if (n < 100) {
1001
1066
  n = 100;
@@ -1081,6 +1146,7 @@ var _PGOrbit = class {
1081
1146
  }
1082
1147
  return true;
1083
1148
  }
1149
+ // in-place mutator
1084
1150
  killOri() {
1085
1151
  const n = this.perm.length;
1086
1152
  for (let i = 0; i < n; i++) {
@@ -1103,6 +1169,7 @@ var _PGOrbit = class {
1103
1169
  }
1104
1170
  return new Perm(newPerm);
1105
1171
  }
1172
+ // returns tuple of sets of identical pieces in this orbit
1106
1173
  identicalPieces() {
1107
1174
  const done = [];
1108
1175
  const n = this.perm.length;
@@ -1191,6 +1258,7 @@ var _PGOrbit = class {
1191
1258
  }
1192
1259
  }
1193
1260
  }
1261
+ // TODO: return type
1194
1262
  toKPuzzle() {
1195
1263
  const n = this.perm.length;
1196
1264
  if (this.isIdentity()) {
@@ -1449,6 +1517,7 @@ var PGPuzzles = {
1449
1517
  pentultimate: "d f 0",
1450
1518
  "master pentultimate": "d f 0.1",
1451
1519
  "elite pentultimate": "d f 0 f 0.145905",
1520
+ // exact value for starminx is sqrt(5(5-2 sqrt(5))/3)
1452
1521
  starminx: "d v 0.937962370425399",
1453
1522
  "starminx 2": "d f 0.23606797749979",
1454
1523
  "pyraminx crystal": "d f 0.447213595499989",
@@ -1568,6 +1637,9 @@ var Quat = class {
1568
1637
  t.a = this.a;
1569
1638
  return t;
1570
1639
  }
1640
+ // return any vector orthogonal to the given one. Find the smallest
1641
+ // component (in absolute value) and return the cross product of that
1642
+ // axis with the given vector.
1571
1643
  orthogonal() {
1572
1644
  const ab = Math.abs(this.b);
1573
1645
  const ac = Math.abs(this.c);
@@ -1580,6 +1652,8 @@ var Quat = class {
1580
1652
  return this.cross(new Quat(0, 0, 0, 1)).normalize();
1581
1653
  }
1582
1654
  }
1655
+ // return the Quaternion that will rotate the this vector
1656
+ // to the b vector through rotatepoint.
1583
1657
  pointrotation(b) {
1584
1658
  const a = this.normalize();
1585
1659
  b = b.normalize();
@@ -1596,6 +1670,8 @@ var Quat = class {
1596
1670
  r.a = a.dot(h);
1597
1671
  return r;
1598
1672
  }
1673
+ // given two vectors, return the portion of the first that
1674
+ // is not in the direction of the second.
1599
1675
  unproject(b) {
1600
1676
  return this.sum(b.smul(-this.dot(b) / (this.len() * b.len())));
1601
1677
  }
@@ -1636,6 +1712,11 @@ var Quat = class {
1636
1712
  }
1637
1713
  return 0;
1638
1714
  }
1715
+ /**
1716
+ * Cuts a face by this plane, or returns null if there
1717
+ * is no intersection.
1718
+ * @param face The face to cut.
1719
+ */
1639
1720
  cutface(face) {
1640
1721
  const d = this.a;
1641
1722
  let seen = 0;
@@ -2050,17 +2131,21 @@ var copyright = "PuzzleGeometry 0.1 Copyright 2018 Tomas Rokicki.";
2050
2131
  var permissivieMoveParsing = false;
2051
2132
  function defaultnets() {
2052
2133
  return {
2134
+ // four faces: tetrahedron
2053
2135
  4: [["F", "D", "L", "R"]],
2136
+ // six faces: cube
2054
2137
  6: [
2055
2138
  ["F", "D", "L", "U", "R"],
2056
2139
  ["R", "F", "", "B", ""]
2057
2140
  ],
2141
+ // eight faces: octahedron
2058
2142
  8: [
2059
2143
  ["F", "D", "L", "R"],
2060
2144
  ["D", "F", "BR", ""],
2061
2145
  ["BR", "D", "", "BB"],
2062
2146
  ["BB", "BR", "U", "BL"]
2063
2147
  ],
2148
+ // twelve faces: dodecahedron; U/F/R/F/BL/BR from megaminx
2064
2149
  12: [
2065
2150
  ["U", "FF", "", "", "", ""],
2066
2151
  ["FF", "U", "R", "FR", "FL", "L"],
@@ -2068,6 +2153,7 @@ function defaultnets() {
2068
2153
  ["DR", "R", "", "BB", "", ""],
2069
2154
  ["BB", "DR", "BR", "BL", "DL", "DD"]
2070
2155
  ],
2156
+ // twenty faces: icosahedron
2071
2157
  20: [
2072
2158
  ["R", "C", "F", "E"],
2073
2159
  ["F", "R", "L", "U"],
@@ -2084,6 +2170,7 @@ function defaultnets() {
2084
2170
  }
2085
2171
  function defaultcolors() {
2086
2172
  return {
2173
+ // the colors should use the same naming convention as the nets, above.
2087
2174
  4: {
2088
2175
  F: "#44ee00" /* Green */,
2089
2176
  D: "#ffff00" /* Yellow */,
@@ -2322,22 +2409,27 @@ function defaultOrientations() {
2322
2409
  ["FLR", [0, 1, 0]],
2323
2410
  ["F", [0, 0, 1]]
2324
2411
  ],
2412
+ // FLR towards viewer
2325
2413
  6: [
2326
2414
  ["U", [0, 1, 0]],
2327
2415
  ["F", [0, 0, 1]]
2328
2416
  ],
2417
+ // URF towards viewer
2329
2418
  8: [
2330
2419
  ["U", [0, 1, 0]],
2331
2420
  ["F", [0, 0, 1]]
2332
2421
  ],
2422
+ // FLUR towards viewer
2333
2423
  12: [
2334
2424
  ["U", [0, 1, 0]],
2335
2425
  ["FF", [0, 0, 1]]
2336
2426
  ],
2427
+ // F towards viewer
2337
2428
  20: [
2338
2429
  ["GUQMJ", [0, 1, 0]],
2339
2430
  ["F", [0, 0, 1]]
2340
2431
  ]
2432
+ // F towards viewer
2341
2433
  };
2342
2434
  }
2343
2435
  function findelement(a, p) {
@@ -2459,10 +2551,15 @@ function toFaceCoords(q, maxdist) {
2459
2551
  var PuzzleGeometry = class {
2460
2552
  constructor(puzzleDescription, options) {
2461
2553
  this.puzzleDescription = puzzleDescription;
2554
+ // cubies in each cubie set
2462
2555
  this.cmovesbyslice = [];
2556
+ // parsed move list
2463
2557
  this.duplicatedFaces = [];
2558
+ // which faces are duplicated
2464
2559
  this.duplicatedCubies = [];
2560
+ // which cubies are duplicated
2465
2561
  this.fixedCubie = -1;
2562
+ // fixed cubie, if any
2466
2563
  this.net = [];
2467
2564
  this.colors = [];
2468
2565
  this.notationMapper = new NullMapper();
@@ -2955,6 +3052,8 @@ var PuzzleGeometry = class {
2955
3052
  }
2956
3053
  return s;
2957
3054
  }
3055
+ // same as above, but instead of returning an encoded string, return
3056
+ // an array with offsets.
2958
3057
  keyface3(face) {
2959
3058
  const cm = face.centermass();
2960
3059
  const r = [];
@@ -3377,6 +3476,8 @@ var PuzzleGeometry = class {
3377
3476
  }
3378
3477
  return newmv.modified({ family: this.swizzler.unswizzle(newmv.family) });
3379
3478
  }
3479
+ // We use an extremely permissive parse here; any character but
3480
+ // digits are allowed in a family name.
3380
3481
  stringToBlockMove(mv) {
3381
3482
  const re = RegExp("^(([0-9]+)-)?([0-9]+)?([^0-9]+)([0-9]+'?)?$");
3382
3483
  const p = mv.match(re);
@@ -3898,6 +3999,7 @@ var PuzzleGeometry = class {
3898
3999
  }
3899
4000
  return false;
3900
4001
  }
4002
+ // TODO: This is only public for testing; can we make it private again?
3901
4003
  getOrbitsDef(fortwisty, includemoves = true) {
3902
4004
  const setmoves = [];
3903
4005
  if (fortwisty) {
@@ -4163,6 +4265,10 @@ var PuzzleGeometry = class {
4163
4265
  }
4164
4266
  return new Perm(r);
4165
4267
  }
4268
+ // Given a rotation description that says to align feature1
4269
+ // with a given vector, and then as much as possible feature2
4270
+ // with another given vector, return a Quaternion that
4271
+ // performs this rotation.
4166
4272
  getOrientationRotation(desiredRotation) {
4167
4273
  const [feature1name, [x1, y1, z1]] = desiredRotation[0];
4168
4274
  const direction1 = new Quat(0, x1, -y1, z1);
@@ -4423,6 +4529,10 @@ ${svg.join(
4423
4529
  )}</svg>`;
4424
4530
  return html;
4425
4531
  }
4532
+ // The colorfrac parameter says how much of the face should be
4533
+ // colored (vs dividing lines); we default to 0.77 which seems
4534
+ // to work pretty well. It should be a number between probably
4535
+ // 0.4 and 0.9.
4426
4536
  get3d(options) {
4427
4537
  const stickers = [];
4428
4538
  const rot = this.getInitial3DRotation();
@@ -4516,6 +4626,11 @@ ${svg.join(
4516
4626
  textureMapper: { getuv: g }
4517
4627
  };
4518
4628
  }
4629
+ // From the name of a geometric element (face, vertex, edge), get a
4630
+ // normal vector respecting the default orientation. This is useful
4631
+ // to define the initial position of the camera in a 3D scene. The
4632
+ // return value is normalized, so multiply it by the camera distance.
4633
+ // Returns undefined if no such geometric element.
4519
4634
  getGeoNormal(geoname) {
4520
4635
  const rot = this.getInitial3DRotation();
4521
4636
  const grip = this.swizzler.unswizzle(geoname);