Salome HOME
merge from branch DEV tag mergeto_trunk_04apr08
[modules/yacs.git] / src / lineconn2d / LineConn2d_Box.cxx
1 // File:      LineConn2d_Box.cpp
2 // Created:   03.08.05 20:20:53
3 // Author:    Alexander GRIGORIEV
4 // Copyright: Open Cascade 2005
5
6
7 #include <LineConn2dAfx.h>
8
9 #include <LineConn2d_Box.h>
10 #include <LineConn2d_SegmentIterator.h>
11 #include <LineConn2d_Object.h>
12 #include <LineConn2d.h>
13
14 inline Standard_Boolean compareDist (const gp_XY& aHSize, const gp_XY& aDist)
15 {
16   return (LineConn2d_FABS(aDist.X()) > aHSize.X() ||
17           LineConn2d_FABS(aDist.Y()) > aHSize.Y());
18 }
19
20 //=======================================================================
21 //function : Enlarge
22 //purpose  : 
23 //=======================================================================
24
25 void LineConn2d_Box::Enlarge (const Standard_Real aDiff)
26 {
27   const Standard_Real aD = LineConn2d_FABS(aDiff);
28   myHSize = myHSize + gp_XY (aD, aD);
29 }
30
31 //=======================================================================
32 //function : Limit
33 //purpose  : limit the current box with the internals of theBox
34 //=======================================================================
35
36 void LineConn2d_Box::Limit (const LineConn2d_Box& theBox)
37 {
38   const gp_XY diffC = theBox.Center() - myCenter;
39   // check the condition IsOut
40   if (::compareDist (myHSize + theBox.HSize(), diffC) == Standard_False) {
41     const gp_XY diffH = theBox.HSize() - myHSize;
42     if (diffC.X() - diffH.X() > 0.) {
43       const Standard_Real aShift = 0.5 * (diffC.X() - diffH.X()); // positive
44       myCenter.SetX (myCenter.X() + aShift);
45       myHSize .SetX (myHSize.X()  - aShift);
46     } else if (diffC.X() + diffH.X() < 0.) {
47       const Standard_Real aShift = 0.5 * (diffC.X() + diffH.X()); // negative
48       myCenter.SetX (myCenter.X() + aShift);
49       myHSize .SetX (myHSize.X()  + aShift);
50     }
51     if (diffC.Y() - diffH.Y() > 0.) {
52       const Standard_Real aShift = 0.5 * (diffC.Y() - diffH.Y()); // positive
53       myCenter.SetY (myCenter.Y() + aShift);
54       myHSize .SetY (myHSize.Y()  - aShift);
55     } else if (diffC.Y() + diffH.Y() < 0.) {
56       const Standard_Real aShift = 0.5 * (diffC.Y() + diffH.Y()); // negative
57       myCenter.SetY (myCenter.Y() + aShift);
58       myHSize .SetY (myHSize.Y()  + aShift);
59     }
60   }
61 }
62
63 //=======================================================================
64 //function : Add
65 //purpose  : Update the box by a point
66 //=======================================================================
67
68 void LineConn2d_Box::Add (const gp_XY& thePnt) {
69   if (myHSize.X() < -1e-5) {
70     myCenter = thePnt;
71     myHSize.SetCoord (0., 0.);
72   } else {
73     const gp_XY aDiff = thePnt - myCenter;
74     if (aDiff.X() > myHSize.X()) {
75       const Standard_Real aShift = (aDiff.X() - myHSize.X()) * 0.5;
76       myCenter.SetX (myCenter.X() + aShift);
77       myHSize.SetX  (myHSize.X()  + aShift);
78     } else if (aDiff.X() < -myHSize.X()) {
79       const Standard_Real aShift = (aDiff.X() + myHSize.X()) * 0.5;
80       myCenter.SetX (myCenter.X() + aShift);
81       myHSize.SetX  (myHSize.X()  - aShift);
82     }
83     if (aDiff.Y() > myHSize.Y()) {
84       const Standard_Real aShift = (aDiff.Y() - myHSize.Y()) * 0.5;
85       myCenter.SetY (myCenter.Y() + aShift);
86       myHSize.SetY  (myHSize.Y()  + aShift);
87     } else if (aDiff.Y() < -myHSize.Y()) {
88       const Standard_Real aShift = (aDiff.Y() + myHSize.Y()) * 0.5;
89       myCenter.SetY (myCenter.Y() + aShift);
90       myHSize.SetY  (myHSize.Y()  - aShift);
91     }
92   }
93 }
94
95 //=======================================================================
96 //function : IsOut
97 //purpose  : Intersection Box - Point
98 //=======================================================================
99
100 Standard_Boolean LineConn2d_Box::IsOut (const gp_XY& thePnt) const
101 {
102   return ::compareDist (myHSize, thePnt - myCenter);
103 }
104
105 //=======================================================================
106 //function : IsOut
107 //purpose  : Intersection Box - Box
108 //=======================================================================
109
110 Standard_Boolean LineConn2d_Box::IsOut (const LineConn2d_Box& theBox) const
111 {
112   return ::compareDist (myHSize + theBox.HSize(), theBox.Center() - myCenter);
113 }
114
115 //=======================================================================
116 //function : IsOut
117 //purpose  : Intersection Box - Object
118 //=======================================================================
119
120 Standard_Boolean LineConn2d_Box::IsOut (const LineConn2d_Object& theObj) const
121 {
122   Standard_Boolean aResult (Standard_True);
123   LineConn2d_SegmentIterator anIter (theObj);
124   for (; anIter.More(); anIter.Next())
125     if (IsOut (anIter.Value()) == Standard_False) {
126       aResult = Standard_False;
127       break;
128     }
129   return aResult;
130 }
131
132 //=======================================================================
133 //function : IsOut
134 //purpose  : Intersection Box - Segment
135 //=======================================================================
136
137 Standard_Boolean LineConn2d_Box::IsOut (const LineConn2d_Segment& theSeg) const
138 {
139   Standard_Boolean aResult (Standard_True);
140   // Intersect the line containing the segment.
141   const Standard_Real aProd[3] = {
142     theSeg.Delta() ^ (myCenter - theSeg.Origin()),
143     theSeg.Delta().X() * myHSize.Y(),
144     theSeg.Delta().Y() * myHSize.X()
145   };
146   if (LineConn2d_FABS(aProd[0]) < (LineConn2d_FABS(aProd[1]) +
147                                    LineConn2d_FABS(aProd[2])))
148   {
149     // Intersection with line detected; check the segment as bounding box
150     const gp_XY aHSeg    (0.5 * theSeg.Delta().X(),
151                           0.5 * theSeg.Delta().Y());
152     const gp_XY aHSegAbs (LineConn2d_FABS(aHSeg.X()),
153                           LineConn2d_FABS(aHSeg.Y()));
154     aResult = ::compareDist (myHSize + aHSegAbs,
155                              theSeg.Origin() + aHSeg - myCenter);
156   }
157   return aResult;
158 }
159
160 //=======================================================================
161 //function : Intersect
162 //purpose  : 
163 //=======================================================================
164
165 Standard_Integer LineConn2d_Box::Intersect
166                                 (Standard_Real             outInter[2],
167                                  const LineConn2d_Segment& theSeg) const
168 {
169   Standard_Integer nInter (0);
170   Standard_Real    anAlpha[2];
171   // Four sides of the box rectangle
172   const gp_XY aSegDelta[4] = {
173     gp_XY (-2 * myHSize.X(), 0.),
174     gp_XY (0., -2 * myHSize.Y()),
175     gp_XY (2 * myHSize.X(), 0.),
176     gp_XY (0., 2 * myHSize.Y())
177   };
178   LineConn2d_Segment aSeg (gp_XY(0., 0.), myCenter + myHSize);
179
180   // Intersect aSeg with all four sides of the box
181   for (Standard_Integer i = 0; i < 4; i++) {
182     aSeg.SetOrigin (aSeg.Extremity());
183     aSeg.SetDelta  (aSegDelta[i]);
184     if (theSeg.IsIntersect (aSeg, anAlpha)) {
185       outInter[nInter] = anAlpha[0];
186       if (nInter++ > 0) {
187         // Check to exclude coincident intersection points
188         if (LineConn2d::IsSmall (outInter[0] - outInter[1]))
189           --nInter;
190         else {
191           if (outInter[0] > outInter[1]) {
192             const Standard_Real aTmp = outInter[0];
193             outInter[0] = outInter[1];
194             outInter[1] = aTmp;
195           }
196           break;
197         }
198       }
199     }
200   }
201   return nInter;
202 }