> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.szVMkVmQJ-$/rev.521
 * 
 * authors: 
 *   
 *   Farid

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   https://creativecommons.org/licenses/by-sa/3.0/ 
 */ 



// This sketch builds on a prior work, "Graph visualizer", created by Farid
// http://studio.sketchpad.cc/sp/pad/view/ro.9$AY6Dpp9Kq$w/rev.509



package mypack;





    int width;
    int height;
    Graph graph;
    int count = 0;
    int state = 0;
    GraphGenerator graphGenerator;
    String[] stateNames;
    int mouseState;


    public void setup()
    {
        width = 800;
        height =800;
        size(800, 800);
        smooth();
        Initialize();
    }

    void Initialize()
    {
        frameRate(30);
        mouseState=-1;
        InitializeNames();
        ResourceManager.getInstance().appletWidth = width;
        ResourceManager.getInstance().appletHeight = height;
        graphGenerator = new GraphGenerator();
        graph = new Graph();

        graphGenerator.CompleteGraph(this, graph, 6);
    }

    void InitializeNames()
    {
        stateNames = new String[120];
        stateNames[0] = "Complete graph with 6 nodes";
    }

    void Update()
    {
       if(state==0)
       {
           count=count+1;
           if(count%30==0)
           {
           state=1;
           count=0;
           }
           }
       if(mouseState==-1)
       {
           if(mousePressed)
           {
               if(mouseX>60 && mouseX<200&&mouseY>30&&mouseY<50)
               {
                mouseState=0;
                count=0;
                return;
                }
                
                 if(mouseX>60 && mouseX<200&&mouseY>60&&mouseY<80)
               {
                mouseState=2;
                return;
                }
            }
        }


            if(mouseState!=-1)
            {
                if(mouseState==0)
                  if(!mousePressed)
                   {
                       
                       state=state+1;
                       mouseState=-1;
                       UpdateGraph();
                    }
                    
                    
               if(mouseState==2)
                  if(!mousePressed)
                   {
                       state=state-1;
                       
                       if(state<2)
                       state=55;
                       mouseState=-1;
                       UpdateGraph();
                    }
            }
    }


