Java Fruchterman和Reingold算法顶点在输出中占据相同的位置(图形布局)

Java Fruchterman和Reingold算法顶点在输出中占据相同的位置(图形布局),java,algorithm,layout,graph,graph-drawing,Java,Algorithm,Layout,Graph,Graph Drawing,我试图在Java中实现Fruchterman和Reingold算法,但由于某些原因,输出顶点的坐标有时会占用相同的坐标,这不是该算法想要的。我哪里出错了 坐标对象(向量) 节点对象 import java.util.LinkedList; public class Node { private LinkedList<Node> incidentList; //has 30 elements for 30 vertices. 1 if incident, 0 if not

我试图在Java中实现Fruchterman和Reingold算法,但由于某些原因,输出顶点的坐标有时会占用相同的坐标,这不是该算法想要的。我哪里出错了

坐标对象(向量)

节点对象

import java.util.LinkedList;

public class Node {
    private LinkedList<Node> incidentList; //has 30 elements for 30 vertices. 1 if incident, 0 if not
    private int color;
    private Coordinates coord;
    private Coordinates disp;

    public Coordinates getDisp() {
        return disp;
    }

    public void setDisp(float x, float y) {
        disp.setX(x);
        disp.setY(y);
    }
    public void setDisp(Coordinates d) {
        disp = d;
    }

    private int id;
    public Node(){
        incidentList = new LinkedList<Node>();
        color = 0;
        coord = new Coordinates(0,0);
        disp = new Coordinates(0,0);
        id = -1;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public LinkedList<Node> getIncidentList() {
        return incidentList;
    }
    public void addEdge(Node n) {
        incidentList.add(n);
    }
    public void removeEdge(Node n){
        incidentList.remove(n);
    }
    public int getColor() {
        return color;
    }
    public void setColor(int color) {
        this.color = color;
    }
    public Coordinates getCoord() {
        return coord;
    }
    public void setCoord(float x, float y) {
        coord.setX(x);
        coord.setY(y);
    }
    public int getDegree(){
        return incidentList.size();
    }

    public boolean isAdjacent(Node n){
        return incidentList.contains(n);
    }

}
import java.util.LinkedList;
公共类节点{
private LinkedList incidentList;//30个顶点包含30个元素。如果是偶发事件,则为1;如果不是偶发事件,则为0
私人内特色;
私人协调机构;
私人坐标显示;
公共坐标getDisp(){
返回disp;
}
公共void setDisp(浮点x,浮点y){
显示设置x(x);
副秘书长(y);
}
公共void setDisp(坐标d){
disp=d;
}
私有int-id;
公共节点(){
incidentList=新链接列表();
颜色=0;
坐标=新坐标(0,0);
disp=新坐标(0,0);
id=-1;
}
公共int getId(){
返回id;
}
公共无效集合id(内部id){
this.id=id;
}
公共链接列表getIncidentList(){
返回意外事件列表;
}
公共无效添加(节点n){
意外事故清单。添加(n);
}
公共无效删除(节点n){
意外事件列表。删除(n);
}
public int getColor(){
返回颜色;
}
公共void setColor(int-color){
这个颜色=颜色;
}
公共坐标getCoord(){
返回坐标;
}
公共无效设置坐标(浮动x,浮动y){
坐标setX(x);
协调塞蒂(y);
}
公共int getDegree(){
返回incidentList.size();
}
公共布尔不相邻(节点n){
返回意外事件列表。包含(n);
}
}
图形对象(具有布局算法功能frlayout)

import java.util.ArrayList;
导入java.util.Random;
公共类MyGraph{
私人最终int不尊重=-1;
私人最终int MORECOLOR=-3;
专用最终浮点数ε=0.003f;
私有ArrayList graphNodes;//最多30个顶点
私有int-n证书=0;
私人智力得分=50;
int maxColor=0;
int[]colorPopulation=新int[15];
双边界x,边界y,C;
公共双getBoundx(){
返回boundx;
}
公共无效setBoundx(双边界X){
this.boundx=boundx;
}
公共双边界(){
返回边界;
}
公共空间退边界(双边界){
this.boundy=boundy;
}
公共双getC(){
返回C;
}
公共无效setC(双c){
C=C;
}
公共整数getScore(){
返回分数;
}
公共核心(整数分数){
这个分数=分数;
}
public int getnVertices(){
返回证书;
}
公共MyGraph(){
graphNodes=新的ArrayList();
}
公共阵列列表getGraphNodes(){
返回图形节点;
}
//将新节点添加到图形中
//还要设置该节点的id
公共void addNode(节点n){
添加(n)个图形节点;
n、 setId(nVertices++);
}
公共无效添加(节点n1、节点n2){
n1.附录(n2);
n2.附录(n1);
}
//随机生成具有parsity的图
public void random生成(双重解析){//parse介于0和1之间
Random gen=新的Random(System.currentTimeMillis());
int tempnertices=6;//在此处更改为随机数
for(int i=0;iimport java.util.LinkedList;

public class Node {
    private LinkedList<Node> incidentList; //has 30 elements for 30 vertices. 1 if incident, 0 if not
    private int color;
    private Coordinates coord;
    private Coordinates disp;

    public Coordinates getDisp() {
        return disp;
    }

    public void setDisp(float x, float y) {
        disp.setX(x);
        disp.setY(y);
    }
    public void setDisp(Coordinates d) {
        disp = d;
    }

    private int id;
    public Node(){
        incidentList = new LinkedList<Node>();
        color = 0;
        coord = new Coordinates(0,0);
        disp = new Coordinates(0,0);
        id = -1;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public LinkedList<Node> getIncidentList() {
        return incidentList;
    }
    public void addEdge(Node n) {
        incidentList.add(n);
    }
    public void removeEdge(Node n){
        incidentList.remove(n);
    }
    public int getColor() {
        return color;
    }
    public void setColor(int color) {
        this.color = color;
    }
    public Coordinates getCoord() {
        return coord;
    }
    public void setCoord(float x, float y) {
        coord.setX(x);
        coord.setY(y);
    }
    public int getDegree(){
        return incidentList.size();
    }

    public boolean isAdjacent(Node n){
        return incidentList.contains(n);
    }

}
import java.util.ArrayList;
import java.util.Random;


public class MyGraph{
    private final int DISRESPECT = -1;
    private final int MORECOLOR = -3;
    private final float EPSILON = 0.003f;
    private ArrayList<Node> graphNodes; //maximum of 30 vertices
    private int nVertices = 0;
    private int score = 50;
    int maxColor = 0;
    int[] colorPopulation = new int[15];
    double boundx, boundy, C;

    public double getBoundx() {
        return boundx;
    }

    public void setBoundx(double boundx) {
        this.boundx = boundx;
    }

    public double getBoundy() {
        return boundy;
    }

    public void setBoundy(double boundy) {
        this.boundy = boundy;
    }

    public double getC() {
        return C;
    }

    public void setC(double c) {
        C = c;
    }

    public int getScore() {
        return score;
    }
    public void setScore(int score) {
        this.score = score;
    }
    public int getnVertices() {
        return nVertices;
    }
    public MyGraph(){
        graphNodes = new ArrayList<Node>();
    }
    public ArrayList<Node> getGraphNodes() {
        return graphNodes;
    }

    //add a new node into the graph
    //also set the id of that node
    public void addNode(Node n){
        graphNodes.add(n);
        n.setId(nVertices++);
    }
    public void addEdge(Node n1, Node n2){
        n1.addEdge(n2);
        n2.addEdge(n1);
    }

    //randomly generate a graph with parsity
    public void randomGenerating(double parse){ //parse is between 0 and 1
        Random gen = new Random(System.currentTimeMillis());
        int tempNVertices = 6; //CHANGE HERE TO BECOME A RANDOM NUMBER
        for(int i = 0; i< tempNVertices; i++){
            Node n = new Node();
            float x = 0,y = 0;
            while(true){
                boolean flag = true;
                x = gen.nextFloat();
                y = gen.nextFloat();
                for(int j = 0; j < i; j++){
                    if(x*boundx == graphNodes.get(j).getCoord().getX() && y*boundx == graphNodes.get(j).getCoord().getY())
                        flag = false; break;
                }
                if (flag)
                    break;
            }
            n.setCoord((float)(x*boundx),(float)(y*boundy));
            addNode(n);
        }
        for(int i = 0; i < tempNVertices; i++){
            for(int j = i + 1; j < tempNVertices; j++){
                if(gen.nextDouble() < parse){
                    addEdge(graphNodes.get(i),graphNodes.get(j));
                }
            }
        }
    }

    public void frLayout(){
        double w = boundx, h = boundy;
        double area = w*h;
        double k = C*Math.sqrt(area/nVertices);
        double temperature = 1000;
        for(int i = 0; i < nVertices; i++)
            System.out.println(graphNodes.get(i).getCoord().getX()+" "+graphNodes.get(i).getCoord().getY());
        System.out.println("------------------------------");
        for(int m = 0; m< 900; m++){
            for(int i = 0; i < nVertices; i++){
                Node v = graphNodes.get(i);
                v.setDisp(0,0);
                for(int j = 0; j< nVertices; j++){
                    Node u = graphNodes.get(j);
                    if(i!= j){
                        Coordinates delta = v.getCoord().subtract(u.getCoord());
                        double myFr = fr(u,v,k);

                        v.setDisp(v.getDisp().add(delta.unit().scale((float)myFr)));
                        if(Double.isNaN(v.getDisp().getX())){
                            System.out.println("PANIC: "+u.getCoord().getX()+" "+u.getCoord().getY()+" "+delta.getX()+" "+v.getCoord().getX());
                            return;
                        }
                    }
                }
            }
            for(int i = 0; i < nVertices; i++){
                Node v = graphNodes.get(i);
                for(int j = i+1; j< nVertices; j++){
                    Node u = graphNodes.get(j);
                    if(v.isAdjacent(u)){
                        Coordinates delta = v.getCoord().subtract(u.getCoord());
                        double myFa = fa(u,v,k);
                        v.setDisp(v.getDisp().subtract(delta.unit().scale((float)myFa)));
                        u.setDisp(u.getDisp().add(delta.unit().scale((float)myFa)));

                    }
                }
            }

            for(int i = 0; i< nVertices; i++){
                //actually adjusting the nodes
                Node v = graphNodes.get(i);
                if(i == 0){
                    System.out.println(v.getCoord().getX()+" "+v.getCoord().getY());
                    Coordinates disp = v.getDisp().unit().scale((float)Math.min(v.getDisp().length(), temperature));
                    System.out.println(">>"+disp.getX()+" "+disp.getY());
                }
                Coordinates newCoord = (v.getCoord().add(v.getDisp().unit().scale((float)Math.min(v.getDisp().length(), temperature))));
                v.setCoord(newCoord.getX(), newCoord.getY());

//                //prevent from going outside of bound
//                float x = (float)Math.min(w, Math.max(0,v.getCoord().getX()));
//                float y = (float)Math.min(h, Math.max(0, v.getCoord().getY()));
//                
//                v.setCoord(x,y);
                if(i == 0){
                    System.out.println(v.getCoord().getX()+" "+v.getCoord().getY());
                }
            }
            temperature *= 0.9;
            System.out.println("TEMPERATURE = "+temperature);
        }
        for(int i = 0; i< nVertices; i++){
            Node v = graphNodes.get(i);
            System.out.println(v.getCoord().getX()+" "+v.getCoord().getY());;
        }
    }
    private double fa(Node ni, Node nj, double k){
        double distance = ni.getCoord().distance(nj.getCoord());
        return distance*distance/k;
    }
    private double fr(Node ni, Node nj, double k){
        double distance = ni.getCoord().distance(nj.getCoord());
        return k*k/(distance+0.000001);
    }
    public static void main(String[] args){
        MyGraph grph = new MyGraph();
        grph.setBoundx(480);
        grph.setBoundy(480);
        grph.setC(1);
        grph.randomGenerating(1);
        grph.frLayout();
    }

}