From: Benjamin Auder <benjamin.auder@somewhere> Date: Wed, 31 Jan 2018 01:30:32 +0000 (+0100) Subject: Better graph rendering by randomizing appearances and links left/right in dot string X-Git-Url: https://git.auder.net/%7B%7B%20asset%28%27mixstore/images/assets/current/doc/%7B%7B%20pkg.url%20%7D%7D?a=commitdiff_plain;h=48a55161a22d169781fa3e0805ed2da7dac952cf;p=erdiag.git Better graph rendering by randomizing appearances and links left/right in dot string --- diff --git a/README.md b/README.md index 6352f4d..acf706e 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,9 @@ This parser reads ER diagrams definition files, and produces two types of diagra [Graphviz](https://www.graphviz.org/) is used on server side to translate parsed graph descriptions into SVG objects. *Note:* at the moment only the conceptual graph is implemented, and no comments are allowed in textual descriptions. -At least the former is planned, and also probably a way to indicate relative identifiers. +At least the former is planned, and also probably a way to indicate relative identifiers, and maybe links between relationships. + +*Note bis:* temporary dependency to [underscore](http://underscorejs.org/); good library but used so far only for its shuffle() method. ----- diff --git a/example.html b/example.html index 22d2d3a..dcb2fcd 100644 --- a/example.html +++ b/example.html @@ -1,5 +1,6 @@ <div id="test"></div> +<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script> <script src="parser.js"></script> <script> let er = diff --git a/parser.js b/parser.js index 8a4c524..ba113e5 100644 --- a/parser.js +++ b/parser.js @@ -177,6 +177,7 @@ class ErDiags } // "Modèle conceptuel des données". TODO: option for graph size + // NOTE: randomizing helps to obtain better graphs (sometimes) drawMcd(id, mcdStyle) //mcdStyle: bubble, or compact { let element = document.getElementById(id); @@ -188,8 +189,11 @@ class ErDiags } // Build dot graph input let mcdDot = 'graph {\n'; + mcdDot += 'rankdir="LR";\n'; // Nodes: - Object.keys(this.entities).forEach( name => { + if (mcdStyle == "compact") + mcdDot += "node [shape=plaintext];\n"; + _.shuffle(Object.keys(this.entities)).forEach( name => { if (mcdStyle == "bubble") { mcdDot += name + '[shape=rectangle, label="' + name + '"'; @@ -198,16 +202,20 @@ class ErDiags mcdDot += '];\n'; if (!!this.entities[name].attributes) { - this.entities[name].attributes.forEach( a => { + _.shuffle(this.entities[name].attributes).forEach( a => { let label = (a.isKey ? '#' : '') + a.name; - mcdDot += name + '_' + a.name + '[shape=ellipse, label="' + label + '"];\n'; - mcdDot += name + '_' + a.name + ' -- ' + name + ';\n'; + let attrName = name + '_' + a.name; + mcdDot += attrName + '[shape=ellipse, label="' + label + '"];\n'; + if (Math.random() < 0.5) + mcdDot += attrName + ' -- ' + name + ';\n'; + else + mcdDot += name + ' -- ' + attrName + ';\n'; }); } } else { - mcdDot += name + '[shape=plaintext, label=<'; + mcdDot += name + '[label=<'; if (this.entities[name].weak) { mcdDot += '<table port="name" BORDER="1" ALIGN="LEFT" CELLPADDING="0" CELLSPACING="3" CELLBORDER="0">' + @@ -231,13 +239,17 @@ class ErDiags }); // Inheritances: this.inheritances.forEach( i => { - i.children.forEach( c => { - mcdDot += c + ':name -- ' + i.parent + ':name [len="1.00", dir="forward", arrowhead="vee", style="dashed"];\n'; + _.shuffle(i.children).forEach( c => { + if (Math.random() < 0.5) + mcdDot += c + ':name -- ' + i.parent; + else + mcdDot += i.parent + ':name -- ' + c; + mcdDot += ':name [dir="forward", arrowhead="vee", style="dashed"];\n'; }); }); // Relationships: let assoceCounter = 0; - this.associations.forEach( a => { + _.shuffle(this.associations).forEach( a => { let name = !!a.name && a.name.length > 0 ? a.name : '_assoce' + assoceCounter++; @@ -245,20 +257,28 @@ class ErDiags if (a.weak) mcdDot += ', peripheries=2'; mcdDot += '];\n'; - a.entities.forEach( e => { - mcdDot += e.name + ':name -- ' + name + '[len="1.00", label="' + ErDiags.CARDINAL[e.card] + '"];\n'; + _.shuffle(a.entities).forEach( e => { + if (Math.random() < 0.5) + mcdDot += e.name + ':name -- ' + name; + else + mcdDot += name + ':name -- ' + e.name; + mcdDot += '[label="' + ErDiags.CARDINAL[e.card] + '"];\n'; }); if (!!a.attributes) { - a.attributes.forEach( attr => { + _.shuffle(a.attributes).forEach( attr => { let label = (attr.isKey ? '#' : '') + attr.name; - mcdDot += name + '_' + attr.name + '[len="1.00", shape=ellipse, label="' + label + '"];\n'; - mcdDot += name + '_' + attr.name + ' -- ' + name + ';\n'; + mcdDot += name + '_' + attr.name + '[shape=ellipse, label="' + label + '"];\n'; + let attrName = name + '_' + attr.name; + if (Math.random() < 0.5) + mcdDot += attrName + ' -- ' + name + ';\n'; + else + mcdDot += name + ' -- ' + attrName + ';\n'; }); } }); mcdDot += '}'; - //console.log(mcdDot); + console.log(mcdDot); ErDiags.AjaxGet(mcdDot, graphSvg => { this.mcdGraph = graphSvg; element.innerHTML = graphSvg; @@ -266,6 +286,7 @@ class ErDiags } // "Modèle logique des données" + // TODO: this one should draw links from foreign keys to keys (port=... in <TD>) drawMld(id) { let element = document.getElementById(id);