RDG-Networks 0.3.6__py3-none-any.whl → 0.3.7__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- {RDG_Networks-0.3.6.dist-info → RDG_Networks-0.3.7.dist-info}/METADATA +1 -1
- {RDG_Networks-0.3.6.dist-info → RDG_Networks-0.3.7.dist-info}/RECORD +11 -11
- {RDG_Networks-0.3.6.dist-info → RDG_Networks-0.3.7.dist-info}/entry_points.txt +1 -0
- RDG_networks/__init__.py +3 -1
- RDG_networks/save_to_stl.py +13 -1
- RDG_networks/thickness/__init__.py +2 -0
- RDG_networks/thickness/generate_line_segments_thickness.py +2 -2
- RDG_networks/thickness/generate_line_segments_thickness_static.py +240 -0
- RDG_networks/thickness/generate_line_segments_thickness_orientation backup.py +0 -202
- {RDG_Networks-0.3.6.dist-info → RDG_Networks-0.3.7.dist-info}/LICENSE.txt +0 -0
- {RDG_Networks-0.3.6.dist-info → RDG_Networks-0.3.7.dist-info}/WHEEL +0 -0
- {RDG_Networks-0.3.6.dist-info → RDG_Networks-0.3.7.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,5 @@
|
|
1
1
|
RDG_networks/Classes.py,sha256=_9X3JPHFAYYlaC8IZ_H9__sfz99G5l9UfPl65lL60_4,7977
|
2
|
-
RDG_networks/__init__.py,sha256=
|
2
|
+
RDG_networks/__init__.py,sha256=tKoHFugrHAkce3wyw62MvOzcSfoBr2tpSp6da7Y54LQ,1764
|
3
3
|
RDG_networks/draw_segments.py,sha256=U53N5GXmQHWKdM1Q1faP_EGKjc6enOu2mcsunzSFpP0,984
|
4
4
|
RDG_networks/generate_line_network.py,sha256=lJ4rhObim3WcEQoebomewRQKWNJC5phFyFYRW7qjXIg,1127
|
5
5
|
RDG_networks/generate_line_segments.py,sha256=QV8_k7q6TD5c7Hcb2Ms_apEdWYw4XdLr7rdJgh49v4Q,9004
|
@@ -7,16 +7,16 @@ RDG_networks/generate_line_segments_dynamic.py,sha256=GoIhGXYbcvjqR5BJCnkvAGp8QB
|
|
7
7
|
RDG_networks/generate_line_segments_static.py,sha256=7KvHZi3krv-tAGydJR_gbMMmHKZ5azzrKcQe3fuWzCE,9265
|
8
8
|
RDG_networks/get_intersection_segments.py,sha256=mXB5qCy1oOps4Vu1mX6flW6v_4Xxc71YK41yOWjJX8o,2797
|
9
9
|
RDG_networks/sample_in_polygon.py,sha256=qpPpW-Da1vK8ZkVWMJ0zBsE8IgyMB619gCdybSkzKSQ,1605
|
10
|
-
RDG_networks/save_to_stl.py,sha256=
|
10
|
+
RDG_networks/save_to_stl.py,sha256=St8kGw6wl8uOGx8KhrZhBfe89-mOfp5JKhz0dEDBvc0,3894
|
11
11
|
RDG_networks/thickness/Classes.py,sha256=gVe_q5Rh_1DBiJoZ8H0FyJ4xG-IAcespjUpUirxFfAA,8125
|
12
|
-
RDG_networks/thickness/__init__.py,sha256=
|
13
|
-
RDG_networks/thickness/generate_line_segments_thickness.py,sha256=
|
14
|
-
RDG_networks/thickness/generate_line_segments_thickness_orientation backup.py,sha256=5gcStrs4SNLp17tFb9XsN4TLWpOaeu0cHteEedISs5E,8204
|
12
|
+
RDG_networks/thickness/__init__.py,sha256=jyyA7Bp519TkOGNSYDVxPKxCgO9vTYpQvpFytnIuqQs,892
|
13
|
+
RDG_networks/thickness/generate_line_segments_thickness.py,sha256=meLFptrXWt_povCTlEA0n_TYVfi_-HF9KUvW_tBpt4w,29194
|
15
14
|
RDG_networks/thickness/generate_line_segments_thickness_orientation.py,sha256=oTEwQkXRBuoHvEdIGU30p21e2QHW1UlmApzRO1s5c64,16821
|
15
|
+
RDG_networks/thickness/generate_line_segments_thickness_static.py,sha256=zvYkLZpmyl711Kr7LCEFbXeVUgxQuA1n9Z5jD8W2iXc,9021
|
16
16
|
RDG_networks/thickness/sample_in_polygon.py,sha256=nJ-yqfoCCGfC6_EpGL3L1t1LOYdqWZd-7v5bxy6th34,1849
|
17
|
-
RDG_Networks-0.3.
|
18
|
-
RDG_Networks-0.3.
|
19
|
-
RDG_Networks-0.3.
|
20
|
-
RDG_Networks-0.3.
|
21
|
-
RDG_Networks-0.3.
|
22
|
-
RDG_Networks-0.3.
|
17
|
+
RDG_Networks-0.3.7.dist-info/LICENSE.txt,sha256=BHUkX2GsdTr30sKmVZ1MLGR1njnx17EX_oUuuSVZZPE,598
|
18
|
+
RDG_Networks-0.3.7.dist-info/METADATA,sha256=A_gS2IRz_hQxrek9dkl2BawsJ6SKYuBxIUBCdhkjb58,2422
|
19
|
+
RDG_Networks-0.3.7.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
20
|
+
RDG_Networks-0.3.7.dist-info/entry_points.txt,sha256=DRd5hzsY9jAz5e_gkd3gNoIwqj6RAZEtISlV1qpsIE8,1038
|
21
|
+
RDG_Networks-0.3.7.dist-info/top_level.txt,sha256=4gUUYafD5Al9V8ZSiViVGYHpRMMCsCBcGgCNodk9Syg,13
|
22
|
+
RDG_Networks-0.3.7.dist-info/RECORD,,
|
@@ -7,6 +7,7 @@ generate_line_segments_dynamic = RDG_networks.generate_line_segments_dynamic:mai
|
|
7
7
|
generate_line_segments_static = RDG_networks.generate_line_segments_static:main
|
8
8
|
generate_line_segments_thickness = RDG_networks.thickness.generate_line_segments_thickness:main
|
9
9
|
generate_line_segments_thickness_orientation = RDG_networks.thickness.generate_line_segments_dynamic_orientation:main
|
10
|
+
generate_line_segments_thickness_static = RDG_networks.generate_line_segments_thickness_static:main
|
10
11
|
get_alignment_mean = RDG_networks.thickness.get_alignment_mean:main
|
11
12
|
get_intersection_segments = RDG_networks.get_intersection_segments:main
|
12
13
|
rotate_network = RDG_networks.thickness.rotate_network:main
|
RDG_networks/__init__.py
CHANGED
@@ -9,6 +9,7 @@ from .generate_line_segments_static import generate_line_segments_static
|
|
9
9
|
from .draw_segments import draw_segments
|
10
10
|
from .thickness.generate_line_segments_thickness import generate_line_segments_thickness
|
11
11
|
from .thickness.generate_line_segments_thickness_orientation import generate_line_segments_thickness_orientation
|
12
|
+
from .thickness.generate_line_segments_thickness_static import generate_line_segments_thickness_static
|
12
13
|
from .thickness.generate_line_segments_thickness_orientation import translate_network
|
13
14
|
from .thickness.generate_line_segments_thickness_orientation import clip_network
|
14
15
|
from .thickness.generate_line_segments_thickness_orientation import rotate_network
|
@@ -22,8 +23,9 @@ __all__ = ['generate_line_segments',
|
|
22
23
|
'clip_network',
|
23
24
|
'rotate_network',
|
24
25
|
'get_alignment_mean',
|
25
|
-
'generate_line_segments_dynamic',
|
26
26
|
'generate_line_segments_static',
|
27
|
+
'generate_line_segments_thickness_static',
|
28
|
+
'generate_line_segments_dynamic',
|
27
29
|
'generate_line_network',
|
28
30
|
'get_intersection_segments',
|
29
31
|
'draw_segments',
|
RDG_networks/save_to_stl.py
CHANGED
@@ -87,7 +87,7 @@ def merge_3d_meshes(mesh_list):
|
|
87
87
|
|
88
88
|
return merged_mesh
|
89
89
|
|
90
|
-
def save_to_stl(seg_thick_dict, thickness, name):
|
90
|
+
def save_to_stl(seg_thick_dict, thickness, name, frame_thickness = None):
|
91
91
|
mesh_list = []
|
92
92
|
for k,v in seg_thick_dict.items():
|
93
93
|
p = []
|
@@ -98,6 +98,18 @@ def save_to_stl(seg_thick_dict, thickness, name):
|
|
98
98
|
None
|
99
99
|
|
100
100
|
mesh_list.append(polygon_to_3d_mesh(Polygon(p), thickness=thickness))
|
101
|
+
|
102
|
+
if frame_thickness != None:
|
103
|
+
t = frame_thickness
|
104
|
+
bottom = Polygon([ (0,0-t), (0,0),(1,0),(1,0-t)])
|
105
|
+
top = Polygon([(0,1),(0,1+t), (1,1+t), (1,1)])
|
106
|
+
right = Polygon([(1,0-t), (1,1+t), (1+t,1+t), (1+t,0-t)])
|
107
|
+
left = Polygon([(0-t,0-t),(0-t,1+t), (0,1+t), (0,0-t)])
|
108
|
+
|
109
|
+
f = [bottom,top, right, left]
|
110
|
+
|
111
|
+
for f_ in f:
|
112
|
+
mesh_list.append(polygon_to_3d_mesh(f_, thickness=thickness))
|
101
113
|
|
102
114
|
merged_mesh = merge_3d_meshes(mesh_list)
|
103
115
|
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
from .generate_line_segments_thickness import generate_line_segments_thickness
|
4
4
|
from .generate_line_segments_thickness_orientation import generate_line_segments_thickness_orientation
|
5
|
+
from .generate_line_segments_thickness_static import generate_line_segments_thickness_static
|
5
6
|
from .generate_line_segments_thickness_orientation import translate_network
|
6
7
|
from .generate_line_segments_thickness_orientation import clip_network
|
7
8
|
from .generate_line_segments_thickness_orientation import rotate_network
|
@@ -10,6 +11,7 @@ from .generate_line_segments_thickness_orientation import get_alignment_mean
|
|
10
11
|
__all__ = [
|
11
12
|
'generate_line_segments_thickness',
|
12
13
|
'generate_line_segments_thickness_orientation',
|
14
|
+
'generate_line_segments_thickness_static',
|
13
15
|
'translate_network',
|
14
16
|
'clip_network',
|
15
17
|
'rotate_network',
|
@@ -606,8 +606,8 @@ def generate_line_segments_thickness(
|
|
606
606
|
angles = [config[i]['angle']]
|
607
607
|
else:
|
608
608
|
nucleation_point = None
|
609
|
-
if angles != 'uniform':
|
610
|
-
|
609
|
+
# if angles != 'uniform':
|
610
|
+
# angles=[angles[i]]
|
611
611
|
|
612
612
|
output = add_line_segment(segments_dict,
|
613
613
|
polygon_arr,
|
@@ -0,0 +1,240 @@
|
|
1
|
+
import numpy as np
|
2
|
+
import random
|
3
|
+
from typing import List, Dict, Tuple, Union, Optional
|
4
|
+
from shapely.geometry import Polygon as Polygon_Shapely, LineString
|
5
|
+
|
6
|
+
from .Classes import Line, LineSegment, Polygon
|
7
|
+
|
8
|
+
def minDistance_line_point(A, B, E):
|
9
|
+
# vector AB
|
10
|
+
AB = np.array(B) - np.array(A)
|
11
|
+
EB = np.array(B) - np.array(E)
|
12
|
+
AE = np.array(E) - np.array(A)
|
13
|
+
|
14
|
+
# Calculating the dot product
|
15
|
+
AB_BE = np.dot(AB, EB)
|
16
|
+
AB_AE = np.dot(AB, AE)
|
17
|
+
|
18
|
+
# Case 1
|
19
|
+
if (AB_BE > 0):
|
20
|
+
# Finding the magnitude
|
21
|
+
y = E[1] - B[1]
|
22
|
+
x = E[0] - B[0]
|
23
|
+
reqAns = np.sqrt(x * x + y * y)
|
24
|
+
|
25
|
+
# Case 2
|
26
|
+
elif (AB_AE < 0):
|
27
|
+
y = E[1] - A[1]
|
28
|
+
x = E[0] - A[0]
|
29
|
+
reqAns = np.sqrt(x * x + y * y)
|
30
|
+
|
31
|
+
# Case 3
|
32
|
+
else:
|
33
|
+
reqAns = np.linalg.outer(AB, AE) / np.linalg.norm(AB)
|
34
|
+
|
35
|
+
return reqAns
|
36
|
+
|
37
|
+
def doLinesIntersect(line1, line2):
|
38
|
+
"""
|
39
|
+
Check if two lines intersect and return the intersection point.
|
40
|
+
|
41
|
+
Args:
|
42
|
+
- line1 (Line): The first line segment.
|
43
|
+
- line2 (Line): The second line segment.
|
44
|
+
|
45
|
+
Returns:
|
46
|
+
- intersect (bool): True if the lines intersect, False otherwise.
|
47
|
+
- intersection_point (tuple or None): The intersection point (x, y) if lines intersect, None otherwise.
|
48
|
+
"""
|
49
|
+
|
50
|
+
x1, y1 = line1[0]
|
51
|
+
v1, w1 = (np.cos(line1[1]), np.sin(line1[1]))
|
52
|
+
|
53
|
+
x2, y2 = line2[0]
|
54
|
+
v2, w2 = (np.cos(line2[1]), np.sin(line2[1]))
|
55
|
+
|
56
|
+
determinant = v1 * w2 - v2 * w1
|
57
|
+
|
58
|
+
if determinant == 0:
|
59
|
+
return False, (None, None)
|
60
|
+
|
61
|
+
t1 = ((x2 - x1) * w2 - (y2 - y1) * v2) / determinant
|
62
|
+
t2 = ((x2 - x1) * w1 - (y2 - y1) * v1) / determinant
|
63
|
+
|
64
|
+
intersect_x = x1 + v1 * t1
|
65
|
+
intersect_y = y2 + w2 * t2
|
66
|
+
|
67
|
+
if -1e-6 < intersect_x < 1 + 1e-6 and -1e-6 < intersect_y < 1 + 1e-6:
|
68
|
+
return True, (intersect_x, intersect_y)
|
69
|
+
else:
|
70
|
+
return False, (None, None)
|
71
|
+
|
72
|
+
def seeds(number_of_lines, radius = 0.015, number_of_trials = 10000):
|
73
|
+
Line = {}
|
74
|
+
line_id = 0
|
75
|
+
|
76
|
+
nucleation_points = [(0,0), (1,0), (1,1), (0,1)]
|
77
|
+
angle = [0,np.pi/2, np.pi, 3*np.pi/2]
|
78
|
+
|
79
|
+
Line = {'b1':[ (0,0), 0], 'b2':[ (1,0), np.pi/2], 'b3':[ (1,1), np.pi], 'b4':[ (0,1), 3*np.pi/2] }
|
80
|
+
|
81
|
+
for i in range(number_of_lines):
|
82
|
+
new_points = (random.uniform(0,1), random.uniform(0,1))
|
83
|
+
|
84
|
+
line_new_point = []
|
85
|
+
for j in range(len(nucleation_points)):
|
86
|
+
start = (np.cos(angle[i])*10+nucleation_points[i][0], np.sin(angle[i])*10+nucleation_points[i][1])
|
87
|
+
end = (-np.cos(angle[i])*10+nucleation_points[i][0], -np.sin(angle[i])*10+nucleation_points[i][1])
|
88
|
+
line_new_point += [minDistance_line_point(start, end, new_points)]
|
89
|
+
|
90
|
+
trial = 0
|
91
|
+
while sum(np.array(line_new_point) < radius) != 0 or np.sum( np.sqrt(np.sum((np.array(nucleation_points) - np.array(new_points))**2, axis = 1)) < radius) != 0:
|
92
|
+
new_points = (random.uniform(0,1), random.uniform(0,1))
|
93
|
+
|
94
|
+
line_new_point = []
|
95
|
+
for j in range(len(nucleation_points)):
|
96
|
+
start = (np.cos(angle[i])*10+nucleation_points[i][0], np.sin(angle[i])*10+nucleation_points[i][1])
|
97
|
+
end = (-np.cos(angle[i])*10+nucleation_points[i][0], -np.sin(angle[i])*10+nucleation_points[i][1])
|
98
|
+
line_new_point += [minDistance_line_point(start, end, new_points)]
|
99
|
+
|
100
|
+
trial += 1
|
101
|
+
|
102
|
+
if trial > number_of_trials:
|
103
|
+
break
|
104
|
+
|
105
|
+
if trial <= number_of_trials:
|
106
|
+
nucleation_points += [new_points]
|
107
|
+
angles = [0, np.pi/4, np.pi/2, 3*np.pi/4]
|
108
|
+
angle_new = random.uniform(0, 2*np.pi) #random.choice(angles)#np.pi #random.uniform(0, 2*np.pi)
|
109
|
+
angle += [angle_new]
|
110
|
+
Line[line_id] = [ new_points ,angle_new]
|
111
|
+
line_id += 1
|
112
|
+
else:
|
113
|
+
print('jammed')
|
114
|
+
break
|
115
|
+
|
116
|
+
return Line
|
117
|
+
|
118
|
+
def all_intersection(Line):
|
119
|
+
intersections_dict = {}
|
120
|
+
|
121
|
+
for k,v in Line.items():
|
122
|
+
#intersections_dict[k] = {}
|
123
|
+
intersections_dict[k] = {'back':{}, 'front':{}}
|
124
|
+
|
125
|
+
for kk,vv in Line.items():
|
126
|
+
intersect, (intersect_x, intersect_y) = doLinesIntersect(v ,vv)
|
127
|
+
|
128
|
+
if intersect:
|
129
|
+
segment_length = np.sqrt( (v[0][0] - intersect_x)**2 + (v[0][1] - intersect_y)**2)
|
130
|
+
|
131
|
+
if intersect_x < v[0][0]:
|
132
|
+
intersections_dict[k]['back'][kk] = [(intersect_x, intersect_y), segment_length]
|
133
|
+
else:
|
134
|
+
if intersect_x == v[0][0] and intersect_y < v[0][1]:
|
135
|
+
intersections_dict[k]['back'][kk] = [(intersect_x, intersect_y), segment_length]
|
136
|
+
else:
|
137
|
+
intersections_dict[k]['front'][kk] = [(intersect_x, intersect_y), segment_length]
|
138
|
+
intersections_dict[k]['back'] = dict(sorted(intersections_dict[k]['back'].items(), key=lambda e:e[1], reverse = True))
|
139
|
+
intersections_dict[k]['front'] = dict(sorted(intersections_dict[k]['front'].items(), key=lambda e:e[1]))
|
140
|
+
|
141
|
+
return intersections_dict
|
142
|
+
|
143
|
+
def transform_to_standard_lines(segments):
|
144
|
+
data = []
|
145
|
+
for s in segments:
|
146
|
+
start = (s[3], s[4])
|
147
|
+
end = (s[5], s[6])
|
148
|
+
line = LineSegment(start=start, end=end, id=s[0], neighbors_initial=[s[1], s[2]], neighbors=None)
|
149
|
+
data.append(line)
|
150
|
+
|
151
|
+
return data
|
152
|
+
|
153
|
+
def static_line_graph_generation(seed_loc, intersections_dict):
|
154
|
+
borders = ['b1', 'b2', 'b3', 'b4']
|
155
|
+
segments = []
|
156
|
+
edges = []
|
157
|
+
|
158
|
+
for k,v in seed_loc.items():
|
159
|
+
if k not in borders:
|
160
|
+
#front
|
161
|
+
for kk_f, vv_f in intersections_dict[k]['front'].items():
|
162
|
+
try:
|
163
|
+
d_k_kk = intersections_dict[kk_f]['back'][k][1]
|
164
|
+
front_coordinate = intersections_dict[kk_f]['back'][k][0]
|
165
|
+
front_id = kk_f
|
166
|
+
where = 'back'
|
167
|
+
except:
|
168
|
+
d_k_kk = intersections_dict[kk_f]['front'][k][1]
|
169
|
+
front_coordinate = intersections_dict[kk_f]['front'][k][0]
|
170
|
+
front_id = kk_f
|
171
|
+
where = 'front'
|
172
|
+
|
173
|
+
if vv_f[1] > d_k_kk:
|
174
|
+
#check kk neighbors
|
175
|
+
boolean = []
|
176
|
+
for kkk, vvv in intersections_dict[kk_f][where].items():
|
177
|
+
if vvv[1] < d_k_kk:
|
178
|
+
try:
|
179
|
+
d_kk_kkk = intersections_dict[kkk]['back'][kk_f][1]
|
180
|
+
except:
|
181
|
+
d_kk_kkk = intersections_dict[kkk]['front'][kk_f][1]
|
182
|
+
|
183
|
+
if d_kk_kkk > vvv[1]:
|
184
|
+
boolean += [0]
|
185
|
+
else:
|
186
|
+
boolean += [1]
|
187
|
+
|
188
|
+
#print(k,kk, boolean)
|
189
|
+
|
190
|
+
if sum(boolean) == 0:
|
191
|
+
#print(k, kk, front_coordinate)
|
192
|
+
break
|
193
|
+
|
194
|
+
#back
|
195
|
+
for kk_b, vv_b in intersections_dict[k]['back'].items():
|
196
|
+
try:
|
197
|
+
d_k_kk = intersections_dict[kk_b]['back'][k][1]
|
198
|
+
back_coordinate = intersections_dict[kk_b]['back'][k][0]
|
199
|
+
back_id = kk_b
|
200
|
+
where = 'back'
|
201
|
+
except:
|
202
|
+
d_k_kk = intersections_dict[kk_b]['front'][k][1]
|
203
|
+
back_coordinate = intersections_dict[kk_b]['front'][k][0]
|
204
|
+
back_id = kk_b
|
205
|
+
where = 'front'
|
206
|
+
|
207
|
+
if vv_b[1] > d_k_kk:
|
208
|
+
boolean = []
|
209
|
+
for kkk, vvv in intersections_dict[kk_b][where].items():
|
210
|
+
if vvv[1] < d_k_kk:
|
211
|
+
try:
|
212
|
+
d_kk_kkk = intersections_dict[kkk]['back'][kk_b][1]
|
213
|
+
except:
|
214
|
+
d_kk_kkk = intersections_dict[kkk]['front'][kk_b][1]
|
215
|
+
|
216
|
+
if d_kk_kkk > vvv[1]:
|
217
|
+
boolean += [0]
|
218
|
+
else:
|
219
|
+
boolean += [1]
|
220
|
+
|
221
|
+
if sum(boolean) == 0:
|
222
|
+
break
|
223
|
+
|
224
|
+
try:
|
225
|
+
if k!= kk_f and k!= kk_b and kk_f != kk_b and (k, kk_f) not in edges and (kk_f, k) not in edges and (k, kk_b) not in edges and (kk_b, k) not in edges:
|
226
|
+
segments+= [[k, kk_f, kk_b, front_coordinate[0], front_coordinate[1], back_coordinate[0], back_coordinate[1]]]
|
227
|
+
edges += [(k,kk_f)]
|
228
|
+
edges += [(k,kk_b)]
|
229
|
+
except:
|
230
|
+
None
|
231
|
+
|
232
|
+
return segments
|
233
|
+
|
234
|
+
def generate_line_segments_thickness_static(size, seed_loc=None):
|
235
|
+
if seed_loc is None:
|
236
|
+
seed_loc = seeds(size, 0.0)
|
237
|
+
segments = static_line_graph_generation(seed_loc, all_intersection(seed_loc))
|
238
|
+
segments = transform_to_standard_lines(segments)
|
239
|
+
|
240
|
+
return segments
|
@@ -1,202 +0,0 @@
|
|
1
|
-
import numpy as np
|
2
|
-
from typing import List, Dict, Tuple, Union, Optional
|
3
|
-
from shapely.geometry import Polygon as Polygon_Shapely, LineString
|
4
|
-
from shapely.geometry import Point
|
5
|
-
import matplotlib.pyplot as plt
|
6
|
-
from concurrent.futures import ProcessPoolExecutor
|
7
|
-
|
8
|
-
from .Classes import Line, LineSegment, Polygon
|
9
|
-
from .generate_line_segments_thickness import generate_line_segments_thickness
|
10
|
-
|
11
|
-
def rotate(point, center, rotation_matrix):
|
12
|
-
"""
|
13
|
-
Rotates a point around the center using the given rotation matrix.
|
14
|
-
point: numpy array representing the point to rotate
|
15
|
-
center: numpy array representing the center of rotation
|
16
|
-
rotation_matrix: 2x2 numpy array representing the rotation matrix
|
17
|
-
"""
|
18
|
-
translated_point = point - center
|
19
|
-
rotated_point = np.dot(rotation_matrix, translated_point)
|
20
|
-
final_point = rotated_point + center
|
21
|
-
|
22
|
-
return final_point
|
23
|
-
|
24
|
-
def unit_vector(v):
|
25
|
-
""" Returns the unit vector of the vector. """
|
26
|
-
return v / np.linalg.norm(v)
|
27
|
-
|
28
|
-
def angle_between(v1, v2):
|
29
|
-
""" Returns the angle in radians between vectors 'v1' and 'v2'."""
|
30
|
-
v1_u = unit_vector(v1)
|
31
|
-
v2_u = unit_vector(v2)
|
32
|
-
return np.arccos(np.clip(np.dot(v1_u, v2_u), -1.0, 1.0))
|
33
|
-
|
34
|
-
def get_alignment_mean(line_vector_arr, director):
|
35
|
-
"""Get the mean alignment."""
|
36
|
-
S_all = []
|
37
|
-
for item in line_vector_arr:
|
38
|
-
line_vector = item['line_vector']
|
39
|
-
area = item['area']
|
40
|
-
P2 = 0.5*(3*(np.cos(angle_between(line_vector, director)))**2-1)
|
41
|
-
S_all.append(P2*area)
|
42
|
-
|
43
|
-
return float(np.mean(S_all))
|
44
|
-
|
45
|
-
def compute_alignment_for_angle(
|
46
|
-
angle: float,
|
47
|
-
segment_thickness_dict: dict,
|
48
|
-
director: np.ndarray,
|
49
|
-
box_size: float
|
50
|
-
) -> tuple[float, float]:
|
51
|
-
"""Compute the alignment for a given angle."""
|
52
|
-
rotation_matrix = np.array([[np.cos(angle), -np.sin(angle)], [np.sin(angle), np.cos(angle)]])
|
53
|
-
center = np.array([box_size / 2, box_size / 2])
|
54
|
-
line_vectors = [
|
55
|
-
{'line_vector': np.diff(rotate(np.array([seg.middle_segment.start, seg.middle_segment.end]), center, rotation_matrix), axis=0)[0],
|
56
|
-
'area': seg.area()}
|
57
|
-
for seg in segment_thickness_dict.values()
|
58
|
-
]
|
59
|
-
|
60
|
-
alignment = get_alignment_mean(line_vectors, director)
|
61
|
-
return angle, alignment
|
62
|
-
|
63
|
-
|
64
|
-
def get_max_alignment_angle(
|
65
|
-
segment_thickness_dict: dict,
|
66
|
-
director: np.ndarray,
|
67
|
-
box_size: float,
|
68
|
-
grid_points: int = 360
|
69
|
-
) -> float:
|
70
|
-
"""Find the angle with the maximum alignment."""
|
71
|
-
angles = np.linspace(0, 2 * np.pi, grid_points)
|
72
|
-
|
73
|
-
with ProcessPoolExecutor() as executor:
|
74
|
-
results = executor.map(
|
75
|
-
compute_alignment_for_angle,
|
76
|
-
angles,
|
77
|
-
[segment_thickness_dict] * grid_points,
|
78
|
-
[director] * grid_points,
|
79
|
-
[box_size] * grid_points
|
80
|
-
)
|
81
|
-
|
82
|
-
return max(results, key=lambda x: x[1])[0]
|
83
|
-
|
84
|
-
def orientate_network(
|
85
|
-
segment_thickness_dict: dict,
|
86
|
-
config: list[dict],
|
87
|
-
rotate_angle: float,
|
88
|
-
box_size: float
|
89
|
-
) -> list[dict]:
|
90
|
-
"""
|
91
|
-
Rotates and clips a network of line segments within a bounding box.
|
92
|
-
|
93
|
-
Parameters:
|
94
|
-
segment_thickness_dict (dict): Segment data with start and end points.
|
95
|
-
config (list[dict]): Segment configuration with angle and thickness.
|
96
|
-
rotate_angle (float): Rotation angle in radians.
|
97
|
-
box_size (float): Size of the bounding box.
|
98
|
-
|
99
|
-
Returns:
|
100
|
-
list[dict]: New segment positions, angles, and thicknesses.
|
101
|
-
"""
|
102
|
-
center = np.array([box_size / 2, box_size / 2])
|
103
|
-
rotation_matrix = np.array([[np.cos(rotate_angle), -np.sin(rotate_angle)], [np.sin(rotate_angle), np.cos(rotate_angle)]])
|
104
|
-
box = Polygon_Shapely([(0, 0), (box_size, 0), (box_size, box_size), (0, box_size)])
|
105
|
-
|
106
|
-
segment_thickness_dict_new = {}
|
107
|
-
# orientated_config = []
|
108
|
-
for i, segment in enumerate(segment_thickness_dict.values()):
|
109
|
-
for vertex in segment.vertices:
|
110
|
-
angle_rotated = config[i]['angle'] - rotate_angle
|
111
|
-
start_rotated = rotate(np.array(v.middle_segment.start), center, rotation_matrix)
|
112
|
-
end_rotated = rotate(np.array(v.middle_segment.end), center, rotation_matrix)
|
113
|
-
|
114
|
-
# Find the intersection between the rotated line and the square
|
115
|
-
line_middle_point = LineString([start_rotated, end_rotated])
|
116
|
-
|
117
|
-
# Calculate the intersection between the box and the line
|
118
|
-
intersection = box.intersection(line_middle_point)
|
119
|
-
|
120
|
-
# Check if the line intersects the polygon
|
121
|
-
if intersection.is_empty:
|
122
|
-
continue
|
123
|
-
else:
|
124
|
-
length = intersection.length
|
125
|
-
# midpoint = intersection.interpolate(1/2, normalized=True)
|
126
|
-
midpoint = intersection.interpolate(length/2)
|
127
|
-
|
128
|
-
x = midpoint.xy[0][0]
|
129
|
-
y = midpoint.xy[1][0]
|
130
|
-
|
131
|
-
# orientated_config.append({ 'location': (x,y), 'angle': angle_rotated, 'thickness': config[i]['thickness'] })
|
132
|
-
|
133
|
-
# return orientated_config
|
134
|
-
|
135
|
-
return segment_thickness_dict_new
|
136
|
-
|
137
|
-
def generate_line_segments_thickness_orientation(
|
138
|
-
size: int,
|
139
|
-
thickness_arr: List[float],
|
140
|
-
orientation: List[int],
|
141
|
-
angles: List[float],
|
142
|
-
config: List[List[float]] = None,
|
143
|
-
epsilon: float = 0,
|
144
|
-
box_size: float = 1,
|
145
|
-
grid_points: int = 360
|
146
|
-
) -> List[Tuple[Dict[str, LineSegment], Dict[str, Dict[str, object]], Dict[int, Polygon], np.ndarray]]:
|
147
|
-
"""
|
148
|
-
Generates a specified number of line segments and updates the polygon and segment thickness dictionaries.
|
149
|
-
|
150
|
-
Args:
|
151
|
-
size (int): The number of line segments to generate.
|
152
|
-
thickness_arr (List[float]): A list containing the thickness values for each segment to be generated.
|
153
|
-
angles (str): The angle distribution method for generating segments. Defaults to 'uniform'.
|
154
|
-
List[float]: list of angles in radians.
|
155
|
-
orientation (List[int]): the orientation of the model.
|
156
|
-
config (List[List[float]]): A list of configurations for the nucleation points and angles.
|
157
|
-
epsilon (float): the minimum distance between two line.
|
158
|
-
box_size (float): the size of the system.
|
159
|
-
grid_points (int): the number of points to test for the alignment.
|
160
|
-
|
161
|
-
Returns:
|
162
|
-
- an array of dictionaries for each orientation containing:
|
163
|
-
Tuple[Dict[str, LineSegment], Dict[str, Dict[str, object]], Dict[int, Polygon]]:
|
164
|
-
- Updated dictionary of line segments.
|
165
|
-
- Updated dictionary of polygons.
|
166
|
-
- Updated dictionary of segment thicknesses.
|
167
|
-
- Array of the nucleation points and angles [x,y,theta].
|
168
|
-
"""
|
169
|
-
# Size of the box
|
170
|
-
box_size_0 = box_size*np.sqrt(2)
|
171
|
-
|
172
|
-
# Initial structure
|
173
|
-
data_dict = generate_line_segments_thickness(size = size,
|
174
|
-
thickness_arr = thickness_arr,
|
175
|
-
epsilon= epsilon,
|
176
|
-
config = config,
|
177
|
-
angles = angles,
|
178
|
-
box_size= box_size_0)
|
179
|
-
|
180
|
-
segment_thickness_dict = data_dict['segment_thickness_dict']
|
181
|
-
generated_config = data_dict['generated_config']
|
182
|
-
|
183
|
-
# Calculate alignment with the y axis
|
184
|
-
director = (0,1)
|
185
|
-
max_angle = get_max_alignment_angle(segment_thickness_dict, director, box_size, grid_points)
|
186
|
-
|
187
|
-
# Regenerate network for each orientation
|
188
|
-
output = [{'orientation': 'original', 'data_dict': data_dict}]
|
189
|
-
for o in orientation:
|
190
|
-
rotate_angle = o-max_angle
|
191
|
-
orientated_config = orientate_network(segment_thickness_dict, generated_config, rotate_angle, box_size)
|
192
|
-
|
193
|
-
data_dict_new = generate_line_segments_thickness(size=size,
|
194
|
-
thickness_arr=thickness_arr,
|
195
|
-
epsilon=epsilon,
|
196
|
-
config=orientated_config,
|
197
|
-
angles=angles,
|
198
|
-
box_size=box_size)
|
199
|
-
|
200
|
-
output.append({'orientation': o, 'data_dict': data_dict_new})
|
201
|
-
|
202
|
-
return output
|
File without changes
|
File without changes
|
File without changes
|