Spaces:
Running
Running
align box in multiple function
Browse files- modules/toXML.py +125 -111
modules/toXML.py
CHANGED
@@ -16,131 +16,145 @@ def find_position(pool_index, BPMN_id):
|
|
16 |
|
17 |
return position
|
18 |
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
# Step 1: Calculate the center of each bounding box and group them by pool
|
23 |
pool_groups = {}
|
24 |
for pool_index, element_indices in pred['pool_dict'].items():
|
25 |
pool_groups[pool_index] = []
|
26 |
for i in element_indices:
|
27 |
-
if i >= len(
|
28 |
-
continue
|
29 |
-
if class_dict[
|
30 |
-
x1, y1, x2, y2 =
|
31 |
center = [(x1 + x2) / 2, (y1 + y2) / 2]
|
32 |
pool_groups[pool_index].append((center, i))
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
|
|
|
|
48 |
for pool_index, centers in pool_groups.items():
|
49 |
-
# Group bounding boxes by checking if their centers are within ±50 pixels on the y-axis
|
50 |
y_groups = group_centers(centers.copy(), axis=1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
|
52 |
-
|
53 |
-
for group in y_groups:
|
54 |
-
avg_y = sum([c[0][1] for c in group]) / len(group) # Calculate the average y-coordinate
|
55 |
-
for (center, idx) in group:
|
56 |
-
label = class_dict[modified_pred['labels'][idx]]
|
57 |
-
if label in size:
|
58 |
-
new_center = (center[0], avg_y) # Align the y-coordinate
|
59 |
-
modified_pred['boxes'][idx] = [
|
60 |
-
new_center[0] - size[label][0] / 2,
|
61 |
-
new_center[1] - size[label][1] / 2,
|
62 |
-
new_center[0] + size[label][0] / 2,
|
63 |
-
new_center[1] + size[label][1] / 2
|
64 |
-
]
|
65 |
-
|
66 |
-
# Recalculate centers after vertical alignment
|
67 |
-
centers = []
|
68 |
-
for group in y_groups:
|
69 |
-
for center, idx in group:
|
70 |
-
x1, y1, x2, y2 = modified_pred['boxes'][idx]
|
71 |
-
center = [(x1 + x2) / 2, (y1 + y2) / 2]
|
72 |
-
centers.append((center, idx))
|
73 |
|
74 |
-
|
75 |
-
|
|
|
|
|
76 |
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
position = find_position(pool_index, modified_pred['BPMN_id'])
|
101 |
-
|
102 |
-
if keep_elements == [] or position is None:
|
103 |
-
min_x, min_y, max_x, max_y = modified_pred['boxes'][position]
|
104 |
-
else:
|
105 |
-
size_elements = get_size_elements(st.session_state.size_scale)
|
106 |
-
min_x, min_y, max_x, max_y = calculate_pool_bounds(modified_pred['boxes'], modified_pred['labels'], keep_elements, size_elements)
|
107 |
-
|
108 |
-
pool_width = max_x - min_x
|
109 |
-
pool_height = max_y - min_y
|
110 |
-
if pool_width < 300 or pool_height < 30:
|
111 |
-
error("The pool is maybe too small, please add more elements or increase the scale by zooming on the image.")
|
112 |
-
continue
|
113 |
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
continue
|
135 |
-
x1, y1, x2, y2 = modified_pred['boxes'][position]
|
136 |
-
if x1 > min_left:
|
137 |
-
x1 = min_left
|
138 |
-
if x2 < max_right:
|
139 |
-
x2 = max_right
|
140 |
-
modified_pred['boxes'][position] = [x1, y1, x2, y2]
|
141 |
|
142 |
return modified_pred['boxes']
|
143 |
|
|
|
144 |
# Function to create a BPMN XML file from prediction results
|
145 |
def create_XML(full_pred, text_mapping, size_scale, scale):
|
146 |
namespaces = {
|
@@ -184,7 +198,7 @@ def create_XML(full_pred, text_mapping, size_scale, scale):
|
|
184 |
bpmnplane = ET.SubElement(bpmndi, 'bpmndi:BPMNPlane', id='BPMNPlane_1', bpmnElement='collaboration_1')
|
185 |
|
186 |
full_pred['boxes'] = rescale_boxes(scale, old_boxes['boxes'])
|
187 |
-
full_pred['boxes'] = align_boxes(full_pred, size_elements)
|
188 |
|
189 |
|
190 |
# Add diagram elements for each pool
|
|
|
16 |
|
17 |
return position
|
18 |
|
19 |
+
# Calculate the center of each bounding box and group them by pool
|
20 |
+
def calculate_centers_and_group_by_pool(pred, class_dict):
|
|
|
|
|
21 |
pool_groups = {}
|
22 |
for pool_index, element_indices in pred['pool_dict'].items():
|
23 |
pool_groups[pool_index] = []
|
24 |
for i in element_indices:
|
25 |
+
if i >= len(pred['labels']):
|
26 |
+
continue
|
27 |
+
if class_dict[pred['labels'][i]] not in ['dataObject', 'dataStore']:
|
28 |
+
x1, y1, x2, y2 = pred['boxes'][i]
|
29 |
center = [(x1 + x2) / 2, (y1 + y2) / 2]
|
30 |
pool_groups[pool_index].append((center, i))
|
31 |
+
return pool_groups
|
32 |
+
|
33 |
+
# Group centers within a specified range
|
34 |
+
def group_centers(centers, axis, range_=50):
|
35 |
+
groups = []
|
36 |
+
while centers:
|
37 |
+
center, idx = centers.pop(0)
|
38 |
+
group = [(center, idx)]
|
39 |
+
for other_center, other_idx in centers[:]:
|
40 |
+
if abs(center[axis] - other_center[axis]) <= range_:
|
41 |
+
group.append((other_center, other_idx))
|
42 |
+
centers.remove((other_center, other_idx))
|
43 |
+
groups.append(group)
|
44 |
+
return groups
|
45 |
+
|
46 |
+
# Align the elements within each pool
|
47 |
+
def align_elements_within_pool(modified_pred, pool_groups, class_dict, size):
|
48 |
for pool_index, centers in pool_groups.items():
|
|
|
49 |
y_groups = group_centers(centers.copy(), axis=1)
|
50 |
+
align_y_coordinates(modified_pred, y_groups, class_dict, size)
|
51 |
+
|
52 |
+
centers = recalculate_centers(modified_pred, y_groups)
|
53 |
+
x_groups = group_centers(centers.copy(), axis=0)
|
54 |
+
align_x_coordinates(modified_pred, x_groups, class_dict, size)
|
55 |
+
|
56 |
+
# Align the y-coordinates of the centers of grouped bounding boxes
|
57 |
+
def align_y_coordinates(modified_pred, y_groups, class_dict, size):
|
58 |
+
for group in y_groups:
|
59 |
+
avg_y = sum([c[0][1] for c in group]) / len(group)
|
60 |
+
for (center, idx) in group:
|
61 |
+
label = class_dict[modified_pred['labels'][idx]]
|
62 |
+
if label in size:
|
63 |
+
new_center = (center[0], avg_y)
|
64 |
+
modified_pred['boxes'][idx] = [
|
65 |
+
new_center[0] - size[label][0] / 2,
|
66 |
+
new_center[1] - size[label][1] / 2,
|
67 |
+
new_center[0] + size[label][0] / 2,
|
68 |
+
new_center[1] + size[label][1] / 2
|
69 |
+
]
|
70 |
+
|
71 |
+
# Recalculate centers after alignment
|
72 |
+
def recalculate_centers(modified_pred, groups):
|
73 |
+
centers = []
|
74 |
+
for group in groups:
|
75 |
+
for center, idx in group:
|
76 |
+
x1, y1, x2, y2 = modified_pred['boxes'][idx]
|
77 |
+
center = [(x1 + x2) / 2, (y1 + y2) / 2]
|
78 |
+
centers.append((center, idx))
|
79 |
+
return centers
|
80 |
+
|
81 |
+
# Align the x-coordinates of the centers of grouped bounding boxes
|
82 |
+
def align_x_coordinates(modified_pred, x_groups, class_dict, size):
|
83 |
+
for group in x_groups:
|
84 |
+
avg_x = sum([c[0][0] for c in group]) / len(group)
|
85 |
+
for (center, idx) in group:
|
86 |
+
label = class_dict[modified_pred['labels'][idx]]
|
87 |
+
if label in size:
|
88 |
+
new_center = (avg_x, center[1])
|
89 |
+
modified_pred['boxes'][idx] = [
|
90 |
+
new_center[0] - size[label][0] / 2,
|
91 |
+
modified_pred['boxes'][idx][1],
|
92 |
+
new_center[0] + size[label][0] / 2,
|
93 |
+
modified_pred['boxes'][idx][3]
|
94 |
+
]
|
95 |
+
|
96 |
+
# Expand the pool bounding boxes to fit the aligned elements
|
97 |
+
def expand_pool_bounding_boxes(modified_pred, pred, size_elements):
|
98 |
+
for idx, (pool_index, keep_elements) in enumerate(modified_pred['pool_dict'].items()):
|
99 |
+
if len(keep_elements) != 0:
|
100 |
+
marge = 50
|
101 |
+
else:
|
102 |
+
marge = 0
|
103 |
|
104 |
+
position = find_position(pool_index, modified_pred['BPMN_id'])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
|
106 |
+
if keep_elements == [] or position is None:
|
107 |
+
min_x, min_y, max_x, max_y = modified_pred['boxes'][position]
|
108 |
+
else:
|
109 |
+
min_x, min_y, max_x, max_y = calculate_pool_bounds(modified_pred['boxes'], modified_pred['labels'], keep_elements, size_elements)
|
110 |
|
111 |
+
pool_width = max_x - min_x
|
112 |
+
pool_height = max_y - min_y
|
113 |
+
if pool_width < 300 or pool_height < 30:
|
114 |
+
error("The pool is maybe too small, please add more elements or increase the scale by zooming on the image.")
|
115 |
+
continue
|
116 |
+
|
117 |
+
modified_pred['boxes'][position] = [min_x - marge, min_y - marge // 2, min_x + pool_width + marge, min_y + pool_height + marge // 2]
|
118 |
+
|
119 |
+
# Adjust left and right boundaries of all pools
|
120 |
+
def adjust_pool_boundaries(modified_pred, pred):
|
121 |
+
min_left, max_right = 0, 0
|
122 |
+
for pool_index, element_indices in pred['pool_dict'].items():
|
123 |
+
position = find_position(pool_index, modified_pred['BPMN_id'])
|
124 |
+
if position >= len(modified_pred['boxes']):
|
125 |
+
continue
|
126 |
+
x1, y1, x2, y2 = modified_pred['boxes'][position]
|
127 |
+
left = x1
|
128 |
+
right = x2
|
129 |
+
if left < min_left:
|
130 |
+
min_left = left
|
131 |
+
if right > max_right:
|
132 |
+
max_right = right
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
133 |
|
134 |
+
for pool_index, element_indices in pred['pool_dict'].items():
|
135 |
+
position = find_position(pool_index, modified_pred['BPMN_id'])
|
136 |
+
if position >= len(modified_pred['boxes']):
|
137 |
+
continue
|
138 |
+
x1, y1, x2, y2 = modified_pred['boxes'][position]
|
139 |
+
if x1 > min_left:
|
140 |
+
x1 = min_left
|
141 |
+
if x2 < max_right:
|
142 |
+
x2 = max_right
|
143 |
+
modified_pred['boxes'][position] = [x1, y1, x2, y2]
|
144 |
+
|
145 |
+
# Main function to align boxes
|
146 |
+
def align_boxes(pred, size, class_dict):
|
147 |
+
modified_pred = copy.deepcopy(pred)
|
148 |
+
pool_groups = calculate_centers_and_group_by_pool(pred, class_dict)
|
149 |
+
align_elements_within_pool(modified_pred, pool_groups, class_dict, size)
|
150 |
+
|
151 |
+
if len(pred['pool_dict']) > 1:
|
152 |
+
expand_pool_bounding_boxes(modified_pred, pred, size)
|
153 |
+
adjust_pool_boundaries(modified_pred, pred)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
|
155 |
return modified_pred['boxes']
|
156 |
|
157 |
+
|
158 |
# Function to create a BPMN XML file from prediction results
|
159 |
def create_XML(full_pred, text_mapping, size_scale, scale):
|
160 |
namespaces = {
|
|
|
198 |
bpmnplane = ET.SubElement(bpmndi, 'bpmndi:BPMNPlane', id='BPMNPlane_1', bpmnElement='collaboration_1')
|
199 |
|
200 |
full_pred['boxes'] = rescale_boxes(scale, old_boxes['boxes'])
|
201 |
+
full_pred['boxes'] = align_boxes(full_pred, size_elements, class_dict)
|
202 |
|
203 |
|
204 |
# Add diagram elements for each pool
|