0025853: Edges disappear or reappear when displaying new edges
[occt.git] / samples / mfc / occtdemo / SplitShape / SplitShape_Presentation.cpp
CommitLineData
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
36OCCDemo_Presentation* OCCDemo_Presentation::Current = new SplitShape_Presentation;
37
38// Initialization of array of samples
39const 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
57SplitShape_Presentation::SplitShape_Presentation()
58{
59 myNbSamples = sizeof(SampleFuncs)/sizeof(PSampleFuncType);
60 setName ("SplitShape");
61}
62
63//////////////////////////////////////////////////////////////////////
64// Sample execution
65//////////////////////////////////////////////////////////////////////
66
67void 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
78Standard_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
93Standard_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
158Standard_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
230void 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
299void 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}