7fd59977 |
1 | // SplitShape_Presentation.cpp: implementation of the SplitShape_Presentation class. |
2 | // Split shape by wire |
3 | ////////////////////////////////////////////////////////////////////// |
4 | |
5 | #include "stdafx.h" |
6 | #include "SplitShape_Presentation.h" |
7 | |
8 | #include <BRepAlgoAPI_Section.hxx> |
9 | #include <BRepFeat_SplitShape.hxx> |
10 | |
11 | #include <BRep_Builder.hxx> |
12 | #include <BRepTools.hxx> |
13 | #include <gp_Pln.hxx> |
14 | #include <Geom_Plane.hxx> |
15 | #include <TopExp_Explorer.hxx> |
16 | #include <TopoDS_Edge.hxx> |
17 | #include <TopoDS.hxx> |
18 | #include <TopoDS_Face.hxx> |
19 | #include <TopTools_ListOfShape.hxx> |
20 | #include <TopoDS_Shell.hxx> |
21 | #include <TopTools_ListIteratorOfListOfShape.hxx> |
22 | #include <Geom_RectangularTrimmedSurface.hxx> |
23 | #include <BRepBuilderAPI_MakeWire.hxx> |
24 | #include <TopoDS_Iterator.hxx> |
25 | #include <TopoDS_Wire.hxx> |
26 | #include <Prs3d_LineAspect.hxx> |
27 | #include <AIS_Drawer.hxx> |
28 | #include <TopLoc_Location.hxx> |
29 | #include <BRepOffsetAPI_MakeOffset.hxx> |
30 | #include <BRepBuilderAPI_MakePolygon.hxx> |
31 | #include <BRepPrimAPI_MakePrism.hxx> |
32 | #include <BRepAdaptor_Curve.hxx> |
33 | |
34 | |
35 | // Initialization of global variable with an instance of this class |
36 | OCCDemo_Presentation* OCCDemo_Presentation::Current = new SplitShape_Presentation; |
37 | |
38 | // Initialization of array of samples |
39 | const SplitShape_Presentation::PSampleFuncType SplitShape_Presentation::SampleFuncs[] = |
40 | { |
41 | &SplitShape_Presentation::sample1, |
42 | &SplitShape_Presentation::sample2 |
43 | }; |
44 | |
45 | #ifdef WNT |
46 | #define EOL "\r\n" |
47 | #define DELIM "\\" |
48 | #else |
49 | #define EOL "\n" |
50 | #define DELIM "/" |
51 | #endif |
52 | |
53 | ////////////////////////////////////////////////////////////////////// |
54 | // Construction/Destruction |
55 | ////////////////////////////////////////////////////////////////////// |
56 | |
57 | SplitShape_Presentation::SplitShape_Presentation() |
58 | { |
59 | myNbSamples = sizeof(SampleFuncs)/sizeof(PSampleFuncType); |
60 | setName ("SplitShape"); |
61 | } |
62 | |
63 | ////////////////////////////////////////////////////////////////////// |
64 | // Sample execution |
65 | ////////////////////////////////////////////////////////////////////// |
66 | |
67 | void SplitShape_Presentation::DoSample() |
68 | { |
69 | getAISContext()->EraseAll(); |
70 | if (myIndex >=0 && myIndex < myNbSamples) |
71 | (this->*SampleFuncs[myIndex])(); |
72 | } |
73 | |
74 | ////////////////////////////////////////////////////////////////////// |
75 | // Auxiliary functions |
76 | ////////////////////////////////////////////////////////////////////// |
77 | |
78 | Standard_Boolean SplitShape_Presentation::readShell(TCollection_AsciiString& theText) |
79 | { |
80 | myShell.Nullify(); |
81 | TCollection_AsciiString aPath; |
82 | aPath = aPath + GetDataDir() + DELIM + "shell1.brep"; |
83 | BRep_Builder aBld; |
84 | Standard_Boolean isRead = BRepTools::Read (myShell, aPath.ToCString(), aBld); |
85 | if (!isRead) |
86 | { |
87 | theText = aPath + " is not found"; |
88 | setResultText(theText.ToCString()); |
89 | } |
90 | return isRead; |
91 | } |
92 | |
93 | Standard_Boolean SplitShape_Presentation::computeSection |
94 | (BRepAlgoAPI_Section& aSecAlgo, |
95 | TopoDS_Wire& aSecWire, |
96 | TCollection_AsciiString& aText) |
97 | { |
98 | aText += |
99 | " aSecAlgo.Approximation(Standard_True); // approximate new geometries" EOL |
100 | " aSecAlgo.ComputePCurveOn1(Standard_True); // pcurves must be computed on shell" EOL |
101 | " aSecAlgo.Build();" EOL |
102 | " if (!aSecAlgo.IsDone())" EOL |
103 | " return;" EOL |
104 | " TopoDS_Shape aSection = aSecAlgo.Shape(); // get compound of section edges" EOL EOL |
105 | |
106 | " // connect section edges to a wire" EOL |
107 | " TopTools_ListOfShape aEdges;" EOL |
108 | " TopExp_Explorer ex(aSection, TopAbs_EDGE);" EOL |
109 | " if (!ex.More()) // is section empty?" EOL |
110 | " return;" EOL |
111 | " for (; ex.More(); ex.Next())" EOL |
112 | " aEdges.Append(ex.Current());" EOL |
113 | " BRepBuilderAPI_MakeWire aWMaker;" EOL |
114 | " aWMaker.Add(aEdges);" EOL |
115 | " if (!aWMaker.IsDone())" EOL |
116 | " return;" EOL |
117 | " TopoDS_Wire aSecWire = aWMaker.Wire();" EOL EOL; |
118 | setResultText(aText.ToCString()); |
119 | |
120 | // define parameters and perform section |
121 | aSecAlgo.Approximation(Standard_True); // approximate new geometries |
122 | aSecAlgo.ComputePCurveOn1(Standard_True); // pcurves must be computed on shell |
123 | aSecAlgo.Build(); |
124 | if (!aSecAlgo.IsDone()) |
125 | { |
126 | aText += EOL "Error: section algo has failed" EOL; |
127 | setResultText(aText.ToCString()); |
128 | return Standard_False; |
129 | } |
130 | TopoDS_Shape aSection = aSecAlgo.Shape(); // get compound of section edges |
131 | |
132 | // connect section edges to a wire |
133 | TopTools_ListOfShape aEdges; |
134 | TopExp_Explorer ex(aSection, TopAbs_EDGE); |
135 | if (!ex.More()) // is section empty? |
136 | { |
137 | aText += EOL "Error: no intersection found" EOL; |
138 | setResultText(aText.ToCString()); |
139 | return Standard_False; |
140 | } |
141 | for (; ex.More(); ex.Next()) |
142 | aEdges.Append(ex.Current()); |
143 | BRepBuilderAPI_MakeWire aWMaker; |
144 | aWMaker.Add(aEdges); |
145 | if (!aWMaker.IsDone()) |
146 | { |
147 | aText += EOL "Error: connecting of section edges has failed" EOL; |
148 | setResultText(aText.ToCString()); |
149 | return Standard_False; |
150 | } |
151 | aSecWire = aWMaker.Wire(); |
152 | |
153 | return Standard_True; |
154 | } |
155 | |
156 | ///////////////////////////////////////////////////////////////////// |
157 | |
158 | Standard_Boolean SplitShape_Presentation::splitAndComposeLeft |
159 | (const BRepAlgoAPI_Section& aSecAlgo, |
160 | const TopoDS_Wire& aSecWire, TopoDS_Shell& aNewShell, |
161 | TCollection_AsciiString& aText) |
162 | { |
163 | aText += |
164 | " // initialize splitting algo with the shell" EOL |
165 | " BRepFeat_SplitShape aSplitter(myShell);" EOL EOL |
166 | |
167 | " // add splitting edges" EOL |
168 | " TopoDS_Iterator its(aSecWire);" EOL |
169 | " for (; its.More(); its.Next())" EOL |
170 | " {" EOL |
171 | " const TopoDS_Edge& aEdge = TopoDS::Edge(its.Value());" EOL |
172 | " // determine an ancestor face of this edge" EOL |
173 | " TopoDS_Face aFace;" EOL |
174 | " if (aSecAlgo.HasAncestorFaceOn1(aEdge, aFace))" EOL |
175 | " aSplitter.Add (aEdge, aFace);" EOL |
176 | " }" EOL EOL |
177 | |
178 | " // perform splitting" EOL |
179 | " aSplitter.Build();" EOL |
180 | " if (!aSplitter.IsDone())" EOL |
181 | " return;" EOL EOL |
182 | |
183 | " // compose a new shell from the left side faces" EOL |
184 | " TopoDS_Shell aNewShell;" EOL |
185 | " aBld.MakeShell(aNewShell);" EOL |
186 | " const TopTools_ListOfShape& aLF = aSplitter.Left();" EOL |
187 | " TopTools_ListIteratorOfListOfShape it(aLF);" EOL |
188 | " for (; it.More(); it.Next())" EOL |
189 | " aBld.Add (aNewShell, it.Value());" EOL EOL; |
190 | setResultText(aText.ToCString()); |
191 | |
192 | // initialize splitting algo with the shell |
193 | BRepFeat_SplitShape aSplitter(myShell); |
194 | |
195 | // add splitting edges |
196 | TopoDS_Iterator its(aSecWire); |
197 | for (; its.More(); its.Next()) |
198 | { |
199 | const TopoDS_Edge& aEdge = TopoDS::Edge(its.Value()); |
200 | // determine an ancestor face of this edge |
201 | TopoDS_Face aFace; |
202 | if (aSecAlgo.HasAncestorFaceOn1(aEdge, aFace)) |
203 | aSplitter.Add (aEdge, aFace); |
204 | } |
205 | |
206 | // perform splitting |
207 | aSplitter.Build(); |
208 | if (!aSplitter.IsDone()) |
209 | { |
210 | aText += EOL "Error: splitting algo has failed" EOL; |
211 | setResultText(aText.ToCString()); |
212 | return Standard_False; |
213 | } |
214 | |
215 | // compose a new shell from the left side faces |
216 | BRep_Builder aBld; |
217 | aBld.MakeShell(aNewShell); |
218 | const TopTools_ListOfShape& aLF = aSplitter.Left(); |
219 | TopTools_ListIteratorOfListOfShape it(aLF); |
220 | for (; it.More(); it.Next()) |
221 | aBld.Add (aNewShell, it.Value()); |
222 | |
223 | return Standard_True; |
224 | } |
225 | |
226 | ////////////////////////////////////////////////////////////////////// |
227 | // Sample functions |
228 | ////////////////////////////////////////////////////////////////////// |
229 | |
230 | void SplitShape_Presentation::sample1() |
231 | { |
232 | ResetView(); |
233 | SetViewCenter(60.457558475728, -20.351205260916); |
234 | SetViewScale(29.468160110195); |
235 | |
236 | setResultTitle ("Split shell by plane"); |
237 | TCollection_AsciiString aText = |
238 | " // define initial shell" EOL |
239 | " TopoDS_Shell myShell;" EOL |
240 | " // myShell = ...;" EOL EOL |
241 | |
242 | " // define secant plane" EOL |
243 | " gp_Pln aPln(gp_Pnt(65,11,0), gp_Dir(1,-0.1,-0.3));" EOL EOL |
244 | |
245 | " // make section of myShell by the plane" EOL |
246 | " Standard_Boolean performNow = Standard_False;" EOL |
247 | " BRepAlgoAPI_Section aSecAlgo (myShell, aPln, performNow);" EOL |
248 | ; |
249 | setResultText(aText.ToCString()); |
250 | |
251 | // read shell |
252 | if (myShell.IsNull() && !readShell(aText)) |
253 | return; |
254 | |
255 | Handle(AIS_InteractiveObject) aIShell = drawShape (myShell); |
256 | if (WAIT_A_SECOND) return; |
257 | |
258 | // define secant plane |
259 | gp_Pln aPln(gp_Pnt(65,11,0), gp_Dir(1,-0.1,-0.3)); |
260 | |
261 | Handle(Geom_Surface) aPlane = new Geom_Plane(aPln); |
262 | aPlane = new Geom_RectangularTrimmedSurface(aPlane,-5.,20.,-13.,13.); |
263 | Handle(AIS_InteractiveObject) aIPlane = drawSurface(aPlane); |
264 | |
265 | if (WAIT_A_LITTLE) return; |
266 | |
267 | // make section of myShell by the plane |
268 | TopoDS_Wire aSecWire; |
269 | Standard_Boolean performNow = Standard_False; |
270 | BRepAlgoAPI_Section aSecAlgo (myShell, aPln, performNow); |
271 | if (!computeSection(aSecAlgo, aSecWire, aText)) |
272 | return; |
273 | |
274 | getAISContext()->Erase(aIPlane); |
275 | Handle(AIS_InteractiveObject) aISecWire = drawShape (aSecWire,Quantity_NOC_GREEN,Standard_False); |
276 | Handle(Prs3d_LineAspect) aLA = |
277 | new Prs3d_LineAspect(Quantity_NOC_GREEN,Aspect_TOL_SOLID,3.); |
278 | aISecWire->Attributes()->SetWireAspect(aLA); |
279 | getAISContext()->Display(aISecWire); |
280 | if (WAIT_A_LITTLE) return; |
281 | |
282 | aText += |
283 | " //aSecWire.Reverse(); // orient wire to have the left side as you need" EOL EOL; |
284 | setResultText(aText.ToCString()); |
285 | //aSecWire.Reverse(); // orient wire to have the left side as you need |
286 | |
287 | // split myShell by aSecWire and compose the left side subshell |
288 | TopoDS_Shell aNewShell; |
289 | if (!splitAndComposeLeft(aSecAlgo, aSecWire, aNewShell, aText)) |
290 | return; |
291 | |
292 | drawShape (aNewShell); |
293 | getAISContext()->Erase(aIShell); |
294 | getAISContext()->Erase(aISecWire); |
295 | } |
296 | |
297 | ///////////////////////////////////////////////////////////////////// |
298 | |
299 | void SplitShape_Presentation::sample2() |
300 | { |
301 | setResultTitle ("Cut hole from shell"); |
302 | TCollection_AsciiString aText = |
303 | " // define initial shell" EOL |
304 | " TopoDS_Shell myShell;" EOL |
305 | " // myShell = ...;" EOL EOL |
306 | |
307 | " // define contour of the hole and its normal direction" EOL |
308 | " TopoDS_Wire aCont;" EOL |
309 | " gp_Dir aNormal(-0.2, -0.7, 0.4);" EOL |
310 | " // aCont = ... ;" EOL EOL |
311 | |
312 | " // project the contour on the shell along aNormal;" EOL |
313 | " // for that create prism from the contour" EOL |
314 | " // and find intersection with the shell" EOL |
315 | " Standard_Real dist = 8;" EOL |
316 | " gp_Vec aPrismVec(aNormal.Reversed().XYZ()*dist*2);" EOL |
317 | " BRepPrimAPI_MakePrism aSweeper(aCont,aPrismVec);" EOL |
318 | " if (!aSweeper.IsDone())" EOL |
319 | " return;" EOL |
320 | " TopoDS_Shape aPrism = aSweeper.Shape();" EOL EOL |
321 | |
322 | " // make section of myShell by the prism" EOL |
323 | " TopoDS_Wire aSecWire;" EOL |
324 | " Standard_Boolean performNow = Standard_False;" EOL |
325 | " BRepAlgoAPI_Section aSecAlgo (myShell, aPrism, performNow);" EOL |
326 | ; |
327 | setResultText(aText.ToCString()); |
328 | |
329 | // read shell |
330 | if (myShell.IsNull() && !readShell(aText)) |
331 | return; |
332 | |
333 | Handle(AIS_InteractiveObject) aIShell = drawShape (myShell); |
334 | if (WAIT_A_SECOND) return; |
335 | |
336 | // define contour of the hole and its normal direction |
337 | TopoDS_Wire aCont; |
338 | gp_Dir aNormal(-0.2, -0.7, 0.4); |
339 | |
340 | Standard_Real dx=2, dy=1.5, aOffValue=1.5; |
341 | TopoDS_Wire aPol = BRepBuilderAPI_MakePolygon(gp_Pnt(-dx,-dy,0), gp_Pnt(dx,-dy,0), |
342 | gp_Pnt(dx,dy,0), gp_Pnt(-dx,dy,0), |
343 | Standard_True); |
344 | // transform contour to a needed location |
345 | gp_Pnt aOrigin(78,16,10); |
346 | gp_Dir aXDir(1, 0, 0); |
347 | gp_Ax2 aSystem(aOrigin, aNormal, aXDir); |
348 | gp_Trsf aTrsf; |
349 | aTrsf.SetDisplacement(gp::XOY(), aSystem); |
350 | aPol.Location(TopLoc_Location(aTrsf)); |
351 | BRepOffsetAPI_MakeOffset aOffAlgo (aPol, GeomAbs_Arc); |
352 | aOffAlgo.Perform (aOffValue); |
353 | aCont = TopoDS::Wire(aOffAlgo.Shape()); |
354 | |
355 | Handle(AIS_InteractiveObject) aICont = drawShape (aCont); |
356 | if (WAIT_A_SECOND) return; |
357 | |
358 | // project the contour on the shell along aNormal; |
359 | // for that create prism from the contour |
360 | // and find intersection with the shell |
361 | Standard_Real dist = 8; |
362 | gp_Vec aPrismVec(aNormal.Reversed().XYZ()*dist); |
363 | BRepPrimAPI_MakePrism aSweeper(aCont,aPrismVec); |
364 | if (!aSweeper.IsDone()) |
365 | { |
366 | aText += EOL "Error: sweeping algo has failed" EOL; |
367 | setResultText(aText.ToCString()); |
368 | return; |
369 | } |
370 | TopoDS_Shape aPrism = aSweeper.Shape(); |
371 | |
372 | Handle(AIS_InteractiveObject) aIPrism = drawShape(aPrism, Quantity_NOC_LEMONCHIFFON3); |
373 | if (WAIT_A_LITTLE) return; |
374 | |
375 | // make section of myShell by the prism |
376 | TopoDS_Wire aSecWire; |
377 | Standard_Boolean performNow = Standard_False; |
378 | BRepAlgoAPI_Section aSecAlgo (myShell, aPrism, performNow); |
379 | if (!computeSection(aSecAlgo, aSecWire, aText)) |
380 | return; |
381 | |
382 | aText += |
383 | " aSecWire.Reverse(); // orient wire to have the left side as you need" EOL EOL; |
384 | setResultText(aText.ToCString()); |
385 | //aSecWire.Reverse(); // orient wire to have the left side as you need |
386 | // get an edge from the initial contour and |
387 | // determine the corresponding projection edge from the section wire; |
388 | // check orientations of their first derivatives |
389 | TopoDS_Shape aEdgeP, aEdge1, aFace, aEdge2; |
390 | TopoDS_Iterator it(aPol); |
391 | aEdgeP = it.Value(); |
392 | aEdge1 = aOffAlgo.Generated(aEdgeP).First(); |
393 | aFace = aSweeper.Generated(aEdge1).First(); |
394 | for (it.Initialize(aSecWire); it.More() && aEdge2.IsNull(); it.Next()) |
395 | { |
396 | TopoDS_Shape aF; |
397 | if (aSecAlgo.HasAncestorFaceOn2(it.Value(),aF) && aF.IsSame(aFace)) |
398 | aEdge2 = it.Value(); |
399 | } |
400 | if (aEdge2.IsNull()) |
401 | { |
402 | aText += EOL "Error: cannot orient projected contour due to" EOL |
403 | "failure restoring history of modification" EOL; |
404 | setResultText(aText.ToCString()); |
405 | return; |
406 | } |
407 | BRepAdaptor_Curve aC1(TopoDS::Edge(aEdge1)), aC2(TopoDS::Edge(aEdge2)); |
408 | gp_Pnt p1, p2; |
409 | gp_Vec v1, v2; |
410 | aC1.D1(aC1.FirstParameter(), p1, v1); |
411 | aC2.D1(aC2.FirstParameter(), p2, v2); |
412 | if (aEdge1.Orientation() == TopAbs_REVERSED) v1.Reverse(); |
413 | if (aEdge2.Orientation() == TopAbs_REVERSED) v2.Reverse(); |
414 | Standard_Real pr = v1 * v2; |
415 | if (pr > 0.) |
416 | aSecWire.Reverse(); |
417 | |
418 | getAISContext()->Erase(aIPrism); |
419 | Handle(AIS_InteractiveObject) aISecWire = drawShape (aSecWire,Quantity_NOC_GREEN,Standard_False); |
420 | Handle(Prs3d_LineAspect) aLA = |
421 | new Prs3d_LineAspect(Quantity_NOC_GREEN,Aspect_TOL_SOLID,3.); |
422 | aISecWire->Attributes()->SetWireAspect(aLA); |
423 | getAISContext()->Display(aISecWire); |
424 | if (WAIT_A_SECOND) return; |
425 | |
426 | // split myShell by aSecWire and compose the left side subshell |
427 | TopoDS_Shell aNewShell; |
428 | if (!splitAndComposeLeft(aSecAlgo, aSecWire, aNewShell, aText)) |
429 | return; |
430 | |
431 | drawShape (aNewShell); |
432 | getAISContext()->Erase(aIShell); |
433 | getAISContext()->Erase(aISecWire); |
434 | } |