00001 /** 00002 \file Robots/LoBot/misc/LoClipper.C 00003 00004 This file defines the non-inline member functions of the 00005 lobot::Clipper class. 00006 */ 00007 00008 // //////////////////////////////////////////////////////////////////// // 00009 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00010 // by the University of Southern California (USC) and the iLab at USC. // 00011 // See http://iLab.usc.edu for information about this project. // 00012 // //////////////////////////////////////////////////////////////////// // 00013 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00014 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00015 // in Visual Environments, and Applications'' by Christof Koch and // 00016 // Laurent Itti, California Institute of Technology, 2001 (patent // 00017 // pending; application number 09/912,225 filed July 23, 2001; see // 00018 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00019 // //////////////////////////////////////////////////////////////////// // 00020 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00023 // redistribute it and/or modify it under the terms of the GNU General // 00024 // Public License as published by the Free Software Foundation; either // 00025 // version 2 of the License, or (at your option) any later version. // 00026 // // 00027 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00028 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00029 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00030 // PURPOSE. See the GNU General Public License for more details. // 00031 // // 00032 // You should have received a copy of the GNU General Public License // 00033 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00034 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00035 // Boston, MA 02111-1307 USA. // 00036 // //////////////////////////////////////////////////////////////////// // 00037 // 00038 // Primary maintainer for this file: mviswana usc edu 00039 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/LoBot/misc/LoClipper.C $ 00040 // $Id: LoClipper.C 13445 2010-05-21 06:12:57Z mviswana $ 00041 // 00042 00043 //------------------------------ HEADERS -------------------------------- 00044 00045 // lobot headers 00046 #include "Robots/LoBot/misc/LoClipper.H" 00047 00048 //----------------------------- NAMESPACE ------------------------------- 00049 00050 namespace lobot { 00051 00052 //------------------------- INITIALIZATION ----------------------------- 00053 00054 Clipper::Clipper(float left, float right, float bottom, float top) 00055 { 00056 clip_boundary(left, right, bottom, top) ; 00057 } 00058 00059 Clipper::Clipper(const float boundary[4]) 00060 { 00061 clip_boundary(boundary) ; 00062 } 00063 00064 //------------------ COHEN-SUTHERLAND LINE CLIPPING --------------------- 00065 00066 unsigned char 00067 Clipper:: 00068 clip(const float end_points[4], float new_end_points[4]) const 00069 { 00070 unsigned char return_code = 0 ; 00071 00072 new_end_points[0] = end_points[0] ; 00073 new_end_points[1] = end_points[1] ; 00074 new_end_points[2] = end_points[2] ; 00075 new_end_points[3] = end_points[3] ; 00076 00077 float dx = new_end_points[2] - new_end_points[0] ; 00078 float dy = new_end_points[3] - new_end_points[1] ; 00079 00080 for(;;) 00081 { 00082 unsigned char code1 = cs_code(new_end_points) ; 00083 unsigned char code2 = cs_code(new_end_points + 2) ; 00084 00085 if (trivial_accept(code1, code2)) { 00086 if (return_code == 0) 00087 return_code = COMPLETELY_INSIDE ; 00088 return return_code ; 00089 } 00090 00091 if (trivial_reject(code1, code2)) 00092 return COMPLETELY_OUTSIDE ; 00093 00094 if (outside(new_end_points)) 00095 { // first end-point outside clipping rectangle 00096 chop(new_end_points, code1, dx, dy) ; 00097 return_code |= FIRST_POINT_CLIPPED ; 00098 } 00099 else // second end-point must be outside clipping rectangle 00100 { // or else the line would have been accepted or rejected 00101 chop(new_end_points + 2, code2, dx, dy) ; 00102 return_code |= SECOND_POINT_CLIPPED ; 00103 } 00104 } 00105 00106 return return_code ; 00107 } 00108 00109 /// The Cohen-Sutherland code for a point consists of four bit flags as 00110 /// described below: 00111 /// bit 3 = 1 ==> point is to the left of the clipping rectangle 00112 /// bit 2 = 1 ==> point is above the clipping rectangle 00113 /// bit 1 = 1 ==> point is to the right of the clipping rectangle 00114 /// bit 0 = 1 ==> point is below the clipping rectangle 00115 unsigned char Clipper::cs_code(const float point[2]) const 00116 { 00117 unsigned char code = 0 ; // initially assume point is inside 00118 00119 if (point[0] < m_clip_boundary[0]) 00120 code |= LEFT_BIT ; 00121 00122 if (point[1] > m_clip_boundary[3]) 00123 code |= TOP_BIT ; 00124 00125 if (point[0] > m_clip_boundary[1]) 00126 code |= RIGHT_BIT ; 00127 00128 if (point[1] < m_clip_boundary[2]) 00129 code |= BOTTOM_BIT ; 00130 00131 return code ; 00132 } 00133 00134 /* 00135 If a line can not be trivially accepted or rejected, we break the line 00136 into two parts at the appropriate clipping boundary and reject the 00137 portion that lies outside. Then we test the remaining portion against 00138 the edges and continue until we get an acceptance or rejection. 00139 00140 The remaining portion of the line is obtained by "moving" that point 00141 along the line to the intersection of the line with the clipping 00142 boundary it is being tested against. For eg., consider the situation 00143 shown below: 00144 00145 +-------- 00146 | P2 00147 | /| 00148 |/ | 00149 I/ | 00150 /| dy 00151 / h | 00152 / | | 00153 /-+-|--+ 00154 P1 | 00155 +--> dx 00156 00157 We need to compute the intersection of P1-P2 with the left boundary 00158 of the clipping rectangle and make P1 that intersection. Let the 00159 intersection point be I. Obviously, the x-coordinate of I is the 00160 x-coordinate of the left edge. Let the horizontal distance between 00161 P1 and the left edge be d. From similar triangles, we get: 00162 00163 h/dy = d/dx ==> h = d * dy/dx 00164 00165 We can easily compute d: 00166 00167 d = left - P1.x 00168 00169 Therefore, 00170 00171 I.y = P1.y + (left - P1.x) * dy/dx 00172 00173 And if P1 were to become I, then we'd get: 00174 00175 P1.y = P1.y + (left - P1.x) * dy/dx 00176 or P1.y += (left - P1.x) * dy/dx 00177 00178 Similar reasoning can be applied for the other cases. 00179 */ 00180 void 00181 Clipper:: 00182 chop(float point[2], unsigned char code, float dx, float dy) const 00183 { 00184 if (code & LEFT_BIT) 00185 { 00186 point[1] += (m_clip_boundary[0] - point[0]) * dy/dx ; 00187 point[0] = m_clip_boundary[0] ; 00188 } 00189 else if (code & RIGHT_BIT) 00190 { 00191 point[1] += (m_clip_boundary[1] - point[0]) * dy/dx ; 00192 point[0] = m_clip_boundary[1] ; 00193 } 00194 else if (code & BOTTOM_BIT) 00195 { 00196 point[0] += (m_clip_boundary[2] - point[1]) * dx/dy ; 00197 point[1] = m_clip_boundary[2] ; 00198 } 00199 else if (code & TOP_BIT) 00200 { 00201 point[0] += (m_clip_boundary[3] - point[1]) * dx/dy ; 00202 point[1] = m_clip_boundary[3] ; 00203 } 00204 } 00205 00206 //---------------------------------------------------------------------- 00207 00208 } // end of namespace encapsulating this file's definitions 00209 00210 /* So things look consistent in everyone's emacs... */ 00211 /* Local Variables: */ 00212 /* indent-tabs-mode: nil */ 00213 /* End: */