@knowvah/dot-engine 2.6.12 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/api.js +18 -4
- package/dist/api.js.map +3 -3
- 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/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.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 +2460 -901
- 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/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 +2340 -781
- package/dist/render.js.map +4 -4
- package/package.json +1 -1
- 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/multicolor.ts +88 -24
- package/src/common/poly-gencode.ts +16 -8
- package/src/common/poly-init.ts +19 -1
- 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/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;
|
|
@@ -6286,9 +6293,15 @@ function scanCdata(text, p, base, dataOf, tokens) {
|
|
|
6286
6293
|
if (end > p) tokens.push({ kind: "cdata", start: base + p, end: base + end, data: dataOf(base + p, base + end) });
|
|
6287
6294
|
return close < 0 ? -1 : close + CDATA_CLOSE.length;
|
|
6288
6295
|
}
|
|
6296
|
+
var CONTENT_NON_XML = /[\x00-\x08\x0b\x0c\x0e-\x1f\ufffe\uffff]|[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/;
|
|
6289
6297
|
function scanText(text, p, base, tokens) {
|
|
6290
6298
|
const e = text.indexOf("<", p);
|
|
6291
6299
|
const slice = text.slice(p, e < 0 ? text.length : e);
|
|
6300
|
+
const bad = CONTENT_NON_XML.exec(slice)?.index;
|
|
6301
|
+
if (bad !== void 0) {
|
|
6302
|
+
if (bad > 0) tokens.push({ kind: "text", start: base + p, end: base + p + bad });
|
|
6303
|
+
return { at: p + bad, held: false, invalid: p + bad };
|
|
6304
|
+
}
|
|
6292
6305
|
const from = e < 0 ? heldRefStart(slice) : void 0;
|
|
6293
6306
|
const end = from === void 0 ? p + slice.length : p + from;
|
|
6294
6307
|
if (end > p) tokens.push({ kind: "text", start: base + p, end: base + end });
|
|
@@ -6308,6 +6321,7 @@ function scanContent(text, base, inCdata, dataOf) {
|
|
|
6308
6321
|
}
|
|
6309
6322
|
if (text[p] !== "<") {
|
|
6310
6323
|
const scanned = scanText(text, p, base, tokens);
|
|
6324
|
+
if (scanned.invalid !== void 0) return { tokens, consumed: scanned.at, invalid: base + scanned.invalid, inCdata: false };
|
|
6311
6325
|
if (scanned.held) return { tokens, consumed: scanned.at, inCdata: false };
|
|
6312
6326
|
p = scanned.at;
|
|
6313
6327
|
continue;
|
|
@@ -7314,11 +7328,79 @@ var parseHtmlLabelRv = (src, stderr) => {
|
|
|
7314
7328
|
};
|
|
7315
7329
|
var parseHtmlLabel = (src) => parseHtmlLabelRv(src, new StderrLines(() => void 0)).label;
|
|
7316
7330
|
|
|
7331
|
+
// src/gvc/image-resolver.ts
|
|
7332
|
+
var activeResolver = null;
|
|
7333
|
+
var EXT_MIME = {
|
|
7334
|
+
png: "image/png",
|
|
7335
|
+
jpg: "image/jpeg",
|
|
7336
|
+
jpeg: "image/jpeg",
|
|
7337
|
+
gif: "image/gif",
|
|
7338
|
+
svg: "image/svg+xml",
|
|
7339
|
+
webp: "image/webp"
|
|
7340
|
+
};
|
|
7341
|
+
var FALLBACK_MIME = "application/octet-stream";
|
|
7342
|
+
function inferMimeFromSrc(src) {
|
|
7343
|
+
const dot = src.lastIndexOf(".");
|
|
7344
|
+
if (dot < 0 || dot === src.length - 1) return FALLBACK_MIME;
|
|
7345
|
+
const ext = src.slice(dot + 1).toLowerCase();
|
|
7346
|
+
return EXT_MIME[ext] ?? FALLBACK_MIME;
|
|
7347
|
+
}
|
|
7348
|
+
function findImageBytes(src, resolver) {
|
|
7349
|
+
const active = resolver ?? activeResolver;
|
|
7350
|
+
if (active === null) return null;
|
|
7351
|
+
const result = active(src);
|
|
7352
|
+
if (result === null) return null;
|
|
7353
|
+
if (result instanceof Uint8Array) {
|
|
7354
|
+
return { bytes: result, mime: inferMimeFromSrc(src) };
|
|
7355
|
+
}
|
|
7356
|
+
return { bytes: result.bytes, mime: result.mime ?? inferMimeFromSrc(src) };
|
|
7357
|
+
}
|
|
7358
|
+
var B64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
7359
|
+
function base64Encode(bytes) {
|
|
7360
|
+
const len = bytes.length;
|
|
7361
|
+
const out = [];
|
|
7362
|
+
let i = 0;
|
|
7363
|
+
for (; i + 2 < len; i += 3) {
|
|
7364
|
+
const n = bytes[i] << 16 | bytes[i + 1] << 8 | bytes[i + 2];
|
|
7365
|
+
out.push(
|
|
7366
|
+
B64_CHARS[n >> 18 & 63],
|
|
7367
|
+
B64_CHARS[n >> 12 & 63],
|
|
7368
|
+
B64_CHARS[n >> 6 & 63],
|
|
7369
|
+
B64_CHARS[n & 63]
|
|
7370
|
+
);
|
|
7371
|
+
}
|
|
7372
|
+
const remaining = len - i;
|
|
7373
|
+
if (remaining === 1) {
|
|
7374
|
+
const n = bytes[i] << 16;
|
|
7375
|
+
out.push(B64_CHARS[n >> 18 & 63], B64_CHARS[n >> 12 & 63], "==");
|
|
7376
|
+
} else if (remaining === 2) {
|
|
7377
|
+
const n = bytes[i] << 16 | bytes[i + 1] << 8;
|
|
7378
|
+
out.push(
|
|
7379
|
+
B64_CHARS[n >> 18 & 63],
|
|
7380
|
+
B64_CHARS[n >> 12 & 63],
|
|
7381
|
+
B64_CHARS[n >> 6 & 63],
|
|
7382
|
+
"="
|
|
7383
|
+
);
|
|
7384
|
+
}
|
|
7385
|
+
return out.join("");
|
|
7386
|
+
}
|
|
7387
|
+
function toDataUri(bytes, mime) {
|
|
7388
|
+
return "data:" + mime + ";base64," + base64Encode(bytes);
|
|
7389
|
+
}
|
|
7390
|
+
|
|
7317
7391
|
// src/gvc/usershape.ts
|
|
7318
7392
|
var activeSizer = null;
|
|
7319
7393
|
function findImageSize(src) {
|
|
7320
7394
|
return activeSizer !== null ? activeSizer(src) : null;
|
|
7321
7395
|
}
|
|
7396
|
+
var STRERROR_ENOENT = "No such file or directory";
|
|
7397
|
+
function imageIsSupplied(name, sizer, resolver) {
|
|
7398
|
+
const size = sizer !== void 0 ? sizer(name) : findImageSize(name);
|
|
7399
|
+
return size !== null || findImageBytes(name, resolver) !== null;
|
|
7400
|
+
}
|
|
7401
|
+
function imageOpenWarning(name) {
|
|
7402
|
+
return `${STRERROR_ENOENT} while opening ${name}`;
|
|
7403
|
+
}
|
|
7322
7404
|
|
|
7323
7405
|
// src/common/pointset.ts
|
|
7324
7406
|
function cmpPair(a, b) {
|
|
@@ -7371,6 +7453,173 @@ var PointSet = class {
|
|
|
7371
7453
|
}
|
|
7372
7454
|
};
|
|
7373
7455
|
|
|
7456
|
+
// src/common/emit-types.ts
|
|
7457
|
+
var PS2INCH = 1 / 72;
|
|
7458
|
+
var HTML_BF = 1 << 0;
|
|
7459
|
+
var HTML_IF = 1 << 1;
|
|
7460
|
+
var HTML_UL = 1 << 2;
|
|
7461
|
+
var HTML_SUP = 1 << 3;
|
|
7462
|
+
var HTML_SUB = 1 << 4;
|
|
7463
|
+
var HTML_S = 1 << 5;
|
|
7464
|
+
var HTML_OL = 1 << 6;
|
|
7465
|
+
|
|
7466
|
+
// src/common/htmltable-pos-runs.ts
|
|
7467
|
+
function itemFontFlags(item) {
|
|
7468
|
+
let f = 0;
|
|
7469
|
+
if (item.bold) f |= HTML_BF;
|
|
7470
|
+
if (item.italic) f |= HTML_IF;
|
|
7471
|
+
if (item.underline) f |= HTML_UL;
|
|
7472
|
+
if (item.superscript) f |= HTML_SUP;
|
|
7473
|
+
if (item.subscript) f |= HTML_SUB;
|
|
7474
|
+
if (item.strikethrough) f |= HTML_S;
|
|
7475
|
+
if (item.overline) f |= HTML_OL;
|
|
7476
|
+
return f;
|
|
7477
|
+
}
|
|
7478
|
+
function itemFace(item, finfo) {
|
|
7479
|
+
return {
|
|
7480
|
+
fs: item.fontSize !== void 0 ? item.fontSize : finfo.fontsize,
|
|
7481
|
+
face: item.fontFace !== void 0 ? item.fontFace : finfo.fontname
|
|
7482
|
+
};
|
|
7483
|
+
}
|
|
7484
|
+
function measureItem(item, finfo, measurer) {
|
|
7485
|
+
if (item.text === void 0) return null;
|
|
7486
|
+
const { fs, face } = itemFace(item, finfo);
|
|
7487
|
+
const flags = itemFontFlags(item);
|
|
7488
|
+
const sz = measurer.measure(
|
|
7489
|
+
item.text,
|
|
7490
|
+
face,
|
|
7491
|
+
fs,
|
|
7492
|
+
{ bold: !!(flags & HTML_BF), italic: !!(flags & HTML_IF) }
|
|
7493
|
+
);
|
|
7494
|
+
return { w: sz.w, h: sz.h, fs, yoffsetCenterline: sz.yoffsetCenterline, yoffsetLayout: sz.yoffsetLayout };
|
|
7495
|
+
}
|
|
7496
|
+
function newRun() {
|
|
7497
|
+
return { items: [], width: 0, fontSize: 0, height: 0, maxOffset: 0, maxLayout: 0 };
|
|
7498
|
+
}
|
|
7499
|
+
function runLeftX(run, box, centerX) {
|
|
7500
|
+
if (run.just === "left") return box.ll.x;
|
|
7501
|
+
if (run.just === "right") return box.ur.x - run.width;
|
|
7502
|
+
return centerX - run.width / 2;
|
|
7503
|
+
}
|
|
7504
|
+
function accumulateItem(cur, item, m) {
|
|
7505
|
+
cur.items.push(item);
|
|
7506
|
+
cur.width += m.w;
|
|
7507
|
+
cur.fontSize = Math.max(cur.fontSize, m.fs);
|
|
7508
|
+
cur.height = Math.max(cur.height, m.h);
|
|
7509
|
+
cur.maxOffset = Math.max(cur.maxOffset, m.yoffsetCenterline ?? 0.05 * m.fs);
|
|
7510
|
+
cur.maxLayout = Math.max(cur.maxLayout, m.yoffsetLayout ?? 0);
|
|
7511
|
+
}
|
|
7512
|
+
function buildLineRuns(texts, finfo, measurer) {
|
|
7513
|
+
const runs = [];
|
|
7514
|
+
let cur = newRun();
|
|
7515
|
+
const flush = (br) => {
|
|
7516
|
+
if (cur.items.length === 0 && br !== void 0) {
|
|
7517
|
+
const { br: _b, brAlign: _a, ...fontProps } = br;
|
|
7518
|
+
const empty = { text: "", ...fontProps };
|
|
7519
|
+
const m = measureItem(empty, finfo, measurer);
|
|
7520
|
+
if (m !== null) accumulateItem(cur, empty, m);
|
|
7521
|
+
}
|
|
7522
|
+
cur.just = br?.brAlign;
|
|
7523
|
+
runs.push(cur);
|
|
7524
|
+
cur = newRun();
|
|
7525
|
+
};
|
|
7526
|
+
for (const txt of texts) {
|
|
7527
|
+
for (const item of txt.items) {
|
|
7528
|
+
if (item.br) {
|
|
7529
|
+
flush(item);
|
|
7530
|
+
continue;
|
|
7531
|
+
}
|
|
7532
|
+
const m = measureItem(item, finfo, measurer);
|
|
7533
|
+
if (m !== null) accumulateItem(cur, item, m);
|
|
7534
|
+
}
|
|
7535
|
+
if (cur.items.length > 0) flush();
|
|
7536
|
+
}
|
|
7537
|
+
return runs;
|
|
7538
|
+
}
|
|
7539
|
+
function runSimpleKey(run, finfo) {
|
|
7540
|
+
if (run.items.length > 1) return null;
|
|
7541
|
+
const item = run.items[0];
|
|
7542
|
+
if (item === void 0) return void 0;
|
|
7543
|
+
if (itemFontFlags(item) !== 0) return null;
|
|
7544
|
+
return itemFace(item, finfo);
|
|
7545
|
+
}
|
|
7546
|
+
function runsAreSimple(runs, finfo) {
|
|
7547
|
+
let prevFs = -1;
|
|
7548
|
+
let prevFace = null;
|
|
7549
|
+
for (const run of runs) {
|
|
7550
|
+
const key = runSimpleKey(run, finfo);
|
|
7551
|
+
if (key === null) return false;
|
|
7552
|
+
if (key === void 0) continue;
|
|
7553
|
+
if (prevFs < 0) prevFs = key.fs;
|
|
7554
|
+
else if (key.fs !== prevFs) return false;
|
|
7555
|
+
if (prevFace === null) prevFace = key.face;
|
|
7556
|
+
else if (key.face !== prevFace) return false;
|
|
7557
|
+
}
|
|
7558
|
+
return true;
|
|
7559
|
+
}
|
|
7560
|
+
function placeRunItems(run, startX, baseline, finfo, measurer) {
|
|
7561
|
+
const lines = [];
|
|
7562
|
+
let x = startX;
|
|
7563
|
+
for (const item of run.items) {
|
|
7564
|
+
const { fs, face } = itemFace(item, finfo);
|
|
7565
|
+
const flags = itemFontFlags(item);
|
|
7566
|
+
const sz = measurer.measure(
|
|
7567
|
+
item.text,
|
|
7568
|
+
face,
|
|
7569
|
+
fs,
|
|
7570
|
+
{ bold: !!(flags & HTML_BF), italic: !!(flags & HTML_IF) }
|
|
7571
|
+
);
|
|
7572
|
+
lines.push({
|
|
7573
|
+
text: item.text,
|
|
7574
|
+
x,
|
|
7575
|
+
baseline,
|
|
7576
|
+
width: sz.w,
|
|
7577
|
+
fontSize: fs,
|
|
7578
|
+
fontName: face,
|
|
7579
|
+
fontColor: item.fontColor ?? finfo.fontcolor,
|
|
7580
|
+
fontFlags: flags
|
|
7581
|
+
});
|
|
7582
|
+
x += sz.w;
|
|
7583
|
+
}
|
|
7584
|
+
return lines;
|
|
7585
|
+
}
|
|
7586
|
+
function placeTextRuns(runs, box, finfo, measurer) {
|
|
7587
|
+
if (runsAreSimple(runs, finfo)) {
|
|
7588
|
+
return placeSimpleRuns(runs, box, finfo, measurer);
|
|
7589
|
+
}
|
|
7590
|
+
return placeComplexRuns(runs, box, finfo, measurer);
|
|
7591
|
+
}
|
|
7592
|
+
function placeSimpleRuns(runs, box, finfo, measurer) {
|
|
7593
|
+
const centerX = (box.ll.x + box.ur.x) / 2;
|
|
7594
|
+
const lines = [];
|
|
7595
|
+
let baseline = box.ur.y;
|
|
7596
|
+
for (let i = 0; i < runs.length; i++) {
|
|
7597
|
+
const run = runs[i];
|
|
7598
|
+
const ascent = run.maxLayout > 0 ? run.maxLayout : freetypeAscent(run.fontSize, finfo.fontname);
|
|
7599
|
+
baseline -= i === 0 ? ascent : run.height;
|
|
7600
|
+
lines.push(...placeRunItems(run, runLeftX(run, box, centerX), baseline, finfo, measurer));
|
|
7601
|
+
}
|
|
7602
|
+
return lines;
|
|
7603
|
+
}
|
|
7604
|
+
function placeComplexRuns(runs, box, finfo, measurer) {
|
|
7605
|
+
const centerX = (box.ll.x + box.ur.x) / 2;
|
|
7606
|
+
const lines = [];
|
|
7607
|
+
let curbline = 0;
|
|
7608
|
+
let ysize = 0;
|
|
7609
|
+
for (let i = 0; i < runs.length; i++) {
|
|
7610
|
+
const run = runs[i];
|
|
7611
|
+
const lfsize = i === 0 ? run.fontSize - run.maxOffset : run.fontSize + ysize - curbline - run.maxOffset;
|
|
7612
|
+
curbline += lfsize;
|
|
7613
|
+
ysize += run.fontSize;
|
|
7614
|
+
const baseline = box.ur.y - curbline;
|
|
7615
|
+
for (const pl of placeRunItems(run, runLeftX(run, box, centerX), baseline, finfo, measurer)) {
|
|
7616
|
+
pl.yoffsetCenterline = 1;
|
|
7617
|
+
lines.push(pl);
|
|
7618
|
+
}
|
|
7619
|
+
}
|
|
7620
|
+
return lines;
|
|
7621
|
+
}
|
|
7622
|
+
|
|
7374
7623
|
// src/common/htmltable-fontinfo.ts
|
|
7375
7624
|
var SIZE_SAVEF = { fontsize: 0 };
|
|
7376
7625
|
var EMIT_SAVEF = { fontsize: 0 };
|
|
@@ -7432,87 +7681,33 @@ var findCol = (ps, row, startCol, colspan, rowspan) => {
|
|
|
7432
7681
|
return col;
|
|
7433
7682
|
};
|
|
7434
7683
|
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
7684
|
var sizeTextContent = (texts, measurer, env = defaultSizeEnv()) => {
|
|
7491
|
-
const lines =
|
|
7492
|
-
const simple =
|
|
7685
|
+
const lines = buildLineRuns(texts, env, measurer);
|
|
7686
|
+
const simple = runsAreSimple(lines, env);
|
|
7493
7687
|
let w = 0;
|
|
7494
7688
|
let h = 0;
|
|
7495
7689
|
for (const ln of lines) {
|
|
7496
7690
|
w = Math.max(w, ln.width);
|
|
7497
|
-
const lsize = simple ? ln.
|
|
7691
|
+
const lsize = simple ? ln.height : ln.fontSize;
|
|
7498
7692
|
h += ln.items.length > 0 ? lsize : DEFAULT_FONTSIZE;
|
|
7499
7693
|
}
|
|
7500
|
-
if (lines.length === 1) h = lines[0].items.length > 0 ? lines[0].
|
|
7694
|
+
if (lines.length === 1) h = lines[0].items.length > 0 ? lines[0].height : DEFAULT_FONTSIZE;
|
|
7501
7695
|
return { w, h };
|
|
7502
7696
|
};
|
|
7503
|
-
var missingImages = /* @__PURE__ */ new WeakSet();
|
|
7697
|
+
var missingImages = { set: /* @__PURE__ */ new WeakSet() };
|
|
7504
7698
|
var sizeHtmlImg = (img, { imageSizer, stderr }) => {
|
|
7505
|
-
if (img.width !== void 0 && img.height !== void 0) return missingImages.has(img) ? 1 : 0;
|
|
7699
|
+
if (img.width !== void 0 && img.height !== void 0) return missingImages.set.has(img) ? 1 : 0;
|
|
7506
7700
|
const sz = imageSizer !== void 0 ? imageSizer(img.src) : findImageSize(img.src);
|
|
7507
7701
|
if (sz !== null) {
|
|
7508
7702
|
img.width = sz.w;
|
|
7509
7703
|
img.height = sz.h;
|
|
7510
7704
|
return 0;
|
|
7511
7705
|
}
|
|
7706
|
+
if (!imageIsSupplied(img.src, imageSizer)) agerrLine(stderr, `Warning: ${imageOpenWarning(img.src)}`);
|
|
7512
7707
|
agerrLine(stderr, `Error: No or improper image file="${img.src}"`);
|
|
7513
7708
|
img.width = 0;
|
|
7514
7709
|
img.height = 0;
|
|
7515
|
-
missingImages.add(img);
|
|
7710
|
+
missingImages.set.add(img);
|
|
7516
7711
|
return 1;
|
|
7517
7712
|
};
|
|
7518
7713
|
var sizeContentItem = (item, measurer, env) => {
|
|
@@ -7551,7 +7746,11 @@ var WARN_CELL_TOO_SMALL = "Warning: cell size too small for content";
|
|
|
7551
7746
|
var WARN_CELL_UNSPECIFIED = "Warning: fixed cell size with unspecified width or height";
|
|
7552
7747
|
var WARN_TABLE_TOO_SMALL = "Warning: table size too small for content";
|
|
7553
7748
|
var WARN_TABLE_UNSPECIFIED = "Warning: fixed table size with unspecified width or height";
|
|
7554
|
-
var sizeWarned = /* @__PURE__ */ new WeakSet();
|
|
7749
|
+
var sizeWarned = { set: /* @__PURE__ */ new WeakSet() };
|
|
7750
|
+
registerRenderState(() => {
|
|
7751
|
+
missingImages.set = /* @__PURE__ */ new WeakSet();
|
|
7752
|
+
sizeWarned.set = /* @__PURE__ */ new WeakSet();
|
|
7753
|
+
});
|
|
7555
7754
|
var fixedCellCheck = (cell2, sz, warn, out) => {
|
|
7556
7755
|
if (!cell2.fixedsize) return { rv: 0, zero: false };
|
|
7557
7756
|
if (cell2.width && cell2.height) {
|
|
@@ -7573,8 +7772,8 @@ var getCellSize = (cell2, tbl, measurer, env) => {
|
|
|
7573
7772
|
}
|
|
7574
7773
|
let szx = cw + margin;
|
|
7575
7774
|
let szy = ch + margin;
|
|
7576
|
-
const warn = !sizeWarned.has(cell2);
|
|
7577
|
-
sizeWarned.add(cell2);
|
|
7775
|
+
const warn = !sizeWarned.set.has(cell2);
|
|
7776
|
+
sizeWarned.set.add(cell2);
|
|
7578
7777
|
const fixed = fixedCellCheck(cell2, { w: szx, h: szy }, warn, env.stderr);
|
|
7579
7778
|
rv |= fixed.rv;
|
|
7580
7779
|
if (fixed.zero) {
|
|
@@ -7670,8 +7869,8 @@ var layoutHtmlTable = (tbl, measurer, env = defaultSizeEnv()) => {
|
|
|
7670
7869
|
return { entries, widths, heights, spacing, border: border2, rv };
|
|
7671
7870
|
};
|
|
7672
7871
|
var warnFixedTable = (tbl, dims, out) => {
|
|
7673
|
-
const warn = !sizeWarned.has(tbl);
|
|
7674
|
-
sizeWarned.add(tbl);
|
|
7872
|
+
const warn = !sizeWarned.set.has(tbl);
|
|
7873
|
+
sizeWarned.set.add(tbl);
|
|
7675
7874
|
if (tbl.fixedsize !== true) return 0;
|
|
7676
7875
|
if (tbl.width && tbl.height) {
|
|
7677
7876
|
if (tbl.width >= dims.wd && tbl.height >= dims.ht) return 0;
|
|
@@ -7728,173 +7927,6 @@ var INIT_DELTA = 10;
|
|
|
7728
7927
|
var LOOP_TRIES = 15;
|
|
7729
7928
|
var ROUTESPL_FUDGE = 1e-4;
|
|
7730
7929
|
|
|
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
7930
|
// src/common/htmltable-pos.ts
|
|
7899
7931
|
function alignContentBox(box, cell2, w, h) {
|
|
7900
7932
|
const out = { ll: { ...box.ll }, ur: { ...box.ur } };
|
|
@@ -8196,6 +8228,20 @@ function htmlTextLabel(text, finfo, placed, dim) {
|
|
|
8196
8228
|
};
|
|
8197
8229
|
}
|
|
8198
8230
|
|
|
8231
|
+
// src/model/lazy-attrs.ts
|
|
8232
|
+
var SharedEmptyAttrs = class extends Map {
|
|
8233
|
+
set(key, _value) {
|
|
8234
|
+
throw new Error(`attrs.set("${key}") on a shared empty map; use ownAttrs()`);
|
|
8235
|
+
}
|
|
8236
|
+
delete(key) {
|
|
8237
|
+
throw new Error(`attrs.delete("${key}") on a shared empty map; use ownAttrs()`);
|
|
8238
|
+
}
|
|
8239
|
+
clear() {
|
|
8240
|
+
throw new Error("attrs.clear() on a shared empty map; use ownAttrs()");
|
|
8241
|
+
}
|
|
8242
|
+
};
|
|
8243
|
+
var EMPTY_ATTRS = new SharedEmptyAttrs();
|
|
8244
|
+
|
|
8199
8245
|
// src/model/algData.ts
|
|
8200
8246
|
var THETA_UNSET = 10;
|
|
8201
8247
|
|
|
@@ -8298,10 +8344,10 @@ var Node = class {
|
|
|
8298
8344
|
*/
|
|
8299
8345
|
nodeDefaultsSnapshot;
|
|
8300
8346
|
/** @see lib/cgraph/node.c:agnode */
|
|
8301
|
-
constructor(id, name, root) {
|
|
8347
|
+
constructor(id, name, root, lazyAttrs = false) {
|
|
8302
8348
|
this.id = id;
|
|
8303
8349
|
this.name = name;
|
|
8304
|
-
this.attrs = /* @__PURE__ */ new Map();
|
|
8350
|
+
this.attrs = lazyAttrs ? EMPTY_ATTRS : /* @__PURE__ */ new Map();
|
|
8305
8351
|
this.info = makeNodeInfo();
|
|
8306
8352
|
this.root = root;
|
|
8307
8353
|
}
|
|
@@ -8471,12 +8517,12 @@ var Edge = class _Edge {
|
|
|
8471
8517
|
*/
|
|
8472
8518
|
info;
|
|
8473
8519
|
/** @see lib/cgraph/edge.c:agedge */
|
|
8474
|
-
constructor(tail, head, name) {
|
|
8520
|
+
constructor(tail, head, name, lazyAttrs = false) {
|
|
8475
8521
|
this.seq = _Edge._nextSeq++;
|
|
8476
8522
|
this.tail = tail;
|
|
8477
8523
|
this.head = head;
|
|
8478
8524
|
this.name = name;
|
|
8479
|
-
this.attrs = /* @__PURE__ */ new Map();
|
|
8525
|
+
this.attrs = lazyAttrs ? EMPTY_ATTRS : /* @__PURE__ */ new Map();
|
|
8480
8526
|
this.info = makeEdgeInfo(makePort(), makePort());
|
|
8481
8527
|
}
|
|
8482
8528
|
};
|
|
@@ -8900,7 +8946,7 @@ function copyVirtualEdgeInfo(e, orig) {
|
|
|
8900
8946
|
e.seq = orig.seq;
|
|
8901
8947
|
}
|
|
8902
8948
|
function newVirtualEdge(u, v, orig) {
|
|
8903
|
-
const e = new Edge(u, v, "");
|
|
8949
|
+
const e = new Edge(u, v, "", true);
|
|
8904
8950
|
e.info.edge_type = VIRTUAL;
|
|
8905
8951
|
if (orig) {
|
|
8906
8952
|
copyVirtualEdgeInfo(e, orig);
|
|
@@ -9001,7 +9047,7 @@ function removeFromRank(g, n) {
|
|
|
9001
9047
|
}
|
|
9002
9048
|
}
|
|
9003
9049
|
function virtualNode(g) {
|
|
9004
|
-
const n = new Node(0, "", g.root);
|
|
9050
|
+
const n = new Node(0, "", g.root, true);
|
|
9005
9051
|
n.info.node_type = VIRTUAL;
|
|
9006
9052
|
n.info.lw = 1;
|
|
9007
9053
|
n.info.rw = 1;
|
|
@@ -9313,10 +9359,10 @@ var ARROW_EPSILON = 1e-4;
|
|
|
9313
9359
|
var vsub = (p, q) => ({ x: p.x - q.x, y: p.y - q.y });
|
|
9314
9360
|
var vadd = (p, q) => ({ x: p.x + q.x, y: p.y + q.y });
|
|
9315
9361
|
var vscale = (c, p) => ({ x: c * p.x, y: c * p.y });
|
|
9316
|
-
var negUnit = (u,
|
|
9362
|
+
var negUnit = (u, dist5) => {
|
|
9317
9363
|
if (u.x === 0 && u.y === 0) return { x: 0, y: 0 };
|
|
9318
9364
|
const h = Math.hypot(u.x, u.y);
|
|
9319
|
-
return { x:
|
|
9365
|
+
return { x: dist5 * (-u.x / h), y: dist5 * (-u.y / h) };
|
|
9320
9366
|
};
|
|
9321
9367
|
var backwardDelta = (u, penwidth) => negUnit(u, penwidth / 2);
|
|
9322
9368
|
function axialProjection(phiSrc, from, to, sign2) {
|
|
@@ -9899,9 +9945,9 @@ function makeEllipseInsideFn(rx, ry, penwidth = DEFAULT_NODEPENWIDTH) {
|
|
|
9899
9945
|
return (lx, ly) => lx * lx / (erx * erx) + ly * ly / (ery * ery) < 1;
|
|
9900
9946
|
}
|
|
9901
9947
|
function tailArrowEndClip(path4, tailTip, elen) {
|
|
9902
|
-
|
|
9903
|
-
const
|
|
9904
|
-
return
|
|
9948
|
+
const sp = [path4[3], path4[2], path4[1], tailTip];
|
|
9949
|
+
const clipped = elen > 0 ? bezierClipNode(sp, 0, 0, (x, y) => distFused({ x, y }, tailTip) <= elen, false) : sp;
|
|
9950
|
+
return [clipped[3], clipped[2], clipped[1], clipped[0]];
|
|
9905
9951
|
}
|
|
9906
9952
|
|
|
9907
9953
|
// src/layout/dot/edge-route-geom.ts
|
|
@@ -11598,11 +11644,12 @@ function emitHtmlLine(line, pos, renderer, job) {
|
|
|
11598
11644
|
}
|
|
11599
11645
|
function bgFillPaint(ctx) {
|
|
11600
11646
|
const penWidth = htmlFillPenWidth();
|
|
11601
|
-
const spec =
|
|
11647
|
+
const spec = findHtmlStopColor(ctx.bgcolor);
|
|
11602
11648
|
if (spec === null) return { fill: ctx.bgcolor, penWidth };
|
|
11603
11649
|
return {
|
|
11604
|
-
fill: spec
|
|
11605
|
-
stop: spec
|
|
11650
|
+
fill: spec.fill,
|
|
11651
|
+
stop: spec.stop ?? "black",
|
|
11652
|
+
gradientFrac: spec.frac,
|
|
11606
11653
|
gradientAngle: ctx.gradientangle ?? 0,
|
|
11607
11654
|
radial: htmlStyle(ctx.style).radial,
|
|
11608
11655
|
penWidth
|
|
@@ -12032,7 +12079,7 @@ function transformUnitVertex(R2, g, c, bb) {
|
|
|
12032
12079
|
const r = libmHypot(D.x, D.y);
|
|
12033
12080
|
return { x: r * Math.cos(alpha) * bb.x, y: r * Math.sin(alpha) * bb.y };
|
|
12034
12081
|
}
|
|
12035
|
-
function polygonVertices(bb, g,
|
|
12082
|
+
function polygonVertices(bb, g, isBox4) {
|
|
12036
12083
|
const sectorangle = 2 * Math.PI / g.sides;
|
|
12037
12084
|
const sidelength = Math.sin(sectorangle / 2);
|
|
12038
12085
|
const c = {
|
|
@@ -12050,7 +12097,7 @@ function polygonVertices(bb, g, isBox3) {
|
|
|
12050
12097
|
R2.y = fma(sidelength, Math.sin(angle), R2.y);
|
|
12051
12098
|
const P = transformUnitVertex(R2, g, c, bb);
|
|
12052
12099
|
verts.push(P);
|
|
12053
|
-
if (
|
|
12100
|
+
if (isBox4) {
|
|
12054
12101
|
verts.push({ x: -P.x, y: P.y }, { x: -P.x, y: -P.y }, { x: P.x, y: -P.y });
|
|
12055
12102
|
break;
|
|
12056
12103
|
}
|
|
@@ -12141,14 +12188,14 @@ function starVertexGen(bb) {
|
|
|
12141
12188
|
}
|
|
12142
12189
|
return { verts: starVertices(bb.x, bb.y), xmax: sz.x / 2, ymax: sz.y / 2 };
|
|
12143
12190
|
}
|
|
12144
|
-
function polygonBB(bb, minSize, p, sides2,
|
|
12191
|
+
function polygonBB(bb, minSize, p, sides2, isBox4) {
|
|
12145
12192
|
const geom = {
|
|
12146
12193
|
sides: sides2,
|
|
12147
12194
|
orientation: p.orientation,
|
|
12148
12195
|
distortion: p.distortion,
|
|
12149
12196
|
skew: p.skew
|
|
12150
12197
|
};
|
|
12151
|
-
const { verts, xmax, ymax } = p.optionShape === STAR ? starVertexGen(bb) : polygonVertices(bb, geom,
|
|
12198
|
+
const { verts, xmax, ymax } = p.optionShape === STAR ? starVertexGen(bb) : polygonVertices(bb, geom, isBox4);
|
|
12152
12199
|
const xmax2 = 2 * xmax;
|
|
12153
12200
|
const ymax2 = 2 * ymax;
|
|
12154
12201
|
const nbb = { x: Math.max(minSize.x, xmax2), y: Math.max(minSize.y, ymax2) };
|
|
@@ -12160,7 +12207,7 @@ function polygonBB(bb, minSize, p, sides2, isBox3) {
|
|
|
12160
12207
|
v.x *= scalex;
|
|
12161
12208
|
v.y *= scaley;
|
|
12162
12209
|
}
|
|
12163
|
-
return { ...polygonPeripheryBB(verts,
|
|
12210
|
+
return { ...polygonPeripheryBB(verts, isBox4 ? 4 : sides2, p, nbb), base: nbb };
|
|
12164
12211
|
}
|
|
12165
12212
|
function gvNodesize(widthPts, heightPts, flip) {
|
|
12166
12213
|
if (flip) return { lw: heightPts / 2, rw: heightPts / 2, ht: widthPts };
|
|
@@ -12185,9 +12232,9 @@ function applySizeConstraints(p, bb0, width0, height0) {
|
|
|
12185
12232
|
function polySize(p) {
|
|
12186
12233
|
const init = initialSizePts(p);
|
|
12187
12234
|
const dimen = quantize(padLabelDimen(p.labelDimen, p.margin, p.isPlain), p.quantumIn);
|
|
12188
|
-
const { sides: sides2, isBox:
|
|
12235
|
+
const { sides: sides2, isBox: isBox4 } = effectiveShape(p);
|
|
12189
12236
|
let bb = { x: dimen.x, y: dimen.y };
|
|
12190
|
-
if (
|
|
12237
|
+
if (isBox4) {
|
|
12191
12238
|
} else if (p.optionShape === STAR) {
|
|
12192
12239
|
bb = starSize(bb);
|
|
12193
12240
|
} else if (p.optionShape === CYLINDER) {
|
|
@@ -12199,16 +12246,16 @@ function polySize(p) {
|
|
|
12199
12246
|
const c = applySizeConstraints(p, bb, init.width, init.height);
|
|
12200
12247
|
const penwidth = p.penwidth ?? 1;
|
|
12201
12248
|
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,
|
|
12249
|
+
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
12250
|
const result = assembleResult(p, dimen, grown, c.fixedshape);
|
|
12204
|
-
return { ...result, ...labelSpace(p, dimen, c.bb, minBb,
|
|
12251
|
+
return { ...result, ...labelSpace(p, dimen, c.bb, minBb, isBox4, c.fixedshape) };
|
|
12205
12252
|
}
|
|
12206
|
-
function labelSpace(p, dimen, bb, minBb,
|
|
12253
|
+
function labelSpace(p, dimen, bb, minBb, isBox4, fixedshape) {
|
|
12207
12254
|
const spacex = dimen.x - p.labelDimen.x;
|
|
12208
12255
|
let spaceX;
|
|
12209
12256
|
if (p.nojustify) {
|
|
12210
12257
|
spaceX = dimen.x - spacex;
|
|
12211
|
-
} else if (
|
|
12258
|
+
} else if (isBox4) {
|
|
12212
12259
|
spaceX = Math.max(dimen.x, bb.x) - spacex;
|
|
12213
12260
|
} else if (dimen.y < bb.y) {
|
|
12214
12261
|
spaceX = Math.max(dimen.x, bb.x * Math.sqrt(1 - dimen.y * dimen.y / (bb.y * bb.y))) - spacex;
|
|
@@ -12221,8 +12268,8 @@ function labelSpace(p, dimen, bb, minBb, isBox3, fixedshape) {
|
|
|
12221
12268
|
function effectiveShape(p) {
|
|
12222
12269
|
let sides2 = p.sides;
|
|
12223
12270
|
if (sides2 <= 2 && (p.distortion !== 0 || p.skew !== 0)) sides2 = 120;
|
|
12224
|
-
const
|
|
12225
|
-
return { sides: sides2, isBox:
|
|
12271
|
+
const isBox4 = sides2 === 4 && Math.abs(p.orientation % 90) < 0.5 && p.distortion === 0 && p.skew === 0;
|
|
12272
|
+
return { sides: sides2, isBox: isBox4 };
|
|
12226
12273
|
}
|
|
12227
12274
|
function labelValign(p) {
|
|
12228
12275
|
const ll = p.labelloc?.[0];
|
|
@@ -12664,17 +12711,27 @@ function buildNodeLabel(n, g, measurer) {
|
|
|
12664
12711
|
const content = isHtml ? htmlValueContent(labelAttr) : labelAttr ?? n.name;
|
|
12665
12712
|
n.info.label = makeAnyLabel(content, isHtml, font, measurer, n);
|
|
12666
12713
|
}
|
|
12714
|
+
function warnMissingImage(n, g, shapefile) {
|
|
12715
|
+
if (shapefile !== void 0 && shapefile !== "" && nodeAttr(n, g, "shape") !== "epsf") return;
|
|
12716
|
+
const image = nodeAttr(n, g, "image");
|
|
12717
|
+
if (image === void 0 || image === "") return;
|
|
12718
|
+
const gvc = g.root.info.gvc;
|
|
12719
|
+
if (imageIsSupplied(image, gvc?.imageSizer, gvc?.imageResolver)) return;
|
|
12720
|
+
agwarningf(imageOpenWarning(image));
|
|
12721
|
+
agwarningf(`No or improper image="${image}" for node "${n.name}"`);
|
|
12722
|
+
}
|
|
12667
12723
|
function polyInit(n, g, measurer) {
|
|
12668
12724
|
const shapeName2 = nodeAttr(n, g, "shape") ?? "ellipse";
|
|
12669
12725
|
const shapefile = nodeAttr(n, g, "shapefile");
|
|
12670
12726
|
n.info.shape = bindShape(shapeName2, shapefile);
|
|
12671
12727
|
if (shapefile !== void 0 && shapefile !== "" && shapeName2 !== "epsf") {
|
|
12672
|
-
agwarningf(`No or improper shapefile="${shapefile}" for node "${n.name}"
|
|
12728
|
+
agwarningf(`No or improper shapefile="${shapefile}" for node "${n.name}"`);
|
|
12673
12729
|
}
|
|
12674
12730
|
if (n.info.shape.kind === 2 /* SH_RECORD */) {
|
|
12675
12731
|
if (n.info.shape_info === void 0) recordNodeInit(n, g, measurer);
|
|
12676
12732
|
return;
|
|
12677
12733
|
}
|
|
12734
|
+
warnMissingImage(n, g, shapefile);
|
|
12678
12735
|
buildNodeLabel(n, g, measurer);
|
|
12679
12736
|
if (n.info.shape_info !== void 0) return;
|
|
12680
12737
|
const polyDesc = n.info.shape.polygon;
|
|
@@ -12682,6 +12739,16 @@ function polyInit(n, g, measurer) {
|
|
|
12682
12739
|
}
|
|
12683
12740
|
|
|
12684
12741
|
// src/common/multicolor.ts
|
|
12742
|
+
var parseSegsState = { warned: false };
|
|
12743
|
+
registerRenderState(() => {
|
|
12744
|
+
parseSegsState.warned = false;
|
|
12745
|
+
});
|
|
12746
|
+
function claimWarned() {
|
|
12747
|
+
if (parseSegsState.warned) return false;
|
|
12748
|
+
parseSegsState.warned = true;
|
|
12749
|
+
return true;
|
|
12750
|
+
}
|
|
12751
|
+
var claimNever = () => false;
|
|
12685
12752
|
var EPS = 1e-5;
|
|
12686
12753
|
function aeq0(x) {
|
|
12687
12754
|
return x < EPS && x > -EPS;
|
|
@@ -12695,17 +12762,14 @@ function getSegLen(token) {
|
|
|
12695
12762
|
const parsed = parseFloat(rest);
|
|
12696
12763
|
return !isNaN(parsed) && parsed >= 0 ? { color, v: parsed } : { color, v: -1 };
|
|
12697
12764
|
}
|
|
12698
|
-
function appendSeg(token, left2, segs,
|
|
12765
|
+
function appendSeg(token, left2, segs, claim) {
|
|
12699
12766
|
const { color, v } = getSegLen(token);
|
|
12700
12767
|
if (v < 0) return null;
|
|
12701
12768
|
let t = v;
|
|
12702
12769
|
let rval = 0;
|
|
12703
12770
|
const del = t - left2;
|
|
12704
12771
|
if (del > 0) {
|
|
12705
|
-
if (!aeq0(del) &&
|
|
12706
|
-
warnedExceeded.v = true;
|
|
12707
|
-
rval = 3;
|
|
12708
|
-
}
|
|
12772
|
+
if (!aeq0(del) && claim()) rval = 3;
|
|
12709
12773
|
t = left2;
|
|
12710
12774
|
}
|
|
12711
12775
|
left2 -= t;
|
|
@@ -12729,19 +12793,13 @@ function trimTrailing(segs) {
|
|
|
12729
12793
|
segs.pop();
|
|
12730
12794
|
}
|
|
12731
12795
|
}
|
|
12732
|
-
function
|
|
12796
|
+
function scanSegs(colorlist, claim) {
|
|
12733
12797
|
const segs = [];
|
|
12734
12798
|
let left2 = 1;
|
|
12735
12799
|
let rval = 0;
|
|
12736
|
-
let badFloatCount = 0;
|
|
12737
|
-
const warnedExceeded = { v: false };
|
|
12738
12800
|
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
|
-
}
|
|
12801
|
+
const result = appendSeg(token, left2, segs, claim);
|
|
12802
|
+
if (result === null) return { segs: [], error: claim() ? 2 : 1 };
|
|
12745
12803
|
if (result.rval === 3) rval = 3;
|
|
12746
12804
|
left2 = result.left;
|
|
12747
12805
|
if (aeq0(left2)) {
|
|
@@ -12753,6 +12811,91 @@ function parseSegs(colorlist) {
|
|
|
12753
12811
|
trimTrailing(segs);
|
|
12754
12812
|
return { segs, error: rval };
|
|
12755
12813
|
}
|
|
12814
|
+
function parseSegs(colorlist, context) {
|
|
12815
|
+
const result = scanSegs(colorlist, claimWarned);
|
|
12816
|
+
if (result.error === 3) {
|
|
12817
|
+
const tail = context === void 0 ? "" : context();
|
|
12818
|
+
agwarningf(`Total size > 1 in "${colorlist}" color spec ${tail}`);
|
|
12819
|
+
} else if (result.error === 2) {
|
|
12820
|
+
agerrorf(`Illegal value in "${colorlist}" color attribute; float expected after ';'`);
|
|
12821
|
+
if (context !== void 0) agerr("prev", context());
|
|
12822
|
+
}
|
|
12823
|
+
return result;
|
|
12824
|
+
}
|
|
12825
|
+
function parseSegsSilent(colorlist) {
|
|
12826
|
+
return scanSegs(colorlist, claimNever);
|
|
12827
|
+
}
|
|
12828
|
+
function edgeSegsContext(e) {
|
|
12829
|
+
return () => {
|
|
12830
|
+
const directed = !e.tail.root.kind.endsWith("undirected");
|
|
12831
|
+
return `in edge ${e.tail.name}${directed ? " -> " : " -- "}${e.head.name}`;
|
|
12832
|
+
};
|
|
12833
|
+
}
|
|
12834
|
+
|
|
12835
|
+
// src/gvc/gvrender-set-style.ts
|
|
12836
|
+
var SUPPORTED_STYLES = /* @__PURE__ */ new Set([
|
|
12837
|
+
"solid",
|
|
12838
|
+
"dashed",
|
|
12839
|
+
"dotted",
|
|
12840
|
+
"invis",
|
|
12841
|
+
"invisible",
|
|
12842
|
+
"bold",
|
|
12843
|
+
"setlinewidth",
|
|
12844
|
+
"filled",
|
|
12845
|
+
"unfilled",
|
|
12846
|
+
"tapered"
|
|
12847
|
+
]);
|
|
12848
|
+
var BOX_ORIENTATION_TOLERANCE = 0.5;
|
|
12849
|
+
var BOX_ORIENTATION_STEP = 90;
|
|
12850
|
+
var BOX_SIDES = 4;
|
|
12851
|
+
var ELLIPSE_MAX_SIDES = 2;
|
|
12852
|
+
function styleName(token) {
|
|
12853
|
+
const paren = token.indexOf("(");
|
|
12854
|
+
return paren < 0 ? token : token.slice(0, paren);
|
|
12855
|
+
}
|
|
12856
|
+
function gvrenderSetStyle(styles) {
|
|
12857
|
+
if (styles === null) return;
|
|
12858
|
+
for (const token of styles) {
|
|
12859
|
+
const name = styleName(token);
|
|
12860
|
+
if (!SUPPORTED_STYLES.has(name)) {
|
|
12861
|
+
agwarningf(`gvrender_set_style: unsupported style ${name} - ignoring`);
|
|
12862
|
+
}
|
|
12863
|
+
}
|
|
12864
|
+
}
|
|
12865
|
+
function isBox(p) {
|
|
12866
|
+
if (p === null) return false;
|
|
12867
|
+
return p.sides === BOX_SIDES && Math.abs(p.orientation % BOX_ORIENTATION_STEP) < BOX_ORIENTATION_TOLERANCE && p.distortion === 0 && p.skew === 0;
|
|
12868
|
+
}
|
|
12869
|
+
function isEllipse(p) {
|
|
12870
|
+
return p !== null && p.sides <= ELLIPSE_MAX_SIDES;
|
|
12871
|
+
}
|
|
12872
|
+
function checkStyleTokens(styles, shape) {
|
|
12873
|
+
return styles.filter((p) => {
|
|
12874
|
+
if (p === "rounded" || p === "diagonals" || p === "radial") return false;
|
|
12875
|
+
if (p === "striped") return !isBox(shape);
|
|
12876
|
+
if (p === "wedged") return !isEllipse(shape);
|
|
12877
|
+
return true;
|
|
12878
|
+
});
|
|
12879
|
+
}
|
|
12880
|
+
function checkClusterStyleTokens(styles) {
|
|
12881
|
+
return styles.filter((p) => p !== "radial" && p !== "striped" && p !== "rounded");
|
|
12882
|
+
}
|
|
12883
|
+
function countChar(s, ch) {
|
|
12884
|
+
return [...s].filter((c) => c === ch).length;
|
|
12885
|
+
}
|
|
12886
|
+
function multicolorTaken(color) {
|
|
12887
|
+
if (countChar(color, ";") === 0 || countChar(color, ":") === 0) return false;
|
|
12888
|
+
const { error } = parseSegsSilent(color);
|
|
12889
|
+
return error !== 1 && error !== 2;
|
|
12890
|
+
}
|
|
12891
|
+
function edgeStyleResets(e, styles) {
|
|
12892
|
+
const spl = e.info.spl;
|
|
12893
|
+
if (spl === void 0 || spl.size <= 1 || styles.length === 0) return 0;
|
|
12894
|
+
const color = e.attrs.get("color") ?? "";
|
|
12895
|
+
const otherBranch = styles.includes("tapered") || countChar(color, ":") > 0;
|
|
12896
|
+
if (otherBranch && !multicolorTaken(color)) return 0;
|
|
12897
|
+
return spl.list.filter((bz) => bz.sflag !== 0 || bz.eflag !== 0).length;
|
|
12898
|
+
}
|
|
12756
12899
|
|
|
12757
12900
|
// src/util/math.ts
|
|
12758
12901
|
var INT32_MAX = 2147483647;
|
|
@@ -15735,11 +15878,11 @@ var SEG_EPS = 1e-5;
|
|
|
15735
15878
|
function reportColorNames(names) {
|
|
15736
15879
|
for (const name of names) resolveRenderColor(firstColor(name));
|
|
15737
15880
|
}
|
|
15738
|
-
function
|
|
15881
|
+
function countChar2(s, ch) {
|
|
15739
15882
|
return s.split(ch).length - 1;
|
|
15740
15883
|
}
|
|
15741
15884
|
function multicolorNames(color, arrows) {
|
|
15742
|
-
const { segs, error } =
|
|
15885
|
+
const { segs, error } = parseSegsSilent(color);
|
|
15743
15886
|
if (error === 1 || error === 2) return null;
|
|
15744
15887
|
const out = [];
|
|
15745
15888
|
const front = segs[0]?.color ?? null;
|
|
@@ -15761,9 +15904,9 @@ function taperedNames(color, fillcolor, hasFill) {
|
|
|
15761
15904
|
return hasFill ? [pen, fillcolor === "" ? DEFAULT_COLOR2 : fillcolor] : [pen];
|
|
15762
15905
|
}
|
|
15763
15906
|
function edgeGraphicsColors(spec) {
|
|
15764
|
-
const numc =
|
|
15907
|
+
const numc = countChar2(spec.color, ":");
|
|
15765
15908
|
let color = spec.color;
|
|
15766
|
-
if (
|
|
15909
|
+
if (countChar2(color, ";") > 0 && numc > 0) {
|
|
15767
15910
|
const multi = multicolorNames(color, spec.arrows);
|
|
15768
15911
|
if (multi !== null) return multi;
|
|
15769
15912
|
color = DEFAULT_COLOR2;
|
|
@@ -15916,8 +16059,8 @@ function drawWedge(seg2, e, ctx) {
|
|
|
15916
16059
|
ctx.renderer.bezier(ptsUp.map((p) => ({ x: p.x, y: -p.y })), true, ctx.job);
|
|
15917
16060
|
return angle1;
|
|
15918
16061
|
}
|
|
15919
|
-
function wedgedEllipse(job, pf, clrs, renderer) {
|
|
15920
|
-
const { segs, error } = parseSegs(clrs);
|
|
16062
|
+
function wedgedEllipse(job, pf, clrs, renderer, context) {
|
|
16063
|
+
const { segs, error } = parseSegs(clrs, context);
|
|
15921
16064
|
if (error === 1 || error === 2) return error;
|
|
15922
16065
|
const ctrX = (pf[0].x + pf[1].x) / 2;
|
|
15923
16066
|
const ctrY = (pf[0].y + pf[1].y) / 2;
|
|
@@ -15949,8 +16092,8 @@ function drawBand(p, seg2, ctx) {
|
|
|
15949
16092
|
ctx.renderer.polygon([...p], true, ctx.job);
|
|
15950
16093
|
p[0].x = p[3].x = p[1].x;
|
|
15951
16094
|
}
|
|
15952
|
-
function stripedBox(job, pts, clrs, rotate, renderer) {
|
|
15953
|
-
const { segs, error } = parseSegs(clrs);
|
|
16095
|
+
function stripedBox(job, pts, clrs, rotate, renderer, context) {
|
|
16096
|
+
const { segs, error } = parseSegs(clrs, context);
|
|
15954
16097
|
if (error === 1 || error === 2) return error;
|
|
15955
16098
|
const p = rotate ? [{ ...pts[2] }, { ...pts[3] }, { ...pts[0] }, { ...pts[1] }] : [{ ...pts[0] }, { ...pts[1] }, { ...pts[2] }, { ...pts[3] }];
|
|
15956
16099
|
const lastx = p[1].x;
|
|
@@ -16108,6 +16251,27 @@ function escapeXmlText(s) {
|
|
|
16108
16251
|
return gvXmlEscape(s, FLAGS_TEXT);
|
|
16109
16252
|
}
|
|
16110
16253
|
|
|
16254
|
+
// src/gvc/device-transform.ts
|
|
16255
|
+
function transformPoint(p, job) {
|
|
16256
|
+
if ((job.flags & GVRENDER_DOES_TRANSFORM) !== 0) {
|
|
16257
|
+
return p;
|
|
16258
|
+
}
|
|
16259
|
+
const sx = job.zoom * job.devscale.x;
|
|
16260
|
+
const sy = job.zoom * job.devscale.y;
|
|
16261
|
+
const tx = job.translation.x;
|
|
16262
|
+
const ty = job.translation.y;
|
|
16263
|
+
return applyScale(p, tx, ty, sx, sy);
|
|
16264
|
+
}
|
|
16265
|
+
function applyScale(p, tx, ty, sx, sy) {
|
|
16266
|
+
const x = (p.x + tx) * sx;
|
|
16267
|
+
const y = (p.y + ty) * sy;
|
|
16268
|
+
return buildPoint(x, y);
|
|
16269
|
+
}
|
|
16270
|
+
function buildPoint(x, y) {
|
|
16271
|
+
const pt = { x, y };
|
|
16272
|
+
return pt;
|
|
16273
|
+
}
|
|
16274
|
+
|
|
16111
16275
|
// src/gvc/device-cluster.ts
|
|
16112
16276
|
function applyClusterGradient(obj, fill) {
|
|
16113
16277
|
obj.fill = fill.kind === "radial" ? 3 /* Radial */ : 2 /* Linear */;
|
|
@@ -16155,6 +16319,7 @@ function applyClusterObjState(sg, job) {
|
|
|
16155
16319
|
const fillRes = resolveClusterFillEx(clusterAttrsOf(sg));
|
|
16156
16320
|
if (job.obj === null) return false;
|
|
16157
16321
|
const obj = job.obj;
|
|
16322
|
+
gvrenderSetStyle(checkClusterStyleTokens(styleTokens2(clusterStyle(sg))));
|
|
16158
16323
|
return withColorScheme(clusterAttr(sg, "colorscheme"), () => {
|
|
16159
16324
|
const filled = applyClusterFill(obj, fillRes);
|
|
16160
16325
|
applyClusterPenState(obj, sg);
|
|
@@ -16162,17 +16327,47 @@ function applyClusterObjState(sg, job) {
|
|
|
16162
16327
|
return filled;
|
|
16163
16328
|
});
|
|
16164
16329
|
}
|
|
16165
|
-
function
|
|
16330
|
+
function isStripedCluster(sg) {
|
|
16331
|
+
const flags = parseStyleFlags(clusterStyle(sg));
|
|
16332
|
+
return flags.striped && !flags.rounded;
|
|
16333
|
+
}
|
|
16334
|
+
function stripedFillSpec(sg) {
|
|
16166
16335
|
const flags = parseStyleFlags(clusterStyle(sg));
|
|
16167
|
-
if (!flags.striped || flags.rounded) return [];
|
|
16168
16336
|
const color = clusterAttr(sg, "color") ?? "";
|
|
16169
16337
|
let fill = clusterAttr(sg, "fillcolor") || color;
|
|
16170
16338
|
const bg = clusterAttr(sg, "bgcolor") ?? "";
|
|
16171
16339
|
if ((!flags.filled || fill === "") && bg !== "") fill = bg;
|
|
16172
|
-
|
|
16340
|
+
return fill === "" ? "lightgrey" : fill;
|
|
16341
|
+
}
|
|
16342
|
+
function stripedClusterColors(sg) {
|
|
16343
|
+
if (!isStripedCluster(sg)) return [];
|
|
16344
|
+
const { segs, error } = parseSegs(stripedFillSpec(sg), () => `in cluster ${sg.name}`);
|
|
16173
16345
|
if (error === 1 || error === 2) return [];
|
|
16174
16346
|
return segs.flatMap((seg2) => seg2.color !== null && seg2.t > 0 ? [seg2.color] : []);
|
|
16175
16347
|
}
|
|
16348
|
+
function renderStripedClusterBox(sg, renderer, job) {
|
|
16349
|
+
withColorScheme(clusterAttr(sg, "colorscheme"), () => {
|
|
16350
|
+
const { ll, ur } = sg.info.bb;
|
|
16351
|
+
const af = [
|
|
16352
|
+
{ x: ll.x, y: ll.y },
|
|
16353
|
+
{ x: ur.x, y: ll.y },
|
|
16354
|
+
{ x: ur.x, y: ur.y },
|
|
16355
|
+
{ x: ll.x, y: ur.y }
|
|
16356
|
+
].map((p) => transformPoint(p, job));
|
|
16357
|
+
const obj = job.obj;
|
|
16358
|
+
const savedFill = obj?.fill;
|
|
16359
|
+
if (obj !== null && savedFill !== void 0) obj.fill = 1 /* Solid */;
|
|
16360
|
+
stripedBox(job, af, stripedFillSpec(sg), false, renderer, () => `in cluster ${sg.name}`);
|
|
16361
|
+
if (obj !== null && savedFill !== void 0) obj.fill = savedFill;
|
|
16362
|
+
const rawPts = [
|
|
16363
|
+
{ x: ll.x, y: ll.y },
|
|
16364
|
+
{ x: ll.x, y: ur.y },
|
|
16365
|
+
{ x: ur.x, y: ur.y },
|
|
16366
|
+
{ x: ur.x, y: ll.y }
|
|
16367
|
+
];
|
|
16368
|
+
renderer.polygon(rawPts.map((p) => transformPoint(p, job)), false, job);
|
|
16369
|
+
});
|
|
16370
|
+
}
|
|
16176
16371
|
function applyClusterFill(obj, fillRes) {
|
|
16177
16372
|
if (fillRes.kind === "none") {
|
|
16178
16373
|
obj.fill = 0 /* None */;
|
|
@@ -16238,7 +16433,7 @@ function renderEllipseRing(ring, coord, filled, j, ctx) {
|
|
|
16238
16433
|
const pf = ring.map(
|
|
16239
16434
|
(v) => transformPoint({ x: v.x + coord.x, y: v.y + coord.y }, ctx.job)
|
|
16240
16435
|
);
|
|
16241
|
-
wedgedEllipse(ctx.job, pf, ctx.fillcolor, ctx.renderer);
|
|
16436
|
+
wedgedEllipse(ctx.job, pf, ctx.fillcolor, ctx.renderer, () => `in node ${ctx.nodeName}`);
|
|
16242
16437
|
renderEllipse(ring, coord, ctx.renderer, ctx.job, false);
|
|
16243
16438
|
} else {
|
|
16244
16439
|
renderEllipse(ring, coord, ctx.renderer, ctx.job, filled);
|
|
@@ -16247,7 +16442,7 @@ function renderEllipseRing(ring, coord, filled, j, ctx) {
|
|
|
16247
16442
|
}
|
|
16248
16443
|
function renderStripedRing(ring, coord, ctx) {
|
|
16249
16444
|
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);
|
|
16445
|
+
stripedBox(ctx.job, af, ctx.fillcolor, true, ctx.renderer, () => `in node ${ctx.nodeName}`);
|
|
16251
16446
|
renderPolygon(ring, coord, ctx.renderer, ctx.job, false);
|
|
16252
16447
|
}
|
|
16253
16448
|
function renderPolyRing(ring, coord, filled, j, ctx) {
|
|
@@ -16373,6 +16568,10 @@ function applyPenState(obj, styleAttr, colorAttr, penwidthAttr) {
|
|
|
16373
16568
|
function applyNodeStyle(obj, n, job) {
|
|
16374
16569
|
const styleAttr = nodeAttr(n, n.root, "style");
|
|
16375
16570
|
const colorAttr = nodeAttr(n, n.root, "color");
|
|
16571
|
+
if (!isPointNode(n)) {
|
|
16572
|
+
const shape = n.info.shape;
|
|
16573
|
+
gvrenderSetStyle(checkStyleTokens(styleTokens2(styleAttr), shape?.polygon ?? null));
|
|
16574
|
+
}
|
|
16376
16575
|
const penwidth = nodeAttr(n, n.root, "penwidth");
|
|
16377
16576
|
if (n.info.shape?.kind === 2 /* SH_RECORD */) {
|
|
16378
16577
|
applyPenState(obj, styleAttr, colorAttr, penwidth);
|
|
@@ -16384,7 +16583,7 @@ function applyNodeStyle(obj, n, job) {
|
|
|
16384
16583
|
}
|
|
16385
16584
|
function prepareDrawPoly(poly, filled, obj) {
|
|
16386
16585
|
if (poly.peripheries !== 0 || !filled) return poly;
|
|
16387
|
-
obj.penColor =
|
|
16586
|
+
obj.penColor = resolveRenderColor("transparent");
|
|
16388
16587
|
return { ...poly, peripheries: 1 };
|
|
16389
16588
|
}
|
|
16390
16589
|
function vertexScale(n, poly) {
|
|
@@ -16414,6 +16613,7 @@ function resolveNodeDrawCtx(job, n) {
|
|
|
16414
16613
|
job,
|
|
16415
16614
|
style: styleFlags,
|
|
16416
16615
|
fillcolor: nodeAttr(n, n.root, "fillcolor") ?? "",
|
|
16616
|
+
nodeName: n.name,
|
|
16417
16617
|
...specialCornerFlags(drawPoly.option, styleFlags)
|
|
16418
16618
|
};
|
|
16419
16619
|
return { poly: drawPoly, coord, filled, ringCtx };
|
|
@@ -17773,7 +17973,7 @@ function pruneForeignClusterNodes(par, clust) {
|
|
|
17773
17973
|
}
|
|
17774
17974
|
function markClusterNode(clust, n, g) {
|
|
17775
17975
|
if ((n.info.ranktype ?? 0) !== 0) {
|
|
17776
|
-
agwarningf(`${n.name} was already in a rankset, deleted from cluster ${g.name}
|
|
17976
|
+
agwarningf(`${n.name} was already in a rankset, deleted from cluster ${g.name}`);
|
|
17777
17977
|
agDeleteFromCluster(clust, n);
|
|
17778
17978
|
return;
|
|
17779
17979
|
}
|
|
@@ -18352,7 +18552,7 @@ function findCharset(g) {
|
|
|
18352
18552
|
}
|
|
18353
18553
|
if (p === "big-5" || p === "big5") return CHAR_BIG5;
|
|
18354
18554
|
if (p === "utf-8" || p === "utf8") return CHAR_UTF8;
|
|
18355
|
-
agwarningf(`Unsupported charset "${raw}" - assuming utf-8
|
|
18555
|
+
agwarningf(`Unsupported charset "${raw}" - assuming utf-8`);
|
|
18356
18556
|
return CHAR_UTF8;
|
|
18357
18557
|
}
|
|
18358
18558
|
function maptoken(p, names, vals) {
|
|
@@ -18570,7 +18770,7 @@ function portToTbl(tbl, id) {
|
|
|
18570
18770
|
}
|
|
18571
18771
|
|
|
18572
18772
|
// src/common/compass-port.ts
|
|
18573
|
-
function
|
|
18773
|
+
function isBox2(n) {
|
|
18574
18774
|
return n.info.shape?.polygon === P_BOX;
|
|
18575
18775
|
}
|
|
18576
18776
|
function gdRankdir(n) {
|
|
@@ -18761,7 +18961,7 @@ function compassPort(n, args, pp) {
|
|
|
18761
18961
|
const { bp, compass, sides: sides2 } = args;
|
|
18762
18962
|
const { b, p, defined: defBp } = compassBbox(n, bp);
|
|
18763
18963
|
const dir = compassDirection(compass, b, p, sides2);
|
|
18764
|
-
if (bp === null && !
|
|
18964
|
+
if (bp === null && !isBox2(n)) applyIctxt(n, dir, b, p);
|
|
18765
18965
|
const defFinal = dir.rv === 1 ? defBp : dir.defined || defBp;
|
|
18766
18966
|
applyDir(pp, bp, dir, gdRankdir(n), defFinal);
|
|
18767
18967
|
return dir.rv;
|
|
@@ -20043,7 +20243,7 @@ function emitParallelEdgePaths(e, job, colorList) {
|
|
|
20043
20243
|
const spl = e.info.spl;
|
|
20044
20244
|
const numc = (colorList.match(/:/g) ?? []).length;
|
|
20045
20245
|
const segData = buildSegData(spl?.list ?? [], (2 + numc) / 2);
|
|
20046
|
-
const colors =
|
|
20246
|
+
const colors = parseSegsSilent(colorList).segs.map((s) => s.color ?? DEFAULT_COLOR3);
|
|
20047
20247
|
emitColorPasses(segData, colors, job);
|
|
20048
20248
|
return {
|
|
20049
20249
|
headColor: colors[0] ?? DEFAULT_COLOR3,
|
|
@@ -20875,25 +21075,14 @@ function walkNodesAndEdges(g, renderer, job, info) {
|
|
|
20875
21075
|
}
|
|
20876
21076
|
}
|
|
20877
21077
|
|
|
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;
|
|
21078
|
+
// src/gvc/first-layer.ts
|
|
21079
|
+
var NATIVE_LANGNAME = /* @__PURE__ */ new Map([
|
|
21080
|
+
["cmapx-np", "cmapx_np"],
|
|
21081
|
+
["imap-np", "imap_np"]
|
|
21082
|
+
]);
|
|
21083
|
+
function warnLayersUnsupported(format, numLayers, doesLayers) {
|
|
21084
|
+
if (numLayers <= 1 || doesLayers) return;
|
|
21085
|
+
agwarningf(`layers not supported in ${NATIVE_LANGNAME.get(format) ?? format} output`);
|
|
20897
21086
|
}
|
|
20898
21087
|
|
|
20899
21088
|
// src/gvc/device-labels.ts
|
|
@@ -21038,6 +21227,7 @@ function setEdgePen(e, job) {
|
|
|
21038
21227
|
obj.pen = resolvePenType(flags);
|
|
21039
21228
|
obj.penWidth = resolvePenWidth(flags, e.attrs.get("penwidth"));
|
|
21040
21229
|
obj.rawStyle = styleTokens2(e.attrs.get("style"));
|
|
21230
|
+
if (e.info.spl !== void 0) gvrenderSetStyle(obj.rawStyle);
|
|
21041
21231
|
}
|
|
21042
21232
|
function renderEdge(e, renderer, job) {
|
|
21043
21233
|
emitEdgeComments(e, renderer, job);
|
|
@@ -21053,6 +21243,8 @@ function renderEdge(e, renderer, job) {
|
|
|
21053
21243
|
withColorScheme(e.attrs.get("colorscheme"), () => {
|
|
21054
21244
|
renderer.beginEdge(e, job);
|
|
21055
21245
|
reportEdgeColors(e);
|
|
21246
|
+
const styles = styleTokens2(e.attrs.get("style"));
|
|
21247
|
+
for (let i = edgeStyleResets(e, styles); i > 0; i--) gvrenderSetStyle(styles);
|
|
21056
21248
|
reportEdgeLabelColors(e);
|
|
21057
21249
|
renderer.endEdge(e, job);
|
|
21058
21250
|
});
|
|
@@ -21066,6 +21258,10 @@ function renderGraphLabel(g, renderer, job) {
|
|
|
21066
21258
|
}
|
|
21067
21259
|
function renderClusterBox(sg, filled, renderer, job) {
|
|
21068
21260
|
const { ll, ur } = sg.info.bb;
|
|
21261
|
+
if (isStripedCluster(sg)) {
|
|
21262
|
+
renderStripedClusterBox(sg, renderer, job);
|
|
21263
|
+
return;
|
|
21264
|
+
}
|
|
21069
21265
|
if (parseStyleFlags(clusterStyle(sg)).rounded) {
|
|
21070
21266
|
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
21267
|
emitRoundedBezier(af, { x: 0, y: 0 }, filled, { renderer, job });
|
|
@@ -21089,7 +21285,7 @@ function renderOneCluster(sg, renderer, job) {
|
|
|
21089
21285
|
resolveObjAnchor(sg, labelTextOf2(sg.info.label), svgClusterId(sg, job), job.obj);
|
|
21090
21286
|
}
|
|
21091
21287
|
const anchored = beginAnchorIf(renderer, job);
|
|
21092
|
-
if ((clusterPeripheries(sg) !== 0 || filled) && job.obj?.pen !== 0 /* None */) {
|
|
21288
|
+
if ((clusterPeripheries(sg) !== 0 || filled || isStripedCluster(sg)) && job.obj?.pen !== 0 /* None */) {
|
|
21093
21289
|
renderClusterBox(sg, filled, renderer, job);
|
|
21094
21290
|
}
|
|
21095
21291
|
renderClusterLabel(sg, renderer, job);
|
|
@@ -21119,6 +21315,7 @@ function renderGraph(g, job, renderer) {
|
|
|
21119
21315
|
job.numLayers = layered ? info.numLayers : 1;
|
|
21120
21316
|
job.layerIDs = info.layerIDs;
|
|
21121
21317
|
renderer.beginGraph(g, job);
|
|
21318
|
+
warnLayersUnsupported(job.format, info.numLayers, renderer.beginLayer !== void 0);
|
|
21122
21319
|
for (let ln = 1; ln <= job.numLayers; ln++) {
|
|
21123
21320
|
job.layerNum = ln;
|
|
21124
21321
|
if (layered) renderer.beginLayer(info.layerIDs[ln], job);
|
|
@@ -21180,13 +21377,21 @@ function render(ctx, g, format, inlineImages = false) {
|
|
|
21180
21377
|
}
|
|
21181
21378
|
|
|
21182
21379
|
// src/common/htmltable-emit-fill.ts
|
|
21380
|
+
var MSG_MANY_COLORS = "More than 2 colors specified for a gradient - ignoring remaining";
|
|
21381
|
+
function findHtmlStopColor(color, silent = false) {
|
|
21382
|
+
const { segs, error } = silent ? parseSegsSilent(color) : parseSegs(color);
|
|
21383
|
+
const first = segs[0];
|
|
21384
|
+
const second = segs[1];
|
|
21385
|
+
if (error !== 0 || first === void 0 || second === void 0 || first.color === null) {
|
|
21386
|
+
return null;
|
|
21387
|
+
}
|
|
21388
|
+
if (segs.length > 2 && !silent) agwarningf(MSG_MANY_COLORS);
|
|
21389
|
+
const frac = first.hasFraction ? first.t : second.hasFraction ? 1 - second.t : 0;
|
|
21390
|
+
return { fill: first.color, stop: second.color, frac };
|
|
21391
|
+
}
|
|
21183
21392
|
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"];
|
|
21393
|
+
const spec = findHtmlStopColor(color, true);
|
|
21394
|
+
return spec === null ? null : [spec.fill, spec.stop ?? "black"];
|
|
21190
21395
|
}
|
|
21191
21396
|
var paintObj = {
|
|
21192
21397
|
parent: null,
|
|
@@ -21243,6 +21448,12 @@ function resetHtmlFillPenWidth() {
|
|
|
21243
21448
|
htmlFillPen = 1;
|
|
21244
21449
|
}
|
|
21245
21450
|
registerRenderState(resetHtmlFillPenWidth);
|
|
21451
|
+
var DEFAULT_LINE_STYLE = ["solid", "setlinewidth(1)"];
|
|
21452
|
+
function htmlBorderStyle(pen) {
|
|
21453
|
+
if (pen === 1 /* Dashed */) return ["dashed"];
|
|
21454
|
+
if (pen === 2 /* Dotted */) return ["dotted"];
|
|
21455
|
+
return DEFAULT_LINE_STYLE;
|
|
21456
|
+
}
|
|
21246
21457
|
function penTypeOf(style2) {
|
|
21247
21458
|
const st = htmlStyle(style2);
|
|
21248
21459
|
if (st.dashed) return 1 /* Dashed */;
|
|
@@ -21250,12 +21461,13 @@ function penTypeOf(style2) {
|
|
|
21250
21461
|
return 3 /* Solid */;
|
|
21251
21462
|
}
|
|
21252
21463
|
function withHtmlPaint(paint, job, drawFn) {
|
|
21253
|
-
paintObj.fillColor = paint.fill !== void 0 ? resolveRenderColor(paint.fill) : { type: "none" };
|
|
21464
|
+
paintObj.fillColor = paint.fill !== void 0 ? resolveRenderColor(firstColor(paint.fill)) : { type: "none" };
|
|
21254
21465
|
paintObj.penColor = paint.pen !== void 0 ? resolveRenderColor(paint.pen) : { type: "string", s: "transparent" };
|
|
21255
21466
|
applyHtmlFill(paint);
|
|
21256
21467
|
paintObj.pen = penTypeOf(paint.penStyle);
|
|
21257
21468
|
paintObj.penWidth = paint.penWidth !== void 0 ? paint.penWidth : 1;
|
|
21258
21469
|
paintObj.rawStyle = paintObj.pen === 3 /* Solid */ ? ["solid"] : [];
|
|
21470
|
+
gvrenderSetStyle(htmlBorderStyle(paintObj.pen));
|
|
21259
21471
|
paintObj.emitState = job.obj?.emitState ?? 8 /* NDraw */;
|
|
21260
21472
|
job.pushObj(paintObj);
|
|
21261
21473
|
try {
|
|
@@ -21269,7 +21481,7 @@ function applyHtmlFill(paint) {
|
|
|
21269
21481
|
paintObj.fill = paint.radial === true ? 3 /* Radial */ : 2 /* Linear */;
|
|
21270
21482
|
paintObj.stopColor = resolveRenderColor(paint.stop);
|
|
21271
21483
|
paintObj.gradientAngle = paint.gradientAngle ?? 0;
|
|
21272
|
-
paintObj.gradientFrac = 0;
|
|
21484
|
+
paintObj.gradientFrac = paint.gradientFrac ?? 0;
|
|
21273
21485
|
return;
|
|
21274
21486
|
}
|
|
21275
21487
|
paintObj.fill = paint.fill !== void 0 ? 1 /* Solid */ : 0 /* None */;
|
|
@@ -21572,6 +21784,7 @@ function resolveClusterFillEx(attrs) {
|
|
|
21572
21784
|
|
|
21573
21785
|
// src/common/splines-clip.ts
|
|
21574
21786
|
var ARR_NORM = 1;
|
|
21787
|
+
var dist = distFused;
|
|
21575
21788
|
var SplineClipHelper = class _SplineClipHelper {
|
|
21576
21789
|
static makeEmptySpl() {
|
|
21577
21790
|
return { list: [], size: 0, bb: { ll: { x: 0, y: 0 }, ur: { x: 0, y: 0 } } };
|
|
@@ -21664,15 +21877,11 @@ var SplineClipHelper = class _SplineClipHelper {
|
|
|
21664
21877
|
if (j) return [eflag, sflag];
|
|
21665
21878
|
return [sflag, eflag];
|
|
21666
21879
|
}
|
|
21667
|
-
/** DIST(p, q). */
|
|
21668
|
-
static dist(p, q) {
|
|
21669
|
-
return Math.hypot(p.x - q.x, p.y - q.y);
|
|
21670
|
-
}
|
|
21671
21880
|
/** Sphere inside-fn around `tip` with radius `r` for bezierClip. */
|
|
21672
21881
|
static sphereCtx(tip2, r) {
|
|
21673
21882
|
return {
|
|
21674
21883
|
ctx: { nodeCoord: { x: 0, y: 0 }, rw: 0, bp: null },
|
|
21675
|
-
fn: (_c, p) =>
|
|
21884
|
+
fn: (_c, p) => dist(p, tip2) <= r
|
|
21676
21885
|
};
|
|
21677
21886
|
}
|
|
21678
21887
|
/**
|
|
@@ -21704,7 +21913,7 @@ var SplineClipHelper = class _SplineClipHelper {
|
|
|
21704
21913
|
);
|
|
21705
21914
|
spl.eflag = eflag;
|
|
21706
21915
|
spl.ep = ps[endp + 3];
|
|
21707
|
-
if (endp > startp &&
|
|
21916
|
+
if (endp > startp && dist(ps[endp], ps[endp + 3]) < elen) {
|
|
21708
21917
|
endp -= 3;
|
|
21709
21918
|
}
|
|
21710
21919
|
const sp = [spl.ep, ps[endp + 2], ps[endp + 1], ps[endp]];
|
|
@@ -21731,7 +21940,7 @@ var SplineClipHelper = class _SplineClipHelper {
|
|
|
21731
21940
|
);
|
|
21732
21941
|
spl.sflag = sflag;
|
|
21733
21942
|
spl.sp = ps[startp];
|
|
21734
|
-
if (endp > startp &&
|
|
21943
|
+
if (endp > startp && dist(ps[startp], ps[startp + 3]) < slen) {
|
|
21735
21944
|
startp += 3;
|
|
21736
21945
|
}
|
|
21737
21946
|
const sp = [ps[startp + 3], ps[startp + 2], ps[startp + 1], spl.sp];
|
|
@@ -21832,7 +22041,7 @@ var SplineClipHelper = class _SplineClipHelper {
|
|
|
21832
22041
|
if (sflag && eflag && endp === startp) {
|
|
21833
22042
|
const p = ps[endp];
|
|
21834
22043
|
const q = ps[endp + 3];
|
|
21835
|
-
const d =
|
|
22044
|
+
const d = dist(p, q);
|
|
21836
22045
|
let hlen = hlen0;
|
|
21837
22046
|
let tlen = tlen0;
|
|
21838
22047
|
if (hlen + tlen >= d) {
|
|
@@ -21875,7 +22084,7 @@ var SplineClipHelper = class _SplineClipHelper {
|
|
|
21875
22084
|
let hlen = hlen0;
|
|
21876
22085
|
const p = ps[endp];
|
|
21877
22086
|
const q = ps[endp + 3];
|
|
21878
|
-
const maxd = 0.9 *
|
|
22087
|
+
const maxd = 0.9 * dist(p, q);
|
|
21879
22088
|
if (hlen >= maxd) hlen = maxd;
|
|
21880
22089
|
const r = { x: p.x, y: p.y };
|
|
21881
22090
|
if (p.y === q.y) {
|
|
@@ -21895,7 +22104,7 @@ var SplineClipHelper = class _SplineClipHelper {
|
|
|
21895
22104
|
let tlen = tlen0;
|
|
21896
22105
|
const p = ps[startp];
|
|
21897
22106
|
const q = ps[startp + 3];
|
|
21898
|
-
const maxd = 0.9 *
|
|
22107
|
+
const maxd = 0.9 * dist(p, q);
|
|
21899
22108
|
if (tlen >= maxd) tlen = maxd;
|
|
21900
22109
|
const r = { x: p.x, y: p.y };
|
|
21901
22110
|
if (p.y === q.y) {
|
|
@@ -24029,13 +24238,13 @@ function dfsNode(Xg, v, frames) {
|
|
|
24029
24238
|
frames.push({ v, edges: v.outEdges(Xg).slice(), i: 0 });
|
|
24030
24239
|
}
|
|
24031
24240
|
function dfsStep2(Xg, frames) {
|
|
24032
|
-
const
|
|
24033
|
-
if (
|
|
24034
|
-
const e =
|
|
24241
|
+
const fr7 = frames[frames.length - 1];
|
|
24242
|
+
if (fr7.i < fr7.edges.length) {
|
|
24243
|
+
const e = fr7.edges[fr7.i++];
|
|
24035
24244
|
if (e.head.info.onstack) reverseEdge2(Xg, e);
|
|
24036
24245
|
else if (!e.head.info.mark) dfsNode(Xg, e.head, frames);
|
|
24037
24246
|
} else {
|
|
24038
|
-
|
|
24247
|
+
fr7.v.info.onstack = 0;
|
|
24039
24248
|
frames.pop();
|
|
24040
24249
|
}
|
|
24041
24250
|
}
|
|
@@ -25807,7 +26016,7 @@ function fillRankVlist(g, r, root) {
|
|
|
25807
26016
|
rankArr[r].v = rootRank.v;
|
|
25808
26017
|
rankArr[r].vStart = lead.info.order ?? 0;
|
|
25809
26018
|
const maxi = computeMaxi(g, r);
|
|
25810
|
-
if (maxi === -1) agwarningf(`degenerate concentrated rank ${g.name},${r}
|
|
26019
|
+
if (maxi === -1) agwarningf(`degenerate concentrated rank ${g.name},${r}`);
|
|
25811
26020
|
rankArr[r].n = maxi + 1;
|
|
25812
26021
|
return 0;
|
|
25813
26022
|
}
|
|
@@ -28626,7 +28835,7 @@ function routeSplinesInternal(pp, polyline) {
|
|
|
28626
28835
|
];
|
|
28627
28836
|
const pl = shortestPath(poly, eps);
|
|
28628
28837
|
if (pl === null) {
|
|
28629
|
-
|
|
28838
|
+
agerrorf("in routesplines, Pshortestpath failed");
|
|
28630
28839
|
return null;
|
|
28631
28840
|
}
|
|
28632
28841
|
emitDump("S3_POLY", dumpNames, () => ({
|
|
@@ -30632,9 +30841,9 @@ function writePortlabelPos(l, pe, pf, angleStr, distanceStr) {
|
|
|
30632
30841
|
const angleDeg = lateDouble(angleStr, PORT_LABEL_ANGLE, -180);
|
|
30633
30842
|
const angle = Math.atan2(pf.y - pe.y, pf.x - pe.x) + RADIANS(angleDeg);
|
|
30634
30843
|
const distMult = lateDouble(distanceStr || void 0, 1, 0);
|
|
30635
|
-
const
|
|
30636
|
-
l.pos.x = pe.x +
|
|
30637
|
-
l.pos.y = pe.y +
|
|
30844
|
+
const dist5 = PORT_LABEL_DISTANCE * distMult;
|
|
30845
|
+
l.pos.x = pe.x + dist5 * Math.cos(angle);
|
|
30846
|
+
l.pos.y = pe.y + dist5 * Math.sin(angle);
|
|
30638
30847
|
l.set = true;
|
|
30639
30848
|
}
|
|
30640
30849
|
function updateBB(g, l) {
|
|
@@ -31036,7 +31245,7 @@ function translateDrawing(g) {
|
|
|
31036
31245
|
if (e.tail !== v) continue;
|
|
31037
31246
|
if (e.info.spl === void 0) {
|
|
31038
31247
|
if (!(g.info.concentrate ?? false) && (e.info.edge_type ?? 0) !== IGNORED_EDGE) {
|
|
31039
|
-
|
|
31248
|
+
agerrorf(`lost ${e.tail.name} ${e.head.name} edge`);
|
|
31040
31249
|
}
|
|
31041
31250
|
continue;
|
|
31042
31251
|
}
|
|
@@ -31799,9 +32008,14 @@ function nodeInsideFn2(box) {
|
|
|
31799
32008
|
function clipToNodes(bezier2, tailBox, headBox, penwidth = DEFAULT_NODEPENWIDTH, clip = CLIP_BOTH) {
|
|
31800
32009
|
const step1 = clip.tail ? bezierClipNode(bezier2, tailBox.center.x, tailBox.center.y, nodeInsideFn2(tailBox), true) : bezier2;
|
|
31801
32010
|
const step2 = clip.head ? bezierClipNode(step1, headBox.center.x, headBox.center.y, nodeInsideFn2(headBox), false) : step1;
|
|
31802
|
-
const
|
|
32011
|
+
const startp = 0;
|
|
32012
|
+
let endp = 0;
|
|
32013
|
+
const arrowTip = step2[endp + 3];
|
|
31803
32014
|
const elen = normalArrowLen(penwidth);
|
|
31804
|
-
|
|
32015
|
+
if (endp > startp && distFused(step2[endp], step2[endp + 3]) < elen) {
|
|
32016
|
+
endp -= 3;
|
|
32017
|
+
}
|
|
32018
|
+
const clipped = arrowEndClip(step2.slice(endp, endp + 4), arrowTip, elen);
|
|
31805
32019
|
const arrowDir = normalizeVec({
|
|
31806
32020
|
x: clipped[3].x - arrowTip.x,
|
|
31807
32021
|
y: clipped[3].y - arrowTip.y
|
|
@@ -34340,8 +34554,7 @@ function ensureDummyNodes(sg, gstart) {
|
|
|
34340
34554
|
}
|
|
34341
34555
|
function orthoEdges(g, useLbls, clipAndInstall2) {
|
|
34342
34556
|
if (useLbls) {
|
|
34343
|
-
|
|
34344
|
-
"warn",
|
|
34557
|
+
agwarningf(
|
|
34345
34558
|
"Orthogonal edges do not currently handle edge labels. Try using xlabels.\n"
|
|
34346
34559
|
);
|
|
34347
34560
|
useLbls = false;
|
|
@@ -34476,7 +34689,7 @@ function dispatchOrthoEdges(g, useLbls) {
|
|
|
34476
34689
|
}
|
|
34477
34690
|
|
|
34478
34691
|
// src/common/arrows-geometry.ts
|
|
34479
|
-
function
|
|
34692
|
+
function dist3(a, b) {
|
|
34480
34693
|
return Math.hypot(a.x - b.x, a.y - b.y);
|
|
34481
34694
|
}
|
|
34482
34695
|
|
|
@@ -34580,7 +34793,7 @@ function getCycleCentroid(g, edge) {
|
|
|
34580
34793
|
}
|
|
34581
34794
|
function bend(spl, centroid) {
|
|
34582
34795
|
const midpt = midPointf(spl[0], spl[3]);
|
|
34583
|
-
const distVal =
|
|
34796
|
+
const distVal = dist3(spl[3], spl[0]);
|
|
34584
34797
|
const r = distVal / 5;
|
|
34585
34798
|
const vX = centroid.x - midpt.x;
|
|
34586
34799
|
const vY = centroid.y - midpt.y;
|
|
@@ -35193,7 +35406,7 @@ function arrowEndClipIdx(state3, endp) {
|
|
|
35193
35406
|
const elen = arrowClipLength(edgeArrowName(e, "head"), edgeArrowsize(e), edgePenwidthAttr(e));
|
|
35194
35407
|
bez.eflag = bez.eflag || 1;
|
|
35195
35408
|
bez.ep = { ...bez.list[endp + 3] };
|
|
35196
|
-
if (endp > state3.starti &&
|
|
35409
|
+
if (endp > state3.starti && distFused(bez.list[endp], bez.list[endp + 3]) < elen) endp -= 3;
|
|
35197
35410
|
const seg2 = [bez.list[endp], bez.list[endp + 1], bez.list[endp + 2], bez.list[endp + 3]];
|
|
35198
35411
|
const clipped = arrowEndClip(seg2, bez.ep, elen);
|
|
35199
35412
|
for (let k = 0; k < 4; k++) bez.list[endp + k] = clipped[k];
|
|
@@ -35204,7 +35417,7 @@ function arrowStartClipIdx(state3, startp, endp) {
|
|
|
35204
35417
|
const slen = arrowClipLength(edgeArrowName(e, "tail"), edgeArrowsize(e), edgePenwidthAttr(e));
|
|
35205
35418
|
bez.sflag = bez.sflag || 1;
|
|
35206
35419
|
bez.sp = { ...bez.list[startp] };
|
|
35207
|
-
if (endp > startp &&
|
|
35420
|
+
if (endp > startp && distFused(bez.list[startp], bez.list[startp + 3]) < slen) startp += 3;
|
|
35208
35421
|
const seg2 = [bez.list[startp], bez.list[startp + 1], bez.list[startp + 2], bez.list[startp + 3]];
|
|
35209
35422
|
const clipped = tailArrowEndClip(seg2, bez.sp, slen);
|
|
35210
35423
|
for (let k = 0; k < 4; k++) bez.list[startp + k] = clipped[k];
|
|
@@ -36473,120 +36686,522 @@ var DOT_LAYOUT_ENGINE = {
|
|
|
36473
36686
|
};
|
|
36474
36687
|
|
|
36475
36688
|
// 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;
|
|
36689
|
+
var FLT_MAX = 34028234663852886e22;
|
|
36690
|
+
function greaterPriorityF(h, i, j, dist5) {
|
|
36691
|
+
return dist5[h.data[i]] < dist5[h.data[j]];
|
|
36692
|
+
}
|
|
36693
|
+
function heapifyF(h, start, dist5) {
|
|
36694
|
+
let i = start;
|
|
36490
36695
|
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 = [];
|
|
36696
|
+
const l = ngLeft(i);
|
|
36697
|
+
const r = ngRight(i);
|
|
36698
|
+
let largest = ngInsideHeap(h, l) && greaterPriorityF(h, l, i, dist5) ? l : i;
|
|
36699
|
+
if (ngInsideHeap(h, r) && greaterPriorityF(h, r, largest, dist5)) largest = r;
|
|
36700
|
+
if (largest === i) break;
|
|
36701
|
+
ngExchange(h, largest, i);
|
|
36702
|
+
i = largest;
|
|
36703
|
+
}
|
|
36704
|
+
}
|
|
36705
|
+
function initHeapF(startVertex, dist5, n) {
|
|
36706
|
+
const h = {
|
|
36707
|
+
data: new Array(Math.max(n - 1, 0)).fill(0),
|
|
36708
|
+
heapSize: n - 1,
|
|
36709
|
+
index: new Int32Array(n)
|
|
36710
|
+
};
|
|
36711
|
+
let count = 0;
|
|
36513
36712
|
for (let i = 0; i < n; i++) {
|
|
36514
|
-
if (i !==
|
|
36713
|
+
if (i !== startVertex) {
|
|
36714
|
+
h.data[count] = i;
|
|
36715
|
+
h.index[i] = count;
|
|
36716
|
+
count++;
|
|
36717
|
+
}
|
|
36515
36718
|
}
|
|
36516
|
-
|
|
36719
|
+
for (let j = Math.trunc((n - 1) / 2); j >= 0; j--) heapifyF(h, j, dist5);
|
|
36720
|
+
return h;
|
|
36721
|
+
}
|
|
36722
|
+
function extractMaxF(h, dist5) {
|
|
36723
|
+
if (h.heapSize === 0) return -1;
|
|
36724
|
+
const max = h.data[0];
|
|
36725
|
+
h.data[0] = h.data[h.heapSize - 1];
|
|
36726
|
+
h.index[h.data[0]] = 0;
|
|
36727
|
+
h.heapSize--;
|
|
36728
|
+
heapifyF(h, 0, dist5);
|
|
36729
|
+
return max;
|
|
36730
|
+
}
|
|
36731
|
+
function increaseKeyF(h, increasedVertex, newDist, dist5) {
|
|
36732
|
+
if (dist5[increasedVertex] <= newDist) return;
|
|
36733
|
+
let i = h.index[increasedVertex];
|
|
36734
|
+
dist5[increasedVertex] = newDist;
|
|
36735
|
+
while (i > 0 && dist5[h.data[ngParent(i)]] > newDist) {
|
|
36736
|
+
ngAssign(h, i, ngParent(i));
|
|
36737
|
+
i = ngParent(i);
|
|
36738
|
+
}
|
|
36739
|
+
h.data[i] = increasedVertex;
|
|
36740
|
+
h.index[increasedVertex] = i;
|
|
36741
|
+
}
|
|
36742
|
+
function dijkstra(vertex, graph, n, dist5) {
|
|
36743
|
+
for (let i = 0; i < n; i++) dist5[i] = FLT_MAX;
|
|
36744
|
+
dist5[vertex] = 0;
|
|
36745
|
+
const vd = graph[vertex];
|
|
36746
|
+
for (let i = 1; i < vd.nedges; i++) dist5[vd.edges[i]] = vd.ewgts[i];
|
|
36747
|
+
const h = initHeapF(vertex, dist5, n);
|
|
36748
|
+
for (let closest = extractMaxF(h, dist5); closest >= 0; closest = extractMaxF(h, dist5)) {
|
|
36749
|
+
const closestDist = dist5[closest];
|
|
36750
|
+
if (closestDist === FLT_MAX) break;
|
|
36751
|
+
const cd = graph[closest];
|
|
36752
|
+
for (let i = 1; i < cd.nedges; i++) {
|
|
36753
|
+
increaseKeyF(h, cd.edges[i], Math.fround(closestDist + Math.fround(cd.ewgts[i])), dist5);
|
|
36754
|
+
}
|
|
36755
|
+
}
|
|
36756
|
+
}
|
|
36757
|
+
var MAX_DIST = 2147483647;
|
|
36758
|
+
function ngLeft(i) {
|
|
36759
|
+
return 2 * i;
|
|
36517
36760
|
}
|
|
36518
|
-
function
|
|
36519
|
-
|
|
36520
|
-
dist4[src] = 0;
|
|
36521
|
-
const v = graph[src];
|
|
36522
|
-
for (let i = 1; i < v.nedges; i++) dist4[v.edges[i]] = v.ewgts[i];
|
|
36761
|
+
function ngRight(i) {
|
|
36762
|
+
return 2 * i + 1;
|
|
36523
36763
|
}
|
|
36524
|
-
function
|
|
36525
|
-
|
|
36526
|
-
|
|
36527
|
-
|
|
36528
|
-
|
|
36529
|
-
|
|
36530
|
-
|
|
36531
|
-
|
|
36764
|
+
function ngParent(i) {
|
|
36765
|
+
return Math.trunc(i / 2);
|
|
36766
|
+
}
|
|
36767
|
+
function ngInsideHeap(h, i) {
|
|
36768
|
+
return i < h.heapSize;
|
|
36769
|
+
}
|
|
36770
|
+
function ngGreaterPriority(h, i, j, dist5) {
|
|
36771
|
+
return dist5[h.data[i]] < dist5[h.data[j]];
|
|
36772
|
+
}
|
|
36773
|
+
function ngAssign(h, i, j) {
|
|
36774
|
+
h.data[i] = h.data[j];
|
|
36775
|
+
h.index[h.data[i]] = i;
|
|
36776
|
+
}
|
|
36777
|
+
function ngExchange(h, i, j) {
|
|
36778
|
+
const t = h.data[i];
|
|
36779
|
+
h.data[i] = h.data[j];
|
|
36780
|
+
h.data[j] = t;
|
|
36781
|
+
h.index[h.data[i]] = i;
|
|
36782
|
+
h.index[h.data[j]] = j;
|
|
36783
|
+
}
|
|
36784
|
+
function ngHeapify(h, start, dist5) {
|
|
36785
|
+
let i = start;
|
|
36786
|
+
for (; ; ) {
|
|
36787
|
+
const l = ngLeft(i);
|
|
36788
|
+
const r = ngRight(i);
|
|
36789
|
+
let largest = ngInsideHeap(h, l) && ngGreaterPriority(h, l, i, dist5) ? l : i;
|
|
36790
|
+
if (ngInsideHeap(h, r) && ngGreaterPriority(h, r, largest, dist5)) largest = r;
|
|
36791
|
+
if (largest === i) break;
|
|
36792
|
+
ngExchange(h, largest, i);
|
|
36793
|
+
i = largest;
|
|
36794
|
+
}
|
|
36795
|
+
}
|
|
36796
|
+
function ngInitHeap(startVertex, dist5, n) {
|
|
36797
|
+
const h = {
|
|
36798
|
+
data: new Array(Math.max(n - 1, 0)).fill(0),
|
|
36799
|
+
heapSize: n - 1,
|
|
36800
|
+
index: new Int32Array(n)
|
|
36801
|
+
};
|
|
36802
|
+
let count = 0;
|
|
36803
|
+
for (let i = 0; i < n; i++) {
|
|
36804
|
+
if (i !== startVertex) {
|
|
36805
|
+
h.data[count] = i;
|
|
36806
|
+
h.index[i] = count;
|
|
36807
|
+
count++;
|
|
36532
36808
|
}
|
|
36533
36809
|
}
|
|
36810
|
+
for (let j = Math.trunc((n - 1) / 2); j >= 0; j--) ngHeapify(h, j, dist5);
|
|
36811
|
+
return h;
|
|
36812
|
+
}
|
|
36813
|
+
function ngExtractMax(h, dist5) {
|
|
36814
|
+
if (h.heapSize === 0) return -1;
|
|
36815
|
+
const max = h.data[0];
|
|
36816
|
+
h.data[0] = h.data[h.heapSize - 1];
|
|
36817
|
+
h.index[h.data[0]] = 0;
|
|
36818
|
+
h.heapSize--;
|
|
36819
|
+
ngHeapify(h, 0, dist5);
|
|
36820
|
+
return max;
|
|
36534
36821
|
}
|
|
36535
|
-
function
|
|
36536
|
-
|
|
36537
|
-
|
|
36538
|
-
|
|
36539
|
-
|
|
36540
|
-
|
|
36541
|
-
|
|
36542
|
-
|
|
36822
|
+
function ngIncreaseKey(h, increasedVertex, newDist, dist5) {
|
|
36823
|
+
if (dist5[increasedVertex] <= newDist) return;
|
|
36824
|
+
let i = h.index[increasedVertex];
|
|
36825
|
+
dist5[increasedVertex] = newDist;
|
|
36826
|
+
while (i > 0 && dist5[h.data[ngParent(i)]] > newDist) {
|
|
36827
|
+
ngAssign(h, i, ngParent(i));
|
|
36828
|
+
i = ngParent(i);
|
|
36829
|
+
}
|
|
36830
|
+
h.data[i] = increasedVertex;
|
|
36831
|
+
h.index[increasedVertex] = i;
|
|
36832
|
+
}
|
|
36833
|
+
function toDistType(w) {
|
|
36834
|
+
return Math.trunc(Math.fround(w));
|
|
36835
|
+
}
|
|
36836
|
+
function ngdijkstra(vertex, graph, n, dist5) {
|
|
36837
|
+
let prevClosestDist = MAX_DIST;
|
|
36838
|
+
for (let i = 0; i < n; i++) dist5[i] = MAX_DIST;
|
|
36839
|
+
dist5[vertex] = 0;
|
|
36840
|
+
const vd = graph[vertex];
|
|
36841
|
+
for (let i = 1; i < vd.nedges; i++) dist5[vd.edges[i]] = toDistType(vd.ewgts[i]);
|
|
36842
|
+
const h = ngInitHeap(vertex, dist5, n);
|
|
36843
|
+
for (let closest = ngExtractMax(h, dist5); closest >= 0; closest = ngExtractMax(h, dist5)) {
|
|
36844
|
+
const closestDist = dist5[closest];
|
|
36845
|
+
if (closestDist === MAX_DIST) break;
|
|
36846
|
+
const cd = graph[closest];
|
|
36847
|
+
for (let i = 1; i < cd.nedges; i++) {
|
|
36848
|
+
ngIncreaseKey(h, cd.edges[i], closestDist + toDistType(cd.ewgts[i]) | 0, dist5);
|
|
36849
|
+
}
|
|
36850
|
+
prevClosestDist = closestDist;
|
|
36851
|
+
}
|
|
36852
|
+
for (let i = 0; i < n; i++) {
|
|
36853
|
+
if (dist5[i] === MAX_DIST) {
|
|
36854
|
+
dist5[i] = MAX_DIST - prevClosestDist < 10 ? MAX_DIST : prevClosestDist + 10;
|
|
36855
|
+
}
|
|
36543
36856
|
}
|
|
36544
36857
|
}
|
|
36545
36858
|
|
|
36546
36859
|
// src/layout/neato/bfs.ts
|
|
36547
|
-
function bfsInit(src, n,
|
|
36548
|
-
for (let i = 0; i < n; i++)
|
|
36549
|
-
|
|
36860
|
+
function bfsInit(src, n, dist5) {
|
|
36861
|
+
for (let i = 0; i < n; i++) dist5[i] = -1;
|
|
36862
|
+
dist5[src] = 0;
|
|
36550
36863
|
return [src];
|
|
36551
36864
|
}
|
|
36552
|
-
function bfsFixDisconnected(n,
|
|
36865
|
+
function bfsFixDisconnected(n, dist5, closestDist) {
|
|
36553
36866
|
for (let i = 0; i < n; i++) {
|
|
36554
|
-
if (
|
|
36867
|
+
if (dist5[i] < 0) dist5[i] = closestDist + 10;
|
|
36555
36868
|
}
|
|
36556
36869
|
}
|
|
36557
|
-
function bfsVisitNeighbors(vertex, graph,
|
|
36870
|
+
function bfsVisitNeighbors(vertex, graph, dist5, queue) {
|
|
36558
36871
|
const vd = graph[vertex];
|
|
36559
|
-
const d =
|
|
36872
|
+
const d = dist5[vertex];
|
|
36560
36873
|
const unit = graph[0].ewgts.length === 0;
|
|
36561
36874
|
for (let i = 1; i < vd.nedges; i++) {
|
|
36562
36875
|
const nb = vd.edges[i];
|
|
36563
|
-
if (
|
|
36564
|
-
|
|
36876
|
+
if (dist5[nb] < 0) {
|
|
36877
|
+
dist5[nb] = d + (unit ? 1 : Math.trunc(Math.fround(vd.ewgts[i])));
|
|
36565
36878
|
queue.push(nb);
|
|
36566
36879
|
}
|
|
36567
36880
|
}
|
|
36568
36881
|
return d;
|
|
36569
36882
|
}
|
|
36570
|
-
function bfs(src, graph, n,
|
|
36571
|
-
const queue = bfsInit(src, n,
|
|
36883
|
+
function bfs(src, graph, n, dist5) {
|
|
36884
|
+
const queue = bfsInit(src, n, dist5);
|
|
36572
36885
|
let closestDist = 0;
|
|
36573
36886
|
let head = 0;
|
|
36574
36887
|
while (head < queue.length) {
|
|
36575
36888
|
const vertex = queue[head++];
|
|
36576
|
-
closestDist = bfsVisitNeighbors(vertex, graph,
|
|
36889
|
+
closestDist = bfsVisitNeighbors(vertex, graph, dist5, queue);
|
|
36890
|
+
}
|
|
36891
|
+
bfsFixDisconnected(n, dist5, closestDist);
|
|
36892
|
+
}
|
|
36893
|
+
function packedIndex(i, j, n) {
|
|
36894
|
+
return i * (2 * n - i - 1) / 2 + j;
|
|
36895
|
+
}
|
|
36896
|
+
function computeWeightedApspPacked(graph, n) {
|
|
36897
|
+
const result = new Float32Array(n * (n + 1) / 2);
|
|
36898
|
+
const di = new Float32Array(n);
|
|
36899
|
+
for (let i = 0; i < n; i++) {
|
|
36900
|
+
dijkstra(i, graph, n, di);
|
|
36901
|
+
for (let j = i; j < n; j++) result[packedIndex(i, j, n)] = di[j];
|
|
36902
|
+
}
|
|
36903
|
+
return result;
|
|
36904
|
+
}
|
|
36905
|
+
|
|
36906
|
+
// src/common/crand.ts
|
|
36907
|
+
var C_RAND_MAX = 2147483647;
|
|
36908
|
+
var UNSEEDED_STATE2 = 1;
|
|
36909
|
+
var state2 = UNSEEDED_STATE2;
|
|
36910
|
+
registerRenderState(() => {
|
|
36911
|
+
state2 = UNSEEDED_STATE2;
|
|
36912
|
+
});
|
|
36913
|
+
function csrand(seed) {
|
|
36914
|
+
state2 = seed;
|
|
36915
|
+
}
|
|
36916
|
+
function crand() {
|
|
36917
|
+
state2 = state2 * 16807 % 2147483647;
|
|
36918
|
+
return state2;
|
|
36919
|
+
}
|
|
36920
|
+
function cdrand() {
|
|
36921
|
+
return crand() / C_RAND_MAX;
|
|
36922
|
+
}
|
|
36923
|
+
function gvRandom(bound) {
|
|
36924
|
+
const discardThreshold = C_RAND_MAX - 2147483648 % bound;
|
|
36925
|
+
let r;
|
|
36926
|
+
do {
|
|
36927
|
+
r = crand();
|
|
36928
|
+
} while (r > discardThreshold);
|
|
36929
|
+
return r % bound;
|
|
36930
|
+
}
|
|
36931
|
+
function gvPermutation(bound) {
|
|
36932
|
+
if (bound <= 0) return [];
|
|
36933
|
+
const p = [];
|
|
36934
|
+
for (let i = 0; i < bound; i++) p.push(i);
|
|
36935
|
+
for (let i = bound - 1; i > 0; --i) {
|
|
36936
|
+
const j = gvRandom(i + 1);
|
|
36937
|
+
const t = p[i];
|
|
36938
|
+
p[i] = p[j];
|
|
36939
|
+
p[j] = t;
|
|
36940
|
+
}
|
|
36941
|
+
return p;
|
|
36942
|
+
}
|
|
36943
|
+
|
|
36944
|
+
// src/layout/neato/matrix-ops.ts
|
|
36945
|
+
var fr = Math.fround;
|
|
36946
|
+
function fma2(a, b, c) {
|
|
36947
|
+
const p = a * b;
|
|
36948
|
+
return Number.isFinite(p) && Number.isFinite(c) ? fma(a, b, c) : p + c;
|
|
36949
|
+
}
|
|
36950
|
+
function orthog1(n, vec) {
|
|
36951
|
+
let sum = 0;
|
|
36952
|
+
for (let i = 0; i < n; i++) sum += vec[i];
|
|
36953
|
+
sum /= n;
|
|
36954
|
+
for (let i = 0; i < n; i++) vec[i] = vec[i] - sum;
|
|
36955
|
+
}
|
|
36956
|
+
function orthog1f(n, vec) {
|
|
36957
|
+
let sum = fr(0);
|
|
36958
|
+
for (let i = 0; i < n; i++) sum = fr(sum + vec[i]);
|
|
36959
|
+
sum = fr(sum / n);
|
|
36960
|
+
for (let i = 0; i < n; i++) vec[i] = vec[i] - sum;
|
|
36961
|
+
}
|
|
36962
|
+
function rightMultWithVectorFF(m, n, vector, result) {
|
|
36963
|
+
for (let i = 0; i < n; i++) result[i] = 0;
|
|
36964
|
+
let index = 0;
|
|
36965
|
+
for (let i = 0; i < n; i++) {
|
|
36966
|
+
const vi = vector[i];
|
|
36967
|
+
let res = fr(m[index++] * vi);
|
|
36968
|
+
for (let j = i + 1; j < n; j++, index++) {
|
|
36969
|
+
res = fr(res + fr(m[index] * vector[j]));
|
|
36970
|
+
result[j] = result[j] + fr(m[index] * vi);
|
|
36971
|
+
}
|
|
36972
|
+
result[i] = result[i] + res;
|
|
36973
|
+
}
|
|
36974
|
+
}
|
|
36975
|
+
function vectorsSubtractionF(n, v1, v2, result) {
|
|
36976
|
+
for (let i = 0; i < n; i++) result[i] = v1[i] - v2[i];
|
|
36977
|
+
}
|
|
36978
|
+
function vectorsMultAdditionF(n, v1, alpha, v2) {
|
|
36979
|
+
const a = fr(alpha);
|
|
36980
|
+
for (let i = 0; i < n; i++) v1[i] = v1[i] + fr(a * v2[i]);
|
|
36981
|
+
}
|
|
36982
|
+
function vectorsInnerProductF(n, v1, v2) {
|
|
36983
|
+
let result = 0;
|
|
36984
|
+
for (let i = 0; i < n; i++) result += fr(v1[i] * v2[i]);
|
|
36985
|
+
return result;
|
|
36986
|
+
}
|
|
36987
|
+
function copyVectorF(n, src, dst) {
|
|
36988
|
+
for (let i = 0; i < n; i++) dst[i] = src[i];
|
|
36989
|
+
}
|
|
36990
|
+
function maxAbsF(n, vec) {
|
|
36991
|
+
let max = fr(-1e30);
|
|
36992
|
+
for (let i = 0; i < n; i++) {
|
|
36993
|
+
const a = fr(Math.abs(vec[i]));
|
|
36994
|
+
if (a > max) max = a;
|
|
36995
|
+
}
|
|
36996
|
+
return max;
|
|
36997
|
+
}
|
|
36998
|
+
function squareVec(n, vec) {
|
|
36999
|
+
for (let i = 0; i < n; i++) vec[i] = vec[i] * vec[i];
|
|
37000
|
+
}
|
|
37001
|
+
function invertVec(n, vec) {
|
|
37002
|
+
for (let i = 0; i < n; i++) {
|
|
37003
|
+
if (vec[i] !== 0) vec[i] = 1 / vec[i];
|
|
37004
|
+
}
|
|
37005
|
+
}
|
|
37006
|
+
function sqrtVecF(n, source, target) {
|
|
37007
|
+
for (let i = 0; i < n; i++) {
|
|
37008
|
+
if (source[i] >= 0) target[i] = fr(Math.sqrt(source[i]));
|
|
37009
|
+
}
|
|
37010
|
+
}
|
|
37011
|
+
function invertSqrtVec(n, vec) {
|
|
37012
|
+
for (let i = 0; i < n; i++) {
|
|
37013
|
+
if (vec[i] > 0) vec[i] = 1 / fr(Math.sqrt(vec[i]));
|
|
37014
|
+
}
|
|
37015
|
+
}
|
|
37016
|
+
var BLOCK_NONE = 1;
|
|
37017
|
+
function innerProduct(n, v1, v2, block) {
|
|
37018
|
+
let result = 0;
|
|
37019
|
+
const blocked = block === BLOCK_NONE ? 0 : n - n % block;
|
|
37020
|
+
let i = 0;
|
|
37021
|
+
for (; i < blocked; i++) result += v1[i] * v2[i];
|
|
37022
|
+
for (; i < n; i++) result = fma2(v1[i], v2[i], result);
|
|
37023
|
+
return result;
|
|
37024
|
+
}
|
|
37025
|
+
function scadd(vec1, end, fac, vec2) {
|
|
37026
|
+
for (let i = 0; i <= end; i++) vec1[i] = fma2(fac, vec2[i], vec1[i]);
|
|
37027
|
+
}
|
|
37028
|
+
function norm(vec, end, block) {
|
|
37029
|
+
return Math.sqrt(innerProduct(end + 1, vec, vec, block));
|
|
37030
|
+
}
|
|
37031
|
+
function vectorsScalarMult(n, vector, alpha, result) {
|
|
37032
|
+
for (let i = 0; i < n; i++) result[i] = vector[i] * alpha;
|
|
37033
|
+
}
|
|
37034
|
+
function copyVector(n, source, dest) {
|
|
37035
|
+
for (let i = 0; i < n; i++) dest[i] = source[i];
|
|
37036
|
+
}
|
|
37037
|
+
function vectorsAddition(n, v1, v2, result) {
|
|
37038
|
+
for (let i = 0; i < n; i++) result[i] = v1[i] + v2[i];
|
|
37039
|
+
}
|
|
37040
|
+
function vectorsSubtraction(n, v1, v2, result) {
|
|
37041
|
+
for (let i = 0; i < n; i++) result[i] = v1[i] - v2[i];
|
|
37042
|
+
}
|
|
37043
|
+
function maxAbs(n, vector) {
|
|
37044
|
+
let maxVal = -1e50;
|
|
37045
|
+
for (let i = 0; i < n; i++) {
|
|
37046
|
+
const a = Math.abs(vector[i]);
|
|
37047
|
+
if (a > maxVal) maxVal = a;
|
|
37048
|
+
}
|
|
37049
|
+
return maxVal;
|
|
37050
|
+
}
|
|
37051
|
+
function rightMultWithVectorF(matrix, n, vector, result, block) {
|
|
37052
|
+
const blocked = block === BLOCK_NONE ? 0 : n - n % block;
|
|
37053
|
+
for (let i = 0; i < n; i++) {
|
|
37054
|
+
const row = matrix[i];
|
|
37055
|
+
let res = 0;
|
|
37056
|
+
let j = 0;
|
|
37057
|
+
for (; j < blocked; j++) res += row[j] * vector[j];
|
|
37058
|
+
for (; j < n; j++) res = fma2(row[j], vector[j], res);
|
|
37059
|
+
result[i] = res;
|
|
37060
|
+
}
|
|
37061
|
+
}
|
|
37062
|
+
function rightMultWithVector(matrix, n, vector, result) {
|
|
37063
|
+
for (let i = 0; i < n; i++) {
|
|
37064
|
+
let res = 0;
|
|
37065
|
+
const row = matrix[i];
|
|
37066
|
+
for (let j = 0; j < row.nedges; j++) res = fma2(row.ewgts[j], vector[row.edges[j]], res);
|
|
37067
|
+
result[i] = res;
|
|
37068
|
+
}
|
|
37069
|
+
}
|
|
37070
|
+
var RANGE = 500;
|
|
37071
|
+
function initVecOrth1(n, vec) {
|
|
37072
|
+
for (let i = 0; i < n; i++) vec[i] = crand() % RANGE;
|
|
37073
|
+
orthog1(n, vec);
|
|
37074
|
+
}
|
|
37075
|
+
|
|
37076
|
+
// src/layout/neato/conjgrad.ts
|
|
37077
|
+
var BLOCK_INITIAL_RR = 4;
|
|
37078
|
+
var BLOCK_P_AP = 8;
|
|
37079
|
+
function cgNextDirection(n, w, alpha, rR) {
|
|
37080
|
+
vectorsScalarMult(n, w.Ap, alpha, w.Ap);
|
|
37081
|
+
vectorsSubtraction(n, w.r, w.Ap, w.r);
|
|
37082
|
+
const rRNew = innerProduct(n, w.r, w.r, BLOCK_NONE);
|
|
37083
|
+
if (rR === 0) {
|
|
37084
|
+
agerrorf("conjugate_gradient: unexpected length 0 vector\n");
|
|
37085
|
+
return null;
|
|
37086
|
+
}
|
|
37087
|
+
const beta = rRNew / rR;
|
|
37088
|
+
vectorsScalarMult(n, w.p, beta, w.p);
|
|
37089
|
+
vectorsAddition(n, w.r, w.p, w.p);
|
|
37090
|
+
return rRNew;
|
|
37091
|
+
}
|
|
37092
|
+
function cgStart(A3, x, b, n) {
|
|
37093
|
+
const w = {
|
|
37094
|
+
r: new Float64Array(n),
|
|
37095
|
+
p: new Float64Array(n),
|
|
37096
|
+
Ap: new Float64Array(n),
|
|
37097
|
+
alphap: new Float64Array(n)
|
|
37098
|
+
};
|
|
37099
|
+
const Ax = new Float64Array(n);
|
|
37100
|
+
const orthB = Float64Array.from(b.subarray(0, n));
|
|
37101
|
+
orthog1(n, orthB);
|
|
37102
|
+
orthog1(n, x);
|
|
37103
|
+
rightMultWithVector(A3, n, x, Ax);
|
|
37104
|
+
vectorsSubtraction(n, orthB, Ax, w.r);
|
|
37105
|
+
w.p.set(w.r.subarray(0, n));
|
|
37106
|
+
return w;
|
|
37107
|
+
}
|
|
37108
|
+
function conjugateGradient(A3, x, b, n, tol, maxIterations) {
|
|
37109
|
+
const w = cgStart(A3, x, b, n);
|
|
37110
|
+
let rR = innerProduct(n, w.r, w.r, BLOCK_INITIAL_RR);
|
|
37111
|
+
for (let i = 0; i < maxIterations && maxAbs(n, w.r) > tol; i++) {
|
|
37112
|
+
rightMultWithVector(A3, n, w.p, w.Ap);
|
|
37113
|
+
const pAp = innerProduct(n, w.p, w.Ap, BLOCK_P_AP);
|
|
37114
|
+
if (pAp === 0) break;
|
|
37115
|
+
const alpha = rR / pAp;
|
|
37116
|
+
vectorsScalarMult(n, w.p, alpha, w.alphap);
|
|
37117
|
+
vectorsAddition(n, x, w.alphap, x);
|
|
37118
|
+
if (i < maxIterations - 1) {
|
|
37119
|
+
const next = cgNextDirection(n, w, alpha, rR);
|
|
37120
|
+
if (next === null) return 1;
|
|
37121
|
+
rR = next;
|
|
37122
|
+
}
|
|
37123
|
+
}
|
|
37124
|
+
return 0;
|
|
37125
|
+
}
|
|
37126
|
+
var CGF_BLOCK_AX = 4;
|
|
37127
|
+
var CGF_BLOCK_AP = 4;
|
|
37128
|
+
var CGF_BLOCK_INITIAL_RR = 4;
|
|
37129
|
+
var CGF_BLOCK_P_AP = 8;
|
|
37130
|
+
function cgfInit(A3, x, b, n, ortho1) {
|
|
37131
|
+
const orthB = new Float64Array(n);
|
|
37132
|
+
copyVector(n, b, orthB);
|
|
37133
|
+
if (ortho1) {
|
|
37134
|
+
orthog1(n, orthB);
|
|
37135
|
+
orthog1(n, x);
|
|
37136
|
+
}
|
|
37137
|
+
const Ax = new Float64Array(n);
|
|
37138
|
+
rightMultWithVectorF(A3, n, x, Ax, CGF_BLOCK_AX);
|
|
37139
|
+
const r = new Float64Array(n);
|
|
37140
|
+
vectorsSubtraction(n, orthB, Ax, r);
|
|
37141
|
+
const p = new Float64Array(n);
|
|
37142
|
+
copyVector(n, r, p);
|
|
37143
|
+
return {
|
|
37144
|
+
r,
|
|
37145
|
+
p,
|
|
37146
|
+
Ap: new Float64Array(n),
|
|
37147
|
+
alphap: new Float64Array(n),
|
|
37148
|
+
rr: innerProduct(n, r, r, CGF_BLOCK_INITIAL_RR)
|
|
37149
|
+
};
|
|
37150
|
+
}
|
|
37151
|
+
function cgfUpdate(n, alpha, st) {
|
|
37152
|
+
vectorsScalarMult(n, st.Ap, alpha, st.Ap);
|
|
37153
|
+
vectorsSubtraction(n, st.r, st.Ap, st.r);
|
|
37154
|
+
const rrNew = innerProduct(n, st.r, st.r, BLOCK_NONE);
|
|
37155
|
+
if (st.rr === 0) {
|
|
37156
|
+
agerrorf("conjugate_gradient: unexpected length 0 vector\n");
|
|
37157
|
+
return 1;
|
|
37158
|
+
}
|
|
37159
|
+
const beta = rrNew / st.rr;
|
|
37160
|
+
st.rr = rrNew;
|
|
37161
|
+
vectorsScalarMult(n, st.p, beta, st.p);
|
|
37162
|
+
vectorsAddition(n, st.r, st.p, st.p);
|
|
37163
|
+
return 0;
|
|
37164
|
+
}
|
|
37165
|
+
function conjugateGradientF(A3, x, b, n, opts) {
|
|
37166
|
+
const { tol, maxIterations, ortho1 } = opts;
|
|
37167
|
+
const st = cgfInit(A3, x, b, n, ortho1);
|
|
37168
|
+
for (let i = 0; i < maxIterations && maxAbs(n, st.r) > tol; i++) {
|
|
37169
|
+
rightMultWithVectorF(A3, n, st.p, st.Ap, CGF_BLOCK_AP);
|
|
37170
|
+
const pAp = innerProduct(n, st.p, st.Ap, CGF_BLOCK_P_AP);
|
|
37171
|
+
if (pAp === 0) break;
|
|
37172
|
+
const alpha = st.rr / pAp;
|
|
37173
|
+
vectorsScalarMult(n, st.p, alpha, st.alphap);
|
|
37174
|
+
vectorsAddition(n, x, st.alphap, x);
|
|
37175
|
+
if (i < maxIterations - 1 && cgfUpdate(n, alpha, st) === 1) return 1;
|
|
36577
37176
|
}
|
|
36578
|
-
|
|
37177
|
+
return 0;
|
|
36579
37178
|
}
|
|
36580
37179
|
|
|
36581
37180
|
// src/layout/neato/stress.ts
|
|
37181
|
+
var TOLERANCE_CG = 1e-3;
|
|
36582
37182
|
var DFLT_ITERATIONS = 200;
|
|
37183
|
+
var OPT_SMART_INIT = 4;
|
|
37184
|
+
function mdsModel(graph, nG) {
|
|
37185
|
+
if (graph[0].ewgts.length === 0) return null;
|
|
37186
|
+
const Dij = computeWeightedApspPacked(graph, nG);
|
|
37187
|
+
let shift = 0;
|
|
37188
|
+
for (let i = 0; i < nG; i++) {
|
|
37189
|
+
shift += i;
|
|
37190
|
+
for (let e = 1; e < graph[i].nedges; e++) {
|
|
37191
|
+
const j = graph[i].edges[e];
|
|
37192
|
+
if (j < i) continue;
|
|
37193
|
+
Dij[i * nG + j - shift] = graph[i].ewgts[e];
|
|
37194
|
+
}
|
|
37195
|
+
}
|
|
37196
|
+
return Dij;
|
|
37197
|
+
}
|
|
36583
37198
|
|
|
36584
37199
|
// src/layout/neato/sgd-dijkstra.ts
|
|
36585
|
-
var
|
|
37200
|
+
var FLT_MAX2 = 34028234663852886e22;
|
|
36586
37201
|
var left = (i) => 2 * i;
|
|
36587
37202
|
var right = (i) => 2 * i + 1;
|
|
36588
37203
|
var parent = (i) => Math.trunc(i / 2);
|
|
36589
|
-
var greaterPriority = (h, i, j,
|
|
37204
|
+
var greaterPriority = (h, i, j, dist5) => dist5[h.data[i]] < dist5[h.data[j]];
|
|
36590
37205
|
function exchange2(h, i, j) {
|
|
36591
37206
|
const t = h.data[i];
|
|
36592
37207
|
h.data[i] = h.data[j];
|
|
@@ -36594,19 +37209,19 @@ function exchange2(h, i, j) {
|
|
|
36594
37209
|
h.index[h.data[i]] = i;
|
|
36595
37210
|
h.index[h.data[j]] = j;
|
|
36596
37211
|
}
|
|
36597
|
-
function heapify(h, start,
|
|
37212
|
+
function heapify(h, start, dist5) {
|
|
36598
37213
|
let i = start;
|
|
36599
37214
|
for (; ; ) {
|
|
36600
37215
|
const l = left(i);
|
|
36601
37216
|
const r = right(i);
|
|
36602
|
-
let largest = l < h.heapSize && greaterPriority(h, l, i,
|
|
36603
|
-
if (r < h.heapSize && greaterPriority(h, r, largest,
|
|
37217
|
+
let largest = l < h.heapSize && greaterPriority(h, l, i, dist5) ? l : i;
|
|
37218
|
+
if (r < h.heapSize && greaterPriority(h, r, largest, dist5)) largest = r;
|
|
36604
37219
|
if (largest === i) break;
|
|
36605
37220
|
exchange2(h, largest, i);
|
|
36606
37221
|
i = largest;
|
|
36607
37222
|
}
|
|
36608
37223
|
}
|
|
36609
|
-
function initHeap(startVertex,
|
|
37224
|
+
function initHeap(startVertex, dist5, n) {
|
|
36610
37225
|
const h = {
|
|
36611
37226
|
data: new Int32Array(Math.max(n - 1, 0)),
|
|
36612
37227
|
heapSize: n - 1,
|
|
@@ -36618,23 +37233,23 @@ function initHeap(startVertex, dist4, n) {
|
|
|
36618
37233
|
h.data[count] = i;
|
|
36619
37234
|
h.index[i] = count++;
|
|
36620
37235
|
}
|
|
36621
|
-
for (let j = Math.trunc((n - 1) / 2); j >= 0; j--) heapify(h, j,
|
|
37236
|
+
for (let j = Math.trunc((n - 1) / 2); j >= 0; j--) heapify(h, j, dist5);
|
|
36622
37237
|
return h;
|
|
36623
37238
|
}
|
|
36624
|
-
function extractMax(h,
|
|
37239
|
+
function extractMax(h, dist5) {
|
|
36625
37240
|
if (h.heapSize === 0) return -1;
|
|
36626
37241
|
const max = h.data[0];
|
|
36627
37242
|
h.data[0] = h.data[h.heapSize - 1];
|
|
36628
37243
|
h.index[h.data[0]] = 0;
|
|
36629
37244
|
h.heapSize--;
|
|
36630
|
-
heapify(h, 0,
|
|
37245
|
+
heapify(h, 0, dist5);
|
|
36631
37246
|
return max;
|
|
36632
37247
|
}
|
|
36633
|
-
function increaseKey(h, v, newDist,
|
|
36634
|
-
if (
|
|
36635
|
-
|
|
37248
|
+
function increaseKey(h, v, newDist, dist5) {
|
|
37249
|
+
if (dist5[v] <= newDist) return;
|
|
37250
|
+
dist5[v] = newDist;
|
|
36636
37251
|
let i = h.index[v];
|
|
36637
|
-
while (i > 0 &&
|
|
37252
|
+
while (i > 0 && dist5[h.data[parent(i)]] > newDist) {
|
|
36638
37253
|
h.data[i] = h.data[parent(i)];
|
|
36639
37254
|
h.index[h.data[i]] = i;
|
|
36640
37255
|
i = parent(i);
|
|
@@ -36643,7 +37258,7 @@ function increaseKey(h, v, newDist, dist4) {
|
|
|
36643
37258
|
h.index[v] = i;
|
|
36644
37259
|
}
|
|
36645
37260
|
function dijkstraSgd(graph, source, terms) {
|
|
36646
|
-
const dists = new Float32Array(graph.n).fill(
|
|
37261
|
+
const dists = new Float32Array(graph.n).fill(FLT_MAX2);
|
|
36647
37262
|
dists[source] = 0;
|
|
36648
37263
|
for (let i = graph.sources[source]; i < graph.sources[source + 1]; i++) {
|
|
36649
37264
|
dists[graph.targets[i]] = graph.weights[i];
|
|
@@ -36652,7 +37267,7 @@ function dijkstraSgd(graph, source, terms) {
|
|
|
36652
37267
|
let offset = 0;
|
|
36653
37268
|
for (let closest = extractMax(h, dists); closest >= 0; closest = extractMax(h, dists)) {
|
|
36654
37269
|
const d = dists[closest];
|
|
36655
|
-
if (d ===
|
|
37270
|
+
if (d === FLT_MAX2) break;
|
|
36656
37271
|
if (graph.pinneds[closest] || closest < source) {
|
|
36657
37272
|
terms[offset++] = { i: source, j: closest, d, w: Math.fround(1 / Math.fround(d * d)) };
|
|
36658
37273
|
}
|
|
@@ -36671,7 +37286,7 @@ function lenattr(ep, g) {
|
|
|
36671
37286
|
const val2 = /^\s*[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?/.exec(s);
|
|
36672
37287
|
const len = val2 === null ? Number.NaN : parseFloat(val2[0]);
|
|
36673
37288
|
if (Number.isNaN(len) || len < 0 || len === 0) {
|
|
36674
|
-
|
|
37289
|
+
agwarningf(`bad edge len "${s}" in ${g.name} - setting to ${DEFAULT_EDGE_LEN.toFixed(2)}`);
|
|
36675
37290
|
return DEFAULT_EDGE_LEN;
|
|
36676
37291
|
}
|
|
36677
37292
|
return len;
|
|
@@ -36835,12 +37450,11 @@ function neatoMode(g) {
|
|
|
36835
37450
|
if (str === void 0 || str === "") return MODE_MAJOR;
|
|
36836
37451
|
const mode = modeByName().get(str);
|
|
36837
37452
|
if (mode !== void 0) return mode;
|
|
36838
|
-
|
|
37453
|
+
agwarningf(`Illegal value ${str} for attribute "mode" in graph ${g.root.name} - ignored`);
|
|
36839
37454
|
return MODE_MAJOR;
|
|
36840
37455
|
}
|
|
36841
37456
|
function checkMode(g, mode) {
|
|
36842
|
-
const value = g.root.attrs.get("mode") ||
|
|
36843
|
-
if (mode === MODE_HIER) unsupported("mode", value, "hierarchical stress majorization");
|
|
37457
|
+
const value = g.root.attrs.get("mode") || "ipsep";
|
|
36844
37458
|
if (mode === MODE_IPSEP && ipsepHasConstraints(g)) {
|
|
36845
37459
|
unsupported("mode", value, "constrained (ipsep) majorization");
|
|
36846
37460
|
}
|
|
@@ -37193,10 +37807,10 @@ function solve(a, b, c, n) {
|
|
|
37193
37807
|
}
|
|
37194
37808
|
|
|
37195
37809
|
// src/layout/neato/kk-paths.ts
|
|
37196
|
-
function newPathState(n,
|
|
37810
|
+
function newPathState(n, dist5, adj, initialDist2) {
|
|
37197
37811
|
return {
|
|
37198
37812
|
n,
|
|
37199
|
-
dist:
|
|
37813
|
+
dist: dist5,
|
|
37200
37814
|
adj,
|
|
37201
37815
|
initialDist: initialDist2,
|
|
37202
37816
|
heap: new Int32Array(n + 1),
|
|
@@ -37274,10 +37888,10 @@ function s1(s, src) {
|
|
|
37274
37888
|
function shortestPath2(s) {
|
|
37275
37889
|
for (let v = 0; v < s.n; v++) s1(s, v);
|
|
37276
37890
|
}
|
|
37277
|
-
function
|
|
37891
|
+
function mdsModel2(dist5, n, edges) {
|
|
37278
37892
|
for (const { tailSeq: i, headSeq: j, len } of edges) {
|
|
37279
37893
|
if (i === j) continue;
|
|
37280
|
-
for (const k of [i * n + j, j * n + i]) if (k <
|
|
37894
|
+
for (const k of [i * n + j, j * n + i]) if (k < dist5.length) dist5[k] = len;
|
|
37281
37895
|
}
|
|
37282
37896
|
}
|
|
37283
37897
|
|
|
@@ -37370,12 +37984,12 @@ function initialPositions2(g, st) {
|
|
|
37370
37984
|
}
|
|
37371
37985
|
}
|
|
37372
37986
|
function distvec(p0, p1, del) {
|
|
37373
|
-
let
|
|
37987
|
+
let dist5 = 0;
|
|
37374
37988
|
for (let k = 0; k < NDIM; k++) {
|
|
37375
37989
|
del[k] = p0[k] - p1[k];
|
|
37376
|
-
|
|
37990
|
+
dist5 += del[k] * del[k];
|
|
37377
37991
|
}
|
|
37378
|
-
return Math.sqrt(
|
|
37992
|
+
return Math.sqrt(dist5);
|
|
37379
37993
|
}
|
|
37380
37994
|
function springFactors(g) {
|
|
37381
37995
|
const byEnds = /* @__PURE__ */ new Map();
|
|
@@ -37392,9 +38006,9 @@ function fillRow(st, i, del) {
|
|
|
37392
38006
|
const vi = st.nodes[i];
|
|
37393
38007
|
for (let j = 0; j < st.n; j++) {
|
|
37394
38008
|
if (i === j) continue;
|
|
37395
|
-
const
|
|
38009
|
+
const dist5 = distvec(vi.info.pos, st.nodes[j].info.pos, del);
|
|
37396
38010
|
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] /
|
|
38011
|
+
const v = st.spring[i * st.n + j] * (del[k] - st.dist[i * st.n + j] * del[k] / dist5);
|
|
37398
38012
|
st.t[(i * st.n + j) * NDIM + k] = v;
|
|
37399
38013
|
st.sumT[i * NDIM + k] += v;
|
|
37400
38014
|
}
|
|
@@ -37423,9 +38037,9 @@ function updateArrays(st, i) {
|
|
|
37423
38037
|
for (let k = 0; k < NDIM; k++) st.sumT[i * NDIM + k] = 0;
|
|
37424
38038
|
for (let j = 0; j < n; j++) {
|
|
37425
38039
|
if (i === j) continue;
|
|
37426
|
-
const
|
|
38040
|
+
const dist5 = distvec(vi.info.pos, st.nodes[j].info.pos, del);
|
|
37427
38041
|
for (let k = 0; k < NDIM; k++) {
|
|
37428
|
-
const tij = st.spring[i * n + j] * (del[k] - st.dist[i * n + j] * del[k] /
|
|
38042
|
+
const tij = st.spring[i * n + j] * (del[k] - st.dist[i * n + j] * del[k] / dist5);
|
|
37429
38043
|
st.t[(i * n + j) * NDIM + k] = tij;
|
|
37430
38044
|
st.sumT[i * NDIM + k] += tij;
|
|
37431
38045
|
const old = st.t[(j * n + i) * NDIM + k];
|
|
@@ -37492,7 +38106,7 @@ function moveNode(st, m) {
|
|
|
37492
38106
|
function solveModel(g, st) {
|
|
37493
38107
|
for (let m = chooseNode(st); m >= 0; m = chooseNode(st)) moveNode(st, m);
|
|
37494
38108
|
if (st.move === st.maxIter) {
|
|
37495
|
-
|
|
38109
|
+
agwarningf(`Max. iterations (${st.maxIter}) reached on graph ${g.name}`);
|
|
37496
38110
|
}
|
|
37497
38111
|
}
|
|
37498
38112
|
function mdsEdges(g, nodes, lens) {
|
|
@@ -37505,84 +38119,852 @@ function kkNeato(g, nG, model) {
|
|
|
37505
38119
|
if (nG < 2 || maxIter < 0) return;
|
|
37506
38120
|
const { st, adj, ini, lens } = scanGraphMode(g, maxIter);
|
|
37507
38121
|
shortestPath2(newPathState(st.n, st.dist, adj, ini));
|
|
37508
|
-
if (model === MODEL_MDS2)
|
|
38122
|
+
if (model === MODEL_MDS2) mdsModel2(st.dist, st.n, mdsEdges(g, st.nodes, lens));
|
|
37509
38123
|
initialPositions2(g, st);
|
|
37510
38124
|
diffeqModel(g, st);
|
|
37511
38125
|
solveModel(g, st);
|
|
37512
38126
|
}
|
|
37513
38127
|
|
|
37514
|
-
// src/layout/neato/
|
|
37515
|
-
var
|
|
37516
|
-
|
|
37517
|
-
|
|
37518
|
-
|
|
37519
|
-
|
|
37520
|
-
for (
|
|
38128
|
+
// src/layout/neato/make-graph-data.ts
|
|
38129
|
+
var MODE_IPSEP2 = 3;
|
|
38130
|
+
var EDIST_IN = 1;
|
|
38131
|
+
var EDIST_OUT = -1;
|
|
38132
|
+
var EDIST_NONE = 0;
|
|
38133
|
+
function graphHasLen(g) {
|
|
38134
|
+
for (const e of g.edges) {
|
|
38135
|
+
if (e.attrs.has("len")) return true;
|
|
38136
|
+
}
|
|
38137
|
+
return false;
|
|
37521
38138
|
}
|
|
37522
|
-
|
|
37523
|
-
|
|
37524
|
-
|
|
37525
|
-
|
|
37526
|
-
|
|
38139
|
+
var edistsOf = (v) => v.edists;
|
|
38140
|
+
function reverseBackEdge(graph, i, e, mode) {
|
|
38141
|
+
const node = graph[i];
|
|
38142
|
+
const j = node.edges[e];
|
|
38143
|
+
edistsOf(node)[e] = mode === MODE_IPSEP2 ? EDIST_OUT : EDIST_IN;
|
|
38144
|
+
const target = graph[j];
|
|
38145
|
+
let f = 1;
|
|
38146
|
+
while (f < target.nedges && target.edges[f] !== i) f++;
|
|
38147
|
+
if (f >= target.nedges) throw new Error(`neato: edge ${i}-${j} has no reverse entry`);
|
|
38148
|
+
edistsOf(target)[f] = EDIST_OUT;
|
|
38149
|
+
}
|
|
38150
|
+
function dfsCycle(graph, start, st) {
|
|
38151
|
+
const { mode, mark, onstack } = st;
|
|
38152
|
+
const stack = [{ i: start, e: 1 }];
|
|
38153
|
+
mark[start] = 1;
|
|
38154
|
+
onstack[start] = 1;
|
|
38155
|
+
for (let frame = stack.at(-1); frame !== void 0; frame = stack.at(-1)) {
|
|
38156
|
+
const { i } = frame;
|
|
38157
|
+
const node = graph[i];
|
|
38158
|
+
if (frame.e >= node.nedges) {
|
|
38159
|
+
onstack[i] = 0;
|
|
38160
|
+
stack.pop();
|
|
38161
|
+
continue;
|
|
38162
|
+
}
|
|
38163
|
+
const e = frame.e++;
|
|
38164
|
+
if (edistsOf(node)[e] === EDIST_IN) continue;
|
|
38165
|
+
const j = node.edges[e];
|
|
38166
|
+
if (onstack[j]) {
|
|
38167
|
+
reverseBackEdge(graph, i, e, mode);
|
|
38168
|
+
} else if (!mark[j]) {
|
|
38169
|
+
mark[j] = 1;
|
|
38170
|
+
onstack[j] = 1;
|
|
38171
|
+
stack.push({ i: j, e: 1 });
|
|
38172
|
+
}
|
|
38173
|
+
}
|
|
37527
38174
|
}
|
|
37528
|
-
function
|
|
38175
|
+
function acyclic2(graph, nv, mode) {
|
|
38176
|
+
const st = { mode, mark: new Uint8Array(nv), onstack: new Uint8Array(nv) };
|
|
38177
|
+
for (let i = 0; i < nv; i++) {
|
|
38178
|
+
if (st.mark[i]) continue;
|
|
38179
|
+
dfsCycle(graph, i, st);
|
|
38180
|
+
}
|
|
38181
|
+
}
|
|
38182
|
+
function edgeDist2(dir, np, head) {
|
|
38183
|
+
if (dir !== void 0 && dir.startsWith("none")) return EDIST_NONE;
|
|
38184
|
+
return np === head ? EDIST_IN : EDIST_OUT;
|
|
38185
|
+
}
|
|
38186
|
+
function addNeighbours(g, np, entry, o) {
|
|
38187
|
+
const seen2 = /* @__PURE__ */ new Map();
|
|
38188
|
+
for (const ep of [...np.outEdges(g), ...np.inEdges(g)]) {
|
|
38189
|
+
if (ep.head === ep.tail) continue;
|
|
38190
|
+
const vp = ep.tail === np ? ep.head : ep.tail;
|
|
38191
|
+
const vid = vp.info.id;
|
|
38192
|
+
const dist5 = o.haveLen ? lateDouble(ep.attrs.get("len"), 1, 0) : 1;
|
|
38193
|
+
const idx = seen2.get(vid);
|
|
38194
|
+
if (idx !== void 0) {
|
|
38195
|
+
if (o.haveLen) entry.ewgts[idx] = Math.max(entry.ewgts[idx], dist5);
|
|
38196
|
+
continue;
|
|
38197
|
+
}
|
|
38198
|
+
seen2.set(vid, entry.nedges);
|
|
38199
|
+
entry.edges.push(vid);
|
|
38200
|
+
if (o.haveLen || o.haveDir) entry.ewgts.push(dist5);
|
|
38201
|
+
if (o.haveDir) edistsOf(entry).push(edgeDist2(ep.attrs.get("dir"), np, ep.head));
|
|
38202
|
+
entry.nedges++;
|
|
38203
|
+
}
|
|
38204
|
+
}
|
|
38205
|
+
function makeGraphDataC(g, nodeList, haveLen, haveDir, mode = -1) {
|
|
38206
|
+
const vtx = nodeList.map((_, i) => ({
|
|
38207
|
+
nedges: 1,
|
|
38208
|
+
edges: [i],
|
|
38209
|
+
ewgts: haveLen || haveDir ? [0] : [],
|
|
38210
|
+
...haveDir ? { edists: [0] } : {}
|
|
38211
|
+
}));
|
|
38212
|
+
for (const np of nodeList) addNeighbours(g, np, vtx[np.info.id], { haveLen, haveDir });
|
|
38213
|
+
if (haveDir) acyclic2(vtx, nodeList.length, mode);
|
|
38214
|
+
return vtx;
|
|
38215
|
+
}
|
|
38216
|
+
|
|
38217
|
+
// src/layout/neato/kkutils.ts
|
|
38218
|
+
function compareKeys(a, b) {
|
|
38219
|
+
if (a < b) return -1;
|
|
38220
|
+
if (a > b) return 1;
|
|
38221
|
+
return 0;
|
|
38222
|
+
}
|
|
38223
|
+
function gvSortByPlace(place, ordering, first, count) {
|
|
38224
|
+
const slice = Array.from(ordering.subarray(first, first + count));
|
|
38225
|
+
gvQsort(slice, (x, y) => compareKeys(place[x], place[y]));
|
|
38226
|
+
for (let i = 0; i < count; i++) ordering[first + i] = slice[i];
|
|
38227
|
+
}
|
|
38228
|
+
function quicksortPlace(place, ordering, size) {
|
|
38229
|
+
gvSortByPlace(place, ordering, 0, size);
|
|
38230
|
+
}
|
|
38231
|
+
function quicksortPlacef(place, ordering, first, last) {
|
|
38232
|
+
if (first < last) {
|
|
38233
|
+
gvSortByPlace(place, ordering, first, last - first + 1);
|
|
38234
|
+
}
|
|
38235
|
+
}
|
|
38236
|
+
function computeApspDijkstra(graph, n) {
|
|
38237
|
+
const dij = [];
|
|
38238
|
+
for (let i = 0; i < n; i++) dij.push(new Int32Array(n));
|
|
38239
|
+
for (let i = 0; i < n; i++) ngdijkstra(i, graph, n, dij[i]);
|
|
38240
|
+
return dij;
|
|
38241
|
+
}
|
|
38242
|
+
function computeApspSimple(graph, n) {
|
|
38243
|
+
const dij = [];
|
|
38244
|
+
for (let i = 0; i < n; i++) dij.push(new Int32Array(n));
|
|
38245
|
+
for (let i = 0; i < n; i++) bfs(i, graph, n, dij[i]);
|
|
38246
|
+
return dij;
|
|
38247
|
+
}
|
|
38248
|
+
function computeApsp(graph, n) {
|
|
38249
|
+
return graph[0].ewgts.length > 0 ? computeApspDijkstra(graph, n) : computeApspSimple(graph, n);
|
|
38250
|
+
}
|
|
38251
|
+
|
|
38252
|
+
// src/layout/neato/quad-prog-solve.ts
|
|
38253
|
+
var fr2 = Math.fround;
|
|
38254
|
+
var TOLERANCE = fr2(0.01);
|
|
38255
|
+
var BOUND = 1e9;
|
|
38256
|
+
var BLOCK_EPSILON = 1e-9;
|
|
38257
|
+
var NO_SPLIT = -1;
|
|
38258
|
+
var BITS = new DataView(new ArrayBuffer(8));
|
|
38259
|
+
function oddNeighbour(s, awayFromZero) {
|
|
38260
|
+
BITS.setFloat64(0, s);
|
|
38261
|
+
const hi = BITS.getUint32(0);
|
|
38262
|
+
const lo = BITS.getUint32(4);
|
|
38263
|
+
if (awayFromZero) {
|
|
38264
|
+
BITS.setUint32(4, lo + 1);
|
|
38265
|
+
} else if (lo === 0) {
|
|
38266
|
+
BITS.setUint32(0, hi - 1);
|
|
38267
|
+
BITS.setUint32(4, 4294967295);
|
|
38268
|
+
} else {
|
|
38269
|
+
BITS.setUint32(4, lo - 1);
|
|
38270
|
+
}
|
|
38271
|
+
return BITS.getFloat64(0);
|
|
38272
|
+
}
|
|
38273
|
+
function fmaf(a, b, c) {
|
|
38274
|
+
const p = a * b;
|
|
38275
|
+
const s = p + c;
|
|
38276
|
+
const bv = s - p;
|
|
38277
|
+
const err = p - (s - bv) + (c - bv);
|
|
38278
|
+
if (err === 0 || !Number.isFinite(s)) return fr2(s);
|
|
38279
|
+
BITS.setFloat64(0, s);
|
|
38280
|
+
if ((BITS.getUint32(4) & 1) !== 0) return fr2(s);
|
|
38281
|
+
return fr2(oddNeighbour(s, err > 0 === s > 0));
|
|
38282
|
+
}
|
|
38283
|
+
function blockPlaceNumerator(blockDeg, desPlaceBlock, negLapTimesDesired, toBlockConnectivity, curPlace) {
|
|
38284
|
+
const t = fmaf(blockDeg, desPlaceBlock, negLapTimesDesired);
|
|
38285
|
+
return fmaf(toBlockConnectivity, curPlace, t);
|
|
38286
|
+
}
|
|
38287
|
+
function equals(a, b) {
|
|
38288
|
+
return Math.abs(fr2(a - b)) < TOLERANCE;
|
|
38289
|
+
}
|
|
38290
|
+
function fminf(a, b) {
|
|
38291
|
+
if (Number.isNaN(a)) return b;
|
|
38292
|
+
if (Number.isNaN(b)) return a;
|
|
38293
|
+
return a < b ? a : b;
|
|
38294
|
+
}
|
|
38295
|
+
function fmaxf(a, b) {
|
|
38296
|
+
if (Number.isNaN(a)) return b;
|
|
38297
|
+
if (Number.isNaN(b)) return a;
|
|
38298
|
+
return a > b ? a : b;
|
|
38299
|
+
}
|
|
38300
|
+
function unpackMatrix(packedMat, n) {
|
|
38301
|
+
const flat = new Float32Array(n * n);
|
|
38302
|
+
const mat = new Array(n);
|
|
38303
|
+
for (let i = 0; i < n; i++) mat[i] = flat.subarray(i * n, (i + 1) * n);
|
|
38304
|
+
for (let i = 0, k = 0; i < n; i++) {
|
|
38305
|
+
for (let j = i; j < n; j++, k++) {
|
|
38306
|
+
mat[j][i] = mat[i][j] = packedMat[k];
|
|
38307
|
+
}
|
|
38308
|
+
}
|
|
38309
|
+
return mat;
|
|
38310
|
+
}
|
|
38311
|
+
function ensureMonotonicOrderingWithGaps(place, n, ordering, levels, numLevels, levelsGap) {
|
|
38312
|
+
let lowerBound = fr2(-1e9);
|
|
38313
|
+
let level = -1;
|
|
38314
|
+
let maxInLevel = 0;
|
|
38315
|
+
for (let i = 0; i < n; i++) {
|
|
38316
|
+
if (i >= maxInLevel) {
|
|
38317
|
+
level++;
|
|
38318
|
+
maxInLevel = level === numLevels ? n : levels[level];
|
|
38319
|
+
lowerBound = i > 0 ? fr2(place[ordering[i - 1]] + levelsGap) : fr2(-1e9);
|
|
38320
|
+
quicksortPlacef(place, ordering, i, maxInLevel - 1);
|
|
38321
|
+
}
|
|
38322
|
+
const node = ordering[i];
|
|
38323
|
+
if (place[node] < lowerBound) place[node] = lowerBound;
|
|
38324
|
+
}
|
|
38325
|
+
}
|
|
38326
|
+
function computeNodeLevels(e) {
|
|
38327
|
+
const lev = new Int32Array(e.n);
|
|
38328
|
+
let level = -1;
|
|
38329
|
+
let maxInLevel = 0;
|
|
38330
|
+
for (let i = 0; i < e.n; i++) {
|
|
38331
|
+
if (i >= maxInLevel) {
|
|
38332
|
+
level++;
|
|
38333
|
+
maxInLevel = level === e.numLevels ? e.n : e.levels[level];
|
|
38334
|
+
}
|
|
38335
|
+
lev[e.ordering[i]] = level;
|
|
38336
|
+
}
|
|
38337
|
+
return lev;
|
|
38338
|
+
}
|
|
38339
|
+
function growBlock(c, left2, curPlace) {
|
|
38340
|
+
const { place, lev, levelsGap, e } = c;
|
|
38341
|
+
const gap = e.fArray4;
|
|
38342
|
+
let targetPlace = curPlace;
|
|
38343
|
+
gap[e.ordering[left2]] = 0;
|
|
38344
|
+
let right2;
|
|
38345
|
+
for (right2 = left2 + 1; right2 < e.n; right2++) {
|
|
38346
|
+
if (lev[right2] > lev[right2 - 1]) {
|
|
38347
|
+
targetPlace = fr2(targetPlace + levelsGap);
|
|
38348
|
+
}
|
|
38349
|
+
const node = e.ordering[right2];
|
|
38350
|
+
if (Math.abs(fr2(place[node] - targetPlace)) > BLOCK_EPSILON) break;
|
|
38351
|
+
gap[node] = fr2(place[node] - curPlace);
|
|
38352
|
+
}
|
|
38353
|
+
return right2;
|
|
38354
|
+
}
|
|
38355
|
+
function computeDesiredPlaces(c, left2, right2) {
|
|
38356
|
+
const { e, place, b } = c;
|
|
38357
|
+
for (let i = left2; i < right2; i++) {
|
|
38358
|
+
const node = e.ordering[i];
|
|
38359
|
+
let newPlaceI = -b[node];
|
|
38360
|
+
const lapNode = e.A[node];
|
|
38361
|
+
for (let j = 0; j < e.n; j++) {
|
|
38362
|
+
if (j === node) continue;
|
|
38363
|
+
newPlaceI = fmaf(lapNode[j], place[j], newPlaceI);
|
|
38364
|
+
}
|
|
38365
|
+
e.fArray1[node] = fr2(fr2(newPlaceI / -lapNode[node]) - e.fArray4[node]);
|
|
38366
|
+
}
|
|
38367
|
+
}
|
|
38368
|
+
function collectWhere(c, from, to, test) {
|
|
38369
|
+
for (let j = from; j < to; j++) {
|
|
38370
|
+
const node = c.e.ordering[j];
|
|
38371
|
+
if (test(c.e.fArray1[node])) c.block.push(node);
|
|
38372
|
+
}
|
|
38373
|
+
}
|
|
38374
|
+
function orderBlockByLevels(c, left2, right2, curPlace) {
|
|
38375
|
+
const { e } = c;
|
|
38376
|
+
c.block.length = 0;
|
|
38377
|
+
let firstNextLevel = 0;
|
|
38378
|
+
for (let i = left2; i < right2; i = firstNextLevel) {
|
|
38379
|
+
const level = c.lev[e.ordering[i]];
|
|
38380
|
+
firstNextLevel = level === e.numLevels ? right2 : Math.min(right2, e.levels[level]);
|
|
38381
|
+
collectWhere(c, i, firstNextLevel, (d) => d < curPlace);
|
|
38382
|
+
collectWhere(c, i, firstNextLevel, (d) => d === curPlace);
|
|
38383
|
+
collectWhere(c, i, firstNextLevel, (d) => d > curPlace);
|
|
38384
|
+
}
|
|
38385
|
+
}
|
|
38386
|
+
function computePrefixDesiredPlaces(c, curPlace) {
|
|
38387
|
+
const { e, block } = c;
|
|
38388
|
+
let desPlaceBlock = 0;
|
|
38389
|
+
let blockDeg = 0;
|
|
38390
|
+
for (let i = 0; i < block.length; i++) {
|
|
38391
|
+
const node = block[i];
|
|
38392
|
+
let toBlockConnectivity = 0;
|
|
38393
|
+
const lapNode = e.A[node];
|
|
38394
|
+
for (let j = 0; j < i; j++) {
|
|
38395
|
+
toBlockConnectivity = fr2(toBlockConnectivity - lapNode[block[j]]);
|
|
38396
|
+
}
|
|
38397
|
+
toBlockConnectivity = fr2(toBlockConnectivity * 2);
|
|
38398
|
+
const num2 = blockPlaceNumerator(
|
|
38399
|
+
blockDeg,
|
|
38400
|
+
desPlaceBlock,
|
|
38401
|
+
fr2(-lapNode[node] * e.fArray1[node]),
|
|
38402
|
+
toBlockConnectivity,
|
|
38403
|
+
curPlace
|
|
38404
|
+
);
|
|
38405
|
+
desPlaceBlock = fr2(num2 / fr2(fr2(blockDeg - lapNode[node]) + toBlockConnectivity));
|
|
38406
|
+
e.fArray2[i] = desPlaceBlock;
|
|
38407
|
+
blockDeg = fr2(blockDeg + fr2(toBlockConnectivity - lapNode[node]));
|
|
38408
|
+
}
|
|
38409
|
+
if (e.n >= 0 && block.length === e.n) {
|
|
38410
|
+
e.fArray2[e.n - 1] = curPlace;
|
|
38411
|
+
}
|
|
38412
|
+
}
|
|
38413
|
+
function computeSuffixDesiredPlaces(c, curPlace) {
|
|
38414
|
+
const { e, block } = c;
|
|
38415
|
+
let desPlaceBlock = 0;
|
|
38416
|
+
let blockDeg = 0;
|
|
38417
|
+
for (let i = block.length - 1; i >= 0; i--) {
|
|
38418
|
+
const node = block[i];
|
|
38419
|
+
let toBlockConnectivity = 0;
|
|
38420
|
+
const lapNode = e.A[node];
|
|
38421
|
+
for (let j = i + 1; j < block.length; j++) {
|
|
38422
|
+
toBlockConnectivity = fr2(toBlockConnectivity - lapNode[block[j]]);
|
|
38423
|
+
}
|
|
38424
|
+
toBlockConnectivity = fr2(toBlockConnectivity * 2);
|
|
38425
|
+
const num2 = blockPlaceNumerator(
|
|
38426
|
+
blockDeg,
|
|
38427
|
+
desPlaceBlock,
|
|
38428
|
+
fr2(-lapNode[node] * e.fArray1[node]),
|
|
38429
|
+
toBlockConnectivity,
|
|
38430
|
+
curPlace
|
|
38431
|
+
);
|
|
38432
|
+
desPlaceBlock = fr2(num2 / fr2(fr2(blockDeg - lapNode[node]) + toBlockConnectivity));
|
|
38433
|
+
e.fArray3[i] = desPlaceBlock;
|
|
38434
|
+
blockDeg = fr2(blockDeg + fr2(toBlockConnectivity - lapNode[node]));
|
|
38435
|
+
}
|
|
38436
|
+
if (e.n >= 0 && block.length === e.n) {
|
|
38437
|
+
e.fArray3[0] = curPlace;
|
|
38438
|
+
}
|
|
38439
|
+
}
|
|
38440
|
+
var LIMITED = new Float64Array(2);
|
|
38441
|
+
function limitMoves(prefix, suffix, curPlace) {
|
|
38442
|
+
if (suffix < prefix) {
|
|
38443
|
+
if (suffix < curPlace) {
|
|
38444
|
+
if (prefix > curPlace) prefix = curPlace;
|
|
38445
|
+
suffix = prefix;
|
|
38446
|
+
} else if (prefix > curPlace) {
|
|
38447
|
+
prefix = suffix;
|
|
38448
|
+
}
|
|
38449
|
+
}
|
|
38450
|
+
LIMITED[0] = prefix;
|
|
38451
|
+
LIMITED[1] = suffix;
|
|
38452
|
+
}
|
|
38453
|
+
function findBestSplit(c, curPlace) {
|
|
38454
|
+
const { e, block } = c;
|
|
38455
|
+
let bestI = NO_SPLIT;
|
|
38456
|
+
let maxMovement = 0;
|
|
38457
|
+
for (let i = 0; i < block.length; i++) {
|
|
38458
|
+
const suffixDesPlace = e.fArray3[i];
|
|
38459
|
+
const prefixDesPlace = i > 0 ? e.fArray2[i - 1] : suffixDesPlace;
|
|
38460
|
+
limitMoves(prefixDesPlace, suffixDesPlace, curPlace);
|
|
38461
|
+
const movement = (block.length - i) * Math.abs(fr2(LIMITED[1] - curPlace)) + i * Math.abs(fr2(LIMITED[0] - curPlace));
|
|
38462
|
+
if (movement > maxMovement) {
|
|
38463
|
+
maxMovement = movement;
|
|
38464
|
+
bestI = i;
|
|
38465
|
+
}
|
|
38466
|
+
}
|
|
38467
|
+
return bestI;
|
|
38468
|
+
}
|
|
38469
|
+
function computeUpperBound(c, right2) {
|
|
38470
|
+
const { e, place, lev, levelsGap, block } = c;
|
|
38471
|
+
if (right2 >= e.n) return BOUND;
|
|
38472
|
+
const lastGap = e.fArray4[block[block.length - 1]];
|
|
38473
|
+
const nextPlace = place[e.ordering[right2]];
|
|
38474
|
+
if (lev[e.ordering[right2]] > lev[e.ordering[right2 - 1]]) {
|
|
38475
|
+
return fr2(fr2(nextPlace - levelsGap) - lastGap);
|
|
38476
|
+
}
|
|
38477
|
+
return fr2(nextPlace - lastGap);
|
|
38478
|
+
}
|
|
38479
|
+
function nextLowerBound(c, right2) {
|
|
38480
|
+
const { e, place, lev, levelsGap, block } = c;
|
|
38481
|
+
const last = place[block[block.length - 1]];
|
|
38482
|
+
if (right2 < e.n && lev[e.ordering[right2]] > lev[e.ordering[right2 - 1]]) {
|
|
38483
|
+
return fr2(last + levelsGap);
|
|
38484
|
+
}
|
|
38485
|
+
return last;
|
|
38486
|
+
}
|
|
38487
|
+
function moveSplitBlock(c, bestI, left2, right2, curPlace) {
|
|
38488
|
+
const { e, place, block } = c;
|
|
38489
|
+
let suffixDesPlace = e.fArray3[bestI];
|
|
38490
|
+
let prefixDesPlace = bestI > 0 ? e.fArray2[bestI - 1] : suffixDesPlace;
|
|
38491
|
+
suffixDesPlace = fminf(suffixDesPlace, computeUpperBound(c, right2));
|
|
38492
|
+
prefixDesPlace = fmaxf(prefixDesPlace, c.lowerBound);
|
|
38493
|
+
limitMoves(prefixDesPlace, suffixDesPlace, curPlace);
|
|
38494
|
+
prefixDesPlace = LIMITED[0];
|
|
38495
|
+
suffixDesPlace = LIMITED[1];
|
|
38496
|
+
for (let i = 0; i < bestI; i++) {
|
|
38497
|
+
place[block[i]] = fr2(prefixDesPlace + e.fArray4[block[i]]);
|
|
38498
|
+
}
|
|
38499
|
+
for (let i = bestI; i < block.length; i++) {
|
|
38500
|
+
place[block[i]] = fr2(suffixDesPlace + e.fArray4[block[i]]);
|
|
38501
|
+
}
|
|
38502
|
+
c.lowerBound = nextLowerBound(c, right2);
|
|
38503
|
+
for (let i = left2; i < right2; i++) e.ordering[i] = block[i - left2];
|
|
38504
|
+
c.converged = c.converged && equals(prefixDesPlace, curPlace) && equals(suffixDesPlace, curPlace);
|
|
38505
|
+
}
|
|
38506
|
+
function processBlock(c, left2) {
|
|
38507
|
+
const curPlace = c.place[c.e.ordering[left2]];
|
|
38508
|
+
const right2 = growBlock(c, left2, curPlace);
|
|
38509
|
+
computeDesiredPlaces(c, left2, right2);
|
|
38510
|
+
orderBlockByLevels(c, left2, right2, curPlace);
|
|
38511
|
+
computePrefixDesiredPlaces(c, curPlace);
|
|
38512
|
+
computeSuffixDesiredPlaces(c, curPlace);
|
|
38513
|
+
const bestI = findBestSplit(c, curPlace);
|
|
38514
|
+
if (bestI !== NO_SPLIT) {
|
|
38515
|
+
moveSplitBlock(c, bestI, left2, right2, curPlace);
|
|
38516
|
+
} else {
|
|
38517
|
+
c.lowerBound = nextLowerBound(c, right2);
|
|
38518
|
+
}
|
|
38519
|
+
return right2;
|
|
38520
|
+
}
|
|
38521
|
+
function constrainedMajorizationNewWithGaps(e, b, coords, curAxis, maxIterations, levelsGap) {
|
|
38522
|
+
const place = coords[curAxis];
|
|
38523
|
+
if (maxIterations <= 0) return;
|
|
38524
|
+
const gap = fr2(levelsGap);
|
|
38525
|
+
ensureMonotonicOrderingWithGaps(place, e.n, e.ordering, e.levels, e.numLevels, gap);
|
|
38526
|
+
const c = {
|
|
38527
|
+
e,
|
|
38528
|
+
place,
|
|
38529
|
+
b,
|
|
38530
|
+
lev: computeNodeLevels(e),
|
|
38531
|
+
levelsGap: gap,
|
|
38532
|
+
block: [],
|
|
38533
|
+
lowerBound: fr2(-BOUND),
|
|
38534
|
+
converged: false
|
|
38535
|
+
};
|
|
38536
|
+
for (let counter = 0; counter < maxIterations && !c.converged; counter++) {
|
|
38537
|
+
c.converged = true;
|
|
38538
|
+
c.lowerBound = fr2(-BOUND);
|
|
38539
|
+
for (let left2 = 0, right2; left2 < e.n; left2 = right2) {
|
|
38540
|
+
right2 = processBlock(c, left2);
|
|
38541
|
+
}
|
|
38542
|
+
orthog1f(e.n, place);
|
|
38543
|
+
}
|
|
38544
|
+
}
|
|
38545
|
+
function initConstrainedMajorization(packedMat, n, ordering, levels, numLevels) {
|
|
38546
|
+
return {
|
|
38547
|
+
A: unpackMatrix(packedMat, n),
|
|
38548
|
+
n,
|
|
38549
|
+
fArray1: new Float32Array(n),
|
|
38550
|
+
fArray2: new Float32Array(n),
|
|
38551
|
+
fArray3: new Float32Array(n),
|
|
38552
|
+
fArray4: new Float32Array(n),
|
|
38553
|
+
ordering,
|
|
38554
|
+
levels,
|
|
38555
|
+
numLevels
|
|
38556
|
+
};
|
|
38557
|
+
}
|
|
38558
|
+
|
|
38559
|
+
// src/layout/neato/conjgrad-mkernel.ts
|
|
38560
|
+
var fr3 = Math.fround;
|
|
38561
|
+
var RIGHT_MULT_BLOCK = 16;
|
|
38562
|
+
var ZERO_LENGTH_MESSAGE = "conjugate_gradient: unexpected length 0 vector\n";
|
|
38563
|
+
function rightMultWithVectorFFFused(m, n, vector, result) {
|
|
37529
38564
|
for (let i = 0; i < n; i++) result[i] = 0;
|
|
37530
38565
|
let index = 0;
|
|
37531
38566
|
for (let i = 0; i < n; i++) {
|
|
37532
38567
|
const vi = vector[i];
|
|
37533
|
-
let res =
|
|
38568
|
+
let res = fmaf(m[index++], vi, 0);
|
|
38569
|
+
const len = n - i - 1;
|
|
38570
|
+
const blockEnd = i + 1 + (len - len % RIGHT_MULT_BLOCK);
|
|
37534
38571
|
for (let j = i + 1; j < n; j++, index++) {
|
|
37535
|
-
|
|
37536
|
-
|
|
38572
|
+
const mij = m[index];
|
|
38573
|
+
res = j < blockEnd ? fr3(res + fr3(mij * vector[j])) : fmaf(mij, vector[j], res);
|
|
38574
|
+
result[j] = fmaf(mij, vi, result[j]);
|
|
37537
38575
|
}
|
|
37538
38576
|
result[i] = result[i] + res;
|
|
37539
38577
|
}
|
|
37540
38578
|
}
|
|
37541
|
-
function
|
|
37542
|
-
for (let i = 0; i < n; i++)
|
|
38579
|
+
function vectorsMultAdditionFused(n, v1, alpha, v2) {
|
|
38580
|
+
for (let i = 0; i < n; i++) v1[i] = fmaf(alpha, v2[i], v1[i]);
|
|
37543
38581
|
}
|
|
37544
|
-
|
|
37545
|
-
|
|
37546
|
-
|
|
38582
|
+
var CgStep = { CONTINUE: 0, STOP: 1, ERROR: 2 };
|
|
38583
|
+
function initialState(A3, x, b, n) {
|
|
38584
|
+
const Ax = new Float32Array(n);
|
|
38585
|
+
const st = { n, r: new Float32Array(n), p: new Float32Array(n), Ap: new Float32Array(n), rR: 0 };
|
|
38586
|
+
orthog1f(n, x);
|
|
38587
|
+
orthog1f(n, b);
|
|
38588
|
+
rightMultWithVectorFFFused(A3, n, x, Ax);
|
|
38589
|
+
orthog1f(n, Ax);
|
|
38590
|
+
vectorsSubtractionF(n, b, Ax, st.r);
|
|
38591
|
+
copyVectorF(n, st.r, st.p);
|
|
38592
|
+
st.rR = vectorsInnerProductF(n, st.r, st.r);
|
|
38593
|
+
return st;
|
|
37547
38594
|
}
|
|
37548
|
-
function
|
|
37549
|
-
|
|
37550
|
-
|
|
37551
|
-
|
|
38595
|
+
function cgIteration(A3, x, st, last) {
|
|
38596
|
+
const { n, r, p, Ap } = st;
|
|
38597
|
+
orthog1f(n, p);
|
|
38598
|
+
orthog1f(n, x);
|
|
38599
|
+
orthog1f(n, r);
|
|
38600
|
+
rightMultWithVectorFFFused(A3, n, p, Ap);
|
|
38601
|
+
orthog1f(n, Ap);
|
|
38602
|
+
const pAp = vectorsInnerProductF(n, p, Ap);
|
|
38603
|
+
if (pAp === 0) return CgStep.STOP;
|
|
38604
|
+
const alpha = st.rR / pAp;
|
|
38605
|
+
vectorsMultAdditionFused(n, x, fr3(alpha), p);
|
|
38606
|
+
if (last) return CgStep.CONTINUE;
|
|
38607
|
+
vectorsMultAdditionFused(n, r, fr3(-alpha), Ap);
|
|
38608
|
+
const rRNew = vectorsInnerProductF(n, r, r);
|
|
38609
|
+
if (st.rR === 0) {
|
|
38610
|
+
agerrorf(ZERO_LENGTH_MESSAGE);
|
|
38611
|
+
return CgStep.ERROR;
|
|
38612
|
+
}
|
|
38613
|
+
const beta = fr3(rRNew / st.rR);
|
|
38614
|
+
st.rR = rRNew;
|
|
38615
|
+
for (let j = 0; j < n; j++) p[j] = fmaf(beta, p[j], r[j]);
|
|
38616
|
+
return CgStep.CONTINUE;
|
|
38617
|
+
}
|
|
38618
|
+
function conjugateGradientMkernelFused(A3, x, b, n, o) {
|
|
38619
|
+
const st = initialState(A3, x, b, n);
|
|
38620
|
+
for (let i = 0; i < o.maxIterations && maxAbsF(n, st.r) > o.tol; i++) {
|
|
38621
|
+
const step = cgIteration(A3, x, st, i >= o.maxIterations - 1);
|
|
38622
|
+
if (step === CgStep.STOP) break;
|
|
38623
|
+
if (step === CgStep.ERROR) return 1;
|
|
38624
|
+
}
|
|
38625
|
+
return 0;
|
|
37552
38626
|
}
|
|
37553
|
-
|
|
37554
|
-
|
|
38627
|
+
|
|
38628
|
+
// src/layout/neato/opt-arrangement.ts
|
|
38629
|
+
var HIERARCHY_CG_TOL = 1e-3;
|
|
38630
|
+
function constructB(graph, n, b) {
|
|
38631
|
+
for (let i = 0; i < n; i++) {
|
|
38632
|
+
if (graph[0].edists == null) continue;
|
|
38633
|
+
let bI = 0;
|
|
38634
|
+
const node = graph[i];
|
|
38635
|
+
for (let j = 1; j < node.nedges; j++) {
|
|
38636
|
+
bI += Math.fround(Math.fround(node.ewgts[j]) * node.edists[j]);
|
|
38637
|
+
}
|
|
38638
|
+
b[i] = bI;
|
|
38639
|
+
}
|
|
37555
38640
|
}
|
|
37556
|
-
function
|
|
37557
|
-
|
|
38641
|
+
function setUniformWeights(graph, n) {
|
|
38642
|
+
const old = [];
|
|
37558
38643
|
for (let i = 0; i < n; i++) {
|
|
37559
|
-
const
|
|
37560
|
-
|
|
38644
|
+
const node = graph[i];
|
|
38645
|
+
old.push(node.ewgts);
|
|
38646
|
+
const weights = new Array(node.nedges).fill(1);
|
|
38647
|
+
weights[0] = -(node.nedges - 1);
|
|
38648
|
+
node.ewgts = weights;
|
|
37561
38649
|
}
|
|
37562
|
-
return
|
|
38650
|
+
return old;
|
|
37563
38651
|
}
|
|
37564
|
-
function
|
|
37565
|
-
|
|
38652
|
+
function computeYCoords(graph, n, yCoords, maxIterations) {
|
|
38653
|
+
let rv = 0;
|
|
38654
|
+
const b = new Float64Array(n);
|
|
38655
|
+
constructB(graph, n, b);
|
|
38656
|
+
initVecOrth1(n, yCoords);
|
|
38657
|
+
const oldEwgts = setUniformWeights(graph, n);
|
|
38658
|
+
if (conjugateGradient(graph, yCoords, b, n, HIERARCHY_CG_TOL, maxIterations) < 0) {
|
|
38659
|
+
rv = 1;
|
|
38660
|
+
}
|
|
38661
|
+
for (let i = 0; i < n; i++) graph[i].ewgts = oldEwgts[i];
|
|
38662
|
+
return rv;
|
|
37566
38663
|
}
|
|
37567
|
-
|
|
38664
|
+
|
|
38665
|
+
// src/layout/neato/compute-hierarchy.ts
|
|
38666
|
+
function countLevels(y, ordering, n, tol) {
|
|
38667
|
+
let numLevels = 0;
|
|
38668
|
+
for (let i = 1; i < n; i++) {
|
|
38669
|
+
if (y[ordering[i]] - y[ordering[i - 1]] > tol) numLevels++;
|
|
38670
|
+
}
|
|
38671
|
+
return numLevels;
|
|
38672
|
+
}
|
|
38673
|
+
function fillLevels(y, ordering, n, tol, numLevels) {
|
|
38674
|
+
if (numLevels === 0) {
|
|
38675
|
+
const levels2 = new Int32Array(1);
|
|
38676
|
+
levels2[0] = n;
|
|
38677
|
+
return levels2;
|
|
38678
|
+
}
|
|
38679
|
+
const levels = new Int32Array(numLevels);
|
|
38680
|
+
let count = 0;
|
|
38681
|
+
for (let i = 1; i < n; i++) {
|
|
38682
|
+
if (y[ordering[i]] - y[ordering[i - 1]] > tol) levels[count++] = i;
|
|
38683
|
+
}
|
|
38684
|
+
return levels;
|
|
38685
|
+
}
|
|
38686
|
+
function computeHierarchy(graph, n, absTol, relTol, given) {
|
|
38687
|
+
let y;
|
|
38688
|
+
if (given) {
|
|
38689
|
+
y = given;
|
|
38690
|
+
} else {
|
|
38691
|
+
y = new Float64Array(n);
|
|
38692
|
+
if (computeYCoords(graph, n, y, n)) return null;
|
|
38693
|
+
}
|
|
38694
|
+
const ordering = new Int32Array(n);
|
|
38695
|
+
for (let i = 0; i < n; i++) ordering[i] = i;
|
|
38696
|
+
quicksortPlace(y, ordering, n);
|
|
38697
|
+
const hierarchySpan = y[ordering[n - 1]] - y[ordering[0]];
|
|
38698
|
+
const relative = relTol * hierarchySpan / (n - 1);
|
|
38699
|
+
const tol = absTol > relative ? absTol : relative;
|
|
38700
|
+
const numLevels = countLevels(y, ordering, n, tol);
|
|
38701
|
+
return { ordering, levels: fillLevels(y, ordering, n, tol, numLevels), numLevels };
|
|
38702
|
+
}
|
|
38703
|
+
|
|
38704
|
+
// src/layout/neato/smart-ini-x.ts
|
|
38705
|
+
var fr4 = Math.fround;
|
|
38706
|
+
var SCALE_FACTOR = 256;
|
|
38707
|
+
var DBL_EPSILON = 2220446049250313e-31;
|
|
38708
|
+
var POWER_LENGTH_FLOOR = 1e-10;
|
|
38709
|
+
var BLOCK_STANDARDIZE_NORM = 4;
|
|
38710
|
+
var BLOCK_MAT_MULT_ROW = 4;
|
|
38711
|
+
var BLOCK_MAT_MULT_ORTHOG = 8;
|
|
38712
|
+
var BLOCK_GUESS_ORTHOG = 8;
|
|
38713
|
+
var BLOCK_GUESS_LEN = BLOCK_NONE;
|
|
38714
|
+
var BLOCK_LOOP_LEN = BLOCK_NONE;
|
|
38715
|
+
var BLOCK_ANGLE = 8;
|
|
38716
|
+
var BLOCK_UNIFORM_SUMS = 4;
|
|
38717
|
+
var BLOCK_AVGS = 4;
|
|
38718
|
+
function standardize(orthog, nvtxs) {
|
|
38719
|
+
let avg = 0;
|
|
38720
|
+
for (let i = 0; i < nvtxs; i++) avg += orthog[i];
|
|
38721
|
+
avg /= nvtxs;
|
|
38722
|
+
for (let i = 0; i < nvtxs; i++) orthog[i] = orthog[i] - avg;
|
|
38723
|
+
const len = norm(orthog, nvtxs - 1, BLOCK_STANDARDIZE_NORM);
|
|
38724
|
+
if (Math.abs(len) < DBL_EPSILON) return;
|
|
38725
|
+
vectorsScalarMult(nvtxs, orthog, 1 / len, orthog);
|
|
38726
|
+
}
|
|
38727
|
+
function matMultVecOrthog(mat, dim, vec, result, orthog) {
|
|
38728
|
+
const blocked = dim - dim % BLOCK_MAT_MULT_ROW;
|
|
38729
|
+
for (let i = 0; i < dim; i++) {
|
|
38730
|
+
const row = mat[i];
|
|
38731
|
+
let sum = 0;
|
|
38732
|
+
let j = 0;
|
|
38733
|
+
for (; j < blocked; j++) sum += row[j] * vec[j];
|
|
38734
|
+
for (; j < dim; j++) sum = fma2(row[j], vec[j], sum);
|
|
38735
|
+
result[i] = sum;
|
|
38736
|
+
}
|
|
38737
|
+
const alpha = -innerProduct(dim, result, orthog, BLOCK_MAT_MULT_ORTHOG);
|
|
38738
|
+
scadd(result, dim - 1, alpha, orthog);
|
|
38739
|
+
}
|
|
38740
|
+
function orthogonalizeAgainstEigs(p, vec, count, block) {
|
|
38741
|
+
for (let j = 0; j < count; j++) {
|
|
38742
|
+
const alpha = -innerProduct(p.n, p.eigs[j], vec, block);
|
|
38743
|
+
scadd(vec, p.n - 1, alpha, p.eigs[j]);
|
|
38744
|
+
}
|
|
38745
|
+
}
|
|
38746
|
+
function chooseStartVector(p, i) {
|
|
38747
|
+
const curr = p.eigs[i];
|
|
38748
|
+
for (; ; ) {
|
|
38749
|
+
for (let j = 0; j < p.n; j++) curr[j] = crand() % 100;
|
|
38750
|
+
const alpha = -innerProduct(p.n, p.orthog, curr, BLOCK_GUESS_ORTHOG);
|
|
38751
|
+
scadd(curr, p.n - 1, alpha, p.orthog);
|
|
38752
|
+
orthogonalizeAgainstEigs(p, curr, i, BLOCK_NONE);
|
|
38753
|
+
const len = norm(curr, p.n - 1, BLOCK_GUESS_LEN);
|
|
38754
|
+
if (len < POWER_LENGTH_FLOOR) continue;
|
|
38755
|
+
vectorsScalarMult(p.n, curr, 1 / len, curr);
|
|
38756
|
+
return;
|
|
38757
|
+
}
|
|
38758
|
+
}
|
|
38759
|
+
function iterateEigenvector(p, i, tol, work) {
|
|
38760
|
+
const curr = p.eigs[i];
|
|
38761
|
+
for (; ; ) {
|
|
38762
|
+
copyVector(p.n, curr, work.last);
|
|
38763
|
+
matMultVecOrthog(p.mat, p.n, curr, work.tmp, p.orthog);
|
|
38764
|
+
copyVector(p.n, work.tmp, curr);
|
|
38765
|
+
orthogonalizeAgainstEigs(p, curr, i, BLOCK_NONE);
|
|
38766
|
+
const len = norm(curr, p.n - 1, BLOCK_LOOP_LEN);
|
|
38767
|
+
if (len < POWER_LENGTH_FLOOR) {
|
|
38768
|
+
return { nullSpace: true, eval: 0 };
|
|
38769
|
+
}
|
|
38770
|
+
vectorsScalarMult(p.n, curr, 1 / len, curr);
|
|
38771
|
+
const angle = innerProduct(p.n, curr, work.last, BLOCK_ANGLE);
|
|
38772
|
+
if (!(Math.abs(angle) < tol)) {
|
|
38773
|
+
return { nullSpace: false, eval: angle * len };
|
|
38774
|
+
}
|
|
38775
|
+
}
|
|
38776
|
+
}
|
|
38777
|
+
function fillNullSpaceEigenvectors(p, from, neigs) {
|
|
38778
|
+
for (let i = from; i < neigs; i++) {
|
|
38779
|
+
const curr = p.eigs[i];
|
|
38780
|
+
for (let j = 0; j < p.n; j++) curr[j] = crand() % 100;
|
|
38781
|
+
orthogonalizeAgainstEigs(p, curr, i, BLOCK_NONE);
|
|
38782
|
+
const len = norm(curr, p.n - 1, BLOCK_NONE);
|
|
38783
|
+
vectorsScalarMult(p.n, curr, 1 / len, curr);
|
|
38784
|
+
p.evals[i] = 0;
|
|
38785
|
+
}
|
|
38786
|
+
}
|
|
38787
|
+
function sortEigenvectors(p, neigs, tmp) {
|
|
38788
|
+
for (let i = 0; i < neigs - 1; i++) {
|
|
38789
|
+
let largestIndex = i;
|
|
38790
|
+
let largestEval = p.evals[largestIndex];
|
|
38791
|
+
for (let j = i + 1; j < neigs; j++) {
|
|
38792
|
+
if (largestEval < p.evals[j]) {
|
|
38793
|
+
largestIndex = j;
|
|
38794
|
+
largestEval = p.evals[largestIndex];
|
|
38795
|
+
}
|
|
38796
|
+
}
|
|
38797
|
+
if (largestIndex !== i) {
|
|
38798
|
+
copyVector(p.n, p.eigs[i], tmp);
|
|
38799
|
+
copyVector(p.n, p.eigs[largestIndex], p.eigs[i]);
|
|
38800
|
+
copyVector(p.n, tmp, p.eigs[largestIndex]);
|
|
38801
|
+
p.evals[largestIndex] = p.evals[i];
|
|
38802
|
+
p.evals[i] = largestEval;
|
|
38803
|
+
}
|
|
38804
|
+
}
|
|
38805
|
+
}
|
|
38806
|
+
function powerIterationOrthog(p, neigsIn, pIterationThreshold) {
|
|
38807
|
+
const work = { tmp: new Float64Array(p.n), last: new Float64Array(p.n) };
|
|
38808
|
+
const tol = 1 - pIterationThreshold;
|
|
38809
|
+
const neigs = neigsIn >= p.n ? p.n : neigsIn;
|
|
38810
|
+
let i = 0;
|
|
38811
|
+
for (; i < neigs; i++) {
|
|
38812
|
+
chooseStartVector(p, i);
|
|
38813
|
+
const res = iterateEigenvector(p, i, tol, work);
|
|
38814
|
+
if (res.nullSpace) break;
|
|
38815
|
+
p.evals[i] = res.eval;
|
|
38816
|
+
}
|
|
38817
|
+
fillNullSpaceEigenvectors(p, i, neigs);
|
|
38818
|
+
sortEigenvectors(p, neigs, work.tmp);
|
|
38819
|
+
}
|
|
38820
|
+
function computeAvgs(Dij, n) {
|
|
38821
|
+
const rowAvg = new Float32Array(n);
|
|
38822
|
+
let sum = 0;
|
|
38823
|
+
const blocked = n - n % BLOCK_AVGS;
|
|
37568
38824
|
for (let i = 0; i < n; i++) {
|
|
37569
|
-
|
|
38825
|
+
let sumRow = 0;
|
|
38826
|
+
const row = Dij[i];
|
|
38827
|
+
let j = 0;
|
|
38828
|
+
for (; j < blocked; j++) {
|
|
38829
|
+
sum += row[j] * row[j];
|
|
38830
|
+
sumRow += row[j] * row[j];
|
|
38831
|
+
}
|
|
38832
|
+
for (; j < n; j++) {
|
|
38833
|
+
sum = fma2(row[j], row[j], sum);
|
|
38834
|
+
sumRow = fma2(row[j], row[j], sumRow);
|
|
38835
|
+
}
|
|
38836
|
+
rowAvg[i] = fr4(fr4(sumRow) / n);
|
|
37570
38837
|
}
|
|
38838
|
+
return { rowAvg, allAvg: fr4(fr4(sum) / (n * n)) };
|
|
37571
38839
|
}
|
|
37572
|
-
function
|
|
38840
|
+
function computeBij(Dij, n) {
|
|
38841
|
+
const Bij = [];
|
|
38842
|
+
for (let i = 0; i < n; i++) Bij.push(new Float32Array(n));
|
|
38843
|
+
const { rowAvg, allAvg } = computeAvgs(Dij, n);
|
|
37573
38844
|
for (let i = 0; i < n; i++) {
|
|
37574
|
-
|
|
38845
|
+
for (let j = 0; j <= i; j++) {
|
|
38846
|
+
const fD = fr4(Dij[i][j]);
|
|
38847
|
+
const t = fr4(fma2(-fD, fD, rowAvg[i]));
|
|
38848
|
+
Bij[i][j] = fr4(fr4(t + rowAvg[j]) - allAvg);
|
|
38849
|
+
Bij[j][i] = Bij[i][j];
|
|
38850
|
+
}
|
|
38851
|
+
}
|
|
38852
|
+
return Bij;
|
|
38853
|
+
}
|
|
38854
|
+
function cmdsOrthog(n, dim, eigs, tol, input) {
|
|
38855
|
+
const { orthog, Dij } = input;
|
|
38856
|
+
const Bij = computeBij(Dij, n);
|
|
38857
|
+
const evals = new Float64Array(dim);
|
|
38858
|
+
const orthogAux = Float64Array.from(orthog.subarray(0, n));
|
|
38859
|
+
standardize(orthogAux, n);
|
|
38860
|
+
powerIterationOrthog({ mat: Bij, n, eigs, evals, orthog: orthogAux }, dim, tol);
|
|
38861
|
+
for (let i = 0; i < dim; i++) {
|
|
38862
|
+
for (let j = 0; j < n; j++) eigs[i][j] = eigs[i][j] * Math.sqrt(Math.abs(evals[i]));
|
|
37575
38863
|
}
|
|
37576
38864
|
}
|
|
37577
|
-
function
|
|
38865
|
+
function scaleGivenCoords(Dij, n, x) {
|
|
38866
|
+
let sum1 = 0;
|
|
38867
|
+
let sum2 = 0;
|
|
38868
|
+
for (let i = 1; i < n; i++) {
|
|
38869
|
+
const blocked = i - i % BLOCK_UNIFORM_SUMS;
|
|
38870
|
+
for (let j = 0; j < i; j++) {
|
|
38871
|
+
const d = Dij[i][j];
|
|
38872
|
+
const f = Math.abs(x[i] - x[j]);
|
|
38873
|
+
const t1 = 1 / d;
|
|
38874
|
+
const t2 = 1 / Math.imul(d, d) * f;
|
|
38875
|
+
if (j < blocked) {
|
|
38876
|
+
sum1 += t1 * f;
|
|
38877
|
+
sum2 += t2 * f;
|
|
38878
|
+
} else {
|
|
38879
|
+
sum1 = fma2(t1, f, sum1);
|
|
38880
|
+
sum2 = fma2(t2, f, sum2);
|
|
38881
|
+
}
|
|
38882
|
+
}
|
|
38883
|
+
}
|
|
38884
|
+
const uniLength = Math.abs(sum2) === Infinity ? 0 : sum1 / sum2;
|
|
38885
|
+
for (let i = 0; i < n; i++) x[i] = x[i] * uniLength;
|
|
38886
|
+
return uniLength;
|
|
38887
|
+
}
|
|
38888
|
+
function computeLaplacian(Dij, n) {
|
|
38889
|
+
const lap = [];
|
|
37578
38890
|
for (let i = 0; i < n; i++) {
|
|
37579
|
-
|
|
38891
|
+
const row = new Float32Array(n);
|
|
38892
|
+
let degree = fr4(0);
|
|
38893
|
+
for (let j = 0; j < n; j++) {
|
|
38894
|
+
if (j === i) continue;
|
|
38895
|
+
const w = fr4(fr4(-1) / fr4(fr4(Dij[i][j]) * fr4(Dij[i][j])));
|
|
38896
|
+
row[j] = w;
|
|
38897
|
+
degree = fr4(degree - w);
|
|
38898
|
+
}
|
|
38899
|
+
row[i] = degree;
|
|
38900
|
+
lap.push(row);
|
|
38901
|
+
}
|
|
38902
|
+
return lap;
|
|
38903
|
+
}
|
|
38904
|
+
function computeResidualDistances(Dij, n, x) {
|
|
38905
|
+
for (let i = 1; i < n; i++) {
|
|
38906
|
+
const posI = x[i];
|
|
38907
|
+
for (let j = 0; j < i; j++) {
|
|
38908
|
+
const t = posI - x[j];
|
|
38909
|
+
const d = Dij[i][j];
|
|
38910
|
+
const diff = fma2(d, d, -(t * t));
|
|
38911
|
+
const v = diff > 0 ? Math.sqrt(diff) : 0;
|
|
38912
|
+
Dij[i][j] = v;
|
|
38913
|
+
Dij[j][i] = v;
|
|
38914
|
+
}
|
|
37580
38915
|
}
|
|
37581
38916
|
}
|
|
38917
|
+
function balanceOf(i, n, y, ctx) {
|
|
38918
|
+
const posI = y[i];
|
|
38919
|
+
let b = 0;
|
|
38920
|
+
for (let j = 0; j < n; j++) {
|
|
38921
|
+
if (j === i) continue;
|
|
38922
|
+
const term = fr4(fr4(ctx.Dij[i][j]) * -ctx.lap[i][j]);
|
|
38923
|
+
if (posI >= y[j]) b += term;
|
|
38924
|
+
else b -= term;
|
|
38925
|
+
}
|
|
38926
|
+
return b;
|
|
38927
|
+
}
|
|
38928
|
+
function solveBalanced(ctx, n, y, balance, convTol) {
|
|
38929
|
+
let converged = false;
|
|
38930
|
+
for (let iterations2 = 0; iterations2 < 200 && !converged; iterations2++) {
|
|
38931
|
+
if (conjugateGradientF(ctx.lap, y, balance, n, { tol: convTol, maxIterations: n, ortho1: true }) < 0) return 1;
|
|
38932
|
+
converged = true;
|
|
38933
|
+
for (let i = 0; i < n; i++) {
|
|
38934
|
+
const b = balanceOf(i, n, y, ctx);
|
|
38935
|
+
if (b !== balance[i] && Math.abs(1 - b / balance[i]) > 1e-5) {
|
|
38936
|
+
converged = false;
|
|
38937
|
+
balance[i] = b;
|
|
38938
|
+
}
|
|
38939
|
+
}
|
|
38940
|
+
}
|
|
38941
|
+
return 0;
|
|
38942
|
+
}
|
|
38943
|
+
function imdsGivenDim(graph, n, givenCoords, newCoords, conjTol) {
|
|
38944
|
+
const x = givenCoords;
|
|
38945
|
+
const y = newCoords;
|
|
38946
|
+
const Dij = computeApsp(graph, n);
|
|
38947
|
+
for (let i = 0; i < n; i++) {
|
|
38948
|
+
for (let j = 0; j < n; j++) Dij[i][j] = Dij[i][j] * SCALE_FACTOR;
|
|
38949
|
+
}
|
|
38950
|
+
const uniLength = scaleGivenCoords(Dij, n, x);
|
|
38951
|
+
cmdsOrthog(n, 1, [y], conjTol, { orthog: x, Dij });
|
|
38952
|
+
const lap = computeLaplacian(Dij, n);
|
|
38953
|
+
computeResidualDistances(Dij, n, x);
|
|
38954
|
+
const ctx = { Dij, lap };
|
|
38955
|
+
const balance = new Float64Array(n);
|
|
38956
|
+
for (let i = 0; i < n; i++) balance[i] = balanceOf(i, n, y, ctx);
|
|
38957
|
+
if (solveBalanced(ctx, n, y, balance, conjTol) === 1) return 1;
|
|
38958
|
+
for (let i = 0; !(Math.abs(uniLength) < DBL_EPSILON) && i < n; i++) {
|
|
38959
|
+
x[i] = x[i] / uniLength;
|
|
38960
|
+
y[i] = y[i] / uniLength;
|
|
38961
|
+
}
|
|
38962
|
+
return 0;
|
|
38963
|
+
}
|
|
37582
38964
|
|
|
37583
38965
|
// src/layout/neato/stress-kernel.ts
|
|
37584
|
-
var
|
|
37585
|
-
var
|
|
38966
|
+
var fr5 = Math.fround;
|
|
38967
|
+
var TOLERANCE_CG2 = 1e-3;
|
|
37586
38968
|
var OPT_EXP_FLAG = 2;
|
|
37587
38969
|
function computeApspPacked2(graph, n) {
|
|
37588
38970
|
const Dij = new Float32Array(n * (n + 1) / 2);
|
|
@@ -37642,9 +39024,9 @@ function cgStep(st, last) {
|
|
|
37642
39024
|
vectorsMultAdditionF(n, st.r, -alpha, st.Ap);
|
|
37643
39025
|
const rRNew = vectorsInnerProductF(n, st.r, st.r);
|
|
37644
39026
|
if (st.rR === 0) return false;
|
|
37645
|
-
const betaF =
|
|
39027
|
+
const betaF = fr5(rRNew / st.rR);
|
|
37646
39028
|
st.rR = rRNew;
|
|
37647
|
-
for (let j = 0; j < n; j++) st.p[j] =
|
|
39029
|
+
for (let j = 0; j < n; j++) st.p[j] = fr5(betaF * st.p[j]) + st.r[j];
|
|
37648
39030
|
}
|
|
37649
39031
|
return true;
|
|
37650
39032
|
}
|
|
@@ -37706,8 +39088,8 @@ function buildLap1(lap1, lap2, coords, shape) {
|
|
|
37706
39088
|
for (let k = 0; k < dim; k++) {
|
|
37707
39089
|
const ck = coords[k];
|
|
37708
39090
|
for (let x = 0; x < len; x++) {
|
|
37709
|
-
const tmp =
|
|
37710
|
-
distAccumulator[x] = distAccumulator[x] +
|
|
39091
|
+
const tmp = fr5(ck[i] + fr5(-1 * ck[i + 1 + x]));
|
|
39092
|
+
distAccumulator[x] = distAccumulator[x] + fr5(tmp * tmp);
|
|
37711
39093
|
}
|
|
37712
39094
|
}
|
|
37713
39095
|
invertSqrtVec(len, distAccumulator);
|
|
@@ -37719,7 +39101,7 @@ function buildLap1(lap1, lap2, coords, shape) {
|
|
|
37719
39101
|
let degree = 0;
|
|
37720
39102
|
if (exp === 2) {
|
|
37721
39103
|
for (let j = 0; j < len; j++, count++) {
|
|
37722
|
-
const val2 = lap1[count] =
|
|
39104
|
+
const val2 = lap1[count] = fr5(lap1[count] * distAccumulator[j]);
|
|
37723
39105
|
degree += val2;
|
|
37724
39106
|
degrees[i + j + 1] = degrees[i + j + 1] - val2;
|
|
37725
39107
|
}
|
|
@@ -37753,10 +39135,10 @@ function computeStress(st) {
|
|
|
37753
39135
|
}
|
|
37754
39136
|
function solveAxis(st, k, havePinned, nodes) {
|
|
37755
39137
|
if (!havePinned) {
|
|
37756
|
-
return conjugateGradientMkernel2(st.lap2, st.coords[k], st.b[k], st.n,
|
|
39138
|
+
return conjugateGradientMkernel2(st.lap2, st.coords[k], st.b[k], st.n, TOLERANCE_CG2, st.n);
|
|
37757
39139
|
}
|
|
37758
39140
|
copyVectorF(st.n, st.coords[k], st.tmpCoords);
|
|
37759
|
-
const rc = conjugateGradientMkernel2(st.lap2, st.tmpCoords, st.b[k], st.n,
|
|
39141
|
+
const rc = conjugateGradientMkernel2(st.lap2, st.tmpCoords, st.b[k], st.n, TOLERANCE_CG2, st.n);
|
|
37760
39142
|
if (rc < 0) return rc;
|
|
37761
39143
|
for (let i = 0; i < st.n; i++) {
|
|
37762
39144
|
if (!isFixed(nodes[i])) st.coords[k][i] = st.tmpCoords[i];
|
|
@@ -37772,10 +39154,10 @@ function stressMajorizationKDMkernel(Dij, n, dCoords, nodes, o) {
|
|
|
37772
39154
|
const coords = [];
|
|
37773
39155
|
for (let i = 0; i < dim; i++) {
|
|
37774
39156
|
const c = new Float32Array(n);
|
|
37775
|
-
for (let j = 0; j < n; j++) c[j] =
|
|
39157
|
+
for (let j = 0; j < n; j++) c[j] = fr5(dCoords[i][j]);
|
|
37776
39158
|
coords.push(c);
|
|
37777
39159
|
}
|
|
37778
|
-
const constantTerm =
|
|
39160
|
+
const constantTerm = fr5(n * (n - 1) / 2);
|
|
37779
39161
|
const lap2 = Dij;
|
|
37780
39162
|
buildLap2(lap2, n, exp);
|
|
37781
39163
|
const lapLength = n * (n + 1) / 2;
|
|
@@ -37810,6 +39192,261 @@ function stressMajorizationKDMkernel(Dij, n, dCoords, nodes, o) {
|
|
|
37810
39192
|
return iterations;
|
|
37811
39193
|
}
|
|
37812
39194
|
|
|
39195
|
+
// src/layout/neato/constrained-majorization.ts
|
|
39196
|
+
var fr6 = Math.fround;
|
|
39197
|
+
var LOCAL_CONSTR_MAJOR_ITERATIONS = 15;
|
|
39198
|
+
var LEVELS_SEP_TOL = 0.1;
|
|
39199
|
+
var ABS_TOL = 0.01;
|
|
39200
|
+
var SUBSPACE_ITERATIONS = 15;
|
|
39201
|
+
var FLT_MAX3 = 34028234663852886e22;
|
|
39202
|
+
var DBL_MAX = Number.MAX_VALUE;
|
|
39203
|
+
var MIN_LEVELS = 1;
|
|
39204
|
+
var Y_AXIS = 1;
|
|
39205
|
+
function unsupported2(what) {
|
|
39206
|
+
throw new RenderError(`hierarchical stress majorization: ${what} is not supported yet`, "UNSUPPORTED_FEATURE");
|
|
39207
|
+
}
|
|
39208
|
+
function modelDistances(graph, n, model) {
|
|
39209
|
+
if (model === MODEL_SUBSET) unsupported2("the subset distance model");
|
|
39210
|
+
if (model === MODEL_CIRCUIT) unsupported2("the circuit distance model");
|
|
39211
|
+
return model === MODEL_MDS2 ? mdsModel(graph, n) : null;
|
|
39212
|
+
}
|
|
39213
|
+
function unconstrainedMajorization(graph, n, dCoords, nodes, o) {
|
|
39214
|
+
if (o.maxi < 0) return 0;
|
|
39215
|
+
const weighted = (graph[0]?.ewgts.length ?? 0) > 0;
|
|
39216
|
+
const Dij = modelDistances(graph, n, o.model) ?? (weighted ? computeWeightedApspPacked2(graph, n) : computeApspPacked2(graph, n));
|
|
39217
|
+
if ((o.opts & OPT_SMART_INIT) !== 0 && n > 1) unsupported2("the smart initial layout");
|
|
39218
|
+
return stressMajorizationKDMkernel(Dij, n, dCoords, nodes, {
|
|
39219
|
+
dim: o.dim,
|
|
39220
|
+
opts: o.opts,
|
|
39221
|
+
maxi: o.maxi,
|
|
39222
|
+
epsilon: o.epsilon
|
|
39223
|
+
});
|
|
39224
|
+
}
|
|
39225
|
+
function hasDirectionality(graph, n) {
|
|
39226
|
+
if (!graph[0]?.edists) return false;
|
|
39227
|
+
let directionalityExist = false;
|
|
39228
|
+
for (let i = 0; i < n; i++) {
|
|
39229
|
+
const edists = graph[i].edists;
|
|
39230
|
+
for (let j = 1; j < graph[i].nedges; j++) {
|
|
39231
|
+
directionalityExist ||= edists[j] !== 0;
|
|
39232
|
+
}
|
|
39233
|
+
}
|
|
39234
|
+
return directionalityExist;
|
|
39235
|
+
}
|
|
39236
|
+
function separateLevels(y, h, n, levelsGap) {
|
|
39237
|
+
const { ordering, levels, numLevels } = h;
|
|
39238
|
+
let displacement = 0;
|
|
39239
|
+
for (let i = 0; i < numLevels; i++) {
|
|
39240
|
+
const shortfall = levelsGap - (y[ordering[levels[i]]] + displacement - y[ordering[levels[i] - 1]]);
|
|
39241
|
+
displacement += 0 > shortfall ? 0 : shortfall;
|
|
39242
|
+
const stop = i < numLevels - 1 ? levels[i + 1] : n;
|
|
39243
|
+
for (let j = levels[i]; j < stop; j++) y[ordering[j]] += displacement;
|
|
39244
|
+
}
|
|
39245
|
+
}
|
|
39246
|
+
function smartInitLayers(graph, n, dCoords, nodes, o) {
|
|
39247
|
+
const { dim } = o;
|
|
39248
|
+
if (dim > 2) {
|
|
39249
|
+
const sub = { dim: dim - 1, opts: o.opts, model: o.model, maxi: SUBSPACE_ITERATIONS, epsilon: o.epsilon };
|
|
39250
|
+
if (unconstrainedMajorization(graph, n, dCoords.slice(1), nodes, sub) < 0) return -1;
|
|
39251
|
+
dCoords[dim - 1].set(dCoords[1].subarray(0, n));
|
|
39252
|
+
}
|
|
39253
|
+
const x = dCoords[0];
|
|
39254
|
+
const y = dCoords[1];
|
|
39255
|
+
if (computeYCoords(graph, n, y, n)) return -1;
|
|
39256
|
+
const h = computeHierarchy(graph, n, ABS_TOL, LEVELS_SEP_TOL, y);
|
|
39257
|
+
if (h === null) return -1;
|
|
39258
|
+
if (h.numLevels < MIN_LEVELS) {
|
|
39259
|
+
return unconstrainedMajorization(graph, n, dCoords, nodes, o);
|
|
39260
|
+
}
|
|
39261
|
+
if (o.levelsGap > 0) separateLevels(y, h, n, o.levelsGap);
|
|
39262
|
+
if (dim === 2 && imdsGivenDim(graph, n, y, x, o.epsilon)) return -1;
|
|
39263
|
+
return h;
|
|
39264
|
+
}
|
|
39265
|
+
function plainInitLayers(graph, n, dCoords, nodes, dim) {
|
|
39266
|
+
initLayout(n, dim, dCoords, nodes);
|
|
39267
|
+
const h = computeHierarchy(graph, n, ABS_TOL, LEVELS_SEP_TOL, null);
|
|
39268
|
+
return h === null ? -1 : h;
|
|
39269
|
+
}
|
|
39270
|
+
function distanceKD(coords, dim, i, j) {
|
|
39271
|
+
let sum = 0;
|
|
39272
|
+
for (let k = 0; k < dim; k++) {
|
|
39273
|
+
const d = coords[k][i] - coords[k][j];
|
|
39274
|
+
sum = fma2(d, d, sum);
|
|
39275
|
+
}
|
|
39276
|
+
return Math.sqrt(sum);
|
|
39277
|
+
}
|
|
39278
|
+
function scaleDownLayout(dCoords, n, dim) {
|
|
39279
|
+
let max = 1;
|
|
39280
|
+
for (let i = 0; i < dim; i++) {
|
|
39281
|
+
for (let j = 0; j < n; j++) {
|
|
39282
|
+
const a = Math.abs(dCoords[i][j]);
|
|
39283
|
+
if (a > max) max = a;
|
|
39284
|
+
}
|
|
39285
|
+
}
|
|
39286
|
+
for (let i = 0; i < dim; i++) {
|
|
39287
|
+
for (let j = 0; j < n; j++) dCoords[i][j] *= 10 / max;
|
|
39288
|
+
}
|
|
39289
|
+
}
|
|
39290
|
+
function scaleDistances(Dij, dCoords, n, dim) {
|
|
39291
|
+
const length = n + Math.trunc(n * (n - 1) / 2);
|
|
39292
|
+
const sum1 = Math.trunc(n * (n - 1) / 2);
|
|
39293
|
+
let sum2 = 0;
|
|
39294
|
+
for (let count = 0, i = 0; i < n - 1; i++) {
|
|
39295
|
+
count++;
|
|
39296
|
+
for (let j = i + 1; j < n; j++, count++) {
|
|
39297
|
+
sum2 += distanceKD(dCoords, dim, i, j) / Dij[count];
|
|
39298
|
+
}
|
|
39299
|
+
}
|
|
39300
|
+
const scaleRatio = fr6(sum2 / sum1);
|
|
39301
|
+
for (let i = 0; i < length; i++) Dij[i] = Dij[i] * scaleRatio;
|
|
39302
|
+
}
|
|
39303
|
+
function centerLayout(dCoords, n, dim) {
|
|
39304
|
+
for (let i = 0; i < dim; i++) orthog1(n, dCoords[i]);
|
|
39305
|
+
const y0 = dCoords[Y_AXIS][0];
|
|
39306
|
+
for (let i = 0; i < n; i++) dCoords[Y_AXIS][i] -= y0;
|
|
39307
|
+
}
|
|
39308
|
+
function negatedDegrees(lap2, n) {
|
|
39309
|
+
const degrees = new Float64Array(n);
|
|
39310
|
+
for (let i = 0, count = 0; i < n - 1; i++) {
|
|
39311
|
+
let degree = 0;
|
|
39312
|
+
count++;
|
|
39313
|
+
for (let j = 1; j < n - i; j++, count++) {
|
|
39314
|
+
const val2 = lap2[count];
|
|
39315
|
+
degree += val2;
|
|
39316
|
+
degrees[i + j] -= val2;
|
|
39317
|
+
}
|
|
39318
|
+
degrees[i] -= degree;
|
|
39319
|
+
}
|
|
39320
|
+
return degrees;
|
|
39321
|
+
}
|
|
39322
|
+
function buildLap22(lap2, n) {
|
|
39323
|
+
const lapLength = n + Math.trunc(n * (n - 1) / 2);
|
|
39324
|
+
squareVec(lapLength, lap2);
|
|
39325
|
+
invertVec(lapLength, lap2);
|
|
39326
|
+
const degrees = negatedDegrees(lap2, n);
|
|
39327
|
+
for (let step = n, count = 0, i = 0; i < n; i++, count += step, step--) {
|
|
39328
|
+
lap2[count] = degrees[i];
|
|
39329
|
+
}
|
|
39330
|
+
}
|
|
39331
|
+
function inverseDistances(st, i, len) {
|
|
39332
|
+
const { coords, tmpCoords, distAccumulator } = st;
|
|
39333
|
+
distAccumulator.fill(0, 0, st.n);
|
|
39334
|
+
for (let k = 0; k < st.dim; k++) {
|
|
39335
|
+
const ck = coords[k];
|
|
39336
|
+
for (let j = 0; j < len; j++) tmpCoords[j] = ck[i] - ck[i + 1 + j];
|
|
39337
|
+
for (let j = 0; j < len; j++) tmpCoords[j] = tmpCoords[j] * tmpCoords[j];
|
|
39338
|
+
for (let j = 0; j < len; j++) distAccumulator[j] = tmpCoords[j] + distAccumulator[j];
|
|
39339
|
+
}
|
|
39340
|
+
invertSqrtVec(len, distAccumulator);
|
|
39341
|
+
for (let j = 0; j < len; j++) {
|
|
39342
|
+
if (distAccumulator[j] >= FLT_MAX3 || distAccumulator[j] < 0) distAccumulator[j] = 0;
|
|
39343
|
+
}
|
|
39344
|
+
}
|
|
39345
|
+
function buildLap12(st) {
|
|
39346
|
+
const { n, lap1, lap2, degrees, distAccumulator } = st;
|
|
39347
|
+
degrees.fill(0);
|
|
39348
|
+
sqrtVecF(n + Math.trunc(n * (n - 1) / 2), lap2, lap1);
|
|
39349
|
+
let count = 0;
|
|
39350
|
+
for (let i = 0; i < n - 1; i++) {
|
|
39351
|
+
const len = n - i - 1;
|
|
39352
|
+
inverseDistances(st, i, len);
|
|
39353
|
+
count++;
|
|
39354
|
+
let degree = 0;
|
|
39355
|
+
for (let j = 0; j < len; j++, count++) {
|
|
39356
|
+
const val2 = fr6(lap1[count] * distAccumulator[j]);
|
|
39357
|
+
lap1[count] = val2;
|
|
39358
|
+
degree += val2;
|
|
39359
|
+
degrees[i + j + 1] -= val2;
|
|
39360
|
+
}
|
|
39361
|
+
degrees[i] -= degree;
|
|
39362
|
+
}
|
|
39363
|
+
for (let step = n, count2 = 0, i = 0; i < n; i++, count2 += step, step--) {
|
|
39364
|
+
lap1[count2] = degrees[i];
|
|
39365
|
+
}
|
|
39366
|
+
}
|
|
39367
|
+
function computeNewStress(st, constantTerm) {
|
|
39368
|
+
const { n, dim, lap1, lap2, coords, b, tmpCoords } = st;
|
|
39369
|
+
for (let k = 0; k < dim; k++) rightMultWithVectorFFFused(lap1, n, coords[k], b[k]);
|
|
39370
|
+
let newStress = 0;
|
|
39371
|
+
for (let k = 0; k < dim; k++) newStress += vectorsInnerProductF(n, coords[k], b[k]);
|
|
39372
|
+
newStress *= 2;
|
|
39373
|
+
newStress += constantTerm;
|
|
39374
|
+
for (let k = 0; k < dim; k++) {
|
|
39375
|
+
rightMultWithVectorFFFused(lap2, n, coords[k], tmpCoords);
|
|
39376
|
+
newStress -= vectorsInnerProductF(n, coords[k], tmpCoords);
|
|
39377
|
+
}
|
|
39378
|
+
return newStress;
|
|
39379
|
+
}
|
|
39380
|
+
function solveAxes(st, ctx) {
|
|
39381
|
+
for (let k = 0; k < st.dim; k++) {
|
|
39382
|
+
if (k === Y_AXIS) {
|
|
39383
|
+
constrainedMajorizationNewWithGaps(
|
|
39384
|
+
ctx.cMajEnv,
|
|
39385
|
+
st.b[k],
|
|
39386
|
+
st.coords,
|
|
39387
|
+
k,
|
|
39388
|
+
LOCAL_CONSTR_MAJOR_ITERATIONS,
|
|
39389
|
+
ctx.levelsGap
|
|
39390
|
+
);
|
|
39391
|
+
} else if (conjugateGradientMkernelFused(st.lap2, st.coords[k], st.b[k], st.n, { tol: TOLERANCE_CG, maxIterations: st.n })) {
|
|
39392
|
+
return true;
|
|
39393
|
+
}
|
|
39394
|
+
}
|
|
39395
|
+
return false;
|
|
39396
|
+
}
|
|
39397
|
+
function majorize(st, ctx, dCoords) {
|
|
39398
|
+
const constantTerm = Math.trunc(st.n * (st.n - 1) / 2);
|
|
39399
|
+
let oldStress = DBL_MAX;
|
|
39400
|
+
let iterations = 0;
|
|
39401
|
+
for (let converged = false; iterations < ctx.maxi && !converged; iterations++) {
|
|
39402
|
+
buildLap12(st);
|
|
39403
|
+
const newStress = computeNewStress(st, constantTerm);
|
|
39404
|
+
converged = Math.abs(newStress - oldStress) / Math.abs(oldStress + 1e-10) < ctx.epsilon;
|
|
39405
|
+
converged ||= iterations > 1 && newStress > oldStress;
|
|
39406
|
+
oldStress = newStress;
|
|
39407
|
+
if (solveAxes(st, ctx)) return -1;
|
|
39408
|
+
}
|
|
39409
|
+
for (let i = 0; i < st.dim; i++) {
|
|
39410
|
+
for (let j = 0; j < st.n; j++) dCoords[i][j] = st.coords[i][j];
|
|
39411
|
+
}
|
|
39412
|
+
return iterations;
|
|
39413
|
+
}
|
|
39414
|
+
function toFloatCoords(dCoords, n, dim) {
|
|
39415
|
+
const coords = [];
|
|
39416
|
+
for (let i = 0; i < dim; i++) coords.push(Float32Array.from(dCoords[i].subarray(0, n)));
|
|
39417
|
+
return coords;
|
|
39418
|
+
}
|
|
39419
|
+
function newLoopState(lap2, coords, n) {
|
|
39420
|
+
const dim = coords.length;
|
|
39421
|
+
return {
|
|
39422
|
+
n,
|
|
39423
|
+
dim,
|
|
39424
|
+
lap2,
|
|
39425
|
+
coords,
|
|
39426
|
+
lap1: new Float32Array(n + Math.trunc(n * (n - 1) / 2)),
|
|
39427
|
+
b: Array.from({ length: dim }, () => new Float32Array(n)),
|
|
39428
|
+
tmpCoords: new Float32Array(n),
|
|
39429
|
+
distAccumulator: new Float32Array(n),
|
|
39430
|
+
degrees: new Float64Array(n)
|
|
39431
|
+
};
|
|
39432
|
+
}
|
|
39433
|
+
function stressMajorizationWithHierarchy(graph, n, dCoords, nodes, o) {
|
|
39434
|
+
if (!hasDirectionality(graph, n)) return unconstrainedMajorization(graph, n, dCoords, nodes, o);
|
|
39435
|
+
const smartIni = (o.opts & OPT_SMART_INIT) !== 0;
|
|
39436
|
+
const layers = smartIni ? smartInitLayers(graph, n, dCoords, nodes, o) : plainInitLayers(graph, n, dCoords, nodes, o.dim);
|
|
39437
|
+
if (typeof layers === "number") return layers;
|
|
39438
|
+
if (n === 1) return 0;
|
|
39439
|
+
if (o.maxi === 0) return 0;
|
|
39440
|
+
const Dij = modelDistances(graph, n, o.model) ?? computeApspPacked2(graph, n);
|
|
39441
|
+
if (!smartIni) scaleDownLayout(dCoords, n, o.dim);
|
|
39442
|
+
if (o.levelsGap > 0) scaleDistances(Dij, dCoords, n, o.dim);
|
|
39443
|
+
centerLayout(dCoords, n, o.dim);
|
|
39444
|
+
const st = newLoopState(Dij, toFloatCoords(dCoords, n, o.dim), n);
|
|
39445
|
+
buildLap22(Dij, n);
|
|
39446
|
+
const cMajEnv = initConstrainedMajorization(Dij, n, layers.ordering, layers.levels, layers.numLevels);
|
|
39447
|
+
return majorize(st, { cMajEnv, levelsGap: o.levelsGap, maxi: o.maxi, epsilon: o.epsilon }, dCoords);
|
|
39448
|
+
}
|
|
39449
|
+
|
|
37813
39450
|
// src/common/utils-inputscale.ts
|
|
37814
39451
|
var POINTS_PER_INCH3 = 72;
|
|
37815
39452
|
function getInputscale(g) {
|
|
@@ -37996,61 +39633,47 @@ function neatoMaxIter(maxiter, mode, n) {
|
|
|
37996
39633
|
if (mode === MODE_MAJOR) return DFLT_ITERATIONS;
|
|
37997
39634
|
return mode === MODE_SGD ? SGD_ITERATIONS : 100 * n;
|
|
37998
39635
|
}
|
|
37999
|
-
|
|
38000
|
-
|
|
38001
|
-
const
|
|
39636
|
+
var levelsGapOf = (g) => lateDouble(g.root.attrs.get("levelsgap"), 0, -Number.MAX_VALUE);
|
|
39637
|
+
function solveStress(c, vtx, dCoords, nodeList) {
|
|
39638
|
+
const { g, mode, model, haveLen, opts } = c;
|
|
38002
39639
|
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
39640
|
const maxi = neatoMaxIter(g.attrs.get("maxiter"), mode, n);
|
|
38007
39641
|
const epsilon = lateDouble(g.attrs.get("epsilon"), 1e-4, 0);
|
|
39642
|
+
if (mode === MODE_HIER) {
|
|
39643
|
+
return stressMajorizationWithHierarchy(vtx, n, dCoords, nodeList, {
|
|
39644
|
+
dim: DFLT_DIM,
|
|
39645
|
+
opts,
|
|
39646
|
+
model,
|
|
39647
|
+
maxi,
|
|
39648
|
+
epsilon,
|
|
39649
|
+
levelsGap: levelsGapOf(g)
|
|
39650
|
+
});
|
|
39651
|
+
}
|
|
38008
39652
|
const weighted = haveLen && mode !== MODE_IPSEP;
|
|
38009
39653
|
const Dij = weighted ? computeWeightedApspPacked2(vtx, n) : computeApspPacked2(vtx, n);
|
|
38010
|
-
|
|
38011
|
-
stressMajorizationKDMkernel(Dij, n, dCoords, nodeList, {
|
|
39654
|
+
return stressMajorizationKDMkernel(Dij, n, dCoords, nodeList, {
|
|
38012
39655
|
dim: DFLT_DIM,
|
|
38013
|
-
opts
|
|
39656
|
+
opts,
|
|
38014
39657
|
maxi,
|
|
38015
39658
|
epsilon
|
|
38016
39659
|
});
|
|
38017
|
-
for (let i = 0; i < n; i++) {
|
|
38018
|
-
nodeList[i].info.pos = [dCoords[0][i], dCoords[1][i]];
|
|
38019
|
-
}
|
|
38020
39660
|
}
|
|
38021
|
-
function
|
|
38022
|
-
|
|
38023
|
-
|
|
39661
|
+
function runMajorization(g, mode, model) {
|
|
39662
|
+
const nodeList = assignNodeIds2(g);
|
|
39663
|
+
const n = nodeList.length;
|
|
39664
|
+
const haveLen = graphHasLen(g);
|
|
39665
|
+
const init = checkStart(g, n, mode === MODE_HIER ? INIT_SELF : INIT_RANDOM);
|
|
39666
|
+
const opts = init === INIT_SELF ? OPT_EXP_FLAG | OPT_SMART_INIT : OPT_EXP_FLAG;
|
|
39667
|
+
const haveDir = mode === MODE_HIER || mode === MODE_IPSEP;
|
|
39668
|
+
const vtx = makeGraphDataC(g, nodeList, haveLen, haveDir, mode);
|
|
39669
|
+
const dCoords = [new Float64Array(n), new Float64Array(n)];
|
|
39670
|
+
if (solveStress({ g, mode, model, haveLen, opts }, vtx, dCoords, nodeList) < 0) {
|
|
39671
|
+
agerr("prev", "layout aborted");
|
|
39672
|
+
return;
|
|
38024
39673
|
}
|
|
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
|
-
}
|
|
39674
|
+
for (let i = 0; i < n; i++) {
|
|
39675
|
+
nodeList[i].info.pos = [dCoords[0][i], dCoords[1][i]];
|
|
38052
39676
|
}
|
|
38053
|
-
return vtx;
|
|
38054
39677
|
}
|
|
38055
39678
|
function solveModel2(g, mode, model) {
|
|
38056
39679
|
if (g.nodes.size < 2) return;
|
|
@@ -38242,6 +39865,25 @@ function esepFactor(g) {
|
|
|
38242
39865
|
return { x: SEPFACT * DFLT_MARGIN, y: SEPFACT * DFLT_MARGIN, doAdd: true };
|
|
38243
39866
|
}
|
|
38244
39867
|
|
|
39868
|
+
// src/common/libm-trig.ts
|
|
39869
|
+
var OCTAGON_TRIG = /* @__PURE__ */ new Map([
|
|
39870
|
+
[-0.39269908169872414, [0.9238795325112867, -0.3826834323650898]],
|
|
39871
|
+
[0.39269908169872414, [0.9238795325112867, 0.3826834323650898]],
|
|
39872
|
+
[1.1780972450961724, [0.38268343236508984, 0.9238795325112867]],
|
|
39873
|
+
[1.9634954084936207, [-0.3826834323650897, 0.9238795325112867]],
|
|
39874
|
+
[2.748893571891069, [-0.9238795325112867, 0.3826834323650899]],
|
|
39875
|
+
[3.5342917352885173, [-0.9238795325112868, -0.38268343236508967]],
|
|
39876
|
+
[4.319689898685965, [-0.38268343236509034, -0.9238795325112865]],
|
|
39877
|
+
[5.105088062083414, [0.38268343236509, -0.9238795325112866]],
|
|
39878
|
+
[5.890486225480862, [0.9238795325112865, -0.3826834323650904]]
|
|
39879
|
+
]);
|
|
39880
|
+
function libmCos(x) {
|
|
39881
|
+
return OCTAGON_TRIG.get(x)?.[0] ?? Math.cos(x);
|
|
39882
|
+
}
|
|
39883
|
+
function libmSin(x) {
|
|
39884
|
+
return OCTAGON_TRIG.get(x)?.[1] ?? Math.sin(x);
|
|
39885
|
+
}
|
|
39886
|
+
|
|
38245
39887
|
// src/layout/neato/delaunay.ts
|
|
38246
39888
|
var ICCERRBOUND_A = (10 + 96 * 2 ** -53) * 2 ** -53;
|
|
38247
39889
|
function ulpExp(v) {
|
|
@@ -38410,6 +40052,32 @@ function delaunayTri(xv, yv, n) {
|
|
|
38410
40052
|
return edges;
|
|
38411
40053
|
}
|
|
38412
40054
|
|
|
40055
|
+
// src/layout/neato/gts-triangle.ts
|
|
40056
|
+
var SQRT3 = 1.73205080757;
|
|
40057
|
+
function gtsTriangleEnclosing(px, py, n, scale) {
|
|
40058
|
+
let xmin = px[0];
|
|
40059
|
+
let xmax = px[0];
|
|
40060
|
+
let ymin = py[0];
|
|
40061
|
+
let ymax = py[0];
|
|
40062
|
+
for (let i = 1; i < n; i++) {
|
|
40063
|
+
if (px[i] > xmax) xmax = px[i];
|
|
40064
|
+
else if (px[i] < xmin) xmin = px[i];
|
|
40065
|
+
if (py[i] > ymax) ymax = py[i];
|
|
40066
|
+
else if (py[i] < ymin) ymin = py[i];
|
|
40067
|
+
}
|
|
40068
|
+
const xo = (xmax + xmin) / 2;
|
|
40069
|
+
const yo = (ymax + ymin) / 2;
|
|
40070
|
+
const dx = xmax - xo;
|
|
40071
|
+
const dy = ymax - yo;
|
|
40072
|
+
let r = scale * Math.sqrt(fma(dx, dx, dy * dy));
|
|
40073
|
+
if (r === 0) r = scale;
|
|
40074
|
+
return [
|
|
40075
|
+
[fma(r, SQRT3, xo), yo - r],
|
|
40076
|
+
[xo, fma(r, 2, yo)],
|
|
40077
|
+
[fma(-r, SQRT3, xo), yo - r]
|
|
40078
|
+
];
|
|
40079
|
+
}
|
|
40080
|
+
|
|
38413
40081
|
// src/layout/neato/cdt-surface.ts
|
|
38414
40082
|
var pairKey = (u, v) => u < v ? u * 1048576 + v : v * 1048576 + u;
|
|
38415
40083
|
var Cdt = class {
|
|
@@ -38920,27 +40588,15 @@ var Cdt = class {
|
|
|
38920
40588
|
return { nfaces: kept.length, faces, neigh };
|
|
38921
40589
|
}
|
|
38922
40590
|
};
|
|
38923
|
-
var SQRT3 = 1.7320508075688772;
|
|
38924
40591
|
function mkSurface(x, y, n, segs, nsegs) {
|
|
38925
40592
|
const px = x.slice(0, n);
|
|
38926
40593
|
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
40594
|
const s0 = n;
|
|
38942
|
-
|
|
38943
|
-
|
|
40595
|
+
const enc = gtsTriangleEnclosing(px, py, n, 100);
|
|
40596
|
+
for (const [ex, ey] of enc) {
|
|
40597
|
+
px.push(ex);
|
|
40598
|
+
py.push(ey);
|
|
40599
|
+
}
|
|
38944
40600
|
const cdt = new Cdt(px, py);
|
|
38945
40601
|
const cons = [];
|
|
38946
40602
|
for (let k = 0; k < nsegs; k++) {
|
|
@@ -38987,9 +40643,9 @@ function sharedEdge(faces, p3, q3) {
|
|
|
38987
40643
|
return { i: p1, j: p2 };
|
|
38988
40644
|
}
|
|
38989
40645
|
function addTriEdge(g, t, h, seg2) {
|
|
38990
|
-
const
|
|
40646
|
+
const dist5 = Math.sqrt(dist2(g.nodes[t].ctr, g.nodes[h].ctr));
|
|
38991
40647
|
const idx = g.edges.length;
|
|
38992
|
-
g.edges.push({ t, h, seg: seg2, dist:
|
|
40648
|
+
g.edges.push({ t, h, seg: seg2, dist: dist5 });
|
|
38993
40649
|
g.nodes[t].edges.push(idx);
|
|
38994
40650
|
g.nodes[h].edges.push(idx);
|
|
38995
40651
|
}
|
|
@@ -39793,8 +41449,8 @@ function ellipseTangentSlope(a, b, p) {
|
|
|
39793
41449
|
function circumscribedCorner(a, b, i, nsides) {
|
|
39794
41450
|
const angle0 = 2 * Math.PI * (i - 0.5) / nsides;
|
|
39795
41451
|
const angle1 = 2 * Math.PI * (i + 0.5) / nsides;
|
|
39796
|
-
const p0 = { x: a *
|
|
39797
|
-
const p1 = { x: a *
|
|
41452
|
+
const p0 = { x: a * libmCos(angle0), y: b * libmSin(angle0) };
|
|
41453
|
+
const p1 = { x: a * libmCos(angle1), y: b * libmSin(angle1) };
|
|
39798
41454
|
const m0 = ellipseTangentSlope(a, b, p0);
|
|
39799
41455
|
const m1 = ellipseTangentSlope(a, b, p1);
|
|
39800
41456
|
const x = (fms(p1.x, m1, fma(m0, p0.x, -p0.y)) + p1.y) / (m0 - m1);
|
|
@@ -42130,52 +43786,14 @@ function armPow(x, y) {
|
|
|
42130
43786
|
return expInline(ehi, elo, signBias);
|
|
42131
43787
|
}
|
|
42132
43788
|
|
|
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
43789
|
// src/layout/sfdp/quadtree.ts
|
|
42172
43790
|
function pointDistance(p1, o1, p2, o2, dim) {
|
|
42173
|
-
let
|
|
43791
|
+
let dist5 = 0;
|
|
42174
43792
|
for (let i = 0; i < dim; i++) {
|
|
42175
43793
|
const d = p1[o1 + i] - p2[o2 + i];
|
|
42176
|
-
|
|
43794
|
+
dist5 = fma(d, d, dist5);
|
|
42177
43795
|
}
|
|
42178
|
-
return Math.sqrt(
|
|
43796
|
+
return Math.sqrt(dist5);
|
|
42179
43797
|
}
|
|
42180
43798
|
function quadTreeNew(dim, center, width2, maxLevel) {
|
|
42181
43799
|
return {
|
|
@@ -42310,8 +43928,8 @@ function getSupernodesInternal(qt, bh, pt, ptOff, nodeid, out) {
|
|
|
42310
43928
|
l = l.next;
|
|
42311
43929
|
}
|
|
42312
43930
|
if (qt.qts !== null) {
|
|
42313
|
-
const
|
|
42314
|
-
if (qt.width < bh *
|
|
43931
|
+
const dist5 = pointDistance(qt.center, 0, pt, ptOff, dim);
|
|
43932
|
+
if (qt.width < bh * dist5) {
|
|
42315
43933
|
for (let i = 0; i < dim; i++) {
|
|
42316
43934
|
out.center[dim * out.nsuper + i] = qt.average[i];
|
|
42317
43935
|
}
|
|
@@ -42409,12 +44027,12 @@ function onedOptimizerTrain(opt, work) {
|
|
|
42409
44027
|
else optHill(opt, i);
|
|
42410
44028
|
}
|
|
42411
44029
|
function distance(x, dim, i, j) {
|
|
42412
|
-
let
|
|
44030
|
+
let dist5 = 0;
|
|
42413
44031
|
for (let k = 0; k < dim; k++) {
|
|
42414
44032
|
const d = x[i * dim + k] - x[j * dim + k];
|
|
42415
|
-
|
|
44033
|
+
dist5 = fma(d, d, dist5);
|
|
42416
44034
|
}
|
|
42417
|
-
return Math.sqrt(
|
|
44035
|
+
return Math.sqrt(dist5);
|
|
42418
44036
|
}
|
|
42419
44037
|
function distanceCropped(x, dim, i, j) {
|
|
42420
44038
|
return Math.max(distance(x, dim, i, j), MINDIST);
|
|
@@ -42422,16 +44040,16 @@ function distanceCropped(x, dim, i, j) {
|
|
|
42422
44040
|
function gatherLeaves(A3, p, checked, x, dim) {
|
|
42423
44041
|
const { ia, ja } = A3;
|
|
42424
44042
|
const leaves = [];
|
|
42425
|
-
let
|
|
44043
|
+
let dist5 = 0;
|
|
42426
44044
|
for (let j = ia[p]; j < ia[p + 1]; j++) {
|
|
42427
44045
|
const c = ja[j];
|
|
42428
44046
|
if (ia[c + 1] - ia[c] === 1) {
|
|
42429
44047
|
checked[c] = true;
|
|
42430
|
-
|
|
44048
|
+
dist5 += distance(x, dim, p, c);
|
|
42431
44049
|
leaves.push(c);
|
|
42432
44050
|
}
|
|
42433
44051
|
}
|
|
42434
|
-
return { leaves, avgDist:
|
|
44052
|
+
return { leaves, avgDist: dist5 / leaves.length };
|
|
42435
44053
|
}
|
|
42436
44054
|
function beautifyLeaves(dim, A3, x) {
|
|
42437
44055
|
const { ia, ja, m } = A3;
|
|
@@ -42454,7 +44072,7 @@ function beautifyLeaves(dim, A3, x) {
|
|
|
42454
44072
|
}
|
|
42455
44073
|
}
|
|
42456
44074
|
function averageEdgeLength(A3, dim, coord) {
|
|
42457
|
-
let
|
|
44075
|
+
let dist5 = 0;
|
|
42458
44076
|
const { ia, ja } = A3;
|
|
42459
44077
|
if (ia[A3.m] === 0) return 1;
|
|
42460
44078
|
for (let i = 0; i < A3.m; i++) {
|
|
@@ -42464,10 +44082,10 @@ function averageEdgeLength(A3, dim, coord) {
|
|
|
42464
44082
|
const dd = coord[dim * i + k] - coord[dim * ja[j]];
|
|
42465
44083
|
d = fma(dd, dd, d);
|
|
42466
44084
|
}
|
|
42467
|
-
|
|
44085
|
+
dist5 += Math.sqrt(d);
|
|
42468
44086
|
}
|
|
42469
44087
|
}
|
|
42470
|
-
return
|
|
44088
|
+
return dist5 / ia[A3.m];
|
|
42471
44089
|
}
|
|
42472
44090
|
function updateStep(adaptiveCooling, step, fnorm, fnorm0) {
|
|
42473
44091
|
if (!adaptiveCooling) return COOL * step;
|
|
@@ -42478,18 +44096,18 @@ function updateStep(adaptiveCooling, step, fnorm, fnorm0) {
|
|
|
42478
44096
|
}
|
|
42479
44097
|
return 0.99 * step / COOL;
|
|
42480
44098
|
}
|
|
42481
|
-
function repulsivePow(
|
|
42482
|
-
return armPow(
|
|
44099
|
+
function repulsivePow(dist5, p) {
|
|
44100
|
+
return armPow(dist5, 1 - p);
|
|
42483
44101
|
}
|
|
42484
44102
|
function attractiveForce(ctx, i) {
|
|
42485
44103
|
const { A: A3, x, dim, fp, f } = ctx;
|
|
42486
44104
|
const { ia, ja } = A3;
|
|
42487
44105
|
for (let j = ia[i]; j < ia[i + 1]; j++) {
|
|
42488
44106
|
if (ja[j] === i) continue;
|
|
42489
|
-
const
|
|
44107
|
+
const dist5 = distance(x, dim, i, ja[j]);
|
|
42490
44108
|
for (let k = 0; k < dim; k++) {
|
|
42491
44109
|
const t = fp.CRK * (x[i * dim + k] - x[ja[j] * dim + k]);
|
|
42492
|
-
f[k] = fma(-t,
|
|
44110
|
+
f[k] = fma(-t, dist5, f[k]);
|
|
42493
44111
|
}
|
|
42494
44112
|
}
|
|
42495
44113
|
}
|
|
@@ -42497,9 +44115,9 @@ function repulsiveForceDirect(ctx, i) {
|
|
|
42497
44115
|
const { x, dim, n, fp, f } = ctx;
|
|
42498
44116
|
for (let j = 0; j < n; j++) {
|
|
42499
44117
|
if (j === i) continue;
|
|
42500
|
-
const
|
|
44118
|
+
const dist5 = distanceCropped(x, dim, i, j);
|
|
42501
44119
|
for (let k = 0; k < dim; k++) {
|
|
42502
|
-
f[k] += fp.KP * (x[i * dim + k] - x[j * dim + k]) / repulsivePow(
|
|
44120
|
+
f[k] += fp.KP * (x[i * dim + k] - x[j * dim + k]) / repulsivePow(dist5, fp.p);
|
|
42503
44121
|
}
|
|
42504
44122
|
}
|
|
42505
44123
|
}
|
|
@@ -42509,9 +44127,9 @@ function repulsiveForceQT(ctx, qt, i, acc) {
|
|
|
42509
44127
|
acc.countsAvg += counts;
|
|
42510
44128
|
acc.nsuperAvg += nsuper;
|
|
42511
44129
|
for (let j = 0; j < nsuper; j++) {
|
|
42512
|
-
const
|
|
44130
|
+
const dist5 = Math.max(distances[j], MINDIST);
|
|
42513
44131
|
for (let k = 0; k < dim; k++) {
|
|
42514
|
-
f[k] += supernodeWgts[j] * fp.KP * (x[i * dim + k] - center[j * dim + k]) / repulsivePow(
|
|
44132
|
+
f[k] += supernodeWgts[j] * fp.KP * (x[i * dim + k] - center[j * dim + k]) / repulsivePow(dist5, fp.p);
|
|
42515
44133
|
}
|
|
42516
44134
|
}
|
|
42517
44135
|
}
|
|
@@ -42767,7 +44385,7 @@ function diagPreconNew(A3) {
|
|
|
42767
44385
|
}
|
|
42768
44386
|
return diag;
|
|
42769
44387
|
}
|
|
42770
|
-
function
|
|
44388
|
+
function conjugateGradient2(A3, precon, n, x, rhs, tol, maxit) {
|
|
42771
44389
|
let rho = 0;
|
|
42772
44390
|
let rhoOld = 1;
|
|
42773
44391
|
let iter = 0;
|
|
@@ -42808,7 +44426,7 @@ function smSolve(A3, dim, x0, rhs, tol, maxit) {
|
|
|
42808
44426
|
x[i] = x0[i * dim + k];
|
|
42809
44427
|
b[i] = rhs[i * dim + k];
|
|
42810
44428
|
}
|
|
42811
|
-
res +=
|
|
44429
|
+
res += conjugateGradient2(A3, precond, n, x, b, tol, maxit);
|
|
42812
44430
|
for (let i = 0; i < n; i++) {
|
|
42813
44431
|
rhs[i * dim + k] = x[i];
|
|
42814
44432
|
}
|
|
@@ -43162,7 +44780,7 @@ function idealDistanceAvoidOverlap(dim, A3, x, width2, idealDistance) {
|
|
|
43162
44780
|
for (let j = ia[i]; j < ia[i + 1]; j++) {
|
|
43163
44781
|
const jj = ja[j];
|
|
43164
44782
|
if (jj === i) continue;
|
|
43165
|
-
const
|
|
44783
|
+
const dist5 = distance(x, dim, i, jj);
|
|
43166
44784
|
const dx = Math.abs(x[i * dim] - x[jj * dim]);
|
|
43167
44785
|
const dy = Math.abs(x[i * dim + 1] - x[jj * dim + 1]);
|
|
43168
44786
|
const wx = width2[i * dim] + width2[jj * dim];
|
|
@@ -43185,9 +44803,9 @@ function idealDistanceAvoidOverlap(dim, A3, x, width2, idealDistance) {
|
|
|
43185
44803
|
t = Math.min(expandmax, t);
|
|
43186
44804
|
t = Math.max(expandmin, t);
|
|
43187
44805
|
if (t > 1) {
|
|
43188
|
-
idealDistance[j] = t *
|
|
44806
|
+
idealDistance[j] = t * dist5;
|
|
43189
44807
|
} else {
|
|
43190
|
-
idealDistance[j] = -t *
|
|
44808
|
+
idealDistance[j] = -t * dist5;
|
|
43191
44809
|
}
|
|
43192
44810
|
}
|
|
43193
44811
|
}
|
|
@@ -43282,9 +44900,9 @@ function overlapSmootherNew(m, dim, x, width2, neighborhoodOnly, shrink) {
|
|
|
43282
44900
|
w[j] = -1 / d[j] / d[j];
|
|
43283
44901
|
d[j] = -d[j];
|
|
43284
44902
|
}
|
|
43285
|
-
const
|
|
44903
|
+
const dist5 = d[j];
|
|
43286
44904
|
diagW += w[j];
|
|
43287
|
-
d[j] = w[j] *
|
|
44905
|
+
d[j] = w[j] * dist5;
|
|
43288
44906
|
diagD += d[j];
|
|
43289
44907
|
}
|
|
43290
44908
|
w[jdiag] = -diagW;
|
|
@@ -43295,11 +44913,11 @@ function overlapSmootherNew(m, dim, x, width2, neighborhoodOnly, shrink) {
|
|
|
43295
44913
|
function totalDistance(m, dim, x, y) {
|
|
43296
44914
|
let total = 0;
|
|
43297
44915
|
for (let i = 0; i < m; i++) {
|
|
43298
|
-
let
|
|
44916
|
+
let dist5 = 0;
|
|
43299
44917
|
for (let j = 0; j < dim; j++) {
|
|
43300
|
-
|
|
44918
|
+
dist5 += (y[i * dim + j] - x[i * dim + j]) * (y[i * dim + j] - x[i * dim + j]);
|
|
43301
44919
|
}
|
|
43302
|
-
total += Math.sqrt(
|
|
44920
|
+
total += Math.sqrt(dist5);
|
|
43303
44921
|
}
|
|
43304
44922
|
return total;
|
|
43305
44923
|
}
|
|
@@ -43332,18 +44950,18 @@ function stressMajorizationSmooth(sm, dim, x, maxitSm) {
|
|
|
43332
44950
|
idiag = j;
|
|
43333
44951
|
continue;
|
|
43334
44952
|
}
|
|
43335
|
-
let
|
|
44953
|
+
let dist5 = distance(x, dim, i, jd[j]);
|
|
43336
44954
|
if (d[j] === 0) {
|
|
43337
44955
|
dd[j] = 0;
|
|
43338
44956
|
} else {
|
|
43339
|
-
if (
|
|
44957
|
+
if (dist5 === 0) {
|
|
43340
44958
|
const dij = d[j] / Lw.a[j];
|
|
43341
44959
|
for (let k = 0; k < dim; k++) {
|
|
43342
44960
|
x[jd[j] * dim + k] += 1e-4 * (cdrand() + 1e-4) * dij;
|
|
43343
44961
|
}
|
|
43344
|
-
|
|
44962
|
+
dist5 = distance(x, dim, i, jd[j]);
|
|
43345
44963
|
}
|
|
43346
|
-
dd[j] = d[j] /
|
|
44964
|
+
dd[j] = d[j] / dist5;
|
|
43347
44965
|
}
|
|
43348
44966
|
diag += dd[j];
|
|
43349
44967
|
}
|
|
@@ -43362,9 +44980,9 @@ function stressMajorizationSmooth(sm, dim, x, maxitSm) {
|
|
|
43362
44980
|
return diff;
|
|
43363
44981
|
}
|
|
43364
44982
|
function scaleToEdgeLength(dim, A3, x, avgLabelSize) {
|
|
43365
|
-
let
|
|
43366
|
-
|
|
43367
|
-
for (let i = 0; i < dim * A3.m; i++) x[i] *=
|
|
44983
|
+
let dist5 = averageEdgeLength(A3, dim, x);
|
|
44984
|
+
dist5 = avgLabelSize / Math.max(dist5, MACHINEACC);
|
|
44985
|
+
for (let i = 0; i < dim * A3.m; i++) x[i] *= dist5;
|
|
43368
44986
|
}
|
|
43369
44987
|
function removeOverlapPrism(dim, A3, x, labelSizes, ntry, initialScaling, doShrinking) {
|
|
43370
44988
|
if (!labelSizes) return;
|
|
@@ -43731,7 +45349,7 @@ function makeHasEdge(g) {
|
|
|
43731
45349
|
}
|
|
43732
45350
|
return (a, b) => pairs.get(a)?.has(b) === true || undirected && pairs.get(b)?.has(a) === true;
|
|
43733
45351
|
}
|
|
43734
|
-
function mkNConstraintG(g, list, intersect,
|
|
45352
|
+
function mkNConstraintG(g, list, intersect, dist5) {
|
|
43735
45353
|
const cg = newCg();
|
|
43736
45354
|
const flat = flatten(list);
|
|
43737
45355
|
let lastn;
|
|
@@ -43748,7 +45366,7 @@ function mkNConstraintG(g, list, intersect, dist4) {
|
|
|
43748
45366
|
const nxp = flat[j];
|
|
43749
45367
|
if (!intersect(p, nxp)) continue;
|
|
43750
45368
|
const e = cgEdge(cg, cnodeOf(p), cnodeOf(nxp));
|
|
43751
|
-
e.info.minlen =
|
|
45369
|
+
e.info.minlen = dist5(p.bb, nxp.bb);
|
|
43752
45370
|
e.info.weight = hasEdge(p.np, nxp.np) ? 100 : 1;
|
|
43753
45371
|
created.push(e);
|
|
43754
45372
|
}
|
|
@@ -43795,12 +45413,12 @@ function buildVisibility(flat, intersect) {
|
|
|
43795
45413
|
}
|
|
43796
45414
|
return vg;
|
|
43797
45415
|
}
|
|
43798
|
-
function mapGraphs(vg, flat, cg,
|
|
45416
|
+
function mapGraphs(vg, flat, cg, dist5) {
|
|
43799
45417
|
for (let i = 0; i < flat.length; i++) {
|
|
43800
45418
|
const tp = flat[i];
|
|
43801
45419
|
for (const j of vg[i]) {
|
|
43802
45420
|
const hp = flat[j];
|
|
43803
|
-
const delta2 =
|
|
45421
|
+
const delta2 = dist5(tp.bb, hp.bb);
|
|
43804
45422
|
const ce = cgEdge(cg, cnodeOf(tp), cnodeOf(hp));
|
|
43805
45423
|
ce.info.weight = 1;
|
|
43806
45424
|
if ((ce.info.minlen ?? 0) < delta2) {
|
|
@@ -43810,15 +45428,15 @@ function mapGraphs(vg, flat, cg, dist4) {
|
|
|
43810
45428
|
}
|
|
43811
45429
|
}
|
|
43812
45430
|
}
|
|
43813
|
-
function mkConstraintG(list, intersect,
|
|
45431
|
+
function mkConstraintG(list, intersect, dist5) {
|
|
43814
45432
|
const cg = newCg();
|
|
43815
45433
|
const flat = flatten(list);
|
|
43816
45434
|
buildChain(cg, flat);
|
|
43817
|
-
mapGraphs(buildVisibility(flat, intersect), flat, cg,
|
|
45435
|
+
mapGraphs(buildVisibility(flat, intersect), flat, cg, dist5);
|
|
43818
45436
|
return cg;
|
|
43819
45437
|
}
|
|
43820
|
-
function buildConstraintGraph(g, list, ifn,
|
|
43821
|
-
return ortho ? mkConstraintG(list, ifn,
|
|
45438
|
+
function buildConstraintGraph(g, list, ifn, dist5, ortho) {
|
|
45439
|
+
return ortho ? mkConstraintG(list, ifn, dist5) : mkNConstraintG(g, list, ifn, dist5);
|
|
43822
45440
|
}
|
|
43823
45441
|
function newItems() {
|
|
43824
45442
|
return new DtBag((p) => p.val, cmpitem);
|
|
@@ -43959,7 +45577,7 @@ function inflatePts(verts, xmargin, ymargin) {
|
|
|
43959
45577
|
v.y *= ymargin;
|
|
43960
45578
|
}
|
|
43961
45579
|
}
|
|
43962
|
-
function
|
|
45580
|
+
function isBox3(verts) {
|
|
43963
45581
|
if (verts.length !== 4) return false;
|
|
43964
45582
|
const [v0, v1, v2, v3] = verts;
|
|
43965
45583
|
if (v0.y === v1.y) {
|
|
@@ -44019,7 +45637,7 @@ function clusterVerts(n, xmargin, ymargin) {
|
|
|
44019
45637
|
function polyKind(n, poly, verts) {
|
|
44020
45638
|
const name = shapeName(n);
|
|
44021
45639
|
if (name === "box") return POLY_BOX;
|
|
44022
|
-
if (name === "polygon" &&
|
|
45640
|
+
if (name === "polygon" && isBox3(verts)) return POLY_BOX;
|
|
44023
45641
|
if (poly.sides < 3 && poly.regular) return POLY_CIRCLE;
|
|
44024
45642
|
return 0;
|
|
44025
45643
|
}
|
|
@@ -44527,7 +46145,7 @@ function heapSiftUp(h, i) {
|
|
|
44527
46145
|
i = parent2;
|
|
44528
46146
|
}
|
|
44529
46147
|
}
|
|
44530
|
-
function
|
|
46148
|
+
function heapSiftDown2(h, i) {
|
|
44531
46149
|
const n = h.length;
|
|
44532
46150
|
for (; ; ) {
|
|
44533
46151
|
let smallest = i;
|
|
@@ -44544,7 +46162,7 @@ function heapSiftDown3(h, i) {
|
|
|
44544
46162
|
}
|
|
44545
46163
|
function makeHeap(h) {
|
|
44546
46164
|
for (let i = (h.length >> 1) - 1; i >= 0; i--) {
|
|
44547
|
-
|
|
46165
|
+
heapSiftDown2(h, i);
|
|
44548
46166
|
}
|
|
44549
46167
|
}
|
|
44550
46168
|
function heapFindMin(h) {
|
|
@@ -44553,7 +46171,7 @@ function heapFindMin(h) {
|
|
|
44553
46171
|
function heapDeleteMin(h) {
|
|
44554
46172
|
h[0] = h[h.length - 1];
|
|
44555
46173
|
h.pop();
|
|
44556
|
-
if (h.length > 0)
|
|
46174
|
+
if (h.length > 0) heapSiftDown2(h, 0);
|
|
44557
46175
|
}
|
|
44558
46176
|
function heapInsert(h, c) {
|
|
44559
46177
|
h.push(c);
|
|
@@ -44637,27 +46255,27 @@ var Block = class _Block {
|
|
|
44637
46255
|
* @see lib/vpsc/block.cpp: Block::merge(Block* b, Constraint* c)
|
|
44638
46256
|
*/
|
|
44639
46257
|
mergeTwoArg(b, c) {
|
|
44640
|
-
const
|
|
46258
|
+
const dist5 = c.right.offset - c.left.offset - c.gap;
|
|
44641
46259
|
let l = c.left.block;
|
|
44642
46260
|
let r = c.right.block;
|
|
44643
46261
|
if (this.vars.length < b.vars.length) {
|
|
44644
|
-
r.mergeInto(l, c,
|
|
46262
|
+
r.mergeInto(l, c, dist5);
|
|
44645
46263
|
} else {
|
|
44646
|
-
l.mergeInto(r, c, -
|
|
46264
|
+
l.mergeInto(r, c, -dist5);
|
|
44647
46265
|
}
|
|
44648
46266
|
}
|
|
44649
46267
|
/**
|
|
44650
46268
|
* Merge block b into this across constraint c by dist.
|
|
44651
46269
|
* @see lib/vpsc/block.cpp: Block::merge(Block *b, Constraint *c, double dist)
|
|
44652
46270
|
*/
|
|
44653
|
-
mergeInto(b, c,
|
|
46271
|
+
mergeInto(b, c, dist5) {
|
|
44654
46272
|
c.active = true;
|
|
44655
|
-
this.wposn += b.wposn -
|
|
46273
|
+
this.wposn += b.wposn - dist5 * b.weight;
|
|
44656
46274
|
this.weight += b.weight;
|
|
44657
46275
|
this.posn = this.wposn / this.weight;
|
|
44658
46276
|
for (const v of b.vars) {
|
|
44659
46277
|
v.block = this;
|
|
44660
|
-
v.offset +=
|
|
46278
|
+
v.offset += dist5;
|
|
44661
46279
|
this.vars.push(v);
|
|
44662
46280
|
}
|
|
44663
46281
|
b.deleted = true;
|
|
@@ -44946,13 +46564,13 @@ var Blocks = class {
|
|
|
44946
46564
|
r.deleteMinInConstraint();
|
|
44947
46565
|
let l = c.left.block;
|
|
44948
46566
|
if (l.in.length === 0) l.setUpInConstraints();
|
|
44949
|
-
let
|
|
46567
|
+
let dist5 = c.right.offset - c.left.offset - c.gap;
|
|
44950
46568
|
if (r.vars.length < l.vars.length) {
|
|
44951
|
-
|
|
46569
|
+
dist5 = -dist5;
|
|
44952
46570
|
[l, r] = [r, l];
|
|
44953
46571
|
}
|
|
44954
46572
|
this.timeCtr.value++;
|
|
44955
|
-
r.mergeInto(l, c,
|
|
46573
|
+
r.mergeInto(l, c, dist5);
|
|
44956
46574
|
r.mergeIn(l);
|
|
44957
46575
|
r.timeStamp = this.timeCtr.value;
|
|
44958
46576
|
this.removeBlock(l);
|
|
@@ -44970,12 +46588,12 @@ var Blocks = class {
|
|
|
44970
46588
|
l.deleteMinOutConstraint();
|
|
44971
46589
|
let r = c.right.block;
|
|
44972
46590
|
r.setUpOutConstraints();
|
|
44973
|
-
let
|
|
46591
|
+
let dist5 = c.left.offset + c.gap - c.right.offset;
|
|
44974
46592
|
if (l.vars.length > r.vars.length) {
|
|
44975
|
-
|
|
46593
|
+
dist5 = -dist5;
|
|
44976
46594
|
[l, r] = [r, l];
|
|
44977
46595
|
}
|
|
44978
|
-
l.mergeInto(r, c,
|
|
46596
|
+
l.mergeInto(r, c, dist5);
|
|
44979
46597
|
l.mergeOut(r);
|
|
44980
46598
|
this.removeBlock(r);
|
|
44981
46599
|
c = l.findMinOutConstraint();
|
|
@@ -45491,7 +47109,7 @@ function warnUnrecognizedOverlap(flag) {
|
|
|
45491
47109
|
const s = flag.toLowerCase();
|
|
45492
47110
|
if (s.startsWith("prism") || NAMED_MODES.has(s)) return;
|
|
45493
47111
|
if (mapBoolDflt(flag, false) === mapBoolDflt(flag, true)) return;
|
|
45494
|
-
|
|
47112
|
+
agwarningf(`Unrecognized overlap value "${flag}" - using false`);
|
|
45495
47113
|
}
|
|
45496
47114
|
function getAdjustMode(flag) {
|
|
45497
47115
|
warnUnrecognizedOverlap(flag);
|
|
@@ -45524,7 +47142,7 @@ function adjustLate(g, am) {
|
|
|
45524
47142
|
case AM_VPSC:
|
|
45525
47143
|
return vpscAdjust(g);
|
|
45526
47144
|
default:
|
|
45527
|
-
|
|
47145
|
+
agwarningf(`Unhandled adjust option ${am.print}`);
|
|
45528
47146
|
return 0;
|
|
45529
47147
|
}
|
|
45530
47148
|
}
|
|
@@ -46498,20 +48116,20 @@ function coincidentDelta() {
|
|
|
46498
48116
|
} while (xdelta === 0 && ydelta === 0);
|
|
46499
48117
|
return { xdelta, ydelta };
|
|
46500
48118
|
}
|
|
46501
|
-
function doRep(p, q, xdelta, ydelta,
|
|
48119
|
+
function doRep(p, q, xdelta, ydelta, dist5) {
|
|
46502
48120
|
let force;
|
|
46503
|
-
if (!(
|
|
48121
|
+
if (!(dist5 > 0)) {
|
|
46504
48122
|
const d = coincidentDelta();
|
|
46505
48123
|
xdelta = d.xdelta;
|
|
46506
48124
|
ydelta = d.ydelta;
|
|
46507
|
-
|
|
48125
|
+
dist5 = libmHypot(xdelta, ydelta);
|
|
46508
48126
|
}
|
|
46509
|
-
if (
|
|
48127
|
+
if (dist5 > fdpParms.Mlimit) {
|
|
46510
48128
|
force = 0;
|
|
46511
48129
|
} else if (parms.useNew) {
|
|
46512
|
-
force = parms.K * parms.K / (
|
|
48130
|
+
force = parms.K * parms.K / (dist5 * dist5 * dist5);
|
|
46513
48131
|
} else {
|
|
46514
|
-
force = parms.K * parms.K / (
|
|
48132
|
+
force = parms.K * parms.K / (dist5 * dist5);
|
|
46515
48133
|
}
|
|
46516
48134
|
if (isPort(p) && isPort(q)) force *= 10;
|
|
46517
48135
|
const dq = disp(q);
|
|
@@ -46533,8 +48151,8 @@ function doNeighbor(grid2, i, j, nodes) {
|
|
|
46533
48151
|
for (const q of cellp.nodes) {
|
|
46534
48152
|
const xdelta = q.info.pos[0] - p.info.pos[0];
|
|
46535
48153
|
const ydelta = q.info.pos[1] - p.info.pos[1];
|
|
46536
|
-
const
|
|
46537
|
-
if (
|
|
48154
|
+
const dist5 = libmHypot(xdelta, ydelta);
|
|
48155
|
+
if (dist5 < parms.Cell) doRep(p, q, xdelta, ydelta, dist5);
|
|
46538
48156
|
}
|
|
46539
48157
|
}
|
|
46540
48158
|
}
|
|
@@ -46566,12 +48184,12 @@ function applyAttr(p, q, e) {
|
|
|
46566
48184
|
ydelta = d.ydelta;
|
|
46567
48185
|
dist22 = fma(xdelta, xdelta, ydelta * ydelta);
|
|
46568
48186
|
}
|
|
46569
|
-
const
|
|
48187
|
+
const dist5 = Math.sqrt(dist22);
|
|
46570
48188
|
let force;
|
|
46571
48189
|
if (parms.useNew) {
|
|
46572
|
-
force = (e.info.factor ?? 1) * (
|
|
48190
|
+
force = (e.info.factor ?? 1) * (dist5 - (e.info.dist ?? 1)) / dist5;
|
|
46573
48191
|
} else {
|
|
46574
|
-
force = (e.info.factor ?? 1) *
|
|
48192
|
+
force = (e.info.factor ?? 1) * dist5 / (e.info.dist ?? 1);
|
|
46575
48193
|
}
|
|
46576
48194
|
const dq = disp(q);
|
|
46577
48195
|
const dp = disp(p);
|
|
@@ -46746,16 +48364,16 @@ function cntOverlaps(g) {
|
|
|
46746
48364
|
function applyRep2(p, q, rs) {
|
|
46747
48365
|
let xdelta = q.info.pos[0] - p.info.pos[0];
|
|
46748
48366
|
let ydelta = q.info.pos[1] - p.info.pos[1];
|
|
46749
|
-
let
|
|
46750
|
-
if (!(
|
|
48367
|
+
let dist5 = libmHypot(xdelta, ydelta);
|
|
48368
|
+
if (!(dist5 > 0)) {
|
|
46751
48369
|
const d = coincidentDelta();
|
|
46752
48370
|
xdelta = d.xdelta;
|
|
46753
48371
|
ydelta = d.ydelta;
|
|
46754
|
-
|
|
48372
|
+
dist5 = libmHypot(xdelta, ydelta);
|
|
46755
48373
|
}
|
|
46756
48374
|
const ov = overlap4(p, q) ? 1 : 0;
|
|
46757
|
-
let force = ov ? rs.ov / (
|
|
46758
|
-
if (
|
|
48375
|
+
let force = ov ? rs.ov / (dist5 * dist5) : rs.nonov / (dist5 * dist5);
|
|
48376
|
+
if (dist5 > fdpParms.Mlimit) force = 0;
|
|
46759
48377
|
const dq = disp(q);
|
|
46760
48378
|
const dp = disp(p);
|
|
46761
48379
|
dq[0] = fma(xdelta, force, dq[0]);
|
|
@@ -46768,10 +48386,10 @@ function applyAttr2(p, q) {
|
|
|
46768
48386
|
if (overlap4(p, q)) return;
|
|
46769
48387
|
const xdelta = q.info.pos[0] - p.info.pos[0];
|
|
46770
48388
|
const ydelta = q.info.pos[1] - p.info.pos[1];
|
|
46771
|
-
const
|
|
48389
|
+
const dist5 = libmHypot(xdelta, ydelta);
|
|
46772
48390
|
const din = rad(p) + rad(q);
|
|
46773
|
-
const dout =
|
|
46774
|
-
const force = dout * dout / ((xParams.K + din) *
|
|
48391
|
+
const dout = dist5 - din;
|
|
48392
|
+
const force = dout * dout / ((xParams.K + din) * dist5);
|
|
46775
48393
|
const dq = disp(q);
|
|
46776
48394
|
const dp = disp(p);
|
|
46777
48395
|
dq[0] = fms(xdelta, force, dq[0]);
|
|
@@ -47926,9 +49544,9 @@ function pcpRotate(n, dim, x) {
|
|
|
47926
49544
|
axis[0] = -(-y[0] + y[3] - Math.sqrt(radicand)) / (2 * y[1]);
|
|
47927
49545
|
axis[1] = 1;
|
|
47928
49546
|
}
|
|
47929
|
-
const
|
|
47930
|
-
axis[0] = axis[0] /
|
|
47931
|
-
axis[1] = axis[1] /
|
|
49547
|
+
const dist5 = Math.sqrt(fma(axis[0], axis[0], 1));
|
|
49548
|
+
axis[0] = axis[0] / dist5;
|
|
49549
|
+
axis[1] = axis[1] / dist5;
|
|
47932
49550
|
for (let i = 0; i < n; i++) {
|
|
47933
49551
|
const x0 = fma(x[dim * i], axis[0], x[dim * i + 1] * axis[1]);
|
|
47934
49552
|
const x1 = fma(-x[dim * i], axis[1], x[dim * i + 1] * axis[0]);
|
|
@@ -48341,10 +49959,10 @@ function buildSpanTree(nodes, edges) {
|
|
|
48341
49959
|
}
|
|
48342
49960
|
return map;
|
|
48343
49961
|
}
|
|
48344
|
-
function measureDist(leaf, anc,
|
|
49962
|
+
function measureDist(leaf, anc, dist5, change) {
|
|
48345
49963
|
const p = anc.tparent;
|
|
48346
49964
|
if (!p) return;
|
|
48347
|
-
const d =
|
|
49965
|
+
const d = dist5 + 1;
|
|
48348
49966
|
if (p.distone === 0) {
|
|
48349
49967
|
p.leafone = leaf;
|
|
48350
49968
|
p.distone = d;
|
|
@@ -49844,11 +51462,11 @@ var DEFAULT_COLOR5 = "black";
|
|
|
49844
51462
|
var PENWIDTH_NORMAL4 = 1;
|
|
49845
51463
|
var PENWIDTH_THRESHOLD4 = 5e-3;
|
|
49846
51464
|
var EPS3 = 1e-5;
|
|
49847
|
-
function
|
|
51465
|
+
function dist4(a, b) {
|
|
49848
51466
|
return Math.sqrt(dist2(a, b));
|
|
49849
51467
|
}
|
|
49850
51468
|
function approxLen(list, off) {
|
|
49851
|
-
return
|
|
51469
|
+
return dist4(list[off], list[off + 1]) + dist4(list[off + 1], list[off + 2]) + dist4(list[off + 2], list[off + 3]);
|
|
49852
51470
|
}
|
|
49853
51471
|
function splitCubic(v, t) {
|
|
49854
51472
|
const left2 = [];
|
|
@@ -49927,7 +51545,7 @@ function drawSplitSpline(list, segs, job) {
|
|
|
49927
51545
|
return endColor;
|
|
49928
51546
|
}
|
|
49929
51547
|
function emitSplitEdgePaths(e, job, colorList) {
|
|
49930
|
-
const segs = parseSegs(colorList).segs;
|
|
51548
|
+
const segs = parseSegs(colorList, edgeSegsContext(e)).segs;
|
|
49931
51549
|
const firstColor2 = segs[0]?.color ?? DEFAULT_COLOR5;
|
|
49932
51550
|
const spl = e.info.spl;
|
|
49933
51551
|
let endColor = firstColor2;
|
|
@@ -49948,8 +51566,8 @@ var forfunc = (cur, total, init) => (1 - cur / total) * init / 2;
|
|
|
49948
51566
|
var revfunc = (cur, total, init) => cur / total * init / 2;
|
|
49949
51567
|
var nonefunc = (_cur, _total, init) => init / 2;
|
|
49950
51568
|
var bothfunc = (cur, total, init) => {
|
|
49951
|
-
const
|
|
49952
|
-
return
|
|
51569
|
+
const fr7 = cur / total;
|
|
51570
|
+
return fr7 <= 0.5 ? fr7 * init : (1 - fr7) * init;
|
|
49953
51571
|
};
|
|
49954
51572
|
function taperfun(dir, directed) {
|
|
49955
51573
|
if (dir === "forward") return forfunc;
|
|
@@ -51383,7 +53001,7 @@ var DotWriterBase = class {
|
|
|
51383
53001
|
|
|
51384
53002
|
// src/render/dot/edge-draw.ts
|
|
51385
53003
|
var DEFAULT_COLOR6 = "black";
|
|
51386
|
-
var
|
|
53004
|
+
var DEFAULT_LINE_STYLE2 = ["solid", "setlinewidth(1)"];
|
|
51387
53005
|
function emitArrowOp(buf, op, pen) {
|
|
51388
53006
|
switch (op.kind) {
|
|
51389
53007
|
case "polygon":
|
|
@@ -51418,8 +53036,9 @@ var EdgeDrawBase = class extends DotWriterBase {
|
|
|
51418
53036
|
*/
|
|
51419
53037
|
attachmentPolyline(pts, pencolor, job) {
|
|
51420
53038
|
const obj = job.obj;
|
|
53039
|
+
gvrenderSetStyle(DEFAULT_LINE_STYLE2);
|
|
51421
53040
|
if (obj !== null) {
|
|
51422
|
-
obj.rawStyle = [...
|
|
53041
|
+
obj.rawStyle = [...DEFAULT_LINE_STYLE2];
|
|
51423
53042
|
obj.pen = 3 /* Solid */;
|
|
51424
53043
|
obj.penWidth = 1;
|
|
51425
53044
|
obj.penColor = resolveRenderColor(pencolor.split(":")[0]);
|
|
@@ -51473,8 +53092,8 @@ var EdgeDrawBase = class extends DotWriterBase {
|
|
|
51473
53092
|
* under that segment's pen. Reuses the same split geometry
|
|
51474
53093
|
* (splitSplineByColor) as the SVG path. @see lib/common/emit.c:1975 multicolor
|
|
51475
53094
|
*/
|
|
51476
|
-
emitSplitSpline(bzList, colorAttr, edraw, job) {
|
|
51477
|
-
const segs = parseSegs(colorAttr).segs;
|
|
53095
|
+
emitSplitSpline(bzList, e, colorAttr, edraw, job) {
|
|
53096
|
+
const segs = parseSegs(colorAttr, edgeSegsContext(e)).segs;
|
|
51478
53097
|
const firstColor2 = segs[0]?.color ?? DEFAULT_COLOR6;
|
|
51479
53098
|
let endColor = firstColor2;
|
|
51480
53099
|
for (const bz of bzList) {
|
|
@@ -51497,7 +53116,7 @@ var EdgeDrawBase = class extends DotWriterBase {
|
|
|
51497
53116
|
const segData = bzList.map(
|
|
51498
53117
|
(bz) => bz !== void 0 && bz.size >= 4 ? buildOffsetLists(bz.list, (2 + numc) / 2) : { offlist: [], tmplist: [] }
|
|
51499
53118
|
);
|
|
51500
|
-
const colors =
|
|
53119
|
+
const colors = parseSegsSilent(colorAttr).segs.map((s) => s.color ?? DEFAULT_COLOR6);
|
|
51501
53120
|
for (const color of colors) {
|
|
51502
53121
|
const pen = xdotPenColor(resolveRenderColor(color));
|
|
51503
53122
|
for (const sd of segData) {
|
|
@@ -51653,7 +53272,7 @@ var XdotRenderer = class extends EdgeDrawBase {
|
|
|
51653
53272
|
let tailArrowColor;
|
|
51654
53273
|
let headArrowColor;
|
|
51655
53274
|
if (numsemi > 0 && numc > 0) {
|
|
51656
|
-
const c = this.emitSplitSpline(spl.list, colorAttr, edraw, job);
|
|
53275
|
+
const c = this.emitSplitSpline(spl.list, e, colorAttr, edraw, job);
|
|
51657
53276
|
tailArrowColor = c.firstColor;
|
|
51658
53277
|
headArrowColor = c.endColor;
|
|
51659
53278
|
} else if (edgeIsTapered(e)) {
|
|
@@ -51889,66 +53508,6 @@ function svgTaperedEdge(e, job) {
|
|
|
51889
53508
|
svgArrowPolygons(e, job);
|
|
51890
53509
|
}
|
|
51891
53510
|
|
|
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
53511
|
// src/render/svg.ts
|
|
51953
53512
|
function emitMulticolorArrows(e, job, headColor, tailColor) {
|
|
51954
53513
|
const obj = job.obj;
|
|
@@ -52364,7 +53923,7 @@ function peg$parse(input, options) {
|
|
|
52364
53923
|
return s;
|
|
52365
53924
|
}
|
|
52366
53925
|
function peg$f13(t, m, attrs) {
|
|
52367
|
-
if (m) agwarningf("attribute macros not implemented"
|
|
53926
|
+
if (m) agwarningf("attribute macros not implemented");
|
|
52368
53927
|
return { type: "attr", target: t, attrs };
|
|
52369
53928
|
}
|
|
52370
53929
|
function peg$f14(a) {
|
|
@@ -56263,7 +57822,7 @@ function isPeggyError(err) {
|
|
|
56263
57822
|
function warnNumberAmbiguities(src, upTo) {
|
|
56264
57823
|
for (const a of scanNumberAmbiguities(src, Stripper.strip(src))) {
|
|
56265
57824
|
if (a.offset > upTo) break;
|
|
56266
|
-
agerrFinished(numberAmbiguityMessage(a)
|
|
57825
|
+
agerrFinished(numberAmbiguityMessage(a));
|
|
56267
57826
|
}
|
|
56268
57827
|
}
|
|
56269
57828
|
function parse(src) {
|