@diagrammo/dgmo 0.47.0 → 0.48.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/dist/advanced.js +11 -11
- package/dist/auto.js +16 -16
- package/dist/auto.mjs +41 -12
- package/dist/block.js +4 -4
- package/dist/{chunk-FNB3PNGF.js → chunk-7DTWEFUE.js} +3 -3
- package/dist/{chunk-2DXMZRWJ.js → chunk-B65G5DNL.js} +8 -1
- package/dist/{chunk-RZCF2VVM.js → chunk-B7JUCQUA.js} +3 -1
- package/dist/{chunk-DU7W62N5.js → chunk-FANX6UJR.js} +3 -3
- package/dist/{chunk-6FZYCKXB.js → chunk-HSH73DP6.js} +2 -2
- package/dist/{chunk-P4RH4OSP.js → chunk-ILKORZ3H.js} +2 -2
- package/dist/{chunk-Y5QGVTVC.js → chunk-JTSMEYIZ.js} +7 -3
- package/dist/{chunk-RCERWOJR.js → chunk-ODZVHU3R.js} +1 -2
- package/dist/{chunk-DZAQBW35.js → chunk-SGZYXELT.js} +3 -7
- package/dist/{chunk-CUVHQHZ7.js → chunk-THXCFRTU.js} +3 -3
- package/dist/{chunk-IH6ZMVQ5.js → chunk-UC7TFHUM.js} +29 -11
- package/dist/{chunk-EMS2SK26.js → chunk-ZBWMSD5N.js} +3 -1
- package/dist/cli.cjs +15 -15
- package/dist/{dgmo-router-DZCIDUO5.js → dgmo-router-X35VLZLM.js} +3 -3
- package/dist/element.js +16 -16
- package/dist/element.mjs +41 -12
- package/dist/{flowchart-renderer-ZAEOL4DX.js → flowchart-renderer-SNDSII4D.js} +2 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +4 -4
- package/dist/{parser-FUSKFGZN.js → parser-2EWECDSA.js} +2 -2
- package/dist/{renderer-UWA5XS74.js → renderer-4JHRUBE6.js} +3 -3
- package/dist/{renderer-WZRREQ2P.js → renderer-5MYBMBYO.js} +2 -2
- package/dist/{renderer-TOCOVLHS.js → renderer-B2OMQIQG.js} +3 -3
- package/dist/{renderer-2XQQQ6QR.js → renderer-N43WR5GV.js} +3 -3
- package/dist/{renderer-T7YKC5VP.js → renderer-ZRNG54CW.js} +3 -3
- package/dist/{state-renderer-RFYHSP4K.js → state-renderer-B4DQBM6M.js} +2 -2
- package/package.json +23 -71
- package/dist/advanced.cjs +0 -71648
- package/dist/advanced.d.cts +0 -5719
- package/dist/auto.cjs +0 -70648
- package/dist/auto.d.cts +0 -54
- package/dist/block.cjs +0 -70208
- package/dist/block.d.cts +0 -115
- package/dist/editor.cjs +0 -526
- package/dist/editor.d.cts +0 -26
- package/dist/element.cjs +0 -70530
- package/dist/element.d.cts +0 -62
- package/dist/highlight.cjs +0 -852
- package/dist/highlight.d.cts +0 -49
- package/dist/index.cjs +0 -70491
- package/dist/index.d.cts +0 -160
- package/dist/pert.cjs +0 -325
- package/dist/pert.d.cts +0 -559
- package/dist/themes-1-CuKpeH.d.cts +0 -908
- package/src/advanced.ts +0 -873
- package/src/arc/parser.ts +0 -15
- package/src/arc/renderer.ts +0 -633
- package/src/auto/index.ts +0 -621
- package/src/auto/shared.ts +0 -370
- package/src/auto/styles.ts +0 -73
- package/src/block/layout.ts +0 -198
- package/src/block/parser.ts +0 -427
- package/src/block/renderer.ts +0 -484
- package/src/block/types.ts +0 -67
- package/src/boxes-and-lines/collapse.ts +0 -96
- package/src/boxes-and-lines/focus.ts +0 -257
- package/src/boxes-and-lines/label-placement.ts +0 -339
- package/src/boxes-and-lines/layout-grouped.ts +0 -912
- package/src/boxes-and-lines/layout-layered.ts +0 -722
- package/src/boxes-and-lines/layout-search.ts +0 -1678
- package/src/boxes-and-lines/layout.ts +0 -398
- package/src/boxes-and-lines/parser.ts +0 -1181
- package/src/boxes-and-lines/renderer.ts +0 -1465
- package/src/boxes-and-lines/types.ts +0 -66
- package/src/c4/layout.ts +0 -2441
- package/src/c4/parser.ts +0 -1158
- package/src/c4/renderer.ts +0 -2008
- package/src/c4/types.ts +0 -89
- package/src/chart-type-registry.ts +0 -529
- package/src/chart-types.ts +0 -225
- package/src/chart.ts +0 -685
- package/src/charts-d3/bar.ts +0 -338
- package/src/charts-d3/chord.ts +0 -140
- package/src/charts-d3/function.ts +0 -147
- package/src/charts-d3/funnel.ts +0 -104
- package/src/charts-d3/heatmap.ts +0 -145
- package/src/charts-d3/index.ts +0 -337
- package/src/charts-d3/interactions.ts +0 -477
- package/src/charts-d3/line.ts +0 -344
- package/src/charts-d3/mount.ts +0 -151
- package/src/charts-d3/pie.ts +0 -117
- package/src/charts-d3/polar.ts +0 -89
- package/src/charts-d3/radar.ts +0 -0
- package/src/charts-d3/sankey.ts +0 -0
- package/src/charts-d3/scatter.ts +0 -185
- package/src/charts-d3/shared.ts +0 -208
- package/src/class/layout.ts +0 -326
- package/src/class/parser.ts +0 -635
- package/src/class/renderer.ts +0 -793
- package/src/class/types.ts +0 -58
- package/src/cli-banner.ts +0 -106
- package/src/cli.ts +0 -1080
- package/src/colors-diagnostics.ts +0 -35
- package/src/colors.ts +0 -379
- package/src/completion-types.ts +0 -27
- package/src/completion.ts +0 -2668
- package/src/cycle/layout.ts +0 -1026
- package/src/cycle/parser.ts +0 -387
- package/src/cycle/renderer.ts +0 -653
- package/src/cycle/types.ts +0 -101
- package/src/d3.ts +0 -1434
- package/src/data-chart-parser.ts +0 -1007
- package/src/dgmo-router.ts +0 -296
- package/src/diagnostics-registry.ts +0 -108
- package/src/diagnostics.ts +0 -0
- package/src/dimensions.ts +0 -20
- package/src/directives-registry.ts +0 -396
- package/src/editor/dgmo.grammar +0 -76
- package/src/editor/dgmo.grammar.d.ts +0 -2
- package/src/editor/dgmo.grammar.js +0 -18
- package/src/editor/dgmo.grammar.terms.d.ts +0 -5
- package/src/editor/dgmo.grammar.terms.js +0 -35
- package/src/editor/highlight-api.ts +0 -596
- package/src/editor/highlight.ts +0 -36
- package/src/editor/index.ts +0 -27
- package/src/editor/keywords.ts +0 -128
- package/src/editor/tokens.ts +0 -30
- package/src/element/index.ts +0 -432
- package/src/embed/css.ts +0 -312
- package/src/embed/escape.ts +0 -15
- package/src/embed/index.ts +0 -280
- package/src/er/classify.ts +0 -228
- package/src/er/layout.ts +0 -530
- package/src/er/parser.ts +0 -750
- package/src/er/renderer.ts +0 -725
- package/src/er/types.ts +0 -52
- package/src/error-card.ts +0 -269
- package/src/event-line/diagnostics.ts +0 -117
- package/src/event-line/parser.ts +0 -643
- package/src/event-line/renderer.ts +0 -1742
- package/src/event-line/types.ts +0 -74
- package/src/fonts.ts +0 -3
- package/src/gantt/calculator.ts +0 -979
- package/src/gantt/parser.ts +0 -1641
- package/src/gantt/renderer.ts +0 -3787
- package/src/gantt/resolver.ts +0 -172
- package/src/gantt/types.ts +0 -206
- package/src/graph/diagnostics.ts +0 -64
- package/src/graph/edge-spline.ts +0 -29
- package/src/graph/flowchart-parser.ts +0 -759
- package/src/graph/flowchart-renderer.ts +0 -817
- package/src/graph/layout.ts +0 -472
- package/src/graph/notes.ts +0 -21
- package/src/graph/state-collapse.ts +0 -78
- package/src/graph/state-parser.ts +0 -574
- package/src/graph/state-renderer.ts +0 -653
- package/src/graph/types.ts +0 -65
- package/src/index.ts +0 -261
- package/src/infra/compute.ts +0 -1385
- package/src/infra/layout.ts +0 -888
- package/src/infra/parser.ts +0 -1234
- package/src/infra/renderer.ts +0 -2534
- package/src/infra/roles.ts +0 -75
- package/src/infra/types.ts +0 -216
- package/src/infra/validation.ts +0 -201
- package/src/journey-map/layout.ts +0 -490
- package/src/journey-map/parser.ts +0 -557
- package/src/journey-map/renderer.ts +0 -1580
- package/src/journey-map/types.ts +0 -47
- package/src/kanban/mutations.ts +0 -175
- package/src/kanban/parser.ts +0 -509
- package/src/kanban/renderer.ts +0 -1449
- package/src/kanban/types.ts +0 -39
- package/src/label-layout.ts +0 -368
- package/src/map/colorize.ts +0 -54
- package/src/map/completion.ts +0 -316
- package/src/map/context-labels.ts +0 -609
- package/src/map/data/PROVENANCE.json +0 -1
- package/src/map/data/README.md +0 -40
- package/src/map/data/airport-collisions.json +0 -1
- package/src/map/data/airports.json +0 -1
- package/src/map/data/gazetteer.json +0 -1
- package/src/map/data/lakes.json +0 -1
- package/src/map/data/mountain-ranges.json +0 -1
- package/src/map/data/na-lakes.json +0 -1
- package/src/map/data/na-land.json +0 -1
- package/src/map/data/region-names.json +0 -1
- package/src/map/data/rivers.json +0 -1
- package/src/map/data/types.ts +0 -121
- package/src/map/data/us-states.json +0 -1
- package/src/map/data/water-bodies.json +0 -1
- package/src/map/data/world-coarse.json +0 -1
- package/src/map/data/world-detail.json +0 -1
- package/src/map/diagnostics.ts +0 -134
- package/src/map/dimensions.ts +0 -150
- package/src/map/geo-query.ts +0 -295
- package/src/map/geo.ts +0 -438
- package/src/map/invert.ts +0 -111
- package/src/map/layout.ts +0 -5069
- package/src/map/legend-band.ts +0 -127
- package/src/map/load-data.ts +0 -186
- package/src/map/parser.ts +0 -783
- package/src/map/renderer.ts +0 -1445
- package/src/map/resolved-types.ts +0 -160
- package/src/map/resolver.ts +0 -1146
- package/src/map/types.ts +0 -194
- package/src/mindmap/collapse.ts +0 -67
- package/src/mindmap/layout.ts +0 -649
- package/src/mindmap/parser.ts +0 -430
- package/src/mindmap/renderer.ts +0 -637
- package/src/mindmap/text-wrap.ts +0 -218
- package/src/mindmap/types.ts +0 -56
- package/src/org/collapse.ts +0 -151
- package/src/org/layout.ts +0 -1262
- package/src/org/parser.ts +0 -519
- package/src/org/renderer.ts +0 -866
- package/src/org/resolver.ts +0 -636
- package/src/palettes/atlas.ts +0 -77
- package/src/palettes/blueprint.ts +0 -73
- package/src/palettes/catppuccin.ts +0 -84
- package/src/palettes/color-utils.ts +0 -443
- package/src/palettes/index.ts +0 -67
- package/src/palettes/nord.ts +0 -67
- package/src/palettes/registry.ts +0 -114
- package/src/palettes/slate.ts +0 -73
- package/src/palettes/tidewater.ts +0 -73
- package/src/palettes/tokyo-night.ts +0 -86
- package/src/palettes/types.ts +0 -88
- package/src/pert/analyzer.ts +0 -1183
- package/src/pert/diagnostics.ts +0 -110
- package/src/pert/index.ts +0 -43
- package/src/pert/internal.ts +0 -252
- package/src/pert/layout.ts +0 -971
- package/src/pert/monte-carlo.ts +0 -446
- package/src/pert/parser.ts +0 -1606
- package/src/pert/renderer.ts +0 -4009
- package/src/pert/share-normalize.ts +0 -62
- package/src/pert/types.ts +0 -604
- package/src/pyramid/parser.ts +0 -185
- package/src/pyramid/renderer.ts +0 -768
- package/src/pyramid/types.ts +0 -28
- package/src/quadrant/parser.ts +0 -18
- package/src/quadrant/renderer.ts +0 -638
- package/src/raci/diagnostics.ts +0 -213
- package/src/raci/index.ts +0 -23
- package/src/raci/mutations.ts +0 -321
- package/src/raci/parser.ts +0 -699
- package/src/raci/renderer.ts +0 -1627
- package/src/raci/types.ts +0 -82
- package/src/raci/variants.ts +0 -320
- package/src/render.ts +0 -268
- package/src/ring/parser.ts +0 -212
- package/src/ring/renderer.ts +0 -490
- package/src/ring/types.ts +0 -27
- package/src/sequence/collapse.ts +0 -174
- package/src/sequence/parser.ts +0 -1596
- package/src/sequence/participant-inference.ts +0 -152
- package/src/sequence/renderer.ts +0 -3168
- package/src/sequence/tag-resolution.ts +0 -164
- package/src/sharing.ts +0 -211
- package/src/sitemap/collapse.ts +0 -100
- package/src/sitemap/layout.ts +0 -925
- package/src/sitemap/parser.ts +0 -755
- package/src/sitemap/renderer.ts +0 -828
- package/src/sitemap/types.ts +0 -42
- package/src/slope/parser.ts +0 -18
- package/src/slope/renderer.ts +0 -378
- package/src/swimlane/diagnostics.ts +0 -94
- package/src/swimlane/layout.ts +0 -597
- package/src/swimlane/parser.ts +0 -613
- package/src/swimlane/renderer.ts +0 -681
- package/src/swimlane/types.ts +0 -151
- package/src/tech-radar/interactive.ts +0 -1129
- package/src/tech-radar/layout.ts +0 -197
- package/src/tech-radar/parser.ts +0 -436
- package/src/tech-radar/renderer.ts +0 -1239
- package/src/tech-radar/shared.ts +0 -151
- package/src/tech-radar/types.ts +0 -86
- package/src/themes.ts +0 -22
- package/src/timeline/parser.ts +0 -472
- package/src/timeline/renderer.ts +0 -3024
- package/src/timeline/types.ts +0 -33
- package/src/timeline/viz-parser.ts +0 -21
- package/src/treemap/diagnostics.ts +0 -62
- package/src/treemap/layout-radial.ts +0 -233
- package/src/treemap/layout.ts +0 -189
- package/src/treemap/parser.ts +0 -463
- package/src/treemap/renderer-radial.ts +0 -438
- package/src/treemap/renderer.ts +0 -572
- package/src/treemap/treemap-shared.ts +0 -309
- package/src/treemap/types.ts +0 -60
- package/src/utils/arrow-markers.ts +0 -51
- package/src/utils/arrows-diagnostics.ts +0 -62
- package/src/utils/arrows.ts +0 -227
- package/src/utils/brand.ts +0 -61
- package/src/utils/card.ts +0 -183
- package/src/utils/collapse-engine/tree-edges.ts +0 -115
- package/src/utils/collapse-engine/tree.ts +0 -117
- package/src/utils/d3-helpers.ts +0 -219
- package/src/utils/d3-types.ts +0 -9
- package/src/utils/description-helpers.ts +0 -38
- package/src/utils/duration.ts +0 -312
- package/src/utils/export-container.ts +0 -41
- package/src/utils/expr-eval.ts +0 -27
- package/src/utils/fit-canvas.ts +0 -64
- package/src/utils/hover-styles.ts +0 -673
- package/src/utils/inline-markdown.ts +0 -96
- package/src/utils/legend-constants.ts +0 -48
- package/src/utils/legend-d3.ts +0 -618
- package/src/utils/legend-integration.ts +0 -107
- package/src/utils/legend-layout.ts +0 -776
- package/src/utils/legend-svg.ts +0 -214
- package/src/utils/legend-types.ts +0 -272
- package/src/utils/name-normalize.ts +0 -163
- package/src/utils/note-box/constants.ts +0 -25
- package/src/utils/note-box/index.ts +0 -11
- package/src/utils/note-box/metrics.ts +0 -90
- package/src/utils/note-box/svg.ts +0 -331
- package/src/utils/notes/bounds.ts +0 -30
- package/src/utils/notes/build.ts +0 -131
- package/src/utils/notes/index.ts +0 -18
- package/src/utils/notes/model.ts +0 -19
- package/src/utils/notes/parse.ts +0 -131
- package/src/utils/notes/place.ts +0 -177
- package/src/utils/notes/resolve.ts +0 -88
- package/src/utils/number-format.ts +0 -36
- package/src/utils/parsing.ts +0 -953
- package/src/utils/reserved-key-registry.ts +0 -239
- package/src/utils/safe-href.ts +0 -38
- package/src/utils/scaling.ts +0 -97
- package/src/utils/svg-embed.ts +0 -251
- package/src/utils/tag-groups.ts +0 -607
- package/src/utils/text-measure.ts +0 -122
- package/src/utils/time-ticks.ts +0 -253
- package/src/utils/title-constants.ts +0 -24
- package/src/utils/visual-conventions.ts +0 -61
- package/src/utils/wrapped-desc.ts +0 -87
- package/src/venn/parser.ts +0 -18
- package/src/venn/renderer.ts +0 -1047
- package/src/version-control/diagnostics.ts +0 -67
- package/src/version-control/parser.ts +0 -544
- package/src/version-control/renderer.ts +0 -724
- package/src/version-control/types.ts +0 -100
- package/src/visualizations/parse.ts +0 -1560
- package/src/visualizations/types.ts +0 -262
- package/src/wireframe/layout.ts +0 -479
- package/src/wireframe/parser.ts +0 -1114
- package/src/wireframe/renderer.ts +0 -1318
- package/src/wireframe/types.ts +0 -110
- package/src/wordcloud/parser.ts +0 -18
- package/src/wordcloud/renderer.ts +0 -357
package/src/kanban/types.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import type { DgmoError } from '../diagnostics';
|
|
2
|
-
import type { TagGroup, TagEntry } from '../utils/tag-groups';
|
|
3
|
-
|
|
4
|
-
/** @deprecated Use `TagEntry` from `utils/tag-groups` */
|
|
5
|
-
export type KanbanTagEntry = TagEntry;
|
|
6
|
-
/** @deprecated Use `TagGroup` from `utils/tag-groups` */
|
|
7
|
-
export type KanbanTagGroup = TagGroup;
|
|
8
|
-
|
|
9
|
-
export interface KanbanCard {
|
|
10
|
-
readonly id: string;
|
|
11
|
-
readonly title: string;
|
|
12
|
-
readonly tags: Readonly<Record<string, string>>; // groupName → value
|
|
13
|
-
readonly details: readonly string[]; // freeform indented lines
|
|
14
|
-
readonly lineNumber: number; // first line of the card (1-based)
|
|
15
|
-
readonly endLineNumber: number; // last line inclusive (1-based)
|
|
16
|
-
readonly color?: string; // explicit color override via (color) suffix
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface KanbanColumn {
|
|
20
|
-
readonly id: string;
|
|
21
|
-
readonly name: string;
|
|
22
|
-
readonly wipLimit?: number;
|
|
23
|
-
readonly color?: string;
|
|
24
|
-
readonly collapsed?: boolean; // `[Column] collapsed: true` view-state marker
|
|
25
|
-
readonly metadata?: Readonly<Record<string, string>>;
|
|
26
|
-
readonly cards: readonly KanbanCard[];
|
|
27
|
-
readonly lineNumber: number;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface ParsedKanban {
|
|
31
|
-
readonly type: 'kanban';
|
|
32
|
-
readonly title?: string;
|
|
33
|
-
readonly titleLineNumber?: number;
|
|
34
|
-
readonly columns: readonly KanbanColumn[];
|
|
35
|
-
readonly tagGroups: readonly KanbanTagGroup[];
|
|
36
|
-
readonly options: Readonly<Record<string, string>>;
|
|
37
|
-
readonly diagnostics: readonly DgmoError[];
|
|
38
|
-
readonly error: string | null;
|
|
39
|
-
}
|
package/src/label-layout.ts
DELETED
|
@@ -1,368 +0,0 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// Shared label collision detection and placement utilities
|
|
3
|
-
// ---------------------------------------------------------------------------
|
|
4
|
-
|
|
5
|
-
import { measureText } from './utils/text-measure';
|
|
6
|
-
|
|
7
|
-
export interface LabelRect {
|
|
8
|
-
x: number;
|
|
9
|
-
y: number;
|
|
10
|
-
w: number;
|
|
11
|
-
h: number;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface PointCircle {
|
|
15
|
-
cx: number;
|
|
16
|
-
cy: number;
|
|
17
|
-
r: number;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/** Axis-aligned bounding box overlap test. */
|
|
21
|
-
export function rectsOverlap(a: LabelRect, b: LabelRect): boolean {
|
|
22
|
-
return (
|
|
23
|
-
a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/** Rect vs circle overlap using nearest-point-on-rect distance check. */
|
|
28
|
-
export function rectCircleOverlap(
|
|
29
|
-
rect: LabelRect,
|
|
30
|
-
circle: PointCircle
|
|
31
|
-
): boolean {
|
|
32
|
-
const nearestX = Math.max(rect.x, Math.min(circle.cx, rect.x + rect.w));
|
|
33
|
-
const nearestY = Math.max(rect.y, Math.min(circle.cy, rect.y + rect.h));
|
|
34
|
-
const dx = nearestX - circle.cx;
|
|
35
|
-
const dy = nearestY - circle.cy;
|
|
36
|
-
return dx * dx + dy * dy < circle.r * circle.r;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/** Line-segment vs axis-aligned rect intersection (Liang–Barsky clip). True
|
|
40
|
-
* when any part of the segment lies inside or crosses the rect. */
|
|
41
|
-
export function segmentRectOverlap(
|
|
42
|
-
x0: number,
|
|
43
|
-
y0: number,
|
|
44
|
-
x1: number,
|
|
45
|
-
y1: number,
|
|
46
|
-
rect: LabelRect
|
|
47
|
-
): boolean {
|
|
48
|
-
const dx = x1 - x0;
|
|
49
|
-
const dy = y1 - y0;
|
|
50
|
-
let t0 = 0;
|
|
51
|
-
let t1 = 1;
|
|
52
|
-
const edges: Array<[number, number]> = [
|
|
53
|
-
[-dx, x0 - rect.x],
|
|
54
|
-
[dx, rect.x + rect.w - x0],
|
|
55
|
-
[-dy, y0 - rect.y],
|
|
56
|
-
[dy, rect.y + rect.h - y0],
|
|
57
|
-
];
|
|
58
|
-
for (const [p, q] of edges) {
|
|
59
|
-
if (p === 0) {
|
|
60
|
-
if (q < 0) return false; // parallel and outside this edge
|
|
61
|
-
} else {
|
|
62
|
-
const t = q / p;
|
|
63
|
-
if (p < 0) {
|
|
64
|
-
if (t > t1) return false;
|
|
65
|
-
if (t > t0) t0 = t;
|
|
66
|
-
} else {
|
|
67
|
-
if (t < t0) return false;
|
|
68
|
-
if (t < t1) t1 = t;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
return true;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/** Segment vs segment proper intersection (orientation test). True when the two
|
|
76
|
-
* open segments cross. Shared endpoints / collinear touching count as crossing
|
|
77
|
-
* too (the conservative choice for "do these two leader lines tangle?"). */
|
|
78
|
-
export function segmentsCross(
|
|
79
|
-
ax: number,
|
|
80
|
-
ay: number,
|
|
81
|
-
bx: number,
|
|
82
|
-
by: number,
|
|
83
|
-
cx: number,
|
|
84
|
-
cy: number,
|
|
85
|
-
dx: number,
|
|
86
|
-
dy: number
|
|
87
|
-
): boolean {
|
|
88
|
-
const o = (
|
|
89
|
-
px: number,
|
|
90
|
-
py: number,
|
|
91
|
-
qx: number,
|
|
92
|
-
qy: number,
|
|
93
|
-
rx: number,
|
|
94
|
-
ry: number
|
|
95
|
-
): number => Math.sign((qx - px) * (ry - py) - (qy - py) * (rx - px));
|
|
96
|
-
const o1 = o(ax, ay, bx, by, cx, cy);
|
|
97
|
-
const o2 = o(ax, ay, bx, by, dx, dy);
|
|
98
|
-
const o3 = o(cx, cy, dx, dy, ax, ay);
|
|
99
|
-
const o4 = o(cx, cy, dx, dy, bx, by);
|
|
100
|
-
if (o1 !== o2 && o3 !== o4) return true;
|
|
101
|
-
// Collinear-overlap edge cases: treat any on-segment touch as a crossing.
|
|
102
|
-
const onSeg = (
|
|
103
|
-
px: number,
|
|
104
|
-
py: number,
|
|
105
|
-
qx: number,
|
|
106
|
-
qy: number,
|
|
107
|
-
rx: number,
|
|
108
|
-
ry: number
|
|
109
|
-
): boolean =>
|
|
110
|
-
Math.min(px, qx) <= rx &&
|
|
111
|
-
rx <= Math.max(px, qx) &&
|
|
112
|
-
Math.min(py, qy) <= ry &&
|
|
113
|
-
ry <= Math.max(py, qy);
|
|
114
|
-
if (o1 === 0 && onSeg(ax, ay, bx, by, cx, cy)) return true;
|
|
115
|
-
if (o2 === 0 && onSeg(ax, ay, bx, by, dx, dy)) return true;
|
|
116
|
-
if (o3 === 0 && onSeg(cx, cy, dx, dy, ax, ay)) return true;
|
|
117
|
-
if (o4 === 0 && onSeg(cx, cy, dx, dy, bx, by)) return true;
|
|
118
|
-
return false;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// ---------------------------------------------------------------------------
|
|
122
|
-
// Quadrant chart point label placement
|
|
123
|
-
// ---------------------------------------------------------------------------
|
|
124
|
-
|
|
125
|
-
export interface QuadrantLabelPoint {
|
|
126
|
-
label: string;
|
|
127
|
-
cx: number; // pixel x
|
|
128
|
-
cy: number; // pixel y
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
interface PlacedQuadrantLabel {
|
|
132
|
-
label: string;
|
|
133
|
-
x: number; // text x
|
|
134
|
-
y: number; // text y (center of label)
|
|
135
|
-
anchor: 'middle' | 'start' | 'end';
|
|
136
|
-
connectorLine?: { x1: number; y1: number; x2: number; y2: number };
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Greedy label placement for quadrant chart points.
|
|
141
|
-
* Avoids collisions with other point labels, point circles, and obstacle rects
|
|
142
|
-
* (quadrant watermark labels). Labels are constrained within chartBounds.
|
|
143
|
-
*
|
|
144
|
-
* Pure function — no DOM dependency.
|
|
145
|
-
*/
|
|
146
|
-
export function computeQuadrantPointLabels(
|
|
147
|
-
points: QuadrantLabelPoint[],
|
|
148
|
-
chartBounds: { left: number; top: number; right: number; bottom: number },
|
|
149
|
-
obstacles: LabelRect[],
|
|
150
|
-
pointRadius: number,
|
|
151
|
-
fontSize: number
|
|
152
|
-
): PlacedQuadrantLabel[] {
|
|
153
|
-
const labelHeight = fontSize + 4;
|
|
154
|
-
const stepSize = labelHeight + 2;
|
|
155
|
-
const minGap = pointRadius + 4;
|
|
156
|
-
|
|
157
|
-
// Build collision circles for all points
|
|
158
|
-
const pointCircles: PointCircle[] = points.map((p) => ({
|
|
159
|
-
cx: p.cx,
|
|
160
|
-
cy: p.cy,
|
|
161
|
-
r: pointRadius,
|
|
162
|
-
}));
|
|
163
|
-
|
|
164
|
-
const placedLabels: LabelRect[] = [];
|
|
165
|
-
const results: PlacedQuadrantLabel[] = [];
|
|
166
|
-
|
|
167
|
-
for (let i = 0; i < points.length; i++) {
|
|
168
|
-
const pt = points[i]!; // In-bounds by loop guard.
|
|
169
|
-
const labelWidth = measureText(pt.label, fontSize) + 8;
|
|
170
|
-
|
|
171
|
-
// Try 4 directions: above, below, left, right
|
|
172
|
-
// Each direction generates candidate (labelX, labelY, anchor)
|
|
173
|
-
type Candidate = {
|
|
174
|
-
rect: LabelRect;
|
|
175
|
-
textX: number;
|
|
176
|
-
textY: number;
|
|
177
|
-
anchor: 'middle' | 'start' | 'end';
|
|
178
|
-
dist: number;
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
let best: Candidate | null = null;
|
|
182
|
-
|
|
183
|
-
// Direction generators: for a given offset, produce a candidate rect + text position
|
|
184
|
-
const directions: Array<{
|
|
185
|
-
gen: (offset: number) => {
|
|
186
|
-
rect: LabelRect;
|
|
187
|
-
textX: number;
|
|
188
|
-
textY: number;
|
|
189
|
-
anchor: 'middle' | 'start' | 'end';
|
|
190
|
-
} | null;
|
|
191
|
-
}> = [
|
|
192
|
-
{
|
|
193
|
-
// Above
|
|
194
|
-
gen: (offset) => {
|
|
195
|
-
const lx = pt.cx - labelWidth / 2;
|
|
196
|
-
const ly = pt.cy - offset - labelHeight;
|
|
197
|
-
if (
|
|
198
|
-
ly < chartBounds.top ||
|
|
199
|
-
lx < chartBounds.left ||
|
|
200
|
-
lx + labelWidth > chartBounds.right
|
|
201
|
-
)
|
|
202
|
-
return null;
|
|
203
|
-
return {
|
|
204
|
-
rect: { x: lx, y: ly, w: labelWidth, h: labelHeight },
|
|
205
|
-
textX: pt.cx,
|
|
206
|
-
textY: ly + labelHeight / 2,
|
|
207
|
-
anchor: 'middle',
|
|
208
|
-
};
|
|
209
|
-
},
|
|
210
|
-
},
|
|
211
|
-
{
|
|
212
|
-
// Below
|
|
213
|
-
gen: (offset) => {
|
|
214
|
-
const lx = pt.cx - labelWidth / 2;
|
|
215
|
-
const ly = pt.cy + offset;
|
|
216
|
-
if (
|
|
217
|
-
ly + labelHeight > chartBounds.bottom ||
|
|
218
|
-
lx < chartBounds.left ||
|
|
219
|
-
lx + labelWidth > chartBounds.right
|
|
220
|
-
)
|
|
221
|
-
return null;
|
|
222
|
-
return {
|
|
223
|
-
rect: { x: lx, y: ly, w: labelWidth, h: labelHeight },
|
|
224
|
-
textX: pt.cx,
|
|
225
|
-
textY: ly + labelHeight / 2,
|
|
226
|
-
anchor: 'middle',
|
|
227
|
-
};
|
|
228
|
-
},
|
|
229
|
-
},
|
|
230
|
-
{
|
|
231
|
-
// Right
|
|
232
|
-
gen: (offset) => {
|
|
233
|
-
const lx = pt.cx + offset;
|
|
234
|
-
const ly = pt.cy - labelHeight / 2;
|
|
235
|
-
if (
|
|
236
|
-
lx + labelWidth > chartBounds.right ||
|
|
237
|
-
ly < chartBounds.top ||
|
|
238
|
-
ly + labelHeight > chartBounds.bottom
|
|
239
|
-
)
|
|
240
|
-
return null;
|
|
241
|
-
return {
|
|
242
|
-
rect: { x: lx, y: ly, w: labelWidth, h: labelHeight },
|
|
243
|
-
textX: lx,
|
|
244
|
-
textY: pt.cy,
|
|
245
|
-
anchor: 'start',
|
|
246
|
-
};
|
|
247
|
-
},
|
|
248
|
-
},
|
|
249
|
-
{
|
|
250
|
-
// Left
|
|
251
|
-
gen: (offset) => {
|
|
252
|
-
const lx = pt.cx - offset - labelWidth;
|
|
253
|
-
const ly = pt.cy - labelHeight / 2;
|
|
254
|
-
if (
|
|
255
|
-
lx < chartBounds.left ||
|
|
256
|
-
ly < chartBounds.top ||
|
|
257
|
-
ly + labelHeight > chartBounds.bottom
|
|
258
|
-
)
|
|
259
|
-
return null;
|
|
260
|
-
return {
|
|
261
|
-
rect: { x: lx, y: ly, w: labelWidth, h: labelHeight },
|
|
262
|
-
textX: lx + labelWidth,
|
|
263
|
-
textY: pt.cy,
|
|
264
|
-
anchor: 'end',
|
|
265
|
-
};
|
|
266
|
-
},
|
|
267
|
-
},
|
|
268
|
-
];
|
|
269
|
-
|
|
270
|
-
for (const { gen } of directions) {
|
|
271
|
-
for (let offset = minGap; ; offset += stepSize) {
|
|
272
|
-
const cand = gen(offset);
|
|
273
|
-
if (!cand) break; // out of bounds in this direction
|
|
274
|
-
|
|
275
|
-
// Check collisions with placed labels
|
|
276
|
-
let collision = false;
|
|
277
|
-
for (const pl of placedLabels) {
|
|
278
|
-
if (rectsOverlap(cand.rect, pl)) {
|
|
279
|
-
collision = true;
|
|
280
|
-
break;
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Check collisions with point circles
|
|
285
|
-
if (!collision) {
|
|
286
|
-
for (const circle of pointCircles) {
|
|
287
|
-
if (rectCircleOverlap(cand.rect, circle)) {
|
|
288
|
-
collision = true;
|
|
289
|
-
break;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// Check collisions with obstacle rects (quadrant labels)
|
|
295
|
-
if (!collision) {
|
|
296
|
-
for (const obs of obstacles) {
|
|
297
|
-
if (rectsOverlap(cand.rect, obs)) {
|
|
298
|
-
collision = true;
|
|
299
|
-
break;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
if (!collision) {
|
|
305
|
-
const dist = offset;
|
|
306
|
-
if (!best || dist < best.dist) {
|
|
307
|
-
best = {
|
|
308
|
-
rect: cand.rect,
|
|
309
|
-
textX: cand.textX,
|
|
310
|
-
textY: cand.textY,
|
|
311
|
-
anchor: cand.anchor,
|
|
312
|
-
dist,
|
|
313
|
-
};
|
|
314
|
-
}
|
|
315
|
-
break; // best for this direction found
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// Fallback: place above at minGap (may overlap, but at least visible)
|
|
321
|
-
if (!best) {
|
|
322
|
-
const lx = pt.cx - labelWidth / 2;
|
|
323
|
-
const ly = pt.cy - minGap - labelHeight;
|
|
324
|
-
best = {
|
|
325
|
-
rect: { x: lx, y: ly, w: labelWidth, h: labelHeight },
|
|
326
|
-
textX: pt.cx,
|
|
327
|
-
textY: ly + labelHeight / 2,
|
|
328
|
-
anchor: 'middle',
|
|
329
|
-
dist: minGap,
|
|
330
|
-
};
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
placedLabels.push(best.rect);
|
|
334
|
-
|
|
335
|
-
// Connector line when label is pushed beyond immediate adjacency
|
|
336
|
-
let connectorLine: PlacedQuadrantLabel['connectorLine'];
|
|
337
|
-
if (best.dist > minGap + stepSize) {
|
|
338
|
-
// Determine connector endpoints: from point edge to label edge
|
|
339
|
-
const dx = best.textX - pt.cx;
|
|
340
|
-
const dy = best.textY - pt.cy;
|
|
341
|
-
const angle = Math.atan2(dy, dx);
|
|
342
|
-
const x1 = pt.cx + Math.cos(angle) * pointRadius;
|
|
343
|
-
const y1 = pt.cy + Math.sin(angle) * pointRadius;
|
|
344
|
-
|
|
345
|
-
// Label edge: closest point on label rect to the point
|
|
346
|
-
const x2 = Math.max(
|
|
347
|
-
best.rect.x,
|
|
348
|
-
Math.min(pt.cx, best.rect.x + best.rect.w)
|
|
349
|
-
);
|
|
350
|
-
const y2 = Math.max(
|
|
351
|
-
best.rect.y,
|
|
352
|
-
Math.min(pt.cy, best.rect.y + best.rect.h)
|
|
353
|
-
);
|
|
354
|
-
|
|
355
|
-
connectorLine = { x1, y1, x2, y2 };
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
results.push({
|
|
359
|
-
label: pt.label,
|
|
360
|
-
x: best.textX,
|
|
361
|
-
y: best.textY,
|
|
362
|
-
anchor: best.anchor,
|
|
363
|
-
...(connectorLine !== undefined && { connectorLine }),
|
|
364
|
-
});
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
return results;
|
|
368
|
-
}
|
package/src/map/colorize.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
// Political fill-assignment pass (§24B colorize). PURE + DETERMINISTIC — no
|
|
2
|
-
// projection, no palette, no DOM. Given the per-topology arc-adjacency graph
|
|
3
|
-
// (from geo.ts buildAdjacency), assign every drawn region a colour INDEX such
|
|
4
|
-
// that no two arc-neighbours share one. The only job of a political fill is
|
|
5
|
-
// boundary disambiguation; "no two neighbours share a hue" is the minimal
|
|
6
|
-
// property — and a planar political map famously needs only a handful of colours.
|
|
7
|
-
//
|
|
8
|
-
// FIRST-FIT greedy: each region takes the LOWEST index not used by an
|
|
9
|
-
// already-coloured neighbour. This is collision-free by construction (a node with
|
|
10
|
-
// k coloured neighbours has at most k forbidden indices, so index ≤ k is always
|
|
11
|
-
// free) AND clusters regions into the FEWEST colours — on the shipped graphs the
|
|
12
|
-
// max index used is 5 (world) / 4 (us-states), i.e. 5–6 colours total. The caller
|
|
13
|
-
// generates exactly that many palette tints, so the fills stay on-palette (no
|
|
14
|
-
// need for the old Δ+1 ≈ 17 wheel hues).
|
|
15
|
-
|
|
16
|
-
/** Result of {@link assignColors}: a colour INDEX per ISO + the number of
|
|
17
|
-
* distinct colours actually used (`= maxIndex + 1`). The index is a stable
|
|
18
|
-
* function of (ISO, global arc-adjacency) — extent-independent (AC10). */
|
|
19
|
-
export interface ColorAssignment {
|
|
20
|
-
readonly byIso: Map<string, number>;
|
|
21
|
-
readonly huesNeeded: number;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/** First-fit greedy graph-coloring over `isos` using `adjacency` (ISO → neighbour
|
|
25
|
-
* ISOs). Visits ISOs in stable ascending order; each takes the lowest index not
|
|
26
|
-
* taken by an already-coloured neighbour — collision-free, and minimises the
|
|
27
|
-
* total colour count.
|
|
28
|
-
*
|
|
29
|
-
* EVERY iso in `isos` is assigned an index — including zero-degree nodes
|
|
30
|
-
* (islands, DC, territories with no neighbour entry) — so the caller never needs
|
|
31
|
-
* a fallback fill (F14). */
|
|
32
|
-
export function assignColors(
|
|
33
|
-
isos: readonly string[],
|
|
34
|
-
adjacency: ReadonlyMap<string, readonly string[]>
|
|
35
|
-
): ColorAssignment {
|
|
36
|
-
const sorted = [...isos].sort();
|
|
37
|
-
const byIso = new Map<string, number>();
|
|
38
|
-
let maxIndex = -1;
|
|
39
|
-
|
|
40
|
-
for (const iso of sorted) {
|
|
41
|
-
const taken = new Set<number>();
|
|
42
|
-
for (const n of adjacency.get(iso) ?? []) {
|
|
43
|
-
const c = byIso.get(n);
|
|
44
|
-
if (c !== undefined) taken.add(c);
|
|
45
|
-
}
|
|
46
|
-
// Lowest index not taken by a neighbour (always exists: ≤ neighbour count).
|
|
47
|
-
let h = 0;
|
|
48
|
-
while (taken.has(h)) h++;
|
|
49
|
-
byIso.set(iso, h);
|
|
50
|
-
if (h > maxIndex) maxIndex = h;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return { byIso, huesNeeded: maxIndex + 1 };
|
|
54
|
-
}
|