2021-08-30 15:57:05 +00:00
|
|
|
|
|
|
|
const isNeighbor = function (itemA, itemB) {
|
|
|
|
let neighborA = itemA.neighbor,
|
|
|
|
neighborB = itemB.neighbor;
|
|
|
|
|
|
|
|
if (neighborA === undefined && neighborB === undefined) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (neighborA && neighborA.includes(itemB.id)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (neighborB && neighborB.includes(itemA.id)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-10-29 07:46:18 +00:00
|
|
|
SV.registerLayout('AdjoinMatrixGraph', {
|
2021-08-30 15:57:05 +00:00
|
|
|
sourcesPreprocess(sources) {
|
|
|
|
let dataLength = sources.length;
|
|
|
|
let matrixNodeLength = dataLength * dataLength;
|
|
|
|
let matrixNodes = [];
|
|
|
|
let i, j;
|
|
|
|
|
|
|
|
for (i = 0; i < matrixNodeLength; i++) {
|
|
|
|
matrixNodes.push({
|
|
|
|
id: `mn-${i}`,
|
|
|
|
type: 'matrixNode',
|
|
|
|
indexTop: i < dataLength ? sources[i].id : undefined,
|
|
|
|
indexLeft: i % dataLength === 0? sources[i / dataLength].id : undefined,
|
|
|
|
data: 0
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < dataLength; i++) {
|
|
|
|
for (j = 0; j < dataLength; j++) {
|
|
|
|
let itemI = sources[i],
|
|
|
|
itemJ = sources[j];
|
|
|
|
|
|
|
|
if (itemI.id !== itemJ.id && isNeighbor(itemI, itemJ)) {
|
|
|
|
matrixNodes[i * dataLength + j].data = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sources.push(...matrixNodes);
|
|
|
|
|
|
|
|
return sources;
|
|
|
|
},
|
|
|
|
|
|
|
|
defineOptions() {
|
|
|
|
return {
|
|
|
|
element: {
|
|
|
|
default: {
|
|
|
|
type: 'circle',
|
|
|
|
label: '[id]',
|
|
|
|
size: 40,
|
|
|
|
style: {
|
|
|
|
stroke: '#333',
|
|
|
|
fill: '#95e1d3'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
matrixNode: {
|
|
|
|
type: 'indexed-node',
|
|
|
|
label: '[data]',
|
|
|
|
size: [40, 40],
|
|
|
|
style: {
|
|
|
|
stroke: '#333',
|
|
|
|
fill: '#95e1d3'
|
|
|
|
},
|
|
|
|
indexOptions: {
|
|
|
|
indexTop: { position: 'top' },
|
|
|
|
indexLeft: { position: 'left' }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
link: {
|
|
|
|
neighbor: {
|
|
|
|
style: {
|
|
|
|
stroke: '#333'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
layout: {
|
|
|
|
radius: 150,
|
|
|
|
interval: 250
|
|
|
|
},
|
|
|
|
behavior: {
|
|
|
|
dragNode: ['default']
|
|
|
|
}
|
|
|
|
};
|
|
|
|
},
|
|
|
|
|
|
|
|
layout(elements, layoutOptions) {
|
|
|
|
let nodes = elements.filter(item => item.type === 'default'),
|
|
|
|
matrixNodes = elements.filter(item => item.type === 'matrixNode'),
|
|
|
|
nodeLength = nodes.length,
|
|
|
|
matrixNodeLength = matrixNodes.length,
|
|
|
|
{ interval, radius } = layoutOptions,
|
|
|
|
intervalAngle = 2 * Math.PI / nodes.length,
|
|
|
|
matrixNodeSize = matrixNodes[0].get('size')[0],
|
|
|
|
i;
|
|
|
|
|
|
|
|
const matrixY = -radius,
|
|
|
|
matrixX = interval;
|
|
|
|
|
|
|
|
for (i = 0; i < nodeLength; i++) {
|
|
|
|
let [x, y] = Vector.rotation(-intervalAngle * i, [0, -radius]);
|
|
|
|
|
|
|
|
nodes[i].set({ x, y });
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < matrixNodeLength; i++) {
|
|
|
|
let x = matrixX + (i % nodeLength) * matrixNodeSize;
|
|
|
|
y = matrixY + Math.floor(i / nodeLength) * matrixNodeSize;
|
|
|
|
|
|
|
|
matrixNodes[i].set({ x, y });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|