FiberFusing 1.9.2__tar.gz → 1.9.4__tar.gz

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.
Files changed (116) hide show
  1. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/__init__.py +1 -0
  2. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/_version.py +3 -3
  3. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/generic_fiber.py +9 -38
  4. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/loader.py +0 -81
  5. fiberfusing-1.9.4/FiberFusing/geometries/__init__.py +13 -0
  6. fiberfusing-1.9.4/FiberFusing/geometries/base_class.py +173 -0
  7. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/geometries/linestring.py +70 -21
  8. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/geometries/point.py +56 -22
  9. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/geometries/polygon.py +273 -9
  10. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/geometries/utils.py +9 -9
  11. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/geometry.py +5 -0
  12. fiberfusing-1.9.4/FiberFusing/graded_index.py +16 -0
  13. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/optical_structure.py +3 -9
  14. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/profile.py +12 -17
  15. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/shapes/ellipse.py +0 -1
  16. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing.egg-info/PKG-INFO +2 -2
  17. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing.egg-info/SOURCES.txt +1 -0
  18. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing.egg-info/requires.txt +1 -1
  19. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/PKG-INFO +2 -2
  20. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/examples/extra/custom_graded_index_fiber.py +8 -4
  21. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/examples/extra/randomize_core.py +1 -2
  22. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/examples/extra/structure_shift.py +1 -2
  23. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/examples/geometry/plot_line_3.py +1 -2
  24. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/examples/geometry/plot_line_4.py +1 -2
  25. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/examples/geometry/plot_line_5.py +1 -2
  26. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/examples/geometry/plot_ring_10.py +1 -2
  27. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/examples/geometry/plot_ring_2.py +1 -2
  28. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/examples/geometry/plot_ring_3.py +1 -2
  29. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/examples/geometry/plot_ring_4.py +1 -2
  30. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/examples/geometry/plot_ring_5.py +1 -2
  31. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/examples/geometry/plot_ring_7.py +1 -2
  32. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/pyproject.toml +1 -1
  33. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/tests/test_boundaries.py +1 -2
  34. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/tests/test_fiber.py +8 -4
  35. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/tests/test_fused_structure.py +5 -10
  36. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/tests/test_geometries.py +4 -8
  37. fiberfusing-1.9.2/FiberFusing/geometries/__init__.py +0 -3
  38. fiberfusing-1.9.2/FiberFusing/geometries/base_class.py +0 -442
  39. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/.flake8 +0 -0
  40. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/.github/dependabot.yml +0 -0
  41. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/.github/workflows/deploy_PyPi.yml +0 -0
  42. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/.github/workflows/deploy_anaconda.yml +0 -0
  43. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/.github/workflows/deploy_coverage.yml +0 -0
  44. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/.github/workflows/deploy_documentation.yml +0 -0
  45. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/.gitignore +0 -0
  46. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/background.py +0 -0
  47. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/connection/__init__.py +0 -0
  48. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/connection/connection.py +0 -0
  49. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/connection/connection_optimization.py +0 -0
  50. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/connection/utils.py +0 -0
  51. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/coordinate_system.py +0 -0
  52. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/directories.py +0 -0
  53. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/__init__.py +0 -0
  54. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/fiber_files/1550BHP.yaml +0 -0
  55. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/fiber_files/DCF13.yaml +0 -0
  56. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/fiber_files/DCF1300S_20.yaml +0 -0
  57. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/fiber_files/DCF1300S_26.yaml +0 -0
  58. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/fiber_files/DCF1300S_33.yaml +0 -0
  59. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/fiber_files/DCF1300S_42.yaml +0 -0
  60. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/fiber_files/F2028M12.yaml +0 -0
  61. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/fiber_files/F2028M21.yaml +0 -0
  62. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/fiber_files/F2028M24.yaml +0 -0
  63. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/fiber_files/F2058G1.yaml +0 -0
  64. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/fiber_files/F2058L1.yaml +0 -0
  65. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/fiber_files/HI1060.yaml +0 -0
  66. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/fiber_files/HP630.yaml +0 -0
  67. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/fiber_files/SM1950.yaml +0 -0
  68. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/fiber_files/SMF28.yaml +0 -0
  69. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/fiber_files/fluorine_doped_1%_capillary.yaml +0 -0
  70. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/fiber_files/fluorine_doped_2%_capillary.yaml +0 -0
  71. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/fiber_files/test_fiber.yaml +0 -0
  72. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/fiber/fiber_files/test_multimode_fiber.yaml +0 -0
  73. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/helper.py +0 -0
  74. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/plottings.py +0 -0
  75. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/shapes/__init__.py +0 -0
  76. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/shapes/base.py +0 -0
  77. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/shapes/circle.py +0 -0
  78. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/shapes/square.py +0 -0
  79. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/structures.py +0 -0
  80. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing/utils.py +0 -0
  81. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing.egg-info/dependency_links.txt +0 -0
  82. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/FiberFusing.egg-info/top_level.txt +0 -0
  83. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/LICENSE +0 -0
  84. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/README.rst +0 -0
  85. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/Makefile +0 -0
  86. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/examples/README.rst +0 -0
  87. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/examples/extra/README.rst +0 -0
  88. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/examples/extra/custom_step_index_fiber.py +0 -0
  89. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/examples/extra/loading_fiber.py +0 -0
  90. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/examples/geometry/README.rst +0 -0
  91. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/examples/geometry/plot_single.py +0 -0
  92. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/images/example_3x3.png +0 -0
  93. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/images/logo.png +0 -0
  94. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/make.bat +0 -0
  95. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/source/_static/default.css +0 -0
  96. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/source/_static/thumbnail.png +0 -0
  97. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/source/code/components.rst +0 -0
  98. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/source/code/coordinate_system.rst +0 -0
  99. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/source/code/geometry.rst +0 -0
  100. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/source/code/shapes.rst +0 -0
  101. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/source/code/utils.rst +0 -0
  102. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/source/code.rst +0 -0
  103. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/source/conf.py +0 -0
  104. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/source/gallery/index.rst +0 -0
  105. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/source/index.rst +0 -0
  106. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/source/references.rst +0 -0
  107. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/source/sg_execution_times.rst +0 -0
  108. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/docs/source/theory.rst +0 -0
  109. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/meta.yaml +0 -0
  110. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/notebook.ipynb +0 -0
  111. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/setup.cfg +0 -0
  112. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/tests/__init__.py +0 -0
  113. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/tests/fiber_loader.py +0 -0
  114. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/tests/test_cooordinate_system.py +0 -0
  115. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/tests/test_generic_fiber.py +0 -0
  116. {fiberfusing-1.9.2 → fiberfusing-1.9.4}/tests/test_polygon.py +0 -0
