0025266: Debug statements in the source are getting flushed on to the console
[occt.git] / src / ShapeUpgrade / ShapeUpgrade_SplitSurfaceContinuity.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 #include <ShapeUpgrade_SplitSurfaceContinuity.ixx>
18 #include <Geom_BSplineSurface.hxx>
19 #include <Precision.hxx>
20 #include <ShapeUpgrade.hxx>
21 #include <TColGeom_HArray2OfSurface.hxx>
22 #include <TColStd_HArray1OfInteger.hxx>
23 #include <Geom_SweptSurface.hxx>
24 #include <TColStd_HSequenceOfReal.hxx>
25 #include <Geom_SurfaceOfRevolution.hxx>
26 #include <ShapeUpgrade_SplitCurve3dContinuity.hxx>
27 #include <Geom_SurfaceOfLinearExtrusion.hxx>
28 #include <TColGeom_HArray1OfCurve.hxx>
29 #include <gp_Ax1.hxx>
30 #include <Geom_RectangularTrimmedSurface.hxx>
31 #include <Geom_OffsetSurface.hxx>
32 #include <ShapeExtend.hxx>
33 //======================================================================
34 //function : ShapeUpgrade_SplitSurface
35 //purpose  : 
36 //=======================================================================
37
38 ShapeUpgrade_SplitSurfaceContinuity::ShapeUpgrade_SplitSurfaceContinuity()
39 {
40   myCriterion = GeomAbs_C1;
41   myTolerance = Precision::Confusion();
42   
43 }
44
45 //=======================================================================
46 //function : SetCrierion
47 //purpose  : 
48 //=======================================================================
49
50  void ShapeUpgrade_SplitSurfaceContinuity::SetCriterion(const GeomAbs_Shape Criterion)
51 {
52   myCriterion = Criterion;
53   switch (myCriterion) {
54     default         :
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   }
60 }
61
62 //=======================================================================
63 //function : SetTolerance
64 //purpose  : 
65 //=======================================================================
66
67  void ShapeUpgrade_SplitSurfaceContinuity::SetTolerance(const Standard_Real Tol)
68 {
69   myTolerance = Tol;
70 }
71
72 //=======================================================================
73 //function : Build
74 //purpose  : 
75 //=======================================================================
76
77  void ShapeUpgrade_SplitSurfaceContinuity::Compute(const Standard_Boolean Segment) 
78 {
79   if(!Segment) {
80     Standard_Real UF,UL,VF,VL;
81     mySurface->Bounds(UF,UL,VF,VL);
82     if(!Precision::IsInfinite(UF)) myUSplitValues->SetValue(1,UF);
83     if(!Precision::IsInfinite(UL)) myUSplitValues->SetValue(myUSplitValues->Length(),UL);
84     if(!Precision::IsInfinite(VF)) myVSplitValues->SetValue(1,VF);
85     if(!Precision::IsInfinite(VL)) myVSplitValues->SetValue(myVSplitValues->Length(),VL);
86   }
87   
88   Standard_Real UFirst = myUSplitValues->Value(1);
89   Standard_Real ULast  = myUSplitValues->Value(myUSplitValues->Length());
90   Standard_Real VFirst = myVSplitValues->Value(1);
91   Standard_Real VLast  = myVSplitValues->Value(myVSplitValues->Length());
92   Standard_Real precision = Precision::Confusion();
93 //  if (ShapeUpgrade::Debug()) cout << "SplitSurfaceContinuity::Build" << endl;
94   if(mySurface->Continuity() < myCriterion) 
95     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE2);
96   if (myUSplitValues->Length() >2 || myVSplitValues->Length() >2 )
97     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
98   
99   if (mySurface->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution))) {      
100     Handle(Geom_SurfaceOfRevolution) Surface = Handle(Geom_SurfaceOfRevolution)::DownCast(mySurface);
101     if(Surface->Continuity() >=  myCriterion && myUSplitValues->Length() ==2 && myVSplitValues->Length() ==2 ) {
102       return;
103     }
104     Handle(Geom_Curve) BasCurve = Surface->BasisCurve(); 
105     ShapeUpgrade_SplitCurve3dContinuity spc;
106     spc.Init(BasCurve,VFirst,VLast);
107     spc.SetCriterion(myCriterion);
108     spc.SetTolerance(myTolerance);
109     spc.SetSplitValues(myVSplitValues);
110     spc.Compute();
111     myVSplitValues->Clear();
112     myVSplitValues->ChangeSequence() = spc.SplitValues()->Sequence();
113     if ( spc.Status ( ShapeExtend_DONE1 ) )
114       myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
115     if ( spc.Status ( ShapeExtend_DONE2 ) )
116       myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
117     if ( spc.Status ( ShapeExtend_DONE3 ) )
118       myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
119     return;
120   }   
121   if (mySurface->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))) {
122     Handle(Geom_SurfaceOfLinearExtrusion) Surface = Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(mySurface);
123    if(Surface->Continuity() >=  myCriterion && myUSplitValues->Length() ==2 && myVSplitValues->Length() == 2) {
124       return;
125     }
126     Handle(Geom_Curve) BasCurve = Surface->BasisCurve();
127     ShapeUpgrade_SplitCurve3dContinuity spc;
128     spc.Init(BasCurve,UFirst,ULast);
129     spc.SetCriterion(myCriterion);
130     spc.SetTolerance(myTolerance);
131     spc.SetSplitValues(myUSplitValues);
132     spc.Compute(); 
133     myUSplitValues->Clear();
134     myUSplitValues->ChangeSequence() = spc.SplitValues()->Sequence();
135     if ( spc.Status ( ShapeExtend_DONE1 ) )
136       myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
137     if ( spc.Status ( ShapeExtend_DONE2 ) )
138       myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
139     if ( spc.Status ( ShapeExtend_DONE3 ) ) {
140       myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
141       Handle(Geom_Curve) aNewBascurve = spc.GetCurve();
142       Surface->SetBasisCurve(aNewBascurve);
143     }
144     return;
145   }
146   
147   if (mySurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
148     Handle(Geom_RectangularTrimmedSurface) tmp = Handle(Geom_RectangularTrimmedSurface)::DownCast (mySurface);
149     if(tmp->Continuity() >=  myCriterion && myUSplitValues->Length() ==2 && myVSplitValues->Length() == 2) {
150       return;
151     }
152     Standard_Real U1,U2,V1,V2;
153     tmp->Bounds(U1,U2,V1,V2);
154     Handle(Geom_Surface) theSurf = tmp->BasisSurface();
155     ShapeUpgrade_SplitSurfaceContinuity sps;
156     sps.Init(theSurf,Max(U1,UFirst),Min(U2,ULast),Max(V1,VFirst),Min(V2,VLast));
157     sps.SetUSplitValues(myUSplitValues);
158     sps.SetVSplitValues(myVSplitValues);
159     sps.SetTolerance(myTolerance);
160     sps.SetCriterion(myCriterion);
161     sps.Compute(Standard_True);
162     myUSplitValues->Clear();
163     myUSplitValues->ChangeSequence() = sps.USplitValues()->Sequence();
164     myVSplitValues->Clear();
165     myVSplitValues->ChangeSequence() = sps.VSplitValues()->Sequence();
166     myStatus |= sps.myStatus;
167     return;
168   }
169   else if (mySurface->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) {
170     GeomAbs_Shape BasCriterion;
171     switch (myCriterion) {
172       default         :
173       case GeomAbs_C1 : BasCriterion = GeomAbs_C2; break;
174       case GeomAbs_C2 : BasCriterion = GeomAbs_C3; break;
175       case GeomAbs_C3 : //if (ShapeUpgrade::Debug()) cout<<". this criterion is not suitable for a Offset Surface"<<endl;; 
176 #ifdef SHAPEUPGRADE_DEB
177                         cout << "Warning: ShapeUpgrade_SplitSurfaceContinuity: criterion C3 for Offset surface" << endl; 
178 #endif
179       case GeomAbs_CN : BasCriterion = GeomAbs_CN; break;
180       
181     }
182     Handle(Geom_OffsetSurface) tmp = Handle(Geom_OffsetSurface)::DownCast (mySurface);
183     Handle(Geom_Surface) theSurf = tmp->BasisSurface();
184     if(theSurf->Continuity() >=  BasCriterion && myUSplitValues->Length() ==2 && myVSplitValues->Length() == 2) {
185       return;
186     }
187     ShapeUpgrade_SplitSurfaceContinuity sps;
188     sps.Init(theSurf,UFirst,ULast,VFirst,VLast);
189     sps.SetUSplitValues(myUSplitValues);
190     sps.SetVSplitValues(myVSplitValues);
191     sps.SetTolerance(myTolerance);
192     sps.SetCriterion(BasCriterion);
193     sps.Compute(Standard_True);
194     myUSplitValues->Clear();
195     myUSplitValues->ChangeSequence() = sps.USplitValues()->Sequence();
196     myVSplitValues->Clear();
197     myVSplitValues->ChangeSequence() = sps.VSplitValues()->Sequence();
198     myStatus |= sps.myStatus;
199     return;
200   }
201   
202   Handle(Geom_BSplineSurface) MyBSpline;
203   if(mySurface->IsKind(STANDARD_TYPE(Geom_BSplineSurface)))
204     MyBSpline = Handle(Geom_BSplineSurface)::DownCast(mySurface->Copy());
205   if (MyBSpline.IsNull()) {
206 //    if (ShapeUpgrade::Debug()) cout<<". "<<" Surface is not a Bspline"<<endl;
207     return;
208   } 
209   if(mySurface->Continuity() >= myCriterion) {
210     return;
211   }
212   
213   // it is a BSplineSurface
214   Standard_Integer UDeg=MyBSpline->UDegree();
215   Standard_Integer VDeg=MyBSpline->VDegree();
216   Standard_Integer NbUKnots= MyBSpline->NbUKnots(); 
217   Standard_Integer UFirstInd =MyBSpline->FirstUKnotIndex()+1,
218   ULastInd = MyBSpline->LastUKnotIndex()-1,
219   VFirstInd =MyBSpline->FirstVKnotIndex()+1,
220   VLastInd = MyBSpline->LastVKnotIndex()-1;
221   Standard_Integer NbVKnots= MyBSpline->NbVKnots();
222   
223 //  if (ShapeUpgrade::Debug()) cout<<". NbUKnots="<<NbUKnots<<endl;
224   if (NbUKnots>2) {
225     // Only the internal knots are checked.
226     Standard_Integer iknot= UFirstInd;
227     for(Standard_Integer j =2; j <= myUSplitValues->Length(); j++) {
228       ULast =  myUSplitValues->Value(j);
229       
230       for (; iknot <= ULastInd; iknot++) {
231         Standard_Real valknot = MyBSpline->UKnot(iknot);
232         if(valknot <= UFirst + precision) continue;
233           if( valknot >= ULast - precision) break;
234         Standard_Integer Continuity=UDeg-MyBSpline->UMultiplicity(iknot);
235         if (Continuity < myCont) { 
236           // At this knot, the Surface is C0; try to remove Knot.
237           Standard_Integer newMultiplicity=UDeg - myCont;
238           Standard_Boolean corrected = Standard_False;
239           if ( newMultiplicity >= 0 )
240             corrected=MyBSpline->RemoveUKnot(iknot, newMultiplicity, myTolerance);
241           if (corrected && newMultiplicity > 0) {
242                 Continuity=UDeg-MyBSpline->UMultiplicity(iknot);
243                 corrected = (Continuity >= myCont);
244                 }
245           if (corrected) {
246             // at this knot, the continuity is now C1. Nothing else to do.
247 //          if (ShapeUpgrade::Debug()) cout<<". Correction at UKnot "<<iknot<<endl;
248             // PTV 15.05.2002 decrease iknot and ULastIndex values if knot removed
249             if (newMultiplicity ==0) { iknot--; ULastInd--; }
250             myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
251           }
252           else {
253             // impossible to force C1 within the tolerance: 
254             // this knot will be a splitting value.
255             Standard_Real u=MyBSpline->UKnot(iknot);
256             myUSplitValues->InsertBefore(j++,u);
257             myNbResultingRow++;
258 //          if (ShapeUpgrade::Debug()) cout<<". Splitting at Knot "<<iknot<<endl;
259           }
260         }
261       }
262       UFirst = ULast;
263     }
264   }
265 //  if (ShapeUpgrade::Debug()) cout<<". NbVKnots="<<NbVKnots<<endl;
266   if (NbVKnots>2) {
267     // Only the internal knots are checked.
268     Standard_Integer iknot=VFirstInd;
269     for(Standard_Integer j1 =2; j1 <= myVSplitValues->Length(); j1++) {
270       VLast =  myVSplitValues->Value(j1);
271       for (; iknot <= VLastInd; iknot++) {
272         Standard_Real valknot = MyBSpline->VKnot(iknot);
273         if(valknot <= VFirst + precision) continue;
274         if( valknot >= VLast - precision) break;
275         Standard_Integer Continuity=VDeg-MyBSpline->VMultiplicity(iknot);
276         if (Continuity < myCont) { 
277           // At this knot, the Surface is C0; try to remove Knot.
278           Standard_Integer newMultiplicity=VDeg - myCont;
279           Standard_Boolean corrected = Standard_False;
280           if( newMultiplicity >= 0 )
281             corrected=MyBSpline->RemoveVKnot(iknot, newMultiplicity, myTolerance);
282           if (corrected && newMultiplicity > 0) {
283                 Continuity=VDeg-MyBSpline->VMultiplicity(iknot);
284                 corrected = (Continuity >= myCont);
285           }
286           if (corrected ) {
287             // at this knot, the continuity is now Criterion. Nothing else to do.
288 //          if (ShapeUpgrade::Debug()) cout<<". Correction at VKnot "<<iknot<<endl;
289             // PTV 15.05.2002 decrease iknot and ULastIndex values if knot removed
290             if (newMultiplicity ==0) { iknot--; VLastInd--; }
291             myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
292           }
293           else {
294             // this knot will be a splitting value.
295             Standard_Real v=MyBSpline->VKnot(iknot);
296             myVSplitValues->InsertBefore(j1++,v);
297             myNbResultingCol++;
298 //          if (ShapeUpgrade::Debug()) cout<<". Splitting at Knot "<<iknot<<endl;
299           }
300         }
301       }
302       VFirst = VLast;
303     }
304   }
305   if ( Status ( ShapeExtend_DONE3 ) ) {
306     mySurface = MyBSpline;
307   }
308
309   if (myUSplitValues->Length() >2 || myVSplitValues->Length() >2 )
310     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
311 }
312
313
314
315