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