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 |
36 | IMPLEMENT_STANDARD_RTTIEXT(ShapeUpgrade_SplitSurfaceContinuity,ShapeUpgrade_SplitSurface) |
37 | |
7fd59977 |
38 | //====================================================================== |
39 | //function : ShapeUpgrade_SplitSurface |
40 | //purpose : |
41 | //======================================================================= |
7fd59977 |
42 | ShapeUpgrade_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 | |