@knowvah/dot-engine 2.6.12 → 2.7.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/README.md +1 -1
- package/dist/api.js +18 -4
- package/dist/api.js.map +3 -3
- package/dist/common/attr-get.d.ts +30 -0
- package/dist/common/attr-get.d.ts.map +1 -0
- package/dist/common/htmltable-emit-fill.d.ts +20 -2
- package/dist/common/htmltable-emit-fill.d.ts.map +1 -1
- package/dist/common/htmltable-emit.d.ts.map +1 -1
- package/dist/common/htmltable-lex-expat.d.ts.map +1 -1
- package/dist/common/htmltable-pos-runs.d.ts +7 -4
- package/dist/common/htmltable-pos-runs.d.ts.map +1 -1
- package/dist/common/htmltable.d.ts.map +1 -1
- package/dist/common/libm-trig.d.ts +5 -0
- package/dist/common/libm-trig.d.ts.map +1 -0
- package/dist/common/make-label.d.ts.map +1 -1
- package/dist/common/multicolor.d.ts +21 -13
- package/dist/common/multicolor.d.ts.map +1 -1
- package/dist/common/poly-gencode.d.ts +1 -2
- package/dist/common/poly-gencode.d.ts.map +1 -1
- package/dist/common/poly-init.d.ts +2 -12
- package/dist/common/poly-init.d.ts.map +1 -1
- package/dist/common/splines-clip.d.ts +7 -0
- package/dist/common/splines-clip.d.ts.map +1 -1
- package/dist/gvc/context.d.ts +6 -0
- package/dist/gvc/context.d.ts.map +1 -1
- package/dist/gvc/device-cluster.d.ts +15 -0
- package/dist/gvc/device-cluster.d.ts.map +1 -1
- package/dist/gvc/device.d.ts.map +1 -1
- package/dist/gvc/first-layer.d.ts +9 -0
- package/dist/gvc/first-layer.d.ts.map +1 -0
- package/dist/gvc/gvrender-set-style.d.ts +28 -0
- package/dist/gvc/gvrender-set-style.d.ts.map +1 -0
- package/dist/gvc/usershape.d.ts +18 -0
- package/dist/gvc/usershape.d.ts.map +1 -1
- package/dist/index.js +2478 -912
- package/dist/index.js.map +4 -4
- package/dist/layout/dot/compound.d.ts.map +1 -1
- package/dist/layout/dot/edge-route-clip.d.ts +14 -4
- package/dist/layout/dot/edge-route-clip.d.ts.map +1 -1
- package/dist/layout/dot/edge-route-routing.d.ts.map +1 -1
- package/dist/layout/dot/graph-label.d.ts.map +1 -1
- package/dist/layout/neato/__fixtures__/dijkstra-f.d.ts +11 -0
- package/dist/layout/neato/__fixtures__/dijkstra-f.d.ts.map +1 -0
- package/dist/layout/neato/__fixtures__/hier-imds.d.ts +36 -0
- package/dist/layout/neato/__fixtures__/hier-imds.d.ts.map +1 -0
- package/dist/layout/neato/__fixtures__/hier-majorization.d.ts +32 -0
- package/dist/layout/neato/__fixtures__/hier-majorization.d.ts.map +1 -0
- package/dist/layout/neato/cdt-surface.d.ts.map +1 -1
- package/dist/layout/neato/compute-hierarchy.d.ts +24 -0
- package/dist/layout/neato/compute-hierarchy.d.ts.map +1 -0
- package/dist/layout/neato/conjgrad-mkernel.d.ts +20 -0
- package/dist/layout/neato/conjgrad-mkernel.d.ts.map +1 -0
- package/dist/layout/neato/conjgrad.d.ts +19 -0
- package/dist/layout/neato/conjgrad.d.ts.map +1 -1
- package/dist/layout/neato/constrained-majorization.d.ts +26 -0
- package/dist/layout/neato/constrained-majorization.d.ts.map +1 -0
- package/dist/layout/neato/dijkstra.d.ts +33 -16
- package/dist/layout/neato/dijkstra.d.ts.map +1 -1
- package/dist/layout/neato/gts-triangle.d.ts +14 -0
- package/dist/layout/neato/gts-triangle.d.ts.map +1 -0
- package/dist/layout/neato/init.d.ts +2 -12
- package/dist/layout/neato/init.d.ts.map +1 -1
- package/dist/layout/neato/kkutils.d.ts +20 -0
- package/dist/layout/neato/kkutils.d.ts.map +1 -0
- package/dist/layout/neato/make-graph-data.d.ts +43 -0
- package/dist/layout/neato/make-graph-data.d.ts.map +1 -0
- package/dist/layout/neato/matrix-ops.d.ts +46 -0
- package/dist/layout/neato/matrix-ops.d.ts.map +1 -1
- package/dist/layout/neato/opt-arrangement.d.ts +20 -0
- package/dist/layout/neato/opt-arrangement.d.ts.map +1 -0
- package/dist/layout/neato/quad-prog-solve.d.ts +44 -0
- package/dist/layout/neato/quad-prog-solve.d.ts.map +1 -0
- package/dist/layout/neato/smart-ini-x.d.ts +9 -0
- package/dist/layout/neato/smart-ini-x.d.ts.map +1 -0
- package/dist/layout/neato/splines.d.ts +1 -1
- package/dist/layout/neato/splines.d.ts.map +1 -1
- package/dist/layout/neato/start.d.ts +4 -1
- package/dist/layout/neato/start.d.ts.map +1 -1
- package/dist/layout/neato/stress.d.ts +8 -0
- package/dist/layout/neato/stress.d.ts.map +1 -1
- package/dist/model/edge.d.ts +1 -1
- package/dist/model/edge.d.ts.map +1 -1
- package/dist/model/lazy-attrs.d.ts +10 -0
- package/dist/model/lazy-attrs.d.ts.map +1 -0
- package/dist/model/node.d.ts +1 -1
- package/dist/model/node.d.ts.map +1 -1
- package/dist/ortho/index.d.ts.map +1 -1
- package/dist/render/dot/edge-draw.d.ts +1 -1
- package/dist/render/dot/edge-draw.d.ts.map +1 -1
- package/dist/render/svg-multicolor.d.ts +2 -2
- package/dist/render/svg-multicolor.d.ts.map +1 -1
- package/dist/render.js +2358 -792
- package/dist/render.js.map +4 -4
- package/package.json +1 -1
- package/src/common/attr-get.ts +46 -0
- package/src/common/graph-init.ts +1 -1
- package/src/common/htmltable-emit-fill.ts +56 -11
- package/src/common/htmltable-emit.ts +4 -3
- package/src/common/htmltable-lex-expat.ts +21 -3
- package/src/common/htmltable-pos-runs.ts +11 -6
- package/src/common/htmltable.ts +28 -116
- package/src/common/libm-trig.ts +43 -0
- package/src/common/make-label.ts +14 -2
- package/src/common/multicolor.ts +88 -24
- package/src/common/poly-gencode.ts +16 -8
- package/src/common/poly-init.ts +23 -19
- package/src/common/postproc.ts +2 -2
- package/src/common/splines-clip.ts +15 -12
- package/src/common/splines-routespl.ts +2 -2
- package/src/common/textmeasure-lookup.ts +1 -1
- package/src/gvc/context.ts +8 -0
- package/src/gvc/device-cluster.ts +63 -8
- package/src/gvc/device.ts +16 -2
- package/src/gvc/first-layer.ts +26 -0
- package/src/gvc/gvrender-set-style.ts +114 -0
- package/src/gvc/usershape.ts +26 -0
- package/src/layout/dot/cluster.ts +1 -1
- package/src/layout/dot/compound.ts +3 -4
- package/src/layout/dot/conc.ts +1 -1
- package/src/layout/dot/edge-route-clip.ts +19 -7
- package/src/layout/dot/edge-route-routing.ts +11 -3
- package/src/layout/dot/fastgr.ts +2 -2
- package/src/layout/dot/graph-label.ts +1 -15
- package/src/layout/neato/__fixtures__/dijkstra-f.ts +17 -0
- package/src/layout/neato/__fixtures__/hier/c1554.gv +33 -0
- package/src/layout/neato/__fixtures__/hier/c1554.plain +26 -0
- package/src/layout/neato/__fixtures__/hier/c1554.xdot +161 -0
- package/src/layout/neato/__fixtures__/hier/cases/cycle.gv +1 -0
- package/src/layout/neato/__fixtures__/hier/cases/cycle.plain +10 -0
- package/src/layout/neato/__fixtures__/hier/cases/cycle.stderr +0 -0
- package/src/layout/neato/__fixtures__/hier/cases/dirnone.gv +1 -0
- package/src/layout/neato/__fixtures__/hier/cases/dirnone.plain +11 -0
- package/src/layout/neato/__fixtures__/hier/cases/dirnone.stderr +0 -0
- package/src/layout/neato/__fixtures__/hier/cases/epsilon.gv +1 -0
- package/src/layout/neato/__fixtures__/hier/cases/epsilon.plain +13 -0
- package/src/layout/neato/__fixtures__/hier/cases/epsilon.stderr +0 -0
- package/src/layout/neato/__fixtures__/hier/cases/levelsgap.gv +1 -0
- package/src/layout/neato/__fixtures__/hier/cases/levelsgap.plain +8 -0
- package/src/layout/neato/__fixtures__/hier/cases/levelsgap.stderr +0 -0
- package/src/layout/neato/__fixtures__/hier/cases/mds.gv +1 -0
- package/src/layout/neato/__fixtures__/hier/cases/mds.plain +10 -0
- package/src/layout/neato/__fixtures__/hier/cases/mds.stderr +0 -0
- package/src/layout/neato/__fixtures__/hier/cases/multiedge.gv +1 -0
- package/src/layout/neato/__fixtures__/hier/cases/multiedge.plain +10 -0
- package/src/layout/neato/__fixtures__/hier/cases/multiedge.stderr +0 -0
- package/src/layout/neato/__fixtures__/hier/cases/neglevelsgap.gv +1 -0
- package/src/layout/neato/__fixtures__/hier/cases/neglevelsgap.plain +8 -0
- package/src/layout/neato/__fixtures__/hier/cases/neglevelsgap.stderr +0 -0
- package/src/layout/neato/__fixtures__/hier/cases/startrandom.gv +1 -0
- package/src/layout/neato/__fixtures__/hier/cases/startrandom.plain +10 -0
- package/src/layout/neato/__fixtures__/hier/cases/startrandom.stderr +0 -0
- package/src/layout/neato/__fixtures__/hier/cases/startregular.gv +1 -0
- package/src/layout/neato/__fixtures__/hier/cases/startregular.plain +10 -0
- package/src/layout/neato/__fixtures__/hier/cases/startregular.stderr +0 -0
- package/src/layout/neato/__fixtures__/hier/cases/tdist.gv +1 -0
- package/src/layout/neato/__fixtures__/hier/cases/tdist.plain +13 -0
- package/src/layout/neato/__fixtures__/hier/cases/tdist.stderr +0 -0
- package/src/layout/neato/__fixtures__/hier/cases/undirected.gv +1 -0
- package/src/layout/neato/__fixtures__/hier/cases/undirected.plain +10 -0
- package/src/layout/neato/__fixtures__/hier/cases/undirected.stderr +0 -0
- package/src/layout/neato/__fixtures__/hier/hier-probe.gv +1 -0
- package/src/layout/neato/__fixtures__/hier/hier-probe.plain +16 -0
- package/src/layout/neato/__fixtures__/hier/hier-probe.xdot +62 -0
- package/src/layout/neato/__fixtures__/hier-imds.ts +151 -0
- package/src/layout/neato/__fixtures__/hier-majorization.ts +145 -0
- package/src/layout/neato/cdt-surface.ts +6 -16
- package/src/layout/neato/compute-hierarchy.ts +90 -0
- package/src/layout/neato/conjgrad-mkernel.ts +141 -0
- package/src/layout/neato/conjgrad.ts +208 -0
- package/src/layout/neato/constrained-majorization.ts +479 -0
- package/src/layout/neato/dijkstra.ts +218 -92
- package/src/layout/neato/edge-len.ts +2 -2
- package/src/layout/neato/fdp-adjust.ts +3 -3
- package/src/layout/neato/gts-triangle.ts +42 -0
- package/src/layout/neato/init.ts +57 -57
- package/src/layout/neato/kk.ts +2 -2
- package/src/layout/neato/kkutils.ts +96 -0
- package/src/layout/neato/make-graph-data.ts +166 -0
- package/src/layout/neato/matrix-ops.ts +138 -0
- package/src/layout/neato/opt-arrangement.ts +86 -0
- package/src/layout/neato/quad-prog-solve.ts +489 -0
- package/src/layout/neato/smart-ini-x.ts +503 -0
- package/src/layout/neato/splines.ts +4 -4
- package/src/layout/neato/start.ts +7 -6
- package/src/layout/neato/stress.ts +28 -0
- package/src/model/edge.ts +3 -2
- package/src/model/lazy-attrs.ts +36 -0
- package/src/model/node.ts +3 -2
- package/src/ortho/index.ts +2 -3
- package/src/parser/dot.js +1 -1
- package/src/parser/dot.pegjs +1 -1
- package/src/parser/index.ts +1 -1
- package/src/render/color-resolve.ts +2 -2
- package/src/render/dot/edge-draw.ts +6 -3
- package/src/render/dot.ts +1 -1
- package/src/render/svg-edge-split.ts +2 -2
- package/src/render/svg-multicolor.ts +4 -3
- package/src/render/svg-parallel-edge.ts +2 -2
package/dist/render.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
// src/common/render-state.ts
|
|
2
|
+
var resets = [];
|
|
3
|
+
function registerRenderState(reset2) {
|
|
4
|
+
resets.push(reset2);
|
|
5
|
+
}
|
|
6
|
+
function resetRenderState() {
|
|
7
|
+
for (const reset2 of resets) reset2();
|
|
8
|
+
}
|
|
9
|
+
|
|
1
10
|
// src/errors.ts
|
|
2
11
|
var FRIENDLY_MESSAGES = {
|
|
3
12
|
SYNTAX_ERROR: "There is a syntax error in the DOT source.",
|
|
@@ -214,6 +223,12 @@ var GvcContext = class {
|
|
|
214
223
|
* rendering happens in between and must see the layout state
|
|
215
224
|
* (e.g. cluster arrays).
|
|
216
225
|
*
|
|
226
|
+
* Contract (AD-4/AD-8): first resets the C process state (RNG streams,
|
|
227
|
+
* sequence counters, once-only warnings), so each `layout` call behaves
|
|
228
|
+
* as one native run — drive one graph per `layout`. Caller-installed hooks
|
|
229
|
+
* (setTextMeasurer, setImageSizer, setImageResolver, the per-context
|
|
230
|
+
* measurer/sizer/resolver) are configuration and are not reset.
|
|
231
|
+
*
|
|
217
232
|
* @throws TypeError (ERR_INVALID_ARG_TYPE / ERR_INVALID_ARG_VALUE) for a
|
|
218
233
|
* bad `g`, or an engine argument that is not registered
|
|
219
234
|
* @throws RenderError (UNKNOWN_LAYOUT) if the `layout` attribute names no
|
|
@@ -224,6 +239,7 @@ var GvcContext = class {
|
|
|
224
239
|
* @see lib/gvc/gvlayout.c:gvLayoutJobs
|
|
225
240
|
*/
|
|
226
241
|
layout(g, engineName) {
|
|
242
|
+
resetRenderState();
|
|
227
243
|
const selected = this.checkLayoutArgs(g, engineName);
|
|
228
244
|
const attr2 = g.attrs?.get("layout");
|
|
229
245
|
let engine = selected;
|
|
@@ -5079,15 +5095,6 @@ var ALL_FONT_METRICS = [
|
|
|
5079
5095
|
CALIBRI_FAMILY
|
|
5080
5096
|
];
|
|
5081
5097
|
|
|
5082
|
-
// src/common/render-state.ts
|
|
5083
|
-
var resets = [];
|
|
5084
|
-
function registerRenderState(reset2) {
|
|
5085
|
-
resets.push(reset2);
|
|
5086
|
-
}
|
|
5087
|
-
function resetRenderState() {
|
|
5088
|
-
for (const reset2 of resets) reset2();
|
|
5089
|
-
}
|
|
5090
|
-
|
|
5091
5098
|
// src/common/agerr.ts
|
|
5092
5099
|
var PREFIX_ERROR = "Error";
|
|
5093
5100
|
var PREFIX_WARNING = "Warning";
|
|
@@ -5152,7 +5159,7 @@ function getFamilyMetrics(fontName) {
|
|
|
5152
5159
|
if (!warnedFontNames.has(fontName)) {
|
|
5153
5160
|
warnedFontNames.add(fontName);
|
|
5154
5161
|
agwarningf(
|
|
5155
|
-
`no hard-coded metrics for '${fontName}'. Falling back to 'Times' metrics`
|
|
5162
|
+
`Warning: no hard-coded metrics for '${fontName}'. Falling back to 'Times' metrics`
|
|
5156
5163
|
);
|
|
5157
5164
|
}
|
|
5158
5165
|
return TIMES_FALLBACK;
|
|
@@ -5537,6 +5544,17 @@ function createMeasurer() {
|
|
|
5537
5544
|
function setAspect(_g) {
|
|
5538
5545
|
}
|
|
5539
5546
|
|
|
5547
|
+
// src/common/attr-get.ts
|
|
5548
|
+
function nodeAttr(n, g, key) {
|
|
5549
|
+
const own = n.attrs.get(key);
|
|
5550
|
+
if (own !== void 0) return own;
|
|
5551
|
+
if (n.nodeDefaultsSnapshot !== void 0) return n.nodeDefaultsSnapshot.get(key);
|
|
5552
|
+
return g.nodeDefaults.get(key) ?? (g !== g.root ? g.root.nodeDefaults.get(key) : void 0);
|
|
5553
|
+
}
|
|
5554
|
+
function graphAttrInherited(sg, key) {
|
|
5555
|
+
return sg.attrs.get(key) ?? sg.graphDefaultsSnapshot?.get(key);
|
|
5556
|
+
}
|
|
5557
|
+
|
|
5540
5558
|
// src/common/htmltable-types.ts
|
|
5541
5559
|
var HtmlParseError = class extends DotEngineError {
|
|
5542
5560
|
type = "semantic";
|
|
@@ -6286,9 +6304,15 @@ function scanCdata(text, p, base, dataOf, tokens) {
|
|
|
6286
6304
|
if (end > p) tokens.push({ kind: "cdata", start: base + p, end: base + end, data: dataOf(base + p, base + end) });
|
|
6287
6305
|
return close < 0 ? -1 : close + CDATA_CLOSE.length;
|
|
6288
6306
|
}
|
|
6307
|
+
var CONTENT_NON_XML = /[\x00-\x08\x0b\x0c\x0e-\x1f\ufffe\uffff]|[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/;
|
|
6289
6308
|
function scanText(text, p, base, tokens) {
|
|
6290
6309
|
const e = text.indexOf("<", p);
|
|
6291
6310
|
const slice = text.slice(p, e < 0 ? text.length : e);
|
|
6311
|
+
const bad = CONTENT_NON_XML.exec(slice)?.index;
|
|
6312
|
+
if (bad !== void 0) {
|
|
6313
|
+
if (bad > 0) tokens.push({ kind: "text", start: base + p, end: base + p + bad });
|
|
6314
|
+
return { at: p + bad, held: false, invalid: p + bad };
|
|
6315
|
+
}
|
|
6292
6316
|
const from = e < 0 ? heldRefStart(slice) : void 0;
|
|
6293
6317
|
const end = from === void 0 ? p + slice.length : p + from;
|
|
6294
6318
|
if (end > p) tokens.push({ kind: "text", start: base + p, end: base + end });
|
|
@@ -6308,6 +6332,7 @@ function scanContent(text, base, inCdata, dataOf) {
|
|
|
6308
6332
|
}
|
|
6309
6333
|
if (text[p] !== "<") {
|
|
6310
6334
|
const scanned = scanText(text, p, base, tokens);
|
|
6335
|
+
if (scanned.invalid !== void 0) return { tokens, consumed: scanned.at, invalid: base + scanned.invalid, inCdata: false };
|
|
6311
6336
|
if (scanned.held) return { tokens, consumed: scanned.at, inCdata: false };
|
|
6312
6337
|
p = scanned.at;
|
|
6313
6338
|
continue;
|
|
@@ -7314,11 +7339,79 @@ var parseHtmlLabelRv = (src, stderr) => {
|
|
|
7314
7339
|
};
|
|
7315
7340
|
var parseHtmlLabel = (src) => parseHtmlLabelRv(src, new StderrLines(() => void 0)).label;
|
|
7316
7341
|
|
|
7342
|
+
// src/gvc/image-resolver.ts
|
|
7343
|
+
var activeResolver = null;
|
|
7344
|
+
var EXT_MIME = {
|
|
7345
|
+
png: "image/png",
|
|
7346
|
+
jpg: "image/jpeg",
|
|
7347
|
+
jpeg: "image/jpeg",
|
|
7348
|
+
gif: "image/gif",
|
|
7349
|
+
svg: "image/svg+xml",
|
|
7350
|
+
webp: "image/webp"
|
|
7351
|
+
};
|
|
7352
|
+
var FALLBACK_MIME = "application/octet-stream";
|
|
7353
|
+
function inferMimeFromSrc(src) {
|
|
7354
|
+
const dot = src.lastIndexOf(".");
|
|
7355
|
+
if (dot < 0 || dot === src.length - 1) return FALLBACK_MIME;
|
|
7356
|
+
const ext = src.slice(dot + 1).toLowerCase();
|
|
7357
|
+
return EXT_MIME[ext] ?? FALLBACK_MIME;
|
|
7358
|
+
}
|
|
7359
|
+
function findImageBytes(src, resolver) {
|
|
7360
|
+
const active = resolver ?? activeResolver;
|
|
7361
|
+
if (active === null) return null;
|
|
7362
|
+
const result = active(src);
|
|
7363
|
+
if (result === null) return null;
|
|
7364
|
+
if (result instanceof Uint8Array) {
|
|
7365
|
+
return { bytes: result, mime: inferMimeFromSrc(src) };
|
|
7366
|
+
}
|
|
7367
|
+
return { bytes: result.bytes, mime: result.mime ?? inferMimeFromSrc(src) };
|
|
7368
|
+
}
|
|
7369
|
+
var B64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
7370
|
+
function base64Encode(bytes) {
|
|
7371
|
+
const len = bytes.length;
|
|
7372
|
+
const out = [];
|
|
7373
|
+
let i = 0;
|
|
7374
|
+
for (; i + 2 < len; i += 3) {
|
|
7375
|
+
const n = bytes[i] << 16 | bytes[i + 1] << 8 | bytes[i + 2];
|
|
7376
|
+
out.push(
|
|
7377
|
+
B64_CHARS[n >> 18 & 63],
|
|
7378
|
+
B64_CHARS[n >> 12 & 63],
|
|
7379
|
+
B64_CHARS[n >> 6 & 63],
|
|
7380
|
+
B64_CHARS[n & 63]
|
|
7381
|
+
);
|
|
7382
|
+
}
|
|
7383
|
+
const remaining = len - i;
|
|
7384
|
+
if (remaining === 1) {
|
|
7385
|
+
const n = bytes[i] << 16;
|
|
7386
|
+
out.push(B64_CHARS[n >> 18 & 63], B64_CHARS[n >> 12 & 63], "==");
|
|
7387
|
+
} else if (remaining === 2) {
|
|
7388
|
+
const n = bytes[i] << 16 | bytes[i + 1] << 8;
|
|
7389
|
+
out.push(
|
|
7390
|
+
B64_CHARS[n >> 18 & 63],
|
|
7391
|
+
B64_CHARS[n >> 12 & 63],
|
|
7392
|
+
B64_CHARS[n >> 6 & 63],
|
|
7393
|
+
"="
|
|
7394
|
+
);
|
|
7395
|
+
}
|
|
7396
|
+
return out.join("");
|
|
7397
|
+
}
|
|
7398
|
+
function toDataUri(bytes, mime) {
|
|
7399
|
+
return "data:" + mime + ";base64," + base64Encode(bytes);
|
|
7400
|
+
}
|
|
7401
|
+
|
|
7317
7402
|
// src/gvc/usershape.ts
|
|
7318
7403
|
var activeSizer = null;
|
|
7319
7404
|
function findImageSize(src) {
|
|
7320
7405
|
return activeSizer !== null ? activeSizer(src) : null;
|
|
7321
7406
|
}
|
|
7407
|
+
var STRERROR_ENOENT = "No such file or directory";
|
|
7408
|
+
function imageIsSupplied(name, sizer, resolver) {
|
|
7409
|
+
const size = sizer !== void 0 ? sizer(name) : findImageSize(name);
|
|
7410
|
+
return size !== null || findImageBytes(name, resolver) !== null;
|
|
7411
|
+
}
|
|
7412
|
+
function imageOpenWarning(name) {
|
|
7413
|
+
return `${STRERROR_ENOENT} while opening ${name}`;
|
|
7414
|
+
}
|
|
7322
7415
|
|
|
7323
7416
|
// src/common/pointset.ts
|
|
7324
7417
|
function cmpPair(a, b) {
|
|
@@ -7371,6 +7464,173 @@ var PointSet = class {
|
|
|
7371
7464
|
}
|
|
7372
7465
|
};
|
|
7373
7466
|
|
|
7467
|
+
// src/common/emit-types.ts
|
|
7468
|
+
var PS2INCH = 1 / 72;
|
|
7469
|
+
var HTML_BF = 1 << 0;
|
|
7470
|
+
var HTML_IF = 1 << 1;
|
|
7471
|
+
var HTML_UL = 1 << 2;
|
|
7472
|
+
var HTML_SUP = 1 << 3;
|
|
7473
|
+
var HTML_SUB = 1 << 4;
|
|
7474
|
+
var HTML_S = 1 << 5;
|
|
7475
|
+
var HTML_OL = 1 << 6;
|
|
7476
|
+
|
|
7477
|
+
// src/common/htmltable-pos-runs.ts
|
|
7478
|
+
function itemFontFlags(item) {
|
|
7479
|
+
let f = 0;
|
|
7480
|
+
if (item.bold) f |= HTML_BF;
|
|
7481
|
+
if (item.italic) f |= HTML_IF;
|
|
7482
|
+
if (item.underline) f |= HTML_UL;
|
|
7483
|
+
if (item.superscript) f |= HTML_SUP;
|
|
7484
|
+
if (item.subscript) f |= HTML_SUB;
|
|
7485
|
+
if (item.strikethrough) f |= HTML_S;
|
|
7486
|
+
if (item.overline) f |= HTML_OL;
|
|
7487
|
+
return f;
|
|
7488
|
+
}
|
|
7489
|
+
function itemFace(item, finfo) {
|
|
7490
|
+
return {
|
|
7491
|
+
fs: item.fontSize !== void 0 ? item.fontSize : finfo.fontsize,
|
|
7492
|
+
face: item.fontFace !== void 0 ? item.fontFace : finfo.fontname
|
|
7493
|
+
};
|
|
7494
|
+
}
|
|
7495
|
+
function measureItem(item, finfo, measurer) {
|
|
7496
|
+
if (item.text === void 0) return null;
|
|
7497
|
+
const { fs, face } = itemFace(item, finfo);
|
|
7498
|
+
const flags = itemFontFlags(item);
|
|
7499
|
+
const sz = measurer.measure(
|
|
7500
|
+
item.text,
|
|
7501
|
+
face,
|
|
7502
|
+
fs,
|
|
7503
|
+
{ bold: !!(flags & HTML_BF), italic: !!(flags & HTML_IF) }
|
|
7504
|
+
);
|
|
7505
|
+
return { w: sz.w, h: sz.h, fs, yoffsetCenterline: sz.yoffsetCenterline, yoffsetLayout: sz.yoffsetLayout };
|
|
7506
|
+
}
|
|
7507
|
+
function newRun() {
|
|
7508
|
+
return { items: [], width: 0, fontSize: 0, height: 0, maxOffset: 0, maxLayout: 0 };
|
|
7509
|
+
}
|
|
7510
|
+
function runLeftX(run, box, centerX) {
|
|
7511
|
+
if (run.just === "left") return box.ll.x;
|
|
7512
|
+
if (run.just === "right") return box.ur.x - run.width;
|
|
7513
|
+
return centerX - run.width / 2;
|
|
7514
|
+
}
|
|
7515
|
+
function accumulateItem(cur, item, m) {
|
|
7516
|
+
cur.items.push(item);
|
|
7517
|
+
cur.width += m.w;
|
|
7518
|
+
cur.fontSize = Math.max(cur.fontSize, m.fs);
|
|
7519
|
+
cur.height = Math.max(cur.height, m.h);
|
|
7520
|
+
cur.maxOffset = Math.max(cur.maxOffset, m.yoffsetCenterline ?? 0.05 * m.fs);
|
|
7521
|
+
cur.maxLayout = Math.max(cur.maxLayout, m.yoffsetLayout ?? 0);
|
|
7522
|
+
}
|
|
7523
|
+
function buildLineRuns(texts, finfo, measurer) {
|
|
7524
|
+
const runs = [];
|
|
7525
|
+
let cur = newRun();
|
|
7526
|
+
const flush = (br) => {
|
|
7527
|
+
if (cur.items.length === 0 && br !== void 0) {
|
|
7528
|
+
const { br: _b, brAlign: _a, ...fontProps } = br;
|
|
7529
|
+
const empty = { text: "", ...fontProps };
|
|
7530
|
+
const m = measureItem(empty, finfo, measurer);
|
|
7531
|
+
if (m !== null) accumulateItem(cur, empty, m);
|
|
7532
|
+
}
|
|
7533
|
+
cur.just = br?.brAlign;
|
|
7534
|
+
runs.push(cur);
|
|
7535
|
+
cur = newRun();
|
|
7536
|
+
};
|
|
7537
|
+
for (const txt of texts) {
|
|
7538
|
+
for (const item of txt.items) {
|
|
7539
|
+
if (item.br) {
|
|
7540
|
+
flush(item);
|
|
7541
|
+
continue;
|
|
7542
|
+
}
|
|
7543
|
+
const m = measureItem(item, finfo, measurer);
|
|
7544
|
+
if (m !== null) accumulateItem(cur, item, m);
|
|
7545
|
+
}
|
|
7546
|
+
if (cur.items.length > 0) flush();
|
|
7547
|
+
}
|
|
7548
|
+
return runs;
|
|
7549
|
+
}
|
|
7550
|
+
function runSimpleKey(run, finfo) {
|
|
7551
|
+
if (run.items.length > 1) return null;
|
|
7552
|
+
const item = run.items[0];
|
|
7553
|
+
if (item === void 0) return void 0;
|
|
7554
|
+
if (itemFontFlags(item) !== 0) return null;
|
|
7555
|
+
return itemFace(item, finfo);
|
|
7556
|
+
}
|
|
7557
|
+
function runsAreSimple(runs, finfo) {
|
|
7558
|
+
let prevFs = -1;
|
|
7559
|
+
let prevFace = null;
|
|
7560
|
+
for (const run of runs) {
|
|
7561
|
+
const key = runSimpleKey(run, finfo);
|
|
7562
|
+
if (key === null) return false;
|
|
7563
|
+
if (key === void 0) continue;
|
|
7564
|
+
if (prevFs < 0) prevFs = key.fs;
|
|
7565
|
+
else if (key.fs !== prevFs) return false;
|
|
7566
|
+
if (prevFace === null) prevFace = key.face;
|
|
7567
|
+
else if (key.face !== prevFace) return false;
|
|
7568
|
+
}
|
|
7569
|
+
return true;
|
|
7570
|
+
}
|
|
7571
|
+
function placeRunItems(run, startX, baseline, finfo, measurer) {
|
|
7572
|
+
const lines = [];
|
|
7573
|
+
let x = startX;
|
|
7574
|
+
for (const item of run.items) {
|
|
7575
|
+
const { fs, face } = itemFace(item, finfo);
|
|
7576
|
+
const flags = itemFontFlags(item);
|
|
7577
|
+
const sz = measurer.measure(
|
|
7578
|
+
item.text,
|
|
7579
|
+
face,
|
|
7580
|
+
fs,
|
|
7581
|
+
{ bold: !!(flags & HTML_BF), italic: !!(flags & HTML_IF) }
|
|
7582
|
+
);
|
|
7583
|
+
lines.push({
|
|
7584
|
+
text: item.text,
|
|
7585
|
+
x,
|
|
7586
|
+
baseline,
|
|
7587
|
+
width: sz.w,
|
|
7588
|
+
fontSize: fs,
|
|
7589
|
+
fontName: face,
|
|
7590
|
+
fontColor: item.fontColor ?? finfo.fontcolor,
|
|
7591
|
+
fontFlags: flags
|
|
7592
|
+
});
|
|
7593
|
+
x += sz.w;
|
|
7594
|
+
}
|
|
7595
|
+
return lines;
|
|
7596
|
+
}
|
|
7597
|
+
function placeTextRuns(runs, box, finfo, measurer) {
|
|
7598
|
+
if (runsAreSimple(runs, finfo)) {
|
|
7599
|
+
return placeSimpleRuns(runs, box, finfo, measurer);
|
|
7600
|
+
}
|
|
7601
|
+
return placeComplexRuns(runs, box, finfo, measurer);
|
|
7602
|
+
}
|
|
7603
|
+
function placeSimpleRuns(runs, box, finfo, measurer) {
|
|
7604
|
+
const centerX = (box.ll.x + box.ur.x) / 2;
|
|
7605
|
+
const lines = [];
|
|
7606
|
+
let baseline = box.ur.y;
|
|
7607
|
+
for (let i = 0; i < runs.length; i++) {
|
|
7608
|
+
const run = runs[i];
|
|
7609
|
+
const ascent = run.maxLayout > 0 ? run.maxLayout : freetypeAscent(run.fontSize, finfo.fontname);
|
|
7610
|
+
baseline -= i === 0 ? ascent : run.height;
|
|
7611
|
+
lines.push(...placeRunItems(run, runLeftX(run, box, centerX), baseline, finfo, measurer));
|
|
7612
|
+
}
|
|
7613
|
+
return lines;
|
|
7614
|
+
}
|
|
7615
|
+
function placeComplexRuns(runs, box, finfo, measurer) {
|
|
7616
|
+
const centerX = (box.ll.x + box.ur.x) / 2;
|
|
7617
|
+
const lines = [];
|
|
7618
|
+
let curbline = 0;
|
|
7619
|
+
let ysize = 0;
|
|
7620
|
+
for (let i = 0; i < runs.length; i++) {
|
|
7621
|
+
const run = runs[i];
|
|
7622
|
+
const lfsize = i === 0 ? run.fontSize - run.maxOffset : run.fontSize + ysize - curbline - run.maxOffset;
|
|
7623
|
+
curbline += lfsize;
|
|
7624
|
+
ysize += run.fontSize;
|
|
7625
|
+
const baseline = box.ur.y - curbline;
|
|
7626
|
+
for (const pl of placeRunItems(run, runLeftX(run, box, centerX), baseline, finfo, measurer)) {
|
|
7627
|
+
pl.yoffsetCenterline = 1;
|
|
7628
|
+
lines.push(pl);
|
|
7629
|
+
}
|
|
7630
|
+
}
|
|
7631
|
+
return lines;
|
|
7632
|
+
}
|
|
7633
|
+
|
|
7374
7634
|
// src/common/htmltable-fontinfo.ts
|
|
7375
7635
|
var SIZE_SAVEF = { fontsize: 0 };
|
|
7376
7636
|
var EMIT_SAVEF = { fontsize: 0 };
|
|
@@ -7432,87 +7692,33 @@ var findCol = (ps, row, startCol, colspan, rowspan) => {
|
|
|
7432
7692
|
return col;
|
|
7433
7693
|
};
|
|
7434
7694
|
var defaultSizeEnv = () => ({ fontsize: DEFAULT_FONTSIZE, fontname: "" });
|
|
7435
|
-
var itemFont = (item, env) => ({
|
|
7436
|
-
fs: item.fontSize !== void 0 ? item.fontSize : env.fontsize,
|
|
7437
|
-
face: item.fontFace !== void 0 ? item.fontFace : env.fontname
|
|
7438
|
-
});
|
|
7439
|
-
var measureItem = (item, measurer, env) => {
|
|
7440
|
-
const { fs, face } = itemFont(item, env);
|
|
7441
|
-
const flags = item.bold === true || item.italic === true ? { bold: item.bold === true, italic: item.italic === true } : void 0;
|
|
7442
|
-
return measurer.measure(item.text ?? "", face, fs, flags);
|
|
7443
|
-
};
|
|
7444
|
-
var splitSizedLines = (texts, measurer, env) => {
|
|
7445
|
-
const lines = [];
|
|
7446
|
-
let cur = { items: [], width: 0, mxysize: 0, mxfsize: 0 };
|
|
7447
|
-
const accumulate = (item) => {
|
|
7448
|
-
const sz = measureItem(item, measurer, env);
|
|
7449
|
-
cur.items.push(item);
|
|
7450
|
-
cur.width += sz.w;
|
|
7451
|
-
cur.mxysize = Math.max(cur.mxysize, sz.h);
|
|
7452
|
-
cur.mxfsize = Math.max(cur.mxfsize, itemFont(item, env).fs);
|
|
7453
|
-
};
|
|
7454
|
-
const flush = (br) => {
|
|
7455
|
-
if (cur.items.length === 0 && br !== void 0) {
|
|
7456
|
-
const { br: _b, brAlign: _a, ...fontProps } = br;
|
|
7457
|
-
accumulate({ text: "", ...fontProps });
|
|
7458
|
-
}
|
|
7459
|
-
lines.push(cur);
|
|
7460
|
-
cur = { items: [], width: 0, mxysize: 0, mxfsize: 0 };
|
|
7461
|
-
};
|
|
7462
|
-
for (const txt of texts) {
|
|
7463
|
-
for (const item of txt.items) {
|
|
7464
|
-
if (item.br) {
|
|
7465
|
-
flush(item);
|
|
7466
|
-
continue;
|
|
7467
|
-
}
|
|
7468
|
-
if (item.text === void 0) continue;
|
|
7469
|
-
accumulate(item);
|
|
7470
|
-
}
|
|
7471
|
-
if (cur.items.length > 0) flush();
|
|
7472
|
-
}
|
|
7473
|
-
return lines;
|
|
7474
|
-
};
|
|
7475
|
-
var itemHasFlags = (i) => i.bold === true || i.italic === true || i.underline === true || i.strikethrough === true || i.overline === true || i.subscript === true || i.superscript === true;
|
|
7476
|
-
var htmlTextIsSimple = (lines, env) => {
|
|
7477
|
-
let prevFs = -1;
|
|
7478
|
-
let prevFace = null;
|
|
7479
|
-
for (const ln of lines) {
|
|
7480
|
-
const item = ln.items[0];
|
|
7481
|
-
if (ln.items.length > 1 || itemHasFlags(item)) return false;
|
|
7482
|
-
const { fs, face } = itemFont(item, env);
|
|
7483
|
-
if (prevFs < 0) prevFs = fs;
|
|
7484
|
-
else if (fs !== prevFs) return false;
|
|
7485
|
-
if (prevFace === null) prevFace = face;
|
|
7486
|
-
else if (face !== prevFace) return false;
|
|
7487
|
-
}
|
|
7488
|
-
return true;
|
|
7489
|
-
};
|
|
7490
7695
|
var sizeTextContent = (texts, measurer, env = defaultSizeEnv()) => {
|
|
7491
|
-
const lines =
|
|
7492
|
-
const simple =
|
|
7696
|
+
const lines = buildLineRuns(texts, env, measurer);
|
|
7697
|
+
const simple = runsAreSimple(lines, env);
|
|
7493
7698
|
let w = 0;
|
|
7494
7699
|
let h = 0;
|
|
7495
7700
|
for (const ln of lines) {
|
|
7496
7701
|
w = Math.max(w, ln.width);
|
|
7497
|
-
const lsize = simple ? ln.
|
|
7702
|
+
const lsize = simple ? ln.height : ln.fontSize;
|
|
7498
7703
|
h += ln.items.length > 0 ? lsize : DEFAULT_FONTSIZE;
|
|
7499
7704
|
}
|
|
7500
|
-
if (lines.length === 1) h = lines[0].items.length > 0 ? lines[0].
|
|
7705
|
+
if (lines.length === 1) h = lines[0].items.length > 0 ? lines[0].height : DEFAULT_FONTSIZE;
|
|
7501
7706
|
return { w, h };
|
|
7502
7707
|
};
|
|
7503
|
-
var missingImages = /* @__PURE__ */ new WeakSet();
|
|
7708
|
+
var missingImages = { set: /* @__PURE__ */ new WeakSet() };
|
|
7504
7709
|
var sizeHtmlImg = (img, { imageSizer, stderr }) => {
|
|
7505
|
-
if (img.width !== void 0 && img.height !== void 0) return missingImages.has(img) ? 1 : 0;
|
|
7710
|
+
if (img.width !== void 0 && img.height !== void 0) return missingImages.set.has(img) ? 1 : 0;
|
|
7506
7711
|
const sz = imageSizer !== void 0 ? imageSizer(img.src) : findImageSize(img.src);
|
|
7507
7712
|
if (sz !== null) {
|
|
7508
7713
|
img.width = sz.w;
|
|
7509
7714
|
img.height = sz.h;
|
|
7510
7715
|
return 0;
|
|
7511
7716
|
}
|
|
7717
|
+
if (!imageIsSupplied(img.src, imageSizer)) agerrLine(stderr, `Warning: ${imageOpenWarning(img.src)}`);
|
|
7512
7718
|
agerrLine(stderr, `Error: No or improper image file="${img.src}"`);
|
|
7513
7719
|
img.width = 0;
|
|
7514
7720
|
img.height = 0;
|
|
7515
|
-
missingImages.add(img);
|
|
7721
|
+
missingImages.set.add(img);
|
|
7516
7722
|
return 1;
|
|
7517
7723
|
};
|
|
7518
7724
|
var sizeContentItem = (item, measurer, env) => {
|
|
@@ -7551,7 +7757,11 @@ var WARN_CELL_TOO_SMALL = "Warning: cell size too small for content";
|
|
|
7551
7757
|
var WARN_CELL_UNSPECIFIED = "Warning: fixed cell size with unspecified width or height";
|
|
7552
7758
|
var WARN_TABLE_TOO_SMALL = "Warning: table size too small for content";
|
|
7553
7759
|
var WARN_TABLE_UNSPECIFIED = "Warning: fixed table size with unspecified width or height";
|
|
7554
|
-
var sizeWarned = /* @__PURE__ */ new WeakSet();
|
|
7760
|
+
var sizeWarned = { set: /* @__PURE__ */ new WeakSet() };
|
|
7761
|
+
registerRenderState(() => {
|
|
7762
|
+
missingImages.set = /* @__PURE__ */ new WeakSet();
|
|
7763
|
+
sizeWarned.set = /* @__PURE__ */ new WeakSet();
|
|
7764
|
+
});
|
|
7555
7765
|
var fixedCellCheck = (cell2, sz, warn, out) => {
|
|
7556
7766
|
if (!cell2.fixedsize) return { rv: 0, zero: false };
|
|
7557
7767
|
if (cell2.width && cell2.height) {
|
|
@@ -7573,8 +7783,8 @@ var getCellSize = (cell2, tbl, measurer, env) => {
|
|
|
7573
7783
|
}
|
|
7574
7784
|
let szx = cw + margin;
|
|
7575
7785
|
let szy = ch + margin;
|
|
7576
|
-
const warn = !sizeWarned.has(cell2);
|
|
7577
|
-
sizeWarned.add(cell2);
|
|
7786
|
+
const warn = !sizeWarned.set.has(cell2);
|
|
7787
|
+
sizeWarned.set.add(cell2);
|
|
7578
7788
|
const fixed = fixedCellCheck(cell2, { w: szx, h: szy }, warn, env.stderr);
|
|
7579
7789
|
rv |= fixed.rv;
|
|
7580
7790
|
if (fixed.zero) {
|
|
@@ -7670,8 +7880,8 @@ var layoutHtmlTable = (tbl, measurer, env = defaultSizeEnv()) => {
|
|
|
7670
7880
|
return { entries, widths, heights, spacing, border: border2, rv };
|
|
7671
7881
|
};
|
|
7672
7882
|
var warnFixedTable = (tbl, dims, out) => {
|
|
7673
|
-
const warn = !sizeWarned.has(tbl);
|
|
7674
|
-
sizeWarned.add(tbl);
|
|
7883
|
+
const warn = !sizeWarned.set.has(tbl);
|
|
7884
|
+
sizeWarned.set.add(tbl);
|
|
7675
7885
|
if (tbl.fixedsize !== true) return 0;
|
|
7676
7886
|
if (tbl.width && tbl.height) {
|
|
7677
7887
|
if (tbl.width >= dims.wd && tbl.height >= dims.ht) return 0;
|
|
@@ -7728,173 +7938,6 @@ var INIT_DELTA = 10;
|
|
|
7728
7938
|
var LOOP_TRIES = 15;
|
|
7729
7939
|
var ROUTESPL_FUDGE = 1e-4;
|
|
7730
7940
|
|
|
7731
|
-
// src/common/emit-types.ts
|
|
7732
|
-
var PS2INCH = 1 / 72;
|
|
7733
|
-
var HTML_BF = 1 << 0;
|
|
7734
|
-
var HTML_IF = 1 << 1;
|
|
7735
|
-
var HTML_UL = 1 << 2;
|
|
7736
|
-
var HTML_SUP = 1 << 3;
|
|
7737
|
-
var HTML_SUB = 1 << 4;
|
|
7738
|
-
var HTML_S = 1 << 5;
|
|
7739
|
-
var HTML_OL = 1 << 6;
|
|
7740
|
-
|
|
7741
|
-
// src/common/htmltable-pos-runs.ts
|
|
7742
|
-
function itemFontFlags(item) {
|
|
7743
|
-
let f = 0;
|
|
7744
|
-
if (item.bold) f |= HTML_BF;
|
|
7745
|
-
if (item.italic) f |= HTML_IF;
|
|
7746
|
-
if (item.underline) f |= HTML_UL;
|
|
7747
|
-
if (item.superscript) f |= HTML_SUP;
|
|
7748
|
-
if (item.subscript) f |= HTML_SUB;
|
|
7749
|
-
if (item.strikethrough) f |= HTML_S;
|
|
7750
|
-
if (item.overline) f |= HTML_OL;
|
|
7751
|
-
return f;
|
|
7752
|
-
}
|
|
7753
|
-
function itemFace(item, finfo) {
|
|
7754
|
-
return {
|
|
7755
|
-
fs: item.fontSize !== void 0 ? item.fontSize : finfo.fontsize,
|
|
7756
|
-
face: item.fontFace !== void 0 ? item.fontFace : finfo.fontname
|
|
7757
|
-
};
|
|
7758
|
-
}
|
|
7759
|
-
function measureItem2(item, finfo, measurer) {
|
|
7760
|
-
if (item.text === void 0) return null;
|
|
7761
|
-
const { fs, face } = itemFace(item, finfo);
|
|
7762
|
-
const flags = itemFontFlags(item);
|
|
7763
|
-
const sz = measurer.measure(
|
|
7764
|
-
item.text,
|
|
7765
|
-
face,
|
|
7766
|
-
fs,
|
|
7767
|
-
{ bold: !!(flags & HTML_BF), italic: !!(flags & HTML_IF) }
|
|
7768
|
-
);
|
|
7769
|
-
return { w: sz.w, h: sz.h, fs, yoffsetCenterline: sz.yoffsetCenterline, yoffsetLayout: sz.yoffsetLayout };
|
|
7770
|
-
}
|
|
7771
|
-
function newRun() {
|
|
7772
|
-
return { items: [], width: 0, fontSize: 0, height: 0, maxOffset: 0, maxLayout: 0 };
|
|
7773
|
-
}
|
|
7774
|
-
function runLeftX(run, box, centerX) {
|
|
7775
|
-
if (run.just === "left") return box.ll.x;
|
|
7776
|
-
if (run.just === "right") return box.ur.x - run.width;
|
|
7777
|
-
return centerX - run.width / 2;
|
|
7778
|
-
}
|
|
7779
|
-
function accumulateItem(cur, item, m) {
|
|
7780
|
-
cur.items.push(item);
|
|
7781
|
-
cur.width += m.w;
|
|
7782
|
-
cur.fontSize = Math.max(cur.fontSize, m.fs);
|
|
7783
|
-
cur.height = Math.max(cur.height, m.h);
|
|
7784
|
-
cur.maxOffset = Math.max(cur.maxOffset, m.yoffsetCenterline ?? 0.05 * m.fs);
|
|
7785
|
-
cur.maxLayout = Math.max(cur.maxLayout, m.yoffsetLayout ?? 0);
|
|
7786
|
-
}
|
|
7787
|
-
function buildLineRuns(texts, finfo, measurer) {
|
|
7788
|
-
const runs = [];
|
|
7789
|
-
let cur = newRun();
|
|
7790
|
-
const flush = (br) => {
|
|
7791
|
-
if (cur.items.length === 0 && br !== void 0) {
|
|
7792
|
-
const { br: _b, brAlign: _a, ...fontProps } = br;
|
|
7793
|
-
const empty = { text: "", ...fontProps };
|
|
7794
|
-
const m = measureItem2(empty, finfo, measurer);
|
|
7795
|
-
if (m !== null) accumulateItem(cur, empty, m);
|
|
7796
|
-
}
|
|
7797
|
-
cur.just = br?.brAlign;
|
|
7798
|
-
runs.push(cur);
|
|
7799
|
-
cur = newRun();
|
|
7800
|
-
};
|
|
7801
|
-
for (const txt of texts) {
|
|
7802
|
-
for (const item of txt.items) {
|
|
7803
|
-
if (item.br) {
|
|
7804
|
-
flush(item);
|
|
7805
|
-
continue;
|
|
7806
|
-
}
|
|
7807
|
-
const m = measureItem2(item, finfo, measurer);
|
|
7808
|
-
if (m !== null) accumulateItem(cur, item, m);
|
|
7809
|
-
}
|
|
7810
|
-
if (cur.items.length > 0) flush();
|
|
7811
|
-
}
|
|
7812
|
-
return runs;
|
|
7813
|
-
}
|
|
7814
|
-
function runSimpleKey(run, finfo) {
|
|
7815
|
-
if (run.items.length > 1) return null;
|
|
7816
|
-
const item = run.items[0];
|
|
7817
|
-
if (item === void 0) return void 0;
|
|
7818
|
-
if (itemFontFlags(item) !== 0) return null;
|
|
7819
|
-
return itemFace(item, finfo);
|
|
7820
|
-
}
|
|
7821
|
-
function runsAreSimple(runs, finfo) {
|
|
7822
|
-
let prevFs = -1;
|
|
7823
|
-
let prevFace = null;
|
|
7824
|
-
for (const run of runs) {
|
|
7825
|
-
const key = runSimpleKey(run, finfo);
|
|
7826
|
-
if (key === null) return false;
|
|
7827
|
-
if (key === void 0) continue;
|
|
7828
|
-
if (prevFs < 0) prevFs = key.fs;
|
|
7829
|
-
else if (key.fs !== prevFs) return false;
|
|
7830
|
-
if (prevFace === null) prevFace = key.face;
|
|
7831
|
-
else if (key.face !== prevFace) return false;
|
|
7832
|
-
}
|
|
7833
|
-
return true;
|
|
7834
|
-
}
|
|
7835
|
-
function placeRunItems(run, startX, baseline, finfo, measurer) {
|
|
7836
|
-
const lines = [];
|
|
7837
|
-
let x = startX;
|
|
7838
|
-
for (const item of run.items) {
|
|
7839
|
-
const { fs, face } = itemFace(item, finfo);
|
|
7840
|
-
const flags = itemFontFlags(item);
|
|
7841
|
-
const sz = measurer.measure(
|
|
7842
|
-
item.text,
|
|
7843
|
-
face,
|
|
7844
|
-
fs,
|
|
7845
|
-
{ bold: !!(flags & HTML_BF), italic: !!(flags & HTML_IF) }
|
|
7846
|
-
);
|
|
7847
|
-
lines.push({
|
|
7848
|
-
text: item.text,
|
|
7849
|
-
x,
|
|
7850
|
-
baseline,
|
|
7851
|
-
width: sz.w,
|
|
7852
|
-
fontSize: fs,
|
|
7853
|
-
fontName: face,
|
|
7854
|
-
fontColor: item.fontColor ?? finfo.fontcolor,
|
|
7855
|
-
fontFlags: flags
|
|
7856
|
-
});
|
|
7857
|
-
x += sz.w;
|
|
7858
|
-
}
|
|
7859
|
-
return lines;
|
|
7860
|
-
}
|
|
7861
|
-
function placeTextRuns(runs, box, finfo, measurer) {
|
|
7862
|
-
if (runsAreSimple(runs, finfo)) {
|
|
7863
|
-
return placeSimpleRuns(runs, box, finfo, measurer);
|
|
7864
|
-
}
|
|
7865
|
-
return placeComplexRuns(runs, box, finfo, measurer);
|
|
7866
|
-
}
|
|
7867
|
-
function placeSimpleRuns(runs, box, finfo, measurer) {
|
|
7868
|
-
const centerX = (box.ll.x + box.ur.x) / 2;
|
|
7869
|
-
const lines = [];
|
|
7870
|
-
let baseline = box.ur.y;
|
|
7871
|
-
for (let i = 0; i < runs.length; i++) {
|
|
7872
|
-
const run = runs[i];
|
|
7873
|
-
const ascent = run.maxLayout > 0 ? run.maxLayout : freetypeAscent(run.fontSize, finfo.fontname);
|
|
7874
|
-
baseline -= i === 0 ? ascent : run.height;
|
|
7875
|
-
lines.push(...placeRunItems(run, runLeftX(run, box, centerX), baseline, finfo, measurer));
|
|
7876
|
-
}
|
|
7877
|
-
return lines;
|
|
7878
|
-
}
|
|
7879
|
-
function placeComplexRuns(runs, box, finfo, measurer) {
|
|
7880
|
-
const centerX = (box.ll.x + box.ur.x) / 2;
|
|
7881
|
-
const lines = [];
|
|
7882
|
-
let curbline = 0;
|
|
7883
|
-
let ysize = 0;
|
|
7884
|
-
for (let i = 0; i < runs.length; i++) {
|
|
7885
|
-
const run = runs[i];
|
|
7886
|
-
const lfsize = i === 0 ? run.fontSize - run.maxOffset : run.fontSize + ysize - curbline - run.maxOffset;
|
|
7887
|
-
curbline += lfsize;
|
|
7888
|
-
ysize += run.fontSize;
|
|
7889
|
-
const baseline = box.ur.y - curbline;
|
|
7890
|
-
for (const pl of placeRunItems(run, runLeftX(run, box, centerX), baseline, finfo, measurer)) {
|
|
7891
|
-
pl.yoffsetCenterline = 1;
|
|
7892
|
-
lines.push(pl);
|
|
7893
|
-
}
|
|
7894
|
-
}
|
|
7895
|
-
return lines;
|
|
7896
|
-
}
|
|
7897
|
-
|
|
7898
7941
|
// src/common/htmltable-pos.ts
|
|
7899
7942
|
function alignContentBox(box, cell2, w, h) {
|
|
7900
7943
|
const out = { ll: { ...box.ll }, ur: { ...box.ur } };
|
|
@@ -8196,6 +8239,20 @@ function htmlTextLabel(text, finfo, placed, dim) {
|
|
|
8196
8239
|
};
|
|
8197
8240
|
}
|
|
8198
8241
|
|
|
8242
|
+
// src/model/lazy-attrs.ts
|
|
8243
|
+
var SharedEmptyAttrs = class extends Map {
|
|
8244
|
+
set(key, _value) {
|
|
8245
|
+
throw new Error(`attrs.set("${key}") on a shared empty map; use ownAttrs()`);
|
|
8246
|
+
}
|
|
8247
|
+
delete(key) {
|
|
8248
|
+
throw new Error(`attrs.delete("${key}") on a shared empty map; use ownAttrs()`);
|
|
8249
|
+
}
|
|
8250
|
+
clear() {
|
|
8251
|
+
throw new Error("attrs.clear() on a shared empty map; use ownAttrs()");
|
|
8252
|
+
}
|
|
8253
|
+
};
|
|
8254
|
+
var EMPTY_ATTRS = new SharedEmptyAttrs();
|
|
8255
|
+
|
|
8199
8256
|
// src/model/algData.ts
|
|
8200
8257
|
var THETA_UNSET = 10;
|
|
8201
8258
|
|
|
@@ -8298,10 +8355,10 @@ var Node = class {
|
|
|
8298
8355
|
*/
|
|
8299
8356
|
nodeDefaultsSnapshot;
|
|
8300
8357
|
/** @see lib/cgraph/node.c:agnode */
|
|
8301
|
-
constructor(id, name, root) {
|
|
8358
|
+
constructor(id, name, root, lazyAttrs = false) {
|
|
8302
8359
|
this.id = id;
|
|
8303
8360
|
this.name = name;
|
|
8304
|
-
this.attrs = /* @__PURE__ */ new Map();
|
|
8361
|
+
this.attrs = lazyAttrs ? EMPTY_ATTRS : /* @__PURE__ */ new Map();
|
|
8305
8362
|
this.info = makeNodeInfo();
|
|
8306
8363
|
this.root = root;
|
|
8307
8364
|
}
|
|
@@ -8471,12 +8528,12 @@ var Edge = class _Edge {
|
|
|
8471
8528
|
*/
|
|
8472
8529
|
info;
|
|
8473
8530
|
/** @see lib/cgraph/edge.c:agedge */
|
|
8474
|
-
constructor(tail, head, name) {
|
|
8531
|
+
constructor(tail, head, name, lazyAttrs = false) {
|
|
8475
8532
|
this.seq = _Edge._nextSeq++;
|
|
8476
8533
|
this.tail = tail;
|
|
8477
8534
|
this.head = head;
|
|
8478
8535
|
this.name = name;
|
|
8479
|
-
this.attrs = /* @__PURE__ */ new Map();
|
|
8536
|
+
this.attrs = lazyAttrs ? EMPTY_ATTRS : /* @__PURE__ */ new Map();
|
|
8480
8537
|
this.info = makeEdgeInfo(makePort(), makePort());
|
|
8481
8538
|
}
|
|
8482
8539
|
};
|
|
@@ -8728,12 +8785,17 @@ var DEFAULT_FONTNAME = "Times-Roman";
|
|
|
8728
8785
|
var DEFAULT_COLOR = "black";
|
|
8729
8786
|
function getPenColor(obj) {
|
|
8730
8787
|
if (obj === void 0) return void 0;
|
|
8731
|
-
const pc = obj
|
|
8788
|
+
const pc = aggetObj(obj, "pencolor");
|
|
8732
8789
|
if (pc !== void 0 && pc !== "") return pc;
|
|
8733
|
-
const c = obj
|
|
8790
|
+
const c = aggetObj(obj, "color");
|
|
8734
8791
|
if (c !== void 0 && c !== "") return c;
|
|
8735
8792
|
return void 0;
|
|
8736
8793
|
}
|
|
8794
|
+
function aggetObj(obj, key) {
|
|
8795
|
+
if (obj instanceof Node) return nodeAttr(obj, obj.root, key);
|
|
8796
|
+
if (obj instanceof Graph) return graphAttrInherited(obj, key);
|
|
8797
|
+
return obj.attrs.get(key);
|
|
8798
|
+
}
|
|
8737
8799
|
function rootOf(obj) {
|
|
8738
8800
|
return obj instanceof Edge ? obj.tail.root : obj.root;
|
|
8739
8801
|
}
|
|
@@ -8900,7 +8962,7 @@ function copyVirtualEdgeInfo(e, orig) {
|
|
|
8900
8962
|
e.seq = orig.seq;
|
|
8901
8963
|
}
|
|
8902
8964
|
function newVirtualEdge(u, v, orig) {
|
|
8903
|
-
const e = new Edge(u, v, "");
|
|
8965
|
+
const e = new Edge(u, v, "", true);
|
|
8904
8966
|
e.info.edge_type = VIRTUAL;
|
|
8905
8967
|
if (orig) {
|
|
8906
8968
|
copyVirtualEdgeInfo(e, orig);
|
|
@@ -9001,7 +9063,7 @@ function removeFromRank(g, n) {
|
|
|
9001
9063
|
}
|
|
9002
9064
|
}
|
|
9003
9065
|
function virtualNode(g) {
|
|
9004
|
-
const n = new Node(0, "", g.root);
|
|
9066
|
+
const n = new Node(0, "", g.root, true);
|
|
9005
9067
|
n.info.node_type = VIRTUAL;
|
|
9006
9068
|
n.info.lw = 1;
|
|
9007
9069
|
n.info.rw = 1;
|
|
@@ -9313,10 +9375,10 @@ var ARROW_EPSILON = 1e-4;
|
|
|
9313
9375
|
var vsub = (p, q) => ({ x: p.x - q.x, y: p.y - q.y });
|
|
9314
9376
|
var vadd = (p, q) => ({ x: p.x + q.x, y: p.y + q.y });
|
|
9315
9377
|
var vscale = (c, p) => ({ x: c * p.x, y: c * p.y });
|
|
9316
|
-
var negUnit = (u,
|
|
9378
|
+
var negUnit = (u, dist5) => {
|
|
9317
9379
|
if (u.x === 0 && u.y === 0) return { x: 0, y: 0 };
|
|
9318
9380
|
const h = Math.hypot(u.x, u.y);
|
|
9319
|
-
return { x:
|
|
9381
|
+
return { x: dist5 * (-u.x / h), y: dist5 * (-u.y / h) };
|
|
9320
9382
|
};
|
|
9321
9383
|
var backwardDelta = (u, penwidth) => negUnit(u, penwidth / 2);
|
|
9322
9384
|
function axialProjection(phiSrc, from, to, sign2) {
|
|
@@ -9899,9 +9961,9 @@ function makeEllipseInsideFn(rx, ry, penwidth = DEFAULT_NODEPENWIDTH) {
|
|
|
9899
9961
|
return (lx, ly) => lx * lx / (erx * erx) + ly * ly / (ery * ery) < 1;
|
|
9900
9962
|
}
|
|
9901
9963
|
function tailArrowEndClip(path4, tailTip, elen) {
|
|
9902
|
-
|
|
9903
|
-
const
|
|
9904
|
-
return
|
|
9964
|
+
const sp = [path4[3], path4[2], path4[1], tailTip];
|
|
9965
|
+
const clipped = elen > 0 ? bezierClipNode(sp, 0, 0, (x, y) => distFused({ x, y }, tailTip) <= elen, false) : sp;
|
|
9966
|
+
return [clipped[3], clipped[2], clipped[1], clipped[0]];
|
|
9905
9967
|
}
|
|
9906
9968
|
|
|
9907
9969
|
// src/layout/dot/edge-route-geom.ts
|
|
@@ -11598,11 +11660,12 @@ function emitHtmlLine(line, pos, renderer, job) {
|
|
|
11598
11660
|
}
|
|
11599
11661
|
function bgFillPaint(ctx) {
|
|
11600
11662
|
const penWidth = htmlFillPenWidth();
|
|
11601
|
-
const spec =
|
|
11663
|
+
const spec = findHtmlStopColor(ctx.bgcolor);
|
|
11602
11664
|
if (spec === null) return { fill: ctx.bgcolor, penWidth };
|
|
11603
11665
|
return {
|
|
11604
|
-
fill: spec
|
|
11605
|
-
stop: spec
|
|
11666
|
+
fill: spec.fill,
|
|
11667
|
+
stop: spec.stop ?? "black",
|
|
11668
|
+
gradientFrac: spec.frac,
|
|
11606
11669
|
gradientAngle: ctx.gradientangle ?? 0,
|
|
11607
11670
|
radial: htmlStyle(ctx.style).radial,
|
|
11608
11671
|
penWidth
|
|
@@ -12032,7 +12095,7 @@ function transformUnitVertex(R2, g, c, bb) {
|
|
|
12032
12095
|
const r = libmHypot(D.x, D.y);
|
|
12033
12096
|
return { x: r * Math.cos(alpha) * bb.x, y: r * Math.sin(alpha) * bb.y };
|
|
12034
12097
|
}
|
|
12035
|
-
function polygonVertices(bb, g,
|
|
12098
|
+
function polygonVertices(bb, g, isBox4) {
|
|
12036
12099
|
const sectorangle = 2 * Math.PI / g.sides;
|
|
12037
12100
|
const sidelength = Math.sin(sectorangle / 2);
|
|
12038
12101
|
const c = {
|
|
@@ -12050,7 +12113,7 @@ function polygonVertices(bb, g, isBox3) {
|
|
|
12050
12113
|
R2.y = fma(sidelength, Math.sin(angle), R2.y);
|
|
12051
12114
|
const P = transformUnitVertex(R2, g, c, bb);
|
|
12052
12115
|
verts.push(P);
|
|
12053
|
-
if (
|
|
12116
|
+
if (isBox4) {
|
|
12054
12117
|
verts.push({ x: -P.x, y: P.y }, { x: -P.x, y: -P.y }, { x: P.x, y: -P.y });
|
|
12055
12118
|
break;
|
|
12056
12119
|
}
|
|
@@ -12141,14 +12204,14 @@ function starVertexGen(bb) {
|
|
|
12141
12204
|
}
|
|
12142
12205
|
return { verts: starVertices(bb.x, bb.y), xmax: sz.x / 2, ymax: sz.y / 2 };
|
|
12143
12206
|
}
|
|
12144
|
-
function polygonBB(bb, minSize, p, sides2,
|
|
12207
|
+
function polygonBB(bb, minSize, p, sides2, isBox4) {
|
|
12145
12208
|
const geom = {
|
|
12146
12209
|
sides: sides2,
|
|
12147
12210
|
orientation: p.orientation,
|
|
12148
12211
|
distortion: p.distortion,
|
|
12149
12212
|
skew: p.skew
|
|
12150
12213
|
};
|
|
12151
|
-
const { verts, xmax, ymax } = p.optionShape === STAR ? starVertexGen(bb) : polygonVertices(bb, geom,
|
|
12214
|
+
const { verts, xmax, ymax } = p.optionShape === STAR ? starVertexGen(bb) : polygonVertices(bb, geom, isBox4);
|
|
12152
12215
|
const xmax2 = 2 * xmax;
|
|
12153
12216
|
const ymax2 = 2 * ymax;
|
|
12154
12217
|
const nbb = { x: Math.max(minSize.x, xmax2), y: Math.max(minSize.y, ymax2) };
|
|
@@ -12160,7 +12223,7 @@ function polygonBB(bb, minSize, p, sides2, isBox3) {
|
|
|
12160
12223
|
v.x *= scalex;
|
|
12161
12224
|
v.y *= scaley;
|
|
12162
12225
|
}
|
|
12163
|
-
return { ...polygonPeripheryBB(verts,
|
|
12226
|
+
return { ...polygonPeripheryBB(verts, isBox4 ? 4 : sides2, p, nbb), base: nbb };
|
|
12164
12227
|
}
|
|
12165
12228
|
function gvNodesize(widthPts, heightPts, flip) {
|
|
12166
12229
|
if (flip) return { lw: heightPts / 2, rw: heightPts / 2, ht: widthPts };
|
|
@@ -12185,9 +12248,9 @@ function applySizeConstraints(p, bb0, width0, height0) {
|
|
|
12185
12248
|
function polySize(p) {
|
|
12186
12249
|
const init = initialSizePts(p);
|
|
12187
12250
|
const dimen = quantize(padLabelDimen(p.labelDimen, p.margin, p.isPlain), p.quantumIn);
|
|
12188
|
-
const { sides: sides2, isBox:
|
|
12251
|
+
const { sides: sides2, isBox: isBox4 } = effectiveShape(p);
|
|
12189
12252
|
let bb = { x: dimen.x, y: dimen.y };
|
|
12190
|
-
if (
|
|
12253
|
+
if (isBox4) {
|
|
12191
12254
|
} else if (p.optionShape === STAR) {
|
|
12192
12255
|
bb = starSize(bb);
|
|
12193
12256
|
} else if (p.optionShape === CYLINDER) {
|
|
@@ -12199,16 +12262,16 @@ function polySize(p) {
|
|
|
12199
12262
|
const c = applySizeConstraints(p, bb, init.width, init.height);
|
|
12200
12263
|
const penwidth = p.penwidth ?? 1;
|
|
12201
12264
|
const hasOutline = penwidth > 0 || p.peripheries < 1;
|
|
12202
|
-
const grown = sides2 < 3 ? { ...ellipsePeripheryBB(c.bb, p.peripheries, penwidth, hasOutline), base: c.bb } : polygonBB(c.bb, { x: c.width, y: c.height }, { ...p, penwidth, hasOutline }, sides2,
|
|
12265
|
+
const grown = sides2 < 3 ? { ...ellipsePeripheryBB(c.bb, p.peripheries, penwidth, hasOutline), base: c.bb } : polygonBB(c.bb, { x: c.width, y: c.height }, { ...p, penwidth, hasOutline }, sides2, isBox4);
|
|
12203
12266
|
const result = assembleResult(p, dimen, grown, c.fixedshape);
|
|
12204
|
-
return { ...result, ...labelSpace(p, dimen, c.bb, minBb,
|
|
12267
|
+
return { ...result, ...labelSpace(p, dimen, c.bb, minBb, isBox4, c.fixedshape) };
|
|
12205
12268
|
}
|
|
12206
|
-
function labelSpace(p, dimen, bb, minBb,
|
|
12269
|
+
function labelSpace(p, dimen, bb, minBb, isBox4, fixedshape) {
|
|
12207
12270
|
const spacex = dimen.x - p.labelDimen.x;
|
|
12208
12271
|
let spaceX;
|
|
12209
12272
|
if (p.nojustify) {
|
|
12210
12273
|
spaceX = dimen.x - spacex;
|
|
12211
|
-
} else if (
|
|
12274
|
+
} else if (isBox4) {
|
|
12212
12275
|
spaceX = Math.max(dimen.x, bb.x) - spacex;
|
|
12213
12276
|
} else if (dimen.y < bb.y) {
|
|
12214
12277
|
spaceX = Math.max(dimen.x, bb.x * Math.sqrt(1 - dimen.y * dimen.y / (bb.y * bb.y))) - spacex;
|
|
@@ -12221,8 +12284,8 @@ function labelSpace(p, dimen, bb, minBb, isBox3, fixedshape) {
|
|
|
12221
12284
|
function effectiveShape(p) {
|
|
12222
12285
|
let sides2 = p.sides;
|
|
12223
12286
|
if (sides2 <= 2 && (p.distortion !== 0 || p.skew !== 0)) sides2 = 120;
|
|
12224
|
-
const
|
|
12225
|
-
return { sides: sides2, isBox:
|
|
12287
|
+
const isBox4 = sides2 === 4 && Math.abs(p.orientation % 90) < 0.5 && p.distortion === 0 && p.skew === 0;
|
|
12288
|
+
return { sides: sides2, isBox: isBox4 };
|
|
12226
12289
|
}
|
|
12227
12290
|
function labelValign(p) {
|
|
12228
12291
|
const ll = p.labelloc?.[0];
|
|
@@ -12634,12 +12697,6 @@ function drawRecordBox(job, n, ll, ur, filled) {
|
|
|
12634
12697
|
var DEFAULT_LW = 27;
|
|
12635
12698
|
var DEFAULT_RW = 27;
|
|
12636
12699
|
var DEFAULT_HT = 36;
|
|
12637
|
-
function nodeAttr(n, g, key) {
|
|
12638
|
-
const own = n.attrs.get(key);
|
|
12639
|
-
if (own !== void 0) return own;
|
|
12640
|
-
if (n.nodeDefaultsSnapshot !== void 0) return n.nodeDefaultsSnapshot.get(key);
|
|
12641
|
-
return g.nodeDefaults.get(key) ?? (g !== g.root ? g.root.nodeDefaults.get(key) : void 0);
|
|
12642
|
-
}
|
|
12643
12700
|
function readFontAttrs(n, g) {
|
|
12644
12701
|
return {
|
|
12645
12702
|
fontname: nodeAttr(n, g, "fontname") ?? DEFAULT_FONTNAME,
|
|
@@ -12664,17 +12721,27 @@ function buildNodeLabel(n, g, measurer) {
|
|
|
12664
12721
|
const content = isHtml ? htmlValueContent(labelAttr) : labelAttr ?? n.name;
|
|
12665
12722
|
n.info.label = makeAnyLabel(content, isHtml, font, measurer, n);
|
|
12666
12723
|
}
|
|
12724
|
+
function warnMissingImage(n, g, shapefile) {
|
|
12725
|
+
if (shapefile !== void 0 && shapefile !== "" && nodeAttr(n, g, "shape") !== "epsf") return;
|
|
12726
|
+
const image = nodeAttr(n, g, "image");
|
|
12727
|
+
if (image === void 0 || image === "") return;
|
|
12728
|
+
const gvc = g.root.info.gvc;
|
|
12729
|
+
if (imageIsSupplied(image, gvc?.imageSizer, gvc?.imageResolver)) return;
|
|
12730
|
+
agwarningf(imageOpenWarning(image));
|
|
12731
|
+
agwarningf(`No or improper image="${image}" for node "${n.name}"`);
|
|
12732
|
+
}
|
|
12667
12733
|
function polyInit(n, g, measurer) {
|
|
12668
12734
|
const shapeName2 = nodeAttr(n, g, "shape") ?? "ellipse";
|
|
12669
12735
|
const shapefile = nodeAttr(n, g, "shapefile");
|
|
12670
12736
|
n.info.shape = bindShape(shapeName2, shapefile);
|
|
12671
12737
|
if (shapefile !== void 0 && shapefile !== "" && shapeName2 !== "epsf") {
|
|
12672
|
-
agwarningf(`No or improper shapefile="${shapefile}" for node "${n.name}"
|
|
12738
|
+
agwarningf(`No or improper shapefile="${shapefile}" for node "${n.name}"`);
|
|
12673
12739
|
}
|
|
12674
12740
|
if (n.info.shape.kind === 2 /* SH_RECORD */) {
|
|
12675
12741
|
if (n.info.shape_info === void 0) recordNodeInit(n, g, measurer);
|
|
12676
12742
|
return;
|
|
12677
12743
|
}
|
|
12744
|
+
warnMissingImage(n, g, shapefile);
|
|
12678
12745
|
buildNodeLabel(n, g, measurer);
|
|
12679
12746
|
if (n.info.shape_info !== void 0) return;
|
|
12680
12747
|
const polyDesc = n.info.shape.polygon;
|
|
@@ -12682,6 +12749,16 @@ function polyInit(n, g, measurer) {
|
|
|
12682
12749
|
}
|
|
12683
12750
|
|
|
12684
12751
|
// src/common/multicolor.ts
|
|
12752
|
+
var parseSegsState = { warned: false };
|
|
12753
|
+
registerRenderState(() => {
|
|
12754
|
+
parseSegsState.warned = false;
|
|
12755
|
+
});
|
|
12756
|
+
function claimWarned() {
|
|
12757
|
+
if (parseSegsState.warned) return false;
|
|
12758
|
+
parseSegsState.warned = true;
|
|
12759
|
+
return true;
|
|
12760
|
+
}
|
|
12761
|
+
var claimNever = () => false;
|
|
12685
12762
|
var EPS = 1e-5;
|
|
12686
12763
|
function aeq0(x) {
|
|
12687
12764
|
return x < EPS && x > -EPS;
|
|
@@ -12695,17 +12772,14 @@ function getSegLen(token) {
|
|
|
12695
12772
|
const parsed = parseFloat(rest);
|
|
12696
12773
|
return !isNaN(parsed) && parsed >= 0 ? { color, v: parsed } : { color, v: -1 };
|
|
12697
12774
|
}
|
|
12698
|
-
function appendSeg(token, left2, segs,
|
|
12775
|
+
function appendSeg(token, left2, segs, claim) {
|
|
12699
12776
|
const { color, v } = getSegLen(token);
|
|
12700
12777
|
if (v < 0) return null;
|
|
12701
12778
|
let t = v;
|
|
12702
12779
|
let rval = 0;
|
|
12703
12780
|
const del = t - left2;
|
|
12704
12781
|
if (del > 0) {
|
|
12705
|
-
if (!aeq0(del) &&
|
|
12706
|
-
warnedExceeded.v = true;
|
|
12707
|
-
rval = 3;
|
|
12708
|
-
}
|
|
12782
|
+
if (!aeq0(del) && claim()) rval = 3;
|
|
12709
12783
|
t = left2;
|
|
12710
12784
|
}
|
|
12711
12785
|
left2 -= t;
|
|
@@ -12729,19 +12803,13 @@ function trimTrailing(segs) {
|
|
|
12729
12803
|
segs.pop();
|
|
12730
12804
|
}
|
|
12731
12805
|
}
|
|
12732
|
-
function
|
|
12806
|
+
function scanSegs(colorlist, claim) {
|
|
12733
12807
|
const segs = [];
|
|
12734
12808
|
let left2 = 1;
|
|
12735
12809
|
let rval = 0;
|
|
12736
|
-
let badFloatCount = 0;
|
|
12737
|
-
const warnedExceeded = { v: false };
|
|
12738
12810
|
for (const token of colorlist.split(":")) {
|
|
12739
|
-
const result = appendSeg(token, left2, segs,
|
|
12740
|
-
if (result === null) {
|
|
12741
|
-
const errCode = badFloatCount === 0 ? 2 : 1;
|
|
12742
|
-
badFloatCount++;
|
|
12743
|
-
return { segs: [], error: errCode };
|
|
12744
|
-
}
|
|
12811
|
+
const result = appendSeg(token, left2, segs, claim);
|
|
12812
|
+
if (result === null) return { segs: [], error: claim() ? 2 : 1 };
|
|
12745
12813
|
if (result.rval === 3) rval = 3;
|
|
12746
12814
|
left2 = result.left;
|
|
12747
12815
|
if (aeq0(left2)) {
|
|
@@ -12753,6 +12821,91 @@ function parseSegs(colorlist) {
|
|
|
12753
12821
|
trimTrailing(segs);
|
|
12754
12822
|
return { segs, error: rval };
|
|
12755
12823
|
}
|
|
12824
|
+
function parseSegs(colorlist, context) {
|
|
12825
|
+
const result = scanSegs(colorlist, claimWarned);
|
|
12826
|
+
if (result.error === 3) {
|
|
12827
|
+
const tail = context === void 0 ? "" : context();
|
|
12828
|
+
agwarningf(`Total size > 1 in "${colorlist}" color spec ${tail}`);
|
|
12829
|
+
} else if (result.error === 2) {
|
|
12830
|
+
agerrorf(`Illegal value in "${colorlist}" color attribute; float expected after ';'`);
|
|
12831
|
+
if (context !== void 0) agerr("prev", context());
|
|
12832
|
+
}
|
|
12833
|
+
return result;
|
|
12834
|
+
}
|
|
12835
|
+
function parseSegsSilent(colorlist) {
|
|
12836
|
+
return scanSegs(colorlist, claimNever);
|
|
12837
|
+
}
|
|
12838
|
+
function edgeSegsContext(e) {
|
|
12839
|
+
return () => {
|
|
12840
|
+
const directed = !e.tail.root.kind.endsWith("undirected");
|
|
12841
|
+
return `in edge ${e.tail.name}${directed ? " -> " : " -- "}${e.head.name}`;
|
|
12842
|
+
};
|
|
12843
|
+
}
|
|
12844
|
+
|
|
12845
|
+
// src/gvc/gvrender-set-style.ts
|
|
12846
|
+
var SUPPORTED_STYLES = /* @__PURE__ */ new Set([
|
|
12847
|
+
"solid",
|
|
12848
|
+
"dashed",
|
|
12849
|
+
"dotted",
|
|
12850
|
+
"invis",
|
|
12851
|
+
"invisible",
|
|
12852
|
+
"bold",
|
|
12853
|
+
"setlinewidth",
|
|
12854
|
+
"filled",
|
|
12855
|
+
"unfilled",
|
|
12856
|
+
"tapered"
|
|
12857
|
+
]);
|
|
12858
|
+
var BOX_ORIENTATION_TOLERANCE = 0.5;
|
|
12859
|
+
var BOX_ORIENTATION_STEP = 90;
|
|
12860
|
+
var BOX_SIDES = 4;
|
|
12861
|
+
var ELLIPSE_MAX_SIDES = 2;
|
|
12862
|
+
function styleName(token) {
|
|
12863
|
+
const paren = token.indexOf("(");
|
|
12864
|
+
return paren < 0 ? token : token.slice(0, paren);
|
|
12865
|
+
}
|
|
12866
|
+
function gvrenderSetStyle(styles) {
|
|
12867
|
+
if (styles === null) return;
|
|
12868
|
+
for (const token of styles) {
|
|
12869
|
+
const name = styleName(token);
|
|
12870
|
+
if (!SUPPORTED_STYLES.has(name)) {
|
|
12871
|
+
agwarningf(`gvrender_set_style: unsupported style ${name} - ignoring`);
|
|
12872
|
+
}
|
|
12873
|
+
}
|
|
12874
|
+
}
|
|
12875
|
+
function isBox(p) {
|
|
12876
|
+
if (p === null) return false;
|
|
12877
|
+
return p.sides === BOX_SIDES && Math.abs(p.orientation % BOX_ORIENTATION_STEP) < BOX_ORIENTATION_TOLERANCE && p.distortion === 0 && p.skew === 0;
|
|
12878
|
+
}
|
|
12879
|
+
function isEllipse(p) {
|
|
12880
|
+
return p !== null && p.sides <= ELLIPSE_MAX_SIDES;
|
|
12881
|
+
}
|
|
12882
|
+
function checkStyleTokens(styles, shape) {
|
|
12883
|
+
return styles.filter((p) => {
|
|
12884
|
+
if (p === "rounded" || p === "diagonals" || p === "radial") return false;
|
|
12885
|
+
if (p === "striped") return !isBox(shape);
|
|
12886
|
+
if (p === "wedged") return !isEllipse(shape);
|
|
12887
|
+
return true;
|
|
12888
|
+
});
|
|
12889
|
+
}
|
|
12890
|
+
function checkClusterStyleTokens(styles) {
|
|
12891
|
+
return styles.filter((p) => p !== "radial" && p !== "striped" && p !== "rounded");
|
|
12892
|
+
}
|
|
12893
|
+
function countChar(s, ch) {
|
|
12894
|
+
return [...s].filter((c) => c === ch).length;
|
|
12895
|
+
}
|
|
12896
|
+
function multicolorTaken(color) {
|
|
12897
|
+
if (countChar(color, ";") === 0 || countChar(color, ":") === 0) return false;
|
|
12898
|
+
const { error } = parseSegsSilent(color);
|
|
12899
|
+
return error !== 1 && error !== 2;
|
|
12900
|
+
}
|
|
12901
|
+
function edgeStyleResets(e, styles) {
|
|
12902
|
+
const spl = e.info.spl;
|
|
12903
|
+
if (spl === void 0 || spl.size <= 1 || styles.length === 0) return 0;
|
|
12904
|
+
const color = e.attrs.get("color") ?? "";
|
|
12905
|
+
const otherBranch = styles.includes("tapered") || countChar(color, ":") > 0;
|
|
12906
|
+
if (otherBranch && !multicolorTaken(color)) return 0;
|
|
12907
|
+
return spl.list.filter((bz) => bz.sflag !== 0 || bz.eflag !== 0).length;
|
|
12908
|
+
}
|
|
12756
12909
|
|
|
12757
12910
|
// src/util/math.ts
|
|
12758
12911
|
var INT32_MAX = 2147483647;
|
|
@@ -15735,11 +15888,11 @@ var SEG_EPS = 1e-5;
|
|
|
15735
15888
|
function reportColorNames(names) {
|
|
15736
15889
|
for (const name of names) resolveRenderColor(firstColor(name));
|
|
15737
15890
|
}
|
|
15738
|
-
function
|
|
15891
|
+
function countChar2(s, ch) {
|
|
15739
15892
|
return s.split(ch).length - 1;
|
|
15740
15893
|
}
|
|
15741
15894
|
function multicolorNames(color, arrows) {
|
|
15742
|
-
const { segs, error } =
|
|
15895
|
+
const { segs, error } = parseSegsSilent(color);
|
|
15743
15896
|
if (error === 1 || error === 2) return null;
|
|
15744
15897
|
const out = [];
|
|
15745
15898
|
const front = segs[0]?.color ?? null;
|
|
@@ -15761,9 +15914,9 @@ function taperedNames(color, fillcolor, hasFill) {
|
|
|
15761
15914
|
return hasFill ? [pen, fillcolor === "" ? DEFAULT_COLOR2 : fillcolor] : [pen];
|
|
15762
15915
|
}
|
|
15763
15916
|
function edgeGraphicsColors(spec) {
|
|
15764
|
-
const numc =
|
|
15917
|
+
const numc = countChar2(spec.color, ":");
|
|
15765
15918
|
let color = spec.color;
|
|
15766
|
-
if (
|
|
15919
|
+
if (countChar2(color, ";") > 0 && numc > 0) {
|
|
15767
15920
|
const multi = multicolorNames(color, spec.arrows);
|
|
15768
15921
|
if (multi !== null) return multi;
|
|
15769
15922
|
color = DEFAULT_COLOR2;
|
|
@@ -15916,8 +16069,8 @@ function drawWedge(seg2, e, ctx) {
|
|
|
15916
16069
|
ctx.renderer.bezier(ptsUp.map((p) => ({ x: p.x, y: -p.y })), true, ctx.job);
|
|
15917
16070
|
return angle1;
|
|
15918
16071
|
}
|
|
15919
|
-
function wedgedEllipse(job, pf, clrs, renderer) {
|
|
15920
|
-
const { segs, error } = parseSegs(clrs);
|
|
16072
|
+
function wedgedEllipse(job, pf, clrs, renderer, context) {
|
|
16073
|
+
const { segs, error } = parseSegs(clrs, context);
|
|
15921
16074
|
if (error === 1 || error === 2) return error;
|
|
15922
16075
|
const ctrX = (pf[0].x + pf[1].x) / 2;
|
|
15923
16076
|
const ctrY = (pf[0].y + pf[1].y) / 2;
|
|
@@ -15949,8 +16102,8 @@ function drawBand(p, seg2, ctx) {
|
|
|
15949
16102
|
ctx.renderer.polygon([...p], true, ctx.job);
|
|
15950
16103
|
p[0].x = p[3].x = p[1].x;
|
|
15951
16104
|
}
|
|
15952
|
-
function stripedBox(job, pts, clrs, rotate, renderer) {
|
|
15953
|
-
const { segs, error } = parseSegs(clrs);
|
|
16105
|
+
function stripedBox(job, pts, clrs, rotate, renderer, context) {
|
|
16106
|
+
const { segs, error } = parseSegs(clrs, context);
|
|
15954
16107
|
if (error === 1 || error === 2) return error;
|
|
15955
16108
|
const p = rotate ? [{ ...pts[2] }, { ...pts[3] }, { ...pts[0] }, { ...pts[1] }] : [{ ...pts[0] }, { ...pts[1] }, { ...pts[2] }, { ...pts[3] }];
|
|
15956
16109
|
const lastx = p[1].x;
|
|
@@ -16108,6 +16261,27 @@ function escapeXmlText(s) {
|
|
|
16108
16261
|
return gvXmlEscape(s, FLAGS_TEXT);
|
|
16109
16262
|
}
|
|
16110
16263
|
|
|
16264
|
+
// src/gvc/device-transform.ts
|
|
16265
|
+
function transformPoint(p, job) {
|
|
16266
|
+
if ((job.flags & GVRENDER_DOES_TRANSFORM) !== 0) {
|
|
16267
|
+
return p;
|
|
16268
|
+
}
|
|
16269
|
+
const sx = job.zoom * job.devscale.x;
|
|
16270
|
+
const sy = job.zoom * job.devscale.y;
|
|
16271
|
+
const tx = job.translation.x;
|
|
16272
|
+
const ty = job.translation.y;
|
|
16273
|
+
return applyScale(p, tx, ty, sx, sy);
|
|
16274
|
+
}
|
|
16275
|
+
function applyScale(p, tx, ty, sx, sy) {
|
|
16276
|
+
const x = (p.x + tx) * sx;
|
|
16277
|
+
const y = (p.y + ty) * sy;
|
|
16278
|
+
return buildPoint(x, y);
|
|
16279
|
+
}
|
|
16280
|
+
function buildPoint(x, y) {
|
|
16281
|
+
const pt = { x, y };
|
|
16282
|
+
return pt;
|
|
16283
|
+
}
|
|
16284
|
+
|
|
16111
16285
|
// src/gvc/device-cluster.ts
|
|
16112
16286
|
function applyClusterGradient(obj, fill) {
|
|
16113
16287
|
obj.fill = fill.kind === "radial" ? 3 /* Radial */ : 2 /* Linear */;
|
|
@@ -16155,6 +16329,7 @@ function applyClusterObjState(sg, job) {
|
|
|
16155
16329
|
const fillRes = resolveClusterFillEx(clusterAttrsOf(sg));
|
|
16156
16330
|
if (job.obj === null) return false;
|
|
16157
16331
|
const obj = job.obj;
|
|
16332
|
+
gvrenderSetStyle(checkClusterStyleTokens(styleTokens2(clusterStyle(sg))));
|
|
16158
16333
|
return withColorScheme(clusterAttr(sg, "colorscheme"), () => {
|
|
16159
16334
|
const filled = applyClusterFill(obj, fillRes);
|
|
16160
16335
|
applyClusterPenState(obj, sg);
|
|
@@ -16162,17 +16337,47 @@ function applyClusterObjState(sg, job) {
|
|
|
16162
16337
|
return filled;
|
|
16163
16338
|
});
|
|
16164
16339
|
}
|
|
16165
|
-
function
|
|
16340
|
+
function isStripedCluster(sg) {
|
|
16341
|
+
const flags = parseStyleFlags(clusterStyle(sg));
|
|
16342
|
+
return flags.striped && !flags.rounded;
|
|
16343
|
+
}
|
|
16344
|
+
function stripedFillSpec(sg) {
|
|
16166
16345
|
const flags = parseStyleFlags(clusterStyle(sg));
|
|
16167
|
-
if (!flags.striped || flags.rounded) return [];
|
|
16168
16346
|
const color = clusterAttr(sg, "color") ?? "";
|
|
16169
16347
|
let fill = clusterAttr(sg, "fillcolor") || color;
|
|
16170
16348
|
const bg = clusterAttr(sg, "bgcolor") ?? "";
|
|
16171
16349
|
if ((!flags.filled || fill === "") && bg !== "") fill = bg;
|
|
16172
|
-
|
|
16350
|
+
return fill === "" ? "lightgrey" : fill;
|
|
16351
|
+
}
|
|
16352
|
+
function stripedClusterColors(sg) {
|
|
16353
|
+
if (!isStripedCluster(sg)) return [];
|
|
16354
|
+
const { segs, error } = parseSegs(stripedFillSpec(sg), () => `in cluster ${sg.name}`);
|
|
16173
16355
|
if (error === 1 || error === 2) return [];
|
|
16174
16356
|
return segs.flatMap((seg2) => seg2.color !== null && seg2.t > 0 ? [seg2.color] : []);
|
|
16175
16357
|
}
|
|
16358
|
+
function renderStripedClusterBox(sg, renderer, job) {
|
|
16359
|
+
withColorScheme(clusterAttr(sg, "colorscheme"), () => {
|
|
16360
|
+
const { ll, ur } = sg.info.bb;
|
|
16361
|
+
const af = [
|
|
16362
|
+
{ x: ll.x, y: ll.y },
|
|
16363
|
+
{ x: ur.x, y: ll.y },
|
|
16364
|
+
{ x: ur.x, y: ur.y },
|
|
16365
|
+
{ x: ll.x, y: ur.y }
|
|
16366
|
+
].map((p) => transformPoint(p, job));
|
|
16367
|
+
const obj = job.obj;
|
|
16368
|
+
const savedFill = obj?.fill;
|
|
16369
|
+
if (obj !== null && savedFill !== void 0) obj.fill = 1 /* Solid */;
|
|
16370
|
+
stripedBox(job, af, stripedFillSpec(sg), false, renderer, () => `in cluster ${sg.name}`);
|
|
16371
|
+
if (obj !== null && savedFill !== void 0) obj.fill = savedFill;
|
|
16372
|
+
const rawPts = [
|
|
16373
|
+
{ x: ll.x, y: ll.y },
|
|
16374
|
+
{ x: ll.x, y: ur.y },
|
|
16375
|
+
{ x: ur.x, y: ur.y },
|
|
16376
|
+
{ x: ur.x, y: ll.y }
|
|
16377
|
+
];
|
|
16378
|
+
renderer.polygon(rawPts.map((p) => transformPoint(p, job)), false, job);
|
|
16379
|
+
});
|
|
16380
|
+
}
|
|
16176
16381
|
function applyClusterFill(obj, fillRes) {
|
|
16177
16382
|
if (fillRes.kind === "none") {
|
|
16178
16383
|
obj.fill = 0 /* None */;
|
|
@@ -16238,7 +16443,7 @@ function renderEllipseRing(ring, coord, filled, j, ctx) {
|
|
|
16238
16443
|
const pf = ring.map(
|
|
16239
16444
|
(v) => transformPoint({ x: v.x + coord.x, y: v.y + coord.y }, ctx.job)
|
|
16240
16445
|
);
|
|
16241
|
-
wedgedEllipse(ctx.job, pf, ctx.fillcolor, ctx.renderer);
|
|
16446
|
+
wedgedEllipse(ctx.job, pf, ctx.fillcolor, ctx.renderer, () => `in node ${ctx.nodeName}`);
|
|
16242
16447
|
renderEllipse(ring, coord, ctx.renderer, ctx.job, false);
|
|
16243
16448
|
} else {
|
|
16244
16449
|
renderEllipse(ring, coord, ctx.renderer, ctx.job, filled);
|
|
@@ -16247,7 +16452,7 @@ function renderEllipseRing(ring, coord, filled, j, ctx) {
|
|
|
16247
16452
|
}
|
|
16248
16453
|
function renderStripedRing(ring, coord, ctx) {
|
|
16249
16454
|
const af = ring.map((v) => transformPoint({ x: v.x + coord.x, y: v.y + coord.y }, ctx.job));
|
|
16250
|
-
stripedBox(ctx.job, af, ctx.fillcolor, true, ctx.renderer);
|
|
16455
|
+
stripedBox(ctx.job, af, ctx.fillcolor, true, ctx.renderer, () => `in node ${ctx.nodeName}`);
|
|
16251
16456
|
renderPolygon(ring, coord, ctx.renderer, ctx.job, false);
|
|
16252
16457
|
}
|
|
16253
16458
|
function renderPolyRing(ring, coord, filled, j, ctx) {
|
|
@@ -16373,6 +16578,10 @@ function applyPenState(obj, styleAttr, colorAttr, penwidthAttr) {
|
|
|
16373
16578
|
function applyNodeStyle(obj, n, job) {
|
|
16374
16579
|
const styleAttr = nodeAttr(n, n.root, "style");
|
|
16375
16580
|
const colorAttr = nodeAttr(n, n.root, "color");
|
|
16581
|
+
if (!isPointNode(n)) {
|
|
16582
|
+
const shape = n.info.shape;
|
|
16583
|
+
gvrenderSetStyle(checkStyleTokens(styleTokens2(styleAttr), shape?.polygon ?? null));
|
|
16584
|
+
}
|
|
16376
16585
|
const penwidth = nodeAttr(n, n.root, "penwidth");
|
|
16377
16586
|
if (n.info.shape?.kind === 2 /* SH_RECORD */) {
|
|
16378
16587
|
applyPenState(obj, styleAttr, colorAttr, penwidth);
|
|
@@ -16384,7 +16593,7 @@ function applyNodeStyle(obj, n, job) {
|
|
|
16384
16593
|
}
|
|
16385
16594
|
function prepareDrawPoly(poly, filled, obj) {
|
|
16386
16595
|
if (poly.peripheries !== 0 || !filled) return poly;
|
|
16387
|
-
obj.penColor =
|
|
16596
|
+
obj.penColor = resolveRenderColor("transparent");
|
|
16388
16597
|
return { ...poly, peripheries: 1 };
|
|
16389
16598
|
}
|
|
16390
16599
|
function vertexScale(n, poly) {
|
|
@@ -16414,6 +16623,7 @@ function resolveNodeDrawCtx(job, n) {
|
|
|
16414
16623
|
job,
|
|
16415
16624
|
style: styleFlags,
|
|
16416
16625
|
fillcolor: nodeAttr(n, n.root, "fillcolor") ?? "",
|
|
16626
|
+
nodeName: n.name,
|
|
16417
16627
|
...specialCornerFlags(drawPoly.option, styleFlags)
|
|
16418
16628
|
};
|
|
16419
16629
|
return { poly: drawPoly, coord, filled, ringCtx };
|
|
@@ -17773,7 +17983,7 @@ function pruneForeignClusterNodes(par, clust) {
|
|
|
17773
17983
|
}
|
|
17774
17984
|
function markClusterNode(clust, n, g) {
|
|
17775
17985
|
if ((n.info.ranktype ?? 0) !== 0) {
|
|
17776
|
-
agwarningf(`${n.name} was already in a rankset, deleted from cluster ${g.name}
|
|
17986
|
+
agwarningf(`${n.name} was already in a rankset, deleted from cluster ${g.name}`);
|
|
17777
17987
|
agDeleteFromCluster(clust, n);
|
|
17778
17988
|
return;
|
|
17779
17989
|
}
|
|
@@ -18352,7 +18562,7 @@ function findCharset(g) {
|
|
|
18352
18562
|
}
|
|
18353
18563
|
if (p === "big-5" || p === "big5") return CHAR_BIG5;
|
|
18354
18564
|
if (p === "utf-8" || p === "utf8") return CHAR_UTF8;
|
|
18355
|
-
agwarningf(`Unsupported charset "${raw}" - assuming utf-8
|
|
18565
|
+
agwarningf(`Unsupported charset "${raw}" - assuming utf-8`);
|
|
18356
18566
|
return CHAR_UTF8;
|
|
18357
18567
|
}
|
|
18358
18568
|
function maptoken(p, names, vals) {
|
|
@@ -18570,7 +18780,7 @@ function portToTbl(tbl, id) {
|
|
|
18570
18780
|
}
|
|
18571
18781
|
|
|
18572
18782
|
// src/common/compass-port.ts
|
|
18573
|
-
function
|
|
18783
|
+
function isBox2(n) {
|
|
18574
18784
|
return n.info.shape?.polygon === P_BOX;
|
|
18575
18785
|
}
|
|
18576
18786
|
function gdRankdir(n) {
|
|
@@ -18761,7 +18971,7 @@ function compassPort(n, args, pp) {
|
|
|
18761
18971
|
const { bp, compass, sides: sides2 } = args;
|
|
18762
18972
|
const { b, p, defined: defBp } = compassBbox(n, bp);
|
|
18763
18973
|
const dir = compassDirection(compass, b, p, sides2);
|
|
18764
|
-
if (bp === null && !
|
|
18974
|
+
if (bp === null && !isBox2(n)) applyIctxt(n, dir, b, p);
|
|
18765
18975
|
const defFinal = dir.rv === 1 ? defBp : dir.defined || defBp;
|
|
18766
18976
|
applyDir(pp, bp, dir, gdRankdir(n), defFinal);
|
|
18767
18977
|
return dir.rv;
|
|
@@ -20043,7 +20253,7 @@ function emitParallelEdgePaths(e, job, colorList) {
|
|
|
20043
20253
|
const spl = e.info.spl;
|
|
20044
20254
|
const numc = (colorList.match(/:/g) ?? []).length;
|
|
20045
20255
|
const segData = buildSegData(spl?.list ?? [], (2 + numc) / 2);
|
|
20046
|
-
const colors =
|
|
20256
|
+
const colors = parseSegsSilent(colorList).segs.map((s) => s.color ?? DEFAULT_COLOR3);
|
|
20047
20257
|
emitColorPasses(segData, colors, job);
|
|
20048
20258
|
return {
|
|
20049
20259
|
headColor: colors[0] ?? DEFAULT_COLOR3,
|
|
@@ -20875,25 +21085,14 @@ function walkNodesAndEdges(g, renderer, job, info) {
|
|
|
20875
21085
|
}
|
|
20876
21086
|
}
|
|
20877
21087
|
|
|
20878
|
-
// src/gvc/
|
|
20879
|
-
|
|
20880
|
-
|
|
20881
|
-
|
|
20882
|
-
|
|
20883
|
-
|
|
20884
|
-
|
|
20885
|
-
|
|
20886
|
-
const ty = job.translation.y;
|
|
20887
|
-
return applyScale(p, tx, ty, sx, sy);
|
|
20888
|
-
}
|
|
20889
|
-
function applyScale(p, tx, ty, sx, sy) {
|
|
20890
|
-
const x = (p.x + tx) * sx;
|
|
20891
|
-
const y = (p.y + ty) * sy;
|
|
20892
|
-
return buildPoint(x, y);
|
|
20893
|
-
}
|
|
20894
|
-
function buildPoint(x, y) {
|
|
20895
|
-
const pt = { x, y };
|
|
20896
|
-
return pt;
|
|
21088
|
+
// src/gvc/first-layer.ts
|
|
21089
|
+
var NATIVE_LANGNAME = /* @__PURE__ */ new Map([
|
|
21090
|
+
["cmapx-np", "cmapx_np"],
|
|
21091
|
+
["imap-np", "imap_np"]
|
|
21092
|
+
]);
|
|
21093
|
+
function warnLayersUnsupported(format, numLayers, doesLayers) {
|
|
21094
|
+
if (numLayers <= 1 || doesLayers) return;
|
|
21095
|
+
agwarningf(`layers not supported in ${NATIVE_LANGNAME.get(format) ?? format} output`);
|
|
20897
21096
|
}
|
|
20898
21097
|
|
|
20899
21098
|
// src/gvc/device-labels.ts
|
|
@@ -21038,6 +21237,7 @@ function setEdgePen(e, job) {
|
|
|
21038
21237
|
obj.pen = resolvePenType(flags);
|
|
21039
21238
|
obj.penWidth = resolvePenWidth(flags, e.attrs.get("penwidth"));
|
|
21040
21239
|
obj.rawStyle = styleTokens2(e.attrs.get("style"));
|
|
21240
|
+
if (e.info.spl !== void 0) gvrenderSetStyle(obj.rawStyle);
|
|
21041
21241
|
}
|
|
21042
21242
|
function renderEdge(e, renderer, job) {
|
|
21043
21243
|
emitEdgeComments(e, renderer, job);
|
|
@@ -21053,6 +21253,8 @@ function renderEdge(e, renderer, job) {
|
|
|
21053
21253
|
withColorScheme(e.attrs.get("colorscheme"), () => {
|
|
21054
21254
|
renderer.beginEdge(e, job);
|
|
21055
21255
|
reportEdgeColors(e);
|
|
21256
|
+
const styles = styleTokens2(e.attrs.get("style"));
|
|
21257
|
+
for (let i = edgeStyleResets(e, styles); i > 0; i--) gvrenderSetStyle(styles);
|
|
21056
21258
|
reportEdgeLabelColors(e);
|
|
21057
21259
|
renderer.endEdge(e, job);
|
|
21058
21260
|
});
|
|
@@ -21066,6 +21268,10 @@ function renderGraphLabel(g, renderer, job) {
|
|
|
21066
21268
|
}
|
|
21067
21269
|
function renderClusterBox(sg, filled, renderer, job) {
|
|
21068
21270
|
const { ll, ur } = sg.info.bb;
|
|
21271
|
+
if (isStripedCluster(sg)) {
|
|
21272
|
+
renderStripedClusterBox(sg, renderer, job);
|
|
21273
|
+
return;
|
|
21274
|
+
}
|
|
21069
21275
|
if (parseStyleFlags(clusterStyle(sg)).rounded) {
|
|
21070
21276
|
const af = [{ x: ll.x, y: ll.y }, { x: ur.x, y: ll.y }, { x: ur.x, y: ur.y }, { x: ll.x, y: ur.y }];
|
|
21071
21277
|
emitRoundedBezier(af, { x: 0, y: 0 }, filled, { renderer, job });
|
|
@@ -21089,7 +21295,7 @@ function renderOneCluster(sg, renderer, job) {
|
|
|
21089
21295
|
resolveObjAnchor(sg, labelTextOf2(sg.info.label), svgClusterId(sg, job), job.obj);
|
|
21090
21296
|
}
|
|
21091
21297
|
const anchored = beginAnchorIf(renderer, job);
|
|
21092
|
-
if ((clusterPeripheries(sg) !== 0 || filled) && job.obj?.pen !== 0 /* None */) {
|
|
21298
|
+
if ((clusterPeripheries(sg) !== 0 || filled || isStripedCluster(sg)) && job.obj?.pen !== 0 /* None */) {
|
|
21093
21299
|
renderClusterBox(sg, filled, renderer, job);
|
|
21094
21300
|
}
|
|
21095
21301
|
renderClusterLabel(sg, renderer, job);
|
|
@@ -21119,6 +21325,7 @@ function renderGraph(g, job, renderer) {
|
|
|
21119
21325
|
job.numLayers = layered ? info.numLayers : 1;
|
|
21120
21326
|
job.layerIDs = info.layerIDs;
|
|
21121
21327
|
renderer.beginGraph(g, job);
|
|
21328
|
+
warnLayersUnsupported(job.format, info.numLayers, renderer.beginLayer !== void 0);
|
|
21122
21329
|
for (let ln = 1; ln <= job.numLayers; ln++) {
|
|
21123
21330
|
job.layerNum = ln;
|
|
21124
21331
|
if (layered) renderer.beginLayer(info.layerIDs[ln], job);
|
|
@@ -21180,13 +21387,21 @@ function render(ctx, g, format, inlineImages = false) {
|
|
|
21180
21387
|
}
|
|
21181
21388
|
|
|
21182
21389
|
// src/common/htmltable-emit-fill.ts
|
|
21390
|
+
var MSG_MANY_COLORS = "More than 2 colors specified for a gradient - ignoring remaining";
|
|
21391
|
+
function findHtmlStopColor(color, silent = false) {
|
|
21392
|
+
const { segs, error } = silent ? parseSegsSilent(color) : parseSegs(color);
|
|
21393
|
+
const first = segs[0];
|
|
21394
|
+
const second = segs[1];
|
|
21395
|
+
if (error !== 0 || first === void 0 || second === void 0 || first.color === null) {
|
|
21396
|
+
return null;
|
|
21397
|
+
}
|
|
21398
|
+
if (segs.length > 2 && !silent) agwarningf(MSG_MANY_COLORS);
|
|
21399
|
+
const frac = first.hasFraction ? first.t : second.hasFraction ? 1 - second.t : 0;
|
|
21400
|
+
return { fill: first.color, stop: second.color, frac };
|
|
21401
|
+
}
|
|
21183
21402
|
function parseGradientSpec(color) {
|
|
21184
|
-
const
|
|
21185
|
-
|
|
21186
|
-
const c0 = color.slice(0, idx).trim();
|
|
21187
|
-
const c1 = color.slice(idx + 1).trim();
|
|
21188
|
-
if (c0.length === 0) return null;
|
|
21189
|
-
return [c0, c1.length > 0 ? c1 : "black"];
|
|
21403
|
+
const spec = findHtmlStopColor(color, true);
|
|
21404
|
+
return spec === null ? null : [spec.fill, spec.stop ?? "black"];
|
|
21190
21405
|
}
|
|
21191
21406
|
var paintObj = {
|
|
21192
21407
|
parent: null,
|
|
@@ -21243,6 +21458,12 @@ function resetHtmlFillPenWidth() {
|
|
|
21243
21458
|
htmlFillPen = 1;
|
|
21244
21459
|
}
|
|
21245
21460
|
registerRenderState(resetHtmlFillPenWidth);
|
|
21461
|
+
var DEFAULT_LINE_STYLE = ["solid", "setlinewidth(1)"];
|
|
21462
|
+
function htmlBorderStyle(pen) {
|
|
21463
|
+
if (pen === 1 /* Dashed */) return ["dashed"];
|
|
21464
|
+
if (pen === 2 /* Dotted */) return ["dotted"];
|
|
21465
|
+
return DEFAULT_LINE_STYLE;
|
|
21466
|
+
}
|
|
21246
21467
|
function penTypeOf(style2) {
|
|
21247
21468
|
const st = htmlStyle(style2);
|
|
21248
21469
|
if (st.dashed) return 1 /* Dashed */;
|
|
@@ -21250,12 +21471,13 @@ function penTypeOf(style2) {
|
|
|
21250
21471
|
return 3 /* Solid */;
|
|
21251
21472
|
}
|
|
21252
21473
|
function withHtmlPaint(paint, job, drawFn) {
|
|
21253
|
-
paintObj.fillColor = paint.fill !== void 0 ? resolveRenderColor(paint.fill) : { type: "none" };
|
|
21474
|
+
paintObj.fillColor = paint.fill !== void 0 ? resolveRenderColor(firstColor(paint.fill)) : { type: "none" };
|
|
21254
21475
|
paintObj.penColor = paint.pen !== void 0 ? resolveRenderColor(paint.pen) : { type: "string", s: "transparent" };
|
|
21255
21476
|
applyHtmlFill(paint);
|
|
21256
21477
|
paintObj.pen = penTypeOf(paint.penStyle);
|
|
21257
21478
|
paintObj.penWidth = paint.penWidth !== void 0 ? paint.penWidth : 1;
|
|
21258
21479
|
paintObj.rawStyle = paintObj.pen === 3 /* Solid */ ? ["solid"] : [];
|
|
21480
|
+
gvrenderSetStyle(htmlBorderStyle(paintObj.pen));
|
|
21259
21481
|
paintObj.emitState = job.obj?.emitState ?? 8 /* NDraw */;
|
|
21260
21482
|
job.pushObj(paintObj);
|
|
21261
21483
|
try {
|
|
@@ -21269,7 +21491,7 @@ function applyHtmlFill(paint) {
|
|
|
21269
21491
|
paintObj.fill = paint.radial === true ? 3 /* Radial */ : 2 /* Linear */;
|
|
21270
21492
|
paintObj.stopColor = resolveRenderColor(paint.stop);
|
|
21271
21493
|
paintObj.gradientAngle = paint.gradientAngle ?? 0;
|
|
21272
|
-
paintObj.gradientFrac = 0;
|
|
21494
|
+
paintObj.gradientFrac = paint.gradientFrac ?? 0;
|
|
21273
21495
|
return;
|
|
21274
21496
|
}
|
|
21275
21497
|
paintObj.fill = paint.fill !== void 0 ? 1 /* Solid */ : 0 /* None */;
|
|
@@ -21572,6 +21794,7 @@ function resolveClusterFillEx(attrs) {
|
|
|
21572
21794
|
|
|
21573
21795
|
// src/common/splines-clip.ts
|
|
21574
21796
|
var ARR_NORM = 1;
|
|
21797
|
+
var dist = distFused;
|
|
21575
21798
|
var SplineClipHelper = class _SplineClipHelper {
|
|
21576
21799
|
static makeEmptySpl() {
|
|
21577
21800
|
return { list: [], size: 0, bb: { ll: { x: 0, y: 0 }, ur: { x: 0, y: 0 } } };
|
|
@@ -21664,15 +21887,11 @@ var SplineClipHelper = class _SplineClipHelper {
|
|
|
21664
21887
|
if (j) return [eflag, sflag];
|
|
21665
21888
|
return [sflag, eflag];
|
|
21666
21889
|
}
|
|
21667
|
-
/** DIST(p, q). */
|
|
21668
|
-
static dist(p, q) {
|
|
21669
|
-
return Math.hypot(p.x - q.x, p.y - q.y);
|
|
21670
|
-
}
|
|
21671
21890
|
/** Sphere inside-fn around `tip` with radius `r` for bezierClip. */
|
|
21672
21891
|
static sphereCtx(tip2, r) {
|
|
21673
21892
|
return {
|
|
21674
21893
|
ctx: { nodeCoord: { x: 0, y: 0 }, rw: 0, bp: null },
|
|
21675
|
-
fn: (_c, p) =>
|
|
21894
|
+
fn: (_c, p) => dist(p, tip2) <= r
|
|
21676
21895
|
};
|
|
21677
21896
|
}
|
|
21678
21897
|
/**
|
|
@@ -21704,7 +21923,7 @@ var SplineClipHelper = class _SplineClipHelper {
|
|
|
21704
21923
|
);
|
|
21705
21924
|
spl.eflag = eflag;
|
|
21706
21925
|
spl.ep = ps[endp + 3];
|
|
21707
|
-
if (endp > startp &&
|
|
21926
|
+
if (endp > startp && dist(ps[endp], ps[endp + 3]) < elen) {
|
|
21708
21927
|
endp -= 3;
|
|
21709
21928
|
}
|
|
21710
21929
|
const sp = [spl.ep, ps[endp + 2], ps[endp + 1], ps[endp]];
|
|
@@ -21731,7 +21950,7 @@ var SplineClipHelper = class _SplineClipHelper {
|
|
|
21731
21950
|
);
|
|
21732
21951
|
spl.sflag = sflag;
|
|
21733
21952
|
spl.sp = ps[startp];
|
|
21734
|
-
if (endp > startp &&
|
|
21953
|
+
if (endp > startp && dist(ps[startp], ps[startp + 3]) < slen) {
|
|
21735
21954
|
startp += 3;
|
|
21736
21955
|
}
|
|
21737
21956
|
const sp = [ps[startp + 3], ps[startp + 2], ps[startp + 1], spl.sp];
|
|
@@ -21832,7 +22051,7 @@ var SplineClipHelper = class _SplineClipHelper {
|
|
|
21832
22051
|
if (sflag && eflag && endp === startp) {
|
|
21833
22052
|
const p = ps[endp];
|
|
21834
22053
|
const q = ps[endp + 3];
|
|
21835
|
-
const d =
|
|
22054
|
+
const d = dist(p, q);
|
|
21836
22055
|
let hlen = hlen0;
|
|
21837
22056
|
let tlen = tlen0;
|
|
21838
22057
|
if (hlen + tlen >= d) {
|
|
@@ -21875,7 +22094,7 @@ var SplineClipHelper = class _SplineClipHelper {
|
|
|
21875
22094
|
let hlen = hlen0;
|
|
21876
22095
|
const p = ps[endp];
|
|
21877
22096
|
const q = ps[endp + 3];
|
|
21878
|
-
const maxd = 0.9 *
|
|
22097
|
+
const maxd = 0.9 * dist(p, q);
|
|
21879
22098
|
if (hlen >= maxd) hlen = maxd;
|
|
21880
22099
|
const r = { x: p.x, y: p.y };
|
|
21881
22100
|
if (p.y === q.y) {
|
|
@@ -21895,7 +22114,7 @@ var SplineClipHelper = class _SplineClipHelper {
|
|
|
21895
22114
|
let tlen = tlen0;
|
|
21896
22115
|
const p = ps[startp];
|
|
21897
22116
|
const q = ps[startp + 3];
|
|
21898
|
-
const maxd = 0.9 *
|
|
22117
|
+
const maxd = 0.9 * dist(p, q);
|
|
21899
22118
|
if (tlen >= maxd) tlen = maxd;
|
|
21900
22119
|
const r = { x: p.x, y: p.y };
|
|
21901
22120
|
if (p.y === q.y) {
|
|
@@ -22606,9 +22825,6 @@ function readLabelPos(sg) {
|
|
|
22606
22825
|
}
|
|
22607
22826
|
return pos;
|
|
22608
22827
|
}
|
|
22609
|
-
function graphAttrInherited(sg, key) {
|
|
22610
|
-
return sg.attrs.get(key) ?? sg.graphDefaultsSnapshot?.get(key);
|
|
22611
|
-
}
|
|
22612
22828
|
function readFontParams(sg) {
|
|
22613
22829
|
return {
|
|
22614
22830
|
fontsize: parseFloat(graphAttrInherited(sg, "fontsize") ?? "") || DEFAULT_FONTSIZE2,
|
|
@@ -24029,13 +24245,13 @@ function dfsNode(Xg, v, frames) {
|
|
|
24029
24245
|
frames.push({ v, edges: v.outEdges(Xg).slice(), i: 0 });
|
|
24030
24246
|
}
|
|
24031
24247
|
function dfsStep2(Xg, frames) {
|
|
24032
|
-
const
|
|
24033
|
-
if (
|
|
24034
|
-
const e =
|
|
24248
|
+
const fr7 = frames[frames.length - 1];
|
|
24249
|
+
if (fr7.i < fr7.edges.length) {
|
|
24250
|
+
const e = fr7.edges[fr7.i++];
|
|
24035
24251
|
if (e.head.info.onstack) reverseEdge2(Xg, e);
|
|
24036
24252
|
else if (!e.head.info.mark) dfsNode(Xg, e.head, frames);
|
|
24037
24253
|
} else {
|
|
24038
|
-
|
|
24254
|
+
fr7.v.info.onstack = 0;
|
|
24039
24255
|
frames.pop();
|
|
24040
24256
|
}
|
|
24041
24257
|
}
|
|
@@ -25807,7 +26023,7 @@ function fillRankVlist(g, r, root) {
|
|
|
25807
26023
|
rankArr[r].v = rootRank.v;
|
|
25808
26024
|
rankArr[r].vStart = lead.info.order ?? 0;
|
|
25809
26025
|
const maxi = computeMaxi(g, r);
|
|
25810
|
-
if (maxi === -1) agwarningf(`degenerate concentrated rank ${g.name},${r}
|
|
26026
|
+
if (maxi === -1) agwarningf(`degenerate concentrated rank ${g.name},${r}`);
|
|
25811
26027
|
rankArr[r].n = maxi + 1;
|
|
25812
26028
|
return 0;
|
|
25813
26029
|
}
|
|
@@ -28626,7 +28842,7 @@ function routeSplinesInternal(pp, polyline) {
|
|
|
28626
28842
|
];
|
|
28627
28843
|
const pl = shortestPath(poly, eps);
|
|
28628
28844
|
if (pl === null) {
|
|
28629
|
-
|
|
28845
|
+
agerrorf("in routesplines, Pshortestpath failed");
|
|
28630
28846
|
return null;
|
|
28631
28847
|
}
|
|
28632
28848
|
emitDump("S3_POLY", dumpNames, () => ({
|
|
@@ -30632,9 +30848,9 @@ function writePortlabelPos(l, pe, pf, angleStr, distanceStr) {
|
|
|
30632
30848
|
const angleDeg = lateDouble(angleStr, PORT_LABEL_ANGLE, -180);
|
|
30633
30849
|
const angle = Math.atan2(pf.y - pe.y, pf.x - pe.x) + RADIANS(angleDeg);
|
|
30634
30850
|
const distMult = lateDouble(distanceStr || void 0, 1, 0);
|
|
30635
|
-
const
|
|
30636
|
-
l.pos.x = pe.x +
|
|
30637
|
-
l.pos.y = pe.y +
|
|
30851
|
+
const dist5 = PORT_LABEL_DISTANCE * distMult;
|
|
30852
|
+
l.pos.x = pe.x + dist5 * Math.cos(angle);
|
|
30853
|
+
l.pos.y = pe.y + dist5 * Math.sin(angle);
|
|
30638
30854
|
l.set = true;
|
|
30639
30855
|
}
|
|
30640
30856
|
function updateBB(g, l) {
|
|
@@ -31036,7 +31252,7 @@ function translateDrawing(g) {
|
|
|
31036
31252
|
if (e.tail !== v) continue;
|
|
31037
31253
|
if (e.info.spl === void 0) {
|
|
31038
31254
|
if (!(g.info.concentrate ?? false) && (e.info.edge_type ?? 0) !== IGNORED_EDGE) {
|
|
31039
|
-
|
|
31255
|
+
agerrorf(`lost ${e.tail.name} ${e.head.name} edge`);
|
|
31040
31256
|
}
|
|
31041
31257
|
continue;
|
|
31042
31258
|
}
|
|
@@ -31799,9 +32015,14 @@ function nodeInsideFn2(box) {
|
|
|
31799
32015
|
function clipToNodes(bezier2, tailBox, headBox, penwidth = DEFAULT_NODEPENWIDTH, clip = CLIP_BOTH) {
|
|
31800
32016
|
const step1 = clip.tail ? bezierClipNode(bezier2, tailBox.center.x, tailBox.center.y, nodeInsideFn2(tailBox), true) : bezier2;
|
|
31801
32017
|
const step2 = clip.head ? bezierClipNode(step1, headBox.center.x, headBox.center.y, nodeInsideFn2(headBox), false) : step1;
|
|
31802
|
-
const
|
|
32018
|
+
const startp = 0;
|
|
32019
|
+
let endp = 0;
|
|
32020
|
+
const arrowTip = step2[endp + 3];
|
|
31803
32021
|
const elen = normalArrowLen(penwidth);
|
|
31804
|
-
|
|
32022
|
+
if (endp > startp && distFused(step2[endp], step2[endp + 3]) < elen) {
|
|
32023
|
+
endp -= 3;
|
|
32024
|
+
}
|
|
32025
|
+
const clipped = arrowEndClip(step2.slice(endp, endp + 4), arrowTip, elen);
|
|
31805
32026
|
const arrowDir = normalizeVec({
|
|
31806
32027
|
x: clipped[3].x - arrowTip.x,
|
|
31807
32028
|
y: clipped[3].y - arrowTip.y
|
|
@@ -34340,8 +34561,7 @@ function ensureDummyNodes(sg, gstart) {
|
|
|
34340
34561
|
}
|
|
34341
34562
|
function orthoEdges(g, useLbls, clipAndInstall2) {
|
|
34342
34563
|
if (useLbls) {
|
|
34343
|
-
|
|
34344
|
-
"warn",
|
|
34564
|
+
agwarningf(
|
|
34345
34565
|
"Orthogonal edges do not currently handle edge labels. Try using xlabels.\n"
|
|
34346
34566
|
);
|
|
34347
34567
|
useLbls = false;
|
|
@@ -34476,7 +34696,7 @@ function dispatchOrthoEdges(g, useLbls) {
|
|
|
34476
34696
|
}
|
|
34477
34697
|
|
|
34478
34698
|
// src/common/arrows-geometry.ts
|
|
34479
|
-
function
|
|
34699
|
+
function dist3(a, b) {
|
|
34480
34700
|
return Math.hypot(a.x - b.x, a.y - b.y);
|
|
34481
34701
|
}
|
|
34482
34702
|
|
|
@@ -34580,7 +34800,7 @@ function getCycleCentroid(g, edge) {
|
|
|
34580
34800
|
}
|
|
34581
34801
|
function bend(spl, centroid) {
|
|
34582
34802
|
const midpt = midPointf(spl[0], spl[3]);
|
|
34583
|
-
const distVal =
|
|
34803
|
+
const distVal = dist3(spl[3], spl[0]);
|
|
34584
34804
|
const r = distVal / 5;
|
|
34585
34805
|
const vX = centroid.x - midpt.x;
|
|
34586
34806
|
const vY = centroid.y - midpt.y;
|
|
@@ -35193,7 +35413,7 @@ function arrowEndClipIdx(state3, endp) {
|
|
|
35193
35413
|
const elen = arrowClipLength(edgeArrowName(e, "head"), edgeArrowsize(e), edgePenwidthAttr(e));
|
|
35194
35414
|
bez.eflag = bez.eflag || 1;
|
|
35195
35415
|
bez.ep = { ...bez.list[endp + 3] };
|
|
35196
|
-
if (endp > state3.starti &&
|
|
35416
|
+
if (endp > state3.starti && distFused(bez.list[endp], bez.list[endp + 3]) < elen) endp -= 3;
|
|
35197
35417
|
const seg2 = [bez.list[endp], bez.list[endp + 1], bez.list[endp + 2], bez.list[endp + 3]];
|
|
35198
35418
|
const clipped = arrowEndClip(seg2, bez.ep, elen);
|
|
35199
35419
|
for (let k = 0; k < 4; k++) bez.list[endp + k] = clipped[k];
|
|
@@ -35204,7 +35424,7 @@ function arrowStartClipIdx(state3, startp, endp) {
|
|
|
35204
35424
|
const slen = arrowClipLength(edgeArrowName(e, "tail"), edgeArrowsize(e), edgePenwidthAttr(e));
|
|
35205
35425
|
bez.sflag = bez.sflag || 1;
|
|
35206
35426
|
bez.sp = { ...bez.list[startp] };
|
|
35207
|
-
if (endp > startp &&
|
|
35427
|
+
if (endp > startp && distFused(bez.list[startp], bez.list[startp + 3]) < slen) startp += 3;
|
|
35208
35428
|
const seg2 = [bez.list[startp], bez.list[startp + 1], bez.list[startp + 2], bez.list[startp + 3]];
|
|
35209
35429
|
const clipped = tailArrowEndClip(seg2, bez.sp, slen);
|
|
35210
35430
|
for (let k = 0; k < 4; k++) bez.list[startp + k] = clipped[k];
|
|
@@ -36473,120 +36693,522 @@ var DOT_LAYOUT_ENGINE = {
|
|
|
36473
36693
|
};
|
|
36474
36694
|
|
|
36475
36695
|
// src/layout/neato/dijkstra.ts
|
|
36476
|
-
|
|
36477
|
-
|
|
36478
|
-
|
|
36479
|
-
|
|
36480
|
-
|
|
36481
|
-
|
|
36482
|
-
const tmp = heap[parent2];
|
|
36483
|
-
heap[parent2] = heap[pos];
|
|
36484
|
-
heap[pos] = tmp;
|
|
36485
|
-
pos = parent2;
|
|
36486
|
-
}
|
|
36487
|
-
}
|
|
36488
|
-
function heapSiftDown2(heap, dist4) {
|
|
36489
|
-
let pos = 0;
|
|
36696
|
+
var FLT_MAX = 34028234663852886e22;
|
|
36697
|
+
function greaterPriorityF(h, i, j, dist5) {
|
|
36698
|
+
return dist5[h.data[i]] < dist5[h.data[j]];
|
|
36699
|
+
}
|
|
36700
|
+
function heapifyF(h, start, dist5) {
|
|
36701
|
+
let i = start;
|
|
36490
36702
|
for (; ; ) {
|
|
36491
|
-
const l =
|
|
36492
|
-
const r =
|
|
36493
|
-
let
|
|
36494
|
-
if (
|
|
36495
|
-
if (
|
|
36496
|
-
|
|
36497
|
-
|
|
36498
|
-
|
|
36499
|
-
|
|
36500
|
-
|
|
36501
|
-
|
|
36502
|
-
|
|
36503
|
-
|
|
36504
|
-
|
|
36505
|
-
|
|
36506
|
-
|
|
36507
|
-
heap[0] = last;
|
|
36508
|
-
heapSiftDown2(heap, dist4);
|
|
36509
|
-
return top;
|
|
36510
|
-
}
|
|
36511
|
-
function heapBuildExcluding(src, n, dist4) {
|
|
36512
|
-
const heap = [];
|
|
36703
|
+
const l = ngLeft(i);
|
|
36704
|
+
const r = ngRight(i);
|
|
36705
|
+
let largest = ngInsideHeap(h, l) && greaterPriorityF(h, l, i, dist5) ? l : i;
|
|
36706
|
+
if (ngInsideHeap(h, r) && greaterPriorityF(h, r, largest, dist5)) largest = r;
|
|
36707
|
+
if (largest === i) break;
|
|
36708
|
+
ngExchange(h, largest, i);
|
|
36709
|
+
i = largest;
|
|
36710
|
+
}
|
|
36711
|
+
}
|
|
36712
|
+
function initHeapF(startVertex, dist5, n) {
|
|
36713
|
+
const h = {
|
|
36714
|
+
data: new Array(Math.max(n - 1, 0)).fill(0),
|
|
36715
|
+
heapSize: n - 1,
|
|
36716
|
+
index: new Int32Array(n)
|
|
36717
|
+
};
|
|
36718
|
+
let count = 0;
|
|
36513
36719
|
for (let i = 0; i < n; i++) {
|
|
36514
|
-
if (i !==
|
|
36720
|
+
if (i !== startVertex) {
|
|
36721
|
+
h.data[count] = i;
|
|
36722
|
+
h.index[i] = count;
|
|
36723
|
+
count++;
|
|
36724
|
+
}
|
|
36515
36725
|
}
|
|
36516
|
-
|
|
36726
|
+
for (let j = Math.trunc((n - 1) / 2); j >= 0; j--) heapifyF(h, j, dist5);
|
|
36727
|
+
return h;
|
|
36517
36728
|
}
|
|
36518
|
-
function
|
|
36519
|
-
|
|
36520
|
-
|
|
36521
|
-
|
|
36522
|
-
|
|
36729
|
+
function extractMaxF(h, dist5) {
|
|
36730
|
+
if (h.heapSize === 0) return -1;
|
|
36731
|
+
const max = h.data[0];
|
|
36732
|
+
h.data[0] = h.data[h.heapSize - 1];
|
|
36733
|
+
h.index[h.data[0]] = 0;
|
|
36734
|
+
h.heapSize--;
|
|
36735
|
+
heapifyF(h, 0, dist5);
|
|
36736
|
+
return max;
|
|
36523
36737
|
}
|
|
36524
|
-
function
|
|
36525
|
-
|
|
36526
|
-
|
|
36527
|
-
|
|
36528
|
-
|
|
36529
|
-
|
|
36530
|
-
|
|
36531
|
-
|
|
36738
|
+
function increaseKeyF(h, increasedVertex, newDist, dist5) {
|
|
36739
|
+
if (dist5[increasedVertex] <= newDist) return;
|
|
36740
|
+
let i = h.index[increasedVertex];
|
|
36741
|
+
dist5[increasedVertex] = newDist;
|
|
36742
|
+
while (i > 0 && dist5[h.data[ngParent(i)]] > newDist) {
|
|
36743
|
+
ngAssign(h, i, ngParent(i));
|
|
36744
|
+
i = ngParent(i);
|
|
36745
|
+
}
|
|
36746
|
+
h.data[i] = increasedVertex;
|
|
36747
|
+
h.index[increasedVertex] = i;
|
|
36748
|
+
}
|
|
36749
|
+
function dijkstra(vertex, graph, n, dist5) {
|
|
36750
|
+
for (let i = 0; i < n; i++) dist5[i] = FLT_MAX;
|
|
36751
|
+
dist5[vertex] = 0;
|
|
36752
|
+
const vd = graph[vertex];
|
|
36753
|
+
for (let i = 1; i < vd.nedges; i++) dist5[vd.edges[i]] = vd.ewgts[i];
|
|
36754
|
+
const h = initHeapF(vertex, dist5, n);
|
|
36755
|
+
for (let closest = extractMaxF(h, dist5); closest >= 0; closest = extractMaxF(h, dist5)) {
|
|
36756
|
+
const closestDist = dist5[closest];
|
|
36757
|
+
if (closestDist === FLT_MAX) break;
|
|
36758
|
+
const cd = graph[closest];
|
|
36759
|
+
for (let i = 1; i < cd.nedges; i++) {
|
|
36760
|
+
increaseKeyF(h, cd.edges[i], Math.fround(closestDist + Math.fround(cd.ewgts[i])), dist5);
|
|
36532
36761
|
}
|
|
36533
36762
|
}
|
|
36534
36763
|
}
|
|
36535
|
-
|
|
36536
|
-
|
|
36537
|
-
|
|
36538
|
-
|
|
36539
|
-
|
|
36540
|
-
|
|
36541
|
-
|
|
36542
|
-
|
|
36764
|
+
var MAX_DIST = 2147483647;
|
|
36765
|
+
function ngLeft(i) {
|
|
36766
|
+
return 2 * i;
|
|
36767
|
+
}
|
|
36768
|
+
function ngRight(i) {
|
|
36769
|
+
return 2 * i + 1;
|
|
36770
|
+
}
|
|
36771
|
+
function ngParent(i) {
|
|
36772
|
+
return Math.trunc(i / 2);
|
|
36773
|
+
}
|
|
36774
|
+
function ngInsideHeap(h, i) {
|
|
36775
|
+
return i < h.heapSize;
|
|
36776
|
+
}
|
|
36777
|
+
function ngGreaterPriority(h, i, j, dist5) {
|
|
36778
|
+
return dist5[h.data[i]] < dist5[h.data[j]];
|
|
36779
|
+
}
|
|
36780
|
+
function ngAssign(h, i, j) {
|
|
36781
|
+
h.data[i] = h.data[j];
|
|
36782
|
+
h.index[h.data[i]] = i;
|
|
36783
|
+
}
|
|
36784
|
+
function ngExchange(h, i, j) {
|
|
36785
|
+
const t = h.data[i];
|
|
36786
|
+
h.data[i] = h.data[j];
|
|
36787
|
+
h.data[j] = t;
|
|
36788
|
+
h.index[h.data[i]] = i;
|
|
36789
|
+
h.index[h.data[j]] = j;
|
|
36790
|
+
}
|
|
36791
|
+
function ngHeapify(h, start, dist5) {
|
|
36792
|
+
let i = start;
|
|
36793
|
+
for (; ; ) {
|
|
36794
|
+
const l = ngLeft(i);
|
|
36795
|
+
const r = ngRight(i);
|
|
36796
|
+
let largest = ngInsideHeap(h, l) && ngGreaterPriority(h, l, i, dist5) ? l : i;
|
|
36797
|
+
if (ngInsideHeap(h, r) && ngGreaterPriority(h, r, largest, dist5)) largest = r;
|
|
36798
|
+
if (largest === i) break;
|
|
36799
|
+
ngExchange(h, largest, i);
|
|
36800
|
+
i = largest;
|
|
36801
|
+
}
|
|
36802
|
+
}
|
|
36803
|
+
function ngInitHeap(startVertex, dist5, n) {
|
|
36804
|
+
const h = {
|
|
36805
|
+
data: new Array(Math.max(n - 1, 0)).fill(0),
|
|
36806
|
+
heapSize: n - 1,
|
|
36807
|
+
index: new Int32Array(n)
|
|
36808
|
+
};
|
|
36809
|
+
let count = 0;
|
|
36810
|
+
for (let i = 0; i < n; i++) {
|
|
36811
|
+
if (i !== startVertex) {
|
|
36812
|
+
h.data[count] = i;
|
|
36813
|
+
h.index[i] = count;
|
|
36814
|
+
count++;
|
|
36815
|
+
}
|
|
36816
|
+
}
|
|
36817
|
+
for (let j = Math.trunc((n - 1) / 2); j >= 0; j--) ngHeapify(h, j, dist5);
|
|
36818
|
+
return h;
|
|
36819
|
+
}
|
|
36820
|
+
function ngExtractMax(h, dist5) {
|
|
36821
|
+
if (h.heapSize === 0) return -1;
|
|
36822
|
+
const max = h.data[0];
|
|
36823
|
+
h.data[0] = h.data[h.heapSize - 1];
|
|
36824
|
+
h.index[h.data[0]] = 0;
|
|
36825
|
+
h.heapSize--;
|
|
36826
|
+
ngHeapify(h, 0, dist5);
|
|
36827
|
+
return max;
|
|
36828
|
+
}
|
|
36829
|
+
function ngIncreaseKey(h, increasedVertex, newDist, dist5) {
|
|
36830
|
+
if (dist5[increasedVertex] <= newDist) return;
|
|
36831
|
+
let i = h.index[increasedVertex];
|
|
36832
|
+
dist5[increasedVertex] = newDist;
|
|
36833
|
+
while (i > 0 && dist5[h.data[ngParent(i)]] > newDist) {
|
|
36834
|
+
ngAssign(h, i, ngParent(i));
|
|
36835
|
+
i = ngParent(i);
|
|
36836
|
+
}
|
|
36837
|
+
h.data[i] = increasedVertex;
|
|
36838
|
+
h.index[increasedVertex] = i;
|
|
36839
|
+
}
|
|
36840
|
+
function toDistType(w) {
|
|
36841
|
+
return Math.trunc(Math.fround(w));
|
|
36842
|
+
}
|
|
36843
|
+
function ngdijkstra(vertex, graph, n, dist5) {
|
|
36844
|
+
let prevClosestDist = MAX_DIST;
|
|
36845
|
+
for (let i = 0; i < n; i++) dist5[i] = MAX_DIST;
|
|
36846
|
+
dist5[vertex] = 0;
|
|
36847
|
+
const vd = graph[vertex];
|
|
36848
|
+
for (let i = 1; i < vd.nedges; i++) dist5[vd.edges[i]] = toDistType(vd.ewgts[i]);
|
|
36849
|
+
const h = ngInitHeap(vertex, dist5, n);
|
|
36850
|
+
for (let closest = ngExtractMax(h, dist5); closest >= 0; closest = ngExtractMax(h, dist5)) {
|
|
36851
|
+
const closestDist = dist5[closest];
|
|
36852
|
+
if (closestDist === MAX_DIST) break;
|
|
36853
|
+
const cd = graph[closest];
|
|
36854
|
+
for (let i = 1; i < cd.nedges; i++) {
|
|
36855
|
+
ngIncreaseKey(h, cd.edges[i], closestDist + toDistType(cd.ewgts[i]) | 0, dist5);
|
|
36856
|
+
}
|
|
36857
|
+
prevClosestDist = closestDist;
|
|
36858
|
+
}
|
|
36859
|
+
for (let i = 0; i < n; i++) {
|
|
36860
|
+
if (dist5[i] === MAX_DIST) {
|
|
36861
|
+
dist5[i] = MAX_DIST - prevClosestDist < 10 ? MAX_DIST : prevClosestDist + 10;
|
|
36862
|
+
}
|
|
36543
36863
|
}
|
|
36544
36864
|
}
|
|
36545
36865
|
|
|
36546
36866
|
// src/layout/neato/bfs.ts
|
|
36547
|
-
function bfsInit(src, n,
|
|
36548
|
-
for (let i = 0; i < n; i++)
|
|
36549
|
-
|
|
36867
|
+
function bfsInit(src, n, dist5) {
|
|
36868
|
+
for (let i = 0; i < n; i++) dist5[i] = -1;
|
|
36869
|
+
dist5[src] = 0;
|
|
36550
36870
|
return [src];
|
|
36551
36871
|
}
|
|
36552
|
-
function bfsFixDisconnected(n,
|
|
36872
|
+
function bfsFixDisconnected(n, dist5, closestDist) {
|
|
36553
36873
|
for (let i = 0; i < n; i++) {
|
|
36554
|
-
if (
|
|
36874
|
+
if (dist5[i] < 0) dist5[i] = closestDist + 10;
|
|
36555
36875
|
}
|
|
36556
36876
|
}
|
|
36557
|
-
function bfsVisitNeighbors(vertex, graph,
|
|
36877
|
+
function bfsVisitNeighbors(vertex, graph, dist5, queue) {
|
|
36558
36878
|
const vd = graph[vertex];
|
|
36559
|
-
const d =
|
|
36879
|
+
const d = dist5[vertex];
|
|
36560
36880
|
const unit = graph[0].ewgts.length === 0;
|
|
36561
36881
|
for (let i = 1; i < vd.nedges; i++) {
|
|
36562
36882
|
const nb = vd.edges[i];
|
|
36563
|
-
if (
|
|
36564
|
-
|
|
36883
|
+
if (dist5[nb] < 0) {
|
|
36884
|
+
dist5[nb] = d + (unit ? 1 : Math.trunc(Math.fround(vd.ewgts[i])));
|
|
36565
36885
|
queue.push(nb);
|
|
36566
36886
|
}
|
|
36567
36887
|
}
|
|
36568
36888
|
return d;
|
|
36569
36889
|
}
|
|
36570
|
-
function bfs(src, graph, n,
|
|
36571
|
-
const queue = bfsInit(src, n,
|
|
36890
|
+
function bfs(src, graph, n, dist5) {
|
|
36891
|
+
const queue = bfsInit(src, n, dist5);
|
|
36572
36892
|
let closestDist = 0;
|
|
36573
36893
|
let head = 0;
|
|
36574
36894
|
while (head < queue.length) {
|
|
36575
36895
|
const vertex = queue[head++];
|
|
36576
|
-
closestDist = bfsVisitNeighbors(vertex, graph,
|
|
36896
|
+
closestDist = bfsVisitNeighbors(vertex, graph, dist5, queue);
|
|
36897
|
+
}
|
|
36898
|
+
bfsFixDisconnected(n, dist5, closestDist);
|
|
36899
|
+
}
|
|
36900
|
+
function packedIndex(i, j, n) {
|
|
36901
|
+
return i * (2 * n - i - 1) / 2 + j;
|
|
36902
|
+
}
|
|
36903
|
+
function computeWeightedApspPacked(graph, n) {
|
|
36904
|
+
const result = new Float32Array(n * (n + 1) / 2);
|
|
36905
|
+
const di = new Float32Array(n);
|
|
36906
|
+
for (let i = 0; i < n; i++) {
|
|
36907
|
+
dijkstra(i, graph, n, di);
|
|
36908
|
+
for (let j = i; j < n; j++) result[packedIndex(i, j, n)] = di[j];
|
|
36909
|
+
}
|
|
36910
|
+
return result;
|
|
36911
|
+
}
|
|
36912
|
+
|
|
36913
|
+
// src/common/crand.ts
|
|
36914
|
+
var C_RAND_MAX = 2147483647;
|
|
36915
|
+
var UNSEEDED_STATE2 = 1;
|
|
36916
|
+
var state2 = UNSEEDED_STATE2;
|
|
36917
|
+
registerRenderState(() => {
|
|
36918
|
+
state2 = UNSEEDED_STATE2;
|
|
36919
|
+
});
|
|
36920
|
+
function csrand(seed) {
|
|
36921
|
+
state2 = seed;
|
|
36922
|
+
}
|
|
36923
|
+
function crand() {
|
|
36924
|
+
state2 = state2 * 16807 % 2147483647;
|
|
36925
|
+
return state2;
|
|
36926
|
+
}
|
|
36927
|
+
function cdrand() {
|
|
36928
|
+
return crand() / C_RAND_MAX;
|
|
36929
|
+
}
|
|
36930
|
+
function gvRandom(bound) {
|
|
36931
|
+
const discardThreshold = C_RAND_MAX - 2147483648 % bound;
|
|
36932
|
+
let r;
|
|
36933
|
+
do {
|
|
36934
|
+
r = crand();
|
|
36935
|
+
} while (r > discardThreshold);
|
|
36936
|
+
return r % bound;
|
|
36937
|
+
}
|
|
36938
|
+
function gvPermutation(bound) {
|
|
36939
|
+
if (bound <= 0) return [];
|
|
36940
|
+
const p = [];
|
|
36941
|
+
for (let i = 0; i < bound; i++) p.push(i);
|
|
36942
|
+
for (let i = bound - 1; i > 0; --i) {
|
|
36943
|
+
const j = gvRandom(i + 1);
|
|
36944
|
+
const t = p[i];
|
|
36945
|
+
p[i] = p[j];
|
|
36946
|
+
p[j] = t;
|
|
36577
36947
|
}
|
|
36578
|
-
|
|
36948
|
+
return p;
|
|
36949
|
+
}
|
|
36950
|
+
|
|
36951
|
+
// src/layout/neato/matrix-ops.ts
|
|
36952
|
+
var fr = Math.fround;
|
|
36953
|
+
function fma2(a, b, c) {
|
|
36954
|
+
const p = a * b;
|
|
36955
|
+
return Number.isFinite(p) && Number.isFinite(c) ? fma(a, b, c) : p + c;
|
|
36956
|
+
}
|
|
36957
|
+
function orthog1(n, vec) {
|
|
36958
|
+
let sum = 0;
|
|
36959
|
+
for (let i = 0; i < n; i++) sum += vec[i];
|
|
36960
|
+
sum /= n;
|
|
36961
|
+
for (let i = 0; i < n; i++) vec[i] = vec[i] - sum;
|
|
36962
|
+
}
|
|
36963
|
+
function orthog1f(n, vec) {
|
|
36964
|
+
let sum = fr(0);
|
|
36965
|
+
for (let i = 0; i < n; i++) sum = fr(sum + vec[i]);
|
|
36966
|
+
sum = fr(sum / n);
|
|
36967
|
+
for (let i = 0; i < n; i++) vec[i] = vec[i] - sum;
|
|
36968
|
+
}
|
|
36969
|
+
function rightMultWithVectorFF(m, n, vector, result) {
|
|
36970
|
+
for (let i = 0; i < n; i++) result[i] = 0;
|
|
36971
|
+
let index = 0;
|
|
36972
|
+
for (let i = 0; i < n; i++) {
|
|
36973
|
+
const vi = vector[i];
|
|
36974
|
+
let res = fr(m[index++] * vi);
|
|
36975
|
+
for (let j = i + 1; j < n; j++, index++) {
|
|
36976
|
+
res = fr(res + fr(m[index] * vector[j]));
|
|
36977
|
+
result[j] = result[j] + fr(m[index] * vi);
|
|
36978
|
+
}
|
|
36979
|
+
result[i] = result[i] + res;
|
|
36980
|
+
}
|
|
36981
|
+
}
|
|
36982
|
+
function vectorsSubtractionF(n, v1, v2, result) {
|
|
36983
|
+
for (let i = 0; i < n; i++) result[i] = v1[i] - v2[i];
|
|
36984
|
+
}
|
|
36985
|
+
function vectorsMultAdditionF(n, v1, alpha, v2) {
|
|
36986
|
+
const a = fr(alpha);
|
|
36987
|
+
for (let i = 0; i < n; i++) v1[i] = v1[i] + fr(a * v2[i]);
|
|
36988
|
+
}
|
|
36989
|
+
function vectorsInnerProductF(n, v1, v2) {
|
|
36990
|
+
let result = 0;
|
|
36991
|
+
for (let i = 0; i < n; i++) result += fr(v1[i] * v2[i]);
|
|
36992
|
+
return result;
|
|
36993
|
+
}
|
|
36994
|
+
function copyVectorF(n, src, dst) {
|
|
36995
|
+
for (let i = 0; i < n; i++) dst[i] = src[i];
|
|
36996
|
+
}
|
|
36997
|
+
function maxAbsF(n, vec) {
|
|
36998
|
+
let max = fr(-1e30);
|
|
36999
|
+
for (let i = 0; i < n; i++) {
|
|
37000
|
+
const a = fr(Math.abs(vec[i]));
|
|
37001
|
+
if (a > max) max = a;
|
|
37002
|
+
}
|
|
37003
|
+
return max;
|
|
37004
|
+
}
|
|
37005
|
+
function squareVec(n, vec) {
|
|
37006
|
+
for (let i = 0; i < n; i++) vec[i] = vec[i] * vec[i];
|
|
37007
|
+
}
|
|
37008
|
+
function invertVec(n, vec) {
|
|
37009
|
+
for (let i = 0; i < n; i++) {
|
|
37010
|
+
if (vec[i] !== 0) vec[i] = 1 / vec[i];
|
|
37011
|
+
}
|
|
37012
|
+
}
|
|
37013
|
+
function sqrtVecF(n, source, target) {
|
|
37014
|
+
for (let i = 0; i < n; i++) {
|
|
37015
|
+
if (source[i] >= 0) target[i] = fr(Math.sqrt(source[i]));
|
|
37016
|
+
}
|
|
37017
|
+
}
|
|
37018
|
+
function invertSqrtVec(n, vec) {
|
|
37019
|
+
for (let i = 0; i < n; i++) {
|
|
37020
|
+
if (vec[i] > 0) vec[i] = 1 / fr(Math.sqrt(vec[i]));
|
|
37021
|
+
}
|
|
37022
|
+
}
|
|
37023
|
+
var BLOCK_NONE = 1;
|
|
37024
|
+
function innerProduct(n, v1, v2, block) {
|
|
37025
|
+
let result = 0;
|
|
37026
|
+
const blocked = block === BLOCK_NONE ? 0 : n - n % block;
|
|
37027
|
+
let i = 0;
|
|
37028
|
+
for (; i < blocked; i++) result += v1[i] * v2[i];
|
|
37029
|
+
for (; i < n; i++) result = fma2(v1[i], v2[i], result);
|
|
37030
|
+
return result;
|
|
37031
|
+
}
|
|
37032
|
+
function scadd(vec1, end, fac, vec2) {
|
|
37033
|
+
for (let i = 0; i <= end; i++) vec1[i] = fma2(fac, vec2[i], vec1[i]);
|
|
37034
|
+
}
|
|
37035
|
+
function norm(vec, end, block) {
|
|
37036
|
+
return Math.sqrt(innerProduct(end + 1, vec, vec, block));
|
|
37037
|
+
}
|
|
37038
|
+
function vectorsScalarMult(n, vector, alpha, result) {
|
|
37039
|
+
for (let i = 0; i < n; i++) result[i] = vector[i] * alpha;
|
|
37040
|
+
}
|
|
37041
|
+
function copyVector(n, source, dest) {
|
|
37042
|
+
for (let i = 0; i < n; i++) dest[i] = source[i];
|
|
37043
|
+
}
|
|
37044
|
+
function vectorsAddition(n, v1, v2, result) {
|
|
37045
|
+
for (let i = 0; i < n; i++) result[i] = v1[i] + v2[i];
|
|
37046
|
+
}
|
|
37047
|
+
function vectorsSubtraction(n, v1, v2, result) {
|
|
37048
|
+
for (let i = 0; i < n; i++) result[i] = v1[i] - v2[i];
|
|
37049
|
+
}
|
|
37050
|
+
function maxAbs(n, vector) {
|
|
37051
|
+
let maxVal = -1e50;
|
|
37052
|
+
for (let i = 0; i < n; i++) {
|
|
37053
|
+
const a = Math.abs(vector[i]);
|
|
37054
|
+
if (a > maxVal) maxVal = a;
|
|
37055
|
+
}
|
|
37056
|
+
return maxVal;
|
|
37057
|
+
}
|
|
37058
|
+
function rightMultWithVectorF(matrix, n, vector, result, block) {
|
|
37059
|
+
const blocked = block === BLOCK_NONE ? 0 : n - n % block;
|
|
37060
|
+
for (let i = 0; i < n; i++) {
|
|
37061
|
+
const row = matrix[i];
|
|
37062
|
+
let res = 0;
|
|
37063
|
+
let j = 0;
|
|
37064
|
+
for (; j < blocked; j++) res += row[j] * vector[j];
|
|
37065
|
+
for (; j < n; j++) res = fma2(row[j], vector[j], res);
|
|
37066
|
+
result[i] = res;
|
|
37067
|
+
}
|
|
37068
|
+
}
|
|
37069
|
+
function rightMultWithVector(matrix, n, vector, result) {
|
|
37070
|
+
for (let i = 0; i < n; i++) {
|
|
37071
|
+
let res = 0;
|
|
37072
|
+
const row = matrix[i];
|
|
37073
|
+
for (let j = 0; j < row.nedges; j++) res = fma2(row.ewgts[j], vector[row.edges[j]], res);
|
|
37074
|
+
result[i] = res;
|
|
37075
|
+
}
|
|
37076
|
+
}
|
|
37077
|
+
var RANGE = 500;
|
|
37078
|
+
function initVecOrth1(n, vec) {
|
|
37079
|
+
for (let i = 0; i < n; i++) vec[i] = crand() % RANGE;
|
|
37080
|
+
orthog1(n, vec);
|
|
37081
|
+
}
|
|
37082
|
+
|
|
37083
|
+
// src/layout/neato/conjgrad.ts
|
|
37084
|
+
var BLOCK_INITIAL_RR = 4;
|
|
37085
|
+
var BLOCK_P_AP = 8;
|
|
37086
|
+
function cgNextDirection(n, w, alpha, rR) {
|
|
37087
|
+
vectorsScalarMult(n, w.Ap, alpha, w.Ap);
|
|
37088
|
+
vectorsSubtraction(n, w.r, w.Ap, w.r);
|
|
37089
|
+
const rRNew = innerProduct(n, w.r, w.r, BLOCK_NONE);
|
|
37090
|
+
if (rR === 0) {
|
|
37091
|
+
agerrorf("conjugate_gradient: unexpected length 0 vector\n");
|
|
37092
|
+
return null;
|
|
37093
|
+
}
|
|
37094
|
+
const beta = rRNew / rR;
|
|
37095
|
+
vectorsScalarMult(n, w.p, beta, w.p);
|
|
37096
|
+
vectorsAddition(n, w.r, w.p, w.p);
|
|
37097
|
+
return rRNew;
|
|
37098
|
+
}
|
|
37099
|
+
function cgStart(A3, x, b, n) {
|
|
37100
|
+
const w = {
|
|
37101
|
+
r: new Float64Array(n),
|
|
37102
|
+
p: new Float64Array(n),
|
|
37103
|
+
Ap: new Float64Array(n),
|
|
37104
|
+
alphap: new Float64Array(n)
|
|
37105
|
+
};
|
|
37106
|
+
const Ax = new Float64Array(n);
|
|
37107
|
+
const orthB = Float64Array.from(b.subarray(0, n));
|
|
37108
|
+
orthog1(n, orthB);
|
|
37109
|
+
orthog1(n, x);
|
|
37110
|
+
rightMultWithVector(A3, n, x, Ax);
|
|
37111
|
+
vectorsSubtraction(n, orthB, Ax, w.r);
|
|
37112
|
+
w.p.set(w.r.subarray(0, n));
|
|
37113
|
+
return w;
|
|
37114
|
+
}
|
|
37115
|
+
function conjugateGradient(A3, x, b, n, tol, maxIterations) {
|
|
37116
|
+
const w = cgStart(A3, x, b, n);
|
|
37117
|
+
let rR = innerProduct(n, w.r, w.r, BLOCK_INITIAL_RR);
|
|
37118
|
+
for (let i = 0; i < maxIterations && maxAbs(n, w.r) > tol; i++) {
|
|
37119
|
+
rightMultWithVector(A3, n, w.p, w.Ap);
|
|
37120
|
+
const pAp = innerProduct(n, w.p, w.Ap, BLOCK_P_AP);
|
|
37121
|
+
if (pAp === 0) break;
|
|
37122
|
+
const alpha = rR / pAp;
|
|
37123
|
+
vectorsScalarMult(n, w.p, alpha, w.alphap);
|
|
37124
|
+
vectorsAddition(n, x, w.alphap, x);
|
|
37125
|
+
if (i < maxIterations - 1) {
|
|
37126
|
+
const next = cgNextDirection(n, w, alpha, rR);
|
|
37127
|
+
if (next === null) return 1;
|
|
37128
|
+
rR = next;
|
|
37129
|
+
}
|
|
37130
|
+
}
|
|
37131
|
+
return 0;
|
|
37132
|
+
}
|
|
37133
|
+
var CGF_BLOCK_AX = 4;
|
|
37134
|
+
var CGF_BLOCK_AP = 4;
|
|
37135
|
+
var CGF_BLOCK_INITIAL_RR = 4;
|
|
37136
|
+
var CGF_BLOCK_P_AP = 8;
|
|
37137
|
+
function cgfInit(A3, x, b, n, ortho1) {
|
|
37138
|
+
const orthB = new Float64Array(n);
|
|
37139
|
+
copyVector(n, b, orthB);
|
|
37140
|
+
if (ortho1) {
|
|
37141
|
+
orthog1(n, orthB);
|
|
37142
|
+
orthog1(n, x);
|
|
37143
|
+
}
|
|
37144
|
+
const Ax = new Float64Array(n);
|
|
37145
|
+
rightMultWithVectorF(A3, n, x, Ax, CGF_BLOCK_AX);
|
|
37146
|
+
const r = new Float64Array(n);
|
|
37147
|
+
vectorsSubtraction(n, orthB, Ax, r);
|
|
37148
|
+
const p = new Float64Array(n);
|
|
37149
|
+
copyVector(n, r, p);
|
|
37150
|
+
return {
|
|
37151
|
+
r,
|
|
37152
|
+
p,
|
|
37153
|
+
Ap: new Float64Array(n),
|
|
37154
|
+
alphap: new Float64Array(n),
|
|
37155
|
+
rr: innerProduct(n, r, r, CGF_BLOCK_INITIAL_RR)
|
|
37156
|
+
};
|
|
37157
|
+
}
|
|
37158
|
+
function cgfUpdate(n, alpha, st) {
|
|
37159
|
+
vectorsScalarMult(n, st.Ap, alpha, st.Ap);
|
|
37160
|
+
vectorsSubtraction(n, st.r, st.Ap, st.r);
|
|
37161
|
+
const rrNew = innerProduct(n, st.r, st.r, BLOCK_NONE);
|
|
37162
|
+
if (st.rr === 0) {
|
|
37163
|
+
agerrorf("conjugate_gradient: unexpected length 0 vector\n");
|
|
37164
|
+
return 1;
|
|
37165
|
+
}
|
|
37166
|
+
const beta = rrNew / st.rr;
|
|
37167
|
+
st.rr = rrNew;
|
|
37168
|
+
vectorsScalarMult(n, st.p, beta, st.p);
|
|
37169
|
+
vectorsAddition(n, st.r, st.p, st.p);
|
|
37170
|
+
return 0;
|
|
37171
|
+
}
|
|
37172
|
+
function conjugateGradientF(A3, x, b, n, opts) {
|
|
37173
|
+
const { tol, maxIterations, ortho1 } = opts;
|
|
37174
|
+
const st = cgfInit(A3, x, b, n, ortho1);
|
|
37175
|
+
for (let i = 0; i < maxIterations && maxAbs(n, st.r) > tol; i++) {
|
|
37176
|
+
rightMultWithVectorF(A3, n, st.p, st.Ap, CGF_BLOCK_AP);
|
|
37177
|
+
const pAp = innerProduct(n, st.p, st.Ap, CGF_BLOCK_P_AP);
|
|
37178
|
+
if (pAp === 0) break;
|
|
37179
|
+
const alpha = st.rr / pAp;
|
|
37180
|
+
vectorsScalarMult(n, st.p, alpha, st.alphap);
|
|
37181
|
+
vectorsAddition(n, x, st.alphap, x);
|
|
37182
|
+
if (i < maxIterations - 1 && cgfUpdate(n, alpha, st) === 1) return 1;
|
|
37183
|
+
}
|
|
37184
|
+
return 0;
|
|
36579
37185
|
}
|
|
36580
37186
|
|
|
36581
37187
|
// src/layout/neato/stress.ts
|
|
37188
|
+
var TOLERANCE_CG = 1e-3;
|
|
36582
37189
|
var DFLT_ITERATIONS = 200;
|
|
37190
|
+
var OPT_SMART_INIT = 4;
|
|
37191
|
+
function mdsModel(graph, nG) {
|
|
37192
|
+
if (graph[0].ewgts.length === 0) return null;
|
|
37193
|
+
const Dij = computeWeightedApspPacked(graph, nG);
|
|
37194
|
+
let shift = 0;
|
|
37195
|
+
for (let i = 0; i < nG; i++) {
|
|
37196
|
+
shift += i;
|
|
37197
|
+
for (let e = 1; e < graph[i].nedges; e++) {
|
|
37198
|
+
const j = graph[i].edges[e];
|
|
37199
|
+
if (j < i) continue;
|
|
37200
|
+
Dij[i * nG + j - shift] = graph[i].ewgts[e];
|
|
37201
|
+
}
|
|
37202
|
+
}
|
|
37203
|
+
return Dij;
|
|
37204
|
+
}
|
|
36583
37205
|
|
|
36584
37206
|
// src/layout/neato/sgd-dijkstra.ts
|
|
36585
|
-
var
|
|
37207
|
+
var FLT_MAX2 = 34028234663852886e22;
|
|
36586
37208
|
var left = (i) => 2 * i;
|
|
36587
37209
|
var right = (i) => 2 * i + 1;
|
|
36588
37210
|
var parent = (i) => Math.trunc(i / 2);
|
|
36589
|
-
var greaterPriority = (h, i, j,
|
|
37211
|
+
var greaterPriority = (h, i, j, dist5) => dist5[h.data[i]] < dist5[h.data[j]];
|
|
36590
37212
|
function exchange2(h, i, j) {
|
|
36591
37213
|
const t = h.data[i];
|
|
36592
37214
|
h.data[i] = h.data[j];
|
|
@@ -36594,19 +37216,19 @@ function exchange2(h, i, j) {
|
|
|
36594
37216
|
h.index[h.data[i]] = i;
|
|
36595
37217
|
h.index[h.data[j]] = j;
|
|
36596
37218
|
}
|
|
36597
|
-
function heapify(h, start,
|
|
37219
|
+
function heapify(h, start, dist5) {
|
|
36598
37220
|
let i = start;
|
|
36599
37221
|
for (; ; ) {
|
|
36600
37222
|
const l = left(i);
|
|
36601
37223
|
const r = right(i);
|
|
36602
|
-
let largest = l < h.heapSize && greaterPriority(h, l, i,
|
|
36603
|
-
if (r < h.heapSize && greaterPriority(h, r, largest,
|
|
37224
|
+
let largest = l < h.heapSize && greaterPriority(h, l, i, dist5) ? l : i;
|
|
37225
|
+
if (r < h.heapSize && greaterPriority(h, r, largest, dist5)) largest = r;
|
|
36604
37226
|
if (largest === i) break;
|
|
36605
37227
|
exchange2(h, largest, i);
|
|
36606
37228
|
i = largest;
|
|
36607
37229
|
}
|
|
36608
37230
|
}
|
|
36609
|
-
function initHeap(startVertex,
|
|
37231
|
+
function initHeap(startVertex, dist5, n) {
|
|
36610
37232
|
const h = {
|
|
36611
37233
|
data: new Int32Array(Math.max(n - 1, 0)),
|
|
36612
37234
|
heapSize: n - 1,
|
|
@@ -36618,23 +37240,23 @@ function initHeap(startVertex, dist4, n) {
|
|
|
36618
37240
|
h.data[count] = i;
|
|
36619
37241
|
h.index[i] = count++;
|
|
36620
37242
|
}
|
|
36621
|
-
for (let j = Math.trunc((n - 1) / 2); j >= 0; j--) heapify(h, j,
|
|
37243
|
+
for (let j = Math.trunc((n - 1) / 2); j >= 0; j--) heapify(h, j, dist5);
|
|
36622
37244
|
return h;
|
|
36623
37245
|
}
|
|
36624
|
-
function extractMax(h,
|
|
37246
|
+
function extractMax(h, dist5) {
|
|
36625
37247
|
if (h.heapSize === 0) return -1;
|
|
36626
37248
|
const max = h.data[0];
|
|
36627
37249
|
h.data[0] = h.data[h.heapSize - 1];
|
|
36628
37250
|
h.index[h.data[0]] = 0;
|
|
36629
37251
|
h.heapSize--;
|
|
36630
|
-
heapify(h, 0,
|
|
37252
|
+
heapify(h, 0, dist5);
|
|
36631
37253
|
return max;
|
|
36632
37254
|
}
|
|
36633
|
-
function increaseKey(h, v, newDist,
|
|
36634
|
-
if (
|
|
36635
|
-
|
|
37255
|
+
function increaseKey(h, v, newDist, dist5) {
|
|
37256
|
+
if (dist5[v] <= newDist) return;
|
|
37257
|
+
dist5[v] = newDist;
|
|
36636
37258
|
let i = h.index[v];
|
|
36637
|
-
while (i > 0 &&
|
|
37259
|
+
while (i > 0 && dist5[h.data[parent(i)]] > newDist) {
|
|
36638
37260
|
h.data[i] = h.data[parent(i)];
|
|
36639
37261
|
h.index[h.data[i]] = i;
|
|
36640
37262
|
i = parent(i);
|
|
@@ -36643,7 +37265,7 @@ function increaseKey(h, v, newDist, dist4) {
|
|
|
36643
37265
|
h.index[v] = i;
|
|
36644
37266
|
}
|
|
36645
37267
|
function dijkstraSgd(graph, source, terms) {
|
|
36646
|
-
const dists = new Float32Array(graph.n).fill(
|
|
37268
|
+
const dists = new Float32Array(graph.n).fill(FLT_MAX2);
|
|
36647
37269
|
dists[source] = 0;
|
|
36648
37270
|
for (let i = graph.sources[source]; i < graph.sources[source + 1]; i++) {
|
|
36649
37271
|
dists[graph.targets[i]] = graph.weights[i];
|
|
@@ -36652,7 +37274,7 @@ function dijkstraSgd(graph, source, terms) {
|
|
|
36652
37274
|
let offset = 0;
|
|
36653
37275
|
for (let closest = extractMax(h, dists); closest >= 0; closest = extractMax(h, dists)) {
|
|
36654
37276
|
const d = dists[closest];
|
|
36655
|
-
if (d ===
|
|
37277
|
+
if (d === FLT_MAX2) break;
|
|
36656
37278
|
if (graph.pinneds[closest] || closest < source) {
|
|
36657
37279
|
terms[offset++] = { i: source, j: closest, d, w: Math.fround(1 / Math.fround(d * d)) };
|
|
36658
37280
|
}
|
|
@@ -36671,7 +37293,7 @@ function lenattr(ep, g) {
|
|
|
36671
37293
|
const val2 = /^\s*[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?/.exec(s);
|
|
36672
37294
|
const len = val2 === null ? Number.NaN : parseFloat(val2[0]);
|
|
36673
37295
|
if (Number.isNaN(len) || len < 0 || len === 0) {
|
|
36674
|
-
|
|
37296
|
+
agwarningf(`bad edge len "${s}" in ${g.name} - setting to ${DEFAULT_EDGE_LEN.toFixed(2)}`);
|
|
36675
37297
|
return DEFAULT_EDGE_LEN;
|
|
36676
37298
|
}
|
|
36677
37299
|
return len;
|
|
@@ -36835,12 +37457,11 @@ function neatoMode(g) {
|
|
|
36835
37457
|
if (str === void 0 || str === "") return MODE_MAJOR;
|
|
36836
37458
|
const mode = modeByName().get(str);
|
|
36837
37459
|
if (mode !== void 0) return mode;
|
|
36838
|
-
|
|
37460
|
+
agwarningf(`Illegal value ${str} for attribute "mode" in graph ${g.root.name} - ignored`);
|
|
36839
37461
|
return MODE_MAJOR;
|
|
36840
37462
|
}
|
|
36841
37463
|
function checkMode(g, mode) {
|
|
36842
|
-
const value = g.root.attrs.get("mode") ||
|
|
36843
|
-
if (mode === MODE_HIER) unsupported("mode", value, "hierarchical stress majorization");
|
|
37464
|
+
const value = g.root.attrs.get("mode") || "ipsep";
|
|
36844
37465
|
if (mode === MODE_IPSEP && ipsepHasConstraints(g)) {
|
|
36845
37466
|
unsupported("mode", value, "constrained (ipsep) majorization");
|
|
36846
37467
|
}
|
|
@@ -37193,10 +37814,10 @@ function solve(a, b, c, n) {
|
|
|
37193
37814
|
}
|
|
37194
37815
|
|
|
37195
37816
|
// src/layout/neato/kk-paths.ts
|
|
37196
|
-
function newPathState(n,
|
|
37817
|
+
function newPathState(n, dist5, adj, initialDist2) {
|
|
37197
37818
|
return {
|
|
37198
37819
|
n,
|
|
37199
|
-
dist:
|
|
37820
|
+
dist: dist5,
|
|
37200
37821
|
adj,
|
|
37201
37822
|
initialDist: initialDist2,
|
|
37202
37823
|
heap: new Int32Array(n + 1),
|
|
@@ -37274,10 +37895,10 @@ function s1(s, src) {
|
|
|
37274
37895
|
function shortestPath2(s) {
|
|
37275
37896
|
for (let v = 0; v < s.n; v++) s1(s, v);
|
|
37276
37897
|
}
|
|
37277
|
-
function
|
|
37898
|
+
function mdsModel2(dist5, n, edges) {
|
|
37278
37899
|
for (const { tailSeq: i, headSeq: j, len } of edges) {
|
|
37279
37900
|
if (i === j) continue;
|
|
37280
|
-
for (const k of [i * n + j, j * n + i]) if (k <
|
|
37901
|
+
for (const k of [i * n + j, j * n + i]) if (k < dist5.length) dist5[k] = len;
|
|
37281
37902
|
}
|
|
37282
37903
|
}
|
|
37283
37904
|
|
|
@@ -37370,12 +37991,12 @@ function initialPositions2(g, st) {
|
|
|
37370
37991
|
}
|
|
37371
37992
|
}
|
|
37372
37993
|
function distvec(p0, p1, del) {
|
|
37373
|
-
let
|
|
37994
|
+
let dist5 = 0;
|
|
37374
37995
|
for (let k = 0; k < NDIM; k++) {
|
|
37375
37996
|
del[k] = p0[k] - p1[k];
|
|
37376
|
-
|
|
37997
|
+
dist5 += del[k] * del[k];
|
|
37377
37998
|
}
|
|
37378
|
-
return Math.sqrt(
|
|
37999
|
+
return Math.sqrt(dist5);
|
|
37379
38000
|
}
|
|
37380
38001
|
function springFactors(g) {
|
|
37381
38002
|
const byEnds = /* @__PURE__ */ new Map();
|
|
@@ -37392,9 +38013,9 @@ function fillRow(st, i, del) {
|
|
|
37392
38013
|
const vi = st.nodes[i];
|
|
37393
38014
|
for (let j = 0; j < st.n; j++) {
|
|
37394
38015
|
if (i === j) continue;
|
|
37395
|
-
const
|
|
38016
|
+
const dist5 = distvec(vi.info.pos, st.nodes[j].info.pos, del);
|
|
37396
38017
|
for (let k = 0; k < NDIM; k++) {
|
|
37397
|
-
const v = st.spring[i * st.n + j] * (del[k] - st.dist[i * st.n + j] * del[k] /
|
|
38018
|
+
const v = st.spring[i * st.n + j] * (del[k] - st.dist[i * st.n + j] * del[k] / dist5);
|
|
37398
38019
|
st.t[(i * st.n + j) * NDIM + k] = v;
|
|
37399
38020
|
st.sumT[i * NDIM + k] += v;
|
|
37400
38021
|
}
|
|
@@ -37423,9 +38044,9 @@ function updateArrays(st, i) {
|
|
|
37423
38044
|
for (let k = 0; k < NDIM; k++) st.sumT[i * NDIM + k] = 0;
|
|
37424
38045
|
for (let j = 0; j < n; j++) {
|
|
37425
38046
|
if (i === j) continue;
|
|
37426
|
-
const
|
|
38047
|
+
const dist5 = distvec(vi.info.pos, st.nodes[j].info.pos, del);
|
|
37427
38048
|
for (let k = 0; k < NDIM; k++) {
|
|
37428
|
-
const tij = st.spring[i * n + j] * (del[k] - st.dist[i * n + j] * del[k] /
|
|
38049
|
+
const tij = st.spring[i * n + j] * (del[k] - st.dist[i * n + j] * del[k] / dist5);
|
|
37429
38050
|
st.t[(i * n + j) * NDIM + k] = tij;
|
|
37430
38051
|
st.sumT[i * NDIM + k] += tij;
|
|
37431
38052
|
const old = st.t[(j * n + i) * NDIM + k];
|
|
@@ -37492,7 +38113,7 @@ function moveNode(st, m) {
|
|
|
37492
38113
|
function solveModel(g, st) {
|
|
37493
38114
|
for (let m = chooseNode(st); m >= 0; m = chooseNode(st)) moveNode(st, m);
|
|
37494
38115
|
if (st.move === st.maxIter) {
|
|
37495
|
-
|
|
38116
|
+
agwarningf(`Max. iterations (${st.maxIter}) reached on graph ${g.name}`);
|
|
37496
38117
|
}
|
|
37497
38118
|
}
|
|
37498
38119
|
function mdsEdges(g, nodes, lens) {
|
|
@@ -37505,84 +38126,852 @@ function kkNeato(g, nG, model) {
|
|
|
37505
38126
|
if (nG < 2 || maxIter < 0) return;
|
|
37506
38127
|
const { st, adj, ini, lens } = scanGraphMode(g, maxIter);
|
|
37507
38128
|
shortestPath2(newPathState(st.n, st.dist, adj, ini));
|
|
37508
|
-
if (model === MODEL_MDS2)
|
|
38129
|
+
if (model === MODEL_MDS2) mdsModel2(st.dist, st.n, mdsEdges(g, st.nodes, lens));
|
|
37509
38130
|
initialPositions2(g, st);
|
|
37510
38131
|
diffeqModel(g, st);
|
|
37511
38132
|
solveModel(g, st);
|
|
37512
38133
|
}
|
|
37513
38134
|
|
|
37514
|
-
// src/layout/neato/
|
|
37515
|
-
var
|
|
37516
|
-
|
|
37517
|
-
|
|
37518
|
-
|
|
37519
|
-
|
|
37520
|
-
for (
|
|
38135
|
+
// src/layout/neato/make-graph-data.ts
|
|
38136
|
+
var MODE_IPSEP2 = 3;
|
|
38137
|
+
var EDIST_IN = 1;
|
|
38138
|
+
var EDIST_OUT = -1;
|
|
38139
|
+
var EDIST_NONE = 0;
|
|
38140
|
+
function graphHasLen(g) {
|
|
38141
|
+
for (const e of g.edges) {
|
|
38142
|
+
if (e.attrs.has("len")) return true;
|
|
38143
|
+
}
|
|
38144
|
+
return false;
|
|
37521
38145
|
}
|
|
37522
|
-
|
|
37523
|
-
|
|
37524
|
-
|
|
37525
|
-
|
|
37526
|
-
|
|
38146
|
+
var edistsOf = (v) => v.edists;
|
|
38147
|
+
function reverseBackEdge(graph, i, e, mode) {
|
|
38148
|
+
const node = graph[i];
|
|
38149
|
+
const j = node.edges[e];
|
|
38150
|
+
edistsOf(node)[e] = mode === MODE_IPSEP2 ? EDIST_OUT : EDIST_IN;
|
|
38151
|
+
const target = graph[j];
|
|
38152
|
+
let f = 1;
|
|
38153
|
+
while (f < target.nedges && target.edges[f] !== i) f++;
|
|
38154
|
+
if (f >= target.nedges) throw new Error(`neato: edge ${i}-${j} has no reverse entry`);
|
|
38155
|
+
edistsOf(target)[f] = EDIST_OUT;
|
|
38156
|
+
}
|
|
38157
|
+
function dfsCycle(graph, start, st) {
|
|
38158
|
+
const { mode, mark, onstack } = st;
|
|
38159
|
+
const stack = [{ i: start, e: 1 }];
|
|
38160
|
+
mark[start] = 1;
|
|
38161
|
+
onstack[start] = 1;
|
|
38162
|
+
for (let frame = stack.at(-1); frame !== void 0; frame = stack.at(-1)) {
|
|
38163
|
+
const { i } = frame;
|
|
38164
|
+
const node = graph[i];
|
|
38165
|
+
if (frame.e >= node.nedges) {
|
|
38166
|
+
onstack[i] = 0;
|
|
38167
|
+
stack.pop();
|
|
38168
|
+
continue;
|
|
38169
|
+
}
|
|
38170
|
+
const e = frame.e++;
|
|
38171
|
+
if (edistsOf(node)[e] === EDIST_IN) continue;
|
|
38172
|
+
const j = node.edges[e];
|
|
38173
|
+
if (onstack[j]) {
|
|
38174
|
+
reverseBackEdge(graph, i, e, mode);
|
|
38175
|
+
} else if (!mark[j]) {
|
|
38176
|
+
mark[j] = 1;
|
|
38177
|
+
onstack[j] = 1;
|
|
38178
|
+
stack.push({ i: j, e: 1 });
|
|
38179
|
+
}
|
|
38180
|
+
}
|
|
37527
38181
|
}
|
|
37528
|
-
function
|
|
38182
|
+
function acyclic2(graph, nv, mode) {
|
|
38183
|
+
const st = { mode, mark: new Uint8Array(nv), onstack: new Uint8Array(nv) };
|
|
38184
|
+
for (let i = 0; i < nv; i++) {
|
|
38185
|
+
if (st.mark[i]) continue;
|
|
38186
|
+
dfsCycle(graph, i, st);
|
|
38187
|
+
}
|
|
38188
|
+
}
|
|
38189
|
+
function edgeDist2(dir, np, head) {
|
|
38190
|
+
if (dir !== void 0 && dir.startsWith("none")) return EDIST_NONE;
|
|
38191
|
+
return np === head ? EDIST_IN : EDIST_OUT;
|
|
38192
|
+
}
|
|
38193
|
+
function addNeighbours(g, np, entry, o) {
|
|
38194
|
+
const seen2 = /* @__PURE__ */ new Map();
|
|
38195
|
+
for (const ep of [...np.outEdges(g), ...np.inEdges(g)]) {
|
|
38196
|
+
if (ep.head === ep.tail) continue;
|
|
38197
|
+
const vp = ep.tail === np ? ep.head : ep.tail;
|
|
38198
|
+
const vid = vp.info.id;
|
|
38199
|
+
const dist5 = o.haveLen ? lateDouble(ep.attrs.get("len"), 1, 0) : 1;
|
|
38200
|
+
const idx = seen2.get(vid);
|
|
38201
|
+
if (idx !== void 0) {
|
|
38202
|
+
if (o.haveLen) entry.ewgts[idx] = Math.max(entry.ewgts[idx], dist5);
|
|
38203
|
+
continue;
|
|
38204
|
+
}
|
|
38205
|
+
seen2.set(vid, entry.nedges);
|
|
38206
|
+
entry.edges.push(vid);
|
|
38207
|
+
if (o.haveLen || o.haveDir) entry.ewgts.push(dist5);
|
|
38208
|
+
if (o.haveDir) edistsOf(entry).push(edgeDist2(ep.attrs.get("dir"), np, ep.head));
|
|
38209
|
+
entry.nedges++;
|
|
38210
|
+
}
|
|
38211
|
+
}
|
|
38212
|
+
function makeGraphDataC(g, nodeList, haveLen, haveDir, mode = -1) {
|
|
38213
|
+
const vtx = nodeList.map((_, i) => ({
|
|
38214
|
+
nedges: 1,
|
|
38215
|
+
edges: [i],
|
|
38216
|
+
ewgts: haveLen || haveDir ? [0] : [],
|
|
38217
|
+
...haveDir ? { edists: [0] } : {}
|
|
38218
|
+
}));
|
|
38219
|
+
for (const np of nodeList) addNeighbours(g, np, vtx[np.info.id], { haveLen, haveDir });
|
|
38220
|
+
if (haveDir) acyclic2(vtx, nodeList.length, mode);
|
|
38221
|
+
return vtx;
|
|
38222
|
+
}
|
|
38223
|
+
|
|
38224
|
+
// src/layout/neato/kkutils.ts
|
|
38225
|
+
function compareKeys(a, b) {
|
|
38226
|
+
if (a < b) return -1;
|
|
38227
|
+
if (a > b) return 1;
|
|
38228
|
+
return 0;
|
|
38229
|
+
}
|
|
38230
|
+
function gvSortByPlace(place, ordering, first, count) {
|
|
38231
|
+
const slice = Array.from(ordering.subarray(first, first + count));
|
|
38232
|
+
gvQsort(slice, (x, y) => compareKeys(place[x], place[y]));
|
|
38233
|
+
for (let i = 0; i < count; i++) ordering[first + i] = slice[i];
|
|
38234
|
+
}
|
|
38235
|
+
function quicksortPlace(place, ordering, size) {
|
|
38236
|
+
gvSortByPlace(place, ordering, 0, size);
|
|
38237
|
+
}
|
|
38238
|
+
function quicksortPlacef(place, ordering, first, last) {
|
|
38239
|
+
if (first < last) {
|
|
38240
|
+
gvSortByPlace(place, ordering, first, last - first + 1);
|
|
38241
|
+
}
|
|
38242
|
+
}
|
|
38243
|
+
function computeApspDijkstra(graph, n) {
|
|
38244
|
+
const dij = [];
|
|
38245
|
+
for (let i = 0; i < n; i++) dij.push(new Int32Array(n));
|
|
38246
|
+
for (let i = 0; i < n; i++) ngdijkstra(i, graph, n, dij[i]);
|
|
38247
|
+
return dij;
|
|
38248
|
+
}
|
|
38249
|
+
function computeApspSimple(graph, n) {
|
|
38250
|
+
const dij = [];
|
|
38251
|
+
for (let i = 0; i < n; i++) dij.push(new Int32Array(n));
|
|
38252
|
+
for (let i = 0; i < n; i++) bfs(i, graph, n, dij[i]);
|
|
38253
|
+
return dij;
|
|
38254
|
+
}
|
|
38255
|
+
function computeApsp(graph, n) {
|
|
38256
|
+
return graph[0].ewgts.length > 0 ? computeApspDijkstra(graph, n) : computeApspSimple(graph, n);
|
|
38257
|
+
}
|
|
38258
|
+
|
|
38259
|
+
// src/layout/neato/quad-prog-solve.ts
|
|
38260
|
+
var fr2 = Math.fround;
|
|
38261
|
+
var TOLERANCE = fr2(0.01);
|
|
38262
|
+
var BOUND = 1e9;
|
|
38263
|
+
var BLOCK_EPSILON = 1e-9;
|
|
38264
|
+
var NO_SPLIT = -1;
|
|
38265
|
+
var BITS = new DataView(new ArrayBuffer(8));
|
|
38266
|
+
function oddNeighbour(s, awayFromZero) {
|
|
38267
|
+
BITS.setFloat64(0, s);
|
|
38268
|
+
const hi = BITS.getUint32(0);
|
|
38269
|
+
const lo = BITS.getUint32(4);
|
|
38270
|
+
if (awayFromZero) {
|
|
38271
|
+
BITS.setUint32(4, lo + 1);
|
|
38272
|
+
} else if (lo === 0) {
|
|
38273
|
+
BITS.setUint32(0, hi - 1);
|
|
38274
|
+
BITS.setUint32(4, 4294967295);
|
|
38275
|
+
} else {
|
|
38276
|
+
BITS.setUint32(4, lo - 1);
|
|
38277
|
+
}
|
|
38278
|
+
return BITS.getFloat64(0);
|
|
38279
|
+
}
|
|
38280
|
+
function fmaf(a, b, c) {
|
|
38281
|
+
const p = a * b;
|
|
38282
|
+
const s = p + c;
|
|
38283
|
+
const bv = s - p;
|
|
38284
|
+
const err = p - (s - bv) + (c - bv);
|
|
38285
|
+
if (err === 0 || !Number.isFinite(s)) return fr2(s);
|
|
38286
|
+
BITS.setFloat64(0, s);
|
|
38287
|
+
if ((BITS.getUint32(4) & 1) !== 0) return fr2(s);
|
|
38288
|
+
return fr2(oddNeighbour(s, err > 0 === s > 0));
|
|
38289
|
+
}
|
|
38290
|
+
function blockPlaceNumerator(blockDeg, desPlaceBlock, negLapTimesDesired, toBlockConnectivity, curPlace) {
|
|
38291
|
+
const t = fmaf(blockDeg, desPlaceBlock, negLapTimesDesired);
|
|
38292
|
+
return fmaf(toBlockConnectivity, curPlace, t);
|
|
38293
|
+
}
|
|
38294
|
+
function equals(a, b) {
|
|
38295
|
+
return Math.abs(fr2(a - b)) < TOLERANCE;
|
|
38296
|
+
}
|
|
38297
|
+
function fminf(a, b) {
|
|
38298
|
+
if (Number.isNaN(a)) return b;
|
|
38299
|
+
if (Number.isNaN(b)) return a;
|
|
38300
|
+
return a < b ? a : b;
|
|
38301
|
+
}
|
|
38302
|
+
function fmaxf(a, b) {
|
|
38303
|
+
if (Number.isNaN(a)) return b;
|
|
38304
|
+
if (Number.isNaN(b)) return a;
|
|
38305
|
+
return a > b ? a : b;
|
|
38306
|
+
}
|
|
38307
|
+
function unpackMatrix(packedMat, n) {
|
|
38308
|
+
const flat = new Float32Array(n * n);
|
|
38309
|
+
const mat = new Array(n);
|
|
38310
|
+
for (let i = 0; i < n; i++) mat[i] = flat.subarray(i * n, (i + 1) * n);
|
|
38311
|
+
for (let i = 0, k = 0; i < n; i++) {
|
|
38312
|
+
for (let j = i; j < n; j++, k++) {
|
|
38313
|
+
mat[j][i] = mat[i][j] = packedMat[k];
|
|
38314
|
+
}
|
|
38315
|
+
}
|
|
38316
|
+
return mat;
|
|
38317
|
+
}
|
|
38318
|
+
function ensureMonotonicOrderingWithGaps(place, n, ordering, levels, numLevels, levelsGap) {
|
|
38319
|
+
let lowerBound = fr2(-1e9);
|
|
38320
|
+
let level = -1;
|
|
38321
|
+
let maxInLevel = 0;
|
|
38322
|
+
for (let i = 0; i < n; i++) {
|
|
38323
|
+
if (i >= maxInLevel) {
|
|
38324
|
+
level++;
|
|
38325
|
+
maxInLevel = level === numLevels ? n : levels[level];
|
|
38326
|
+
lowerBound = i > 0 ? fr2(place[ordering[i - 1]] + levelsGap) : fr2(-1e9);
|
|
38327
|
+
quicksortPlacef(place, ordering, i, maxInLevel - 1);
|
|
38328
|
+
}
|
|
38329
|
+
const node = ordering[i];
|
|
38330
|
+
if (place[node] < lowerBound) place[node] = lowerBound;
|
|
38331
|
+
}
|
|
38332
|
+
}
|
|
38333
|
+
function computeNodeLevels(e) {
|
|
38334
|
+
const lev = new Int32Array(e.n);
|
|
38335
|
+
let level = -1;
|
|
38336
|
+
let maxInLevel = 0;
|
|
38337
|
+
for (let i = 0; i < e.n; i++) {
|
|
38338
|
+
if (i >= maxInLevel) {
|
|
38339
|
+
level++;
|
|
38340
|
+
maxInLevel = level === e.numLevels ? e.n : e.levels[level];
|
|
38341
|
+
}
|
|
38342
|
+
lev[e.ordering[i]] = level;
|
|
38343
|
+
}
|
|
38344
|
+
return lev;
|
|
38345
|
+
}
|
|
38346
|
+
function growBlock(c, left2, curPlace) {
|
|
38347
|
+
const { place, lev, levelsGap, e } = c;
|
|
38348
|
+
const gap = e.fArray4;
|
|
38349
|
+
let targetPlace = curPlace;
|
|
38350
|
+
gap[e.ordering[left2]] = 0;
|
|
38351
|
+
let right2;
|
|
38352
|
+
for (right2 = left2 + 1; right2 < e.n; right2++) {
|
|
38353
|
+
if (lev[right2] > lev[right2 - 1]) {
|
|
38354
|
+
targetPlace = fr2(targetPlace + levelsGap);
|
|
38355
|
+
}
|
|
38356
|
+
const node = e.ordering[right2];
|
|
38357
|
+
if (Math.abs(fr2(place[node] - targetPlace)) > BLOCK_EPSILON) break;
|
|
38358
|
+
gap[node] = fr2(place[node] - curPlace);
|
|
38359
|
+
}
|
|
38360
|
+
return right2;
|
|
38361
|
+
}
|
|
38362
|
+
function computeDesiredPlaces(c, left2, right2) {
|
|
38363
|
+
const { e, place, b } = c;
|
|
38364
|
+
for (let i = left2; i < right2; i++) {
|
|
38365
|
+
const node = e.ordering[i];
|
|
38366
|
+
let newPlaceI = -b[node];
|
|
38367
|
+
const lapNode = e.A[node];
|
|
38368
|
+
for (let j = 0; j < e.n; j++) {
|
|
38369
|
+
if (j === node) continue;
|
|
38370
|
+
newPlaceI = fmaf(lapNode[j], place[j], newPlaceI);
|
|
38371
|
+
}
|
|
38372
|
+
e.fArray1[node] = fr2(fr2(newPlaceI / -lapNode[node]) - e.fArray4[node]);
|
|
38373
|
+
}
|
|
38374
|
+
}
|
|
38375
|
+
function collectWhere(c, from, to, test) {
|
|
38376
|
+
for (let j = from; j < to; j++) {
|
|
38377
|
+
const node = c.e.ordering[j];
|
|
38378
|
+
if (test(c.e.fArray1[node])) c.block.push(node);
|
|
38379
|
+
}
|
|
38380
|
+
}
|
|
38381
|
+
function orderBlockByLevels(c, left2, right2, curPlace) {
|
|
38382
|
+
const { e } = c;
|
|
38383
|
+
c.block.length = 0;
|
|
38384
|
+
let firstNextLevel = 0;
|
|
38385
|
+
for (let i = left2; i < right2; i = firstNextLevel) {
|
|
38386
|
+
const level = c.lev[e.ordering[i]];
|
|
38387
|
+
firstNextLevel = level === e.numLevels ? right2 : Math.min(right2, e.levels[level]);
|
|
38388
|
+
collectWhere(c, i, firstNextLevel, (d) => d < curPlace);
|
|
38389
|
+
collectWhere(c, i, firstNextLevel, (d) => d === curPlace);
|
|
38390
|
+
collectWhere(c, i, firstNextLevel, (d) => d > curPlace);
|
|
38391
|
+
}
|
|
38392
|
+
}
|
|
38393
|
+
function computePrefixDesiredPlaces(c, curPlace) {
|
|
38394
|
+
const { e, block } = c;
|
|
38395
|
+
let desPlaceBlock = 0;
|
|
38396
|
+
let blockDeg = 0;
|
|
38397
|
+
for (let i = 0; i < block.length; i++) {
|
|
38398
|
+
const node = block[i];
|
|
38399
|
+
let toBlockConnectivity = 0;
|
|
38400
|
+
const lapNode = e.A[node];
|
|
38401
|
+
for (let j = 0; j < i; j++) {
|
|
38402
|
+
toBlockConnectivity = fr2(toBlockConnectivity - lapNode[block[j]]);
|
|
38403
|
+
}
|
|
38404
|
+
toBlockConnectivity = fr2(toBlockConnectivity * 2);
|
|
38405
|
+
const num2 = blockPlaceNumerator(
|
|
38406
|
+
blockDeg,
|
|
38407
|
+
desPlaceBlock,
|
|
38408
|
+
fr2(-lapNode[node] * e.fArray1[node]),
|
|
38409
|
+
toBlockConnectivity,
|
|
38410
|
+
curPlace
|
|
38411
|
+
);
|
|
38412
|
+
desPlaceBlock = fr2(num2 / fr2(fr2(blockDeg - lapNode[node]) + toBlockConnectivity));
|
|
38413
|
+
e.fArray2[i] = desPlaceBlock;
|
|
38414
|
+
blockDeg = fr2(blockDeg + fr2(toBlockConnectivity - lapNode[node]));
|
|
38415
|
+
}
|
|
38416
|
+
if (e.n >= 0 && block.length === e.n) {
|
|
38417
|
+
e.fArray2[e.n - 1] = curPlace;
|
|
38418
|
+
}
|
|
38419
|
+
}
|
|
38420
|
+
function computeSuffixDesiredPlaces(c, curPlace) {
|
|
38421
|
+
const { e, block } = c;
|
|
38422
|
+
let desPlaceBlock = 0;
|
|
38423
|
+
let blockDeg = 0;
|
|
38424
|
+
for (let i = block.length - 1; i >= 0; i--) {
|
|
38425
|
+
const node = block[i];
|
|
38426
|
+
let toBlockConnectivity = 0;
|
|
38427
|
+
const lapNode = e.A[node];
|
|
38428
|
+
for (let j = i + 1; j < block.length; j++) {
|
|
38429
|
+
toBlockConnectivity = fr2(toBlockConnectivity - lapNode[block[j]]);
|
|
38430
|
+
}
|
|
38431
|
+
toBlockConnectivity = fr2(toBlockConnectivity * 2);
|
|
38432
|
+
const num2 = blockPlaceNumerator(
|
|
38433
|
+
blockDeg,
|
|
38434
|
+
desPlaceBlock,
|
|
38435
|
+
fr2(-lapNode[node] * e.fArray1[node]),
|
|
38436
|
+
toBlockConnectivity,
|
|
38437
|
+
curPlace
|
|
38438
|
+
);
|
|
38439
|
+
desPlaceBlock = fr2(num2 / fr2(fr2(blockDeg - lapNode[node]) + toBlockConnectivity));
|
|
38440
|
+
e.fArray3[i] = desPlaceBlock;
|
|
38441
|
+
blockDeg = fr2(blockDeg + fr2(toBlockConnectivity - lapNode[node]));
|
|
38442
|
+
}
|
|
38443
|
+
if (e.n >= 0 && block.length === e.n) {
|
|
38444
|
+
e.fArray3[0] = curPlace;
|
|
38445
|
+
}
|
|
38446
|
+
}
|
|
38447
|
+
var LIMITED = new Float64Array(2);
|
|
38448
|
+
function limitMoves(prefix, suffix, curPlace) {
|
|
38449
|
+
if (suffix < prefix) {
|
|
38450
|
+
if (suffix < curPlace) {
|
|
38451
|
+
if (prefix > curPlace) prefix = curPlace;
|
|
38452
|
+
suffix = prefix;
|
|
38453
|
+
} else if (prefix > curPlace) {
|
|
38454
|
+
prefix = suffix;
|
|
38455
|
+
}
|
|
38456
|
+
}
|
|
38457
|
+
LIMITED[0] = prefix;
|
|
38458
|
+
LIMITED[1] = suffix;
|
|
38459
|
+
}
|
|
38460
|
+
function findBestSplit(c, curPlace) {
|
|
38461
|
+
const { e, block } = c;
|
|
38462
|
+
let bestI = NO_SPLIT;
|
|
38463
|
+
let maxMovement = 0;
|
|
38464
|
+
for (let i = 0; i < block.length; i++) {
|
|
38465
|
+
const suffixDesPlace = e.fArray3[i];
|
|
38466
|
+
const prefixDesPlace = i > 0 ? e.fArray2[i - 1] : suffixDesPlace;
|
|
38467
|
+
limitMoves(prefixDesPlace, suffixDesPlace, curPlace);
|
|
38468
|
+
const movement = (block.length - i) * Math.abs(fr2(LIMITED[1] - curPlace)) + i * Math.abs(fr2(LIMITED[0] - curPlace));
|
|
38469
|
+
if (movement > maxMovement) {
|
|
38470
|
+
maxMovement = movement;
|
|
38471
|
+
bestI = i;
|
|
38472
|
+
}
|
|
38473
|
+
}
|
|
38474
|
+
return bestI;
|
|
38475
|
+
}
|
|
38476
|
+
function computeUpperBound(c, right2) {
|
|
38477
|
+
const { e, place, lev, levelsGap, block } = c;
|
|
38478
|
+
if (right2 >= e.n) return BOUND;
|
|
38479
|
+
const lastGap = e.fArray4[block[block.length - 1]];
|
|
38480
|
+
const nextPlace = place[e.ordering[right2]];
|
|
38481
|
+
if (lev[e.ordering[right2]] > lev[e.ordering[right2 - 1]]) {
|
|
38482
|
+
return fr2(fr2(nextPlace - levelsGap) - lastGap);
|
|
38483
|
+
}
|
|
38484
|
+
return fr2(nextPlace - lastGap);
|
|
38485
|
+
}
|
|
38486
|
+
function nextLowerBound(c, right2) {
|
|
38487
|
+
const { e, place, lev, levelsGap, block } = c;
|
|
38488
|
+
const last = place[block[block.length - 1]];
|
|
38489
|
+
if (right2 < e.n && lev[e.ordering[right2]] > lev[e.ordering[right2 - 1]]) {
|
|
38490
|
+
return fr2(last + levelsGap);
|
|
38491
|
+
}
|
|
38492
|
+
return last;
|
|
38493
|
+
}
|
|
38494
|
+
function moveSplitBlock(c, bestI, left2, right2, curPlace) {
|
|
38495
|
+
const { e, place, block } = c;
|
|
38496
|
+
let suffixDesPlace = e.fArray3[bestI];
|
|
38497
|
+
let prefixDesPlace = bestI > 0 ? e.fArray2[bestI - 1] : suffixDesPlace;
|
|
38498
|
+
suffixDesPlace = fminf(suffixDesPlace, computeUpperBound(c, right2));
|
|
38499
|
+
prefixDesPlace = fmaxf(prefixDesPlace, c.lowerBound);
|
|
38500
|
+
limitMoves(prefixDesPlace, suffixDesPlace, curPlace);
|
|
38501
|
+
prefixDesPlace = LIMITED[0];
|
|
38502
|
+
suffixDesPlace = LIMITED[1];
|
|
38503
|
+
for (let i = 0; i < bestI; i++) {
|
|
38504
|
+
place[block[i]] = fr2(prefixDesPlace + e.fArray4[block[i]]);
|
|
38505
|
+
}
|
|
38506
|
+
for (let i = bestI; i < block.length; i++) {
|
|
38507
|
+
place[block[i]] = fr2(suffixDesPlace + e.fArray4[block[i]]);
|
|
38508
|
+
}
|
|
38509
|
+
c.lowerBound = nextLowerBound(c, right2);
|
|
38510
|
+
for (let i = left2; i < right2; i++) e.ordering[i] = block[i - left2];
|
|
38511
|
+
c.converged = c.converged && equals(prefixDesPlace, curPlace) && equals(suffixDesPlace, curPlace);
|
|
38512
|
+
}
|
|
38513
|
+
function processBlock(c, left2) {
|
|
38514
|
+
const curPlace = c.place[c.e.ordering[left2]];
|
|
38515
|
+
const right2 = growBlock(c, left2, curPlace);
|
|
38516
|
+
computeDesiredPlaces(c, left2, right2);
|
|
38517
|
+
orderBlockByLevels(c, left2, right2, curPlace);
|
|
38518
|
+
computePrefixDesiredPlaces(c, curPlace);
|
|
38519
|
+
computeSuffixDesiredPlaces(c, curPlace);
|
|
38520
|
+
const bestI = findBestSplit(c, curPlace);
|
|
38521
|
+
if (bestI !== NO_SPLIT) {
|
|
38522
|
+
moveSplitBlock(c, bestI, left2, right2, curPlace);
|
|
38523
|
+
} else {
|
|
38524
|
+
c.lowerBound = nextLowerBound(c, right2);
|
|
38525
|
+
}
|
|
38526
|
+
return right2;
|
|
38527
|
+
}
|
|
38528
|
+
function constrainedMajorizationNewWithGaps(e, b, coords, curAxis, maxIterations, levelsGap) {
|
|
38529
|
+
const place = coords[curAxis];
|
|
38530
|
+
if (maxIterations <= 0) return;
|
|
38531
|
+
const gap = fr2(levelsGap);
|
|
38532
|
+
ensureMonotonicOrderingWithGaps(place, e.n, e.ordering, e.levels, e.numLevels, gap);
|
|
38533
|
+
const c = {
|
|
38534
|
+
e,
|
|
38535
|
+
place,
|
|
38536
|
+
b,
|
|
38537
|
+
lev: computeNodeLevels(e),
|
|
38538
|
+
levelsGap: gap,
|
|
38539
|
+
block: [],
|
|
38540
|
+
lowerBound: fr2(-BOUND),
|
|
38541
|
+
converged: false
|
|
38542
|
+
};
|
|
38543
|
+
for (let counter = 0; counter < maxIterations && !c.converged; counter++) {
|
|
38544
|
+
c.converged = true;
|
|
38545
|
+
c.lowerBound = fr2(-BOUND);
|
|
38546
|
+
for (let left2 = 0, right2; left2 < e.n; left2 = right2) {
|
|
38547
|
+
right2 = processBlock(c, left2);
|
|
38548
|
+
}
|
|
38549
|
+
orthog1f(e.n, place);
|
|
38550
|
+
}
|
|
38551
|
+
}
|
|
38552
|
+
function initConstrainedMajorization(packedMat, n, ordering, levels, numLevels) {
|
|
38553
|
+
return {
|
|
38554
|
+
A: unpackMatrix(packedMat, n),
|
|
38555
|
+
n,
|
|
38556
|
+
fArray1: new Float32Array(n),
|
|
38557
|
+
fArray2: new Float32Array(n),
|
|
38558
|
+
fArray3: new Float32Array(n),
|
|
38559
|
+
fArray4: new Float32Array(n),
|
|
38560
|
+
ordering,
|
|
38561
|
+
levels,
|
|
38562
|
+
numLevels
|
|
38563
|
+
};
|
|
38564
|
+
}
|
|
38565
|
+
|
|
38566
|
+
// src/layout/neato/conjgrad-mkernel.ts
|
|
38567
|
+
var fr3 = Math.fround;
|
|
38568
|
+
var RIGHT_MULT_BLOCK = 16;
|
|
38569
|
+
var ZERO_LENGTH_MESSAGE = "conjugate_gradient: unexpected length 0 vector\n";
|
|
38570
|
+
function rightMultWithVectorFFFused(m, n, vector, result) {
|
|
37529
38571
|
for (let i = 0; i < n; i++) result[i] = 0;
|
|
37530
38572
|
let index = 0;
|
|
37531
38573
|
for (let i = 0; i < n; i++) {
|
|
37532
38574
|
const vi = vector[i];
|
|
37533
|
-
let res =
|
|
38575
|
+
let res = fmaf(m[index++], vi, 0);
|
|
38576
|
+
const len = n - i - 1;
|
|
38577
|
+
const blockEnd = i + 1 + (len - len % RIGHT_MULT_BLOCK);
|
|
37534
38578
|
for (let j = i + 1; j < n; j++, index++) {
|
|
37535
|
-
|
|
37536
|
-
|
|
38579
|
+
const mij = m[index];
|
|
38580
|
+
res = j < blockEnd ? fr3(res + fr3(mij * vector[j])) : fmaf(mij, vector[j], res);
|
|
38581
|
+
result[j] = fmaf(mij, vi, result[j]);
|
|
37537
38582
|
}
|
|
37538
38583
|
result[i] = result[i] + res;
|
|
37539
38584
|
}
|
|
37540
38585
|
}
|
|
37541
|
-
function
|
|
37542
|
-
for (let i = 0; i < n; i++)
|
|
38586
|
+
function vectorsMultAdditionFused(n, v1, alpha, v2) {
|
|
38587
|
+
for (let i = 0; i < n; i++) v1[i] = fmaf(alpha, v2[i], v1[i]);
|
|
37543
38588
|
}
|
|
37544
|
-
|
|
37545
|
-
|
|
37546
|
-
|
|
38589
|
+
var CgStep = { CONTINUE: 0, STOP: 1, ERROR: 2 };
|
|
38590
|
+
function initialState(A3, x, b, n) {
|
|
38591
|
+
const Ax = new Float32Array(n);
|
|
38592
|
+
const st = { n, r: new Float32Array(n), p: new Float32Array(n), Ap: new Float32Array(n), rR: 0 };
|
|
38593
|
+
orthog1f(n, x);
|
|
38594
|
+
orthog1f(n, b);
|
|
38595
|
+
rightMultWithVectorFFFused(A3, n, x, Ax);
|
|
38596
|
+
orthog1f(n, Ax);
|
|
38597
|
+
vectorsSubtractionF(n, b, Ax, st.r);
|
|
38598
|
+
copyVectorF(n, st.r, st.p);
|
|
38599
|
+
st.rR = vectorsInnerProductF(n, st.r, st.r);
|
|
38600
|
+
return st;
|
|
37547
38601
|
}
|
|
37548
|
-
function
|
|
37549
|
-
|
|
37550
|
-
|
|
37551
|
-
|
|
38602
|
+
function cgIteration(A3, x, st, last) {
|
|
38603
|
+
const { n, r, p, Ap } = st;
|
|
38604
|
+
orthog1f(n, p);
|
|
38605
|
+
orthog1f(n, x);
|
|
38606
|
+
orthog1f(n, r);
|
|
38607
|
+
rightMultWithVectorFFFused(A3, n, p, Ap);
|
|
38608
|
+
orthog1f(n, Ap);
|
|
38609
|
+
const pAp = vectorsInnerProductF(n, p, Ap);
|
|
38610
|
+
if (pAp === 0) return CgStep.STOP;
|
|
38611
|
+
const alpha = st.rR / pAp;
|
|
38612
|
+
vectorsMultAdditionFused(n, x, fr3(alpha), p);
|
|
38613
|
+
if (last) return CgStep.CONTINUE;
|
|
38614
|
+
vectorsMultAdditionFused(n, r, fr3(-alpha), Ap);
|
|
38615
|
+
const rRNew = vectorsInnerProductF(n, r, r);
|
|
38616
|
+
if (st.rR === 0) {
|
|
38617
|
+
agerrorf(ZERO_LENGTH_MESSAGE);
|
|
38618
|
+
return CgStep.ERROR;
|
|
38619
|
+
}
|
|
38620
|
+
const beta = fr3(rRNew / st.rR);
|
|
38621
|
+
st.rR = rRNew;
|
|
38622
|
+
for (let j = 0; j < n; j++) p[j] = fmaf(beta, p[j], r[j]);
|
|
38623
|
+
return CgStep.CONTINUE;
|
|
38624
|
+
}
|
|
38625
|
+
function conjugateGradientMkernelFused(A3, x, b, n, o) {
|
|
38626
|
+
const st = initialState(A3, x, b, n);
|
|
38627
|
+
for (let i = 0; i < o.maxIterations && maxAbsF(n, st.r) > o.tol; i++) {
|
|
38628
|
+
const step = cgIteration(A3, x, st, i >= o.maxIterations - 1);
|
|
38629
|
+
if (step === CgStep.STOP) break;
|
|
38630
|
+
if (step === CgStep.ERROR) return 1;
|
|
38631
|
+
}
|
|
38632
|
+
return 0;
|
|
37552
38633
|
}
|
|
37553
|
-
|
|
37554
|
-
|
|
38634
|
+
|
|
38635
|
+
// src/layout/neato/opt-arrangement.ts
|
|
38636
|
+
var HIERARCHY_CG_TOL = 1e-3;
|
|
38637
|
+
function constructB(graph, n, b) {
|
|
38638
|
+
for (let i = 0; i < n; i++) {
|
|
38639
|
+
if (graph[0].edists == null) continue;
|
|
38640
|
+
let bI = 0;
|
|
38641
|
+
const node = graph[i];
|
|
38642
|
+
for (let j = 1; j < node.nedges; j++) {
|
|
38643
|
+
bI += Math.fround(Math.fround(node.ewgts[j]) * node.edists[j]);
|
|
38644
|
+
}
|
|
38645
|
+
b[i] = bI;
|
|
38646
|
+
}
|
|
37555
38647
|
}
|
|
37556
|
-
function
|
|
37557
|
-
|
|
38648
|
+
function setUniformWeights(graph, n) {
|
|
38649
|
+
const old = [];
|
|
37558
38650
|
for (let i = 0; i < n; i++) {
|
|
37559
|
-
const
|
|
37560
|
-
|
|
38651
|
+
const node = graph[i];
|
|
38652
|
+
old.push(node.ewgts);
|
|
38653
|
+
const weights = new Array(node.nedges).fill(1);
|
|
38654
|
+
weights[0] = -(node.nedges - 1);
|
|
38655
|
+
node.ewgts = weights;
|
|
37561
38656
|
}
|
|
37562
|
-
return
|
|
38657
|
+
return old;
|
|
37563
38658
|
}
|
|
37564
|
-
function
|
|
37565
|
-
|
|
38659
|
+
function computeYCoords(graph, n, yCoords, maxIterations) {
|
|
38660
|
+
let rv = 0;
|
|
38661
|
+
const b = new Float64Array(n);
|
|
38662
|
+
constructB(graph, n, b);
|
|
38663
|
+
initVecOrth1(n, yCoords);
|
|
38664
|
+
const oldEwgts = setUniformWeights(graph, n);
|
|
38665
|
+
if (conjugateGradient(graph, yCoords, b, n, HIERARCHY_CG_TOL, maxIterations) < 0) {
|
|
38666
|
+
rv = 1;
|
|
38667
|
+
}
|
|
38668
|
+
for (let i = 0; i < n; i++) graph[i].ewgts = oldEwgts[i];
|
|
38669
|
+
return rv;
|
|
37566
38670
|
}
|
|
37567
|
-
|
|
38671
|
+
|
|
38672
|
+
// src/layout/neato/compute-hierarchy.ts
|
|
38673
|
+
function countLevels(y, ordering, n, tol) {
|
|
38674
|
+
let numLevels = 0;
|
|
38675
|
+
for (let i = 1; i < n; i++) {
|
|
38676
|
+
if (y[ordering[i]] - y[ordering[i - 1]] > tol) numLevels++;
|
|
38677
|
+
}
|
|
38678
|
+
return numLevels;
|
|
38679
|
+
}
|
|
38680
|
+
function fillLevels(y, ordering, n, tol, numLevels) {
|
|
38681
|
+
if (numLevels === 0) {
|
|
38682
|
+
const levels2 = new Int32Array(1);
|
|
38683
|
+
levels2[0] = n;
|
|
38684
|
+
return levels2;
|
|
38685
|
+
}
|
|
38686
|
+
const levels = new Int32Array(numLevels);
|
|
38687
|
+
let count = 0;
|
|
38688
|
+
for (let i = 1; i < n; i++) {
|
|
38689
|
+
if (y[ordering[i]] - y[ordering[i - 1]] > tol) levels[count++] = i;
|
|
38690
|
+
}
|
|
38691
|
+
return levels;
|
|
38692
|
+
}
|
|
38693
|
+
function computeHierarchy(graph, n, absTol, relTol, given) {
|
|
38694
|
+
let y;
|
|
38695
|
+
if (given) {
|
|
38696
|
+
y = given;
|
|
38697
|
+
} else {
|
|
38698
|
+
y = new Float64Array(n);
|
|
38699
|
+
if (computeYCoords(graph, n, y, n)) return null;
|
|
38700
|
+
}
|
|
38701
|
+
const ordering = new Int32Array(n);
|
|
38702
|
+
for (let i = 0; i < n; i++) ordering[i] = i;
|
|
38703
|
+
quicksortPlace(y, ordering, n);
|
|
38704
|
+
const hierarchySpan = y[ordering[n - 1]] - y[ordering[0]];
|
|
38705
|
+
const relative = relTol * hierarchySpan / (n - 1);
|
|
38706
|
+
const tol = absTol > relative ? absTol : relative;
|
|
38707
|
+
const numLevels = countLevels(y, ordering, n, tol);
|
|
38708
|
+
return { ordering, levels: fillLevels(y, ordering, n, tol, numLevels), numLevels };
|
|
38709
|
+
}
|
|
38710
|
+
|
|
38711
|
+
// src/layout/neato/smart-ini-x.ts
|
|
38712
|
+
var fr4 = Math.fround;
|
|
38713
|
+
var SCALE_FACTOR = 256;
|
|
38714
|
+
var DBL_EPSILON = 2220446049250313e-31;
|
|
38715
|
+
var POWER_LENGTH_FLOOR = 1e-10;
|
|
38716
|
+
var BLOCK_STANDARDIZE_NORM = 4;
|
|
38717
|
+
var BLOCK_MAT_MULT_ROW = 4;
|
|
38718
|
+
var BLOCK_MAT_MULT_ORTHOG = 8;
|
|
38719
|
+
var BLOCK_GUESS_ORTHOG = 8;
|
|
38720
|
+
var BLOCK_GUESS_LEN = BLOCK_NONE;
|
|
38721
|
+
var BLOCK_LOOP_LEN = BLOCK_NONE;
|
|
38722
|
+
var BLOCK_ANGLE = 8;
|
|
38723
|
+
var BLOCK_UNIFORM_SUMS = 4;
|
|
38724
|
+
var BLOCK_AVGS = 4;
|
|
38725
|
+
function standardize(orthog, nvtxs) {
|
|
38726
|
+
let avg = 0;
|
|
38727
|
+
for (let i = 0; i < nvtxs; i++) avg += orthog[i];
|
|
38728
|
+
avg /= nvtxs;
|
|
38729
|
+
for (let i = 0; i < nvtxs; i++) orthog[i] = orthog[i] - avg;
|
|
38730
|
+
const len = norm(orthog, nvtxs - 1, BLOCK_STANDARDIZE_NORM);
|
|
38731
|
+
if (Math.abs(len) < DBL_EPSILON) return;
|
|
38732
|
+
vectorsScalarMult(nvtxs, orthog, 1 / len, orthog);
|
|
38733
|
+
}
|
|
38734
|
+
function matMultVecOrthog(mat, dim, vec, result, orthog) {
|
|
38735
|
+
const blocked = dim - dim % BLOCK_MAT_MULT_ROW;
|
|
38736
|
+
for (let i = 0; i < dim; i++) {
|
|
38737
|
+
const row = mat[i];
|
|
38738
|
+
let sum = 0;
|
|
38739
|
+
let j = 0;
|
|
38740
|
+
for (; j < blocked; j++) sum += row[j] * vec[j];
|
|
38741
|
+
for (; j < dim; j++) sum = fma2(row[j], vec[j], sum);
|
|
38742
|
+
result[i] = sum;
|
|
38743
|
+
}
|
|
38744
|
+
const alpha = -innerProduct(dim, result, orthog, BLOCK_MAT_MULT_ORTHOG);
|
|
38745
|
+
scadd(result, dim - 1, alpha, orthog);
|
|
38746
|
+
}
|
|
38747
|
+
function orthogonalizeAgainstEigs(p, vec, count, block) {
|
|
38748
|
+
for (let j = 0; j < count; j++) {
|
|
38749
|
+
const alpha = -innerProduct(p.n, p.eigs[j], vec, block);
|
|
38750
|
+
scadd(vec, p.n - 1, alpha, p.eigs[j]);
|
|
38751
|
+
}
|
|
38752
|
+
}
|
|
38753
|
+
function chooseStartVector(p, i) {
|
|
38754
|
+
const curr = p.eigs[i];
|
|
38755
|
+
for (; ; ) {
|
|
38756
|
+
for (let j = 0; j < p.n; j++) curr[j] = crand() % 100;
|
|
38757
|
+
const alpha = -innerProduct(p.n, p.orthog, curr, BLOCK_GUESS_ORTHOG);
|
|
38758
|
+
scadd(curr, p.n - 1, alpha, p.orthog);
|
|
38759
|
+
orthogonalizeAgainstEigs(p, curr, i, BLOCK_NONE);
|
|
38760
|
+
const len = norm(curr, p.n - 1, BLOCK_GUESS_LEN);
|
|
38761
|
+
if (len < POWER_LENGTH_FLOOR) continue;
|
|
38762
|
+
vectorsScalarMult(p.n, curr, 1 / len, curr);
|
|
38763
|
+
return;
|
|
38764
|
+
}
|
|
38765
|
+
}
|
|
38766
|
+
function iterateEigenvector(p, i, tol, work) {
|
|
38767
|
+
const curr = p.eigs[i];
|
|
38768
|
+
for (; ; ) {
|
|
38769
|
+
copyVector(p.n, curr, work.last);
|
|
38770
|
+
matMultVecOrthog(p.mat, p.n, curr, work.tmp, p.orthog);
|
|
38771
|
+
copyVector(p.n, work.tmp, curr);
|
|
38772
|
+
orthogonalizeAgainstEigs(p, curr, i, BLOCK_NONE);
|
|
38773
|
+
const len = norm(curr, p.n - 1, BLOCK_LOOP_LEN);
|
|
38774
|
+
if (len < POWER_LENGTH_FLOOR) {
|
|
38775
|
+
return { nullSpace: true, eval: 0 };
|
|
38776
|
+
}
|
|
38777
|
+
vectorsScalarMult(p.n, curr, 1 / len, curr);
|
|
38778
|
+
const angle = innerProduct(p.n, curr, work.last, BLOCK_ANGLE);
|
|
38779
|
+
if (!(Math.abs(angle) < tol)) {
|
|
38780
|
+
return { nullSpace: false, eval: angle * len };
|
|
38781
|
+
}
|
|
38782
|
+
}
|
|
38783
|
+
}
|
|
38784
|
+
function fillNullSpaceEigenvectors(p, from, neigs) {
|
|
38785
|
+
for (let i = from; i < neigs; i++) {
|
|
38786
|
+
const curr = p.eigs[i];
|
|
38787
|
+
for (let j = 0; j < p.n; j++) curr[j] = crand() % 100;
|
|
38788
|
+
orthogonalizeAgainstEigs(p, curr, i, BLOCK_NONE);
|
|
38789
|
+
const len = norm(curr, p.n - 1, BLOCK_NONE);
|
|
38790
|
+
vectorsScalarMult(p.n, curr, 1 / len, curr);
|
|
38791
|
+
p.evals[i] = 0;
|
|
38792
|
+
}
|
|
38793
|
+
}
|
|
38794
|
+
function sortEigenvectors(p, neigs, tmp) {
|
|
38795
|
+
for (let i = 0; i < neigs - 1; i++) {
|
|
38796
|
+
let largestIndex = i;
|
|
38797
|
+
let largestEval = p.evals[largestIndex];
|
|
38798
|
+
for (let j = i + 1; j < neigs; j++) {
|
|
38799
|
+
if (largestEval < p.evals[j]) {
|
|
38800
|
+
largestIndex = j;
|
|
38801
|
+
largestEval = p.evals[largestIndex];
|
|
38802
|
+
}
|
|
38803
|
+
}
|
|
38804
|
+
if (largestIndex !== i) {
|
|
38805
|
+
copyVector(p.n, p.eigs[i], tmp);
|
|
38806
|
+
copyVector(p.n, p.eigs[largestIndex], p.eigs[i]);
|
|
38807
|
+
copyVector(p.n, tmp, p.eigs[largestIndex]);
|
|
38808
|
+
p.evals[largestIndex] = p.evals[i];
|
|
38809
|
+
p.evals[i] = largestEval;
|
|
38810
|
+
}
|
|
38811
|
+
}
|
|
38812
|
+
}
|
|
38813
|
+
function powerIterationOrthog(p, neigsIn, pIterationThreshold) {
|
|
38814
|
+
const work = { tmp: new Float64Array(p.n), last: new Float64Array(p.n) };
|
|
38815
|
+
const tol = 1 - pIterationThreshold;
|
|
38816
|
+
const neigs = neigsIn >= p.n ? p.n : neigsIn;
|
|
38817
|
+
let i = 0;
|
|
38818
|
+
for (; i < neigs; i++) {
|
|
38819
|
+
chooseStartVector(p, i);
|
|
38820
|
+
const res = iterateEigenvector(p, i, tol, work);
|
|
38821
|
+
if (res.nullSpace) break;
|
|
38822
|
+
p.evals[i] = res.eval;
|
|
38823
|
+
}
|
|
38824
|
+
fillNullSpaceEigenvectors(p, i, neigs);
|
|
38825
|
+
sortEigenvectors(p, neigs, work.tmp);
|
|
38826
|
+
}
|
|
38827
|
+
function computeAvgs(Dij, n) {
|
|
38828
|
+
const rowAvg = new Float32Array(n);
|
|
38829
|
+
let sum = 0;
|
|
38830
|
+
const blocked = n - n % BLOCK_AVGS;
|
|
37568
38831
|
for (let i = 0; i < n; i++) {
|
|
37569
|
-
|
|
38832
|
+
let sumRow = 0;
|
|
38833
|
+
const row = Dij[i];
|
|
38834
|
+
let j = 0;
|
|
38835
|
+
for (; j < blocked; j++) {
|
|
38836
|
+
sum += row[j] * row[j];
|
|
38837
|
+
sumRow += row[j] * row[j];
|
|
38838
|
+
}
|
|
38839
|
+
for (; j < n; j++) {
|
|
38840
|
+
sum = fma2(row[j], row[j], sum);
|
|
38841
|
+
sumRow = fma2(row[j], row[j], sumRow);
|
|
38842
|
+
}
|
|
38843
|
+
rowAvg[i] = fr4(fr4(sumRow) / n);
|
|
37570
38844
|
}
|
|
38845
|
+
return { rowAvg, allAvg: fr4(fr4(sum) / (n * n)) };
|
|
37571
38846
|
}
|
|
37572
|
-
function
|
|
38847
|
+
function computeBij(Dij, n) {
|
|
38848
|
+
const Bij = [];
|
|
38849
|
+
for (let i = 0; i < n; i++) Bij.push(new Float32Array(n));
|
|
38850
|
+
const { rowAvg, allAvg } = computeAvgs(Dij, n);
|
|
37573
38851
|
for (let i = 0; i < n; i++) {
|
|
37574
|
-
|
|
38852
|
+
for (let j = 0; j <= i; j++) {
|
|
38853
|
+
const fD = fr4(Dij[i][j]);
|
|
38854
|
+
const t = fr4(fma2(-fD, fD, rowAvg[i]));
|
|
38855
|
+
Bij[i][j] = fr4(fr4(t + rowAvg[j]) - allAvg);
|
|
38856
|
+
Bij[j][i] = Bij[i][j];
|
|
38857
|
+
}
|
|
38858
|
+
}
|
|
38859
|
+
return Bij;
|
|
38860
|
+
}
|
|
38861
|
+
function cmdsOrthog(n, dim, eigs, tol, input) {
|
|
38862
|
+
const { orthog, Dij } = input;
|
|
38863
|
+
const Bij = computeBij(Dij, n);
|
|
38864
|
+
const evals = new Float64Array(dim);
|
|
38865
|
+
const orthogAux = Float64Array.from(orthog.subarray(0, n));
|
|
38866
|
+
standardize(orthogAux, n);
|
|
38867
|
+
powerIterationOrthog({ mat: Bij, n, eigs, evals, orthog: orthogAux }, dim, tol);
|
|
38868
|
+
for (let i = 0; i < dim; i++) {
|
|
38869
|
+
for (let j = 0; j < n; j++) eigs[i][j] = eigs[i][j] * Math.sqrt(Math.abs(evals[i]));
|
|
37575
38870
|
}
|
|
37576
38871
|
}
|
|
37577
|
-
function
|
|
38872
|
+
function scaleGivenCoords(Dij, n, x) {
|
|
38873
|
+
let sum1 = 0;
|
|
38874
|
+
let sum2 = 0;
|
|
38875
|
+
for (let i = 1; i < n; i++) {
|
|
38876
|
+
const blocked = i - i % BLOCK_UNIFORM_SUMS;
|
|
38877
|
+
for (let j = 0; j < i; j++) {
|
|
38878
|
+
const d = Dij[i][j];
|
|
38879
|
+
const f = Math.abs(x[i] - x[j]);
|
|
38880
|
+
const t1 = 1 / d;
|
|
38881
|
+
const t2 = 1 / Math.imul(d, d) * f;
|
|
38882
|
+
if (j < blocked) {
|
|
38883
|
+
sum1 += t1 * f;
|
|
38884
|
+
sum2 += t2 * f;
|
|
38885
|
+
} else {
|
|
38886
|
+
sum1 = fma2(t1, f, sum1);
|
|
38887
|
+
sum2 = fma2(t2, f, sum2);
|
|
38888
|
+
}
|
|
38889
|
+
}
|
|
38890
|
+
}
|
|
38891
|
+
const uniLength = Math.abs(sum2) === Infinity ? 0 : sum1 / sum2;
|
|
38892
|
+
for (let i = 0; i < n; i++) x[i] = x[i] * uniLength;
|
|
38893
|
+
return uniLength;
|
|
38894
|
+
}
|
|
38895
|
+
function computeLaplacian(Dij, n) {
|
|
38896
|
+
const lap = [];
|
|
37578
38897
|
for (let i = 0; i < n; i++) {
|
|
37579
|
-
|
|
38898
|
+
const row = new Float32Array(n);
|
|
38899
|
+
let degree = fr4(0);
|
|
38900
|
+
for (let j = 0; j < n; j++) {
|
|
38901
|
+
if (j === i) continue;
|
|
38902
|
+
const w = fr4(fr4(-1) / fr4(fr4(Dij[i][j]) * fr4(Dij[i][j])));
|
|
38903
|
+
row[j] = w;
|
|
38904
|
+
degree = fr4(degree - w);
|
|
38905
|
+
}
|
|
38906
|
+
row[i] = degree;
|
|
38907
|
+
lap.push(row);
|
|
38908
|
+
}
|
|
38909
|
+
return lap;
|
|
38910
|
+
}
|
|
38911
|
+
function computeResidualDistances(Dij, n, x) {
|
|
38912
|
+
for (let i = 1; i < n; i++) {
|
|
38913
|
+
const posI = x[i];
|
|
38914
|
+
for (let j = 0; j < i; j++) {
|
|
38915
|
+
const t = posI - x[j];
|
|
38916
|
+
const d = Dij[i][j];
|
|
38917
|
+
const diff = fma2(d, d, -(t * t));
|
|
38918
|
+
const v = diff > 0 ? Math.sqrt(diff) : 0;
|
|
38919
|
+
Dij[i][j] = v;
|
|
38920
|
+
Dij[j][i] = v;
|
|
38921
|
+
}
|
|
38922
|
+
}
|
|
38923
|
+
}
|
|
38924
|
+
function balanceOf(i, n, y, ctx) {
|
|
38925
|
+
const posI = y[i];
|
|
38926
|
+
let b = 0;
|
|
38927
|
+
for (let j = 0; j < n; j++) {
|
|
38928
|
+
if (j === i) continue;
|
|
38929
|
+
const term = fr4(fr4(ctx.Dij[i][j]) * -ctx.lap[i][j]);
|
|
38930
|
+
if (posI >= y[j]) b += term;
|
|
38931
|
+
else b -= term;
|
|
37580
38932
|
}
|
|
38933
|
+
return b;
|
|
38934
|
+
}
|
|
38935
|
+
function solveBalanced(ctx, n, y, balance, convTol) {
|
|
38936
|
+
let converged = false;
|
|
38937
|
+
for (let iterations2 = 0; iterations2 < 200 && !converged; iterations2++) {
|
|
38938
|
+
if (conjugateGradientF(ctx.lap, y, balance, n, { tol: convTol, maxIterations: n, ortho1: true }) < 0) return 1;
|
|
38939
|
+
converged = true;
|
|
38940
|
+
for (let i = 0; i < n; i++) {
|
|
38941
|
+
const b = balanceOf(i, n, y, ctx);
|
|
38942
|
+
if (b !== balance[i] && Math.abs(1 - b / balance[i]) > 1e-5) {
|
|
38943
|
+
converged = false;
|
|
38944
|
+
balance[i] = b;
|
|
38945
|
+
}
|
|
38946
|
+
}
|
|
38947
|
+
}
|
|
38948
|
+
return 0;
|
|
38949
|
+
}
|
|
38950
|
+
function imdsGivenDim(graph, n, givenCoords, newCoords, conjTol) {
|
|
38951
|
+
const x = givenCoords;
|
|
38952
|
+
const y = newCoords;
|
|
38953
|
+
const Dij = computeApsp(graph, n);
|
|
38954
|
+
for (let i = 0; i < n; i++) {
|
|
38955
|
+
for (let j = 0; j < n; j++) Dij[i][j] = Dij[i][j] * SCALE_FACTOR;
|
|
38956
|
+
}
|
|
38957
|
+
const uniLength = scaleGivenCoords(Dij, n, x);
|
|
38958
|
+
cmdsOrthog(n, 1, [y], conjTol, { orthog: x, Dij });
|
|
38959
|
+
const lap = computeLaplacian(Dij, n);
|
|
38960
|
+
computeResidualDistances(Dij, n, x);
|
|
38961
|
+
const ctx = { Dij, lap };
|
|
38962
|
+
const balance = new Float64Array(n);
|
|
38963
|
+
for (let i = 0; i < n; i++) balance[i] = balanceOf(i, n, y, ctx);
|
|
38964
|
+
if (solveBalanced(ctx, n, y, balance, conjTol) === 1) return 1;
|
|
38965
|
+
for (let i = 0; !(Math.abs(uniLength) < DBL_EPSILON) && i < n; i++) {
|
|
38966
|
+
x[i] = x[i] / uniLength;
|
|
38967
|
+
y[i] = y[i] / uniLength;
|
|
38968
|
+
}
|
|
38969
|
+
return 0;
|
|
37581
38970
|
}
|
|
37582
38971
|
|
|
37583
38972
|
// src/layout/neato/stress-kernel.ts
|
|
37584
|
-
var
|
|
37585
|
-
var
|
|
38973
|
+
var fr5 = Math.fround;
|
|
38974
|
+
var TOLERANCE_CG2 = 1e-3;
|
|
37586
38975
|
var OPT_EXP_FLAG = 2;
|
|
37587
38976
|
function computeApspPacked2(graph, n) {
|
|
37588
38977
|
const Dij = new Float32Array(n * (n + 1) / 2);
|
|
@@ -37642,9 +39031,9 @@ function cgStep(st, last) {
|
|
|
37642
39031
|
vectorsMultAdditionF(n, st.r, -alpha, st.Ap);
|
|
37643
39032
|
const rRNew = vectorsInnerProductF(n, st.r, st.r);
|
|
37644
39033
|
if (st.rR === 0) return false;
|
|
37645
|
-
const betaF =
|
|
39034
|
+
const betaF = fr5(rRNew / st.rR);
|
|
37646
39035
|
st.rR = rRNew;
|
|
37647
|
-
for (let j = 0; j < n; j++) st.p[j] =
|
|
39036
|
+
for (let j = 0; j < n; j++) st.p[j] = fr5(betaF * st.p[j]) + st.r[j];
|
|
37648
39037
|
}
|
|
37649
39038
|
return true;
|
|
37650
39039
|
}
|
|
@@ -37706,8 +39095,8 @@ function buildLap1(lap1, lap2, coords, shape) {
|
|
|
37706
39095
|
for (let k = 0; k < dim; k++) {
|
|
37707
39096
|
const ck = coords[k];
|
|
37708
39097
|
for (let x = 0; x < len; x++) {
|
|
37709
|
-
const tmp =
|
|
37710
|
-
distAccumulator[x] = distAccumulator[x] +
|
|
39098
|
+
const tmp = fr5(ck[i] + fr5(-1 * ck[i + 1 + x]));
|
|
39099
|
+
distAccumulator[x] = distAccumulator[x] + fr5(tmp * tmp);
|
|
37711
39100
|
}
|
|
37712
39101
|
}
|
|
37713
39102
|
invertSqrtVec(len, distAccumulator);
|
|
@@ -37719,7 +39108,7 @@ function buildLap1(lap1, lap2, coords, shape) {
|
|
|
37719
39108
|
let degree = 0;
|
|
37720
39109
|
if (exp === 2) {
|
|
37721
39110
|
for (let j = 0; j < len; j++, count++) {
|
|
37722
|
-
const val2 = lap1[count] =
|
|
39111
|
+
const val2 = lap1[count] = fr5(lap1[count] * distAccumulator[j]);
|
|
37723
39112
|
degree += val2;
|
|
37724
39113
|
degrees[i + j + 1] = degrees[i + j + 1] - val2;
|
|
37725
39114
|
}
|
|
@@ -37753,10 +39142,10 @@ function computeStress(st) {
|
|
|
37753
39142
|
}
|
|
37754
39143
|
function solveAxis(st, k, havePinned, nodes) {
|
|
37755
39144
|
if (!havePinned) {
|
|
37756
|
-
return conjugateGradientMkernel2(st.lap2, st.coords[k], st.b[k], st.n,
|
|
39145
|
+
return conjugateGradientMkernel2(st.lap2, st.coords[k], st.b[k], st.n, TOLERANCE_CG2, st.n);
|
|
37757
39146
|
}
|
|
37758
39147
|
copyVectorF(st.n, st.coords[k], st.tmpCoords);
|
|
37759
|
-
const rc = conjugateGradientMkernel2(st.lap2, st.tmpCoords, st.b[k], st.n,
|
|
39148
|
+
const rc = conjugateGradientMkernel2(st.lap2, st.tmpCoords, st.b[k], st.n, TOLERANCE_CG2, st.n);
|
|
37760
39149
|
if (rc < 0) return rc;
|
|
37761
39150
|
for (let i = 0; i < st.n; i++) {
|
|
37762
39151
|
if (!isFixed(nodes[i])) st.coords[k][i] = st.tmpCoords[i];
|
|
@@ -37772,10 +39161,10 @@ function stressMajorizationKDMkernel(Dij, n, dCoords, nodes, o) {
|
|
|
37772
39161
|
const coords = [];
|
|
37773
39162
|
for (let i = 0; i < dim; i++) {
|
|
37774
39163
|
const c = new Float32Array(n);
|
|
37775
|
-
for (let j = 0; j < n; j++) c[j] =
|
|
39164
|
+
for (let j = 0; j < n; j++) c[j] = fr5(dCoords[i][j]);
|
|
37776
39165
|
coords.push(c);
|
|
37777
39166
|
}
|
|
37778
|
-
const constantTerm =
|
|
39167
|
+
const constantTerm = fr5(n * (n - 1) / 2);
|
|
37779
39168
|
const lap2 = Dij;
|
|
37780
39169
|
buildLap2(lap2, n, exp);
|
|
37781
39170
|
const lapLength = n * (n + 1) / 2;
|
|
@@ -37810,6 +39199,261 @@ function stressMajorizationKDMkernel(Dij, n, dCoords, nodes, o) {
|
|
|
37810
39199
|
return iterations;
|
|
37811
39200
|
}
|
|
37812
39201
|
|
|
39202
|
+
// src/layout/neato/constrained-majorization.ts
|
|
39203
|
+
var fr6 = Math.fround;
|
|
39204
|
+
var LOCAL_CONSTR_MAJOR_ITERATIONS = 15;
|
|
39205
|
+
var LEVELS_SEP_TOL = 0.1;
|
|
39206
|
+
var ABS_TOL = 0.01;
|
|
39207
|
+
var SUBSPACE_ITERATIONS = 15;
|
|
39208
|
+
var FLT_MAX3 = 34028234663852886e22;
|
|
39209
|
+
var DBL_MAX = Number.MAX_VALUE;
|
|
39210
|
+
var MIN_LEVELS = 1;
|
|
39211
|
+
var Y_AXIS = 1;
|
|
39212
|
+
function unsupported2(what) {
|
|
39213
|
+
throw new RenderError(`hierarchical stress majorization: ${what} is not supported yet`, "UNSUPPORTED_FEATURE");
|
|
39214
|
+
}
|
|
39215
|
+
function modelDistances(graph, n, model) {
|
|
39216
|
+
if (model === MODEL_SUBSET) unsupported2("the subset distance model");
|
|
39217
|
+
if (model === MODEL_CIRCUIT) unsupported2("the circuit distance model");
|
|
39218
|
+
return model === MODEL_MDS2 ? mdsModel(graph, n) : null;
|
|
39219
|
+
}
|
|
39220
|
+
function unconstrainedMajorization(graph, n, dCoords, nodes, o) {
|
|
39221
|
+
if (o.maxi < 0) return 0;
|
|
39222
|
+
const weighted = (graph[0]?.ewgts.length ?? 0) > 0;
|
|
39223
|
+
const Dij = modelDistances(graph, n, o.model) ?? (weighted ? computeWeightedApspPacked2(graph, n) : computeApspPacked2(graph, n));
|
|
39224
|
+
if ((o.opts & OPT_SMART_INIT) !== 0 && n > 1) unsupported2("the smart initial layout");
|
|
39225
|
+
return stressMajorizationKDMkernel(Dij, n, dCoords, nodes, {
|
|
39226
|
+
dim: o.dim,
|
|
39227
|
+
opts: o.opts,
|
|
39228
|
+
maxi: o.maxi,
|
|
39229
|
+
epsilon: o.epsilon
|
|
39230
|
+
});
|
|
39231
|
+
}
|
|
39232
|
+
function hasDirectionality(graph, n) {
|
|
39233
|
+
if (!graph[0]?.edists) return false;
|
|
39234
|
+
let directionalityExist = false;
|
|
39235
|
+
for (let i = 0; i < n; i++) {
|
|
39236
|
+
const edists = graph[i].edists;
|
|
39237
|
+
for (let j = 1; j < graph[i].nedges; j++) {
|
|
39238
|
+
directionalityExist ||= edists[j] !== 0;
|
|
39239
|
+
}
|
|
39240
|
+
}
|
|
39241
|
+
return directionalityExist;
|
|
39242
|
+
}
|
|
39243
|
+
function separateLevels(y, h, n, levelsGap) {
|
|
39244
|
+
const { ordering, levels, numLevels } = h;
|
|
39245
|
+
let displacement = 0;
|
|
39246
|
+
for (let i = 0; i < numLevels; i++) {
|
|
39247
|
+
const shortfall = levelsGap - (y[ordering[levels[i]]] + displacement - y[ordering[levels[i] - 1]]);
|
|
39248
|
+
displacement += 0 > shortfall ? 0 : shortfall;
|
|
39249
|
+
const stop = i < numLevels - 1 ? levels[i + 1] : n;
|
|
39250
|
+
for (let j = levels[i]; j < stop; j++) y[ordering[j]] += displacement;
|
|
39251
|
+
}
|
|
39252
|
+
}
|
|
39253
|
+
function smartInitLayers(graph, n, dCoords, nodes, o) {
|
|
39254
|
+
const { dim } = o;
|
|
39255
|
+
if (dim > 2) {
|
|
39256
|
+
const sub = { dim: dim - 1, opts: o.opts, model: o.model, maxi: SUBSPACE_ITERATIONS, epsilon: o.epsilon };
|
|
39257
|
+
if (unconstrainedMajorization(graph, n, dCoords.slice(1), nodes, sub) < 0) return -1;
|
|
39258
|
+
dCoords[dim - 1].set(dCoords[1].subarray(0, n));
|
|
39259
|
+
}
|
|
39260
|
+
const x = dCoords[0];
|
|
39261
|
+
const y = dCoords[1];
|
|
39262
|
+
if (computeYCoords(graph, n, y, n)) return -1;
|
|
39263
|
+
const h = computeHierarchy(graph, n, ABS_TOL, LEVELS_SEP_TOL, y);
|
|
39264
|
+
if (h === null) return -1;
|
|
39265
|
+
if (h.numLevels < MIN_LEVELS) {
|
|
39266
|
+
return unconstrainedMajorization(graph, n, dCoords, nodes, o);
|
|
39267
|
+
}
|
|
39268
|
+
if (o.levelsGap > 0) separateLevels(y, h, n, o.levelsGap);
|
|
39269
|
+
if (dim === 2 && imdsGivenDim(graph, n, y, x, o.epsilon)) return -1;
|
|
39270
|
+
return h;
|
|
39271
|
+
}
|
|
39272
|
+
function plainInitLayers(graph, n, dCoords, nodes, dim) {
|
|
39273
|
+
initLayout(n, dim, dCoords, nodes);
|
|
39274
|
+
const h = computeHierarchy(graph, n, ABS_TOL, LEVELS_SEP_TOL, null);
|
|
39275
|
+
return h === null ? -1 : h;
|
|
39276
|
+
}
|
|
39277
|
+
function distanceKD(coords, dim, i, j) {
|
|
39278
|
+
let sum = 0;
|
|
39279
|
+
for (let k = 0; k < dim; k++) {
|
|
39280
|
+
const d = coords[k][i] - coords[k][j];
|
|
39281
|
+
sum = fma2(d, d, sum);
|
|
39282
|
+
}
|
|
39283
|
+
return Math.sqrt(sum);
|
|
39284
|
+
}
|
|
39285
|
+
function scaleDownLayout(dCoords, n, dim) {
|
|
39286
|
+
let max = 1;
|
|
39287
|
+
for (let i = 0; i < dim; i++) {
|
|
39288
|
+
for (let j = 0; j < n; j++) {
|
|
39289
|
+
const a = Math.abs(dCoords[i][j]);
|
|
39290
|
+
if (a > max) max = a;
|
|
39291
|
+
}
|
|
39292
|
+
}
|
|
39293
|
+
for (let i = 0; i < dim; i++) {
|
|
39294
|
+
for (let j = 0; j < n; j++) dCoords[i][j] *= 10 / max;
|
|
39295
|
+
}
|
|
39296
|
+
}
|
|
39297
|
+
function scaleDistances(Dij, dCoords, n, dim) {
|
|
39298
|
+
const length = n + Math.trunc(n * (n - 1) / 2);
|
|
39299
|
+
const sum1 = Math.trunc(n * (n - 1) / 2);
|
|
39300
|
+
let sum2 = 0;
|
|
39301
|
+
for (let count = 0, i = 0; i < n - 1; i++) {
|
|
39302
|
+
count++;
|
|
39303
|
+
for (let j = i + 1; j < n; j++, count++) {
|
|
39304
|
+
sum2 += distanceKD(dCoords, dim, i, j) / Dij[count];
|
|
39305
|
+
}
|
|
39306
|
+
}
|
|
39307
|
+
const scaleRatio = fr6(sum2 / sum1);
|
|
39308
|
+
for (let i = 0; i < length; i++) Dij[i] = Dij[i] * scaleRatio;
|
|
39309
|
+
}
|
|
39310
|
+
function centerLayout(dCoords, n, dim) {
|
|
39311
|
+
for (let i = 0; i < dim; i++) orthog1(n, dCoords[i]);
|
|
39312
|
+
const y0 = dCoords[Y_AXIS][0];
|
|
39313
|
+
for (let i = 0; i < n; i++) dCoords[Y_AXIS][i] -= y0;
|
|
39314
|
+
}
|
|
39315
|
+
function negatedDegrees(lap2, n) {
|
|
39316
|
+
const degrees = new Float64Array(n);
|
|
39317
|
+
for (let i = 0, count = 0; i < n - 1; i++) {
|
|
39318
|
+
let degree = 0;
|
|
39319
|
+
count++;
|
|
39320
|
+
for (let j = 1; j < n - i; j++, count++) {
|
|
39321
|
+
const val2 = lap2[count];
|
|
39322
|
+
degree += val2;
|
|
39323
|
+
degrees[i + j] -= val2;
|
|
39324
|
+
}
|
|
39325
|
+
degrees[i] -= degree;
|
|
39326
|
+
}
|
|
39327
|
+
return degrees;
|
|
39328
|
+
}
|
|
39329
|
+
function buildLap22(lap2, n) {
|
|
39330
|
+
const lapLength = n + Math.trunc(n * (n - 1) / 2);
|
|
39331
|
+
squareVec(lapLength, lap2);
|
|
39332
|
+
invertVec(lapLength, lap2);
|
|
39333
|
+
const degrees = negatedDegrees(lap2, n);
|
|
39334
|
+
for (let step = n, count = 0, i = 0; i < n; i++, count += step, step--) {
|
|
39335
|
+
lap2[count] = degrees[i];
|
|
39336
|
+
}
|
|
39337
|
+
}
|
|
39338
|
+
function inverseDistances(st, i, len) {
|
|
39339
|
+
const { coords, tmpCoords, distAccumulator } = st;
|
|
39340
|
+
distAccumulator.fill(0, 0, st.n);
|
|
39341
|
+
for (let k = 0; k < st.dim; k++) {
|
|
39342
|
+
const ck = coords[k];
|
|
39343
|
+
for (let j = 0; j < len; j++) tmpCoords[j] = ck[i] - ck[i + 1 + j];
|
|
39344
|
+
for (let j = 0; j < len; j++) tmpCoords[j] = tmpCoords[j] * tmpCoords[j];
|
|
39345
|
+
for (let j = 0; j < len; j++) distAccumulator[j] = tmpCoords[j] + distAccumulator[j];
|
|
39346
|
+
}
|
|
39347
|
+
invertSqrtVec(len, distAccumulator);
|
|
39348
|
+
for (let j = 0; j < len; j++) {
|
|
39349
|
+
if (distAccumulator[j] >= FLT_MAX3 || distAccumulator[j] < 0) distAccumulator[j] = 0;
|
|
39350
|
+
}
|
|
39351
|
+
}
|
|
39352
|
+
function buildLap12(st) {
|
|
39353
|
+
const { n, lap1, lap2, degrees, distAccumulator } = st;
|
|
39354
|
+
degrees.fill(0);
|
|
39355
|
+
sqrtVecF(n + Math.trunc(n * (n - 1) / 2), lap2, lap1);
|
|
39356
|
+
let count = 0;
|
|
39357
|
+
for (let i = 0; i < n - 1; i++) {
|
|
39358
|
+
const len = n - i - 1;
|
|
39359
|
+
inverseDistances(st, i, len);
|
|
39360
|
+
count++;
|
|
39361
|
+
let degree = 0;
|
|
39362
|
+
for (let j = 0; j < len; j++, count++) {
|
|
39363
|
+
const val2 = fr6(lap1[count] * distAccumulator[j]);
|
|
39364
|
+
lap1[count] = val2;
|
|
39365
|
+
degree += val2;
|
|
39366
|
+
degrees[i + j + 1] -= val2;
|
|
39367
|
+
}
|
|
39368
|
+
degrees[i] -= degree;
|
|
39369
|
+
}
|
|
39370
|
+
for (let step = n, count2 = 0, i = 0; i < n; i++, count2 += step, step--) {
|
|
39371
|
+
lap1[count2] = degrees[i];
|
|
39372
|
+
}
|
|
39373
|
+
}
|
|
39374
|
+
function computeNewStress(st, constantTerm) {
|
|
39375
|
+
const { n, dim, lap1, lap2, coords, b, tmpCoords } = st;
|
|
39376
|
+
for (let k = 0; k < dim; k++) rightMultWithVectorFFFused(lap1, n, coords[k], b[k]);
|
|
39377
|
+
let newStress = 0;
|
|
39378
|
+
for (let k = 0; k < dim; k++) newStress += vectorsInnerProductF(n, coords[k], b[k]);
|
|
39379
|
+
newStress *= 2;
|
|
39380
|
+
newStress += constantTerm;
|
|
39381
|
+
for (let k = 0; k < dim; k++) {
|
|
39382
|
+
rightMultWithVectorFFFused(lap2, n, coords[k], tmpCoords);
|
|
39383
|
+
newStress -= vectorsInnerProductF(n, coords[k], tmpCoords);
|
|
39384
|
+
}
|
|
39385
|
+
return newStress;
|
|
39386
|
+
}
|
|
39387
|
+
function solveAxes(st, ctx) {
|
|
39388
|
+
for (let k = 0; k < st.dim; k++) {
|
|
39389
|
+
if (k === Y_AXIS) {
|
|
39390
|
+
constrainedMajorizationNewWithGaps(
|
|
39391
|
+
ctx.cMajEnv,
|
|
39392
|
+
st.b[k],
|
|
39393
|
+
st.coords,
|
|
39394
|
+
k,
|
|
39395
|
+
LOCAL_CONSTR_MAJOR_ITERATIONS,
|
|
39396
|
+
ctx.levelsGap
|
|
39397
|
+
);
|
|
39398
|
+
} else if (conjugateGradientMkernelFused(st.lap2, st.coords[k], st.b[k], st.n, { tol: TOLERANCE_CG, maxIterations: st.n })) {
|
|
39399
|
+
return true;
|
|
39400
|
+
}
|
|
39401
|
+
}
|
|
39402
|
+
return false;
|
|
39403
|
+
}
|
|
39404
|
+
function majorize(st, ctx, dCoords) {
|
|
39405
|
+
const constantTerm = Math.trunc(st.n * (st.n - 1) / 2);
|
|
39406
|
+
let oldStress = DBL_MAX;
|
|
39407
|
+
let iterations = 0;
|
|
39408
|
+
for (let converged = false; iterations < ctx.maxi && !converged; iterations++) {
|
|
39409
|
+
buildLap12(st);
|
|
39410
|
+
const newStress = computeNewStress(st, constantTerm);
|
|
39411
|
+
converged = Math.abs(newStress - oldStress) / Math.abs(oldStress + 1e-10) < ctx.epsilon;
|
|
39412
|
+
converged ||= iterations > 1 && newStress > oldStress;
|
|
39413
|
+
oldStress = newStress;
|
|
39414
|
+
if (solveAxes(st, ctx)) return -1;
|
|
39415
|
+
}
|
|
39416
|
+
for (let i = 0; i < st.dim; i++) {
|
|
39417
|
+
for (let j = 0; j < st.n; j++) dCoords[i][j] = st.coords[i][j];
|
|
39418
|
+
}
|
|
39419
|
+
return iterations;
|
|
39420
|
+
}
|
|
39421
|
+
function toFloatCoords(dCoords, n, dim) {
|
|
39422
|
+
const coords = [];
|
|
39423
|
+
for (let i = 0; i < dim; i++) coords.push(Float32Array.from(dCoords[i].subarray(0, n)));
|
|
39424
|
+
return coords;
|
|
39425
|
+
}
|
|
39426
|
+
function newLoopState(lap2, coords, n) {
|
|
39427
|
+
const dim = coords.length;
|
|
39428
|
+
return {
|
|
39429
|
+
n,
|
|
39430
|
+
dim,
|
|
39431
|
+
lap2,
|
|
39432
|
+
coords,
|
|
39433
|
+
lap1: new Float32Array(n + Math.trunc(n * (n - 1) / 2)),
|
|
39434
|
+
b: Array.from({ length: dim }, () => new Float32Array(n)),
|
|
39435
|
+
tmpCoords: new Float32Array(n),
|
|
39436
|
+
distAccumulator: new Float32Array(n),
|
|
39437
|
+
degrees: new Float64Array(n)
|
|
39438
|
+
};
|
|
39439
|
+
}
|
|
39440
|
+
function stressMajorizationWithHierarchy(graph, n, dCoords, nodes, o) {
|
|
39441
|
+
if (!hasDirectionality(graph, n)) return unconstrainedMajorization(graph, n, dCoords, nodes, o);
|
|
39442
|
+
const smartIni = (o.opts & OPT_SMART_INIT) !== 0;
|
|
39443
|
+
const layers = smartIni ? smartInitLayers(graph, n, dCoords, nodes, o) : plainInitLayers(graph, n, dCoords, nodes, o.dim);
|
|
39444
|
+
if (typeof layers === "number") return layers;
|
|
39445
|
+
if (n === 1) return 0;
|
|
39446
|
+
if (o.maxi === 0) return 0;
|
|
39447
|
+
const Dij = modelDistances(graph, n, o.model) ?? computeApspPacked2(graph, n);
|
|
39448
|
+
if (!smartIni) scaleDownLayout(dCoords, n, o.dim);
|
|
39449
|
+
if (o.levelsGap > 0) scaleDistances(Dij, dCoords, n, o.dim);
|
|
39450
|
+
centerLayout(dCoords, n, o.dim);
|
|
39451
|
+
const st = newLoopState(Dij, toFloatCoords(dCoords, n, o.dim), n);
|
|
39452
|
+
buildLap22(Dij, n);
|
|
39453
|
+
const cMajEnv = initConstrainedMajorization(Dij, n, layers.ordering, layers.levels, layers.numLevels);
|
|
39454
|
+
return majorize(st, { cMajEnv, levelsGap: o.levelsGap, maxi: o.maxi, epsilon: o.epsilon }, dCoords);
|
|
39455
|
+
}
|
|
39456
|
+
|
|
37813
39457
|
// src/common/utils-inputscale.ts
|
|
37814
39458
|
var POINTS_PER_INCH3 = 72;
|
|
37815
39459
|
function getInputscale(g) {
|
|
@@ -37996,61 +39640,47 @@ function neatoMaxIter(maxiter, mode, n) {
|
|
|
37996
39640
|
if (mode === MODE_MAJOR) return DFLT_ITERATIONS;
|
|
37997
39641
|
return mode === MODE_SGD ? SGD_ITERATIONS : 100 * n;
|
|
37998
39642
|
}
|
|
37999
|
-
|
|
38000
|
-
|
|
38001
|
-
const
|
|
39643
|
+
var levelsGapOf = (g) => lateDouble(g.root.attrs.get("levelsgap"), 0, -Number.MAX_VALUE);
|
|
39644
|
+
function solveStress(c, vtx, dCoords, nodeList) {
|
|
39645
|
+
const { g, mode, model, haveLen, opts } = c;
|
|
38002
39646
|
const n = nodeList.length;
|
|
38003
|
-
const haveLen = graphHasLen(g);
|
|
38004
|
-
const vtx = makeGraphDataC(g, nodeList, haveLen, mode === MODE_HIER || mode === MODE_IPSEP);
|
|
38005
|
-
checkStart(g);
|
|
38006
39647
|
const maxi = neatoMaxIter(g.attrs.get("maxiter"), mode, n);
|
|
38007
39648
|
const epsilon = lateDouble(g.attrs.get("epsilon"), 1e-4, 0);
|
|
39649
|
+
if (mode === MODE_HIER) {
|
|
39650
|
+
return stressMajorizationWithHierarchy(vtx, n, dCoords, nodeList, {
|
|
39651
|
+
dim: DFLT_DIM,
|
|
39652
|
+
opts,
|
|
39653
|
+
model,
|
|
39654
|
+
maxi,
|
|
39655
|
+
epsilon,
|
|
39656
|
+
levelsGap: levelsGapOf(g)
|
|
39657
|
+
});
|
|
39658
|
+
}
|
|
38008
39659
|
const weighted = haveLen && mode !== MODE_IPSEP;
|
|
38009
39660
|
const Dij = weighted ? computeWeightedApspPacked2(vtx, n) : computeApspPacked2(vtx, n);
|
|
38010
|
-
|
|
38011
|
-
stressMajorizationKDMkernel(Dij, n, dCoords, nodeList, {
|
|
39661
|
+
return stressMajorizationKDMkernel(Dij, n, dCoords, nodeList, {
|
|
38012
39662
|
dim: DFLT_DIM,
|
|
38013
|
-
opts
|
|
39663
|
+
opts,
|
|
38014
39664
|
maxi,
|
|
38015
39665
|
epsilon
|
|
38016
39666
|
});
|
|
38017
|
-
for (let i = 0; i < n; i++) {
|
|
38018
|
-
nodeList[i].info.pos = [dCoords[0][i], dCoords[1][i]];
|
|
38019
|
-
}
|
|
38020
39667
|
}
|
|
38021
|
-
function
|
|
38022
|
-
|
|
38023
|
-
|
|
39668
|
+
function runMajorization(g, mode, model) {
|
|
39669
|
+
const nodeList = assignNodeIds2(g);
|
|
39670
|
+
const n = nodeList.length;
|
|
39671
|
+
const haveLen = graphHasLen(g);
|
|
39672
|
+
const init = checkStart(g, n, mode === MODE_HIER ? INIT_SELF : INIT_RANDOM);
|
|
39673
|
+
const opts = init === INIT_SELF ? OPT_EXP_FLAG | OPT_SMART_INIT : OPT_EXP_FLAG;
|
|
39674
|
+
const haveDir = mode === MODE_HIER || mode === MODE_IPSEP;
|
|
39675
|
+
const vtx = makeGraphDataC(g, nodeList, haveLen, haveDir, mode);
|
|
39676
|
+
const dCoords = [new Float64Array(n), new Float64Array(n)];
|
|
39677
|
+
if (solveStress({ g, mode, model, haveLen, opts }, vtx, dCoords, nodeList) < 0) {
|
|
39678
|
+
agerr("prev", "layout aborted");
|
|
39679
|
+
return;
|
|
38024
39680
|
}
|
|
38025
|
-
|
|
38026
|
-
|
|
38027
|
-
function makeGraphDataC(g, nodeList, haveLen, haveDir) {
|
|
38028
|
-
const vtx = nodeList.map((_, i) => ({
|
|
38029
|
-
nedges: 1,
|
|
38030
|
-
edges: [i],
|
|
38031
|
-
ewgts: haveLen || haveDir ? [0] : []
|
|
38032
|
-
}));
|
|
38033
|
-
for (const np of nodeList) {
|
|
38034
|
-
const i = np.info.id;
|
|
38035
|
-
const entry = vtx[i];
|
|
38036
|
-
const seen2 = /* @__PURE__ */ new Map();
|
|
38037
|
-
for (const ep of [...np.outEdges(g), ...np.inEdges(g)]) {
|
|
38038
|
-
if (ep.head === ep.tail) continue;
|
|
38039
|
-
const vp = ep.tail === np ? ep.head : ep.tail;
|
|
38040
|
-
const vid = vp.info.id;
|
|
38041
|
-
const dist4 = haveLen ? lateDouble(ep.attrs.get("len"), 1, 0) : 1;
|
|
38042
|
-
const idx = seen2.get(vid);
|
|
38043
|
-
if (idx !== void 0) {
|
|
38044
|
-
if (haveLen) entry.ewgts[idx] = Math.max(entry.ewgts[idx], dist4);
|
|
38045
|
-
continue;
|
|
38046
|
-
}
|
|
38047
|
-
seen2.set(vid, entry.nedges);
|
|
38048
|
-
entry.edges.push(vid);
|
|
38049
|
-
if (haveLen || haveDir) entry.ewgts.push(dist4);
|
|
38050
|
-
entry.nedges++;
|
|
38051
|
-
}
|
|
39681
|
+
for (let i = 0; i < n; i++) {
|
|
39682
|
+
nodeList[i].info.pos = [dCoords[0][i], dCoords[1][i]];
|
|
38052
39683
|
}
|
|
38053
|
-
return vtx;
|
|
38054
39684
|
}
|
|
38055
39685
|
function solveModel2(g, mode, model) {
|
|
38056
39686
|
if (g.nodes.size < 2) return;
|
|
@@ -38242,6 +39872,25 @@ function esepFactor(g) {
|
|
|
38242
39872
|
return { x: SEPFACT * DFLT_MARGIN, y: SEPFACT * DFLT_MARGIN, doAdd: true };
|
|
38243
39873
|
}
|
|
38244
39874
|
|
|
39875
|
+
// src/common/libm-trig.ts
|
|
39876
|
+
var OCTAGON_TRIG = /* @__PURE__ */ new Map([
|
|
39877
|
+
[-0.39269908169872414, [0.9238795325112867, -0.3826834323650898]],
|
|
39878
|
+
[0.39269908169872414, [0.9238795325112867, 0.3826834323650898]],
|
|
39879
|
+
[1.1780972450961724, [0.38268343236508984, 0.9238795325112867]],
|
|
39880
|
+
[1.9634954084936207, [-0.3826834323650897, 0.9238795325112867]],
|
|
39881
|
+
[2.748893571891069, [-0.9238795325112867, 0.3826834323650899]],
|
|
39882
|
+
[3.5342917352885173, [-0.9238795325112868, -0.38268343236508967]],
|
|
39883
|
+
[4.319689898685965, [-0.38268343236509034, -0.9238795325112865]],
|
|
39884
|
+
[5.105088062083414, [0.38268343236509, -0.9238795325112866]],
|
|
39885
|
+
[5.890486225480862, [0.9238795325112865, -0.3826834323650904]]
|
|
39886
|
+
]);
|
|
39887
|
+
function libmCos(x) {
|
|
39888
|
+
return OCTAGON_TRIG.get(x)?.[0] ?? Math.cos(x);
|
|
39889
|
+
}
|
|
39890
|
+
function libmSin(x) {
|
|
39891
|
+
return OCTAGON_TRIG.get(x)?.[1] ?? Math.sin(x);
|
|
39892
|
+
}
|
|
39893
|
+
|
|
38245
39894
|
// src/layout/neato/delaunay.ts
|
|
38246
39895
|
var ICCERRBOUND_A = (10 + 96 * 2 ** -53) * 2 ** -53;
|
|
38247
39896
|
function ulpExp(v) {
|
|
@@ -38410,6 +40059,32 @@ function delaunayTri(xv, yv, n) {
|
|
|
38410
40059
|
return edges;
|
|
38411
40060
|
}
|
|
38412
40061
|
|
|
40062
|
+
// src/layout/neato/gts-triangle.ts
|
|
40063
|
+
var SQRT3 = 1.73205080757;
|
|
40064
|
+
function gtsTriangleEnclosing(px, py, n, scale) {
|
|
40065
|
+
let xmin = px[0];
|
|
40066
|
+
let xmax = px[0];
|
|
40067
|
+
let ymin = py[0];
|
|
40068
|
+
let ymax = py[0];
|
|
40069
|
+
for (let i = 1; i < n; i++) {
|
|
40070
|
+
if (px[i] > xmax) xmax = px[i];
|
|
40071
|
+
else if (px[i] < xmin) xmin = px[i];
|
|
40072
|
+
if (py[i] > ymax) ymax = py[i];
|
|
40073
|
+
else if (py[i] < ymin) ymin = py[i];
|
|
40074
|
+
}
|
|
40075
|
+
const xo = (xmax + xmin) / 2;
|
|
40076
|
+
const yo = (ymax + ymin) / 2;
|
|
40077
|
+
const dx = xmax - xo;
|
|
40078
|
+
const dy = ymax - yo;
|
|
40079
|
+
let r = scale * Math.sqrt(fma(dx, dx, dy * dy));
|
|
40080
|
+
if (r === 0) r = scale;
|
|
40081
|
+
return [
|
|
40082
|
+
[fma(r, SQRT3, xo), yo - r],
|
|
40083
|
+
[xo, fma(r, 2, yo)],
|
|
40084
|
+
[fma(-r, SQRT3, xo), yo - r]
|
|
40085
|
+
];
|
|
40086
|
+
}
|
|
40087
|
+
|
|
38413
40088
|
// src/layout/neato/cdt-surface.ts
|
|
38414
40089
|
var pairKey = (u, v) => u < v ? u * 1048576 + v : v * 1048576 + u;
|
|
38415
40090
|
var Cdt = class {
|
|
@@ -38920,27 +40595,15 @@ var Cdt = class {
|
|
|
38920
40595
|
return { nfaces: kept.length, faces, neigh };
|
|
38921
40596
|
}
|
|
38922
40597
|
};
|
|
38923
|
-
var SQRT3 = 1.7320508075688772;
|
|
38924
40598
|
function mkSurface(x, y, n, segs, nsegs) {
|
|
38925
40599
|
const px = x.slice(0, n);
|
|
38926
40600
|
const py = y.slice(0, n);
|
|
38927
|
-
let xmin = px[0];
|
|
38928
|
-
let xmax = px[0];
|
|
38929
|
-
let ymin = py[0];
|
|
38930
|
-
let ymax = py[0];
|
|
38931
|
-
for (let i = 1; i < n; i++) {
|
|
38932
|
-
if (px[i] > xmax) xmax = px[i];
|
|
38933
|
-
else if (px[i] < xmin) xmin = px[i];
|
|
38934
|
-
if (py[i] > ymax) ymax = py[i];
|
|
38935
|
-
else if (py[i] < ymin) ymin = py[i];
|
|
38936
|
-
}
|
|
38937
|
-
const xo = (xmax + xmin) / 2;
|
|
38938
|
-
const yo = (ymax + ymin) / 2;
|
|
38939
|
-
let r = 100 * Math.hypot(xmax - xo, ymax - yo);
|
|
38940
|
-
if (r === 0) r = 100;
|
|
38941
40601
|
const s0 = n;
|
|
38942
|
-
|
|
38943
|
-
|
|
40602
|
+
const enc = gtsTriangleEnclosing(px, py, n, 100);
|
|
40603
|
+
for (const [ex, ey] of enc) {
|
|
40604
|
+
px.push(ex);
|
|
40605
|
+
py.push(ey);
|
|
40606
|
+
}
|
|
38944
40607
|
const cdt = new Cdt(px, py);
|
|
38945
40608
|
const cons = [];
|
|
38946
40609
|
for (let k = 0; k < nsegs; k++) {
|
|
@@ -38987,9 +40650,9 @@ function sharedEdge(faces, p3, q3) {
|
|
|
38987
40650
|
return { i: p1, j: p2 };
|
|
38988
40651
|
}
|
|
38989
40652
|
function addTriEdge(g, t, h, seg2) {
|
|
38990
|
-
const
|
|
40653
|
+
const dist5 = Math.sqrt(dist2(g.nodes[t].ctr, g.nodes[h].ctr));
|
|
38991
40654
|
const idx = g.edges.length;
|
|
38992
|
-
g.edges.push({ t, h, seg: seg2, dist:
|
|
40655
|
+
g.edges.push({ t, h, seg: seg2, dist: dist5 });
|
|
38993
40656
|
g.nodes[t].edges.push(idx);
|
|
38994
40657
|
g.nodes[h].edges.push(idx);
|
|
38995
40658
|
}
|
|
@@ -39793,8 +41456,8 @@ function ellipseTangentSlope(a, b, p) {
|
|
|
39793
41456
|
function circumscribedCorner(a, b, i, nsides) {
|
|
39794
41457
|
const angle0 = 2 * Math.PI * (i - 0.5) / nsides;
|
|
39795
41458
|
const angle1 = 2 * Math.PI * (i + 0.5) / nsides;
|
|
39796
|
-
const p0 = { x: a *
|
|
39797
|
-
const p1 = { x: a *
|
|
41459
|
+
const p0 = { x: a * libmCos(angle0), y: b * libmSin(angle0) };
|
|
41460
|
+
const p1 = { x: a * libmCos(angle1), y: b * libmSin(angle1) };
|
|
39798
41461
|
const m0 = ellipseTangentSlope(a, b, p0);
|
|
39799
41462
|
const m1 = ellipseTangentSlope(a, b, p1);
|
|
39800
41463
|
const x = (fms(p1.x, m1, fma(m0, p0.x, -p0.y)) + p1.y) / (m0 - m1);
|
|
@@ -42130,52 +43793,14 @@ function armPow(x, y) {
|
|
|
42130
43793
|
return expInline(ehi, elo, signBias);
|
|
42131
43794
|
}
|
|
42132
43795
|
|
|
42133
|
-
// src/common/crand.ts
|
|
42134
|
-
var C_RAND_MAX = 2147483647;
|
|
42135
|
-
var UNSEEDED_STATE2 = 1;
|
|
42136
|
-
var state2 = UNSEEDED_STATE2;
|
|
42137
|
-
registerRenderState(() => {
|
|
42138
|
-
state2 = UNSEEDED_STATE2;
|
|
42139
|
-
});
|
|
42140
|
-
function csrand(seed) {
|
|
42141
|
-
state2 = seed;
|
|
42142
|
-
}
|
|
42143
|
-
function crand() {
|
|
42144
|
-
state2 = state2 * 16807 % 2147483647;
|
|
42145
|
-
return state2;
|
|
42146
|
-
}
|
|
42147
|
-
function cdrand() {
|
|
42148
|
-
return crand() / C_RAND_MAX;
|
|
42149
|
-
}
|
|
42150
|
-
function gvRandom(bound) {
|
|
42151
|
-
const discardThreshold = C_RAND_MAX - 2147483648 % bound;
|
|
42152
|
-
let r;
|
|
42153
|
-
do {
|
|
42154
|
-
r = crand();
|
|
42155
|
-
} while (r > discardThreshold);
|
|
42156
|
-
return r % bound;
|
|
42157
|
-
}
|
|
42158
|
-
function gvPermutation(bound) {
|
|
42159
|
-
if (bound <= 0) return [];
|
|
42160
|
-
const p = [];
|
|
42161
|
-
for (let i = 0; i < bound; i++) p.push(i);
|
|
42162
|
-
for (let i = bound - 1; i > 0; --i) {
|
|
42163
|
-
const j = gvRandom(i + 1);
|
|
42164
|
-
const t = p[i];
|
|
42165
|
-
p[i] = p[j];
|
|
42166
|
-
p[j] = t;
|
|
42167
|
-
}
|
|
42168
|
-
return p;
|
|
42169
|
-
}
|
|
42170
|
-
|
|
42171
43796
|
// src/layout/sfdp/quadtree.ts
|
|
42172
43797
|
function pointDistance(p1, o1, p2, o2, dim) {
|
|
42173
|
-
let
|
|
43798
|
+
let dist5 = 0;
|
|
42174
43799
|
for (let i = 0; i < dim; i++) {
|
|
42175
43800
|
const d = p1[o1 + i] - p2[o2 + i];
|
|
42176
|
-
|
|
43801
|
+
dist5 = fma(d, d, dist5);
|
|
42177
43802
|
}
|
|
42178
|
-
return Math.sqrt(
|
|
43803
|
+
return Math.sqrt(dist5);
|
|
42179
43804
|
}
|
|
42180
43805
|
function quadTreeNew(dim, center, width2, maxLevel) {
|
|
42181
43806
|
return {
|
|
@@ -42310,8 +43935,8 @@ function getSupernodesInternal(qt, bh, pt, ptOff, nodeid, out) {
|
|
|
42310
43935
|
l = l.next;
|
|
42311
43936
|
}
|
|
42312
43937
|
if (qt.qts !== null) {
|
|
42313
|
-
const
|
|
42314
|
-
if (qt.width < bh *
|
|
43938
|
+
const dist5 = pointDistance(qt.center, 0, pt, ptOff, dim);
|
|
43939
|
+
if (qt.width < bh * dist5) {
|
|
42315
43940
|
for (let i = 0; i < dim; i++) {
|
|
42316
43941
|
out.center[dim * out.nsuper + i] = qt.average[i];
|
|
42317
43942
|
}
|
|
@@ -42409,12 +44034,12 @@ function onedOptimizerTrain(opt, work) {
|
|
|
42409
44034
|
else optHill(opt, i);
|
|
42410
44035
|
}
|
|
42411
44036
|
function distance(x, dim, i, j) {
|
|
42412
|
-
let
|
|
44037
|
+
let dist5 = 0;
|
|
42413
44038
|
for (let k = 0; k < dim; k++) {
|
|
42414
44039
|
const d = x[i * dim + k] - x[j * dim + k];
|
|
42415
|
-
|
|
44040
|
+
dist5 = fma(d, d, dist5);
|
|
42416
44041
|
}
|
|
42417
|
-
return Math.sqrt(
|
|
44042
|
+
return Math.sqrt(dist5);
|
|
42418
44043
|
}
|
|
42419
44044
|
function distanceCropped(x, dim, i, j) {
|
|
42420
44045
|
return Math.max(distance(x, dim, i, j), MINDIST);
|
|
@@ -42422,16 +44047,16 @@ function distanceCropped(x, dim, i, j) {
|
|
|
42422
44047
|
function gatherLeaves(A3, p, checked, x, dim) {
|
|
42423
44048
|
const { ia, ja } = A3;
|
|
42424
44049
|
const leaves = [];
|
|
42425
|
-
let
|
|
44050
|
+
let dist5 = 0;
|
|
42426
44051
|
for (let j = ia[p]; j < ia[p + 1]; j++) {
|
|
42427
44052
|
const c = ja[j];
|
|
42428
44053
|
if (ia[c + 1] - ia[c] === 1) {
|
|
42429
44054
|
checked[c] = true;
|
|
42430
|
-
|
|
44055
|
+
dist5 += distance(x, dim, p, c);
|
|
42431
44056
|
leaves.push(c);
|
|
42432
44057
|
}
|
|
42433
44058
|
}
|
|
42434
|
-
return { leaves, avgDist:
|
|
44059
|
+
return { leaves, avgDist: dist5 / leaves.length };
|
|
42435
44060
|
}
|
|
42436
44061
|
function beautifyLeaves(dim, A3, x) {
|
|
42437
44062
|
const { ia, ja, m } = A3;
|
|
@@ -42454,7 +44079,7 @@ function beautifyLeaves(dim, A3, x) {
|
|
|
42454
44079
|
}
|
|
42455
44080
|
}
|
|
42456
44081
|
function averageEdgeLength(A3, dim, coord) {
|
|
42457
|
-
let
|
|
44082
|
+
let dist5 = 0;
|
|
42458
44083
|
const { ia, ja } = A3;
|
|
42459
44084
|
if (ia[A3.m] === 0) return 1;
|
|
42460
44085
|
for (let i = 0; i < A3.m; i++) {
|
|
@@ -42464,10 +44089,10 @@ function averageEdgeLength(A3, dim, coord) {
|
|
|
42464
44089
|
const dd = coord[dim * i + k] - coord[dim * ja[j]];
|
|
42465
44090
|
d = fma(dd, dd, d);
|
|
42466
44091
|
}
|
|
42467
|
-
|
|
44092
|
+
dist5 += Math.sqrt(d);
|
|
42468
44093
|
}
|
|
42469
44094
|
}
|
|
42470
|
-
return
|
|
44095
|
+
return dist5 / ia[A3.m];
|
|
42471
44096
|
}
|
|
42472
44097
|
function updateStep(adaptiveCooling, step, fnorm, fnorm0) {
|
|
42473
44098
|
if (!adaptiveCooling) return COOL * step;
|
|
@@ -42478,18 +44103,18 @@ function updateStep(adaptiveCooling, step, fnorm, fnorm0) {
|
|
|
42478
44103
|
}
|
|
42479
44104
|
return 0.99 * step / COOL;
|
|
42480
44105
|
}
|
|
42481
|
-
function repulsivePow(
|
|
42482
|
-
return armPow(
|
|
44106
|
+
function repulsivePow(dist5, p) {
|
|
44107
|
+
return armPow(dist5, 1 - p);
|
|
42483
44108
|
}
|
|
42484
44109
|
function attractiveForce(ctx, i) {
|
|
42485
44110
|
const { A: A3, x, dim, fp, f } = ctx;
|
|
42486
44111
|
const { ia, ja } = A3;
|
|
42487
44112
|
for (let j = ia[i]; j < ia[i + 1]; j++) {
|
|
42488
44113
|
if (ja[j] === i) continue;
|
|
42489
|
-
const
|
|
44114
|
+
const dist5 = distance(x, dim, i, ja[j]);
|
|
42490
44115
|
for (let k = 0; k < dim; k++) {
|
|
42491
44116
|
const t = fp.CRK * (x[i * dim + k] - x[ja[j] * dim + k]);
|
|
42492
|
-
f[k] = fma(-t,
|
|
44117
|
+
f[k] = fma(-t, dist5, f[k]);
|
|
42493
44118
|
}
|
|
42494
44119
|
}
|
|
42495
44120
|
}
|
|
@@ -42497,9 +44122,9 @@ function repulsiveForceDirect(ctx, i) {
|
|
|
42497
44122
|
const { x, dim, n, fp, f } = ctx;
|
|
42498
44123
|
for (let j = 0; j < n; j++) {
|
|
42499
44124
|
if (j === i) continue;
|
|
42500
|
-
const
|
|
44125
|
+
const dist5 = distanceCropped(x, dim, i, j);
|
|
42501
44126
|
for (let k = 0; k < dim; k++) {
|
|
42502
|
-
f[k] += fp.KP * (x[i * dim + k] - x[j * dim + k]) / repulsivePow(
|
|
44127
|
+
f[k] += fp.KP * (x[i * dim + k] - x[j * dim + k]) / repulsivePow(dist5, fp.p);
|
|
42503
44128
|
}
|
|
42504
44129
|
}
|
|
42505
44130
|
}
|
|
@@ -42509,9 +44134,9 @@ function repulsiveForceQT(ctx, qt, i, acc) {
|
|
|
42509
44134
|
acc.countsAvg += counts;
|
|
42510
44135
|
acc.nsuperAvg += nsuper;
|
|
42511
44136
|
for (let j = 0; j < nsuper; j++) {
|
|
42512
|
-
const
|
|
44137
|
+
const dist5 = Math.max(distances[j], MINDIST);
|
|
42513
44138
|
for (let k = 0; k < dim; k++) {
|
|
42514
|
-
f[k] += supernodeWgts[j] * fp.KP * (x[i * dim + k] - center[j * dim + k]) / repulsivePow(
|
|
44139
|
+
f[k] += supernodeWgts[j] * fp.KP * (x[i * dim + k] - center[j * dim + k]) / repulsivePow(dist5, fp.p);
|
|
42515
44140
|
}
|
|
42516
44141
|
}
|
|
42517
44142
|
}
|
|
@@ -42767,7 +44392,7 @@ function diagPreconNew(A3) {
|
|
|
42767
44392
|
}
|
|
42768
44393
|
return diag;
|
|
42769
44394
|
}
|
|
42770
|
-
function
|
|
44395
|
+
function conjugateGradient2(A3, precon, n, x, rhs, tol, maxit) {
|
|
42771
44396
|
let rho = 0;
|
|
42772
44397
|
let rhoOld = 1;
|
|
42773
44398
|
let iter = 0;
|
|
@@ -42808,7 +44433,7 @@ function smSolve(A3, dim, x0, rhs, tol, maxit) {
|
|
|
42808
44433
|
x[i] = x0[i * dim + k];
|
|
42809
44434
|
b[i] = rhs[i * dim + k];
|
|
42810
44435
|
}
|
|
42811
|
-
res +=
|
|
44436
|
+
res += conjugateGradient2(A3, precond, n, x, b, tol, maxit);
|
|
42812
44437
|
for (let i = 0; i < n; i++) {
|
|
42813
44438
|
rhs[i * dim + k] = x[i];
|
|
42814
44439
|
}
|
|
@@ -43162,7 +44787,7 @@ function idealDistanceAvoidOverlap(dim, A3, x, width2, idealDistance) {
|
|
|
43162
44787
|
for (let j = ia[i]; j < ia[i + 1]; j++) {
|
|
43163
44788
|
const jj = ja[j];
|
|
43164
44789
|
if (jj === i) continue;
|
|
43165
|
-
const
|
|
44790
|
+
const dist5 = distance(x, dim, i, jj);
|
|
43166
44791
|
const dx = Math.abs(x[i * dim] - x[jj * dim]);
|
|
43167
44792
|
const dy = Math.abs(x[i * dim + 1] - x[jj * dim + 1]);
|
|
43168
44793
|
const wx = width2[i * dim] + width2[jj * dim];
|
|
@@ -43185,9 +44810,9 @@ function idealDistanceAvoidOverlap(dim, A3, x, width2, idealDistance) {
|
|
|
43185
44810
|
t = Math.min(expandmax, t);
|
|
43186
44811
|
t = Math.max(expandmin, t);
|
|
43187
44812
|
if (t > 1) {
|
|
43188
|
-
idealDistance[j] = t *
|
|
44813
|
+
idealDistance[j] = t * dist5;
|
|
43189
44814
|
} else {
|
|
43190
|
-
idealDistance[j] = -t *
|
|
44815
|
+
idealDistance[j] = -t * dist5;
|
|
43191
44816
|
}
|
|
43192
44817
|
}
|
|
43193
44818
|
}
|
|
@@ -43282,9 +44907,9 @@ function overlapSmootherNew(m, dim, x, width2, neighborhoodOnly, shrink) {
|
|
|
43282
44907
|
w[j] = -1 / d[j] / d[j];
|
|
43283
44908
|
d[j] = -d[j];
|
|
43284
44909
|
}
|
|
43285
|
-
const
|
|
44910
|
+
const dist5 = d[j];
|
|
43286
44911
|
diagW += w[j];
|
|
43287
|
-
d[j] = w[j] *
|
|
44912
|
+
d[j] = w[j] * dist5;
|
|
43288
44913
|
diagD += d[j];
|
|
43289
44914
|
}
|
|
43290
44915
|
w[jdiag] = -diagW;
|
|
@@ -43295,11 +44920,11 @@ function overlapSmootherNew(m, dim, x, width2, neighborhoodOnly, shrink) {
|
|
|
43295
44920
|
function totalDistance(m, dim, x, y) {
|
|
43296
44921
|
let total = 0;
|
|
43297
44922
|
for (let i = 0; i < m; i++) {
|
|
43298
|
-
let
|
|
44923
|
+
let dist5 = 0;
|
|
43299
44924
|
for (let j = 0; j < dim; j++) {
|
|
43300
|
-
|
|
44925
|
+
dist5 += (y[i * dim + j] - x[i * dim + j]) * (y[i * dim + j] - x[i * dim + j]);
|
|
43301
44926
|
}
|
|
43302
|
-
total += Math.sqrt(
|
|
44927
|
+
total += Math.sqrt(dist5);
|
|
43303
44928
|
}
|
|
43304
44929
|
return total;
|
|
43305
44930
|
}
|
|
@@ -43332,18 +44957,18 @@ function stressMajorizationSmooth(sm, dim, x, maxitSm) {
|
|
|
43332
44957
|
idiag = j;
|
|
43333
44958
|
continue;
|
|
43334
44959
|
}
|
|
43335
|
-
let
|
|
44960
|
+
let dist5 = distance(x, dim, i, jd[j]);
|
|
43336
44961
|
if (d[j] === 0) {
|
|
43337
44962
|
dd[j] = 0;
|
|
43338
44963
|
} else {
|
|
43339
|
-
if (
|
|
44964
|
+
if (dist5 === 0) {
|
|
43340
44965
|
const dij = d[j] / Lw.a[j];
|
|
43341
44966
|
for (let k = 0; k < dim; k++) {
|
|
43342
44967
|
x[jd[j] * dim + k] += 1e-4 * (cdrand() + 1e-4) * dij;
|
|
43343
44968
|
}
|
|
43344
|
-
|
|
44969
|
+
dist5 = distance(x, dim, i, jd[j]);
|
|
43345
44970
|
}
|
|
43346
|
-
dd[j] = d[j] /
|
|
44971
|
+
dd[j] = d[j] / dist5;
|
|
43347
44972
|
}
|
|
43348
44973
|
diag += dd[j];
|
|
43349
44974
|
}
|
|
@@ -43362,9 +44987,9 @@ function stressMajorizationSmooth(sm, dim, x, maxitSm) {
|
|
|
43362
44987
|
return diff;
|
|
43363
44988
|
}
|
|
43364
44989
|
function scaleToEdgeLength(dim, A3, x, avgLabelSize) {
|
|
43365
|
-
let
|
|
43366
|
-
|
|
43367
|
-
for (let i = 0; i < dim * A3.m; i++) x[i] *=
|
|
44990
|
+
let dist5 = averageEdgeLength(A3, dim, x);
|
|
44991
|
+
dist5 = avgLabelSize / Math.max(dist5, MACHINEACC);
|
|
44992
|
+
for (let i = 0; i < dim * A3.m; i++) x[i] *= dist5;
|
|
43368
44993
|
}
|
|
43369
44994
|
function removeOverlapPrism(dim, A3, x, labelSizes, ntry, initialScaling, doShrinking) {
|
|
43370
44995
|
if (!labelSizes) return;
|
|
@@ -43731,7 +45356,7 @@ function makeHasEdge(g) {
|
|
|
43731
45356
|
}
|
|
43732
45357
|
return (a, b) => pairs.get(a)?.has(b) === true || undirected && pairs.get(b)?.has(a) === true;
|
|
43733
45358
|
}
|
|
43734
|
-
function mkNConstraintG(g, list, intersect,
|
|
45359
|
+
function mkNConstraintG(g, list, intersect, dist5) {
|
|
43735
45360
|
const cg = newCg();
|
|
43736
45361
|
const flat = flatten(list);
|
|
43737
45362
|
let lastn;
|
|
@@ -43748,7 +45373,7 @@ function mkNConstraintG(g, list, intersect, dist4) {
|
|
|
43748
45373
|
const nxp = flat[j];
|
|
43749
45374
|
if (!intersect(p, nxp)) continue;
|
|
43750
45375
|
const e = cgEdge(cg, cnodeOf(p), cnodeOf(nxp));
|
|
43751
|
-
e.info.minlen =
|
|
45376
|
+
e.info.minlen = dist5(p.bb, nxp.bb);
|
|
43752
45377
|
e.info.weight = hasEdge(p.np, nxp.np) ? 100 : 1;
|
|
43753
45378
|
created.push(e);
|
|
43754
45379
|
}
|
|
@@ -43795,12 +45420,12 @@ function buildVisibility(flat, intersect) {
|
|
|
43795
45420
|
}
|
|
43796
45421
|
return vg;
|
|
43797
45422
|
}
|
|
43798
|
-
function mapGraphs(vg, flat, cg,
|
|
45423
|
+
function mapGraphs(vg, flat, cg, dist5) {
|
|
43799
45424
|
for (let i = 0; i < flat.length; i++) {
|
|
43800
45425
|
const tp = flat[i];
|
|
43801
45426
|
for (const j of vg[i]) {
|
|
43802
45427
|
const hp = flat[j];
|
|
43803
|
-
const delta2 =
|
|
45428
|
+
const delta2 = dist5(tp.bb, hp.bb);
|
|
43804
45429
|
const ce = cgEdge(cg, cnodeOf(tp), cnodeOf(hp));
|
|
43805
45430
|
ce.info.weight = 1;
|
|
43806
45431
|
if ((ce.info.minlen ?? 0) < delta2) {
|
|
@@ -43810,15 +45435,15 @@ function mapGraphs(vg, flat, cg, dist4) {
|
|
|
43810
45435
|
}
|
|
43811
45436
|
}
|
|
43812
45437
|
}
|
|
43813
|
-
function mkConstraintG(list, intersect,
|
|
45438
|
+
function mkConstraintG(list, intersect, dist5) {
|
|
43814
45439
|
const cg = newCg();
|
|
43815
45440
|
const flat = flatten(list);
|
|
43816
45441
|
buildChain(cg, flat);
|
|
43817
|
-
mapGraphs(buildVisibility(flat, intersect), flat, cg,
|
|
45442
|
+
mapGraphs(buildVisibility(flat, intersect), flat, cg, dist5);
|
|
43818
45443
|
return cg;
|
|
43819
45444
|
}
|
|
43820
|
-
function buildConstraintGraph(g, list, ifn,
|
|
43821
|
-
return ortho ? mkConstraintG(list, ifn,
|
|
45445
|
+
function buildConstraintGraph(g, list, ifn, dist5, ortho) {
|
|
45446
|
+
return ortho ? mkConstraintG(list, ifn, dist5) : mkNConstraintG(g, list, ifn, dist5);
|
|
43822
45447
|
}
|
|
43823
45448
|
function newItems() {
|
|
43824
45449
|
return new DtBag((p) => p.val, cmpitem);
|
|
@@ -43959,7 +45584,7 @@ function inflatePts(verts, xmargin, ymargin) {
|
|
|
43959
45584
|
v.y *= ymargin;
|
|
43960
45585
|
}
|
|
43961
45586
|
}
|
|
43962
|
-
function
|
|
45587
|
+
function isBox3(verts) {
|
|
43963
45588
|
if (verts.length !== 4) return false;
|
|
43964
45589
|
const [v0, v1, v2, v3] = verts;
|
|
43965
45590
|
if (v0.y === v1.y) {
|
|
@@ -44019,7 +45644,7 @@ function clusterVerts(n, xmargin, ymargin) {
|
|
|
44019
45644
|
function polyKind(n, poly, verts) {
|
|
44020
45645
|
const name = shapeName(n);
|
|
44021
45646
|
if (name === "box") return POLY_BOX;
|
|
44022
|
-
if (name === "polygon" &&
|
|
45647
|
+
if (name === "polygon" && isBox3(verts)) return POLY_BOX;
|
|
44023
45648
|
if (poly.sides < 3 && poly.regular) return POLY_CIRCLE;
|
|
44024
45649
|
return 0;
|
|
44025
45650
|
}
|
|
@@ -44527,7 +46152,7 @@ function heapSiftUp(h, i) {
|
|
|
44527
46152
|
i = parent2;
|
|
44528
46153
|
}
|
|
44529
46154
|
}
|
|
44530
|
-
function
|
|
46155
|
+
function heapSiftDown2(h, i) {
|
|
44531
46156
|
const n = h.length;
|
|
44532
46157
|
for (; ; ) {
|
|
44533
46158
|
let smallest = i;
|
|
@@ -44544,7 +46169,7 @@ function heapSiftDown3(h, i) {
|
|
|
44544
46169
|
}
|
|
44545
46170
|
function makeHeap(h) {
|
|
44546
46171
|
for (let i = (h.length >> 1) - 1; i >= 0; i--) {
|
|
44547
|
-
|
|
46172
|
+
heapSiftDown2(h, i);
|
|
44548
46173
|
}
|
|
44549
46174
|
}
|
|
44550
46175
|
function heapFindMin(h) {
|
|
@@ -44553,7 +46178,7 @@ function heapFindMin(h) {
|
|
|
44553
46178
|
function heapDeleteMin(h) {
|
|
44554
46179
|
h[0] = h[h.length - 1];
|
|
44555
46180
|
h.pop();
|
|
44556
|
-
if (h.length > 0)
|
|
46181
|
+
if (h.length > 0) heapSiftDown2(h, 0);
|
|
44557
46182
|
}
|
|
44558
46183
|
function heapInsert(h, c) {
|
|
44559
46184
|
h.push(c);
|
|
@@ -44637,27 +46262,27 @@ var Block = class _Block {
|
|
|
44637
46262
|
* @see lib/vpsc/block.cpp: Block::merge(Block* b, Constraint* c)
|
|
44638
46263
|
*/
|
|
44639
46264
|
mergeTwoArg(b, c) {
|
|
44640
|
-
const
|
|
46265
|
+
const dist5 = c.right.offset - c.left.offset - c.gap;
|
|
44641
46266
|
let l = c.left.block;
|
|
44642
46267
|
let r = c.right.block;
|
|
44643
46268
|
if (this.vars.length < b.vars.length) {
|
|
44644
|
-
r.mergeInto(l, c,
|
|
46269
|
+
r.mergeInto(l, c, dist5);
|
|
44645
46270
|
} else {
|
|
44646
|
-
l.mergeInto(r, c, -
|
|
46271
|
+
l.mergeInto(r, c, -dist5);
|
|
44647
46272
|
}
|
|
44648
46273
|
}
|
|
44649
46274
|
/**
|
|
44650
46275
|
* Merge block b into this across constraint c by dist.
|
|
44651
46276
|
* @see lib/vpsc/block.cpp: Block::merge(Block *b, Constraint *c, double dist)
|
|
44652
46277
|
*/
|
|
44653
|
-
mergeInto(b, c,
|
|
46278
|
+
mergeInto(b, c, dist5) {
|
|
44654
46279
|
c.active = true;
|
|
44655
|
-
this.wposn += b.wposn -
|
|
46280
|
+
this.wposn += b.wposn - dist5 * b.weight;
|
|
44656
46281
|
this.weight += b.weight;
|
|
44657
46282
|
this.posn = this.wposn / this.weight;
|
|
44658
46283
|
for (const v of b.vars) {
|
|
44659
46284
|
v.block = this;
|
|
44660
|
-
v.offset +=
|
|
46285
|
+
v.offset += dist5;
|
|
44661
46286
|
this.vars.push(v);
|
|
44662
46287
|
}
|
|
44663
46288
|
b.deleted = true;
|
|
@@ -44946,13 +46571,13 @@ var Blocks = class {
|
|
|
44946
46571
|
r.deleteMinInConstraint();
|
|
44947
46572
|
let l = c.left.block;
|
|
44948
46573
|
if (l.in.length === 0) l.setUpInConstraints();
|
|
44949
|
-
let
|
|
46574
|
+
let dist5 = c.right.offset - c.left.offset - c.gap;
|
|
44950
46575
|
if (r.vars.length < l.vars.length) {
|
|
44951
|
-
|
|
46576
|
+
dist5 = -dist5;
|
|
44952
46577
|
[l, r] = [r, l];
|
|
44953
46578
|
}
|
|
44954
46579
|
this.timeCtr.value++;
|
|
44955
|
-
r.mergeInto(l, c,
|
|
46580
|
+
r.mergeInto(l, c, dist5);
|
|
44956
46581
|
r.mergeIn(l);
|
|
44957
46582
|
r.timeStamp = this.timeCtr.value;
|
|
44958
46583
|
this.removeBlock(l);
|
|
@@ -44970,12 +46595,12 @@ var Blocks = class {
|
|
|
44970
46595
|
l.deleteMinOutConstraint();
|
|
44971
46596
|
let r = c.right.block;
|
|
44972
46597
|
r.setUpOutConstraints();
|
|
44973
|
-
let
|
|
46598
|
+
let dist5 = c.left.offset + c.gap - c.right.offset;
|
|
44974
46599
|
if (l.vars.length > r.vars.length) {
|
|
44975
|
-
|
|
46600
|
+
dist5 = -dist5;
|
|
44976
46601
|
[l, r] = [r, l];
|
|
44977
46602
|
}
|
|
44978
|
-
l.mergeInto(r, c,
|
|
46603
|
+
l.mergeInto(r, c, dist5);
|
|
44979
46604
|
l.mergeOut(r);
|
|
44980
46605
|
this.removeBlock(r);
|
|
44981
46606
|
c = l.findMinOutConstraint();
|
|
@@ -45491,7 +47116,7 @@ function warnUnrecognizedOverlap(flag) {
|
|
|
45491
47116
|
const s = flag.toLowerCase();
|
|
45492
47117
|
if (s.startsWith("prism") || NAMED_MODES.has(s)) return;
|
|
45493
47118
|
if (mapBoolDflt(flag, false) === mapBoolDflt(flag, true)) return;
|
|
45494
|
-
|
|
47119
|
+
agwarningf(`Unrecognized overlap value "${flag}" - using false`);
|
|
45495
47120
|
}
|
|
45496
47121
|
function getAdjustMode(flag) {
|
|
45497
47122
|
warnUnrecognizedOverlap(flag);
|
|
@@ -45524,7 +47149,7 @@ function adjustLate(g, am) {
|
|
|
45524
47149
|
case AM_VPSC:
|
|
45525
47150
|
return vpscAdjust(g);
|
|
45526
47151
|
default:
|
|
45527
|
-
|
|
47152
|
+
agwarningf(`Unhandled adjust option ${am.print}`);
|
|
45528
47153
|
return 0;
|
|
45529
47154
|
}
|
|
45530
47155
|
}
|
|
@@ -46498,20 +48123,20 @@ function coincidentDelta() {
|
|
|
46498
48123
|
} while (xdelta === 0 && ydelta === 0);
|
|
46499
48124
|
return { xdelta, ydelta };
|
|
46500
48125
|
}
|
|
46501
|
-
function doRep(p, q, xdelta, ydelta,
|
|
48126
|
+
function doRep(p, q, xdelta, ydelta, dist5) {
|
|
46502
48127
|
let force;
|
|
46503
|
-
if (!(
|
|
48128
|
+
if (!(dist5 > 0)) {
|
|
46504
48129
|
const d = coincidentDelta();
|
|
46505
48130
|
xdelta = d.xdelta;
|
|
46506
48131
|
ydelta = d.ydelta;
|
|
46507
|
-
|
|
48132
|
+
dist5 = libmHypot(xdelta, ydelta);
|
|
46508
48133
|
}
|
|
46509
|
-
if (
|
|
48134
|
+
if (dist5 > fdpParms.Mlimit) {
|
|
46510
48135
|
force = 0;
|
|
46511
48136
|
} else if (parms.useNew) {
|
|
46512
|
-
force = parms.K * parms.K / (
|
|
48137
|
+
force = parms.K * parms.K / (dist5 * dist5 * dist5);
|
|
46513
48138
|
} else {
|
|
46514
|
-
force = parms.K * parms.K / (
|
|
48139
|
+
force = parms.K * parms.K / (dist5 * dist5);
|
|
46515
48140
|
}
|
|
46516
48141
|
if (isPort(p) && isPort(q)) force *= 10;
|
|
46517
48142
|
const dq = disp(q);
|
|
@@ -46533,8 +48158,8 @@ function doNeighbor(grid2, i, j, nodes) {
|
|
|
46533
48158
|
for (const q of cellp.nodes) {
|
|
46534
48159
|
const xdelta = q.info.pos[0] - p.info.pos[0];
|
|
46535
48160
|
const ydelta = q.info.pos[1] - p.info.pos[1];
|
|
46536
|
-
const
|
|
46537
|
-
if (
|
|
48161
|
+
const dist5 = libmHypot(xdelta, ydelta);
|
|
48162
|
+
if (dist5 < parms.Cell) doRep(p, q, xdelta, ydelta, dist5);
|
|
46538
48163
|
}
|
|
46539
48164
|
}
|
|
46540
48165
|
}
|
|
@@ -46566,12 +48191,12 @@ function applyAttr(p, q, e) {
|
|
|
46566
48191
|
ydelta = d.ydelta;
|
|
46567
48192
|
dist22 = fma(xdelta, xdelta, ydelta * ydelta);
|
|
46568
48193
|
}
|
|
46569
|
-
const
|
|
48194
|
+
const dist5 = Math.sqrt(dist22);
|
|
46570
48195
|
let force;
|
|
46571
48196
|
if (parms.useNew) {
|
|
46572
|
-
force = (e.info.factor ?? 1) * (
|
|
48197
|
+
force = (e.info.factor ?? 1) * (dist5 - (e.info.dist ?? 1)) / dist5;
|
|
46573
48198
|
} else {
|
|
46574
|
-
force = (e.info.factor ?? 1) *
|
|
48199
|
+
force = (e.info.factor ?? 1) * dist5 / (e.info.dist ?? 1);
|
|
46575
48200
|
}
|
|
46576
48201
|
const dq = disp(q);
|
|
46577
48202
|
const dp = disp(p);
|
|
@@ -46746,16 +48371,16 @@ function cntOverlaps(g) {
|
|
|
46746
48371
|
function applyRep2(p, q, rs) {
|
|
46747
48372
|
let xdelta = q.info.pos[0] - p.info.pos[0];
|
|
46748
48373
|
let ydelta = q.info.pos[1] - p.info.pos[1];
|
|
46749
|
-
let
|
|
46750
|
-
if (!(
|
|
48374
|
+
let dist5 = libmHypot(xdelta, ydelta);
|
|
48375
|
+
if (!(dist5 > 0)) {
|
|
46751
48376
|
const d = coincidentDelta();
|
|
46752
48377
|
xdelta = d.xdelta;
|
|
46753
48378
|
ydelta = d.ydelta;
|
|
46754
|
-
|
|
48379
|
+
dist5 = libmHypot(xdelta, ydelta);
|
|
46755
48380
|
}
|
|
46756
48381
|
const ov = overlap4(p, q) ? 1 : 0;
|
|
46757
|
-
let force = ov ? rs.ov / (
|
|
46758
|
-
if (
|
|
48382
|
+
let force = ov ? rs.ov / (dist5 * dist5) : rs.nonov / (dist5 * dist5);
|
|
48383
|
+
if (dist5 > fdpParms.Mlimit) force = 0;
|
|
46759
48384
|
const dq = disp(q);
|
|
46760
48385
|
const dp = disp(p);
|
|
46761
48386
|
dq[0] = fma(xdelta, force, dq[0]);
|
|
@@ -46768,10 +48393,10 @@ function applyAttr2(p, q) {
|
|
|
46768
48393
|
if (overlap4(p, q)) return;
|
|
46769
48394
|
const xdelta = q.info.pos[0] - p.info.pos[0];
|
|
46770
48395
|
const ydelta = q.info.pos[1] - p.info.pos[1];
|
|
46771
|
-
const
|
|
48396
|
+
const dist5 = libmHypot(xdelta, ydelta);
|
|
46772
48397
|
const din = rad(p) + rad(q);
|
|
46773
|
-
const dout =
|
|
46774
|
-
const force = dout * dout / ((xParams.K + din) *
|
|
48398
|
+
const dout = dist5 - din;
|
|
48399
|
+
const force = dout * dout / ((xParams.K + din) * dist5);
|
|
46775
48400
|
const dq = disp(q);
|
|
46776
48401
|
const dp = disp(p);
|
|
46777
48402
|
dq[0] = fms(xdelta, force, dq[0]);
|
|
@@ -47926,9 +49551,9 @@ function pcpRotate(n, dim, x) {
|
|
|
47926
49551
|
axis[0] = -(-y[0] + y[3] - Math.sqrt(radicand)) / (2 * y[1]);
|
|
47927
49552
|
axis[1] = 1;
|
|
47928
49553
|
}
|
|
47929
|
-
const
|
|
47930
|
-
axis[0] = axis[0] /
|
|
47931
|
-
axis[1] = axis[1] /
|
|
49554
|
+
const dist5 = Math.sqrt(fma(axis[0], axis[0], 1));
|
|
49555
|
+
axis[0] = axis[0] / dist5;
|
|
49556
|
+
axis[1] = axis[1] / dist5;
|
|
47932
49557
|
for (let i = 0; i < n; i++) {
|
|
47933
49558
|
const x0 = fma(x[dim * i], axis[0], x[dim * i + 1] * axis[1]);
|
|
47934
49559
|
const x1 = fma(-x[dim * i], axis[1], x[dim * i + 1] * axis[0]);
|
|
@@ -48341,10 +49966,10 @@ function buildSpanTree(nodes, edges) {
|
|
|
48341
49966
|
}
|
|
48342
49967
|
return map;
|
|
48343
49968
|
}
|
|
48344
|
-
function measureDist(leaf, anc,
|
|
49969
|
+
function measureDist(leaf, anc, dist5, change) {
|
|
48345
49970
|
const p = anc.tparent;
|
|
48346
49971
|
if (!p) return;
|
|
48347
|
-
const d =
|
|
49972
|
+
const d = dist5 + 1;
|
|
48348
49973
|
if (p.distone === 0) {
|
|
48349
49974
|
p.leafone = leaf;
|
|
48350
49975
|
p.distone = d;
|
|
@@ -49844,11 +51469,11 @@ var DEFAULT_COLOR5 = "black";
|
|
|
49844
51469
|
var PENWIDTH_NORMAL4 = 1;
|
|
49845
51470
|
var PENWIDTH_THRESHOLD4 = 5e-3;
|
|
49846
51471
|
var EPS3 = 1e-5;
|
|
49847
|
-
function
|
|
51472
|
+
function dist4(a, b) {
|
|
49848
51473
|
return Math.sqrt(dist2(a, b));
|
|
49849
51474
|
}
|
|
49850
51475
|
function approxLen(list, off) {
|
|
49851
|
-
return
|
|
51476
|
+
return dist4(list[off], list[off + 1]) + dist4(list[off + 1], list[off + 2]) + dist4(list[off + 2], list[off + 3]);
|
|
49852
51477
|
}
|
|
49853
51478
|
function splitCubic(v, t) {
|
|
49854
51479
|
const left2 = [];
|
|
@@ -49927,7 +51552,7 @@ function drawSplitSpline(list, segs, job) {
|
|
|
49927
51552
|
return endColor;
|
|
49928
51553
|
}
|
|
49929
51554
|
function emitSplitEdgePaths(e, job, colorList) {
|
|
49930
|
-
const segs = parseSegs(colorList).segs;
|
|
51555
|
+
const segs = parseSegs(colorList, edgeSegsContext(e)).segs;
|
|
49931
51556
|
const firstColor2 = segs[0]?.color ?? DEFAULT_COLOR5;
|
|
49932
51557
|
const spl = e.info.spl;
|
|
49933
51558
|
let endColor = firstColor2;
|
|
@@ -49948,8 +51573,8 @@ var forfunc = (cur, total, init) => (1 - cur / total) * init / 2;
|
|
|
49948
51573
|
var revfunc = (cur, total, init) => cur / total * init / 2;
|
|
49949
51574
|
var nonefunc = (_cur, _total, init) => init / 2;
|
|
49950
51575
|
var bothfunc = (cur, total, init) => {
|
|
49951
|
-
const
|
|
49952
|
-
return
|
|
51576
|
+
const fr7 = cur / total;
|
|
51577
|
+
return fr7 <= 0.5 ? fr7 * init : (1 - fr7) * init;
|
|
49953
51578
|
};
|
|
49954
51579
|
function taperfun(dir, directed) {
|
|
49955
51580
|
if (dir === "forward") return forfunc;
|
|
@@ -51383,7 +53008,7 @@ var DotWriterBase = class {
|
|
|
51383
53008
|
|
|
51384
53009
|
// src/render/dot/edge-draw.ts
|
|
51385
53010
|
var DEFAULT_COLOR6 = "black";
|
|
51386
|
-
var
|
|
53011
|
+
var DEFAULT_LINE_STYLE2 = ["solid", "setlinewidth(1)"];
|
|
51387
53012
|
function emitArrowOp(buf, op, pen) {
|
|
51388
53013
|
switch (op.kind) {
|
|
51389
53014
|
case "polygon":
|
|
@@ -51418,8 +53043,9 @@ var EdgeDrawBase = class extends DotWriterBase {
|
|
|
51418
53043
|
*/
|
|
51419
53044
|
attachmentPolyline(pts, pencolor, job) {
|
|
51420
53045
|
const obj = job.obj;
|
|
53046
|
+
gvrenderSetStyle(DEFAULT_LINE_STYLE2);
|
|
51421
53047
|
if (obj !== null) {
|
|
51422
|
-
obj.rawStyle = [...
|
|
53048
|
+
obj.rawStyle = [...DEFAULT_LINE_STYLE2];
|
|
51423
53049
|
obj.pen = 3 /* Solid */;
|
|
51424
53050
|
obj.penWidth = 1;
|
|
51425
53051
|
obj.penColor = resolveRenderColor(pencolor.split(":")[0]);
|
|
@@ -51473,8 +53099,8 @@ var EdgeDrawBase = class extends DotWriterBase {
|
|
|
51473
53099
|
* under that segment's pen. Reuses the same split geometry
|
|
51474
53100
|
* (splitSplineByColor) as the SVG path. @see lib/common/emit.c:1975 multicolor
|
|
51475
53101
|
*/
|
|
51476
|
-
emitSplitSpline(bzList, colorAttr, edraw, job) {
|
|
51477
|
-
const segs = parseSegs(colorAttr).segs;
|
|
53102
|
+
emitSplitSpline(bzList, e, colorAttr, edraw, job) {
|
|
53103
|
+
const segs = parseSegs(colorAttr, edgeSegsContext(e)).segs;
|
|
51478
53104
|
const firstColor2 = segs[0]?.color ?? DEFAULT_COLOR6;
|
|
51479
53105
|
let endColor = firstColor2;
|
|
51480
53106
|
for (const bz of bzList) {
|
|
@@ -51497,7 +53123,7 @@ var EdgeDrawBase = class extends DotWriterBase {
|
|
|
51497
53123
|
const segData = bzList.map(
|
|
51498
53124
|
(bz) => bz !== void 0 && bz.size >= 4 ? buildOffsetLists(bz.list, (2 + numc) / 2) : { offlist: [], tmplist: [] }
|
|
51499
53125
|
);
|
|
51500
|
-
const colors =
|
|
53126
|
+
const colors = parseSegsSilent(colorAttr).segs.map((s) => s.color ?? DEFAULT_COLOR6);
|
|
51501
53127
|
for (const color of colors) {
|
|
51502
53128
|
const pen = xdotPenColor(resolveRenderColor(color));
|
|
51503
53129
|
for (const sd of segData) {
|
|
@@ -51653,7 +53279,7 @@ var XdotRenderer = class extends EdgeDrawBase {
|
|
|
51653
53279
|
let tailArrowColor;
|
|
51654
53280
|
let headArrowColor;
|
|
51655
53281
|
if (numsemi > 0 && numc > 0) {
|
|
51656
|
-
const c = this.emitSplitSpline(spl.list, colorAttr, edraw, job);
|
|
53282
|
+
const c = this.emitSplitSpline(spl.list, e, colorAttr, edraw, job);
|
|
51657
53283
|
tailArrowColor = c.firstColor;
|
|
51658
53284
|
headArrowColor = c.endColor;
|
|
51659
53285
|
} else if (edgeIsTapered(e)) {
|
|
@@ -51889,66 +53515,6 @@ function svgTaperedEdge(e, job) {
|
|
|
51889
53515
|
svgArrowPolygons(e, job);
|
|
51890
53516
|
}
|
|
51891
53517
|
|
|
51892
|
-
// src/gvc/image-resolver.ts
|
|
51893
|
-
var activeResolver = null;
|
|
51894
|
-
var EXT_MIME = {
|
|
51895
|
-
png: "image/png",
|
|
51896
|
-
jpg: "image/jpeg",
|
|
51897
|
-
jpeg: "image/jpeg",
|
|
51898
|
-
gif: "image/gif",
|
|
51899
|
-
svg: "image/svg+xml",
|
|
51900
|
-
webp: "image/webp"
|
|
51901
|
-
};
|
|
51902
|
-
var FALLBACK_MIME = "application/octet-stream";
|
|
51903
|
-
function inferMimeFromSrc(src) {
|
|
51904
|
-
const dot = src.lastIndexOf(".");
|
|
51905
|
-
if (dot < 0 || dot === src.length - 1) return FALLBACK_MIME;
|
|
51906
|
-
const ext = src.slice(dot + 1).toLowerCase();
|
|
51907
|
-
return EXT_MIME[ext] ?? FALLBACK_MIME;
|
|
51908
|
-
}
|
|
51909
|
-
function findImageBytes(src, resolver) {
|
|
51910
|
-
const active = resolver ?? activeResolver;
|
|
51911
|
-
if (active === null) return null;
|
|
51912
|
-
const result = active(src);
|
|
51913
|
-
if (result === null) return null;
|
|
51914
|
-
if (result instanceof Uint8Array) {
|
|
51915
|
-
return { bytes: result, mime: inferMimeFromSrc(src) };
|
|
51916
|
-
}
|
|
51917
|
-
return { bytes: result.bytes, mime: result.mime ?? inferMimeFromSrc(src) };
|
|
51918
|
-
}
|
|
51919
|
-
var B64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
51920
|
-
function base64Encode(bytes) {
|
|
51921
|
-
const len = bytes.length;
|
|
51922
|
-
const out = [];
|
|
51923
|
-
let i = 0;
|
|
51924
|
-
for (; i + 2 < len; i += 3) {
|
|
51925
|
-
const n = bytes[i] << 16 | bytes[i + 1] << 8 | bytes[i + 2];
|
|
51926
|
-
out.push(
|
|
51927
|
-
B64_CHARS[n >> 18 & 63],
|
|
51928
|
-
B64_CHARS[n >> 12 & 63],
|
|
51929
|
-
B64_CHARS[n >> 6 & 63],
|
|
51930
|
-
B64_CHARS[n & 63]
|
|
51931
|
-
);
|
|
51932
|
-
}
|
|
51933
|
-
const remaining = len - i;
|
|
51934
|
-
if (remaining === 1) {
|
|
51935
|
-
const n = bytes[i] << 16;
|
|
51936
|
-
out.push(B64_CHARS[n >> 18 & 63], B64_CHARS[n >> 12 & 63], "==");
|
|
51937
|
-
} else if (remaining === 2) {
|
|
51938
|
-
const n = bytes[i] << 16 | bytes[i + 1] << 8;
|
|
51939
|
-
out.push(
|
|
51940
|
-
B64_CHARS[n >> 18 & 63],
|
|
51941
|
-
B64_CHARS[n >> 12 & 63],
|
|
51942
|
-
B64_CHARS[n >> 6 & 63],
|
|
51943
|
-
"="
|
|
51944
|
-
);
|
|
51945
|
-
}
|
|
51946
|
-
return out.join("");
|
|
51947
|
-
}
|
|
51948
|
-
function toDataUri(bytes, mime) {
|
|
51949
|
-
return "data:" + mime + ";base64," + base64Encode(bytes);
|
|
51950
|
-
}
|
|
51951
|
-
|
|
51952
53518
|
// src/render/svg.ts
|
|
51953
53519
|
function emitMulticolorArrows(e, job, headColor, tailColor) {
|
|
51954
53520
|
const obj = job.obj;
|
|
@@ -52364,7 +53930,7 @@ function peg$parse(input, options) {
|
|
|
52364
53930
|
return s;
|
|
52365
53931
|
}
|
|
52366
53932
|
function peg$f13(t, m, attrs) {
|
|
52367
|
-
if (m) agwarningf("attribute macros not implemented"
|
|
53933
|
+
if (m) agwarningf("attribute macros not implemented");
|
|
52368
53934
|
return { type: "attr", target: t, attrs };
|
|
52369
53935
|
}
|
|
52370
53936
|
function peg$f14(a) {
|
|
@@ -56263,7 +57829,7 @@ function isPeggyError(err) {
|
|
|
56263
57829
|
function warnNumberAmbiguities(src, upTo) {
|
|
56264
57830
|
for (const a of scanNumberAmbiguities(src, Stripper.strip(src))) {
|
|
56265
57831
|
if (a.offset > upTo) break;
|
|
56266
|
-
agerrFinished(numberAmbiguityMessage(a)
|
|
57832
|
+
agerrFinished(numberAmbiguityMessage(a));
|
|
56267
57833
|
}
|
|
56268
57834
|
}
|
|
56269
57835
|
function parse(src) {
|