Skip to content

Commit 9068fcc

Browse files
committed
New optional layouts
1 parent 2c12bdf commit 9068fcc

File tree

2 files changed

+56
-17
lines changed

2 files changed

+56
-17
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ Set of tools for processing, storing, and visualizing data from Meshtastic mesh
6262
- **Traceroute** - showing nodes from traceroute requests 🆕
6363
- **Physical sender** - showing `sender` and `to` of messages passed through the network *(prototype)*
6464
- **Neighbors** - showing connections reported by nodes as `neighbors` *(early prototype)*
65+
- Three layouts: Cose-Bilkent, Circle, and Concentric
6566

6667
### 4. Auxiliary script to dump and copy data (`cron-task.sh`)
6768
- to be run from cron

webpage/index.html

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
</head>
3232

3333
<body>
34-
<strong>Map of mesh node connections.</strong> Updated: <span id="whenupdated"></span>
34+
<strong>Map of mesh node connections.</strong> Updated: <span id="whenupdated"></span> | <A href="https://github.com/filipsPL/meshtastic-network-visualization/">GitHub</A>
3535
<div class="controls">
3636
<select id="fileSelect">
3737
<option value="data/cytoscape_traceroutes_1h.json">🚇 Traceroutes :: 1 hour</option>
@@ -50,12 +50,20 @@
5050
<option value="data/cytoscape_neighbors_3h.json">🔗 Neighbors :: 3 hours</option>
5151
<option value="data/cytoscape_neighbors_24h.json">🔗 Neighbors :: 24 hours</option>
5252
</select>
53+
54+
<select id="layoutSelect">
55+
<option value="cose-bilkent">Cose-Bilkent Layout</option>
56+
<option value="circle">Circle Layout</option>
57+
<option value="concentric">Concentric Layout</option>
58+
</select>
5359
</div>
5460
<div id="cy"></div>
5561
<script>
5662
let cy; // Define cy in global scope
63+
let currentFilename; // Store the current filename
5764

5865
function loadData(filename) {
66+
currentFilename = filename; // Store the current filename
5967
fetch(filename)
6068
.then(response => {
6169
if (!response.ok) {
@@ -95,6 +103,42 @@
95103
cy.destroy();
96104
}
97105

106+
// Determine layout based on dropdown selection
107+
const layoutType = document.getElementById('layoutSelect').value;
108+
let layoutConfig;
109+
switch(layoutType) {
110+
case 'cose-bilkent':
111+
layoutConfig = {
112+
name: "cose-bilkent",
113+
animate: false,
114+
idealEdgeLength: 100,
115+
randomize: true,
116+
nodeRepulsion: 7000,
117+
edgeElasticity: 0.45,
118+
nestingFactor: 10.1,
119+
numIter: 30000,
120+
gravity: 0.25,
121+
tile: true
122+
};
123+
break;
124+
case 'concentric':
125+
layoutConfig = {
126+
name: 'concentric',
127+
minNodeSpacing: 50,
128+
concentric: function(node) {
129+
return node.data('connections');
130+
},
131+
levelWidth: function() {
132+
return 2;
133+
}
134+
};
135+
break;
136+
default:
137+
layoutConfig = {
138+
name: 'circle'
139+
};
140+
}
141+
98142
// Initialize Cytoscape.js
99143
cy = cytoscape({
100144
container: document.getElementById('cy'),
@@ -114,9 +158,7 @@
114158
'background-color': 'mapData(connections, 1, 10, #d2dbfa, #003aff)',
115159
'shape': 'round-rectangle'
116160
}
117-
118161
},
119-
120162
{
121163
selector: 'node[role=2]',
122164
style: {
@@ -144,7 +186,6 @@
144186
'content': (ele) => `[RPT] ${ele.data('label')}`
145187
}
146188
},
147-
148189
{
149190
selector: 'edge',
150191
style: {
@@ -159,18 +200,7 @@
159200
}
160201
}
161202
],
162-
layout: {
163-
name: "cose-bilkent",
164-
animate: false,
165-
idealEdgeLength: 100,
166-
randomize: true,
167-
nodeRepulsion: 7000,
168-
edgeElasticity: 0.45,
169-
nestingFactor: 10.1,
170-
numIter: 30000,
171-
gravity: 0.25,
172-
tile: true
173-
}
203+
layout: layoutConfig
174204
});
175205
})
176206
.catch(error => {
@@ -193,11 +223,19 @@
193223
});
194224
}
195225

196-
// Add event listener for dropdown changes
226+
// Add event listener for data file dropdown changes
197227
document.getElementById('fileSelect').addEventListener('change', function () {
198228
loadData(this.value);
199229
});
200230

231+
// Add event listener for layout dropdown changes
232+
document.getElementById('layoutSelect').addEventListener('change', function () {
233+
// Reload the current data with the new layout
234+
if (currentFilename) {
235+
loadData(currentFilename);
236+
}
237+
});
238+
201239
// Load initial data
202240
loadData(document.getElementById('fileSelect').value);
203241
</script>

0 commit comments

Comments
 (0)