@mstone6969/graph 0.1.0 → 0.2.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 (238) hide show
  1. package/README.md +111 -14
  2. package/dist/ExcelWriter-3ZSYUH4T.cjs +154 -0
  3. package/dist/GraphType.js +24 -38
  4. package/dist/PdfWriter-6HJFYMCO.cjs +205 -0
  5. package/dist/catalog-YWX6FHRM.cjs +8 -0
  6. package/dist/catalog.js +5 -1
  7. package/dist/charts/bars/index.js +2 -12
  8. package/dist/charts/comparison/EffectForestPlot.js +1 -1
  9. package/dist/charts/comparison/index.js +1 -8
  10. package/dist/charts/demography/Nomogram.js +3 -3
  11. package/dist/charts/density/HexbinChart.js +6 -4
  12. package/dist/charts/diagrams/ArchitectureCanvas.js +68 -0
  13. package/dist/charts/diagrams/ArchitectureDiagram.js +331 -0
  14. package/dist/charts/diagrams/ArchitectureLayout.js +106 -0
  15. package/dist/charts/diagrams/ArchitectureLinkLabels.js +78 -0
  16. package/dist/charts/diagrams/ArchitectureModel.js +108 -0
  17. package/dist/charts/diagrams/ArchitectureRouter.js +348 -0
  18. package/dist/charts/diagrams/ArchitectureSamples.js +312 -0
  19. package/dist/charts/diagrams/ArchitectureShapes.js +130 -0
  20. package/dist/charts/diagrams/ArchitectureText.js +25 -0
  21. package/dist/charts/diagrams/DiagramText.js +38 -0
  22. package/dist/charts/diagrams/EntityRelationshipDiagram.js +465 -0
  23. package/dist/charts/diagrams/ErCrowsFoot.js +33 -0
  24. package/dist/charts/diagrams/ErSamples.js +205 -0
  25. package/dist/charts/diagrams/ErSchema.js +122 -0
  26. package/dist/charts/diagrams/LogicCircuit.js +154 -0
  27. package/dist/charts/diagrams/LogicCircuitLayout.js +600 -0
  28. package/dist/charts/diagrams/LogicCircuitSamples.js +66 -0
  29. package/dist/charts/diagrams/LogicGateDiagram.js +216 -0
  30. package/dist/charts/diagrams/LogicGateSymbol.js +113 -0
  31. package/dist/charts/diagrams/NetworkTopologyDiagram.js +247 -0
  32. package/dist/charts/diagrams/SequenceDiagram.js +351 -0
  33. package/dist/charts/diagrams/SequenceLayout.js +422 -0
  34. package/dist/charts/diagrams/SequenceModel.js +221 -0
  35. package/dist/charts/diagrams/TopologyLayout.js +143 -0
  36. package/dist/charts/diagrams/architectureEnums.js +50 -0
  37. package/dist/charts/diagrams/index.js +26 -0
  38. package/dist/charts/diagrams/logicEnums.js +42 -0
  39. package/dist/charts/diagrams/sequenceEnums.js +40 -0
  40. package/dist/charts/distribution/HistogramChart.js +25 -3
  41. package/dist/charts/distribution/index.js +1 -3
  42. package/dist/charts/earthscience/HovmollerDiagram.js +477 -0
  43. package/dist/charts/earthscience/HovmollerEnums.js +42 -0
  44. package/dist/charts/earthscience/HovmollerField.js +180 -0
  45. package/dist/charts/earthscience/HovmollerSample.js +40 -0
  46. package/dist/charts/earthscience/HovmollerSpeed.js +71 -0
  47. package/dist/charts/earthscience/index.js +10 -2
  48. package/dist/charts/engineering/ConstellationDiagram.js +26 -6
  49. package/dist/charts/engineering/EyeDiagram.js +2 -1
  50. package/dist/charts/engineering/PoleZeroPlot.js +32 -8
  51. package/dist/charts/financial/RelativeStrengthRotation.js +434 -0
  52. package/dist/charts/financial/RelativeStrengthRotationMath.js +71 -0
  53. package/dist/charts/financial/RelativeStrengthRotationSamples.js +27 -0
  54. package/dist/charts/financial/index.js +5 -3
  55. package/dist/charts/flow/index.js +1 -5
  56. package/dist/charts/frameworks/AnsoffMatrix.js +523 -0
  57. package/dist/charts/frameworks/FrameworkText.js +98 -0
  58. package/dist/charts/frameworks/NpsGauge.js +279 -0
  59. package/dist/charts/frameworks/NpsSurvey.js +58 -0
  60. package/dist/charts/frameworks/PerceptualMap.js +419 -0
  61. package/dist/charts/frameworks/PerceptualProjection.js +142 -0
  62. package/dist/charts/frameworks/PositioningSamples.js +191 -0
  63. package/dist/charts/frameworks/RaciMatrix.js +458 -0
  64. package/dist/charts/frameworks/RaciPlan.js +81 -0
  65. package/dist/charts/frameworks/RaciSamples.js +76 -0
  66. package/dist/charts/frameworks/SwotMatrix.js +358 -0
  67. package/dist/charts/frameworks/SwotSamples.js +85 -0
  68. package/dist/charts/frameworks/VanWestendorpChart.js +187 -0
  69. package/dist/charts/frameworks/VanWestendorpSurvey.js +197 -0
  70. package/dist/charts/frameworks/index.js +26 -0
  71. package/dist/charts/frameworks/raciEnums.js +30 -0
  72. package/dist/charts/frameworks/swotEnums.js +34 -0
  73. package/dist/charts/genomics/CircosPlot.js +1 -1
  74. package/dist/charts/geoflows/GeoFlowChart.js +2 -2
  75. package/dist/charts/geoflows/GeoFlowSample.js +2 -1
  76. package/dist/charts/geomaps/FloorPlanMap.js +324 -0
  77. package/dist/charts/geomaps/FloorPlanModel.js +179 -0
  78. package/dist/charts/geomaps/FloorPlanSamples.js +416 -0
  79. package/dist/charts/geomaps/GeoLand.js +2 -2
  80. package/dist/charts/geomaps/GeoSamples.js +2 -1
  81. package/dist/charts/geomaps/GraticuleMap.js +2 -2
  82. package/dist/charts/geomaps/RoomLabelFit.js +200 -0
  83. package/dist/charts/geomaps/TissotMap.js +2 -2
  84. package/dist/charts/geomaps/index.js +8 -4
  85. package/dist/charts/hierarchy/SunburstChart.js +17 -10
  86. package/dist/charts/hierarchy/index.js +2 -11
  87. package/dist/charts/indicators/BulletChart.js +8 -2
  88. package/dist/charts/indicators/SpeedometerChart.js +1 -1
  89. package/dist/charts/indicators/ThermometerChart.js +1 -1
  90. package/dist/charts/lifescience/LoessFit.js +113 -0
  91. package/dist/charts/lifescience/MaPlot.js +337 -0
  92. package/dist/charts/lifescience/MaPlotSamples.js +35 -0
  93. package/dist/charts/lifescience/OncoGlyph.js +137 -0
  94. package/dist/charts/lifescience/OncoPrint.js +373 -0
  95. package/dist/charts/lifescience/OncoPrintMatrix.js +107 -0
  96. package/dist/charts/lifescience/OncoPrintSamples.js +142 -0
  97. package/dist/charts/lifescience/PedigreeChart.js +306 -0
  98. package/dist/charts/lifescience/PedigreeLayout.js +261 -0
  99. package/dist/charts/lifescience/PedigreeRows.js +70 -0
  100. package/dist/charts/lifescience/PedigreeSamples.js +161 -0
  101. package/dist/charts/lifescience/PedigreeSymbol.js +47 -0
  102. package/dist/charts/lifescience/RamachandranPlot.js +364 -0
  103. package/dist/charts/lifescience/RamachandranRegions.js +2712 -0
  104. package/dist/charts/lifescience/RamachandranSamples.js +235 -0
  105. package/dist/charts/lifescience/index.js +25 -0
  106. package/dist/charts/lifescience/pedigreeEnums.js +21 -0
  107. package/dist/charts/lifescience/ramachandranEnums.js +34 -0
  108. package/dist/charts/linesareas/DualAxisChart.js +1 -1
  109. package/dist/charts/linesareas/LineEnums.js +1 -15
  110. package/dist/charts/linesareas/MultiLineChart.js +1 -1
  111. package/dist/charts/linesareas/TrendChart.js +15 -5
  112. package/dist/charts/linesareas/index.js +2 -6
  113. package/dist/charts/massive/MassiveChart.js +3 -2
  114. package/dist/charts/mathematical/FourierSeriesChart.js +7 -1
  115. package/dist/charts/mathematical/index.js +2 -6
  116. package/dist/charts/matrix/GridPlot.js +27 -2
  117. package/dist/charts/matrix/TilegramChart.js +2 -2
  118. package/dist/charts/mlcharts/AttentionGrid.js +79 -0
  119. package/dist/charts/mlcharts/AttentionHeatmap.js +329 -0
  120. package/dist/charts/mlcharts/AttentionModel.js +132 -0
  121. package/dist/charts/mlcharts/AttentionSamples.js +82 -0
  122. package/dist/charts/mlcharts/CellNumber.js +8 -0
  123. package/dist/charts/mlcharts/CurveDiagnosticSamples.js +95 -0
  124. package/dist/charts/mlcharts/CurvePickMark.js +31 -0
  125. package/dist/charts/mlcharts/DecisionBoundaryChart.js +316 -0
  126. package/dist/charts/mlcharts/DecisionSamples.js +60 -0
  127. package/dist/charts/mlcharts/DecisionSurface.js +130 -0
  128. package/dist/charts/mlcharts/DistinctTicks.js +13 -0
  129. package/dist/charts/mlcharts/ElbowMath.js +153 -0
  130. package/dist/charts/mlcharts/ElbowPlot.js +273 -0
  131. package/dist/charts/mlcharts/ExplainabilitySamples.js +70 -0
  132. package/dist/charts/mlcharts/FeatureImportanceChart.js +150 -0
  133. package/dist/charts/mlcharts/ImportanceRanking.js +98 -0
  134. package/dist/charts/mlcharts/LearningCurveChart.js +276 -0
  135. package/dist/charts/mlcharts/LearningCurveMath.js +92 -0
  136. package/dist/charts/mlcharts/PartialDependence.js +92 -0
  137. package/dist/charts/mlcharts/PartialDependencePlot.js +225 -0
  138. package/dist/charts/mlcharts/WideLabel.js +28 -0
  139. package/dist/charts/mlcharts/curveDiagnosticEnums.js +37 -0
  140. package/dist/charts/mlcharts/index.js +32 -0
  141. package/dist/charts/proportion/index.js +5 -9
  142. package/dist/charts/scatter/CategoryScatterBase.js +1 -4
  143. package/dist/charts/scatter/ConnectedScatter.js +7 -4
  144. package/dist/charts/scatter/MarginalScatter.js +13 -8
  145. package/dist/charts/scatter/index.js +4 -17
  146. package/dist/charts/scientific/SpectrogramChart.js +9 -3
  147. package/dist/charts/scientific/index.js +2 -2
  148. package/dist/charts/signals/index.js +3 -13
  149. package/dist/charts/statistics/LorenzCurve.js +7 -4
  150. package/dist/charts/threebars/Candlestick3DChart.js +18 -2
  151. package/dist/charts/threeglobe/GlobeChart.js +2 -2
  152. package/dist/charts/threeglobe/GlobeSamples.js +2 -1
  153. package/dist/charts/threeglobe/RingGlobe.js +1 -1
  154. package/dist/charts/threenetwork/ConeTreeChart.js +2 -1
  155. package/dist/charts/threenetwork/Gantt3DChart.js +3 -2
  156. package/dist/charts/threesurfaces/Ridgeline3DChart.js +22 -4
  157. package/dist/charts/threevolume/LorenzAttractor.js +19 -0
  158. package/dist/charts/threevolume/VolumeRaycastChart.js +4 -3
  159. package/dist/charts/threevolume/volumeEnums.js +1 -0
  160. package/dist/charts/timeline/index.js +2 -10
  161. package/dist/chunk-753UBLV2.cjs +33 -0
  162. package/dist/chunk-VX54A7KA.cjs +17 -0
  163. package/dist/{chunk-W5GAAAZY.cjs → chunk-WAODDPYX.cjs} +24874 -17620
  164. package/dist/chunk-Z3JPIJSC.cjs +338 -0
  165. package/dist/core/CartesianChart.js +87 -11
  166. package/dist/core/Chart.js +63 -15
  167. package/dist/core/Chart2D.js +54 -17
  168. package/dist/core/Chart3D.js +56 -20
  169. package/dist/core/ChartExportError.js +2 -0
  170. package/dist/core/ChartExporter.js +50 -8
  171. package/dist/core/ColumnCheck.js +53 -0
  172. package/dist/core/Context2D.js +29 -15
  173. package/dist/core/Context3D.js +7 -2
  174. package/dist/core/ExcelWriter.js +152 -0
  175. package/dist/core/ExportText.js +28 -0
  176. package/dist/core/MarkOrigin.js +88 -0
  177. package/dist/core/MarkStyle.js +294 -0
  178. package/dist/core/Palette.js +27 -7
  179. package/dist/core/PdfPage.js +13 -0
  180. package/dist/core/PdfWriter.js +245 -0
  181. package/dist/core/Scales.js +52 -2
  182. package/dist/core/SceneOverlay.js +4 -4
  183. package/dist/core/TextFit.js +37 -0
  184. package/dist/core/Theme.js +28 -1
  185. package/dist/core/enums.js +33 -1
  186. package/dist/core/pathMorph.js +15 -0
  187. package/dist/data/SampleData.js +1 -17
  188. package/dist/data/WorldSample.js +23 -0
  189. package/dist/index.cjs +810 -691
  190. package/dist/index.d.cts +8390 -2925
  191. package/dist/index.d.ts +8392 -2927
  192. package/dist/index.js +106 -56
  193. package/dist/react/ChartView.js +18 -8
  194. package/dist/react/GraphHandle.js +2 -0
  195. package/dist/react/components.js +74 -116
  196. package/package.json +13 -3
  197. package/dist/catalog-4UP2YFNR.cjs +0 -7
  198. package/dist/charts/bars/BulletBar.js +0 -184
  199. package/dist/charts/bars/ErrorBarColumn.js +0 -147
  200. package/dist/charts/bars/HistogramBar.js +0 -217
  201. package/dist/charts/bars/MarimekkoBar.js +0 -191
  202. package/dist/charts/bars/ParetoBar.js +0 -143
  203. package/dist/charts/comparison/PanelChart.js +0 -70
  204. package/dist/charts/comparison/SmallMultipleBars.js +0 -134
  205. package/dist/charts/comparison/SpanChart.js +0 -118
  206. package/dist/charts/comparison/TrellisChart.js +0 -158
  207. package/dist/charts/distribution/RidgeSlabs3DChart.js +0 -169
  208. package/dist/charts/financial/Candlestick3D.js +0 -157
  209. package/dist/charts/flow/BumpFlow.js +0 -212
  210. package/dist/charts/flow/StreamFlow.js +0 -174
  211. package/dist/charts/geomaps/ThiessenMap.js +0 -106
  212. package/dist/charts/hierarchy/ConeTree3D.js +0 -135
  213. package/dist/charts/hierarchy/Hierarchy3DChart.js +0 -27
  214. package/dist/charts/hierarchy/SpherePack3D.js +0 -81
  215. package/dist/charts/hierarchy/SunburstTower3D.js +0 -93
  216. package/dist/charts/hierarchy/TreemapSkyline3D.js +0 -98
  217. package/dist/charts/linesareas/ConnectedScatterTime.js +0 -206
  218. package/dist/charts/linesareas/SmallMultipleLines.js +0 -153
  219. package/dist/charts/mathematical/ParametricSurface3D.js +0 -234
  220. package/dist/charts/mathematical/StrangeAttractor3D.js +0 -251
  221. package/dist/charts/proportion/ConeFunnel.js +0 -126
  222. package/dist/charts/proportion/ExtrudedPieChart.js +0 -123
  223. package/dist/charts/scatter/BeeswarmScatter.js +0 -151
  224. package/dist/charts/scatter/BinnedScatterBase.js +0 -51
  225. package/dist/charts/scatter/ContourScatter.js +0 -116
  226. package/dist/charts/scatter/GridBinScatter.js +0 -98
  227. package/dist/charts/scatter/HexbinScatter.js +0 -74
  228. package/dist/charts/scatter/StripScatter.js +0 -107
  229. package/dist/charts/scatter/SunflowerScatter.js +0 -109
  230. package/dist/charts/signals/ConstellationChart.js +0 -153
  231. package/dist/charts/signals/CorrelogramChart.js +0 -171
  232. package/dist/charts/signals/EyeDiagramChart.js +0 -155
  233. package/dist/charts/signals/PoleZeroChart.js +0 -164
  234. package/dist/charts/signals/SpectrogramChart.js +0 -79
  235. package/dist/charts/timeline/CalendarSkylineChart.js +0 -128
  236. package/dist/charts/timeline/ScheduleBlocksChart.js +0 -119
  237. package/dist/charts/timeline/SpiralTimeline.js +0 -154
  238. package/dist/charts/timeline/StreamTimeline.js +0 -141
