Main Page Namespace List Class Hierarchy Compound List File List Namespace Members Compound Members File Members Related Pages

# SGNode.cpp

Go to the documentation of this file.

    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> // needed only for the gw_node_shape enum values
    00050
    00051 #define NOT_TO_COMPARE_PERCENTAGE .15
    00052 #define MIN_LIGATURE .7
    00053
    00055 // ShockInfo class implementation
    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 // SGNode class implementation
    00085
    00086
    00087 // Begin DAGNode virtual functions
    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 // End DAGNode virtual functions
    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         /*sprintf(lbl, "%s:%d",
    00237                 (const char*) GetNodeLbl(),
    00238                 GetDFSIndex());*/
    00239
    00240         //sprintf(lbl, "%d:%d", GetDFSIndex(), m_nType - 100);
    00241
    00242         return lbl;
    00243 }
    00244
    00246 leda_color SGNode::GetColorForGraph() const
    00247 {
    00248         unsigned char c;
    00249
    00250         /*if (m_seg1 < 2.0 && m_seg2 < 2.0)
    00251                 c = 128;
    00252         else if (m_seg1 < 2.0 || m_seg2 < 2.0)
    00253                 c = 192;
    00254         else*/
    00255                 c = 255;
    00256
    00257         return leda_color(c, c, c);
    00258 }
    00259
    00265 int SGNode::GetShapeForGraph() const
    00266 {
    00267   //using namespace LEDA;
    00268
    00269         /*int nShockCount = GetShockCount();
    00270
    00271         if (nShockCount == 0) // The root node has no shock
    00272                 return leda_ellipse_node;
    00273
    00274         double r1 = m_seg1 / nShockCount;
    00275         double r2 = m_seg2 / nShockCount;
    00276
    00277         if (r1 >= MIN_LIGATURE && r2 >= MIN_LIGATURE)
    00278                 return ellipse_node;
    00279         else if (r1 >= MIN_LIGATURE || r2 >= MIN_LIGATURE)
    00280                 return leda_roundrect_node;
    00281         else
    00282                 return leda_rectangle_node;*/
    00283         return leda_ellipse_node;
    00284 }
    00285
    00286 POINTS SGNode::GetVelocityRadiusArray(int& d0, int& dN, bool bReverseOrder /*=false*/) const
    00287 {
    00288         int i, nSize = m_shocks.GetSize();
    00289         double s;
    00290
    00291         // we don't want to consider those end points that join branches
    00292         // because they're usually outliers wrt to the branch pts.
    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 // ShockBranch
    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; // speed is delta s
    00423                 //avgRadius += si.radius;
    00424
    00425                 // The area is the sum of the trapezoids
    00426                 if (i > 0)
    00427                         area += .5 * (prevRadius + si.radius) * si.speed;
    00428
    00429                 prevRadius = si.radius;
    00430         }
    00431
    00432         // Compute the average radius of the brach.
    00433         //avgRadius /= size;
    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         // Compute the average velocity of the brach.
    00451         // Firts, eliminate NOT_TO_COMPARE_PERCENTAGE percentage
    00452         // of the extreme values before computing avg.
    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                         //DBG_MSG("Illegal dr_ds value!!!");
    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         // If either branch has only one shock, it is likely that this one shock
    00530         // will have some error. So, we must treat this case differently.
    00531
    00532         //if (GetSize() == rhs.GetSize() || (GetSize() > 1 && rhs.GetSize() > 1))
    00533                 return AvgRadius() > rhs.AvgRadius();
    00534         //else
    00535         //      return MaxR() > rhs.MaxR() || MinR() > rhs.MinR();
    00536 }
    00537
    00538 void ShockBranch::SetSegments(const SEGMENTS& segs, const double& d)
    00539 {
    00540         ASSERT(d >= 0);
    00541         segments = segs;
    00542
    00543         // first segment should start at point zero
    00544         if (d > 0.0)
    00545         {
    00546                 // Shift all the segments by d
    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