# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

chain.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "stdpacs.h"
00027 
00028 #include "pacs/chain.h"
00029 
00030 using namespace std;
00031 using namespace NLMISC;
00032 
00033 
00034 // Functions for vertices comparison.
00035 // total order relation
00036 static inline bool      isStrictlyLess(const CVector &a, const CVector &b)
00037 {
00038         if (a.x < b.x)  return true;
00039         if (a.x > b.x)  return false;
00040         if (a.y < b.y)  return true;
00041         if (a.y > b.y)  return false;
00042         if (a.z < b.y)  return true;
00043         return false;
00044 }
00045 
00046 static inline bool      isStrictlyGreater(const CVector &a, const CVector &b)
00047 {
00048         if (a.x > b.x)  return true;
00049         if (a.x < b.x)  return false;
00050         if (a.y > b.y)  return true;
00051         if (a.y < b.y)  return false;
00052         if (a.z > b.y)  return true;
00053         return false;
00054 }
00055 
00056 static inline bool      isEqual(const CVector &a, const CVector &b)
00057 {
00058         return (a == b);
00059 }
00060 
00061 
00062 // COrderedChain3f methods implementation
00063 
00064 void    NLPACS::COrderedChain3f::serial(IStream &f)
00065 {
00066         /*
00067         Version 0:
00068                 - base version.
00069         */
00070         (void)f.serialVersion(0);
00071 
00072         f.serialCont(_Vertices);
00073         f.serial(_Forward);
00074         f.serial(_ParentId);
00075         f.serial(_IndexInParent);
00076 }
00077 
00078 // end of COrderedChain3f methods implementation
00079 
00080 // COrderedChain methods implementation
00081 
00082 // translates the ordered chain by the vector translation
00083 void    NLPACS::COrderedChain::translate(const CVector &translation)
00084 {
00085         uint    i;
00086         CVector2s       translat;
00087         translat.pack(translation);
00088         for (i=0; i<_Vertices.size(); ++i)
00089                 _Vertices[i] += translat;
00090 }
00091 
00092 //
00093 void    NLPACS::COrderedChain::traverse(sint from, sint to, bool forward, vector<NLPACS::CVector2s> &path) const
00094 {
00095         sint    i;
00096         if (forward)
00097         {
00098                 if (from < 0)   from = 0;
00099                 if (to < 0)             to = _Vertices.size()-1;
00100 
00101                 for (i=from+1; i<=to; ++i)
00102                         path.push_back(_Vertices[i]);
00103         }
00104         else
00105         {
00106                 if (from < 0)   from = _Vertices.size()-2;
00107                 if (to < 0)             to = -1;
00108 
00109                 for (i=from; i>to; --i)
00110                         path.push_back(_Vertices[i]);
00111         }
00112 }
00113 
00114 //
00115 float   NLPACS::COrderedChain::distance(const CVector &position) const
00116 {
00117         float           minDist = 1.0e10f;
00118         uint            i;
00119         CVector2f       pos = CVector2f(position);
00120 
00121         for (i=0; i+1<_Vertices.size(); ++i)
00122         {
00123                 CVector2f       a = _Vertices[i].unpack(),
00124                                         b = _Vertices[i+1].unpack();
00125 
00126                 CVector2f       d = (b-a);
00127                 float           len = d.norm();
00128                 d /= len;
00129                 CVector2f       n = CVector2f(d.y, -d.x);
00130 
00131                 float           l = (pos-a)*d;
00132                 float           dist;
00133 
00134                 if (l < 0.0f)
00135                 {
00136                         dist = (pos-a).norm();
00137                 }
00138                 else if (l > len)
00139                 {
00140                         dist = (pos-b).norm();
00141                 }
00142                 else
00143                 {
00144                         dist = (float)fabs((pos-a)*n);
00145                 }
00146 
00147                 if (dist < minDist)
00148                 {
00149                         minDist = dist;
00150                 }
00151         }
00152 
00153         return minDist;
00154 }
00155 
00156 
00157 // serialises the ordered chain
00158 void    NLPACS::COrderedChain::serial(IStream &f)
00159 {
00160         /*
00161         Version 0:
00162                 - base version.
00163         Version 1:
00164                 - added _Min and _Max vectors
00165         */
00166         sint    ver= f.serialVersion(1);
00167 
00168         f.serialCont(_Vertices);
00169         f.serial(_Forward);
00170         f.serial(_ParentId);
00171         f.serial(_IndexInParent);
00172         f.serial(_Length);
00173 
00174         if (ver >= 1)
00175         {
00176                 f.serial(_Min, _Max);
00177         }
00178         else if (f.isReading() && !_Vertices.empty())
00179         {
00180                 uint    i;
00181                 _Max = _Min = _Vertices[0];
00182                 for (i=1; i<_Vertices.size(); ++i)
00183                 {
00184                         _Min.minof(_Min, _Vertices[i]);
00185                         _Max.maxof(_Max, _Vertices[i]);
00186                 }
00187         }
00188 }
00189 
00190 // end of COrderedChain methods implementation
00191 
00192 
00193 // CChain methods implementation
00194 
00195 // builds the CChain from a list of vertices and a left and right surfaces id.
00196 // the chains vector is the vector where to store generated ordered chains.
00197 // thisId is the current id of the CChain, and edge is the number of the edge the CChain belongs to (-1
00198 // if none.)
00199 void    NLPACS::CChain::make(const vector<CVector> &vertices, sint32 left, sint32 right, vector<COrderedChain> &chains, uint16 thisId,
00200                                                          vector<COrderedChain3f> &fullChains)
00201 {
00202         sint            first = 0, last = 0, i;
00203 
00204         _Left = left;
00205         _Right = right;
00206         _Length = 0.0f;
00207 
00208         // splits the vertices list in ordered sub chains.
00209         while (first < (sint)vertices.size()-1)
00210         {
00211                 last = first+1;
00212                 bool    forward = isStrictlyLess(vertices[first], vertices[last]);
00213 
00214                 // first checks if the subchain goes forward or backward.
00215                 if (forward)
00216                         for (; last < (sint)vertices.size() && isStrictlyLess(vertices[last-1], vertices[last]); ++last)
00217                                 ;
00218                 else
00219                         for (; last < (sint)vertices.size() && isStrictlyGreater(vertices[last-1], vertices[last]); ++last)
00220                                 ;
00221                 --last;
00222 
00223                 // inserts the new subchain id within the CChain.
00224                 uint32  subChainId = chains.size();
00225                 if (subChainId > 65535)
00226                         nlerror("in NLPACS::CChain::make(): reached the maximum number of ordered chains");
00227                 _SubChains.push_back((uint16)subChainId);
00228 
00229                 // and creates a new COrderedChain
00230                 fullChains.resize(fullChains.size()+1);
00231                 COrderedChain3f &subchain3f = fullChains.back();
00232                 subchain3f._Vertices.reserve(last-first+1);
00233                 subchain3f._Forward = forward;
00234                 subchain3f._ParentId = thisId;
00235                 subchain3f._IndexInParent = _SubChains.size()-1;
00236 
00237                 // and then copies the vertices (sorted, btw!)
00238                 if (forward)
00239                         for (i=first; i<=last; ++i)
00240                                 subchain3f._Vertices.push_back(vertices[i]);
00241                 else
00242                         for (i=last; i>=first; --i)
00243                                 subchain3f._Vertices.push_back(vertices[i]);
00244 
00245                 first = last;
00246 
00247                 chains.resize(chains.size()+1);
00248                 COrderedChain   &subchain = chains.back();
00249                 subchain.pack(subchain3f);
00250                 subchain.computeMinMax();
00251 
00252                 float   length = 0.0f;
00253                 for (i=0; i<(sint)subchain._Vertices.size()-1; ++i)
00254                         length += (subchain._Vertices[i+1]-subchain._Vertices[i]).norm();
00255 
00256                 subchain._Length = length;
00257                 _Length += length;
00258         }
00259 }
00260 
00261 // serialises the CChain
00262 void    NLPACS::CChain::serial(IStream &f)
00263 {
00264         /*
00265         Version 0:
00266                 - base version.
00267         */
00268         (void)f.serialVersion(0);
00269 
00270         f.serialCont(_SubChains);
00271         f.serial(_Left, _Right);
00272         f.serial(_StartTip, _StopTip);
00273         f.serial(_Length);
00274         f.serial(_LeftLoop, _LeftLoopIndex);
00275         f.serial(_RightLoop, _RightLoopIndex);
00276 }
00277 
00278 
00279 
00280 // unifiies the chain
00281 void    NLPACS::CChain::unify(vector<NLPACS::COrderedChain> &ochains)
00282 {
00283         CVector2s       snap;
00284         uint            i;
00285 
00286         snap = (ochains[_SubChains[0]].isForward()) ? ochains[_SubChains[0]]._Vertices.back() : ochains[_SubChains[0]]._Vertices.front();
00287 
00288         for (i=1; i<_SubChains.size(); ++i)
00289         {
00290                 if (ochains[_SubChains[i]].isForward())
00291                 {
00292                         if (ochains[_SubChains[i]]._Vertices.front() != snap)
00293                                 nlwarning("ochain %d and %d are not stuck together", _SubChains[i-1], _SubChains[i]);
00294                         ochains[_SubChains[i]]._Vertices.front() = snap;
00295                         snap = ochains[_SubChains[i]]._Vertices.back();
00296                 }
00297                 else
00298                 {
00299                         if (ochains[_SubChains[i]]._Vertices.back() != snap)
00300                                 nlwarning("ochain %d and %d are not stuck together", _SubChains[i-1], _SubChains[i]);
00301                         ochains[_SubChains[i]]._Vertices.back() = snap;
00302                         snap = ochains[_SubChains[i]]._Vertices.front();
00303                 }
00304         }
00305 
00306 }
00307 
00308 //
00309 void    NLPACS::CChain::setStartVector(const NLPACS::CVector2s &v, vector<NLPACS::COrderedChain> &ochains)
00310 {
00311         if (ochains[_SubChains.front()].isForward())
00312                 ochains[_SubChains.front()]._Vertices.front() = v;
00313         else
00314                 ochains[_SubChains.front()]._Vertices.back() = v;
00315 }
00316 
00317 //
00318 void    NLPACS::CChain::setStopVector(const NLPACS::CVector2s &v, vector<NLPACS::COrderedChain> &ochains)
00319 {
00320         if (ochains[_SubChains.back()].isForward())
00321                 ochains[_SubChains.back()]._Vertices.back() = v;
00322         else
00323                 ochains[_SubChains.back()]._Vertices.front() = v;
00324 }
00325 
00326 //
00327 NLPACS::CVector2s       NLPACS::CChain::getStartVector(vector<NLPACS::COrderedChain> &ochains)
00328 {
00329         if (ochains[_SubChains.front()].isForward())
00330                 return ochains[_SubChains.front()]._Vertices.front();
00331         else
00332                 return ochains[_SubChains.front()]._Vertices.back();
00333 }
00334 
00335 //
00336 NLPACS::CVector2s       NLPACS::CChain::getStopVector(vector<NLPACS::COrderedChain> &ochains)
00337 {
00338         if (ochains[_SubChains.back()].isForward())
00339                 return ochains[_SubChains.back()]._Vertices.back();
00340         else
00341                 return ochains[_SubChains.back()]._Vertices.front();
00342 }
00343 
00344 // end of CChain methods implementation
00345