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 | |
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;; |
0797d9d3 |
176 | #ifdef OCCT_DEBUG |
7fd59977 |
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 | |