首页 > 解决方案 > 矩形的其他两个点给出两个点和宽度

问题描述

给定附图中黑色显示的两个点,我需要找到矩形的另外两个点。缺失的点以黄色显示,宽度为红色,我也有。矩形可以任意旋转。

我也知道这些点是在矩形的同一侧还是相反侧。

如图所示,我需要解决四种可能的安排。 矩形的绘制

标签: pythongeometry

解决方案


由于您已将 python 标签添加到您的问题中,我假设您想使用 python 解决此问题。

两种情景

  • 给定的点代表对角线 (1)
  • 或给定的点代表一条边 (2)

(1) 对角线法:

Diagonal Approach Sketch (就在这里,我们用的是泰勒斯定理。如果你不知道,就去查吧。它很有用。)

(2) 边缘方法:

边缘接近草图

Python代码

这是纯粹的计算。只需更改此脚本末尾的属性即可。

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]}")

可视化

如果您想直观地查看结果,只需将这些代码行附加到上脚本的末尾即可。

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()

结果

对角线方法示例

边缘方法示例


推荐阅读