void RenderButton()
{
if(mouseState!=0)    
    fill(200,50,100,200);
    else
    fill(20,200,20,200);
    rect(60,30,140,20);




if(mouseState!=2)    
    fill(200,50,100,200);
    else
    fill(20,200,20,200);
   rect(60,60,140,20);
   fill(250, 250, 250);
            
    textSize(16);
     text("Next", 110, 46);
     

    text("Previous", 110, 76);
     //previous
}
    void UpdateGraph()
    {

        if (state == 1)
            {
                graphGenerator.CompleteGraph(this, graph, 6);
                stateNames[state] = "Complete graph with 6 nodes";
                return;
            }

        if (state == 2)
            {
                graphGenerator.CompleteGraph(this, graph, 10);
                stateNames[state] = "Complete graph with 10 nodes";
                return;
            }

        if (state == 3)
            {
                graphGenerator.CompleteGraph(this, graph, 14);
                stateNames[state] = "Complete graph with 14 nodes";
                return;
            }

        if (state == 4)
            {
                graphGenerator.CompleteGraph(this, graph, 18);
                stateNames[state] = "Complete graph with 18 nodes";
                return;
            }

        if (state == 5)
            {
                graphGenerator.CompleteGraph(this, graph, 22);
                stateNames[state] = "Complete graph with 22 nodes";
                return;
            }

        if (state == 6)
            {
                graphGenerator.CompleteGraph(this, graph, 26);
                stateNames[state] = "Complete graph with 26 nodes";
                return;
            }

        if (state == 7)
            {
                graphGenerator.CompleteGraph(this, graph, 30);
                stateNames[state] = "Complete graph with 30 nodes";
                return;
            }

        if (state == 8)
            {
                graphGenerator.CompleteGraph(this, graph, 34);
                stateNames[state] = "Complete graph with 34 nodes";
                return;
            }

        if (state == 9)
            {
                graphGenerator.StarGraph(this, graph, 8);
                stateNames[state] = "Star graph with 8 nodes";
                return;
            }

        if (state == 10)
            {
                graphGenerator.StarGraph(this, graph, 14);
                stateNames[state] = "Star graph with 14 nodes";
                return;
            }

        if (state == 11)
            {
                graphGenerator.StarGraph(this, graph, 20);
                stateNames[state] = "Star graph with 20 nodes";
                return;
            }

        if (state == 12)
            {
                graphGenerator.StarGraph(this, graph, 24);
                stateNames[state] = "Star graph with 24 nodes";
                return;
            }

        if (state == 13)
            {
                graphGenerator.StarGraph(this, graph, 34);
                stateNames[state] = "Star graph with 34 nodes";
                return;
            }

        if (state == 14)
            {
                graphGenerator.StarGraph(this, graph, 54);
                stateNames[state] = "Star graph with 54 nodes";
                return;
            }

        if (state == 15)
            {
                graphGenerator.StarGraph(this, graph, 64);
                stateNames[state] = "Star graph with 64 nodes";
                return;
            }

        if (state == 16)
            {
                graphGenerator.StarGraph(this, graph, 74);
                stateNames[state] = "Star graph with 64 nodes";
                return;
            }

        if (state == 17)
            {
                graphGenerator.BananaGraph(this, graph, 8, 4);
                stateNames[state] = "Banana graph with 8 branches and 3 nodes";
                return;
            }

        if (state == 18)
            {
                graphGenerator.BananaGraph(this, graph, 8, 5);
                stateNames[state] = "Banana graph with 8 branches and 4 nodes";
                return;
            }

        if (state == 19)
            {
                graphGenerator.BananaGraph(this, graph, 8, 6);
                stateNames[state] = "Banana graph with 8 branches and 5 nodes";
                return;
            }

        if (state == 20)
            {
                graphGenerator.BananaGraph(this, graph, 8, 7);
                stateNames[state] = "Banana graph with 8 branches and 6 nodes";
                return;
            }

        if (state == 21)
            {
                graphGenerator.BananaGraph(this, graph, 8, 8);
                stateNames[state] = "Banana graph with 8 branches and 7 nodes";
                return;
            }

        if (state == 22)
            {
                graphGenerator.BananaGraph(this, graph, 10, 4);
                stateNames[state] = "Banana graph with 10 branches and 3 nodes";
                return;
            }

        if (state == 23)
            {
                graphGenerator.BananaGraph(this, graph, 10, 6);
                stateNames[state] = "Banana graph with 10 branches and 5 nodes";
                return;
            }

        if (state == 24)
            {
                graphGenerator.BananaGraph(this, graph, 10, 8);
                stateNames[state] = "Banana graph with 10 branches and 7 nodes";
                return;
            }

        if (state == 25)
            {
                graphGenerator.BananaGraph(this, graph, 12, 4);
                stateNames[state] = "Banana graph with 12 branches and 3 nodes";
                return;
            }

        if (state == 26)
            {
                graphGenerator.BananaGraph(this, graph, 12, 6);
                stateNames[state] = "Banana graph with 12 branches and 5 nodes";
                return;
            }

        if (state == 27)
            {
                graphGenerator.BananaGraph(this, graph, 12, 8);
                stateNames[state] = "Banana graph with 12 branches and 7 nodes";
                return;
            }

        if (state == 28)
            {
                graphGenerator.BananaGraph(this, graph, 14, 6);
                stateNames[state] = "Banana graph with 14 branches and 5 nodes";
                return;
            }

        if (state == 29)
            {
                graphGenerator.BinaryGraph(this, graph, 6, 4);
                stateNames[state] = "Binary graph with 6 and 4 nodes";
                return;
            }

        if (state == 30)
            {
                graphGenerator.BinaryGraph(this, graph, 8, 4);
                stateNames[state] = "Binary graph with 8 and 4 nodes";
                return;
            }

        if (state == 31)
            {
                graphGenerator.BinaryGraph(this, graph, 10, 4);
                stateNames[state] = "Binary graph with 10 and 4 nodes";
                return;
            }

        if (state == 32)
            {
                graphGenerator.BinaryGraph(this, graph, 12, 4);
                stateNames[state] = "Binary graph with 12 and 4 nodes";
                return;
            }

        if (state == 33)
            {
                graphGenerator.BinaryGraph(this, graph, 14, 4);
                stateNames[state] = "Binary graph with 14 and 4 nodes";
                return;
            }

        if (state == 34)
            {
                graphGenerator.BinaryGraph(this, graph, 16, 4);
                stateNames[state] = "Binary graph with 16 and 4 nodes";
                return;
            }

        if (state == 35)
            {
                graphGenerator.BinaryGraph(this, graph, 12, 6);
                stateNames[state] = "Binary graph with 12 and 6 nodes";
                return;
            }

        if (state == 36)
            {
                graphGenerator.BinaryGraph(this, graph, 14, 10);
                stateNames[state] = "Binary graph with 14 and 10 nodes";
                return;
            }

        if (state == 37)
            {
                graphGenerator.BinaryGraph(this, graph, 16, 14);
                stateNames[state] = "Binary graph with 16 and 14 nodes";
                return;
            }

        if (state == 38)
            {
                graphGenerator.BinaryGraph(this, graph, 16, 18);
                stateNames[state] = "Binary graph with 16 and 18 nodes";
                return;
            }

        if (state == 39)
            {
                graphGenerator.TreeGraph(this, graph, 2);
                stateNames[state] = "Tree with 2 levels";
                return;
            }

        if (state == 40)
            {
                graphGenerator.TreeGraph(this, graph, 3);
                stateNames[state] = "Tree with 3 levels";
                return;
            }

        if (state == 41)
            {
                graphGenerator.TreeGraph(this, graph, 4);
                stateNames[state] = "Tree with 4 levels";
                return;
            }

        if (state == 42)
            {
                graphGenerator.TreeGraph(this, graph, 5);
                stateNames[state] = "Tree with 5 levels";
                return;
            }

        if (state == 43)
            {
                graphGenerator.TreeGraph(this, graph, 6);
                stateNames[state] = "Tree with 6 levels";
                return;
            }

        if (state == 44)
            {
                graphGenerator.CycleGraph(this, graph, 6);
                stateNames[state] = "Cycle graph with 6 nodes";
                return;
            }

        if (state == 45)
            {
                graphGenerator.CycleGraph(this, graph, 12);
                stateNames[state] = "Cycle graph with 12 nodes";
                return;
            }

        if (state == 46)
            {
                graphGenerator.CycleGraph(this, graph, 20);
                stateNames[state] = "Cycle graph with 20 nodes";
                return;
            }

        if (state == 47)
            {
                graphGenerator.FriendShip(this, graph, 8);
                stateNames[state] = "FriendShip graph with 6 nodes";
                return;
            }

        if (state == 48)
            {
                graphGenerator.FriendShip(this, graph, 10);
                stateNames[state] = "FriendShip graph with 10 nodes";
                return;
            }

        if (state == 49)
            {
                graphGenerator.FriendShip(this, graph, 14);
                stateNames[state] = "FriendShip graph with 14 nodes";
                return;
            }

        if (state == 50)
            {
                graphGenerator.CLEBSH(this, graph);
                stateNames[state] = "CLEBSH graph";
                return;
            }

        if (state == 51)
            {
                graphGenerator.DURER(this, graph);
                stateNames[state] = "DURER graph";
                return;
            }

        if (state == 52)
            {
                graphGenerator.Franklin(this, graph);
                stateNames[state] = "Franklin graph";
                return;
            }

        if (state == 53)
            {
                graphGenerator.HERSCHEL(this, graph);
                stateNames[state] = "HERSCHEL graph";
                return;
            }

        if (state == 54)
            {
                graphGenerator.sousselier(this, graph);
                stateNames[state] = "sousselier graph";
                return;
            }

        if (state == 55)
            {
                graphGenerator.tietze(this, graph);
                stateNames[state] = "tietze graph";
                return;
            }

        if (state == 56)
            state = 0;

    
    



    }

    void Render()
    {
       stroke(128, 128, 128);
        background(255, 255, 255);
        // image(image, 0, 0, 1400, 800);
        // text(frameRate, 10, 100);
        fill(0,0,0);
        if (state != 0)
            text(stateNames[state], 800, 20);

        if (state != 0)
            RenderGraph();

        if (state == 0)
            {
                fill(220, 90, 120);
                textSize(44);
                text("Graph visualizer", 100, 400);
                fill(20, 20, 20);
                textSize(14);
                // text("Using Processingjs", 100, 440);
                return;
            }
            
            RenderButton();
            
            

    }

    void RenderGraph()
    {
        stroke(128, 128, 128);
        RenderEdges();
        stroke(128, 128, 128);
        RenderNodes();
    }

    void RenderNodes()
    {
        try
            {
                for (Node node : graph.nodes)
                    {
                        fill(node.R, node.G, node.B, 200);
                        RenderNode(node);
                        // text(c + "", node.x - 60, node.y);
                    }
            } catch (Exception e)
            {
                // TODO: handle exception
            }
    }

    void RenderEdges()
    {

        for (int i = 0; i < graph.nodes.size(); i++)
            for (int j = i + 1; j < graph.nodes.size(); j++)
                {
                    try
                        {
                            if (graph.HasEdge(i, j))
                                line(graph.nodes.get(i).x,
                                        graph.nodes.get(i).y,
                                        graph.nodes.get(j).x,
                                        graph.nodes.get(j).y);
                        } catch (Exception e)
                        {
                            // TODO: handle exception
                        }
                }
    }

    void RenderNode(Node node)
    {
        ellipse(node.x, node.y, ResourceManager.getInstance().nodesSize,
                ResourceManager.getInstance().nodesSize);
    }

    public void draw()
    {
        Update();
        Render();
    }

  









