o
    oi&                     @   s   d dl mZmZmZmZ d dlZd dlmZmZm	Z	m
Z
mZ d dlmZmZmZ d dlmZ d dlmZ d dlmZ dd	gZG d
d deZde	defddZde	de	defddZdde	dee	 defdd	ZdS )    )IteratorOptionalTupleUnionN)Module	ParameterTensor	normalizewhere)KORNIA_CHECKKORNIA_CHECK_IS_TENSORKORNIA_CHECK_SHAPE)batched_dot_product)
Hyperplane)_torch_svd_castParametrizedLinefit_linec                	       s*  e Zd ZdZdededdf fddZdefdd	Zdefd
dZde	defddZ
dee fddZedefddZedefddZde	fddZedededd fddZdeeef defddZdedefdd Zdedefd!d"Zdedefd#d$Zd*d&ed'edeeef fd(d)Z  ZS )+r   zClass that describes a parametrize line.

    A parametrized line is defined by an origin point :math:`o` and a unit
    direction vector :math:`d` such that the line corresponds to the set

    .. math::

        l(t) = o + t * d
    origin	directionreturnNc                    s"   t    t|| _t|| _dS )al  Initialize a parametrized line of direction and origin.

        Args:
            origin: any point on the line of any dimension.
            direction: the normalized vector direction of any dimension.

        Example:
            >>> o = torch.tensor([0.0, 0.0])
            >>> d = torch.tensor([1.0, 1.0])
            >>> l = ParametrizedLine(o, d)

        N)super__init__r   _origin
_direction)selfr   r   	__class__ H/home/ubuntu/.local/lib/python3.10/site-packages/kornia/geometry/line.pyr   ,   s   

zParametrizedLine.__init__c                 C   s   d| j  d| j S )NzOrigin: z
Direction: r   r   r   r   r   r   __str__=      zParametrizedLine.__str__c                 C   s   t | S N)strr    r   r   r   __repr__@   s   zParametrizedLine.__repr__idxc                 C   s   |dkr| j S | jS )Nr   r   )r   r&   r   r   r   __getitem__C   r"   zParametrizedLine.__getitem__c                 c   s    | j | jfE d H  d S r#   r   r    r   r   r   __iter__F   s   zParametrizedLine.__iter__c                 C      | j S )zReturn the line origin point.)r   r    r   r   r   r   I      zParametrizedLine.originc                 C   r)   )z!Return the line direction vector.)r   r    r   r   r   r   N   r*   zParametrizedLine.directionc                 C   s   | j jd S )z-Return the dimension in which the line holds.)r   shaper    r   r   r   dimS   s   zParametrizedLine.dimp0p1c                 C   s   t |t|| dddS )a  Construct a parametrized line going from a point :math:`p0` to :math:`p1`.

        Args:
            p0: tensor with first point :math:`(B, D)` where `D` is the point dimension.
            p1: tensor with second point :math:`(B, D)` where `D` is the point dimension.

        Example:
            >>> p0 = torch.tensor([0.0, 0.0])
            >>> p1 = torch.tensor([1.0, 1.0])
            >>> l = ParametrizedLine.through(p0, p1)

           r+   )pr-   )r   r	   )clsr.   r/   r   r   r   throughW   s   zParametrizedLine.throughtc                 C   s   | j | j|  S )ad  Get the point at :math:`t` along this line.

        Args:
            t: step along the line.

        Return:
            tensor with the point.

        Example:
            >>> p0 = torch.tensor([0.0, 0.0])
            >>> p1 = torch.tensor([1.0, 1.0])
            >>> l = ParametrizedLine.through(p0, p1)
            >>> p2 = l.point_at(0.1)

        r   )r   r4   r   r   r   point_atg   s   zParametrizedLine.point_atpointc                 C   s   | j | j|| j   | j  S )zvReturn the projection of a point onto the line.

        Args:
            point: the point to be projected.

        r   r   r6   r   r   r   
