TargetProcess/tauCharts

View on GitHub
src/elements/decorators/layer-labels-penalties.ts

Summary

Maintainability
A
0 mins
Test Coverage
import * as utilsDraw from '../../utils/utils-draw';
import {EdgeInfo} from './layer-labels';

export interface LabelPenaltyModel {
    i: number;
    x0: number;
    y0: number;
    x: number;
    y: number;
    w: number;
    h: number;
    size: number;
    hide: boolean;
    extr: string;
}

type LabelPenaltyFunction = (
    labels: LabelPenaltyModel[],
    edges: EdgeInfo[],
    penaltyRate?: number
) => (index: number) => number;

var intersect = (x1, x2, x3, x4, y1, y2, y3, y4) => utilsDraw.isIntersect(
    x1, y1,
    x2, y2,
    x3, y3,
    x4, y4
);

const _penalties: {[alias: string]: LabelPenaltyFunction} = {};

export class LayerLabelsPenalties {

    static reg(alias: string, funcPenalty: LabelPenaltyFunction) {
        _penalties[alias] = funcPenalty;
        return this;
    }

    static get(alias) {
        return _penalties[alias];
    }
}

LayerLabelsPenalties
    .reg('auto:avoid-label-label-overlap', (labels, edges, penaltyRate = 1.0) => {
        return (index) => {
            var x21 = labels[index].x;
            var y21 = labels[index].y - labels[index].h + 2.0;
            var x22 = labels[index].x + labels[index].w;
            var y22 = labels[index].y + 2.0;

            return labels.reduce((sum, labi, i) => {
                var k = Number(i !== index);
                var x11 = labi.x;
                var y11 = labi.y - labi.h + 2.0;
                var x12 = labi.x + labi.w;
                var y12 = labi.y + 2.0;
                var x_overlap = Math.max(0, Math.min(x12, x22) - Math.max(x11, x21));
                var y_overlap = Math.max(0, Math.min(y12, y22) - Math.max(y11, y21));
                var overlap_area = x_overlap * y_overlap;
                return sum + (k * (overlap_area * penaltyRate));
            }, 0);
        };
    })
    .reg('auto:avoid-label-anchor-overlap', (labels, edges, penaltyRate = 1.0) => {
        return (index) => {
            var lab0 = labels[index];
            var x21 = lab0.x - lab0.w / 2;
            var x22 = lab0.x + lab0.w / 2;
            var y21 = lab0.y - lab0.h / 2 + 2.0;
            var y22 = lab0.y + lab0.h / 2 + 2.0;
            return labels.reduce((sum, anchor) => {
                var x11 = anchor.x0 - anchor.size / 2;
                var x12 = anchor.x0 + anchor.size / 2;
                var y11 = anchor.y0 - anchor.size / 2;
                var y12 = anchor.y0 + anchor.size / 2;
                var x_overlap = Math.max(0, Math.min(x12, x22) - Math.max(x11, x21));
                var y_overlap = Math.max(0, Math.min(y12, y22) - Math.max(y11, y21));
                var overlap_area = x_overlap * y_overlap;
                return sum + (overlap_area * penaltyRate);
            }, 0);
        };
    })
    .reg('auto:avoid-label-edges-overlap', (labels, edges, penaltyRate = 1.0) => {
        return (index) => {
            var label = labels[index];
            var x0 = label.x - label.w / 2;
            var x1 = label.x + label.w / 2;
            var y0 = label.y - label.h / 2;
            var y1 = label.y + label.h / 2;
            return edges.reduce((sum, edge) => {
                var overlapLeftTopRightBottom = intersect(x0, x1, edge.x0, edge.x1, y0, y1, edge.y0, edge.y1);
                var overlapLeftBottomRightTop = intersect(x0, x1, edge.x0, edge.x1, y1, y0, edge.y0, edge.y1);
                return sum + (Number(overlapLeftTopRightBottom) + Number(overlapLeftBottomRightTop)) * penaltyRate;
            }, 0);
        };
    });