2007-03-08 04:03:40 +08:00
|
|
|
/**********************************************************************
|
2018-07-03 20:08:12 +08:00
|
|
|
* File: pdblock.cpp
|
2007-03-08 04:03:40 +08:00
|
|
|
* Description: PDBLK member functions and iterator functions.
|
2018-07-03 20:08:12 +08:00
|
|
|
* Author: Ray Smith
|
|
|
|
* Created: Fri Mar 15 09:41:28 GMT 1991
|
2007-03-08 04:03:40 +08:00
|
|
|
*
|
|
|
|
* (C) Copyright 1991, Hewlett-Packard Ltd.
|
|
|
|
** 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.
|
|
|
|
*
|
|
|
|
**********************************************************************/
|
|
|
|
|
2017-07-15 00:30:14 +08:00
|
|
|
#include "pdblock.h"
|
2018-05-20 05:52:04 +08:00
|
|
|
#include <cstdlib>
|
2017-07-15 00:30:14 +08:00
|
|
|
#include <memory> // std::unique_ptr
|
|
|
|
#include "allheaders.h"
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2010-09-30 23:53:40 +08:00
|
|
|
// Include automatically generated configuration file if running autoconf.
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config_auto.h"
|
|
|
|
#endif
|
|
|
|
|
2007-03-08 04:03:40 +08:00
|
|
|
#define BLOCK_LABEL_HEIGHT 150 //char height of block id
|
|
|
|
|
2018-07-03 20:08:12 +08:00
|
|
|
const ERRCODE BADBLOCKLINE = "Y coordinate in block out of bounds";
|
|
|
|
const ERRCODE LOSTBLOCKLINE = "Can't find rectangle for line";
|
|
|
|
|
2007-03-08 04:03:40 +08:00
|
|
|
CLISTIZE (PDBLK)
|
|
|
|
/**********************************************************************
|
|
|
|
* PDBLK::PDBLK
|
|
|
|
*
|
|
|
|
* Constructor for a simple rectangular block.
|
|
|
|
**********************************************************************/
|
|
|
|
PDBLK::PDBLK ( //rectangular block
|
Use POSIX data types and macros (#878)
* api: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccmain: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccstruct: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* classify: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* cutil: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* dict: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* textord: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* training: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* wordrec: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccutil: Replace Tesseract data types by POSIX data types
Now all Tesseract data types which are no longer needed can be removed
from ccutil/host.h.
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccmain: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccstruct: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* classify: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* dict: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* lstm: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* textord: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* wordrec: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccutil: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Remove the macros which are now unused from ccutil/host.h.
Remove also the obsolete history comments.
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* Fix build error caused by ambiguous ClipToRange
Error message vom Appveyor CI:
C:\projects\tesseract\ccstruct\coutln.cpp(818): error C2672: 'ClipToRange': no matching overloaded function found [C:\projects\tesseract\build\libtesseract.vcxproj]
C:\projects\tesseract\ccstruct\coutln.cpp(818): error C2782: 'T ClipToRange(const T &,const T &,const T &)': template parameter 'T' is ambiguous [C:\projects\tesseract\build\libtesseract.vcxproj]
c:\projects\tesseract\ccutil\helpers.h(122): note: see declaration of 'ClipToRange'
C:\projects\tesseract\ccstruct\coutln.cpp(818): note: could be 'char'
C:\projects\tesseract\ccstruct\coutln.cpp(818): note: or 'int'
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* unittest: Replace Tesseract's MAX_INT8 by POSIX INT8_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* arch: Replace Tesseract's MAX_INT8 by POSIX INT8_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
2018-03-14 04:36:30 +08:00
|
|
|
int16_t xmin, //bottom left
|
|
|
|
int16_t ymin, int16_t xmax, //top right
|
|
|
|
int16_t ymax): box (ICOORD (xmin, ymin), ICOORD (xmax, ymax)) {
|
2007-03-08 04:03:40 +08:00
|
|
|
//boundaries
|
|
|
|
ICOORDELT_IT left_it = &leftside;
|
|
|
|
ICOORDELT_IT right_it = &rightside;
|
|
|
|
|
2016-12-13 00:20:05 +08:00
|
|
|
hand_poly = nullptr;
|
2007-03-08 04:03:40 +08:00
|
|
|
left_it.set_to_list (&leftside);
|
|
|
|
right_it.set_to_list (&rightside);
|
|
|
|
//make default box
|
|
|
|
left_it.add_to_end (new ICOORDELT (xmin, ymin));
|
|
|
|
left_it.add_to_end (new ICOORDELT (xmin, ymax));
|
|
|
|
right_it.add_to_end (new ICOORDELT (xmax, ymin));
|
|
|
|
right_it.add_to_end (new ICOORDELT (xmax, ymax));
|
2009-07-11 10:14:57 +08:00
|
|
|
index_ = 0;
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* PDBLK::set_sides
|
|
|
|
*
|
|
|
|
* Sets left and right vertex lists
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
void PDBLK::set_sides( //set vertex lists
|
|
|
|
ICOORDELT_LIST *left, //left vertices
|
|
|
|
ICOORDELT_LIST *right //right vertices
|
|
|
|
) {
|
|
|
|
//boundaries
|
|
|
|
ICOORDELT_IT left_it = &leftside;
|
|
|
|
ICOORDELT_IT right_it = &rightside;
|
|
|
|
|
2018-05-21 03:46:46 +08:00
|
|
|
leftside.clear();
|
|
|
|
left_it.move_to_first();
|
|
|
|
left_it.add_list_before(left);
|
|
|
|
rightside.clear();
|
|
|
|
right_it.move_to_first();
|
|
|
|
right_it.add_list_before(right);
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* PDBLK::contains
|
|
|
|
*
|
|
|
|
* Return TRUE if the given point is within the block.
|
|
|
|
**********************************************************************/
|
|
|
|
|
2018-05-21 03:46:46 +08:00
|
|
|
bool PDBLK::contains( //test containment
|
|
|
|
ICOORD pt //point to test
|
|
|
|
) {
|
2007-03-08 04:03:40 +08:00
|
|
|
BLOCK_RECT_IT it = this; //rectangle iterator
|
|
|
|
ICOORD bleft, tright; //corners of rectangle
|
|
|
|
|
2018-05-21 03:46:46 +08:00
|
|
|
for (it.start_block(); !it.cycled_rects(); it.forward()) {
|
2007-03-08 04:03:40 +08:00
|
|
|
//get rectangle
|
|
|
|
it.bounding_box (bleft, tright);
|
|
|
|
//inside rect
|
2018-05-21 03:46:46 +08:00
|
|
|
if (pt.x() >= bleft.x() && pt.x() <= tright.x()
|
|
|
|
&& pt.y() >= bleft.y() && pt.y() <= tright.y())
|
|
|
|
return true; //is inside
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
2018-05-21 03:46:46 +08:00
|
|
|
return false; //not inside
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* PDBLK::move
|
|
|
|
*
|
|
|
|
* Reposition block
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
void PDBLK::move( // reposition block
|
|
|
|
const ICOORD vec // by vector
|
|
|
|
) {
|
2008-04-22 08:41:37 +08:00
|
|
|
ICOORDELT_IT it(&leftside);
|
2007-03-08 04:03:40 +08:00
|
|
|
|
|
|
|
for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
|
|
|
|
*(it.data ()) += vec;
|
|
|
|
|
|
|
|
it.set_to_list (&rightside);
|
|
|
|
|
|
|
|
for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
|
|
|
|
*(it.data ()) += vec;
|
|
|
|
|
|
|
|
box.move (vec);
|
|
|
|
}
|
|
|
|
|
2010-11-24 02:34:14 +08:00
|
|
|
// Returns a binary Pix mask with a 1 pixel for every pixel within the
|
|
|
|
// block. Rotates the coordinate system by rerotation prior to rendering.
|
2015-05-13 07:47:02 +08:00
|
|
|
Pix* PDBLK::render_mask(const FCOORD& rerotation, TBOX* mask_box) {
|
2010-11-24 02:34:14 +08:00
|
|
|
TBOX rotated_box(box);
|
|
|
|
rotated_box.rotate(rerotation);
|
|
|
|
Pix* pix = pixCreate(rotated_box.width(), rotated_box.height(), 1);
|
2016-12-13 00:20:05 +08:00
|
|
|
if (hand_poly != nullptr) {
|
2010-11-24 02:34:14 +08:00
|
|
|
// We are going to rotate, so get a deep copy of the points and
|
|
|
|
// make a new POLY_BLOCK with it.
|
|
|
|
ICOORDELT_LIST polygon;
|
|
|
|
polygon.deep_copy(hand_poly->points(), ICOORDELT::deep_copy);
|
|
|
|
POLY_BLOCK image_block(&polygon, hand_poly->isA());
|
|
|
|
image_block.rotate(rerotation);
|
|
|
|
// Block outline is a polygon, so use a PB_LINE_IT to get the
|
|
|
|
// rasterized interior. (Runs of interior pixels on a line.)
|
|
|
|
PB_LINE_IT *lines = new PB_LINE_IT(&image_block);
|
|
|
|
for (int y = box.bottom(); y < box.top(); ++y) {
|
2017-07-15 00:30:14 +08:00
|
|
|
const std::unique_ptr</*non-const*/ ICOORDELT_LIST> segments(
|
|
|
|
lines->get_line(y));
|
2010-11-24 02:34:14 +08:00
|
|
|
if (!segments->empty()) {
|
2017-05-10 21:23:49 +08:00
|
|
|
ICOORDELT_IT s_it(segments.get());
|
2010-11-24 02:34:14 +08:00
|
|
|
// Each element of segments is a start x and x size of the
|
|
|
|
// run of interior pixels.
|
|
|
|
for (s_it.mark_cycle_pt(); !s_it.cycled_list(); s_it.forward()) {
|
|
|
|
int start = s_it.data()->x();
|
|
|
|
int xext = s_it.data()->y();
|
|
|
|
// Set the run of pixels to 1.
|
|
|
|
pixRasterop(pix, start - rotated_box.left(),
|
|
|
|
rotated_box.height() - 1 - (y - rotated_box.bottom()),
|
2016-12-13 00:20:05 +08:00
|
|
|
xext, 1, PIX_SET, nullptr, 0, 0);
|
2010-11-24 02:34:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
delete lines;
|
|
|
|
} else {
|
|
|
|
// Just fill the whole block as there is only a bounding box.
|
|
|
|
pixRasterop(pix, 0, 0, rotated_box.width(), rotated_box.height(),
|
2016-12-13 00:20:05 +08:00
|
|
|
PIX_SET, nullptr, 0, 0);
|
2010-11-24 02:34:14 +08:00
|
|
|
}
|
2016-12-13 00:20:05 +08:00
|
|
|
if (mask_box != nullptr) *mask_box = rotated_box;
|
2010-11-24 02:34:14 +08:00
|
|
|
return pix;
|
|
|
|
}
|
|
|
|
|
2007-03-08 04:03:40 +08:00
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* PDBLK::plot
|
|
|
|
*
|
|
|
|
* Plot the outline of a block in the given colour.
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
#ifndef GRAPHICS_DISABLED
|
|
|
|
void PDBLK::plot( //draw outline
|
2008-02-01 08:36:18 +08:00
|
|
|
ScrollView* window, //window to draw in
|
Use POSIX data types and macros (#878)
* api: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccmain: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccstruct: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* classify: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* cutil: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* dict: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* textord: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* training: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* wordrec: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccutil: Replace Tesseract data types by POSIX data types
Now all Tesseract data types which are no longer needed can be removed
from ccutil/host.h.
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccmain: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccstruct: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* classify: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* dict: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* lstm: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* textord: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* wordrec: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccutil: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Remove the macros which are now unused from ccutil/host.h.
Remove also the obsolete history comments.
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* Fix build error caused by ambiguous ClipToRange
Error message vom Appveyor CI:
C:\projects\tesseract\ccstruct\coutln.cpp(818): error C2672: 'ClipToRange': no matching overloaded function found [C:\projects\tesseract\build\libtesseract.vcxproj]
C:\projects\tesseract\ccstruct\coutln.cpp(818): error C2782: 'T ClipToRange(const T &,const T &,const T &)': template parameter 'T' is ambiguous [C:\projects\tesseract\build\libtesseract.vcxproj]
c:\projects\tesseract\ccutil\helpers.h(122): note: see declaration of 'ClipToRange'
C:\projects\tesseract\ccstruct\coutln.cpp(818): note: could be 'char'
C:\projects\tesseract\ccstruct\coutln.cpp(818): note: or 'int'
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* unittest: Replace Tesseract's MAX_INT8 by POSIX INT8_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* arch: Replace Tesseract's MAX_INT8 by POSIX INT8_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
2018-03-14 04:36:30 +08:00
|
|
|
int32_t serial, //serial number
|
2008-02-01 08:36:18 +08:00
|
|
|
ScrollView::Color colour //colour to draw in
|
2007-03-08 04:03:40 +08:00
|
|
|
) {
|
|
|
|
ICOORD startpt; //start of outline
|
|
|
|
ICOORD endpt; //end of outline
|
|
|
|
ICOORD prevpt; //previous point
|
|
|
|
ICOORDELT_IT it = &leftside; //iterator
|
|
|
|
|
|
|
|
//set the colour
|
2008-04-22 08:41:37 +08:00
|
|
|
window->Pen(colour);
|
2008-02-01 08:36:18 +08:00
|
|
|
window->TextAttributes("Times", BLOCK_LABEL_HEIGHT, false, false, false);
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2016-12-13 00:20:05 +08:00
|
|
|
if (hand_poly != nullptr) {
|
2009-07-11 10:14:57 +08:00
|
|
|
hand_poly->plot(window, serial);
|
2008-12-31 02:15:44 +08:00
|
|
|
} else if (!leftside.empty ()) {
|
2007-03-08 04:03:40 +08:00
|
|
|
startpt = *(it.data ()); //bottom left corner
|
|
|
|
// tprintf("Block %d bottom left is (%d,%d)\n",
|
|
|
|
// serial,startpt.x(),startpt.y());
|
|
|
|
char temp_buff[34];
|
2014-01-22 16:10:15 +08:00
|
|
|
#if defined(__UNIX__) || defined(MINGW)
|
2017-07-15 00:30:14 +08:00
|
|
|
snprintf(temp_buff, sizeof(temp_buff), "%" PRId32, serial);
|
2007-03-08 04:03:40 +08:00
|
|
|
#else
|
|
|
|
ultoa (serial, temp_buff, 10);
|
|
|
|
#endif
|
2008-02-01 08:36:18 +08:00
|
|
|
window->Text(startpt.x (), startpt.y (), temp_buff);
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2008-02-01 08:36:18 +08:00
|
|
|
window->SetCursor(startpt.x (), startpt.y ());
|
2007-03-08 04:03:40 +08:00
|
|
|
do {
|
|
|
|
prevpt = *(it.data ()); //previous point
|
|
|
|
it.forward (); //move to next point
|
|
|
|
//draw round corner
|
2008-02-01 08:36:18 +08:00
|
|
|
window->DrawTo(prevpt.x (), it.data ()->y ());
|
|
|
|
window->DrawTo(it.data ()->x (), it.data ()->y ());
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
while (!it.at_last ()); //until end of list
|
|
|
|
endpt = *(it.data ()); //end point
|
|
|
|
|
|
|
|
//other side of boundary
|
2008-02-01 08:36:18 +08:00
|
|
|
window->SetCursor(startpt.x (), startpt.y ());
|
2007-03-08 04:03:40 +08:00
|
|
|
it.set_to_list (&rightside);
|
|
|
|
prevpt = startpt;
|
|
|
|
for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
|
|
|
|
//draw round corner
|
2008-02-01 08:36:18 +08:00
|
|
|
window->DrawTo(prevpt.x (), it.data ()->y ());
|
|
|
|
window->DrawTo(it.data ()->x (), it.data ()->y ());
|
2007-03-08 04:03:40 +08:00
|
|
|
prevpt = *(it.data ()); //previous point
|
|
|
|
}
|
|
|
|
//close boundary
|
2008-02-01 08:36:18 +08:00
|
|
|
window->DrawTo(endpt.x(), endpt.y());
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* PDBLK::operator=
|
|
|
|
*
|
|
|
|
* Assignment - duplicate the block structure, but with an EMPTY row list.
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
PDBLK & PDBLK::operator= ( //assignment
|
|
|
|
const PDBLK & source //from this
|
|
|
|
) {
|
|
|
|
// this->ELIST_LINK::operator=(source);
|
|
|
|
if (!leftside.empty ())
|
|
|
|
leftside.clear ();
|
|
|
|
if (!rightside.empty ())
|
|
|
|
rightside.clear ();
|
2008-12-31 02:15:44 +08:00
|
|
|
leftside.deep_copy(&source.leftside, &ICOORDELT::deep_copy);
|
|
|
|
rightside.deep_copy(&source.rightside, &ICOORDELT::deep_copy);
|
2007-03-08 04:03:40 +08:00
|
|
|
box = source.box;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* BLOCK_RECT_IT::BLOCK_RECT_IT
|
|
|
|
*
|
|
|
|
* Construct a block rectangle iterator.
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
BLOCK_RECT_IT::BLOCK_RECT_IT (
|
|
|
|
//iterate rectangles
|
|
|
|
PDBLK * blkptr //from block
|
|
|
|
):left_it (&blkptr->leftside), right_it (&blkptr->rightside) {
|
|
|
|
block = blkptr; //remember block
|
|
|
|
//non empty list
|
|
|
|
if (!blkptr->leftside.empty ()) {
|
|
|
|
start_block(); //ready for iteration
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* BLOCK_RECT_IT::set_to_block
|
|
|
|
*
|
|
|
|
* Start a new block.
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
void BLOCK_RECT_IT::set_to_block( //start (new) block
|
|
|
|
PDBLK *blkptr) { //block to start
|
|
|
|
block = blkptr; //remember block
|
|
|
|
//set iterators
|
|
|
|
left_it.set_to_list (&blkptr->leftside);
|
|
|
|
right_it.set_to_list (&blkptr->rightside);
|
|
|
|
if (!blkptr->leftside.empty ())
|
|
|
|
start_block(); //ready for iteration
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* BLOCK_RECT_IT::start_block
|
|
|
|
*
|
|
|
|
* Restart a block.
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
void BLOCK_RECT_IT::start_block() { //start (new) block
|
|
|
|
left_it.move_to_first ();
|
|
|
|
right_it.move_to_first ();
|
|
|
|
left_it.mark_cycle_pt ();
|
|
|
|
right_it.mark_cycle_pt ();
|
|
|
|
ymin = left_it.data ()->y (); //bottom of first box
|
|
|
|
ymax = left_it.data_relative (1)->y ();
|
|
|
|
if (right_it.data_relative (1)->y () < ymax)
|
|
|
|
//smallest step
|
|
|
|
ymax = right_it.data_relative (1)->y ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* BLOCK_RECT_IT::forward
|
|
|
|
*
|
|
|
|
* Move to the next rectangle in the block.
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
void BLOCK_RECT_IT::forward() { //next rectangle
|
|
|
|
if (!left_it.empty ()) { //non-empty list
|
|
|
|
if (left_it.data_relative (1)->y () == ymax)
|
|
|
|
left_it.forward (); //move to meet top
|
|
|
|
if (right_it.data_relative (1)->y () == ymax)
|
|
|
|
right_it.forward ();
|
|
|
|
//last is special
|
|
|
|
if (left_it.at_last () || right_it.at_last ()) {
|
|
|
|
left_it.move_to_first (); //restart
|
|
|
|
right_it.move_to_first ();
|
|
|
|
//now at bottom
|
|
|
|
ymin = left_it.data ()->y ();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ymin = ymax; //new bottom
|
|
|
|
}
|
|
|
|
//next point
|
|
|
|
ymax = left_it.data_relative (1)->y ();
|
|
|
|
if (right_it.data_relative (1)->y () < ymax)
|
|
|
|
//least step forward
|
|
|
|
ymax = right_it.data_relative (1)->y ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* BLOCK_LINE_IT::get_line
|
|
|
|
*
|
|
|
|
* Get the the start and width of a line in the block.
|
|
|
|
**********************************************************************/
|
|
|
|
|
Use POSIX data types and macros (#878)
* api: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccmain: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccstruct: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* classify: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* cutil: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* dict: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* textord: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* training: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* wordrec: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccutil: Replace Tesseract data types by POSIX data types
Now all Tesseract data types which are no longer needed can be removed
from ccutil/host.h.
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccmain: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccstruct: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* classify: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* dict: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* lstm: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* textord: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* wordrec: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccutil: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Remove the macros which are now unused from ccutil/host.h.
Remove also the obsolete history comments.
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* Fix build error caused by ambiguous ClipToRange
Error message vom Appveyor CI:
C:\projects\tesseract\ccstruct\coutln.cpp(818): error C2672: 'ClipToRange': no matching overloaded function found [C:\projects\tesseract\build\libtesseract.vcxproj]
C:\projects\tesseract\ccstruct\coutln.cpp(818): error C2782: 'T ClipToRange(const T &,const T &,const T &)': template parameter 'T' is ambiguous [C:\projects\tesseract\build\libtesseract.vcxproj]
c:\projects\tesseract\ccutil\helpers.h(122): note: see declaration of 'ClipToRange'
C:\projects\tesseract\ccstruct\coutln.cpp(818): note: could be 'char'
C:\projects\tesseract\ccstruct\coutln.cpp(818): note: or 'int'
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* unittest: Replace Tesseract's MAX_INT8 by POSIX INT8_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* arch: Replace Tesseract's MAX_INT8 by POSIX INT8_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
2018-03-14 04:36:30 +08:00
|
|
|
int16_t BLOCK_LINE_IT::get_line( //get a line
|
|
|
|
int16_t y, //line to get
|
|
|
|
int16_t &xext //output extent
|
2007-03-08 04:03:40 +08:00
|
|
|
) {
|
|
|
|
ICOORD bleft; //bounding box
|
|
|
|
ICOORD tright; //of block & rect
|
|
|
|
|
|
|
|
//get block box
|
|
|
|
block->bounding_box (bleft, tright);
|
|
|
|
if (y < bleft.y () || y >= tright.y ()) {
|
|
|
|
// block->print(stderr,FALSE);
|
|
|
|
BADBLOCKLINE.error ("BLOCK_LINE_IT::get_line", ABORT, "Y=%d", y);
|
|
|
|
}
|
|
|
|
|
|
|
|
//get rectangle box
|
|
|
|
rect_it.bounding_box (bleft, tright);
|
|
|
|
//inside rectangle
|
|
|
|
if (y >= bleft.y () && y < tright.y ()) {
|
|
|
|
//width of line
|
|
|
|
xext = tright.x () - bleft.x ();
|
|
|
|
return bleft.x (); //start of line
|
|
|
|
}
|
|
|
|
for (rect_it.start_block (); !rect_it.cycled_rects (); rect_it.forward ()) {
|
|
|
|
//get rectangle box
|
|
|
|
rect_it.bounding_box (bleft, tright);
|
|
|
|
//inside rectangle
|
|
|
|
if (y >= bleft.y () && y < tright.y ()) {
|
|
|
|
//width of line
|
|
|
|
xext = tright.x () - bleft.x ();
|
|
|
|
return bleft.x (); //start of line
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LOSTBLOCKLINE.error ("BLOCK_LINE_IT::get_line", ABORT, "Y=%d", y);
|
|
|
|
return 0; //dummy to stop warning
|
|
|
|
}
|