tesseract
3.03
|
00001 /********************************************************************** 00002 * File: points.c (Formerly coords.c) 00003 * Description: Member functions for coordinate classes. 00004 * Author: Ray Smith 00005 * Created: Fri Mar 15 08:58:17 GMT 1991 00006 * 00007 * (C) Copyright 1991, Hewlett-Packard Ltd. 00008 ** Licensed under the Apache License, Version 2.0 (the "License"); 00009 ** you may not use this file except in compliance with the License. 00010 ** You may obtain a copy of the License at 00011 ** http://www.apache.org/licenses/LICENSE-2.0 00012 ** Unless required by applicable law or agreed to in writing, software 00013 ** distributed under the License is distributed on an "AS IS" BASIS, 00014 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 ** See the License for the specific language governing permissions and 00016 ** limitations under the License. 00017 * 00018 **********************************************************************/ 00019 00020 #ifdef _MSC_VER 00021 #define _USE_MATH_DEFINES 00022 #endif // _MSC_VER 00023 00024 #include <stdlib.h> 00025 #include "helpers.h" 00026 #include "ndminx.h" 00027 #include "serialis.h" 00028 #include "points.h" 00029 00030 ELISTIZE (ICOORDELT) //turn to list 00031 bool FCOORD::normalise() { //Convert to unit vec 00032 float len = length (); 00033 00034 if (len < 0.0000000001) { 00035 return false; 00036 } 00037 xcoord /= len; 00038 ycoord /= len; 00039 return true; 00040 } 00041 00042 // Set from the given x,y, shrinking the vector to fit if needed. 00043 void ICOORD::set_with_shrink(int x, int y) { 00044 // Fit the vector into an ICOORD, which is 16 bit. 00045 int factor = 1; 00046 int max_extent = MAX(abs(x), abs(y)); 00047 if (max_extent > MAX_INT16) 00048 factor = max_extent / MAX_INT16 + 1; 00049 xcoord = x / factor; 00050 ycoord = y / factor; 00051 } 00052 00053 // The fortran/basic sgn function returns -1, 0, 1 if x < 0, x == 0, x > 0 00054 // respectively. 00055 static int sign(int x) { 00056 if (x < 0) 00057 return -1; 00058 else 00059 return x > 0 ? 1 : 0; 00060 } 00061 00062 // Writes to the given file. Returns false in case of error. 00063 bool ICOORD::Serialize(FILE* fp) const { 00064 if (fwrite(&xcoord, sizeof(xcoord), 1, fp) != 1) return false; 00065 if (fwrite(&ycoord, sizeof(ycoord), 1, fp) != 1) return false; 00066 return true; 00067 } 00068 // Reads from the given file. Returns false in case of error. 00069 // If swap is true, assumes a big/little-endian swap is needed. 00070 bool ICOORD::DeSerialize(bool swap, FILE* fp) { 00071 if (fread(&xcoord, sizeof(xcoord), 1, fp) != 1) return false; 00072 if (fread(&ycoord, sizeof(ycoord), 1, fp) != 1) return false; 00073 if (swap) { 00074 ReverseN(&xcoord, sizeof(xcoord)); 00075 ReverseN(&ycoord, sizeof(ycoord)); 00076 } 00077 return true; 00078 } 00079 00080 // Setup for iterating over the pixels in a vector by the well-known 00081 // Bresenham rendering algorithm. 00082 // Starting with major/2 in the accumulator, on each step add major_step, 00083 // and then add minor to the accumulator. When the accumulator >= major 00084 // subtract major and step a minor step. 00085 00086 void ICOORD::setup_render(ICOORD* major_step, ICOORD* minor_step, 00087 int* major, int* minor) const { 00088 int abs_x = abs(xcoord); 00089 int abs_y = abs(ycoord); 00090 if (abs_x >= abs_y) { 00091 // X-direction is major. 00092 major_step->xcoord = sign(xcoord); 00093 major_step->ycoord = 0; 00094 minor_step->xcoord = 0; 00095 minor_step->ycoord = sign(ycoord); 00096 *major = abs_x; 00097 *minor = abs_y; 00098 } else { 00099 // Y-direction is major. 00100 major_step->xcoord = 0; 00101 major_step->ycoord = sign(ycoord); 00102 minor_step->xcoord = sign(xcoord); 00103 minor_step->ycoord = 0; 00104 *major = abs_y; 00105 *minor = abs_x; 00106 } 00107 } 00108 00109 // Returns the standard feature direction corresponding to this. 00110 // See binary_angle_plus_pi below for a description of the direction. 00111 uinT8 FCOORD::to_direction() const { 00112 return binary_angle_plus_pi(angle()); 00113 } 00114 // Sets this with a unit vector in the given standard feature direction. 00115 void FCOORD::from_direction(uinT8 direction) { 00116 double radians = angle_from_direction(direction); 00117 xcoord = cos(radians); 00118 ycoord = sin(radians); 00119 } 00120 00121 // Converts an angle in radians (from ICOORD::angle or FCOORD::angle) to a 00122 // standard feature direction as an unsigned angle in 256ths of a circle 00123 // measured anticlockwise from (-1, 0). 00124 uinT8 FCOORD::binary_angle_plus_pi(double radians) { 00125 return Modulo(IntCastRounded((radians + M_PI) * 128.0 / M_PI), 256); 00126 } 00127 // Inverse of binary_angle_plus_pi returns an angle in radians for the 00128 // given standard feature direction. 00129 double FCOORD::angle_from_direction(uinT8 direction) { 00130 return direction * M_PI / 128.0 - M_PI; 00131 } 00132 00133 // Returns the point on the given line nearest to this, ie the point such 00134 // that the vector point->this is perpendicular to the line. 00135 // The line is defined as a line_point and a dir_vector for its direction. 00136 FCOORD FCOORD::nearest_pt_on_line(const FCOORD& line_point, 00137 const FCOORD& dir_vector) const { 00138 FCOORD point_vector(*this - line_point); 00139 // The dot product (%) is |dir_vector||point_vector|cos theta, so dividing by 00140 // the square of the length of dir_vector gives us the fraction of dir_vector 00141 // to add to line1 to get the appropriate point, so 00142 // result = line1 + lambda dir_vector. 00143 double lambda = point_vector % dir_vector / dir_vector.sqlength(); 00144 return line_point + (dir_vector * lambda); 00145 }