0024624: Lost word in license statement in source files
[occt.git] / src / ShapeUpgrade / ShapeUpgrade_SplitSurfaceContinuity.cxx
CommitLineData
b311480e 1// Created on: 1999-04-14
2// Created by: Roman LYGIN
3// Copyright (c) 1999-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 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
38ShapeUpgrade_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 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