/***********************/





public class Graph
{
    public List<Node> nodes;
    public boolean[][] w;

    public Graph()
    {
        nodes = new ArrayList<Node>();
    }

    public void AddNode(double x, double y)
    {
        Node newNode = new Node((float) x, (float) y);
        AddNode(newNode);
    }

    public void AddNode(double x, double y, float R, float G, float B)
    {
        Node newNode = new Node((float) x, (float) y, R, G, B);
        AddNode(newNode);
    }

    public void AddNode(Node node)
    {
        nodes.add(node);
        if (nodes.size() == 1)
            {
                w = new boolean[1][1];
                w[0][0] = false;
            }
        else
            {
                boolean[][] nw = new boolean[nodes.size()][nodes.size()];
                for (int i = 0; i < nodes.size() - 1; i++)
                    for (int j = 0; j < nodes.size() - 1; j++)
                        nw[i][j] = w[i][j];
                w = nw;
            }
    }

    public void DeleteNode(int index)
    {
        if (index >= nodes.size())
            return;
        boolean[][] nw = new boolean[nodes.size() - 1][nodes.size() - 1];
        int r = 0;
        int c;
        for (int i = 0; i < nodes.size(); i++)
            {
                if (i != index)
                    {
                        c = 0;
                        for (int j = 0; j < nodes.size(); j++)
                            {
                                if (j != index)
                                    {
                                        nw[r][c] = w[i][j];
                                        c++;
                                    }
                            }
                        r++;
                    }
            }
        w = nw;
        nodes.remove(index);
    }

    public boolean HasEdge(int index1, int index2)
    {
        if (index1 < 0)
            return false;
        if (index2 < 0)
            return false;
        if (index1 >= nodes.size() || index2 >= nodes.size())
            return false;
        return w[index1][index2];
    }

    public void AddEdge(int index1, int index2)
    {
        if (index1 < 0)
            return;
        if (index2 < 0)
            return;
        if (index1 >= nodes.size() || index2 >= nodes.size())
            return;
        if (index1 == index2)
            return;
        w[index1][index2] = true;
        w[index2][index1] = true;
    }

    public void DeleteEdge(int index1, int index2)
    {
        if (index1 < 0)
            return;
        if (index2 < 0)
            return;
        if (index1 >= nodes.size() || index2 >= nodes.size())
            return;
        if (index1 == index2)
            return;
        w[index1][index2] = false;
        w[index2][index1] = false;
    }

