<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def apply(self, points):
 """Applies the rigid transformation to a set of 3D objects. Parameters points : :obj:`BagOfPoints` A set of objects to transform. Could be any subclass of BagOfPoints. Returns ------- :obj:`BagOfPoints` A transformed set of objects of the same type as the input. Raises ------ ValueError If the input is not a Bag of 3D points or if the points are not in this transform's from_frame. """

        if not isinstance(points, BagOfPoints):
            raise ValueError('Rigid transformations can only be applied to bags of points')
        if points.dim != 3:
            raise ValueError('Rigid transformations can only be applied to 3-dimensional points')
        if points.frame != self._from_frame:
            raise ValueError('Cannot transform points in frame %s with rigid transformation from frame %s to frame %s' %(points.frame, self._from_frame, self._to_frame))

        if isinstance(points, BagOfVectors):
            # rotation only
            x = points.data
            x_tf = self.rotation.dot(x)
        else:
            # extract numpy data, homogenize, and transform
            x = points.data
            if len(x.shape) == 1:
                x = x[:,np.newaxis]
            x_homog = np.r_[x, np.ones([1, points.num_points])]
            x_homog_tf = self.matrix.dot(x_homog)
            x_tf = x_homog_tf[0:3,:]

        # output in BagOfPoints format
        if isinstance(points, PointCloud):
            return PointCloud(x_tf, frame=self._to_frame)
        elif isinstance(points, Point):
            return Point(x_tf, frame=self._to_frame)
        elif isinstance(points, Direction):
            return Direction(x_tf, frame=self._to_frame)
        elif isinstance(points, NormalCloud):
            return NormalCloud(x_tf, frame=self._to_frame)
        raise ValueError('Type %s not yet supported' %(type(points)))