prographs 0.12.0 → 0.13.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 (269) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/README.md +6 -4
  3. package/dist/AutoGraph-PDPEAIXL.cjs +145 -0
  4. package/dist/GraphType.js +19 -0
  5. package/dist/autograph/chartIndex.js +521 -0
  6. package/dist/autograph/chartModules.js +2 -1
  7. package/dist/autograph/index.cjs +98 -93
  8. package/dist/catalog-DI4XZ46L.cjs +142 -0
  9. package/dist/catalog.js +2 -1
  10. package/dist/charts/biologycharts/BiologySamples.js +59 -0
  11. package/dist/charts/biologycharts/PunnettSquare.js +342 -0
  12. package/dist/charts/biologycharts/biologyEnums.js +22 -1
  13. package/dist/charts/biologycharts/index.js +5 -3
  14. package/dist/charts/doecharts/DoeSamples.js +78 -0
  15. package/dist/charts/doecharts/SipocDiagram.js +453 -0
  16. package/dist/charts/doecharts/index.js +4 -2
  17. package/dist/charts/fieldcharts/SpeciesAccumulationCurve.js +350 -0
  18. package/dist/charts/fieldcharts/fieldEnums.js +8 -1
  19. package/dist/charts/fieldcharts/index.js +5 -3
  20. package/dist/charts/signals/AntennaPatternChart.js +492 -0
  21. package/dist/charts/signals/SignalSamples.js +17 -0
  22. package/dist/charts/signals/index.js +5 -3
  23. package/dist/charts/softwarediagrams/ComponentDiagram.js +504 -0
  24. package/dist/charts/softwarediagrams/DeploymentDiagram.js +419 -0
  25. package/dist/charts/softwarediagrams/SoftwareSamples.js +283 -1
  26. package/dist/charts/softwarediagrams/index.js +7 -3
  27. package/dist/charts/softwarediagrams/softwareEnums.js +45 -1
  28. package/dist/charts/sportscharts/PowerDurationCurve.js +301 -0
  29. package/dist/charts/sportscharts/SportsSamples.js +102 -0
  30. package/dist/charts/sportscharts/TrainingLoadChart.js +325 -0
  31. package/dist/charts/sportscharts/index.js +6 -2
  32. package/dist/charts/strategycharts/BassDiffusionChart.js +362 -0
  33. package/dist/charts/strategycharts/BassModel.js +96 -0
  34. package/dist/charts/strategycharts/BurnRunwayChart.js +284 -0
  35. package/dist/charts/strategycharts/CapTableChart.js +366 -0
  36. package/dist/charts/strategycharts/KanbanBoard.js +324 -0
  37. package/dist/charts/strategycharts/OkrTree.js +339 -0
  38. package/dist/charts/strategycharts/StrategyPane.js +27 -0
  39. package/dist/charts/strategycharts/StrategySamples.js +251 -0
  40. package/dist/charts/strategycharts/index.js +15 -3
  41. package/dist/charts/threefields/BsfcMap3DChart.js +231 -0
  42. package/dist/charts/threefields/CompressorMap3DChart.js +217 -0
  43. package/dist/charts/threefields/FieldGrid.js +50 -0
  44. package/dist/charts/threefields/LossLandscape3DChart.js +201 -0
  45. package/dist/charts/threefields/MapSheet.js +77 -0
  46. package/dist/charts/threefields/TerrainRoute3DChart.js +201 -0
  47. package/dist/charts/threefields/TerrainRouteMath.js +40 -0
  48. package/dist/charts/threefields/ThreeFieldBase.js +117 -0
  49. package/dist/charts/threefields/ThreeFieldsSamples.js +80 -0
  50. package/dist/charts/threefields/WaferMap3DChart.js +218 -0
  51. package/dist/charts/threefields/index.js +19 -0
  52. package/dist/charts/threesurfaces/index.js +2 -2
  53. package/dist/charts/tradingcharts/KeltnerChannelChart.js +171 -0
  54. package/dist/charts/tradingcharts/TradingMath.js +20 -0
  55. package/dist/charts/tradingcharts/index.js +4 -2
  56. package/dist/{chunk-ZL6XDXMK.cjs → chunk-26PSLEP4.cjs} +8 -8
  57. package/dist/{chunk-W3US6EFP.cjs → chunk-2BO5DZUP.cjs} +12 -12
  58. package/dist/{chunk-5DP7OUSE.cjs → chunk-2GG5YYSC.cjs} +6 -6
  59. package/dist/{chunk-7FG4JSVO.cjs → chunk-2GL2VNJU.cjs} +253 -33
  60. package/dist/{chunk-LCWMRCLF.cjs → chunk-2PYOI7OY.cjs} +21 -21
  61. package/dist/{chunk-JFWJAEBD.cjs → chunk-3U4MCSKI.cjs} +4 -4
  62. package/dist/{chunk-CUPLHZRR.cjs → chunk-3ZMM3FSK.cjs} +4 -4
  63. package/dist/{chunk-L2AV62DP.cjs → chunk-4767WQJ7.cjs} +6 -6
  64. package/dist/{chunk-DA2EYIIP.cjs → chunk-4E7FSSBF.cjs} +1210 -168
  65. package/dist/{chunk-VS5LQEZB.cjs → chunk-526STI2S.cjs} +5 -5
  66. package/dist/{chunk-RXIMEK6C.cjs → chunk-55767YPI.cjs} +20 -20
  67. package/dist/{chunk-JXLSKIUV.cjs → chunk-5FBQOMMT.cjs} +26 -26
  68. package/dist/{chunk-27PZV5BR.cjs → chunk-5N4Z7MTS.cjs} +4 -4
  69. package/dist/{chunk-KEWCUIQA.cjs → chunk-5WEV6YWA.cjs} +22 -22
  70. package/dist/chunk-5XOVVC5X.cjs +3281 -0
  71. package/dist/{chunk-HK5J7Q2W.cjs → chunk-6HLXVWXU.cjs} +9 -9
  72. package/dist/{chunk-7JG47RW4.cjs → chunk-6LQT4WJ5.cjs} +25 -25
  73. package/dist/{chunk-OCVTI6X4.cjs → chunk-6YTWOUFD.cjs} +329 -36
  74. package/dist/{chunk-W7IQCAVN.cjs → chunk-7F6W6HKL.cjs} +11 -11
  75. package/dist/{chunk-F2DCJXDM.cjs → chunk-7L6KYU5A.cjs} +21 -21
  76. package/dist/{chunk-GTGR6LPR.cjs → chunk-A4GIN4FE.cjs} +17 -17
  77. package/dist/{chunk-B2CETSR6.cjs → chunk-A4US7SA7.cjs} +5 -5
  78. package/dist/{chunk-3DIF2YYW.cjs → chunk-AOXPBLPW.cjs} +10 -10
  79. package/dist/{chunk-7TTR4UF5.cjs → chunk-ATI45Z4M.cjs} +2 -2
  80. package/dist/{chunk-5BFCIX2V.cjs → chunk-CPPMO4IQ.cjs} +434 -148
  81. package/dist/{chunk-AYZZQ6AC.cjs → chunk-CZ5KGF6Q.cjs} +9 -9
  82. package/dist/{chunk-7THJ3ZBK.cjs → chunk-D4I35MCE.cjs} +2 -2
  83. package/dist/{chunk-MCPPFRLN.cjs → chunk-DCGAAN3Z.cjs} +2 -2
  84. package/dist/{chunk-VABL6CVX.cjs → chunk-DEY36N37.cjs} +21 -21
  85. package/dist/{chunk-RNCKGJCC.cjs → chunk-DXHXD3DK.cjs} +3 -3
  86. package/dist/{chunk-A56ZGMVZ.cjs → chunk-E7B45DBZ.cjs} +11 -11
  87. package/dist/{chunk-DOR6L4MT.cjs → chunk-EJC6EAC5.cjs} +18 -18
  88. package/dist/{chunk-UPGNM7MA.cjs → chunk-EULJOOMA.cjs} +11 -11
  89. package/dist/{chunk-G4AZL4GO.cjs → chunk-EYM6LEIF.cjs} +474 -70
  90. package/dist/{chunk-NJ4X6XGV.cjs → chunk-EZTYX2GH.cjs} +5 -5
  91. package/dist/chunk-FDD4UP73.cjs +521 -0
  92. package/dist/{chunk-WJ3VH2Q4.cjs → chunk-GEAIGM3J.cjs} +110 -615
  93. package/dist/{chunk-P3SBHF43.cjs → chunk-GRUYVXTS.cjs} +2 -2
  94. package/dist/{chunk-NX4Z5LMS.cjs → chunk-H3SZXND5.cjs} +5 -5
  95. package/dist/{chunk-EE4S4TOE.cjs → chunk-HS45TOFJ.cjs} +21 -21
  96. package/dist/chunk-INGOG6OV.cjs +899 -0
  97. package/dist/{chunk-UDKA6DGT.cjs → chunk-J3CDXZHF.cjs} +4 -4
  98. package/dist/{chunk-YO6G7TKI.cjs → chunk-JAU5ADEU.cjs} +11 -11
  99. package/dist/{chunk-22LBK4GA.cjs → chunk-JQEBSHX3.cjs} +4 -4
  100. package/dist/{chunk-RXX3U7VQ.cjs → chunk-KLXGLMFU.cjs} +10 -10
  101. package/dist/chunk-KVOX36J3.cjs +327 -0
  102. package/dist/chunk-L6BGNHFL.cjs +139 -0
  103. package/dist/{chunk-GMER35L3.cjs → chunk-L7TB7PU5.cjs} +20 -20
  104. package/dist/{chunk-AFXYNBL2.cjs → chunk-LBTRYEM2.cjs} +4 -4
  105. package/dist/{chunk-WYYCKIOD.cjs → chunk-LLULNJSP.cjs} +11 -11
  106. package/dist/{chunk-J27XOSLP.cjs → chunk-LSO46AFV.cjs} +8 -8
  107. package/dist/{chunk-5XJO45ES.cjs → chunk-LZ2KJ7ZX.cjs} +11 -11
  108. package/dist/chunk-M4IQ5LIZ.cjs +422 -0
  109. package/dist/{chunk-Y2KIUKJF.cjs → chunk-MPDHDKYZ.cjs} +11 -11
  110. package/dist/{chunk-4EMPKRZU.cjs → chunk-MRQ42ZJE.cjs} +3 -3
  111. package/dist/{chunk-EU5D2MF4.cjs → chunk-MYV4KZWP.cjs} +9 -9
  112. package/dist/{chunk-XD7KN4UN.cjs → chunk-MZXVLC24.cjs} +6 -6
  113. package/dist/{chunk-PPSONARU.cjs → chunk-NLBVDFIR.cjs} +41 -2
  114. package/dist/{chunk-L3PEGMGM.cjs → chunk-NY3TBZY4.cjs} +33 -33
  115. package/dist/{chunk-6YNYXXB6.cjs → chunk-OGVVSFAR.cjs} +3 -3
  116. package/dist/{chunk-MLV7QLB6.cjs → chunk-OMTQIQMN.cjs} +6 -6
  117. package/dist/{chunk-BEEOSNK7.cjs → chunk-PEJJ6TXJ.cjs} +15 -144
  118. package/dist/{chunk-SOKOWUF5.cjs → chunk-PPGWHIU7.cjs} +2 -2
  119. package/dist/{chunk-IELWOM2J.cjs → chunk-PPO6SDAN.cjs} +6 -6
  120. package/dist/{chunk-6JTZZCSL.cjs → chunk-PUMKX5F2.cjs} +3 -3
  121. package/dist/{chunk-RFOXFY2U.cjs → chunk-PXBYWCNB.cjs} +190 -799
  122. package/dist/{chunk-3BYXOISI.cjs → chunk-Q3HB3IX6.cjs} +4 -4
  123. package/dist/{chunk-RXCOVONX.cjs → chunk-RBMUOIXE.cjs} +289 -34
  124. package/dist/{chunk-MSBNHCSE.cjs → chunk-RJHGCUUD.cjs} +6 -6
  125. package/dist/{chunk-I6VG7F6Z.cjs → chunk-RSONDMYW.cjs} +708 -141
  126. package/dist/{chunk-GZDNPHMT.cjs → chunk-SHMPFCUE.cjs} +19 -19
  127. package/dist/{chunk-ZIBVCOW6.cjs → chunk-SN4FCXFC.cjs} +19 -19
  128. package/dist/{chunk-7KM52NMN.cjs → chunk-SN5T7WYO.cjs} +2 -2
  129. package/dist/{chunk-7MSZR65Z.cjs → chunk-SQJZGVDR.cjs} +7 -7
  130. package/dist/chunk-SYABFMD7.cjs +633 -0
  131. package/dist/{chunk-2RRFEYFH.cjs → chunk-TICB3MAC.cjs} +16 -16
  132. package/dist/{chunk-AOOKHUV5.cjs → chunk-U7Z7XYR2.cjs} +5 -5
  133. package/dist/{chunk-JEWQAXVG.cjs → chunk-UA2THQFV.cjs} +6 -6
  134. package/dist/{chunk-LHZPAHU3.cjs → chunk-VIK4L2YF.cjs} +112 -521
  135. package/dist/{chunk-4YWMAQ4J.cjs → chunk-VM2Y6BDY.cjs} +4 -4
  136. package/dist/{chunk-IRRKE2ZE.cjs → chunk-VMS3KWYI.cjs} +21 -21
  137. package/dist/{chunk-4SLARW6F.cjs → chunk-VU5NUD46.cjs} +17 -17
  138. package/dist/{chunk-XHY6TVYG.cjs → chunk-VV5CVOF7.cjs} +13 -13
  139. package/dist/{chunk-CCIBPGPZ.cjs → chunk-VYSAWPSS.cjs} +57 -57
  140. package/dist/{chunk-TTNEMQ2A.cjs → chunk-W7YRWEWQ.cjs} +22 -22
  141. package/dist/{chunk-C7MUOGEW.cjs → chunk-X7R5SY62.cjs} +6 -6
  142. package/dist/{chunk-ILR5KBMB.cjs → chunk-XOK3KTSS.cjs} +6 -6
  143. package/dist/{chunk-2CZM2I3T.cjs → chunk-XUIX45VU.cjs} +19 -19
  144. package/dist/{chunk-TGRMPS3A.cjs → chunk-XWH46PVJ.cjs} +165 -43
  145. package/dist/{chunk-WQYXXECR.cjs → chunk-Y5XVMK3K.cjs} +6 -6
  146. package/dist/{chunk-AK4TX2WG.cjs → chunk-YCNKEDTG.cjs} +13 -13
  147. package/dist/{chunk-PJJB24DU.cjs → chunk-YEF7SE3X.cjs} +20 -20
  148. package/dist/{chunk-RVLV4XW6.cjs → chunk-YMTVPMU3.cjs} +22 -22
  149. package/dist/data/index.cjs +2 -2
  150. package/dist/entries/autograph-lazy.cjs +2 -2
  151. package/dist/entries/charts/acoustictransport.cjs +3 -3
  152. package/dist/entries/charts/analysischarts.cjs +3 -3
  153. package/dist/entries/charts/astrocharts.cjs +3 -3
  154. package/dist/entries/charts/bars.cjs +3 -3
  155. package/dist/entries/charts/bayesiancharts.cjs +3 -3
  156. package/dist/entries/charts/biocharts.cjs +3 -3
  157. package/dist/entries/charts/biologycharts.cjs +11 -3
  158. package/dist/entries/charts/biologycharts.d.ts +1 -1
  159. package/dist/entries/charts/biologycharts.js +3 -2
  160. package/dist/entries/charts/business.cjs +3 -3
  161. package/dist/entries/charts/carecharts.cjs +3 -3
  162. package/dist/entries/charts/chemistrycharts.cjs +3 -3
  163. package/dist/entries/charts/civicscharts.cjs +3 -3
  164. package/dist/entries/charts/clinicalcharts.cjs +3 -3
  165. package/dist/entries/charts/comparison.cjs +3 -3
  166. package/dist/entries/charts/demography.cjs +3 -3
  167. package/dist/entries/charts/density.cjs +3 -3
  168. package/dist/entries/charts/diagrams.cjs +3 -3
  169. package/dist/entries/charts/distribution.cjs +3 -3
  170. package/dist/entries/charts/doecharts.cjs +13 -3
  171. package/dist/entries/charts/doecharts.d.ts +1 -1
  172. package/dist/entries/charts/doecharts.js +2 -1
  173. package/dist/entries/charts/earthscience.cjs +3 -3
  174. package/dist/entries/charts/economicscharts.cjs +3 -3
  175. package/dist/entries/charts/energycharts.cjs +3 -3
  176. package/dist/entries/charts/engineering.cjs +3 -3
  177. package/dist/entries/charts/fieldcharts.cjs +7 -3
  178. package/dist/entries/charts/fieldcharts.d.ts +1 -1
  179. package/dist/entries/charts/fieldcharts.js +3 -2
  180. package/dist/entries/charts/financial.cjs +3 -3
  181. package/dist/entries/charts/flow.cjs +3 -3
  182. package/dist/entries/charts/frameworks.cjs +3 -3
  183. package/dist/entries/charts/genomics.cjs +3 -3
  184. package/dist/entries/charts/geoflows.cjs +3 -3
  185. package/dist/entries/charts/geomaps.cjs +3 -3
  186. package/dist/entries/charts/geosciencecharts.cjs +3 -3
  187. package/dist/entries/charts/hierarchy.cjs +3 -3
  188. package/dist/entries/charts/indicators.cjs +3 -3
  189. package/dist/entries/charts/inferencecharts.cjs +3 -3
  190. package/dist/entries/charts/layoutcharts.cjs +3 -3
  191. package/dist/entries/charts/lifescience.cjs +4 -4
  192. package/dist/entries/charts/linesareas.cjs +3 -3
  193. package/dist/entries/charts/logisticscharts.cjs +3 -3
  194. package/dist/entries/charts/machinecharts.cjs +7 -3
  195. package/dist/entries/charts/machinecharts.d.ts +1 -1
  196. package/dist/entries/charts/machinecharts.js +2 -1
  197. package/dist/entries/charts/massive.cjs +3 -3
  198. package/dist/entries/charts/mathematical.cjs +3 -3
  199. package/dist/entries/charts/matrix.cjs +3 -3
  200. package/dist/entries/charts/medicalcharts.cjs +4 -4
  201. package/dist/entries/charts/mlcharts.cjs +4 -4
  202. package/dist/entries/charts/modelcharts.cjs +6 -5
  203. package/dist/entries/charts/multivariate.cjs +3 -3
  204. package/dist/entries/charts/musiccharts.cjs +3 -3
  205. package/dist/entries/charts/network.cjs +3 -3
  206. package/dist/entries/charts/physicscharts.cjs +3 -3
  207. package/dist/entries/charts/pictorial.cjs +4 -4
  208. package/dist/entries/charts/portfoliocharts.cjs +3 -3
  209. package/dist/entries/charts/productcharts.cjs +3 -3
  210. package/dist/entries/charts/proportion.cjs +3 -3
  211. package/dist/entries/charts/qualitycharts.cjs +3 -3
  212. package/dist/entries/charts/radial.cjs +3 -3
  213. package/dist/entries/charts/reliabilitycharts.cjs +5 -3
  214. package/dist/entries/charts/scatter.cjs +3 -3
  215. package/dist/entries/charts/scientific.cjs +3 -3
  216. package/dist/entries/charts/seriescharts.cjs +3 -3
  217. package/dist/entries/charts/signals.cjs +7 -3
  218. package/dist/entries/charts/signals.d.ts +1 -1
  219. package/dist/entries/charts/signals.js +2 -1
  220. package/dist/entries/charts/softwarediagrams.cjs +21 -3
  221. package/dist/entries/charts/softwarediagrams.d.ts +1 -1
  222. package/dist/entries/charts/softwarediagrams.js +4 -2
  223. package/dist/entries/charts/sportscharts.cjs +13 -3
  224. package/dist/entries/charts/sportscharts.d.ts +1 -1
  225. package/dist/entries/charts/sportscharts.js +3 -1
  226. package/dist/entries/charts/statistics.cjs +6 -6
  227. package/dist/entries/charts/strategycharts.cjs +30 -3
  228. package/dist/entries/charts/strategycharts.d.ts +1 -1
  229. package/dist/entries/charts/strategycharts.js +6 -1
  230. package/dist/entries/charts/structure.cjs +3 -3
  231. package/dist/entries/charts/surveycharts.cjs +3 -3
  232. package/dist/entries/charts/systemscharts.cjs +3 -3
  233. package/dist/entries/charts/textcharts.cjs +5 -5
  234. package/dist/entries/charts/thematicmaps.cjs +4 -4
  235. package/dist/entries/charts/threebars.cjs +3 -3
  236. package/dist/entries/charts/threefields.cjs +53 -0
  237. package/dist/entries/charts/threefields.d.ts +1 -0
  238. package/dist/entries/charts/threefields.js +6 -0
  239. package/dist/entries/charts/threeglobe.cjs +3 -3
  240. package/dist/entries/charts/threenetwork.cjs +3 -3
  241. package/dist/entries/charts/threestrata.cjs +3 -3
  242. package/dist/entries/charts/threesurfaces.cjs +7 -3
  243. package/dist/entries/charts/threesurfaces.d.ts +1 -1
  244. package/dist/entries/charts/threesurfaces.js +2 -1
  245. package/dist/entries/charts/threevolume.cjs +4 -4
  246. package/dist/entries/charts/timeline.cjs +3 -3
  247. package/dist/entries/charts/tracecharts.cjs +3 -3
  248. package/dist/entries/charts/trackscharts.cjs +3 -3
  249. package/dist/entries/charts/tradingcharts.cjs +6 -4
  250. package/dist/entries/charts/tradingcharts.d.ts +1 -1
  251. package/dist/entries/charts/tradingcharts.js +2 -1
  252. package/dist/entries/three.cjs +60 -20
  253. package/dist/entries/three.d.ts +1 -1
  254. package/dist/entries/three.js +7 -1
  255. package/dist/index.cjs +258 -97
  256. package/dist/index.d.cts +1953 -10
  257. package/dist/index.d.ts +1953 -10
  258. package/dist/index.js +26 -5
  259. package/dist/page/index.cjs +2 -2
  260. package/dist/react/components.js +58 -1
  261. package/dist/react/index.cjs +135 -92
  262. package/dist/react/index.d.ts +1 -1
  263. package/dist/react/index.js +2 -2
  264. package/package.json +1 -1
  265. package/dist/AutoGraph-XLBJQDRB.cjs +0 -140
  266. package/dist/catalog-O7XGDD2H.cjs +0 -137
  267. package/dist/chunk-77K2HTRC.cjs +0 -3220
  268. package/dist/chunk-XEK47TVD.cjs +0 -323
  269. /package/dist/{chunk-UMEKIIHJ.cjs → chunk-LNWTC72Y.cjs} +0 -0
