"""Helper variable or function for UI Elements."""importnumpyasnpfromfury.decoratorsimportwarn_on_args_to_kwargsTWO_PI=2*np.pi
[docs]@warn_on_args_to_kwargs()defclip_overflow(textblock,width,*,side="right"):"""Clips overflowing text of TextBlock2D with respect to width. Parameters ---------- textblock : TextBlock2D The textblock object whose text needs to be clipped. width : int Required width of the clipped text. side : str, optional Clips the overflowing text according to side. It takes values "left" or "right". Returns ------- clipped text : str Clipped version of the text. """original_str=textblock.messageprev_bg=textblock.have_bgclip_idx=check_overflow(textblock,width,overflow_postfix="...",side=side)ifclip_idx==0:returnoriginal_strtextblock.have_bg=prev_bgreturntextblock.message
[docs]@warn_on_args_to_kwargs()defwrap_overflow(textblock,wrap_width,*,side="right"):"""Wraps overflowing text of TextBlock2D with respect to width. Parameters ---------- textblock : TextBlock2D The textblock object whose text needs to be wrapped. wrap_width : int Required width of the wrapped text. side : str, optional Clips the overflowing text according to side. It takes values "left" or "right". Returns ------- wrapped text : str Wrapped version of the text. """original_str=textblock.messagestr_copy=textblock.messagewrap_idxs=[]wrap_idx=check_overflow(textblock,wrap_width,overflow_postfix="",side=side)ifwrap_idx==0:returnoriginal_strwrap_idxs.append(wrap_idx)whilewrap_idx!=0:str_copy=str_copy[wrap_idx:]textblock.message=str_copywrap_idx=check_overflow(textblock,wrap_width,overflow_postfix="",side=side)ifwrap_idx!=0:wrap_idxs.append(wrap_idxs[-1]+wrap_idx+1)foridxinwrap_idxs:original_str=original_str[:idx]+"\n"+original_str[idx:]textblock.message=original_strreturntextblock.message
[docs]@warn_on_args_to_kwargs()defcheck_overflow(textblock,width,*,overflow_postfix="",side="right"):"""Checks if the text is overflowing. Parameters ---------- textblock : TextBlock2D The textblock object whose text is to be checked. width: int Required width of the text. overflow_postfix: str, optional Postfix to be added to the text if it is overflowing. Returns ------- mid_ptr: int Overflow index of the text. """side=side.lower()ifsidenotin["left","right"]:raiseValueError("side can only take values 'left' or 'right'")original_str=textblock.messagestart_ptr=0mid_ptr=0end_ptr=len(original_str)ifside=="left":original_str=original_str[::-1]iftextblock.cal_size_from_message()[0]<=width:return0whilestart_ptr<end_ptr:mid_ptr=(start_ptr+end_ptr)//2textblock.message=original_str[:mid_ptr]+overflow_postfixiftextblock.cal_size_from_message()[0]<width:start_ptr=mid_ptreliftextblock.cal_size_from_message()[0]>width:end_ptr=mid_ptrif(mid_ptr==(start_ptr+end_ptr)//2ortextblock.cal_size_from_message()[0]==width):ifside=="left":textblock.message=textblock.message[::-1]returnmid_ptr
[docs]defcal_bounding_box_2d(vertices):"""Calculate the min, max position and the size of the bounding box. Parameters ---------- vertices : ndarray vertices of the actors. """ifvertices.ndim!=2orvertices.shape[1]notin[2,3]:raiseIOError("vertices should be a 2D array with shape (n,2) or (n,3).")ifvertices.shape[1]==3:vertices=vertices[:,:-1]min_x,min_y=vertices[0]max_x,max_y=vertices[0]forx,yinvertices:ifx<min_x:min_x=xify<min_y:min_y=yifx>max_x:max_x=xify>max_y:max_y=ybounding_box_min=np.asarray([min_x,min_y],dtype="int")bounding_box_max=np.asarray([max_x,max_y],dtype="int")bounding_box_size=np.asarray([max_x-min_x,max_y-min_y],dtype="int")returnbounding_box_min,bounding_box_max,bounding_box_size
[docs]defrotate_2d(vertices,angle):"""Rotate the given vertices by an angle. Parameters ---------- vertices : ndarray vertices of the actors. angle: float Value by which the vertices are rotated in radian. """ifvertices.ndim!=2orvertices.shape[1]!=3:raiseIOError("vertices should be a 2D array with shape (n,3).")rotation_matrix=np.array([[np.cos(angle),np.sin(angle),0],[-np.sin(angle),np.cos(angle),0],[0,0,1],])new_vertices=np.matmul(vertices,rotation_matrix)returnnew_vertices