ign-borea 0.1.5__py3-none-any.whl → 0.2.2__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.
Files changed (40) hide show
  1. borea/datastruct/dtm.py +2 -2
  2. borea/datastruct/shot.py +9 -3
  3. borea/datastruct/workdata.py +19 -12
  4. borea/format/conl.py +1 -5
  5. borea/format/rpc.py +12 -4
  6. borea/geodesy/local_euclidean_proj.py +9 -9
  7. borea/geodesy/proj_engine.py +10 -7
  8. borea/geodesy/transform_geodesy.py +171 -45
  9. borea/process/p_add_data/p_gen_param.py +3 -14
  10. borea/process/p_add_data/p_proj.py +57 -0
  11. borea/process/p_add_data/p_unit_shot.py +3 -3
  12. borea/process/p_format/p_write_opk.py +5 -5
  13. borea/process/p_func/p_spaceresection.py +2 -2
  14. borea/process/p_func/p_tf_proj_pt.py +50 -0
  15. borea/reader/orientation/manage_reader.py +2 -2
  16. borea/reader/orientation/reader_opk.py +3 -3
  17. borea/reader/reader_camera.py +3 -2
  18. borea/reader/reader_point.py +7 -7
  19. borea/stat/statistics.py +2 -2
  20. borea/transform_world_image/transform_shot/conversion_coor_shot.py +4 -4
  21. borea/transform_world_image/transform_shot/image_world_shot.py +1 -1
  22. borea/transform_world_image/transform_shot/world_image_shot.py +1 -1
  23. borea/transform_world_image/transform_worksite/image_world_least_square.py +1 -1
  24. borea/transform_world_image/transform_worksite/space_resection.py +2 -2
  25. borea/utils/check/check_path.py +26 -0
  26. borea/utils/solver/__init__.py +0 -0
  27. borea/utils/solver/solver.py +18 -0
  28. borea/worksite/worksite.py +10 -5
  29. borea/writer/writer_con.py +10 -3
  30. borea/writer/writer_df_to_txt.py +2 -2
  31. borea/writer/writer_opk.py +3 -3
  32. borea/writer/writer_rpc.py +7 -4
  33. borea_tools/spaceresection_opk.py +2 -2
  34. borea_tools/transform_proj_points.py +30 -0
  35. {ign_borea-0.1.5.dist-info → ign_borea-0.2.2.dist-info}/METADATA +2 -3
  36. {ign_borea-0.1.5.dist-info → ign_borea-0.2.2.dist-info}/RECORD +40 -34
  37. {ign_borea-0.1.5.dist-info → ign_borea-0.2.2.dist-info}/WHEEL +1 -1
  38. {ign_borea-0.1.5.dist-info → ign_borea-0.2.2.dist-info}/entry_points.txt +1 -0
  39. {ign_borea-0.1.5.dist-info → ign_borea-0.2.2.dist-info}/LICENSE +0 -0
  40. {ign_borea-0.1.5.dist-info → ign_borea-0.2.2.dist-info}/top_level.txt +0 -0
borea/datastruct/dtm.py CHANGED
@@ -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()
borea/datastruct/shot.py CHANGED
@@ -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
  """
borea/format/conl.py CHANGED
@@ -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",
borea/format/rpc.py CHANGED
@@ -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
@@ -1,13 +1,12 @@
1
1
  """
2
2
  Module for class ProjEngine, transform geodesy
3
3
  """
4
- from dataclasses import dataclass
5
4
  import pyproj
6
5
  import numpy as np
6
+ import pandas as pd
7
7
 
8
8
 
9
- # pylint: disable=unsubscriptable-object
10
- @dataclass
9
+ # pylint: disable=too-many-instance-attributes
11
10
  class TransformGeodesy():
12
11
  """
13
12
  This class provides functions to tranform coordinate system.
@@ -16,50 +15,157 @@ class TransformGeodesy():
16
15
 
17
16
  Args:
18
17
  geoid (list): List of geoid to use.
