import io.data2viz.color.* import io.data2viz.geom.* import io.data2viz.math.* import io.data2viz.viz.* import io.data2viz.force.* data class Item(val name:String, val index:Int, val parents:List<Int> = listOf()) val items = listOf( Item("Northern Undead Asylum", 0), Item("Firelink Shrine", 1, listOf(0, 16, 20, 2, 3, 11)), Item("Undead Burg", 2, listOf(3, 4, 10)), Item("Undead Parish", 3, listOf(7, 9)), Item("Depths", 4, listOf(5)), Item("Blighttown", 5, listOf(6, 18, 21)), Item("Quelaag's Domain", 6, listOf(14, 11)), Item("Sen's Fortress", 7, listOf(8)), Item("Anor Londo", 8, listOf(12, 23)), Item("Darkroot Garden", 9, listOf(10)), Item("Darkroot Basin", 10, listOf(18)), Item("New Londo Ruins", 11, listOf(18, 19)), Item("The Duke's Archives", 12, listOf(13)), Item("Crystal Cave", 13), Item("Demon Ruins", 14, listOf(15)), Item("Lost Izalith", 15), Item("The Catacombs", 16, listOf(17)), Item("Tomb of Giants", 17), Item("The Valley of Drakes", 18), Item("The Abyss", 19), Item("Kiln of The First Flame", 20), Item("The great Hollow", 21, listOf(22)), Item("Ash lake", 22), Item("Painted world", 23) ) fun main() { val vizSize = 900.0 val particleTexts = mutableListOf<TextNode>() val particleNodes = mutableListOf<CircleNode>() val particleLinks = mutableListOf<LineNode>() lateinit var forceLink:ForceLink<Item> val simulation = forceSimulation<Item> { forceLink = forceLink { linkGet = { domain.parents.map { Link<Item>(this, nodes[it], 10.0) } } iterations = 5 } forceCenter { center = point(vizSize / 2, vizSize / 2) } forceCollision { radiusGet = { 65.0 } iterations = 3 } domainObjects = items } viz { size = size(vizSize, vizSize) forceLink.links.forEach { particleLinks += line { x1 = it.source.x y1 = it.source.y x2 = it.target.x x2 = it.target.y stroke = Colors.Web.black.withAlpha(40.pct) } } simulation.nodes.forEach { particleNodes += circle { fill = Colors.Web.black radius = 3.0 + it.domain.parents.size } particleTexts += text { fill = Colors.Web.black textContent = items[it.index].name textAlign = textAlign(TextHAlign.MIDDLE, TextVAlign.MIDDLE) fontWeight = FontWeight.BOLD } } animation { simulation.nodes.forEach { node -> particleTexts[node.index].x = node.x particleTexts[node.index].y = node.y - 15.0 particleNodes[node.index].x = node.x particleNodes[node.index].y = node.y } forceLink.links.forEachIndexed { index, link -> particleLinks[index].x1 = link.source.x particleLinks[index].x2 = link.target.x particleLinks[index].y1 = link.source.y particleLinks[index].y2 = link.target.y } } }.bindRendererOnNewCanvas() }