Wed 28 Aug 21:38:52 CEST 2024
This commit is contained in:
		
							parent
							
								
									6991c1db88
								
							
						
					
					
						commit
						62f810fecd
					
				
							
								
								
									
										289
									
								
								src/SimNDT/core/quadtree.pyx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										289
									
								
								src/SimNDT/core/quadtree.pyx
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,289 @@ | ||||||
|  | cimport cython | ||||||
|  | import math | ||||||
|  | 
 | ||||||
|  | import numpy as np | ||||||
|  | cimport numpy as np | ||||||
|  | 
 | ||||||
|  | cdef extern from "math.h": | ||||||
|  |     double sin(double x) | ||||||
|  |     double cos(double x) | ||||||
|  |     double sqrt(double x) | ||||||
|  | 
 | ||||||
|  | DEF pi = 3.141592 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | cdef class Rect: | ||||||
|  |     cdef int x, y, w, h | ||||||
|  |     def __init__(self,  int x,  int y,  int w,  int h): | ||||||
|  |         self.x = x | ||||||
|  |         self.y = y | ||||||
|  |         self.w = w | ||||||
|  |         self.h = h | ||||||
|  | 
 | ||||||
|  |     cpdef collide(self, int x, int y): | ||||||
|  |         return ((self.x <= x <= self.x + self.w) and | ||||||
|  |                  (self.y <= y <= self.y + self.h)) | ||||||
|  | 
 | ||||||
|  |     cpdef intersect(self, Rect rect): | ||||||
|  |         return ((self.x < rect.x + rect.w) and (rect.x < self.x + self.w) and | ||||||
|  |                 (self.y < rect.y + rect.h) and (rect.y < self.y + self.h)) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | cdef class Object: | ||||||
|  |     cdef int x0, y0, w, h | ||||||
|  | 
 | ||||||
|  |     cpdef getRect(self): | ||||||
|  |         return Rect(self.x0, self.y0, self.w, self.h) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | cdef class Circle(Object): | ||||||
|  |     cdef: | ||||||
|  |         int x, y,  r | ||||||
|  |     def __init__(self, int x, int y, int r): | ||||||
|  |         self.x = x | ||||||
|  |         self.y = y | ||||||
|  |         self.r = r | ||||||
|  |         self.x0 = self.x - self.r | ||||||
|  |         self.y0 = self.y - self.r | ||||||
|  |         self.w =  2 * self.r | ||||||
|  |         self.h = 2 * self.r | ||||||
|  | 
 | ||||||
|  |     cpdef area(self): | ||||||
|  |         return pi * self.r**2 | ||||||
|  | 
 | ||||||
|  |     cpdef distance(self, int x, int y): | ||||||
|  |         return math.sqrt((self.x - x)**2 + (self.y - y)**2) | ||||||
|  | 
 | ||||||
|  |     cpdef collide(self, x, y): | ||||||
|  |         return (self.distance(x, y) <= self.r) | ||||||
|  | 
 | ||||||
|  |     cpdef intersect(self, Circle circle): | ||||||
|  |         if (self.distance(circle.x, circle.y) <= self.r + circle.r): | ||||||
|  |             return True | ||||||
|  |         else: | ||||||
|  |             return False | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | cdef class Ellipse2(Object): | ||||||
|  | 
 | ||||||
|  |     cdef public int x, y, a, b | ||||||
|  |     cdef public double theta | ||||||
|  |     cdef double k1_, k2_, k3_ | ||||||
|  | 
 | ||||||
|  |     def __init__(self, int x, int y, int da, int db, double theta): | ||||||
|  |         cdef double c, s | ||||||
|  | 
 | ||||||
|  |         if (da > db): | ||||||
|  |             a = da | ||||||
|  |             b = db | ||||||
|  |         else: | ||||||
|  |             a = db | ||||||
|  |             b = da | ||||||
|  | 
 | ||||||
|  |         c = cos(theta) | ||||||
|  |         s = sin(theta) | ||||||
|  | 
 | ||||||
|  |         #Find k1_, k2_, k3_ - define when a point x,y is on the ellipse | ||||||
|  |         k1_ = sqr(c / a) + sqr(s / b); | ||||||
|  |         k2_ = 2 * s * c * ((1 / sqr(a)) - (1 / sqr(b))); | ||||||
|  |         k3_ = sqr(s / a) + sqr(c / b); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | cdef class Ellipse(Object): | ||||||
|  | 
 | ||||||
|  |     cdef int _x, _y, _a, _b | ||||||
|  |     cdef double _theta | ||||||
|  |     cdef Rect rect | ||||||
|  | 
 | ||||||