    public void ApplyRGraph(float r)
    {
        for (int i = 0; i < nodes.size(); i++)
            for (int j = 0; j < nodes.size(); j++)
                {
                    w[i][j] = false;
                    w[j][i] = false;
                    if (Distance(nodes.get(i), nodes.get(j)) < r)
                        {
                            w[i][j] = true;
                            w[j][i] = true;
                        }
                }

    }

    double Distance(Node node1, Node node2)
    {
        return Math.sqrt(Math.pow(node1.x - node2.x, 2)
                + Math.pow(node1.y - node2.y, 2));
    }

    public void Clear()
    {
        nodes.clear();
        w = new boolean[0][0];
    }

}




public class GraphGenerator
{
    float x1;

    public GraphGenerator()
    {
        x1 = 10;
    }

    public void CompleteGraph(PApplet applet, Graph graph, int n)
    {
        graph.Clear();
        float del = 360 / (float) (n);
        float t = 0;

        float c_x = (ResourceManager.getInstance().appletWidth - 20) / 2;
        float c_y = ResourceManager.getInstance().appletHeight / 2;

        float x2 = ResourceManager.getInstance().appletWidth - 100;

        float y1 = 24;
        float y2 = ResourceManager.getInstance().appletHeight - 24;
        for (int i = 1; i <= n; i++)
            {
                graph.AddNode(

                        (float) (((c_x + Math.cos(DegGrad(t))
                                * ((x2 - x1 - 60) / 2)))),
                        (float) ((c_y + Math.sin(DegGrad(t))
                                * ((y2 - y1 - 10) / 2))),
                        random(160, 250), 0, random(140));
                t = t + del;
            }
        for (int i = 0; i < n; i++)
            for (int j = i + 1; j < n; j++)
                graph.AddEdge(i, j);
    }

     public void StarGraph(PApplet applet, Graph graph, int n)
    {
        graph.Clear();
        float t = 0;

        float c_x = (ResourceManager.getInstance().appletWidth - 20) / 2;
        float c_y = ResourceManager.getInstance().appletHeight / 2;

        float x2 = ResourceManager.getInstance().appletWidth - 100;

        float y1 = 24;
        float y2 = ResourceManager.getInstance().appletHeight - 24;
        float del = 360 / (float) (n - 1);
        t = 0;
        graph.AddNode(c_x, c_y);
        for (int i = 1; i < n; i++)
            {
                graph.AddNode((c_x + Math.cos(DegGrad(t))
                        * ((x2 - x1 - 60) / 2)), (c_y + Math.sin(DegGrad(t))
                        * ((y2 - y1 - 30) / 2)), random(160, 250), 0,
                        random(140));
                t = t + del;
            }
        for (int i = 1; i < n; i++)
            {
                graph.AddEdge(0, i);
            }
    }

   


public void BananaGraph(PApplet applet, Graph graph, int n, int m)
    {
        graph.Clear();
        float t = 0;
        n = n + 1;
        float c_x = (ResourceManager.getInstance().appletWidth - 20) / 2;
        float c_y = ResourceManager.getInstance().appletHeight / 2;

        float x2 = ResourceManager.getInstance().appletWidth - 100;

        float y1 = 24;
        float y2 = ResourceManager.getInstance().appletHeight - 24;

        float del = 360 / (float) (n - 1);
        t = 0;
        graph.AddNode(c_x, c_y);
        float innerDel = 360 / (float) (m - 1);
        float innerTheta = 0;
        int innerLength = 60;
        int v = 300;
        for (int i = 1; i < n; i++)
            {
                double nx = (c_x + Math.cos(DegGrad(t)) * ((x2 - x1 - v) / 2));
                double ny = (c_y + Math.sin(DegGrad(t)) * ((y2 - y1 - v) / 2));
                graph.AddNode(nx, ny, random(160, 250), 0,
                        random(140));
                t = t + del;
            }
        for (int i = 1; i < n; i++)
            {
                graph.AddEdge(0, i);
            }

        t = 0;
        for (int i = 1; i < n; i++)
            {
                double nx = (c_x + Math.cos(DegGrad(t)) * ((x2 - x1 - v) / 2));
                double ny = (c_y + Math.sin(DegGrad(t)) * ((y2 - y1 - v) / 2));
                innerTheta = t + 180;
                t = t + del;
                for (int j = 0; j < m - 2; j++)
                    {
                        innerTheta = innerTheta + innerDel;
                        double innerX = nx + Math.cos(DegGrad(innerTheta))
                                * innerLength;
                        double innerY = ny + Math.sin(DegGrad(innerTheta))
                                * innerLength;
                        graph.AddNode(innerX, innerY, random(160, 250),
                                0, random(140));
                    }
            }

        int cnt = n;
        for (int i = 1; i < n; i++)
            for (int j = 1; j <= m - 2; j++)
                {
                    graph.AddEdge(i, cnt);
                    cnt++;
                }
    }

    public void BinaryGraph(PApplet applet, Graph graph, int n, int m)
    {
        graph.Clear();
        float t = 0;

        float c_x = (ResourceManager.getInstance().appletWidth - 20) / 2;
        float c_y = ResourceManager.getInstance().appletHeight / 2;

        float x2 = ResourceManager.getInstance().appletWidth - 100;

        float y1 = 24;
        float y2 = ResourceManager.getInstance().appletHeight - 24;

        float del = (y2 - y1 - 80) / (float) n;
        for (int i = 1; i <= n; i++)
            graph.AddNode(new Node(c_x - 300, 20 + i * del, random(160,
                    250), 0, random(140)));

        del = (y2 - y1 - 80) / (float) m;
        for (int i = 1; i <= m; i++)
            graph.AddNode(new Node(c_x + 200, 20 + i * del, random(160,
                    250), 0, random(140)));

        for (int i = 0; i < n; i++)
            for (int j = n; j < n + m; j++)
                graph.AddEdge(i, j);
    }

