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