last update 20 Sep 2009 |
00001 /* 00002 * Copyright (C) 1998-2004 00003 * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany 00004 * 00005 * 00006 * This file is part of the Computer Vision and Robotics Library (CVR-Lib) 00007 * 00008 * The CVR-Lib is free software; you can redistribute it and/or 00009 * modify it under the terms of the BSD License. 00010 * 00011 * All rights reserved. 00012 * 00013 * Redistribution and use in source and binary forms, with or without 00014 * modification, are permitted provided that the following conditions are met: 00015 * 00016 * 1. Redistributions of source code must retain the above copyright notice, 00017 * this list of conditions and the following disclaimer. 00018 * 00019 * 2. Redistributions in binary form must reproduce the above copyright notice, 00020 * this list of conditions and the following disclaimer in the documentation 00021 * and/or other materials provided with the distribution. 00022 * 00023 * 3. Neither the name of the authors nor the names of its contributors may be 00024 * used to endorse or promote products derived from this software without 00025 * specific prior written permission. 00026 * 00027 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00028 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00029 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00030 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00031 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00032 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00033 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00034 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00035 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00036 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00037 * POSSIBILITY OF SUCH DAMAGE. 00038 */ 00039 00040 00041 00042 /** 00043 * \file cvrChainCode.h 00044 * Declares chainCode and constants for Canzler code 00045 * \author LTI 00046 * \date 19.08.1998 00047 * 00048 * $Id: cvrChainCode.h,v 1.5 2005/06/06 12:59:56 doerfler Exp $ 00049 */ 00050 00051 #ifndef _CVR_CHAIN_CODE_H_ 00052 #define _CVR_CHAIN_CODE_H_ 00053 00054 #include "cvrIoHandler.h" 00055 #include "cvrPoint.h" 00056 00057 namespace cvr { 00058 00059 /** 00060 * Elements of a Chaincode. 00061 * The used directions follows the next diagram: 00062 * 00063 * \code 00064 * NW N NE 00065 * \ | / 00066 * W - x - E 00067 * / | \ 00068 * SW S SE 00069 * \endcode 00070 * 00071 * The "int" value resulting from casting these chain codes is 00072 * proportional to the angle with a proportionality constant of 45°, 00073 * i.e. if 'c' is a chainCode object, then the equivalent direction 00074 * in degrees is 45*int(c.getDirection()). 00075 * 00076 * @ingroup gShape 00077 */ 00078 class chainCode { 00079 public: 00080 /** 00081 * Directions used in chain codes 00082 * The used directions follows the next diagram: 00083 * 00084 * \code 00085 * NW N NE 00086 * \ | / 00087 * W - x - E 00088 * / | \ 00089 * SW S SE 00090 * \endcode 00091 * 00092 * The "int" value resulting from casting these chain codes is 00093 * proportional to the angle with a proportionality constant of 45°, 00094 * i.e. if 'c' is a chainCode object, then the equivalent direction 00095 * in degrees is 45*int(c.getDirection()). 00096 */ 00097 enum direction {UNKNOWN=-2, /**< Unknown */ 00098 NOMOVE=-1, /**< No Move */ 00099 E=0, /**< East (or Right) */ 00100 NE, /**< North-East (or Right-Up) */ 00101 N, /**< North (or Up) */ 00102 NW, /**< North-West (or North-West) */ 00103 W, /**< West (or West) */ 00104 SW, /**< South-West (or Left-Down) */ 00105 S, /**< South (or Down) */ 00106 SE /**< South-East (or Right-Down) */ 00107 }; 00108 00109 /** 00110 * @name Canzler Codes 00111 * 00112 * Given two chain codes for a sequence of three adjacent pixels, 00113 * the Canzler-Codes give you information about which borders of the middle 00114 * pixel belong to the boundary. With the getCanzlerCode() you can obtain 00115 * the corresponding coding for the pixel pointed by this chain code, if 00116 * the next chain code is the one given. They are somehow similar to the 00117 * so called "chain crack codes", but instead of specifying a direction 00118 * of the boundary, they code which "crack codes" belong to the middle 00119 * pixel between two chain codes. 00120 * 00121 * There are 16 Canzler-Codes, that can be obtained by the combination 00122 * of the four values Top, Right, Bottom and Left, which specify that 00123 * the border runs on the top, right, bottom and/or left edge of the 00124 * pixel respectively. 00125 */ 00126 //@{ 00127 static const ubyte Nothing; /// Nothing has the value 0 00128 static const ubyte Top; /// Top has value 1 (the first bit) 00129 static const ubyte Right; /// Right has value 2 (the second bit) 00130 static const ubyte Bottom; /// Bottom has value 4 (the third bit) 00131 static const ubyte Left; /// Left has value 8 (the fourth bit) 00132 //@} 00133 00134 /** 00135 * default constructor 00136 */ 00137 chainCode(const direction& v = NOMOVE) 00138 : value(v) { 00139 }; 00140 00141 /** 00142 * constructor to cast an integer 00143 */ 00144 chainCode(const int v) : value(direction(v%8)) {}; 00145 00146 /** 00147 * copy constructor 00148 */ 00149 chainCode(const chainCode& other) 00150 : value(other.value) { 00151 }; 00152 00153 /** Constrcutor. This constructor creates a chainCode object using the 00154 sign of the parameters to calculate the direction. 00155 Image-coordinates are used, i.e. a positive "y" implies a 00156 change towards "south", and a positive x implies a 00157 change towards "east". */ 00158 chainCode(const int x,const int y) : value(UNKNOWN) { 00159 fromDeltas(x,y); 00160 }; 00161 00162 /** 00163 * Constructor.This constructor creates a chainCode object using 00164 * two points 00165 */ 00166 chainCode(const ipoint& here,const ipoint& next) : value(UNKNOWN) { 00167 ipoint tmp(next); 00168 tmp.subtract(here); 00169 fromDeltas(tmp.x,tmp.y); 00170 }; 00171 00172 /** 00173 * returns direction of this chain element 00174 */ 00175 inline direction getDirection() const; 00176 00177 /** 00178 * Possible Direction.returns true if this object contains one of 00179 * the eight posible directions, and false otherwise 00180 */ 00181 inline bool isDirection() const; 00182 00183 /** 00184 * returns next point with start point "here" and using this chainCode. 00185 */ 00186 inline ipoint getNext(const ipoint& here) const; 00187 00188 /** 00189 * returns previous point with start point "here" and using this chainCode. 00190 */ 00191 inline ipoint getPrevious(const ipoint& here) const; 00192 00193 /** 00194 * returns change in x. 00195 * For example, if the value is NW, deltaX() returns -1. 00196 */ 00197 inline int deltaX() const; 00198 00199 /** 00200 * returns change in y. 00201 * For example, if the value is NW, deltaY() returns -1. 00202 */ 00203 inline int deltaY() const; 00204 00205 /** 00206 * returns point with changes in both direction, x and y. 00207 */ 00208 inline ipoint delta() const; 00209 00210 /** 00211 * become other object 00212 */ 00213 inline chainCode& operator=(const direction& other) { 00214 return copy(other); 00215 }; 00216 00217 /** 00218 * become other object 00219 */ 00220 inline chainCode& copy(const direction& other); 00221 00222 /** 00223 * become other object 00224 */ 00225 inline chainCode& copy(const chainCode& other); 00226 00227 /** 00228 * become other object 00229 */ 00230 inline chainCode& operator=(const chainCode& other) { 00231 return(copy(other)); 00232 }; 00233 00234 /** 00235 * compare with another object 00236 */ 00237 inline bool compare(const chainCode& other); 00238 00239 /** 00240 * compare with another object 00241 */ 00242 inline bool operator==(const chainCode& other) { 00243 return compare(other); 00244 }; 00245 00246 /** 00247 * compare with another object 00248 */ 00249 inline bool compare(const direction& other); 00250 00251 /** 00252 * compare with another object 00253 */ 00254 inline bool operator==(const direction& other) { 00255 return compare(other); 00256 }; 00257 00258 /** 00259 * subtract the angles of the first and second chain code elements and 00260 * leave the result here! 00261 */ 00262 inline chainCode& subtract(const chainCode& first, 00263 const chainCode& second); 00264 /** 00265 * subtract the angle equivalent of the <em>other</em> chainCode 00266 * from *this 00267 */ 00268 inline chainCode operator-(const chainCode& other) const { 00269 chainCode tmp; 00270 tmp.subtract(*this,other); 00271 return tmp; 00272 }; 00273 00274 /** 00275 * subtract the angle equivalent of the other chain code from this one. 00276 * The result will be left in this instance, and a reference to it will 00277 * be returned. 00278 */ 00279 inline chainCode& subtract(const chainCode& other); 00280 00281 /** 00282 * subtract another chain code 00283 */ 00284 inline chainCode& operator-=(const chainCode& other) { 00285 return subtract(other); 00286 }; 00287 00288 /** 00289 * add the angles of the first and second chain codes 00290 */ 00291 inline chainCode& add(const chainCode& first, 00292 const chainCode& second); 00293 00294 /** 00295 * add the angles of this and the other chain code 00296 */ 00297 inline chainCode operator+(const chainCode& other) const { 00298 chainCode tmp; 00299 tmp.add(*this,other); 00300 return tmp; 00301 }; 00302 00303 /** 00304 * add the angles of the other chain code to this chainCode and 00305 * leave the result in this instance. Returns a reference to the instance 00306 */ 00307 inline chainCode& add(const chainCode& other); 00308 00309 /** 00310 * add another chain code 00311 */ 00312 inline chainCode& operator+=(const chainCode& other) { 00313 return add(other); 00314 }; 00315 00316 /** 00317 * divide chain code equivalent angle with an integer. The result 00318 * will be left in this instance and a reference to it will be returned 00319 */ 00320 inline chainCode& divide(const int other) { 00321 value=static_cast<direction>(static_cast<int>(value)/other); 00322 return (*this); 00323 }; 00324 00325 /** 00326 * divide chain code angle with integer. 00327 */ 00328 inline chainCode operator/(const int other) { 00329 chainCode tmp(*this); 00330 tmp.divide(other); 00331 return (tmp); 00332 } 00333 00334 /** 00335 * return the Canzler Code for the pixel pointed by this chainCode 00336 * if the second chainCode is the one given as parameter. 00337 * 00338 * The result a the bitwise OR of some of the codes Top, Bottom, Left and 00339 * Right. 00340 * 00341 * @param nextChainCode the next chain code of this one in the chain 00342 * code sequence. 00343 * @return the canzler bit-coding for the edges of the pixel pointed 00344 * by this chainCode which are part of the boundary. The values 00345 * returned are bit or of the constants Left, Top, Right and 00346 * Bottom. 00347 */ 00348 inline ubyte getCanzlerCode(const chainCode& nextChainCode) const; 00349 00350 protected: 00351 /** 00352 * Attribute containing the chain code 00353 */ 00354 direction value; 00355 00356 /** 00357 * compute chain code from x and y deltas 00358 */ 00359 inline void fromDeltas(const int x,const int y); 00360 }; 00361 00362 //*********************************************************** 00363 // Global IO functions 00364 //*********************************************************** 00365 00366 /** 00367 * read the matrix from the given ioHandler. The complete flag indicates 00368 * if the enclosing begin and end should be also be readed 00369 * 00370 * @ingroup gStorable 00371 */ 00372 bool read(ioHandler& handler,chainCode& cc,const bool complete=true); 00373 00374 /** 00375 * write the matrix in the given ioHandler. The complete flag indicates 00376 * if the enclosing begin and end should be also be written or not 00377 * 00378 * @ingroup gStorable 00379 */ 00380 bool write(ioHandler& handler,const chainCode& cc,const bool complete=true); 00381 } 00382 00383 #include "cvrChainCode_inline.h" 00384 00385 #endif 00386 00387 00388