00001
00043 #include "SGNode.h"
00044 #include "HelperFunctions.h"
00045 #include "Exceptions.h"
00046 #include <stdio.h>
00047 #include <ctype.h>
00048
00049 #include <LEDA/graphwin.h>
00050
00051 #define NOT_TO_COMPARE_PERCENTAGE .15
00052 #define MIN_LIGATURE .7
00053
00055
00056
00058 istream& ShockInfo::Read(istream& is)
00059 {
00060 return is.read((char*)this, sizeof(ShockInfo));
00061 }
00062
00064 ostream& ShockInfo::Write(ostream& os) const
00065 {
00066 return os.write((char*)this, sizeof(ShockInfo));
00067 }
00068
00070 void ShockInfo::Print(ostream& os) const
00071 {
00072 PRINT_OPEN(os, xcoord);
00073 PRINT(os, ycoord);
00074 PRINT(os, radius);
00075 PRINT(os, type);
00076 PRINT(os, dir);
00077 PRINT(os, dr);
00078 PRINT(os, speed);
00079 PRINT(os, dr_ds);
00080 PRINT_CLOSE(os, int(color));
00081 }
00082
00084
00085
00086
00087
00088
00093 DAGNode* SGNode::CreateObject() const
00094 {
00095 return (DAGNode*) new SGNode();
00096 }
00097
00098 void SGNode::Clear()
00099 {
00100 DAGNode::Clear();
00101
00102 m_nType = 0;
00103 m_nRole = UNK_ROLE;
00104
00105 m_cEndPt = 0;
00106 m_seg1 = 0;
00107 m_seg2 = 0;
00108 m_strBranchId.Clear();
00109 m_shocks.Clear();
00110
00111 m_nEndPt0 = NOTSET_POINT;
00112 m_nEndPtN = NOTSET_POINT;
00113 }
00114
00116 DAGNode& SGNode::operator=(const DAGNode& rhs)
00117 {
00118 DAGNode::operator=(rhs);
00119
00120 const SGNode* pRhs = dynamic_cast<const SGNode*>(&rhs);
00121
00122 if (!pRhs)
00123 THROW_EXCEPTION("Invalid pointer type.");
00124
00125 m_nType = pRhs->m_nType;
00126 m_nRole = pRhs->m_nRole;
00127
00128 m_cEndPt = pRhs->m_cEndPt;
00129 m_seg1 = pRhs->m_seg1;
00130 m_seg2 = pRhs->m_seg2;
00131 m_strBranchId = pRhs->m_strBranchId;
00132 m_shocks = pRhs->m_shocks;
00133
00134 m_nEndPt0 = pRhs->m_nEndPt0;
00135 m_nEndPtN = pRhs->m_nEndPtN;
00136
00137 return *this;
00138 }
00139
00140
00141
00143 SGNode::SGNode(String szId, int nType) : DAGNode(szId)
00144 {
00145 m_nType = nType;
00146 m_strBranchId = szId;
00147 m_cEndPt = '\0';
00148 m_seg1 = m_seg2 = 0.0;
00149
00150 for (int i = 0, len = szId.Len(); i < len; i++)
00151 {
00152 if (!isdigit(szId[i]))
00153 {
00154 m_cEndPt = szId[i];
00155 break;
00156 }
00157 }
00158 }
00159
00160 void SGNode::ComputeDerivedValues()
00161 {
00162 DAGNode::ComputeDerivedValues();
00163
00164 m_shocks.ComputeDerivedValues();
00165 }
00166
00168 void SGNode::ComputeSpeeds()
00169 {
00170 for (int i = 1, size = m_shocks.GetSize(); i < size; i++)
00171 m_shocks[i].speed = m_shocks[i].radius - m_shocks[i-1].radius;
00172
00173 m_shocks[0].speed = m_shocks[1].speed;
00174 }
00175
00177 istream& SGNode::Read(istream& is)
00178 {
00179 DAGNode::Read(is);
00180
00181 is.read((char*) &m_nType, sizeof(m_nType));
00182 is.read((char*) &m_nRole, sizeof(m_nRole));
00183 is.read((char*) &m_cEndPt, sizeof(m_cEndPt));
00184 is.read((char*) &m_seg1, sizeof(m_seg1));
00185 is.read((char*) &m_seg2, sizeof(m_seg2));
00186 is.read((char*) &m_nEndPt0, sizeof(m_nEndPt0));
00187 is.read((char*) &m_nEndPtN, sizeof(m_nEndPtN));
00188
00189 m_strBranchId.Read(is);
00190 m_shocks.Read(is);
00191
00192 return is;
00193 }
00194
00196 ostream& SGNode::Write(ostream& os) const
00197 {
00198 DAGNode::Write(os);
00199
00200 os.write((char*) &m_nType, sizeof(m_nType));
00201 os.write((char*) &m_nRole, sizeof(m_nRole));
00202 os.write((char*) &m_cEndPt, sizeof(m_cEndPt));
00203 os.write((char*) &m_seg1, sizeof(m_seg1));
00204 os.write((char*) &m_seg2, sizeof(m_seg2));
00205 os.write((char*) &m_nEndPt0, sizeof(m_nEndPt0));
00206 os.write((char*) &m_nEndPtN, sizeof(m_nEndPtN));
00207
00208 m_strBranchId.Write(os);
00209 m_shocks.Write(os);
00210
00211 return os;
00212 }
00213
00215 void SGNode::Print(ostream& os) const
00216 {
00217 DAGNode::Print(os);
00218
00219 PRINT_OPEN(os, m_strBranchId);
00220 PRINT(os, m_nType);
00221 PRINT(os, m_nRole);
00222 PRINT(os, GetShockCount());
00223 PRINT(os, m_seg1);
00224 PRINT_CLOSE(os, m_seg2);
00225 }
00226
00228 NODE_LABEL SGNode::GetLblForGraph() const
00229 {
00230 char lbl[100];
00231
00232 sprintf(lbl, "%s:%d",
00233 (const char*) GetNodeLbl(),
00234 m_nType - 100);
00235
00236
00237
00238
00239
00240
00241
00242 return lbl;
00243 }
00244
00246 leda_color SGNode::GetColorForGraph() const
00247 {
00248 unsigned char c;
00249
00250
00251
00252
00253
00254
00255 c = 255;
00256
00257 return leda_color(c, c, c);
00258 }
00259
00265 int SGNode::GetShapeForGraph() const
00266 {
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 return leda_ellipse_node;
00284 }
00285
00286 POINTS SGNode::GetVelocityRadiusArray(int& d0, int& dN, bool bReverseOrder ) const
00287 {
00288 int i, nSize = m_shocks.GetSize();
00289 double s;
00290
00291
00292
00293 ASSERT(m_nEndPt0 != NOTSET_POINT && m_nEndPtN != NOTSET_POINT);
00294
00295 d0 = (nSize > 3 && m_nEndPt0 == JOINT_POINT) ? 1:0;
00296 dN = (nSize > 3 && m_nEndPtN == JOINT_POINT) ? 1:0;
00297 nSize -= d0 + dN;
00298
00299 POINTS data(nSize);
00300
00301 if (!bReverseOrder)
00302 {
00303 for (i = 0, s = 0.0; i < nSize; i++)
00304 {
00305 const ShockInfo& si = m_shocks[i + d0];
00306 data[i].Set(s += si.speed, si.radius);
00307 }
00308 }
00309 else
00310 {
00311 int nLast = nSize - 1 + d0;
00312
00313 for (i = 0, s = 0.0; i < nSize; i++)
00314 {
00315 const ShockInfo& si = m_shocks[nLast - i];
00316 data[i].Set(s += si.speed, si.radius);
00317 }
00318 }
00319
00320 return data;
00321 }
00322
00324
00325
00326 void ShockBranch::Print(ostream &os) const
00327 {
00328 for (int i = 0; i < GetSize(); i++)
00329 {
00330 os << endl;
00331 operator[](i).Print(os);
00332 }
00333
00334 os << endl;
00335 PRINT_OPEN(os, avgRadius);
00336 PRINT(os, area);
00337 PRINT(os, length);
00338 PRINT(os, avgVelocity);
00339 PRINT(os, MinR());
00340 PRINT_CLOSE(os, MaxR());
00341 segments.Print(os);
00342 os << endl;
00343 }
00344
00346 double ShockBranch::CompareAreas(const ShockBranch& rhs, const double& scale) const
00347 {
00348 double a1, a2;
00349
00350 a1 = Area();
00351 a2 = rhs.Area() * scale;
00352
00353 return SIMILARITY(a1, a2);
00354 }
00355
00357 double ShockBranch::CompareRadii(const ShockBranch& rhs, const double& scale) const
00358 {
00359 double a1, a2;
00360
00361 a1 = AvgRadius();
00362 a2 = rhs.AvgRadius() * scale;
00363
00364 return SIMILARITY(a1, a2);
00365 }
00366
00371 int CompareShockDrDs(const void* elem1, const void* elem2)
00372 {
00373 ShockInfo* e1 = (ShockInfo*) elem1;
00374 ShockInfo* e2 = (ShockInfo*) elem2;
00375
00376 ASSERT(e1 && e2);
00377
00378 if (e1->dr_ds > e2->dr_ds)
00379 return 1;
00380 else if (e1->dr_ds < e2->dr_ds)
00381 return -1;
00382 else
00383 return 0;
00384 }
00385
00387 double ShockBranch::CompareVelocities(const ShockBranch& rhs, const double& scale) const
00388 {
00389 double avg1, avg2;
00390
00391 avg1 = AvgVelocity();
00392 avg2 = rhs.AvgVelocity() * scale;
00393
00394 return SIMILARITY(avg1, avg2);
00395 }
00396
00397 void ShockBranch::ComputeDerivedValues()
00398 {
00399 int i, size = GetSize();
00400 double dx, dy, prevRadius, mean_x;
00401
00402 area = 0;
00403 avgRadius = 0;
00404 avgVelocity = 0;
00405 length = 0;
00406
00407 bValuesComputed = true;
00408
00409 if (size == 0)
00410 return;
00411 else if (size == 1)
00412 {
00413 avgRadius = operator[](0).radius;
00414 area = 2 * avgRadius;
00415 return;
00416 }
00417
00418 for (i = 0; i < size; i++)
00419 {
00420 const ShockInfo& si = (*this)[i];
00421
00422 length += si.speed;
00423
00424
00425
00426 if (i > 0)
00427 area += .5 * (prevRadius + si.radius) * si.speed;
00428
00429 prevRadius = si.radius;
00430 }
00431
00432
00433
00434
00435 ASSERT(segments.GetSize() > 0);
00436
00437 for (i = 0; i < segments.GetSize(); i++)
00438 {
00439 const SEGMENT& s = segments[i];
00440
00441 mean_x = (s.p0.x + s.p1.x) / 2.0;
00442 avgRadius += s.m * mean_x + s.b;
00443 }
00444
00445 avgRadius /= segments.GetSize();
00446
00447 ASSERT(avgRadius >= 0);
00448
00449
00450
00451
00452
00453 ShockBranch b(*this);
00454 int min, max, nanCount = 0;
00455
00456 ASSERT(NOT_TO_COMPARE_PERCENTAGE > 0 && NOT_TO_COMPARE_PERCENTAGE <= 1);
00457
00458 b.Sort(CompareShockDrDs);
00459
00460 min = round(size * NOT_TO_COMPARE_PERCENTAGE);
00461 max = size - min;
00462
00463 for (i = min; i < max; i++)
00464 {
00465 if (isnan(b[i].dr_ds) || !finite(b[i].dr_ds))
00466 {
00467
00468 nanCount++;
00469 continue;
00470 }
00471
00472 avgVelocity += b[i].dr_ds;
00473 }
00474
00475 if (avgVelocity != 0)
00476 avgVelocity /= max - min - nanCount;
00477 }
00478
00479 istream& ShockBranch::Read(istream& is)
00480 {
00481 SmartArray<ShockInfo>::Read(is);
00482
00483 segments.Read(is);
00484 is.read((char*) &dir, sizeof(dir));
00485
00486 is.read((char*) &bValuesComputed, sizeof(bValuesComputed));
00487 is.read((char*) &area, sizeof(area));
00488 is.read((char*) &length, sizeof(length));
00489 is.read((char*) &avgRadius, sizeof(avgRadius));
00490 is.read((char*) &avgVelocity, sizeof(avgVelocity));
00491
00492 return is;
00493 }
00494
00495 ostream& ShockBranch::Write(ostream& os) const
00496 {
00497 SmartArray<ShockInfo>::Write(os);
00498
00499 segments.Write(os);
00500 os.write((char*) &dir, sizeof(dir));
00501
00502 os.write((char*) &bValuesComputed, sizeof(bValuesComputed));
00503 os.write((char*) &area, sizeof(area));
00504 os.write((char*) &length, sizeof(length));
00505 os.write((char*) &avgRadius, sizeof(avgRadius));
00506 os.write((char*) &avgVelocity, sizeof(avgVelocity));
00507
00508 return os;
00509 }
00510
00511 bool ShockBranch::operator==(const ShockBranch& rhs) const
00512 {
00513 ASSERT(bValuesComputed && rhs.bValuesComputed);
00514
00515 return AvgRadius() == rhs.AvgRadius();
00516 }
00517
00525 bool ShockBranch::operator>(const ShockBranch& rhs) const
00526 {
00527 ASSERT(bValuesComputed && rhs.bValuesComputed);
00528
00529
00530
00531
00532
00533 return AvgRadius() > rhs.AvgRadius();
00534
00535
00536 }
00537
00538 void ShockBranch::SetSegments(const SEGMENTS& segs, const double& d)
00539 {
00540 ASSERT(d >= 0);
00541 segments = segs;
00542
00543
00544 if (d > 0.0)
00545 {
00546
00547 for(int i = 0; i < segments.GetSize(); i++)
00548 {
00549 SEGMENT& s = segments[i];
00550 s.p0.x -= d;
00551 s.p1.x -= d;
00552 s.b += s.m * d;
00553 }
00554 }
00555 }
00556
00557