@@ -5,6 +5,7 @@ from .geometries.polygon import Polygon, EmptyPolygon # noqa: F401
5
5
  from .shapes import Circle, Square # noqa: F401
6
6
  from .background import BackGround # noqa: F401
7
7
  from .optical_structure import CircleOpticalStructure # noqa: F401
8
+ from .graded_index import GradedIndex # noqa: F401
8
9
  micro = 1e-6
9
10
 
10
11
 
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '1.9.2'
32
- __version_tuple__ = version_tuple = (1, 9, 2)
31
+ __version__ = version = '1.9.4'
32
+ __version_tuple__ = version_tuple = (1, 9, 4)
33
33
 
34
- __commit_id__ = commit_id = 'gf65944ebc'
34
+ __commit_id__ = commit_id = 'g4851a65b0'
@@ -12,7 +12,7 @@ from FiberFusing.geometries.point import Point
12
12
  from FiberFusing.coordinate_system import CoordinateSystem
13
13
  from FiberFusing.plottings import plot_polygon
14
14
  from FiberFusing.helper import _plot_helper
15
-
15
+ from FiberFusing.graded_index import GradedIndex
16
16
 
17
17
  pp = pprint.PrettyPrinter(indent=4, sort_dicts=False, compact=True, width=1)
18
18
 
@@ -110,7 +110,7 @@ class GenericFiber():
110
110
 
111
111
  return fiber_copy
112
112
 
