<!DOCTYPE html>
<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

        <title>PIXI ForceLayout</title>

        <link rel="stylesheet" href="../3rdparty/highlight/styles/default.css" />
        <link rel="stylesheet" href="../../css/doctest.css" />

        <script src="../3rdparty/highlight/highlight.pack.js"></script>
        <script src="../../dist/iwmlib.3rdparty.js"></script>

        <script src="../../dist/iwmlib.js"></script>
        <script src="../../dist/iwmlib.pixi.js"></script>

        <script src="./lib/graphology.min.js"></script>
        <script src="./lib/graphology-layout-forceatlas2.js"></script>
    </head>
    <body onload="Doctest.run()">
        <h1><a href="../index.html">lib.</a><a href="index.html">pixi.</a>ForceLayout</h1>
        <p>
            Comparison of a <a href="https://github.com/d3/d3-force/blob/master/README.md">D3 ForceLayout</a> with a
            <a href="https://github.com/graphology/graphology-layout-forceatlas2">ForceAtlas 2</a> forcelayout.
        </p>
        <h2>Let's look at the D3 ForceLayout:</h2>
        <br />
        <canvas id="canvas" class="interactive"></canvas>
        <script class="doctest">
            const app = new PIXIApp({
                view: canvas,
                width: 900,
                height: 420,
                transparent: false
            })
                .setup()
                .run()

            app.loadTextures(
                ['./assets/circle.png'],
                (textures) => {
                    // add sprites
                    //--------------------
                    const sprites = []

                    for (let i = 0; i < 100; i++) {
                        const sprite = new PIXI.Sprite(textures.get('./assets/circle.png'))
                        sprite.x = randomInt(0, app.size.width)
                        sprite.y = randomInt(0, app.size.height)
                        sprite.width = sprite.height = 2
                        sprite.anchor.set(0.5, 0.5)
                        sprite.__random = Math.random()
                        sprites.push(sprite)
                    }

                    app.scene.addChild(...sprites)

                    // force simulation
                    //--------------------
                    const forceCollide = d3.forceCollide().radius((d) => d.width / 2 + 1)
                    const simulation = d3
                        .forceSimulation(sprites)
                        .on('tick', () => {
                            //forceCollide.radius(d => d.radius)
                        })
                        .force('collide', forceCollide)
                        .force('x', d3.forceX(app.center.x))
                        .force('y', d3.forceY(app.center.y))
                        .stop()
                        .force(
                            'radial',
                            d3.forceRadial(
                                (d) => {
                                    return d.__random < 0.5 ? 60 : 160
                                },
                                app.center.x,
                                app.center.y
                            )
                        )

                    d3.timeout(() => {
                        simulation.restart()
                    }, 500)
                },
                { resolutionDependent: false }
            )
        </script>

        <h2>D3 ForceLayout with links:</h2>
        <br />
        <canvas id="canvas2" class="interactive"></canvas>
        <script class="doctest">
            const app2 = new PIXIApp({
                view: canvas2,
                width: 900,
                height: 420,
                transparent: false
            })
                .setup()
                .run()

            app2.loadTextures(
                ['./assets/circle2.png'],
                (textures) => {
                    // add sprites
                    //--------------------
                    const sprites = []

                    for (let i = 0; i < 100; i++) {
                        const sprite = new PIXI.Sprite(textures.get('./assets/circle2.png'))
                        sprite.id = i
                        sprite.x = randomInt(0, app2.size.width)
                        sprite.y = randomInt(0, app2.size.height)
                        sprite.width = sprite.height = 16
                        sprite.anchor.set(0.5, 0.5)
                        sprites.push(sprite)
                    }

                    app2.scene.addChild(...sprites)

                    const links = new PIXI.Graphics()
                    app2.scene.addChildAt(links, 0)

                    // force simulation
                    //--------------------
                    const forceCollide = d3.forceCollide().radius((d) => d.width / 2 + 4)
                    const forceLink = d3
                        .forceLink([
                            { source: 88, target: 8 },
                            { source: 47, target: 55 },
                            { source: 70, target: 1 },
                            { source: 12, target: 12 },
                            { source: 26, target: 33 },
                            { source: 48, target: 53 },
                            { source: 10, target: 70 },
                            { source: 68, target: 61 },
                            { source: 28, target: 65 },
                            { source: 12, target: 34 },
                            { source: 6, target: 55 },
                            { source: 9, target: 16 },
                            { source: 87, target: 96 },
                            { source: 64, target: 24 },
                            { source: 98, target: 14 },
                            { source: 18, target: 23 },
                            { source: 53, target: 62 },
                            { source: 11, target: 53 },
                            { source: 43, target: 23 },
                            { source: 80, target: 9 },
                            { source: 72, target: 88 },
                            { source: 62, target: 3 },
                            { source: 72, target: 15 },
                            { source: 84, target: 25 },
                            { source: 57, target: 58 },
                            { source: 87, target: 19 }
                        ])
                        .id((d) => d.id)
                        .strength(0.05)
                    const simulation = d3
                        .forceSimulation(sprites)
                        .on('tick', () => {
                            links.clear()
                            links.lineStyle(1, 0xfdc02f)
                            for (let link of forceLink.links()) {
                                links.moveTo(link.source.x, link.source.y)
                                links.lineTo(link.target.x, link.target.y)
                            }
                        })
                        .force('collide', forceCollide)
                        .force('link', forceLink)
                        .stop()

                    d3.timeout(() => {
                        simulation.restart()
                    }, 1000)
                },
                { resolutionDependent: false }
            )
        </script>
    </body>
</html>