private getSvgPathForSelfLink()

in src/sankeyDiagram.ts [1959:2081]


    private getSvgPathForSelfLink(link: SankeyDiagramLink, minHeight: number) {
        let pathParams: string = "";
        const distanceBetweenLinks: number = 3;
        const distanceFromNodeToLinks: number = 5;

        let fixedLinkHeight = link.height - distanceBetweenLinks;

        if (this.dataView.settings.cyclesLinks.selfLinksWeight && this.dataView.settings.cyclesLinks.drawCycles === CyclesDrawType.Backward) {
            fixedLinkHeight = Math.min(link.destination.width, minHeight);
        }

        let linkKneeSize: number = Math.min(link.destination.width, minHeight);

        let x0: number,
            x1: number,
            xi: (t: number) => number,
            x2: number,
            x3: number,
            y0: number,
            y1: number;

        if (link.destination.x < link.source.x) {
            x0 = link.source.x;
            x1 = link.destination.x + link.destination.width;
        } else {
            x0 = link.source.x + link.source.width;
            x1 = link.destination.x;
        }

        // drawing area as combination of 4 lines in one path element of svg to fill this area with required color

        y0 = link.source.y
            - (fixedLinkHeight + SankeyDiagram.NodeAndBackwardLinkDistance)
            + link.dySource + (fixedLinkHeight) / SankeyDiagram.MiddleFactor
            - (fixedLinkHeight) / 2;
        y1 = link.destination.y
            - (fixedLinkHeight + SankeyDiagram.NodeAndBackwardLinkDistance)
            + (link.dyDestination || 0)
            + (fixedLinkHeight) / SankeyDiagram.MiddleFactor - (fixedLinkHeight) / 2;

        pathParams += `M ${x0} ${y0}`;

        pathParams += `L ${link.destination.x + link.destination.width} ${y1}`;

        pathParams +=
            `C ${link.destination.x + distanceFromNodeToLinks + link.destination.width} ${y1},` +
            ` ${link.destination.x + distanceFromNodeToLinks + link.destination.width + linkKneeSize} ${y1},` +
            ` ${link.destination.x + distanceFromNodeToLinks + link.destination.width + linkKneeSize} ${y1 + linkKneeSize}`;

        // right border of link
        y0 = link.destination.y - (fixedLinkHeight + SankeyDiagram.NodeAndBackwardLinkDistance)
            + (link.dyDestination || 0) + (fixedLinkHeight) / SankeyDiagram.MiddleFactor + (fixedLinkHeight - distanceBetweenLinks) / 2;
        y1 = link.destination.y - (fixedLinkHeight + SankeyDiagram.NodeAndBackwardLinkDistance)
            + (link.dyDestination || 0) + (fixedLinkHeight) / SankeyDiagram.MiddleFactor - (fixedLinkHeight - distanceBetweenLinks) / 2;

        let limit = y1 + link.destination.width + (fixedLinkHeight) * 2 - link.destination.width - distanceBetweenLinks;
        if (limit > link.destination.y + fixedLinkHeight - linkKneeSize - distanceBetweenLinks) {
            limit = link.destination.y + fixedLinkHeight - linkKneeSize - distanceBetweenLinks;
        }

        // tslint:disable-next-line: no-suspicious-comment
        pathParams += `L ${link.destination.x + distanceFromNodeToLinks + link.destination.width + linkKneeSize} ${limit}`; // TODO change to C

        pathParams +=
            `C ${link.destination.x + distanceFromNodeToLinks + link.destination.width + linkKneeSize} ` +
            `${link.destination.y + fixedLinkHeight - linkKneeSize}, ` +
            `${link.destination.x + link.destination.width + linkKneeSize} ${link.destination.y + fixedLinkHeight} ,` +
            `${link.destination.x + link.destination.width} ${link.destination.y + fixedLinkHeight}`;

        pathParams += `L ${link.destination.x + link.destination.width} ${link.destination.y + distanceBetweenLinks}`;

        pathParams += `C ${link.destination.x + link.destination.width} ${link.destination.y + distanceBetweenLinks},`;
        pathParams += `${link.destination.x + distanceFromNodeToLinks + link.destination.width} ${link.destination.y + distanceBetweenLinks},`;
        pathParams += `${link.destination.x + distanceFromNodeToLinks + link.destination.width} ${link.destination.y - SankeyDiagram.NodeAndBackwardLinkDistance / 2}`;
        pathParams += `L ${link.destination.x + distanceFromNodeToLinks + link.destination.width} ${link.destination.y - SankeyDiagram.NodeAndBackwardLinkDistance / 2}`;

        pathParams += `C ${link.destination.x + distanceFromNodeToLinks + link.destination.width} ${link.destination.y - SankeyDiagram.NodeAndBackwardLinkDistance / 2},`;
        pathParams += `${link.destination.x + distanceFromNodeToLinks + link.destination.width} ${link.destination.y - SankeyDiagram.NodeAndBackwardLinkDistance},`;
        pathParams += `${link.destination.x + link.destination.width} ${link.destination.y - SankeyDiagram.NodeAndBackwardLinkDistance}`;

        pathParams += `L ${link.destination.x + link.destination.width} ${link.destination.y - SankeyDiagram.NodeAndBackwardLinkDistance}`;
        pathParams += `L ${x1} ${link.source.y - SankeyDiagram.NodeAndBackwardLinkDistance}`;

        pathParams += `C ${x1} ${link.source.y - SankeyDiagram.NodeAndBackwardLinkDistance},`;
        pathParams += `${x1 - distanceFromNodeToLinks} ${link.source.y - SankeyDiagram.NodeAndBackwardLinkDistance},`;
        pathParams += `${x1 - distanceFromNodeToLinks} ${link.source.y - SankeyDiagram.NodeAndBackwardLinkDistance / 2}`;

        pathParams += `L ${x1 - distanceFromNodeToLinks} ${link.source.y - SankeyDiagram.NodeAndBackwardLinkDistance / 2}`;
        pathParams += `C ${x1 - distanceFromNodeToLinks} ${link.source.y - SankeyDiagram.NodeAndBackwardLinkDistance / 2},`;
        pathParams += ` ${x1 - distanceFromNodeToLinks} ${link.source.y + distanceBetweenLinks},`;
        pathParams += ` ${link.source.x} ${link.source.y + distanceBetweenLinks}`;

        limit = y0 + SankeyDiagram.NodeAndBackwardLinkDistance + fixedLinkHeight;
        if (limit > link.source.y + link.source.height - distanceBetweenLinks) {
            limit = link.source.y + link.source.height - distanceBetweenLinks;
        }

        pathParams += `L ${link.source.x} ${limit}`;

        pathParams +=
            `C ${link.source.x} ${limit},` +
            `${link.source.x - linkKneeSize - distanceFromNodeToLinks} ${limit},` +
            `${link.source.x - linkKneeSize - distanceFromNodeToLinks} ${limit - linkKneeSize}`;

        // left border of link
        y1 = link.source.y - (fixedLinkHeight + SankeyDiagram.NodeAndBackwardLinkDistance)
            + (link.dyDestination || 0) + (fixedLinkHeight) / SankeyDiagram.MiddleFactor - (fixedLinkHeight) / 2;

        pathParams +=
            `L ${link.source.x - distanceFromNodeToLinks - linkKneeSize} ${y1 + linkKneeSize},`;

        pathParams +=
            `C ${link.source.x - distanceFromNodeToLinks - linkKneeSize} ${y1 + linkKneeSize},` +
            `${link.source.x - distanceFromNodeToLinks - linkKneeSize} ${y1},` +
            `${link.source.x - distanceFromNodeToLinks} ${y1}`;

        pathParams += `L ${link.source.x} ${y1}`;

        // close path to get closed area
        pathParams += ` Z`;

        return pathParams;
    }