19
- crs (pyproj): CRS pyproj of the worksite.
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
20
  """
21
- carto_to_geoc = None
22
- geoc_to_carto = None
23
- carto_to_geog = None
24
- geog_to_carto = None
25
- geog_to_geoid = None
26
- geoid_to_geog = None
27
-
28
- def __tf_init__(self, geoid: list, crs: pyproj) -> None:
29
- crs_geoc = pyproj.crs.GeocentricCRS(name=crs.name, datum=crs.datum.name)
30
- crs_geog = pyproj.crs.GeographicCRS(name=crs.name, datum=crs.datum.name)
31
- # Transform cartographic coordinates to geographic coordinates
32
- self.carto_to_geog = pyproj.Transformer.from_crs(crs, crs_geog).transform
33
- # Transform geographic coordinates to cartographic coordinates
34
- self.geog_to_carto = pyproj.Transformer.from_crs(crs_geog, crs).transform
35
- # Transform cartographic coordinates to geocentric coordinates
36
- self.carto_to_geoc = pyproj.Transformer.from_crs(crs, crs_geoc).transform
37
- # Transform geocentric coordinates to cartographic coordinates
38
- self.geoc_to_carto = pyproj.Transformer.from_crs(crs_geoc, crs).transform
39
-
40
- if geoid:
41
- self.tf_geoid(geoid)
42
-
43
- def tf_geoid(self, geoid: list) -> None:
44
- """
45
- Create attribute transform, to transform geographic coordinates to geoide coordinates.
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
46
33
 
47
- Args:
48
- geoid (list): List of geoid to use.
34
+ @property
35
+ def carto_to_geog(self) -> pyproj.Transformer:
49
36
  """
50
- try:
51
- # Transform geoide coordinates to geographic coordinates
52
- self.geoid_to_geog = pyproj.Transformer.from_pipeline(f"+proj=vgridshift "
53
- f"+grids={','.join(geoid)} "
54
- "+multiplier=1").transform
55
- # Transform geographic coordinates to geoide coordinates
56
- self.geog_to_geoid = pyproj.Transformer.from_pipeline(f"+proj=vgridshift "
57
- f"+grids={','.join(geoid)} "
58
- "+multiplier=-1").transform
59
- except pyproj.exceptions.ProjError as e:
60
- raise pyproj.exceptions.ProjError(f"{geoid} The name or path of geotif is incorrect or "
61
- "does not exist in "
62
- f"{pyproj.datadir.get_data_dir()}!!!{e}") from e
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
63
169
 
64
170
  def tranform_height(self, coor: np.ndarray) -> float:
65
171
  """
@@ -83,7 +189,7 @@ class TransformGeodesy():
83
189
  raise ValueError("The geoid has not been entered, "
84
190
  "cannot transform z altitude to height.") from info
85
191
 
86
- if new_z == np.inf:
192
+ if np.all(new_z == np.inf):
87
193
  raise ValueError("out geoid")
88
194
  return new_z
89
195
 
@@ -112,3 +218,23 @@ class TransformGeodesy():
112
218
  if np.all(new_z == np.inf):
113
219
  raise ValueError("out geoid")
114
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
@@ -36,13 +36,13 @@ def args_output_shot(parser: argparse) -> argparse:
36
36
  Returns:
37
37
  argsparse: Parser with argument.
38
38
  """
39
- parser.add_argument('-ob', '--order_axe_output',
39
+ parser.add_argument('--ob', '--order_axe_output',
40
40
  type=str, default=None,
41
41
  help="Order of rotation matrix axes you want in output.")
42
- parser.add_argument('-ou', '--output_unit_angle',
42
+ parser.add_argument('--ou', '--output_unit_angle',
43
43
  type=str, default=None, choices=["degree", "radian", None],
44
44
  help="Unit of the angle of shooting, 'degree' or 'radian'")
45
- parser.add_argument('-oa', '--output_linear_alteration',
45
+ parser.add_argument('--oa', '--output_linear_alteration',
46
46
  type=bool, default=None,
47
47
  help="True if z shot corrected by linear alteration.")
48
48
  return parser