
| Current Path : /home/cgabriel/20_dev/12_procpy/dataninja/ |
Linux ift1.ift-informatik.de 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 |
| Current File : //home/cgabriel/20_dev/12_procpy/dataninja/rearr_gridsu.py |
import os
import sys
import re
import math
import procpy
import tkinter
import random
try:
import json
except:
import pip
pip.main(["install","json"])
import json
#************************************************************************
class Rearr_grid (object):
def __init__ (self,graph):
self.graph = graph
#************************************************************************
def rearrange (self,griddata,mode):
if mode == 0:
self.fit_blocks_to_grid(griddata)
self.newbends_for_arrows()
return(griddata)
#************************************************************************
def fit_blocks_to_grid (self,griddata):
for block in self.graph.blocks:
x = griddata['X'] * int((block.bbox[0] + 0.5*griddata['X'])/griddata['X'])
y = griddata['Y'] * int((block.bbox[1] + 0.5*griddata['Y'])/griddata['Y'])
dx = block.bbox[0] - x
dy = block.bbox[1] - y
block.newbbox = [ block.bbox[0] - dx, block.bbox[1] - dy,
block.bbox[2] - dx, block.bbox[3] - dy ]
return()
#************************************************************************
def newbends_for_arrows (self):
print("newbends_for_arrows-nxs")
for block in self.graph.blocks:
bx = (block.bbox[0]+block.bbox[2])/2
by = (block.bbox[1]+block.bbox[3])/2
for arrow in block.arrows_out:
jump = arrow.target_block
arrow.channels = self.compute_channels(block,jump)
arrow.anchorline = 0
self.compare_channels()
# for block in self.graph.blocks:#
#
# for arrow in block.arrows_out:
# print arrow.channels
self.choose_points_from_channels()
#************************************************************************
# the code does not run, by nxs
def choose_direction(self,source,target, var): # --> SHAPE-001-VALID
# if x and y direction are possible, choose appropriate
var1 = var # use local variable
if (("n" in var1) or ("s" in var1)) and (("w" in var1)^("e" in var1)):
if source.newbbox[1]<=(target.newbbox[1]+target.newbbox[3])/2<=source.newbbox[3]:
var1 = var1.replace("n","").replace("s","") # if source and target are on the same level,
else: # chose east/west
var1 = var1.replace("w","").replace("e","") # else choose north/south
elif (("n" in var1) or ("s" in var1)) and (("w" in var1) and ("e" in var1)):
if source.newbbox[0]<= (target.newbbox[0]+target.newbbox[2])/2<=source.newbbox[2]:
var1 = var1.replace("w","").replace("e","") # choose north/south
else: # if source and target are on top of each other
var1 = var1.replace("n","").replace("s","") # choose south/west
return var1
#************************************************************************
def define_starting_channel(self,source, target, nextdirection):
exit = self.choose_direction(source,target, source.exit)
if exit in "we": #arrows should exit in east or west
newchannel = [source.newbbox[1],source.newbbox[3]]
first_dir = 'X'
if exit == "e":
channel_length = [source.newbbox[2],max(source.newbbox[2]+70,nextdirection['Y'][1])]
elif exit == "w":
channel_length = [max(0,min(nextdirection['Y'][0],source.newbbox[0]-70)),source.newbbox[0]]
else:
channel_length = [min(source.newbbox[2],nextdirection['Y'][0]),max(source.newbbox[0],nextdirection['Y'][1])]
elif exit in "ns": #arrows should exit in north or south
newchannel = [source.newbbox[0],source.newbbox[2]]
first_dir = 'Y'
if exit == "n" :
channel_length = [max(0,min(source.newbbox[1]-70,nextdirection['X'][0])),source.newbbox[1]]
elif exit == "s":
channel_length = [source.newbbox[3],max(source.newbbox[3]+70,nextdirection['X'][1])]
else:
channel_length = [min(source.newbbox[3],nextdirection['X'][0]),max(source.newbbox[1],nextdirection['X'][1])]
else: #####
newchannel = [source.newbbox[1],source.newbbox[3]]
channel_length = [min(source.newbbox[2],nextdirection['Y'][0]),max(source.newbbox[0],nextdirection['Y'][1])]
first_dir = 'X'
return newchannel, channel_length, first_dir
#************************************************************************
def define_nextdirection(self,source, target):
nextdirection = {'Y':[],'X':[]}
entrance = self.choose_direction(source, target, target.entrance)
#### define nextdirection if entrance is west/east
if "w" in entrance and "e" in entrance: # if west and east is possible, decide which one of them
entrance = {True: "w", False: "e"}[source.newbbox[2]>target.newbbox[2]+5]
if entrance =="w":
nextdirection['Y'].append({True: max(source.newbbox[2],target.newbbox[0]-70),
False: max(0,target.newbbox[0]-70)}[source.newbbox[2]<target.newbbox[0]-5])
nextdirection['Y'].append(target.newbbox[0])
elif entrance == "e":
nextdirection['Y'].append(target.newbbox[2])
nextdirection['Y'].append({True: min(source.newbbox[0],target.newbbox[2]+70),
False: target.newbbox[2]+70}[source.newbbox[0]>target.newbbox[2]+5])
else:
nextdirection['Y'] = [target.newbbox[0],target.newbbox[2]]
#### define nextdirection if entrance is north/south
if "n" in entrance and "s" in entrance: # if north and south is possible, choose one of them
entrance = {True:"n", False: "s"}[source.newbbox[3]<target.newbbox[3]-5]
if entrance =="n":
nextdirection['X'].append({True: max(source.newbbox[3],target.newbbox[1]-70),
False: max(0,target.newbbox[1]-70)}[source.newbbox[3]<target.newbbox[1]-5])
nextdirection['X'].append(target.newbbox[1])
elif entrance == "s":
nextdirection['X'].append(target.newbbox[3])
nextdirection['X'].append({True: min(source.newbbox[1],target.newbbox[3]+70),
False: target.newbbox[3]+70}[source.newbbox[1]>target.newbbox[3]+5])
else:
nextdirection['X'] = [target.newbbox[1],target.newbbox[3]]
return nextdirection # <-- ENDREQ
#************************************************************************
def compute_channels(self,source, target):
nextdirection = self.define_nextdirection(source, target) # define nextdirection depending on entrance of target
newchannel, channel_length, first_dir = self.define_starting_channel(source, target, nextdirection)
######### old version: always shortest possible connection #####################################################
# if ((source.newbbox[0]<=target.newbbox[0] and source.newbbox[2]>=target.bbox[2]) # create vertical arrow
# or (source.newbbox[0]>=target.newbbox[0] and source.newbbox[2]<=target.bbox[2])): # if blocks are in vertical line
#
# newchannel = [source.newbbox[0],source.newbbox[2]]
# channel_length = [min(source.newbbox[3],target.newbbox[1]),max(source.newbbox[1],target.newbbox[3])]
# first_dir = 'Y'
# else:
#
# newchannel = [source.newbbox[1],source.newbbox[3]]
# channel_length = [min(source.newbbox[2],target.newbbox[0]),max(source.newbbox[0],target.newbbox[2])]
# first_dir = 'X'
#
# target_dock ={'Y':[target.newbbox[1],target.newbbox[3]],'X':[target.newbbox[0],target.newbbox[2]]}
# nextdirection ={'X':[target.newbbox[1],target.newbbox[3]],'Y':[target.newbbox[0],target.newbbox[2]]}
################################################################################################################
direction = first_dir # the direction of the current newchannel, x or y
target_dock ={'Y':[target.newbbox[1],target.newbbox[3]],'X':[target.newbbox[0],target.newbbox[2]]}
target_reached = 0 # is 1 if target is reached
channel = [] # the computed channels
blocklist = self.all_blocks_except(source,target) # all blocks in the canvas
count = 0 # counts the channels
secondrun = True # determines the trys to create fitting channels
### Definition of mode: how to go around blocks #####
if source.newbbox[3]>=target.newbbox[3]: # evtl. anpassung noetig in y-direction
mode = 1
else:
mode = 0
while target_reached == 0:
### Not-Stopp ####################################
if count>=20:
if not secondrun:
mode = {1:0,0:1}[mode]
newchannel = channel[0]
channel = []
count = 0
secondrun = True
else:
print("*********************************************")
print("**** Please reorder your blocks *************")
print("*********************************************")
return
### calculate optimal width of newchannel ############
newchannel = self.channel_optimal_width(newchannel, channel_length, blocklist, direction)
### append optimal newchannel to channel #############
channel.append(newchannel)
direction = {'X':'Y','Y':'X'}[direction]
leftright={'X':target.newbbox[3]>=channel_length[1],'Y':target.newbbox[2]>=channel_length[1]}
### new channel ####################################
newchannel = self.new_channel(blocklist,newchannel,channel_length, direction, leftright[direction])
### if old direction is chosen again ###############
if len(channel)>=2 and newchannel!="" and (abs(newchannel[0]-channel[-2][0])<1 or abs(newchannel[1]-channel[-2][1])<1): # and in or geaendert
if mode == 0:
newchannel= [max(0,channel[-1][0]-70), channel[-1][0]]
else:
newchannel= [channel[-1][1], channel[-1][1]+70]
del channel[-1]
direction={'X':'Y','Y':'X'}[direction]
### no newchannel was calculated ####################
if newchannel=="":
### nextdirection can not be taken because it does not intersect with current channel
if nextdirection[direction][1]<=channel_length[0] or nextdirection[direction][0]>=channel_length[1]: # --> SHAPE-001-VALID
newchannel = channel_length # <-- ENDREQ
elif (channel[-1][0]<target_dock[direction][0]<channel[-1][1]): # relevant only if blocks are note exactly on the same level
channel[-1][0] = target_dock[direction][0]
target_reached = 1
elif (channel[-1][0]<target_dock[direction][1]<channel[-1][1]):
channel[-1][1] = target_dock[direction][1]
target_reached = 1
elif (target_dock[direction][0]-channel[-1][0]<=0.5 and # --> BUG-0002-VALID
target_dock[direction][1]-channel[-1][1]>=-0.5): # <-- ENDREQ
### target is reached
target_reached = 1
else:
### take the shortest possible way
newchannel = nextdirection[direction]
#### Channel length ################################
diff1 = nextdirection[{'X':'Y','Y':'X'}[direction]][0] - channel[-1][0] # --> SHAPE-001-VALID
diff2 = nextdirection[{'X':'Y','Y':'X'}[direction]][1] - channel[-1][1]
if (diff1<=0) and (diff2>=0):
channel_length = channel[-1]
else:
channel_length = [min(channel[-1][0],nextdirection[{'X':'Y','Y':'X'}[direction]][0]),
max(channel[-1][1],nextdirection[{'X':'Y','Y':'X'}[direction]][1])] # <-- ENDREQ
count += 1
return channel
#**************************************************************
def new_channel(self,blocklist,channel,channel_length,direction,leftright):
#Coordinates of channel
ax1 = round(channel_length[0])
ax2 = round(channel_length[1])
ay1 = round(channel[0])
ay2 = round(channel[1])
newchannel = ""
# print "ax1,ax2,ay1,ay2: "+str([ax1,ax2,ay1,ay2])
for block in self.graph.blocks:
#Block-Koordinaten
if direction == 'Y':
cx1 = round(block.newbbox[0])
cx2 = round(block.newbbox[2])
cy1 = round(block.newbbox[1])
cy2 = round(block.newbbox[3])
else:
cx1 = round(block.newbbox[1])
cx2 = round(block.newbbox[3])
cy1 = round(block.newbbox[0])
cy2 = round(block.newbbox[2])
# print "cx1,cx2,cy1,cy2: "+str([cx1,cx2,cy1,cy2])
if (ax1<cx1<ax2 or ax1<cx2<ax2) and (ay1<cy1<ay2 or ay1<cy2<ay2 or (cy1<=ay1 and cy2>=ay2)):
if leftright == 1:
ax1 = min(ax1,cx2)
ax2 = min(cx1,ax2)
else:
ax1 = max(ax1,cx2)
ax2 = max(cx1,ax2)
newchannel = [ax1,ax2]
return newchannel
#************************************************************************
def all_blocks_except(self,*block1):
blocklist = []
for block in self.graph.blocks:
identical = 0
for specialblock in block1:
if block == specialblock:
identical = 1
if identical == 0:
blocklist.append(block)
return blocklist
#************************************************************************
def channel_optimal_width(self,channel, channel_length, blocklist, direction):
optimal_channel = [channel[0],channel[1]]
minimal_width = 5
#Coordinates of channel
ax1 = round(channel_length[0])
ax2 = round(channel_length[1])
ay1 = round(channel[0])
ay2 = round(channel[1])
for block in self.graph.blocks: #blocklist:
if direction == 'X':
cx1 = round(block.newbbox[0])
cx2 = round(block.newbbox[2])
cy1 = round(block.newbbox[1])
cy2 = round(block.newbbox[3])
else:
cx1 = round(block.newbbox[1])
cx2 = round(block.newbbox[3])
cy1 = round(block.newbbox[0])
cy2 = round(block.newbbox[2])
if (ax1 < cx1 < ax2) or (ax1 < cx2 < ax2):
if ay1 < cy1 < ay2:
optimal_channel[1] = min(cy1,ay2)
elif ay1 < cy2 < ay2:
optimal_channel[0] = max(cy2,ay1)
if (optimal_channel[1]-optimal_channel[0])<minimal_width:
optimal_channel = channel
return optimal_channel
#************************************************************************
def choose_points_from_channels(self):
print("choose_points_from_channels-nxs")
for block in self.graph.blocks:
for arrow in block.arrows_out:
if not 'channels' in vars(arrow):
continue
jump = arrow.target_block
arrow.newbends = []
p = {'X': None, 'Y': None }
# if ((block.newbbox[0]<=jump.newbbox[0] and block.newbbox[2]>=jump.bbox[2]) # if blocks are in vertical line
# or (block.newbbox[0]>=jump.newbbox[0] and block.newbbox[2]<=jump.bbox[2])): # vertical channel at first
# act_direction = 'Y'
# else:
# act_direction = 'X'
if self.choose_direction(block,jump,block.exit) in "ns": # --> SHAPE-001-VALID
act_direction = 'Y'
else:
act_direction = 'X' # <-- ENDREQ
for channel in arrow.channels:
act_direction = { 'X': 'Y', 'Y': 'X'}[act_direction]
#pos = random.uniform(0.01,0.99)
pos = 0.5
p[act_direction] = pos*channel[0] + (1-pos)*channel[1]
if len(arrow.channels)==1:
if act_direction=='Y':
p['X']= (jump.newbbox[0]+block.newbbox[2])/2
else:
p['Y']= (jump.newbbox[1]+block.newbbox[3])/2
if p['X'] and p['Y']:
arrow.newbends.append([p['X'],p['Y']])
return()
#************************************************************************
def compare_channels(self):
for block in self.graph.blocks:
for arrow in block.arrows_out:
if not 'channels' in vars(arrow):
continue
pos = 0
for channel in arrow.channels:
arrow.channels[pos] = self.fit_to_parallel_channels(block, arrow.target_block, arrow.channels, pos)
pos += 1
return()
#****************************************************************
def fit_to_parallel_channels(self,source, target, channels, pos):
a = channels[pos]
direction_a = {True: 'X', False: 'Y'}[(self.choose_direction(source,target,source.exit) in "ns")^(pos%2==0)]
# the direction of the current channel depends on the shape of the source and its number
ax1, ax2 = self.get_channel_length(source, target, channels, pos, direction_a)
for block in self.graph.blocks:
for arrow in block.arrows_out:
pos_b = 0
for chan in arrow.channels:
direction_b = {True: 'X', False: 'Y'}[(block.shape in "f")^(pos_b%2==0)]
bx1, bx2 = self.get_channel_length(block, arrow.target_block, arrow.channels, pos_b, direction_b)
if block==source and arrow.target_block==target and pos_b==pos:
pass
elif direction_a == direction_b and ((ax1 <=bx1 < ax2) or (ax1 < bx2 <= ax2)
or (bx1<=ax1 and bx2>=ax2)):
if round(a[0]) < round(chan[0]) < round(a[1]) and round(a[1]-chan[1])<round(chan[0]-a[0]):
a[1] = chan[0]
elif round(a[0]) < round(chan[1]) < round(a[1]) and round(a[1]-chan[1])>=round(chan[0]-a[0]):
a[0] = chan[1]
elif round(chan[0])<=round(a[0]) and round(chan[1])>=round(a[1]):
a[1] = (a[0]+a[1])/2
pos_b += 1
return(a)
#******************************************************
def get_channel_length(self,source, target,channels, pos,direction):
if pos == 0 and direction == 'X': # --> BUG-0004-VALID
x1 = (source.newbbox[0]+source.newbbox[2])/2 # arrow starts from diamond shape in
elif pos == 0 and direction == 'Y': # y-direction, must be taken care off
x1 = (source.newbbox[1]+source.newbbox[3])/2 # here
else:
x1 = (channels[pos-1][0]+channels[pos-1][1])/2
if pos == len(channels)-1 and direction=='X':
x2 = (target.newbbox[0]+target.newbbox[2])/2
elif pos == len(channels)-1 and direction=='Y':
x2 = (target.newbbox[1]+target.newbbox[3])/2
else:
x2 = (channels[pos+1][0]+channels[pos+1][1])/2 # <-- ENDREQ
xx1 = min(x1,x2)
xx2 = max(x1,x2)
return(xx1,xx2)