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)
class PointBase(cengal.entities.copyable.versions.v_0.copyable.CopyableMixin):
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
dimension: int = 0
def copy(self) -> PointBase:
59    def copy(self) -> 'PointBase':
60        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_

def shallow_copy(self) -> PointBase:
62    def shallow_copy(self) -> 'PointBase':
63        raise NotImplementedError

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_

def updated_copy( self, update: Dict) -> PointBase:
65    def updated_copy(self, update: Dict) -> 'PointBase':
66        raise NotImplementedError

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_

dim: int
68    @property
69    def dim(self) -> int:
70        return self.dimension
def clear(self):
75    def clear(self):
76        raise NotImplementedError
class PointDimensionIndexError(builtins.Exception):
79class PointDimensionIndexError(Exception):
80    pass

Common base class for all non-exit exceptions.

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
args
class PointNd(PointBase):
 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
PointNd( dimension: int, *args: Union[Tuple[Sequence[Union[float, int]]], Tuple[Union[float, int]]], **kwargs: Dict[str, Union[float, int]])
 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)
dimension: int = None
def copy(self) -> PointNd:
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_

def shallow_copy(self) -> PointNd:
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_

def updated_copy( self, update: Dict) -> PointNd:
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_

def clear(self):
146    def clear(self):
147        self._point = [self._ndarray_type()] * self.dim
148        if numpy_present:
149            self._point = array(self._point)
def as_list(self) -> List[Union[float, int]]:
183    def as_list(self) -> RawListPointType:
184        return list(self._point)
def crop_to(self, *args) -> PointNd:
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_

def expand_to( self, dimension: int, *args) -> PointNd:
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_

Inherited Members
class Point1d(PointNd):
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)
Point1d( *args: Union[Tuple[Sequence[Union[float, int]]], Tuple[Union[float, int]]], **kwargs: Dict[str, Union[float, int]])
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)
dimension: int = 1
class Point2d(PointNd):
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)
Point2d( *args: Union[Tuple[Sequence[Union[float, int]]], Tuple[Union[float, int]]], **kwargs: Dict[str, Union[float, int]])
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)
dimension: int = 2
class Point3d(PointNd):
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)
Point3d( *args: Union[Tuple[Sequence[Union[float, int]]], Tuple[Union[float, int]]], **kwargs: Dict[str, Union[float, int]])
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)
dimension: int = 3
class PointNdXYZ(PointNd):
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)
PointNdXYZ( dimension: int, *args: Union[Tuple[Sequence[Union[float, int]]], Tuple[Union[float, int]]], **kwargs: Dict[str, Union[float, int]])
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)
dimension: int = None
def convert_point_to_xyz( point: PointNd) -> PointNd:
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)