@macrostrat/column-views 3.4.2 → 3.5.1
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.
- package/CHANGELOG.md +25 -0
- package/dist/column-views.css +7 -7
- package/dist/column.cjs +21 -21
- package/dist/column.cjs.map +1 -1
- package/dist/column.d.ts +3 -1
- package/dist/column.js +4 -4
- package/dist/column.js.map +1 -1
- package/dist/data-provider/store.cjs +26 -3
- package/dist/data-provider/store.cjs.map +1 -1
- package/dist/data-provider/store.d.ts +52 -0
- package/dist/data-provider/store.js +27 -4
- package/dist/data-provider/store.js.map +1 -1
- package/dist/data-provider/unit-selection.cjs +10 -4
- package/dist/data-provider/unit-selection.cjs.map +1 -1
- package/dist/data-provider/unit-selection.d.ts +3 -0
- package/dist/data-provider/unit-selection.js +10 -4
- package/dist/data-provider/unit-selection.js.map +1 -1
- package/dist/index.cjs +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -1
- package/dist/prepare-units/helpers.cjs +58 -36
- package/dist/prepare-units/helpers.cjs.map +1 -1
- package/dist/prepare-units/helpers.d.ts +13 -5
- package/dist/prepare-units/helpers.js +59 -37
- package/dist/prepare-units/helpers.js.map +1 -1
- package/dist/prepare-units/index.cjs +1 -0
- package/dist/prepare-units/index.cjs.map +1 -1
- package/dist/prepare-units/index.d.ts +2 -2
- package/dist/prepare-units/index.js +1 -0
- package/dist/prepare-units/index.js.map +1 -1
- package/dist/unit-details/panel.cjs +1 -1
- package/dist/unit-details/panel.cjs.map +1 -1
- package/dist/unit-details/panel.js +1 -1
- package/dist/unit-details/panel.js.map +1 -1
- package/dist/units/boxes.module.sass.cjs +3 -3
- package/dist/units/boxes.module.sass.js +3 -3
- package/dist/units/index.cjs +5 -5
- package/dist/units/index.cjs.map +1 -1
- package/dist/units/index.d.ts +2 -2
- package/dist/units/index.js +5 -5
- package/dist/units/index.js.map +1 -1
- package/package.json +4 -4
- package/src/column.ts +6 -4
- package/src/correlation-chart/stories/namibia-correlation.stories.ts +151 -0
- package/src/data-provider/store.ts +48 -4
- package/src/data-provider/unit-selection.ts +10 -5
- package/src/prepare-units/helpers.ts +98 -50
- package/src/prepare-units/index.ts +4 -1
- package/src/unit-details/panel.ts +1 -1
- package/src/units/boxes.module.sass +2 -2
- package/src/units/index.ts +7 -7
|
@@ -11,26 +11,40 @@ import {
|
|
|
11
11
|
import {
|
|
12
12
|
AgeRangeRelationship,
|
|
13
13
|
compareAgeRanges,
|
|
14
|
+
mergeAgeRanges,
|
|
15
|
+
MergeMode,
|
|
14
16
|
} from "@macrostrat/stratigraphy-utils";
|
|
15
17
|
import type { ExtUnit, SectionInfo, StratigraphicPackage } from "./types";
|
|
16
18
|
|
|
17
19
|
const dt = 0.001;
|
|
18
20
|
|
|
19
|
-
export type
|
|
20
|
-
|
|
21
|
+
export type UnitWithLayoutParameters<T extends BaseUnit> = T & {
|
|
22
|
+
layout: UnitLayoutData<T>;
|
|
21
23
|
};
|
|
22
24
|
|
|
23
|
-
type
|
|
25
|
+
export type UnitWithLayoutHints<T extends BaseUnit> = T & {
|
|
26
|
+
layoutHints?: UnitLayoutHints;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
interface UnitLayoutInfo {
|
|
24
30
|
column: number;
|
|
25
31
|
nColumns: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
type UnitLayoutHints = Partial<UnitLayoutInfo>;
|
|
35
|
+
|
|
36
|
+
type UnitLayoutData<T extends BaseUnit> = UnitLayoutInfo & {
|
|
37
|
+
totalColumns: number;
|
|
26
38
|
unitGroup: UnitGroup<T>;
|
|
27
39
|
};
|
|
28
40
|
|
|
29
41
|
class UnitGroup<T extends BaseUnit> implements StratigraphicPackage {
|
|
30
42
|
units: T[];
|
|
43
|
+
axisType: ColumnAxisType;
|
|
31
44
|
|
|
32
|
-
constructor(units: T[]) {
|
|
45
|
+
constructor(units: T[], axisType: ColumnAxisType = ColumnAxisType.AGE) {
|
|
33
46
|
this.units = units;
|
|
47
|
+
this.axisType = axisType;
|
|
34
48
|
}
|
|
35
49
|
|
|
36
50
|
get t_age(): number {
|
|
@@ -41,7 +55,7 @@ class UnitGroup<T extends BaseUnit> implements StratigraphicPackage {
|
|
|
41
55
|
return Math.max(...this.units.map((d) => d.b_age));
|
|
42
56
|
}
|
|
43
57
|
|
|
44
|
-
getUnits():
|
|
58
|
+
getUnits(): UnitWithLayoutParameters<T>[] {
|
|
45
59
|
return assignColumnsToUnitsWithinOverlappingGroup(this);
|
|
46
60
|
}
|
|
47
61
|
}
|
|
@@ -49,39 +63,51 @@ class UnitGroup<T extends BaseUnit> implements StratigraphicPackage {
|
|
|
49
63
|
function groupUnitsByMutualOverlap<T extends BaseUnit>(
|
|
50
64
|
units: T[],
|
|
51
65
|
tolerance: number = dt,
|
|
66
|
+
axisType: ColumnAxisType = ColumnAxisType.AGE,
|
|
52
67
|
): UnitGroup<T>[] {
|
|
53
68
|
/** Group units within a section that have mutual overlap. */
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
69
|
+
|
|
70
|
+
const sections = groupUnitsIntoSectionsByOverlap(units, axisType, tolerance);
|
|
71
|
+
|
|
72
|
+
console.log("Grouped sections", sections);
|
|
73
|
+
|
|
59
74
|
return sections.map((d) => {
|
|
60
|
-
return new UnitGroup(d.units);
|
|
75
|
+
return new UnitGroup(d.units, axisType);
|
|
61
76
|
});
|
|
62
77
|
}
|
|
63
78
|
|
|
64
79
|
const sortByAge = createUnitSorter(ColumnAxisType.AGE);
|
|
65
80
|
|
|
66
81
|
function assignColumnsToUnitsWithinOverlappingGroup<T extends BaseUnit>(
|
|
67
|
-
group: UnitGroup<T
|
|
68
|
-
):
|
|
82
|
+
group: UnitGroup<UnitWithLayoutHints<T>>,
|
|
83
|
+
): UnitWithLayoutParameters<T>[] {
|
|
69
84
|
/** A relatively naïve function to assign columns to units within a mutually overlapping group.
|
|
70
85
|
* This gets the number of columns that would be needed to accommodate the units in the group.
|
|
71
86
|
* It then assigns columns to units in the group based on the number of columns needed, with
|
|
72
87
|
* lower units further to the left.
|
|
73
88
|
*/
|
|
74
89
|
|
|
75
|
-
const sortedUnits = [...group.units].sort((
|
|
90
|
+
const sortedUnits = [...group.units].sort(createUnitSorter(group.axisType));
|
|
76
91
|
|
|
77
92
|
const columns: T[][] = [];
|
|
78
93
|
|
|
94
|
+
let nColumns = 1;
|
|
95
|
+
|
|
79
96
|
for (const unit of sortedUnits) {
|
|
97
|
+
let startIndex = 0;
|
|
98
|
+
let endIndex = 0;
|
|
80
99
|
// Find a column that is not already occupied by an overlapping unit
|
|
100
|
+
const colHint = unit.layoutHints?.column;
|
|
101
|
+
if (colHint != null) {
|
|
102
|
+
columns[colHint] ??= [];
|
|
103
|
+
columns[colHint].push(unit);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
81
106
|
let didAddToExistingColumn = false;
|
|
107
|
+
|
|
82
108
|
for (const column of columns) {
|
|
83
109
|
const lastUnit = column[column.length - 1];
|
|
84
|
-
if (!unitsOverlap(unit, lastUnit,
|
|
110
|
+
if (!unitsOverlap(unit, lastUnit, group.axisType, dt)) {
|
|
85
111
|
column.push(unit);
|
|
86
112
|
didAddToExistingColumn = true;
|
|
87
113
|
break;
|
|
@@ -92,14 +118,17 @@ function assignColumnsToUnitsWithinOverlappingGroup<T extends BaseUnit>(
|
|
|
92
118
|
}
|
|
93
119
|
}
|
|
94
120
|
|
|
95
|
-
|
|
121
|
+
console.log(columns);
|
|
122
|
+
|
|
123
|
+
const units: UnitWithLayoutParameters<T>[] = columns.flatMap(
|
|
96
124
|
(column, columnIndex) =>
|
|
97
125
|
column.map((unit) => {
|
|
98
126
|
return {
|
|
99
127
|
...unit,
|
|
100
|
-
|
|
128
|
+
layout: {
|
|
101
129
|
column: columnIndex,
|
|
102
|
-
nColumns:
|
|
130
|
+
nColumns: 1,
|
|
131
|
+
totalColumns: columns.length,
|
|
103
132
|
unitGroup: group,
|
|
104
133
|
},
|
|
105
134
|
};
|
|
@@ -121,7 +150,7 @@ export function preprocessUnits<T extends UnitLong = UnitLong>(
|
|
|
121
150
|
tolerance = 0.01; // 1cm tolerance for height/depth columns
|
|
122
151
|
}
|
|
123
152
|
|
|
124
|
-
const unitGroups = groupUnitsByMutualOverlap(units, tolerance);
|
|
153
|
+
const unitGroups = groupUnitsByMutualOverlap(units, tolerance, axisType);
|
|
125
154
|
|
|
126
155
|
const divisions: any[] = [];
|
|
127
156
|
// Serialize all groups' units to a single array
|
|
@@ -186,7 +215,7 @@ export function groupUnitsIntoSectionsBySectionID<T extends UnitLong>(
|
|
|
186
215
|
interface WorkingSection {
|
|
187
216
|
units: UnitLong[];
|
|
188
217
|
// Position or age
|
|
189
|
-
heightRange
|
|
218
|
+
heightRange: [number, number];
|
|
190
219
|
}
|
|
191
220
|
|
|
192
221
|
export function groupUnitsIntoSectionsByOverlap<T extends BaseUnit>(
|
|
@@ -201,41 +230,60 @@ export function groupUnitsIntoSectionsByOverlap<T extends BaseUnit>(
|
|
|
201
230
|
* */
|
|
202
231
|
// Start with each unit as its own "section", and progressively merge...
|
|
203
232
|
const sectionList: WorkingSection[] = [];
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
(
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
233
|
+
|
|
234
|
+
const initialSections: WorkingSection[] = units.map((unit) => {
|
|
235
|
+
return {
|
|
236
|
+
units: [unit],
|
|
237
|
+
heightRange: getUnitHeightRange(unit, axisType),
|
|
238
|
+
};
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
const isOverlapping = (a: WorkingSection, b: WorkingSection) => {
|
|
242
|
+
const res = compareAgeRanges(a.heightRange, b.heightRange, tolerance);
|
|
243
|
+
return res !== AgeRangeRelationship.Disjoint;
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
const mergeSections = (a: WorkingSection, b: WorkingSection) => {
|
|
247
|
+
return {
|
|
248
|
+
units: [...a.units, ...b.units],
|
|
249
|
+
heightRange: mergeAgeRanges(
|
|
250
|
+
[a.heightRange, b.heightRange],
|
|
251
|
+
MergeMode.Outer,
|
|
252
|
+
),
|
|
253
|
+
};
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
// Merge overlapping sections progressively until no more merges are possible
|
|
257
|
+
let finalSectionList = initialSections;
|
|
258
|
+
|
|
259
|
+
while (true) {
|
|
260
|
+
let merged = false;
|
|
261
|
+
const nextSections: WorkingSection[] = [];
|
|
262
|
+
|
|
263
|
+
for (const section of finalSectionList) {
|
|
264
|
+
if (nextSections.length === 0) {
|
|
265
|
+
nextSections.push(section);
|
|
227
266
|
} else {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
267
|
+
const lastSection = nextSections[nextSections.length - 1];
|
|
268
|
+
if (isOverlapping(section, lastSection)) {
|
|
269
|
+
// Merge with the last section
|
|
270
|
+
nextSections[nextSections.length - 1] = mergeSections(lastSection, section);
|
|
271
|
+
merged = true;
|
|
272
|
+
} else {
|
|
273
|
+
nextSections.push(section);
|
|
274
|
+
}
|
|
232
275
|
}
|
|
233
276
|
}
|
|
277
|
+
|
|
278
|
+
finalSectionList = nextSections;
|
|
279
|
+
|
|
280
|
+
// Stop when no more merges occurred in this pass
|
|
281
|
+
if (!merged) {
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
234
284
|
}
|
|
235
|
-
// We should have a section for each unit, now we can convert to SectionInfo
|
|
236
|
-
// Ages have to be really actually ages, not heights
|
|
237
285
|
|
|
238
|
-
return
|
|
286
|
+
return finalSectionList.map((section, i) => {
|
|
239
287
|
const [b_age, t_age] = getSectionAgeRange(section.units);
|
|
240
288
|
const [b_pos, t_pos] = getSectionPosRange(section.units, axisType);
|
|
241
289
|
return {
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
mergeOverlappingSections,
|
|
7
7
|
preprocessSectionUnit,
|
|
8
8
|
preprocessUnits,
|
|
9
|
+
UnitWithLayoutHints,
|
|
9
10
|
} from "./helpers";
|
|
10
11
|
import { ColumnAxisType } from "@macrostrat/column-components";
|
|
11
12
|
import { useMemo } from "react";
|
|
@@ -43,7 +44,7 @@ export function usePreparedColumnUnits(
|
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
export function prepareColumnUnits(
|
|
46
|
-
units: UnitLong[],
|
|
47
|
+
units: UnitWithLayoutHints<UnitLong>[],
|
|
47
48
|
options: PrepareColumnOptions,
|
|
48
49
|
): PreparedColumnData {
|
|
49
50
|
/** Prepare units for rendering into Macrostrat columns */
|
|
@@ -184,6 +185,8 @@ export function prepareColumnUnits(
|
|
|
184
185
|
* We do this after merging sections so that we can
|
|
185
186
|
* handle cases where there are overlapping units across sections
|
|
186
187
|
* */
|
|
188
|
+
console.log(sections2, "sections");
|
|
189
|
+
|
|
187
190
|
const sectionsOut = sections2.map((section) => {
|
|
188
191
|
return {
|
|
189
192
|
...section,
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
.labeled-unit
|
|
5
5
|
--column-unit-background-internal: var(--column-unit-background-color, var(--column-background-color))
|
|
6
6
|
:global(.unit-overlay)
|
|
7
|
-
font-size: 10px
|
|
8
|
-
font-style: italic
|
|
7
|
+
font-size: var(--column-unit-font-size, 10px)
|
|
8
|
+
font-style: var(--column-unit-font-style, italic)
|
|
9
9
|
display: flex
|
|
10
10
|
align-items: center
|
|
11
11
|
justify-content: center
|
package/src/units/index.ts
CHANGED
|
@@ -14,7 +14,7 @@ import { useEnvironments, useLithologies } from "@macrostrat/data-provider";
|
|
|
14
14
|
import { useMemo } from "react";
|
|
15
15
|
import { resolveID } from "./resolvers";
|
|
16
16
|
import { BaseUnit, Lithology } from "@macrostrat/api-types";
|
|
17
|
-
import {
|
|
17
|
+
import { UnitWithLayoutParameters } from "../prepare-units/helpers.ts";
|
|
18
18
|
|
|
19
19
|
export * from "./composite";
|
|
20
20
|
export * from "./types";
|
|
@@ -58,7 +58,7 @@ export function BasicUnitComponent({ division, ...rest }) {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
interface UnitComponentProps<T extends BaseUnit> {
|
|
61
|
-
division:
|
|
61
|
+
division: UnitWithLayoutParameters<T> | T;
|
|
62
62
|
nColumns: number;
|
|
63
63
|
width?: number;
|
|
64
64
|
}
|
|
@@ -78,11 +78,11 @@ export function UnitComponent<T extends BaseUnit>({
|
|
|
78
78
|
let x = 0;
|
|
79
79
|
|
|
80
80
|
let reducedWidth = _nColumns;
|
|
81
|
-
if ("
|
|
82
|
-
const
|
|
83
|
-
_nColumns = Math.min(_nColumns,
|
|
84
|
-
columnIx =
|
|
85
|
-
reducedWidth = width /
|
|
81
|
+
if ("layout" in division) {
|
|
82
|
+
const layout = division.layout;
|
|
83
|
+
_nColumns = Math.min(_nColumns, layout.totalColumns);
|
|
84
|
+
columnIx = layout.column;
|
|
85
|
+
reducedWidth = width / layout.totalColumns / layout.nColumns;
|
|
86
86
|
x = (columnIx * width) / _nColumns;
|
|
87
87
|
}
|
|
88
88
|
return h(TrackedLabeledUnit, {
|