|  |     def __init__(self, int x, int y, int a, int b, double theta): | ||||||
|  | 
 | ||||||
|  |         cdef double xmin, xmax, ymin, ymax | ||||||
|  |         cdef np.ndarray[np.float32_t, ndim=1] t, xx, yy | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         self._x = x | ||||||
|  |         self._y = y | ||||||
|  |         self._a = a | ||||||
|  |         self._b = b | ||||||
|  |         self._theta = theta | ||||||
|  | 
 | ||||||
|  |         t	= np.linspace(0,2*pi,20, endpoint=True, dtype=np.float32) | ||||||
|  |         xx	= self._x  + self._a * np.cos(t) | ||||||
|  |         yy	= self._y  + self._b * np.sin(t) | ||||||
|  | 
 | ||||||
|  |         xmin = np.min(xx) | ||||||
|  |         xmax = np.max(xx) | ||||||
|  |         ymin = np.min(yy) | ||||||
|  |         ymax = np.max(yy) | ||||||
|  | 
 | ||||||
|  |         self.w = int(xmax-xmin) | ||||||
|  |         self.h = int(ymax-ymin) | ||||||
|  | 
 | ||||||
|  |         self.x0 = int((xmax+xmin)/2.0) | ||||||
|  |         self.y0 = int((ymax+ymin)/2.0) | ||||||
|  | 
 | ||||||
|  |         self.rect = self.getRect() | ||||||
|  | 
 | ||||||
|  |     cpdef x(self): | ||||||
|  |         return self._x | ||||||
|  | 
 | ||||||
|  |     cpdef y(self): | ||||||
|  |         return self._y | ||||||
|  | 
 | ||||||
|  |     cpdef a(self): | ||||||
|  |         return self._a | ||||||
|  | 
 | ||||||
|  |     cpdef b(self): | ||||||
|  |         return self._b | ||||||
|  | 
 | ||||||
|  |     cpdef theta(self): | ||||||
|  |         return self._theta | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     cpdef area(self): | ||||||
|  |         return pi * self._a * self._b | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     cpdef intersect2(self, Ellipse ellipse): | ||||||
|  | 
 | ||||||