@@ -1,251 +0,0 @@
1
- import { Chart3D } from "../../core/Chart3D.js";
2
- import { ChartFamily, DataShape, Dimension } from "../../core/enums.js";
3
- import { SampleData } from "../../data/SampleData.js";
4
- import { MathNumerics } from "./MathNumerics.js";
5
- import { scaleLinear } from "d3";
6
- import { BufferGeometry, CatmullRomCurve3, Color, Float32BufferAttribute, InstancedMesh, Line, LineBasicMaterial, Mesh, MeshStandardMaterial, Object3D, SphereGeometry, TubeGeometry, Vector3 } from "three";
7
- // src/charts/mathematical/StrangeAttractor3D.ts
8
- var AttractorSystem = /* @__PURE__ */ function(AttractorSystem) {
9
- AttractorSystem["Lorenz"] = "lorenz";
10
- AttractorSystem["Rossler"] = "rossler";
11
- AttractorSystem["Aizawa"] = "aizawa";
12
- AttractorSystem["Thomas"] = "thomas";
13
- AttractorSystem["Halvorsen"] = "halvorsen";
14
- AttractorSystem["ChenLee"] = "chen-lee";
15
- return AttractorSystem;
16
- }({});
17
- var AttractorRender = /* @__PURE__ */ function(AttractorRender) {
18
- AttractorRender["Tube"] = "tube";
19
- AttractorRender["Line"] = "line";
20
- AttractorRender["Beads"] = "beads";
21
- return AttractorRender;
22
- }({});
23
- var SYSTEMS = {
24
- ["lorenz"]: {
25
- flow: (x, y, z) => [
26
- 10 * (y - x),
27
- x * (28 - z) - y,
28
- x * y - 8 / 3 * z
29
- ],
30
- start: [
31
- 1,
32
- 1,
33
- 20
34
- ],
35
- dt: .006,
36
- steps: 6e3
37
- },
38
- ["rossler"]: {
39
- flow: (x, y, z) => [
40
- -y - z,
41
- x + .2 * y,
42
- .2 + z * (x - 5.7)
43
- ],
44
- start: [
45
- 1,
46
- 1,
47
- 0
48
- ],
49
- dt: .03,
50
- steps: 6e3
51
- },
52
- ["aizawa"]: {
53
- flow: (x, y, z) => [
54
- (z - .7) * x - 3.5 * y,
55
- 3.5 * x + (z - .7) * y,
56
- .6 + .95 * z - z ** 3 / 3 - (x * x + y * y) * (1 + .25 * z) + .1 * z * x ** 3
57
- ],
58
- start: [
59
- .1,
60
- 0,
61
- .1
62
- ],
63
- dt: .012,
64
- steps: 7e3
65
- },
66
- ["thomas"]: {
67
- flow: (x, y, z) => [
68
- Math.sin(y) - .19 * x,
69
- Math.sin(z) - .19 * y,
70
- Math.sin(x) - .19 * z
71
- ],
72
- start: [
73
- 1.1,
74
- 1.1,
75
- -.1
76
- ],
77
- dt: .06,
78
- steps: 7e3
79
- },
80
- ["halvorsen"]: {
81
- flow: (x, y, z) => [
82
- -1.4 * x - 4 * y - 4 * z - y * y,
83
- -1.4 * y - 4 * z - 4 * x - z * z,
84
- -1.4 * z - 4 * x - 4 * y - x * x
85
- ],
86
- start: [
87
- -1.5,
88
- 0,
89
- 0
90
- ],
91
- dt: .006,
92
- steps: 6e3
93
- },
94
- ["chen-lee"]: {
95
- flow: (x, y, z) => [
96
- 5 * x - y * z,
97
- -10 * y + x * z,
98
- -3.8 * z + x * y / 3
99
- ],
100
- start: [
101
- 1,
102
- 1,
103
- 1
104
- ],
105
- dt: .005,
106
- steps: 7e3
107
- }
108
- };
109
- var SETTLE = 400;
110
- /** Chaotic flows in three dimensions: trajectories that never repeat yet stay on one shape, with colour tracing time. */
111
- var StrangeAttractor3D = class extends Chart3D {
112
- static meta = {
113
- id: "strange-attractor-3d",
114
- name: "Strange attractor",
115
- family: ChartFamily.Mathematical,
116
- dimension: Dimension.Three,
117
- shape: DataShape.Function,
118
- description: "Integrates a chaotic three-dimensional system and draws its trajectory as a tube, a line or a stream of beads.",
119
- tags: [
120
- "lorenz",
121
- "chaos",
122
- "dynamical system",
123
- "butterfly"
124
- ],
125
- sample: (seed) => MathNumerics.fit(SampleData.points(seed, 3, 3), "x", "y", [[-.3, .3], [-.3, .3]]).map(([x, y]) => ({
126
- x,
127
- y
128
- })),
129
- variants: {
130
- system: Object.values(AttractorSystem),
131
- render: Object.values(AttractorRender),
132
- trajectories: [
133
- 1,
134
- 2,
135
- 3
136
- ]
137
- }
138
- };
139
- defaults() {
140
- return {
141
- system: "lorenz",
142
- render: "tube",
143
- trajectories: 1,
144
- x: "x",
145
- y: "y",
146
- azimuth: 50,
147
- elevation: 14,
148
- distance: 3.6
149
- };
150
- }
151
- integrate(nudge) {
152
- const { flow, start, dt, steps } = SYSTEMS[this.options.system];
153
- let [x, y, z] = [
154
- start[0] + nudge[0],
155
- start[1] + nudge[1],
156
- start[2]
157
- ];
158
- const out = [];
159
- const add = (a, b, c, k, h) => [
160
- a + h * k[0],
161
- b + h * k[1],
162
- c + h * k[2]
163
- ];
164
- for (let i = 0; i < steps + SETTLE; i++) {
165
- const k1 = flow(x, y, z), k2 = flow(...add(x, y, z, k1, dt / 2)), k3 = flow(...add(x, y, z, k2, dt / 2)), k4 = flow(...add(x, y, z, k3, dt));
166
- x += dt * (k1[0] + 2 * k2[0] + 2 * k3[0] + k4[0]) / 6;
167
- y += dt * (k1[1] + 2 * k2[1] + 2 * k3[1] + k4[1]) / 6;
168
- z += dt * (k1[2] + 2 * k2[2] + 2 * k3[2] + k4[2]) / 6;
169
- if (!Number.isFinite(x + y + z)) break;
170
- if (i >= SETTLE) out.push(new Vector3(x, z, y));
171
- }
172
- return out;
173
- }
174
- build(ctx) {
175
- const { data, trajectories, render, x, y } = this.options;
176
- const paths = Array.from({ length: trajectories }, (_, i) => {
177
- const row = data[i];
178
- return [Number.isFinite(+row?.[x]) ? +row[x] : i * .1, Number.isFinite(+row?.[y]) ? +row[y] : 0];
179
- }).map((nudge) => this.integrate(nudge)).filter((path) => path.length > 1);
180
- const all = paths.flat();
181
- if (!all.length) return;
182
- const span = (axis) => {
183
- const values = all.map((p) => p[axis]), a = Math.min(...values.slice(0, 4e3), ...values.slice(-4e3)), b = Math.max(...values.slice(0, 4e3), ...values.slice(-4e3));
184
- return [
185
- a,
186
- b,
187
- (a + b) / 2
188
- ];
189
- };
190
- const [x0, x1, cx] = span("x"), [y0, y1, cy] = span("y"), [z0, z1, cz] = span("z");
191
- const unit = 1.9 / Math.max(x1 - x0, y1 - y0, z1 - z0, 1e-6);
192
- const fit = (p) => new Vector3((p.x - cx) * unit, (p.y - cy) * unit, (p.z - cz) * unit);
193
- const multi = paths.length > 1;
194
- const tint = (path, t) => new Color(multi ? ctx.palette.color(`Start ${path + 1}`) : ctx.palette.sequential(.25 + .75 * t));
195
- paths.forEach((raw, index) => {
196
- const path = raw.map(fit);
197
- const tag = () => ({
198
- title: multi ? `Trajectory ${index + 1}` : "Trajectory",
199
- rows: [["Steps", path.length]]
200
- });
201
- if (render === "line") {
202
- const geometry = new BufferGeometry().setFromPoints(path);
203
- const colors = path.flatMap((_, i) => tint(index, i / path.length).toArray());
204
- geometry.setAttribute("color", new Float32BufferAttribute(colors, 3));
205
- const line = new Line(geometry, new LineBasicMaterial({ vertexColors: true }));
206
- ctx.reveal((progress) => geometry.setDrawRange(0, Math.floor(path.length * progress)), 2.4);
207
- ctx.root.add(line);
208
- } else if (render === "beads") {
209
- const every = Math.ceil(path.length / 1400);
210
- const picked = path.filter((_, i) => i % every === 0);
211
- const beads = new InstancedMesh(new SphereGeometry(.012, 8, 6), new MeshStandardMaterial({ roughness: .4 }), picked.length);
212
- const dummy = new Object3D();
213
- beads.castShadow = true;
214
- picked.forEach((p, i) => {
215
- dummy.position.copy(p);
216
- dummy.updateMatrix();
217
- beads.setMatrixAt(i, dummy.matrix);
218
- beads.setColorAt(i, tint(index, i / picked.length));
219
- });
220
- ctx.reveal((progress) => {
221
- beads.count = Math.max(1, Math.floor(picked.length * progress));
222
- }, 2.4);
223
- ctx.root.add(beads);
224
- ctx.pick(beads, tag);
225
- } else {
226
- const every = Math.ceil(path.length / 1300);
227
- const curve = new CatmullRomCurve3(path.filter((_, i) => i % every === 0));
228
- const segments = 1600, sides = 6;
229
- const geometry = new TubeGeometry(curve, segments, multi ? .009 : .012, sides, false);
230
- const colors = [];
231
- for (let i = 0; i <= segments; i++) for (let j = 0; j <= sides; j++) colors.push(...tint(index, i / segments).toArray());
232
- geometry.setAttribute("color", new Float32BufferAttribute(colors, 3));
233
- const tube = new Mesh(geometry, new MeshStandardMaterial({
234
- vertexColors: true,
235
- roughness: .42,
236
- metalness: .05
237
- }));
238
- tube.castShadow = true;
239
- const total = geometry.index?.count ?? 0;
240
- ctx.reveal((progress) => geometry.setDrawRange(0, Math.floor(total * progress)), 2.4);
241
- ctx.root.add(tube);
242
- ctx.pick(tube, tag);
243
- }
244
- });
245
- const spin = scaleLinear([0, 60], [0, Math.PI * 2]);
246
- ctx.onFrame((t) => {
247
- if (!this.options.autoRotate) ctx.root.rotation.y = spin(t) * .25;
248
- });
249
- }
250
- };
251
- export { AttractorRender, AttractorSystem, StrangeAttractor3D };
@@ -1,126 +0,0 @@
1
- import { Chart3D } from "../../core/Chart3D.js";
2
- import { ChartFamily, DataShape, Dimension } from "../../core/enums.js";
3
- import { Scales } from "../../core/Scales.js";
4
- import { ShareData } from "./ShareData.js";
5
- import { FunnelChart } from "./FunnelChart.js";
6
- import { CylinderGeometry, Mesh, MeshStandardMaterial, PlaneGeometry, ShadowMaterial } from "three";
7
- // src/charts/proportion/ConeFunnel.ts
8
- /** Cross-section of the solid. `Discs` stacks flat cylinders instead of tapering. */
9
- var ConeProfile = /* @__PURE__ */ function(ConeProfile) {
10
- ConeProfile["Cone"] = "cone";
11
- ConeProfile["Pyramid"] = "square-pyramid";
12
- ConeProfile["Hexagon"] = "hexagonal";
13
- ConeProfile["Discs"] = "stacked-discs";
14
- return ConeProfile;
15
- }({});
16
- var ConeApex = /* @__PURE__ */ function(ConeApex) {
17
- ConeApex["Down"] = "apex-down";
18
- ConeApex["Up"] = "apex-up";
19
- return ConeApex;
20
- }({});
21
- var ConeDepth = /* @__PURE__ */ function(ConeDepth) {
22
- ConeDepth["Equal"] = "equal-height";
23
- ConeDepth["Proportional"] = "proportional-height";
24
- return ConeDepth;
25
- }({});
26
- var SEGMENTS = {
27
- ["cone"]: 64,
28
- ["square-pyramid"]: 4,
29
- ["hexagonal"]: 6,
30
- ["stacked-discs"]: 64
31
- };
32
- var TALL = 1.7;
33
- /** A funnel with depth, where each layer's cross-section area follows its stage's value. */
34
- var ConeFunnel = class extends Chart3D {
35
- static meta = {
36
- id: "cone-funnel",
37
- name: "Cone funnel",
38
- family: ChartFamily.Composition,
39
- dimension: Dimension.Three,
40
- shape: DataShape.Table,
41
- description: "Stacks tapered 3D layers whose cross-section area follows each stage of a funnel or pyramid.",
42
- tags: [
43
- "3d funnel",
44
- "3d pyramid",
45
- "conversion"
46
- ],
47
- sample: (seed) => FunnelChart.meta.sample(seed),
48
- variants: {
49
- profile: [
50
- "cone",
51
- "square-pyramid",
52
- "hexagonal",
53
- "stacked-discs"
54
- ],
55
- apex: ["apex-down", "apex-up"],
56
- depth: ["equal-height", "proportional-height"],
57
- gap: [.03, .1]
58
- }
59
- };
60
- defaults() {
61
- return {
62
- category: "category",
63
- value: "value",
64
- limit: 8,
65
- profile: "cone",
66
- apex: "apex-down",
67
- depth: "equal-height",
68
- gap: .03,
69
- distance: 4.9
70
- };
71
- }
72
- build(ctx) {
73
- const { data, category, value, limit, profile, apex, depth, gap } = this.options;
74
- const shares = ShareData.collect(data, category, value, void 0, limit);
75
- ShareData.register(ctx, shares);
76
- if (!shares.length) return;
77
- const down = apex === "apex-down";
78
- const stack = down ? shares : [...shares].reverse();
79
- const top = Math.max(...shares.map((share) => share.value));
80
- const radius = (amount) => .82 * Math.sqrt(amount / top);
81
- const free = TALL - gap * (stack.length - 1);
82
- const whole = shares.reduce((total, share) => total + share.value, 0);
83
- const floor = free / stack.length / 3;
84
- const heights = stack.map((share) => depth === "equal-height" ? free / stack.length : floor + (free - floor * stack.length) * share.value / whole);
85
- const discs = profile === "stacked-discs";
86
- let y = TALL / 2 - .05;
87
- const shadow = new Mesh(new PlaneGeometry(3, 3), new ShadowMaterial({ opacity: .16 }));
88
- shadow.rotation.x = -Math.PI / 2;
89
- shadow.position.y = -1.7 / 2 - .08;
90
- shadow.receiveShadow = true;
91
- ctx.root.add(shadow);
92
- stack.forEach((share, i) => {
93
- const height = heights[i], next = stack[i + 1], before = stack[i - 1];
94
- const upper = discs ? radius(share.value) : down ? radius(share.value) : before ? radius(before.value) : Math.max(.02, radius(share.value) * .2);
95
- const lower = discs ? radius(share.value) : down ? next ? radius(next.value) : Math.max(.02, radius(share.value) * .55) : radius(share.value);
96
- const flat = profile === "square-pyramid" || profile === "hexagonal";
97
- const material = new MeshStandardMaterial({
98
- color: ShareData.fill(ctx, share),
99
- roughness: .5,
100
- metalness: .05,
101
- flatShading: flat
102
- });
103
- const mesh = new Mesh(new CylinderGeometry(upper, lower, height, SEGMENTS[profile], 1), material);
104
- if (profile === "square-pyramid") mesh.rotation.y = Math.PI / 4;
105
- mesh.castShadow = mesh.receiveShadow = true;
106
- const centre = y - height / 2;
107
- ctx.root.add(mesh);
108
- ctx.reveal((t) => {
109
- mesh.scale.set(Math.max(.001, t), Math.max(.001, t), Math.max(.001, t));
110
- mesh.position.y = centre;
111
- }, .7, i * .08);
112
- ctx.pick(mesh, () => ({
113
- title: share.name,
114
- color: ShareData.fill(ctx, share),
115
- rows: [[value, share.value], ["Share", ShareData.percent(share.fraction)]]
116
- }));
117
- ctx.label(`${ShareData.fit(share.name, 80)} ${Scales.format(share.value, top)}`, [
118
- Math.max(upper, lower) + .34,
119
- centre,
120
- 0
121
- ], "ink", 11);
122
- y -= height + gap;
123
- });
124
- }
125
- };
126
- export { ConeApex, ConeDepth, ConeFunnel, ConeProfile };
@@ -1,123 +0,0 @@
1
- import { Chart3D } from "../../core/Chart3D.js";
2
- import { ChartFamily, DataShape, Dimension } from "../../core/enums.js";
3
- import { SampleData } from "../../data/SampleData.js";
4
- import { ShareData } from "./ShareData.js";
5
- import { ShareSort } from "./ShareEnums.js";
6
- import { pie } from "d3";
7
- import { ExtrudeGeometry, Mesh, MeshStandardMaterial, PlaneGeometry, ShadowMaterial, Shape } from "three";
8
- // src/charts/proportion/ExtrudedPieChart.ts
9
- /** `Flat` is one disc; `ByValue` adds height so the largest slice stands tallest. */
10
- var PieHeight = /* @__PURE__ */ function(PieHeight) {
11
- PieHeight["Flat"] = "flat";
12
- PieHeight["ByValue"] = "height-by-value";
13
- return PieHeight;
14
- }({});
15
- var PiePull = /* @__PURE__ */ function(PiePull) {
16
- PiePull["None"] = "no-pull";
17
- PiePull["Largest"] = "pull-largest";
18
- PiePull["All"] = "pull-all";
19
- return PiePull;
20
- }({});
21
- var RADIUS = .95;
22
- var FLOOR = -.32;
23
- var PAD = .012;
24
- /** A presentation pie with depth. Height can carry the value too, so tilt never hides the ranking. */
25
- var ExtrudedPieChart = class extends Chart3D {
26
- static meta = {
27
- id: "extruded-pie",
28
- name: "Extruded pie",
29
- family: ChartFamily.Composition,
30
- dimension: Dimension.Three,
31
- shape: DataShape.Table,
32
- description: "Extrudes pie or donut slices into solid wedges, optionally raising each slice by its value.",
33
- tags: ["3d donut", "extruded pie"],
34
- sample: (seed) => SampleData.categories(seed, 6, 1),
35
- variants: {
36
- hole: [0, .5],
37
- rise: ["height-by-value", "flat"],
38
- pull: [
39
- "no-pull",
40
- "pull-largest",
41
- "pull-all"
42
- ],
43
- sort: [ShareSort.Descending, ShareSort.Data],
44
- labels: [true, false]
45
- }
46
- };
47
- defaults() {
48
- return {
49
- category: "category",
50
- value: "value",
51
- limit: 8,
52
- sort: ShareSort.Descending,
53
- hole: 0,
54
- rise: "height-by-value",
55
- pull: "no-pull",
56
- labels: true,
57
- elevation: 34,
58
- distance: 4.4
59
- };
60
- }
61
- wedge(from, to, depth) {
62
- const inner = this.options.hole * RADIUS;
63
- const pad = to - from > PAD * 4 ? PAD : 0;
64
- const shape = new Shape();
65
- shape.absarc(0, 0, RADIUS, from + pad, to - pad, false);
66
- if (inner > 0) shape.absarc(0, 0, inner, to - pad * 2, from + pad * 2, true);
67
- else shape.lineTo(0, 0);
68
- shape.closePath();
69
- const geometry = new ExtrudeGeometry(shape, {
70
- depth,
71
- bevelEnabled: true,
72
- bevelSize: .012,
73
- bevelThickness: .012,
74
- bevelSegments: 2,
75
- curveSegments: Math.max(8, Math.ceil((to - from) * 24))
76
- });
77
- geometry.rotateX(-Math.PI / 2);
78
- return geometry;
79
- }
80
- build(ctx) {
81
- const { data, category, value, limit, sort, rise, pull, labels } = this.options;
82
- const shares = ShareData.collect(data, category, value, sort, limit);
83
- ShareData.register(ctx, shares);
84
- if (!shares.length) return;
85
- const top = Math.max(...shares.map((share) => share.value));
86
- const slices = pie().value((share) => share.value).sort(null)(shares);
87
- const shadow = new Mesh(new PlaneGeometry(3.4, 3.4), new ShadowMaterial({ opacity: .18 }));
88
- shadow.rotation.x = -Math.PI / 2;
89
- shadow.position.y = FLOOR;
90
- shadow.receiveShadow = true;
91
- ctx.root.add(shadow);
92
- slices.forEach((slice, i) => {
93
- const share = slice.data, mid = (slice.startAngle + slice.endAngle) / 2;
94
- const depth = rise === "flat" ? .24 : .1 + .42 * (share.value / top);
95
- const pulled = pull === "pull-all" || pull === "pull-largest" && share.value === top ? .12 : 0;
96
- const mesh = new Mesh(this.wedge(slice.startAngle, slice.endAngle, depth), new MeshStandardMaterial({
97
- color: ShareData.fill(ctx, share),
98
- roughness: .46,
99
- metalness: .05
100
- }));
101
- mesh.castShadow = mesh.receiveShadow = true;
102
- mesh.position.set(Math.cos(mid) * pulled, -.308, -Math.sin(mid) * pulled);
103
- ctx.root.add(mesh);
104
- ctx.reveal((t) => {
105
- mesh.scale.y = Math.max(.001, t);
106
- }, .8, i * .06);
107
- ctx.pick(mesh, () => ({
108
- title: share.name,
109
- color: ShareData.fill(ctx, share),
110
- rows: [[value, share.value], ["Share", ShareData.percent(share.fraction)]]
111
- }));
112
- if (labels && slice.endAngle - slice.startAngle > .2) {
113
- const reach = RADIUS + pulled + .14;
114
- ctx.label(ShareData.percent(share.fraction), [
115
- Math.cos(mid) * reach,
116
- FLOOR + depth + .02,
117
- -Math.sin(mid) * reach
118
- ], "ink", 11);
119
- }
120
- });
121
- }
122
- };
123
- export { ExtrudedPieChart, PieHeight, PiePull };
@@ -1,151 +0,0 @@
1
- import { ChartFamily, DataShape, Dimension, Orientation, ScaleKind } from "../../core/enums.js";
2
- import { SampleData } from "../../data/SampleData.js";
3
- import { CategoryScatterBase } from "./CategoryScatterBase.js";
4
- import { ascending, forceCollide, forceSimulation, forceX, forceY, max, scaleSqrt } from "d3";
5
- // src/charts/scatter/BeeswarmScatter.ts
6
- var BeeswarmLayout = /* @__PURE__ */ function(BeeswarmLayout) {
7
- BeeswarmLayout["Dodge"] = "dodge";
8
- BeeswarmLayout["Force"] = "force";
9
- BeeswarmLayout["Stacked"] = "stacked-dots";
10
- return BeeswarmLayout;
11
- }({});
12
- var BeeswarmSide = /* @__PURE__ */ function(BeeswarmSide) {
13
- BeeswarmSide["Both"] = "two-sided";
14
- BeeswarmSide["One"] = "one-sided";
15
- return BeeswarmSide;
16
- }({});
17
- var BeeswarmLanes = /* @__PURE__ */ function(BeeswarmLanes) {
18
- BeeswarmLanes["PerGroup"] = "per-group";
19
- BeeswarmLanes["Shared"] = "shared";
20
- return BeeswarmLanes;
21
- }({});
22
- /** Each point nudged just far enough to avoid its neighbours, so the swarm's shape is the distribution. */
23
- var BeeswarmScatter = class extends CategoryScatterBase {
24
- static meta = {
25
- id: "beeswarm-scatter",
26
- name: "Beeswarm scatter",
27
- family: ChartFamily.Distribution,
28
- dimension: Dimension.Two,
29
- shape: DataShape.Table,
30
- description: "Packs points along one measure without overlap, keeping each observation individually visible.",
31
- tags: [
32
- "swarm",
33
- "dodge",
34
- "wilkinson dot plot"
35
- ],
36
- sample: (seed) => SampleData.points(seed, 120, 3).map((row) => ({
37
- group: row.group,
38
- value: row.y,
39
- size: row.size
40
- })),
41
- variants: {
42
- orientation: [Orientation.Horizontal, Orientation.Vertical],
43
- layout: [
44
- "dodge",
45
- "force",
46
- "stacked-dots"
47
- ],
48
- side: ["two-sided", "one-sided"],
49
- lanes: ["per-group", "shared"],
50
- sized: [false, true],
51
- scale: [ScaleKind.Linear, ScaleKind.Log]
52
- },
53
- valid: (v) => !(v.layout === "stacked-dots" && v.sized) && !(v.layout === "force" && v.side === "one-sided")
54
- };
55
- defaults() {
56
- return {
57
- ...super.defaults(),
58
- orientation: Orientation.Horizontal,
59
- layout: "dodge",
60
- side: "two-sided",
61
- lanes: "per-group",
62
- sized: false,
63
- radius: 3.5
64
- };
65
- }
66
- /** Greedy dodge: sorted by value, each dot takes the free offset closest to the lane axis. */
67
- dodge(bees) {
68
- const placed = [];
69
- const oneSided = this.options.side === "one-sided";
70
- for (const bee of [...bees].sort((a, b) => ascending(a.along, b.along))) {
71
- const near = placed.filter((other) => Math.abs(other.along - bee.along) < other.radius + bee.radius + 1);
72
- bee.offset = [0, ...near.flatMap((other) => {
73
- const gap = other.radius + bee.radius + 1;
74
- const rise = Math.sqrt(Math.max(0, gap ** 2 - (other.along - bee.along) ** 2));
75
- return [other.offset + rise, other.offset - rise];
76
- })].filter((offset) => !oneSided || offset >= 0).sort((a, b) => Math.abs(a) - Math.abs(b)).find((offset) => near.every((other) => (other.along - bee.along) ** 2 + (other.offset - offset) ** 2 >= (other.radius + bee.radius + .9) ** 2)) ?? 0;
77
- placed.push(bee);
78
- }
79
- }
80
- force(bees) {
81
- const nodes = bees.map((bee) => ({
82
- x: bee.along,
83
- y: 0,
84
- home: bee.along,
85
- r: bee.radius + 1
86
- }));
87
- forceSimulation(nodes).stop().force("x", forceX((d) => d.home).strength(1)).force("y", forceY(0).strength(.08)).force("collide", forceCollide((d) => d.r)).tick(160);
88
- nodes.forEach((node, i) => {
89
- bees[i].along = node.x;
90
- bees[i].offset = node.y;
91
- });
92
- }
93
- /** Wilkinson dot plot: dots snap into value bins and stack from the axis. */
94
- stack(bees) {
95
- const step = (this.options.radius + 1) * 2;
96
- const columns = /* @__PURE__ */ new Map();
97
- for (const bee of [...bees].sort((a, b) => ascending(a.along, b.along))) {
98
- const bin = Math.round(bee.along / step), height = columns.get(bin) ?? 0;
99
- columns.set(bin, height + 1);
100
- bee.along = bin * step;
101
- bee.offset = (this.options.side === "one-sided" ? height : Math.ceil(height / 2) * (height % 2 ? 1 : -1)) * step;
102
- }
103
- }
104
- arrange(bees) {
105
- const { layout } = this.options;
106
- if (layout === "force") this.force(bees);
107
- else if (layout === "stacked-dots") this.stack(bees);
108
- else this.dodge(bees);
109
- }
110
- laneOf(group) {
111
- return this.options.lanes === "shared" ? "" : group;
112
- }
113
- plotLanes(ctx, axes, lanes) {
114
- const vertical = this.vertical, oneSided = this.options.side === "one-sided";
115
- const all = lanes.flatMap((lane) => lane.points);
116
- all.forEach((point) => ctx.palette.color(point.group));
117
- const area = scaleSqrt([0, max(all, (point) => point.size) || 1], [1.5, this.options.radius * 2.2]);
118
- const radius = (point) => this.options.sized ? area(point.size) : this.options.radius;
119
- const bees = lanes.flatMap((lane) => {
120
- const base = lane.center + (oneSided ? (vertical ? -1 : 1) * (lane.breadth / 2 - 4) : 0);
121
- const swarm = lane.points.map((point) => ({
122
- ...point,
123
- along: axes.value(point.value),
124
- radius: radius(point),
125
- offset: 0,
126
- center: base
127
- }));
128
- this.arrange(swarm);
129
- const reach = Math.max(1, ...swarm.map((bee) => Math.abs(bee.offset) + bee.radius));
130
- const squeeze = Math.min(1, (oneSided ? lane.breadth - 8 : lane.breadth / 2) / reach);
131
- return swarm.map((bee) => ({
132
- ...bee,
133
- offset: (oneSided ? (vertical ? 1 : -1) * Math.abs(bee.offset) : bee.offset) * squeeze
134
- }));
135
- });
136
- const cx = (d) => vertical ? d.center + d.offset : d.along;
137
- const cy = (d) => vertical ? d.along : d.center + d.offset;
138
- const dots = ctx.marks("dots", "circle", bees, (d) => d.index).attr("fill", (d) => ctx.palette.color(d.group)).attr("stroke", ctx.theme.surface).attr("stroke-width", 1);
139
- ctx.set(dots, {
140
- cx,
141
- cy,
142
- r: (d) => d.radius
143
- }, {
144
- cx: (d) => vertical ? d.center : d.along,
145
- cy: (d) => vertical ? d.along : d.center,
146
- r: 0
147
- }, 1);
148
- ctx.hover(dots, (d) => this.tooltip(ctx, d));
149
- }
150
- };
151
- export { BeeswarmLanes, BeeswarmLayout, BeeswarmScatter, BeeswarmSide };
@@ -1,51 +0,0 @@
1
- import { ScatterBase } from "./ScatterBase.js";
2
- // src/charts/scatter/BinnedScatterBase.ts
3
- var BinEncoding = /* @__PURE__ */ function(BinEncoding) {
4
- BinEncoding["Color"] = "color";
5
- BinEncoding["Size"] = "size";
6
- BinEncoding["Both"] = "color-and-size";
7
- return BinEncoding;
8
- }({});
9
- var BinCount = /* @__PURE__ */ function(BinCount) {
10
- BinCount["Linear"] = "linear-count";
11
- BinCount["Sqrt"] = "sqrt-count";
12
- BinCount["Log"] = "log-count";
13
- return BinCount;
14
- }({});
15
- /** Shared count-to-mark mapping for charts that aggregate points into cells. */
16
- var BinnedScatterBase = class extends ScatterBase {
17
- defaults() {
18
- return {
19
- ...super.defaults(),
20
- encoding: "color",
21
- count: "linear-count",
22
- raw: false
23
- };
24
- }
25
- /** Share of the peak in 0..1 after the count transform. */
26
- share(count, peak) {
27
- const { count: kind } = this.options;
28
- if (kind === "log-count") return Math.log1p(count) / Math.log1p(peak);
29
- if (kind === "sqrt-count") return Math.sqrt(count / peak);
30
- return count / peak;
31
- }
32
- shade(ctx, share) {
33
- return ctx.palette.sequential(this.options.encoding === "size" ? .62 : .14 + share * .86);
34
- }
35
- /** Linear size scale of a cell, so mark area stays proportional to the share. */
36
- extent(share) {
37
- return this.options.encoding === "color" ? 1 : Math.sqrt(share);
38
- }
39
- drawRaw(ctx, points) {
40
- const dots = ctx.marks("raw", "circle", this.options.raw ? points : [], (d) => d.index).attr("fill", ctx.theme.inkMuted).attr("fill-opacity", .5);
41
- ctx.set(dots, {
42
- cx: (d) => d.px,
43
- cy: (d) => d.py,
44
- r: 1.5
45
- });
46
- }
47
- legendItems() {
48
- return [];
49
- }
50
- };
51
- export { BinCount, BinEncoding, BinnedScatterBase };