Python: how to calculate the bucket points - python

import numpy as np
import math
length = 10
points = [(1,2,3),(1,1,1),(23, 29, 0),(17, 0, 5)]
bucketed_points = {}
max_x = max([x for (x,y,z) in points])
max_y = max([y for (x,y,z) in points])
max_z = max([z for (x,y,z) in points])
x_buckets = int(max_x)/length + 1
y_buckets = int(max_y)/length + 1
z_buckets = int(max_z)/length + 1
for x in range(0, int(x_buckets)):
for y in range(0, int(y_buckets)):
for z in range(0, int(z_buckets)):
bucketed_points["{0},{1},{2}".format(x, y, z)] = []
for point in points:
# Here's where we actually put them in buckets
x, y, z = point
x, y, z = map(lambda a: int(math.floor(a/length)), [x, y, z])
bucketed_points["{0},{1},{2}".format(x, y, z)].append(point)
print(bucketed_points)
I have four points (1,2,3), (1,1,1),(23, 29, 0), (17, 0, 5), what I need to do is moving all the points to the new location (0,0,0), (0,0,0), (20,30,0), (20,0,10) which represent the center points for a cube whose side length equals 10 (length = 10).

Related

Using uniform cost search on a matrix in python

Good day, I have an 11x11 matrix (shown below) where the 0s represent open spaces and the 1s represent walls. The horizontal and vertical movements are weighted at 1 and the diagonal movements are weighted at sqrt(2) The matrix looks as follows:
`board = [[0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,1,1,1,0,1,1,0],
[0,1,0,0,0,0,1,1,0,1,1,0],
[0,1,1,0,0,0,0,0,0,1,1,0],
[0,1,1,1,0,0,0,0,0,1,1,0],
[0,1,1,1,1,0,0,0,0,1,1,0],
[0,1,1,1,1,1,1,1,1,1,1,0],
[1,1,1,1,1,1,1,1,1,1,1,0],
[0,0,0,0,0,0,0,0,0,0,1,0],
[0,0,0,0,0,0,0,0,0,0,1,0],
[0,0,1,1,1,1,1,1,1,1,1,0],
[0,0,0,0,0,0,0,0,0,0,0,0]]`
My goal is to write a Uniform cost search code in python to find the most cost effective path from a starting point (e.g [1,1]) to an end point (e.g [5,1]). Most of the code I have come across works with graphs and not matrices. I need help with working around this with a matrix.
I am fairly new at python and all help and advice will be highly appreciated. I am using python 3.
Since nobody seems to know an easy answer to this question I will post my (hopefully correct) answer. The used approach is not really efficient and based on a flood fill like algorithm.
First we define a list with all possible directions. Those are represented by a lambda function which return the new indices (xand y), the current weight and the current path:
from math import sqrt
dirs = [
lambda x, y, z, p: (x, y - 1, z + 1, p + [(x, y)]), # up
lambda x, y, z, p: (x, y + 1, z + 1, p + [(x, y)]), # down
lambda x, y, z, p: (x - 1, y, z + 1, p + [(x, y)]), # left
lambda x, y, z, p: (x + 1, y, z + 1, p + [(x, y)]), # right
lambda x, y, z, p: (x - 1, y - 1, z + sqrt(2), p + [(x, y)]), # up left
lambda x, y, z, p: (x + 1, y - 1, z + sqrt(2), p + [(x, y)]), # up right
lambda x, y, z, p: (x - 1, y + 1, z + sqrt(2), p + [(x, y)]), # down left
lambda x, y, z, p: (x + 1, y + 1, z + sqrt(2), p + [(x, y)]) # down right
]
Then we create some functions. The first one checks if the indices calculated by the directions are valid indices for the matrix and that there is no wall.
def valid(grid, x, y):
return 0 <= x < len(grid) and 0 <= y < len(grid[0]) and grid[x][y] == 0
The adjacent function yields every direction for every cell at the frontier (imagine it like a wave) and the flood function moves the wave one step forwards and replaces the old step with walls (1).
def adjacent(grid, frontier):
for (x, y, z, p) in frontier:
for d in dirs:
nx, ny, nz, np = d(x, y, z, p)
if valid(grid, nx, ny):
yield (nx, ny, nz, np)
def flood(grid, lst):
res = list(adjacent(grid, frontier))
for (x, y, z, p) in frontier:
grid[x][y] = 1
return res
In the following funtion we call the defined functions and return a tuple of the weight of the shortest path and the shortest path.
def shortest(grid, start, end):
start, end = tuple(start), tuple(end)
frontier = [(start[0], start[1], 0, [])]
res = []
while frontier and grid[end[0]][end[1]] == 0:
frontier = flood(grid, frontier)
for (x, y, z, p) in frontier:
if (x, y) == end:
res.append((z, p + [(x, y)]))
if not res:
return ()
return sorted(res)[0]
I tested it for (0, 0) to (8, 8) and the output seems plausable. It will probably fail if the cost for two horizontal / vertical steps is lower than the cost for the equal diagonal step.
EDIT: Result for (0, 0) to (8, 8) with P as path:
[[P,P,P,P,P,P,P,P,P,P,P,0],
[0,0,0,0,0,1,1,1,0,1,1,P],
[0,1,0,0,0,0,1,1,0,1,1,P],
[0,1,1,0,0,0,0,0,0,1,1,P],
[0,1,1,1,0,0,0,0,0,1,1,P],
[0,1,1,1,1,0,0,0,0,1,1,P],
[0,1,1,1,1,1,1,1,1,1,1,P],
[1,1,1,1,1,1,1,1,1,1,1,P],
[0,0,0,P,P,P,P,P,P,P,1,P],
[0,0,P,0,0,0,0,0,0,0,1,P],
[0,P,1,1,1,1,1,1,1,1,1,P],
[0,0,P,P,P,P,P,P,P,P,P,0]]
Weight: 39.071067811865476
EDIT 2: Add copy paste version.
from math import sqrt
board = [[0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,1,1,1,0,1,1,0],
[0,1,0,0,0,0,1,1,0,1,1,0],
[0,1,1,0,0,0,0,0,0,1,1,0],
[0,1,1,1,0,0,0,0,0,1,1,0],
[0,1,1,1,1,0,0,0,0,1,1,0],
[0,1,1,1,1,1,1,1,1,1,1,0],
[1,1,1,1,1,1,1,1,1,1,1,0],
[0,0,0,0,0,0,0,0,0,0,1,0],
[0,0,0,0,0,0,0,0,0,0,1,0],
[0,0,1,1,1,1,1,1,1,1,1,0],
[0,0,0,0,0,0,0,0,0,0,0,0]]
dirs = [
lambda x, y, z, p: (x, y - 1, z + 1, p + [(x, y)]), # up
lambda x, y, z, p: (x, y + 1, z + 1, p + [(x, y)]), # down
lambda x, y, z, p: (x - 1, y, z + 1, p + [(x, y)]), # left
lambda x, y, z, p: (x + 1, y, z + 1, p + [(x, y)]), # right
lambda x, y, z, p: (x - 1, y - 1, z + sqrt(2), p + [(x, y)]), # up left
lambda x, y, z, p: (x + 1, y - 1, z + sqrt(2), p + [(x, y)]), # up right
lambda x, y, z, p: (x - 1, y + 1, z + sqrt(2), p + [(x, y)]), # down left
lambda x, y, z, p: (x + 1, y + 1, z + sqrt(2), p + [(x, y)]) # down right
]
def valid(grid, x, y):
return 0 <= x < len(grid) and 0 <= y < len(grid[0]) and grid[x][y] == 0
def adjacent(grid, frontier):
for (x, y, z, p) in frontier:
for d in dirs:
nx, ny, nz, np = d(x, y, z, p)
if valid(grid, nx, ny):
yield (nx, ny, nz, np)
def flood(grid, frontier):
res = list(adjacent(grid, frontier))
for (x, y, z, p) in frontier:
grid[x][y] = 1
return res
def shortest(grid, start, end):
start, end = tuple(start), tuple(end)
frontier = [(start[0], start[1], 0, [])]
res = []
while frontier and grid[end[0]][end[1]] == 0:
frontier = flood(grid, frontier)
for (x, y, z, p) in frontier:
if (x, y) == end:
res.append((z, p + [(x, y)]))
if not res:
return ()
return sorted(res)[0]
print(shortest(board, (0, 0), (8, 8)))

