RDG-Networks 0.3.1__py3-none-any.whl → 0.3.4__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: RDG-Networks
3
- Version: 0.3.1
3
+ Version: 0.3.4
4
4
  Summary: Most of the code from the RDG Networks project
5
5
  Home-page: https://github.com/NiekMooij/RDG_networks
6
6
  Author: Niek Mooij
@@ -1,5 +1,5 @@
1
1
  RDG_networks/Classes.py,sha256=_9X3JPHFAYYlaC8IZ_H9__sfz99G5l9UfPl65lL60_4,7977
2
- RDG_networks/__init__.py,sha256=Re-b4Ky4fp0QzUB8R8c4VysUMkHEP1VrfXLeOA8W_2w,922
2
+ RDG_networks/__init__.py,sha256=juPsGdSg0t8rIjaELwsQPUKYXVVu1GrdbBI2ncd7lZ0,938
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
@@ -9,12 +9,11 @@ RDG_networks/get_intersection_segments.py,sha256=mXB5qCy1oOps4Vu1mX6flW6v_4Xxc71
9
9
  RDG_networks/sample_in_polygon.py,sha256=qpPpW-Da1vK8ZkVWMJ0zBsE8IgyMB619gCdybSkzKSQ,1605
10
10
  RDG_networks/thickness/Classes.py,sha256=kgWNP5NCc11dTVAfujk30r_MsY2Xf4dAOmoalLRHa5E,8063
11
11
  RDG_networks/thickness/__init__.py,sha256=ixi8dBaMi-M_kCdxGfx8V0o_vOTv_anpAgLnPaBwysc,190
12
- RDG_networks/thickness/functions.py,sha256=cEUd858EZtf7ZUjq-MS1dctlWHPBxQzAY-B2Vko4DzU,11596
13
- RDG_networks/thickness/generate_line_segments_dynamic_thickness.py,sha256=M8jOad-Jg_J14Y263k9RTNoLd0VblOTKTumqwOlCM_I,25598
12
+ RDG_networks/thickness/generate_line_segments_dynamic_thickness.py,sha256=i10rjKTB9PoFyMaUxVS99YQqegUXfeVfB1qZWryvxRk,25598
14
13
  RDG_networks/thickness/sample_in_polygon.py,sha256=nJ-yqfoCCGfC6_EpGL3L1t1LOYdqWZd-7v5bxy6th34,1849
15
- RDG_Networks-0.3.1.dist-info/LICENSE.txt,sha256=BHUkX2GsdTr30sKmVZ1MLGR1njnx17EX_oUuuSVZZPE,598
16
- RDG_Networks-0.3.1.dist-info/METADATA,sha256=UD1uvMqUKZzK6p-v0KdyWB_pQUvUcHR4nkuYV3AxAPU,2422
17
- RDG_Networks-0.3.1.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
18
- RDG_Networks-0.3.1.dist-info/entry_points.txt,sha256=6AGpOd8ecHGEsoUhRj0j6VvN_Fg0QNCY8h5rInAJom0,542
19
- RDG_Networks-0.3.1.dist-info/top_level.txt,sha256=4gUUYafD5Al9V8ZSiViVGYHpRMMCsCBcGgCNodk9Syg,13
20
- RDG_Networks-0.3.1.dist-info/RECORD,,
14
+ RDG_Networks-0.3.4.dist-info/LICENSE.txt,sha256=BHUkX2GsdTr30sKmVZ1MLGR1njnx17EX_oUuuSVZZPE,598
15
+ RDG_Networks-0.3.4.dist-info/METADATA,sha256=NrwTO4MslrgfxoBqUxHctABU8Ibht3LxDJZHtdb3k9w,2422
16
+ RDG_Networks-0.3.4.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
17
+ RDG_Networks-0.3.4.dist-info/entry_points.txt,sha256=6AGpOd8ecHGEsoUhRj0j6VvN_Fg0QNCY8h5rInAJom0,542
18
+ RDG_Networks-0.3.4.dist-info/top_level.txt,sha256=4gUUYafD5Al9V8ZSiViVGYHpRMMCsCBcGgCNodk9Syg,13
19
+ RDG_Networks-0.3.4.dist-info/RECORD,,
RDG_networks/__init__.py CHANGED
@@ -7,14 +7,14 @@ from .get_intersection_segments import get_intersection_segments
7
7
  from .generate_line_segments_dynamic import generate_line_segments_dynamic
8
8
  from .generate_line_segments_static import generate_line_segments_static
