Integration of OCCT 6.5.0 from SVN
[occt.git] / samples / mfc / occtdemo / SplitShape / SplitShape_Presentation.cpp
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 }