svg依存關係圖中節點間連線的起止點的確定

節點連線的規律:

1.每個節點至多隻有一個出線

2.每個節點上的終止點滿足:起點在當前節點的左側,則終點在當前節點的點位也靠左,並且層級越低越靠左;起點在當前節點的右側,則終點在當前節點的點位也靠右,並且層級越低越靠右。

知道了所有終點的位置,則空閒的那個點位就是起始點位。

下面是java代碼的實現示例:

public class App {
//沒有出線的標誌
private static final int NOOUT = -1;

public static void main(String[] args) throws Exception {
//gg存放的是節點間的關係(第n個節點與哪個節點相連)
//車輛仍舊可以堅持到最近的修理廠。
//int[] gg = {2,2,-1,2,3,6,7,3,2};
//戴相龍說中國經濟發展爲亞洲作出積極貢獻
int[] gg = {1, -1, 4, 4, 7, 7, 5, 1, 9 ,7};

//節點的層級信息
Map<Integer,Integer> high = new TreeMap<>();
//各個節點的層級緩存信息
Map<String,Integer> highTempMap = new HashMap<>();
//節點的點數信息
Map<Integer,int[]> node = new TreeMap<>();
//連線的起終信息
Map<Integer,int[]> result = new TreeMap<>();

int temp = -1;
for(int i =0,j=gg.length;i<j;i++){
temp = gg[i];
if(temp == NOOUT){
continue;
}
high.put(i, getLevel(i, temp, gg,highTempMap));
}
System.out.println("層級統計---"+high);
highTempMap = null;

int count = 0;
for(int i=0,j=gg.length;i<j;i++){
count = 0;
if(gg[i] != NOOUT){
count++;
}
for(int m=0;m<j;m++){
if(gg[m] == i){
count++;
}
}
node.put(i, new int[count]);
}

getEnd(high, node, result, gg);
getStart(node, result);

for(Entry<Integer, int[]> entry : result.entrySet()){
System.out.println("節點"+entry.getKey()+"------起點:"+entry.getValue()[0]+"----終點:"+entry.getValue()[1]);
}

}


/**
* 層級關係的統計
* @param start 起始節點的順序索引
* @param end 終止節點的順序索引
* @param gg 節點關係描述
* @return
*/
public static int getLevel(int start,int end,int[] gg,Map<String,Integer> highMap){
if(highMap.get(start+"-"+end) != null){
return highMap.get(start+"-"+end);
}
int result = 0;
//相鄰節點,直接返回
if(Math.abs(end - start) == 1){
//二者有關係
if(gg[start] == end || gg[end] == start){
result = 1;
}
highMap.put(start+"-"+end,result);
return result;
}else{
//非相鄰節點,遞歸計算
int left =0,right = 0;
if(start < end){
//中間節點的高度+起止點的是否相連
left = getLevel(start, end-1,gg,highMap)+(gg[start] == end-1 || gg[end-1] == start ? 1 : 0);
right = getLevel(end, start+1,gg,highMap)+(gg[end] == start+1 || gg[start+1] == end ? 1 : 0);
}else{
left = getLevel(end+1, start,gg,highMap)+(gg[start] == end+1 || gg[end+1] == start ? 1 : 0);
right = getLevel(start-1, end,gg,highMap)+(gg[start-1] == end || gg[end] == start-1 ? 1 : 0);
}
result = Math.max(left, right);
highMap.put(start+"-"+end,result);
return result;
}
}

/**
* 連線終點的確定
* @param high
* @param node
* @param result
* @param gg
*/
public static void getEnd(Map<Integer,Integer> high,Map<Integer,int[]> node,Map<Integer,int[]> result,int[] gg){
int temp;
for(int i=0,j=gg.length; i<j; i++){
temp = gg[i];
if(temp == NOOUT){
continue;
}

int[] se = new int[2];
int level = high.get(i);
int[] countE = node.get(temp);

//找終點
int end = -1;
int endLength = countE.length;
//是否右拐
boolean turnRight = i < temp;
//終點節點只有一個點
if(endLength == 1){
end = 0;
}else if(level == 1){
if(turnRight){
end = 0;
}else{
end = endLength-1;
}
}else{
//獲取終點所有的層級
int[] levels = getEndNodeLevels(temp, high, gg,turnRight);
//只有一個
if(levels.length == 0){
if(turnRight){
end = 0;
}else{
end = endLength-1;
}
}else{
//右拐 連接點靠左
Arrays.sort(levels);
int index = 0;
for(int aa : levels){
if(level == aa){
break;
}
index++;
}
if(turnRight){
//小於當前層級的個數
end = index;
}else{
end = endLength - index-1;
}
}

}
countE[end] = 1;
se[1] = end+1;
result.put(i, se);

}
}

/**
* 獲取終點節點的同一方向的所有層級
* @param endNode
* @param high
* @param gg
* @param turnRight
* @return
*/
public static int[] getEndNodeLevels(int endNode,Map<Integer,Integer> high,int[] gg,boolean turnRight){
List<Integer> result = new ArrayList<>();
//turnRight true 右拐 
// false 左拐
for(int i=0,j=gg.length;i<j;i++){
if(gg[i] == endNode){
if(turnRight && i < endNode){
result.add(high.get(i));
continue;
}

if(!turnRight && i > endNode){
result.add(high.get(i));
continue;
}
}
}

int[] aa = new int[result.size()];
for(int i=0,j=result.size();i<j;i++){
aa[i] = result.get(i);
}
return aa;
}

/**
* 連線起點的確定
* @param node
* @param result
*/
public static void getStart(Map<Integer,int[]> node,Map<Integer,int[]> result){
int[] temp,se;
for(Entry<Integer, int[]> entry : node.entrySet()){
temp = entry.getValue();
for(int i=0,j=temp.length;i<j;i++){
if(temp[i] == 0){
se = result.get(entry.getKey());
se[0] = i+1;
break;
}
}
}
}

}


最後就是根據節點關係生成svg的xml文件描述,這裏就不敘說了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章