matlab 如何得到一个线段穿过一个正方形的长度?

5rgfhyps  于 2023-05-23  发布在  Matlab
关注(0)|答案(4)|浏览(245)

我有一行,由参数m, h定义,其中

y = m*x + h

这条线穿过网格(即对于网格的每个正方形(a, b)(即正方形[a, a+1] x [b, b+1]),我想确定给定的直线是否与这个正方形相交,如果是,正方形中线段的长度是多少。
最终,我希望能够一次使用多行代码(即mh是matlab风格的向量),但我们现在可以专注于“简单”的情况。
我想知道如何判断直线是否与正方形相交:
1.计算直线与垂直线x = ax = a + 1以及水平线y = by = b + 1的交点
1.检查这4个点中是否有2个在正方形边界上(即a <= x < a + 1b <= y < b + 1
如果这些点上的两个点在正方形上,则直线与正方形相交。然后,要计算长度,只需减去这两个点,并使用毕达哥拉斯定理。
我的问题更多的是在执行方面:我怎样才能很好地实现这一点(特别是在选择减去哪两个点时)?

kninwzqo

kninwzqo1#

设正方形由角点**(a,b),(a+1,b),(a,b+1),(a+1,b+1)定义。
步骤1:检查直线是否与正方形相交。
(a)将4个角点的坐标中的每一个依次代入
y-mx- h**。如果该评估的符号包括正项和负项,则转到步骤b。否则,直线不与正方形相交。
(B)现在有两个子案例:
(b1)情况1:在步骤(a)中,您有三个点,其中y - mx - h评估为一个符号,第四个点评估为另一个符号。假设第四个点是某个**(x*,y*)。则交点是(x*,mx*+h)((y*-h)/m,y*)
(b2)情况2:在步骤(a)中,你有两个点,其中
y-mx- h评估为一个符号,另外两个点评估为另一个符号。选择任意两个符号相同的点,比如(x*,y*)(x*+1,y*)。则交点为(x*,mx* + h)(x*+1,m(x*+1)+ h)**。
你将不得不考虑一些退化的情况,其中直线恰好接触四个角点中的一个,以及直线恰好位于正方形的一侧的情况。

zlwx9yxi

zlwx9yxi2#

m为0时(当试图计算与y = k的交集时),您提出的方法可能会遇到步骤(1)中的问题。
如果m为0,那么很容易(线段长度为1或0,取决于b <= h <= b+1是否为0)。
否则,您可以通过替换找到x = aa+1的交集,例如y_ay_{a+1}。然后,将y_ay_{a+1}裁剪到bb+1之间(比如,y1y2,即y1 = min(b+1, max(b, y_a))和类似的y2),并使用比例abs((y1-y2)/m) * sqrt(m^2+1)
这利用了x=kx=k+1之间的线段是sqrt(m^2+1)y的差是m以及相似性的事实。

j2cgzkjk

j2cgzkjk3#

你可以这样做:先求正方形的圆心,再求对角线的长度。如果从正方形中心到直线的距离小于对角线的长度,那么直线将与正方形相交。一旦你知道这条线会相交,你就可以很容易地找到相交的线段。我想你是想为代数重建技术做权重矩阵。我希望这是正确的答案。这是我在堆栈流中的第一个答案。:)

ni65a41a

ni65a41a4#

下面是Tryer给出的答案在python3中的实现。
在开发过程中,我遇到了一个他没有触及的b2子用例的边缘情况。也就是说,如果斜率的大小大于1,则交点的形式为**((Y*-h)/m,Y*)((Y*+1-h)/m,Y*+1),而不是(x*,mx* + h)(x*+1,m(x*+1)+ h)**。

import math

def distance(pt1: tuple[float,float],pt2: tuple[float,float])-> float:
    return math.sqrt((pt1[0]-pt2[0])*(pt1[0]-pt2[0]) + (pt1[1]-pt2[1])*(pt1[1]-pt2[1]))

def calc_pt_sign(pt: tuple[float,float], m, b) -> float:
    return  pt[1] - (m* pt[0]) - b 

#based on https://stackoverflow.com/questions/4379693/how-to-get-the-length-of-a-segment-crossing-a-square
def get_intersection_pts(sq_x, sq_y, m, b)-> tuple[tuple[float,float],tuple[float,float]]:
    #step 1
    sq = ((sq_x - 0.5, sq_y -0.5 ),
        (sq_x + 0.5, sq_y - 0.5),
        (sq_x - 0.5, sq_y + 0.5),
        (sq_x + 0.5, sq_y + 0.5))
    calcs = [calc_pt_sign(pt, m, b) for pt in sq]
    num_negitives = 0
    for val in calcs:
        if val < 0:
            num_negitives = num_negitives + 1
    num_pos = 0
    for val in calcs:
        if val >= 0:
            num_pos = num_pos + 1
    # End step 1

    # Case 1
    if num_pos == 3 or num_negitives == 3:
        if num_pos == 3:
            chosen_point = sq[calcs.index(min(calcs))]
            
        else:
            chosen_point = sq[calcs.index(max(calcs))]
        #(x*,mx*+h) and ((y*-h)/m,y*)
        inter_pt_1 = (chosen_point[0], (chosen_point[0]*m)+b)
        inter_pt_2 = ((chosen_point[1]-b)/m,chosen_point[1])
        return inter_pt_1, inter_pt_2
    # Case 2
    if num_pos == 2 or num_negitives == 2:
        chosen_point_1 = sq[0];
        chosen_point_2 = None
        if calcs[0] < 0:
            chosen_point_2 =  sq[calcs.index(min(calcs[1:]))]
        else:
            chosen_point_2 =  sq[calcs.index(max(calcs[1:]))]
        if abs(m) <1:
            inter_pt_1 = chosen_point_1[0], (m*chosen_point_1[0])+b
            inter_pt_2 = chosen_point_2[0], (m*chosen_point_2[0])+b
        else:
            inter_pt_1 = (chosen_point_1[1]-b)/m, chosen_point_1[1]
            inter_pt_2 = (chosen_point_2[1]-b)/m, chosen_point_2[1]
        return inter_pt_1, inter_pt_2
    # No interception Case
    return None

相关问题