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 |
40 | ShapeUpgrade_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 | |