Need help finding test cases for the counting rectangle problem - python

I have this problem:
Given a list of points in Euclidean coordinates, count the number of distinct, non-zero area rectangles can be formed by any 4 points in the input list (Axis-alignment does not matter)
I hope you guys can find edge cases to attack my solution.
This is my code: https://pastebin.com/fzzJEwY1
def countRectangles(intPoints):
ans = 0
def getDistance(point1, point2):
x1, y1 = point1[0], point1[1]
x2, y2 = point2[0], point2[1]
return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)
def getMidPoint(point1, point2):
x1, y1 = point1[0], point1[1]
x2, y2 = point2[0], point2[1]
midPoint = ((x1 + x2) / 2, (y1 + y2) / 2)
return midPoint
def intToFloatList(points):
for i, point in enumerate(points):
curX, curY = point[0], point[1]
points[i] = (float(curX), float(curY))
return points
distanceMidPoint_PointsMap = {}
points = intToFloatList(intPoints)
for i, point in enumerate(points):
for j in range(i+1, len(points)):
nextPoint = points[j]
curSqrdDistance = getDistance(point, nextPoint)
curMidPoint = getMidPoint(point, nextPoint)
key = (curSqrdDistance, curMidPoint)
if key not in distanceMidPoint_PointsMap:
distanceMidPoint_PointsMap[key] = set()
distanceMidPoint_PointsMap[key].add((point, nextPoint))
for key, val in distanceMidPoint_PointsMap.items():
if len(val) > 1:
ans += len(val)
return ans // 2
I have tried both axis-aligned and non-axis-aligned test cases and my solution passed.

Related

Handle overlapping lines in intersection of 2 lines

This python code finds the intersection for lines and I have modified it for handling colinear lines so it returns the intersection of 2 lines when they are collinear.
How to handle cases when they are overlapping in that case it should not return any point of intersection.
The output for this comes
(2,0)
But it should not return an intersection as both of the 2 lines are overlapped.
Input
line1 = ((0, 0), (2, 0))
line2 = ((1, 0), (2, 0))
Code
def line_intersection(line1, line2):
x1, y1 = line1[0]
x2, y2 = line1[1]
x3, y3 = line2[0]
x4, y4 = line2[1]
# Check if the lines are collinear
if (y2 - y1) * (x4 - x3) == (y4 - y3) * (x2 - x1):
# Check if they have a common endpoint
if (x1, y1) == (x3, y3) or (x1, y1) == (x4, y4) or (x2, y2) == (x3, y3) or (x2, y2) == (x4, y4):
return (x1, y1) if (x1, y1) == (x3, y3) or (x1, y1) == (x4, y4) else (x2, y2)
else:
# Return "overlapping" if the lines overlap
if max(x1, x2) >= min(x3, x4) and min(x1, x2) <= max(x3, x4) and max(y1, y2) >= min(y3, y4) and min(y1, y2) <= max(y3, y4):
return "overlapping"
else:
return None
def det(a, b):
return a[0] * b[1] - a[1] * b[0]
xdiff = (x1 - x3, x2 - x4)
ydiff = (y1 - y3, y2 - y4)
div = det(xdiff, ydiff)
if div == 0:
return None
d = (det((x1, y1), (x2, y2)), det((x3, y3), (x4, y4)))
x = det(d, xdiff) / div
y = det(d, ydiff) / div
point = (x, y)
# Check if the intersection point is on both lines
if (x >= min(x1, x2) and x <= max(x1, x2)) and (y >= min(y1, y2) and y <= max(y1, y2)) and (x >= min(x3, x4) and x <= max(x3, x4)) and (y >= min(y3, y4) and y <= max(y3, y4)):
return point
else:
return None
Your method of vector differences makes it very hard to precisely dectect colinearity or overlapping lines.
I think it would be much easier if you used the angles of the directing vectors to detect colinearity (this way is also better to avoid aprox. erors in comparisons).
import math
def get_angle(vector):
#if vector lenght == 0
if vector[0] == vector[1] == 0:
return None
angle = math.atan(vector[0]/vector[1]) if not vector[1] == 0 else math.pi/2 if vector[0] > 0 else -math.pi/2
while angle < 0:
angle = angle+(math.pi)
return angle
def similar_angle(angle1, angle2):
if angle1 == None or angle2 == None:
return True
return abs(angle1 - angle2) < 0.0001
x1, y1 = 0,0
x2, y2 = 1,1
x3, y3 = 0,1
x4, y4 = 1,2
#direction vectors of both lines
v12 = (x2-x1, y2-y1)
v34 = (x4-x3, y4-y3)
#angles of each vector
vs = [v12, v34]
angles = list()
for v in vs:
angle = get_angle(v)
angles.append(angle)
#colinearity
if abs(angles[0] - angles[1]) < 0.0001:
print('colinear')
condition_1 = similar_angle( get_angle( (x4-x1, y4-y1) ), get_angle( (x3-x1, y3-y1) ) )
condition_2 = similar_angle( get_angle( (x4-x1, y4-y1) ), get_angle( (x4-x2, y4-y2) ) )
#overlapped
if condition_1 and condition_2:
print('overlapped')
else:
print('not colinear')

