0031642: Visualization - crash in Graphic3d_Structure::SetVisual() on redisplaying...
[occt.git] / src / ShapeUpgrade / ShapeUpgrade_SplitCurve2dContinuity.cxx
1 // Created on: 1999-04-14
2 // Created by: Roman LYGIN
3 // Copyright (c) 1999-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <Geom2d_BSplineCurve.hxx>
19 #include <Geom2d_OffsetCurve.hxx>
20 #include <Geom2d_TrimmedCurve.hxx>
21 #include <Precision.hxx>
22 #include <ShapeExtend.hxx>
23 #include <ShapeUpgrade.hxx>
24 #include <ShapeUpgrade_SplitCurve2dContinuity.hxx>
25 #include <Standard_ErrorHandler.hxx>
26 #include <Standard_Failure.hxx>
27 #include <Standard_Type.hxx>
28 #include <TColGeom2d_HArray1OfCurve.hxx>
29 #include <TColStd_HSequenceOfReal.hxx>
30
31 IMPLEMENT_STANDARD_RTTIEXT(ShapeUpgrade_SplitCurve2dContinuity,ShapeUpgrade_SplitCurve2d)
32
33 //=======================================================================
34 //function : ShapeUpgrade_SplitCurve2dContinuity
35 //purpose  : 
36 //=======================================================================
37 ShapeUpgrade_SplitCurve2dContinuity::ShapeUpgrade_SplitCurve2dContinuity()
38 {
39   myCriterion = GeomAbs_C1;
40   myTolerance = Precision::PConfusion();
41   myCont =1;
42 }
43
44 //=======================================================================
45 //function : SetCriterion
46 //purpose  : 
47 //=======================================================================
48
49  void ShapeUpgrade_SplitCurve2dContinuity::SetCriterion(const GeomAbs_Shape Criterion) 
50 {
51   myCriterion = Criterion;
52   switch (myCriterion) {
53     case GeomAbs_C0 : myCont = 0; break;
54     case GeomAbs_C1 : myCont = 1; break;
55     case GeomAbs_C2 : myCont = 2; break;
56     case GeomAbs_C3 : myCont = 3; break;
57     case GeomAbs_CN : myCont = 4; break;
58     default         : myCont = 1;  
59   }
60 }
61
62 //=======================================================================
63 //function : SetTolerance
64 //purpose  : 
65 //=======================================================================
66
67  void ShapeUpgrade_SplitCurve2dContinuity::SetTolerance(const Standard_Real Tol) 
68 {
69   myTolerance = Tol;
70 }
71
72 //=======================================================================
73 //function : Compute
74 //purpose  : 
75 //=======================================================================
76
77 void ShapeUpgrade_SplitCurve2dContinuity::Compute()    
78
79   if(myCurve->Continuity() < myCriterion) 
80     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE2);
81   if (mySplitValues->Length() > 2)
82     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
83   Standard_Real precision = Precision::PConfusion();
84   Standard_Real First =  mySplitValues->Value(1);
85   Standard_Real Last = mySplitValues->Value(mySplitValues->Length());
86   if (myCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
87     Handle(Geom2d_TrimmedCurve) tmp = Handle(Geom2d_TrimmedCurve)::DownCast (myCurve);
88     Handle(Geom2d_Curve) BasCurve = tmp->BasisCurve();
89     ShapeUpgrade_SplitCurve2dContinuity spc;
90 //    spc.Init(BasCurve,Max(First,tmp->FirstParameter()),Min(Last,tmp->LastParameter())); 
91     spc.Init(BasCurve,First,Last);
92     spc.SetSplitValues(mySplitValues);
93     spc.SetTolerance(myTolerance);
94     spc.SetCriterion(myCriterion);
95     spc.Compute();
96     mySplitValues->Clear();
97     mySplitValues->ChangeSequence() = spc.SplitValues()->Sequence();
98     //mySplitValues = spc.SplitValues();
99     myStatus |= spc.myStatus;
100     return;
101   }
102   else if (myCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve))) {
103     GeomAbs_Shape BasCriterion;
104     switch (myCriterion) {
105       default         :
106       case GeomAbs_C1 : BasCriterion = GeomAbs_C2; break;
107       case GeomAbs_C2 : BasCriterion = GeomAbs_C3; break;
108       case GeomAbs_C3 : //if (ShapeUpgrade::Debug()) std::cout<<". this criterion is not suitable for a Offset curve"<<std::endl; 
109 #ifdef OCCT_DEBUG
110                         std::cout << "Warning: ShapeUpgrade_SplitCurve2dContinuity: criterion C3 for Offset curve" << std::endl; 
111 #endif
112       case GeomAbs_CN : BasCriterion = GeomAbs_CN; break;
113     }
114     Handle(Geom2d_OffsetCurve) tmp = Handle(Geom2d_OffsetCurve)::DownCast (myCurve);
115     Handle(Geom2d_Curve) BasCurve = tmp->BasisCurve();
116     //Standard_Real Offset = tmp->Offset(); // Offset not used (skl)
117     ShapeUpgrade_SplitCurve2dContinuity spc;
118 //    spc.Init(BasCurve,Max(tmp->FirstParameter(),First),Min(tmp->LastParameter(),Last));
119     spc.Init(BasCurve,First,Last);
120     spc.SetSplitValues(mySplitValues);
121     spc.SetTolerance(myTolerance);
122     spc.SetCriterion(BasCriterion); 
123     spc.Compute();
124     mySplitValues->Clear();
125     mySplitValues->ChangeSequence() = spc.SplitValues()->Sequence();
126     myStatus |= spc.myStatus;
127     return;
128   }
129
130   Handle(Geom2d_BSplineCurve) MyBSpline = Handle(Geom2d_BSplineCurve)::DownCast (myCurve);
131   if (MyBSpline.IsNull()) {
132 //    if (ShapeUpgrade::Debug()) std::cout<<". curve is not a Bspline"<<std::endl;
133     return;
134   }
135   
136   myNbCurves=1;
137   Standard_Integer Deg=MyBSpline->Degree();
138   Standard_Integer NbKnots= MyBSpline->NbKnots(); 
139 //  if (ShapeUpgrade::Debug()) std::cout<<". NbKnots="<<NbKnots<<std::endl;
140   if (NbKnots <= 2) {
141     return;
142   }
143   Standard_Integer FirstInd =MyBSpline->FirstUKnotIndex()+1,
144   LastInd = MyBSpline->LastUKnotIndex()-1;
145   Standard_Integer iknot = FirstInd;
146   for(Standard_Integer j =2; j <= mySplitValues->Length(); j++) {
147     Last =  mySplitValues->Value(j);
148     for (; iknot <= LastInd; iknot++) {
149       Standard_Real valknot = MyBSpline->Knot(iknot);
150       if(valknot <= First + precision) continue;
151       if(valknot >= Last - precision) break;
152       Standard_Integer Continuity=Deg-MyBSpline->Multiplicity(iknot);
153       //Standard_Real tt = MyBSpline->Knot(iknot); // tt not used (skl)
154       if (Continuity < myCont) { 
155         // At this knot, the curve is C0; try to remove Knot.
156         Standard_Boolean corrected = Standard_False;
157         Standard_Integer newMultiplicity = Deg - myCont;
158         if (newMultiplicity < 0) newMultiplicity = 0;
159         {
160           try {
161             OCC_CATCH_SIGNALS
162             corrected = MyBSpline->RemoveKnot(iknot, newMultiplicity, myTolerance);
163           }
164       catch (Standard_Failure const&) {
165             corrected = Standard_False;
166           }
167         }
168         if (corrected && newMultiplicity > 0) {
169          Continuity=Deg-MyBSpline->Multiplicity(iknot);
170          corrected = (Continuity >= myCont);
171         }
172         if (corrected) {
173           // at this knot, the continuity is now C1. Nothing else to do.
174 //        if (ShapeUpgrade::Debug()) std::cout<<". Correction at Knot "<<iknot<<std::endl;
175           myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
176         }
177         else {
178           // impossible to force C1 within the tolerance: 
179           // this knot will be a splitting value.
180           mySplitValues->InsertBefore(j++,MyBSpline->Knot(iknot));
181           myNbCurves++;
182 //        if (ShapeUpgrade::Debug()) std::cout<<". Splitting at Knot "<<iknot<<std::endl;
183         }
184       }
185     }
186     
187     First = Last;
188   }
189   
190   if (mySplitValues->Length() > 2)
191     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
192 }
193