@@ -0,0 +1,217 @@
1
+ import { ChartFamily, DataShape, Dimension } from "../../core/enums.js";
2
+ import { MachineChart } from "../machinecharts/MachineChart.js";
3
+ import { MachineMesh } from "../machinecharts/MachineMesh.js";
4
+ import { MachineSamples } from "../machinecharts/MachineSamples.js";
5
+ import { ColorRamp } from "../threesurfaces/ColorRamp.js";
6
+ import { SurfaceGeometry } from "../threesurfaces/SurfaceGeometry.js";
7
+ import { CEIL, FLOOR } from "../threesurfaces/SurfaceSpace.js";
8
+ import { TubeBatch } from "../threesurfaces/TubeBatch.js";
9
+ import { MapSheet } from "./MapSheet.js";
10
+ import { ThreeFieldBase } from "./ThreeFieldBase.js";
11
+ import { group, max, mean, scaleLinear } from "d3";
12
+ // src/charts/threefields/CompressorMap3DChart.ts
13
+ /** The surge line as a wall from floor to ceiling, as a ribbon standing on the edge of the surface, or left out. */
14
+ var CompressorMap3DSurge = /* @__PURE__ */ function(CompressorMap3DSurge) {
15
+ CompressorMap3DSurge["Wall"] = "surge-wall";
16
+ CompressorMap3DSurge["Ribbon"] = "surge-ribbon";
17
+ CompressorMap3DSurge["None"] = "no-surge";
18
+ return CompressorMap3DSurge;
19
+ }({});
20
+ var EFFICIENCY = "Efficiency";
21
+ var SPEED = "Speed lines";
22
+ var PEAK = "Peak efficiency";
23
+ var BETWEEN = 5;
24
+ /**
25
+ * A compressor map with efficiency as height: the operating range as a sheet over corrected flow and pressure ratio, the
26
+ * speed lines drawn across it and the surge line as a wall. Use it to show how sharply efficiency falls away from the
27
+ * design point; the 2D compressor map takes the same rows and reads values more exactly.
28
+ */
29
+ var CompressorMap3DChart = class extends ThreeFieldBase {
30
+ static meta = {
31
+ id: "compressor-map-3d",
32
+ name: "3D compressor map",
33
+ family: ChartFamily.Scientific,
34
+ dimension: Dimension.Three,
35
+ shape: DataShape.Table,
36
+ description: "Raises isentropic efficiency into a surface over corrected mass flow and pressure ratio, with the speed lines drawn on it and the surge line as a wall or ribbon.",
37
+ tags: [
38
+ "turbomachinery",
39
+ "turbocharger",
40
+ "surge line",
41
+ "efficiency island",
42
+ "speed line",
43
+ "gas turbine",
44
+ "performance map"
45
+ ],
46
+ sample: (seed) => MachineSamples.compressor(seed),
47
+ variants: {
48
+ surge: Object.values(CompressorMap3DSurge),
49
+ ridge: [false, true],
50
+ markers: [true, false],
51
+ floorMap: [true, false]
52
+ }
53
+ };
54
+ defaults() {
55
+ return {
56
+ ...super.defaults(),
57
+ x: "flow",
58
+ y: "pressureRatio",
59
+ series: "speed",
60
+ efficiency: "efficiency",
61
+ surge: "surge-wall",
62
+ ridge: false,
63
+ markers: true,
64
+ floorMap: true,
65
+ xLabel: "Mass flow (kg/s)",
66
+ yLabel: "Pressure ratio",
67
+ zLabel: "Efficiency"
68
+ };
69
+ }
70
+ get rows() {
71
+ return (Array.isArray(this.options.data) ? this.options.data : []).filter((row) => row !== null && typeof row === "object");
72
+ }
73
+ /** Speed lines from surge to choke, slowest first: lower speeds pass less flow. */
74
+ lines() {
75
+ const { x, y, series, efficiency } = this.options;
76
+ const points = this.rows.flatMap((row) => {
77
+ const flow = MachineChart.number(row[x]), ratio = MachineChart.number(row[y]);
78
+ return flow === null || ratio === null ? [] : [{
79
+ speed: String(row[series] ?? "Speed"),
80
+ x: flow,
81
+ y: ratio,
82
+ z: MachineChart.number(row[efficiency]) ?? NaN
83
+ }];
84
+ });
85
+ return [...group(points, (d) => d.speed)].map(([speed, own]) => ({
86
+ speed,
87
+ points: own.sort((a, b) => a.x - b.x)
88
+ })).sort((a, b) => mean(a.points, (d) => d.x) - mean(b.points, (d) => d.x));
89
+ }
90
+ table() {
91
+ const { x, y, series, efficiency } = this.options;
92
+ return {
93
+ columns: [
94
+ series,
95
+ x,
96
+ y,
97
+ efficiency
98
+ ],
99
+ rows: this.lines().flatMap((line) => line.points.map((d) => [
100
+ d.speed,
101
+ d.x,
102
+ d.y,
103
+ Number.isFinite(d.z) ? d.z : null
104
+ ]))
105
+ };
106
+ }
107
+ build(ctx) {
108
+ const { surge, ridge, markers, floorMap } = this.options, { theme, palette } = ctx;
109
+ const lines = this.lines().map((line) => line.points.every((d) => Number.isFinite(d.z)) ? line : {
110
+ ...line,
111
+ points: line.points.map((d) => ({
112
+ ...d,
113
+ z: NaN
114
+ }))
115
+ });
116
+ const all = lines.flatMap((line) => line.points), measured = lines.filter((line) => line.points.length > 1 && Number.isFinite(line.points[0].z));
117
+ const mesh = new MachineMesh(measured.map((line) => line.points), 24, BETWEEN), sheet = new MapSheet(mesh, all, false, [FLOOR + (floorMap ? .42 : .3), CEIL]);
118
+ const percent = (max(all, (d) => d.z) ?? 0) <= 1.5;
119
+ const efficiency = (value) => percent ? `${MachineChart.short(value * 100)}%` : MachineChart.short(value);
120
+ const ramp = new ColorRamp(palette.sequential), [low, high] = sheet.z;
121
+ const paint = (value) => ramp.at(.08 + .9 * (value - low) / (high - low));
122
+ palette.color(EFFICIENCY);
123
+ const ink = palette.color(SPEED), dark = ctx.color(theme.ink);
124
+ this.box(ctx, {
125
+ x: this.ticks(sheet.x, sheet.across),
126
+ y: this.ticks(sheet.y, sheet.depth),
127
+ z: mesh.rows ? scaleLinear(sheet.z, [0, 1]).ticks(4).map((value) => [sheet.level(value), efficiency(value)]) : []
128
+ });
129
+ if (!all.length) return;
130
+ const lift = this.rise(ctx);
131
+ const tip = (d) => ({
132
+ title: `Speed ${d.speed}`,
133
+ color: ink,
134
+ rows: [
135
+ ["Flow", MachineChart.short(d.x, 4)],
136
+ ["Pressure ratio", MachineChart.short(d.y, 4)],
137
+ ...Number.isFinite(d.z) ? [["Efficiency", efficiency(d.z)]] : []
138
+ ]
139
+ });
140
+ if (mesh.rows) this.solid(ctx, sheet.geometry(paint), lift, (k) => {
141
+ const node = mesh.nodes[Math.floor(k / mesh.columns)][k % mesh.columns];
142
+ return { rows: [
143
+ ["Efficiency", efficiency(node.z)],
144
+ ["Flow", MachineChart.short(node.x, 4)],
145
+ ["Pressure ratio", MachineChart.short(node.y, 4)]
146
+ ] };
147
+ });
148
+ const traced = lines.filter((line) => line.points.length > 1).map((line) => {
149
+ const row = measured.indexOf(line);
150
+ return {
151
+ line,
152
+ nodes: row < 0 || !mesh.rows ? line.points : mesh.nodes[row * BETWEEN]
153
+ };
154
+ });
155
+ for (const { line, nodes } of traced) {
156
+ const tube = this.tubes(new TubeBatch(.007).add(nodes.map((node) => sheet.place(node, .008))), lift, ink);
157
+ if (tube) ctx.pick(tube, () => ({
158
+ title: `Speed ${line.speed}`,
159
+ color: ink,
160
+ rows: [["Flow at surge", MachineChart.short(line.points[0].x)], ["Flow at choke", MachineChart.short(line.points.at(-1).x)]]
161
+ }));
162
+ const [x, y, z] = nodes.map((node) => sheet.place(node)).reduce((crest, point) => point[1] > crest[1] ? point : crest);
163
+ ctx.label(line.speed, [
164
+ x,
165
+ y + .085,
166
+ z
167
+ ], "secondary", 10, lift);
168
+ }
169
+ const shown = markers ? all : [];
170
+ this.dots(ctx, shown.map((d) => sheet.place(d, .008)), .014, () => ctx.color(ink), lift, (k) => tip(shown[k]));
171
+ const ends = (pick) => (mesh.rows && measured.length === traced.length ? mesh.nodes : traced.map(({ nodes }) => nodes)).map(pick);
172
+ const surged = traced.length > 1 ? ends((nodes) => nodes[0]) : [], choked = traced.length > 1 ? ends((nodes) => nodes[nodes.length - 1]) : [];
173
+ if (surge !== "no-surge" && surged.length) {
174
+ const edge = surged.map((node) => sheet.place(node, .01));
175
+ this.tubes(new TubeBatch(.011).add(edge), lift, theme.ink);
176
+ const wall = surge === "surge-wall";
177
+ const band = wall ? SurfaceGeometry.curtain(edge.map(([x, , z]) => [
178
+ x,
179
+ CEIL + .06,
180
+ z
181
+ ]), FLOOR + .002, () => dark, () => dark) : SurfaceGeometry.curtain(edge.map(([x, y, z]) => [
182
+ x,
183
+ y + .07,
184
+ z
185
+ ]), (k) => edge[k][1] - .07, () => dark, () => dark);
186
+ this.solid(ctx, band, lift, void 0, wall ? {
187
+ transparent: true,
188
+ opacity: .16,
189
+ depthWrite: false
190
+ } : {}).castShadow = !wall;
191
+ const [x, y, z] = edge[Math.floor(edge.length / 2)];
192
+ this.tag(ctx, "Surge line", [
193
+ x,
194
+ wall ? CEIL + .14 : y + .21,
195
+ z
196
+ ], lift);
197
+ }
198
+ const peaks = ridge ? measured.map((line) => line.points.reduce((best, d) => d.z > best.z ? d : best)) : [];
199
+ const crest = peaks.length ? palette.color(PEAK) : "";
200
+ if (peaks.length > 1) this.tubes(new TubeBatch(.006).add(peaks.map((d) => sheet.place(d, .012))), lift, crest);
201
+ this.dots(ctx, peaks.map((d) => sheet.place(d, .012)), .024, () => ctx.color(crest), lift, (k) => ({
202
+ ...tip(peaks[k]),
203
+ title: `Peak efficiency at ${peaks[k].speed}`,
204
+ color: crest
205
+ }));
206
+ if (!floorMap) return;
207
+ const flat = new TubeBatch(.004);
208
+ for (const { nodes } of traced) flat.add(nodes.map((node) => sheet.floor(node, .006)));
209
+ this.tubes(flat, ctx.root, ink);
210
+ const islands = new TubeBatch(.004);
211
+ for (const { value, paths } of sheet.contours(mesh.levels())) for (const path of paths) islands.add(path.map((node) => sheet.floor(node, .006)), paint(value));
212
+ this.tubes(islands, ctx.root);
213
+ this.tubes(new TubeBatch(.007).add(surged.map((node) => sheet.floor(node, .007))), ctx.root, theme.ink);
214
+ this.tubes(new TubeBatch(.004).add(choked.map((node) => sheet.floor(node, .007))), ctx.root, theme.inkMuted);
215
+ }
216
+ };
217
+ export { CompressorMap3DChart, CompressorMap3DSurge };
@@ -0,0 +1,50 @@
1
+ // src/charts/threefields/FieldGrid.ts
2
+ /** Reads a gridded surface by data position, so paths given in the grid's own units can be laid on it. */
3
+ var FieldGrid = class FieldGrid {
4
+ field;
5
+ space;
6
+ constructor(field, space) {
7
+ this.field = field;
8
+ this.space = space;
9
+ }
10
+ /** Fractional index of `value` along an axis that runs one way, held inside it. */
11
+ static index(axis, value) {
12
+ const last = axis.length - 1, falling = axis[0] > axis[last];
13
+ let i = 0;
14
+ while (i < last - 1 && (falling ? axis[i + 1] > value : axis[i + 1] < value)) i++;
15
+ const span = axis[i + 1] - axis[i];
16
+ return i + (span ? Math.max(0, Math.min(1, (value - axis[i]) / span)) : 0);
17
+ }
18
+ index(x, y) {
19
+ return [FieldGrid.index(this.field.x, x), FieldGrid.index(this.field.y, y)];
20
+ }
21
+ /** The gridded value under a point; a point past the grid reads its nearest edge. */
22
+ value(x, y) {
23
+ return this.field.sample(...this.index(x, y));
24
+ }
25
+ /** World position on the surface under a point. */
26
+ at(x, y, lift = 0) {
27
+ return this.space.at(...this.index(x, y), lift);
28
+ }
29
+ /** Lays a track on the surface, cutting each leg so no piece spans more than `cell` grid cells and the line cannot dive under a ridge. */
30
+ drape(track, lift = 0, cell = .5) {
31
+ const path = [], knots = [];
32
+ let before = null;
33
+ for (const [x, y] of track) {
34
+ const here = this.index(x, y);
35
+ const pieces = before ? Math.max(1, Math.ceil(Math.max(Math.abs(here[0] - before[0]), Math.abs(here[1] - before[1])) / cell)) : 1;
36
+ for (let piece = 1; piece < pieces; piece++) {
37
+ const t = piece / pieces;
38
+ path.push(this.space.at(before[0] + (here[0] - before[0]) * t, before[1] + (here[1] - before[1]) * t, lift));
39
+ }
40
+ knots.push(path.length);
41
+ path.push(this.space.at(here[0], here[1], lift));
42
+ before = here;
43
+ }
44
+ return {
45
+ path,
46
+ knots
47
+ };
48
+ }
49
+ };
50
+ export { FieldGrid };
@@ -0,0 +1,201 @@
1
+ import { ChartFamily, DataShape, Dimension, ScaleKind } from "../../core/enums.js";
2
+ import { Scales } from "../../core/Scales.js";
3
+ import { ModelSamples } from "../modelcharts/ModelSamples.js";
4
+ import { ColorRamp } from "../threesurfaces/ColorRamp.js";
5
+ import { SurfaceOverlay } from "../threesurfaces/SurfaceBase.js";
6
+ import { SurfaceField } from "../threesurfaces/SurfaceField.js";
7
+ import { SurfaceGeometry } from "../threesurfaces/SurfaceGeometry.js";
8
+ import { CEIL, FLOOR, SurfaceSpace } from "../threesurfaces/SurfaceSpace.js";
9
+ import { TubeBatch } from "../threesurfaces/TubeBatch.js";
10
+ import { FieldGrid } from "./FieldGrid.js";
11
+ import { ThreeFieldBase } from "./ThreeFieldBase.js";
12
+ import { format, mean, scaleLinear, scaleLog } from "d3";
13
+ // src/charts/threefields/LossLandscape3DChart.ts
14
+ /** How an optimiser's run is drawn: a tube with a ball on each step, the tube alone, or not at all. */
15
+ var LossLandscape3DTrail = /* @__PURE__ */ function(LossLandscape3DTrail) {
16
+ LossLandscape3DTrail["Steps"] = "step-markers";
17
+ LossLandscape3DTrail["Path"] = "path-only";
18
+ LossLandscape3DTrail["None"] = "no-path";
19
+ return LossLandscape3DTrail;
20
+ }({});
21
+ var MOST_DOTS = 90;
22
+ var figure = format(".3~g");
23
+ /**
24
+ * The loss over two directions in parameter space as a height surface, with each optimiser's run laid on it as a tube.
25
+ * Use it when the depth of a valley or the sharpness of a minimum matters more than exact levels; the 2D loss
26
+ * landscape takes the same data and reads levels more precisely.
27
+ */
28
+ var LossLandscape3DChart = class LossLandscape3DChart extends ThreeFieldBase {
29
+ static meta = {
30
+ id: "loss-landscape-3d",
31
+ name: "3D loss landscape",
32
+ family: ChartFamily.Scientific,
33
+ dimension: Dimension.Three,
34
+ shape: DataShape.Grid,
35
+ description: "Raises a loss over two parameter directions into a surface on a linear or log height, and lays the path of each optimiser on it as a tube with a marker per step.",
36
+ tags: [
37
+ "machine learning",
38
+ "optimisation",
39
+ "gradient descent",
40
+ "loss surface",
41
+ "training",
42
+ "optimizer path"
43
+ ],
44
+ sample: (seed) => ModelSamples.lossSurface(seed),
45
+ variants: {
46
+ scale: [ScaleKind.Linear, ScaleKind.Log],
47
+ trail: Object.values(LossLandscape3DTrail),
48
+ overlay: [
49
+ SurfaceOverlay.Contours,
50
+ SurfaceOverlay.Mesh,
51
+ SurfaceOverlay.None
52
+ ],
53
+ floorMap: [false, true]
54
+ }
55
+ };
56
+ defaults() {
57
+ return {
58
+ ...super.defaults(),
59
+ scale: ScaleKind.Linear,
60
+ trail: "step-markers",
61
+ overlay: SurfaceOverlay.Contours,
62
+ floorMap: false,
63
+ levels: 9,
64
+ xLabel: "Direction 1",
65
+ yLabel: "Direction 2",
66
+ zLabel: "Loss"
67
+ };
68
+ }
69
+ /** The grid, with its depth axis turned when that brings the lower of its two ends to the front, where no wall hides the valley floor. */
70
+ get losses() {
71
+ const field = SurfaceField.from(this.options.data).capped(90), { nx, ny } = field;
72
+ const end = (j) => mean(Array.from({ length: nx }, (_, i) => field.at(i, j)).filter(Number.isFinite)) ?? 0;
73
+ if (!(end(ny - 1) < end(0))) return field;
74
+ const turned = new Float64Array(nx * ny);
75
+ for (let j = 0; j < ny; j++) turned.set(field.z.subarray((ny - 1 - j) * nx, (ny - j) * nx), j * nx);
76
+ return new SurfaceField(field.x, [...field.y].reverse(), turned);
77
+ }
78
+ table() {
79
+ return this.gridTable(SurfaceField.from(this.options.data));
80
+ }
81
+ /** `Log` is log10 while every loss is positive, and asinh around zero otherwise, so zero and negative losses stay on the chart. */
82
+ static warp({ zMin, zMax, zDomain }, scale = ScaleKind.Linear) {
83
+ if (scale !== ScaleKind.Log) return {
84
+ to: (loss) => loss,
85
+ ticks: scaleLinear(zDomain, [0, 1]).ticks(4)
86
+ };
87
+ if (!(zMin > 0)) {
88
+ const bend = Math.max(zMax - zMin, 1e-9) / 50;
89
+ return {
90
+ to: (loss) => Math.asinh(loss / bend),
91
+ ticks: scaleLinear(zDomain, [0, 1]).ticks(4)
92
+ };
93
+ }
94
+ const all = scaleLog([zMin, Math.max(zMax, zMin * 1.0001)], [0, 1]).ticks(), tens = all.filter((tick) => Math.abs(Math.log10(tick) % 1) < 1e-9);
95
+ return {
96
+ to: Math.log10,
97
+ ticks: tens.length >= 2 ? tens : all.filter((_, i) => i % Math.ceil(all.length / 4) === 0)
98
+ };
99
+ }
100
+ /** Each run with the loss under every step. A step past the grid sits on its nearest edge, and one over a gap is left out. */
101
+ runs(ctx, losses, grid) {
102
+ const paths = this.options.data?.paths;
103
+ if (this.options.trail === "no-path" || !Array.isArray(paths)) return [];
104
+ return paths.filter((path) => path && Array.isArray(path.points)).map((path, i) => {
105
+ const name = String(path.name ?? `Path ${i + 1}`);
106
+ const read = path.points.map((point, index) => ({
107
+ index,
108
+ x: +point?.[0],
109
+ y: +point?.[1]
110
+ })).filter((step) => Number.isFinite(step.x) && Number.isFinite(step.y)).map((step) => ({
111
+ ...step,
112
+ loss: losses.sample(...grid.index(step.x, step.y))
113
+ })).filter((step) => Number.isFinite(step.loss));
114
+ const { path: laid, knots } = grid.drape(read.map((step) => [step.x, step.y]), .012);
115
+ return {
116
+ name,
117
+ color: "",
118
+ steps: read.map((step, k) => ({
119
+ ...step,
120
+ at: laid[knots[k]]
121
+ })),
122
+ path: laid
123
+ };
124
+ }).filter((run) => run.steps.length).map((run) => ({
125
+ ...run,
126
+ color: ctx.palette.color(run.name)
127
+ }));
128
+ }
129
+ build(ctx) {
130
+ const { scale, trail, overlay, floorMap, levels, xLabel, yLabel, zLabel } = this.options;
131
+ const losses = this.losses, warp = LossLandscape3DChart.warp(losses, scale);
132
+ const field = losses.map(warp.to);
133
+ const space = new SurfaceSpace(field, ScaleKind.Linear, [FLOOR + (floorMap ? .42 : .04), CEIL]), grid = new FieldGrid(field, space);
134
+ const [low, high] = field.zDomain, ramp = new ColorRamp(ctx.palette.sequential);
135
+ const paint = (value) => ramp.at(.05 + .95 * (value - low) / (high - low));
136
+ const [x0, x1] = field.xDomain, [y0, y1] = field.yDomain, reach = losses.zDomain[1] - losses.zDomain[0];
137
+ this.box(ctx, {
138
+ x: this.ticks(field.xDomain, (v) => (v - x0) / (x1 - x0 || 1) * 2 - 1),
139
+ y: this.ticks(field.yDomain, (v) => 1 - (v - y0) / (y1 - y0 || 1) * 2),
140
+ z: warp.ticks.map((loss) => [space.level(warp.to(loss)), scale === ScaleKind.Log ? figure(loss) : Scales.format(loss, reach)])
141
+ });
142
+ const lift = this.rise(ctx);
143
+ this.solid(ctx, SurfaceGeometry.grid(field.nx, field.ny, (i, j) => space.at(i, j), (i, j) => paint(field.at(i, j))), lift, (k) => {
144
+ const i = k % field.nx, j = Math.floor(k / field.nx);
145
+ return { rows: [
146
+ [zLabel, figure(losses.at(i, j))],
147
+ [xLabel, figure(field.x[i])],
148
+ [yLabel, figure(field.y[j])]
149
+ ] };
150
+ });
151
+ if (!field.hasData) return;
152
+ if (overlay === SurfaceOverlay.Mesh) this.meshLines(ctx, space, lift);
153
+ if (overlay === SurfaceOverlay.Contours) this.contourLines(ctx, space, lift, levels);
154
+ if (floorMap) this.floorContours(ctx, space, paint, levels);
155
+ const runs = this.runs(ctx, losses, grid);
156
+ const tip = (run, step, title = `${run.name}, step ${step.index}`) => ({
157
+ title,
158
+ color: run.color,
159
+ rows: [
160
+ [zLabel, figure(step.loss)],
161
+ [xLabel, figure(step.x)],
162
+ [yLabel, figure(step.y)]
163
+ ]
164
+ });
165
+ for (const run of runs) {
166
+ this.casing(run.path, .008, ctx.theme.surface, lift);
167
+ const tube = this.tubes(new TubeBatch(.008).add(run.path), lift, run.color);
168
+ if (tube) ctx.pick(tube, () => ({
169
+ title: run.name,
170
+ color: run.color,
171
+ rows: [
172
+ ["Steps", run.steps.length - 1],
173
+ ["Loss at start", figure(run.steps[0].loss)],
174
+ ["Loss at end", figure(run.steps.at(-1).loss)]
175
+ ]
176
+ }));
177
+ if (floorMap) this.tubes(new TubeBatch(.004).add(run.path.map(([x, , z]) => [
178
+ x,
179
+ FLOOR + .008,
180
+ z
181
+ ])), ctx.root, run.color);
182
+ }
183
+ const between = trail === "step-markers" ? runs.flatMap((run) => {
184
+ const every = Math.max(1, Math.ceil(run.steps.length / MOST_DOTS));
185
+ return run.steps.slice(1, -1).filter((_, k) => (k + 1) % every === 0).map((step) => ({
186
+ run,
187
+ step
188
+ }));
189
+ }) : [];
190
+ this.dots(ctx, between.map(({ step }) => step.at), .014, (k) => ctx.color(between[k].run.color), lift, (k) => tip(between[k].run, between[k].step));
191
+ this.rings(ctx, runs.map((run) => run.steps[0].at), .03, (k) => ctx.color(runs[k].color), lift, (k) => tip(runs[k], runs[k].steps[0], `${runs[k].name}, start`));
192
+ const ended = runs.filter((run) => run.steps.length > 1);
193
+ this.dots(ctx, ended.map((run) => run.steps.at(-1).at), .03, (k) => ctx.color(ended[k].color), lift, (k) => tip(ended[k], ended[k].steps.at(-1), `${ended[k].name}, end after ${ended[k].steps.at(-1).index} steps`));
194
+ const lowest = losses.z.indexOf(losses.zMin);
195
+ if (lowest >= 0) this.pins(ctx, [{
196
+ at: space.at(lowest % field.nx, Math.floor(lowest / field.nx)),
197
+ text: `Lowest loss ${figure(losses.zMin)}`
198
+ }], lift);
199
+ }
200
+ };
201
+ export { LossLandscape3DChart, LossLandscape3DTrail };
@@ -0,0 +1,77 @@
1
+ import { SurfaceField } from "../threesurfaces/SurfaceField.js";
2
+ import { SurfaceGeometry } from "../threesurfaces/SurfaceGeometry.js";
3
+ import { CEIL, FLOOR } from "../threesurfaces/SurfaceSpace.js";
4
+ import { extent } from "d3";
5
+ // src/charts/threefields/MapSheet.ts
6
+ var span = (values) => {
7
+ const [low, high] = extent(values.filter(Number.isFinite));
8
+ return low === void 0 || high === void 0 ? [0, 1] : high > low ? [low, high] : [low - 1, low + 1];
9
+ };
10
+ var mix = (a, b, t) => ({
11
+ x: a.x + (b.x - a.x) * t,
12
+ y: a.y + (b.y - a.y) * t,
13
+ z: a.z + (b.z - a.z) * t
14
+ });
15
+ /**
16
+ * A test-bench map as a sheet in the cube: the map's x runs across, its y runs into the depth and the mapped quantity is
17
+ * the height. The sheet follows the mesh of the sweeps, so its outline is the operating range and not a rectangle.
18
+ */
19
+ var MapSheet = class {
20
+ mesh;
21
+ near;
22
+ range;
23
+ x;
24
+ y;
25
+ z;
26
+ /** `points` are the measured nodes the axes must hold. `near` brings the high end of y to the front. */
27
+ constructor(mesh, points, near = false, range = [FLOOR + .3, CEIL]) {
28
+ this.mesh = mesh;
29
+ this.near = near;
30
+ this.range = range;
31
+ const all = [...mesh.nodes.flat(), ...points];
32
+ this.x = span(all.map((node) => node.x));
33
+ this.y = span(all.map((node) => node.y));
34
+ this.z = span(all.map((node) => node.z));
35
+ }
36
+ across = (x) => (x - this.x[0]) / (this.x[1] - this.x[0]) * 2 - 1;
37
+ depth = (y) => (1 - (y - this.y[0]) / (this.y[1] - this.y[0]) * 2) * (this.near ? -1 : 1);
38
+ level = (z) => this.range[0] + (z - this.z[0]) / (this.z[1] - this.z[0]) * (this.range[1] - this.range[0]);
39
+ /** A node on the sheet. One with no height lies on the floor. */
40
+ place(node, lift = 0) {
41
+ return [
42
+ this.across(node.x),
43
+ (Number.isFinite(node.z) ? this.level(node.z) : FLOOR) + lift,
44
+ this.depth(node.y)
45
+ ];
46
+ }
47
+ floor(node, lift = 0) {
48
+ return [
49
+ this.across(node.x),
50
+ FLOOR + lift,
51
+ this.depth(node.y)
52
+ ];
53
+ }
54
+ /** The map at fractional mesh coordinates. */
55
+ node(column, row) {
56
+ const { nodes, columns, rows } = this.mesh;
57
+ const i = Math.max(0, Math.min(columns - 2, Math.floor(column))), j = Math.max(0, Math.min(rows - 2, Math.floor(row)));
58
+ return mix(mix(nodes[j][i], nodes[j][i + 1], column - i), mix(nodes[j + 1][i], nodes[j + 1][i + 1], column - i), row - j);
59
+ }
60
+ geometry(paint) {
61
+ const { nodes, columns, rows } = this.mesh;
62
+ return SurfaceGeometry.grid(columns, rows, (i, j) => this.place(nodes[j][i]), (i, j) => paint(nodes[j][i].z));
63
+ }
64
+ /** Lines of equal height across the sheet, each node carrying the level as its z. */
65
+ contours(levels) {
66
+ const { columns, rows, values } = this.mesh;
67
+ if (!rows || !levels.length) return [];
68
+ return new SurfaceField(Array.from({ length: columns }, (_, i) => i), Array.from({ length: rows }, (_, j) => j), Float64Array.from(values)).lines(levels).map(({ value, paths }) => ({
69
+ value,
70
+ paths: paths.map((path) => path.map(([i, j]) => ({
71
+ ...this.node(i, j),
72
+ z: value
73
+ })))
74
+ }));
75
+ }
76
+ };
77
+ export { MapSheet };