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