0031668: Visualization - WebGL sample doesn't work on Emscripten 1.39
[occt.git] / src / ShapeUpgrade / ShapeUpgrade_SplitCurve3dContinuity.cxx
1 // Created on: 1999-04-15
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 <Geom_BSplineCurve.hxx>
19 #include <Geom_Curve.hxx>
20 #include <Geom_OffsetCurve.hxx>
21 #include <Geom_TrimmedCurve.hxx>
22 #include <Precision.hxx>
23 #include <ShapeExtend.hxx>
24 #include <ShapeUpgrade.hxx>
25 #include <ShapeUpgrade_SplitCurve3dContinuity.hxx>
26 #include <Standard_ErrorHandler.hxx>
27 #include <Standard_Failure.hxx>
28 #include <Standard_Type.hxx>
29 #include <TColGeom_HArray1OfCurve.hxx>
30 #include <TColStd_HSequenceOfReal.hxx>
31
32 IMPLEMENT_STANDARD_RTTIEXT(ShapeUpgrade_SplitCurve3dContinuity,ShapeUpgrade_SplitCurve3d)
33
34 //=======================================================================
35 //function : ShapeUpgrade_SplitCurve3dContinuity
36 //purpose  : 
37 //=======================================================================
38 ShapeUpgrade_SplitCurve3dContinuity::ShapeUpgrade_SplitCurve3dContinuity()
39 {
40   myCriterion = GeomAbs_C1;
41   myTolerance = Precision::Confusion();
42   myCont =1;
43 }
44
45 //=======================================================================
46 //function : SetCriterion
47 //purpose  : 
48 //=======================================================================
49
50  void ShapeUpgrade_SplitCurve3dContinuity::SetCriterion(const GeomAbs_Shape Criterion) 
51 {
52   myCriterion = Criterion;
53   switch (myCriterion) {
54     case GeomAbs_C0 : myCont = 0; break;
55     case GeomAbs_C1 : myCont = 1; break;
56     case GeomAbs_C2 : myCont = 2; break;
57     case GeomAbs_C3 : myCont = 3; break;
58     case GeomAbs_CN : myCont = 4; break;
59     default         : myCont = 1;
60   }
61 }
62
63 //=======================================================================
64 //function : SetTolerance
65 //purpose  : 
66 //=======================================================================
67
68  void ShapeUpgrade_SplitCurve3dContinuity::SetTolerance(const Standard_Real Tol) 
69 {
70   myTolerance = Tol;
71 }
72
73 //=======================================================================
74 //function : Compute
75 //purpose  : 
76 //===================================================================
77 void ShapeUpgrade_SplitCurve3dContinuity::Compute()  
78 {  
79   Standard_Real First =  mySplitValues->Value(1);
80   Standard_Real Last =  mySplitValues->Value(mySplitValues->Length());
81   Standard_Real precision = Precision::PConfusion();
82   if(myCurve->Continuity() < myCriterion) 
83     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE2);
84   if (mySplitValues->Length() > 2)
85     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
86   if (myCurve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
87     Handle(Geom_TrimmedCurve) tmp = Handle(Geom_TrimmedCurve)::DownCast (myCurve);
88     Handle(Geom_Curve) BasCurve = tmp->BasisCurve();
89     ShapeUpgrade_SplitCurve3dContinuity spc;
90 //    spc.Init(BasCurve,Max(tmp->FirstParameter(),First),Min(tmp->LastParameter(),Last));
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     myStatus |= spc.myStatus;
99     return;
100   }
101   else if (myCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) {
102     GeomAbs_Shape BasCriterion;
103     switch (myCriterion) {
104       default         :
105       case GeomAbs_C1 : BasCriterion = GeomAbs_C2; break;
106       case GeomAbs_C2 : BasCriterion = GeomAbs_C3; break;
107       case GeomAbs_C3 : // if (ShapeUpgrade::Debug()) std::cout<<". this criterion is not suitable for a Offset curve"<<std::endl; 
108 #ifdef OCCT_DEBUG
109                         std::cout << "Warning: ShapeUpgrade_SplitCurve3dContinuity: criterion C3 for Offset curve" << std::endl; 
110 #endif
111       case GeomAbs_CN : BasCriterion = GeomAbs_CN; break;
112     }
113     Handle(Geom_OffsetCurve) tmp = Handle(Geom_OffsetCurve)::DownCast (myCurve);
114     Handle(Geom_Curve) BasCurve = tmp->BasisCurve();
115     //Standard_Real Offset = tmp->Offset(); // Offset not used (skl)
116     //gp_Dir Direct = tmp->Direction(); // Direct not used (skl)
117     ShapeUpgrade_SplitCurve3dContinuity 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(Geom_BSplineCurve) MyBSpline = Handle(Geom_BSplineCurve)::DownCast (myCurve);
131   if (MyBSpline.IsNull()) {
132 //    if (ShapeUpgrade::Debug()) std::cout<<". curve is not a Bspline"<<std::endl;
133     return ;
134   }
135   // it is a BSplineCurve
136 //  if (ShapeUpgrade::Debug()) std::cout<<". curve is a Bspline"<<std::endl;
137
138   myNbCurves=1;
139   Standard_Integer Deg=MyBSpline->Degree();
140   Standard_Integer NbKnots= MyBSpline->NbKnots(); 
141 //  if (ShapeUpgrade::Debug()) std::cout<<". NbKnots="<<NbKnots<<std::endl;
142   if (NbKnots <= 2) {
143     return;
144   }
145   // Only the internal knots are checked.
146   Standard_Integer FirstInd =MyBSpline->FirstUKnotIndex()+1, 
147   LastInd = MyBSpline->LastUKnotIndex()-1;
148   for(Standard_Integer j =2; j <= mySplitValues->Length(); j++) {
149     Last =  mySplitValues->Value(j);  
150     for (Standard_Integer iknot = FirstInd; iknot <= LastInd; iknot++) {
151       Standard_Real valknot = MyBSpline->Knot(iknot);
152       if(valknot <= First + precision) continue;
153       if(valknot > Last - precision) break;
154       Standard_Integer Continuity=Deg-MyBSpline->Multiplicity(iknot);
155       if (Continuity < myCont) { 
156         // At this knot, the curve is C0; try to remove Knot.
157         Standard_Boolean corrected = Standard_False;
158         Standard_Integer newMultiplicity = Deg - myCont;
159         if (newMultiplicity < 0) newMultiplicity = 0;
160         {
161           try {
162             OCC_CATCH_SIGNALS
163             corrected = MyBSpline->RemoveKnot(iknot, newMultiplicity, myTolerance);
164           }
165       catch (Standard_Failure const&) {
166             corrected = Standard_False;
167           }
168         }
169         
170         
171         if (corrected && newMultiplicity > 0) {
172          Continuity=Deg-MyBSpline->Multiplicity(iknot);
173          corrected = (Continuity >= myCont);
174         }
175         if (corrected) {
176           // at this knot, the continuity is now C1. Nothing else to do.
177 //        if (ShapeUpgrade::Debug()) std::cout<<". Correction at Knot "<<iknot<<std::endl;
178           myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
179           if(newMultiplicity == 0) {
180             //in case if knot is completelly removed
181             //it is necessary to modify last idex and decrease current knot index
182             LastInd = MyBSpline->LastUKnotIndex()-1;
183             iknot--;
184           }
185         }
186         else {
187           // impossible to force C1 within the tolerance: 
188           // this knot will be a splitting value.
189           mySplitValues->InsertBefore(j++,MyBSpline->Knot(iknot));
190           myNbCurves++;
191 //        if (ShapeUpgrade::Debug()) std::cout<<". Splitting at Knot "<<iknot<<std::endl;
192         }
193       }
194     }
195     First = Last;
196   }
197   
198   if (mySplitValues->Length() > 2)
199     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
200 }
201
202 //=======================================================================
203 //function : GetCurve
204 //purpose  : 
205 //=======================================================================
206
207 const Handle(Geom_Curve)& ShapeUpgrade_SplitCurve3dContinuity::GetCurve() const
208 {
209   return myCurve;
210 }