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: Gather independent words in structured blocks
  
  Args:
  ----
      boxes: bounding boxes of all detected words of the page, of shape (N, 5) or (N, 4, 2)
      word_preds: list of all detected words of the page, of shape N
  
  Returns:
  -------
      list of block elements
docstr_tok: ["Gather","independent","words","in","structured","blocks","Args",":","--","--","boxes",":","bounding","boxes","of","all","detected","words","of","the","page",",","of","shape","(","N",",","5",")","or","(","N",",","4",",","2",")","word_preds",":","list","of","all","detected","words","of","the","page",",","of","shape","N","Returns",":","--","--","--","-","list","of","block","elements"]
code: def _build_blocks(
      self, boxes: np.ndarray, word_preds: List[Tuple[str, float]]
  ) -> List[Block]:
      """Gather independent words in structured blocks
  
      Args:
      ----
          boxes: bounding boxes of all detected words of the page, of shape (N, 5) or (N, 4, 2)
          word_preds: list of all detected words of the page, of shape N
  
      Returns:
      -------
          list of block elements
      """
      if boxes.shape[0] != len(word_preds):
          raise ValueError(
              f"Incompatible argument lengths: {boxes.shape[0]}, {len(word_preds)}"
          )
  
      if boxes.shape[0] == 0:
          return []
  
      # Decide whether we try to form lines
      _boxes = boxes
      if self.resolve_lines:
          lines = self._resolve_lines(
              _boxes if _boxes.ndim == 3 else _boxes[:, :4]
          )
          # Decide whether we try to form blocks
          if self.resolve_blocks and len(lines) > 1:
              _blocks = self._resolve_blocks(
                  _boxes if _boxes.ndim == 3 else _boxes[:, :4], lines
              )
          else:
              _blocks = [lines]
      else:
          # Sort bounding boxes, one line for all boxes, one block for the line
          lines = [self._sort_boxes(_boxes if _boxes.ndim == 3 else _boxes[:, :4])[0]]  # type: ignore[list-item]
          _blocks = [lines]
  
      blocks = [
          Block(
              [
                  Line(
                      [
                          Word(
                              *word_preds[idx],
                              tuple([tuple(pt) for pt in boxes[idx].tolist()]),  # type: ignore[arg-type]
                          )
                          if boxes.ndim == 3
                          else Word(
                              *word_preds[idx],
                              (
                                  (boxes[idx, 0], boxes[idx, 1]),
                                  (boxes[idx, 2], boxes[idx, 3]),
                              ),
                          )
                          for idx in line
                      ]
                  )
                  for line in lines
              ]
          )
          for lines in _blocks
      ]
  
      return blocks
  
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 6 for calling the DocumentBuilder obj's underlying member method code with example usage: obj._build_blocks(boxes, word_preds) and returns: blocks, list