9
9
  from .draw_segments import draw_segments
10
- from .thickness.generate_line_segments_dynamic_thickness import generate_line_segments_thickness
10
+ from .thickness.generate_line_segments_dynamic_thickness import generate_line_segments_dynamic_thickness
11
11
 
12
12
  __all__ = ['generate_line_segments',
13
13
  'generate_line_network',
14
14
  'get_intersection_segments',
15
15
  'generate_line_segments_dynamic',
16
16
  'generate_line_segments_static',
17
- 'generate_line_segments_thickness',
17
+ 'generate_line_segments_dynamic_thickness',
18
18
  'draw_segments',
19
19
  'sample_in_polygon',
20
20
  'Line',
@@ -1,8 +1,9 @@
1
1
  import math
2
2
  import numpy as np
3
+ import random
3
4
  from typing import List, Dict, Tuple, Union, Optional
4
5
 
5
- from .Classes import Line, LineSegment
6
+ from .Classes import Line, LineSegment, Polygon
6
7
  from .sample_in_polygon import sample_in_polygon, is_inside_polygon
7
8
 
8
9
  def doLinesIntersect(line1: Line, line2: Line) -> Tuple[bool, Union[Tuple[float, float], None]]:
@@ -40,8 +41,8 @@ def doLinesIntersect(line1: Line, line2: Line) -> Tuple[bool, Union[Tuple[float,
40
41
  return False, (None, None)
41
42
 
42
43
  def doSegmentsIntersect(
43
- segment1: 'LineSegment',
44
- segment2: 'LineSegment'
44
+ segment1: LineSegment,
45
+ segment2: LineSegment
45
46
  ) -> Tuple[bool, Tuple[Optional[float], Optional[float]]]:
46
47
  """
47
48
  Determines if two line segments intersect and returns the intersection point if they do.
@@ -255,7 +256,7 @@ def get_polygons(polygon_id, polygon_arr, neighbor1_1, neighbor1_2, vertex_begin
255
256
  return cycle0, vertices0, cycle1, vertices1, cycle2, vertices2
256
257
 
257
258
  def get_new_segment(
258
- line_segments_to_check: List['LineSegment'],
259
+ line_segments_to_check: List[LineSegment],
259
260
  location: Tuple[float, float],
260
261
  direction: Tuple[float, float],
261
262
  id: Optional[int] = None
@@ -337,7 +338,7 @@ def update_data(
337
338
  vertex_end_2: Tuple[float, float],
338
339
  id_1: int,
339
340
  id_2: int
340
- ) -> Tuple[Dict[int, 'LineSegment'], Dict[str, Dict[str, object]], Dict[int, 'Polygon']]:
341
+ ) -> Tuple[Dict[int, LineSegment], Dict[str, Dict[str, object]], Dict[int, Polygon]]:
341
342
  """
342
343
  Updates the segments, polygons, and segment thickness dictionaries by adding new data derived
343
344
  from provided vertices and neighbor information.
@@ -427,12 +428,12 @@ def update_data(
427
428
  return segments_dict, polygon_arr, segment_thickness_dict
428
429
 
429
430
  def add_line_segment(
430
- segments_dict: Dict[int, 'LineSegment'],
431
+ segments_dict: Dict[int, LineSegment],
431
432
  polygon_arr: Dict[str, Dict[str, object]],
432
- segment_thickness_dict: Dict[int, 'Polygon'],
433
+ segment_thickness_dict: Dict[int, Polygon],
433
434
  thickness: float = 0,
434
435
  angles: str = 'uniform'
435
- ) -> Union[Tuple[Dict[int, 'LineSegment'], Dict[str, Dict[str, object]], Dict[int, 'Polygon']], bool]:
436
+ ) -> Union[Tuple[Dict[int, LineSegment], Dict[str, Dict[str, object]], Dict[int, Polygon]], bool]:
436
437
  """
437
438
  Adds a new line segment to the segments and polygon data structures, with a given thickness and angle distribution.
438
439
 
@@ -520,7 +521,7 @@ def generate_line_segments_dynamic_thickness(
520
521
  size: int,
521
522
  thickness_arr: List[float],
522
523
  angles: str = 'uniform'
523
- ) -> Tuple[Dict[str, 'LineSegment'], Dict[str, Dict[str, object]], Dict[int, 'Polygon']]:
524
+ ) -> Tuple[Dict[str, LineSegment], Dict[str, Dict[str, object]], Dict[int, Polygon]]:
524
525
  """
525
526
  Generates a specified number of line segments and updates the polygon and segment thickness dictionaries.
526
527
 
@@ -1,255 +0,0 @@
1
- import numpy as np
2
- import random
3
- from typing import List, Dict, Tuple, Union, Optional
4
-
5
- from .Classes import Line, LineSegment
6
- from .sample_in_polygon import sample_in_polygon, is_inside_polygon
7
-
8
- def doLinesIntersect(line1: Line, line2: Line) -> Tuple[bool, Union[Tuple[float, float], None]]:
9
- """
10
- Check if two lines intersect and return the intersection point.
11
-
12
- Args:
13
- - line1 (Line): The first line segment.
14
- - line2 (Line): The second line segment.
15
-
16
- Returns:
17
- - intersect (bool): True if the lines intersect, False otherwise.
18
- - intersection_point (tuple or None): The intersection point (x, y) if lines intersect, None otherwise.
19
- """
20
- x1, y1 = line1.location
21
- v1, w1 = line1.direction
22
-
23
- x2, y2 = line2.location
24
- v2, w2 = line2.direction
25
-
26
- determinant = v1 * w2 - v2 * w1
27
-
28
- if determinant == 0:
29
- return False, (None, None)
30
-
31
- t1 = ((x2 - x1) * w2 - (y2 - y1) * v2) / determinant
32
- t2 = ((x2 - x1) * w1 - (y2 - y1) * v1) / determinant
33
-
34
- intersect_x = x1 + v1 * t1
35
- intersect_y = y2 + w2 * t2
36
-
37
- if -1e-6 < intersect_x < 1 + 1e-6 and -1e-6 < intersect_y < 1 + 1e-6:
38
- return True, (intersect_x, intersect_y)
39
- else:
40
- return False, (None, None)
41
-
42
- def doSegmentsIntersect(
43
- segment1: 'LineSegment',
44
- segment2: 'LineSegment'
45
- ) -> Tuple[bool, Tuple[Optional[float], Optional[float]]]:
46
- """
47
- Determines if two line segments intersect and returns the intersection point if they do.
48
-
49
- Args:
50
- segment1 (LineSegment): The first line segment.
51
- segment2 (LineSegment): The second line segment.
52
-
53
- Returns:
54
- Tuple[bool, Tuple[Optional[float], Optional[float]]]:
55
- - A boolean indicating whether the segments intersect.
56
- - A tuple of the x and y coordinates of the intersection point if they intersect,
57
- otherwise (None, None).
58
- """
59
-
60
- # Create line equations based on the segments' start and end points
61
- line1 = Line(location=segment1.start, direction=np.array(segment1.end) - np.array(segment1.start))
62
- line2 = Line(location=segment2.start, direction=np.array(segment2.end) - np.array(segment2.start))
63
-
64
- # Check if the infinite extensions of the two lines intersect
65
- intersect, (intersect_x, intersect_y) = doLinesIntersect(line1, line2)
66
-
67
- # If no intersection, return False
68
- if not intersect:
69
- return False, (None, None)
70
-
71
- # Check if the intersection point is within the bounds of both segments in the x-direction
72
- xcheck = (
73
- (segment1.end[0] <= intersect_x <= segment1.start[0]
74
- or segment1.start[0] <= intersect_x <= segment1.end[0]
75
- or abs(intersect_x - segment1.end[0]) < 1e-6
76
- or abs(intersect_x - segment1.start[0]) < 1e-6)
77
- and
78
- (segment2.end[0] <= intersect_x <= segment2.start[0]
79
- or segment2.start[0] <= intersect_x <= segment2.end[0]
80
- or abs(intersect_x - segment2.end[0]) < 1e-6
81
- or abs(intersect_x - segment2.start[0]) < 1e-6)
82
- )
83
-
84
- # Check if the intersection point is within the bounds of both segments in the y-direction
85
- ycheck = (
86
- (segment1.end[1] <= intersect_y <= segment1.start[1]
87
- or segment1.start[1] <= intersect_y <= segment1.end[1]
88
- or abs(intersect_y - segment1.end[1]) < 1e-6
89
- or abs(intersect_y - segment1.start[1]) < 1e-6)
90
- and
91
- (segment2.end[1] <= intersect_y <= segment2.start[1]
92
- or segment2.start[1] <= intersect_y <= segment2.end[1]
93
- or abs(intersect_y - segment2.end[1]) < 1e-6
94
- or abs(intersect_y - segment2.start[1]) < 1e-6)
95
- )
96
-
97
- # If the intersection point lies within the bounds of both segments, return True with the intersection point
98
- if xcheck and ycheck:
99
- return True, (intersect_x, intersect_y)
100
-
101
- # Otherwise, return False and no intersection point
102
- return False, (None, None)
103
-
104
- def pick_item_with_probability(
105
- polygon_arr: Dict[str, Dict[str, object]]
106
- ) -> Tuple[str, Dict[str, object]]:
107
- """
108
- Randomly selects an item from the polygon array with a probability proportional to the area of the polygons.
109
-
110
- Args:
111
- polygon_arr (Dict[str, Dict[str, object]]):
112
- A dictionary where keys are polygon identifiers (e.g., 'p1', 'p2') and values are dictionaries containing polygon properties,
113
- including an 'area' key that stores the area of the polygon.
114
-
115
- Returns:
116
- Tuple[str, Dict[str, object]]:
117
- - The identifier of the selected polygon.
118
- - The corresponding polygon data (dictionary) containing its properties.
119
- """
120
-
121
- # Calculate the total weight (sum of areas of all polygons)
122
- max_weight = sum(pol['area'] for pol in polygon_arr.values())
123
-
124
- # Generate a random threshold between 0 and the total weight
125
- threshold = random.uniform(0, max_weight)
126
- cumulative_weight = 0
127
-
128
- # Iterate through the polygons, accumulating weights
129
- for item, pol in polygon_arr.items():
130
- weight = pol['area']
131
- cumulative_weight += weight
132
-
133
- # Return the polygon when the cumulative weight surpasses the threshold
134
- if cumulative_weight >= threshold:
135
- return item, pol
136
-
137
- def get_location_and_direction(
138
- polygon_arr: Dict[str, Dict[str, object]],
139
- thickness: float,
140
- max_attempts: int = 1000,
141
- angles: Union[str, List[float]] = 'uniform'
142
- ) -> Union[Tuple[str, Dict[str, object], Tuple[float, float], np.ndarray, np.ndarray], bool]:
143
- """
144
- Attempts to find a valid location and direction within a polygon for placing a new segment. The direction can either be randomly
145
- chosen (uniformly) or from a specified list of angles. It ensures that the segment lies within the polygon's bounds given the
146
- specified thickness.
147
-
148
- Args:
149
- polygon_arr (Dict[str, Dict[str, object]]):
150
- A dictionary where the keys are polygon identifiers and the values are dictionaries containing polygon properties, including 'vertices'.
151
- thickness (float):
152
- The thickness of the segment that needs to fit inside the polygon.
153
- max_attempts (int, optional):
154
- The maximum number of attempts to find a valid location and direction. Defaults to 1000.
155
- angles (Union[str, List[float]], optional):
156
- A string ('uniform' for random directions) or a list of angles (in radians) to choose the direction from. Defaults to 'uniform'.
157
-
158
- Returns:
159
- Union[Tuple[str, Dict[str, object], Tuple[float, float], np.ndarray, np.ndarray], bool]:
160
- - If a valid location and direction are found, returns a tuple containing:
161
- - The polygon ID (`str`).
162
- - The polygon data (`Dict[str, object]`).
163
- - The new location as a tuple of floats (`Tuple[float, float]`).
164
- - The direction vector as a numpy array (`np.ndarray`).
165
- - The perpendicular vector to the direction as a numpy array (`np.ndarray`).
166
- - Returns `False` if no valid location and direction are found after the maximum attempts.
167
- """
168
-
169
- # Generate a new direction based on the angles parameter
170
- if angles == 'uniform':
171
- direction = np.array([random.uniform(-1, 1), random.uniform(-1, 1)])
172
- direction = direction / np.linalg.norm(direction) # Normalize the direction vector
173
- else:
174
- directions = [ (np.cos(angle), np.sin(angle)) for angle in angles ]
175
- direction = random.choice(directions)
176
- direction = np.array(direction) / np.linalg.norm(direction) # Normalize the chosen direction
177
-
178
- # Try to find a valid location and direction up to max_attempts
179
- attempt = 0
180
- while attempt < max_attempts:
181
- polygon_id, polygon = pick_item_with_probability(polygon_arr)
182
-
183
- # Sample a location within the polygon
184
- location_new = sample_in_polygon(polygon['vertices'])
185
-
186
- # Compute the perpendicular vector to the direction
187
- perpendicular = np.array([direction[1], -direction[0]])
188
- perpendicular = perpendicular / np.linalg.norm(perpendicular)
189
-
190
- # Ensure the perpendicular vector is oriented consistently (y-component is non-negative)
191
- if perpendicular[1] < 0:
192
- perpendicular = -perpendicular
193
-
194
- # Compute the positions for the segment with thickness, shifted by half-thickness along the perpendicular direction
195
- p1 = np.array(location_new) + thickness / 2 * perpendicular
196
- p2 = np.array(location_new) - thickness / 2 * perpendicular
197
-
198
- # Check if both endpoints of the segment are inside the polygon
199
- if is_inside_polygon(polygon['vertices'], p1) and is_inside_polygon(polygon['vertices'], p2):
200
- return polygon_id, polygon, location_new, direction, perpendicular
201
-
202
- attempt += 1
203
-
204
- # If no valid location and direction is found, return False
205
- return False
206
-
207
- def get_polygons(polygon_id, polygon_arr, neighbor1_1, neighbor1_2, vertex_begin_1, vertex_end_1, neighbor2_1, neighbor2_2, vertex_begin_2, vertex_end_2, segment_new_id_1, segment_new_id_2):
208
- # Extract vertices and cycle (faces) of the original polygon
209
- vertices = polygon_arr[polygon_id]['vertices']
210
- cycle = polygon_arr[polygon_id]['faces']
211
-
212
- # Get first cycle and vertices
213
- index_start_1, index_end_1 = (cycle.index(neighbor1_1), cycle.index(neighbor1_2))
214
- if index_start_1 < index_end_1:
215
- cycle1 = [segment_new_id_1] + cycle[index_start_1:index_end_1+1]
216
- vertices1 = [vertex_begin_1] + vertices[index_start_1:index_end_1] + [vertex_end_1]
217
- else:
218
- cycle1 = [segment_new_id_1] + cycle[index_start_1:] + cycle[:index_end_1+1]
219
- vertices1 = [vertex_begin_1] + vertices[index_start_1:] + vertices[:index_end_1] + [vertex_end_1]
220
-
221
- # Get second cycle and vertices
222
- index_start_2, index_end_2 = (cycle.index(neighbor2_2), cycle.index(neighbor2_1))
223
- if index_start_2 < index_end_2:
224
- cycle2 = [segment_new_id_2] + cycle[index_start_2:index_end_2+1]
225
- vertices2 = [vertex_end_2] + vertices[index_start_2:index_end_2] + [vertex_begin_2]
226
- else:
227
- cycle2 = [segment_new_id_2] + cycle[index_start_2:] + cycle[:index_end_2+1]
228
- vertices2 = [vertex_end_2] + vertices[index_start_2:] + vertices[:index_end_2] + [vertex_begin_2]
229
-
230
- # Get middle cycle and vertices
231
- cycle0 = [neighbor1_1, segment_new_id_1, neighbor1_2]
232
- vertices0 = [vertex_begin_1, vertex_end_1]
233
-
234
- index_start_0, index_end_0 = (cycle.index(neighbor1_2), cycle.index(neighbor2_2))
235
- if index_start_0 < index_end_0:
236
- cycle0 = cycle0 + cycle[index_start_0:index_end_0+1]
237
- vertices0 = vertices0 + vertices[index_start_0:index_end_0]
238
-
239
- elif index_start_0 > index_end_0:
240
- cycle0 = cycle0 + cycle[index_start_0:] + cycle[:index_end_0+1]
241
- vertices0 = vertices0 + vertices[index_start_0:] + vertices[:index_end_0]
242
-
243
- cycle0 = cycle0 + [segment_new_id_2]
244
- vertices0 = vertices0 + [vertex_end_2] + [vertex_begin_2]
245
-
246
- index_start_0, index_end_0 = (cycle.index(neighbor2_1), cycle.index(neighbor1_1))
247
- if index_start_0 < index_end_0:
248
- cycle0 = cycle0 + cycle[index_start_0:index_end_0+1]
249
- vertices0 = vertices0 + vertices[index_start_0:index_end_0]
250
-
251
- elif index_start_0 > index_end_0:
252
- cycle0 = cycle0 + cycle[index_start_0:] + cycle[:index_end_0+1]
253
- vertices0 = vertices0 + vertices[index_start_0:] + vertices[:index_end_0]
254
-
255
- return cycle0, vertices0, cycle1, vertices1, cycle2, vertices2