113
- def create_and_add_new_structure(self, refractive_index: float = None, NA: float = None, **kwargs) -> None:
113
+ def create_and_add_new_structure(self, refractive_index: float | GradedIndex = None, NA: float = None, **kwargs) -> None:
114
114
  """
115
115
  Adds a new circular structure to the collection.
116
116
 
@@ -136,32 +136,6 @@ class GenericFiber():
136
136
  setattr(self, new_structure.name, new_structure)
137
137
  self.structure_list.append(new_structure)
138
138
 
139
- def create_and_add_new_graded_index_structure(self, refractive_index_in: float, refractive_index_out: float, **kwargs) -> None:
140
- """
141
- Adds a new graded index structure to the collection.
142
-
143
- Parameters
144
- ----------
145
- refractive_index : float, optional
146
- The refractive index of the new structure. If provided, NA should be None.
147
- NA : float, optional
148
- The numerical aperture of the new structure. If provided, refractive_index should be None.
149
-
150
- Raises
151
- ------
152
- ValueError
153
- If both refractive_index and NA are provided or if neither is provided.
154
- """
155
- new_structure = CircleOpticalStructure(
156
- **kwargs,
157
- refractive_index_in=refractive_index_in,
158
- refractive_index_out=refractive_index_out,
159
- position=self.position
160
- )
161
- setattr(self, new_structure.name, new_structure)
162
- self.structure_list.append(new_structure)
163
-
164
-
165
139
  def _interpret_index_or_NA_to_index(self, refractive_index: float, NA: float) -> float:
166
140
  """
167
141
  Interprets and converts NA or index to a refractive index.
@@ -232,12 +206,11 @@ class GenericFiber():
232
206
  raster = structure.polygon.get_rasterized_mesh(coordinate_system=coordinate_system)
233
207
  mesh[numpy.where(raster != 0)] = 0
234
208
 
235
- if structure.is_graded:
209
+ if isinstance(structure.refractive_index, GradedIndex):
236
210
  refractive_index = self.get_graded_index_mesh(
237
211
  coordinate_system=coordinate_system,
238
212
  polygon=structure.polygon,
239
- min_index=structure.refractive_index_in,
240
- max_index=structure.refractive_index_out
213
+ refractive_index=structure.refractive_index,
241
214
  )
242
215
  else:
243
216
  refractive_index = structure.refractive_index
@@ -429,7 +402,7 @@ class GenericFiber():
429
402
 
430
403
  return distance
431
404
 
