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
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 <Geom_BSplineSurface.hxx>
19 #include <Geom_OffsetSurface.hxx>
20 #include <Geom_RectangularTrimmedSurface.hxx>
21 #include <Geom_SurfaceOfLinearExtrusion.hxx>
22 #include <Geom_SurfaceOfRevolution.hxx>
23 #include <Geom_SweptSurface.hxx>
25 #include <Precision.hxx>
26 #include <ShapeExtend.hxx>
27 #include <ShapeUpgrade.hxx>
28 #include <ShapeUpgrade_SplitCurve3dContinuity.hxx>
29 #include <ShapeUpgrade_SplitSurfaceContinuity.hxx>
30 #include <Standard_Type.hxx>
31 #include <TColGeom_HArray1OfCurve.hxx>
32 #include <TColGeom_HArray2OfSurface.hxx>
33 #include <TColStd_HArray1OfInteger.hxx>
34 #include <TColStd_HSequenceOfReal.hxx>
36 IMPLEMENT_STANDARD_RTTIEXT(ShapeUpgrade_SplitSurfaceContinuity,ShapeUpgrade_SplitSurface)
38 //======================================================================
39 //function : ShapeUpgrade_SplitSurface
41 //=======================================================================
42 ShapeUpgrade_SplitSurfaceContinuity::ShapeUpgrade_SplitSurfaceContinuity()
44 myCriterion = GeomAbs_C1;
45 myTolerance = Precision::Confusion();
49 //=======================================================================
50 //function : SetCrierion
52 //=======================================================================
54 void ShapeUpgrade_SplitSurfaceContinuity::SetCriterion(const GeomAbs_Shape Criterion)
56 myCriterion = Criterion;
57 switch (myCriterion) {
59 case GeomAbs_C1 : myCont = 1; break;
60 case GeomAbs_C2 : myCont = 2; break;
61 case GeomAbs_C3 : myCont = 3; break;
62 case GeomAbs_CN : myCont = 4; break;
66 //=======================================================================
67 //function : SetTolerance
69 //=======================================================================
71 void ShapeUpgrade_SplitSurfaceContinuity::SetTolerance(const Standard_Real Tol)
76 //=======================================================================
79 //=======================================================================
81 void ShapeUpgrade_SplitSurfaceContinuity::Compute(const Standard_Boolean Segment)
84 Standard_Real UF,UL,VF,VL;
85 mySurface->Bounds(UF,UL,VF,VL);
86 if(!Precision::IsInfinite(UF)) myUSplitValues->SetValue(1,UF);
87 if(!Precision::IsInfinite(UL)) myUSplitValues->SetValue(myUSplitValues->Length(),UL);
88 if(!Precision::IsInfinite(VF)) myVSplitValues->SetValue(1,VF);
89 if(!Precision::IsInfinite(VL)) myVSplitValues->SetValue(myVSplitValues->Length(),VL);
92 Standard_Real UFirst = myUSplitValues->Value(1);
93 Standard_Real ULast = myUSplitValues->Value(myUSplitValues->Length());
94 Standard_Real VFirst = myVSplitValues->Value(1);
95 Standard_Real VLast = myVSplitValues->Value(myVSplitValues->Length());
96 Standard_Real precision = Precision::Confusion();
97 // if (ShapeUpgrade::Debug()) std::cout << "SplitSurfaceContinuity::Build" << std::endl;
98 if(mySurface->Continuity() < myCriterion)
99 myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE2);
100 if (myUSplitValues->Length() >2 || myVSplitValues->Length() >2 )
101 myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
103 if (mySurface->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
104 Handle(Geom_SurfaceOfRevolution) Surface = Handle(Geom_SurfaceOfRevolution)::DownCast(mySurface);
105 if(Surface->Continuity() >= myCriterion && myUSplitValues->Length() ==2 && myVSplitValues->Length() ==2 ) {
108 Handle(Geom_Curve) BasCurve = Surface->BasisCurve();
109 ShapeUpgrade_SplitCurve3dContinuity spc;
110 spc.Init(BasCurve,VFirst,VLast);
111 spc.SetCriterion(myCriterion);
112 spc.SetTolerance(myTolerance);
113 spc.SetSplitValues(myVSplitValues);
115 myVSplitValues->Clear();
116 myVSplitValues->ChangeSequence() = spc.SplitValues()->Sequence();
117 if ( spc.Status ( ShapeExtend_DONE1 ) )
118 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
119 if ( spc.Status ( ShapeExtend_DONE2 ) )
120 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
121 if ( spc.Status ( ShapeExtend_DONE3 ) )
122 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
125 if (mySurface->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))) {
126 Handle(Geom_SurfaceOfLinearExtrusion) Surface = Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(mySurface);
127 if(Surface->Continuity() >= myCriterion && myUSplitValues->Length() ==2 && myVSplitValues->Length() == 2) {
130 Handle(Geom_Curve) BasCurve = Surface->BasisCurve();
131 ShapeUpgrade_SplitCurve3dContinuity spc;
132 spc.Init(BasCurve,UFirst,ULast);
133 spc.SetCriterion(myCriterion);
134 spc.SetTolerance(myTolerance);
135 spc.SetSplitValues(myUSplitValues);
137 myUSplitValues->Clear();
138 myUSplitValues->ChangeSequence() = spc.SplitValues()->Sequence();
139 if ( spc.Status ( ShapeExtend_DONE1 ) )
140 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
141 if ( spc.Status ( ShapeExtend_DONE2 ) )
142 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
143 if ( spc.Status ( ShapeExtend_DONE3 ) ) {
144 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
145 Handle(Geom_Curve) aNewBascurve = spc.GetCurve();
146 Surface->SetBasisCurve(aNewBascurve);
151 if (mySurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
152 Handle(Geom_RectangularTrimmedSurface) tmp = Handle(Geom_RectangularTrimmedSurface)::DownCast (mySurface);
153 if(tmp->Continuity() >= myCriterion && myUSplitValues->Length() ==2 && myVSplitValues->Length() == 2) {
156 Standard_Real U1,U2,V1,V2;
157 tmp->Bounds(U1,U2,V1,V2);
158 Handle(Geom_Surface) theSurf = tmp->BasisSurface();
159 ShapeUpgrade_SplitSurfaceContinuity sps;
160 sps.Init(theSurf,Max(U1,UFirst),Min(U2,ULast),Max(V1,VFirst),Min(V2,VLast));
161 sps.SetUSplitValues(myUSplitValues);
162 sps.SetVSplitValues(myVSplitValues);
163 sps.SetTolerance(myTolerance);
164 sps.SetCriterion(myCriterion);
165 sps.Compute(Standard_True);
166 myUSplitValues->Clear();
167 myUSplitValues->ChangeSequence() = sps.USplitValues()->Sequence();
168 myVSplitValues->Clear();
169 myVSplitValues->ChangeSequence() = sps.VSplitValues()->Sequence();
170 myStatus |= sps.myStatus;
173 else if (mySurface->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) {
174 GeomAbs_Shape BasCriterion;
175 switch (myCriterion) {
177 case GeomAbs_C1 : BasCriterion = GeomAbs_C2; break;
178 case GeomAbs_C2 : BasCriterion = GeomAbs_C3; break;
179 case GeomAbs_C3 : //if (ShapeUpgrade::Debug()) std::cout<<". this criterion is not suitable for a Offset Surface"<<std::endl;
181 std::cout << "Warning: ShapeUpgrade_SplitSurfaceContinuity: criterion C3 for Offset surface" << std::endl;
183 case GeomAbs_CN : BasCriterion = GeomAbs_CN; break;
186 Handle(Geom_OffsetSurface) tmp = Handle(Geom_OffsetSurface)::DownCast (mySurface);
187 Handle(Geom_Surface) theSurf = tmp->BasisSurface();
188 if(theSurf->Continuity() >= BasCriterion && myUSplitValues->Length() ==2 && myVSplitValues->Length() == 2) {
191 ShapeUpgrade_SplitSurfaceContinuity sps;
192 sps.Init(theSurf,UFirst,ULast,VFirst,VLast);
193 sps.SetUSplitValues(myUSplitValues);
194 sps.SetVSplitValues(myVSplitValues);
195 sps.SetTolerance(myTolerance);
196 sps.SetCriterion(BasCriterion);
197 sps.Compute(Standard_True);
198 myUSplitValues->Clear();
199 myUSplitValues->ChangeSequence() = sps.USplitValues()->Sequence();
200 myVSplitValues->Clear();
201 myVSplitValues->ChangeSequence() = sps.VSplitValues()->Sequence();
202 myStatus |= sps.myStatus;
206 Handle(Geom_BSplineSurface) MyBSpline;
207 if(mySurface->IsKind(STANDARD_TYPE(Geom_BSplineSurface)))
208 MyBSpline = Handle(Geom_BSplineSurface)::DownCast(mySurface->Copy());
209 if (MyBSpline.IsNull()) {
210 // if (ShapeUpgrade::Debug()) std::cout<<". Surface is not a Bspline"<<std::endl;
213 if(mySurface->Continuity() >= myCriterion) {
217 // it is a BSplineSurface
218 Standard_Integer UDeg=MyBSpline->UDegree();
219 Standard_Integer VDeg=MyBSpline->VDegree();
220 Standard_Integer NbUKnots= MyBSpline->NbUKnots();
221 Standard_Integer UFirstInd =MyBSpline->FirstUKnotIndex()+1,
222 ULastInd = MyBSpline->LastUKnotIndex()-1,
223 VFirstInd =MyBSpline->FirstVKnotIndex()+1,
224 VLastInd = MyBSpline->LastVKnotIndex()-1;
225 Standard_Integer NbVKnots= MyBSpline->NbVKnots();
227 // if (ShapeUpgrade::Debug()) std::cout<<". NbUKnots="<<NbUKnots<<std::endl;
229 // Only the internal knots are checked.
230 Standard_Integer iknot= UFirstInd;
231 for(Standard_Integer j =2; j <= myUSplitValues->Length(); j++) {
232 ULast = myUSplitValues->Value(j);
234 for (; iknot <= ULastInd; iknot++) {
235 Standard_Real valknot = MyBSpline->UKnot(iknot);
236 if(valknot <= UFirst + precision) continue;
237 if( valknot >= ULast - precision) break;
238 Standard_Integer Continuity=UDeg-MyBSpline->UMultiplicity(iknot);
239 if (Continuity < myCont) {
240 // At this knot, the Surface is C0; try to remove Knot.
241 Standard_Integer newMultiplicity=UDeg - myCont;
242 Standard_Boolean corrected = Standard_False;
243 if ( newMultiplicity >= 0 )
244 corrected=MyBSpline->RemoveUKnot(iknot, newMultiplicity, myTolerance);
245 if (corrected && newMultiplicity > 0) {
246 Continuity=UDeg-MyBSpline->UMultiplicity(iknot);
247 corrected = (Continuity >= myCont);
250 // at this knot, the continuity is now C1. Nothing else to do.
251 // if (ShapeUpgrade::Debug()) std::cout<<". Correction at UKnot "<<iknot<<std::endl;
252 // PTV 15.05.2002 decrease iknot and ULastIndex values if knot removed
253 if (newMultiplicity ==0) { iknot--; ULastInd--; }
254 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
257 // impossible to force C1 within the tolerance:
258 // this knot will be a splitting value.
259 Standard_Real u=MyBSpline->UKnot(iknot);
260 myUSplitValues->InsertBefore(j++,u);
262 // if (ShapeUpgrade::Debug()) std::cout<<". Splitting at Knot "<<iknot<<std::endl;
269 // if (ShapeUpgrade::Debug()) std::cout<<". NbVKnots="<<NbVKnots<<std::endl;
271 // Only the internal knots are checked.
272 Standard_Integer iknot=VFirstInd;
273 for(Standard_Integer j1 =2; j1 <= myVSplitValues->Length(); j1++) {
274 VLast = myVSplitValues->Value(j1);
275 for (; iknot <= VLastInd; iknot++) {
276 Standard_Real valknot = MyBSpline->VKnot(iknot);
277 if(valknot <= VFirst + precision) continue;
278 if( valknot >= VLast - precision) break;
279 Standard_Integer Continuity=VDeg-MyBSpline->VMultiplicity(iknot);
280 if (Continuity < myCont) {
281 // At this knot, the Surface is C0; try to remove Knot.
282 Standard_Integer newMultiplicity=VDeg - myCont;
283 Standard_Boolean corrected = Standard_False;
284 if( newMultiplicity >= 0 )
285 corrected=MyBSpline->RemoveVKnot(iknot, newMultiplicity, myTolerance);
286 if (corrected && newMultiplicity > 0) {
287 Continuity=VDeg-MyBSpline->VMultiplicity(iknot);
288 corrected = (Continuity >= myCont);
291 // at this knot, the continuity is now Criterion. Nothing else to do.
292 // if (ShapeUpgrade::Debug()) std::cout<<". Correction at VKnot "<<iknot<<std::endl;
293 // PTV 15.05.2002 decrease iknot and ULastIndex values if knot removed
294 if (newMultiplicity ==0) { iknot--; VLastInd--; }
295 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
298 // this knot will be a splitting value.
299 Standard_Real v=MyBSpline->VKnot(iknot);
300 myVSplitValues->InsertBefore(j1++,v);
302 // if (ShapeUpgrade::Debug()) std::cout<<". Splitting at Knot "<<iknot<<std::endl;
309 if ( Status ( ShapeExtend_DONE3 ) ) {
310 mySurface = MyBSpline;
313 if (myUSplitValues->Length() >2 || myVSplitValues->Length() >2 )
314 myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE1);