b311480e |
1 | // Created on: 1994-10-07 |
2 | // Created by: Jean Yves LEBEY |
3 | // Copyright (c) 1994-1999 Matra Datavision |
973c2be1 |
4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
5 | // |
973c2be1 |
6 | // This file is part of Open CASCADE Technology software library. |
b311480e |
7 | // |
d5f74e42 |
8 | // This library is free software; you can redistribute it and/or modify it under |
9 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
10 | // by the Free Software Foundation, with special exception defined in the file |
11 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
12 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
13 | // |
973c2be1 |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
7fd59977 |
16 | |
7fd59977 |
17 | |
42cf5bc1 |
18 | #include <Bnd_Box.hxx> |
7fd59977 |
19 | #include <BRep_Tool.hxx> |
42cf5bc1 |
20 | #include <BRepAdaptor_HSurface.hxx> |
21 | #include <BRepAdaptor_Surface.hxx> |
22 | #include <Geom2dAdaptor_Curve.hxx> |
23 | #include <gp_Pnt.hxx> |
24 | #include <gp_Pnt2d.hxx> |
25 | #include <IntRes2d_IntersectionPoint.hxx> |
26 | #include <IntRes2d_IntersectionSegment.hxx> |
7fd59977 |
27 | #include <Precision.hxx> |
42cf5bc1 |
28 | #include <Standard_Failure.hxx> |
29 | #include <TCollection_AsciiString.hxx> |
7fd59977 |
30 | #include <TopExp.hxx> |
31 | #include <TopExp_Explorer.hxx> |
42cf5bc1 |
32 | #include <TopoDS.hxx> |
33 | #include <TopoDS_Shape.hxx> |
7fd59977 |
34 | #include <TopOpeBRep_define.hxx> |
42cf5bc1 |
35 | #include <TopOpeBRep_EdgesIntersector.hxx> |
36 | #include <TopOpeBRep_Point2d.hxx> |
37 | #include <TopOpeBRepDS_Transition.hxx> |
38 | #include <TopOpeBRepTool_ShapeTool.hxx> |
7fd59977 |
39 | |
40 | //======================================================================= |
41 | //function : Segment1 |
42 | //purpose : |
43 | //======================================================================= |
44 | const IntRes2d_IntersectionSegment& TopOpeBRep_EdgesIntersector::Segment1() const |
45 | { |
46 | if ( ! IsPointOfSegment1() ) |
9775fa61 |
47 | throw Standard_Failure("TopOpeBRep_EdgesIntersector : Not a segment point"); |
7fd59977 |
48 | Standard_Integer iseg = 1 + (myPointIndex - myNbPoints - 1) / 2; |
49 | return mylseg.Value(iseg); |
50 | } |
51 | |
52 | //======================================================================= |
53 | //function : IsOpposite1 |
54 | //purpose : |
55 | //======================================================================= |
56 | Standard_Boolean TopOpeBRep_EdgesIntersector::IsOpposite1() const |
57 | { |
58 | Standard_Boolean b = Segment1().IsOpposite(); |
59 | return b; |
60 | } |
61 | |
62 | //======================================================================= |
63 | //function : InitPoint1 |
64 | //purpose : |
65 | //======================================================================= |
66 | void TopOpeBRep_EdgesIntersector::InitPoint1() |
67 | { |
68 | myPointIndex = 1; |
69 | myIsVertexPointIndex = 0; |
70 | myIsVertexIndex = 0; |
71 | myIsVertexValue = Standard_False; |
72 | } |
73 | |
74 | //======================================================================= |
75 | //function : MorePoint1 |
76 | //purpose : |
77 | //======================================================================= |
78 | Standard_Boolean TopOpeBRep_EdgesIntersector::MorePoint1() const |
79 | { |
80 | return myPointIndex <= myTrueNbPoints; |
81 | } |
82 | |
83 | //======================================================================= |
84 | //function : NextPoint1 |
85 | //purpose : |
86 | //======================================================================= |
87 | void TopOpeBRep_EdgesIntersector::NextPoint1() |
88 | { |
89 | myPointIndex++; |
90 | } |
91 | |
92 | //======================================================================= |
93 | //function : Point1 |
94 | //purpose : |
95 | //======================================================================= |
96 | const IntRes2d_IntersectionPoint& TopOpeBRep_EdgesIntersector::Point1() const |
97 | { |
98 | if ( ! IsPointOfSegment1() ) { // point is an intersection point |
99 | return mylpnt.Value(myPointIndex); |
100 | } |
101 | else { // point is a point of segment |
102 | Standard_Integer i = myPointIndex - myNbPoints - 1; |
103 | if (i % 2 == 0) return Segment1().FirstPoint(); |
104 | else return Segment1().LastPoint(); |
105 | } |
106 | } |
107 | |
108 | //======================================================================= |
109 | //function : Status1 |
110 | //purpose : |
111 | //======================================================================= |
112 | TopOpeBRep_P2Dstatus TopOpeBRep_EdgesIntersector::Status1() const |
113 | { |
114 | if ( ! IsPointOfSegment1() ) { // point is an intersection point |
115 | return TopOpeBRep_P2DINT; |
116 | } |
117 | else { // point is a point of segment |
118 | Standard_Integer i = myPointIndex - myNbPoints - 1; |
119 | if (i % 2 == 0) return TopOpeBRep_P2DSGF; |
120 | else return TopOpeBRep_P2DSGL; |
121 | } |
122 | } |
123 | |
124 | //======================================================================= |
125 | //function : IsPointOfSegment1 |
126 | //purpose : |
127 | //======================================================================= |
128 | Standard_Boolean TopOpeBRep_EdgesIntersector::IsPointOfSegment1() const |
129 | { |
130 | Standard_Boolean b = (myPointIndex > myNbPoints); |
131 | return b; |
132 | } |
133 | |
134 | //======================================================================= |
135 | //function : Index1 |
136 | //purpose : |
137 | //======================================================================= |
138 | Standard_Integer TopOpeBRep_EdgesIntersector::Index1() const |
139 | { |
140 | return myPointIndex; |
141 | } |
142 | |
143 | //======================================================================= |
144 | //function : EdgesConfig1 |
145 | //purpose : |
146 | //======================================================================= |
147 | TopOpeBRepDS_Config TopOpeBRep_EdgesIntersector::EdgesConfig1() const |
148 | { |
149 | TopOpeBRepDS_Config c = TopOpeBRepDS_UNSHGEOMETRY; |
150 | Standard_Boolean ps = IsPointOfSegment1(); |
151 | if ( ps ) { |
152 | Standard_Boolean so; |
153 | so = TopOpeBRepTool_ShapeTool::EdgesSameOriented(myEdge2,myEdge1); |
154 | c = (so) ? TopOpeBRepDS_SAMEORIENTED : TopOpeBRepDS_DIFFORIENTED; |
155 | } |
156 | return c; |
157 | } |
158 | |
159 | //======================================================================= |
160 | //function : Transition1 |
161 | //purpose : |
162 | //======================================================================= |
163 | TopOpeBRepDS_Transition TopOpeBRep_EdgesIntersector::Transition1(const Standard_Integer Index,const TopAbs_Orientation EdgeOrientation) const |
164 | { |
165 | Standard_Boolean pointofsegment = IsPointOfSegment1(); |
166 | Standard_Boolean pur1d = (pointofsegment && mySameDomain); |
167 | |
7fd59977 |
168 | TopAbs_State staB=TopAbs_UNKNOWN,staA=TopAbs_UNKNOWN; |
169 | TopAbs_ShapeEnum shaB=TopAbs_COMPOUND,shaA=TopAbs_COMPOUND; Standard_Boolean pextremity; |
7fd59977 |
170 | |
171 | TopAbs_State staINON = TopAbs_IN; |
172 | Standard_Integer dim = myDimension; |
173 | if (dim == 1) { shaA = shaB = TopAbs_EDGE; } |
174 | else if (dim == 2 && pur1d) { shaA = shaB = TopAbs_EDGE; } |
175 | else if (dim == 2 && !pur1d) { shaA = shaB = TopAbs_FACE; } |
176 | |
177 | if ( (EdgeOrientation == TopAbs_INTERNAL) || |
178 | (EdgeOrientation == TopAbs_EXTERNAL) ) { |
179 | TopOpeBRepDS_Transition TR(staINON,staINON,shaB,shaA); |
180 | TR.Set(EdgeOrientation); |
181 | return TR; |
182 | } |
183 | |
184 | pextremity = Standard_False; // JYL290998 corr regr cto100K1 fex6 fex4 : 5eme inters E/E |
185 | |
186 | const IntRes2d_IntersectionPoint& IP = Point1(); |
187 | const IntRes2d_Transition& T = (Index == 1) ? |
188 | IP.TransitionOfFirst() : IP.TransitionOfSecond(); |
189 | |
190 | switch (T.TransitionType()) { |
191 | |
192 | case IntRes2d_In : |
193 | staB = TopAbs_OUT; |
194 | staA = staINON; |
195 | break; |
196 | |
197 | case IntRes2d_Out : |
198 | staB = staINON; |
199 | staA = TopAbs_OUT; |
200 | break; |
201 | |
202 | case IntRes2d_Touch : |
203 | switch (T.Situation()) { |
204 | |
205 | case IntRes2d_Inside : |
206 | staB = staINON; |
207 | staA = staINON; |
208 | break; |
209 | |
210 | case IntRes2d_Outside : |
211 | staB = TopAbs_OUT; |
212 | staA = TopAbs_OUT; |
213 | break; |
214 | |
215 | case IntRes2d_Unknown : { |
216 | |
217 | // get posindex = position on of point on edge <Index> |
218 | IntRes2d_Position posindex = |
219 | (Index == 1) ? |
220 | IP.TransitionOfFirst().PositionOnCurve() : |
221 | IP.TransitionOfSecond().PositionOnCurve(); |
222 | |
223 | if (pointofsegment) { |
224 | |
225 | // get posother = position of point on the other edge |
226 | IntRes2d_Position posother = |
227 | (Index == 1) ? |
228 | IP.TransitionOfSecond().PositionOnCurve() : |
229 | IP.TransitionOfFirst().PositionOnCurve(); |
230 | |
231 | if (posother == IntRes2d_Middle) { |
232 | if (posindex != IntRes2d_Middle) { |
233 | staB = staINON; |
234 | staA = staINON; |
235 | } |
236 | else // Middle/Middle is impossible |
9775fa61 |
237 | throw Standard_Failure("TopOpeBRep_EdgesIntersector : Situation Unknown MM"); |
7fd59977 |
238 | } |
239 | else { // posother = Head or End |
240 | Standard_Boolean opposite = IsOpposite1(); |
241 | if (opposite) { |
242 | if (posother == IntRes2d_Head) { |
243 | staB = staINON; |
244 | staA = TopAbs_OUT; |
245 | } |
246 | else if (posother == IntRes2d_End) { |
247 | staB = TopAbs_OUT; |
248 | staA = staINON; |
249 | } |
250 | } |
251 | else { |
252 | if (posother == IntRes2d_Head) { |
253 | staB = TopAbs_OUT; |
254 | staA = staINON; |
255 | } |
256 | else if (posother == IntRes2d_End) { |
257 | staB = staINON; |
258 | staA = TopAbs_OUT; |
259 | } |
260 | } |
261 | } |
262 | } // point is a segment point |
263 | |
264 | else { // point is not a segment point |
265 | // two edges intersect on a vertex |
266 | // the vertex is shared by the two edges |
267 | // the edges are tangent on vertex. |
268 | pextremity = Standard_True; |
269 | shaA = shaB = TopAbs_EDGE; |
270 | |
271 | if ( posindex == IntRes2d_Head ) { |
272 | staB = staINON; |
273 | staA = TopAbs_OUT; |
274 | } |
275 | else if (posindex == IntRes2d_End) { |
276 | staB = TopAbs_OUT; |
277 | staA = staINON; |
278 | } |
279 | else { // Middle is impossible |
9775fa61 |
280 | throw Standard_Failure("TopOpeBRep_EdgesIntersector : Situation Unknown M"); |
7fd59977 |
281 | } |
282 | } // point is not a segment point |
283 | |
284 | } // T.Situation == IntRes2d_Unknown |
285 | break; |
286 | |
287 | } // switch T.Situation() |
288 | break; |
289 | |
290 | case IntRes2d_Undecided : |
9775fa61 |
291 | throw Standard_Failure("TopOpeBRep_EdgesIntersector : TransitionType Undecided"); |
7fd59977 |
292 | break; |
293 | |
294 | } // switch TransitionType() |
295 | |
296 | TopOpeBRepDS_Transition TR; |
297 | if (pur1d || pextremity) { |
298 | TR.Set(staB,staA,shaB,shaA); |
299 | } |
300 | else { // +ooOO |
301 | Standard_Boolean composori = Standard_False; |
302 | composori = composori || ((Index == 1) && (!myf2surf1F_sameoriented)); |
303 | composori = composori || ((Index == 2) && (!myf1surf1F_sameoriented)); |
304 | // Index = 1 <==> on demande la transition sur |
305 | // une arete de la 1ere face par rapport a une arete orientee de |
306 | // la 2eme face. |
307 | // EdgeOrientation est l'orientation d'une arete de la 2eme face |
308 | // de l'appel SetFaces(), i.e ume arete de la face dont la surface |
309 | // n'est PAS la surface de reference de l'intersecteur 2d. |
310 | // Cette orientation d'arete dans la face doit etre composee avec |
311 | // l'orientation relative de la topologie de la 2eme face par rapport |
312 | // a la topologie de la 1ere face orientee FORWARD (car la |
313 | // geometrie naturelle de la 1ere face est la reference). |
314 | TopAbs_Orientation eori = EdgeOrientation; |
315 | if (composori) { |
316 | eori = TopAbs::Reverse(eori); |
317 | } |
318 | |
319 | // retournement des etats en fonction de l'orientation de l'arete |
320 | // croisee dans l'espace geometrique de reference. |
321 | TR.Set(staB,staA,shaB,shaA); |
322 | if (eori == TopAbs_REVERSED) { |
323 | TR = TR.Complement(); |
324 | } |
325 | } |
326 | return TR; |
327 | } |
328 | |
329 | //======================================================================= |
330 | //function : Parameter1 |
331 | //purpose : |
332 | //======================================================================= |
333 | Standard_Real TopOpeBRep_EdgesIntersector::Parameter1(const Standard_Integer Index) const |
334 | { |
335 | if (Index == 1) return Point1().ParamOnFirst(); |
336 | else return Point1().ParamOnSecond(); |
337 | } |
338 | |
339 | //======================================================================= |
340 | //function : IsVertex1 |
341 | //purpose : |
342 | //======================================================================= |
343 | Standard_Boolean TopOpeBRep_EdgesIntersector::IsVertex1(const Standard_Integer Index) |
344 | { |
345 | // check if last IsVertex1() call has been performed |
346 | // on current point and with same <Index>. |
347 | if ( myIsVertexPointIndex == myPointIndex && |
348 | myIsVertexIndex == Index ) |
349 | return myIsVertexValue; |
350 | |
351 | // search if current point is a vertex of edge <Index> |
352 | myIsVertexValue = Standard_False; |
353 | IntRes2d_Position pos; |
354 | if (Index == 1) pos = Point1().TransitionOfFirst().PositionOnCurve(); |
355 | else pos = Point1().TransitionOfSecond().PositionOnCurve(); |
356 | |
357 | if ( pos == IntRes2d_Middle ) { |
358 | // search for an INTERNAL vertex on edge <Index> with |
359 | // a 2d parameter <parV> equal to current point parameter <par> |
360 | Standard_Real par = Parameter1(Index); |
361 | const TopoDS_Edge *pE = NULL; |
362 | pE = (Index == 1) ? &myEdge1 : &myEdge2; |
363 | const TopoDS_Edge& E = *pE; |
364 | TopExp_Explorer ex; |
365 | for (ex.Init(E,TopAbs_VERTEX); ex.More(); ex.Next()) { |
366 | // for (TopExp_Explorer ex(E,TopAbs_VERTEX); ex.More(); ex.Next()) { |
367 | const TopoDS_Vertex& V = TopoDS::Vertex(ex.Current()); |
368 | if ( V.Orientation() == TopAbs_INTERNAL) { |
369 | Standard_Real parV = BRep_Tool::Parameter(V,E,myFace1); |
370 | if (Abs(par-parV) <= Precision::PConfusion()) { |
371 | myIsVertexValue = Standard_True; |
372 | myIsVertexVertex = V; |
373 | break; |
374 | } |
375 | } |
376 | } |
377 | } |
378 | else { // pos = head or end |
379 | TopoDS_Vertex V1,V2; |
380 | if (Index == 1) TopExp::Vertices(myEdge1,V1,V2); |
381 | else TopExp::Vertices(myEdge2,V1,V2); |
382 | if ( pos == IntRes2d_Head && !V1.IsNull()) { |
383 | myIsVertexValue = Standard_True; |
384 | myIsVertexVertex = V1; |
385 | } |
386 | else if ( pos == IntRes2d_End && !V2.IsNull()) { |
387 | myIsVertexValue = Standard_True; |
388 | myIsVertexVertex = V2; |
389 | } |
390 | // ... else myIsVertexValue has been set to False |
391 | } |
392 | |
393 | // memorize that IsVertex1() has been called : |
394 | // - on point myPointIndex |
395 | // - on edge <Index> |
396 | myIsVertexPointIndex = myPointIndex; |
397 | myIsVertexIndex = Index; |
398 | |
399 | return myIsVertexValue; |
400 | } |
401 | |
402 | |
403 | //======================================================================= |
404 | //function : Vertex1 |
405 | //purpose : |
406 | //======================================================================= |
407 | const TopoDS_Shape& TopOpeBRep_EdgesIntersector::Vertex1(const Standard_Integer Index) |
408 | { |
409 | if ( ! IsVertex1(Index) ) |
9775fa61 |
410 | throw Standard_Failure("TopOpeBRep_EdgesIntersector : Vertex1"); |
7fd59977 |
411 | return myIsVertexVertex; |
412 | } |
413 | |
414 | //======================================================================= |
415 | //function : Value1 |
416 | //purpose : |
417 | //======================================================================= |
418 | gp_Pnt TopOpeBRep_EdgesIntersector::Value1() const |
419 | { |
420 | gp_Pnt2d p2 = Point1().Value(); |
421 | gp_Pnt p; |
422 | if (Precision::IsInfinite(p2.X()) || Precision::IsInfinite(p2.Y())) { |
423 | Standard_Real inf = Precision::Infinite(); |
424 | p.SetCoord (inf, inf, inf); |
425 | } |
426 | else |
427 | mySurface1->Surface().D0(p2.X(),p2.Y(), p); |
428 | return p; |
429 | } |