b311480e |
1 | // Created on: 1999-05-14 |
2 | // Created by: data exchange team |
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. |
b311480e |
16 | |
7fd59977 |
17 | // 15.06 2000 gka fix against small edges ; merging ends pcurves and 3d curves |
18 | |
7fd59977 |
19 | |
20 | #include <ShapeUpgrade_ShapeConvertToBezier.ixx> |
21 | #include <ShapeUpgrade_WireDivide.hxx> |
22 | #include <ShapeUpgrade_ConvertCurve3dToBezier.hxx> |
23 | #include <ShapeUpgrade_ConvertCurve2dToBezier.hxx> |
24 | #include <TopExp_Explorer.hxx> |
25 | #include <TopoDS_Face.hxx> |
26 | #include <TopoDS.hxx> |
27 | #include <BRep_Builder.hxx> |
28 | #include <ShapeAnalysis_Edge.hxx> |
29 | #include <ShapeBuild_Edge.hxx> |
30 | #include <Geom_Curve.hxx> |
31 | #include <Geom_BezierCurve.hxx> |
32 | #include <Precision.hxx> |
33 | #include <Geom2d_Curve.hxx> |
34 | #include <Geom2d_BezierCurve.hxx> |
35 | #include <BRep_Tool.hxx> |
36 | #include <GeomLib.hxx> |
37 | #include <TopoDS_Edge.hxx> |
38 | #include <ShapeUpgrade_ConvertSurfaceToBezierBasis.hxx> |
39 | #include <TopExp.hxx> |
40 | #include <TopExp.hxx> |
41 | #include <gp_Pnt2d.hxx> |
42 | #include <gp_Pnt.hxx> |
43 | #include <ShapeFix_Wire.hxx> |
44 | #include <ShapeExtend_WireData.hxx> |
45 | #include <TopoDS_Vertex.hxx> |
46 | #include <ShapeUpgrade_FixSmallBezierCurves.hxx> |
47 | #include <ShapeUpgrade_FixSmallBezierCurves.hxx> |
48 | #include <ShapeUpgrade_FixSmallBezierCurves.hxx> |
49 | #include <BRepTools.hxx> |
50 | |
51 | //======================================================================= |
52 | //function : ShapeUpgrade_ShapeConvertToBezier |
53 | //purpose : |
54 | //======================================================================= |
55 | |
56 | ShapeUpgrade_ShapeConvertToBezier::ShapeUpgrade_ShapeConvertToBezier() |
57 | { |
58 | myLevel = 0; |
59 | my2dMode = Standard_False; |
60 | my3dMode = Standard_False; |
61 | mySurfaceMode = Standard_False; |
62 | //set spesial flags to true |
63 | my3dLineMode = Standard_True; |
64 | my3dCircleMode = Standard_True; |
65 | my3dConicMode = Standard_True; |
66 | myPlaneMode = Standard_True; |
67 | myRevolutionMode = Standard_True; |
68 | myExtrusionMode = Standard_True; |
69 | myBSplineMode = Standard_True; |
70 | } |
71 | |
72 | //======================================================================= |
73 | //function : ShapeUpgrade_ShapeConvertToBezier |
74 | //purpose : |
75 | //======================================================================= |
76 | |
77 | ShapeUpgrade_ShapeConvertToBezier::ShapeUpgrade_ShapeConvertToBezier(const TopoDS_Shape& S): |
78 | ShapeUpgrade_ShapeDivide(S) |
79 | { |
80 | myLevel = 0; |
81 | my2dMode = Standard_False; |
82 | my3dMode = Standard_False; |
83 | mySurfaceMode = Standard_False; |
84 | //set spesial flags to true |
85 | my3dLineMode = Standard_True; |
86 | my3dCircleMode = Standard_True; |
87 | my3dConicMode = Standard_True; |
88 | myPlaneMode = Standard_True; |
89 | myRevolutionMode = Standard_True; |
90 | myExtrusionMode = Standard_True; |
91 | myBSplineMode = Standard_True; |
92 | } |
93 | |
94 | //======================================================================= |
95 | //function : Perform |
96 | //purpose : |
97 | //======================================================================= |
98 | |
99 | Standard_Boolean ShapeUpgrade_ShapeConvertToBezier::Perform (const Standard_Boolean newContext) |
100 | { |
101 | myLevel++; |
102 | |
103 | Standard_Boolean res = Standard_False; |
104 | if ( myLevel ==1 ) { |
105 | Standard_Boolean isNewContext = newContext; |
106 | if ( mySurfaceMode ) { |
107 | Standard_Boolean mode2d = my2dMode, mode3d = my3dMode; |
108 | my2dMode = my3dMode = Standard_False; |
109 | res = ShapeUpgrade_ShapeDivide::Perform(isNewContext); |
110 | isNewContext = Standard_False; |
111 | myShape = myResult; |
112 | my2dMode = mode2d; |
113 | my3dMode = mode3d; |
114 | } |
115 | if ( my2dMode || my3dMode ) { |
116 | Standard_Boolean modeS = mySurfaceMode; |
117 | mySurfaceMode = Standard_False; |
118 | res = ShapeUpgrade_ShapeDivide::Perform(isNewContext); |
119 | mySurfaceMode = modeS; |
120 | } |
121 | } |
122 | else res = ShapeUpgrade_ShapeDivide::Perform(newContext); |
123 | //pdn Hereafter the fix on GeomLib:SameParameter. |
124 | //In order to fix this bug all edges that are based on |
125 | //bezier curves (2d or 3d) and have range not equal to [0,1] |
126 | //are performed the following sequence: |
127 | // 1. Segment on bezier curve |
128 | // 2. Changing rande of edge to [0,1] |
129 | if(myLevel == 1) { |
130 | BRep_Builder B; |
131 | ShapeAnalysis_Edge sae; |
132 | ShapeBuild_Edge sbe; |
133 | Standard_Real preci = Precision::PConfusion(); |
134 | for(TopExp_Explorer exp(myResult,TopAbs_FACE); exp.More(); exp.Next()) { |
135 | TopoDS_Face face = TopoDS::Face(exp.Current()); |
136 | face.Orientation(TopAbs_FORWARD); |
137 | for(TopExp_Explorer exp1(face, TopAbs_WIRE); exp1.More(); exp1.Next()) { |
138 | TopoDS_Wire wire= TopoDS::Wire(exp1.Current()); |
139 | Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(wire,face,myPrecision); |
140 | sfw->FixReorder(); |
141 | sfw->FixShifted(); // for cylinders.brep |
142 | Handle(ShapeExtend_WireData) sewd = sfw->WireData(); |
143 | for(Standard_Integer i =1; i <= sewd->NbEdges(); i++) { |
144 | TopoDS_Edge edge = sewd->Edge(i); |
145 | //TopoDS_Edge edge = TopoDS::Edge(exp1.Current()); |
146 | Handle(Geom_Curve) c3d; |
147 | Standard_Real first, last; |
148 | TopoDS_Vertex V1,V2; |
149 | TopExp::Vertices(edge,V1,V2); |
150 | if(sae.Curve3d(edge,c3d,first,last,Standard_False)) { |
151 | if(c3d->IsKind(STANDARD_TYPE(Geom_BezierCurve))) { |
152 | //B.SameRange(edge, Standard_False); |
153 | Handle(Geom_BezierCurve) bezier = Handle(Geom_BezierCurve)::DownCast(c3d); |
154 | if(first!= 0 || last !=1) { |
155 | if(first > preci || last < 1 - preci) { |
156 | bezier->Segment(first,last); |
157 | B.UpdateEdge(edge,bezier,0.); |
158 | } |
159 | sbe.SetRange3d(edge,0,1); |
160 | } |
161 | if(!bezier.IsNull()) { //gka fix against small edges ; merging ends of 3d curves |
162 | gp_Pnt p1 = bezier->Value(first); |
163 | gp_Pnt p2 = bezier->Value(last); |
164 | gp_Pnt p1v = BRep_Tool::Pnt(V1); |
165 | gp_Pnt p2v = BRep_Tool::Pnt(V2); |
166 | if(p1.Distance(p1v) > Precision::Confusion()) |
167 | bezier->SetPole(1,p1v); |
168 | if(p2.Distance(p2v) > Precision::Confusion()) |
169 | bezier->SetPole(bezier->NbPoles(),p2v); |
170 | B.UpdateEdge(edge,bezier,0.); |
171 | } |
172 | } |
173 | else if(my2dMode) |
174 | B.SameRange(edge, Standard_True); |
175 | } |
176 | Handle(Geom2d_Curve) c2d,c2drev; |
177 | Handle(Geom2d_BezierCurve) bezier,bezierR; |
178 | Standard_Boolean isSeam = BRep_Tool::IsClosed ( edge, face ); |
179 | if(!sae.PCurve(edge,face,c2d,first,last,Standard_False)) continue ; |
180 | if(!c2d->IsKind(STANDARD_TYPE(Geom2d_BezierCurve))) continue; |
181 | Handle(Geom2d_Curve) newRevCurve,newCurve; |
182 | bezier = Handle(Geom2d_BezierCurve)::DownCast(c2d); |
183 | if(isSeam) { |
184 | TopoDS_Shape aLocalShape = edge.Reversed(); |
185 | TopoDS_Edge tmpedge = TopoDS::Edge(aLocalShape); |
186 | // TopoDS_Edge tmpedge = TopoDS::Edge(edge.Reversed()); |
187 | if(sae.PCurve(tmpedge,face,c2drev,first,last,Standard_False)) { |
188 | if(c2drev->IsKind(STANDARD_TYPE(Geom2d_BezierCurve))) { |
189 | bezierR = Handle(Geom2d_BezierCurve)::DownCast(c2drev); |
190 | } |
191 | } |
192 | } |
193 | if(first!= 0 || last !=1) { |
194 | if(first > preci || last < 1 - preci) { |
195 | if(!bezier.IsNull()) { |
196 | bezier->Segment(first,last); |
197 | newCurve = bezier; |
198 | } |
199 | else |
200 | GeomLib::SameRange(preci, c2d, first, last, 0, 1, newCurve); |
201 | if(isSeam) { |
202 | if(!bezierR.IsNull()) { |
203 | bezierR->Segment(first, last); |
204 | newRevCurve = bezierR; |
205 | } |
206 | else if(!c2drev.IsNull()) |
207 | GeomLib::SameRange(preci, c2drev, first, last, 0, 1, newRevCurve); |
208 | if(edge.Orientation()==TopAbs_FORWARD) |
209 | B.UpdateEdge ( edge, newCurve, newRevCurve, face, 0. ); |
210 | else |
211 | B.UpdateEdge ( edge, newRevCurve, newCurve, face, 0. ); |
212 | } |
213 | } |
214 | B.Range(edge,face,0,1); |
215 | } |
216 | |
217 | |
218 | TopoDS_Edge edgenext = sewd->Edge((i == sewd->NbEdges() ? 1 : i+1)); |
219 | Handle(Geom2d_Curve) c2dnext,c2drevnext,newnextCurve; |
220 | Standard_Real first2,last2; |
221 | Handle(Geom2d_BezierCurve) beziernext,bezierRnext; |
222 | if(!sae.PCurve(edgenext,face,c2dnext,first2,last2,Standard_False)) continue ; |
223 | if(!c2dnext->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)) ) continue; |
224 | beziernext = Handle(Geom2d_BezierCurve)::DownCast(c2dnext); |
225 | //Handle(Geom2d_Curve) newRevCurve; |
226 | if(isSeam) { |
227 | TopoDS_Shape aLocalShape = edgenext.Reversed(); |
228 | TopoDS_Edge tmpedge = TopoDS::Edge(aLocalShape); |
229 | // TopoDS_Edge tmpedge = TopoDS::Edge(edgenext.Reversed()); |
230 | if(sae.PCurve(tmpedge,face,c2drevnext,first,last,Standard_False)) { |
231 | if(c2drevnext->IsKind(STANDARD_TYPE(Geom2d_BezierCurve))) { |
232 | bezierRnext = Handle(Geom2d_BezierCurve)::DownCast(c2drevnext); |
233 | } |
234 | } |
235 | } |
236 | if(first2!= 0 || last2 !=1) { |
237 | if(first2 > preci || last2 < 1 - preci) { |
238 | if(!beziernext.IsNull()) { |
239 | beziernext->Segment(first2,last2); |
240 | newnextCurve = beziernext; |
241 | } |
242 | else |
243 | GeomLib::SameRange(preci, c2dnext, first2, last2, 0, 1, newnextCurve); |
244 | if(isSeam) { |
245 | if(!bezierRnext.IsNull()) { |
246 | bezierRnext->Segment(first2, last2); |
247 | newRevCurve = bezierRnext; |
248 | } |
249 | else if(!c2drevnext.IsNull()) |
250 | GeomLib::SameRange(preci, c2drevnext, first2, last2, 0, 1, newRevCurve); |
251 | if(edge.Orientation()==TopAbs_FORWARD) |
252 | B.UpdateEdge ( edgenext, newnextCurve, newRevCurve, face, 0. ); |
253 | else |
254 | B.UpdateEdge ( edgenext, newRevCurve, newnextCurve, face, 0. ); |
255 | } |
256 | } |
257 | B.Range(edgenext,face,0,1); |
258 | } |
259 | |
260 | if(bezier.IsNull() || beziernext.IsNull() ) continue; //gka fix against small edges ; merging ends of pcurves |
261 | Standard_Real f1,l1,f2,l2; |
262 | f1 = bezier->FirstParameter(); |
263 | l1 = bezier->LastParameter(); |
264 | f2 = beziernext->FirstParameter(); |
265 | l2 = beziernext->LastParameter(); |
266 | gp_Pnt2d p2d1 = bezier->Value(f1); |
267 | gp_Pnt2d p2d2 = bezier->Value(l1); |
268 | gp_Pnt2d p2d1next = beziernext->Value(f2); |
269 | gp_Pnt2d p2d2next = beziernext->Value(l2); |
270 | if(edge.Orientation() == TopAbs_FORWARD && edgenext.Orientation() == TopAbs_FORWARD) { |
271 | if(p2d2.Distance(p2d1next) > Precision::PConfusion()) { |
272 | gp_Pnt2d pmid = 0.5*(p2d2.XY() + p2d1next.XY()); |
273 | // gp_Pnt2d p1 = bezier->Pole(bezier->NbPoles()); |
274 | // gp_Pnt2d p2 = beziernext->Pole(1); |
275 | bezier->SetPole(bezier->NbPoles(),pmid); |
276 | beziernext->SetPole(1,pmid); |
277 | } |
278 | } |
279 | if(edge.Orientation() == TopAbs_FORWARD && edgenext.Orientation() == TopAbs_REVERSED) { |
280 | if(p2d2.Distance(p2d2next) > Precision::PConfusion()) { |
281 | gp_Pnt2d pmid = 0.5*(p2d2.XY() + p2d2next.XY()); |
282 | // gp_Pnt2d p1 = bezier->Pole(bezier->NbPoles()); |
283 | // gp_Pnt2d p2 = beziernext->Pole(beziernext->NbPoles()); |
284 | bezier->SetPole(bezier->NbPoles(),pmid); |
285 | beziernext->SetPole(beziernext->NbPoles(),pmid); |
286 | } |
287 | } |
288 | if(edge.Orientation() == TopAbs_REVERSED && edgenext.Orientation() == TopAbs_FORWARD) { |
289 | if(p2d1.Distance(p2d1next) > Precision::PConfusion()) { |
290 | gp_Pnt2d pmid = 0.5*(p2d1.XY() + p2d1next.XY()); |
291 | // gp_Pnt2d p1 = bezier->Pole(1); |
292 | // gp_Pnt2d p2 = beziernext->Pole(1); |
293 | bezier->SetPole(1,pmid); |
294 | beziernext->SetPole(1,pmid); |
295 | } |
296 | } |
297 | if(edge.Orientation() == TopAbs_REVERSED && edgenext.Orientation() == TopAbs_REVERSED) { |
298 | if(p2d1.Distance(p2d2next) > Precision::PConfusion()) { |
299 | gp_Pnt2d pmid = 0.5*(p2d1.XY() + p2d2next.XY()); |
300 | // gp_Pnt2d p1 = bezier->Pole(1); |
301 | // gp_Pnt2d p2 = beziernext->Pole(beziernext->NbPoles()); |
302 | bezier->SetPole(1,pmid); |
303 | beziernext->SetPole(beziernext->NbPoles(),pmid); |
304 | } |
305 | } |
306 | |
307 | } |
308 | BRepTools::Update(face); |
309 | } |
310 | } |
311 | |
312 | } |
313 | |
314 | myLevel--; |
315 | |
316 | return res; |
317 | } |
318 | |
319 | //======================================================================= |
320 | //function : GetSplitFaceTool |
321 | //purpose : |
322 | //======================================================================= |
323 | |
324 | Handle(ShapeUpgrade_FaceDivide) ShapeUpgrade_ShapeConvertToBezier::GetSplitFaceTool() const |
325 | { |
326 | Handle(ShapeUpgrade_FaceDivide) tool = new ShapeUpgrade_FaceDivide; |
327 | Handle(ShapeUpgrade_WireDivide) wtool = new ShapeUpgrade_WireDivide; |
328 | if(my3dMode) { |
329 | Handle(ShapeUpgrade_ConvertCurve3dToBezier) curve3dConverter = new ShapeUpgrade_ConvertCurve3dToBezier; |
330 | curve3dConverter->SetLineMode(my3dLineMode); |
331 | curve3dConverter->SetCircleMode(my3dCircleMode); |
332 | curve3dConverter->SetConicMode(my3dConicMode); |
333 | wtool->SetSplitCurve3dTool(curve3dConverter); |
334 | } |
335 | if(my2dMode) |
336 | wtool->SetSplitCurve2dTool(new ShapeUpgrade_ConvertCurve2dToBezier); |
337 | wtool->SetEdgeMode(myEdgeMode); |
338 | Handle(ShapeUpgrade_FixSmallBezierCurves) FixSmallBezierCurvesTool = new ShapeUpgrade_FixSmallBezierCurves; |
339 | wtool->SetFixSmallCurveTool(FixSmallBezierCurvesTool); |
340 | tool->SetWireDivideTool(wtool); |
341 | if(mySurfaceMode) { |
342 | Handle(ShapeUpgrade_ConvertSurfaceToBezierBasis) stool = new ShapeUpgrade_ConvertSurfaceToBezierBasis; |
343 | stool->SetPlaneMode(myPlaneMode); |
344 | stool->SetRevolutionMode(myRevolutionMode); |
345 | stool->SetExtrusionMode(myExtrusionMode); |
346 | stool->SetBSplineMode(myBSplineMode); |
347 | tool->SetSplitSurfaceTool(stool); |
348 | } |
349 | return tool; |
350 | } |
351 | |