<commit_before>/******************************************************************************
 *
 * File:        blobs.h
 * Description: Blob definition
 * Author:      <NAME>, OCR Technology
 *
 * (c) Copyright 1989, Hewlett-Packard Company.
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
 ** You may obtain a copy of the License at
 ** http://www.apache.org/licenses/LICENSE-2.0
 ** Unless required by applicable law or agreed to in writing, software
 ** distributed under the License is distributed on an "AS IS" BASIS,
 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 *
 *****************************************************************************/

#ifndef BLOBS_H
#define BLOBS_H

#include "clst.h"       // for CLIST_ITERATOR, CLISTIZEH
#include "normalis.h"   // for DENORM
#include "points.h"     // for FCOORD, ICOORD
#include "rect.h"       // for TBOX
#include "scrollview.h" // for ScrollView, ScrollView::Color

#include <tesseract/publictypes.h> // for OcrEngineMode

#include "tesstypes.h" // for TDimension

struct Pix;

namespace tesseract {

class BLOCK;
class C_BLOB;
class C_OUTLINE;
class LLSQ;
class ROW;
class WERD;

/*----------------------------------------------------------------------
              T y p e s
----------------------------------------------------------------------*/

struct TPOINT {
  TPOINT() = default;
  TPOINT(TDimension vx, TDimension vy) : x(vx), y(vy) {}
  TPOINT(const ICOORD &ic) : x(ic.x()), y(ic.y()) {}

  void operator+=(const TPOINT &other) {
    x += other.x;
    y += other.y;
  }
  void operator/=(int divisor) {
    x /= divisor;
    y /= divisor;
  }
  bool operator==(const TPOINT &other) const {
    return x == other.x && y == other.y;
  }
  // Returns true when the two line segments cross each other.
  // (Moved from outlines.cpp).
  static bool IsCrossed(const TPOINT &a0, const TPOINT &a1, const TPOINT &b0, const TPOINT &b1);

  // Assign the difference from point p1 to point p2.
  void diff(const TPOINT &p1, const TPOINT &p2) {
    x = p1.x - p2.x;
    y = p1.y - p2.y;
  }

  // Return cross product.
  int cross(const TPOINT &other) const {
    return x * other.y - y * other.x;
  }

  // Return scalar or dot product.
  int dot(const TPOINT &other) const {
    return x * other.x + y * other.y;
  }

  // Calculate length of vector.
  int length() const {
    return x * x + y * y;
  }

  TDimension x = 0; // absolute x coord.
  TDimension y = 0; // absolute y coord.
};

using VECTOR = TPOINT; // structure for coordinates.

struct EDGEPT {
  EDGEPT() = default;
  EDGEPT(const EDGEPT &src) : next(nullptr), prev(nullptr) {
    CopyFrom(src);
  }
  EDGEPT &operator=(const EDGEPT &src) {
    CopyFrom(src);
    return *this;
  }
  // Copies the data elements, but leaves the pointers untouched.
  void CopyFrom(const EDGEPT &src) {
    pos = src.pos;
    vec = src.vec;
    is_hidden = src.is_hidden;
    runlength = src.runlength;
    dir = src.dir;
    fixed = src.fixed;
    src_outline = src.src_outline;
    start_step = src.start_step;
    step_count = src.step_count;
  }
  // Returns the squared distance between the points, with the x-component
  // weighted by x_factor.
  int WeightedDistance(const EDGEPT &other, int x_factor) const {
    int x_dist = pos.x - other.pos.x;
    int y_dist = pos.y - other.pos.y;
    return x_dist * x_dist * x_factor + y_dist * y_dist;
  }
  // Returns true if the positions are equal.
  bool EqualPos(const EDGEPT &other) const {
    return pos == other.pos;
  }
  // Returns the bounding box of the outline segment from *this to *end.
  // Ignores hidden edge flags.
  TBOX SegmentBox(const EDGEPT *end) const {
    TBOX box(pos.x, pos.y, pos.x, pos.y);
    const EDGEPT *pt = this;
    do {
      pt = pt->next;
      if (pt->pos.x < box.left()) {
        box.set_left(pt->pos.x);
      }
      if (pt->pos.x > box.right()) {
        box.set_right(pt->pos.x);
      }
      if (pt->pos.y < box.bottom()) {
        box.set_bottom(pt->pos.y);
      }
      if (pt->pos.y > box.top()) {
        box.set_top(pt->pos.y);
      }
    } while (pt != end && pt != this);
    return box;
  }
  // Returns the area of the outline segment from *this to *end.
  // Ignores hidden edge flags.
  int SegmentArea(const EDGEPT *end) const {
    int area = 0;
    const EDGEPT *pt = this->next;
    do {
      TPOINT origin_vec(pt->pos.x - pos.x, pt->pos.y - pos.y);
      area += origin_vec.cross(pt->vec);
      pt = pt->next;
    } while (pt != end && pt != this);
    return area;
  }
  // Returns true if the number of points in the outline segment from *this to
  // *end is less that min_points and false if we get back to *this first.
  // Ignores hidden edge flags.
  bool ShortNonCircularSegment(int min_points, const EDGEPT *end) const {
    int count = 0;
    const EDGEPT *pt = this;
    do {
      if (pt == end) {
        return true;
      }
      pt = pt->next;
      ++count;
    } while (pt != this && count <= min_points);
    return false;
  }