Python trapezoidal method

I have
data_list = [(-140.0, 0.4622535000000001), (-139.2, 6.153633500000012), (-138.4, 13.410681499999995),(-136.8, 32.82019100000002), (-135.2, 52.21330899999998)]
data_list is (x, area)
How I can calculate volume by applying the trapezoidal method ?
I made by myself seems ok
def trapezoidal_rule(data_list):
volume = 0
for i in range(1, len(data_list)):
x1, y1 = data_list[i - 1]
x2, y2 = data_list[i]
volume += (x2 - x1) * (y1 + y2) / 2
return volume
I asked question because i'm not sure if code is correct
but i'm receiving only -

know what are the pixel values ​through which a line passes over a grayscale image with the Bresenham line algorithm python

How to obtain pixel value of a gray scale image using the Bresenham line algorithm given a line at different angles as shown in this code fraction
I hope and you can help me
import cv2
import numpy as np
img= cv2.imread("0.L3Luzr_Esq.tif")
def bresenham(origin, dest):
# debug code
print origin
print dest
# end debug code
x0 = origin[0]; y0 = origin[1]
x1 = dest[0]; y1 = dest[1]
steep = abs(y1 - y0) > abs(x1 - x0)
backward = x0 > x1
if steep:
x0, y0 = y0, x0
x1, y1 = y1, x1
if backward:
x0, x1 = x1, x0
y0, y1 = y1, y0
dx = x1 - x0
dy = abs(y1 - y0)
error = dx / 2
y = y0
if y0 < y1: ystep = 1
else: ystep = -1
result = []
for x in range(x0, x1):
if steep: result.append((y, x))
else: result.append((x, y))
error -= dy
if error < 0:
y += ystep
error += dx
return result
if backward: return result.reverse()
else: return result
print result
return result

Is there a better way to find points along a curve than Bresenham's line algorithm

