ign-borea 0.1.5__tar.gz → 0.2.2__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 (113) hide show
  1. {ign_borea-0.1.5 → ign_borea-0.2.2}/PKG-INFO +2 -3
  2. {ign_borea-0.1.5 → ign_borea-0.2.2}/README.md +1 -0
  3. {ign_borea-0.1.5 → ign_borea-0.2.2}/README_borea_lib.md +1 -0
  4. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/datastruct/dtm.py +2 -2
  5. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/datastruct/shot.py +9 -3
  6. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/datastruct/workdata.py +19 -12
  7. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/format/conl.py +1 -5
  8. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/format/rpc.py +12 -4
  9. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/geodesy/local_euclidean_proj.py +9 -9
  10. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/geodesy/proj_engine.py +10 -7
  11. ign_borea-0.2.2/borea/geodesy/transform_geodesy.py +240 -0
  12. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/process/p_add_data/p_gen_param.py +3 -14
  13. ign_borea-0.2.2/borea/process/p_add_data/p_proj.py +57 -0
  14. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/process/p_add_data/p_unit_shot.py +3 -3
  15. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/process/p_format/p_write_opk.py +5 -5
  16. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/process/p_func/p_spaceresection.py +2 -2
  17. ign_borea-0.2.2/borea/process/p_func/p_tf_proj_pt.py +50 -0
  18. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/reader/orientation/manage_reader.py +2 -2
  19. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/reader/orientation/reader_opk.py +3 -3
  20. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/reader/reader_camera.py +3 -2
  21. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/reader/reader_point.py +7 -7
  22. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/stat/statistics.py +2 -2
  23. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/transform_world_image/transform_shot/conversion_coor_shot.py +4 -4
  24. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/transform_world_image/transform_shot/image_world_shot.py +1 -1
  25. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/transform_world_image/transform_shot/world_image_shot.py +1 -1
  26. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/transform_world_image/transform_worksite/image_world_least_square.py +1 -1
  27. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/transform_world_image/transform_worksite/space_resection.py +2 -2
  28. ign_borea-0.2.2/borea/utils/check/check_path.py +26 -0
  29. ign_borea-0.2.2/borea/utils/solver/solver.py +18 -0
  30. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/worksite/worksite.py +10 -5
  31. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/writer/writer_con.py +10 -3
  32. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/writer/writer_df_to_txt.py +2 -2
  33. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/writer/writer_opk.py +3 -3
  34. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/writer/writer_rpc.py +7 -4
  35. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea_dependency/requirements-dev.txt +0 -2
  36. ign_borea-0.2.2/borea_tools/__init__.py +0 -0
  37. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea_tools/spaceresection_opk.py +2 -2
  38. ign_borea-0.2.2/borea_tools/transform_proj_points.py +30 -0
  39. {ign_borea-0.1.5 → ign_borea-0.2.2}/ign_borea.egg-info/PKG-INFO +2 -3
  40. {ign_borea-0.1.5 → ign_borea-0.2.2}/ign_borea.egg-info/SOURCES.txt +6 -0
  41. {ign_borea-0.1.5 → ign_borea-0.2.2}/ign_borea.egg-info/entry_points.txt +1 -0
  42. {ign_borea-0.1.5 → ign_borea-0.2.2}/ign_borea.egg-info/requires.txt +0 -2
  43. {ign_borea-0.1.5 → ign_borea-0.2.2}/pyproject.toml +2 -1
  44. ign_borea-0.1.5/borea/geodesy/transform_geodesy.py +0 -114
  45. {ign_borea-0.1.5 → ign_borea-0.2.2}/LICENSE +0 -0
  46. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/__init__.py +0 -0
  47. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/datastruct/__init__.py +0 -0
  48. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/datastruct/camera.py +0 -0
  49. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/datastruct/gcp.py +0 -0
  50. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/format/__init__.py +0 -0
  51. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/geodesy/__init__.py +0 -0
  52. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/geodesy/approx_euclidean_proj.py +0 -0
  53. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/geodesy/euclidean_proj.py +0 -0
  54. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/geodesy/projectionlist/__init__.py +0 -0
  55. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/geodesy/projectionlist/search_proj.py +0 -0
  56. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/process/__init__.py +0 -0
  57. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/process/p_add_data/__init__.py +0 -0
  58. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/process/p_add_data/p_add_shot.py +0 -0
  59. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/process/p_add_data/p_file_gcp2d.py +0 -0
  60. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/process/p_add_data/p_file_gcp3d.py +0 -0
  61. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/process/p_add_data/p_pt2d.py +0 -0
  62. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/process/p_add_data/p_pt3d.py +0 -0
  63. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/process/p_add_data/p_write.py +0 -0
  64. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/process/p_format/__init__.py +0 -0
  65. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/process/p_format/p_read_opk.py +0 -0
  66. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/process/p_format/p_write_con.py +0 -0
  67. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/process/p_format/p_write_rpc.py +0 -0
  68. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/process/p_func/__init__.py +0 -0
  69. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/process/p_func/p_control.py +0 -0
  70. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/process/p_func/p_image_world.py +0 -0
  71. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/process/p_func/p_world_image.py +0 -0
  72. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/reader/__init__.py +0 -0
  73. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/reader/orientation/__init__.py +0 -0
  74. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/stat/__init__.py +0 -0
  75. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/transform_world_image/__init__.py +0 -0
  76. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/transform_world_image/transform_dtm/__init__.py +0 -0
  77. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/transform_world_image/transform_dtm/world_image_dtm.py +0 -0
  78. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/transform_world_image/transform_shot/__init__.py +0 -0
  79. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/transform_world_image/transform_worksite/__init__.py +0 -0
  80. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/transform_world_image/transform_worksite/image_world_intersection.py +0 -0
  81. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/transform_world_image/transform_worksite/image_world_work.py +0 -0
  82. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/transform_world_image/transform_worksite/world_image_work.py +0 -0
  83. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/utils/__init__.py +0 -0
  84. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/utils/check/__init__.py +0 -0
  85. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/utils/check/check_args_opk.py +0 -0
  86. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/utils/check/check_args_reader_pt.py +0 -0
  87. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/utils/check/check_array.py +0 -0
  88. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/utils/check/check_header.py +0 -0
  89. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/utils/check/check_order_axe.py +0 -0
  90. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/utils/miscellaneous/__init__.py +0 -0
  91. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/utils/miscellaneous/miscellaneous.py +0 -0
  92. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/utils/miscellaneous/param_bundle.py +0 -0
  93. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/utils/miscellaneous/sparse.py +0 -0
  94. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/utils/singleton/__init__.py +0 -0
  95. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/utils/singleton/singleton.py +0 -0
  96. {ign_borea-0.1.5/borea/utils/xml → ign_borea-0.2.2/borea/utils/solver}/__init__.py +0 -0
  97. {ign_borea-0.1.5/borea/worksite → ign_borea-0.2.2/borea/utils/xml}/__init__.py +0 -0
  98. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/utils/xml/xml.py +0 -0
  99. {ign_borea-0.1.5/borea/writer → ign_borea-0.2.2/borea/worksite}/__init__.py +0 -0
  100. {ign_borea-0.1.5/borea_tools → ign_borea-0.2.2/borea/writer}/__init__.py +0 -0
  101. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea/writer/manage_writer.py +0 -0
  102. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea_dependency/requirements.txt +0 -0
  103. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea_tools/opk_control.py +0 -0
  104. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea_tools/opk_to_conl.py +0 -0
  105. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea_tools/opk_to_opk.py +0 -0
  106. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea_tools/opk_to_rpc.py +0 -0
  107. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea_tools/pt_image_to_world.py +0 -0
  108. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea_tools/pt_world_to_image.py +0 -0
  109. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea_tools/ptfile_image_to_world.py +0 -0
  110. {ign_borea-0.1.5 → ign_borea-0.2.2}/borea_tools/ptfile_world_to_image.py +0 -0
  111. {ign_borea-0.1.5 → ign_borea-0.2.2}/ign_borea.egg-info/dependency_links.txt +0 -0
  112. {ign_borea-0.1.5 → ign_borea-0.2.2}/ign_borea.egg-info/top_level.txt +0 -0
  113. {ign_borea-0.1.5 → ign_borea-0.2.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ign-borea
3
- Version: 0.1.5
3
+ Version: 0.2.2
4
4
  Summary: A package to manipulate orientation files
5
5
  Author-email: Antoine Cornu <antoine.cornu@ign.fr>, Nicolas Laurain <nicolas.laurain@ign.fr>
6
6
  License: MIT License
@@ -53,8 +53,6 @@ Requires-Dist: dataclasses; extra == "dev"
53
53
  Requires-Dist: pyproj; extra == "dev"
54
54
  Requires-Dist: scipy; extra == "dev"
55
55
  Requires-Dist: pandas; extra == "dev"
56
- Requires-Dist: build; extra == "dev"
57
- Requires-Dist: twine; extra == "dev"
58
56
 
59
57
  [![IGNF badge](https://img.shields.io/badge/IGNF-8cbd3a)](https://www.ign.fr/) [![PyPI Downloads](https://img.shields.io/pypi/dm/ign-borea.svg?label=PyPI%20downloads)](
60
58
  https://pypi.org/project/ign-borea/)
@@ -101,6 +99,7 @@ Some tools are already implemented in the library:
101
99
  * Transforms coordinates file terrain from image: `ptfile-image-to-world -h` [doc](https://github.com/IGNF/Borea/tree/main/borea_tools/docs_tools/README_ptfile_image_to_world.md)
102
100
  * Transforms coordinates file image from terrain: `ptfile-world-to-image -h` [doc](https://github.com/IGNF/Borea/tree/main/borea_tools/docs_tools/README_ptfile_world_to_image.md)
103
101
  * Calculates opk by space resection: `spaceresection-opk -h` [doc](https://github.com/IGNF/Borea/tree/main/borea_tools/docs_tools/README_spaceresection_opk.md)
102
+ * Transform projection of points file: `transform-proj-points -h` [doc](./borea_tools/docs_tools/README_transform_proj_points.md)
104
103
 
105
104
  ## Read data and instantiate worksite
106
105
 
@@ -16,6 +16,7 @@ Why Borea? B for Box and orea is a back slang of aero.
16
16
  * Transforms coordinates file terrain from image: [borea_tools/docs_tools/README_ptfile_image_to_world.md](./borea_tools/docs_tools/README_ptfile_image_to_world.md)
17
17
  * Transforms coordinates file image from terrain: [borea_tools/docs_tools/README_ptfile_world_to_image.md](./borea_tools/docs_tools/README_ptfile_world_to_image.md)
18
18
  * Calculates opk by space resection: [borea_tools/docs_tools/README_spaceresection_opk.md](./borea_tools/docs_tools/README_spaceresection_opk.md)
19
+ * Transform projection of points file: [borea_tools/docs_tools/README_transform_proj_points.md](./borea_tools/docs_tools/README_transform_proj_points.md)
19
20
  * Python lib: [README_borea_lib.md](./README_borea_lib.md)
20
21
 
21
22
  ## Dependency
@@ -43,6 +43,7 @@ Some tools are already implemented in the library:
43
43
  * Transforms coordinates file terrain from image: `ptfile-image-to-world -h` [doc](https://github.com/IGNF/Borea/tree/main/borea_tools/docs_tools/README_ptfile_image_to_world.md)
44
44
  * Transforms coordinates file image from terrain: `ptfile-world-to-image -h` [doc](https://github.com/IGNF/Borea/tree/main/borea_tools/docs_tools/README_ptfile_world_to_image.md)
45
45
  * Calculates opk by space resection: `spaceresection-opk -h` [doc](https://github.com/IGNF/Borea/tree/main/borea_tools/docs_tools/README_spaceresection_opk.md)
46
+ * Transform projection of points file: `transform-proj-points -h` [doc](./borea_tools/docs_tools/README_transform_proj_points.md)
46
47
 
47
48
  ## Read data and instantiate worksite
48
49
 
@@ -1,11 +1,11 @@
1
1
  """
2
2
  A module for manipulating a digital elevation model.
3
3
  """
4
- from pathlib import Path, PureWindowsPath
5
4
  import numpy as np
6
5
  from osgeo import gdal
7
6
  from scipy import ndimage
8
7
  from borea.transform_world_image.transform_dtm.world_image_dtm import WorldImageDtm
8
+ from borea.utils.check.check_path import check_path
9
9
  from borea.utils.singleton.singleton import Singleton
10
10
  gdal.UseExceptions()
11
11
 
@@ -49,7 +49,7 @@ class Dtm(WorldImageDtm, metaclass=Singleton):
49
49
  if path_dtm:
50
50
  gdal.AllRegister()
51
51
  self.type_dtm = type_dtm
52
- self.path_dtm = Path(PureWindowsPath(path_dtm))
52
+ self.path_dtm = check_path(path_dtm)
53
53
  self.img = gdal.Open(self.path_dtm.as_posix())
54
54
  self.rb = self.img.GetRasterBand(1)
55
55
  self.nodata = self.rb.GetNoDataValue()
@@ -9,7 +9,7 @@ from borea.geodesy.local_euclidean_proj import LocalEuclideanProj
9
9
  from borea.utils.check.check_order_axe import check_order_axe
10
10
 
11
11
 
12
- # pylint: disable=too-many-instance-attributes too-many-arguments
12
+ # pylint: disable=too-many-instance-attributes too-many-arguments too-many-positional-arguments
13
13
  class Shot:
14
14
  """
15
15
  Shot class definition.
@@ -153,9 +153,9 @@ class Shot:
153
153
  type_z (str): z type height or altitude.
154
154
  """
155
155
  if type_z == "height":
156
- self.pos_shot[2] = ProjEngine().tranform_height(self.pos_shot)
156
+ self.pos_shot[2] = ProjEngine().tf.tranform_height(self.pos_shot)
157
157
  else:
158
- self.pos_shot[2] = ProjEngine().tranform_altitude(self.pos_shot)
158
+ self.pos_shot[2] = ProjEngine().tf.tranform_altitude(self.pos_shot)
159
159
 
160
160
  def set_linear_alteration(self, linear_alteration: bool) -> None:
161
161
  """
@@ -185,6 +185,12 @@ class Shot:
185
185
  self.ori_shot = -(R.from_euler("x", np.pi) *
186
186
  R.from_matrix(self.mat_rot)).as_euler(order_xyz, degrees=unitori)
187
187
 
188
+ def set_proj_pos(self) -> None:
189
+ """
190
+ Change the projection of the position shot with the epsg_output.
191
+ """
192
+ self.pos_shot = np.array(ProjEngine().tf.proj_to_proj_out(*self.pos_shot))
193
+
188
194
  def get_z_remove_scale_factor(self) -> float:
189
195
  """
190
196
  Return Z after removing the scale factor. The Z of the object is NOT modified.
@@ -33,8 +33,9 @@ class Workdata:
33
33
  self.type_z_data = None
34
34
  self.type_z_shot = None
35
35
  self.approxeucli = False
36
+ self.epsg_output = False
36
37
 
37
- # pylint: disable-next=too-many-arguments
38
+ # pylint: disable-next=too-many-arguments too-many-positional-arguments
38
39
  def add_shot(self, name_shot: str, pos_shot: np.ndarray,
39
40
  ori_shot: np.ndarray, name_cam: str,
40
41
  unit_angle: str, linear_alteration: bool,
@@ -59,24 +60,30 @@ class Workdata:
59
60
  linear_alteration=linear_alteration,
60
61
  order_axe=order_axe)
61
62
 
62
- def set_proj(self, epsg: int, path_geoid: list = None) -> None:
63
+ def set_proj(self, epsg: list, path_geoid: list = None, epsg_output: int = None) -> None:
63
64
  """
64
65
  Setup a projection system to the worksite.
65
66
 
66
67
  Args:
67
- epsg (int): Code epsg of the porjection ex: 2154.
68
+ epsg (list): Code epsg of the projection ex: [2154].
68
69
  path_geoid (str): List of GeoTIFF which represents the geoid in grid form.
70
+ epsg_output (int): Code epsg of the output projection. If you want to change.
69
71
  """
70
72
  ProjEngine.clear()
71
- try: # Check if the epsg exist
72
- crs = CRS.from_epsg(epsg)
73
- del crs
74
- except exceptions.CRSError as e_info:
75
- raise exceptions.CRSError(f"Your EPSG:{epsg} doesn't exist") from e_info
76
-
77
- ProjEngine().set_epsg(epsg, path_geoid)
78
-
79
- # pylint: disable-next=too-many-arguments
73
+ for idepsg in [*epsg, epsg_output]:
74
+ if idepsg:
75
+ try: # Check if the epsg exist
76
+ _ = CRS.from_epsg(idepsg)
77
+ del _
78
+ except exceptions.CRSError as e_info:
79
+ raise exceptions.CRSError(f"Your EPSG:{epsg}"
80
+ " doesn't exist in pyproj.") from e_info
81
+ if epsg_output:
82
+ self.epsg_output = True
83
+
84
+ ProjEngine().set_epsg(epsg, path_geoid, epsg_output)
85
+
86
+ # pylint: disable-next=too-many-arguments too-many-positional-arguments
80
87
  def add_camera(self, name_camera: str, ppax: float, ppay: float,
81
88
  focal: float, width: int, height: int) -> None:
82
89
  """
@@ -33,19 +33,15 @@ class Conl:
33
33
  cam: Camera
34
34
  proj: str
35
35
 
36
- def save_conl(self, path_conical: Path, linalt: bool = True) -> None:
36
+ def save_conl(self, path_conical: Path) -> None:
37
37
  """
38
38
  Save the shot as light conical file.
39
39
 
40
40
  Args:
41
41
  path_conical (Path): path to the light conical file.
42
- linalt (bool): If you want z shot corrected by linear alteration.
43
42
  """
44
43
  date_now = datetime.now()
45
44
 
46
- # Scale factor correction
47
- self.shot.set_linear_alteration(linalt)
48
-
49
45
  # creation XML
50
46
  ori = ET.Element("orientation", {})
51
47
  ET.SubElement(ori, "lastmodificationbylibori",
@@ -9,6 +9,7 @@ from borea.datastruct.dtm import Dtm
9
9
  from borea.transform_world_image.transform_shot.image_world_shot import ImageWorldShot
10
10
  from borea.transform_world_image.transform_shot.world_image_shot import WorldImageShot
11
11
  from borea.utils.miscellaneous.miscellaneous import normalize
12
+ from borea.utils.solver.solver import npsolve
12
13
 
13
14
 
14
15
  class Rpc:
@@ -22,6 +23,7 @@ class Rpc:
22
23
  def __init__(self) -> None:
23
24
  self.param_rpc = {}
24
25
  self.fact_rpc = None
26
+ self.output_epsg = False
25
27
 
26
28
  @classmethod
27
29
  def from_shot(cls, shot: Shot, cam: Camera, param_rpc: dict, unit_data: dict) -> None:
@@ -46,6 +48,7 @@ class Rpc:
46
48
  """
47
49
  obj = cls()
48
50
  obj.fact_rpc = param_rpc["fact_rpc"]
51
+ obj.output_epsg = param_rpc["epsg_output"]
49
52
  obj.param_rpc["ERR_BIAS"] = -1
50
53
  obj.param_rpc["ERR_RAND"] = -1
51
54
 
@@ -107,9 +110,14 @@ class Rpc:
107
110
  tuple: grid image normalize and grid world normalize.
108
111
  """
109
112
  if self.fact_rpc is None:
110
- x_geog, y_geog, z_geog = ProjEngine().carto_to_geog(grid_world[0],
111
- grid_world[1],
112
- grid_world[2])
113
+ if self.output_epsg:
114
+ x_geog, y_geog, z_geog = ProjEngine().tf.proj_to_proj_out(grid_world[0],
115
+ grid_world[1],
116
+ grid_world[2])
117
+ else:
118
+ x_geog, y_geog, z_geog = ProjEngine().tf.carto_to_geog(grid_world[0],
119
+ grid_world[1],
120
+ grid_world[2])
113
121
  else:
114
122
  x_geog = grid_world[0]*self.fact_rpc
115
123
  y_geog = grid_world[1]*self.fact_rpc
@@ -154,7 +162,7 @@ class Rpc:
154
162
  np.array: Rpc coefficients.
155
163
  """
156
164
  mat_obs = self.setup_matrix_obs_rpc(img_norm, world_norm, polynomial_degree)
157
- x = np.linalg.lstsq(mat_obs, img_norm, rcond=None)[0]
165
+ x = npsolve(mat_obs, img_norm)
158
166
 
159
167
  coef_rpc = np.zeros(40)
160
168
  if polynomial_degree == 1:
@@ -37,7 +37,7 @@ class LocalEuclideanProj(EuclideanProj):
37
37
  Returns:
38
38
  np.array: Transition matrix.
39
39
  """
40
- lon, lat = ProjEngine().carto_to_geog(x, y)
40
+ lon, lat = ProjEngine().tf.carto_to_geog(x, y)
41
41
  gamma = ProjEngine().get_meridian_convergence(x, y)
42
42
 
43
43
  # Matrix for switching to local cartesian coordinates
@@ -92,10 +92,10 @@ class LocalEuclideanProj(EuclideanProj):
92
92
  """
93
93
  coor = check_array_transfo(coor[0], coor[1], coor[2])
94
94
 
95
- coor_geoc = np.array(ProjEngine().carto_to_geoc(coor[0], coor[1], coor[2]))
96
- central_geoc = np.array(ProjEngine().carto_to_geoc(self.pt_central[0],
97
- self.pt_central[1],
98
- self.pt_central[2]))
95
+ coor_geoc = np.array(ProjEngine().tf.carto_to_geoc(coor[0], coor[1], coor[2]))
96
+ central_geoc = np.array(ProjEngine().tf.carto_to_geoc(self.pt_central[0],
97
+ self.pt_central[1],
98
+ self.pt_central[2]))
99
99
  dr = np.vstack([coor_geoc[0] - central_geoc[0],
100
100
  coor_geoc[1] - central_geoc[1],
101
101
  coor_geoc[2] - central_geoc[2]])
@@ -115,13 +115,13 @@ class LocalEuclideanProj(EuclideanProj):
115
115
  """
116
116
  coor = np.squeeze(coor)
117
117
 
118
- central_geoc = np.array(ProjEngine().carto_to_geoc(self.pt_central[0],
119
- self.pt_central[1],
120
- self.pt_central[2]))
118
+ central_geoc = np.array(ProjEngine().tf.carto_to_geoc(self.pt_central[0],
119
+ self.pt_central[1],
120
+ self.pt_central[2]))
121
121
  dr = np.vstack([coor[0] - self.pt_central[0],
122
122
  coor[1] - self.pt_central[1],
123
123
  coor[2] - self.pt_central[2]])
124
124
  point_geoc = np.squeeze((self.rot_to_euclidean_local.T @ dr) + np.array([central_geoc]).T)
125
125
  x_gc, y_gc, z_gc = check_array_transfo(point_geoc[0], point_geoc[1], point_geoc[2])
126
- tup = ProjEngine().geoc_to_carto(x_gc, y_gc, z_gc)
126
+ tup = ProjEngine().tf.geoc_to_carto(x_gc, y_gc, z_gc)
127
127
  return np.array([tup[0], tup[1], tup[2]])
@@ -11,30 +11,33 @@ from borea.utils.singleton.singleton import Singleton
11
11
 
12
12
  # pylint: disable=unpacking-non-sequence
13
13
  @dataclass
14
- class ProjEngine(TransformGeodesy, metaclass=Singleton):
14
+ class ProjEngine(metaclass=Singleton):
15
15
  """
16
16
  This class provides functions for using a cartographic system.
17
17
  """
18
18
  epsg: int = None
19
19
  geoid: list = None
20
+ epsg_output: int = None
20
21
 
21
22
  def __post_init__(self) -> None:
22
23
  if self.epsg:
23
- self.crs = pyproj.CRS.from_epsg(self.epsg)
24
+ self.crs = pyproj.CRS.from_epsg(self.epsg[0])
24
25
  self.proj = pyproj.Proj(self.crs)
25
- TransformGeodesy.__tf_init__(self, self.geoid, self.crs)
26
+ self.tf = TransformGeodesy(self.epsg, self.geoid, self.epsg_output)
26
27
 
27
- def set_epsg(self, epsg: int, geoid: list = None) -> None:
28
+ def set_epsg(self, epsg: list, geoid: list = None, epsg_output: int = None) -> None:
28
29
  """
29
30
  Setter of the class ProjEngine.
30
31
  Allows to init the class with data.
31
32
 
32
33
  Args:
33
- epsg (int): Code epsg of the porjection ex: "EPSG:2154".
34
+ epsg (list): Code epsg of the projection ex: [2154].
34
35
  geoid (list): List of geoid to use.
36
+ epsg_output (int): Code epsg of the output projection. If you want to change.
35
37
  """
36
38
  self.epsg = epsg
37
39
  self.geoid = geoid
40
+ self.epsg_output = epsg_output
38
41
  self.__post_init__()
39
42
 
40
43
  def get_meridian_convergence(self, x_carto: Union[np.ndarray, List[float], float],
@@ -50,7 +53,7 @@ class ProjEngine(TransformGeodesy, metaclass=Singleton):
50
53
  Returns:
51
54
  np.array : Meridian convergence in degree.
52
55
  """
53
- (x_geog, y_geog) = self.carto_to_geog(x_carto, y_carto)
56
+ (x_geog, y_geog) = self.tf.carto_to_geog(x_carto, y_carto)
54
57
  return -np.array(self.proj.get_factors(x_geog, y_geog).meridian_convergence)
55
58
 
56
59
  def get_scale_factor(self, x_carto: Union[np.ndarray, List[float], float],
@@ -66,5 +69,5 @@ class ProjEngine(TransformGeodesy, metaclass=Singleton):
66
69
  Returns:
67
70
  np.array: Scale factor and meridian convergence.
68
71
  """
69
- x_geog, y_geog = self.carto_to_geog(x_carto, y_carto)
72
+ x_geog, y_geog = self.tf.carto_to_geog(x_carto, y_carto)
70
73
  return np.array(self.proj.get_factors(x_geog, y_geog).meridional_scale) - 1
@@ -0,0 +1,240 @@
1
+ """
2
+ Module for class ProjEngine, transform geodesy
3
+ """
4
+ import pyproj
5
+ import numpy as np
6
+ import pandas as pd
7
+
8
+
9
+ # pylint: disable=too-many-instance-attributes
10
+ class TransformGeodesy():
11
+ """
12
+ This class provides functions to tranform coordinate system.
13
+ Class parent of ProjEngine.
14
+ Implemented by ProjEngine.
15
+
16
+ Args:
17
+ geoid (list): List of geoid to use.
18
+ epsg (list): Code epsg of the projection ex: [2154].
19
+ epsg_output (int): Code epsg of the output projection. If you want to change.
20
+ """
21
+ def __init__(self, epsg: list, geoid: list, epsg_output: int) -> None:
22
+ self.epsg = epsg
23
+ self.epsg_output = epsg_output
24
+ self.crs = pyproj.CRS.from_epsg(epsg[0])
25
+ self.geoid = geoid
26
+ self._carto_to_geoc = None
27
+ self._geoc_to_carto = None
28
+ self._carto_to_geog = None
29
+ self._geog_to_carto = None
30
+ self._geog_to_geoid = None
31
+ self._geoid_to_geog = None
32
+ self._proj_to_proj_out = None
33
+
34
+ @property
35
+ def carto_to_geog(self) -> pyproj.Transformer:
36
+ """
37
+ Returns the transformation or instantiates it before returning it.
38
+
39
+ Returns:
40
+ pyproj.Transformer : carto_to_geog
41
+ """
42
+ if not self._carto_to_geog:
43
+ try:
44
+ crs_geog = pyproj.CRS.from_epsg(self.epsg[1])
45
+ except (IndexError, pyproj.exceptions.CRSError):
46
+ crs_geog = pyproj.crs.GeographicCRS(name=self.crs.name, datum=self.crs.datum.name)
47
+
48
+ self._carto_to_geog = pyproj.Transformer.from_crs(self.crs, crs_geog).transform
49
+
50
+ return self._carto_to_geog
51
+
52
+ @property
53
+ def geog_to_carto(self) -> pyproj.Transformer:
54
+ """
55
+ Returns the transformation or instantiates it before returning it.
56
+
57
+ Returns:
58
+ pyproj.Transformer : geog_to_carto
59
+ """
60
+ if not self._geog_to_carto:
61
+ try:
62
+ crs_geog = pyproj.CRS.from_epsg(self.epsg[1])
63
+ except (IndexError, pyproj.exceptions.CRSError):
64
+ crs_geog = pyproj.crs.GeographicCRS(name=self.crs.name, datum=self.crs.datum.name)
65
+
66
+ self._geog_to_carto = pyproj.Transformer.from_crs(crs_geog, self.crs).transform
67
+
68
+ return self._geog_to_carto
69
+
70
+ @property
71
+ def carto_to_geoc(self) -> pyproj.Transformer:
72
+ """
73
+ Returns the transformation or instantiates it before returning it.
74
+
75
+ Returns:
76
+ pyproj.Transformer : carto_to_geoc
77
+ """
78
+ if not self._carto_to_geoc:
79
+ try:
80
+ crs_geoc = pyproj.CRS.from_epsg(self.epsg[2])
81
+ except (IndexError, pyproj.exceptions.CRSError):
82
+ crs_geoc = pyproj.crs.GeocentricCRS(name=self.crs.name, datum=self.crs.datum.name)
83
+
84
+ self._carto_to_geoc = pyproj.Transformer.from_crs(self.crs, crs_geoc).transform
85
+
86
+ return self._carto_to_geoc
87
+
88
+ @property
89
+ def geoc_to_carto(self) -> pyproj.Transformer:
90
+ """
91
+ Returns the transformation or instantiates it before returning it.
92
+
93
+ Returns:
94
+ pyproj.Transformer : geoc_to_carto
95
+ """
96
+ if not self._geoc_to_carto:
97
+ try:
98
+ crs_geoc = pyproj.CRS.from_epsg(self.epsg[2])
99
+ except (IndexError, pyproj.exceptions.CRSError):
100
+ crs_geoc = pyproj.crs.GeocentricCRS(name=self.crs.name, datum=self.crs.datum.name)
101
+
102
+ self._geoc_to_carto = pyproj.Transformer.from_crs(crs_geoc, self.crs).transform
103
+
104
+ return self._geoc_to_carto
105
+
106
+ @property
107
+ def geoid_to_geog(self) -> pyproj.Transformer:
108
+ """
109
+ Returns the transformation or instantiates it before returning it.
110
+
111
+ Returns:
112
+ pyproj.Transformer : geoid_to_geog
113
+ """
114
+ if not self.geoid:
115
+ raise ValueError("Mistake Geoid path")
116
+
117
+ if not self._geoid_to_geog:
118
+ try:
119
+ # Transform geoide coordinates to geographic coordinates
120
+ self._geoid_to_geog = pyproj.Transformer.from_pipeline("+proj=vgridshift "
121
+ "+grids="
122
+ f"{','.join(self.geoid)} "
123
+ "+multiplier=1").transform
124
+ except pyproj.exceptions.ProjError as e:
125
+ raise pyproj.exceptions.ProjError(f"{self.geoid} The name or path "
126
+ "of geotif is incorrect or does not exist in "
127
+ f"{pyproj.datadir.get_data_dir()}!!!{e}") from e
128
+
129
+ return self._geoid_to_geog
130
+
131
+ @property
132
+ def geog_to_geoid(self) -> pyproj.Transformer:
133
+ """
134
+ Returns the transformation or instantiates it before returning it.
135
+
136
+ Returns:
137
+ pyproj.Transformer : geog_to_geoid
138
+ """
139
+ if not self.geoid:
140
+ raise ValueError("Mistake Geoid path")
141
+
142
+ if not self._geog_to_geoid:
143
+ try:
144
+ # Transform geoide coordinates to geographic coordinates
145
+ self._geog_to_geoid = pyproj.Transformer.from_pipeline("+proj=vgridshift "
146
+ "+grids="
147
+ f"{','.join(self.geoid)} "
148
+ "+multiplier=-1").transform
149
+ except pyproj.exceptions.ProjError as e:
150
+ raise pyproj.exceptions.ProjError(f"{self.geoid} The name or path "
151
+ "of geotif is incorrect or does not exist in "
152
+ f"{pyproj.datadir.get_data_dir()}!!!{e}") from e
153
+
154
+ return self._geog_to_geoid
155
+
156
+ @property
157
+ def proj_to_proj_out(self) -> pyproj.Transformer:
158
+ """
159
+ Create the pyproj Transformer from crs of worksite to crs geographic ask.
160
+
161
+ Returns:
162
+ pyproj.Transformer : carto_to_geog_out
163
+ """
164
+ if not self._proj_to_proj_out:
165
+ crs_out = pyproj.CRS.from_epsg(self.epsg_output)
166
+ self._proj_to_proj_out = pyproj.Transformer.from_crs(self.crs, crs_out).transform
167
+
168
+ return self._proj_to_proj_out
169
+
170
+ def tranform_height(self, coor: np.ndarray) -> float:
171
+ """
172
+ Converting z in altitude to z in height of point.
173
+
174
+ Args:
175
+ coor (np.array): [X, Y, Z] coordinate of the point.
176
+
177
+ Returns:
178
+ float: New height Z.
179
+ """
180
+ coor_geog = self.carto_to_geog(coor[0], coor[1], coor[2])
181
+ try:
182
+ coor_geog = self.geoid_to_geog(coor_geog[0],
183
+ coor_geog[1],
184
+ coor_geog[2])
185
+ new_z = self.geog_to_carto(coor_geog[0],
186
+ coor_geog[1],
187
+ coor_geog[2])[2]
188
+ except AttributeError as info:
189
+ raise ValueError("The geoid has not been entered, "
190
+ "cannot transform z altitude to height.") from info
191
+
192
+ if np.all(new_z == np.inf):
193
+ raise ValueError("out geoid")
194
+ return new_z
195
+
196
+ def tranform_altitude(self, coor: np.ndarray) -> float:
197
+ """
198
+ Converting z in height to z in altitude of point.
199
+
200
+ Args:
201
+ coor (np.array): [X, Y, Z] coordinate of the point.
202
+
203
+ Returns:
204
+ float: New altitude Z.
205
+ """
206
+ coor_geog = self.carto_to_geog(coor[0], coor[1], coor[2])
207
+ try:
208
+ coor_geog = self.geog_to_geoid(coor_geog[0],
209
+ coor_geog[1],
210
+ coor_geog[2])
211
+ new_z = self.geog_to_carto(coor_geog[0],
212
+ coor_geog[1],
213
+ coor_geog[2])[2]
214
+ except AttributeError as info:
215
+ raise ValueError("The geoid has not been entered, "
216
+ "cannot transform z height to altitude.") from info
217
+
218
+ if np.all(new_z == np.inf):
219
+ raise ValueError("out geoid")
220
+ return new_z
221
+
222
+ def transform_pt_proj(self, df_pt: pd.DataFrame, type_z_input: str = None,
223
+ type_z_output: str = None) -> pd.DataFrame:
224
+ """
225
+ Tranform the input projection to the output projection of points coordinates
226
+ """
227
+ if type_z_input and type_z_output:
228
+ if type_z_input != type_z_output:
229
+ if type_z_output == "altitude":
230
+ df_pt["z"] = self.tranform_altitude(np.array([df_pt['x'],
231
+ df_pt['y'],
232
+ df_pt['z']]))
233
+ if type_z_output == "height":
234
+ df_pt["z"] = self.tranform_height(np.array([df_pt['x'],
235
+ df_pt['y'],
236
+ df_pt['z']]))
237
+
238
+ df_pt["x"], df_pt["y"] = self.proj_to_proj_out(df_pt['x'], df_pt['y'])
239
+
240
+ return df_pt
@@ -2,8 +2,8 @@
2
2
  Args of parser for reading generals parameters
3
3
  """
4
4
  import argparse
5
- import pyproj
6
5
  from borea.worksite.worksite import Worksite
6
+ from borea.process.p_add_data.p_proj import args_proj_param, process_args_proj_param
7
7
  from borea.reader.reader_camera import read_camera
8
8
 
9
9
 
@@ -17,14 +17,7 @@ def args_general_param(parser: argparse) -> argparse:
17
17
  Returns:
18
18
  argsparse: Parser with argument.
19
19
  """
20
- parser.add_argument('-e', '--epsg',
21
- type=int, default=None,
22
- help='EPSG codifier number of the reference system used e.g. "2154".')
23
- parser.add_argument('-y', '--pathgeoid',
24
- type=str, nargs='*', default=None,
25
- help='Path to the pyproj GeoTIFF of the geoid e.g../test/data/geoid.tif'
26
- f' or they must be in {pyproj.datadir.get_data_dir()} and just'
27
- ' need name of file e.g. geoid.tif.')
20
+ parser = args_proj_param(parser)
28
21
  parser.add_argument('-c', '--camera',
29
22
  type=str, nargs='*',
30
23
  help='Files paths of cameras (xml or txt).')
@@ -52,11 +45,7 @@ def process_args_gen_param(args: argparse, work: Worksite) -> Worksite:
52
45
  Worksite: data
53
46
  """
54
47
  # Add a projection to the worksite
55
- if args.epsg is not None:
56
- work.set_proj(args.epsg, args.pathgeoid)
57
- print(f"Projection set-up with EPSG:{args.epsg}.")
58
- else:
59
- print("There is no given projection.")
48
+ work = process_args_proj_param(args, work)
60
49
 
61
50
  # Reading camera file
62
51
  if args.camera is not None:
@@ -0,0 +1,57 @@
1
+ """
2
+ Args of parser for reading projection parameters
3
+ """
4
+ import argparse
5
+ import pyproj
6
+ from borea.worksite.worksite import Worksite
7
+
8
+
9
+ def args_proj_param(parser: argparse) -> argparse:
10
+ """
11
+ Args for adding projection parameter.
12
+
13
+ Args:
14
+ parser (argparse): Parser to add argument.
15
+
16
+ Returns:
17
+ argsparse: Parser with argument.
18
+ """
19
+ parser.add_argument('-e', '--epsg',
20
+ type=int, default=None,
21
+ help='EPSG codifier number of the reference system used e.g. "2154".')
22
+ parser.add_argument('-y', '--pathgeoid',
23
+ type=str, nargs='*', default=None,
24
+ help='Path to the pyproj GeoTIFF of the geoid e.g../test/data/geoid.tif'
25
+ f' or they must be in {pyproj.datadir.get_data_dir()} and just'
26
+ ' need name of file e.g. geoid.tif.')
27
+ parser.add_argument('--geog', '--epsg_geographic',
28
+ type=int, default=None,
29
+ help='EPSG codifier number of the reference geographic system.')
30
+ parser.add_argument('--geoc', '--epsg_geocentric',
31
+ type=int, default=None,
32
+ help='EPSG codifier number of the reference geocentric system.')
33
+ parser.add_argument('--oe', '--epsg_output',
34
+ type=int, default=None,
35
+ help="Code epsg of output Data")
36
+ return parser
37
+
38
+
39
+ def process_args_proj_param(args: argparse, work: Worksite) -> Worksite:
40
+ """
41
+ Processing args with data.
42
+
43
+ Args:
44
+ args (argparse): Arg to apply on worksite (data).
45
+ work (Worksite): Worksite to work on.
46
+
47
+ Returns:
48
+ Worksite: data
49
+ """
50
+ # Add a projection to the worksite
51
+ if args.epsg is not None:
52
+ work.set_proj([args.epsg, args.geog, args.geoc], args.pathgeoid, args.oe)
53
+ print(f"Projection set-up with EPSG:{args.epsg}.")
54
+ else:
55
+ print("There is no given projection.")
56
+
57
+ return work