diff --git a/bzGraflow.js b/bzGraflow.js index a7ea5ce..c1ddb07 100644 --- a/bzGraflow.js +++ b/bzGraflow.js @@ -59,11 +59,6 @@ class BZgraflow extends Buildoz{ } await this.loadNodes(flowObj.nodesFile) this.flow = flowObj.flow - - if(this.hasAnyLoop()) { - console.warn('This flow has loops.Optimization not available') - console.log('===Loops:===>', this.getLoopingLinks()) - } this.refresh() } @@ -198,7 +193,6 @@ class BZgraflow extends Buildoz{ if(this.hasAnyLoop(this.flow.nodes, this.flow.links)){ console.warn('Loop(s) detected... Cannot auto-place !') const backEdges = this.findBackEdges(this.flow.nodes, this.flow.links) - console.log('===BackEdges:===>', backEdges) linksWithoutBackEdges = this.flow.links.filter((link, idx) => (!backEdges.includes(idx)) && (link.from[0] != link.to[0])) } else { linksWithoutBackEdges = this.flow.links @@ -221,14 +215,14 @@ class BZgraflow extends Buildoz{ const layers = this.computeLayers(this.flow.nodes, parents) let maxHeight = 0; let maxWidth = 0 const layerHeights = []; const layerWidths = []; - const indexes = {} // Todo: a + const indexes = {} // indexes[nid] = { base: , ports: { [portId]: } } for(const layer of layers){ let totHeight = 0; let totWidth = 0 for(const [idx, nid] of layer.entries()){ const bb = this.stagedNodes[nid].getBoundingClientRect() totHeight += bb.height + gapy totWidth += bb.width + gapx - indexes[nid] = idx + indexes[nid] = { base: idx, ports: this.computePortOffsets(nid, orientation) } } if(totHeight>maxHeight) maxHeight = totHeight layerHeights.push(totHeight) @@ -236,7 +230,7 @@ class BZgraflow extends Buildoz{ layerWidths.push(totWidth) } - this.reorderLayers(layers, parents, indexes) + this.reorderLayers(layers, parents, indexes, orientation) if(orientation=='horizontal'){ let x = gapx @@ -263,17 +257,45 @@ class BZgraflow extends Buildoz{ x += gapx + bb.width } y += hMax + gapy - console.log(y, hMax, gapy ) } } } - reorderLayers(layers, parents, indexes){ + computePortOffsets(nid, orientation = 'horizontal'){ + const node = this.stagedNodes[nid] + if(!node || !node.ports) return({}) + const axis = (orientation === 'vertical') ? 'x' : 'y' + const nodeRect = node.getBoundingClientRect() + const ports = Object.entries(node.ports) + .map(([pid, p]) => { + const r = p.el.getBoundingClientRect() + const pos = (axis === 'x') + ? (r.left + (r.width / 2) - nodeRect.left) + : (r.top + (r.height / 2) - nodeRect.top) + return({ pid, pos }) + }) + .sort((a, b) => a.pos - b.pos) // smaller pos => "higher/left" => smaller offset + + const denom = ports.length + 1 + const offsets = {} + for(const [rank, item] of ports.entries()){ + offsets[item.pid] = rank / denom // always < 1 + } + return(offsets) + } + + reorderLayers(layers, parents, indexes, orientation = 'horizontal'){ const swap = (vect, todo) => { for(const s of todo){ [vect[s[0]], vect[s[1]]] = [vect[s[1]], vect[s[0]]] } } + const adjIndex = (nid, portId) => { + const info = indexes?.[nid] + const base = (info && info.base !== undefined) ? info.base : 0 + const off = (portId && info?.ports?.[portId] !== undefined) ? info.ports[portId] : 0 + return(base + off) + } for(const [lidx, layer] of layers.entries()){ if(lidx==0) continue const toSwap = [] @@ -284,7 +306,13 @@ class BZgraflow extends Buildoz{ for(let j=i+1; j layers[lidx-1].includes(nid))) - if(((indexes[pnid1] - indexes[pnid2]) * (indexes[nid1] - indexes[nid2])) < 0) { // crossing ! + const link1 = (pnid1) ? this.getLink(pnid1, nid1) : null + const link2 = (pnid2) ? this.getLink(pnid2, nid2) : null + const p1 = adjIndex(pnid1, link1?.from?.[1]) + const p2 = adjIndex(pnid2, link2?.from?.[1]) + const c1 = adjIndex(nid1, link1?.to?.[1]) + const c2 = adjIndex(nid2, link2?.to?.[1]) + if(((p1 - p2) * (c1 - c2)) < 0) { // crossing (now refined by per-port ordering) toSwap.push([i, j]) } }