432
- def get_graded_index_mesh(self, coordinate_system: CoordinateSystem, polygon, min_index: float, max_index: float) -> numpy.ndarray:
405
+ def get_graded_index_mesh(self, coordinate_system: CoordinateSystem, polygon, refractive_index: GradedIndex) -> numpy.ndarray:
433
406
  """
434
407
  Compute the graded index mesh for a given polygon within the coordinate system.
435
408
 
@@ -443,10 +416,8 @@ class GenericFiber():
443
416
  The coordinate system defining the spatial grid where the index profile will be computed.
444
417
  polygon : Polygon
445
418
  The polygon object representing the area for which the graded index mesh is computed.
446
- min_index : float
447
- The minimum refractive index value, typically at the outer boundary of the polygon.
448
- max_index : float
449
- The maximum refractive index value, typically at the center of the polygon.
419
+ refractive_index : GradedIndex
420
+ The graded index object containing the minimum and maximum refractive index values.
450
421
 
451
422
  Returns
452
423
  -------
@@ -485,8 +456,8 @@ class GenericFiber():
485
456
  normalized_distance_mesh = masked_distance_mesh
486
457
 
487
458
  # Scale the normalized mesh to the index range [min_index, max_index]
488
- delta_n = max_index - min_index
489
- graded_index_mesh = normalized_distance_mesh * delta_n + min_index
459
+ delta_n = refractive_index.outside - refractive_index.inside
460
+ graded_index_mesh = normalized_distance_mesh * delta_n + refractive_index.inside
490
461
 
491
462
  return graded_index_mesh
492
463
 
@@ -235,84 +235,3 @@ class FiberLoader:
235
235
  processed_layers = self.reorder_layers_if_needed(processed_layers, order)
236
236
 
237
237
  return {'layers': processed_layers}
238
-
239
-
240
- # =============================================================================
241
- # CONVENIENCE FUNCTIONS FOR BACKWARD COMPATIBILITY
242
- # =============================================================================
243
-
244
- # Global loader instance
245
- _default_loader = FiberLoader()
246
-
247
-
248
- def load_fiber(fiber_name: str, clad_refractive_index: float, position: Tuple[float, float] = (0, 0), remove_cladding: bool = False) -> GenericFiber:
249
- """
250
- Convenience function to load a fiber using the default loader.
251
-
252
- Parameters
253
- ----------
254
- fiber_name : str
255
- The name of the fiber to load.
256
- clad_refractive_index : float
257
- The refractive index of the cladding material.
258
- position : Tuple[float, float], optional
259
- The spatial position of the fiber, defaulting to (0, 0).
260
- remove_cladding : bool, optional
261
- Whether to exclude the cladding layer from the fiber configuration.
262
-
263
- Returns
264
- -------
265
- GenericFiber
266
- A configured GenericFiber object with the specified properties.
267
- """
268
- return _default_loader.load_fiber(fiber_name, clad_refractive_index, position, remove_cladding)
269
-
270
-
271
- def make_fiber(structure_list: List[Dict], clad_refractive_index: float, position: Tuple[float, float] = (0, 0)) -> GenericFiber:
272
- """
273
- Convenience function to make a fiber using the default loader.
274
-
275
- Parameters
276
- ----------
277
- structure_list : List[Dict]
278
- A list of dictionaries, each containing the parameters for a fiber structure.
279
- clad_refractive_index : float
280
- The refractive index of the cladding material.
281
- position : Tuple[float, float], optional
282
- The spatial position of the fiber.
283
-
284
- Returns
285
- -------
286
- GenericFiber
287
- The newly created GenericFiber object populated with specified structures.
288
- """
289
- return _default_loader.make_fiber(structure_list, clad_refractive_index, position)
290
-
291
-
292
- def load_fiber_as_dict(fiber_name: str, clad_refractive_index: float = None, order: str = 'in-to-out') -> dict:
293
- """
294
- Convenience function to load fiber configuration as dictionary using the default loader.
295
-
296
- Parameters
297
- ----------
298
- fiber_name : str
299
- Name of the fiber file without extension.
300
- clad_refractive_index : float, optional
301
- Refractive index to use for material index calculation.
302
- order : str, optional
303
- Layer order in the output dictionary; 'in-to-out' or 'out-to-in' (for backward compatibility).
304
-
305
- Returns
306
- -------
307
- dict
308
- Dictionary containing the processed fiber configuration.
309
- """
310
- # Convert string to enum for backward compatibility
311
- if order == 'out-to-in':
312
- layer_order = LayerOrder.OUT_TO_IN
313
- else:
314
- layer_order = LayerOrder.IN_TO_OUT
315
-
316
- return _default_loader.load_fiber_as_dict(fiber_name, clad_refractive_index, layer_order)
317
-
318
- # -
@@ -0,0 +1,13 @@
1
+ from pydantic import ConfigDict
2
+
3
+ config_dict = ConfigDict(
4
+ extra='forbid',
5
+ arbitrary_types_allowed=True,
6
+ kw_only=True
7
+ )
8
+
9
+ from .base_class import Alteration # noqa: F401
10
+ from .point import Point # noqa: F401
11
+ from .linestring import LineString # noqa: F401
12
+ from .polygon import Polygon, EmptyPolygon # noqa: F401
13
+
@@ -0,0 +1,173 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ from typing import Tuple, Callable, Self
5
+ import copy
6
+ from shapely import affinity
7
+
8
+ import FiberFusing as ff
9
+
10
+
11
+ class Alteration:
12
+ def in_place_copy(function: Callable) -> Callable:
13
+ """
14
+ Decorator to manage in-place operations.
15
+
16
+ Parameters
17
+ ----------
18
+ function : Callable
19
+ The function to wrap.
20
+
21
+ Returns
22
+ -------
23
+ Callable
24
+ Wrapped function that optionally modifies the object in-place.
25
+ """
26
+ def wrapper(self, *args, in_place=False, **kwargs):
27
+ instance = self if in_place else self.copy()
28
+ return function(self, instance, *args, **kwargs)
29
+
30
+ return wrapper
31
+
32
+ def copy(self) -> Self:
33
+ """
34
+ Create a deep copy of the object.
35
+
36
+ Returns
37
+ -------
38
+ Alteration
39
+ A new instance that is a deep copy of the current object.
40
+ """
41
+ return copy.deepcopy(self)
42
+
43
+ def __repr__(self) -> str:
44
+ """
45
+ Return the string representation of the shapely object.
46
+
47
+ Returns
48
+ -------
49
+ str
50
+ The string representation of the shapely object.
51
+ """
52
+ return repr(self._shapely_object)
53
+
54
+ @property
55
+ def is_empty(self) -> bool:
56
+ """
57
+ Check if the shapely object is empty.
58
+
59
+ Returns
60
+ -------
61
+ bool
62
+ True if the object is empty, False otherwise.
63
+ """
64
+ return self._shapely_object.is_empty
65
+
66
+ @in_place_copy
67
+ def union(self, output, *others) -> 'Alteration':
68
+ """
69
+ Perform the union operation with other geometries.
70
+
71
+ Parameters
72
+ ----------
73
+ output : Alteration
74
+ The object to store the result.
75
+ *others : Alteration
76
+ Other geometries to union with.
77
+
78
+ Returns
79
+ -------
80
+ Alteration
81
+ The union of the geometries.
82
+ """
83
+ other_shapes = (o._shapely_object for o in others)
84
+ output._shapely_object = self._shapely_object.union(*other_shapes)
85
+ return output
86
+
87
+ @in_place_copy
88
+ def intersection(self, output, *others) -> Self:
89
+ """
90
+ Perform the intersection operation with other geometries.
91
+
92
+ Parameters
93
+ ----------
94
+ output : Alteration
95
+ The object to store the result.
96
+ *others : Alteration
97
+ Other geometries to intersect with.
98
+
99
+ Returns
100
+ -------
101
+ Alteration
102
+ The intersection of the geometries.
103
+ """
104
+ other_shapes = (o._shapely_object for o in others)
105
+ output._shapely_object = self._shapely_object.intersection(*other_shapes)
106
+ return output
107
+
108
+ @in_place_copy
109
+ def scale(self, output, factor: float, origin: Tuple[float, float] = (0, 0)) -> Self:
110
+ """
111
+ Scale the geometry by a given factor.
112
+
113
+ Parameters
114
+ ----------
115
+ output : Alteration
116
+ The object to store the result.
117
+ factor : float
118
+ The scaling factor.
119
+ origin : tuple of float, optional
120
+ The origin point for scaling, by default (0, 0).
121
+
122
+ Returns
123
+ -------
124
+ Alteration
125
+ The scaled geometry.
126
+ """
127
+ origin_point = ff.geometries.utils.interpret_to_point(origin)
128
+ output._shapely_object = affinity.scale(self._shapely_object, xfact=factor, yfact=factor, origin=origin_point._shapely_object)
129
+ return output
130
+
131
+ @in_place_copy
132
+ def translate(self, output, shift: Tuple[float, float]) -> Self:
133
+ """
134
+ Translate the geometry by a given shift.
135
+
136
+ Parameters
137
+ ----------
138
+ output : Alteration
139
+ The object to store the result.
140
+ shift : tuple of float
141
+ The (x, y) shift values.
142
+
143
+ Returns
144
+ -------
145
+ Alteration
146
+ The translated geometry.
147
+ """
148
+ shift_point = ff.geometries.utils.interpret_to_point(shift)
149
+ output._shapely_object = affinity.translate(self._shapely_object, shift_point.x, shift_point.y)
150
+ return output
151
+
152
+ @in_place_copy
153
+ def rotate(self, output, angle: float, origin: Tuple[float, float] = (0, 0)) -> Self:
154
+ """
155
+ Rotate the geometry by a specified angle around an origin.
156
+
157
+ Parameters
158
+ ----------
159
+ output : Alteration
160
+ The object to store the result.
161
+ angle : float
162
+ The rotation angle in degrees.
163
+ origin : tuple of float, optional
164
+ The origin point for rotation, by default (0, 0).
165
+
166
+ Returns
167
+ -------
168
+ Alteration
169
+ The rotated geometry.
170
+ """
171
+ origin_point = ff.geometries.utils.interpret_to_point(origin)
172
+ output._shapely_object = affinity.rotate(self._shapely_object, angle=angle, origin=origin_point._shapely_object)
173
+ return output
@@ -1,18 +1,17 @@
1
1
  #!/usr/bin/env python
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
- from typing import Optional, Tuple
4
+ from typing import Optional, Tuple, Self
5
5
  import numpy as np
6
6
  from pydantic.dataclasses import dataclass
7
7
  from dataclasses import field
8
- from pydantic import ConfigDict
9
8
  from shapely.affinity import scale
10
9
  import shapely.geometry as geo
11
- from FiberFusing.geometries.base_class import Alteration
12
- import FiberFusing as ff
13
10
 
11
+ from FiberFusing.geometries.base_class import Alteration
12
+ from FiberFusing import geometries
14
13
 
15
- @dataclass(config=ConfigDict(extra='forbid', arbitrary_types_allowed=True))
14
+ @dataclass(config=geometries.config_dict)
16
15
  class LineString(Alteration):
17
16
  coordinates: Optional[Tuple] = field(default=None, repr=False)
18
17
  instance: Optional[geo.LineString] = field(default=None, repr=False)
@@ -44,51 +43,92 @@ class LineString(Alteration):
44
43
  return self._shapely_object.centroid
45
44
 
46
45
  @property
47
- def mid_point(self) -> 'ff.Point':
46
+ def mid_point(self) -> 'geometries.Point':
48
47
  """ Returns the midpoint of the line string as a Shapely Point object. """
49
48
  P0, P1 = self.boundary
50
- return ff.Point(position=[(P0.x + P1.x) / 2, (P0.y + P1.y) / 2])
49
+ return geometries.Point(position=[(P0.x + P1.x) / 2, (P0.y + P1.y) / 2])
51
50
 
52
51
  @property
53
52
  def length(self) -> float:
54
53
  """ Returns the length of the line string. """
55
54
  return self._shapely_object.length
56
55
 
57
- def intersect(self, other: 'LineString') -> None:
58
- """ Intersects this line string with another, updating the shapely object in place. """
56
+ def intersect(self, other: Self) -> None:
57
+ """
58
+ Intersects this line string with another, updating the shapely object in place.
59
+
60
+ Parameters
61
+ ----------
62
+ other : LineString
63
+ The other line string to intersect with.
64
+
65
+ """
59
66
  self._shapely_object = self._shapely_object.intersection(other._shapely_object)
60
67
 
61
- def get_perpendicular(self) -> 'LineString':
68
+ def get_perpendicular(self) -> Self:
62
69
  """ Returns a new LineString object that is perpendicular to this one. """
63
70
  mid = self.mid_point
64
71
  p0, p1 = self.boundary
65
72
  dx, dy = p1.x - p0.x, p1.y - p0.y
66
- new_coords = ff.Point(position=(mid.x - dy, mid.y + dx)), ff.Point(position=(mid.x + dy, mid.y - dx))
73
+ new_coords = geometries.Point(position=(mid.x - dy, mid.y + dx)), geometries.Point(position=(mid.x + dy, mid.y - dx))
67
74
  return LineString(coordinates=new_coords)
68
75
 
69
- def get_position_parametrization(self, t: float) -> 'ff.Point':
70
- """ Returns the point at parameter t along the line. 0 <= t <= 1. """
76
+ def get_position_parametrization(self, t: float) -> 'geometries.Point':
77
+ """
78
+ Returns the point at parameter t along the line. 0 <= t <= 1.
79
+
80
+ Parameters
81
+ ----------
82
+ t : float
83
+ The parameter along the line, where 0 <= t <= 1.
84
+
85
+ Returns
86
+ -------
87
+ geometries.Point
88
+ The point at parameter t along the line.
89
+ """
71
90
  p0, p1 = self.boundary
72
91
  x = p0.x * (1 - t) + p1.x * t
73
92
  y = p0.y * (1 - t) + p1.y * t
74
- return ff.Point(position=(x, y))
93
+ return geometries.Point(position=(x, y))
75
94
 
76
95
  def render_on_axis(self, ax, **kwargs) -> None:
77
- """ Renders the line string on a given matplotlib axis. """
96
+ """
97
+ Renders the line string on a given matplotlib axis.
98
+
99
+ Parameters
100
+ ----------
101
+ ax : matplotlib.axes.Axes
102
+ The axes to render the line string on.
103
+ **kwargs : keyword arguments
104
+ Additional keyword arguments to pass to the plot function.
105
+ """
78
106
  x, y = self._shapely_object.xy
79
107
  ax.plot(x, y, **kwargs)
80
108
 
81
- def make_length(self, length: float) -> 'LineString':
109
+ def make_length(self, length: float) -> Self:
82
110
  """ Returns a new LineString scaled to the specified length. """
83
111
  return self.extend(factor=length / self.length)
84
112
 
85
- def centering(self, center: geo.Point) -> 'LineString':
86
- """ Centers the line string at a given point. """
113
+ def centering(self, center: geo.Point) -> Self:
114
+ """
115
+ Centers the line string at a given point.
116
+
117
+ Parameters
118
+ ----------
119
+ center : geo.Point
120
+ The point to center the line string around.
121
+
122
+ Returns
123
+ -------
124
+ LineString
125
+ A new LineString centered at the specified point.
126
+ """
87
127
  p0, p1 = self.boundary
88
128
  mid = self.mid_point
89
129
  dx, dy = center.x - mid.x, center.y - mid.y
90
130
  new_coords = [(p.x + dx, p.y + dy) for p in [p0, p1]]
91
- new_coords = ff.Point(position=new_coords[0]), ff.Point(position=new_coords[1])
131
+ new_coords = geometries.Point(position=new_coords[0]), geometries.Point(position=new_coords[1])
92
132
  return LineString(coordinates=tuple(new_coords))
93
133
 
94
134
  def get_vector(self) -> np.ndarray:
@@ -98,8 +138,17 @@ class LineString(Alteration):
98
138
  norm = np.sqrt(dx**2 + dy**2)
99
139
  return np.array([dx, dy]) / norm if norm != 0 else np.array([0, 0])
100
140
 
101
- def extend(self, factor: float = 1) -> 'LineString':
102
- """ Returns a new LineString scaled by the specified factor. """
141
+ def extend(self, factor: float = 1) -> Self:
142
+ """
143
+ Returns a new LineString scaled by the specified factor.
144
+
145
+ Parameters
146
+ ----------
147
+ factor : float
148
+ The scaling factor to apply to the line string.
149
+
150
+ Returns
151
+ """
103
152
  scaled_string = scale(self._shapely_object, xfact=factor, yfact=factor, origin='center')
104
153
  return LineString(instance=scaled_string)
105
154
 
@@ -2,19 +2,17 @@
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
4
  # Built-in imports
5
- from typing import Optional, Tuple
5
+ from typing import Optional, Tuple, Self
6
6
  import numpy
7
7
  from pydantic.dataclasses import dataclass
8
- from pydantic import ConfigDict
9
- from FiberFusing.geometries.base_class import Alteration
10
8
  import shapely.geometry as geo
11
9
  import matplotlib.pyplot as plt
12
- import FiberFusing as ff
13
- from FiberFusing.helper import _plot_helper
14
10
 
11
+ from FiberFusing.helper import _plot_helper
12
+ from FiberFusing import geometries
15
13
 
16
- @dataclass(config=ConfigDict(extra='forbid', arbitrary_types_allowed=True))
17
- class Point(Alteration):
14
+ @dataclass(config=geometries.config_dict)
15
+ class Point(geometries.base_class.Alteration):
18
16
  position: Optional[Tuple[float, float]] = None
19
17
  instance: Optional[geo.Point] = None
20
18
  index: Optional[float] = None
@@ -38,54 +36,90 @@ class Point(Alteration):
38
36
  """Returns the y-coordinate of the point."""
39
37
  return self._shapely_object.y
40
38
 
41
- def shift_position(self, shift: Tuple[float, float]) -> 'Point':
39
+ def shift_position(self, shift: Tuple[float, float]) -> Self:
42
40
  """