projectiony   s   zParametrizedLine.projectionc                 C   s<   || j  }tj|| j dd}tj|| dd}|||  S )zReturn the squared distance of a point to its projection onte the line.

        Args:
            point: the point to calculate the distance onto the line.
        r+   r-   )r   torchsumr   )r   r6   dproj	sq_norm_dr   r   r   squared_distance   s   
z!ParametrizedLine.squared_distancec                 C   s   |  | S )zReturn the distance of a point to its projections onto the line.

        Args:
            point: the point to calculate the distance into the line.
        )r?   sqrtr7   r   r   r   distance   s   zParametrizedLine.distanceư>planeepsc                 C   s\   t |jj| jj}| |k}t||jt |jj| jj  | t	|}| 
|}||fS )aD  Return the intersection point between the line and a given plane.

        Args:
            plane: the plane to compute the intersection point.
            eps: epsilon for numerical stability.

        Return:
            - the lambda value used to compute the look at point.
            - the intersected point.

        )r   normaldatar   absr
   offsetr   r:   
empty_liker5   )r   rC   rD   dot_proddot_prod_mask
res_lambda	res_pointr   r   r   	intersect   s   
zParametrizedLine.intersect)rB   )__name__
__module____qualname____doc__r   r   r$   r!   r%   intr'   r   r(   propertyr   r   r-   classmethodr3   r   floatr5   r8   r?   rA   r   r   rN   __classcell__r   r   r   r   r   !   s&    
	(pointsr   c                 C   s   | d }| d }|j ddd}|j ddd}|| }|| }|| jddd}t|dk|| jddd| t|}t|dktjt||gddtjdd	g| jd
	| j
d d}	|	|	jddd }	tj||gdd}
t|
|	S )N.r   .   r+   Tr-   keepdim:0yE>r9                 ?)devicer   r0   )meanr;   r:   r
   
zeros_likecat	ones_liketensorra   expandr,   normr   )rX   xyx_meany_meandxdydenomsloper   r   r   r   r   _fit_line_ols_2d   s    * 
rq   weightsc                 C   s   | d }| d }|j ddd}|| j ddd| }|| j ddd| }|| }|| }|| | }	|| | }
|	j ddd}|
j ddd| }tt||t|}|dk}tjt||gdd}tjdd	g| j| j	d
}|||
d< ||jddd }tj||gdd}t||S )NrY   rZ   r+   Tr\   r^   r9   r_   r`   )ra   dtype)r;   r:   r
   isfiniterc   rd   re   rf   ra   rs   squeezerh   r   )rX   rr   ri   rj   w_sumrk   rl   rm   rn   weighted_dx2weighted_dxdyro   rp   is_verticalr   replacementr   r   r   r   _fit_line_weighted_ols_2d   s&   
r{   c                 C   s6  t | d t| g d | j\}}}|dkr;|dur7t |d t|ddg t| jd |jd k t| |S t| S | d	d
}| | }|durot |d t|ddg t| jd |jd k |d	dt	| | }n|d	d| }t
|\}}}|d	d}|ddddf }	|ddddf }
t|
|	S )ai  Fit a line from a set of points.

    Args:
        points: tensor containing a batch of sets of n-dimensional points. The expected
            shape of the tensor is :math:`(B, N, D)`.
        weights: weights to use to solve the equations system. The expected
            shape of the tensor is :math:`(B, N)`.

    Return:
        A tensor containing the direction of the fitted line of shape :math:`(B, D)`.

    Example:
        >>> points = torch.rand(2, 10, 3)
        >>> weights = torch.ones(2, 10)
        >>> line = fit_line(points, weights)
        >>> line.direction.shape
        torch.Size([2, 3])
    zpoints must be a tensor)BNDr0   Nzweights must be a tensorr|   r}   r   Tr+   .)r   r   r,   r   r{   rq   rb   	transposer:   
diag_embedr   r   )rX   rr   _B_Nr~   rb   A_Vr   r   r   r   r   r      s.   




r#   )typingr   r   r   r   r:   kornia.corer   r   r   r	   r
   kornia.core.checkr   r   r   kornia.geometry.linalgr   kornia.geometry.planer   kornia.utils.helpersr   __all__r   rq   r{   r   r   r   r   r   <module>   s      