]> SALOME platform Git repositories - modules/yacs.git/blob - src/lineconn2d/LineConn2d_Object.cxx
Salome HOME
copy tag mergefrom_BR_V0_1_CC_Salome_04oct07
[modules/yacs.git] / src / lineconn2d / LineConn2d_Object.cxx
1 // File:      LineConn2d_Object.cpp
2 // Created:   03.08.05 21:28:05
3 // Author:    Alexander GRIGORIEV
4 // Copyright: Open Cascade 2005
5
6
7 #include <LineConn2dAfx.h>
8
9 #include <LineConn2d_Object.h>
10 #include <LineConn2d.h>
11 #include <Precision.hxx>
12
13 //=======================================================================
14 //function : Update
15 //purpose  : 
16 //=======================================================================
17
18 void LineConn2d_Object::Update ()
19 {
20   // Create the bounding box of the polyline
21   if (myIsModified) {
22     myBox.Clear();
23     PointIterator anIter (myPoints);
24     for (; anIter.More(); anIter.Next()) {
25       myBox.Add (anIter.Value());
26     }
27     myIsModified = 0;
28   }
29 }
30
31 //=======================================================================
32 //function : IsOut
33 //purpose  : 
34 //=======================================================================
35
36 Standard_Boolean LineConn2d_Object::IsOut (const gp_XY&         thePoint,
37                                            const Standard_Real  theTol) const
38 {
39   const Standard_Real aConfusion   = Precision::Confusion();
40   const Standard_Real aUniConf     = 1. + aConfusion;
41   const Standard_Real aSqConfusion = aConfusion * aConfusion;
42   Standard_Real anYprev (1e+100);
43   const gp_XY * aPnt[2] = { 0L, 0L };
44
45   Standard_Integer aNIntersect (0);
46   PointIterator anIter (myPoints);
47   if (anIter.More()) {
48     aPnt[1] = &myPoints.Last();
49     for (; anIter.More(); anIter.Next()) {
50       aPnt[0] = aPnt[1];
51       aPnt[1] = &anIter.Value();
52       const gp_XY& aPntLow = * (aPnt[0]->X() < aPnt[1]->X() ? aPnt[0]: aPnt[1]);
53       const gp_XY& aPntUp  = * (aPnt[0]->X() < aPnt[1]->X() ? aPnt[1]: aPnt[0]);
54       const gp_XY aVec (aPntUp -  aPntLow);
55
56       // Check the distance (condition ON)
57       Standard_Real aDist (-1.);
58       const Standard_Real aSegLen = aVec.Modulus();
59       if (aSegLen < aConfusion)
60         // Degenerated case
61         aDist = (thePoint - (aPntLow + aPntUp) * 0.5).Modulus();
62       else {
63         // General case
64         const gp_XY aVecN = aVec / aSegLen;
65
66         // Obtain the coordinate of the projection on the segment 
67         const gp_XY aVecP = thePoint - aPntLow;
68         const Standard_Real aCoord = aVecN * aVecP;
69
70         // Check if it projects before the 1st point => distance to 1st point
71         if (aCoord < aConfusion)
72           aDist = aVecP.Modulus();
73         // Check if it projects before the 2nd point => distance to 2nd point
74         else if (aCoord > aSegLen - aConfusion)
75           aDist = (thePoint - aPntUp).Modulus();
76         // Otherwise retrieve the projection point inside the segment
77         else
78           aDist = LineConn2d_FABS (aVecN ^ aVecP);
79       }
80       if (aDist < theTol)
81         // ON detected, we stop the analysis
82         return Standard_False;
83
84       // Rejection test
85       if (thePoint.X() > aPntUp.X() + aConfusion || thePoint.X() < aPntLow.X())
86           continue;
87
88       // Treatment of a vertical contour segment
89       if (aVec.X() <  gp::Resolution() &&
90           aVec.X() > -gp::Resolution())
91       {
92         if (LineConn2d::IsSmall (anYprev - aPntLow.Y()))
93           anYprev = aPntUp.Y();
94         else if (LineConn2d::IsSmall (anYprev - aPntUp.Y()))
95           anYprev = aPntLow.Y();
96         continue;
97       }
98
99       // Evaluate the intersection
100       const Standard_Real anAlpha = (thePoint.X() - aPntLow.X()) / aVec.X();
101       if (anAlpha < aUniConf) {
102         const Standard_Real anYint = aPntLow.Y() + anAlpha * aVec.Y();
103         if (anYint > thePoint.Y()) {
104           const Standard_Real aD2 = anYint - anYprev;
105           if (aD2 * aD2 > aSqConfusion) {
106             ++aNIntersect;
107             anYprev = anYint;
108           }
109         }
110       }
111     }
112   }
113   return ((aNIntersect & 0x01) == 0);
114 }