43
41
  Shifts the point by a given offset and returns a new Point instance.
42
+
43
+ Parameters
44
+ ----------
45
+ shift : tuple of float
46
+ The (x, y) offset to shift the point by.
47
+
48
+ Returns
49
+ -------
50
+ Point
51
+ A new Point instance representing the shifted position.
44
52
  """
45
- point_shift = ff.geometries.utils.interpret_to_point(shift)
53
+ point_shift = geometries.utils.interpret_to_point(shift)
46
54
  return self.__add__(point_shift)
47
55
 
48
- def __add__(self, other) -> 'Point':
56
+ def __add__(self, other) -> Self:
49
57
  """
50
58
  Adds the coordinates of another point to this one and returns a new Point instance.
59
+
60
+ Parameters
61
+ ----------
62
+ other : Point
63
+ The other point to add.
64
+
65
+ Returns
66
+ -------
67
+ Point
68
+ A new Point instance representing the sum of the two points.
51
69
  """
52
- other = ff.geometries.utils.interpret_to_point(other)
70
+ other = geometries.utils.interpret_to_point(other)
53
71
 
54
72
  return Point(position=(self.x + other.x, self.y + other.y))
55
73
 
56
- def __sub__(self, other) -> 'Point':
74
+ def __sub__(self, other) -> Self:
57
75
  """
