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 

Generated on Sat Nov 13 11:21:25 2004 for Noisy DAG Matcher by doxygen1.2.18