1 // Created on: 1993-11-04
2 // Created by: Jean Marc LACHAUME
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
18 #include <Geom2dAdaptor_Curve.hxx>
19 #include <Geom2dHatch_Classifier.hxx>
20 #include <Geom2dHatch_Element.hxx>
21 #include <Geom2dHatch_Hatcher.hxx>
22 #include <Geom2dHatch_Hatching.hxx>
23 #include <Geom2dHatch_Intersector.hxx>
24 #include <HatchGen_Domain.hxx>
25 #include <HatchGen_Domains.hxx>
26 #include <HatchGen_PointOnElement.hxx>
27 #include <HatchGen_PointOnHatching.hxx>
28 #include <IntRes2d_IntersectionPoint.hxx>
29 #include <IntRes2d_IntersectionSegment.hxx>
30 #include <IntRes2d_Transition.hxx>
31 #include <Precision.hxx>
32 #include <Standard_NoSuchObject.hxx>
33 #include <Standard_OutOfRange.hxx>
34 #include <StdFail_NotDone.hxx>
36 #include <TopTrans_CurveTransition.hxx>
38 #define RAISE_IF_NOSUCHOBJECT 0
39 #define TRACE_HATCHER 0
41 //=======================================================================
42 //=======================================================================
43 // Category : General use.
44 //=======================================================================
45 //=======================================================================
47 //=======================================================================
48 // Function : Geom2dHatch_Hatcher
49 // Purpose : Constructor.
50 //=======================================================================
52 Geom2dHatch_Hatcher::Geom2dHatch_Hatcher (const Geom2dHatch_Intersector& Intersector,
53 const Standard_Real Confusion2d,
54 const Standard_Real Confusion3d,
55 const Standard_Boolean KeepPnt,
56 const Standard_Boolean KeepSeg) :
57 myIntersector (Intersector) ,
58 myConfusion2d (Confusion2d) ,
59 myConfusion3d (Confusion3d) ,
60 myKeepPoints (KeepPnt) ,
61 myKeepSegments (KeepSeg) ,
67 //=======================================================================
68 // Function : Intersector
69 // Purpose : Sets the associated intersector.
70 //=======================================================================
72 void Geom2dHatch_Hatcher::Intersector (const Geom2dHatch_Intersector& Intersector)
74 myIntersector = Intersector ;
75 for (Standard_Integer IndH = 1 ; IndH <= myNbHatchings ; IndH++) {
76 if (myHatchings.IsBound (IndH)) {
77 Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind (IndH) ;
78 Hatching.ClrPoints() ;
84 //=======================================================================
85 // Function : Confusion2d
86 // Purpose : Sets the 2dconfusion tolerance.
87 //=======================================================================
89 void Geom2dHatch_Hatcher::Confusion2d (const Standard_Real Confusion)
91 myConfusion2d = Confusion ;
92 for (Standard_Integer IndH = 1 ; IndH <= myNbHatchings ; IndH++) {
93 if (myHatchings.IsBound (IndH)) {
94 Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind (IndH) ;
95 Hatching.ClrPoints() ;
101 //=======================================================================
102 // Function : Confusion3d
103 // Purpose : Sets the 3d confusion tolerance.
104 //=======================================================================
106 void Geom2dHatch_Hatcher::Confusion3d (const Standard_Real Confusion)
108 myConfusion3d = Confusion ;
109 for (Standard_Integer IndH = 1 ; IndH <= myNbHatchings ; IndH++) {
110 if (myHatchings.IsBound (IndH)) {
111 Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind (IndH) ;
112 Hatching.ClrPoints() ;
117 //=======================================================================
118 // Function : KeepPoints
119 // Purpose : Sets the above flag.
120 //=======================================================================
122 void Geom2dHatch_Hatcher::KeepPoints (const Standard_Boolean Keep)
124 myKeepPoints = Keep ;
125 for (Standard_Integer IndH = 1 ; IndH <= myNbHatchings ; IndH++) {
126 if (myHatchings.IsBound (IndH)) {
127 Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind (IndH) ;
128 Hatching.ClrDomains() ;
134 //=======================================================================
135 // Function : KeepSegments
136 // Purpose : Sets the above flag.
137 //=======================================================================
139 void Geom2dHatch_Hatcher::KeepSegments (const Standard_Boolean Keep)
141 myKeepSegments = Keep ;
142 for (Standard_Integer IndH = 1 ; IndH <= myNbHatchings ; IndH++) {
143 if (myHatchings.IsBound (IndH)) {
144 Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind (IndH) ;
145 Hatching.ClrDomains() ;
152 //=======================================================================
153 //=======================================================================
154 // Category : Element.
155 //=======================================================================
156 //=======================================================================
159 //=======================================================================
160 // Function : AddElement
161 // Purpose : Adds an element to the Hatcher and returns its index.
162 //=======================================================================
164 Standard_Integer Geom2dHatch_Hatcher::AddElement (const Geom2dAdaptor_Curve& Curve,
165 const TopAbs_Orientation Orientation)
167 Standard_Integer IndE ;
168 for (IndE = 1 ; IndE <= myNbElements && myElements.IsBound(IndE) ; IndE++) ;
169 if (IndE > myNbElements) {
171 IndE = myNbElements ;
173 Geom2dHatch_Element Element (Curve, Orientation) ;
174 myElements.Bind (IndE, Element) ;
175 for (Standard_Integer IndH = 1 ; IndH <= myNbHatchings; IndH++) {
176 if (myHatchings.IsBound(IndH)) {
177 Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind (IndH) ;
178 Hatching.ClrPoints () ;
184 //=======================================================================
185 // Function : RemElement
186 // Purpose : Removes the IndE-th element from the hatcher.
187 //=======================================================================
189 void Geom2dHatch_Hatcher::RemElement (const Standard_Integer IndE)
191 #if RAISE_IF_NOSUCHOBJECT
192 Standard_NoSuchObject_Raise_if (!myElements.IsBound (IndE), "") ;
194 for (Standard_Integer IndH = 1 ; IndH <= myNbHatchings ; IndH++) {
195 if (myHatchings.IsBound (IndH)) {
196 Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind (IndH) ;
197 Standard_Boolean DomainsToClear = Standard_False ;
198 for (Standard_Integer IPntH = Hatching.NbPoints() ; IPntH > 0 ; IPntH--) {
199 HatchGen_PointOnHatching PntH = Hatching.ChangePoint (IPntH) ;
200 for (Standard_Integer IPntE = PntH.NbPoints() ; IPntE > 0 ; IPntE--) {
201 if (PntH.Point(IPntE).Index() == IndE) {
202 PntH.RemPoint (IPntE) ;
203 DomainsToClear = Standard_True ;
206 if (PntH.NbPoints() == 0) Hatching.RemPoint (IPntH) ;
208 if (DomainsToClear) Hatching.ClrDomains() ;
211 myElements.UnBind (IndE) ;
212 if (IndE == myNbElements) myNbElements-- ;
215 //=======================================================================
216 // Function : ClrElements
217 // Purpose : Removes all the elements from the hatcher.
218 //=======================================================================
220 void Geom2dHatch_Hatcher::ClrElements ()
222 if (myNbElements != 0) {
223 if (myNbHatchings != 0) {
224 for (Standard_Integer IndH = 1 ; IndH <= myNbHatchings ; IndH++) {
225 if (myHatchings.IsBound(IndH)) {
226 Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind (IndH) ;
227 Hatching.ClrPoints() ;
236 //=======================================================================
237 //=======================================================================
238 // Category : Hatching.
239 //=======================================================================
240 //=======================================================================
243 //=======================================================================
244 // Function : AddHatching
245 // Purpose : Adds a hatching to the hatcher and returns its index.
246 //=======================================================================
248 Standard_Integer Geom2dHatch_Hatcher::AddHatching (const Geom2dAdaptor_Curve& Curve)
250 Standard_Integer IndH ;
251 for (IndH = 1 ; IndH <= myNbHatchings && myHatchings.IsBound(IndH) ; IndH++) ;
252 if (IndH > myNbHatchings) {
254 IndH = myNbHatchings ;
256 Geom2dHatch_Hatching Hatching (Curve) ;
257 myHatchings.Bind (IndH, Hatching) ;
261 //=======================================================================
262 // Function : RemHatching
263 // Purpose : Removes the IndH-th hatching from the hatcher.
264 //=======================================================================
266 void Geom2dHatch_Hatcher::RemHatching (const Standard_Integer IndH)
268 #if RAISE_IF_NOSUCHOBJECT
269 Standard_NoSuchObject_Raise_if (!myHatchings.IsBound (IndH), "") ;
271 Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind (IndH) ;
272 Hatching.ClrPoints() ;
273 myHatchings.UnBind (IndH) ;
274 if (IndH == myNbHatchings) myNbHatchings-- ;
277 //=======================================================================
278 // Function : ClrHatchings
279 // Purpose : Removes all the hatchings from the hatcher.
280 //=======================================================================
282 void Geom2dHatch_Hatcher::ClrHatchings ()
284 if (myNbHatchings != 0) {
285 for (Standard_Integer IndH = 1 ; IndH <= myNbHatchings ; IndH++) {
286 if (myHatchings.IsBound(IndH)) {
287 Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind (IndH) ;
288 Hatching.ClrPoints() ;
291 myHatchings.Clear() ;
298 //=======================================================================
299 //=======================================================================
300 // Category : Computation - Trimming
301 //=======================================================================
302 //=======================================================================
304 //=======================================================================
306 // Purpose : Trims all the hatchings of the hatcher by all the elements
308 //=======================================================================
310 void Geom2dHatch_Hatcher::Trim ()
312 for (Standard_Integer IndH = 1 ; IndH <= myNbHatchings ; IndH++)
313 if (myHatchings.IsBound (IndH))
317 //=======================================================================
319 // Purpose : Adds a hatching to the hatcher and trims it by the elements
320 // already given and returns its index.
321 //=======================================================================
323 Standard_Integer Geom2dHatch_Hatcher::Trim (const Geom2dAdaptor_Curve& Curve)
325 Standard_Integer IndH = AddHatching (Curve) ;
330 //=======================================================================
332 // Purpose : Trims the IndH-th hatching by the elements already given.
333 //=======================================================================
335 void Geom2dHatch_Hatcher::Trim (const Standard_Integer IndH)
337 #if RAISE_IF_NOSUCHOBJECT
338 Standard_NoSuchObject_Raise_if (!myHatchings.IsBound (IndH), "") ;
341 Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind (IndH) ;
343 Hatching.ClrPoints() ;
345 Standard_Boolean OK, AllOK ;
347 AllOK = Standard_True ;
348 for (Standard_Integer IndE = 1 ; IndE <= myNbElements ; IndE++) {
349 if (myElements.IsBound (IndE)) {
350 OK = Trim (IndH, IndE) ;
351 AllOK = AllOK && OK ;
354 Hatching.TrimDone (Standard_True) ;
355 Hatching.TrimFailed (!AllOK) ;
358 for (Standard_Integer IPnt = 1 ; IPnt <= Hatching.NbPoints() ; IPnt++) {
359 HatchGen_PointOnHatching& PntH = Hatching.ChangePoint(IPnt) ;
360 OK = GlobalTransition (PntH) ;
361 AllOK = AllOK && OK ;
363 Hatching.Status (AllOK ? HatchGen_NoProblem : HatchGen_TransitionFailure) ;
369 //=======================================================================
370 // Function : IntersectionPointDump
371 // Purpose : Dump of the intersection point.
372 //=======================================================================
374 static void IntersectionPointDump (const IntRes2d_IntersectionPoint& Pnt,
375 const Standard_Integer Index)
377 Standard_Integer SavedPrecision = cout.precision() ;
378 cout.precision (15) ;
379 cout << "----- IntRes2d:: Point # " << setw(3) << Index << " ---------------" << endl ;
380 cout << "-- U: "<<Pnt.Value().X()<<" V: "<<Pnt.Value().Y()<<endl;
381 cout << "-- Parameter on first : " << Pnt.ParamOnFirst() << endl ;
382 cout << "-- Position on first : " ;
383 switch (Pnt.TransitionOfFirst().PositionOnCurve()) {
384 case IntRes2d_Head : cout << "HEAD" ; break ;
385 case IntRes2d_Middle : cout << "MIDDLE" ; break ;
386 case IntRes2d_End : cout << "END" ; break ;
389 cout << "-- IntRes2d:: Transition on first : " ;
390 switch (Pnt.TransitionOfFirst().TransitionType()) {
391 case IntRes2d_In : cout << "IN" ; break ;
392 case IntRes2d_Out : cout << "OUT" ; break ;
393 case IntRes2d_Touch : cout << "TOUCH" ; break ;
394 case IntRes2d_Undecided : cout << "UNDECIDED" ; break ;
397 if (Pnt.TransitionOfFirst().TransitionType() == IntRes2d_Touch) {
398 cout << "-- IntRes2d:: Situation on first : " ;
399 switch (Pnt.TransitionOfFirst().Situation()) {
400 case IntRes2d_Inside : cout << "INSIDE" ; break ;
401 case IntRes2d_Outside : cout << "OUTSIDE" ; break ;
402 case IntRes2d_Unknown : cout << "UNKNOWN" ; break ;
406 cout << "--------------------------------------------" << endl ;
407 cout << "-- Parameter on second : " << Pnt.ParamOnSecond() << endl ;
408 cout << "-- Position on second : " ;
409 switch (Pnt.TransitionOfSecond().PositionOnCurve()) {
410 case IntRes2d_Head : cout << "HEAD" ; break ;
411 case IntRes2d_Middle : cout << "MIDDLE" ; break ;
412 case IntRes2d_End : cout << "END" ; break ;
415 cout << "-- IntRes2d:: Transition on second : " ;
416 switch (Pnt.TransitionOfSecond().TransitionType()) {
417 case IntRes2d_In : cout << "IN" ; break ;
418 case IntRes2d_Out : cout << "OUT" ; break ;
419 case IntRes2d_Touch : cout << "TOUCH" ; break ;
420 case IntRes2d_Undecided : cout << "UNDECIDED" ; break ;
423 if (Pnt.TransitionOfSecond().TransitionType() == IntRes2d_Touch) {
424 cout << "-- IntRes2d:: Situation on second : " ;
425 switch (Pnt.TransitionOfSecond().Situation()) {
426 case IntRes2d_Inside : cout << "INSIDE" ; break ;
427 case IntRes2d_Outside : cout << "OUTSIDE" ; break ;
428 case IntRes2d_Unknown : cout << "UNKNOWN" ; break ;
432 cout << "--------------------------------------------" << endl ;
433 cout.precision (SavedPrecision) ;
438 //=======================================================================
440 // Purpose : Trims the IndH-th hatching of the hatcher by the IndE th
442 //=======================================================================
444 Standard_Boolean Geom2dHatch_Hatcher::Trim (const Standard_Integer IndH,
445 const Standard_Integer IndE)
447 #if RAISE_IF_NOSUCHOBJECT
448 Standard_NoSuchObject_Raise_if (!myHatchings.IsBound (IndH), "") ;
449 Standard_NoSuchObject_Raise_if (!myElements.IsBound (IndE), "") ;
452 Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind (IndH) ;
453 Geom2dHatch_Element& Element = myElements.ChangeFind (IndE) ;
455 Geom2dAdaptor_Curve hatching = Hatching.ChangeCurve() ;
456 Geom2dAdaptor_Curve element = Element.ChangeCurve() ;
458 myIntersector.Intersect (hatching, element) ;
461 cout << "--- Hatcher - Trim:: Hatching # " << setw(3);
462 cout << IndH << " with Element # " << setw(3);
463 cout << IndE << " ----------" << endl ;
466 if (!myIntersector.IsDone()) {
467 cout<<" Intersector -> Done = False ";
468 return Standard_False ;
472 if (myIntersector.IsEmpty()) {
473 cout << "No intersection" << endl ;
474 cout << "--------------------------------------------------------------------" << endl ;
478 if (myIntersector.IsEmpty()) return Standard_True ;
481 cout << "Number of intersection points : " << setw(3) << (myIntersector.NbPoints()) << endl ;
482 cout << "Number of intersection segments : " << setw(3) << (myIntersector.NbSegments()) << endl ;
485 //-----------------------------------------------------------------------
486 // Traitement des points d intersection.
487 //-----------------------------------------------------------------------
489 for (Standard_Integer IPntI = 1 ; IPntI <= myIntersector.NbPoints() ; IPntI++) {
490 const IntRes2d_IntersectionPoint& PntI = myIntersector.Point (IPntI) ;
493 IntersectionPointDump (PntI, IPntI) ;
496 HatchGen_PointOnElement PntE (PntI) ;
497 PntE.SetIndex (IndE) ;
499 HatchGen_PointOnHatching PntH (PntI) ;
500 PntH.SetIndex (IndH) ;
501 PntH.AddPoint (PntE, myConfusion2d) ;
503 Hatching.AddPoint (PntH, myConfusion2d) ;
506 //-----------------------------------------------------------------------
507 // Traitement des segments d intersection.
508 //-----------------------------------------------------------------------
510 for (Standard_Integer ISeg = 1 ; ISeg <= myIntersector.NbSegments() ; ISeg++) {
512 const IntRes2d_IntersectionSegment& Seg = myIntersector.Segment (ISeg) ;
515 cout << "----- Segment # " << setw(3) << ISeg << " -------------" << endl ;
518 Standard_Boolean FirstPoint = Seg.HasFirstPoint() ;
519 Standard_Boolean LastPoint = Seg.HasLastPoint() ;
521 //-----------------------------------------------------------------------
522 // Les deux points peuvent etre confondus.
523 //-----------------------------------------------------------------------
525 if (FirstPoint && LastPoint) {
527 const IntRes2d_IntersectionPoint& Pnt1 = Seg.FirstPoint() ;
528 const IntRes2d_IntersectionPoint& Pnt2 = Seg.LastPoint() ;
530 const IntRes2d_Transition& TrsPnt1H = Pnt1.TransitionOfFirst() ;
531 const IntRes2d_Transition& TrsPnt1E = Pnt1.TransitionOfSecond() ;
532 const IntRes2d_Transition& TrsPnt2H = Pnt2.TransitionOfFirst() ;
533 const IntRes2d_Transition& TrsPnt2E = Pnt2.TransitionOfSecond() ;
535 IntRes2d_TypeTrans TypePnt1H = TrsPnt1H.TransitionType() ;
536 IntRes2d_TypeTrans TypePnt1E = TrsPnt1E.TransitionType() ;
537 IntRes2d_TypeTrans TypePnt2H = TrsPnt2H.TransitionType() ;
538 IntRes2d_TypeTrans TypePnt2E = TrsPnt2E.TransitionType() ;
540 //-----------------------------------------------------------------------
541 // Les deux points peuvent etre confondus au regard de la precision du
543 //-----------------------------------------------------------------------
545 Standard_Boolean Conf2d = Abs (Pnt1.ParamOnFirst() - Pnt2.ParamOnFirst()) <= myConfusion2d ;
547 //-----------------------------------------------------------------------
548 // Les deux points peuvent etre `confondus' au regard des intersections.
549 //-----------------------------------------------------------------------
551 Standard_Boolean Conf3d = Standard_False ;
554 Conf3d = Standard_True ;
555 if (Conf3d) Conf3d = TypePnt1H != IntRes2d_Touch && TypePnt1H != IntRes2d_Undecided ;
556 if (Conf3d) Conf3d = TypePnt1E != IntRes2d_Touch && TypePnt1E != IntRes2d_Undecided ;
557 if (Conf3d) Conf3d = TypePnt2H != IntRes2d_Touch && TypePnt2H != IntRes2d_Undecided ;
558 if (Conf3d) Conf3d = TypePnt2E != IntRes2d_Touch && TypePnt2E != IntRes2d_Undecided ;
559 if (Conf3d) Conf3d = TypePnt1H == TypePnt2H && TypePnt1E == TypePnt2E ;
560 if (Conf3d) Conf3d = Pnt1.Value().Distance (Pnt2.Value()) <= myConfusion3d ;
563 if (Conf2d || Conf3d) {
565 HatchGen_PointOnElement PntE ;
566 PntE.SetIndex (IndE) ;
567 PntE.SetParameter ((Pnt1.ParamOnSecond() + Pnt2.ParamOnSecond()) / 2.) ;
568 switch (TrsPnt1E.PositionOnCurve()) {
569 case IntRes2d_Head: {
570 PntE.SetPosition(TopAbs_FORWARD) ;
573 case IntRes2d_Middle: {
574 switch (TrsPnt2E.PositionOnCurve()) {
575 case IntRes2d_Head: {
576 PntE.SetPosition (TopAbs_FORWARD);
579 case IntRes2d_Middle: {
580 PntE.SetPosition (TopAbs_INTERNAL) ;
584 PntE.SetPosition (TopAbs_REVERSED) ;
594 PntE.SetPosition(TopAbs_REVERSED) ;
601 PntE.SetIntersectionType
602 ((PntE.Position() == TopAbs_INTERNAL) ? HatchGen_TRUE : HatchGen_TOUCH) ;
603 PntE.SetStateBefore ((TypePnt1H == IntRes2d_In) ? TopAbs_OUT : TopAbs_IN) ;
604 PntE.SetStateAfter ((TypePnt2H == IntRes2d_In) ? TopAbs_OUT : TopAbs_IN) ;
606 HatchGen_PointOnHatching PntH ;
607 PntH.SetIndex (IndH) ;
608 PntH.SetParameter ((Pnt1.ParamOnFirst() + Pnt2.ParamOnFirst()) / 2.) ;
609 switch (TrsPnt1H.PositionOnCurve()) {
610 case IntRes2d_Head: {
611 PntH.SetPosition (TopAbs_FORWARD) ;
614 case IntRes2d_Middle: {
615 switch (TrsPnt2H.PositionOnCurve()) {
616 case IntRes2d_Head: {
617 PntH.SetPosition (TopAbs_FORWARD) ;
620 case IntRes2d_Middle: {
621 PntH.SetPosition (TopAbs_INTERNAL) ;
625 PntH.SetPosition (TopAbs_REVERSED) ;
635 PntH.SetPosition (TopAbs_REVERSED) ;
643 PntH.AddPoint (PntE, myConfusion2d) ;
644 Hatching.AddPoint (PntH, myConfusion2d) ;
647 IntersectionPointDump (Pnt1, 1) ;
648 IntersectionPointDump (Pnt2, 2) ;
649 cout << "THESE TWO POINTS ARE "
650 << (Conf2d ? "2D" : "3D")
651 << " CONFUSED INTO THE FOLLOWING" << endl ;
658 //-----------------------------------------------------------------------
659 // Traitement du premier point du segment.
660 //-----------------------------------------------------------------------
664 const IntRes2d_IntersectionPoint& PntI = Seg.FirstPoint() ;
667 IntersectionPointDump (PntI, 1) ;
670 HatchGen_PointOnElement PntE (PntI) ;
671 PntE.SetIndex (IndE) ;
672 PntE.SetSegmentBeginning (Standard_True) ;
673 PntE.SetSegmentEnd (Standard_False) ;
675 HatchGen_PointOnHatching PntH (PntI) ;
676 PntH.SetIndex (IndH) ;
677 PntH.AddPoint (PntE, myConfusion2d) ;
679 Hatching.AddPoint (PntH, myConfusion2d) ;
684 cout << "----- Has no first point --------" << endl ;
685 cout << "---------------------------------" << endl ;
690 //-----------------------------------------------------------------------
691 // Traitement du deuxieme point du segment.
692 //-----------------------------------------------------------------------
696 const IntRes2d_IntersectionPoint& PntI = Seg.LastPoint() ;
699 IntersectionPointDump (PntI, 2) ;
702 HatchGen_PointOnElement PntE (PntI) ;
703 PntE.SetIndex (IndE) ;
704 PntE.SetSegmentBeginning (Standard_False) ;
705 PntE.SetSegmentEnd (Standard_True) ;
707 HatchGen_PointOnHatching PntH (PntI) ;
708 PntH.SetIndex (IndH) ;
709 PntH.AddPoint (PntE, myConfusion2d) ;
711 Hatching.AddPoint (PntH, myConfusion2d) ;
716 cout << "----- Has no last point ---------" << endl ;
717 cout << "---------------------------------" << endl ;
722 cout << "--------------------------------------------------------------------" << endl ;
726 return Standard_True;
728 //=======================================================================
729 //=======================================================================
730 // Category : Computation - Domains
731 //=======================================================================
732 //=======================================================================
734 //=======================================================================
735 // Function : GlobalTransition
736 // Purpose : Returns the before and after states of the complex
737 // transition of the IndP-th intersection point of the
739 //=======================================================================
741 Standard_Boolean Geom2dHatch_Hatcher::GlobalTransition (HatchGen_PointOnHatching& Point)
743 TopAbs_State StateBefore = TopAbs_UNKNOWN ;
744 TopAbs_State StateAfter = TopAbs_UNKNOWN ;
745 Standard_Boolean SegmentBegin = Standard_False ;
746 Standard_Boolean SegmentEnd = Standard_False ;
748 gp_Dir2d Tangente2d, Normale2d ;
749 gp_Dir Tangente, Normale ;
750 Standard_Real Courbure ;
752 const Geom2dAdaptor_Curve& CurveH = HatchingCurve (Point.Index()) ;
754 myIntersector.LocalGeometry(CurveH.Curve(), Point.Parameter(), Tangente2d, Normale2d, Courbure);
756 Tangente.SetCoord (Tangente2d.X(), Tangente2d.Y(), 0.0) ;
757 if (Courbure < Precision::Confusion()) {
758 Normale.SetCoord (-Tangente2d.Y(), Tangente2d.X(), 0.0) ;
760 Normale.SetCoord (Normale2d.X(), Normale2d.Y(), 0.0) ;
763 TopTrans_CurveTransition ComplexTransition ;
764 ComplexTransition.Reset (Tangente, Normale, Courbure) ;
767 printf("\n ----- Global Transition Complex Transition Reset \n");
768 printf("\n P:%+10.5g Tg2d:%+10.5g , %+10.5g N2d:%+10.5g , %+10.5g Crv:%+10.5g\n\n",
769 Point.Parameter(),Tangente.X(),Tangente.Y(),Normale.X(),Normale.Y(),Courbure);
771 for (Standard_Integer IPntE = 1 ; IPntE <= Point.NbPoints() ; IPntE++)
773 const HatchGen_PointOnElement& PntE = Point.Point (IPntE) ;
775 SegmentBegin = SegmentBegin || PntE.SegmentBeginning() ;
776 SegmentEnd = SegmentEnd || PntE.SegmentEnd() ;
778 const Geom2dHatch_Element& Element = myElements.Find (PntE.Index()) ;
779 const Geom2dAdaptor_Curve& CurveE = Element.Curve() ;
781 TopAbs_Orientation ElementOrientation = Element.Orientation() ;
782 Standard_Boolean ToReverse = (ElementOrientation == TopAbs_REVERSED);
783 Standard_Real Param ;
784 switch (PntE.Position())
786 case TopAbs_FORWARD :
787 Param = ToReverse ? CurveE.LastParameter() : CurveE.FirstParameter() ;
790 case TopAbs_INTERNAL :
791 Param = PntE.Parameter() ;
794 case TopAbs_REVERSED :
795 Param = ToReverse ? CurveE.FirstParameter() : CurveE.LastParameter() ;
804 printf("\n ******** ToReverse: %d Param : %g ANParam : %g \n",ToReverse,Param,PntE.Parameter());
806 Param = PntE.Parameter();
808 myIntersector.LocalGeometry(CurveE.Curve(), Param, Tangente2d, Normale2d, Courbure);
810 //-----------------------------------------------------------------------
811 // Calcul de la transition locale. On suppose les relations suivantes :
812 // - Si l orientation de l element est INTERNAL ==> INTERNAL
813 // - Si l orientation de l element est EXTERNAL ==> EXTERNAL
814 // - Si tangence, on a IN-IN ou OUT-OUT ==> INTERNAL/EXTERNAL
815 // - Sinon, on a IN-OUT ou OUT-IN ==> REVERSED/FORWARD
816 // Les deux dernieres conditions avec l element vu en FORWARD.
817 //-----------------------------------------------------------------------
818 TopAbs_Orientation LocalTransition = TopAbs_EXTERNAL;
820 if (ElementOrientation == TopAbs_INTERNAL)
821 LocalTransition = TopAbs_INTERNAL ;
823 else if (ElementOrientation == TopAbs_EXTERNAL)
824 LocalTransition = TopAbs_EXTERNAL ;
826 else if (PntE.IntersectionType() == HatchGen_TANGENT)
828 if (PntE.Position() == TopAbs_INTERNAL)
830 switch (PntE.StateBefore())
832 case TopAbs_IN : LocalTransition = ToReverse ? TopAbs_EXTERNAL : TopAbs_INTERNAL ; break ;
833 case TopAbs_OUT : LocalTransition = ToReverse ? TopAbs_INTERNAL : TopAbs_EXTERNAL ; break ;
839 switch (PntE.StateBefore())
841 case TopAbs_IN : LocalTransition = ToReverse ? TopAbs_FORWARD : TopAbs_REVERSED ; break ;
842 case TopAbs_OUT : LocalTransition = ToReverse ? TopAbs_REVERSED : TopAbs_FORWARD ; break ;
849 switch (PntE.StateBefore())
851 case TopAbs_IN : LocalTransition = ToReverse ? TopAbs_FORWARD : TopAbs_REVERSED ; break ;
852 case TopAbs_OUT : LocalTransition = ToReverse ? TopAbs_REVERSED : TopAbs_FORWARD ; break ;
857 //-----------------------------------------------------------------------
858 // Orientation de la tangente au point d interference.
859 //-----------------------------------------------------------------------
860 TopAbs_Orientation TangenteOrientation = TopAbs_FORWARD;
861 switch (PntE.Position())
863 case TopAbs_FORWARD : TangenteOrientation = ToReverse ? TopAbs_REVERSED : TopAbs_FORWARD ; break ;
864 case TopAbs_INTERNAL : TangenteOrientation = TopAbs_INTERNAL ; break ;
865 case TopAbs_REVERSED : TangenteOrientation = ToReverse ? TopAbs_FORWARD : TopAbs_REVERSED ; break ;
871 //-----------------------------------------------------------------------
872 // Proprietes geometriques.
873 //-----------------------------------------------------------------------
876 Tangente.SetCoord (-Tangente2d.X(), -Tangente2d.Y(), 0.0) ;
878 Tangente.SetCoord ( Tangente2d.X(), Tangente2d.Y(), 0.0) ;
880 Normale.SetCoord ( Normale2d.X(), Normale2d.Y(), 0.0) ;
883 printf("\n \n----- Global Transition Complex Transition Compare" );
884 char *str1 = " ??? ";
885 char *str2 = " ??? ";
886 if(LocalTransition == TopAbs_INTERNAL) str1=" INTERNAL ";
887 if(LocalTransition == TopAbs_REVERSED) str1=" REVERSED ";
888 if(LocalTransition == TopAbs_FORWARD) str1=" FORWARD ";
890 if(TangenteOrientation == TopAbs_INTERNAL) str2=" INTERNAL ";
891 if(TangenteOrientation == TopAbs_REVERSED) str2=" REVERSED ";
892 if(TangenteOrientation == TopAbs_FORWARD) str2=" FORWARD ";
894 printf("\n P:%+10.5g Tg2d:%+10.5g , %+10.5g N2d:%+10.5g , %+10.5g Crv:%+10.5g LocalTr:%s TangOrie:%s\n",
895 Param,Tangente.X(),Tangente.Y(),Normale.X(),Normale.Y(),Courbure,str1,str2);
898 ComplexTransition.Compare (Precision::Angular(),
899 Tangente, Normale, Courbure,
900 LocalTransition, TangenteOrientation) ;
903 switch (ComplexTransition.StateBefore()) {
904 case TopAbs_IN : StateBefore = TopAbs_IN ; break ;
905 case TopAbs_OUT : StateBefore = TopAbs_OUT ; break ;
906 case TopAbs_ON : return Standard_False ;
907 case TopAbs_UNKNOWN : return Standard_False ;
909 switch (ComplexTransition.StateAfter()) {
910 case TopAbs_IN : StateAfter = TopAbs_IN ; break ;
911 case TopAbs_OUT : StateAfter = TopAbs_OUT ; break ;
912 case TopAbs_ON : return Standard_False ;
913 case TopAbs_UNKNOWN : return Standard_False ;
919 printf("\n --> StateBef :"); if(StateBefore==TopAbs_IN) printf(" IN "); else printf(" OUT ");
920 printf("\n --> StateAft :"); if(StateAfter==TopAbs_IN) printf(" IN "); else printf(" OUT ");
921 printf("\n------ Fin GlobalTransition\n");
924 Point.SetStateBefore (StateBefore) ;
925 Point.SetStateAfter (StateAfter) ;
926 Point.SetSegmentBeginning (SegmentBegin) ;
927 Point.SetSegmentEnd (SegmentEnd) ;
928 return Standard_True ;
931 //=======================================================================
932 // Function : ComputeDomains
933 // Purpose : Computes the domains of all the hatchings.
934 //=======================================================================
936 void Geom2dHatch_Hatcher::ComputeDomains ()
938 for (Standard_Integer IndH = 1 ; IndH <= myNbHatchings ; IndH++)
939 if (myHatchings.IsBound (IndH)) ComputeDomains (IndH) ;
942 //=======================================================================
943 // Function : ComputeDomains
944 // Purpose : Computes the domains of the IndH-th hatching.
945 //=======================================================================
947 void Geom2dHatch_Hatcher::ComputeDomains (const Standard_Integer IndH)
949 #if RAISE_IF_NOSUCHOBJECT
950 Standard_NoSuchObject_Raise_if (!myHatchings.IsBound (IndH), "") ;
953 Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind (IndH) ;
954 Hatching.ClrDomains() ;
956 Hatching.IsDone (Standard_False) ;
958 if (!Hatching.TrimDone())
961 if (Hatching.Status() != HatchGen_NoProblem)
964 Standard_Boolean Points = myKeepPoints ;
965 Standard_Boolean Segments = myKeepSegments ;
966 Standard_Integer ISav = 0 ;
967 Standard_Boolean SavPnt = Standard_False ;
968 Standard_Integer NbOpenedSegments = 0 ;
969 Standard_Integer NbPnt = Hatching.NbPoints() ;
970 Standard_Integer IPnt =1;
974 //-- cout << "The hatching # " << setw(3) << IndH << " has to be classified" << endl ;
975 Geom2dHatch_Classifier Classifier(myElements,Hatching.ClassificationPoint(),0.0000001);
976 if(Classifier.State() == TopAbs_IN)
978 HatchGen_Domain domain ;
979 Hatching.AddDomain (domain) ;
982 Hatching.IsDone (Standard_True) ;
986 //for (Standard_Integer IPnt = 1 ; IPnt <= NbPnt ; IPnt++) {
987 for (IPnt = 1 ; IPnt <= NbPnt ; IPnt++)
989 Standard_Boolean NoDomain = Hatching.NbDomains() == 0 ;
990 Standard_Boolean FirstPoint = IPnt == 1 ;
991 Standard_Boolean LastPoint = IPnt == NbPnt ;
993 const HatchGen_PointOnHatching& CurPnt = Hatching.Point (IPnt) ;
996 cout << "===== ComputeDomains:: Hatching # " << setw(3) << IndH << " =====" << endl ;
998 cout << "==========================================" << endl ;
1002 //-----------------------------------------------------------------------
1003 // Calcul des domaines.
1004 //-----------------------------------------------------------------------
1006 TopAbs_State StateBefore = CurPnt.StateBefore() ;
1007 TopAbs_State StateAfter = CurPnt.StateAfter() ;
1008 Standard_Boolean SegmentBegin = CurPnt.SegmentBeginning() ;
1009 Standard_Boolean SegmentEnd = CurPnt.SegmentEnd() ;
1011 HatchGen_Domain domain ;
1013 //-----------------------------------------------------------------------
1014 // Initialisations dues au premier point.
1015 //-----------------------------------------------------------------------
1019 SavPnt = Standard_False ;
1021 NbOpenedSegments = 0 ;
1022 if (SegmentEnd && SegmentBegin)
1024 if (StateAfter == TopAbs_UNKNOWN)
1025 StateAfter = TopAbs_IN ;
1026 if (StateBefore == TopAbs_UNKNOWN)
1027 StateBefore = TopAbs_IN ;
1031 SavPnt = Standard_True ;
1035 else if (SegmentEnd)
1037 if (StateAfter == TopAbs_UNKNOWN)
1038 StateAfter = TopAbs_IN ;
1042 SavPnt = Standard_True ;
1046 else if (SegmentBegin)
1048 if (StateBefore == TopAbs_UNKNOWN)
1049 StateBefore = TopAbs_IN ;
1050 if (StateBefore == TopAbs_IN)
1052 SavPnt = Standard_True ;
1058 if (StateBefore == TopAbs_IN)
1060 SavPnt = Standard_True ;
1066 //-----------------------------------------------------------------------
1067 // Initialisations dues au dernier point.
1068 //-----------------------------------------------------------------------
1072 if (SegmentEnd && SegmentBegin)
1074 if (StateAfter == TopAbs_UNKNOWN)
1075 StateAfter = TopAbs_IN ;
1077 if (StateBefore == TopAbs_UNKNOWN)
1078 StateBefore = TopAbs_IN ;
1080 else if (SegmentEnd)
1082 if (StateAfter == TopAbs_UNKNOWN)
1083 StateAfter = TopAbs_IN ;
1085 else if (SegmentBegin)
1087 if (StateBefore == TopAbs_UNKNOWN)
1088 StateBefore = TopAbs_IN ;
1095 //-----------------------------------------------------------------------
1097 //-----------------------------------------------------------------------
1099 Standard_Boolean ToAppend = Standard_False ;
1101 if (SegmentEnd && SegmentBegin)
1103 if (StateBefore != TopAbs_IN && StateAfter != TopAbs_IN)
1105 Hatching.Status (HatchGen_IncompatibleStates) ;
1117 Hatching.Status (HatchGen_IncoherentParity) ;
1121 Hatching.IsDone(Standard_True);
1127 domain.SetFirstPoint (Hatching.Point(ISav)) ;
1129 domain.SetSecondPoint (CurPnt) ;
1130 ToAppend = Standard_True ;
1131 SavPnt = Standard_True ;
1136 Standard_Boolean isININ = (StateBefore == TopAbs_IN && StateAfter == TopAbs_IN);
1137 if (SavPnt && !isININ)
1141 Hatching.Status (HatchGen_IncoherentParity) ;
1145 Hatching.IsDone(Standard_True);
1151 domain.SetPoints (CurPnt, CurPnt) ;
1152 ToAppend = Standard_True ;
1153 SavPnt = Standard_False ;
1158 else if (SegmentEnd)
1162 if (StateAfter == TopAbs_OUT)
1168 Hatching.Status (HatchGen_IncoherentParity) ;
1172 Hatching.IsDone(Standard_True);
1178 domain.SetFirstPoint (Hatching.Point(ISav)) ;
1180 domain.SetSecondPoint (CurPnt) ;
1181 ToAppend = Standard_True ;
1188 domain.SetFirstPoint (Hatching.Point(ISav)) ;
1190 domain.SetSecondPoint (CurPnt) ;
1191 ToAppend = Standard_True ;
1192 SavPnt = Standard_True ;
1199 if (StateAfter == TopAbs_IN)
1201 SavPnt = Standard_True ;
1206 NbOpenedSegments-- ;
1209 else if (SegmentBegin)
1213 if (StateBefore == TopAbs_OUT)
1215 SavPnt = Standard_True ;
1226 Hatching.Status (HatchGen_IncoherentParity) ;
1230 Hatching.IsDone(Standard_True);
1237 domain.SetFirstPoint (Hatching.Point(ISav)) ;
1239 domain.SetSecondPoint (CurPnt) ;
1240 ToAppend = Standard_True ;
1241 SavPnt = Standard_True ;
1248 if (StateBefore == TopAbs_IN)
1254 Hatching.Status (HatchGen_IncoherentParity) ;
1258 Hatching.IsDone(Standard_True);
1265 domain.SetFirstPoint (Hatching.Point(ISav)) ;
1267 domain.SetSecondPoint (CurPnt) ;
1268 ToAppend = Standard_True ;
1270 //Modified by Sergey KHROMOV - Fri Jan 5 12:05:30 2001
1271 //SavPnt = Standard_False ;
1274 SavPnt = Standard_True ;
1276 //Modified by Sergey KHROMOV - Fri Jan 5 12:05:31 2001
1280 NbOpenedSegments++ ;
1284 //-- ???????????????????????????????????????????????????????????????????????????
1285 //-- Solution provisoire (lbr le 11 Aout 97 )
1286 //-- si On a 2 points dont des points OUT OUT ou IN IN qui delimitent une isos
1287 //-- on transforme les transitions
1288 if (StateBefore == TopAbs_OUT && StateAfter == TopAbs_OUT)
1293 StateAfter = TopAbs_IN;
1295 StateBefore = TopAbs_IN;
1298 //-- ???????????????????????????????????????????????????????????????????????????
1299 if(StateBefore == TopAbs_OUT && StateAfter == TopAbs_OUT)
1305 Hatching.Status (HatchGen_IncoherentParity) ;
1309 Hatching.IsDone(Standard_True);
1317 domain.SetPoints (CurPnt, CurPnt) ;
1318 ToAppend = Standard_True ;
1319 SavPnt = Standard_True ;
1323 else if (StateBefore == TopAbs_OUT && StateAfter == TopAbs_IN )
1325 SavPnt = Standard_True ;
1328 else if (StateBefore == TopAbs_IN && StateAfter == TopAbs_OUT)
1334 Hatching.Status (HatchGen_IncoherentParity) ;
1338 Hatching.IsDone(Standard_True);
1345 domain.SetFirstPoint (Hatching.Point(ISav));
1347 domain.SetSecondPoint (CurPnt) ;
1348 ToAppend = Standard_True ;
1349 SavPnt = Standard_False ;
1352 else if (StateBefore == TopAbs_IN && StateAfter == TopAbs_IN )
1356 if (NbOpenedSegments == 0)
1362 Hatching.Status (HatchGen_IncoherentParity) ;
1366 Hatching.IsDone(Standard_True);
1374 domain.SetFirstPoint (Hatching.Point(ISav)) ;
1376 domain.SetSecondPoint (CurPnt) ;
1377 ToAppend = Standard_True ;
1378 SavPnt = Standard_True ;
1389 Hatching.Status (HatchGen_IncoherentParity) ;
1393 Hatching.IsDone(Standard_True);
1400 domain.SetFirstPoint (Hatching.Point(ISav)) ;
1402 domain.SetSecondPoint (CurPnt) ;
1403 ToAppend = Standard_True ;
1404 SavPnt = Standard_True ;
1413 Hatching.Status (HatchGen_IncoherentParity) ;
1417 Hatching.IsDone(Standard_True);
1423 domain.SetPoints (CurPnt, CurPnt) ;
1424 ToAppend = Standard_True ;
1425 SavPnt = Standard_False ;
1433 Hatching.Status (HatchGen_IncompatibleStates) ;
1438 //-----------------------------------------------------------------------
1439 // Ajout du domaine.
1440 //-----------------------------------------------------------------------
1443 Hatching.AddDomain (domain) ;
1445 //-----------------------------------------------------------------------
1446 // Traitement lie au dernier point.
1447 //-----------------------------------------------------------------------
1451 domain.SetPoints () ;
1452 ToAppend = Standard_False ;
1454 if (SegmentEnd && SegmentBegin)
1462 Hatching.Status (HatchGen_IncoherentParity) ;
1466 Hatching.IsDone(Standard_True);
1473 domain.SetFirstPoint (Hatching.Point(ISav)) ;
1475 ToAppend = Standard_True ;
1478 else if (SegmentEnd)
1480 if (StateAfter == TopAbs_IN)
1486 Hatching.Status (HatchGen_IncoherentParity) ;
1490 Hatching.IsDone(Standard_True);
1497 domain.SetFirstPoint (Hatching.Point(ISav)) ;
1499 ToAppend = Standard_True ;
1502 else if (SegmentBegin)
1510 Hatching.Status (HatchGen_IncoherentParity) ;
1514 Hatching.IsDone(Standard_True);
1521 domain.SetFirstPoint (Hatching.Point(ISav)) ;
1523 ToAppend = Standard_True ;
1528 if (StateAfter == TopAbs_IN)
1534 Hatching.Status (HatchGen_IncoherentParity) ;
1538 Hatching.IsDone(Standard_True);
1545 domain.SetFirstPoint (Hatching.Point(ISav)) ;
1547 ToAppend = Standard_True ;
1552 Hatching.AddDomain (domain) ;
1556 Hatching.IsDone(Standard_True) ;
1559 //=======================================================================
1560 //=======================================================================
1561 // Category : Results.
1562 //=======================================================================
1563 //=======================================================================
1566 //=======================================================================
1567 // Function : Domain
1568 // Purpose : Returns the IDom-th domain of the IndH-th hatching.
1569 //=======================================================================
1571 const HatchGen_Domain& Geom2dHatch_Hatcher::Domain (const Standard_Integer IndH,
1572 const Standard_Integer IDom) const
1574 #if RAISE_IF_NOSUCHOBJECT
1575 Standard_NoSuchObject_Raise_if (!myHatchings.IsBound (IndH), "") ;
1577 const Geom2dHatch_Hatching& Hatching = myHatchings.Find (IndH) ;
1578 StdFail_NotDone_Raise_if (!Hatching.IsDone(), "Geom2dHatch_Hatcher::Domain") ;
1579 #if RAISE_IF_NOSUCHOBJECT
1580 Standard_OutOfRange_Raise_if (IDom < 1 || IDom > Hatching.NbDomains(), "") ;
1582 const HatchGen_Domain& Domain = Hatching.Domain (IDom) ;
1586 //=======================================================================
1587 //=======================================================================
1589 //=======================================================================
1590 //=======================================================================
1592 //=======================================================================
1594 // Purpose : Dumps the hatcher.
1595 //=======================================================================
1597 void Geom2dHatch_Hatcher::Dump () const
1600 cout << "========================================================" << endl ;
1601 cout << "=== Dump of the hatcher ================================" << endl ;
1602 cout << "========================================================" << endl ;
1605 cout << "The points are "
1606 << (myKeepPoints ? " " : "not ")
1609 cout << "The segments are "
1610 << (myKeepSegments ? " " : "not ")
1613 cout << "2D Confusion tolerance : " << myConfusion2d << endl ;
1614 cout << "3D Confusion tolerance : " << myConfusion3d << endl ;
1616 cout << myNbHatchings
1618 << ((myNbHatchings == 1) ? "" : "s")
1620 cout << myNbElements
1622 << ((myNbElements == 1) ? "" : "s")
1626 cout << "========================================================" << endl ;
1627 cout << "=== Hatchings ==========================================" << endl ;
1628 cout << "========================================================" << endl ;
1631 for (Standard_Integer IndH = 1 ; IndH <= myNbHatchings ; IndH++) {
1632 cout << "Hatching # " << IndH ;
1633 if (!myHatchings.IsBound (IndH)) {
1634 cout << " is not bound" << endl ;
1636 const Geom2dHatch_Hatching& Hatching = myHatchings.Find (IndH) ;
1637 Standard_Integer NbPnt = Hatching.NbPoints() ;
1638 cout << " contains " << NbPnt << " restriction points :" << endl ;
1639 for (Standard_Integer IPnt = 1 ; IPnt <= NbPnt ; IPnt++) {
1640 const HatchGen_PointOnHatching& PntH = Hatching.Point (IPnt) ;
1643 cout << "----------------------------------------------" << endl ;
1648 cout << "========================================================" << endl ;
1649 cout << "=== Elements ===========================================" << endl ;
1650 cout << "========================================================" << endl ;
1653 for (Standard_Integer IndE = 1 ; IndE <= myNbElements ; IndE++) {
1654 cout << "Element # " << IndE ;
1655 if (!myElements.IsBound (IndE)) {
1656 cout << " is not bound" << endl ;
1658 const Geom2dHatch_Element& Element = myElements.Find (IndE) ;
1659 switch (Element.Orientation()) {
1660 case TopAbs_FORWARD : cout << " is FORWARD" << endl ; break ;
1661 case TopAbs_REVERSED : cout << " is REVERSED" << endl ; break ;
1662 case TopAbs_INTERNAL : cout << " is INTERNAL" << endl ; break ;
1663 case TopAbs_EXTERNAL : cout << " is EXTERNAL" << endl ; break ;