Search code examples
pythongeometryplane

how to generate rectangle from a plane equation ax+by+cz=d?


given a plane equation, how can you generate four points that comprise a rectangle? I only have the plane equation ax+by+cz=d.

I am following the approach listed here Find Corners of Rectangle, Given Plane equation, height and width

#generate horizontal vector U
        temp_normal=np.array([a,b,c])

        temp_vertical=np.array([0,0,1])

        U=np.cross(temp_normal, temp_vertical)

        # for corner 3 and 4 
        neg_U=np.multiply([-1.0, -1.0, -1.0], U)
#generate vertical vector W       


        W=np.cross(temp_normal,U)
        #for corner 2 and 4
        neg_W=np.multiply([-1.0, -1.0, -1.0], W)




        #make the four corners
        #C1 = P0 + (width / 2) * U + (height / 2) * W
        C1=np.sum([centroid,np.multiply(U, width_array),np.multiply(W, height_array)], axis=0)

        corner1=C1.tolist()


        #C2 = P0 + (width / 2) * U - (height / 2) * W
        C2=np.sum([centroid,np.multiply(U, width_array),np.multiply(neg_W, height_array)], axis=0)

        corner2=C2.tolist()


        #C3 = P0 - (width / 2) * U + (height / 2) * W
        C3=np.sum([centroid,np.multiply(neg_U, width_array),np.multiply(W, height_array)], axis=0)

        corner3=C3.tolist()


        #C4 = P0 - (width / 2) * U - (height / 2) * W  
        C4=np.sum([centroid,np.multiply(neg_U, width_array),np.multiply(neg_W, height_array)], axis=0)
        self.theLw.WriteLine("C4 is " +str(type(C4))+" "+str(C4.tolist()))
        corner4=C4.tolist()


        corners_list.append([corner1, corner2, corner3, corner4])

Solution

  • Find a vector inside that plane using the equation. Find a second one inside that plane, perpendicular to the first one, using the cross-product (of the first and a normal vector to the plane). Then add these vectors (with +- signs, 4 possibilities) to generate 4 corners.

    Edit: to help you a bit more:

    • (a,b,c) is the vector normal to the plane;
    • (0,0,d/c), (0,d/b,0) and (d/a,0,0) are points belonging to the plane, i.e. for instance b1 = (0,d/b,-d/c) is a vector tangent to the plane;
    • The cross-product of two vectors returns a vector that is perpendicular to both. So the product b2 = (a,b,c) x (0,d/b,-d/c) is a vector tangent to the plane, perpendicular to the other one. With that, you have constructed a normal basis of the plane [b1,b2].

    • Start from a point, say (0,0,d/c), and add b1+b2, b1-b2, -b1+b2, -b1-b2 to have 4 corners.

    Ok here is the answer:

    import numpy as np
    
    a = 2; b = 3; c = 4; d = 5
    n = np.array([a,b,c])
    x1 = np.array([0,0,d/c])
    x2 = np.array([0,d/b,0])
    
    def is_equal(n,m):
        return n-m < 1e-10
    
    def is_on_the_plane(v):
        return is_equal(v[0]*a + v[1]*b + v[2]*c, d)
    
    assert is_on_the_plane(x1)
    assert is_on_the_plane(x2)
    
    # Get the normal basis
    b1 = x2 - x1
    b2 = np.cross(n, b1)
    
    c1 = x1 + b1 + b2
    c2 = x1 + b1 - b2
    c3 = x1 - b1 + b2
    c4 = x1 - b1 - b2
    
    assert is_on_the_plane(c1)
    assert is_on_the_plane(c2)
    assert is_on_the_plane(c3)
    assert is_on_the_plane(c4)
    
    assert is_equal(np.dot(c1-c3, c1-x2), 0)
    assert is_equal(np.dot(c2-c1, c2-c4), 0)
    # etc. :
    
    #   c3        c1
    #
    #        x1
    #
    #   c4        c2
    

    It is actually a square, but you can surely find out how to make it a less specific rectangle.