/src/tesseract/src/ccstruct/points.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /********************************************************************** |
2 | | * File: points.cpp (Formerly coords.c) |
3 | | * Description: Member functions for coordinate classes. |
4 | | * Author: Ray Smith |
5 | | * |
6 | | * (C) Copyright 1991, Hewlett-Packard Ltd. |
7 | | ** Licensed under the Apache License, Version 2.0 (the "License"); |
8 | | ** you may not use this file except in compliance with the License. |
9 | | ** You may obtain a copy of the License at |
10 | | ** http://www.apache.org/licenses/LICENSE-2.0 |
11 | | ** Unless required by applicable law or agreed to in writing, software |
12 | | ** distributed under the License is distributed on an "AS IS" BASIS, |
13 | | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 | | ** See the License for the specific language governing permissions and |
15 | | ** limitations under the License. |
16 | | * |
17 | | **********************************************************************/ |
18 | | |
19 | | #define _USE_MATH_DEFINES // for M_PI |
20 | | |
21 | | #include "points.h" |
22 | | |
23 | | #include "helpers.h" |
24 | | #include "serialis.h" |
25 | | |
26 | | #include <algorithm> |
27 | | #include <cmath> // for M_PI |
28 | | #include <cstdlib> |
29 | | |
30 | | namespace tesseract { |
31 | | |
32 | 0 | bool FCOORD::normalise() { // Convert to unit vec |
33 | 0 | float len = length(); |
34 | |
|
35 | 0 | if (len < 0.0000000001) { |
36 | 0 | return false; |
37 | 0 | } |
38 | 0 | xcoord /= len; |
39 | 0 | ycoord /= len; |
40 | 0 | return true; |
41 | 0 | } |
42 | | |
43 | 0 | bool ICOORD::DeSerialize(TFile *f) { |
44 | 0 | return f->DeSerialize(&xcoord) && f->DeSerialize(&ycoord); |
45 | 0 | } |
46 | | |
47 | 0 | bool ICOORD::Serialize(TFile *f) const { |
48 | 0 | return f->Serialize(&xcoord) && f->Serialize(&ycoord); |
49 | 0 | } |
50 | | |
51 | | // Set from the given x,y, shrinking the vector to fit if needed. |
52 | 0 | void ICOORD::set_with_shrink(int x, int y) { |
53 | | // Fit the vector into an ICOORD, which is 16 bit. |
54 | 0 | int factor = 1; |
55 | 0 | int max_extent = std::max(abs(x), abs(y)); |
56 | 0 | if (max_extent > INT16_MAX) { |
57 | 0 | factor = max_extent / INT16_MAX + 1; |
58 | 0 | } |
59 | 0 | xcoord = x / factor; |
60 | 0 | ycoord = y / factor; |
61 | 0 | } |
62 | | |
63 | | // The fortran/basic sgn function returns -1, 0, 1 if x < 0, x == 0, x > 0 |
64 | | // respectively. |
65 | 0 | static int sign(int x) { |
66 | 0 | if (x < 0) { |
67 | 0 | return -1; |
68 | 0 | } else { |
69 | 0 | return x > 0 ? 1 : 0; |
70 | 0 | } |
71 | 0 | } |
72 | | |
73 | | // Writes to the given file. Returns false in case of error. |
74 | 0 | bool ICOORD::Serialize(FILE *fp) const { |
75 | 0 | return tesseract::Serialize(fp, &xcoord) && tesseract::Serialize(fp, &ycoord); |
76 | 0 | } |
77 | | // Reads from the given file. Returns false in case of error. |
78 | | // If swap is true, assumes a big/little-endian swap is needed. |
79 | 0 | bool ICOORD::DeSerialize(bool swap, FILE *fp) { |
80 | 0 | if (!tesseract::DeSerialize(fp, &xcoord)) { |
81 | 0 | return false; |
82 | 0 | } |
83 | 0 | if (!tesseract::DeSerialize(fp, &ycoord)) { |
84 | 0 | return false; |
85 | 0 | } |
86 | 0 | if (swap) { |
87 | 0 | ReverseN(&xcoord, sizeof(xcoord)); |
88 | 0 | ReverseN(&ycoord, sizeof(ycoord)); |
89 | 0 | } |
90 | 0 | return true; |
91 | 0 | } |
92 | | |
93 | | // Setup for iterating over the pixels in a vector by the well-known |
94 | | // Bresenham rendering algorithm. |
95 | | // Starting with major/2 in the accumulator, on each step add major_step, |
96 | | // and then add minor to the accumulator. When the accumulator >= major |
97 | | // subtract major and step a minor step. |
98 | | |
99 | 0 | void ICOORD::setup_render(ICOORD *major_step, ICOORD *minor_step, int *major, int *minor) const { |
100 | 0 | int abs_x = abs(xcoord); |
101 | 0 | int abs_y = abs(ycoord); |
102 | 0 | if (abs_x >= abs_y) { |
103 | | // X-direction is major. |
104 | 0 | major_step->xcoord = sign(xcoord); |
105 | 0 | major_step->ycoord = 0; |
106 | 0 | minor_step->xcoord = 0; |
107 | 0 | minor_step->ycoord = sign(ycoord); |
108 | 0 | *major = abs_x; |
109 | 0 | *minor = abs_y; |
110 | 0 | } else { |
111 | | // Y-direction is major. |
112 | 0 | major_step->xcoord = 0; |
113 | 0 | major_step->ycoord = sign(ycoord); |
114 | 0 | minor_step->xcoord = sign(xcoord); |
115 | 0 | minor_step->ycoord = 0; |
116 | 0 | *major = abs_y; |
117 | 0 | *minor = abs_x; |
118 | 0 | } |
119 | 0 | } |
120 | | |
121 | | // Returns the standard feature direction corresponding to this. |
122 | | // See binary_angle_plus_pi below for a description of the direction. |
123 | 125M | uint8_t FCOORD::to_direction() const { |
124 | 125M | return binary_angle_plus_pi(angle()); |
125 | 125M | } |
126 | | // Sets this with a unit vector in the given standard feature direction. |
127 | 0 | void FCOORD::from_direction(uint8_t direction) { |
128 | 0 | double radians = angle_from_direction(direction); |
129 | 0 | xcoord = cos(radians); |
130 | 0 | ycoord = sin(radians); |
131 | 0 | } |
132 | | |
133 | | // Converts an angle in radians (from ICOORD::angle or FCOORD::angle) to a |
134 | | // standard feature direction as an unsigned angle in 256ths of a circle |
135 | | // measured anticlockwise from (-1, 0). |
136 | 125M | uint8_t FCOORD::binary_angle_plus_pi(double radians) { |
137 | 125M | return Modulo(IntCastRounded((radians + M_PI) * 128.0 / M_PI), 256); |
138 | 125M | } |
139 | | // Inverse of binary_angle_plus_pi returns an angle in radians for the |
140 | | // given standard feature direction. |
141 | 0 | double FCOORD::angle_from_direction(uint8_t direction) { |
142 | 0 | return direction * M_PI / 128.0 - M_PI; |
143 | 0 | } |
144 | | |
145 | | // Returns the point on the given line nearest to this, ie the point such |
146 | | // that the vector point->this is perpendicular to the line. |
147 | | // The line is defined as a line_point and a dir_vector for its direction. |
148 | 0 | FCOORD FCOORD::nearest_pt_on_line(const FCOORD &line_point, const FCOORD &dir_vector) const { |
149 | 0 | FCOORD point_vector(*this - line_point); |
150 | | // The dot product (%) is |dir_vector||point_vector|cos theta, so dividing by |
151 | | // the square of the length of dir_vector gives us the fraction of dir_vector |
152 | | // to add to line1 to get the appropriate point, so |
153 | | // result = line1 + lambda dir_vector. |
154 | 0 | double lambda = point_vector % dir_vector / dir_vector.sqlength(); |
155 | 0 | return line_point + (dir_vector * lambda); |
156 | 0 | } |
157 | | |
158 | | } // namespace tesseract |