@moda-chart/core 0.1.2
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/LICENSE +21 -0
- package/README.md +25 -0
- package/dist/conformance.d.ts +40 -0
- package/dist/conformance.d.ts.map +1 -0
- package/dist/conformance.js +1608 -0
- package/dist/conformance.js.map +1 -0
- package/dist/core.d.ts +448 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +6026 -0
- package/dist/core.js.map +1 -0
- package/dist/geo.d.ts +85 -0
- package/dist/geo.d.ts.map +1 -0
- package/dist/geo.js +264 -0
- package/dist/geo.js.map +1 -0
- package/dist/geometry.d.ts +29 -0
- package/dist/geometry.d.ts.map +1 -0
- package/dist/geometry.js +92 -0
- package/dist/geometry.js.map +1 -0
- package/dist/hierarchy.d.ts +142 -0
- package/dist/hierarchy.d.ts.map +1 -0
- package/dist/hierarchy.js +422 -0
- package/dist/hierarchy.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/maps/world.d.ts +9 -0
- package/dist/maps/world.d.ts.map +1 -0
- package/dist/maps/world.js +9 -0
- package/dist/maps/world.js.map +1 -0
- package/dist/mount.d.ts +75 -0
- package/dist/mount.d.ts.map +1 -0
- package/dist/mount.js +795 -0
- package/dist/mount.js.map +1 -0
- package/dist/scales.d.ts +22 -0
- package/dist/scales.d.ts.map +1 -0
- package/dist/scales.js +118 -0
- package/dist/scales.js.map +1 -0
- package/dist/sparkline.d.ts +4 -0
- package/dist/sparkline.d.ts.map +1 -0
- package/dist/sparkline.js +62 -0
- package/dist/sparkline.js.map +1 -0
- package/dist/styles.css +989 -0
- package/dist/svg.d.ts +21 -0
- package/dist/svg.d.ts.map +1 -0
- package/dist/svg.js +1022 -0
- package/dist/svg.js.map +1 -0
- package/dist/text.d.ts +23 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +67 -0
- package/dist/text.js.map +1 -0
- package/dist/types.d.ts +1881 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/xml.d.ts +13 -0
- package/dist/xml.d.ts.map +1 -0
- package/dist/xml.js +109 -0
- package/dist/xml.js.map +1 -0
- package/package.json +44 -0
package/dist/geo.d.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 지도 지형 디코딩 + 투영 — 외부 의존성 없는 최소 구현.
|
|
3
|
+
*
|
|
4
|
+
* TopoJSON(transform 델타 인코딩 아크 포함)과 GeoJSON
|
|
5
|
+
* FeatureCollection/Feature를 받아 피처별 외곽 링으로 정규화하고,
|
|
6
|
+
* equirectangular / mercator 투영으로 SVG 좌표에 맞춘다.
|
|
7
|
+
* 지도 지오메트리는 임의 폴리곤이라 코어 hitTest가 rect 근사 대신
|
|
8
|
+
* 여기의 ray-casting(pointInRing)으로 해석한다.
|
|
9
|
+
*/
|
|
10
|
+
/** 지도 투영 방식 — mercator는 위도 ±85°로 클램프한다 */
|
|
11
|
+
export type MapProjection = "equirectangular" | "mercator";
|
|
12
|
+
/** [경도, 위도] 또는 투영 후 [x, y] 좌표 쌍 */
|
|
13
|
+
export type Coord = readonly [number, number];
|
|
14
|
+
/**
|
|
15
|
+
* 정규화된 지도 피처 — 디코딩 결과.
|
|
16
|
+
* code는 mapData와 조인하는 기본 키, keys는 이름/ISO 코드 등
|
|
17
|
+
* 추가 조인 후보(전부 소문자로 정규화됨)다.
|
|
18
|
+
*/
|
|
19
|
+
export interface MapFeature {
|
|
20
|
+
/** 조인 기본 키 — featureKey 결과 (world-atlas는 ISO numeric id) */
|
|
21
|
+
code: string;
|
|
22
|
+
/** 표시 이름 — properties.name */
|
|
23
|
+
name: string;
|
|
24
|
+
/** 조인 후보 키 목록 — code/iso_a2/iso_a3/name 등 소문자 정규화 */
|
|
25
|
+
keys: string[];
|
|
26
|
+
/** 폴리곤별 외곽 링 — 각 링은 [lon,lat] 좌표열 */
|
|
27
|
+
rings: Coord[][];
|
|
28
|
+
}
|
|
29
|
+
/** 투영 후 피처 — svg 좌표계 링/경로/앵커/경계상자 */
|
|
30
|
+
export interface FittedMapFeature {
|
|
31
|
+
feature: MapFeature;
|
|
32
|
+
/** svg 좌표계 링 */
|
|
33
|
+
rings: Coord[][];
|
|
34
|
+
path: string;
|
|
35
|
+
/** 최대 면적 링의 도형 중심 — 라벨/툴팁 앵커 */
|
|
36
|
+
cx: number;
|
|
37
|
+
cy: number;
|
|
38
|
+
/** 피처 경계상자 — hitTest 1차 필터 */
|
|
39
|
+
bbox: {
|
|
40
|
+
x0: number;
|
|
41
|
+
y0: number;
|
|
42
|
+
x1: number;
|
|
43
|
+
y1: number;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/** 피처 → 조인 키 추출 시그니처 — map.featureKey 옵션 */
|
|
47
|
+
export type MapFeatureKey = (f: {
|
|
48
|
+
id?: string | number;
|
|
49
|
+
properties?: Record<string, unknown>;
|
|
50
|
+
}) => string | number | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* 지형 소스 → 정규화 피처 목록.
|
|
53
|
+
*
|
|
54
|
+
* 지원 입력:
|
|
55
|
+
* - TopoJSON Topology (objects 중 object 지정 또는 첫 오브젝트)
|
|
56
|
+
* - GeoJSON FeatureCollection / Feature / Polygon / MultiPolygon
|
|
57
|
+
*/
|
|
58
|
+
export declare function decodeMapFeatures(source: unknown, object?: string, keyFn?: MapFeatureKey): MapFeature[];
|
|
59
|
+
/**
|
|
60
|
+
* 피처 + 추가 좌표(마커/라인)를 같은 투영 변환으로 rect에 맞춘다.
|
|
61
|
+
* toXY로 [lon,lat] 원시 좌표를 피처와 같은 스케일의 svg 좌표로 변환한다 —
|
|
62
|
+
* mapPoints/mapLines 레이어가 지역 폴리곤과 정확히 정렬된다.
|
|
63
|
+
*/
|
|
64
|
+
export declare function fitMapData(features: MapFeature[], proj: MapProjection, rect: {
|
|
65
|
+
x: number;
|
|
66
|
+
y: number;
|
|
67
|
+
w: number;
|
|
68
|
+
h: number;
|
|
69
|
+
}, extra?: Coord[]): {
|
|
70
|
+
features: FittedMapFeature[];
|
|
71
|
+
toXY: (c: Coord) => Coord;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* 피처들을 투영해 rect에 맞춘다 — 종횡비 유지 + 2% 여백 + 중앙 정렬.
|
|
75
|
+
* 각 피처에 svg 좌표 링/경로/중심/경계상자를 붙여 반환한다.
|
|
76
|
+
*/
|
|
77
|
+
export declare function fitMapFeatures(features: MapFeature[], proj: MapProjection, rect: {
|
|
78
|
+
x: number;
|
|
79
|
+
y: number;
|
|
80
|
+
w: number;
|
|
81
|
+
h: number;
|
|
82
|
+
}): FittedMapFeature[];
|
|
83
|
+
/** 링 내부 포함 여부 — 레이캐스팅 (짝수 교차=외부) */
|
|
84
|
+
export declare function pointInRing(x: number, y: number, ring: Coord[]): boolean;
|
|
85
|
+
//# sourceMappingURL=geo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geo.d.ts","sourceRoot":"","sources":["../src/geo.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,0CAA0C;AAC1C,MAAM,MAAM,aAAa,GAAG,iBAAiB,GAAG,UAAU,CAAC;AAE3D,mCAAmC;AACnC,MAAM,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE9C;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,qCAAqC;IACrC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC;CAClB;AAED,qCAAqC;AACrC,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,UAAU,CAAC;IACpB,gBAAgB;IAChB,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,8BAA8B;IAC9B,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1D;AAmBD,4CAA4C;AAC5C,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,EAAE;IAC9B,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC,KAAK,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AA8ElC;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,OAAO,EACf,MAAM,CAAC,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,aAAa,GACpB,UAAU,EAAE,CAkDd;AA6CD;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,UAAU,EAAE,EACtB,IAAI,EAAE,aAAa,EACnB,IAAI,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EACpD,KAAK,GAAE,KAAK,EAAO,GAClB;IAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAAC,IAAI,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,KAAK,CAAA;CAAE,CAsE7D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,UAAU,EAAE,EACtB,IAAI,EAAE,aAAa,EACnB,IAAI,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GACnD,gBAAgB,EAAE,CAEpB;AAED,oCAAoC;AACpC,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,OAAO,CASxE"}
|
package/dist/geo.js
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 지도 지형 디코딩 + 투영 — 외부 의존성 없는 최소 구현.
|
|
3
|
+
*
|
|
4
|
+
* TopoJSON(transform 델타 인코딩 아크 포함)과 GeoJSON
|
|
5
|
+
* FeatureCollection/Feature를 받아 피처별 외곽 링으로 정규화하고,
|
|
6
|
+
* equirectangular / mercator 투영으로 SVG 좌표에 맞춘다.
|
|
7
|
+
* 지도 지오메트리는 임의 폴리곤이라 코어 hitTest가 rect 근사 대신
|
|
8
|
+
* 여기의 ray-casting(pointInRing)으로 해석한다.
|
|
9
|
+
*/
|
|
10
|
+
/** 기본 키 후보 — id, ISO 코드, 이름을 모두 조인 후보로 등록한다 */
|
|
11
|
+
function featureKeysOf(f, keyFn) {
|
|
12
|
+
const p = f.properties ?? {};
|
|
13
|
+
const str = (v) => (v == null ? undefined : String(v));
|
|
14
|
+
const custom = keyFn?.(f);
|
|
15
|
+
const name = str(p.name) ?? str(p.NAME) ?? "";
|
|
16
|
+
const candidates = [
|
|
17
|
+
str(custom),
|
|
18
|
+
str(f.id),
|
|
19
|
+
str(p.iso_a2),
|
|
20
|
+
str(p.ISO_A2),
|
|
21
|
+
str(p.iso_a3),
|
|
22
|
+
str(p.ISO_A3),
|
|
23
|
+
str(p.adm0_a3),
|
|
24
|
+
str(p.ADM0_A3),
|
|
25
|
+
name || undefined,
|
|
26
|
+
];
|
|
27
|
+
const keys = [
|
|
28
|
+
...new Set(candidates.filter((x) => !!x).map((x) => x.toLowerCase())),
|
|
29
|
+
];
|
|
30
|
+
const code = str(custom) ?? str(f.id) ?? name;
|
|
31
|
+
return { code: code ?? "", name, keys };
|
|
32
|
+
}
|
|
33
|
+
/** TopoJSON 아크를 델타 디코딩 — transform이 있으면 scale/translate 적용 */
|
|
34
|
+
function decodeTopoArcs(topo) {
|
|
35
|
+
const tf = topo.transform;
|
|
36
|
+
return (topo.arcs ?? []).map((arc) => {
|
|
37
|
+
let x = 0;
|
|
38
|
+
let y = 0;
|
|
39
|
+
return arc.map((p) => {
|
|
40
|
+
x += p[0] ?? 0;
|
|
41
|
+
y += p[1] ?? 0;
|
|
42
|
+
return tf
|
|
43
|
+
? [x * tf.scale[0] + tf.translate[0], y * tf.scale[1] + tf.translate[1]]
|
|
44
|
+
: [x, y];
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/** 아크 인덱스열을 하나의 링으로 스티칭 — 음수 인덱스는 ~i 아크의 역순 */
|
|
49
|
+
function stitchRing(arcs, idxs) {
|
|
50
|
+
const out = [];
|
|
51
|
+
for (const raw of idxs) {
|
|
52
|
+
const arc = arcs[raw < 0 ? ~raw : raw] ?? [];
|
|
53
|
+
const pts = raw < 0 ? [...arc].reverse() : arc;
|
|
54
|
+
// 인접 아크의 공유 끝점은 중복이므로 두 번째 아크부터 첫 점을 버린다
|
|
55
|
+
for (let i = out.length ? 1 : 0; i < pts.length; i++)
|
|
56
|
+
out.push(pts[i]);
|
|
57
|
+
}
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
/** TopoJSON 지오메트리 → 외곽 링 목록 (Polygon/MultiPolygon만) */
|
|
61
|
+
function topoGeomRings(g, arcs) {
|
|
62
|
+
if (g.type === "Polygon")
|
|
63
|
+
return g.arcs.map((r) => stitchRing(arcs, r));
|
|
64
|
+
if (g.type === "MultiPolygon")
|
|
65
|
+
return g.arcs.flatMap((poly) => poly.map((r) => stitchRing(arcs, r)));
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
/** GeoJSON 지오메트리 → 외곽 링 목록 (외곽 링만 사용, 구멍 링 포함) */
|
|
69
|
+
function geoGeomRings(g) {
|
|
70
|
+
if (g.type === "Polygon")
|
|
71
|
+
return (g.coordinates ?? []);
|
|
72
|
+
if (g.type === "MultiPolygon")
|
|
73
|
+
return (g.coordinates ?? []).flatMap((poly) => poly);
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 지형 소스 → 정규화 피처 목록.
|
|
78
|
+
*
|
|
79
|
+
* 지원 입력:
|
|
80
|
+
* - TopoJSON Topology (objects 중 object 지정 또는 첫 오브젝트)
|
|
81
|
+
* - GeoJSON FeatureCollection / Feature / Polygon / MultiPolygon
|
|
82
|
+
*/
|
|
83
|
+
export function decodeMapFeatures(source, object, keyFn) {
|
|
84
|
+
if (!source || typeof source !== "object")
|
|
85
|
+
return [];
|
|
86
|
+
const src = source;
|
|
87
|
+
if (src.type === "Topology") {
|
|
88
|
+
const arcs = decodeTopoArcs(src);
|
|
89
|
+
const objects = src.objects ?? {};
|
|
90
|
+
const target = object ? objects[object] : Object.values(objects)[0];
|
|
91
|
+
const geoms = target?.type === "GeometryCollection"
|
|
92
|
+
? (target.geometries ?? [])
|
|
93
|
+
: target
|
|
94
|
+
? [target]
|
|
95
|
+
: [];
|
|
96
|
+
return geoms.map((g) => ({
|
|
97
|
+
...featureKeysOf(g, keyFn),
|
|
98
|
+
rings: topoGeomRings(g, arcs),
|
|
99
|
+
}));
|
|
100
|
+
}
|
|
101
|
+
const feats = src.type === "FeatureCollection"
|
|
102
|
+
? (src.features ?? [])
|
|
103
|
+
: src.type === "Feature"
|
|
104
|
+
? [src]
|
|
105
|
+
: src.type === "Polygon" || src.type === "MultiPolygon"
|
|
106
|
+
? [
|
|
107
|
+
{
|
|
108
|
+
geometry: src,
|
|
109
|
+
},
|
|
110
|
+
]
|
|
111
|
+
: [];
|
|
112
|
+
return feats
|
|
113
|
+
.map((f) => ({
|
|
114
|
+
...featureKeysOf(f, keyFn),
|
|
115
|
+
rings: geoGeomRings(f.geometry ?? {}),
|
|
116
|
+
}))
|
|
117
|
+
.filter((f) => f.rings.length > 0);
|
|
118
|
+
}
|
|
119
|
+
// ── 투영 + 플롯 맞춤 ─────────────────────────────────────────
|
|
120
|
+
/** 경도/위도 → 투영 좌표 (정규화 전) — mercator는 ±85° 클램프 */
|
|
121
|
+
function projectPoint(proj, lon, lat) {
|
|
122
|
+
if (proj === "mercator") {
|
|
123
|
+
const c = (Math.max(-85, Math.min(85, lat)) * Math.PI) / 180;
|
|
124
|
+
return [lon, (-Math.log(Math.tan(Math.PI / 4 + c / 2)) * 180) / Math.PI];
|
|
125
|
+
}
|
|
126
|
+
return [lon, -lat];
|
|
127
|
+
}
|
|
128
|
+
/** 링의 도형 중심(면적 가중 centroid) — 퇴화하면 경계상자 중심 */
|
|
129
|
+
function ringCentroid(ring) {
|
|
130
|
+
let a = 0;
|
|
131
|
+
let cx = 0;
|
|
132
|
+
let cy = 0;
|
|
133
|
+
for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
|
|
134
|
+
const [xi, yi] = ring[i];
|
|
135
|
+
const [xj, yj] = ring[j];
|
|
136
|
+
const cr = xi * yj - xj * yi;
|
|
137
|
+
a += cr;
|
|
138
|
+
cx += (xi + xj) * cr;
|
|
139
|
+
cy += (yi + yj) * cr;
|
|
140
|
+
}
|
|
141
|
+
if (Math.abs(a) < 1e-9) {
|
|
142
|
+
let x0 = Infinity;
|
|
143
|
+
let y0 = Infinity;
|
|
144
|
+
let x1 = -Infinity;
|
|
145
|
+
let y1 = -Infinity;
|
|
146
|
+
for (const [x, y] of ring) {
|
|
147
|
+
if (x < x0)
|
|
148
|
+
x0 = x;
|
|
149
|
+
if (y < y0)
|
|
150
|
+
y0 = y;
|
|
151
|
+
if (x > x1)
|
|
152
|
+
x1 = x;
|
|
153
|
+
if (y > y1)
|
|
154
|
+
y1 = y;
|
|
155
|
+
}
|
|
156
|
+
return [(x0 + x1) / 2, (y0 + y1) / 2];
|
|
157
|
+
}
|
|
158
|
+
a *= 0.5;
|
|
159
|
+
return [cx / (6 * a), cy / (6 * a)];
|
|
160
|
+
}
|
|
161
|
+
const r2 = (n) => Number(n.toFixed(2));
|
|
162
|
+
/**
|
|
163
|
+
* 피처 + 추가 좌표(마커/라인)를 같은 투영 변환으로 rect에 맞춘다.
|
|
164
|
+
* toXY로 [lon,lat] 원시 좌표를 피처와 같은 스케일의 svg 좌표로 변환한다 —
|
|
165
|
+
* mapPoints/mapLines 레이어가 지역 폴리곤과 정확히 정렬된다.
|
|
166
|
+
*/
|
|
167
|
+
export function fitMapData(features, proj, rect, extra = []) {
|
|
168
|
+
const projected = features.map((f) => ({
|
|
169
|
+
f,
|
|
170
|
+
rings: f.rings.map((ring) => ring.map(([lo, la]) => projectPoint(proj, lo, la))),
|
|
171
|
+
}));
|
|
172
|
+
const pExtra = extra.map(([lo, la]) => projectPoint(proj, lo, la));
|
|
173
|
+
let x0 = Infinity;
|
|
174
|
+
let y0 = Infinity;
|
|
175
|
+
let x1 = -Infinity;
|
|
176
|
+
let y1 = -Infinity;
|
|
177
|
+
const extend = (x, y) => {
|
|
178
|
+
if (x < x0)
|
|
179
|
+
x0 = x;
|
|
180
|
+
if (y < y0)
|
|
181
|
+
y0 = y;
|
|
182
|
+
if (x > x1)
|
|
183
|
+
x1 = x;
|
|
184
|
+
if (y > y1)
|
|
185
|
+
y1 = y;
|
|
186
|
+
};
|
|
187
|
+
for (const p of projected)
|
|
188
|
+
for (const ring of p.rings)
|
|
189
|
+
for (const [x, y] of ring)
|
|
190
|
+
extend(x, y);
|
|
191
|
+
for (const [x, y] of pExtra)
|
|
192
|
+
extend(x, y);
|
|
193
|
+
if (!isFinite(x0) || x1 - x0 <= 0 || y1 - y0 <= 0)
|
|
194
|
+
return { features: [], toXY: () => [0, 0] };
|
|
195
|
+
const margin = 0.02;
|
|
196
|
+
const aw = rect.w * (1 - margin * 2);
|
|
197
|
+
const ah = rect.h * (1 - margin * 2);
|
|
198
|
+
const s = Math.min(aw / (x1 - x0), ah / (y1 - y0));
|
|
199
|
+
const ox = rect.x + (rect.w - (x1 - x0) * s) / 2 - x0 * s;
|
|
200
|
+
const oy = rect.y + (rect.h - (y1 - y0) * s) / 2 - y0 * s;
|
|
201
|
+
const xy = ([x, y]) => [r2(x * s + ox), r2(y * s + oy)];
|
|
202
|
+
/** lon/lat → 투영 → 스케일 변환 */
|
|
203
|
+
const toXY = (c) => xy(projectPoint(proj, c[0], c[1]));
|
|
204
|
+
const fitted = projected.map(({ f, rings }) => {
|
|
205
|
+
const prs = rings.map((ring) => ring.map(xy));
|
|
206
|
+
let bx0 = Infinity;
|
|
207
|
+
let by0 = Infinity;
|
|
208
|
+
let bx1 = -Infinity;
|
|
209
|
+
let by1 = -Infinity;
|
|
210
|
+
let largest = 0;
|
|
211
|
+
let big = prs[0] ?? [];
|
|
212
|
+
const parts = [];
|
|
213
|
+
for (const ring of prs) {
|
|
214
|
+
let la = 0;
|
|
215
|
+
for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
|
|
216
|
+
la += ring[j][0] * ring[i][1] - ring[i][0] * ring[j][1];
|
|
217
|
+
}
|
|
218
|
+
if (Math.abs(la) > largest) {
|
|
219
|
+
largest = Math.abs(la);
|
|
220
|
+
big = ring;
|
|
221
|
+
}
|
|
222
|
+
for (const [x, y] of ring) {
|
|
223
|
+
if (x < bx0)
|
|
224
|
+
bx0 = x;
|
|
225
|
+
if (y < by0)
|
|
226
|
+
by0 = y;
|
|
227
|
+
if (x > bx1)
|
|
228
|
+
bx1 = x;
|
|
229
|
+
if (y > by1)
|
|
230
|
+
by1 = y;
|
|
231
|
+
}
|
|
232
|
+
parts.push(`M${ring.map(([x, y]) => `${r2(x)} ${r2(y)}`).join("L")} Z`);
|
|
233
|
+
}
|
|
234
|
+
const [cx, cy] = ringCentroid(big);
|
|
235
|
+
return {
|
|
236
|
+
feature: f,
|
|
237
|
+
rings: prs,
|
|
238
|
+
path: parts.join(" "),
|
|
239
|
+
cx: r2(cx),
|
|
240
|
+
cy: r2(cy),
|
|
241
|
+
bbox: { x0: bx0, y0: by0, x1: bx1, y1: by1 },
|
|
242
|
+
};
|
|
243
|
+
});
|
|
244
|
+
return { features: fitted, toXY };
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* 피처들을 투영해 rect에 맞춘다 — 종횡비 유지 + 2% 여백 + 중앙 정렬.
|
|
248
|
+
* 각 피처에 svg 좌표 링/경로/중심/경계상자를 붙여 반환한다.
|
|
249
|
+
*/
|
|
250
|
+
export function fitMapFeatures(features, proj, rect) {
|
|
251
|
+
return fitMapData(features, proj, rect).features;
|
|
252
|
+
}
|
|
253
|
+
/** 링 내부 포함 여부 — 레이캐스팅 (짝수 교차=외부) */
|
|
254
|
+
export function pointInRing(x, y, ring) {
|
|
255
|
+
let inside = false;
|
|
256
|
+
for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
|
|
257
|
+
const [xi, yi] = ring[i];
|
|
258
|
+
const [xj, yj] = ring[j];
|
|
259
|
+
if (yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi)
|
|
260
|
+
inside = !inside;
|
|
261
|
+
}
|
|
262
|
+
return inside;
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=geo.js.map
|
package/dist/geo.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geo.js","sourceRoot":"","sources":["../src/geo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SVG 경로 빌더 — 순수 함수.
|
|
3
|
+
*/
|
|
4
|
+
export interface XY {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
}
|
|
8
|
+
/** M/L 직선 패스 */
|
|
9
|
+
export declare function linePath(pts: readonly XY[]): string;
|
|
10
|
+
/**
|
|
11
|
+
* 계단형(step) 패스 — 각 구간 중간 x에서 수직으로 값이 바뀐다
|
|
12
|
+
* (Highcharts 계열의 middle step).
|
|
13
|
+
*/
|
|
14
|
+
export declare function stepPath(pts: readonly XY[]): string;
|
|
15
|
+
/**
|
|
16
|
+
* 스플라인 패스 — Catmull-Rom → cubic Bézier 변환.
|
|
17
|
+
* 포인트를 통과하는 부드러운 곡선을 만든다.
|
|
18
|
+
*/
|
|
19
|
+
export declare function splinePath(pts: readonly XY[]): string;
|
|
20
|
+
/** 중심축 대칭 사다리꼴 패스 — funnel/pyramid 세그먼트 */
|
|
21
|
+
export declare function bandPath(cx: number, y0: number, y1: number, halfTop: number, halfBottom: number): string;
|
|
22
|
+
/** 영역 패스 — 선 + 기저선으로 닫기 */
|
|
23
|
+
export declare function areaPath(pts: readonly XY[], baseline: number): string;
|
|
24
|
+
/**
|
|
25
|
+
* 파이/도넛 조각 패스 — 시계 방향.
|
|
26
|
+
* a0,a1은 라디안 (0 = 12시 방향 기준으로 보정해서 넘긴다).
|
|
27
|
+
*/
|
|
28
|
+
export declare function arcPath(cx: number, cy: number, r0: number, r1: number, a0: number, a1: number): string;
|
|
29
|
+
//# sourceMappingURL=geometry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../src/geometry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,WAAW,EAAE;IACjB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,gBAAgB;AAChB,wBAAgB,QAAQ,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,GAAG,MAAM,CAGnD;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,GAAG,MAAM,CAUnD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,GAAG,MAAM,CAkBrD;AAED,2CAA2C;AAC3C,wBAAgB,QAAQ,CACtB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,MAAM,CAKR;AAED,2BAA2B;AAC3B,wBAAgB,QAAQ,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQrE;AAMD;;;GAGG;AACH,wBAAgB,OAAO,CACrB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,GACT,MAAM,CAsBR"}
|
package/dist/geometry.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SVG 경로 빌더 — 순수 함수.
|
|
3
|
+
*/
|
|
4
|
+
const r2 = (n) => Number(n.toFixed(2));
|
|
5
|
+
/** M/L 직선 패스 */
|
|
6
|
+
export function linePath(pts) {
|
|
7
|
+
if (!pts.length)
|
|
8
|
+
return "";
|
|
9
|
+
return pts.map((p, i) => `${i ? "L" : "M"}${r2(p.x)} ${r2(p.y)}`).join(" ");
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* 계단형(step) 패스 — 각 구간 중간 x에서 수직으로 값이 바뀐다
|
|
13
|
+
* (Highcharts 계열의 middle step).
|
|
14
|
+
*/
|
|
15
|
+
export function stepPath(pts) {
|
|
16
|
+
if (!pts.length)
|
|
17
|
+
return "";
|
|
18
|
+
const out = [`M${r2(pts[0].x)} ${r2(pts[0].y)}`];
|
|
19
|
+
for (let i = 1; i < pts.length; i++) {
|
|
20
|
+
const a = pts[i - 1];
|
|
21
|
+
const b = pts[i];
|
|
22
|
+
const mid = (a.x + b.x) / 2;
|
|
23
|
+
out.push(`L${r2(mid)} ${r2(a.y)}`, `L${r2(mid)} ${r2(b.y)}`, `L${r2(b.x)} ${r2(b.y)}`);
|
|
24
|
+
}
|
|
25
|
+
return out.join(" ");
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 스플라인 패스 — Catmull-Rom → cubic Bézier 변환.
|
|
29
|
+
* 포인트를 통과하는 부드러운 곡선을 만든다.
|
|
30
|
+
*/
|
|
31
|
+
export function splinePath(pts) {
|
|
32
|
+
if (!pts.length)
|
|
33
|
+
return "";
|
|
34
|
+
if (pts.length < 3)
|
|
35
|
+
return linePath(pts);
|
|
36
|
+
const out = [`M${r2(pts[0].x)} ${r2(pts[0].y)}`];
|
|
37
|
+
for (let i = 0; i < pts.length - 1; i++) {
|
|
38
|
+
const p0 = pts[i - 1] ?? pts[i];
|
|
39
|
+
const p1 = pts[i];
|
|
40
|
+
const p2 = pts[i + 1];
|
|
41
|
+
const p3 = pts[i + 2] ?? p2;
|
|
42
|
+
const c1x = p1.x + (p2.x - p0.x) / 6;
|
|
43
|
+
const c1y = p1.y + (p2.y - p0.y) / 6;
|
|
44
|
+
const c2x = p2.x - (p3.x - p1.x) / 6;
|
|
45
|
+
const c2y = p2.y - (p3.y - p1.y) / 6;
|
|
46
|
+
out.push(`C${r2(c1x)} ${r2(c1y)} ${r2(c2x)} ${r2(c2y)} ${r2(p2.x)} ${r2(p2.y)}`);
|
|
47
|
+
}
|
|
48
|
+
return out.join(" ");
|
|
49
|
+
}
|
|
50
|
+
/** 중심축 대칭 사다리꼴 패스 — funnel/pyramid 세그먼트 */
|
|
51
|
+
export function bandPath(cx, y0, y1, halfTop, halfBottom) {
|
|
52
|
+
return (`M${r2(cx - halfTop)} ${r2(y0)} L${r2(cx + halfTop)} ${r2(y0)} ` +
|
|
53
|
+
`L${r2(cx + halfBottom)} ${r2(y1)} L${r2(cx - halfBottom)} ${r2(y1)} Z`);
|
|
54
|
+
}
|
|
55
|
+
/** 영역 패스 — 선 + 기저선으로 닫기 */
|
|
56
|
+
export function areaPath(pts, baseline) {
|
|
57
|
+
if (!pts.length)
|
|
58
|
+
return "";
|
|
59
|
+
const first = pts[0];
|
|
60
|
+
const last = pts[pts.length - 1];
|
|
61
|
+
return (linePath(pts) +
|
|
62
|
+
` L${r2(last.x)} ${r2(baseline)} L${r2(first.x)} ${r2(baseline)} Z`);
|
|
63
|
+
}
|
|
64
|
+
function polar(cx, cy, r, angle) {
|
|
65
|
+
return { x: cx + r * Math.cos(angle), y: cy + r * Math.sin(angle) };
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* 파이/도넛 조각 패스 — 시계 방향.
|
|
69
|
+
* a0,a1은 라디안 (0 = 12시 방향 기준으로 보정해서 넘긴다).
|
|
70
|
+
*/
|
|
71
|
+
export function arcPath(cx, cy, r0, r1, a0, a1) {
|
|
72
|
+
const full = Math.PI * 2;
|
|
73
|
+
let end = a1;
|
|
74
|
+
if (end - a0 >= full - 1e-6)
|
|
75
|
+
end = a0 + full - 1e-4;
|
|
76
|
+
if (end <= a0)
|
|
77
|
+
return "";
|
|
78
|
+
const large = end - a0 > Math.PI ? 1 : 0;
|
|
79
|
+
const p00 = polar(cx, cy, r1, a0);
|
|
80
|
+
const p01 = polar(cx, cy, r1, end);
|
|
81
|
+
if (r0 <= 0) {
|
|
82
|
+
return (`M${r2(cx)} ${r2(cy)} L${r2(p00.x)} ${r2(p00.y)} ` +
|
|
83
|
+
`A${r2(r1)} ${r2(r1)} 0 ${large} 1 ${r2(p01.x)} ${r2(p01.y)} Z`);
|
|
84
|
+
}
|
|
85
|
+
const p10 = polar(cx, cy, r0, end);
|
|
86
|
+
const p11 = polar(cx, cy, r0, a0);
|
|
87
|
+
return (`M${r2(p00.x)} ${r2(p00.y)} ` +
|
|
88
|
+
`A${r2(r1)} ${r2(r1)} 0 ${large} 1 ${r2(p01.x)} ${r2(p01.y)} ` +
|
|
89
|
+
`L${r2(p10.x)} ${r2(p10.y)} ` +
|
|
90
|
+
`A${r2(r0)} ${r2(r0)} 0 ${large} 0 ${r2(p11.x)} ${r2(p11.y)} Z`);
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=geometry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geometry.js","sourceRoot":"","sources":["../src/geometry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 계층/플로우 차트 레이아웃 — 외부 의존성 없는 순수 함수.
|
|
3
|
+
*
|
|
4
|
+
* - normalizeTree: ChartTreeNode 입력을 값 해소·인덱스 부여된 TreeDatum으로
|
|
5
|
+
* - layoutTreemap: squarified treemap (리프 rect 목록)
|
|
6
|
+
* - layoutSunburst: partition (깊이별 링 + 값 비례 각도)
|
|
7
|
+
* - layoutSankey: 최장 경로 열 배정 + 균일 두께 베지어 리본
|
|
8
|
+
* - layoutChord: 그룹 아크 서브디비전 + 중심 통과 리본
|
|
9
|
+
*
|
|
10
|
+
* 모든 결과는 svg 좌표계. 각도는 라디안, 0 = 12시 방향(-π/2 기준은
|
|
11
|
+
* polar()가 처리한다).
|
|
12
|
+
*/
|
|
13
|
+
import type { ChartFlowLink, ChartTreeNode } from "./types.js";
|
|
14
|
+
/** 값이 해소된 트리 노드 — leaf는 입력 value, 내부 노드는 자식 합계 */
|
|
15
|
+
export interface TreeDatum {
|
|
16
|
+
name: string;
|
|
17
|
+
value: number;
|
|
18
|
+
children: TreeDatum[];
|
|
19
|
+
/** DFS 플랫 인덱스 — 포커스/선택/툴팁 식별자 */
|
|
20
|
+
index: number;
|
|
21
|
+
depth: number;
|
|
22
|
+
/** 최상위 조상의 roots 배열 인덱스 — 색/범례 그룹 */
|
|
23
|
+
root: number;
|
|
24
|
+
/** 렌더 키용 경로 — 중복 이름 방지로 인덱스 접미사 포함 */
|
|
25
|
+
path: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 입력 트리를 정규화 — value 없는 노드는 children 합계,
|
|
29
|
+
* 둘 다 없는 리프는 0. DFS 순서로 index를 부여한다.
|
|
30
|
+
*/
|
|
31
|
+
export declare function normalizeTree(nodes: readonly ChartTreeNode[]): TreeDatum[];
|
|
32
|
+
/** 모든 노드를 DFS 순서로 평탄화한다 */
|
|
33
|
+
export declare function flattenTree(roots: TreeDatum[]): TreeDatum[];
|
|
34
|
+
export interface Rect {
|
|
35
|
+
x: number;
|
|
36
|
+
y: number;
|
|
37
|
+
w: number;
|
|
38
|
+
h: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* squarified treemap — 리프 노드의 rect만 반환한다.
|
|
42
|
+
* 내부 노드 rect는 자식들의 합집합이라 별도 렌더하지 않는다.
|
|
43
|
+
*/
|
|
44
|
+
export declare function layoutTreemap(roots: TreeDatum[], rect: Rect): {
|
|
45
|
+
node: TreeDatum;
|
|
46
|
+
rect: Rect;
|
|
47
|
+
}[];
|
|
48
|
+
export interface SunburstCell {
|
|
49
|
+
node: TreeDatum;
|
|
50
|
+
a0: number;
|
|
51
|
+
a1: number;
|
|
52
|
+
r0: number;
|
|
53
|
+
r1: number;
|
|
54
|
+
}
|
|
55
|
+
/** 극좌표 → svg 좌표 — 0 rad = 12시 방향 */
|
|
56
|
+
export declare function polar(cx: number, cy: number, r: number, a: number): readonly [number, number];
|
|
57
|
+
/** 환형 섹터 path — r0>0이면 도넛 조각, 0이면 부채꼴 */
|
|
58
|
+
export declare function arcSector(cx: number, cy: number, r0: number, r1: number, a0: number, a1: number): string;
|
|
59
|
+
/**
|
|
60
|
+
* sunburst partition — 깊이 d 노드는 링 [d*th, (d+1)*th],
|
|
61
|
+
* 각도는 부모 범위 안에서 자식 값 비례로 분할한다.
|
|
62
|
+
*/
|
|
63
|
+
export declare function layoutSunburst(roots: TreeDatum[], cx: number, cy: number, maxR: number): SunburstCell[];
|
|
64
|
+
export interface SankeyNodeLayout {
|
|
65
|
+
name: string;
|
|
66
|
+
index: number;
|
|
67
|
+
value: number;
|
|
68
|
+
layer: number;
|
|
69
|
+
x: number;
|
|
70
|
+
y: number;
|
|
71
|
+
w: number;
|
|
72
|
+
h: number;
|
|
73
|
+
}
|
|
74
|
+
export interface SankeyLinkLayout {
|
|
75
|
+
index: number;
|
|
76
|
+
sourceIndex: number;
|
|
77
|
+
targetIndex: number;
|
|
78
|
+
value: number;
|
|
79
|
+
path: string;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* sankey 레이아웃 — 노드 열은 source로부터의 최장 경로,
|
|
83
|
+
* 노드 높이는 유량 비례(전 열 균일 스케일), 리본은 3차 베지어.
|
|
84
|
+
* 순환 참조는 n회 완화 후 자연스럽게 수렴하지 않는 열에 배치된다.
|
|
85
|
+
*/
|
|
86
|
+
export declare function layoutSankey(links: readonly ChartFlowLink[], rect: Rect, nodeWidth?: number, nodeGap?: number): {
|
|
87
|
+
nodes: SankeyNodeLayout[];
|
|
88
|
+
links: SankeyLinkLayout[];
|
|
89
|
+
};
|
|
90
|
+
export interface ChordGroupLayout {
|
|
91
|
+
index: number;
|
|
92
|
+
name: string;
|
|
93
|
+
value: number;
|
|
94
|
+
a0: number;
|
|
95
|
+
a1: number;
|
|
96
|
+
path: string;
|
|
97
|
+
lx: number;
|
|
98
|
+
ly: number;
|
|
99
|
+
}
|
|
100
|
+
export interface ChordRibbonLayout {
|
|
101
|
+
index: number;
|
|
102
|
+
sourceIndex: number;
|
|
103
|
+
targetIndex: number;
|
|
104
|
+
value: number;
|
|
105
|
+
valueBack: number;
|
|
106
|
+
path: string;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* chord 레이아웃 — 그룹 아크는 행 합 비례, 각 그룹 안에서
|
|
110
|
+
* matrix[i][j] 비례 서브아크를 만들고 (i,j) 리본은 그룹 i의 j-서브아크와
|
|
111
|
+
* 그룹 j의 i-서브아크를 중심을 지나는 2차 곡선으로 잇는다.
|
|
112
|
+
*/
|
|
113
|
+
export declare function layoutChord(matrix: readonly (readonly number[])[], labels: readonly string[], cx: number, cy: number, r: number, groupThickness?: number, padAngle?: number): {
|
|
114
|
+
groups: ChordGroupLayout[];
|
|
115
|
+
ribbons: ChordRibbonLayout[];
|
|
116
|
+
};
|
|
117
|
+
export interface OrgNodeLayout {
|
|
118
|
+
node: TreeDatum;
|
|
119
|
+
x: number;
|
|
120
|
+
y: number;
|
|
121
|
+
w: number;
|
|
122
|
+
h: number;
|
|
123
|
+
/** 노드 중심 — 라벨/앵커 */
|
|
124
|
+
cx: number;
|
|
125
|
+
cy: number;
|
|
126
|
+
}
|
|
127
|
+
export interface OrgLinkLayout {
|
|
128
|
+
/** 부모/자식의 TreeDatum.index */
|
|
129
|
+
from: number;
|
|
130
|
+
to: number;
|
|
131
|
+
/** 엘보 커넥터 — 부모 하단 중심 → 중간 y → 자식 상단 중심 */
|
|
132
|
+
path: string;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* 조직도 레이아웃 — 리프를 DFS 순서로 균등 배치하고 부모는 자식의
|
|
136
|
+
* 중심 위에 둔다 (tidy tree). 깊이별로 같은 y 행을 공유한다.
|
|
137
|
+
*/
|
|
138
|
+
export declare function layoutOrganization(roots: TreeDatum[], rect: Rect): {
|
|
139
|
+
nodes: OrgNodeLayout[];
|
|
140
|
+
links: OrgLinkLayout[];
|
|
141
|
+
};
|
|
142
|
+
//# sourceMappingURL=hierarchy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hierarchy.d.ts","sourceRoot":"","sources":["../src/hierarchy.ts"],"names":[],"mappings":"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"}
|