00001 /*!@file Image/Rectangle.C A basic rectangle class */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Image/Rectangle.C $ 00035 // $Id: Rectangle.C 9412 2008-03-10 23:10:15Z farhan $ 00036 // 00037 00038 #include "Image/Rectangle.H" 00039 00040 #include "Util/Assert.H" 00041 #include "Util/StringConversions.H" 00042 #include "Util/log.H" 00043 00044 #include <sstream> 00045 00046 // ###################################################################### 00047 // converters for Rectangle 00048 // ###################################################################### 00049 00050 // ###################################################################### 00051 std::string convertToString(const Rectangle& val) 00052 { 00053 if (val.isValid()) 00054 { 00055 std::stringstream s; 00056 s<<val.left()<<','<<val.top()<<','<<val.rightO()<<','<<val.bottomO(); 00057 return s.str(); 00058 } 00059 // else... 00060 return "-1,-1,-1,-1"; 00061 } 00062 00063 // ###################################################################### 00064 void convertFromString(const std::string& str, Rectangle& val) 00065 { 00066 std::stringstream s; int t = -1, b = -1, l = -1, r = -1; 00067 char c; s<<str; s>>l>>c>>t>>c>>r>>c>>b; 00068 if (s.fail()) 00069 conversion_error::raise<Rectangle>(str); 00070 00071 val = Rectangle::tlbrO(t, l, b, r); 00072 } 00073 00074 // ###################################################################### 00075 Rectangle constrainRect(const Rectangle& in, 00076 const Rectangle& bounds, 00077 int minw, int maxw, 00078 int minh, int maxh) 00079 { 00080 ASSERT(minw >= 0); 00081 ASSERT(maxw >= minw); 00082 ASSERT(minh >= 0); 00083 ASSERT(maxh >= minh); 00084 00085 Rectangle result = in.getOverlap(bounds); 00086 00087 ASSERT(bounds.contains(result)); 00088 00089 minw = std::min(minw, bounds.width()); 00090 maxw = std::min(maxw, bounds.width()); 00091 00092 minh = std::min(minh, bounds.height()); 00093 maxh = std::min(maxh, bounds.height()); 00094 00095 // 00096 // grow/shrink the width to fit within minw,maxw 00097 // 00098 00099 if (result.width() < minw) 00100 { 00101 const int diff = minw - result.width(); 00102 result = Rectangle::tlbrO(result.top(), 00103 result.left() - diff / 2, 00104 result.bottomO(), 00105 result.rightO() + diff - diff / 2); 00106 ASSERT(result.width() == minw); 00107 } 00108 00109 else if (result.width() > maxw) 00110 { 00111 const int diff = result.width() - maxw; 00112 result = Rectangle::tlbrO(result.top(), 00113 result.left() + diff / 2, 00114 result.bottomO(), 00115 result.rightO() - diff + diff / 2); 00116 ASSERT(result.width() == maxw); 00117 } 00118 00119 // 00120 // shift leftward/rightward to stay within bounds (we may have gone 00121 // out of bounds if had to grow the width to stay wider than minw) 00122 // 00123 00124 if (result.left() < 0) 00125 { 00126 result += Point2D<int>(-result.left(), 0); 00127 ASSERT(result.left() == 0); 00128 } 00129 else if (result.rightO() > bounds.width()) 00130 { 00131 result -= Point2D<int>(result.rightO() - bounds.width(), 0); 00132 ASSERT(result.rightO() == bounds.width()); 00133 } 00134 ASSERT(bounds.contains(result)); 00135 00136 // 00137 // grow/shrink the height to fit within minh,maxh 00138 // 00139 00140 if (result.height() < minh) 00141 { 00142 const int diff = minh - result.height(); 00143 result = Rectangle::tlbrO(result.top() - diff / 2, 00144 result.left(), 00145 result.bottomO() + diff - diff / 2, 00146 result.rightO()); 00147 ASSERT(result.height() == minh); 00148 } 00149 else if (result.height() > maxh) 00150 { 00151 const int diff = result.height() - maxh; 00152 result = Rectangle::tlbrO(result.top() + diff / 2, 00153 result.left(), 00154 result.bottomO() - diff + diff / 2, 00155 result.rightO()); 00156 ASSERT(result.height() == maxh); 00157 } 00158 00159 // 00160 // shift upward/downward to stay within bounds (we may have gone out 00161 // of bounds if had to grow the height to stay taller than minh) 00162 // 00163 00164 if (result.top() < 0) 00165 { 00166 result += Point2D<int>(0, -result.top()); 00167 ASSERT(result.top() == 0); 00168 } 00169 else if (result.bottomO() > bounds.height()) 00170 { 00171 result -= Point2D<int>(0, result.bottomO() - bounds.height()); 00172 ASSERT(result.bottomO() == bounds.height()); 00173 } 00174 ASSERT(bounds.contains(result)); 00175 00176 // 00177 // now verify that we met all of our postconditions: 00178 // 00179 00180 ASSERT(result.width() >= minw); 00181 ASSERT(result.width() <= maxw); 00182 ASSERT(result.height() >= minh); 00183 ASSERT(result.height() <= maxh); 00184 ASSERT(bounds.contains(result)); 00185 00186 return result; 00187 } 00188 00189 // ###################################################################### 00190 /* So things look consistent in everyone's emacs... */ 00191 /* Local Variables: */ 00192 /* indent-tabs-mode: nil */ 00193 /* End: */