00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "stdpacs.h"
00027
00028 #include "pacs/chain.h"
00029
00030 using namespace std;
00031 using namespace NLMISC;
00032
00033
00034
00035
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
00063
00064 void NLPACS::COrderedChain3f::serial(IStream &f)
00065 {
00066
00067
00068
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
00079
00080
00081
00082
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
00158 void NLPACS::COrderedChain::serial(IStream &f)
00159 {
00160
00161
00162
00163
00164
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
00191
00192
00193
00194
00195
00196
00197
00198
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
00209 while (first < (sint)vertices.size()-1)
00210 {
00211 last = first+1;
00212 bool forward = isStrictlyLess(vertices[first], vertices[last]);
00213
00214
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
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
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
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
00262 void NLPACS::CChain::serial(IStream &f)
00263 {
00264
00265
00266
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
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
00345