    public void TreeGraph(PApplet applet, Graph graph, int levels)
    {
        graph.Clear();
        float t = 0;
        float c_x = (ResourceManager.getInstance().appletWidth - 20) / 2;
        float c_y = ResourceManager.getInstance().appletHeight / 2;

        float x2 = ResourceManager.getInstance().appletWidth - 100;

        float y1 = 24;
        float y2 = ResourceManager.getInstance().appletHeight - 24;
        float y = y1 + 20;
        float dely = (y2 - y1 - 10) / (float) levels;
        float dx;
        float x;
        int parts;
        for (int i = 1; i <= levels; i++)
            {
                parts = (int) pow(2, i);
                dx = (x2 - x1 - 10) / (float) parts;
                x = 20 + dx;
                for (int j = 1; j <= pow(2, i - 1); j++)
                    {
                        graph.AddNode(x, y, random(160, 250), 0,
                                random(140));
                        x = x + 2 * dx;
                    }
                y = y + dely;
            }

        for (int i = 1; i <= levels - 1; i++)
            for (int j = (int) pow(2, i - 1) - 1; j < pow(2, i) - 1; j++)
                {
                    // left child
                    graph.AddEdge(j, 2 * j + 1);
                    graph.AddEdge(j, 2 * j + 2);
                }
    }

    public void CycleGraph(PApplet applet, Graph graph, int n)
    {
        graph.Clear();
        float t = 0;

        float c_x = (ResourceManager.getInstance().appletWidth - 20) / 2;
        float c_y = ResourceManager.getInstance().appletHeight / 2;

        float x2 = ResourceManager.getInstance().appletWidth - 100;

        float y1 = 24;
        float y2 = ResourceManager.getInstance().appletHeight - 24;
        float del = 360 / (float) (n);
        t = 0;
        for (int i = 1; i <= n; i++)
            {
                graph.AddNode((c_x + Math.cos(DegGrad(t))
                        * ((x2 - x1 - 60) / 2)), (c_y + Math.sin(DegGrad(t))
                        * ((y2 - y1 - 30) / 2)), random(160, 250), 0,
                        random(140));
                t = t + del;
            }
        for (int i = 0; i < n; i++)
            graph.AddEdge(i, (i + 1) % n);
    }

    public void FriendShip(PApplet applet, Graph graph, int n)
    {
        int m = 3;
        graph.Clear();
        float t = 0;
        n = n + 1;
        float c_x = (ResourceManager.getInstance().appletWidth - 20) / 2;
        float c_y = ResourceManager.getInstance().appletHeight / 2;

        float x2 = ResourceManager.getInstance().appletWidth - 100;

        float y1 = 24;
        float y2 = ResourceManager.getInstance().appletHeight - 24;
        float del = 360 / (float) (n - 1);
        t = 0;
        graph.AddNode(c_x, c_y);
        float innerDel = 90;
        float innerTheta = 0;
        int innerLength = 60;
        int v = 300;
        for (int i = 1; i < n; i++)
            {
                double nx = (c_x + Math.cos(DegGrad(t)) * ((x2 - x1 - v) / 2));
                double ny = (c_y + Math.sin(DegGrad(t)) * ((y2 - y1 - v) / 2));
                graph.AddNode(nx, ny, random(160, 250), 0,
                        random(140));
                t = t + del;
            }
        for (int i = 1; i < n; i++)
            {
                graph.AddEdge(0, i);
            }

        t = 0;
        for (int i = 1; i < n; i++)
            {
                double nx = (c_x + Math.cos(DegGrad(t)) * ((x2 - x1 - v) / 2));
                double ny = (c_y + Math.sin(DegGrad(t)) * ((y2 - y1 - v) / 2));
                innerTheta = t + 180;
                t = t + del;
                for (int j = 0; j < m - 2; j++)
                    {
                        innerTheta = innerTheta + innerDel;
                        double innerX = nx + Math.cos(DegGrad(innerTheta))
                                * innerLength;
                        double innerY = ny + Math.sin(DegGrad(innerTheta))
                                * innerLength;
                        graph.AddNode(innerX, innerY, random(160, 250),
                                0, random(140));
                    }
            }

        int cnt = n;
        for (int i = 1; i < n; i++)
            for (int j = 1; j <= m - 2; j++)
                {
                    graph.AddEdge(i, cnt);
                    graph.AddEdge(0, cnt);
                    cnt++;
                }

    }

