Java Fruchterman和Reingold算法顶点在输出中占据相同的位置(图形布局)
我试图在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
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();
}
}