Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: adapt node size #236

Merged
merged 11 commits into from
Nov 4, 2024
19 changes: 9 additions & 10 deletions packages/layout/src/antv-dagre.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import type {
Point,
PointTuple,
} from './types';
import { cloneFormatData, formatNodeSize, formatNumberFn } from './util';
import { cloneFormatData, formatNumberFn, formatSizeFn } from './util';
import type { Size } from './util/size';
import { parseSize } from './util/size';

/**
* <zh/> 层次/流程图布局的配置项
Expand Down Expand Up @@ -75,7 +77,7 @@ export interface AntVDagreLayoutOptions {
* <en/> Used for collision detection when nodes overlap
* @defaultValue undefined
*/
nodeSize?: number | number[] | ((nodeData: Node) => number);
nodeSize?: Size | ((nodeData: Node) => Size);
/**
* <zh/> 节点间距(px)
*
Expand Down Expand Up @@ -275,7 +277,6 @@ export class AntVDagreLayout implements Layout<AntVDagreLayoutOptions> {
// focusNode,
preset,
} = mergedOptions;

const g = new Graph<NodeData, EdgeData>({
tree: [],
});
Expand All @@ -288,21 +289,19 @@ export class AntVDagreLayout implements Layout<AntVDagreLayoutOptions> {
horisep = ranksepfunc;
vertisep = nodesepfunc;
}
const nodeSizeFunc = formatNodeSize(nodeSize, undefined);

const nodeSizeFunc = formatSizeFn(10, nodeSize, false);

// copy graph to g
const nodes: Node[] = graph.getAllNodes();
const edges: Edge[] = graph.getAllEdges();

nodes.forEach((node) => {
const size = nodeSizeFunc(node);
const size = parseSize(nodeSizeFunc(node));
const verti = vertisep(node);
const hori = horisep(node);
// FIXME: support 2 dimensions?
// const width = size[0] + 2 * hori;
// const height = size[1] + 2 * verti;
const width = size + 2 * hori;
const height = size + 2 * verti;
const width = size[0] + 2 * hori;
const height = size[1] + 2 * verti;
const layer = node.data.layer;
if (isNumber(layer)) {
// 如果有layer属性,加入到node的label中
Expand Down
7 changes: 4 additions & 3 deletions packages/layout/src/concentric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type {
} from './types';
import { cloneFormatData, isArray } from './util';
import { handleSingleNodeGraph } from './util/common';
import { parseSize } from './util/size';

const DEFAULTS_LAYOUT_OPTIONS: Partial<ConcentricLayoutOptions> = {
nodeSize: 30,
Expand All @@ -26,7 +27,7 @@ const DEFAULTS_LAYOUT_OPTIONS: Partial<ConcentricLayoutOptions> = {

/**
* <zh/> 同心圆布局
*
*
* <en/> Concentric layout
*/
export class ConcentricLayout implements Layout<ConcentricLayoutOptions> {
Expand All @@ -51,7 +52,7 @@ export class ConcentricLayout implements Layout<ConcentricLayoutOptions> {
* To directly assign the positions to the nodes.
*/
async assign(graph: Graph, options?: ConcentricLayoutOptions) {
await this.genericConcentricLayout(true, graph, options);
await this.genericConcentricLayout(true, graph, options);
}

private async genericConcentricLayout(
Expand Down Expand Up @@ -112,7 +113,7 @@ export class ConcentricLayout implements Layout<ConcentricLayoutOptions> {
} else if (isFunction(nodeSize)) {
maxNodeSize = -Infinity;
nodes.forEach((node) => {
const currentSize = nodeSize(node);
const currentSize = Math.max(...parseSize(nodeSize(node)));
if (currentSize > maxNodeSize) maxNodeSize = currentSize;
});
} else {
Expand Down
40 changes: 9 additions & 31 deletions packages/layout/src/force-atlas2/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Graph as GGraph } from '@antv/graphlib';
import { isFunction, isNumber, isObject } from '@antv/util';
import { isNumber } from '@antv/util';
import type {
Edge,
EdgeData,
Expand All @@ -14,8 +14,9 @@ import type {
OutNodeData,
PointTuple,
} from '../types';
import { cloneFormatData, isArray } from '../util';
import { cloneFormatData, formatNodeSizeToNumber } from '../util';
import { handleSingleNodeGraph } from '../util/common';
import type { Size } from '../util/size';
import Body from './body';
import Quad from './quad';
import QuadTree from './quad-tree';
Expand Down Expand Up @@ -57,7 +58,7 @@ type CalcGraph = GGraph<OutNodeData, EdgeData>;

/**
* <zh/> Atlas2 力导向布局
*
*
* <en/> Force Atlas 2 layout
*/
export class ForceAtlas2Layout implements Layout<ForceAtlas2LayoutOptions> {
Expand All @@ -82,7 +83,7 @@ export class ForceAtlas2Layout implements Layout<ForceAtlas2LayoutOptions> {
* To directly assign the positions to the nodes.
*/
async assign(graph: Graph, options?: ForceAtlas2LayoutOptions) {
await this.genericForceAtlas2Layout(true, graph, options);
await this.genericForceAtlas2Layout(true, graph, options);
}

private async genericForceAtlas2Layout(
Expand Down Expand Up @@ -122,7 +123,7 @@ export class ForceAtlas2Layout implements Layout<ForceAtlas2LayoutOptions> {
nodes: calcNodes,
edges: calcEdges,
});
const sizes: SizeMap = this.getSizes(calcGraph, graph, nodeSize);
const sizes: SizeMap = this.getSizes(calcGraph, nodeSize);

this.run(calcGraph, graph, maxIteration, sizes, assign, mergedOptions);

Expand Down Expand Up @@ -164,41 +165,18 @@ export class ForceAtlas2Layout implements Layout<ForceAtlas2LayoutOptions> {
* Init the node positions if there is no initial positions.
* And pre-calculate the size (max of width and height) for each node.
* @param calcGraph graph for calculation
* @param graph origin graph
* @param nodeSize node size config from layout options
* @returns {SizeMap} node'id mapped to max of its width and height
*/
private getSizes(
calcGraph: CalcGraph,
graph: Graph,
nodeSize?: number | number[] | ((d?: Node) => number),
nodeSize?: Size | ((d?: Node) => Size),
): SizeMap {
const nodes = calcGraph.getAllNodes();
const sizes: SizeMap = {};
for (let i = 0; i < nodes.length; i += 1) {
const { id, data } = nodes[i];
sizes[id] = 10;
if (isNumber(data.size)) {
sizes[id] = data.size;
} else if (isArray(data.size)) {
if (!isNaN(data.size[0])) sizes[id] = Math.max(data.size[0]);
if (!isNaN(data.size[1])) sizes[id] = Math.max(data.size[1]);
} else if (isObject(data.size)) {
// @ts-ignore
sizes[id] = Math.max(data.size.width, data.size.height);
} else if (isFunction(nodeSize)) {
const originNode = graph.getNode(id);
const size = nodeSize(originNode);
if (isArray(size)) {
sizes[id] = Math.max(...size);
} else {
sizes[id] = size;
}
} else if (isArray(nodeSize)) {
sizes[id] = Math.max(...nodeSize);
} else if (isNumber(nodeSize)) {
sizes[id] = nodeSize;
}
const node = nodes[i];
sizes[node.id] = formatNodeSizeToNumber(nodeSize, undefined)(node);
}
return sizes;
}
Expand Down
47 changes: 9 additions & 38 deletions packages/layout/src/force/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Graph as IGraph } from '@antv/graphlib';
import { isFunction, isNumber, isObject } from '@antv/util';
import { isNumber } from '@antv/util';
import type {
Edge,
ForceLayoutOptions,
Expand All @@ -11,7 +11,7 @@ import type {
OutNode,
Point,
} from '../types';
import { formatNumberFn, isArray } from '../util';
import { formatNodeSizeToNumber, formatNumberFn } from '../util';
import { forceNBody } from './force-n-body';
import {
CalcEdge,
Expand Down Expand Up @@ -42,7 +42,7 @@ const DEFAULTS_LAYOUT_OPTIONS: Partial<ForceLayoutOptions> = {

/**
* <zh/> 力导向布局
*
*
* <en/> Force-directed layout
*/
export class ForceLayout implements LayoutWithIterations<ForceLayoutOptions> {
Expand Down Expand Up @@ -85,7 +85,7 @@ export class ForceLayout implements LayoutWithIterations<ForceLayoutOptions> {
* To directly assign the positions to the nodes.
*/
async assign(graph: Graph, options?: ForceLayoutOptions) {
await this.genericForceLayout(true, graph, options);
await this.genericForceLayout(true, graph, options);
}

/**
Expand Down Expand Up @@ -292,12 +292,7 @@ export class ForceLayout implements LayoutWithIterations<ForceLayoutOptions> {
graph: Graph,
): FormatedOptions {
const formattedOptions = { ...options } as FormatedOptions;
const {
width: propsWidth,
height: propsHeight,
getMass,
nodeSize,
} = options;
const { width: propsWidth, height: propsHeight, getMass } = options;

// === formating width, height, and center =====
formattedOptions.width =
Expand Down Expand Up @@ -326,34 +321,10 @@ export class ForceLayout implements LayoutWithIterations<ForceLayoutOptions> {
}

// === formating node size =====

const nodeSpacingFunc = formatNumberFn<Node>(0, options.nodeSpacing);
let nodeSizeFn;
if (!nodeSize) {
nodeSizeFn = (d?: Node) => {
const { size } = d?.data || {};
if (size) {
if (isArray(size)) {
return Math.max(size[0], size[1]) + nodeSpacingFunc(d);
}
if (isObject<{ width: number; height: number }>(size)) {
return Math.max(size.width, size.height) + nodeSpacingFunc(d);
}
return (size as number) + nodeSpacingFunc(d);
}
return 10 + nodeSpacingFunc(d);
};
} else if (isFunction(nodeSize)) {
nodeSizeFn = (d?: Node) => (nodeSize as Function)(d) + nodeSpacingFunc(d);
} else if (isArray(nodeSize)) {
nodeSizeFn = (d?: Node) => {
const nodeSizeArr = nodeSize as [number, number];
return Math.max(nodeSizeArr[0], nodeSizeArr[1]) + nodeSpacingFunc(d);
};
} else {
nodeSizeFn = (d?: Node) => (nodeSize as number) + nodeSpacingFunc(d);
}
formattedOptions.nodeSize = nodeSizeFn;
formattedOptions.nodeSize = formatNodeSizeToNumber(
options.nodeSize,
options.nodeSpacing,
);

// === formating node / edge strengths =====
const linkDistanceFn = options.linkDistance
Expand Down
20 changes: 5 additions & 15 deletions packages/layout/src/grid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import type {
OutNode,
PointTuple,
} from './types';
import { cloneFormatData, formatNumberFn, formatSizeFn, isArray } from './util';
import { cloneFormatData, formatNumberFn, formatSizeFn } from './util';
import { handleSingleNodeGraph } from './util/common';
import { parseSize } from './util/size';

type RowsAndCols = {
rows: number;
Expand Down Expand Up @@ -46,7 +47,7 @@ const DEFAULTS_LAYOUT_OPTIONS: Partial<GridLayoutOptions> = {

/**
* <zh/> 网格布局
*
*
* <en/> Grid layout
*/
export class GridLayout implements Layout<GridLayoutOptions> {
Expand All @@ -69,7 +70,7 @@ export class GridLayout implements Layout<GridLayoutOptions> {
* To directly assign the positions to the nodes.
*/
async assign(graph: Graph, options?: GridLayoutOptions) {
await this.genericGridLayout(true, graph, options);
await this.genericGridLayout(true, graph, options);
}

private async genericGridLayout(
Expand Down Expand Up @@ -219,18 +220,7 @@ export class GridLayout implements Layout<GridLayoutOptions> {
}

const oNode = graph.getNode(node.id);
const res = nodeSize(oNode) || 30;

let nodeW;
let nodeH;

if (isArray(res)) {
nodeW = res[0];
nodeH = res[1];
} else {
nodeW = res;
nodeH = res;
}
const [nodeW, nodeH] = parseSize(nodeSize(oNode) || 30);

const p =
nodeSpacing !== undefined ? nodeSpacing(node) : preventOverlapPadding;
Expand Down
6 changes: 3 additions & 3 deletions packages/layout/src/radial/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import type {
import {
cloneFormatData,
floydWarshall,
formatNodeSize,
formatNodeSizeToNumber,
getAdjMatrix,
getEuclideanDistance,
} from '../util';
Expand All @@ -37,7 +37,7 @@ const DEFAULTS_LAYOUT_OPTIONS: Partial<RadialLayoutOptions> = {

/**
* <zh/> 径向布局
*
*
* <en/> Radial layout
*/
export class RadialLayout implements Layout<RadialLayoutOptions> {
Expand Down Expand Up @@ -193,7 +193,7 @@ export class RadialLayout implements Layout<RadialLayoutOptions> {
let nodeSizeFunc;
// stagger the overlapped nodes
if (preventOverlap) {
nodeSizeFunc = formatNodeSize(nodeSize, nodeSpacing);
nodeSizeFunc = formatNodeSizeToNumber(nodeSize, nodeSpacing);
const nonoverlapForceParams: RadialNonoverlapForceOptions = {
nodes,
nodeSizeFunc,
Expand Down
Loading
Loading