RDG-Networks 0.3.10__py3-none-any.whl → 0.3.12__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,141 @@
1
+ Metadata-Version: 2.2
2
+ Name: RDG-Networks
3
+ Version: 0.3.12
4
+ Summary: RDG Networks project
5
+ Home-page: https://github.com/NiekMooij/RDG_networks
6
+ Author: Niek Mooij
7
+ Author-email: mooij.niek@gmail.com
8
+ License: All Rights Reserved
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE.txt
13
+ Requires-Dist: networkx
14
+ Requires-Dist: numpy
15
+ Requires-Dist: scipy
16
+ Requires-Dist: shapely
17
+ Requires-Dist: typing
18
+ Dynamic: author
19
+ Dynamic: author-email
20
+ Dynamic: classifier
21
+ Dynamic: description
22
+ Dynamic: description-content-type
23
+ Dynamic: home-page
24
+ Dynamic: license
25
+ Dynamic: requires-dist
26
+ Dynamic: summary
27
+
28
+ ## Overview
29
+
30
+ This Python package provides code regarding the RDG networks project.
31
+
32
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
33
+ [![Python Version](https://img.shields.io/badge/python-3.6%2B-blue.svg)](https://www.python.org/downloads/)
34
+
35
+ ## Table of Contents
36
+
37
+ - [Features](#features)
38
+ - [Installation](#installation)
39
+ - [Usage](#usage)
40
+ - [Configuration](#configuration)
41
+ - [License](#license)
42
+ - [Contact](#contact)
43
+
44
+ ## Features
45
+
46
+ ### No thickness
47
+ - **generate_line_segments:** Function that determines the linesegments of a RDG network.
48
+ - **generate_line_network:** Function that makes the underlying network of the linesegments.
49
+ - **get_intersection_segments:** Function that determines the intersection segments of a RDG network.
50
+ - **generate_line_segments_dynamic:** Function that determines the segments of a dynamic RDG network (with increasing linelengths in time).
51
+ - **draw_segments:** Function that draws the segments.
52
+
53
+ ### Thickness
54
+ - **generate_line_segments_thickness:** Generates segment network with thicknesses
55
+ - **orientate_network:** Generates various rotated versions of the initial network.
56
+
57
+ - **save_to_stl:** Saves the network as a stl file.
58
+ - **save_to_json:** Saves data as a json file.
59
+ - **load_from_json:** Loads data as a json file.
60
+
61
+ ## Installation
62
+ You can install the package using pip:
63
+
64
+ ```bash
65
+ pip install RDG-networks
66
+ ```
67
+
68
+ ## Usage
69
+ ### Output
70
+ The main function is called *generate_line_segments_thickness* and outputs the following data:
71
+ ```python
72
+ data_dict = {'segments_dict': segments_dict,
73
+ 'polygon_arr': polygon_arr,
74
+ 'segment_thickness_dict': segment_thickness_dict,
75
+ 'jammed': jammed,
76
+ 'generated_config': generated_config}
77
+ ```
78
+ - *segment_thickness_dict*: contains the generated network, represented by multiple polygons.
79
+ - *segments_dict*: contains auxilliary information of the generated network.
80
+ - *polygon_arr*: contains auxilliary information of the generated network.
81
+ - *jammed*: A boolean indicating if the system is jammed.
82
+ - *generated_config*: An array containing all nucleation points and orientations of the segments.
83
+
84
+ ### Code example
85
+ ```python
86
+ import matplotlib.pyplot as plt
87
+ import numpy as np
88
+ import os
89
+ import sys
90
+ import random
91
+ from RDG_networks.thickness.generate_line_segments_thickness import generate_line_segments_thickness
92
+ from RDG_networks import save_to_stl
93
+ from RDG_networks.save_data import save_to_json, load_from_json
94
+
95
+ size = 15
96
+ lamb0 = 0.2
97
+ alpha = 0.52
98
+ thickness_arr = [lamb0 * t**(-alpha) for t in range(1, size + 1)]
99
+ box_size = 1
100
+ angles = [random.random() * 2 * np.pi for _ in range(size)]
101
+
102
+ # Generate initial structure with specified parameters
103
+ data_dict = generate_line_segments_thickness(size=size, thickness_arr=thickness_arr, angles=angles, box_size=box_size)
104
+
105
+ # Setup plot
106
+ fig, ax1 = plt.subplots(nrows=1, ncols=1, figsize=(5, 5))
107
+
108
+ segment_thickness_dict = data_dict['segment_thickness_dict']
109
+ for key, segment in segment_thickness_dict.items():
110
+ segment.draw(ax1)
111
+ middle_segment = segment.middle_segment
112
+ if middle_segment:
113
+ middle_segment.draw(ax1)
114
+
115
+ # Set plot limits and disable ticks
116
+ ax1.set(xlim=(0, 1), ylim=(0, 1))
117
+ ax1.set_xticks([])
118
+ ax1.set_yticks([])
119
+
120
+ # Save to STL and JSON files
121
+ save_to_stl(segment_thickness_dict, thickness=0.2, name=os.path.join(sys.path[0], 'network.stl'), frame_thickness=0.1)
122
+ file_path = os.path.join(sys.path[0], 'data.json')
123
+ save_to_json(data_dict, file_path)
124
+ data = load_from_json(file_path)
125
+
126
+ # Display the plot
127
+ plt.show()
128
+ ```
129
+
130
+ ## Configuration
131
+ No specific configuration is required.
132
+
133
+ ## License
134
+ All Rights Reserved
135
+
136
+ The following code and its accompanying documentation are the property of Martijn (Niek) Mooij. All rights are reserved. No part of this code may be reproduced, distributed, or transmitted in any form or by any means, including photocopying, recording, or other electronic or mechanical methods, without the prior written permission of the author, except in the case of brief quotations embodied in critical reviews and certain other noncommercial uses permitted by copyright law. For permission requests, write to the author at mooij.niek@gmail.com.
137
+
138
+ Copyright 2024 Niek Mooij
139
+
140
+ ## Contact
141
+ You can contact me at mooij.niek@gmail.com for any questions or suggestions.
@@ -1,5 +1,5 @@
1
1
  RDG_networks/Classes.py,sha256=_9X3JPHFAYYlaC8IZ_H9__sfz99G5l9UfPl65lL60_4,7977
2
- RDG_networks/__init__.py,sha256=8cc-h5ifS7RP1-N4b1Ow-4bA6MxgFETaS6SD0of54Fk,1575
2
+ RDG_networks/__init__.py,sha256=XWmsAEPzxbMBO3tU9OjDOyGGLIfwvRK7ebGEon3Y8wE,1659
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,17 +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=St8kGw6wl8uOGx8KhrZhBfe89-mOfp5JKhz0dEDBvc0,3894
11
- RDG_networks/thickness/Classes.py,sha256=zRhi2TFDwK1oARvAd1HlxnMWeHSj7KKO-u79_r23tXc,8176
10
+ RDG_networks/save_data.py,sha256=pMbQtWu1-Q_rSOKm_GeT_0wILu4Yk7tLHiyq3g46BQk,4378
11
+ RDG_networks/thickness/Classes.py,sha256=NweH3l77rzZGoAcYwYq_LrpnIsDrXOem6poznTBm9a8,8972
12
12
  RDG_networks/thickness/__init__.py,sha256=DzH-mmdrk5e1LL7oq5kg0xaDjtWR7DiCeKKchArHSIs,703
13
- RDG_networks/thickness/generate_line_segments_thickness.py,sha256=euPMqyHc_RlbFuZO16SSKdZ5NvhKIJA_fOf-rvqv7iA,29214
14
- RDG_networks/thickness/generate_line_segments_thickness_correct.py,sha256=rvvqEMGYX7imosKedyXHyTkBV4C2_24K8UxthXDTe7Q,28627
13
+ RDG_networks/thickness/generate_line_segments_thickness.py,sha256=D32KQMzOsqnzJ05XMgy-BF3PgET5UZLFhPBi_rCH26I,29112
15
14
  RDG_networks/thickness/generate_line_segments_thickness_static.py,sha256=6-2p4GOQFU-dP5Q9nYuaVqeb7wvxk2Fqld3A7cV2pY8,8964
16
15
  RDG_networks/thickness/orientate_network.py,sha256=4jii3y89Jlw1tPmTWoUyrKE7MlHq21JuoiuwnBa1Mkk,15484
17
16
  RDG_networks/thickness/sample_in_polygon.py,sha256=nJ-yqfoCCGfC6_EpGL3L1t1LOYdqWZd-7v5bxy6th34,1849
18
- RDG_Networks-0.3.10.dist-info/LICENSE.txt,sha256=BHUkX2GsdTr30sKmVZ1MLGR1njnx17EX_oUuuSVZZPE,598
19
- RDG_Networks-0.3.10.dist-info/METADATA,sha256=KmHQ5XO8lsAUBhL7uVOTqtS-wXoh7PL--U4aFyJlv40,2578
20
- RDG_Networks-0.3.10.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
21
- RDG_Networks-0.3.10.dist-info/entry_points.txt,sha256=coqOWe9rYYuz9VQvJGFomTzvEP7JY5T9V9gauMhSb_0,986
22
- RDG_Networks-0.3.10.dist-info/top_level.txt,sha256=4gUUYafD5Al9V8ZSiViVGYHpRMMCsCBcGgCNodk9Syg,13
23
- RDG_Networks-0.3.10.dist-info/RECORD,,
17
+ RDG_Networks-0.3.12.dist-info/LICENSE.txt,sha256=BHUkX2GsdTr30sKmVZ1MLGR1njnx17EX_oUuuSVZZPE,598
18
+ RDG_Networks-0.3.12.dist-info/METADATA,sha256=ZA5tiisIP9Use9BFpAnW8xvrI5E7wvMPpqLVB_F3SIE,4998
19
+ RDG_Networks-0.3.12.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
20
+ RDG_Networks-0.3.12.dist-info/entry_points.txt,sha256=TxynZ-ZDOUTjGcNE04io0GRKkUgDKn-Byxf0Zo-tLU8,1080
21
+ RDG_Networks-0.3.12.dist-info/top_level.txt,sha256=4gUUYafD5Al9V8ZSiViVGYHpRMMCsCBcGgCNodk9Syg,13
22
+ RDG_Networks-0.3.12.dist-info/RECORD,,
@@ -9,7 +9,9 @@ generate_line_segments_thickness = RDG_networks.thickness.generate_line_segments
9
9
  generate_line_segments_thickness_static = RDG_networks.generate_line_segments_thickness_static:main
10
10
  get_alignment_mean = RDG_networks.thickness.get_alignment_mean:main
11
11
  get_intersection_segments = RDG_networks.get_intersection_segments:main
12
+ load_from_json = RDG_networks.load_from_json:main
12
13
  orientate_network = RDG_networks.thickness.orientate_network:main
13
14
  rotate_network = RDG_networks.thickness.rotate_network:main
14
- save_to_stl = RDG_networks.save_to_stl:main
15
+ save_data = RDG_networks.save_to_stl:main
16
+ save_to_json = RDG_networks.save_to_json:main
15
17
  translate_network = RDG_networks.thickness.translate_network:main
RDG_networks/__init__.py CHANGED
@@ -14,7 +14,7 @@ from .thickness.orientate_network import translate_network
14
14
  from .thickness.orientate_network import clip_network
15
15
  from .thickness.orientate_network import rotate_network
16
16
  from .thickness.orientate_network import get_alignment_mean
17
- from .save_to_stl import save_to_stl
17
+ from .save_data import save_to_stl, save_to_json, load_from_json
18
18
 
19
19
  __all__ = ['generate_line_segments',
20
20
  'generate_line_segments_thickness',
@@ -33,5 +33,7 @@ __all__ = ['generate_line_segments',
33
33
  'Line',
34
34
  'LineSegment',
35
35
  'Polygon',
36
- 'save_to_stl'
36
+ 'save_to_stl',
37
+ 'save_to_json',
38
+ 'load_from_json'
37
39
  ]
@@ -7,6 +7,7 @@ import matplotlib.pyplot as plt
7
7
  import numpy as np
8
8
  import math
9
9
  import pickle
10
+ import json
10
11
 
11
12
  import numpy as np
12
13
  from stl import mesh
@@ -114,4 +115,16 @@ def save_to_stl(seg_thick_dict, thickness, name, frame_thickness = None):
114
115
  merged_mesh = merge_3d_meshes(mesh_list)
115
116
 
116
117
  # Save the merged mesh as an STL file
117
- merged_mesh.save(name)
118
+ merged_mesh.save(name)
119
+
120
+ def save_to_json(data_dict, file_path):
121
+ data_dict['segments_dict'] = {key: pol.to_dict() for key, pol in data_dict['segments_dict'].items()}
122
+ data_dict['segment_thickness_dict'] = {key: pol.to_dict() for key, pol in data_dict['segment_thickness_dict'].items()}
123
+
124
+ with open(file_path, 'w') as json_file:
125
+ json.dump(data_dict, json_file)
126
+
127
+ def load_from_json(file_path):
128
+ with open(file_path, 'r') as file:
129
+ data = json.load(file)
130
+ return data
@@ -3,6 +3,7 @@ import matplotlib.axes._axes as axes
3
3
  from matplotlib.patches import Polygon as polgon
4
4
  import numpy as np
5
5
  from typing import List, Tuple, Union, Optional
6
+ import json
6
7
 
7
8
  class Line:
8
9
  """
@@ -87,6 +88,21 @@ class LineSegment:
87
88
  """
88
89
  return copy.deepcopy(self)
89
90
 
91
+ def to_dict(self) -> dict:
92
+ """
93
+ Convert the LineSegment object to a dictionary.
94
+
95
+ Returns:
96
+ - dict: A dictionary representation of the LineSegment object.
97
+ """
98
+ return {
99
+ 'start': self.start,
100
+ 'end': self.end,
101
+ 'id': self.id,
102
+ 'neighbors_initial': self.neighbors_initial,
103
+ 'neighbors': self.neighbors
104
+ }
105
+
90
106
  class Polygon:
91
107
  """
92
108
  Represents a polygon defined by a list of vertices.
@@ -178,6 +194,19 @@ class Polygon:
178
194
  x2, y2 = self.vertices[(i + 1) % len(self.vertices)]
179
195
  perimeter += np.sqrt((x1-x2)**2 + (y1-y2)**2)
180
196
  return perimeter
197
+
198
+ def to_dict(self) -> dict:
199
+ """
200
+ Convert the Polygon object to a dictionary.
201
+
202
+ Returns:
203
+ dict: A dictionary representation of the Polygon object.
204
+ """
205
+ return {
206
+ 'vertices': self.vertices,
207
+ 'middle_segment': self.middle_segment.to_dict(),
208
+ 'neighbors': self.neighbors
209
+ }
181
210
 
182
211
  class Cycle:
183
212
  def __init__(self, vertices, id=None):
@@ -642,8 +642,6 @@ def generate_line_segments_thickness(
642
642
  'polygon_arr': polygon_arr,
643
643
  'segment_thickness_dict': segment_thickness_dict,
644
644
  'jammed': jammed,
645
- 'nucleation_points': nucleation_point,
646
- 'nucleation_angles': angles,
647
645
  'generated_config': generated_config}
648
646
 
649
647
  return data_dict
@@ -1,72 +0,0 @@
1
- Metadata-Version: 2.2
2
- Name: RDG-Networks
3
- Version: 0.3.10
4
- Summary: Most of the code from the RDG Networks project
5
- Home-page: https://github.com/NiekMooij/RDG_networks
6
- Author: Niek Mooij
7
- Author-email: mooij.niek@gmail.com
8
- License: All Rights Reserved
9
- Classifier: Programming Language :: Python :: 3
10
- Classifier: Operating System :: OS Independent
11
- License-File: LICENSE.txt
12
- Requires-Dist: networkx
13
- Requires-Dist: numpy
14
- Requires-Dist: scipy
15
- Requires-Dist: shapely
16
- Requires-Dist: typing
17
- Dynamic: author
18
- Dynamic: author-email
19
- Dynamic: classifier
20
- Dynamic: description
21
- Dynamic: home-page
22
- Dynamic: license
23
- Dynamic: requires-dist
24
- Dynamic: summary
25
-
26
- ## Overview
27
-
28
- This Python package provides code regarding the RDG networks project.
29
-
30
- [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
31
- [![Python Version](https://img.shields.io/badge/python-3.6%2B-blue.svg)](https://www.python.org/downloads/)
32
-
33
- ## Table of Contents
34
-
35
- - [Features](#features)
36
- - [Installation](#installation)
37
- - [Usage](#usage)
38
- - [Configuration](#configuration)
39
- - [License](#license)
40
- - [Contact](#contact)
41
-
42
- ## Features
43
-
44
- - **generate_line_segments:** Function that determines the linesegments of a RDG network.
45
- - **generate_line_network:** Function that makes the underlying network of the linesegments.
46
- - **get_intersection_segments:** Function that determines the intersection segments of a RDG network.
47
- - **generate_line_segments_dynamic:** Function that determines the segments of a dynamic RDG network (with increasing linelengths in time).
48
- - **draw_segments:** Function that draws the segments.
49
-
50
-
51
- ## Installation
52
- You can install the package using pip:
53
-
54
- ```bash
55
- pip install RDG-networks
56
- ```
57
-
58
- ## Usage
59
- To use the package, import the relevant script from the functions folder based on the algorithm you'd like to apply.
60
-
61
- ## Configuration
62
- No specific configuration is required.
63
-
64
- ## License
65
- All Rights Reserved
66
-
67
- The following code and its accompanying documentation are the property of Martijn (Niek) Mooij. All rights are reserved. No part of this code may be reproduced, distributed, or transmitted in any form or by any means, including photocopying, recording, or other electronic or mechanical methods, without the prior written permission of the author, except in the case of brief quotations embodied in critical reviews and certain other noncommercial uses permitted by copyright law. For permission requests, write to the author at mooij.niek@gmail.com.
68
-
69
- Copyright 2024 Niek Mooij
70
-
71
- ## Contact
72
- You can contact me at mooij.niek@gmail.com for any questions or suggestions.
@@ -1,633 +0,0 @@
1
- import math
2
- import numpy as np
3
- import random
4
- from typing import List, Dict, Tuple, Union, Optional
5
- from shapely.geometry import Polygon as Polygon_Shapely, LineString
6
-
7
- from .Classes import Line, LineSegment, Polygon
8
- from .sample_in_polygon import sample_in_polygon, is_inside_polygon
9
-
10
- def doLinesIntersect(line1: Line, line2: Line, box_size = 1) -> Tuple[bool, Union[Tuple[float, float], None]]:
11
- """
12
- Check if two lines intersect and return the intersection point.
13
-
14
- Args:
15
- - line1 (Line): The first line segment.
16
- - line2 (Line): The second line segment.
17
- - box_size (float): The size of the bounding box. Defaults to 1.
18
-
19
- Returns:
20
- - intersect (bool): True if the lines intersect, False otherwise.
21
- - intersection_point (tuple or None): The intersection point (x, y) if lines intersect, None otherwise.
22
- """
23
- x1, y1 = line1.location
24
- v1, w1 = line1.direction
25
-
26
- x2, y2 = line2.location
27
- v2, w2 = line2.direction
28
-
29
- determinant = v1 * w2 - v2 * w1
30
-
31
- if determinant == 0:
32
- return False, (None, None)
33
-
34
- t1 = ((x2 - x1) * w2 - (y2 - y1) * v2) / determinant
35
- t2 = ((x2 - x1) * w1 - (y2 - y1) * v1) / determinant
36
-
37
- intersect_x = x1 + v1 * t1
38
- intersect_y = y2 + w2 * t2
39
-
40
-
41
- if -1e-6 < intersect_x < box_size + 1e-6 and -1e-6 < intersect_y < box_size + 1e-6:
42
- return True, (intersect_x, intersect_y)
43
- else:
44
- return False, (None, None)
45
-
46
- def doSegmentsIntersect(
47
- segment1: LineSegment,
48
- segment2: LineSegment,
49
- box_size = 1
50
- ) -> Tuple[bool, Tuple[Optional[float], Optional[float]]]:
51
- """
52
- Determines if two line segments intersect and returns the intersection point if they do.
53
-
54
- Args:
55
- segment1 (LineSegment): The first line segment.
56
- segment2 (LineSegment): The second line segment.
57
-
58
- Returns:
59
- Tuple[bool, Tuple[Optional[float], Optional[float]]]:
60
- - A boolean indicating whether the segments intersect.
61
- - A tuple of the x and y coordinates of the intersection point if they intersect,
62
- otherwise (None, None).
63
- """
64
-
65
- # Create line equations based on the segments' start and end points
66
- line1 = Line(location=segment1.start, direction=np.array(segment1.end) - np.array(segment1.start))
67
- line2 = Line(location=segment2.start, direction=np.array(segment2.end) - np.array(segment2.start))
68
-
69
- # Check if the infinite extensions of the two lines intersect
70
- intersect, (intersect_x, intersect_y) = doLinesIntersect(line1, line2, box_size)
71
-
72
- # If no intersection, return False
73
- if not intersect:
74
- return False, (None, None)
75
-
76
- # Check if the intersection point is within the bounds of both segments in the x-direction
77
- xcheck = (
78
- (segment1.end[0] <= intersect_x <= segment1.start[0]
79
- or segment1.start[0] <= intersect_x <= segment1.end[0]
80
- or abs(intersect_x - segment1.end[0]) < 1e-6
81
- or abs(intersect_x - segment1.start[0]) < 1e-6)
82
- and
83
- (segment2.end[0] <= intersect_x <= segment2.start[0]
84
- or segment2.start[0] <= intersect_x <= segment2.end[0]
85
- or abs(intersect_x - segment2.end[0]) < 1e-6
86
- or abs(intersect_x - segment2.start[0]) < 1e-6)
87
- )
88
-
89
- # Check if the intersection point is within the bounds of both segments in the y-direction
90
- ycheck = (
91
- (segment1.end[1] <= intersect_y <= segment1.start[1]
92
- or segment1.start[1] <= intersect_y <= segment1.end[1]
93
- or abs(intersect_y - segment1.end[1]) < 1e-6
94
- or abs(intersect_y - segment1.start[1]) < 1e-6)
95
- and
96
- (segment2.end[1] <= intersect_y <= segment2.start[1]
97
- or segment2.start[1] <= intersect_y <= segment2.end[1]
98
- or abs(intersect_y - segment2.end[1]) < 1e-6
99
- or abs(intersect_y - segment2.start[1]) < 1e-6)
100
- )
101
-
102
- # If the intersection point lies within the bounds of both segments, return True with the intersection point
103
- if xcheck and ycheck:
104
- return True, (intersect_x, intersect_y)
105
-
106
- # Otherwise, return False and no intersection point
107
- return False, (None, None)
108
-
109
- def pick_item_with_probability(
110
- polygon_arr: Dict[str, Dict[str, object]]
111
- ) -> Tuple[str, Dict[str, object]]:
112
- """
113
- Randomly selects an item from the polygon array with a probability proportional to the area of the polygons.
114
-
115
- Args:
116
- polygon_arr (Dict[str, Dict[str, object]]):
117
- A dictionary where keys are polygon identifiers (e.g., 'p1', 'p2') and values are dictionaries containing polygon properties,
118
- including an 'area' key that stores the area of the polygon.
119
-
120
- Returns:
121
- Tuple[str, Dict[str, object]]:
122
- - The identifier of the selected polygon.
123
- - The corresponding polygon data (dictionary) containing its properties.
124
- """
125
-
126
- # Calculate the total weight (sum of areas of all polygons)
127
- max_weight = sum(pol['area'] for pol in polygon_arr.values())
128
-
129
- # Generate a random threshold between 0 and the total weight
130
- threshold = random.uniform(0, max_weight)
131
- cumulative_weight = 0
132
-
133
- # Iterate through the polygons, accumulating weights
134
- for item, pol in polygon_arr.items():
135
- weight = pol['area']
136
- cumulative_weight += weight
137
-
138
- # Return the polygon when the cumulative weight surpasses the threshold
139
- if cumulative_weight >= threshold:
140
- return item, pol
141
-
142
- def get_location_and_direction(
143
- polygon_arr: Dict[str, Dict[str, object]],
144
- thickness: float,
145
- angle: float,
146
- nucleation_point: Tuple[float, float] = None,
147
- min_distance: float = 0,
148
- max_attempts: int = 1000
149
- ) -> Union[Tuple[str, Dict[str, object], Tuple[float, float], np.ndarray, np.ndarray], bool]:
150
- """
151
- Attempts to find a valid location and direction within a polygon for placing a new segment. The direction can either be randomly
152
- chosen (uniformly) or from a specified list of angles. It ensures that the segment lies within the polygon's bounds given the
153
- specified thickness.
154
-
155
- Args:
156
- polygon_arr (Dict[str, Dict[str, object]]):
157
- A dictionary where the keys are polygon identifiers and the values are dictionaries containing polygon properties, including 'vertices'.
158
- thickness (float):
159
- The thickness of the segment that needs to fit inside the polygon.
160
- max_attempts (int, optional):
161
- The maximum number of attempts to find a valid location and direction. Defaults to 1000.
162
- angle (float):
163
- A float indicating the angle of the new segment.
164
- nucleation_point (Tuple[float, float], optional):
165
- predified nucleation point for the segment. Defaults to None.
166
- min_distance (float, optional):
167
- the minimum distance between two lines. Defaults to 0.
168
-
169
- Returns:
170
- Union[Tuple[str, Dict[str, object], Tuple[float, float], np.ndarray, np.ndarray], bool]:
171
- - If a valid location and direction are found, returns a tuple containing:
172
- - The polygon ID (`str`).
173
- - The polygon data (`Dict[str, object]`).
174
- - The new location as a tuple of floats (`Tuple[float, float]`).
175
- - The direction vector as a numpy array (`np.ndarray`).
176
- - The perpendicular vector to the direction as a numpy array (`np.ndarray`).
177
- - The nucleation point [x,y] of the segment
178
- - The angle of the segment.
179
- - Returns `False` if no valid location and direction are found after the maximum attempts.
180
- """
181
- direction = (np.cos(angle), np.sin(angle))
182
- direction = np.array(direction) / np.linalg.norm(direction)
183
-
184
- # Try to find a valid location and direction up to max_attempts
185
- attempt = 0
186
- while attempt < max_attempts:
187
- polygon_id, polygon = pick_item_with_probability(polygon_arr)
188
-
189
- # Sample a location within the polygon
190
- #check if nucleation point is given
191
- if nucleation_point is not None:
192
- location_new = nucleation_point
193
- else:
194
- location_new = sample_in_polygon(polygon['vertices'])
195
-
196
- # Compute the perpendicular vector to the direction
197
- perpendicular = np.array([direction[1], -direction[0]])
198
- perpendicular = perpendicular / np.linalg.norm(perpendicular)
199
-
200
- # Ensure the perpendicular vector is oriented consistently (y-component is non-negative)
201
- if perpendicular[1] < 0:
202
- perpendicular = -perpendicular
203
-
204
- # Compute the positions for the segment with thickness, shifted by half-thickness along the perpendicular direction
205
- p1 = np.array(location_new) + (thickness/2 + min_distance) * perpendicular
206
- p2 = np.array(location_new) - (thickness/2 + min_distance) * perpendicular
207
-
208
- # Check if both endpoints of the segment are inside the polygon
209
- if is_inside_polygon(polygon['vertices'], p1) and is_inside_polygon(polygon['vertices'], p2):
210
- return polygon_id, polygon, location_new, direction, perpendicular, angle
211
-
212
- attempt += 1
213
-
214
- # If no valid location and direction is found, return False
215
- return False
216
-
217
- 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):
218
- # Extract vertices and cycle (faces) of the original polygon
219
- vertices = polygon_arr[polygon_id]['vertices']
220
- cycle = polygon_arr[polygon_id]['faces']
221
-
222
- # Get first cycle and vertices
223
- index_start_1, index_end_1 = (cycle.index(neighbor1_1), cycle.index(neighbor1_2))
224
- if index_start_1 < index_end_1:
225
- cycle1 = [segment_new_id_1] + cycle[index_start_1:index_end_1+1]
226
- vertices1 = [vertex_begin_1] + vertices[index_start_1:index_end_1] + [vertex_end_1]
227
- else:
228
- cycle1 = [segment_new_id_1] + cycle[index_start_1:] + cycle[:index_end_1+1]
229
- vertices1 = [vertex_begin_1] + vertices[index_start_1:] + vertices[:index_end_1] + [vertex_end_1]
230
-
231
- # Get second cycle and vertices
232
- index_start_2, index_end_2 = (cycle.index(neighbor2_2), cycle.index(neighbor2_1))
233
- if index_start_2 < index_end_2:
234
- cycle2 = [segment_new_id_2] + cycle[index_start_2:index_end_2+1]
235
- vertices2 = [vertex_end_2] + vertices[index_start_2:index_end_2] + [vertex_begin_2]
236
- else:
237
- cycle2 = [segment_new_id_2] + cycle[index_start_2:] + cycle[:index_end_2+1]
238
- vertices2 = [vertex_end_2] + vertices[index_start_2:] + vertices[:index_end_2] + [vertex_begin_2]
239
-
240
- # Get middle cycle and vertices
241
- cycle0 = [neighbor1_1, segment_new_id_1, neighbor1_2]
242
- vertices0 = [vertex_begin_1, vertex_end_1]
243
-
244
- index_start_0, index_end_0 = (cycle.index(neighbor1_2), cycle.index(neighbor2_2))
245
- if index_start_0 < index_end_0:
246
- cycle0 = cycle0 + cycle[index_start_0:index_end_0+1]
247
- vertices0 = vertices0 + vertices[index_start_0:index_end_0]
248
-
249
- elif index_start_0 > index_end_0:
250
- cycle0 = cycle0 + cycle[index_start_0:] + cycle[:index_end_0+1]
251
- vertices0 = vertices0 + vertices[index_start_0:] + vertices[:index_end_0]
252
-
253
- cycle0 = cycle0 + [segment_new_id_2]
254
- vertices0 = vertices0 + [vertex_end_2] + [vertex_begin_2]
255
-
256
- index_start_0, index_end_0 = (cycle.index(neighbor2_1), cycle.index(neighbor1_1))
257
- if index_start_0 < index_end_0:
258
- cycle0 = cycle0 + cycle[index_start_0:index_end_0+1]
259
- vertices0 = vertices0 + vertices[index_start_0:index_end_0]
260
-
261
- elif index_start_0 > index_end_0:
262
- cycle0 = cycle0 + cycle[index_start_0:] + cycle[:index_end_0+1]
263
- vertices0 = vertices0 + vertices[index_start_0:] + vertices[:index_end_0]
264
-
265
- return cycle0, vertices0, cycle1, vertices1, cycle2, vertices2
266
-
267
- def get_new_segment(
268
- line_segments_to_check: List[LineSegment],
269
- location: Tuple[float, float],
270
- direction: Tuple[float, float],
271
- id: Optional[int] = None,
272
- box_size: float = 1
273
- ) -> LineSegment:
274
- """
275
- Creates a new line segment by extending a given location in a specified direction and
276
- determines its neighbors by checking intersections with other line segments.
277
-
278
- Args:
279
- line_segments_to_check (List[LineSegment]): List of existing line segments to check for intersections.
280
- location (Tuple[float, float]): The starting point (x, y) for the new line segment.
281
- direction (Tuple[float, float]): The direction vector in which to extend the line segment.
282
- id (Optional[int]): Optional ID for the new line segment. If not provided, defaults to None.
283
- box_size(optional[Int]]): The size of the box. Defaults to 1.
284
-
285
- Returns:
286
- LineSegment: A new line segment object with its neighbors based on intersections.
287
- """
288
-
289
- # Create a temporary line segment extending from the location in both directions
290
- s_temp = LineSegment(start=np.array(location) - 10*np.sqrt(2)*box_size * np.array(direction), end=np.array(location) + 10*np.sqrt(2)*box_size * np.array(direction))
291
-
292
- intersection_points = []
293
-
294
- # Check for intersections with existing line segments
295
- for segment in line_segments_to_check:
296
- intersect, (intersect_x, intersect_y) = doSegmentsIntersect(s_temp, segment, box_size)
297
-
298
- if intersect:
299
- segment_length = math.sqrt(
300
- (location[0] - intersect_x) ** 2
301
- + (location[1] - intersect_y) ** 2
302
- )
303
- intersection_points.append(
304
- {"id": segment.id, "point": (intersect_x, intersect_y), "segment_length": segment_length}
305
- )
306
-
307
- # Divide intersections into ones behind and in front of the new line
308
- intersections_b = [intersection for intersection in intersection_points if intersection["point"][0] < location[0]]
309
- intersections_f = [intersection for intersection in intersection_points if intersection["point"][0] > location[0]]
310
-
311
- if not intersections_b or not intersections_f:
312
- intersections_b = [intersection for intersection in intersection_points if intersection["point"][1] < location[1]]
313
- intersections_f = [intersection for intersection in intersection_points if intersection["point"][1] > location[1]]
314
-
315
- # Determine the closest intersections for segment start and end
316
- s_start = min(intersections_b, key=lambda x: x["segment_length"])
317
- s_end = min(intersections_f, key=lambda x: x["segment_length"])
318
- start, end = s_start['point'], s_end['point']
319
- start_id, end_id = s_start['id'], s_end['id']
320
-
321
- # Ensure the start comes before the end
322
- if start[0] > end[0]:
323
- start, end = end, start
324
- start_id, end_id = end_id, start_id
325
-
326
- # Create a new line segment and assign neighbors
327
- neighbors_initial = {start_id: start, end_id: end}
328
- segment_new = LineSegment(start=start, end=end, id=id, neighbors_initial=neighbors_initial, neighbors=neighbors_initial)
329
-
330
- return segment_new
331
-
332
- def update_data(
333
- segments_dict: Dict[int, LineSegment],
334
- polygon_arr: Dict[str, Dict[str, object]],
335
- polygon_id: str,
336
- segment_thickness_dict: Dict[int, Polygon],
337
- vertices0: List[Tuple[float, float]],
338
- vertices1: List[Tuple[float, float]],
339
- vertices2: List[Tuple[float, float]],
340
- cycle0: List[int],
341
- cycle1: List[int],
342
- cycle2: List[int],
343
- neighbor1_1: int,
344
- neighbor1_2: int,
345
- neighbor2_1: int,
346
- neighbor2_2: int,
347
- vertex_begin_1: Tuple[float, float],
348
- vertex_end_1: Tuple[float, float],
349
- vertex_begin_2: Tuple[float, float],
350
- vertex_end_2: Tuple[float, float],
351
- id_1: int,
352
- id_2: int
353
- ) -> Tuple[Dict[int, LineSegment], Dict[str, Dict[str, object]], Dict[int, Polygon]]:
354
- """
355
- Updates the segments, polygons, and segment thickness dictionaries by adding new data derived
356
- from provided vertices and neighbor information.
357
-
358
- Args:
359
- segments_dict (Dict[int, LineSegment]): A dictionary of segments with segment ID as the key.
360
- polygon_arr (Dict[str, Dict[str, object]]): A dictionary of polygons with polygon ID as the key.
361
- polygon_id (str): The ID of the polygon being updated.
362
- segment_thickness_dict (Dict[int, Polygon]): A dictionary mapping thickness information to polygon objects.
363
- vertices0 (List[Tuple[float, float]]): Vertices of the base polygon.
364
- vertices1 (List[Tuple[float, float]]): Vertices of the first new polygon.
365
- vertices2 (List[Tuple[float, float]]): Vertices of the second new polygon.
366
- cycle0 (List[int]): List of face indices for the base polygon.
367
- cycle1 (List[int]): List of face indices for the first new polygon.
368
- cycle2 (List[int]): List of face indices for the second new polygon.
369
- neighbor1_1 (int): ID of the first neighbor of the first segment.
370
- neighbor1_2 (int): ID of the second neighbor of the first segment.
371
- neighbor2_1 (int): ID of the first neighbor of the second segment.
372
- neighbor2_2 (int): ID of the second neighbor of the second segment.
373
- vertex_begin_1 (Tuple[float, float]): Starting vertex of the first segment.
374
- vertex_end_1 (Tuple[float, float]): Ending vertex of the first segment.
375
- vertex_begin_2 (Tuple[float, float]): Starting vertex of the second segment.
376
- vertex_end_2 (Tuple[float, float]): Ending vertex of the second segment.
377
- id_1 (int): ID of the first new segment.
378
- id_2 (int): ID of the second new segment.
379
-
380
- Returns:
381
- Tuple[Dict[int, LineSegment], Dict[str, Dict[str, object]], Dict[int, Polygon]]:
382
- - Updated dictionary of line segments.
383
- - Updated dictionary of polygons.
384
- - Updated dictionary of segment thickness.
385
- """
386
-
387
- # Update polygon_arr (a dictionary of polygons)
388
- polygon_new_1 = {
389
- f'p{len(polygon_arr) + 1}': {
390
- 'vertices': vertices1,
391
- 'area': Polygon(vertices=vertices1).area(),
392
- 'faces': cycle1
393
- }
394
- }
395
- polygon_new_2 = {
396
- polygon_id: {
397
- 'vertices': vertices2,
398
- 'area': Polygon(vertices=vertices2).area(),
399
- 'faces': cycle2
400
- }
401
- }
402
- polygon_arr.update(polygon_new_1)
403
- polygon_arr.update(polygon_new_2)
404
-
405
- # Update the segments_dict for the first segment
406
- neighbors_initial_1 = {
407
- neighbor1_1: vertex_begin_1,
408
- neighbor1_2: vertex_end_1
409
- }
410
- segment_new_1 = LineSegment(
411
- start=vertex_begin_1,
412
- end=vertex_end_1,
413
- id=id_1,
414
- neighbors_initial=neighbors_initial_1,
415
- neighbors=neighbors_initial_1
416
- )
417
- segments_dict[segment_new_1.id] = segment_new_1
418
- segments_dict[neighbor1_1].neighbors[id_1] = vertex_begin_1
419
- segments_dict[neighbor1_2].neighbors[id_1] = vertex_end_1
420
-
421
- # Update the segments_dict for the second segment
422
- neighbors_initial_2 = {
423
- neighbor2_1: vertex_begin_2,
424
- neighbor2_2: vertex_end_2
425
- }
426
- segment_new_2 = LineSegment(
427
- start=vertex_begin_2,
428
- end=vertex_end_2,
429
- id=id_2,
430
- neighbors_initial=neighbors_initial_2,
431
- neighbors=neighbors_initial_2
432
- )
433
- segments_dict[segment_new_2.id] = segment_new_2
434
- segments_dict[neighbor2_1].neighbors[id_2] = vertex_begin_2
435
- segments_dict[neighbor2_2].neighbors[id_2] = vertex_end_2
436
-
437
- # Update the segment_thickness_dict with the base polygon
438
- segment_thickness_dict[len(segment_thickness_dict) + 1] = Polygon(vertices=vertices0)
439
-
440
- return segments_dict, polygon_arr, segment_thickness_dict
441
-
442
- def add_line_segment(
443
- segments_dict: Dict[int, LineSegment],
444
- polygon_arr: Dict[str, Dict[str, object]],
445
- segment_thickness_dict: Dict[int, Polygon],
446
- angle: float,
447
- thickness: float = 0,
448
- nucleation_point: Tuple[float, float] = None,
449
- min_distance: float = 0,
450
- box_size: float = 1,
451
- max_attempts: int = 1000
452
- ) -> Union[Tuple[Dict[int, LineSegment], Dict[str, Dict[str, object]], Dict[int, Polygon], List[float], float], bool]:
453
- """
454
- Adds a new line segment to the segments and polygon data structures, with a given thickness and angle distribution.
455
-
456
- Args:
457
- segments_dict (Dict[int, LineSegment]): A dictionary containing the current line segments.
458
- polygon_arr (Dict[str, Dict[str, object]]): A dictionary containing the current polygons and their properties.
459
- segment_thickness_dict (Dict[int, Polygon]): A dictionary storing the thickness information mapped to polygons.
460
- thickness (float): The thickness of the new segment to be added. Defaults to 0.
461
- angles (str): The angle distribution method. Defaults to 'uniform'.
462
- nucleation_point (Tuple[float, float]): A predefined nucleation point for the new segment. Defaults to None.
463
- min_distance (float): The minimum distance between two lines. Defaults to 0.
464
- box_size (float): The size of the box. Defaults to 1.
465
- max_attempts (int): The maximum number of attempts to find a valid location and direction. Defaults to 1000.
466
-
467
- Returns:
468
- Union[Tuple[Dict[int, LineSegment], Dict[str, Dict[str, object]], Dict[int, Polygon]], List[float], float, bool]:
469
- - A tuple containing the updated segments dictionary, polygon dictionary, and thickness dictionary,
470
- or False if no valid location for the new segment is found.
471
- -nucleation point in a list [x,y] and the angle of the segment in radians.
472
- """
473
-
474
- # Get a valid location and direction, or return False if none is found
475
- loc = get_location_and_direction(polygon_arr, angle=angle, thickness=thickness, nucleation_point=nucleation_point, min_distance=min_distance, max_attempts=max_attempts)
476
- if loc:
477
- polygon_id, polygon, location_new, direction_new, perpendicular, angle_new = loc
478
- else:
479
- print('No valid location found')
480
- return False
481
-
482
- # Get the borders of the new segment with the given thickness
483
- line_segments_to_check = [segments_dict[segment] for segment in polygon['faces']]
484
- middle_segment = get_new_segment(line_segments_to_check, location=location_new, direction=direction_new, box_size=box_size)
485
- s1 = get_new_segment(line_segments_to_check, location=np.array(location_new) + thickness * perpendicular / 2, direction=direction_new,box_size=box_size)
486
- s2 = get_new_segment(line_segments_to_check, location=np.array(location_new) - thickness * perpendicular / 2, direction=direction_new, box_size=box_size)
487
-
488
- # Extract neighbor information and segment vertices
489
- neighbor1_1, neighbor1_2 = list(s1.neighbors.keys())
490
- vertex_begin_1, vertex_end_1 = list(s1.neighbors.values())
491
- neighbor2_1, neighbor2_2 = list(s2.neighbors.keys())
492
- vertex_begin_2, vertex_end_2 = list(s2.neighbors.values())
493
- id_1 = str(int((len(segments_dict.keys()) - 2) / 2)) + '_1'
494
- id_2 = str(int((len(segments_dict.keys()) - 2) / 2)) + '_2'
495
-
496
- # Get the resulting polygons after splitting
497
- cycle0, vertices0, cycle1, vertices1, cycle2, vertices2 = get_polygons(
498
- polygon_id,
499
- polygon_arr,
500
- neighbor1_1,
501
- neighbor1_2,
502
- vertex_begin_1,
503
- vertex_end_1,
504
- neighbor2_1,
505
- neighbor2_2,
506
- vertex_begin_2=vertex_begin_2,
507
- vertex_end_2=vertex_end_2,
508
- segment_new_id_1=id_1,
509
- segment_new_id_2=id_2
510
- )
511
-
512
- # Update all relevant data structures
513
- segments_dict, polygon_arr, segment_thickness_dict = update_data(
514
- segments_dict,
515
- polygon_arr,
516
- polygon_id,
517
- segment_thickness_dict,
518
- vertices0,
519
- vertices1,
520
- vertices2,
521
- cycle0,
522
- cycle1,
523
- cycle2,
524
- neighbor1_1,
525
- neighbor1_2,
526
- neighbor2_1,
527
- neighbor2_2,
528
- vertex_begin_1,
529
- vertex_end_1,
530
- vertex_begin_2,
531
- vertex_end_2,
532
- id_1,
533
- id_2
534
- )
535
-
536
- # Associate the middle segment with the newly created thickness entry
537
- segment_thickness_dict[list(segment_thickness_dict.keys())[-1]].middle_segment = middle_segment
538
-
539
- return segments_dict, polygon_arr, segment_thickness_dict, location_new, angle_new
540
-
541
- def generate_line_segments_thickness(
542
- size: int,
543
- thickness_arr: List[float],
544
- angles: str = 'uniform',
545
- config: List[List[float]] = None,
546
- epsilon: float = 0,
547
- box_size: float = 1
548
- ) -> Tuple[Dict[str, LineSegment], Dict[str, Dict[str, object]], Dict[int, Polygon], np.ndarray]:
549
- """
550
- Generates a specified number of line segments and updates the polygon and segment thickness dictionaries.
551
-
552
- Args:
553
- size (int): The number of line segments to generate.
554
- thickness_arr (List[float]): A list containing the thickness values for each segment to be generated.
555
- angles (str): Angle used in the generation of the segments.
556
- config (List[List[float]]): A list of configurations for the nucleation points and angles.
557
- epsilon (float): the minimum distance between two line.
558
- box_size (float): the size of the box.
559
-
560
- Returns:
561
- Tuple[Dict[str, LineSegment], Dict[str, Dict[str, object]], Dict[int, Polygon]]:
562
- - Updated dictionary of line segments.
563
- - Updated dictionary of polygons.
564
- - Updated dictionary of segment thicknesses.
565
- - Array of the nucleation points and angles [x,y,theta].
566
- """
567
-
568
- # Initialize border segments for a square and its polygon representation
569
- borders = [
570
- LineSegment((box_size, 0), (0, 0), id='b1', neighbors_initial={'b2': (0, 0), 'b4': (box_size, 0)}, neighbors={'b2': (0, 0), 'b4': (box_size, 0)}),
571
- LineSegment((0, box_size), (0, 0), id='b2', neighbors_initial={'b1': (0, 0), 'b3': (0, box_size)}, neighbors={'b1': (0, 0), 'b3': (0, box_size)}),
572
- LineSegment((0, box_size), (box_size, box_size), id='b3', neighbors_initial={'b2': (0, box_size), 'b4': (box_size, box_size)}, neighbors={'b2': (0, box_size), 'b4': (box_size, box_size)}),
573
- LineSegment((box_size, box_size), (box_size, 0), id='b4', neighbors_initial={'b1': (box_size, 0), 'b3': (box_size, box_size)}, neighbors={'b1': (box_size, 0), 'b3': (box_size, box_size)})
574
- ]
575
-
576
- polygon_arr = {
577
- 'p1': {
578
- 'vertices': [(0, 0), (0, box_size), (box_size, box_size), (box_size, 0)],
579
- 'area': box_size**2,
580
- 'faces': ['b1', 'b2', 'b3', 'b4']
581
- }
582
- }
583
-
584
- segments = borders
585
- segments_dict = {segment.id: segment for segment in segments}
586
- segment_thickness_dict = {}
587
- generated_config = []
588
-
589
- if config is not None and size > len(config):
590
- print("The size of the configuration is smaller than the size of the segments. Generated a network of the same size as the configuration.")
591
- size = len(config)
592
-
593
- jammed = False
594
- for i in range(size):
595
- if config:
596
- nucleation_point = config[i]['location']
597
- angles = [config[i]['angle']]
598
- else:
599
- nucleation_point = None
600
- # if angles != 'uniform':
601
- # angles=[angles[i]]
602
-
603
- output = add_line_segment(segments_dict,
604
- polygon_arr,
605
- segment_thickness_dict,
606
- thickness=thickness_arr[i],
607
- min_distance = epsilon,
608
- nucleation_point = nucleation_point,
609
- angle=angles[i],
610
- box_size=box_size)
611
- if output:
612
- segments_dict, polygon_arr, segment_thickness_dict, location, angle = output
613
- generated_config.append({ 'location': location, 'angle': angle, 'thickness': thickness_arr[i] })
614
-
615
- else:
616
- if config:
617
- print('Configuration not possible. Point is skipped.')
618
- else:
619
- print(f"Stopped at iteration {len(segment_thickness_dict)}, could not find a valid segment position.")
620
- jammed = True
621
- break
622
-
623
- # Uncomment the following line if you want progress feedback
624
- percentage = np.round(i / size * 100, 3)
625
- print(f'generate_segments: {percentage}% done', end='\r')
626
-
627
- data_dict = {'segments_dict': segments_dict,
628
- 'polygon_arr': polygon_arr,
629
- 'segment_thickness_dict': segment_thickness_dict,
630
- 'jammed': jammed,
631
- 'generated_config': generated_config}
632
-
633
- return data_dict