diff --git a/src/app/components/pb-schema/pb-schema.component.ts b/src/app/components/pb-schema/pb-schema.component.ts index 7f3f21e816f6c24e9da70af5c513cbff61c90e32..d9fc50026721b5fb84b773405dfaf5b35df111fb 100644 --- a/src/app/components/pb-schema/pb-schema.component.ts +++ b/src/app/components/pb-schema/pb-schema.component.ts @@ -122,7 +122,8 @@ export class PbSchemaComponent implements AfterViewInit, OnInit { /** * Builds a Mermaid graph text definition, using Nodes - * to represent basins as well as walls + * to represent basins as well as walls; sorts connexions + * to prevent lines crossings */ private graphDefinition() { this.existingWalls = {}; @@ -140,45 +141,104 @@ export class PbSchemaComponent implements AfterViewInit, OnInit { // debug if (this.model.children.length === 0) { - const b1 = new PbBassin(new PbBassinParams(0.1, 42)); + // EXEMPLE 1 (petit) + /* const b1 = new PbBassin(new PbBassinParams(0.1, 42)); this.model.addChild(b1); const b2 = new PbBassin(new PbBassinParams(0.15, 38)); this.model.addChild(b2); this.model.addChild(new PbCloison(undefined, b1)); this.model.addChild(new PbCloison(b1, b2)); this.model.addChild(new PbCloison(b2, undefined)); - this.model.addChild(new PbCloison(b1, undefined)); + this.model.addChild(new PbCloison(b1, undefined)); */ + + // EXEMPLE 2 (grand) + this.model.addChild(new PbBassin(new PbBassinParams(13.80, 95))); + this.model.addChild(new PbBassin(new PbBassinParams(15.40, 94.70))); + this.model.addChild(new PbBassin(new PbBassinParams(16.20, 94.70))); + this.model.addChild(new PbBassin(new PbBassinParams(17.50, 94.40))); + this.model.addChild(new PbBassin(new PbBassinParams(32.10, 94.25))); + this.model.addChild(new PbBassin(new PbBassinParams(35.00, 94.10))); + this.model.addChild(new PbCloison(undefined, this.model.children[0] as PbBassin)); + this.model.addChild(new PbCloison(undefined, this.model.children[1] as PbBassin)); + this.model.addChild(new PbCloison(undefined, this.model.children[4] as PbBassin)); + this.model.addChild(new PbCloison(undefined, this.model.children[5] as PbBassin)); + this.model.addChild(new PbCloison(this.model.children[0] as PbBassin, this.model.children[2] as PbBassin)); + this.model.addChild(new PbCloison(this.model.children[1] as PbBassin, this.model.children[2] as PbBassin)); + this.model.addChild(new PbCloison(this.model.children[1] as PbBassin, this.model.children[3] as PbBassin)); + this.model.addChild(new PbCloison(this.model.children[1] as PbBassin, this.model.children[4] as PbBassin)); + this.model.addChild(new PbCloison(this.model.children[2] as PbBassin, this.model.children[3] as PbBassin)); + this.model.addChild(new PbCloison(this.model.children[3] as PbBassin, this.model.children[4] as PbBassin)); + this.model.addChild(new PbCloison(this.model.children[4] as PbBassin, this.model.children[5] as PbBassin)); + this.model.addChild(new PbCloison(this.model.children[5] as PbBassin, undefined)); } + const sortedWalls: PbCloison[] = []; for (const c of this.model.children) { if (c instanceof PbBassin) { def.push(`${c.uid}("${this.itemDesription(c)}")`); // rounded edges def.push(`class ${c.uid} basin;`); } else if (c instanceof PbCloison) { - const upstreamBasinId = c.bassinAmont === undefined ? this.upstreamId : c.bassinAmont.uid; - const downstreamBasinId = c.bassinAval === undefined ? this.downstreamId : c.bassinAval.uid; - // record this wall - const basinsPair = upstreamBasinId + "-" + downstreamBasinId; - if (! (basinsPair in this.existingWalls)) { - this.existingWalls[basinsPair] = 0; - } - // affect suffix if needed - if (this.existingWalls[basinsPair] > 0) { - this.wallsSuffixes[c.uid] = this.existingWalls[basinsPair]; - } - this.existingWalls[basinsPair]++; - // draw wall Node - def.push(`${c.uid}["${this.itemDesription(c)}"]`); // square edges - def.push(`class ${c.uid} wall;`); - // draw "arrow" with 2 lines - def.push(`${upstreamBasinId}---${c.uid}`); // up line - def.push(`${c.uid}-->${downstreamBasinId}`); // down arrow + // store, to draw later + sortedWalls.push(c); + } + } + // sort then draw walls + sortedWalls.sort(this.triCloisonsGaucheDroite); + for (const c of sortedWalls) { + const upstreamBasinId = c.bassinAmont === undefined ? this.upstreamId : c.bassinAmont.uid; + const downstreamBasinId = c.bassinAval === undefined ? this.downstreamId : c.bassinAval.uid; + // record this wall + const basinsPair = upstreamBasinId + "-" + downstreamBasinId; + if (! (basinsPair in this.existingWalls)) { + this.existingWalls[basinsPair] = 0; + } + // affect suffix if needed + if (this.existingWalls[basinsPair] > 0) { + this.wallsSuffixes[c.uid] = this.existingWalls[basinsPair]; } + this.existingWalls[basinsPair]++; + // draw wall Node + def.push(`${c.uid}["${this.itemDesription(c)}"]`); // square edges + def.push(`class ${c.uid} wall;`); + // draw "arrow" with 2 lines + def.push(`${upstreamBasinId}---${c.uid}-->${downstreamBasinId}`); } return def.join("\n"); } + /** gauche d'abord, droite ensuite */ + private triCloisonsGaucheDroite(a: PbCloison, b: PbCloison) { + // ultra-gauchistes + if (a.bassinAmont === undefined && a.bassinAval === undefined) { + return -1; + } + if (b.bassinAmont === undefined && b.bassinAval === undefined) { + return 1; + } + // si A est un super-gauchiste + if (a.bassinAmont === undefined || a.bassinAval === undefined) { + // B est-il aussi un super-gauchiste ? + if (b.bassinAmont === undefined || b.bassinAval === undefined) { + // comparer le bassin restant + const bassinA = (a.bassinAmont === undefined ? a.bassinAval : a.bassinAmont); + const bassinB = (b.bassinAmont === undefined ? b.bassinAval : b.bassinAmont); + return (bassinA.findPositionInParent() <= bassinB.findPositionInParent()) ? -1 : 1; + } + // sinon A gagne + return -1; + } + // si B est un super-gauchiste + if (b.bassinAmont === undefined || b.bassinAval === undefined) { + // B gagne (le cas de A super-gauchiste est éliminé avant) + return 1; + } + // sinon, aucun des deux n'est super-gauchiste, comparaison des bassins amont et aval + const sommeA = a.bassinAmont.findPositionInParent() + a.bassinAval.findPositionInParent(); + const sommeB = b.bassinAmont.findPositionInParent() + b.bassinAval.findPositionInParent(); + return (sommeA <= sommeB ? -1 : 1); + }; + private selectNode(item: any) { // highlight clicked element this.clearHighlightedItems();