  // Accessors to hide or reveal a cut edge from feature extractors.
  void Hide() {
    is_hidden = true;
  }
  void Reveal() {
    is_hidden = false;
  }
  bool IsHidden() const {
    return is_hidden;
  }
  void MarkChop() {
    dir = 1;
  }
  bool IsChopPt() const {
    return dir != 0;
  }

  TPOINT pos; // position
  VECTOR vec; // vector to next point
  bool is_hidden = false;
  uint8_t runlength = 0;
  int8_t dir = 0;
  int8_t fixed = 0;
  EDGEPT *next = nullptr;           // anticlockwise element
  EDGEPT *prev = nullptr;           // clockwise element
  C_OUTLINE *src_outline = nullptr; // Outline it came from.
  // The following fields are not used if src_outline is nullptr.
  int start_step = 0; // Location of pos in src_outline.
  int step_count = 0; // Number of steps used (may wrap around).
};

// For use in chop and findseam to keep a list of which EDGEPTs were inserted.
CLISTIZEH(EDGEPT)

struct TESSLINE {<commit_msg>Use bool instead of int8_t for boolean variable<commit_after>/******************************************************************************
 *
 * File:        blobs.h
 * Description: Blob definition
 * Author:      <NAME>, OCR Technology
 *
 * (c) Copyright 1989, Hewlett-Packard Company.
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
 ** You may obtain a copy of the License at
 ** http://www.apache.org/licenses/LICENSE-2.0
 ** Unless required by applicable law or agreed to in writing, software
 ** distributed under the License is distributed on an "AS IS" BASIS,
 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 *
 *****************************************************************************/

#ifndef BLOBS_H
#define BLOBS_H

#include "clst.h"       // for CLIST_ITERATOR, CLISTIZEH
#include "normalis.h"   // for DENORM
#include "points.h"     // for FCOORD, ICOORD
#include "rect.h"       // for TBOX
#include "scrollview.h" // for ScrollView, ScrollView::Color

#include <tesseract/publictypes.h> // for OcrEngineMode

#include "tesstypes.h" // for TDimension

struct Pix;

namespace tesseract {

class BLOCK;
class C_BLOB;
class C_OUTLINE;
class LLSQ;
class ROW;
class WERD;

/*----------------------------------------------------------------------
              T y p e s
----------------------------------------------------------------------*/

struct TPOINT {
  TPOINT() = default;
  TPOINT(TDimension vx, TDimension vy) : x(vx), y(vy) {}
  TPOINT(const ICOORD &ic) : x(ic.x()), y(ic.y()) {}

  void operator+=(const TPOINT &other) {
    x += other.x;
    y += other.y;
  }
  void operator/=(int divisor) {
    x /= divisor;
    y /= divisor;
  }
  bool operator==(const TPOINT &other) const {
    return x == other.x && y == other.y;
  }
  // Returns true when the two line segments cross each other.
  // (Moved from outlines.cpp).
  static bool IsCrossed(const TPOINT &a0, const TPOINT &a1, const TPOINT &b0, const TPOINT &b1);

  // Assign the difference from point p1 to point p2.
  void diff(const TPOINT &p1, const TPOINT &p2) {
    x = p1.x - p2.x;
    y = p1.y - p2.y;
  }

  // Return cross product.
  int cross(const TPOINT &other) const {
    return x * other.y - y * other.x;
  }

  // Return scalar or dot product.
  int dot(const TPOINT &other) const {
    return x * other.x + y * other.y;
  }