    public void CyclePath(PApplet applet, Graph graph, int n, int m)
    {
        n = n * 2;
        graph.Clear();
        float t = 0;

        float c_x = (ResourceManager.getInstance().appletWidth - 20) / 2;
        float c_y = ResourceManager.getInstance().appletHeight / 2;

        float x2 = ResourceManager.getInstance().appletWidth - 100;

        float y1 = 24;
        float y2 = ResourceManager.getInstance().appletHeight - 24;
        float del = 360 / (float) (n);
        t = 0;

        float dx = x2 - x1 - 60;
        float dy = y2 - y1 - 30;
        for (int k = 1; k <= m; k++)
            {
                for (int i = 1; i <= n; i++)
                    {
                        graph.AddNode(
                                (c_x + Math.cos(DegGrad(t)) * ((dx) / 2)),
                                (c_y + Math.sin(DegGrad(t)) * ((dy) / 2)),
                                random(160, 250), 0, random(140));
                        t = t + del;
                    }
                dx = dx - 160;
                dy = dy - 160;
            }
        int cnt = 0;
        for (int k = 1; k <= m; k++)
            {
                for (int i = 0; i < n - 1; i++)
                    {
                        graph.AddEdge(cnt, cnt + 1);
                        cnt++;
                    }
                graph.AddEdge(cnt, cnt - n + 1);
                cnt++;
            }
    }

    public void CLEBSH(PApplet applet, Graph graph)
    {
        int n = 5;
        graph.Clear();
        float t = 0;
        n = n + 1;
        float c_x = (ResourceManager.getInstance().appletWidth - 20) / 2;
        float c_y = ResourceManager.getInstance().appletHeight / 2;

        float x2 = ResourceManager.getInstance().appletWidth - 100;

        float y1 = 24;
        float y2 = ResourceManager.getInstance().appletHeight - 24;

        float del = 360 / (float) (n - 1);
        t = -90;
        for (int i = 1; i < n; i++)
            {
                double nx = (c_x + Math.cos(DegGrad(t)) * ((x2 - x1) / 2));
                double ny = (c_y + Math.sin(DegGrad(t)) * ((y2 - y1) / 2));
                graph.AddNode(nx, ny, random(160, 250), 0,
                        random(140));
                t = t + del;
            }

        t = 90;
        for (int i = 1; i < n; i++)
            {
                double nx = (c_x + Math.cos(DegGrad(t)) * ((x2 - x1 - 360) / 2));
                double ny = (c_y + Math.sin(DegGrad(t)) * ((y2 - y1 - 360) / 2));
                graph.AddNode(nx, ny, random(160, 250), 0,
                        random(140));
                t = t + del;
            }

        t = -90;
        for (int i = 1; i < n; i++)
            {
                double nx = (c_x + Math.cos(DegGrad(t)) * ((x2 - x1 - 560) / 2));
                double ny = (c_y + Math.sin(DegGrad(t)) * ((y2 - y1 - 560) / 2));
                graph.AddNode(nx, ny, random(160, 250), 0,
                        random(140));
                t = t + del;
            }
        for (int i = 0; i <= 4; i++)
            {
                graph.AddEdge(i, (i + 1) % 5);
            }

        graph.AddNode(c_x, c_y);
        graph.AddEdge(0, 6);
        graph.AddEdge(0, 9);
        graph.AddEdge(0, 10);

        graph.AddEdge(1, 5);
        graph.AddEdge(1, 7);
        graph.AddEdge(1, 11);

        graph.AddEdge(2, 6);
        graph.AddEdge(2, 8);
        graph.AddEdge(2, 12);

        graph.AddEdge(3, 7);
        graph.AddEdge(3, 9);
        graph.AddEdge(3, 13);

        graph.AddEdge(4, 5);
        graph.AddEdge(4, 8);
        graph.AddEdge(4, 14);

        graph.AddEdge(5, 12);
        graph.AddEdge(5, 13);
        graph.AddEdge(5, 15);

        graph.AddEdge(6, 13);
        graph.AddEdge(6, 14);
        graph.AddEdge(6, 15);

        graph.AddEdge(7, 10);
        graph.AddEdge(7, 14);
        graph.AddEdge(7, 15);

        graph.AddEdge(8, 10);
        graph.AddEdge(8, 11);
        graph.AddEdge(8, 15);

        graph.AddEdge(9, 11);
        graph.AddEdge(9, 12);
        graph.AddEdge(9, 15);

        graph.AddEdge(10, 12);
        graph.AddEdge(10, 13);

        graph.AddEdge(11, 13);
        graph.AddEdge(11, 14);

        graph.AddEdge(12, 14);

    }

    public void DURER(PApplet applet, Graph graph)
    {
        int n = 6;
        graph.Clear();
        float t = 0;
        n = n + 1;
        float c_x = (ResourceManager.getInstance().appletWidth - 20) / 2;
        float c_y = ResourceManager.getInstance().appletHeight / 2;

        float x2 = ResourceManager.getInstance().appletWidth - 100;

        float y1 = 24;
        float y2 = ResourceManager.getInstance().appletHeight - 24;

        float del = 360 / (float) (n - 1);
        t = 0;
        for (int i = 1; i < n; i++)
            {
                double nx = (c_x + Math.cos(DegGrad(t)) * ((x2 - x1) / 2));
                double ny = (c_y + Math.sin(DegGrad(t)) * ((y2 - y1) / 2));
                graph.AddNode(nx, ny, random(160, 250), 0,
                        random(140));
                t = t + del;
            }

        for (int i = 1; i < n; i++)
            {
                double nx = (c_x + Math.cos(DegGrad(t)) * ((x2 - x1 - 300) / 2));
                double ny = (c_y + Math.sin(DegGrad(t)) * ((y2 - y1 - 300) / 2));
                graph.AddNode(nx, ny, random(160, 250), 0,
                        random(140));
                t = t + del;
            }

        for (int i = 0; i <= 5; i++)
            {
                graph.AddEdge(i, (i + 1) % 6);
                graph.AddEdge(i, i + 6);
            }

        graph.AddEdge(6, 8);
        graph.AddEdge(6, 10);
        graph.AddEdge(7, 9);
        graph.AddEdge(7, 11);
        graph.AddEdge(10, 8);
        graph.AddEdge(10, 6);
        graph.AddEdge(11, 9);

    }

