Commit | Line | Data |
---|---|---|
7fd59977 | 1 | // File: BRepClass3d_SClassifier.cxx |
2 | // Created: Mon Jul 15 17:26:21 1996 | |
3 | // Author: Laurent BUCHARD | |
4 | // <lbr@cracbox.paris1.matra-dtv.fr> | |
5 | ||
6 | ||
7 | // Modified by skv - Thu Sep 4 11:22:05 2003 OCC578 | |
8 | ||
9 | #include <BRepClass3d_SClassifier.ixx> | |
10 | ||
11 | #include <gp_Pnt.hxx> | |
12 | #include <gp_Lin.hxx> | |
13 | #include <gp_Vec.hxx> | |
14 | #include <BRepClass3d_Intersector3d.hxx> | |
15 | #include <TopoDS.hxx> | |
16 | ||
17 | #include <IntCurvesFace_Intersector.hxx> | |
18 | // modified by NIZHNY-MKK Mon Jun 21 15:13:40 2004 | |
19 | #include <Precision.hxx> | |
20 | #include <ElCLib.hxx> | |
bd05fabf S |
21 | #include <Geom_Surface.hxx> |
22 | #include <BRep_Tool.hxx> | |
7fd59977 | 23 | |
bd05fabf S |
24 | static |
25 | void FaceNormal (const TopoDS_Face& aF, | |
26 | const Standard_Real U, | |
27 | const Standard_Real V, | |
28 | gp_Dir& aDN); | |
7fd59977 | 29 | |
bd05fabf S |
30 | static |
31 | Standard_Real GetAddToParam(const gp_Lin& L,const Standard_Real P,const Bnd_Box& B); | |
7fd59977 | 32 | |
33 | ||
bd05fabf S |
34 | |
35 | //======================================================================= | |
36 | //function : BRepClass3d_SClassifier | |
37 | //purpose : | |
38 | //======================================================================= | |
7fd59977 | 39 | BRepClass3d_SClassifier::BRepClass3d_SClassifier() |
40 | { | |
41 | } | |
42 | ||
43 | ||
bd05fabf S |
44 | //======================================================================= |
45 | //function : BRepClass3d_SClassifier | |
46 | //purpose : | |
47 | //======================================================================= | |
7fd59977 | 48 | BRepClass3d_SClassifier::BRepClass3d_SClassifier(BRepClass3d_SolidExplorer& S, |
49 | const gp_Pnt& P, | |
50 | const Standard_Real Tol) { | |
51 | if(S.Reject(P)) { | |
c898afce | 52 | myState=3; //-- in ds solid case without face |
7fd59977 | 53 | } |
54 | else { | |
55 | Perform(S,P,Tol); | |
56 | } | |
57 | } | |
58 | ||
59 | ||
bd05fabf S |
60 | //======================================================================= |
61 | //function : PerformInfinitePoint | |
62 | //purpose : | |
63 | //======================================================================= | |
64 | void BRepClass3d_SClassifier::PerformInfinitePoint(BRepClass3d_SolidExplorer& aSE, | |
7fd59977 | 65 | const Standard_Real /*Tol*/) { |
c898afce Y |
66 | //-- Idea : Take point A in face1 and point B in face B |
67 | //-- (if there is only one face, take 2 points in the same face.) | |
7fd59977 | 68 | //-- |
c898afce Y |
69 | //-- Intersect straight line AB with the solid and produce transition of the |
70 | //-- first point. If the solid has only one face and the straight line AB does not cut it | |
71 | //-- it is not possible to decide. | |
7fd59977 | 72 | |
bd05fabf | 73 | if(aSE.Reject(gp_Pnt(0,0,0))) { |
c898afce | 74 | myState=3; //-- in ds solid case without face |
7fd59977 | 75 | return; |
76 | } | |
bd05fabf S |
77 | // |
78 | //------------------------------------------------------------ | |
79 | // 1 | |
80 | Standard_Boolean bFound, bFlag; | |
81 | Standard_Integer nump; | |
82 | Standard_Real aParam, aU1, aV1, aU2, aV2; | |
7fd59977 | 83 | gp_Pnt A,B; |
bd05fabf | 84 | gp_Dir aDN1, aDN2; |
e450f818 | 85 | TopoDS_Face aF1, aF2; |
bd05fabf S |
86 | // |
87 | nump = 0; | |
88 | aParam = 0.5; | |
7fd59977 | 89 | myFace.Nullify(); |
90 | myState=2; | |
bd05fabf S |
91 | for(aSE.InitShell(); aSE.MoreShell() && nump<2; aSE.NextShell()) { |
92 | for(aSE.InitFace(); aSE.MoreFace() && nump<2; ) { | |
e450f818 | 93 | TopoDS_Face aF = aSE.CurrentFace(); |
bd05fabf S |
94 | aSE.NextFace(); |
95 | if(!nump) { | |
7fd59977 | 96 | nump++; |
bd05fabf S |
97 | bFound=aSE.FindAPointInTheFace(aF, A, aU1, aV1, aParam); |
98 | if (!bFound) { | |
7fd59977 | 99 | return; |
100 | } | |
bd05fabf S |
101 | aF1=aF; |
102 | if(!aSE.MoreFace()) { | |
7fd59977 | 103 | nump++; |
bd05fabf S |
104 | bFound=aSE.FindAPointInTheFace(aF, B, aU2, aV2, aParam); |
105 | if (!bFound) { | |
106 | return; | |
107 | } | |
108 | aF2=aF; | |
7fd59977 | 109 | } |
bd05fabf S |
110 | }// if(nump==0) { |
111 | else if(nump==1) { | |
112 | bFound=aSE.FindAPointInTheFace(aF, B, aU2, aV2, aParam); | |
113 | if(!bFound) { | |
7fd59977 | 114 | return; |
bd05fabf S |
115 | } |
116 | aF2=aF; | |
117 | nump++; | |
7fd59977 | 118 | } |
bd05fabf S |
119 | }// for(aSE.InitFace(); aSE.MoreFace() && nump<2; ) { |
120 | }// for(aSE.InitShell(); aSE.MoreShell() && nump<2; aSE.NextShell()) { | |
121 | // | |
122 | //------------------------------------------------------------ | |
123 | // 2 | |
124 | Standard_Integer cpasbon; | |
125 | Standard_Real parmin, aD2, aSP; | |
126 | IntCurveSurface_TransitionOnCurve aTC; | |
127 | TopAbs_State aState; | |
128 | // | |
129 | parmin = RealLast(); | |
130 | // | |
131 | bFlag=Standard_False; | |
132 | if (aF1!=aF2) { | |
133 | FaceNormal(aF1, aU1, aV1, aDN1); | |
134 | FaceNormal(aF2, aU2, aV2, aDN2); | |
135 | aSP=1.-aDN1*aDN2; | |
136 | if (aSP < 1.e-5) { | |
137 | bFlag=!bFlag; | |
7fd59977 | 138 | } |
139 | } | |
bd05fabf S |
140 | // |
141 | aD2=A.SquareDistance(B); | |
142 | if(aD2<0.000001 || bFlag) { | |
7fd59977 | 143 | B.SetCoord(A.X()+1,A.Y()+1,A.Z()+1); |
144 | } | |
bd05fabf S |
145 | // |
146 | cpasbon = 0; | |
7fd59977 | 147 | gp_Vec AB(A,B); |
bd05fabf | 148 | // |
7fd59977 | 149 | do { |
150 | switch (cpasbon) | |
151 | { | |
152 | case 1 : AB.SetX(-AB.X());break; | |
153 | case 2 : AB.SetY(-AB.Y());break; | |
154 | case 3 : AB.SetZ(-AB.Z());break; | |
155 | case 4 : AB.SetY(-AB.Y());break; | |
156 | case 5 : AB.SetX(-AB.X());break; | |
157 | } | |
158 | gp_Lin L(A,gp_Dir(AB)); | |
159 | //-- cout<<"\npoint A "<<A.X()<<" "<<A.Y()<<" "<<A.Z()<<endl; | |
160 | //-- cout<<"\npoint B "<<B.X()<<" "<<B.Y()<<" "<<B.Z()<<endl; | |
bd05fabf S |
161 | for(aSE.InitShell();aSE.MoreShell();aSE.NextShell()) { |
162 | if(aSE.RejectShell(L) == Standard_False) { | |
163 | for(aSE.InitFace();aSE.MoreFace(); aSE.NextFace()) { | |
164 | if(aSE.RejectFace(L) == Standard_False) { | |
165 | TopoDS_Shape aLocalShape = aSE.CurrentFace(); | |
7fd59977 | 166 | TopoDS_Face f = TopoDS::Face(aLocalShape); |
bd05fabf S |
167 | IntCurvesFace_Intersector& Intersector3d = aSE.Intersector(f); |
168 | Intersector3d.Perform(L,-RealLast(),parmin); | |
7fd59977 | 169 | |
170 | if(Intersector3d.IsDone()) { | |
171 | if(Intersector3d.NbPnt()) { | |
172 | if(Intersector3d.WParameter(1) < parmin) { | |
bd05fabf | 173 | aState=Intersector3d.State(1); |
7fd59977 | 174 | parmin = Intersector3d.WParameter(1); |
bd05fabf S |
175 | if(aState==TopAbs_IN || aState==TopAbs_ON) { |
176 | aTC=Intersector3d.Transition(1); | |
7fd59977 | 177 | //-- The intersection point between the line and a face F |
178 | // -- of the solid is in the face F | |
bd05fabf | 179 | if(aTC == IntCurveSurface_Out) { |
7fd59977 | 180 | //-- The line is going from inside the solid to outside |
181 | //-- the solid. | |
182 | myState = 3; //-- IN -- | |
183 | } | |
bd05fabf | 184 | else if(aTC == IntCurveSurface_In) { |
7fd59977 | 185 | myState = 4; //-- OUT -- |
186 | } | |
187 | myFace = f; | |
188 | } | |
bd05fabf | 189 | /* |
7fd59977 | 190 | else if(Intersector3d.State(1)==TopAbs_ON) { |
191 | //-- The intersection point between the line and a face F | |
192 | //-- of the solid is in the face F | |
193 | if(Intersector3d.Transition(1) == IntCurveSurface_Out) { | |
194 | //-- The line is going from inside the solid to outside | |
195 | //-- the solid. | |
196 | myState = 3; //-- IN -- | |
197 | } | |
198 | else if(Intersector3d.Transition(1) == IntCurveSurface_In) { | |
199 | myState = 4; //-- OUT -- | |
200 | } | |
201 | //-- myState = 2; | |
202 | myFace = f; | |
203 | } | |
bd05fabf | 204 | */ |
7fd59977 | 205 | } |
bd05fabf | 206 | |
7fd59977 | 207 | else { |
208 | //-- No point has been found by the Intersector3d. | |
209 | //-- Or a Point has been found with a greater parameter. | |
210 | } | |
211 | } | |
212 | } | |
213 | } | |
214 | } //-- Exploration of the faces | |
215 | } //-- Shell has not been rejected | |
216 | else { | |
217 | myState=1; | |
218 | } | |
219 | } //-- Exploration of the shells | |
220 | cpasbon++; | |
221 | } | |
222 | while(cpasbon!=0 && cpasbon<5); | |
223 | } | |
224 | //======================================================================= | |
225 | //function : Perform | |
226 | //purpose : | |
227 | //======================================================================= | |
bd05fabf S |
228 | void BRepClass3d_SClassifier::Perform(BRepClass3d_SolidExplorer& SolidExplorer, |
229 | const gp_Pnt& P, | |
230 | const Standard_Real Tol) | |
7fd59977 | 231 | { |
232 | ||
233 | ||
234 | if(SolidExplorer.Reject(P)) { | |
c898afce | 235 | myState=3; //-- in ds solid case without face |
7fd59977 | 236 | return; |
237 | } | |
238 | ||
239 | ||
240 | myFace.Nullify(); | |
241 | myState = 0; | |
242 | if(SolidExplorer.Reject(P) == Standard_False) { | |
243 | gp_Lin L; | |
244 | Standard_Real Par; | |
245 | //-- We compute the intersection betwwen the line builded in the Solid Explorer | |
246 | //-- and the shape. | |
247 | ||
248 | //-- -------------------------------------------------------------------------------- | |
c898afce Y |
249 | //-- Calculate intersection with the face closest to the direction of bounding boxes |
250 | //-- by priority so that to have the smallest possible parmin. | |
251 | //-- optimization to produce as much as possible rejections with other faces. | |
7fd59977 | 252 | Standard_Integer iFlag; |
253 | // | |
254 | ||
255 | // Modified by skv - Thu Sep 4 11:22:05 2003 OCC578 Begin | |
256 | // If found line passes through a bound of any face, it means that the line | |
257 | // is not found properly and it is necessary to repeat whole procedure. | |
258 | // That's why the main loop while is added. | |
259 | Standard_Boolean isFaultyLine = Standard_True; | |
260 | Standard_Integer anIndFace = 0; | |
261 | Standard_Real parmin; | |
262 | ||
263 | while (isFaultyLine) { | |
264 | if (anIndFace == 0) { | |
265 | iFlag = SolidExplorer.Segment(P,L,Par); | |
266 | } else { | |
267 | iFlag = SolidExplorer.OtherSegment(P,L,Par); | |
268 | } | |
269 | ||
270 | Standard_Integer aCurInd = SolidExplorer.GetFaceSegmentIndex(); | |
271 | ||
272 | if (aCurInd > anIndFace) { | |
273 | anIndFace = aCurInd; | |
274 | } else { | |
275 | myState = 1; | |
276 | ||
277 | return; | |
278 | } | |
279 | // Modified by skv - Thu Sep 4 11:22:10 2003 OCC578 End | |
280 | ||
281 | if (iFlag==1) { | |
282 | // IsOnFace | |
283 | // iFlag==1 i.e face is Infinite | |
284 | myState=2; | |
285 | ||
286 | return; | |
287 | } | |
288 | //SolidExplorer.Segment(P,L,Par); | |
7fd59977 | 289 | // |
290 | //process results from uncorrected shells | |
291 | // | |
7fd59977 | 292 | //if(Par > 1.e+100 && L.Direction().IsParallel(gp_Dir(0.,0.,1.),1.e-8)) { |
293 | if (iFlag==2) { | |
7fd59977 | 294 | myState = 4; |
295 | return; | |
296 | } | |
297 | //-- BRepClass3d_Intersector3d Intersector3d; | |
298 | ||
299 | // Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 Begin | |
300 | // Check if the point is ON surface but OUT of the face. | |
301 | // Just skip this face because it is bad for classification. | |
302 | if (iFlag == 3) | |
303 | continue; | |
304 | ||
305 | isFaultyLine = Standard_False; | |
306 | // Standard_Real parmin = RealLast(); | |
307 | ||
308 | // for(SolidExplorer.InitShell(); | |
309 | // SolidExplorer.MoreShell(); | |
310 | // SolidExplorer.NextShell()) { | |
311 | parmin = RealLast(); | |
312 | ||
313 | for(SolidExplorer.InitShell(); | |
314 | SolidExplorer.MoreShell() && !isFaultyLine; | |
315 | SolidExplorer.NextShell()) { | |
316 | // Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 End | |
317 | ||
318 | if(SolidExplorer.RejectShell(L) == Standard_False) { | |
319 | ||
320 | // Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 Begin | |
321 | // for(SolidExplorer.InitFace(); | |
322 | // SolidExplorer.MoreFace(); | |
323 | // SolidExplorer.NextFace()) { | |
324 | for(SolidExplorer.InitFace(); | |
325 | SolidExplorer.MoreFace() && !isFaultyLine; | |
326 | SolidExplorer.NextFace()) { | |
327 | // Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 End | |
328 | ||
329 | if(SolidExplorer.RejectFace(L) == Standard_False) { | |
330 | ||
331 | //-- Intersector3d.Perform(L,Par,Tol,SolidExplorer.CurrentFace()); | |
332 | TopoDS_Shape aLocalShape = SolidExplorer.CurrentFace(); | |
333 | TopoDS_Face f = TopoDS::Face(aLocalShape); | |
334 | // TopoDS_Face f = TopoDS::Face(SolidExplorer.CurrentFace()); | |
335 | IntCurvesFace_Intersector& Intersector3d = SolidExplorer.Intersector(f); | |
336 | ||
337 | // MSV Oct 25, 2001: prolong segment, since there are cases when | |
338 | // the intersector does not find intersection points with the original | |
339 | // segment due to rough triangulation of a parametrized surface | |
340 | Standard_Real addW = Max(10*Tol, 0.01*Par); | |
341 | Standard_Real AddW = addW; | |
342 | ||
343 | Bnd_Box aBoxF = Intersector3d.Bounding(); | |
344 | ||
345 | // MSV 23.09.2004: the box must be finite in order to | |
346 | // correctly prolong the segment to its bounds | |
347 | if (!aBoxF.IsVoid() && !aBoxF.IsWhole()) { | |
348 | Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; | |
349 | aBoxF.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); | |
350 | ||
351 | Standard_Real boxaddW = GetAddToParam(L,Par,aBoxF); | |
352 | addW = Max(addW,boxaddW); | |
353 | } | |
354 | ||
355 | Standard_Real minW = -AddW;//-addW; | |
356 | Standard_Real maxW = Min(Par*10,Par+addW);//Par+addW; | |
357 | //cout << "range [" << minW << "," << maxW << "]" << endl << endl; | |
358 | Intersector3d.Perform(L,minW,maxW); | |
359 | //Intersector3d.Perform(L,-Tol,Par+10.0*Tol); | |
360 | if(Intersector3d.IsDone()) { | |
361 | Standard_Integer i; | |
362 | for (i=1; i <= Intersector3d.NbPnt(); i++) { | |
363 | if(Abs(Intersector3d.WParameter(i)) < Abs(parmin)) { | |
364 | ||
365 | parmin = Intersector3d.WParameter(i); | |
366 | // Modified by skv - Thu Sep 4 12:46:32 2003 OCC578 Begin | |
367 | TopAbs_State aState = Intersector3d.State(i); | |
368 | // Modified by skv - Thu Sep 4 12:46:33 2003 OCC578 End | |
369 | if(Abs(parmin)<=Tol) { | |
370 | myState = 2; | |
371 | myFace = f; | |
372 | } | |
373 | // Modified by skv - Thu Sep 4 12:46:32 2003 OCC578 Begin | |
374 | // Treatment of case TopAbs_ON separately. | |
375 | ||
376 | else if(aState==TopAbs_IN) { | |
377 | // Modified by skv - Thu Sep 4 12:46:32 2003 OCC578 End | |
378 | ||
379 | //-- The intersection point between the line and a face F | |
380 | // -- of the solid is in the face F | |
381 | ||
382 | IntCurveSurface_TransitionOnCurve tran = Intersector3d.Transition(i); | |
383 | if (tran == IntCurveSurface_Tangent) { | |
384 | #ifdef DEB | |
c898afce | 385 | cout<<"*Problem ds BRepClass3d_SClassifier.cxx"<<endl; |
7fd59977 | 386 | #endif |
387 | continue; // ignore this point | |
388 | } | |
389 | // if parmin is negative we should reverse transition | |
390 | if (parmin < 0) | |
391 | tran = (tran == IntCurveSurface_Out | |
392 | ? IntCurveSurface_In : IntCurveSurface_Out); | |
393 | if(tran == IntCurveSurface_Out) { | |
394 | //-- The line is going from inside the solid to outside | |
395 | //-- the solid. | |
396 | myState = 3; //-- IN -- | |
397 | } | |
398 | else /* if(tran == IntCurveSurface_In) */ { | |
399 | myState = 4; //-- OUT -- | |
400 | } | |
401 | myFace = f; | |
402 | } | |
403 | // Modified by skv - Thu Sep 4 12:48:50 2003 OCC578 Begin | |
404 | // If the state is TopAbs_ON, it is necessary to chose | |
405 | // another line and to repeat the whole procedure. | |
406 | else if(aState==TopAbs_ON) { | |
407 | isFaultyLine = Standard_True; | |
408 | ||
409 | break; | |
410 | } | |
411 | // Modified by skv - Thu Sep 4 12:48:50 2003 OCC578 End | |
412 | } | |
413 | else { | |
414 | //-- No point has been found by the Intersector3d. | |
415 | //-- Or a Point has been found with a greater parameter. | |
416 | } | |
417 | } //-- loop by intersection points | |
418 | } //-- Face has not been rejected | |
419 | else { | |
420 | myState = 1; | |
421 | } | |
422 | } | |
423 | } //-- Exploration of the faces | |
424 | } //-- Shell has not been rejected | |
425 | else { | |
426 | myState=1; | |
427 | } | |
428 | } //-- Exploration of the shells | |
429 | ||
430 | // Modified by skv - Thu Sep 4 11:42:03 2003 OCC578 Begin | |
431 | // The end of main loop. | |
432 | } | |
433 | // Modified by skv - Thu Sep 4 11:42:03 2003 OCC578 End | |
434 | ||
435 | #ifdef DEB | |
436 | //################################################# | |
437 | SolidExplorer.DumpSegment(P,L,parmin,State()); | |
438 | //################################################# | |
439 | #endif | |
440 | ||
441 | } //-- Solid has not been rejected | |
442 | else { | |
443 | myState = 1; | |
444 | } | |
445 | } | |
446 | ||
447 | ||
448 | TopAbs_State BRepClass3d_SClassifier::State() const { | |
449 | if(myState==2) return(TopAbs_ON); | |
450 | if(myState==4) return(TopAbs_OUT); //-- | |
451 | else if(myState==3) return(TopAbs_IN); //-- | |
452 | return(TopAbs_OUT); | |
453 | } | |
454 | ||
455 | TopoDS_Face BRepClass3d_SClassifier::Face() const { | |
456 | return(myFace); | |
457 | } | |
458 | ||
459 | Standard_Boolean BRepClass3d_SClassifier::Rejected() const { | |
460 | return(myState==1); | |
461 | } | |
462 | ||
463 | ||
464 | Standard_Boolean BRepClass3d_SClassifier::IsOnAFace() const { | |
465 | return(myState==2); | |
466 | } | |
467 | ||
468 | ||
469 | void BRepClass3d_SClassifier::ForceIn() { | |
470 | myState=3; | |
471 | } | |
472 | ||
473 | void BRepClass3d_SClassifier::ForceOut() { | |
474 | myState=4; | |
475 | } | |
476 | ||
477 | Standard_Real GetAddToParam(const gp_Lin& L, | |
478 | const Standard_Real P, | |
479 | const Bnd_Box& B) | |
480 | { | |
481 | Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; | |
482 | B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); | |
483 | Standard_Real x[2] = {aXmin,aXmax}, y[2] = {aYmin,aYmax}, z[2] = {aZmin,aZmax}; | |
484 | Standard_Integer i = 0, j = 0, k = 0; | |
485 | Standard_Real Par = P; | |
486 | for(i = 0 ; i < 2; i++) { | |
487 | for(j = 0; j < 2; j++) { | |
488 | for(k = 0; k < 2; k++) { | |
489 | Standard_Real X = fabs(x[i]-L.Location().X()); | |
490 | Standard_Real Y = fabs(y[j]-L.Location().Y()); | |
491 | Standard_Real Z = fabs(z[k]-L.Location().Z()); | |
492 | if(X < 1.e+20 && Y < 1.e+20 && Z < 1.e+20) { | |
493 | gp_Pnt aP(x[i],y[j],z[k]); | |
494 | Standard_Real par = ElCLib::Parameter(L,aP); | |
495 | if(par > Par) | |
496 | Par = par; | |
497 | } | |
498 | else | |
499 | return 1.e+20; | |
500 | } | |
501 | } | |
502 | } | |
503 | return Par - P; | |
504 | } | |
bd05fabf S |
505 | //======================================================================= |
506 | //function : FaceNormal | |
507 | //purpose : | |
508 | //======================================================================= | |
509 | void FaceNormal (const TopoDS_Face& aF, | |
510 | const Standard_Real U, | |
511 | const Standard_Real V, | |
512 | gp_Dir& aDN) | |
513 | { | |
514 | gp_Pnt aPnt ; | |
515 | gp_Vec aD1U, aD1V, aN; | |
516 | Handle(Geom_Surface) aS; | |
517 | ||
518 | aS=BRep_Tool::Surface(aF); | |
519 | aS->D1 (U, V, aPnt, aD1U, aD1V); | |
520 | aN=aD1U.Crossed(aD1V); | |
521 | aN.Normalize(); | |
522 | aDN.SetXYZ(aN.XYZ()); | |
523 | if (aF.Orientation() == TopAbs_REVERSED){ | |
524 | aDN.Reverse(); | |
525 | } | |
526 | return; | |
527 | } |