I have a travel time map, I want to get the integer points along the shortest path from source to receiver.
My present solution is that I make a runge-kutta integration from the receiver location and get a series of float points. Then I sample every 5 or some number of points and assume it a straight line between in order to use the Bresenham's line algorithm. With this approach, I will get the integer points.
However, it's not enough fast. Because I need to calculate a lot of receivers' shortest path, the sum of time will be very large.
I used line_profiler to analysis the time-consuming, which shows the major part of time is for function ruge-kutta and its calling function get_velocity
codes are below
def optimal_path_2d(gradx_interp,
grady_interp,
starting_point,
dx,
N=100):
"""
Find the optimal path from starting_point to the zero contour
of travel_time. dx is the grid spacing
Solve the equation x_t = - grad t / | grad t |
"""
def get_velocity(position):
""" return normalized velocity at pos """
x, y = position
vel = np.array([gradx_interp(y, x)[0][0], grady_interp(y, x)[0][0]])
return vel / np.linalg.norm(vel)
def runge_kutta(pos, ds):
""" Fourth order Runge Kutta point update """
k1 = ds * get_velocity(pos)
k2 = ds * get_velocity(pos - k1 / 2.0)
k3 = ds * get_velocity(pos - k2 / 2.0)
k4 = ds * get_velocity(pos - k3)
return pos - (k1 + 2 * k2 + 2 * k3 + k4) / 6.0
x = runge_kutta(starting_point, dx)
xl, yl = [], []
for i in range(N):
xl.append(x[0])
yl.append(x[1])
x = runge_kutta(x, dx)
distance = ((x[0] - xl[-1])**2 +
(x[1] - yl[-1])**2)**0.5
if distance < dx*0.9:
break
return yl, xl
def get_curve(x_curve, y_curve, num_interval):
"""Curve Algorithm based on Bresenham's Line Algorithm
Produces a list of tuples
"""
num = len(x_curve)
if num < num_interval:
print("num_interval is too large.")
ret_set = set()
x0 = x_curve[0]
y0 = y_curve[0]
for i in range(num_interval, num, num_interval):
x1 = x_curve[i]
y1 = y_curve[i]
points_on_line = get_line((x0, y0), (x1, y1))
ret_set.update(points_on_line)
x0 = x1
y0 = y1
if num % num_interval != 0:
n = int(num/num_interval)*num_interval
x0 = x_curve[n]
y0 = y_curve[n]
x1 = x_curve[-1]
y1 = y_curve[-1]
points_on_line = get_line((x0, y0), (x1, y1))
ret_set.update(points_on_line)
return list(ret_set)
def get_line(start, end):
"""modifed version of Bresenham's Line Algorithm
Produces a list of tuples from start and end
>>> points1 = get_line((0, 0), (3, 4))
>>> points2 = get_line((3, 4), (0, 0))
>>> assert(set(points1) == set(points2))
>>> print points1
[(0, 0), (1, 1), (1, 2), (2, 3), (3, 4)]
>>> print points2
[(3, 4), (2, 3), (1, 2), (1, 1), (0, 0)]
"""
# Setup initial conditions
x1, y1 = (int(x) for x in start)
x2, y2 = (int(x) for x in end)
dx = x2 - x1
dy = y2 - y1
# Determine how steep the line is
is_steep = abs(dy) > abs(dx)
# Rotate line
if is_steep:
x1, y1 = y1, x1
x2, y2 = y2, x2
# Swap start and end points if necessary and store swap state
swapped = False
if x1 > x2:
x1, x2 = x2, x1
y1, y2 = y2, y1
swapped = True
# Recalculate differentials
dx = x2 - x1
dy = y2 - y1
# Calculate error
error = int(dx / 2.0)
ystep = 1 if y1 < y2 else -1
# Iterate over bounding box generating points between start and end
y = y1
points = []
for x in range(x1, x2 + 1):
coord = (y, x) if is_steep else (x, y)
points.append(coord)
error -= abs(dy)
if error < 0:
y += ystep
error += dx
# Reverse the list if the coordinates were swapped
if swapped:
points.reverse()
return points
nx = 100
ny = 100
num_interval = 5
loc_src = (10, 10)
loc_rec = (70, 90)
coordx = np.arange(nx)
coordy = np.arange(ny)
X, Y = np.meshgrid(coordx, coords)
travel_time = (X-loc_src[0])**2/5 + (Y-loc_src[1])**2/10 # for simplicity
grad_t_y, grad_t_x = np.gradient(travel_time, dx)
if isinstance(travel_time, np.ma.MaskedArray):
grad_t_y[grad_t_y.mask] = 0.0
grad_t_y = grad_t_y.data
grad_t_x[grad_t_x.mask] = 0.0
grad_t_x = grad_t_x.data
gradx_interp = RectBivariateSpline(coordy, coordx, grad_t_x)
grady_interp = RectBivariateSpline(coordy, coordx, grad_t_y)
yl, xl = optimal_path(gradx_interp, grady_interp, loc_rec, dx)
grid_indx = get_curve(xl, yl, num_interval)
I hear that Cython will be faster, then I learn a little recently and try it. the result is only 2 faster than codes above because I'm really new to Cython. The code below is incomplete, and I just wrote it for testing.
import numpy as np
from numpy.core.umath_tests import inner1d
def func(X_interp, Y_interp):
def get_velocity(double x, double y ):
""" return normalized velocity at pos """
cdef double vel[2], norm
a = X_interp(y, x)
vel[0] = a[0][0]
b = Y_interp(y, x)
vel[1] = b[0][0]
# norm = (vel[0]**2 + vel[1]**2)**0.5
# vel[0] = vel[0]/norm
# vel[1] = vel[1]/norm
return vel
def runge_kutta(double x, double y, double ds):
""" Fourth order Runge Kutta point update """
cdef double k1[2], k2[2], k3[2], k4[2], r[2], pos[2]
pos[0] = x; pos[1] = y
k1 = get_velocity(pos[0], pos[1])
k2 = get_velocity(pos[0] - k1[0]/2.0*ds,pos[1] - k1[1]/2.0*ds)
k3 = get_velocity(pos[0] - k2[0]/2.0*ds,pos[1] - k2[1]/2.0*ds)
k4 = get_velocity(pos[0] - k3[0]/2.0*ds,pos[1] - k3[1]/2.0*ds)
cdef size_t i
for i in range(2):
r[i] = pos[i] - ds * (k1[i] + 2*k2[i] + 2*k3[i] + k4[i])/6.0
return r
for i in range(50):
runge_kutta(0, 0, 1.)
# print(runge_kutta(0, 0, 1.))

z-coordinate of a point on a line in 3d using python

If I have x,y coordinates for a point on line in 3D and I need to get this z-coordinate using python, how can I do it ?? I have the start point (x1,y1,z1) and end point (x2,y2,z2) of the line in 3D, so any suggestions please ???
You can easily setup a parametric equation for the line:
x = x1 + (x2 - x1)*t
y = y1 + (y2 - y1)*t
z = z1 + (z2 - z1)*t
So given a (x,y), solve this equation for t:
x = x1 + (x2 - x1)*t
so
t = (x - x1) / (x2 - x1)
or
t = (y - y1) / (y2 - y1)
Now that you know t, you can find z:
z = z1 + (z2 - z1)*t
So in Python it would be:
def computeZ(p1,p2,x,y):
x1,y1,z1 = p1
x2,y2,z2 = p2
if x2 - x1 != 0:
t = (x - x1) / (x2 - x1)
elif y2 - y1 != 0:
t = (y - y1) / (y2 - y1)
else:
print "no unique z value exists"
return 0
return z1 + (z2 - z1)*t
You only need to know either the X or the Y value, not both. The equation, if you have an X value, A, would be:
((A - x1)*(z2 - z1)/(x2 - x1)) + z1
Using this, you can plug in your two initial points and an x and get the new point like so:
def get_points(p1, p2, x):
x1, y1, z1 = p1
x2, y2, z2 = p2
new_z = ((x - x1)*(z2 - z1)/(x2 - x1)) + z1
new_y = ((x - x1)*(y2 - y1)/(x2 - x1)) + y1
new_p = (x, new_y, new_z)
return new_p

Categories

Resources