    public void Franklin(PApplet applet, Graph graph)
    {
        int n = 6;
        graph.Clear();
        float t = 0;
        n = n + 1;
        float c_x = (ResourceManager.getInstance().appletWidth - 20) / 2;
        float c_y = ResourceManager.getInstance().appletHeight / 2;

        float x2 = ResourceManager.getInstance().appletWidth - 100;

        float y1 = 24;
        float y2 = ResourceManager.getInstance().appletHeight - 24;

        float del = 360 / (float) (n - 1);
        t = 0;
        for (int i = 1; i < n; i++)
            {
                double nx = (c_x + Math.cos(DegGrad(t)) * ((x2 - x1) / 2));
                double ny = (c_y + Math.sin(DegGrad(t)) * ((y2 - y1) / 2));
                graph.AddNode(nx, ny, random(160, 250), 0,
                        random(140));
                t = t + del;
            }

        for (int i = 1; i < n; i++)
            {
                double nx = (c_x + Math.cos(DegGrad(t)) * ((x2 - x1 - 300) / 2));
                double ny = (c_y + Math.sin(DegGrad(t)) * ((y2 - y1 - 300) / 2));
                graph.AddNode(nx, ny, random(160, 250), 0,
                        random(140));
                t = t + del;
            }

        for (int i = 0; i <= 5; i++)
            {
                graph.AddEdge(i, (i + 1) % 6);
                graph.AddEdge(i, i + 6);
            }

        graph.AddEdge(6, 9);
        graph.AddEdge(6, 11);
        graph.AddEdge(7, 8);
        graph.AddEdge(7, 10);
        graph.AddEdge(9, 10);
        graph.AddEdge(8, 11);

    }

    public void HERSCHEL(PApplet applet, Graph graph)
    {
        int n = 8;
        graph.Clear();
        float t = 0;
        n = n + 1;
        float c_x = (ResourceManager.getInstance().appletWidth - 20) / 2;
        float c_y = ResourceManager.getInstance().appletHeight / 2;

        float x2 = ResourceManager.getInstance().appletWidth - 100;

        float y1 = 24;
        float y2 = ResourceManager.getInstance().appletHeight - 24;
        float del = 360 / (float) (n - 1);
        t = 0;
        for (int i = 1; i < n; i++)
            {
                double nx = (c_x + Math.cos(DegGrad(t)) * ((x2 - x1) / 2));
                double ny = (c_y + Math.sin(DegGrad(t)) * ((y2 - y1) / 2));
                graph.AddNode(nx, ny, random(160, 250), 0,
                        random(140));
                t = t + del;
            }

        graph.AddNode(c_x, c_y, random(160, 250), 0, random(140));
        graph.AddNode(c_x + 300, c_y, random(160, 250), 0,
                random(140));
        graph.AddNode(c_x - 300, c_y, random(160, 250), 0,
                random(140));

        for (int i = 0; i <= 7; i++)
            {
                graph.AddEdge(i, (i + 1) % 8);
                if (i % 2 == 1)
                    graph.AddEdge(i, 8);
            }

        graph.AddEdge(0, 9);
        graph.AddEdge(2, 9);
        graph.AddEdge(2, 10);
        graph.AddEdge(4, 10);
        graph.AddEdge(6, 9);
        graph.AddEdge(6, 10);

    }

    public void sousselier(PApplet applet, Graph graph)
    {
        int n = 15;
        graph.Clear();
        float t = 0;
        n = n + 1;
        float c_x = (ResourceManager.getInstance().appletWidth - 20) / 2;
        float c_y = ResourceManager.getInstance().appletHeight / 2;

        float x2 = ResourceManager.getInstance().appletWidth - 100;

        float y1 = 24;
        float y2 = ResourceManager.getInstance().appletHeight - 24;
        float del = 360 / (float) (n - 1);
        t = 0;
        for (int i = 1; i < n; i++)
            {
                double nx = (c_x + Math.cos(DegGrad(t)) * ((x2 - x1) / 2));
                double ny = (c_y + Math.sin(DegGrad(t)) * ((y2 - y1) / 2));
                graph.AddNode(nx, ny, random(160, 250), 0,
                        random(140));
                t = t + del;
            }

        graph.AddNode(c_x, c_y, random(160, 250), 0, random(140));

        for (int i = 0; i <= 14; i++)
            {
                graph.AddEdge(i, (i + 1) % 15);
            }

        graph.AddEdge(0, 4);
        graph.AddEdge(0, 10);
        graph.AddEdge(1, 12);
        graph.AddEdge(2, 15);
        graph.AddEdge(3, 7);
        graph.AddEdge(5, 15);
        graph.AddEdge(6, 10);
        graph.AddEdge(7, 12);
        graph.AddEdge(8, 15);
        graph.AddEdge(9, 13);
        graph.AddEdge(11, 15);
        graph.AddEdge(14, 15);

    }

