# -*- coding: utf-8 -*- from math import dist import numpy as np from Model.DB import SQLSubModel from Model.Geometry.Point import Point class PointXYZ(Point, SQLSubModel): _sub_classes = [] def __init__(self, x:float = 0.0, y:float = 0.0, z:float = 0.0, name:str = "", status = None): super(PointXYZ, self).__init__(name=name, status=status) self._x = float(x) self._y = float(y) self._z = float(z) @classmethod def _sql_create(cls, execute): execute(""" CREATE TABLE geometry_pointXYZ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ind INTEGER NOT NULL, name TEXT, x INTEGER NOT NULL, y INTEGER NOT NULL, z INTEGER NOT NULL, profile INTEGER NOT NULL, FOREIGN KEY(profile) REFERENCES profileXYZ(id) ) """) return cls._create_submodel(execute) @classmethod def _sql_update(cls, execute, version): cls._update_submodel(execute, version) return True @classmethod def _sql_load(cls, execute, data = None): points = [] status = data["status"] profile = data["profile"] table = execute( "SELECT ind, name, x, y, z " + "FROM geometry_pointXYZ " + f"WHERE profile = {profile}" ) # Create points list for _ in table: points.append(None) # Fill points list with new point for row in table: ind = row[0] name = row[1] x = row[2] y = row[3] z = row[4] new = cls( name = name, x = x, y = y, z = z, status = status ) points[ind] = new return points def _sql_save(self, execute, data = None): profile = data["profile"] ind = data["ind"] sql = ( "INSERT OR REPLACE INTO " + "geometry_pointXYZ(ind, name, x, y, z, profile) "+ "VALUES (" + f"{ind}, '{self._sql_format(self._name)}', " + f"{self.x}, {self.y}, {self.z}, " + f"{profile}" + ")" ) execute(sql) return True @classmethod def from_data(cls, header, data): point = None try: if len(header) == 0: point = cls( *data ) else: valid_header = {'name', 'x', 'y', 'z'} d = {} for i, v in enumerate(data): h = header[i].strip().lower().split(' ')[0] if h in valid_header: d[h] = v point = cls(**d) except Exception as e: raise ClipboardFormatError(header, data) return point def __repr__(self): return f"({self._x}, {self._y}, {self._z}, {self._name})" @property def x(self): return self._x @x.setter def x(self, value): self._x = float(value) self._status.modified() @property def y(self): return self._y @y.setter def y(self, value): self._y = float(value) self._status.modified() @property def z(self): return self._z @z.setter def z(self, value): self._z = float(value) self._status.modified() def is_nan(self): """ Returns: True if at least one coordinate is as np.nan """ return (np.isnan(self.x) or np.isnan(self.y) or np.isnan(self.z)) def dist(self, p2): return PointXYZ.distance(self, p2) @staticmethod def distance(p1, p2): """Euclidean distance between p1 and p2. Args: p1: A XYZ Point p2: A XYZ Point Returns: Euclidean distance between the two points """ return dist((p1.x, p1.y, p1.z), (p2.x, p2.y, p2.z))