Get all lattice points lying inside a Shapely polygon

I need to find all the lattice points inside and on a polygon.
Input:
from shapely.geometry import Polygon, mapping
sh_polygon = Polygon(((0,0), (2,0), (2,2), (0,2)))
Output:
(0, 0), (1, 0), (2, 0), (0, 1), (1, 1), (2, 1), (0, 2), (1, 2), (2, 2)
Please suggest if there is a way to get the expected result with or without using Shapely.
I have written this piece of code that gives points inside the polygon, but it doesn't give points on it. Also is there a better way to do the same thing:
from shapely.geometry import Polygon, Point
def get_random_point_in_polygon(poly):
(minx, miny, maxx, maxy) = poly.bounds
minx = int(minx)
miny = int(miny)
maxx = int(maxx)
maxy = int(maxy)
print("poly.bounds:", poly.bounds)
a = []
for x in range(minx, maxx+1):
for y in range(miny, maxy+1):
p = Point(x, y)
if poly.contains(p):
a.append([x, y])
return a
p = Polygon([(0,0), (2,0), (2,2), (0,2)])
point_in_poly = get_random_point_in_polygon(p)
print(len(point_in_poly))
print(point_in_poly)
Output:
poly.bounds: (0.0, 0.0, 2.0, 2.0)
1
[[1, 1]]
I have simplified my problem. Actually, I need to find all points inside and on a square with corners: (77,97), (141,101), (136,165), (73,160).
I would approach the problem as follows.
First, define a grid of lattice points. One could use, for example, itertools.product:
from itertools import product
from shapely.geometry import MultiPoint
points = MultiPoint(list(product(range(5), repeat=2)))
points = MultiPoint(list(product(range(10), range(5))))
or any NumPy solution from Cartesian product of x and y array points into single array of 2D points:
import numpy as np
x = np.linspace(0, 1, 5)
y = np.linspace(0, 1, 10)
points = MultiPoint(np.transpose([np.tile(x, len(y)), np.repeat(y, len(x))]))
Then, using intersection method of Shapely we can get those lattice points that lie both inside and on the boundary of the given polygon.
For your given example:
p = Polygon([(0, 0), (2, 0), (2, 2), (0, 2)])
xmin, ymin, xmax, ymax = p.bounds
x = np.arange(np.floor(xmin), np.ceil(xmax) + 1) # array([0., 1., 2.])
y = np.arange(np.floor(ymin), np.ceil(ymax) + 1) # array([0., 1., 2.])
points = MultiPoint(np.transpose([np.tile(x, len(y)), np.repeat(y, len(x))]))
result = points.intersection(p)
And for a bit more sophisticated example:
p = Polygon([(-4.85571368308564, 37.1753007358263),
(-4.85520937147867, 37.174925051829),
(-4.85259349198842, 37.1783463712614),
(-4.85258684662671, 37.1799609243756),
(-4.85347524651836, 37.1804461589773),
(-4.85343407576431, 37.182006629169),
(-4.85516283166052, 37.1842384372115),
(-4.85624511894443, 37.1837967179202),
(-4.85533824429553, 37.1783762575331),
(-4.85674599573635, 37.177038261295),
(-4.85571368308564, 37.1753007358263)])
xmin, ymin, xmax, ymax = p.bounds # -4.85674599573635, 37.174925051829, -4.85258684662671, 37.1842384372115
n = 1e3
x = np.arange(np.floor(xmin * n) / n, np.ceil(xmax * n) / n, 1 / n) # array([-4.857, -4.856, -4.855, -4.854, -4.853])
y = np.arange(np.floor(ymin * n) / n, np.ceil(ymax * n) / n, 1 / n) # array([37.174, 37.175, 37.176, 37.177, 37.178, 37.179, 37.18 , 37.181, 37.182, 37.183, 37.184, 37.185])
points = MultiPoint(np.transpose([np.tile(x, len(y)), np.repeat(y, len(x))]))
result = points.intersection(p)
Is there not a function that will find lattice points that lie on a line? Those are the only ones you're missing. They are simply solutions to the line segment's defining equation. If not, it's easy enough to write the algorithm yourself, finding the points by brute force.
Do the following for each edge (p1, p2) of the polygon.
p1 = (x1, y1)
p2 = (x2, y2)
xdiff = x2 - x1
ydiff = y2 - y1
# Find the line's equation, y = mx + b
m = ydiff / xdiff
b = y1 - m*x1
for xval in range(x1+1, x2):
yval = m * xval + b
if int(yval) == yval:
# add (xval, yval) to your list of points
I've left details up to you: make sure that x1 < x2 (or adapt otherwise), handle a vertical segment, etc. This isn't particularly elegant, but it's fast, easy to implement, and easy to debug.

