cengal.math.geometry.point.versions.v_0.point
1#!/usr/bin/env python 2# coding=utf-8 3 4# Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space> 5# 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17 18__all__ = ['PointBase', 'PointDimensionIndexError', 'PointNd', 'Point1d', 'Point2d', 'Point3d', 'PointNdXYZ', 'convert_point_to_xyz'] 19 20""" 21Module Docstring 22Docstrings: http://www.python.org/dev/peps/pep-0257/ 23""" 24 25__author__ = "ButenkoMS <gtalk@butenkoms.space>" 26__copyright__ = "Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space>" 27__credits__ = ["ButenkoMS <gtalk@butenkoms.space>", ] 28__license__ = "Apache License, Version 2.0" 29__version__ = "4.4.1" 30__maintainer__ = "ButenkoMS <gtalk@butenkoms.space>" 31__email__ = "gtalk@butenkoms.space" 32# __status__ = "Prototype" 33__status__ = "Development" 34# __status__ = "Production" 35 36 37from copy import copy 38from cengal.entities.copyable import * 39from typing import Any, FrozenSet, Optional, Sequence, List, Set, Tuple, Dict, Union 40numpy_present = True 41try: 42 import numpy as np 43 from numpy import array_equal, array, ndarray 44except: 45 numpy_present = False 46 47RawListPointType = List[Union[float, int]] 48if numpy_present: 49 RawNdarrayPointType = ndarray 50 RawUniversalPointType = Union[RawListPointType, RawNdarrayPointType] 51else: 52 RawUniversalPointType = RawListPointType 53 54 55class PointBase(CopyableMixin): 56 dimension: int = 0 57 58 def copy(self) -> 'PointBase': 59 raise NotImplementedError 60 61 def shallow_copy(self) -> 'PointBase': 62 raise NotImplementedError 63 64 def updated_copy(self, update: Dict) -> 'PointBase': 65 raise NotImplementedError 66 67 @property 68 def dim(self) -> int: 69 return self.dimension 70 71 def __call__(self, *args: Any, **kwds: Any) -> RawListPointType: 72 raise NotImplementedError 73 74 def clear(self): 75 raise NotImplementedError 76 77 78class PointDimensionIndexError(Exception): 79 pass 80 81 82class PointWrongNdarrayTypeError(Exception): 83 pass 84 85 86class PointNd(PointBase): 87 dimension: int = None 88 _dim_names_translation_table: Tuple[Tuple[Set, int]] = tuple() 89 _default_ndarray_type = float 90 _default_shallow_copy = False 91 92 def __init__(self 93 , dimension: int 94 , *args: Union[Tuple[Sequence[Union[float, int]]], Tuple[Union[float, int]]] 95 , **kwargs: Dict[str, Union[float, int]] 96 ) -> None: 97 shallow_copy = kwargs.get('shallow_copy', self._default_shallow_copy) 98 kwargs.pop('shallow_copy', None) 99 if shallow_copy and args and isinstance(args[0], PointNd): 100 first_element = args[0] 101 self.dimension = first_element.dimension 102 self._point = first_element._point 103 self._ndarray_type = first_element._ndarray_type 104 else: 105 if dimension is not None: 106 self.dimension: int = dimension 107 108 self._point: RawListPointType = None 109 self._ndarray_type = kwargs.get('ndarray_type', self._default_ndarray_type) 110 kwargs.pop('ndarray_type', None) 111 if self._ndarray_type not in {int, float}: 112 print(f'Wrong type: {self._ndarray_type}') 113 raise PointWrongNdarrayTypeError 114 115 self.clear() 116 self(*args, **kwargs) 117 118 def __repr__(self): 119 return f'{type(self).__name__}(dimension={self.dimension}, point=({", ".join((str(item) for item in self._point))}), ndarray_type={self._ndarray_type})' 120 121 def copy(self) -> 'PointNd': 122 cls = self.__class__ 123 result = cls.__new__(cls) 124 result.__dict__['dimension'] = self.dimension 125 result.__dict__['_point'] = self._point.copy() 126 result.__dict__['_ndarray_type'] = self._ndarray_type 127 return result 128 129 def shallow_copy(self) -> 'PointNd': 130 cls = self.__class__ 131 result = cls.__new__(cls) 132 result.__dict__['dimension'] = self.dimension 133 result.__dict__['_point'] = self._point 134 result.__dict__['_ndarray_type'] = self._ndarray_type 135 return result 136 137 def updated_copy(self, update: Dict) -> 'PointNd': 138 cls = self.__class__ 139 result = cls.__new__(cls) 140 result.__dict__['dimension'] = self.dimension 141 result.__dict__['_point'] = get_dict_key_with_callable_default(update, '_point', lambda: self._point.copy()) 142 result.__dict__['_ndarray_type'] = self._ndarray_type 143 return result 144 145 def clear(self): 146 self._point = [self._ndarray_type()] * self.dim 147 if numpy_present: 148 self._point = array(self._point) 149 150 def __call__(self 151 , *args: Union[Tuple[Sequence[Union[float, int]]], Tuple[Union[float, int]]] 152 , **kwargs: Dict[str, Union[float, int]] 153 ) -> RawUniversalPointType: 154 if args: 155 first_element = args[0] 156 data = first_element 157 if isinstance(first_element, PointNd): 158 data = first_element() 159 elif isinstance(first_element, (float, int)): 160 data = args 161 162 for index, item in enumerate(data): 163 if index >= self.dim: 164 break 165 166 self._point[index] = item 167 elif kwargs: 168 for dim_name_variants, dim_index in self._dim_names_translation_table: 169 for dim_name in dim_name_variants: 170 if dim_name in kwargs: 171 kwargs[f'n{dim_index}'] = kwargs[dim_name] 172 break 173 174 for dim_index in range(self.dimension): 175 dim_name = f'n{dim_index}' 176 dim_value = kwargs.get(dim_name, None) 177 if dim_value is not None: 178 self._point[dim_index] = dim_value 179 180 return self._point 181 182 def as_list(self) -> RawListPointType: 183 return list(self._point) 184 185 def __setattr__(self, __name: str, __value: Any) -> None: 186 for dim_name_variants, dim_index in self._dim_names_translation_table: 187 if __name in dim_name_variants: 188 self._point[dim_index] = __value 189 return __value 190 191 if __name and __name.startswith('n'): 192 index_str = __name[1:] 193 if index_str.isnumeric(): 194 index = int(index_str) 195 if index < self.dim: 196 self._point[index] = __value 197 return __value 198 else: 199 raise PointDimensionIndexError 200 201 return super().__setattr__(__name, __value) 202 203 def __getattribute__(self, __name: str) -> Any: 204 for dim_name_variants, dim_index in super().__getattribute__('_dim_names_translation_table'): 205 if __name in dim_name_variants: 206 return super().__getattribute__('_point')[dim_index] 207 208 if __name and __name.startswith('n'): 209 index_str = __name[1:] 210 if index_str.isnumeric(): 211 index = int(index_str) 212 if index < super().__getattribute__('dim'): 213 return super().__getattribute__('_point')[index] 214 else: 215 raise PointDimensionIndexError 216 217 return super().__getattribute__(__name) 218 219 def __getitem__(self, index_or_key): 220 if isinstance(index_or_key, int): 221 return self._point[index_or_key] 222 elif isinstance(index_or_key, str): 223 for dim_name_variants, dim_index in self._dim_names_translation_table: 224 if index_or_key in dim_name_variants: 225 return self._point[dim_index] 226 227 if index_or_key and index_or_key.startswith('n'): 228 index_str = index_or_key[1:] 229 if index_str.isnumeric(): 230 index = int(index_str) 231 if index < self.dim: 232 return self._point[index] 233 else: 234 raise PointDimensionIndexError 235 else: 236 raise KeyError 237 238 def __setitem__(self, index_or_key, value): 239 if isinstance(index_or_key, int): 240 self._point[index_or_key] = value 241 elif isinstance(index_or_key, str): 242 for dim_name_variants, dim_index in self._dim_names_translation_table: 243 if index_or_key in dim_name_variants: 244 self._point[dim_index] = value 245 246 if index_or_key and index_or_key.startswith('n'): 247 index_str = index_or_key[1:] 248 if index_str.isnumeric(): 249 index = int(index_str) 250 if index < self.dim: 251 self._point[index] = value 252 else: 253 raise PointDimensionIndexError 254 else: 255 raise KeyError 256 257 def __len__(self): 258 return self.dim 259 260 def crop_to(self, *args) -> 'PointNd': 261 """Example: 262 >> p4 = Point3d(3, 5, 2, 8) 263 >> p3 = convert_point_to_xyz(p4.crop_to('z', 'n0', 3)) 264 >> print(p3) 265 Point3d(2, 3, 8) 266 267 Raises: 268 PointDimensionIndexError: _description_ 269 KeyError: _description_ 270 271 Returns: 272 PointNd: _description_ 273 """ 274 if args: 275 first_item = args[0] 276 data = first_item 277 if isinstance(first_item, (int, str)): 278 data = args 279 280 index_sequence = list() 281 for index_or_key in data: 282 if isinstance(index_or_key, int): 283 index_sequence.append(index_or_key) 284 elif isinstance(index_or_key, str): 285 for dim_name_variants, dim_index in self._dim_names_translation_table: 286 if index_or_key in dim_name_variants: 287 index_sequence.append(dim_index) 288 289 if index_or_key and index_or_key.startswith('n'): 290 index_str = index_or_key[1:] 291 if index_str.isnumeric(): 292 index = int(index_str) 293 if index < self.dim: 294 index_sequence.append(index) 295 else: 296 raise PointDimensionIndexError 297 else: 298 raise KeyError 299 300 croped_data = list() 301 for index in index_sequence: 302 croped_data.append(self._point[index]) 303 304 return PointNd(len(croped_data), croped_data) 305 else: 306 return self.copy() 307 308 def expand_to(self, dimension: int, *args) -> 'PointNd': 309 """Example: 310 >> p2 = Point2d(2, 3) 311 >> p3 = convert_point_to_xyz(p2.expand_to(3, 2, 'n0')) 312 >> print(p3) 313 Point3d(3, 0, 2) 314 315 Args: 316 dimension (int): _description_ 317 *args (Union[Tuple[int], Tuple[str]]): list used to map `point item` with index equal to `list's item index` to `result point item` with index equals to `list's item value`. If value is str: it should starts from 'n' char and continue with (positive) numeric chars only 318 319 Raises: 320 PointDimensionIndexError: when `len(args) > len(self)` 321 KeyError: wrong type of *args or type/format of it's value(s) 322 323 Returns: 324 PointNd: _description_ 325 """ 326 if args: 327 first_item = args[0] 328 data = first_item 329 if isinstance(first_item, (int, str)): 330 data = args 331 332 index_sequence = list() 333 for index_or_key in data: 334 if isinstance(index_or_key, int): 335 index_sequence.append(index_or_key) 336 elif isinstance(index_or_key, str): 337 if index_or_key and index_or_key.startswith('n'): 338 index_str = index_or_key[1:] 339 if index_str.isnumeric(): 340 index = int(index_str) 341 if index < dimension: 342 index_sequence.append(index) 343 else: 344 raise PointDimensionIndexError 345 else: 346 raise KeyError 347 else: 348 raise KeyError 349 else: 350 raise KeyError 351 352 expansion_data = dict() 353 for source_index, destination_index in enumerate(index_sequence): 354 expansion_data[f'n{destination_index}'] = self._point[source_index] 355 356 return PointNd(dimension, **expansion_data) 357 else: 358 return self.copy() 359 360 def __eq__(self, other) -> bool: 361 if isinstance(other, PointNd): 362 if numpy_present: 363 return (self.dim == other.dim) and array_equal(self._point, other._point) 364 else: 365 return (self.dim == other.dim) and (self._point == other._point) 366 367 return False 368 369 def __ne__(self, other) -> bool: 370 return not self.__eq__(other) 371 372 def __hash__(self) -> int: 373 return hash((self.dim, tuple(self._point))) 374 375 def __bool__(self) -> bool: 376 """If not zero point 377 378 Returns: 379 bool: _description_ 380 """ 381 for item in self._point: 382 if item: 383 return True 384 385 return False 386 387 388class Point1d(PointNd): 389 dimension: int = 1 390 _dim_names_translation_table: Tuple[Tuple[Set, int]] = ( 391 ({'x', 'X'}, 0), 392 ) 393 394 def __init__(self 395 , *args: Union[Tuple[Sequence[Union[float, int]]], Tuple[Union[float, int]]] 396 , **kwargs: Dict[str, Union[float, int]] 397 ) -> None: 398 PointNd.__init__(self, None, *args, **kwargs) 399 400 401class Point2d(PointNd): 402 dimension: int = 2 403 _dim_names_translation_table: Tuple[Tuple[Set, int]] = ( 404 ({'x', 'X'}, 0), 405 ({'y', 'Y'}, 1), 406 ) 407 408 def __init__(self 409 , *args: Union[Tuple[Sequence[Union[float, int]]], Tuple[Union[float, int]]] 410 , **kwargs: Dict[str, Union[float, int]] 411 ) -> None: 412 PointNd.__init__(self, None, *args, **kwargs) 413 414 415class Point3d(PointNd): 416 dimension: int = 3 417 _dim_names_translation_table: Tuple[Tuple[Set, int]] = ( 418 ({'x', 'X'}, 0), 419 ({'y', 'Y'}, 1), 420 ({'z', 'Z'}, 2), 421 ) 422 423 def __init__(self 424 , *args: Union[Tuple[Sequence[Union[float, int]]], Tuple[Union[float, int]]] 425 , **kwargs: Dict[str, Union[float, int]] 426 ) -> None: 427 PointNd.__init__(self, None, *args, **kwargs) 428 429 430class PointNdXYZ(PointNd): 431 dimension: int = None 432 _dim_names_translation_table: Tuple[Tuple[Set, int]] = ( 433 ({'x', 'X'}, 0), 434 ({'y', 'Y'}, 1), 435 ({'z', 'Z'}, 2), 436 ) 437 438 def __init__(self 439 , dimension: int 440 , *args: Union[Tuple[Sequence[Union[float, int]]], Tuple[Union[float, int]]] 441 , **kwargs: Dict[str, Union[float, int]] 442 ) -> None: 443 super().__init__(dimension, *args, **kwargs) 444 445 446def convert_point_to_xyz(point: PointNd) -> PointNd: 447 if 1 == point.dim: 448 return Point1d(point, shallow_copy=True) 449 elif 2 == point.dim: 450 return Point2d(point, shallow_copy=True) 451 elif 3 == point.dim: 452 return Point3d(point, shallow_copy=True) 453 elif 3 < point.dim: 454 return PointNdXYZ(point, shallow_copy=True)
56class PointBase(CopyableMixin): 57 dimension: int = 0 58 59 def copy(self) -> 'PointBase': 60 raise NotImplementedError 61 62 def shallow_copy(self) -> 'PointBase': 63 raise NotImplementedError 64 65 def updated_copy(self, update: Dict) -> 'PointBase': 66 raise NotImplementedError 67 68 @property 69 def dim(self) -> int: 70 return self.dimension 71 72 def __call__(self, *args: Any, **kwds: Any) -> RawListPointType: 73 raise NotImplementedError 74 75 def clear(self): 76 raise NotImplementedError
Should make relevant copy of an object (not so general and deep as a deepcopy()). should copy only known object fields. Example: def copy(self): cls = self.__class__ result = cls.__new__(cls) result.__dict__['dimension'] = self.dimension result.__dict__['_point'] = self._point.copy() return result
Raises: NotImplementedError: _description_
Same as copy.copy(self), but should copy only known object fields. Example: def shallow_copy(self): cls = self.__class__ result = cls.__new__(cls) result.__dict__['dimension'] = self.dimension result.__dict__['_point'] = self._point return result
Raises: NotImplementedError: _description_
Will make updated copy of an object. Other behavior should be the same as in the def copy(self)
method.
Example:
# from cengal.data_manipulation.get_dict_key_with_callable_default import get_dict_key_with_callable_default
from cengal.entities.copyable import CopyableMixin, get_dict_key_with_callable_default
def updated_copy(self, update: Dict):
cls = self.__class__
result = cls.__new__(cls)
result.__dict__['dimension'] = update.get('dimension', self.dimension)
result.__dict__['_point'] = get_dict_key_with_callable_default(update, '_point', lambda: self._point.copy())
return result
Raises: NotImplementedError: _description_
Common base class for all non-exit exceptions.
Inherited Members
- builtins.Exception
- Exception
- builtins.BaseException
- with_traceback
- args
87class PointNd(PointBase): 88 dimension: int = None 89 _dim_names_translation_table: Tuple[Tuple[Set, int]] = tuple() 90 _default_ndarray_type = float 91 _default_shallow_copy = False 92 93 def __init__(self 94 , dimension: int 95 , *args: Union[Tuple[Sequence[Union[float, int]]], Tuple[Union[float, int]]] 96 , **kwargs: Dict[str, Union[float, int]] 97 ) -> None: 98 shallow_copy = kwargs.get('shallow_copy', self._default_shallow_copy) 99 kwargs.pop('shallow_copy', None) 100 if shallow_copy and args and isinstance(args[0], PointNd): 101 first_element = args[0] 102 self.dimension = first_element.dimension 103 self._point = first_element._point 104 self._ndarray_type = first_element._ndarray_type 105 else: 106 if dimension is not None: 107 self.dimension: int = dimension 108 109 self._point: RawListPointType = None 110 self._ndarray_type = kwargs.get('ndarray_type', self._default_ndarray_type) 111 kwargs.pop('ndarray_type', None) 112 if self._ndarray_type not in {int, float}: 113 print(f'Wrong type: {self._ndarray_type}') 114 raise PointWrongNdarrayTypeError 115 116 self.clear() 117 self(*args, **kwargs) 118 119 def __repr__(self): 120 return f'{type(self).__name__}(dimension={self.dimension}, point=({", ".join((str(item) for item in self._point))}), ndarray_type={self._ndarray_type})' 121 122 def copy(self) -> 'PointNd': 123 cls = self.__class__ 124 result = cls.__new__(cls) 125 result.__dict__['dimension'] = self.dimension 126 result.__dict__['_point'] = self._point.copy() 127 result.__dict__['_ndarray_type'] = self._ndarray_type 128 return result 129 130 def shallow_copy(self) -> 'PointNd': 131 cls = self.__class__ 132 result = cls.__new__(cls) 133 result.__dict__['dimension'] = self.dimension 134 result.__dict__['_point'] = self._point 135 result.__dict__['_ndarray_type'] = self._ndarray_type 136 return result 137 138 def updated_copy(self, update: Dict) -> 'PointNd': 139 cls = self.__class__ 140 result = cls.__new__(cls) 141 result.__dict__['dimension'] = self.dimension 142 result.__dict__['_point'] = get_dict_key_with_callable_default(update, '_point', lambda: self._point.copy()) 143 result.__dict__['_ndarray_type'] = self._ndarray_type 144 return result 145 146 def clear(self): 147 self._point = [self._ndarray_type()] * self.dim 148 if numpy_present: 149 self._point = array(self._point) 150 151 def __call__(self 152 , *args: Union[Tuple[Sequence[Union[float, int]]], Tuple[Union[float, int]]] 153 , **kwargs: Dict[str, Union[float, int]] 154 ) -> RawUniversalPointType: 155 if args: 156 first_element = args[0] 157 data = first_element 158 if isinstance(first_element, PointNd): 159 data = first_element() 160 elif isinstance(first_element, (float, int)): 161 data = args 162 163 for index, item in enumerate(data): 164 if index >= self.dim: 165 break 166 167 self._point[index] = item 168 elif kwargs: 169 for dim_name_variants, dim_index in self._dim_names_translation_table: 170 for dim_name in dim_name_variants: 171 if dim_name in kwargs: 172 kwargs[f'n{dim_index}'] = kwargs[dim_name] 173 break 174 175 for dim_index in range(self.dimension): 176 dim_name = f'n{dim_index}' 177 dim_value = kwargs.get(dim_name, None) 178 if dim_value is not None: 179 self._point[dim_index] = dim_value 180 181 return self._point 182 183 def as_list(self) -> RawListPointType: 184 return list(self._point) 185 186 def __setattr__(self, __name: str, __value: Any) -> None: 187 for dim_name_variants, dim_index in self._dim_names_translation_table: 188 if __name in dim_name_variants: 189 self._point[dim_index] = __value 190 return __value 191 192 if __name and __name.startswith('n'): 193 index_str = __name[1:] 194 if index_str.isnumeric(): 195 index = int(index_str) 196 if index < self.dim: 197 self._point[index] = __value 198 return __value 199 else: 200 raise PointDimensionIndexError 201 202 return super().__setattr__(__name, __value) 203 204 def __getattribute__(self, __name: str) -> Any: 205 for dim_name_variants, dim_index in super().__getattribute__('_dim_names_translation_table'): 206 if __name in dim_name_variants: 207 return super().__getattribute__('_point')[dim_index] 208 209 if __name and __name.startswith('n'): 210 index_str = __name[1:] 211 if index_str.isnumeric(): 212 index = int(index_str) 213 if index < super().__getattribute__('dim'): 214 return super().__getattribute__('_point')[index] 215 else: 216 raise PointDimensionIndexError 217 218 return super().__getattribute__(__name) 219 220 def __getitem__(self, index_or_key): 221 if isinstance(index_or_key, int): 222 return self._point[index_or_key] 223 elif isinstance(index_or_key, str): 224 for dim_name_variants, dim_index in self._dim_names_translation_table: 225 if index_or_key in dim_name_variants: 226 return self._point[dim_index] 227 228 if index_or_key and index_or_key.startswith('n'): 229 index_str = index_or_key[1:] 230 if index_str.isnumeric(): 231 index = int(index_str) 232 if index < self.dim: 233 return self._point[index] 234 else: 235 raise PointDimensionIndexError 236 else: 237 raise KeyError 238 239 def __setitem__(self, index_or_key, value): 240 if isinstance(index_or_key, int): 241 self._point[index_or_key] = value 242 elif isinstance(index_or_key, str): 243 for dim_name_variants, dim_index in self._dim_names_translation_table: 244 if index_or_key in dim_name_variants: 245 self._point[dim_index] = value 246 247 if index_or_key and index_or_key.startswith('n'): 248 index_str = index_or_key[1:] 249 if index_str.isnumeric(): 250 index = int(index_str) 251 if index < self.dim: 252 self._point[index] = value 253 else: 254 raise PointDimensionIndexError 255 else: 256 raise KeyError 257 258 def __len__(self): 259 return self.dim 260 261 def crop_to(self, *args) -> 'PointNd': 262 """Example: 263 >> p4 = Point3d(3, 5, 2, 8) 264 >> p3 = convert_point_to_xyz(p4.crop_to('z', 'n0', 3)) 265 >> print(p3) 266 Point3d(2, 3, 8) 267 268 Raises: 269 PointDimensionIndexError: _description_ 270 KeyError: _description_ 271 272 Returns: 273 PointNd: _description_ 274 """ 275 if args: 276 first_item = args[0] 277 data = first_item 278 if isinstance(first_item, (int, str)): 279 data = args 280 281 index_sequence = list() 282 for index_or_key in data: 283 if isinstance(index_or_key, int): 284 index_sequence.append(index_or_key) 285 elif isinstance(index_or_key, str): 286 for dim_name_variants, dim_index in self._dim_names_translation_table: 287 if index_or_key in dim_name_variants: 288 index_sequence.append(dim_index) 289 290 if index_or_key and index_or_key.startswith('n'): 291 index_str = index_or_key[1:] 292 if index_str.isnumeric(): 293 index = int(index_str) 294 if index < self.dim: 295 index_sequence.append(index) 296 else: 297 raise PointDimensionIndexError 298 else: 299 raise KeyError 300 301 croped_data = list() 302 for index in index_sequence: 303 croped_data.append(self._point[index]) 304 305 return PointNd(len(croped_data), croped_data) 306 else: 307 return self.copy() 308 309 def expand_to(self, dimension: int, *args) -> 'PointNd': 310 """Example: 311 >> p2 = Point2d(2, 3) 312 >> p3 = convert_point_to_xyz(p2.expand_to(3, 2, 'n0')) 313 >> print(p3) 314 Point3d(3, 0, 2) 315 316 Args: 317 dimension (int): _description_ 318 *args (Union[Tuple[int], Tuple[str]]): list used to map `point item` with index equal to `list's item index` to `result point item` with index equals to `list's item value`. If value is str: it should starts from 'n' char and continue with (positive) numeric chars only 319 320 Raises: 321 PointDimensionIndexError: when `len(args) > len(self)` 322 KeyError: wrong type of *args or type/format of it's value(s) 323 324 Returns: 325 PointNd: _description_ 326 """ 327 if args: 328 first_item = args[0] 329 data = first_item 330 if isinstance(first_item, (int, str)): 331 data = args 332 333 index_sequence = list() 334 for index_or_key in data: 335 if isinstance(index_or_key, int): 336 index_sequence.append(index_or_key) 337 elif isinstance(index_or_key, str): 338 if index_or_key and index_or_key.startswith('n'): 339 index_str = index_or_key[1:] 340 if index_str.isnumeric(): 341 index = int(index_str) 342 if index < dimension: 343 index_sequence.append(index) 344 else: 345 raise PointDimensionIndexError 346 else: 347 raise KeyError 348 else: 349 raise KeyError 350 else: 351 raise KeyError 352 353 expansion_data = dict() 354 for source_index, destination_index in enumerate(index_sequence): 355 expansion_data[f'n{destination_index}'] = self._point[source_index] 356 357 return PointNd(dimension, **expansion_data) 358 else: 359 return self.copy() 360 361 def __eq__(self, other) -> bool: 362 if isinstance(other, PointNd): 363 if numpy_present: 364 return (self.dim == other.dim) and array_equal(self._point, other._point) 365 else: 366 return (self.dim == other.dim) and (self._point == other._point) 367 368 return False 369 370 def __ne__(self, other) -> bool: 371 return not self.__eq__(other) 372 373 def __hash__(self) -> int: 374 return hash((self.dim, tuple(self._point))) 375 376 def __bool__(self) -> bool: 377 """If not zero point 378 379 Returns: 380 bool: _description_ 381 """ 382 for item in self._point: 383 if item: 384 return True 385 386 return False
93 def __init__(self 94 , dimension: int 95 , *args: Union[Tuple[Sequence[Union[float, int]]], Tuple[Union[float, int]]] 96 , **kwargs: Dict[str, Union[float, int]] 97 ) -> None: 98 shallow_copy = kwargs.get('shallow_copy', self._default_shallow_copy) 99 kwargs.pop('shallow_copy', None) 100 if shallow_copy and args and isinstance(args[0], PointNd): 101 first_element = args[0] 102 self.dimension = first_element.dimension 103 self._point = first_element._point 104 self._ndarray_type = first_element._ndarray_type 105 else: 106 if dimension is not None: 107 self.dimension: int = dimension 108 109 self._point: RawListPointType = None 110 self._ndarray_type = kwargs.get('ndarray_type', self._default_ndarray_type) 111 kwargs.pop('ndarray_type', None) 112 if self._ndarray_type not in {int, float}: 113 print(f'Wrong type: {self._ndarray_type}') 114 raise PointWrongNdarrayTypeError 115 116 self.clear() 117 self(*args, **kwargs)
122 def copy(self) -> 'PointNd': 123 cls = self.__class__ 124 result = cls.__new__(cls) 125 result.__dict__['dimension'] = self.dimension 126 result.__dict__['_point'] = self._point.copy() 127 result.__dict__['_ndarray_type'] = self._ndarray_type 128 return result
Should make relevant copy of an object (not so general and deep as a deepcopy()). should copy only known object fields. Example: def copy(self): cls = self.__class__ result = cls.__new__(cls) result.__dict__['dimension'] = self.dimension result.__dict__['_point'] = self._point.copy() return result
Raises: NotImplementedError: _description_
130 def shallow_copy(self) -> 'PointNd': 131 cls = self.__class__ 132 result = cls.__new__(cls) 133 result.__dict__['dimension'] = self.dimension 134 result.__dict__['_point'] = self._point 135 result.__dict__['_ndarray_type'] = self._ndarray_type 136 return result
Same as copy.copy(self), but should copy only known object fields. Example: def shallow_copy(self): cls = self.__class__ result = cls.__new__(cls) result.__dict__['dimension'] = self.dimension result.__dict__['_point'] = self._point return result
Raises: NotImplementedError: _description_
138 def updated_copy(self, update: Dict) -> 'PointNd': 139 cls = self.__class__ 140 result = cls.__new__(cls) 141 result.__dict__['dimension'] = self.dimension 142 result.__dict__['_point'] = get_dict_key_with_callable_default(update, '_point', lambda: self._point.copy()) 143 result.__dict__['_ndarray_type'] = self._ndarray_type 144 return result
Will make updated copy of an object. Other behavior should be the same as in the def copy(self)
method.
Example:
# from cengal.data_manipulation.get_dict_key_with_callable_default import get_dict_key_with_callable_default
from cengal.entities.copyable import CopyableMixin, get_dict_key_with_callable_default
def updated_copy(self, update: Dict):
cls = self.__class__
result = cls.__new__(cls)
result.__dict__['dimension'] = update.get('dimension', self.dimension)
result.__dict__['_point'] = get_dict_key_with_callable_default(update, '_point', lambda: self._point.copy())
return result
Raises: NotImplementedError: _description_
261 def crop_to(self, *args) -> 'PointNd': 262 """Example: 263 >> p4 = Point3d(3, 5, 2, 8) 264 >> p3 = convert_point_to_xyz(p4.crop_to('z', 'n0', 3)) 265 >> print(p3) 266 Point3d(2, 3, 8) 267 268 Raises: 269 PointDimensionIndexError: _description_ 270 KeyError: _description_ 271 272 Returns: 273 PointNd: _description_ 274 """ 275 if args: 276 first_item = args[0] 277 data = first_item 278 if isinstance(first_item, (int, str)): 279 data = args 280 281 index_sequence = list() 282 for index_or_key in data: 283 if isinstance(index_or_key, int): 284 index_sequence.append(index_or_key) 285 elif isinstance(index_or_key, str): 286 for dim_name_variants, dim_index in self._dim_names_translation_table: 287 if index_or_key in dim_name_variants: 288 index_sequence.append(dim_index) 289 290 if index_or_key and index_or_key.startswith('n'): 291 index_str = index_or_key[1:] 292 if index_str.isnumeric(): 293 index = int(index_str) 294 if index < self.dim: 295 index_sequence.append(index) 296 else: 297 raise PointDimensionIndexError 298 else: 299 raise KeyError 300 301 croped_data = list() 302 for index in index_sequence: 303 croped_data.append(self._point[index]) 304 305 return PointNd(len(croped_data), croped_data) 306 else: 307 return self.copy()
Example:
p4 = Point3d(3, 5, 2, 8) p3 = convert_point_to_xyz(p4.crop_to('z', 'n0', 3)) print(p3) Point3d(2, 3, 8)
Raises: PointDimensionIndexError: _description_ KeyError: _description_
Returns: PointNd: _description_
309 def expand_to(self, dimension: int, *args) -> 'PointNd': 310 """Example: 311 >> p2 = Point2d(2, 3) 312 >> p3 = convert_point_to_xyz(p2.expand_to(3, 2, 'n0')) 313 >> print(p3) 314 Point3d(3, 0, 2) 315 316 Args: 317 dimension (int): _description_ 318 *args (Union[Tuple[int], Tuple[str]]): list used to map `point item` with index equal to `list's item index` to `result point item` with index equals to `list's item value`. If value is str: it should starts from 'n' char and continue with (positive) numeric chars only 319 320 Raises: 321 PointDimensionIndexError: when `len(args) > len(self)` 322 KeyError: wrong type of *args or type/format of it's value(s) 323 324 Returns: 325 PointNd: _description_ 326 """ 327 if args: 328 first_item = args[0] 329 data = first_item 330 if isinstance(first_item, (int, str)): 331 data = args 332 333 index_sequence = list() 334 for index_or_key in data: 335 if isinstance(index_or_key, int): 336 index_sequence.append(index_or_key) 337 elif isinstance(index_or_key, str): 338 if index_or_key and index_or_key.startswith('n'): 339 index_str = index_or_key[1:] 340 if index_str.isnumeric(): 341 index = int(index_str) 342 if index < dimension: 343 index_sequence.append(index) 344 else: 345 raise PointDimensionIndexError 346 else: 347 raise KeyError 348 else: 349 raise KeyError 350 else: 351 raise KeyError 352 353 expansion_data = dict() 354 for source_index, destination_index in enumerate(index_sequence): 355 expansion_data[f'n{destination_index}'] = self._point[source_index] 356 357 return PointNd(dimension, **expansion_data) 358 else: 359 return self.copy()
Example:
p2 = Point2d(2, 3) p3 = convert_point_to_xyz(p2.expand_to(3, 2, 'n0')) print(p3) Point3d(3, 0, 2)
Args:
dimension (int): _description_
*args (Union[Tuple[int], Tuple[str]]): list used to map point item
with index equal to list's item index
to result point item
with index equals to list's item value
. If value is str: it should starts from 'n' char and continue with (positive) numeric chars only
Raises:
PointDimensionIndexError: when len(args) > len(self)
KeyError: wrong type of *args or type/format of it's value(s)
Returns: PointNd: _description_
389class Point1d(PointNd): 390 dimension: int = 1 391 _dim_names_translation_table: Tuple[Tuple[Set, int]] = ( 392 ({'x', 'X'}, 0), 393 ) 394 395 def __init__(self 396 , *args: Union[Tuple[Sequence[Union[float, int]]], Tuple[Union[float, int]]] 397 , **kwargs: Dict[str, Union[float, int]] 398 ) -> None: 399 PointNd.__init__(self, None, *args, **kwargs)
Inherited Members
402class Point2d(PointNd): 403 dimension: int = 2 404 _dim_names_translation_table: Tuple[Tuple[Set, int]] = ( 405 ({'x', 'X'}, 0), 406 ({'y', 'Y'}, 1), 407 ) 408 409 def __init__(self 410 , *args: Union[Tuple[Sequence[Union[float, int]]], Tuple[Union[float, int]]] 411 , **kwargs: Dict[str, Union[float, int]] 412 ) -> None: 413 PointNd.__init__(self, None, *args, **kwargs)
Inherited Members
416class Point3d(PointNd): 417 dimension: int = 3 418 _dim_names_translation_table: Tuple[Tuple[Set, int]] = ( 419 ({'x', 'X'}, 0), 420 ({'y', 'Y'}, 1), 421 ({'z', 'Z'}, 2), 422 ) 423 424 def __init__(self 425 , *args: Union[Tuple[Sequence[Union[float, int]]], Tuple[Union[float, int]]] 426 , **kwargs: Dict[str, Union[float, int]] 427 ) -> None: 428 PointNd.__init__(self, None, *args, **kwargs)
Inherited Members
431class PointNdXYZ(PointNd): 432 dimension: int = None 433 _dim_names_translation_table: Tuple[Tuple[Set, int]] = ( 434 ({'x', 'X'}, 0), 435 ({'y', 'Y'}, 1), 436 ({'z', 'Z'}, 2), 437 ) 438 439 def __init__(self 440 , dimension: int 441 , *args: Union[Tuple[Sequence[Union[float, int]]], Tuple[Union[float, int]]] 442 , **kwargs: Dict[str, Union[float, int]] 443 ) -> None: 444 super().__init__(dimension, *args, **kwargs)
Inherited Members
447def convert_point_to_xyz(point: PointNd) -> PointNd: 448 if 1 == point.dim: 449 return Point1d(point, shallow_copy=True) 450 elif 2 == point.dim: 451 return Point2d(point, shallow_copy=True) 452 elif 3 == point.dim: 453 return Point3d(point, shallow_copy=True) 454 elif 3 < point.dim: 455 return PointNdXYZ(point, shallow_copy=True)