0031172: Unexpected result of BRepTools::OuterWire()
[occt.git] / src / TopClass / TopClass_Classifier2d.gxx
CommitLineData
b311480e 1// Created on: 1992-11-17
2// Created by: Laurent BUCHARD
3// Copyright (c) 1992-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
17// Modified: Mon May 13 15:20:43 1996
7fd59977 18//-- Reinitialisation des transitions complexes
19
20// Modified by skv - Wed Jul 12 15:20:58 2006 OCC12627
21
22
23#include <IntRes2d_IntersectionSegment.hxx>
24#include <IntRes2d_IntersectionPoint.hxx>
25#include <gp_Vec2d.hxx>
26
27//=======================================================================
28//function : TopClass_Classifier2d
29//purpose :
30//=======================================================================
31
32TopClass_Classifier2d::TopClass_Classifier2d() :
33 myIsSet(Standard_False),
34 myFirstCompare(Standard_True),
d533dafb 35 myFirstTrans(Standard_True),
36 myParam(0.0),
37 myTolerance(0.0),
38 myClosest(0),
eafb234b 39 myState(TopAbs_UNKNOWN), // skv OCC12627
40 myIsHeadOrEnd(Standard_False) // skv OCC12627
7fd59977 41{
42}
43
44//=======================================================================
45//function : Reset
46//purpose :
47//=======================================================================
48
49void TopClass_Classifier2d::Reset(const gp_Lin2d& L,
50 const Standard_Real P,
51 const Standard_Real Tol)
52{
53 myLin = L;
54 myParam = P;
55 myTolerance = Tol;
56 myState = TopAbs_UNKNOWN;
57 myFirstCompare = Standard_True;
58 myFirstTrans = Standard_True;
59 myClosest = 0;
60 myIsSet = Standard_True;
61// Modified by skv - Wed Jul 12 15:20:58 2006 OCC12627 Begin
62 myIsHeadOrEnd = Standard_False;
63// Modified by skv - Wed Jul 12 15:20:58 2006 OCC12627 End
64}
65
66//=======================================================================
67//function : Compare
68//purpose :
69//=======================================================================
70
71void TopClass_Classifier2d::Compare(const TheEdge& E,
72 const TopAbs_Orientation Or)
73{
74 // intersect the edge and the segment
75 myClosest = 0;
76 myIntersector.Perform(myLin,myParam,myTolerance,E);
77 if (!myIntersector.IsDone()) return;
78 if ((myIntersector.NbPoints() == 0)&&
79 (myIntersector.NbSegments() == 0)) return;
80
81 // find the closest point
82 Standard_Integer iPoint, iSegment, nbPoints, nbSegments;
1d47d8d0 83
7fd59977 84 const IntRes2d_IntersectionPoint *PClosest = NULL;
1d47d8d0 85
7fd59977 86 Standard_Real dMin = RealLast();
87 nbPoints = myIntersector.NbPoints();
88 for (iPoint = 1; iPoint <= nbPoints; iPoint++) {
89 const IntRes2d_IntersectionPoint& PInter = myIntersector.Point(iPoint);
90 // test for ON
91 if (PInter.TransitionOfFirst().PositionOnCurve() == IntRes2d_Head) {
92 myClosest = iPoint;
93 myState = TopAbs_ON;
94 return;
95 }
96 Standard_Real paramfirst = PInter.ParamOnFirst();
97 if (paramfirst < dMin) {
98 myClosest = iPoint;
99 PClosest = &PInter;
100 dMin = paramfirst;
101 }
102 }
103
104 // for the segments we only test the first point
105 nbSegments = myIntersector.NbSegments();
106 for (iSegment = 1; iSegment <= nbSegments; iSegment++) {
107 const IntRes2d_IntersectionSegment& SegInter =
108 myIntersector.Segment(iSegment);
109 const IntRes2d_IntersectionPoint& PInter = SegInter.FirstPoint();
110 if (PInter.TransitionOfFirst().PositionOnCurve() == IntRes2d_Head) {
111 myClosest = nbPoints + iSegment+ iSegment - 1;
112 myState = TopAbs_ON;
113 return;
114 }
115 Standard_Real paramfirst = PInter.ParamOnFirst();
116 if (paramfirst < dMin) {
117 myClosest = nbPoints + iSegment+iSegment - 1;
118 PClosest = &PInter;
119 dMin = paramfirst;
120 }
121 }
122
123 // if no point was found return
124 if (myClosest == 0) return;
125
126 // if the Edge is INTERNAL or EXTERNAL, no problem
127 if (Or == TopAbs_INTERNAL) {
128 myState = TopAbs_IN;
129 return;
130 }
131 else if (Or == TopAbs_EXTERNAL) {
132 myState = TopAbs_OUT;
133 return;
134 }
135
136
137 if ( ! myFirstCompare ) {
138 Standard_Boolean b = (dMin > myParam);
139 if (b) {
140 // dMin > myParam : le point le plus proche (dMin) trouve dans CETTE
141 // intersection ligne,arete n'est pas le plus proche
142 // de TOUS les points d'intersection avec les autres aretes (myParam).
143 return;
144 }
145 }
146
147 // process the closest point PClosest, found at dMin on line.
148 myFirstCompare = Standard_False;
149
150 if(myParam > dMin) { //-- lbr le 13 mai 96
151 myFirstTrans = Standard_True;
152 }
153
154 myParam = dMin;
155 const IntRes2d_Transition& T2 = PClosest->TransitionOfSecond();
156// Modified by skv - Wed Jul 12 15:20:58 2006 OCC12627 Begin
157// Standard_Boolean isHeadorEnd = (T2.PositionOnCurve() == IntRes2d_Head) ||
158// (T2.PositionOnCurve() == IntRes2d_End);
159 myIsHeadOrEnd = (T2.PositionOnCurve() == IntRes2d_Head) ||
160 (T2.PositionOnCurve() == IntRes2d_End);
161// Modified by skv - Wed Jul 12 15:20:58 2006 OCC12627 End
162
163 // transition on the segment
1d47d8d0 164
7fd59977 165 TopAbs_Orientation SegTrans = TopAbs_FORWARD;
1d47d8d0 166
7fd59977 167 const IntRes2d_Transition& T1 = PClosest->TransitionOfFirst();
168 switch (T1.TransitionType()) {
169 case IntRes2d_In :
170 if (Or == TopAbs_REVERSED) SegTrans = TopAbs_REVERSED;
171 else SegTrans = TopAbs_FORWARD;
172 break;
173 case IntRes2d_Out :
174 if (Or == TopAbs_REVERSED) SegTrans = TopAbs_FORWARD;
175 else SegTrans = TopAbs_REVERSED;
176 break;
177 case IntRes2d_Touch :
178 switch (T1.Situation()) {
179 case IntRes2d_Inside :
180 if (Or == TopAbs_REVERSED) SegTrans = TopAbs_EXTERNAL;
181 else SegTrans = TopAbs_INTERNAL;
182 break;
183 case IntRes2d_Outside :
184 if (Or == TopAbs_REVERSED) SegTrans = TopAbs_INTERNAL;
185 else SegTrans = TopAbs_EXTERNAL;
186 break;
187 case IntRes2d_Unknown : return;
188 }
189 break;
190 case IntRes2d_Undecided : return;
191 }
192
193 // are we inside the Edge ?
194 // const IntRes2d_Transition& T2 = PClosest->TransitionOfSecond();
195 if ( ! myIsHeadOrEnd ) {
196 // PClosest is inside the edge
197 switch (SegTrans) {
198
199 case TopAbs_FORWARD :
200 case TopAbs_EXTERNAL :
201 myState = TopAbs_OUT;
202 break;
203
204 case TopAbs_REVERSED :
205 case TopAbs_INTERNAL :
206 myState = TopAbs_IN;
207 break;
208 }
209 }
210 else {
211 // PClosest is Head or End of the edge : update the complex transition
212 gp_Dir2d Tang2d,Norm2d;
213 Standard_Real Curv;
214 myIntersector.LocalGeometry
215 (E,PClosest->ParamOnSecond(),Tang2d,Norm2d,Curv);
216 gp_Dir Tang(Tang2d.X(),Tang2d.Y(),0.);
217 gp_Dir Norm(Norm2d.X(),Norm2d.Y(),0.);
218 if (myFirstTrans) {
219 gp_Dir D(myLin.Direction().X(),myLin.Direction().Y(),0.);
220 myTrans.Reset(D);
221 myFirstTrans = Standard_False;
222 }
223
224 TopAbs_Orientation Ort;
225 if (T2.PositionOnCurve() == IntRes2d_Head) Ort = TopAbs_FORWARD;
226 else Ort = TopAbs_REVERSED;
227 myTrans.Compare(RealEpsilon(), Tang, Norm, Curv, SegTrans, Ort);
228 myState = myTrans.StateBefore();
229 }
230}