class_docstr: Implements a document builder
  
  Args:
  ----
      resolve_lines: whether words should be automatically grouped into lines
      resolve_blocks: whether lines should be automatically grouped into blocks
      paragraph_break: relative length of the minimum space separating paragraphs
      export_as_straight_boxes: if True, force straight boxes in the export (fit a rectangle
          box to all rotated boxes). Else, keep the boxes format unchanged, no matter what it is.
class_docstr_tok: ["Implements","a","document","builder","Args",":","--","--","resolve_lines",":","whether","words","should","be","automatically","grouped","into","lines","resolve_blocks",":","whether","lines","should","be","automatically","grouped","into","blocks","paragraph_break",":","relative","length","of","the","minimum","space","separating","paragraphs","export_as_straight_boxes",":","if","True",",","force","straight","boxes","in","the","export","(","fit","a","rectangle","box","to","all","rotated","boxes",")",".","Else",",","keep","the","boxes","format","unchanged",",","no","matter","what","it","is","."]
docstr: Split a line in sub_lines
  
  Args:
  ----
      boxes: bounding boxes of shape (N, 4)
      word_idcs: list of indexes for the words of the line
  
  Returns:
  -------
      A list of (sub-)lines computed from the original line (words)
docstr_tok: ["Split","a","line","in","sub_lines","Args",":","--","--","boxes",":","bounding","boxes","of","shape","(","N",",","4",")","word_idcs",":","list","of","indexes","for","the","words","of","the","line","Returns",":","--","--","--","-","A","list","of","(","sub-",")","lines","computed","from","the","original","line","(","words",")"]
code: def _resolve_sub_lines(
      self, boxes: np.ndarray, word_idcs: List[int]
  ) -> List[List[int]]:
      """Split a line in sub_lines
  
      Args:
      ----
          boxes: bounding boxes of shape (N, 4)
          word_idcs: list of indexes for the words of the line
  
      Returns:
      -------
          A list of (sub-)lines computed from the original line (words)
      """
      lines = []
      # Sort words horizontally
      word_idcs = [
          word_idcs[idx]
          for idx in boxes[word_idcs, 0].argsort().tolist()
      ]
  
      # Eventually split line horizontally
      if len(word_idcs) < 2:
          lines.append(word_idcs)
      else:
          sub_line = [word_idcs[0]]
          for i in word_idcs[1:]:
              horiz_break = True
  
              prev_box = boxes[sub_line[-1]]
              # Compute distance between boxes
              dist = boxes[i, 0] - prev_box[2]
              # If distance between boxes is lower than paragraph break, same sub-line
              if dist < self.paragraph_break:
                  horiz_break = False
  
              if horiz_break:
                  lines.append(sub_line)
                  sub_line = []
  
              sub_line.append(i)
          lines.append(sub_line)
  
      return lines
  
file_path: doctr/doctr/models/builder.py
imports: from typing import Any, Dict, List, Optional, Tuple
  import numpy
  from scipy.cluster.hierarchy import fclusterdata
  from doctr.io.elements import Block, Document, KIEDocument, KIEPage, Line, Page, Prediction, Word
  from doctr.utils.geometry import estimate_page_angle, resolve_enclosing_bbox, resolve_enclosing_rbbox, rotate_boxes
  from doctr.utils.repr import NestedObject
label_desc: Use image node_id 3 for calling the DocumentBuilder obj's underlying member method code with example usage: obj._resolve_sub_lines(boxes, word_idcs) and returns: lines