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