58
76
  Subtracts the coordinates of another point from this one and returns a new Point instance.
59
77
  """
60
- other = ff.geometries.utils.interpret_to_point(other)
78
+ other = geometries.utils.interpret_to_point(other)
61
79
  return Point(position=(self.x - other.x, self.y - other.y))
62
80
 
63
- def __neg__(self) -> 'Point':
81
+ def __neg__(self) -> Self:
64
82
  """
65
83
  Negates the coordinates of this point and returns a new Point instance.
66
84
  """
67
85
  return Point(position=[-self.x, -self.y])
68
86
 
69
- def __mul__(self, factor: float) -> 'Point':
87
+ def __mul__(self, factor: float) -> Self:
70
88
  """
71
89
  Multiplies the coordinates of this point by a scalar and returns a new Point instance.
72
90
  """
73
91
  return Point(position=[self.x * factor, self.y * factor])
74
92
 
75
- def distance(self, other: 'Point') -> float:
93
+ def distance(self, other: Self) -> float:
76
94
  """
77
95
  Computes the Euclidean distance between this point and another point.
96
+
97
+ Parameters
98
+ ----------
99
+ other : Point
100
+ The other point to compute the distance to.
101
+
102
+ Returns
103
+ -------
104
+ float
105
+ The Euclidean distance between the two points.
78
106
  """
79
107
  return numpy.sqrt((self.x - other.x)**2 + (self.y - other.y)**2)
80
108
 
81
109
  @_plot_helper
82
- def plot(
83
- self,
84
- ax: plt.Axes = None,
85
- marker: str = 'x',
86
- size: int = 20,
87
- label: str = None) -> None:
110
+ def plot(self, ax: plt.Axes = None, marker: str = 'x', size: int = 20, label: str = None) -> None:
88
111
  """
89
112
  Renders this point on the given axis, optionally with text.
113
+
114
+ Parameters
115
+ ----------
116
+ ax : plt.Axes
117
+ The Matplotlib axis to render the point on.
118
+ marker : str
119
+ The marker style for the point.
120
+ size : int
121
+ The size of the point marker.
122
+ label : str
123
+ The label for the point, if any.
90
124
  """
91
125
  ax.scatter(self.x, self.y, label=label, marker=marker, s=size)