Skip to content

Commit 6a672f6

Browse files
committed
Added some callbacks for info meshgen/calcfem -> gui
Added some geometry checks
1 parent 6ec67f6 commit 6a672f6

File tree

6 files changed

+151
-55
lines changed

6 files changed

+151
-55
lines changed

DEV/test2.py

+9-15
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
1-
# file A
2-
class TestA:
1+
import tkinter as tk
32

4-
def main(self):
5-
for n in range(100):
3+
# Create the main window
4+
root = tk.Tk()
5+
root.geometry("300x200")
66

7-
print(n)
7+
# Create a Label widget with text
8+
label = tk.Label(root, text="This is a left-anchored label\nTest next line\nTest third line", anchor="w", justify="left")
9+
label.place(relx=0.01, rely=0.01)
810

9-
10-
# file B
11-
class TestB:
12-
def get_n(self, fun):
13-
return fun
14-
15-
def main(self):
16-
testa = TestA()
17-
testa.main()
18-
print()
11+
# Start the Tkinter main loop
12+
root.mainloop()

DEV/test3.py

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from shapely.geometry import Polygon
2+
3+
# Define two polygons
4+
polygon1 = Polygon([(0, 0), (2, 0), (2, 2), (0, 2)])
5+
polygon2 = Polygon([(0, 0), (2, 0), (3, 2), (1, 2)])
6+
7+
# Check if they share part of the boundary
8+
share_boundary = polygon1.intersects(polygon2) and polygon1.touches(polygon2) and not (polygon1.contains(polygon2) or polygon2.contains(polygon1))
9+
10+
print("Do the polygons share part of the boundary? ", share_boundary)

source/geometry.py

+66-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from source.guistatics import GUIStatics
3232
import copy
3333
from PIL import ImageTk
34+
from shapely.geometry import Polygon
3435

3536
class Geometry(tk.Toplevel):
3637
"""
@@ -682,7 +683,6 @@ def delete_point():
682683

683684
##################################################
684685
# clear all button
685-
##################################################
686686
def clear_all():
687687
"""
688688
Button action, clears all input
@@ -715,6 +715,17 @@ def clear_all():
715715
font=GUIStatics.STANDARD_FONT_BUTTON_MID, width=10, height=1)
716716
button_clear_all.place(relx=widgets_x_start + 0.25, rely=0.02)
717717

