libidx
|
00001 /*************************************************************************** 00002 * Copyright (C) 2008 by Pierre Sermanet * 00003 * pierre.sermanet@gmail.com * 00004 * All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions are met: 00008 * * Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * * Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * * Redistribution under a license not approved by the Open Source 00014 * Initiative (http://www.opensource.org) must display the 00015 * following acknowledgement in all advertising material: 00016 * This product includes software developed at the Courant 00017 * Institute of Mathematical Sciences (http://cims.nyu.edu). 00018 * * The names of the authors may not be used to endorse or promote products 00019 * derived from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 00022 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00023 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00024 * DISCLAIMED. IN NO EVENT SHALL ThE AUTHORS BE LIABLE FOR ANY 00025 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00026 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00027 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00028 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00029 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00031 ***************************************************************************/ 00032 00033 #ifndef GEOMETRY_HPP_ 00034 #define GEOMETRY_HPP_ 00035 00036 #include <math.h> 00037 #include "numerics.h" 00038 00039 namespace ebl { 00040 00042 // rect 00043 00044 template <typename T> 00045 rect<T>::rect(T h0_, T w0_, T height_, T width_) 00046 : h0(h0_), w0(w0_), height(height_), width(width_) { 00047 } 00048 00049 template <typename T> 00050 rect<T>::rect() : h0(0), w0(0), height(0), width(0) { 00051 } 00052 00053 template <typename T> 00054 rect<T>::rect(const rect<T> &r) 00055 : h0(r.h0), w0(r.w0), height(r.height), width(r.width) { 00056 } 00057 00058 template <typename T> 00059 rect<T>::~rect() { 00060 } 00061 00062 template <typename T> 00063 T rect<T>::h1() const { 00064 return h0 + height; 00065 } 00066 00067 template <typename T> 00068 T rect<T>::w1() const { 00069 return w0 + width; 00070 } 00071 00072 template <typename T> 00073 float rect<T>::hcenter() const { 00074 return h0 + height / (float) 2.0; 00075 } 00076 00077 template <typename T> 00078 float rect<T>::wcenter() const { 00079 return w0 + width / (float) 2.0; 00080 } 00081 00082 template <typename T> 00083 T rect<T>::area() const { 00084 return height * width; 00085 } 00086 00087 template <typename T> 00088 float rect<T>::center_distance(const rect<T> &r) const { 00089 float a = r.hcenter() - hcenter(); 00090 float b = r.wcenter() - wcenter(); 00091 return sqrt(a * a + b * b); 00092 } 00093 00094 template <typename T> 00095 float rect<T>::center_hdistance(const rect<T> &r) const { 00096 if (height == 0) eblerror("unexpected 0 height"); 00097 return fabs(hcenter() - r.hcenter()) / height; 00098 } 00099 00100 template <typename T> 00101 float rect<T>::center_wdistance(const rect<T> &r) const { 00102 if (width == 0) eblerror("unexpected 0 width"); 00103 return fabs(wcenter() - r.wcenter()) / width; 00104 } 00105 00106 template <typename T> 00107 T rect<T>::intersection_area(const rect<T> &r) const { 00108 // check height intersection exists 00109 T nh0 = (std::max)(h0, r.h0); 00110 T nh1 = (std::min)(h0 + height, r.h0 + r.height); 00111 if (nh0 >= nh1) // empty intersection 00112 return (T) 0; 00113 // check width intersection exists 00114 T nw0 = (std::max)(w0, r.w0); 00115 T nw1 = (std::min)(w0 + width, r.w0 + r.width); 00116 if (nw0 >= nw1) // empty intersection 00117 return (T) 0; 00118 // intersection exists 00119 return (nh1 - nh0) * (nw1 - nw0); 00120 } 00121 00122 template <typename T> 00123 T rect<T>::union_area(const rect<T> &r) const { 00124 return area() + r.area() - intersection_area(r); 00125 } 00126 00127 template <typename T> 00128 float rect<T>::match(const rect<T> &r) const { 00129 float u = (float) union_area(r); 00130 if (u == 0) return 0; 00131 return intersection_area(r) / u; 00132 } 00133 00134 template <typename T> 00135 float rect<T>::min_match(const rect<T> &r) { 00136 float a1 = (float) area(), a2 = (float) r.area(); 00137 if (a1 == 0 && a2 == 0) return 0; 00138 return intersection_area(r) / std::min(a1, a2); 00139 } 00140 00141 template <typename T> 00142 bool rect<T>::overlap(const rect<T> &r) const { 00143 if (((h0 <= r.h0 + r.height) && (h0 + height >= r.h0)) && 00144 ((w0 <= r.w0 + r.width) && (w0 + width >= r.w0))) 00145 return true; 00146 return false; 00147 } 00148 00149 template <typename T> 00150 float rect<T>::overlap_ratio(const rect<T> &r) const { 00151 T area1 = height * width; 00152 T inter = intersection_area(r); 00153 if (area1 == 0) return 0; 00154 return inter / (float) area1; 00155 } 00156 00157 template <typename T> 00158 bool rect<T>::min_overlap(const rect<T> &r, float minarea) const { 00159 T area1 = height * width; 00160 T area2 = r.height * r.width; 00161 T inter = intersection_area(r); 00162 float min_area = (std::min)(area1, area2); 00163 if (min_area == 0) return 0; 00164 if ((inter / min_area) > minarea) 00165 return true; 00166 return false; 00167 } 00168 00169 template <typename T> 00170 float rect<T>::min_overlap(const rect<T> &r) const { 00171 T area1 = height * width; 00172 T area2 = r.height * r.width; 00173 T inter = intersection_area(r); 00174 float min_area = (float) (std::min)(area1, area2); 00175 if (min_area == 0) return 0; 00176 return inter / min_area; 00177 } 00178 00179 template <typename T> 00180 bool rect<T>::min_overlap(const rect<T> &r, float hmin, float wmin) const { 00181 if (((h0 <= r.h0 + r.height) && (h0 + height >= r.h0)) && 00182 ((w0 <= r.w0 + r.width) && (w0 + width >= r.w0))) { 00183 // there is overlap, now check how much is authorized. 00184 T hoverlap = std::min(h0 + height, r.h0 + r.height) 00185 - std::min(h0, r.h0); 00186 T woverlap = std::min(w0 + width, r.w0 + r.width) - std::max(w0, r.w0); 00187 float min_height = (float) std::min(height, r.height); 00188 float min_width = (float) std::min(width, r.width); 00189 if (min_height == 0 || min_width == 0) return true; 00190 float hratio = hoverlap / (float) std::min(height, r.height); 00191 float wratio = woverlap / (float) std::min(width, r.width); 00192 if (hratio >= hmin || wratio >= wmin) 00193 return true; 00194 } 00195 return false; 00196 } 00197 00198 template <typename T> 00199 bool rect<T>::is_within(const rect<T> &r) { 00200 if (((h0 >= r.h0) && (h0 + height <= r.h0 + r.height)) && 00201 ((w0 >= r.w0) && (w0 + width <= r.w0 + r.width))) 00202 return true; 00203 return false; 00204 } 00205 00206 template <typename T> 00207 void rect<T>::scale_centered(float sh, float sw) { 00208 T addh = (T) (height * ((float)sh - (float)1.0)); 00209 T addw = (T) (width * ((float)sw - (float)1.0)); 00210 h0 -= (T) (addh / (float)2); 00211 w0 -= (T) (addw / (float)2); 00212 height += addh; 00213 width += addw; 00214 } 00215 00216 template <typename T> 00217 void rect<T>::scale_width(float woverh) { 00218 float addw = height * woverh - width; 00219 w0 -= (T) addw/2; 00220 width += (T) addw; 00221 } 00222 00223 template <typename T> 00224 void rect<T>::scale_height(float woverh) { 00225 float addh = width * woverh - height; 00226 h0 -= (T) addh/2; 00227 height += (T) addh; 00228 } 00229 00230 template <typename T> 00231 float rect<T>::radius() { 00232 float a = h0 - hcenter(); 00233 float b = w0 - wcenter(); 00234 return sqrt(a * a + b * b); 00235 } 00236 00237 template <typename T> 00238 void rect<T>::rotate(float alpha) { 00239 // convert alpha from degrees to radians 00240 alpha = (alpha / (float) 180) * PI; 00241 // center on rotation center 00242 float hc = hcenter(), wc = wcenter(); 00243 float h = h0 - hc, w = w0 - wc; 00244 // rotate all 4 corners 00245 float h1 = h, w1 = w; 00246 float h2 = h + height, w2 = w; 00247 float h3 = h, w3 = w + width; 00248 float h4 = h + height, w4 = w + width; 00249 rotate_point(alpha, h1, w1); 00250 rotate_point(alpha, h2, w2); 00251 rotate_point(alpha, h3, w3); 00252 rotate_point(alpha, h4, w4); 00253 // take min/max of all points 00254 h0 = (T) (hc + std::min(h1, std::min(h2, std::min(h3, h4)))); 00255 w0 = (T) (wc + std::min(w1, std::min(w2, std::min(w3, w4)))); 00256 height = (T) (std::max(h1, std::max(h2, std::max(h3, h4))) - h0 + hc); 00257 width = (T) (std::max(w1, std::max(w2, std::max(w3, w4))) - w0 + wc); 00258 } 00259 00260 template <typename T> 00261 void rect<T>::rotate_point(float alpha, float &h, float &w) { 00262 float d = sqrt(h * h + w * w); 00263 if (d == 0) // point in the center, do nothing 00264 return ; 00265 float beta = acos(w / d); 00266 if (h < 0) beta = -beta; 00267 float b = beta - alpha; 00268 h = sin(b) * d; 00269 w = cos(b) * d; 00270 } 00271 00273 // operators 00274 00275 template <typename T> 00276 std::string& operator<<(std::string& out, rect<T>& r) { 00277 out << "rect:<(" << r.h0 << "," << r.w0 << ")," << r.height; 00278 out << "x" << r.width << ">"; 00279 return out; 00280 } 00281 00282 template <typename T> 00283 std::string& operator<<(std::string& out, const rect<T>& r) { 00284 out << "rect:<(" << r.h0 << "," << r.w0 << ")," << r.height; 00285 out << "x" << r.width << ">"; 00286 return out; 00287 } 00288 00289 template <typename T> 00290 std::ostream& operator<<(std::ostream& out, rect<T>& r) { 00291 out << "rect:<(" << r.h0 << "," << r.w0 << ")," << r.height; 00292 out << "x" << r.width << ">"; 00293 return out; 00294 } 00295 00296 template <typename T> 00297 std::ostream& operator<<(std::ostream& out, const rect<T>& r) { 00298 out << "rect:<(" << r.h0 << "," << r.w0 << ")," << r.height; 00299 out << "x" << r.width << ">"; 00300 return out; 00301 } 00302 00303 template <typename T> 00304 rect<T> rect<T>::operator/(double d) { 00305 if (d == 0) eblerror("unexpected division by 0"); 00306 rect<T> newr((T) (h0 / d), (T) (w0 / d), 00307 (T) (height / d), (T) (width / d)); 00308 return newr; 00309 } 00310 00311 template <typename T> 00312 rect<T> rect<T>::operator*(double d) { 00313 rect<T> newr((T) (h0 * d), (T) (w0 * d), 00314 (T) (height * d), (T) (width * d)); 00315 return newr; 00316 } 00317 00318 template <typename T> template <typename T2> 00319 rect<T> rect<T>::operator=(rect<T2> &r2) { 00320 h0 = (T) r2.h0; 00321 w0 = (T) r2.w0; 00322 height = (T) r2.height; 00323 width = (T) r2.width; 00324 return *this; 00325 } 00326 00327 template <typename T> 00328 void rect<T>::shift(T h, T w) { 00329 h0 += h; 00330 w0 += w; 00331 } 00332 00333 } // end namespace ebl 00334 00335 #endif /* GEOMETRY_HPP_ */