|  |         return ( (np.abs(self.rect.x - ellipse.rect.x) * 2.0 < (self.rect.w + ellipse.rect.w) ) and | ||||||
|  |                (np.abs(self.rect.y - ellipse.rect.y) * 2.0 < (self.rect.h + ellipse.rect.h)) ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     cpdef intersect(self, Ellipse ellipse): | ||||||
|  | 
 | ||||||
|  |         cdef double c, Mb, d, d1, d2, cost, sint | ||||||
|  |         cdef double a2, b2, tmp | ||||||
|  | 
 | ||||||
|  |         a2 = ellipse.a()**2 | ||||||
|  |         b2 = ellipse.b()**2 | ||||||
|  | 
 | ||||||
|  |         cost  =	 cos(ellipse.theta()) | ||||||
|  |         sint  =	 sin(ellipse.theta()) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         tmp = ( ( ( (ellipse.x() - self.x())* cost + ( ellipse.y() - self.y())* sint )**2 )/(a2) + | ||||||
|  |                 ( ( (ellipse.x() - self.x())* sint - ( ellipse.y() - self.y())* cost )**2 )/(b2) ) | ||||||
|  | 
 | ||||||
|  |         if tmp <= 1.0: | ||||||
|  |             return True | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         c =	sqrt(self._a**2 - self._b**2) | ||||||
|  |         cost  =	 c * cos(self._theta) | ||||||
|  |         sint  =	 c * sin(self._theta) | ||||||
|  | 
 | ||||||
|  |         d1	= (ellipse.x() - self._x - cost)**2 + (ellipse.y() - self._y - sint)**2 | ||||||
|  |         d1	= sqrt(d1) | ||||||
|  |         d2	= (ellipse.x() - self._x + cost)**2 + (ellipse.y() - self._y + sint)**2 | ||||||
|  |         d2	= sqrt(d2) | ||||||
|  |         d	= sqrt( (self._x-ellipse.x())**2 + (self._y-ellipse.y())**2 ) | ||||||
|  | 
 | ||||||
|  |         if self._a >= 8*ellipse.a(): | ||||||
|  |             Mb	= 0.15*self._a + ellipse.a() | ||||||
|  | 
 | ||||||
|  |         elif ellipse.a() >= 8*self._a: | ||||||
|  |             Mb	= self._a + 0.15*ellipse.a() | ||||||
|  | 
 | ||||||
|  |         else: | ||||||
|  |             Mb	= self._a + ellipse.a() | ||||||
|  | 
 | ||||||
|  |         if	(d1+d2 <= Mb) or (d <= Mb): | ||||||
|  |             return True | ||||||
|  | 
 | ||||||
|  |         return False | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | cdef class Quadtree: | ||||||
|  |     cdef Quadtree ne, se, sw, nw | ||||||
|  |     cdef Rect rect | ||||||
|  |     cdef int depth | ||||||
|  |     cdef list objs | ||||||
|  | 
 | ||||||
|  |     def __init__(self, int depth, Rect rect): | ||||||
|  |         cdef int w, h, x, y | ||||||
|  | 
 | ||||||
|  |         self.rect  = rect | ||||||
|  |         self.depth = depth | ||||||
|  |         self.ne = None | ||||||
|  |         self.se = None | ||||||
|  |         self.sw = None | ||||||
|  |         self.nw = None | ||||||
|  |         self.objs = list() | ||||||
|  |         if (depth > 1): | ||||||
|  |             w = self.rect.w / 2 | ||||||
|  |             h = self.rect.h / 2 | ||||||
|  |             x = self.rect.x + w | ||||||
|  |             y = self.rect.y | ||||||
|  |             self.ne = Quadtree(depth-1, Rect(x, y, w, h)) | ||||||
|  |             w = self.rect.w / 2 | ||||||
|  |             h = self.rect.h / 2 | ||||||
|  |             x = self.rect.x + w | ||||||
|  |             y = self.rect.y + h | ||||||
|  |             self.se = Quadtree(depth-1, Rect(x, y, w, h)) | ||||||
|  |             w = self.rect.w / 2 | ||||||
|  |             h = self.rect.h / 2 | ||||||
|  |             x = self.rect.x | ||||||
|  |             y = self.rect.y + h | ||||||
|  |             self.sw = Quadtree(depth-1, Rect(x, y, w, h)) | ||||||
|  |             w = self.rect.w / 2 | ||||||
|  |             h = self.rect.h / 2 | ||||||
|  |             x = self.rect.x | ||||||
|  |             y = self.rect.y | ||||||
|  |             self.nw = Quadtree(depth-1, Rect(x, y, w, h)) | ||||||
|  | 
 | ||||||
|  |     def insert(self, Object obj): | ||||||
|  | 
 | ||||||
|  |         if (not self.rect.intersect(obj.getRect())): | ||||||
|  |             return | ||||||
|  |         if (self.depth == 1): | ||||||
|  |             self.objs.append(obj) | ||||||
|  |         else: | ||||||
|  |             self.ne.insert(obj) | ||||||
|  |             self.se.insert(obj) | ||||||
|  |             self.sw.insert(obj) | ||||||
|  |             self.nw.insert(obj) | ||||||
|  | 
 | ||||||
|  |     def query(self, Object obj): | ||||||
|  | 
 | ||||||
|  |         inRange = list() | ||||||
|  |         if (not self.rect.intersect(obj.getRect())): | ||||||
|  |             return inRange | ||||||
|  |         if (self.depth == 1): | ||||||
|  |             for o in self.objs: | ||||||
|  |                 if (obj.intersect(o)): | ||||||
|  |                     inRange.append(o) | ||||||
|  |         else: | ||||||
|  |             inRange.extend(self.ne.query(obj)) | ||||||
|  |             inRange.extend(self.se.query(obj)) | ||||||
|  |             inRange.extend(self.sw.query(obj)) | ||||||
|  |             inRange.extend(self.nw.query(obj)) | ||||||
|  |         return inRange | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def ellipseMatrix(int x0, int y0, int a, int b, double theta, | ||||||
|  |                   np.ndarray[np.int32_t, ndim=2] Image, int Color, | ||||||
|  |                   np.ndarray[np.int32_t, ndim=2] XX,  np.ndarray[np.int32_t, ndim=2] YY): | ||||||
|  | 
 | ||||||
|  |     cdef int a2,b2 | ||||||
|  |     cdef double cost, sint | ||||||
|  | 
 | ||||||
|  |     a2 = a**2 | ||||||
|  |     b2 = b**2 | ||||||
|  |     cost = cos(theta) | ||||||
|  |     sint = sin(theta) | ||||||
|  | 
 | ||||||
|  |     Ellipse = ( ( ( (XX-x0)*cost+(YY-y0)*sint )**2 )/(a2) + | ||||||
|  |                 ( ( (XX-x0)*sint-(YY-y0)*cost )**2 )/(b2) ) | ||||||
|  | 
 | ||||||
|  |     Image[Ellipse < 1.0] = Color | ||||||
|  |     return Image | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user