0022792: Globally defined symbol PI conflicts with VTK definition (Intel compiler)
[occt.git] / src / BRepMesh / BRepMesh_Classifier.cxx
1 // File:        BRepMesh_Classifier.cxx
2 // Created:     Thu Jun 26 14:54:02 1997
3 // Author:      Laurent PAINNOT
4 //              <lpa@penox.paris1.matra-dtv.fr>
5
6
7 #include <BRepMesh_Classifier.ixx>
8
9 // Kernel
10 #include <Precision.hxx>
11 #include <Standard_ErrorHandler.hxx>
12 #include <TColStd_ListOfTransient.hxx>
13 #include <TColStd_Array1OfInteger.hxx>
14 #include <TColStd_DataMapOfIntegerInteger.hxx>
15 #include <ElCLib.hxx>
16 // Geometry
17 #include <gp_Pnt.hxx>
18 #include <gp_Pnt2d.hxx>
19 #include <TColgp_SequenceOfPnt2d.hxx>
20 #include <TColgp_Array1OfPnt2d.hxx>
21 #include <GeomAbs_SurfaceType.hxx>
22 #include <Geom2dInt_Geom2dCurveTool.hxx>
23 #include <Geom2d_Line.hxx>
24 #include <Geom2d_BezierCurve.hxx>
25 #include <Geom2d_BSplineCurve.hxx>
26 #include <Geom2d_TrimmedCurve.hxx>
27 // Topology
28 #include <BRep_Tool.hxx>
29 #include <BRepTools.hxx>
30 #include <BRepTools_WireExplorer.hxx>
31 #include <BRepAdaptor_Curve2d.hxx>
32 #include <TopAbs_Orientation.hxx>
33 #include <TopExp.hxx>
34 #include <TopExp_Explorer.hxx>
35 #include <TopoDS_Edge.hxx>
36 #include <TopoDS.hxx>
37 #include <CSLib_Class2d.hxx>
38 #include <Poly_PolygonOnTriangulation.hxx>
39 // BRepMesh
40 #include <BRepMesh_Vertex.hxx>
41 #include <BRepMesh_Array1OfBiPoint.hxx>
42 #include <BRepMesh_PairOfPolygon.hxx>
43
44 #ifdef DEB_MESH
45 static Standard_Integer debwire;
46 static Standard_Integer debedge;
47 static Standard_Integer debclass = 0;
48 #endif
49 static const Standard_Real MIN_DIST = 2.E-5; //EPA: real mesh is created in the grid 10E5x10E5, so intersection should be cheched
50                                              //     with double of discretization.
51 static const Standard_Real PARALL_COND = Sin(M_PI/3.0);
52 static const Standard_Real RESOLUTION = 1.0E-16; //OCC319
53
54
55 //=======================================================================
56 //function : IsLine
57 //purpose  : 
58 //=======================================================================
59
60 static Standard_Boolean IsLine(const Handle(Geom2d_Curve)& C2d)
61 {
62   Standard_Boolean IsALine = Standard_False;
63   if ( C2d->IsKind(STANDARD_TYPE(Geom2d_Line)) )
64   {
65     IsALine = Standard_True;
66   }
67   else if ( C2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) )
68   {
69     Handle(Geom2d_BSplineCurve) BS = *((Handle(Geom2d_BSplineCurve)*)&C2d);
70     IsALine = (BS->NbPoles() == 2);
71   }
72   else if ( C2d->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)) )
73   {
74     Handle(Geom2d_BezierCurve) Bz = *((Handle(Geom2d_BezierCurve)*)&C2d);
75     IsALine = (Bz->NbPoles() == 2);
76   }
77   else if ( C2d->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)) )
78   {
79     Handle(Geom2d_TrimmedCurve) Curv = *((Handle(Geom2d_TrimmedCurve)*)&C2d);
80     IsALine = IsLine(Curv->BasisCurve());
81   }
82   return IsALine;
83 }
84
85 //=======================================================================
86 //function : AnalizeWire
87 //purpose  : 
88 //=======================================================================
89
90 void BRepMesh_Classifier::AnalizeWire (const TColgp_SequenceOfPnt2d&  theSeqPnt2d,
91                                        const Standard_Real Umin,  const Standard_Real Umax,
92                                        const Standard_Real Vmin,  const Standard_Real Vmax)
93 {
94   const Standard_Integer nbpnts = theSeqPnt2d.Length();
95   if (nbpnts < 2) return;
96
97   // Accumulate angle
98   TColgp_Array1OfPnt2d PClass(1,nbpnts);
99   Standard_Integer i, ii;
100   Standard_Real theangle = 0.0;
101   gp_Pnt2d p1 = theSeqPnt2d(1), p2 = theSeqPnt2d(2), p3;
102   PClass(1) = p1;
103   PClass(2) = p2;
104   for (i = 1; i <= nbpnts; i++)
105   { 
106     ii = i + 2;
107     if (ii > nbpnts)
108     {
109       p3 = PClass(ii-nbpnts);
110     }
111     else
112     {
113       p3 = theSeqPnt2d.Value(ii);
114       PClass(ii) = p3;
115     }
116     gp_Vec2d A(p1,p2), B(p2,p3);
117     if (A.SquareMagnitude() > 1.e-16 && B.SquareMagnitude() > 1.e-16)
118     {
119       const Standard_Real a = A.Angle(B);
120       const Standard_Real aa = Abs(a);
121       // Check if vectors are opposite
122       if (aa > Precision::Angular() && (M_PI - aa) > Precision::Angular())
123       {
124         theangle += a;
125         p1 = p2;
126       }
127     }
128     p2 = p3;
129   }
130   // Check for zero angle - treat self intersecting wire as outer
131   if (Abs(theangle) < Precision::Angular()) theangle = 0.0;
132
133   TabClass.Append((void *)new CSLib_Class2d(PClass,Toluv,Toluv,Umin,Vmin,Umax,Vmax));
134   TabOrien.Append((theangle < 0.0) ? 0 : 1);
135 }
136
137 //=======================================================================
138 //function : triangle2Area
139 //purpose  : calculating area under triangle
140 //=======================================================================
141
142 inline static Standard_Real triangle2Area(const gp_XY& p1, const gp_XY& p2)
143 {
144   return p1.Crossed(p2);
145 }
146
147 //=======================================================================
148 //function : getSegmentParams
149 //purpose  : extracting segment attributes 
150 //=======================================================================
151
152 static Standard_Real getSegmentParams(const BRepMesh_Array1OfBiPoint& theBiPoints,
153                                       const Standard_Integer Index,
154                                       Standard_Real& x11,
155                                       Standard_Real& y11,
156                                       Standard_Real& x12,
157                                       Standard_Real& y12,
158                                       Standard_Real& A,
159                                       Standard_Real& B,
160                                       Standard_Real& C)
161 {
162   Standard_Real *aCoordinates;
163   aCoordinates = ((Standard_Real*)(theBiPoints(Index).Coordinates()));
164   x11 =  aCoordinates[0];
165   y11 =  aCoordinates[1];
166   x12 =  aCoordinates[2];
167   y12 =  aCoordinates[3];
168   A   =  aCoordinates[5];
169   B   = -aCoordinates[4];
170   C   = - x11*A - y11*B;
171   return A*A+B*B;
172 }
173
174 //=======================================================================
175 //function : checkWiresIntersection
176 //purpose  : finding intersection.
177 //           If the intersection is found return Standard_True
178 //=======================================================================
179
180 static Standard_Boolean checkWiresIntersection(const Standard_Integer            theFirstWireId,
181                                               const Standard_Integer            theSecondWireId,
182                                               Standard_Integer* const           theFirstOuterSegmentId,
183                                               Standard_Integer                  theLastOuterSegmentId,
184                                               const TColStd_SequenceOfInteger&  theWireLength,
185                                               const BRepMesh_Array1OfBiPoint&   theBiPoints,
186                                               const Standard_Boolean            findNextIntersection   = Standard_False,
187                                               const Standard_Boolean            isFirstSegment         = Standard_False,
188                                               Standard_Integer* const           theFirstInnerSegmentId = 0)
189 {
190   Standard_Real A1, B1, C1, A2, B2, C2, AB, BC, CA, xc, yc;
191   Standard_Real  mu1, d, mu2;
192   Standard_Integer ik = *theFirstOuterSegmentId, jk;
193   Standard_Real x11, x12, y11, y12, x21, x22, y21, y22;
194
195   // Calculate bounds for first wire
196   Standard_Integer ikEnd = theLastOuterSegmentId;
197   Standard_Boolean isFirst = Standard_True;
198   if ( findNextIntersection )
199   {
200     isFirst = isFirstSegment;
201   }
202
203   // Calculate bounds for second wire
204   Standard_Integer jkStart = 0, jkEnd = 0;
205   for (jk = 1; jk <= theSecondWireId; jk++)
206   {
207     jkStart = jkEnd + 1;
208     jkEnd  += theWireLength(jk);
209   }
210
211   // total area under polygon (area of loop)
212   Standard_Real aLoopArea          = 0.0;
213   // area under first triangles of polygon
214   Standard_Real aFirstTriangleArea = 0.0;
215   // contains coordinates of the end point of segment if first intersection point is finding
216   // or coordinates of the intersecting point if second intersection point is finding
217   gp_XY aStartPoint;
218
219   for (; ik <= ikEnd; ik++)
220   {
221     mu1 = getSegmentParams(theBiPoints, ik, x11, y11, x12, y12, A1, B1, C1);
222     // for second intersection point we must count the area from first intersection point 
223     if ( !findNextIntersection )
224     {
225       aLoopArea = 0.0;
226       aStartPoint.SetCoord(x12, y12);
227     }
228
229     //for theFirstWireId == theSecondWireId the algorithm check current wire on selfintersection
230     if ( findNextIntersection && theFirstInnerSegmentId && isFirst)
231     {
232       jk = *theFirstInnerSegmentId;
233     }
234     else if (theSecondWireId == theFirstWireId)
235     {
236       jk = ik + 2;
237     }
238     else
239     {
240       jk = jkStart;
241     }
242
243     // Explore second wire
244     Standard_Boolean aFirstPass = Standard_True;
245     for (; jk <= jkEnd; jk++)
246     {
247       // don't check end's segment of the wire on selfrestriction
248       if ( theSecondWireId == theFirstWireId && isFirst && jk == ikEnd ) continue;
249
250       mu2 = getSegmentParams(theBiPoints, jk, x21, y21, x22, y22, A2, B2, C2);
251       gp_XY p2(x21, y21), p3(x22, y22);
252
253       //different segments may have common vertex (see OCC287 bug for example)
254       AB = A1*B2 - A2*B1;
255       //check on minimal of distance between current segment and points of another linear segments - OCC319
256       d = A1*x22 + B1*y22 + C1;
257       Standard_Real dTol = MIN_DIST*MIN_DIST;
258       if(theFirstWireId != theSecondWireId       && // if compared wires are different &&
259          AB*AB > PARALL_COND*PARALL_COND*mu1*mu2 && // angle between two segments greater then PARALL_COND &&
260          d*d   < dTol*mu1 &&             // distance between vertex of the segment and other one's less then MIN_DIST
261          (x22-x11)*(x22-x12) < 0.0 && (y22-y11)*(y22-y12) < 0.0)
262       {
263         // if we finding the second intersection we must return Standard_False for setting
264         // self-intersection result flag
265         if ( findNextIntersection )
266           return Standard_False;
267
268         // we can step here when finding first intersection, return self-intersection flag
269         return Standard_True;
270       }
271
272       if( aFirstPass )
273       {
274         aFirstTriangleArea = triangle2Area(aStartPoint, p2);
275       }
276       Standard_Real aTmpArea = triangle2Area(p2, p3);
277
278       //look for intersection of two linear segments
279       if(Abs(AB) <= RESOLUTION)
280       {
281         aLoopArea += aTmpArea;
282         continue;  //current segments seem parallel - no intersection
283       }
284       
285       //calculate coordinates of point of the intersection
286       BC = B1*C2 - B2*C1;  xc = BC/AB;
287       CA = C1*A2 - C2*A1;  yc = CA/AB;
288
289       // remember current intersection point and area of first triangle
290       if( findNextIntersection && ik == *theFirstOuterSegmentId && jk == *theFirstInnerSegmentId )
291       {
292         aStartPoint.SetCoord(xc, yc);
293         continue;
294       }
295
296       //check on belonging of intersection point to the both of segments
297       Standard_Boolean isOnLines = Standard_True;
298
299       Standard_Real dd[2][4] = { {(xc-x11), (xc-x12), (xc-x21), (xc-x22)},   //dX
300                                  {(yc-y11), (yc-y12), (yc-y21), (yc-y22)} }; //dY
301
302       Standard_Integer i = 0;
303       for(; i < 2; i++ )
304       {
305         if ( dd[i][0]*dd[i][1] > dTol || dd[i][2]*dd[i][3] > dTol)
306         {
307           isOnLines = Standard_False;
308           break;
309         }
310       }
311
312       // check the intersection point is on the ends of segments
313       if ( isOnLines )
314       {
315         for( i = 0; i < 2; i++ )
316         {
317           //     if it's the last segment and intersection point lies at the end
318           if ( ( jk == jkEnd                                              ||
319           //     dX                        && dY
320           //     or when the start or the end point of the first segment
321                 (Abs(dd[0][0])  < MIN_DIST && Abs(dd[1][0])   < MIN_DIST) ||
322                 (Abs(dd[0][1])  < MIN_DIST && Abs(dd[1][1])   < MIN_DIST)) &&
323           //     is equal to one of the end points of the second
324                (Abs(dd[0][i+2]) < MIN_DIST && Abs(dd[1][i+2]) < MIN_DIST))
325           {
326             // no intersection
327             isOnLines = Standard_False;
328             aLoopArea = aTmpArea = 0.0;
329             aFirstPass = Standard_True;
330             break;
331           }
332         }
333       }
334
335
336       if( isOnLines )
337       {
338         p3.SetX(xc); p3.SetY(yc); 
339         aLoopArea += aFirstTriangleArea;             // First triangle area
340         aLoopArea += triangle2Area(p2, p3); 
341         aLoopArea += triangle2Area(p3, aStartPoint); // Last triangle area
342
343         if( Abs(aLoopArea)/2 > M_PI*MIN_DIST )
344         {
345           if ( findNextIntersection )
346           {
347             // intersection is found, but Standard_False returns, because area is too much
348             return Standard_False;
349           }
350
351           if ( checkWiresIntersection(theFirstWireId, theSecondWireId, &ik, ikEnd, theWireLength,
352                            theBiPoints, Standard_True, isFirst, &jk) )
353           {
354             // small crossing is not intersection, continue cheching
355             aLoopArea = aTmpArea = 0.0;
356             aFirstPass = Standard_True;
357           }
358           else
359           {
360             // if we found only one intersection
361             return Standard_True;
362           }
363         }
364         else if ( findNextIntersection )
365         {
366           // small intersection, skip double checking
367           *theFirstOuterSegmentId = ik;
368           *theFirstInnerSegmentId = jk + 1;
369           return Standard_True;
370         }
371       }
372       if ( aFirstPass )
373       {
374         aFirstPass = Standard_False;
375       }
376
377       aLoopArea += aTmpArea;
378     }
379     
380     if ( isFirst )
381     {
382       isFirst = Standard_False;
383     }
384   }
385   return Standard_False;
386 }
387
388
389 //=======================================================================
390 //function : BRepMesh_Classifier
391 //purpose  : 
392 //=======================================================================
393
394 BRepMesh_Classifier::BRepMesh_Classifier(const TopoDS_Face& aFace,
395                                          const Standard_Real TolUV,
396                                          const BRepMesh_DataMapOfShapePairOfPolygon& edges,
397                                          const TColStd_IndexedMapOfInteger& themap,
398                                          const Handle(BRepMesh_DataStructureOfDelaun)& Str,
399                                          const Standard_Real Umin,
400                                          const Standard_Real Umax,
401                                          const Standard_Real Vmin,
402                                          const Standard_Real Vmax):
403                                          Toluv(TolUV), Face(aFace),
404                                          myState(BRepMesh_NoError)
405 {
406   //-- impasse sur les surfs definies sur plus d une periode
407
408   //-- once definition
409   Face.Orientation(TopAbs_FORWARD);
410
411   TopoDS_Edge  edge;
412   BRepTools_WireExplorer WireExplorer;
413   //TopExp_Explorer FaceExplorer;
414   TopoDS_Iterator FaceExplorer;
415
416   TColgp_SequenceOfPnt2d aWirePoints, aWire;
417   TColStd_SequenceOfInteger aWireLength;
418
419
420   //-- twice definitions
421   TopAbs_Orientation anOr = TopAbs_FORWARD;
422   Standard_Boolean falsewire = Standard_False;
423   Standard_Integer i, index, firstindex = 0, lastindex = 0, nbedges = 0;
424 #ifdef DEB_MESH
425   debwire = 0;
426 #endif
427
428   for(FaceExplorer.Initialize(Face); FaceExplorer.More(); FaceExplorer.Next())
429   {
430     if( FaceExplorer.Value().ShapeType()!= TopAbs_WIRE)
431       continue;
432 #ifdef DEB_MESH
433     if (debclass) { debwire++;  cout <<endl;  cout << "#wire no "<<debwire; debedge = 0;}
434 #endif
435     // For each wire we create a data map, linking vertices (only
436     // the ends of edges) with their positions in the sequence of
437     // all 2d points from this wire.
438     // When we meet some vertex for the second time - the piece
439     // of sequence is treated for a HOLE and quits the sequence.
440     // Actually, we must unbind the vertices belonging to the
441     // loop from the map, but since they can't appear twice on the
442     // valid wire, leave them for a little speed up.
443     nbedges = 0;
444     TColgp_SequenceOfPnt2d SeqPnt2d;
445     TColStd_DataMapOfIntegerInteger NodeInSeq;
446     // Start traversing the wire
447     for (WireExplorer.Init(TopoDS::Wire(FaceExplorer.Value()),Face); WireExplorer.More(); WireExplorer.Next())
448     {
449       edge = WireExplorer.Current();
450 #ifdef DEB_MESH
451       if (debclass) { debedge++; cout << endl; cout << "#edge no "<<debedge <<endl;}
452 #endif
453       anOr = edge.Orientation();
454       if (anOr != TopAbs_FORWARD && anOr != TopAbs_REVERSED) continue;
455       if (edges.IsBound(edge))
456       {
457         // Retrieve polygon
458         // Define the direction for adding points to SeqPnt2d
459         Standard_Integer iFirst,iLast,iIncr;
460         const BRepMesh_PairOfPolygon& pair = edges.Find(edge);
461         Handle(Poly_PolygonOnTriangulation) NOD;
462         if (anOr == TopAbs_FORWARD)
463         {
464           NOD = pair.First();
465           iFirst = 1;
466           iLast  = NOD->NbNodes();
467           iIncr  = 1;
468         }
469         else
470         {
471           NOD = pair.Last();
472           iFirst = NOD->NbNodes();
473           iLast  = 1;
474           iIncr  = -1;
475         }
476         const TColStd_Array1OfInteger& indices = NOD->Nodes();
477
478         // indexFirst and indexLast are the indices of first and last
479         // vertices of the edge in IndexedMap <Str>
480         const Standard_Integer indexFirst = themap.FindKey(indices(iFirst));
481         const Standard_Integer indexLast = themap.FindKey(indices(iLast));
482
483         // Skip degenerated edge : OCC481(apo)
484         if (indexLast == indexFirst && (iLast-iFirst) == iIncr) continue;
485
486         // If there's a gap between edges -> raise <falsewire> flag
487         if (nbedges)
488         {
489           if (indexFirst != lastindex)
490           {
491             falsewire = Standard_True;
492             break;
493           }
494         }
495         else firstindex = indexFirst;
496               lastindex = indexLast;
497
498         // Record first vertex (to detect loops)
499         NodeInSeq.Bind(indexFirst,SeqPnt2d.Length()+1);
500
501         // Add vertices in sequence
502         for (i = iFirst; i != iLast; i += iIncr)
503         {
504           index = (i == iFirst)? indexFirst : themap.FindKey(indices(i));
505
506           gp_Pnt2d vp(Str->GetNode(index).Coord());
507           SeqPnt2d.Append(vp);
508 #ifdef DEB_MESH
509           if (debclass) cout<<"point p"<<index<<" "<<vp.X()<<" "<< vp.Y()<<endl;
510 #endif
511         }
512
513         // Now, is there a loop?
514         if (NodeInSeq.IsBound(indexLast))
515         {
516           // Yes, treat it separately as a hole
517           // 1. Divide points into main wire and a loop
518           const Standard_Integer iWireStart = NodeInSeq(indexLast);
519           if(iWireStart < SeqPnt2d.Length()) {
520             SeqPnt2d.Split(iWireStart, aWire);
521             //OCC319->  the operation will be done later
522             // 2. Proceed the loop
523             //AnalizeWire(aLoop, Umin, Umax, Vmin, Vmax, aWirePoints, aWireLength, NbBiPoint);
524             aWireLength.Append(aWire.Length());
525             aWirePoints.Append(aWire);
526             //<-OCC319
527           }
528         }
529         nbedges++;
530       }
531     }
532
533     if (nbedges)
534     {
535       // Isn't it open?
536       if (falsewire || (firstindex != lastindex) || SeqPnt2d.Length() > 1)
537       {
538         myState = BRepMesh_OpenWire;
539         return;
540       }
541     }
542     else
543     {
544 #ifdef DEB_MESH
545       cout <<"Warning : empty wire" <<endl;
546 #endif
547     }
548   }
549
550   const Standard_Integer nbwires = aWireLength.Length();
551   Standard_Integer NbBiPoint = aWirePoints.Length();
552   BRepMesh_Array1OfBiPoint BiPoints(0,NbBiPoint);
553
554   BRepMesh_BiPoint *BP;
555   Standard_Real *Coordinates1;
556   Standard_Real x1, y1, x2, y2, xstart, ystart;
557   Standard_Integer j, l = 1;
558   BP = &(BiPoints.ChangeValue(1));
559
560   // Fill array of segments (bi-points)
561   for (i = 1; i <= nbwires; i++)
562   {
563     const Standard_Integer len = aWireLength(i) + 1;
564     for (j = 1; j <= len; j++)
565     {
566       // Obtain last point of the segment
567       if (j == len)
568       {
569         x2 = xstart;
570         y2 = ystart;
571       }
572       else
573       {
574         const gp_Pnt2d& PT = aWirePoints(l); l++;
575         x2 = PT.X();
576         y2 = PT.Y();
577       }
578       // Build segment (bi-point)
579       if (j == 1)
580       {
581         xstart = x2;
582         ystart = y2;
583       }
584       else
585       {
586         Coordinates1 = ((Standard_Real*)(BP->Coordinates())); BP++;
587         Coordinates1[0] = x1;
588         Coordinates1[1] = y1;
589         Coordinates1[2] = x2;
590         Coordinates1[3] = y2;
591         Coordinates1[4] = x2 - x1;
592         Coordinates1[5] = y2 - y1;
593       }
594       x1 = x2;
595       y1 = y2;
596     }
597   }
598
599   // Search the intersection
600   // Explore first wire
601   Standard_Integer ik, ikEnd = 0;
602   for(i = 1; i <= nbwires; i++)
603   {
604     ik = ikEnd + 1;  ikEnd += aWireLength(i);
605     // Explore second wire
606     for (j = i; j <= nbwires; j++)
607     {
608       if ( checkWiresIntersection(i, j, &ik, ikEnd, aWireLength, BiPoints) )
609       {
610         myState = BRepMesh_SelfIntersectingWire; return;
611       }
612     }
613   }
614
615   // Find holes
616   for (i = nbwires; i >= 1; i--)
617   {
618     NbBiPoint = aWirePoints.Length() - aWireLength(i) + 1;
619     aWirePoints.Split(NbBiPoint, aWire);
620     AnalizeWire(aWire, Umin, Umax, Vmin, Vmax);
621   }
622 }
623
624
625 //=======================================================================
626 //function : Perform
627 //purpose  : 
628 //=======================================================================
629
630 TopAbs_State BRepMesh_Classifier::Perform(const gp_Pnt2d& aPoint) const
631 {
632   Standard_Boolean isOut = Standard_False;
633
634   Standard_Integer cur, i, nb = TabClass.Length();
635   
636   for (i = 1; i <= nb; i++)
637   {
638     cur = ((CSLib_Class2d*)TabClass(i))->SiDans(aPoint);
639     if (cur == 0)
640     {
641       // Point is ON, but mark it as OUT
642       isOut = Standard_True;
643     }
644     else
645     {
646       isOut = TabOrien(i)? (cur == -1) : (cur == 1);
647     }
648     if (isOut) return TopAbs_OUT;
649   }
650
651   return TopAbs_IN;
652 }
653
654
655 //=======================================================================
656 //function : Destroy
657 //purpose  : 
658 //=======================================================================
659
660 void BRepMesh_Classifier::Destroy()
661 {
662   Standard_Integer i, nb = TabClass.Length();
663   for (i = 1; i <= nb; i++)
664   {
665     if (TabClass(i))
666     {
667       delete ((CSLib_Class2d*)TabClass(i));
668       TabClass(i) = NULL;
669     }
670   }
671 }