u
This commit is contained in:
@@ -711,6 +711,61 @@ function countSvgCrossings(svg) {
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Graphviz self-edges from a lower FK row to id:e dip southeast. Rebuild the
|
||||||
|
* spline so it bulges east + north (up) while keeping start/end ports.
|
||||||
|
* In this SVG, more-negative y is visually higher.
|
||||||
|
*/
|
||||||
|
function fixSelfLoopSvg(svg) {
|
||||||
|
return svg.replace(
|
||||||
|
/<g id="(edge\d+)" class="edge">\s*<title>(\w+):e->\2:e<\/title>\s*<g id="(a_edge\d+)"><a ([^>]+)>\s*<path([^>]*) d="([^"]+)"\/>\s*<polygon([^>]*) points="([^"]+)"\/>\s*<\/a>\s*<\/g>\s*<\/g>/g,
|
||||||
|
(match, edgeId, _table, aId, aAttrs, pathAttrs, d, polyAttrs) => {
|
||||||
|
const pts = [...d.matchAll(/([-\d.]+)[,\s]+([-\d.]+)/g)].map((m) => [
|
||||||
|
Number(m[1]),
|
||||||
|
Number(m[2]),
|
||||||
|
]);
|
||||||
|
if (pts.length < 2) return match;
|
||||||
|
|
||||||
|
const [x0, y0] = pts[0];
|
||||||
|
const [x1, y1] = pts[pts.length - 1];
|
||||||
|
const east = Math.max(x0, x1) + 36;
|
||||||
|
const north = Math.min(y0, y1) - 28;
|
||||||
|
|
||||||
|
// Cubic end tangent is P3-P2; orient arrow along that arrival direction.
|
||||||
|
const tx = x1 - east;
|
||||||
|
const ty = y1 - north;
|
||||||
|
const len = Math.hypot(tx, ty) || 1;
|
||||||
|
const dx = tx / len;
|
||||||
|
const dy = ty / len;
|
||||||
|
const arrowLen = 9;
|
||||||
|
const arrowHalf = 3.5;
|
||||||
|
const baseX = x1 - dx * arrowLen;
|
||||||
|
const baseY = y1 - dy * arrowLen;
|
||||||
|
const px = -dy * arrowHalf;
|
||||||
|
const py = dx * arrowHalf;
|
||||||
|
|
||||||
|
const fmt = (n) => (Math.round(n * 100) / 100).toString();
|
||||||
|
const newDFmt = `M${fmt(x0)},${fmt(y0)}C${fmt(east)},${fmt(y0)} ${fmt(east)},${fmt(north)} ${fmt(baseX)},${fmt(baseY)}`;
|
||||||
|
const newPointsFmt =
|
||||||
|
`${fmt(x1)},${fmt(y1)} ` +
|
||||||
|
`${fmt(baseX + px)},${fmt(baseY + py)} ` +
|
||||||
|
`${fmt(baseX - px)},${fmt(baseY - py)} ` +
|
||||||
|
`${fmt(x1)},${fmt(y1)}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
`<g id="${edgeId}" class="edge">\n` +
|
||||||
|
`<title>${_table}:e->${_table}:e</title>\n` +
|
||||||
|
`<g id="${aId}"><a ${aAttrs}>\n` +
|
||||||
|
`<path${pathAttrs} d="${newDFmt}"/>\n` +
|
||||||
|
`<polygon${polyAttrs} points="${newPointsFmt}"/>\n` +
|
||||||
|
`</a>\n` +
|
||||||
|
`</g>\n` +
|
||||||
|
`</g>`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const schemaSource = readFileSync(schemaPath, 'utf8');
|
const schemaSource = readFileSync(schemaPath, 'utf8');
|
||||||
const { tables, edges } = parseSchema(schemaSource);
|
const { tables, edges } = parseSchema(schemaSource);
|
||||||
|
|
||||||
@@ -742,7 +797,7 @@ for (let pass = 0; pass < 2; pass++) {
|
|||||||
const dot = buildDot(tables, edges, positions);
|
const dot = buildDot(tables, edges, positions);
|
||||||
writeFileSync(dotOutputPath, dot, 'utf8');
|
writeFileSync(dotOutputPath, dot, 'utf8');
|
||||||
|
|
||||||
const svg = graphviz.layout(dot, 'svg', 'dot');
|
const svg = fixSelfLoopSvg(graphviz.layout(dot, 'svg', 'dot'));
|
||||||
writeFileSync(outputPath, svg, 'utf8');
|
writeFileSync(outputPath, svg, 'utf8');
|
||||||
|
|
||||||
const dim = svg.match(/width="([\d.]+)pt" height="([\d.]+)pt"/);
|
const dim = svg.match(/width="([\d.]+)pt" height="([\d.]+)pt"/);
|
||||||
|
|||||||
@@ -670,8 +670,8 @@
|
|||||||
<g id="edge2" class="edge">
|
<g id="edge2" class="edge">
|
||||||
<title>category:e->category:e</title>
|
<title>category:e->category:e</title>
|
||||||
<g id="a_edge2"><a xlink:title="FK_category_parent">
|
<g id="a_edge2"><a xlink:title="FK_category_parent">
|
||||||
<path fill="none" stroke="#2f855a" stroke-width="1.4" d="M1699.9,-415.8C1721.23,-331.75 1747.9,-331.75 1747.9,-429.2 1747.9,-523.22 1723.07,-526.53 1702.17,-451.15"/>
|
<path fill="none" stroke="#2f855a" stroke-width="1.4" d="M1699.9,-415.8C1738.17,-415.8 1738.17,-479.15 1709.27,-456.68"/>
|
||||||
<polygon fill="#2f855a" stroke="#2f855a" stroke-width="1.4" points="1704.6,-450.79 1700.44,-444.65 1699.87,-452.04 1704.6,-450.79"/>
|
<polygon fill="#2f855a" stroke="#2f855a" stroke-width="1.4" points="1702.17,-451.15 1707.13,-459.44 1711.42,-453.91 1702.17,-451.15"/>
|
||||||
</a>
|
</a>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
@@ -753,8 +753,8 @@
|
|||||||
<g id="edge16" class="edge">
|
<g id="edge16" class="edge">
|
||||||
<title>article:e->article:e</title>
|
<title>article:e->article:e</title>
|
||||||
<g id="a_edge16"><a xlink:title="FK_article_fatherarticle">
|
<g id="a_edge16"><a xlink:title="FK_article_fatherarticle">
|
||||||
<path fill="none" stroke="#1a365d" stroke-width="1.4" d="M1990.58,-523C2011.91,-438.95 2038.58,-438.95 2038.58,-549.8 2038.58,-656.75 2013.75,-660.51 1992.85,-585.15"/>
|
<path fill="none" stroke="#1a365d" stroke-width="1.4" d="M1990.58,-523C2028.85,-523 2028.85,-613.15 1999.95,-590.68"/>
|
||||||
<polygon fill="#1a365d" stroke="#1a365d" stroke-width="1.4" points="1995.28,-584.79 1991.12,-578.65 1990.55,-586.04 1995.28,-584.79"/>
|
<polygon fill="#1a365d" stroke="#1a365d" stroke-width="1.4" points="1992.85,-585.15 1997.81,-593.44 2002.1,-587.91 1992.85,-585.15"/>
|
||||||
</a>
|
</a>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 134 KiB |
Reference in New Issue
Block a user