As you have added the python tag to your question, I assume you want to solve this problem using python.
The Two Scenarios
- either the points given represent a diagonal (1)
- or the points given represent an edge (2)
(1) Diagonal Approach:
Diagonal Approach Sketch
(Right here, we use the the theorem of Thales. If you don't know it, just look it up. It's quite useful.)
(2) Edge Approach:
Edge Approach Sketch
Python Code
This is pure calculation. Just change the properties at the very end of this script.
import math
import numpy as np
# lovely method by mujjiga
# from https://stackoverflow.com/questions/55816902/finding-the-intersection-of-two-circles
# returns intersections of two circles
def get_intersections(x0, y0, r0, x1, y1, r1):
# circle 1: (x0, y0), radius r0
# circle 2: (x1, y1), radius r1
d = math.sqrt((x1-x0)**2 + (y1-y0)**2)
# non intersecting
if d > r0 + r1:
return None
# One circle within other
if d < abs(r0-r1):
return None
# coincident circles
if d == 0 and r0 == r1:
return None
else:
a = (r0**2-r1**2+d**2)/(2*d)
h = math.sqrt(r0**2-a**2)
x2 = x0+a*(x1-x0)/d
y2 = y0+a*(y1-y0)/d
x3 = x2+h*(y1-y0)/d
y3 = y2-h*(x1-x0)/d
x4 = x2-h*(y1-y0)/d
y4 = y2+h*(x1-x0)/d
return (x3, y3, x4, y4)
# returns None or 4 possible points
def get_unknown_points(p1, p2, width, is_diagonal):
# convert tuples/lists to nummpy arrays
p1 = np.array(p1, dtype=float)
p2 = np.array(p2, dtype=float)
# vector from p1 to p2
p1_to_p2 = p2 - p1
# magnitude/length of this vector
length = np.linalg.norm(p2 - p1)
if is_diagonal:
mid = p1 + 0.5 * p1_to_p2
mid_radius = length * 0.5
points = get_intersections(
p1[0], p1[1], width, mid[0], mid[1], mid_radius)
# no intersections found
if points is None:
return None
other_points = get_intersections(
p2[0], p2[1], width, mid[0], mid[1], mid_radius)
# return the two different possibilities
possibilities = []
possibilities.append(
((points[0], points[1]), (other_points[0], other_points[1])))
possibilities.append(
((points[2], points[3]), (other_points[2], other_points[3])))
return possibilities
# p1 and p2 do not represent the diagonal
else:
# get a perpendicular vector regarding p1_to_p2 (taken from https://stackoverflow.com/questions/33658620/generating-two-orthogonal-vectors-that-are-orthogonal-to-a-particular-direction)
perpendicular_vector = np.random.randn(2)
perpendicular_vector -= perpendicular_vector.dot(
p1_to_p2) * p1_to_p2 / np.linalg.norm(p1_to_p2)**2
# make length of vector correspond to width
perpendicular_vector /= np.linalg.norm(perpendicular_vector)
perpendicular_vector *= width
# add this vector to p1 and p2 and return both possibilities
possibilities = []
possibilities.append(
((p1[0] + perpendicular_vector[0], p1[1] + perpendicular_vector[1]), (p2[0] + perpendicular_vector[0], p2[1] + perpendicular_vector[1])))
possibilities.append(
((p1[0] - perpendicular_vector[0], p1[1] - perpendicular_vector[1]), (p2[0] - perpendicular_vector[0], p2[1] - perpendicular_vector[1])))
return possibilities
# change these properties
p1 = (4, 5)
p2 = (5, 1)
diagonal = True
width = 1
points = get_unknown_points(p1, p2, width, diagonal)
# output
if points is None:
print("There are no points that can be calculated from the points given!")
else:
print(
f"Possibilty 1: \n\tPoint1: {points[0][0]} \n\tPoint2: {points[0][1]}")
print(
f"Possibilty 2: \n\tPoint1: {points[1][0]} \n\tPoint2: {points[1][1]}")
Visualization
If you want to see the results visually, just append these lines of code to the end of the upper script.
import matplotlib.pyplot as plt
# displaying results
if points is not None:
p1 = np.array(p1, dtype=float)
p2 = np.array(p2, dtype=float)
fig, ax = plt.subplots()
ax.set_xlim((-1, 10))
ax.set_ylim((-1, 10))
if diagonal:
dist = np.linalg.norm(p2 - p1)
mid = p1 + 0.5 * (p2 - p1)
mid_radius = dist * 0.5
circle2 = plt.Circle(mid, mid_radius, color='orange', fill=False)
circle3 = plt.Circle(p1, width, color='g', fill=False)
circle1 = plt.Circle(p2, width, color='g', fill=False)
ax.add_artist(circle1)
ax.add_artist(circle2)
ax.add_artist(circle3)
plt.plot(p1, p2, '.', color='black')
print(points[0][1])
plt.plot([points[0][0][0], points[0][1][0]], [
points[0][0][1], points[0][1][1]], '.', color='red')
plt.plot([points[1][0][0], points[1][1][0]], [
points[1][0][1], points[1][1][1]], '.', color='blue')
plt.gca().set_aspect('equal', adjustable='box')
plt.show()
Results
Diagonal Approach Example
Edge Approach Example