CORDIC algorithm returning bad numbers

I started to implement a CORDIC algorithm from zero and I don't know what I'm missing, here's what I have so far.
import math
from __future__ import division
# angles
n = 5
angles = []
for i in range (0, n):
angles.append(math.atan(1/math.pow(2,i)))
# constants
kn = []
fator = 1.0
for i in range (0, n):
fator = fator * (1 / math.pow(1 + (2**(-i))**2, (1/2)))
kn.append(fator)
# taking an initial point p = (x,y) = (1,0)
z = math.pi/2 # Angle to be calculated
x = 1
y = 0
for i in range (0, n):
if (z < 0):
x = x + y*(2**(-1*i))
y = y - x*(2**(-1*i))
z = z + angles[i]
else:
x = x - y*(2**(-1*i))
y = y + x*(2**(-1*i))
z = z - angles[i]
x = x * kn[n-1]
y = y * kn[n-1]
print x, y
When I plug z = π/2 it returns 0.00883479322917 and 0.107149125055, which makes no sense.
Any help will be great!
#edit, I made some changes and now my code has this lines instead of those ones
for i in range (0, n):
if (z < 0):
x = x0 + y0*(2**(-1*i))
y = y0 - x0*(2**(-1*i))
z = z + angles[i]
else:
x = x0 - y0*(2**(-1*i))
y = y0 + x0*(2**(-1*i))
z = z - angles[i]
x0 = x
y0 = y
x = x * kn[n-1]
y = y * kn[n-1]
Now it's working way better, I had the problem because I wasn't using temporary variables as x0 and y0, now when I plug z = pi/2 it gives me better numbers as (4.28270993661e-13, 1.0) :)