718+
# Check geometry button
719+
def check_geometry_on_button():
720+
"""
721+
722+
:return:
723+
"""
724+
self.check_geometry_detail()
725+
726+
button_check_geometry = tk.Button(self, text="Check Geometry", command=check_geometry_on_button,
727+
font=GUIStatics.STANDARD_FONT_BUTTON_MID, width=16, height=1)
728+
button_check_geometry.place(relx=widgets_x_start + 0.35, rely=0.02)
718729
##################################################
719730
# Add canvas for system visualization - DYNAMIC
720731
self.canvas = tk.Canvas(self, width=GUIStatics.CANVAS_SIZE_X, height=GUIStatics.CANVAS_SIZE_Y,
@@ -823,7 +834,7 @@ def check_and_accept():
823834
:return:
824835
"""
825836

826-
if check_geometry():
837+
if self.check_geometry_detail():
827838
self.return_geometry()
828839
else:
829840
check_geometry_error_window()
@@ -859,6 +870,59 @@ def debug():
859870

860871
self.update_graphics() # if Geometry class is loaded with input self.geometry_input, see init
861872

873+
def check_geometry_detail(self):
874+
"""
875+
Detailed check for geometry
876+
:return:
877+
"""
878+
check_passed = True
879+
880+
check_fail_str = ''
881+
check_failed_list = []
882+
for ip1, poly1 in enumerate(self.polygons.values()):
883+
poly1_shapely = Polygon([(node[0], node[1]) for node in poly1['coordinates']])
884+
for ip2, poly2 in enumerate(list(self.polygons.values())[ip1 + 1:], start=ip1+1):
885+
poly2_shapely = Polygon([(node[0], node[1]) for node in poly2['coordinates']])
886+
# check if positive polygons overlap
887+
if poly1['area_neg_pos'] == 'Positive' and poly2['area_neg_pos'] == 'Positive':
888+
if poly1_shapely.overlaps(poly2_shapely):
889+
check_fail_str = f"Geometryerror: Positive Polygon {ip1} and Positive Polygon {ip2} overlap"
890+
check_failed_list.append(check_fail_str)
891+
# check if negative polygons overlap
892+
if poly1['area_neg_pos'] == 'Negative' and poly2['area_neg_pos'] == 'Negative':
893+
if poly1_shapely.overlaps(poly2_shapely):
894+
check_fail_str = f"Geometryerror: Negative Polygon {ip1} and Negative Polygon {ip2} overlap"
895+
check_failed_list.append(check_fail_str)
896+
# check if negative polygon inside positive polygon
897+
if poly1['area_neg_pos'] == 'Positive' and poly2['area_neg_pos'] == 'Negative':
898+
if poly1_shapely.intersects(poly2_shapely):
899+
if not poly1_shapely.contains(poly2_shapely):
900+
check_fail_str = f"Geometryerror: Positive Polygon {ip1} and Negative Polygon {ip2} intersect"
901+
check_failed_list.append(check_fail_str)
902+
if poly1['area_neg_pos'] == 'Negative' and poly2['area_neg_pos'] == 'Positive':
903+
if poly1_shapely.intersects(poly2_shapely):
904+
if not poly2_shapely.contains(poly1_shapely):
905+
check_fail_str = f"Geometryerror: Negative Polygon {ip1} and Positive Polygon {ip2} intersect"
906+
check_failed_list.append(check_fail_str)
907+
908+
909+
910+
# # Check if negative polygon intersects with positive polygon (boundary crossed/shared)
911+
# if poly1['area_neg_pos'] == 'Positive' and poly2['area_neg_pos'] == 'Negative':
912+
# if poly1_shapely.intersects(poly2_shapely) and not poly1_shapely.contains(poly2_shapely):
913+
# check_fail_str = f"Geometryerror: Positive Polygon {ip1} and Negative Polygon {ip2} intersect"
914+
# check_failed_list.append(check_fail_str)
915+
# if poly1['area_neg_pos'] == 'Negative' and poly2['area_neg_pos'] == 'Positive':
916+
# if poly1_shapely.intersects(poly2_shapely) and not poly2_shapely.contains(poly1_shapely):
917+
# check_fail_str = f"Geometryerror: Negative Polygon {ip1} and Positive Polygon {ip2} intersect"
918+
# check_failed_list.append(check_fail_str)
919+
920+
for elem in check_failed_list:
921+
print(elem)
922+
923+
924+
return check_passed
925+
862926
def update_graphics(self):
863927
"""
864928
Updates the canvas, draws static elements (coordsystem, grid) and draws defined polygons and single points

source/gui.py

+23-23
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ def __init__(self):
9595
self.triangulation_region_dict = None
9696
# Other
9797
GUIStatics.CANVAS_SCALE_FACTOR = 100
98-
self.elemcounter = 0 # Callbackvariable for parsing elements calculated from class CalcFEM to class GUI
98+
self.calc_info = {'step': None, 'n': None, 'other': None} # Callbackvariable for parsing elements calculated from class CalcFEM to class GUI
9999

100100
# some output for user
101101
self.text_information_str = ''
@@ -267,7 +267,7 @@ def thread_create_mesh():
267267
try:
268268
mesh = CreateMesh(self.region_parameters, self.boundary_parameters,
269269
self.node_parameters, self.calculation_parameters)
270-
mesh_generator_output = mesh.create_mesh()
270+
mesh_generator_output = mesh.create_mesh(callback=self.callback_calc)
271271
self.nodes_mesh_gen = mesh_generator_output[0]
272272
self.single_nodes_dict = mesh_generator_output[1]
273273
self.boundary_nodes_dict = mesh_generator_output[2]
@@ -280,15 +280,15 @@ def thread_create_mesh():
280280

281281
window_create_mesh_wait = tk.Toplevel(self)
282282
window_create_mesh_wait.title('CREATING MESH')
283-
window_create_mesh_wait.geometry(f"{200}x{150}")
283+
window_create_mesh_wait.geometry(f"{300}x{150}")
284284
window_create_mesh_wait.resizable(False, False)
285285
icon_image = ImageTk.PhotoImage(data=GUIStatics.return_icon_bytestring())
286286
window_create_mesh_wait.tk.call('wm', 'iconphoto', window_create_mesh_wait._w, icon_image)
287-
tk.Label(window_create_mesh_wait, text="Creating Mesh...\nPlease Wait",
287+
tk.Label(window_create_mesh_wait, text="Creating Mesh...Please Wait",
288288
font=GUIStatics.STANDARD_FONT_MID_BOLD).place(relx=0.15, rely=0.1)
289289
window_create_mesh_wait_label = tk.Label(window_create_mesh_wait, text="",
290-
font=GUIStatics.STANDARD_FONT_MID_BOLD)
291-
window_create_mesh_wait_label.place(relx=0.35, rely=0.6)
290+
font=GUIStatics.STANDARD_FONT_SMALL_BOLD, anchor="sw", justify="left")
291+
window_create_mesh_wait_label.place(relx=0.05, rely=0.3)
292292
thread_mesh = threading.Thread(target=thread_create_mesh)
293293
thread_mesh.start()
294294

@@ -301,11 +301,11 @@ def update_wait_label():
301301
"""
302302
wait_text = ''
303303
while thread_mesh.is_alive():
304-
if wait_text == '.....':
305-
wait_text = ''
306-
wait_text += '.'
304+
wait_text = (f"Current Step: \n"
305+
f"{self.calc_info['step']}\n"
306+
f"{self.calc_info['n']} {self.calc_info['other']}")
307307
window_create_mesh_wait_label.config(text=wait_text)
308-
time.sleep(0.5)
308+
time.sleep(0.05)
309309
window_create_mesh_wait.destroy()
310310

311311
update_thread = threading.Thread(target=update_wait_label)
@@ -349,7 +349,7 @@ def thread_solve_system():
349349
self.calculation_parameters)
350350
try:
351351
calcfem = CalcFEM(params_mesh, params_boundaries_materials)
352-
self.solution = calcfem.calc_fem(callback=self.callback_calcfem)
352+
self.solution = calcfem.calc_fem(callback=self.callback_calc)
353353
except np.linalg.LinAlgError:
354354
err_message = ('Singular Matrix encountered!\n'
355355
'Check Boundary Conditions \n'
@@ -381,15 +381,15 @@ def thread_solve_system():
381381

382382
window_solve_system_wait = tk.Toplevel(self)
383383
window_solve_system_wait.title('SOLVING')
384-
window_solve_system_wait.geometry(f"{200}x{150}")
384+
window_solve_system_wait.geometry(f"{300}x{150}")
385385
window_solve_system_wait.resizable(False, False)
386386
icon_image = ImageTk.PhotoImage(data=GUIStatics.return_icon_bytestring())
387387
window_solve_system_wait.tk.call('wm', 'iconphoto', window_solve_system_wait._w, icon_image)
388-
tk.Label(window_solve_system_wait, text="Solving System...\nPlease Wait",
389-
font=GUIStatics.STANDARD_FONT_MID_BOLD).place(relx=0.15, rely=0.1)
388+
tk.Label(window_solve_system_wait, text="Solving System...Please Wait",
389+
font=GUIStatics.STANDARD_FONT_MID_BOLD, ).place(relx=0.15, rely=0.1)
390390
window_solve_system_wait_label = tk.Label(window_solve_system_wait, text="",
391-
font=GUIStatics.STANDARD_FONT_MID_BOLD)
392-
window_solve_system_wait_label.place(relx=0.35, rely=0.6)
391+
font=GUIStatics.STANDARD_FONT_SMALL_BOLD, anchor="sw", justify="left")
392+
window_solve_system_wait_label.place(relx=0.05, rely=0.3)
393393
thread_mesh = threading.Thread(target=thread_solve_system)
394394
thread_mesh.start()
395395

@@ -400,12 +400,12 @@ def update_wait_label():
400400
"""
401401
wait_text = ''
402402
while thread_mesh.is_alive():
403-
if wait_text == '.....':
404-
wait_text = ''
405-
#wait_text += '.'
406-
wait_text = f"Element: {self.elemcounter} / {len(self.triangulation)}"
403+
wait_text = (f"Current Step: \n"
404+
f"{self.calc_info['step']}\n"
405+
f"{self.calc_info['n']} {self.calc_info['other']}")
406+
407407
window_solve_system_wait_label.config(text=wait_text)
408-
time.sleep(0.1)
408+
time.sleep(0.05)
409409
window_solve_system_wait.destroy()
410410

411411
update_thread = threading.Thread(target=update_wait_label)
@@ -1244,11 +1244,11 @@ def accept_bcs():
12441244
width=12, height=1, font=GUIStatics.STANDARD_FONT_BUTTON_MID_BOLD)
12451245
button_accept.place(relx=widgets_x_start + 0.05, rely=0.895)
12461246

1247-
def callback_calcfem(self, calc_info):
1247+
def callback_calc(self, calc_info):
12481248
"""
12491249
callback for parsing calculation e.g. element matrices to GUI
12501250
"""
1251-
print(f"Current Step: {calc_info['step']} {calc_info['n']} {calc_info['other']}", end='\r')
1251+
self.calc_info = calc_info
12521252

12531253
def create_BC_params(self):
12541254
"""

0 commit comments

Comments
 (0)