    public void tietze(PApplet applet, Graph graph)
    {
        int n = 9;
        graph.Clear();
        float t = 0;
        n = n + 1;
        float c_x = (ResourceManager.getInstance().appletWidth - 20) / 2;
        float c_y = ResourceManager.getInstance().appletHeight / 2;

        float x2 = ResourceManager.getInstance().appletWidth - 100;

        float y1 = 24;
        float y2 = ResourceManager.getInstance().appletHeight - 24;
        float del = 360 / (float) (n - 1);
        t = 0;
        for (int i = 1; i < n; i++)
            {
                double nx = (c_x + Math.cos(DegGrad(t)) * ((x2 - x1) / 2));
                double ny = (c_y + Math.sin(DegGrad(t)) * ((y2 - y1) / 2));
                graph.AddNode(nx, ny, random(160, 250), 0,
                        random(140));
                t = t + del;
            }

        graph.AddNode(c_x + 50, c_y, random(160, 250), 0,
                random(140));
        graph.AddNode(c_x - 50, c_y + 100, random(160, 250), 0,
                random(140));
        graph.AddNode(c_x - 50, c_y - 100, random(160, 250), 0,
                random(140));

        for (int i = 0; i <= 8; i++)
            {
                graph.AddEdge(i, (i + 1) % 9);
            }

        graph.AddEdge(0, 9);
        graph.AddEdge(3, 10);
        graph.AddEdge(6, 11);
        graph.AddEdge(1, 5);
        graph.AddEdge(2, 7);

        graph.AddEdge(9, 10);
        graph.AddEdge(10, 11);
        graph.AddEdge(11, 9);
        graph.AddEdge(4, 8);

    }

  


   

    double DegGrad(float theta)
    {
        return theta * Math.PI / 180;
    }
}




public class ResourceManager
{
    static ResourceManager Instance;
    public int nodesSize;
    public int treshhold;
    public int appletWidth;
    public int appletHeight;
    public Graph graph;

    private ResourceManager()
    {
        nodesSize = 30;
        treshhold = 16;
    }

    public static ResourceManager getInstance()
    {
        if (Instance == null)
            Instance = new ResourceManager();
        return Instance;
    }
}






public class Graph
{
    public List<Node> nodes;
    public boolean[][] w;

    public Graph()
    {
        nodes = new ArrayList<Node>();
    }

    public void AddNode(double x, double y)
    {
        Node newNode = new Node((float) x, (float) y);
        AddNode(newNode);
    }

    public void AddNode(double x, double y, float R, float G, float B)
    {
        Node newNode = new Node((float) x, (float) y, R, G, B);
        AddNode(newNode);
    }

    public void AddNode(Node node)
    {
        nodes.add(node);
        if (nodes.size() == 1)
            {
                w = new boolean[1][1];
                w[0][0] = false;
            }
        else
            {
                boolean[][] nw = new boolean[nodes.size()][nodes.size()];
                for (int i = 0; i < nodes.size() - 1; i++)
                    for (int j = 0; j < nodes.size() - 1; j++)
                        nw[i][j] = w[i][j];
                w = nw;
            }
    }

    public void DeleteNode(int index)
    {
        if (index >= nodes.size())
            return;
        boolean[][] nw = new boolean[nodes.size() - 1][nodes.size() - 1];
        int r = 0;
        int c;
        for (int i = 0; i < nodes.size(); i++)
            {
                if (i != index)
                    {
                        c = 0;
                        for (int j = 0; j < nodes.size(); j++)
                            {
                                if (j != index)
                                    {
                                        nw[r][c] = w[i][j];
                                        c++;
                                    }
                            }
                        r++;
                    }
            }
        w = nw;
        nodes.remove(index);
    }

    public boolean HasEdge(int index1, int index2)
    {
        if (index1 < 0)
            return false;
        if (index2 < 0)
            return false;
        if (index1 >= nodes.size() || index2 >= nodes.size())
            return false;
        return w[index1][index2];
    }

    public void AddEdge(int index1, int index2)
    {
        if (index1 < 0)
            return;
        if (index2 < 0)
            return;
        if (index1 >= nodes.size() || index2 >= nodes.size())
            return;
        if (index1 == index2)
            return;
        w[index1][index2] = true;
        w[index2][index1] = true;
    }

    public void DeleteEdge(int index1, int index2)
    {
        if (index1 < 0)
            return;
        if (index2 < 0)
            return;
        if (index1 >= nodes.size() || index2 >= nodes.size())
            return;
        if (index1 == index2)
            return;
        w[index1][index2] = false;
        w[index2][index1] = false;
    }

    public void ApplyRGraph(float r)
    {
        for (int i = 0; i < nodes.size(); i++)
            for (int j = 0; j < nodes.size(); j++)
                {
                    w[i][j] = false;
                    w[j][i] = false;
                    if (Distance(nodes.get(i), nodes.get(j)) < r)
                        {
                            w[i][j] = true;
                            w[j][i] = true;
                        }
                }

    }

    double Distance(Node node1, Node node2)
    {
        return Math.sqrt(Math.pow(node1.x - node2.x, 2)
                + Math.pow(node1.y - node2.y, 2));
    }

    public void Clear()
    {
        nodes.clear();
        w = new boolean[0][0];
    }

}



public class Node
{
    public float x;
    public float y;
    public float R;
    public float G;
    public float B;

    public Node(float x, float y)
    {
        this.x = x;
        this.y = y;
        R = 240;
        G = 0;
        B = 0;
    }

    public Node(float x, float y, float R, float G, float B)
    {
        this.x = x;
        this.y = y;
        this.R = R;
        this.G = G;
        this.B = B;
    }
}





public class Point
{
    double[] values;
    public int id;

    public Point(double[] values, int id)
    {
        this.values = values;
        this.id = id;
    }
    
}