def findMinimumBoundingRectangle(polyData, linkFrame):
    '''
    Find minimum bounding rectangle of a rectangular point cloud
    The input is assumed to be a rectangular point cloud e.g. the top of a block or table
    Returns transform of far right corner (pointing away from robot)
    '''

    # Originally From: https://github.com/dbworth/minimum-area-bounding-rectangle
    polyData = applyVoxelGrid(polyData, leafSize=0.02)

    def get2DAsPolyData(xy_points):
        '''
        Convert a 2D numpy array to a 3D polydata by appending z=0
        '''
        d = np.vstack((xy_points.T, np.zeros( xy_points.shape[0]) )).T
        d2=d.copy()
        return vtkNumpy.getVtkPolyDataFromNumpyPoints( d2 )

    pts =vtkNumpy.getNumpyFromVtk( polyData , 'Points' )
    xy_points =  pts[:,[0,1]]
    vis.updatePolyData( get2DAsPolyData(xy_points) , 'xy_points', parent=getDebugFolder(), visible=False)
    hull_points = qhull_2d.qhull2D(xy_points)
    vis.updatePolyData( get2DAsPolyData(hull_points) , 'hull_points', parent=getDebugFolder(), visible=False)
    # Reverse order of points, to match output from other qhull implementations
    hull_points = hull_points[::-1]
    # print 'Convex hull points: \n', hull_points, "\n"

    # Find minimum area bounding rectangle
    (rot_angle, rectArea, rectDepth, rectWidth, center_point, corner_points_ground) = min_bounding_rect.minBoundingRect(hull_points)
    vis.updatePolyData( get2DAsPolyData(corner_points_ground) , 'corner_points_ground', parent=getDebugFolder(), visible=False)

    polyDataCentroid = computeCentroid(polyData)
    cornerPoints = np.vstack((corner_points_ground.T, polyDataCentroid[2]*np.ones( corner_points_ground.shape[0]) )).T
    cornerPolyData = vtkNumpy.getVtkPolyDataFromNumpyPoints(cornerPoints)

    # Create a frame at the far right point - which points away from the robot
    farRightCorner = findFarRightCorner(cornerPolyData , linkFrame)
    viewDirection = SegmentationContext.getGlobalInstance().getViewDirection()

    viewFrame = SegmentationContext.getGlobalInstance().getViewFrame()
    #vis.showFrame(viewFrame, "viewFrame")

    robotYaw = math.atan2( viewDirection[1], viewDirection[0] )*180.0/np.pi
    blockAngle =  rot_angle*(180/math.pi)
    #print "robotYaw   ", robotYaw
    #print "blockAngle ", blockAngle
    blockAngleAll = np.array([blockAngle , blockAngle+90 , blockAngle+180, blockAngle+270])

    values = blockAngleAll - robotYaw
    for i in range(0,4):
        if(values[i]>180):
          values[i]=values[i]-360

    values = abs(values)
    min_idx = np.argmin(values)
    if ( (min_idx==1) or (min_idx==3) ):
        #print "flip rectDepth and rectWidth as angle is not away from robot"
        temp = rectWidth ; rectWidth = rectDepth ; rectDepth = temp

    #print "best angle", blockAngleAll[min_idx]
    rot_angle = blockAngleAll[min_idx]*math.pi/180.0

    cornerTransform = transformUtils.frameFromPositionAndRPY( farRightCorner , [0,0, np.rad2deg(rot_angle) ] )

    vis.showFrame(cornerTransform, "cornerTransform", parent=getDebugFolder(), visible=False)

    #print "Minimum area bounding box:"
    #print "Rotation angle:", rot_angle, "rad  (", rot_angle*(180/math.pi), "deg )"
    #print "rectDepth:", rectDepth, " rectWidth:", rectWidth, "  Area:", rectArea
    #print "Center point: \n", center_point # numpy array
    #print "Corner points: \n", cornerPoints, "\n"  # numpy array
    return cornerTransform, rectDepth, rectWidth, rectArea
dataset/ETHPy150Open RobotLocomotion/director/src/python/director/segmentation.py/findMinimumBoundingRectangle/original