GME
13
|
00001 00002 #include "stdafx.h" 00003 #include <math.h> 00004 #include "ArHelper.h" 00005 00006 00007 // --------------------------- CRect && CPoint 00008 00009 CustomPathData::CustomPathData(): 00010 version (CONNECTIONCUSTOMIZATIONDATAVERSION), 00011 aspect (0), 00012 edgeIndex (0), 00013 edgeCount (-1), 00014 type (SimpleEdgeDisplacement), 00015 horizontalOrVerticalEdge (true), 00016 x (0), 00017 y (0) 00018 { 00019 } 00020 00021 CustomPathData& CustomPathData::operator=(const CustomPathData& other) 00022 { 00023 if (this != &other) 00024 { 00025 this->version = other.version; 00026 this->aspect = other.aspect; 00027 this->edgeIndex = other.edgeIndex; 00028 this->edgeCount = other.edgeCount; 00029 this->type = other.type; 00030 this->horizontalOrVerticalEdge = other.horizontalOrVerticalEdge; 00031 this->x = other.x; 00032 this->y = other.y; 00033 this->l = other.l; 00034 this->d = other.d; 00035 } 00036 return *this; 00037 } 00038 00039 void CustomPathData::Serialize(CString& outChannel) 00040 { 00041 outChannel.Format(_T("%ld,%ld,%ld,%d,%ld"), GetVersion(), GetAspect(), GetEdgeIndex(), 00042 GetEdgeCount(), GetType()); 00043 CString additionalDataStr; 00044 additionalDataStr.Format(_T(",%ld,%ld,%ld,%ld"), IsHorizontalOrVertical() ? 1 : 0, 00045 GetX(), GetY(), GetLongDataCount()); 00046 outChannel.Append(additionalDataStr); 00047 for(long i = 0; i < GetLongDataCount(); i++) { 00048 additionalDataStr.Format(_T(",%ld"), l[i]); 00049 outChannel.Append(additionalDataStr); 00050 } 00051 additionalDataStr.Format(_T(",%ld"), GetDoubleDataCount()); 00052 outChannel.Append(additionalDataStr); 00053 for(long i = 0; i < GetDoubleDataCount(); i++) { 00054 additionalDataStr.Format(_T(",%lf"), d[i]); 00055 outChannel.Append(additionalDataStr); 00056 } 00057 } 00058 00059 bool CustomPathData::Deserialize(const CString& inChannel) 00060 { 00061 TRACE(_T("\tResulting token: %s\n"), inChannel); 00062 int curSubPos = 0; 00063 CString versionStr = inChannel.Tokenize(_T(","), curSubPos); 00064 SetVersion(_tcstol(versionStr, NULL, 10)); 00065 ASSERT(GetVersion() == CONNECTIONCUSTOMIZATIONDATAVERSION); 00066 if (GetVersion() != CONNECTIONCUSTOMIZATIONDATAVERSION) { 00067 // TODO: Convert from older version to newer 00068 return false; 00069 } 00070 CString aspectStr = inChannel.Tokenize(_T(","), curSubPos); 00071 SetAspect(_tcstol(aspectStr, NULL, 10)); 00072 CString edgeIndexStr = inChannel.Tokenize(_T(","), curSubPos); 00073 SetEdgeIndex(_tcstol(edgeIndexStr, NULL, 10)); 00074 CString edgeCountStr = inChannel.Tokenize(_T(","), curSubPos); 00075 SetEdgeCount(_tcstol(edgeCountStr, NULL, 10)); 00076 CString edgeCustomTypeStr = inChannel.Tokenize(_T(","), curSubPos); 00077 SetType((PathCustomizationType)_tcstol(edgeCustomTypeStr, NULL, 10)); 00078 TRACE(_T("\tAsp %ld, Ind %ld, Cnt %d, Typ %ld"), GetAspect(), GetEdgeIndex(), GetEdgeCount(), GetType()); 00079 CString directionStr = inChannel.Tokenize(_T(","), curSubPos); 00080 SetHorizontalOrVertical(_tcstol(directionStr, NULL, 10) != 0); 00081 CString positionStr = inChannel.Tokenize(_T(","), curSubPos); 00082 SetX(_tcstol(positionStr, NULL, 10)); 00083 positionStr = inChannel.Tokenize(_T(","), curSubPos); 00084 SetY(_tcstol(positionStr, NULL, 10)); 00085 positionStr = inChannel.Tokenize(_T(","), curSubPos); 00086 long numOfExtraLongData = _tcstol(positionStr, NULL, 10); 00087 ASSERT(numOfExtraLongData >= 0 && numOfExtraLongData <= 4); 00088 TRACE(_T(", Dir %ld, x %ld, y %ld, num %ld"), IsHorizontalOrVertical(), GetX(), GetY(), numOfExtraLongData); 00089 for(long i = 0; i < numOfExtraLongData; i++) { 00090 positionStr = inChannel.Tokenize(_T(","), curSubPos); 00091 AddLongData(_tcstol(positionStr, NULL, 10)); 00092 TRACE(_T(", l%ld %ld"), i, l[i]); 00093 } 00094 TRACE(_T("\n")); 00095 00096 positionStr = inChannel.Tokenize(_T(","), curSubPos); 00097 long numOfExtraDoubleData = _tcstol(positionStr, NULL, 10); 00098 ASSERT(numOfExtraDoubleData >= 0 && numOfExtraDoubleData <= 8); 00099 TRACE(_T(", num %ld"), numOfExtraDoubleData); 00100 for(long i = 0; i < numOfExtraDoubleData; i++) { 00101 positionStr = inChannel.Tokenize(_T(","), curSubPos); 00102 AddDoubleData(_ttof(positionStr)); 00103 TRACE(_T(", l%ld %lf"), i, d[i]); 00104 } 00105 TRACE(_T("\n")); 00106 return true; 00107 } 00108 00109 long CustomPathData::GetVersion(void) const 00110 { 00111 return version; 00112 } 00113 00114 void CustomPathData::SetVersion(long ver) 00115 { 00116 version = ver; 00117 } 00118 00119 long CustomPathData::GetAspect(void) const 00120 { 00121 return aspect; 00122 } 00123 00124 void CustomPathData::SetAspect(long asp) 00125 { 00126 aspect = asp; 00127 } 00128 00129 long CustomPathData::GetEdgeIndex(void) const 00130 { 00131 return edgeIndex; 00132 } 00133 00134 void CustomPathData::SetEdgeIndex(long index) 00135 { 00136 edgeIndex = index; 00137 } 00138 00139 long CustomPathData::GetEdgeCount(void) const 00140 { 00141 return edgeCount; 00142 } 00143 00144 void CustomPathData::SetEdgeCount(long count) 00145 { 00146 edgeCount = count; 00147 } 00148 00149 PathCustomizationType CustomPathData::GetType(void) const 00150 { 00151 return type; 00152 } 00153 00154 void CustomPathData::SetType(PathCustomizationType typ) 00155 { 00156 type = typ; 00157 } 00158 00159 bool CustomPathData::IsHorizontalOrVertical(void) const 00160 { 00161 return horizontalOrVerticalEdge; 00162 } 00163 00164 void CustomPathData::SetHorizontalOrVertical(bool parity) 00165 { 00166 horizontalOrVerticalEdge = parity; 00167 } 00168 00169 long CustomPathData::GetX(void) const 00170 { 00171 return x; 00172 } 00173 00174 void CustomPathData::SetX(long coord) 00175 { 00176 x = coord; 00177 } 00178 00179 long CustomPathData::GetY(void) const 00180 { 00181 return y; 00182 } 00183 00184 void CustomPathData::SetY(long coord) 00185 { 00186 y = coord; 00187 } 00188 00189 long CustomPathData::GetLongDataCount(void) const 00190 { 00191 return (long)l.size(); 00192 } 00193 00194 long CustomPathData::GetLongData(long index) const 00195 { 00196 return l[index]; 00197 } 00198 00199 void CustomPathData::SetLongData(long index, long dat) 00200 { 00201 l[index] = dat; 00202 } 00203 00204 void CustomPathData::AddLongData(long dat) 00205 { 00206 l.push_back(dat); 00207 } 00208 00209 long CustomPathData::GetDoubleDataCount(void) const 00210 { 00211 return (long)d.size(); 00212 } 00213 00214 double CustomPathData::GetDoubleData(long index) const 00215 { 00216 return d[index]; 00217 } 00218 00219 void CustomPathData::SetDoubleData(long index, double dat) 00220 { 00221 d[index] = dat; 00222 } 00223 00224 void CustomPathData::AddDoubleData(double dat) 00225 { 00226 d.push_back(dat); 00227 } 00228 00229 00230 // --------------------------- CRect && CPoint 00231 00232 00233 CRect InflatedRect(const CRect& rect, int a) 00234 { 00235 CRect r = rect; 00236 r.InflateRect(a,a); 00237 return r; 00238 } 00239 00240 CRect DeflatedRect(const CRect& rect, int a) 00241 { 00242 CRect r = rect; 00243 r.DeflateRect(a,a); 00244 return r; 00245 } 00246 00247 bool IsPointNear(const CPoint& p1, const CPoint& p2, int nearness) 00248 { 00249 return p2.x - nearness <= p1.x && p1.x <= p2.x + nearness && 00250 p2.y - nearness <= p1.y && p1.y <= p2.y + nearness; 00251 } 00252 00253 bool IsPointIn(const CPoint& point, const CRect& rect, int nearness) 00254 { 00255 CRect tmpR = rect; 00256 tmpR.InflateRect(nearness, nearness); 00257 return tmpR.PtInRect(point) == TRUE; 00258 } 00259 00260 bool IsRectIn(const CRect& r1, const CRect& r2) 00261 { 00262 return r2.left <= r1.left && r1.right <= r2.right && 00263 r2.top <= r1.top && r1.bottom <= r2.bottom; 00264 } 00265 00266 bool IsRectClip(const CRect& r1, const CRect& r2) 00267 { 00268 CRect rect; 00269 return rect.IntersectRect(&r1, &r2) == TRUE; 00270 } 00271 00272 bool IsPointNearHLine(const CPoint& p, long x1, long x2, long y, int nearness) 00273 { 00274 ASSERT( x1 <= x2 ); 00275 00276 return x1 - nearness <= p.x && p.x <= x2 + nearness && 00277 y - nearness <= p.y && p.y <= y + nearness; 00278 } 00279 00280 bool IsPointNearVLine(const CPoint& p, long y1, long y2, long x, int nearness) 00281 { 00282 ASSERT( y1 <= y2 ); 00283 00284 return y1 - nearness <= p.y && p.y <= y2 + nearness && 00285 x - nearness <= p.x && p.x <= x + nearness; 00286 } 00287 00288 int DistanceFromHLine(const CPoint& p, long x1, long x2, long y) 00289 { 00290 ASSERT( x1 <= x2 ); 00291 00292 return max(abs(p.y - y), max(x1 - p.x, p.x - x2)); 00293 } 00294 00295 int DistanceFromVLine(const CPoint& p, long y1, long y2, long x) 00296 { 00297 ASSERT( y1 <= y2 ); 00298 00299 return max(abs(p.x - x), max(y1 - p.y, p.y - y2)); 00300 } 00301 00302 double DistanceSquareFromLine(const CPoint& start, const CPoint& end, const CPoint& pt) 00303 { 00304 // |det(end-start start-pt)| 00305 // d = ------------------------- 00306 // |end-start| 00307 // 00308 double nom = abs((double)(end.x - start.x) * (start.y - pt.y) - (start.x - pt.x) * (end.y - start.y)); 00309 double denom_square = (double)((end.x - start.x) * (end.x - start.x) + (end.y - start.y) * (end.y - start.y)); 00310 double d_square = nom * nom / denom_square; 00311 return d_square; 00312 } 00313 00314 bool IsOnEdge(const CPoint& start, const CPoint& end, const CPoint& pt, int nearness) 00315 { 00316 if (start.x == end.x) // vertical edge, horizontal move 00317 { 00318 if (abs(end.x - pt.x) <= nearness && pt.y <= max(end.y, start.y) + nearness && pt.y >= min(end.y, start.y) - nearness) 00319 return true; 00320 } 00321 else if (start.y == end.y) // horizontal line, vertical move 00322 { 00323 if (abs(end.y - pt.y) <= nearness && pt.x <= max(end.x, start.x) + nearness && pt.x >= min(end.x, start.x) - nearness) 00324 return true; 00325 } 00326 else 00327 { 00328 // TODO: consider non-linear edges 00329 // 00330 // Is the point close to the edge? 00331 double d_square = DistanceSquareFromLine(start, end, pt); 00332 if (d_square <= nearness * nearness) { 00333 // Check not just if the point is on the line, but if it is on the line segment 00334 // point = m * start + (1 - m) * end 00335 // 00336 // m = (pt + end) / (start + end) 00337 // 0.0 <= m <= 1.0 00338 00339 double m1 = ((double)pt.x - end.x) / (start.x - end.x); 00340 double m2 = ((double)pt.y - end.y) / (start.y - end.y); 00341 //ASSERT(abs(m2 - m1) < 2.0e-1); 00342 if (m1 >= 0.0 && m1 <= 1.0 && m2 >= 0.0 && m2 <= 1.0) 00343 return true; 00344 } 00345 } 00346 return false; 00347 } 00348 00349 bool IsPointNearLine(const CPoint& point, const CPoint& start, const CPoint& end, int nearness) 00350 { 00351 ASSERT( 0 <= nearness ); 00352 00353 // begin Zolmol 00354 // the routing may create edges that have start==end 00355 // thus confusing this algorithm 00356 if( end.x == start.x && end.y == start.y) 00357 return false; 00358 // end Zolmol 00359 00360 CPoint point2 = point; 00361 point2 -= start; 00362 CPoint end2 = end; 00363 end2 -= start; 00364 00365 double x = end2.x; 00366 double y = end2.y; 00367 double u = point2.x; 00368 double v = point2.y; 00369 double xuyv = x * u + y * v; 00370 double x2y2 = x * x + y * y; 00371 00372 if(xuyv < 0 || xuyv > x2y2) 00373 return false; 00374 00375 double expr1 = (x * v - y * u) ; 00376 expr1 *= expr1; 00377 double expr2 = nearness * nearness * x2y2; 00378 00379 return expr1 <= expr2; 00380 } 00381 00382 bool IsLineMeetHLine(const CPoint& start, const CPoint& end, long x1, long x2, long y) 00383 { 00384 ASSERT( x1 <= x2 ); 00385 00386 if( !((start.y <= y && y <= end.y) || (end.y <= y && y <= start.y )) ) 00387 return false; 00388 00389 CPoint end2 = end; 00390 end2 -= start; 00391 x1 -= start.x; 00392 x2 -= start.x; 00393 y -= start.y; 00394 00395 if( end2.y == 0 ) 00396 return y == 0 && (( x1 <= 0 && 0 <= x2 ) || (x1 <= end2.x && end2.x <= x2)); 00397 00398 long x = (long)(((float)end2.x) / end2.y) * y; 00399 return x1 <= x && x <= x2; 00400 } 00401 00402 bool IsLineMeetVLine(const CPoint& start, const CPoint& end, long y1, long y2, long x) 00403 { 00404 ASSERT( y1 <= y2 ); 00405 00406 if( !((start.x <= x && x <= end.x) || (end.x <= x && x <= start.x )) ) 00407 return false; 00408 00409 CPoint end2 = end; 00410 end2 -= start; 00411 y1 -= start.y; 00412 y2 -= start.y; 00413 x -= start.x; 00414 00415 if( end2.x == 0 ) 00416 return x == 0 && (( y1 <= 0 && 0 <= y2 ) || (y1 <= end2.y && end2.y <= y2)); 00417 00418 long y = (long)(((float)end2.y) / end2.x) * x; 00419 return y1 <= y && y <= y2; 00420 } 00421 00422 bool IsLineClipRect(const CPoint& start, const CPoint& end, const CRect& rect) 00423 { 00424 if( rect.PtInRect(start) || rect.PtInRect(end) ) 00425 return true; 00426 00427 return IsLineMeetHLine(start, end, rect.left, rect.right - 1, rect.top) || 00428 IsLineMeetHLine(start, end, rect.left, rect.right - 1, rect.bottom - 1) || 00429 IsLineMeetVLine(start, end, rect.top, rect.bottom - 1, rect.left) || 00430 IsLineMeetVLine(start, end, rect.top, rect.bottom - 1, rect.right - 1); 00431 } 00432 00433 bool Intersect(long a1, long a2, long b1, long b2) 00434 { 00435 return min(a1,a2) <= max(b1,b2) && min(b1,b2) <= max(a1,a2); 00436 } 00437 00438 00439 // --------------------------- RoutingDirection 00440 00441 00442 bool AreInRightAngle(RoutingDirection dir1, RoutingDirection dir2) 00443 { 00444 ASSERT( IsRightAngle(dir1) && IsRightAngle(dir2) ); 00445 return IsHorizontal(dir1) == IsVertical(dir2); 00446 } 00447 00448 RoutingDirection NextClockwiseDir(RoutingDirection dir) 00449 { 00450 if( IsRightAngle(dir) ) 00451 return (RoutingDirection) ((dir+1) % 4); 00452 00453 return dir; 00454 } 00455 00456 RoutingDirection PrevClockwiseDir(RoutingDirection dir) 00457 { 00458 if( IsRightAngle(dir) ) 00459 return (RoutingDirection) ((dir+3) % 4); 00460 00461 return dir; 00462 } 00463 00464 RoutingDirection ReverseDir(RoutingDirection dir) 00465 { 00466 if( IsRightAngle(dir) ) 00467 return (RoutingDirection) ((dir+2) % 4); 00468 00469 return dir; 00470 } 00471 00472 CPoint StepOneInDir(const CPoint& point, RoutingDirection dir) 00473 { 00474 ASSERT( IsRightAngle(dir) ); 00475 CPoint p(point); 00476 00477 switch(dir) 00478 { 00479 case Dir_Top: 00480 p.y--; 00481 break; 00482 00483 case Dir_Right: 00484 p.x++; 00485 break; 00486 00487 case Dir_Bottom: 00488 p.y++; 00489 break; 00490 00491 case Dir_Left: 00492 p.x--; 00493 break; 00494 } 00495 00496 return p; 00497 } 00498 00499 long& GetRectCoord(CRect& rect, RoutingDirection dir) 00500 { 00501 ASSERT( IsRightAngle(dir) ); 00502 00503 switch( dir ) 00504 { 00505 case Dir_Top: 00506 return rect.top; 00507 00508 case Dir_Right: 00509 return rect.right; 00510 00511 case Dir_Bottom: 00512 return rect.bottom; 00513 } 00514 00515 return rect.left; 00516 } 00517 00518 long GetRectOuterCoord(const CRect& rect, RoutingDirection dir) 00519 { 00520 ASSERT( IsRightAngle(dir) ); 00521 00522 switch( dir ) 00523 { 00524 case Dir_Top: 00525 return rect.top-1; 00526 00527 case Dir_Right: 00528 return rect.right; 00529 00530 case Dir_Bottom: 00531 return rect.bottom; 00532 } 00533 00534 return rect.left-1; 00535 } 00536 00537 // Indexes: 00538 // 04 00539 // 1 5 00540 // 3 7 00541 // 26 00542 00543 int GetDirTableIndex(const CSize& offset) 00544 { 00545 return (offset.cx >= 0)*4 + (offset.cy >= 0)*2 + (abs(offset.cx) >= abs(offset.cy)); 00546 } 00547 00548 RoutingDirection majordir_table[] = 00549 { 00550 Dir_Top, 00551 Dir_Left, 00552 Dir_Bottom, 00553 Dir_Left, 00554 Dir_Top, 00555 Dir_Right, 00556 Dir_Bottom, 00557 Dir_Right 00558 }; 00559 00560 RoutingDirection GetMajorDir(const CSize& offset) 00561 { 00562 return majordir_table[GetDirTableIndex(offset)]; 00563 } 00564 00565 RoutingDirection minordir_table[] = 00566 { 00567 Dir_Left, 00568 Dir_Top, 00569 Dir_Left, 00570 Dir_Bottom, 00571 Dir_Right, 00572 Dir_Top, 00573 Dir_Right, 00574 Dir_Bottom 00575 }; 00576 00577 RoutingDirection GetMinorDir(const CSize& offset) 00578 { 00579 return minordir_table[GetDirTableIndex(offset)]; 00580 } 00581 00582 // FG123 00583 // E 4 00584 // D 0 5 00585 // C 6 00586 // BA987 00587 00588 int ExGetDirTableIndex(const CSize& offset) 00589 { 00590 return 00591 offset.cx > 0 ? 00592 ( 00593 offset.cy > 0 ? 00594 ( 00595 offset.cx > offset.cy ? 00596 ( 00597 6 00598 ) : 00599 (offset.cx < offset.cy ? 00600 ( 00601 8 00602 ) : 00603 ( 00604 7 00605 )) 00606 ) : 00607 (offset.cy < 0 ? 00608 ( 00609 offset.cx > -offset.cy ? 00610 ( 00611 4 00612 ) : 00613 (offset.cx < -offset.cy ? 00614 ( 00615 2 00616 ) : 00617 ( 00618 3 00619 )) 00620 ) : 00621 ( 00622 5 00623 )) 00624 ) : 00625 (offset.cx < 0 ? 00626 ( 00627 offset.cy > 0 ? 00628 ( 00629 -offset.cx > offset.cy ? 00630 ( 00631 12 00632 ) : 00633 (-offset.cx < offset.cy ? 00634 ( 00635 10 00636 ) : 00637 ( 00638 11 00639 )) 00640 ) : 00641 (offset.cy < 0 ? 00642 ( 00643 offset.cx < offset.cy ? 00644 ( 00645 14 00646 ) : 00647 (offset.cx > offset.cy ? 00648 ( 00649 16 00650 ) : 00651 ( 00652 15 00653 )) 00654 ) : 00655 ( 00656 13 00657 )) 00658 ) : 00659 ( 00660 offset.cy > 0 ? 00661 ( 00662 9 00663 ) : 00664 (offset.cy < 0 ? 00665 ( 00666 1 00667 ) : 00668 ( 00669 0 00670 )) 00671 )); 00672 } 00673 00674 RoutingDirection exmajordir_table[17] = 00675 { 00676 Dir_None, 00677 Dir_Top, 00678 Dir_Top, 00679 Dir_Right, 00680 Dir_Right, 00681 Dir_Right, 00682 Dir_Right, 00683 Dir_Right, 00684 Dir_Bottom, 00685 Dir_Bottom, 00686 Dir_Bottom, 00687 Dir_Left, 00688 Dir_Left, 00689 Dir_Left, 00690 Dir_Left, 00691 Dir_Left, 00692 Dir_Top 00693 }; 00694 00695 RoutingDirection ExGetMajorDir(const CSize& offset) 00696 { 00697 return exmajordir_table[ExGetDirTableIndex(offset)]; 00698 } 00699 00700 RoutingDirection exminordir_table[17] = 00701 { 00702 Dir_None, 00703 Dir_None, 00704 Dir_Right, 00705 Dir_Top, 00706 Dir_Top, 00707 Dir_None, 00708 Dir_Bottom, 00709 Dir_Bottom, 00710 Dir_Right, 00711 Dir_None, 00712 Dir_Left, 00713 Dir_Bottom, 00714 Dir_Bottom, 00715 Dir_None, 00716 Dir_Top, 00717 Dir_Top, 00718 Dir_Left 00719 }; 00720 00721 RoutingDirection ExGetMinorDir(const CSize& offset) 00722 { 00723 return exminordir_table[ExGetDirTableIndex(offset)]; 00724 } 00725 00726 RoutingDirection GetDir(const CSize& offset, RoutingDirection nodir) 00727 { 00728 if( offset.cx == 0 ) 00729 { 00730 if( offset.cy == 0 ) 00731 return nodir; 00732 00733 if( offset.cy < 0 ) 00734 return Dir_Top; 00735 00736 return Dir_Bottom; 00737 } 00738 00739 if( offset.cy == 0 ) 00740 { 00741 if( offset.cx > 0 ) 00742 return Dir_Right; 00743 00744 return Dir_Left; 00745 } 00746 00747 return Dir_Skew; 00748 } 00749 00750 RoutingDirection GetSkewDir(const CSize& offset, RoutingDirection nodir) 00751 { 00752 if (offset.cx == 0 || abs(offset.cy) > abs(offset.cx)) 00753 { 00754 if (offset.cy == 0) 00755 return nodir; 00756 00757 if (offset.cy < 0) 00758 return Dir_Top; 00759 00760 return Dir_Bottom; 00761 } 00762 00763 if (offset.cy == 0 || abs(offset.cx) >= abs(offset.cy)) 00764 { 00765 if (offset.cx > 0) 00766 return Dir_Right; 00767 00768 return Dir_Left; 00769 } 00770 00771 ASSERT(false); 00772 return Dir_Skew; 00773 } 00774 00775 bool IsPointInDirFrom(const CPoint& point, const CPoint& from, RoutingDirection dir) 00776 { 00777 ASSERT( IsRightAngle(dir) ); 00778 00779 switch( dir ) 00780 { 00781 case Dir_Top: 00782 return point.y <= from.y; 00783 00784 case Dir_Right: 00785 return point.x >= from.x; 00786 00787 case Dir_Bottom: 00788 return point.y >= from.y; 00789 00790 case Dir_Left: 00791 return point.x <= from.x; 00792 } 00793 00794 return false; 00795 } 00796 00797 bool IsPointInDirFrom(const CPoint& point, const CRect& rect, RoutingDirection dir) 00798 { 00799 ASSERT( IsRightAngle(dir) ); 00800 00801 switch( dir ) 00802 { 00803 case Dir_Top: 00804 return point.y < rect.top; 00805 00806 case Dir_Right: 00807 return point.x >= rect.right; 00808 00809 case Dir_Bottom: 00810 return point.y >= rect.bottom; 00811 00812 case Dir_Left: 00813 return point.x < rect.left; 00814 } 00815 00816 return false; 00817 } 00818 00819 bool IsPointBetweenSides(const CPoint& point, const CRect& rect, bool ishorizontal) 00820 { 00821 if( ishorizontal ) 00822 return rect.top <= point.y && point.y < rect.bottom; 00823 00824 return rect.left <= point.x && point.x < rect.right; 00825 } 00826 00827 RoutingDirection PointOnSide(const CPoint& point, const CRect& rect) 00828 { 00829 int dleft = DistanceFromVLine(point, rect.top, rect.bottom, rect.left); 00830 int dtop = DistanceFromHLine(point, rect.left, rect.right, rect.top); 00831 int dright = DistanceFromVLine(point, rect.top, rect.bottom, rect.right); 00832 int dbottom = DistanceFromHLine(point, rect.left, rect.right, rect.bottom); 00833 00834 if (dleft < 3) 00835 return Dir_Left; 00836 if (dtop < 3) 00837 return Dir_Top; 00838 if (dright < 3) 00839 return Dir_Right; 00840 if (dbottom < 3) 00841 return Dir_Bottom; 00842 00843 return GetSkewDir(point - rect.CenterPoint()); 00844 } 00845 00846 bool IsCoordInDirFrom(long coord, long from, RoutingDirection dir) 00847 { 00848 ASSERT( IsRightAngle(dir) ); 00849 00850 if( dir == Dir_Top || dir == Dir_Left ) 00851 return coord <= from; 00852 00853 return coord >= from; 00854 } 00855 00856 RoutingDirection OnWhichEdge(const CRect& rect, const CPoint& point) 00857 { 00858 if( point.y == rect.top && rect.left < point.x && point.x < rect.right - 1 ) 00859 return Dir_Top; 00860 00861 if( point.y == rect.bottom - 1 && rect.left < point.x && point.x < rect.right - 1 ) 00862 return Dir_Bottom; 00863 00864 if( point.x == rect.left && rect.top < point.y && point.y < rect.bottom - 1 ) 00865 return Dir_Left; 00866 00867 if( point.x == rect.right - 1 && rect.top < point.y && point.y < rect.bottom - 1 ) 00868 return Dir_Right; 00869 00870 return Dir_None; 00871 } 00872 00873 00874 // --------------------------- CArFindNearestLine 00875 00876 00877 bool CArFindNearestLine::HLine(int x1, int x2, int y) 00878 { 00879 ASSERT( x1 <= x2 ); 00880 00881 int d1 = DistanceFromHLine(point, x1, x2, y); 00882 int d2 = abs(point.y - y); 00883 00884 if( d1 < dist1 || (d1 == dist1 && d2 < dist2) ) 00885 { 00886 dist1 = d1; 00887 dist2 = d2; 00888 return true; 00889 } 00890 00891 return false; 00892 } 00893 00894 bool CArFindNearestLine::VLine(int y1, int y2, int x) 00895 { 00896 ASSERT( y1 <= y2 ); 00897 00898 int d1 = DistanceFromVLine(point, y1, y2, x); 00899 int d2 = abs(point.x - x); 00900 00901 if( d1 < dist1 || (d1 == dist1 && d2 < dist2) ) 00902 { 00903 dist1 = d1; 00904 dist2 = d2; 00905 return true; 00906 } 00907 00908 return false; 00909 } 00910 00911 00912 // --------------------------- CPointListPath 00913 00914 00915 POSITION CPointListPath::GetHeadEdge(CPoint& start, CPoint& end) const 00916 { 00917 if( GetCount() < 2 ) 00918 return NULL; 00919 00920 POSITION pos = GetHeadPosition(); 00921 ASSERT( pos != NULL ); 00922 00923 start = GetNext(pos); 00924 ASSERT( pos != NULL ); 00925 00926 end = GetAt(pos); 00927 00928 return pos; 00929 } 00930 00931 POSITION CPointListPath::GetTailEdge(CPoint& start, CPoint& end) const 00932 { 00933 if( GetCount() < 2 ) 00934 return NULL; 00935 00936 POSITION pos = GetTailPosition(); 00937 ASSERT( pos != NULL ); 00938 00939 end = GetPrev(pos); 00940 ASSERT( pos != NULL ); 00941 00942 start = GetAt(pos); 00943 00944 return pos; 00945 } 00946 00947 void CPointListPath::GetNextEdge(POSITION& pos, CPoint& start, CPoint& end) const 00948 { 00949 #ifdef _DEBUG 00950 AssertValidPos(pos); 00951 #endif 00952 00953 GetNext(pos); 00954 ASSERT( pos != NULL ); 00955 00956 POSITION p = pos; 00957 start = GetNext(p); 00958 if( p == NULL ) 00959 pos = NULL; 00960 else 00961 end = GetAt(p); 00962 } 00963 00964 void CPointListPath::GetPrevEdge(POSITION& pos, CPoint& start, CPoint& end) const 00965 { 00966 #ifdef _DEBUG 00967 AssertValidPos(pos); 00968 #endif 00969 00970 end = GetPrev(pos); 00971 if( pos != NULL ) 00972 start = GetAt(pos); 00973 } 00974 00975 void CPointListPath::GetEdge(POSITION pos, CPoint& start, CPoint& end) const 00976 { 00977 #ifdef _DEBUG 00978 AssertValidPos(pos); 00979 #endif 00980 00981 start = GetNext(pos); 00982 ASSERT( pos != NULL ); 00983 00984 end = GetAt(pos); 00985 } 00986 00987 POSITION CPointListPath::GetHeadEdgePtrs(CPoint*& start, CPoint*& end) 00988 { 00989 if( GetCount() < 2 ) 00990 return NULL; 00991 00992 POSITION pos = GetHeadPosition(); 00993 ASSERT( pos != NULL ); 00994 00995 start = &(GetNext(pos)); 00996 ASSERT( pos != NULL ); 00997 00998 end = &(GetAt(pos)); 00999 01000 return pos; 01001 } 01002 01003 POSITION CPointListPath::GetTailEdgePtrs(CPoint*& start, CPoint*& end) 01004 { 01005 if( GetCount() < 2 ) 01006 return NULL; 01007 01008 POSITION pos = GetTailPosition(); 01009 ASSERT( pos != NULL ); 01010 01011 end = &(GetPrev(pos)); 01012 ASSERT( pos != NULL ); 01013 01014 start = &(GetAt(pos)); 01015 01016 return pos; 01017 } 01018 01019 void CPointListPath::GetNextEdgePtrs(POSITION& pos, CPoint*& start, CPoint*& end) 01020 { 01021 #ifdef _DEBUG 01022 AssertValidPos(pos); 01023 #endif 01024 01025 start = &(GetNext(pos)); 01026 if (pos != NULL) 01027 end = &(GetAt(pos)); 01028 } 01029 01030 void CPointListPath::GetPrevEdgePtrs(POSITION& pos, CPoint*& start, CPoint*& end) 01031 { 01032 #ifdef _DEBUG 01033 AssertValidPos(pos); 01034 #endif 01035 01036 end = &(GetPrev(pos)); 01037 if( pos != NULL ) 01038 start = &(GetAt(pos)); 01039 } 01040 01041 void CPointListPath::GetEdgePtrs(POSITION pos, CPoint*& start, CPoint*& end) 01042 { 01043 #ifdef _DEBUG 01044 AssertValidPos(pos); 01045 #endif 01046 01047 start = &(GetNext(pos)); 01048 ASSERT( pos != NULL ); 01049 01050 end = &(GetAt(pos)); 01051 } 01052 01053 CPoint* CPointListPath::GetStartPoint(POSITION pos) 01054 { 01055 #ifdef _DEBUG 01056 AssertValidPos(pos); 01057 #endif 01058 01059 return &(GetAt(pos)); 01060 } 01061 01062 CPoint* CPointListPath::GetEndPoint(POSITION pos) 01063 { 01064 #ifdef _DEBUG 01065 AssertValidPos(pos); 01066 #endif 01067 01068 GetNext(pos); 01069 ASSERT( pos != NULL ); 01070 01071 return &(GetAt(pos)); 01072 } 01073 01074 CPoint* CPointListPath::GetPointBeforeEdge(POSITION pos) 01075 { 01076 #ifdef _DEBUG 01077 AssertValidPos(pos); 01078 #endif 01079 01080 GetPrev(pos); 01081 if( pos == NULL ) 01082 return NULL; 01083 01084 return &(GetAt(pos)); 01085 } 01086 01087 CPoint* CPointListPath::GetPointAfterEdge(POSITION pos) 01088 { 01089 #ifdef _DEBUG 01090 AssertValidPos(pos); 01091 #endif 01092 01093 GetNext(pos); 01094 ASSERT( pos != NULL ); 01095 01096 GetNext(pos); 01097 if( pos == NULL ) 01098 return NULL; 01099 01100 return &(GetAt(pos)); 01101 } 01102 01103 POSITION CPointListPath::GetEdgePosBeforePoint(POSITION pos) const 01104 { 01105 #ifdef _DEBUG 01106 AssertValidPos(pos); 01107 #endif 01108 01109 GetPrev(pos); 01110 return pos; 01111 } 01112 01113 POSITION CPointListPath::GetEdgePosAfterPoint(POSITION pos) const 01114 { 01115 #ifdef _DEBUG 01116 AssertValidPos(pos); 01117 #endif 01118 01119 POSITION p = pos; 01120 GetNext(p); 01121 if( p == NULL ) 01122 return NULL; 01123 01124 return pos; 01125 } 01126 01127 POSITION CPointListPath::GetEdgePosForStartPoint(const CPoint& startpoint) 01128 { 01129 POSITION pos = GetHeadPosition(); 01130 while( pos != NULL ) 01131 { 01132 if( GetNext(pos) == startpoint ) 01133 { 01134 ASSERT( pos != NULL ); 01135 GetPrev(pos); 01136 break; 01137 } 01138 } 01139 01140 ASSERT( pos != NULL ); 01141 return pos; 01142 } 01143 01144 #ifdef _DEBUG 01145 01146 void CPointListPath::AssertValidPos(POSITION pos) const 01147 { 01148 ASSERT( pos != NULL ); 01149 01150 POSITION p = GetHeadPosition(); 01151 for(;;) 01152 { 01153 ASSERT( p != NULL ); 01154 if( p == pos ) 01155 return; 01156 01157 GetNext(p); 01158 } 01159 } 01160 01161 void CPointListPath::DumpPoints(const CString& msg) const 01162 { 01163 TRACE(msg); 01164 TRACE(_T(", points dump begin:\n")); 01165 POSITION pos = GetHeadPosition(); 01166 int i = 0; 01167 while(pos != NULL) { 01168 CPoint p = GetNext(pos); 01169 TRACE(_T("%ld.: (%ld, %ld)\n"), i, p.x, p.y); 01170 i++; 01171 } 01172 TRACE(_T("points dump end.\n")); 01173 } 01174 01175 #endif