Use quiver to plot a 2D vector map

I have a set of coordinate pairs (x, y) and I want to plot this set using quiver. I tried to check other relevant questions but I'm still struggling with this.
Imagine I want to plot 4 vectors with two arrays with x and y coordinates:
x = arange(0, 3)
y = arange(0, 3)
# vectors x coordinate values
fx = (0, 1, 1, 2)
# vectors y coordinate values
fy = (1, 0, 1, 2)
X, Y = meshgrid(x, y)
Q = quiver(X, Y, fx, fy)
The result is not 4 but 9 vectors, why?
You can pass four 1-D arrays to plt.quiver:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0, 4)
y = np.arange(0, 4)
# vectors x coordinate values
fx = (0, 1, 1, 2)
# vectors y coordinate values
fy = (1, 0, 1, 2)
Q = plt.quiver(x, y, fx, fy)
plt.xlim(-1, 4)
plt.ylim(-1, 4)
plt.show()
yields

Python checking if a point is in sphere with center x, y ,z

I'm trying to check if a point is within a sphere with a center point of (x, y, z) where (x, y, z) is not (0, 0, 0).
This code I'm using to generate the points I want to check:
def generatecoords(self, i):
x, y, z = generatepoint()
if i >= 1:
valid = False
while valid == False:
coords = self.checkpoint(x, y, z)
for b in world.starlist:
if coords == world.starlist[b].coords:
coords = self.checkpoint(x, y, z)
else:
valid = True
else:
coords = self.checkpoint(x, y, z)
return coords
def checkpoint(self, x, y, z):
d = math.sqrt(x * x + y * y + z * z)
while d >= self.radius:
x, y, z = generatepoint()
d = math.sqrt(x * x + y * y + z * z)
coords = (int(x), int(y), int(z))
return coords
def generatepoint():
x, y, z = [int(random.uniform(-self.radius, self.radius)) \
for b in range(3)]
return x, y, z
These function are called in a for loop to generate the points in a dictionary, while also checking the unlikely chance that points aren't placed on top of another(mostly because I can).
I trying to figure out what I need to add to math.sqrt(x * x + y * y + z * z) so that it accounts for a center that isn't (0, 0, 0). I do know of one way to do it, but it would require several lines of code and I'd rather do it in one. I would have asked this in the comments of the answer in another question, but I'm not allowed to comment on answers yet.
The formula is:
A point (x,y,z) is inside the sphere with center (cx,cy,cz) and radius r if
(x - cx)^2 + (y - cy)^2 + (z - cz)^2 < r^2
Here is a very short function that returns True if the point is in the sphere, and False if not.
The inputs are two numpy arrays: point = [x,y,z] and ref = [x,y,z] and the radius should be a float.
import numpy as np
def inSphere(self, point, ref, radius):
# Calculate the difference between the reference and measuring point
diff = np.subtract(point, ref)
# Calculate square length of vector (distance between ref and point)^2
dist = np.sum(np.power(diff, 2))
# If dist is less than radius^2, return True, else return False
return dist < radius ** 2

Categories

Resources