  // Calculate length of vector.
  int length() const {
    return x * x + y * y;
  }

  TDimension x = 0; // absolute x coord.
  TDimension y = 0; // absolute y coord.
};

using VECTOR = TPOINT; // structure for coordinates.

struct EDGEPT {
  EDGEPT() = default;
  EDGEPT(const EDGEPT &src) : next(nullptr), prev(nullptr) {
    CopyFrom(src);
  }
  EDGEPT &operator=(const EDGEPT &src) {
    CopyFrom(src);
    return *this;
  }
  // Copies the data elements, but leaves the pointers untouched.
  void CopyFrom(const EDGEPT &src) {
    pos = src.pos;
    vec = src.vec;
    is_hidden = src.is_hidden;
    runlength = src.runlength;
    dir = src.dir;
    fixed = src.fixed;
    src_outline = src.src_outline;
    start_step = src.start_step;
    step_count = src.step_count;
  }
  // Returns the squared distance between the points, with the x-component
  // weighted by x_factor.
  int WeightedDistance(const EDGEPT &other, int x_factor) const {
    int x_dist = pos.x - other.pos.x;
    int y_dist = pos.y - other.pos.y;
    return x_dist * x_dist * x_factor + y_dist * y_dist;
  }
  // Returns true if the positions are equal.
  bool EqualPos(const EDGEPT &other) const {
    return pos == other.pos;
  }
  // Returns the bounding box of the outline segment from *this to *end.
  // Ignores hidden edge flags.
  TBOX SegmentBox(const EDGEPT *end) const {
    TBOX box(pos.x, pos.y, pos.x, pos.y);
    const EDGEPT *pt = this;
    do {
      pt = pt->next;
      if (pt->pos.x < box.left()) {
        box.set_left(pt->pos.x);
      }
      if (pt->pos.x > box.right()) {
        box.set_right(pt->pos.x);
      }
      if (pt->pos.y < box.bottom()) {
        box.set_bottom(pt->pos.y);
      }
      if (pt->pos.y > box.top()) {
        box.set_top(pt->pos.y);
      }
    } while (pt != end && pt != this);
    return box;
  }
  // Returns the area of the outline segment from *this to *end.
  // Ignores hidden edge flags.
  int SegmentArea(const EDGEPT *end) const {
    int area = 0;
    const EDGEPT *pt = this->next;
    do {
      TPOINT origin_vec(pt->pos.x - pos.x, pt->pos.y - pos.y);
      area += origin_vec.cross(pt->vec);
      pt = pt->next;
    } while (pt != end && pt != this);
    return area;
  }
  // Returns true if the number of points in the outline segment from *this to
  // *end is less that min_points and false if we get back to *this first.
  // Ignores hidden edge flags.
  bool ShortNonCircularSegment(int min_points, const EDGEPT *end) const {
    int count = 0;
    const EDGEPT *pt = this;
    do {
      if (pt == end) {
        return true;
      }
      pt = pt->next;
      ++count;
    } while (pt != this && count <= min_points);
    return false;
  }

  // Accessors to hide or reveal a cut edge from feature extractors.
  void Hide() {
    is_hidden = true;
  }
  void Reveal() {
    is_hidden = false;
  }
  bool IsHidden() const {
    return is_hidden;
  }
  void MarkChop() {
    dir = 1;
  }
  bool IsChopPt() const {
    return dir != 0;
  }

  TPOINT pos; // position
  VECTOR vec; // vector to next point
  bool is_hidden = false;
  uint8_t runlength = 0;
  int8_t dir = 0;
  bool fixed = false;
  EDGEPT *next = nullptr;           // anticlockwise element
  EDGEPT *prev = nullptr;           // clockwise element
  C_OUTLINE *src_outline = nullptr; // Outline it came from.
  // The following fields are not used if src_outline is nullptr.
  int start_step = 0; // Location of pos in src_outline.
  int step_count = 0; // Number of steps used (may wrap around).
};

// For use in chop and findseam to keep a list of which EDGEPTs were inserted.
CLISTIZEH(EDGEPT)

struct TESSLINE {
{'fraction_non_alphanumeric': 0.1635067250040512, 'fraction_numerical': 0.005428617728082969, 'mean_word_length': 2.422906267332224, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7279822', 'n_tokens_mistral': 4143, 'n_tokens_neox': 4031, 'n_words': 1353}