0026855: Draw commands to debug Boolean Operations Algorithm
[occt.git] / src / BOPTest / BOPTest_DebugCommands.cxx
1 // Created by: Eugeny MALTCHIKOV
2 // Copyright (c) 2015 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15
16 #include <BOPTest.hxx>
17 #include <BOPTest_Objects.hxx>
18 #include <BOPTest_DrawableShape.hxx>
19
20 #include <Draw.hxx>
21 #include <Draw_Color.hxx>
22
23 #include <DBRep.hxx>
24
25 #include <BRep_Builder.hxx>
26
27 #include <TopoDS_Compound.hxx>
28
29 #include <TopExp_Explorer.hxx>
30
31 #include <BOPDS_DS.hxx>
32 #include <BOPDS_Iterator.hxx>
33 #include <BOPDS_MapOfCommonBlock.hxx>
34
35 #include <BOPAlgo_Builder.hxx>
36 #include <BOPAlgo_BuilderFace.hxx>
37 #include <BOPAlgo_BuilderSolid.hxx>
38
39 #include <BOPCol_MapOfShape.hxx>
40 #include <BOPCol_DataMapOfShapeShape.hxx>
41 #include <BOPCol_DataMapOfShapeListOfShape.hxx>
42
43
44 static
45   void GetTypeByName(const char* theName,
46                      TopAbs_ShapeEnum& theType);
47 static
48   void GetNameByType(const TopAbs_ShapeEnum& theType,
49                      char* theName);
50
51 template <class InterfType> static
52   void DumpInterfs(const BOPCol_NCVector<InterfType>& theVInterf,
53                    Draw_Interpretor& di);
54
55 template <class InterfType> static
56   void SearchNewIndex(const char* theCType,
57                       const Standard_Integer theInd,
58                       const BOPCol_NCVector<InterfType>& theVInterf,
59                       Draw_Interpretor& di);
60 static 
61   Standard_Integer bopfinfo(Draw_Interpretor& di,
62                             Standard_Integer n,
63                             const char** a,
64                             const Standard_Integer iPriz);
65
66
67 // commands
68 // 1. filler commands
69 // 1.1 DS commands
70 static Standard_Integer bopds       (Draw_Interpretor&, Standard_Integer, const char**);
71 static Standard_Integer bopiterator (Draw_Interpretor&, Standard_Integer, const char**);
72 static Standard_Integer bopinterf   (Draw_Interpretor&, Standard_Integer, const char**);
73 static Standard_Integer bopnews     (Draw_Interpretor&, Standard_Integer, const char**);
74 static Standard_Integer bopwho      (Draw_Interpretor&, Standard_Integer, const char**);
75 static Standard_Integer bopindex    (Draw_Interpretor&, Standard_Integer, const char**);
76 static Standard_Integer bopsd       (Draw_Interpretor&, Standard_Integer, const char**);
77 static Standard_Integer bopsc       (Draw_Interpretor&, Standard_Integer, const char**);
78
79 // 1.2 pave blocks commands
80 static Standard_Integer boppb       (Draw_Interpretor&, Standard_Integer, const char**);
81 static Standard_Integer bopcb       (Draw_Interpretor&, Standard_Integer, const char**);
82 static Standard_Integer bopsp       (Draw_Interpretor&, Standard_Integer, const char**);
83
84 // 1.3 face info commands
85 static Standard_Integer bopfon      (Draw_Interpretor&, Standard_Integer, const char**);
86 static Standard_Integer bopfin      (Draw_Interpretor&, Standard_Integer, const char**);
87 static Standard_Integer bopfsc      (Draw_Interpretor&, Standard_Integer, const char**);
88 static Standard_Integer bopfav      (Draw_Interpretor&, Standard_Integer, const char**);
89
90 // 2. builder commands
91 // 2.1 images commands
92 static Standard_Integer bopimage    (Draw_Interpretor&, Standard_Integer, const char**);
93 static Standard_Integer boporigin   (Draw_Interpretor&, Standard_Integer, const char**);
94 static Standard_Integer bopfsd      (Draw_Interpretor&, Standard_Integer, const char**);
95
96 // 2.2 building faces
97 static Standard_Integer bopbface    (Draw_Interpretor&, Standard_Integer, const char**);
98 // 2.3 building solids
99 static Standard_Integer bopbsolid   (Draw_Interpretor&, Standard_Integer, const char**);
100
101
102 //=======================================================================
103 //function : DebugCommands
104 //purpose  : 
105 //=======================================================================
106 void BOPTest::DebugCommands(Draw_Interpretor& theCommands)
107 {
108   static Standard_Boolean done = Standard_False;
109   if (done) return;
110   done = Standard_True;
111   // Chapter's name
112   const char* g = "BOPTest commands";
113   // Commands
114   theCommands.Add("bopds",
115                   "Shows the shapes from DS. Use: bopds [v/e/w/f/sh/s/cs/c]",
116                   __FILE__, bopds,       g);
117   theCommands.Add("bopiterator", 
118                   "Shows the pairs of interfered shapes. Use: bopiterator [type1 type2]",
119                   __FILE__, bopiterator, g);
120   theCommands.Add("bopinterf", "Shows interferences of given type. Use: bopinterf type1 type2",
121                   __FILE__, bopinterf,   g);
122   theCommands.Add("bopnews", "Shows the newly created shapes. Use: bopnews [v,e,f]",
123                   __FILE__, bopnews,     g);
124   theCommands.Add("bopwho", "Shows where the new shape was created. Use: bopwho #",
125                   __FILE__, bopwho,      g);
126   theCommands.Add("bopindex", "Gets the index of the shape in the DS. Use: bopindex s",
127                   __FILE__, bopindex,    g);
128   theCommands.Add("bopsd", "Gets the Same domain shape. Use: bopsd #",
129                    __FILE__, bopsd,      g);
130   theCommands.Add("bopsc", "Shows the section curves. Use: bopsc [nF1 nF2]",
131                   __FILE__, bopsc,       g);
132   theCommands.Add("boppb", "Shows information about pave blocks. Use: boppb [#e]",
133                   __FILE__, boppb,       g);
134   theCommands.Add("bopcb", "Shows information about common blocks. Use: bopcb [#e]",
135                   __FILE__, bopcb,       g);
136   theCommands.Add("bopsp", "Shows the splits of edges. Use: bopsp [#e]",
137                   __FILE__, bopsp,       g);
138   theCommands.Add("bopfon", "Shows ON information for the face. Use: bopfon #f",
139                   __FILE__, bopfon,      g);
140   theCommands.Add("bopfin", "Shows IN information for the face. Use: bopfin #f",
141                   __FILE__, bopfin,      g);
142   theCommands.Add("bopfsc", "Shows SC information for the face. Use: bopfsc #f",
143                   __FILE__, bopfsc,      g);
144   theCommands.Add("bopfav", "Shows information about alone vertices for the face. Use: bopfav #f",
145                   __FILE__, bopfav,      g);
146   theCommands.Add("bopimage", "Shows split parts of the shape. Use: bopimage s",
147                   __FILE__, bopimage,    g);
148   theCommands.Add("boporigin", "Shows the original shape for the shape. Use: boporigin s",
149                   __FILE__, boporigin,   g);
150   theCommands.Add("bopfsd", "Shows SD faces for the face: Use: bopfsd f",
151                   __FILE__, bopfsd,      g);
152   theCommands.Add("bopbsolid", "Build solids from set of shared faces. Use: bopbsolid sr cx",
153                   __FILE__, bopbsolid,   g);
154   theCommands.Add("bopbface", "Splits the face by set of shared edges. Use: bopbface fr cx",
155                   __FILE__, bopbface,    g);
156 }
157
158 //=======================================================================
159 //function : bopds
160 //purpose  : 
161 //=======================================================================
162 Standard_Integer bopds (Draw_Interpretor& di,
163                         Standard_Integer n,
164                         const char** a)
165 {
166   if (n > 2) {
167     di << "Shows the shapes from DS. Use: bopds [v/e/w/f/sh/s/cs/c]\n";
168     return 1;
169   }
170   //
171   BOPDS_PDS pDS = BOPTest_Objects::PDS();
172   if (!pDS) {
173     di << " prepare PaveFiller first\n";
174     return 1;
175   }
176   //
177   char buf[32];
178   Standard_CString aText;
179   Standard_Integer i, aNbS;
180   TopAbs_ShapeEnum aType, aTypeShape;
181   Draw_Color aTextColor(Draw_cyan);
182   //
183   BOPDS_DS& aDS = *pDS;
184   aNbS = aDS.NbSourceShapes();
185   //
186   aType = TopAbs_SHAPE;
187   if (n == 2) {
188     GetTypeByName(a[1], aType);
189   }
190   //
191   for (i = 0; i < aNbS; ++i) {
192     const BOPDS_ShapeInfo& aSI = aDS.ShapeInfo(i);
193     const TopoDS_Shape& aS = aSI.Shape();
194     aTypeShape = aSI.ShapeType();
195     if (n == 1) {
196       if (aTypeShape == TopAbs_COMPOUND ||
197           aTypeShape == TopAbs_COMPSOLID ||
198           aTypeShape == TopAbs_SOLID ||
199           aTypeShape == TopAbs_SHELL || 
200           aTypeShape == TopAbs_WIRE) {
201         continue;
202       }
203     }
204     else {
205       if (aTypeShape != aType) {
206         continue;
207       }
208     }
209     //
210     Sprintf(buf, "z%d", i);
211     aText = buf;
212     Handle(BOPTest_DrawableShape) aDShape = new BOPTest_DrawableShape(aS, aText, aTextColor);
213     Draw::Set(aText, aDShape);
214   }
215   //
216   return 0;
217 }
218
219 //=======================================================================
220 //function : bopiterator
221 //purpose  : 
222 //=======================================================================
223 Standard_Integer bopiterator (Draw_Interpretor& di,
224                               Standard_Integer n,
225                               const char** a)
226 {
227   if (n != 1 && n != 3) {
228     di << "Shows the pairs of interfered shapes. Use: bopiterator [type1 type2]\n";
229     return 1;
230   }
231   //
232   BOPDS_PDS pDS = BOPTest_Objects::PDS();
233   if (!pDS) {
234     di << " prepare PaveFiller first\n";
235     return 1;
236   }
237   //
238   Standard_Boolean bFlag;
239   Standard_Integer n1, n2;
240   char buf[64], aST1[10], aST2[10];
241   BOPDS_Iterator aIt;
242   //
243   BOPDS_DS& aDS = *pDS;
244   aIt.SetDS(&aDS);
245   aIt.Prepare();
246   //
247   if (n == 1) {
248     // type has not been defined. show all pairs
249     Standard_Integer i, j;
250     TopAbs_ShapeEnum aT[4] = 
251       {TopAbs_VERTEX, TopAbs_EDGE, TopAbs_FACE, TopAbs_SOLID};
252     for (i = 0; i < 4; ++i) {
253       GetNameByType(aT[i], aST1);
254       //
255       for (j = 0; j < 4; ++j) {
256         GetNameByType(aT[j], aST2);
257         //
258         aIt.Initialize(aT[i], aT[j]);
259         for (; aIt.More(); aIt.Next()) {
260           aIt.Value(n1, n2, bFlag);
261           //
262           Sprintf(buf, "%s/%s: (z%d z%d)\n", aST1, aST2, n1, n2);
263           di << buf;
264         }
265       }
266     }
267   }
268   else if (n == 3) {
269     TopAbs_ShapeEnum aT1, aT2;
270     //
271     GetTypeByName(a[1], aT1);
272     GetTypeByName(a[2], aT2);
273     //
274     GetNameByType(aT1, aST1);
275     GetNameByType(aT2, aST2);
276     //
277     aIt.Initialize(aT1, aT2);
278     for (; aIt.More(); aIt.Next()) {
279       aIt.Value(n1, n2, bFlag);
280       //
281       Sprintf(buf, "%s/%s: (z%d z%d)\n", aST1, aST2, n1, n2);
282       di << buf;
283     }
284   }
285   //
286   return 0;
287 }
288
289 //=======================================================================
290 //function : bopinterf
291 //purpose  : 
292 //=======================================================================
293 Standard_Integer bopinterf (Draw_Interpretor& di,
294                             Standard_Integer n,
295                             const char** a)
296 {
297   if (n != 3) {
298     di << "Shows interferences of given type. Use: bopinterf type1 type2\n";
299     return 1;
300   }
301   //
302   BOPDS_PDS pDS = BOPTest_Objects::PDS();
303   if (!pDS) {
304     di << " prepare PaveFiller first\n";
305     return 1;
306   }
307   //
308   TopAbs_ShapeEnum aT1, aT2;
309   GetTypeByName(a[1], aT1);
310   GetTypeByName(a[2], aT2);
311   //
312   if (aT1 == TopAbs_VERTEX && aT2 == TopAbs_VERTEX) {
313     di << "V/V: ";
314     DumpInterfs<BOPDS_InterfVV>(pDS->InterfVV(), di);
315   }
316   else if ((aT1 == TopAbs_VERTEX && aT2 == TopAbs_EDGE) ||
317            (aT2 == TopAbs_VERTEX && aT1 == TopAbs_EDGE)) {
318     di << "V/E: ";
319     DumpInterfs<BOPDS_InterfVE>(pDS->InterfVE(), di);
320   }
321   else if (aT1 == TopAbs_EDGE && aT2 == TopAbs_EDGE) {
322     di << "E/E: ";
323     DumpInterfs<BOPDS_InterfEE>(pDS->InterfEE(), di);
324   }
325   else if ((aT1 == TopAbs_VERTEX && aT2 == TopAbs_FACE) ||
326            (aT2 == TopAbs_VERTEX && aT1 == TopAbs_FACE)) {
327     di << "V/F: ";
328     DumpInterfs<BOPDS_InterfVF>(pDS->InterfVF(), di);
329   }
330   else if ((aT1 == TopAbs_EDGE && aT2 == TopAbs_FACE) ||
331            (aT2 == TopAbs_EDGE && aT1 == TopAbs_FACE)) {
332     di << "E/F: ";
333     DumpInterfs<BOPDS_InterfEF>(pDS->InterfEF(), di);
334   }
335   else if (aT1 == TopAbs_FACE && aT2 == TopAbs_FACE) {
336     di << "F/F: ";
337     DumpInterfs<BOPDS_InterfFF>(pDS->InterfFF(), di);
338   }
339   else if ((aT1 == TopAbs_VERTEX && aT2 == TopAbs_SOLID) ||
340            (aT2 == TopAbs_VERTEX && aT1 == TopAbs_SOLID)) {
341     di << "V/S: ";
342     DumpInterfs<BOPDS_InterfVZ>(pDS->InterfVZ(), di);
343   }
344   else if ((aT1 == TopAbs_EDGE && aT2 == TopAbs_SOLID) ||
345            (aT2 == TopAbs_EDGE && aT1 == TopAbs_SOLID)) {
346     di << "E/S: ";
347     DumpInterfs<BOPDS_InterfEZ>(pDS->InterfEZ(), di);
348   }
349   else if ((aT1 == TopAbs_FACE && aT2 == TopAbs_SOLID) ||
350            (aT2 == TopAbs_FACE && aT1 == TopAbs_SOLID)) {
351     di << "F/S: ";
352     DumpInterfs<BOPDS_InterfFZ>(pDS->InterfFZ(), di);
353   }
354   else if (aT1 == TopAbs_SOLID && aT2 == TopAbs_SOLID) {
355     di << "S/S: ";
356     DumpInterfs<BOPDS_InterfZZ>(pDS->InterfZZ(), di);
357   }
358   //
359   return 0;
360 }
361
362 //=======================================================================
363 //function : bopwho
364 //purpose  : 
365 //=======================================================================
366 Standard_Integer bopwho (Draw_Interpretor& di,
367                          Standard_Integer n,
368                          const char** a)
369 {
370   if (n != 2) {
371     di << "Shows where the new shape was created. Use: bopwho #\n";
372     return 1;
373   }
374   //
375   BOPDS_PDS pDS=BOPTest_Objects::PDS();
376   if (!pDS) {
377     di << " prepare PaveFiller first\n";
378     return 0;
379   }
380   //
381   Standard_Integer ind = Draw::Atoi(a[1]);
382   if (ind <= 0) {
383     di << " Index must be grater than 0\n";
384     return 1;
385   }
386   //
387   Standard_Integer i1, i2;
388   //
389   i1 = 0;
390   i2 = pDS->NbShapes();
391   if (ind < i1 || ind > i2) {
392     di << " DS does not contain the shape\n";
393     return 1;
394   }
395   //
396   if (!pDS->IsNewShape(ind)) {
397     Standard_Integer iRank = pDS->Rank(ind);
398     di << " Rank: " << iRank << "\n";
399     return 0;
400   }
401   //
402   // the shape is new
403   di << "the shape is new\n";
404   //
405   const BOPDS_ShapeInfo& aSI = pDS->ShapeInfo(ind);
406   if (aSI.ShapeType() != TopAbs_VERTEX) {
407     return 0;
408   }
409   // search among interfs
410   BOPDS_VectorOfInterfVV& aVVs = pDS->InterfVV();
411   BOPDS_VectorOfInterfVE& aVEs = pDS->InterfVE();
412   BOPDS_VectorOfInterfEE& aEEs = pDS->InterfEE();
413   BOPDS_VectorOfInterfVF& aVFs = pDS->InterfVF();
414   BOPDS_VectorOfInterfEF& aEFs = pDS->InterfEF();
415   //
416   SearchNewIndex<BOPDS_InterfVV> ("V/V: ", ind, aVVs, di);
417   SearchNewIndex<BOPDS_InterfVE> ("V/E: ", ind, aVEs, di);
418   SearchNewIndex<BOPDS_InterfEE> ("E/E: ", ind, aEEs, di);
419   SearchNewIndex<BOPDS_InterfVF> ("V/F: ", ind, aVFs, di);
420   SearchNewIndex<BOPDS_InterfEF> ("E/F: ", ind, aEFs, di);
421   //
422   //--------------------------------------FF
423   char buf[64];
424   Standard_Boolean bFound;
425   Standard_Integer i, n1, n2, k, aNb, aNbC, aNbP, nV1, nV2;
426   BOPDS_ListIteratorOfListOfPaveBlock aItLPB;
427   //
428   bFound = Standard_False;
429   BOPDS_VectorOfInterfFF& aFFs = pDS->InterfFF();
430   aNb = aFFs.Extent();
431   for (i = 0; i < aNb; ++i) {
432     const BOPDS_InterfFF& anInt = aFFs(i);
433     anInt.Indices(n1, n2);
434     //
435     const BOPDS_VectorOfCurve& aVNC = anInt.Curves();
436     aNbC = aVNC.Extent();
437     for (k = 0; k < aNbC; ++k) {
438       const BOPDS_Curve& aNC = aVNC(k);
439       const BOPDS_ListOfPaveBlock& aLPB = aNC.PaveBlocks(); 
440       aItLPB.Initialize(aLPB);
441       for(; aItLPB.More(); aItLPB.Next()) {
442         const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
443         aPB->Indices(nV1, nV2);
444         if (ind == nV1 || ind == nV2) {
445           if (!bFound) {
446             di << " FF curves: ";
447             bFound = Standard_True;
448           }
449           Sprintf (buf,"(%d, %d) ", n1, n2);
450           di << buf;
451           break;
452         }
453       }
454     }//for (k=0; k<aNbC; ++k) 
455     if (bFound) {
456       di << "\n";
457     }
458     //
459     bFound = Standard_False;
460     const BOPDS_VectorOfPoint& aVNP = anInt.Points();
461     aNbP = aVNP.Extent();
462     for (k = 0; k < aNbP; ++k) {
463       const BOPDS_Point& aNP = aVNP(k);
464       nV1 = aNP.Index();
465       if (ind == nV1) {
466         if (!bFound) {
467           di << " FF points: ";
468           bFound = Standard_True;
469         }
470         sprintf (buf,"(%d, %d) ", n1, n2);
471         di << buf;
472       }
473     }//for (k=0; k<aNbP; ++k) 
474     if (bFound) {
475       di << "\n";
476     }
477   }
478   //
479   return 0;
480 }
481
482 //=======================================================================
483 //function : bopnews
484 //purpose  : 
485 //=======================================================================
486 Standard_Integer bopnews(Draw_Interpretor& di,
487                          Standard_Integer n,
488                          const char** a)
489
490   if (n != 2) {
491     di << "Shows the newly created shapes. Use: bopnews v/e/f\n";
492     return 1;
493   }
494   //
495   BOPDS_PDS pDS = BOPTest_Objects::PDS();
496   if (!pDS) {
497     di << " prepare PaveFiller first\n";
498     return 1;
499   }
500   //
501   TopAbs_ShapeEnum aType;
502   GetTypeByName(a[1], aType);
503   //
504   if (!(aType == TopAbs_VERTEX ||
505         aType == TopAbs_EDGE ||
506         aType == TopAbs_FACE)) {
507     di << "Use: bopnews v/e/f\n";
508     return 1;
509   }
510   //
511   char buf[32];
512   Standard_CString aText;
513   Standard_Boolean bFound;
514   Standard_Integer i, i1, i2;
515   Draw_Color aTextColor(Draw_cyan);
516   Handle(BOPTest_DrawableShape) aDShape;
517   //
518   bFound = Standard_False;
519   i1 = pDS->NbSourceShapes();
520   i2 = pDS->NbShapes();
521   for (i = i1; i < i2; ++i) {
522     const BOPDS_ShapeInfo& aSI = pDS->ShapeInfo(i);
523     if (aSI.ShapeType() == aType) {
524       const TopoDS_Shape& aS = aSI.Shape();
525       //
526       sprintf (buf, "z%d", i);
527       aText = buf;
528       aDShape = new BOPTest_DrawableShape(aS, aText, aTextColor);
529       Draw::Set(aText, aDShape);
530       //
531       sprintf (buf, "z%d ", i);
532       di << buf;
533       //
534       bFound = Standard_True;
535     }
536   }
537   //
538   if (bFound) {
539     di << "\n";
540   }
541   else {
542     di << " No new shapes found\n";
543   }
544   //
545   return 0;
546 }
547
548 //=======================================================================
549 //function : bopindex
550 //purpose  : 
551 //=======================================================================
552 Standard_Integer bopindex (Draw_Interpretor& di,
553                            Standard_Integer n,
554                            const char** a)
555 {
556   if (n != 2) {
557     di << "Gets the index of the shape in the DS. Use: bopindex s\n";
558     return 1;
559   }
560   //
561   BOPDS_PDS pDS=BOPTest_Objects::PDS();
562   if (!pDS) {
563     di << " prepare PaveFiller first\n";
564     return 1;
565   }
566   //
567   TopoDS_Shape aS = DBRep::Get(a[1]);
568   if (aS.IsNull()) {
569     di << a[1] << " is a null shape\n";
570     return 1;
571   }
572   //
573   Standard_Integer ind = pDS->Index(aS);
574   Standard_Boolean bFound = (ind > 0);
575   if (bFound) {
576     di << " Index: " << ind << "\n";
577   }
578   else {
579     Standard_Integer i1, i2;
580     //
581     i1 = pDS->NbSourceShapes();
582     i2 = pDS->NbShapes();
583     for (ind = i1; ind < i2; ++ind) {
584       const TopoDS_Shape& aSx = pDS->Shape(ind);
585       if (aSx.IsSame(aS)) {
586         di << " Index: " << ind << "\n";
587         bFound = Standard_True;
588         break;
589       }
590     }
591   }
592   //
593   if (!bFound) {
594     di << " DS does not contain the shape\n";
595   }
596   //
597   return 0;
598 }
599   
600 //=======================================================================
601 //function : bopsd
602 //purpose  : 
603 //=======================================================================
604 Standard_Integer bopsd(Draw_Interpretor& di,
605                        Standard_Integer n,
606                        const char** a)
607
608   if (n != 2) {
609     di << "Gets the Same domain shape. Use: bopsd #\n";
610     return 0;
611   }
612   //
613   BOPDS_PDS pDS = BOPTest_Objects::PDS();
614   if (!pDS) {
615     di << " prepare PaveFiller first\n";
616     return 0;
617   }
618   //
619   char buf[32];
620   Standard_Boolean bHasSD;
621   Standard_Integer ind, i1, i2, iSD;
622   //
623   ind = Draw::Atoi(a[1]);
624   //
625   i1 = 0;
626   i2 = pDS->NbShapes();
627   if (ind < i1 || ind > i2) {
628     di << " DS does not contain the shape\n";
629     return 0;
630   }
631   //
632   bHasSD = pDS->HasShapeSD(ind, iSD);
633   if (bHasSD) {
634     Sprintf(buf, " Shape %d has SD shape %d\n", ind, iSD);
635     di << buf;
636   }
637   else {
638     Sprintf (buf, " Shape: %d has no SD shape\n", ind);
639     di << buf;
640   }
641   //
642   return 0;
643 }
644
645 //=======================================================================
646 //function : bopsc
647 //purpose  : 
648 //=======================================================================
649 Standard_Integer bopsc(Draw_Interpretor& di,
650                        Standard_Integer n,
651                        const char** a)
652 {
653   if (n != 1 && n != 3) {
654     di << "Shows the section curves. Use: bopsc [nF1 nF2]\n";
655     return 1;
656   }
657   //
658   BOPDS_PDS pDS=BOPTest_Objects::PDS();
659   if (!pDS) {
660     di << " prepare PaveFiller first\n";
661     return 0;
662   }
663   //
664   char buf[32];
665   Standard_CString aText;
666   Draw_Color aTextColor(Draw_cyan);
667   Standard_Integer nSF1, nSF2, nF1, nF2;
668   Standard_Integer aNb, j, iCnt, k, iPriz, aNbC, aNbP, nSp;
669   Standard_Integer iX;
670   Handle(BOPTest_DrawableShape) aDShape;
671   BOPDS_ListIteratorOfListOfPaveBlock aItLPB;
672   //
673   nSF1 = nSF2 = -1;
674   if (n == 3) {
675     nSF1 = Draw::Atoi(a[1]);
676     nSF2 = Draw::Atoi(a[2]);
677   }
678   //
679   BOPDS_VectorOfInterfFF& aFFs = pDS->InterfFF();
680   //
681   iCnt = 0;
682   iPriz = 0;
683   aNb = aFFs.Extent();
684   for (j = 0; j < aNb; ++j) {
685     const BOPDS_InterfFF& aFF = aFFs(j);
686     if (n == 3) {
687       if (!aFF.Contains(nSF1) || !aFF.Contains(nSF2)) {
688         continue;
689       }
690       iPriz = 1;
691     }
692     //
693     aFF.Indices(nF1, nF2);
694     //
695     iX = 0;
696     const BOPDS_VectorOfCurve& aVNC = aFF.Curves();
697     aNbC = aVNC.Extent();
698     for (k = 0; k < aNbC; ++k) {
699       const BOPDS_Curve& aNC = aVNC(k);
700       const BOPDS_ListOfPaveBlock& aLPB = aNC.PaveBlocks();
701       aItLPB.Initialize(aLPB);
702       for(; aItLPB.More(); aItLPB.Next()) {
703         const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
704         if (!aPB->HasEdge(nSp)) {
705           continue;
706         }
707         //
708         if (!iX) {
709           Sprintf (buf, "[%d %d] section edges: ", nF1, nF2);
710           di << buf;
711           iX = 1;
712         }
713         sprintf (buf, "t_%d_%d", k, nSp);
714         di << buf;
715         //
716         const TopoDS_Shape& aSp = pDS->Shape(nSp);
717         aText = buf;
718         aDShape = new BOPTest_DrawableShape(aSp, aText, aTextColor);
719         Draw::Set(aText, aDShape);
720         di << " ";
721         ++iCnt;
722       }
723     }
724     if (iX) {
725       di << "\n";
726     }
727     //
728     iX = 0;
729     const BOPDS_VectorOfPoint& aVNP = aFF.Points();
730     aNbP = aVNP.Extent();
731     for (k = 0; k < aNbP; ++k) {
732       const BOPDS_Point& aNP = aVNP(k);
733       nSp = aNP.Index();
734       if (nSp < 0) {
735         continue;
736       }
737       if (!iX) {
738         sprintf (buf, "[%d %d] section vertices: ", nF1, nF2);
739         di << buf;
740         iX = 1;
741       }
742       sprintf (buf, "p_%d_%d", k, nSp);
743       di << buf;
744       //
745       const TopoDS_Shape& aSp = pDS->Shape(nSp);
746       aText = buf;
747       aDShape = new BOPTest_DrawableShape(aSp, aText, aTextColor);
748       Draw::Set(aText, aDShape);
749       di << " ";
750       ++iCnt;
751     }
752     if (iX) {
753       di << "\n";
754     }
755     //
756     if (iPriz) {
757       break;
758     }
759   }// for (j=0; j<aNb; ++j) {
760   //
761   if (iCnt) {
762     di << "\n";
763   }
764   else {
765     di << " no sections found\n";
766   }
767   //
768   return 0;
769 }
770
771 //=======================================================================
772 //function : boppb
773 //purpose  : 
774 //=======================================================================
775 Standard_Integer boppb(Draw_Interpretor& di,
776                        Standard_Integer n,
777                        const char** a)
778
779   if (n > 2) {
780     di << "Shows information about pave blocks. Use: boppb [#e]\n";
781     return 1;
782   }
783   //
784   BOPDS_PDS pDS = BOPTest_Objects::PDS();
785   if (!pDS) {
786     di << " prepare PaveFiller first\n";
787     return 1;
788   }
789   //
790   Standard_Boolean bHasPaveBlocks;
791   Standard_Integer ind, i1, i2;
792   TopAbs_ShapeEnum aType;
793   BOPDS_ListIteratorOfListOfPaveBlock aItPB;
794   //
795   i1 = 0;
796   i2 = pDS->NbSourceShapes();
797   if (n == 2) {
798     ind = Draw::Atoi(a[1]);
799     i1 = ind;
800     i2 = ind + 1;
801   }
802   //
803   for (ind = i1; ind < i2; ++ind) {
804     const BOPDS_ShapeInfo& aSI = pDS->ShapeInfo(ind);
805     aType = aSI.ShapeType();
806     if (aType != TopAbs_EDGE) {
807       continue;
808     }
809     //
810     bHasPaveBlocks = pDS->HasPaveBlocks(ind);
811     if (!bHasPaveBlocks) {
812       continue;
813     }
814     //
815     const BOPDS_ListOfPaveBlock& aLPB = pDS->PaveBlocks(ind);
816     aItPB.Initialize(aLPB);
817     for (; aItPB.More(); aItPB.Next()) {
818       const Handle(BOPDS_PaveBlock)& aPB = aItPB.Value();
819       aPB->Dump();
820       printf("\n");
821     }
822   }
823   //
824   return 0;
825 }
826
827 //=======================================================================
828 //function : bopcb
829 //purpose  : 
830 //=======================================================================
831 Standard_Integer bopcb(Draw_Interpretor& di,
832                        Standard_Integer n,
833                        const char** a)
834
835   if (n > 2) {
836     di << "Shows information about common blocks. Use: bopcb [#e]\n";
837     return 1;
838   }
839   //
840   BOPDS_PDS pDS = BOPTest_Objects::PDS();
841   if (!pDS) {
842     di << " prepare PaveFiller first\n";
843     return 1;
844   }
845   //
846   Standard_Boolean bHasPaveBlocks;
847   Standard_Integer ind, i1, i2;
848   TopAbs_ShapeEnum aType;
849   BOPDS_ListIteratorOfListOfPaveBlock aItPB;
850   BOPDS_MapOfCommonBlock aMCB;
851   //
852   i1 = 0;
853   i2 = pDS->NbSourceShapes();
854   if (n == 2) {
855     ind = Draw::Atoi(a[1]);
856     i1 = ind;
857     i2 = ind + 1;
858   }
859   //
860   for (ind = i1; ind < i2; ++ind) {
861     const BOPDS_ShapeInfo& aSI = pDS->ShapeInfo(ind);
862     aType = aSI.ShapeType();
863     if (aType != TopAbs_EDGE) {
864       continue;
865     }
866     //
867     bHasPaveBlocks = pDS->HasPaveBlocks(ind);
868     if (!bHasPaveBlocks) {
869       continue;
870     }
871     //
872     const BOPDS_ListOfPaveBlock& aLPB = pDS->PaveBlocks(ind);
873     aItPB.Initialize(aLPB);
874     for (; aItPB.More(); aItPB.Next()) {
875       const Handle(BOPDS_PaveBlock)& aPB = aItPB.Value();
876       if (pDS->IsCommonBlock(aPB)) {
877         const Handle(BOPDS_CommonBlock)& aCB = pDS->CommonBlock(aPB);
878         if(aMCB.Add(aCB)) {
879           aCB->Dump();
880           printf("\n");
881         }
882       }
883     }
884   }
885   //
886   return 0;
887 }
888
889 //=======================================================================
890 //function : bopsp
891 //purpose  : 
892 //=======================================================================
893 Standard_Integer bopsp(Draw_Interpretor& di,
894                        Standard_Integer n,
895                        const char** a)
896 {
897   if (n > 2) {
898     di << "Shows the splits of edges. Use: bopsp [#e]\n";
899     return 1;
900   }
901   //
902   BOPDS_PDS pDS = BOPTest_Objects::PDS();
903   if (!pDS) {
904     di << " prepare PaveFiller first\n";
905     return 1;
906   }
907   //
908   char buf[32];
909   Standard_Boolean bHasPaveBlocks;
910   Standard_Integer ind, i1, i2, nSp;
911   TopAbs_ShapeEnum aType;
912   BOPDS_ListIteratorOfListOfPaveBlock aItPB;
913   Standard_CString aText;
914   Draw_Color aTextColor(Draw_cyan);
915   Handle(BOPTest_DrawableShape) aDShape;
916   //
917   i1 = 0;
918   i2 = pDS->NbSourceShapes();
919   if (n == 2) {
920     ind = Draw::Atoi(a[1]);
921     i1 = ind;
922     i2 = ind + 1;
923   }
924   //
925   for (ind = i1; ind < i2; ++ind) {
926     const BOPDS_ShapeInfo& aSI = pDS->ShapeInfo(ind);
927     aType = aSI.ShapeType();
928     if (aType != TopAbs_EDGE) {
929       continue;
930     }
931     //
932     bHasPaveBlocks = pDS->HasPaveBlocks(ind);
933     if (!bHasPaveBlocks) {
934       continue;
935     }
936     //
937     di << "Edge " << ind << ": ";
938     //
939     const BOPDS_ListOfPaveBlock& aLPB = pDS->PaveBlocks(ind);
940     aItPB.Initialize(aLPB);
941     for (; aItPB.More(); aItPB.Next()) {
942       const Handle(BOPDS_PaveBlock)& aPB = aItPB.Value();
943       nSp = aPB->Edge();
944       const TopoDS_Shape& aSp = pDS->Shape(nSp);
945       //
946       Sprintf(buf, "z%d_%d", ind, nSp);
947       aText = buf;
948       aDShape = new BOPTest_DrawableShape(aSp, aText, aTextColor);
949       Draw::Set(aText, aDShape);
950       di << buf << " ";
951     }
952     di << "\n";
953   }
954   //
955   return 0;
956 }
957
958 //=======================================================================
959 //function : bopfon
960 //purpose  : 
961 //=======================================================================
962 Standard_Integer bopfon(Draw_Interpretor& di,
963                         Standard_Integer n,
964                         const char** a)
965 {
966   return bopfinfo(di, n, a, 0);
967 }
968
969 //=======================================================================
970 //function : bopfin
971 //purpose  : 
972 //=======================================================================
973 Standard_Integer bopfin(Draw_Interpretor& di,
974                         Standard_Integer n,
975                         const char** a)
976 {
977   return bopfinfo(di, n, a, 1);
978 }
979
980 //=======================================================================
981 //function : bopfspsc
982 //purpose  : 
983 //=======================================================================
984 Standard_Integer bopfsc(Draw_Interpretor& di,
985                         Standard_Integer n,
986                         const char** a)
987 {
988   return bopfinfo(di, n, a, 2);
989 }
990
991 //=======================================================================
992 //function : bopfinfo
993 //purpose  : 
994 //=======================================================================
995 Standard_Integer bopfinfo(Draw_Interpretor& di,
996                           Standard_Integer n,
997                           const char** a,
998                           const Standard_Integer iPriz)
999 {
1000   if (n != 2) {
1001     di << "Shows " << ((iPriz == 0) ? "ON" : ((iPriz == 1) ? "IN" : "SC")) <<
1002       " information for the face. Use: bopf* #f\n";
1003     return 1;
1004   }
1005   //
1006   BOPDS_PDS pDS = BOPTest_Objects::PDS();
1007   if (!pDS) {
1008     di << " prepare PaveFiller first\n";
1009     return 1;
1010   }
1011   //
1012   char aText[32];
1013   Standard_Integer nF, i1, i2, nV, i, aNb;
1014   Handle(BOPDS_PaveBlock) aPB;
1015   //
1016   nF = Draw::Atoi(a[1]);
1017   i1 = 0;
1018   i2 = pDS->NbSourceShapes();
1019   if (nF < i1 || nF > i2) {
1020     di << " DS does not contain the shape\n";
1021     return 1;
1022   }
1023   //
1024   if (pDS->ShapeInfo(nF).ShapeType() != TopAbs_FACE) {
1025     di << " The shape is not a face\n";
1026     return 1;
1027   }
1028   //
1029   if (!pDS->HasFaceInfo(nF)) {
1030     di << " The face has no face information\n";
1031     return 0;
1032   }
1033   //
1034   BOPDS_FaceInfo& aFI = pDS->ChangeFaceInfo(nF);
1035   //
1036   BOPDS_IndexedMapOfPaveBlock aMPB;
1037   BOPCol_MapOfInteger aMI;
1038   if (iPriz == 0) {
1039     strcpy(aText, "On");
1040     aMPB = aFI.ChangePaveBlocksOn();
1041     aMI = aFI.ChangeVerticesOn();
1042   }
1043   else if (iPriz == 1) {
1044     strcpy(aText, "In");
1045     aMPB = aFI.ChangePaveBlocksIn();
1046     aMI = aFI.ChangeVerticesIn();
1047   }
1048   else if (iPriz == 2) {
1049     strcpy(aText, "Sc");
1050     aMPB = aFI.ChangePaveBlocksSc();
1051     aMI = aFI.ChangeVerticesSc();
1052   }
1053   //
1054   if (aMPB.Extent()) {
1055     printf(" pave blocks %s:\n", aText);
1056     aNb = aMPB.Extent();
1057     for (i = 1; i <= aNb; ++i) {
1058       aPB = aMPB(i);
1059       aPB->Dump();
1060       printf(" \n" );
1061     }
1062   }
1063   else {
1064     printf(" no pave blocks %s found\n", aText);
1065   }
1066   //
1067   if (aMI.Extent()) {
1068     printf(" vertices %s:\n", aText);
1069     BOPCol_MapIteratorOfMapOfInteger aItMI(aMI);
1070     for (; aItMI.More(); aItMI.Next()) {
1071       nV = aItMI.Value();
1072       printf(" %d", nV);
1073     }
1074     printf(" \n" );
1075   }
1076   else {
1077     printf(" no verts %s found\n", aText);
1078   }
1079   //
1080   return 0;
1081 }
1082
1083 //=======================================================================
1084 //function : bopfav
1085 //purpose  : alone vertices on face
1086 //=======================================================================
1087 Standard_Integer bopfav(Draw_Interpretor& di,
1088                         Standard_Integer n,
1089                         const char** a)
1090 {
1091   if (n != 2) {
1092     di << "Shows information about alone vertices for the face. Use: bopfav #f\n";
1093     return 1;
1094   }
1095   //
1096   BOPDS_PDS pDS = BOPTest_Objects::PDS();
1097   if (!pDS) {
1098     di << " prepare PaveFiller first\n";
1099     return 0;
1100   }
1101   //
1102   Standard_Integer i1, i2, nF, nV;
1103   //
1104   nF = Draw::Atoi(a[1]);
1105   i1 = 0;
1106   i2 = pDS->NbSourceShapes();
1107   if (nF < i1 || nF > i2) {
1108     di << "DS does not contain the shape\n";
1109     return 1;
1110   }
1111   //
1112   if (pDS->ShapeInfo(nF).ShapeType() != TopAbs_FACE) {
1113     di << " The shape is not a face\n";
1114     return 1;
1115   }
1116   //
1117   if (!pDS->HasFaceInfo(nF)) {
1118     di << " The face has no face information\n";
1119     return 0;
1120   }
1121   //
1122   BOPCol_ListOfInteger aLI;
1123   pDS->AloneVertices(nF, aLI);
1124   if (!aLI.Extent()) {
1125     di << " no alone vertices found\n";
1126     return 0;
1127   }
1128   //
1129   di << " alone vertices: \n";
1130   BOPCol_ListIteratorOfListOfInteger aItLI(aLI);
1131   for (; aItLI.More(); aItLI.Next()) {
1132     nV = aItLI.Value();
1133     di << nV << " ";
1134   }
1135   di <<"\n";
1136   //
1137   return 0;
1138 }
1139
1140 //=======================================================================
1141 //function : bopimage
1142 //purpose  : 
1143 //=======================================================================
1144 Standard_Integer bopimage(Draw_Interpretor& di,
1145                           Standard_Integer n,
1146                           const char** a)
1147
1148   if (n != 2) {
1149     di << "Shows split parts of the shape. Use: bopimage s\n";
1150     return 1;
1151   }
1152   //
1153   BOPDS_PDS pDS = BOPTest_Objects::PDS();
1154   if (!pDS) {
1155     di << " prepare PaveFiller first\n";
1156     return 1;
1157   }
1158   //
1159   TopoDS_Shape aS = DBRep::Get(a[1]);
1160   if (aS.IsNull()) {
1161     di << a[1] << " is a null shape\n";
1162     return 1;
1163   }
1164   //
1165   BOPAlgo_Builder& aBuilder = BOPTest_Objects::Builder();
1166   const BOPCol_DataMapOfShapeListOfShape& anImages = aBuilder.Images();
1167   if (!anImages.IsBound(aS)) {
1168     di << " no images found\n"; 
1169     return 0;
1170   }
1171   //
1172   char buf[32];
1173   Standard_Integer i;
1174   BRep_Builder aBB;
1175   TopoDS_Compound aC;
1176   //
1177   aBB.MakeCompound(aC);
1178   //
1179   const BOPCol_ListOfShape& aLSIm = anImages.Find(aS);
1180   BOPCol_ListIteratorOfListOfShape aIt(aLSIm);
1181   for (i = 0; aIt.More(); aIt.Next(), ++i) {
1182     const TopoDS_Shape& aSIm = aIt.Value();
1183     aBB.Add(aC, aSIm);
1184   }
1185   //
1186   di << i << " images found\n";
1187   sprintf(buf, "%s_im", a[1]);
1188   DBRep::Set(buf, aC);
1189   di << buf << "\n";
1190   //
1191   return 0;
1192 }
1193
1194 //=======================================================================
1195 //function : boporigin
1196 //purpose  : 
1197 //=======================================================================
1198 Standard_Integer boporigin(Draw_Interpretor& di,
1199                            Standard_Integer n,
1200                            const char** a)
1201
1202   if (n != 2) {
1203     di << "Shows the original shape for the shape. Use: boporigin s\n";
1204     return 1;
1205   }
1206   //
1207   BOPDS_PDS pDS = BOPTest_Objects::PDS();
1208   if (!pDS) {
1209     di << " prepare PaveFiller first\n";
1210     return 1;
1211   }
1212   //
1213   TopoDS_Shape aS = DBRep::Get(a[1]);
1214   if (aS.IsNull()) {
1215     di << a[1] << " is a null shape\n";
1216     return 0;
1217   }
1218   //
1219   char buf[32];
1220   //
1221   BOPAlgo_Builder& aBuilder = BOPTest_Objects::Builder();
1222   const BOPCol_DataMapOfShapeShape& aDMI = aBuilder.Origins();
1223   if (!aDMI.IsBound(aS)) {
1224     di << " no origins found\n"; 
1225     return 0;
1226   }
1227   //
1228   const TopoDS_Shape& aSx = aDMI.Find(aS);
1229   //
1230   sprintf(buf, "%s_or", a[1]);
1231   DBRep::Set(buf, aSx);
1232   //
1233   di << buf << "\n";
1234   //
1235   return 0;
1236 }
1237
1238 //=======================================================================
1239 //function : bopfsd
1240 //purpose  : 
1241 //=======================================================================
1242 Standard_Integer bopfsd(Draw_Interpretor& di,
1243                         Standard_Integer n,
1244                         const char** a)
1245
1246   if (n != 2) {
1247     di << "Shows SD faces for the face: Use: bopfsd f\n";
1248     return 1;
1249   }
1250   //
1251   BOPDS_PDS pDS = BOPTest_Objects::PDS();
1252   if (!pDS) {
1253     di << " prepare PaveFiller first\n";
1254     return 1;
1255   }
1256   //
1257   TopoDS_Shape aS = DBRep::Get(a[1]);
1258   if (aS.IsNull()) {
1259     di << a[1] << " is a null shape\n";
1260     return 1;
1261   }
1262   //
1263   BOPAlgo_Builder& aBuilder = BOPTest_Objects::Builder();
1264   const BOPCol_DataMapOfShapeShape& aDMSD = aBuilder.ShapesSD();
1265   if (!aDMSD.IsBound(aS)) {
1266     di << " shape has no sd shape\n"; 
1267     return 0;
1268   }
1269   //
1270   char buf[32];
1271   Standard_Integer i;
1272   BRep_Builder aBB;
1273   TopoDS_Compound aC;
1274   //
1275   aBB.MakeCompound(aC);
1276   //
1277   BOPCol_DataMapIteratorOfDataMapOfShapeShape aItSD;
1278   aItSD.Initialize(aDMSD);
1279   for (i = 0; aItSD.More(); aItSD.Next()) {
1280     const TopoDS_Shape& aSK = aItSD.Key();
1281     const TopoDS_Shape& aSV = aItSD.Value();
1282     if (aSK.IsEqual(aS)) {
1283       if (!aSV.IsEqual(aS)) {
1284         aBB.Add(aC, aS);
1285         ++i;
1286       }
1287     }
1288     //
1289     else if (aSV.IsEqual(aS)) {
1290       if (!aSK.IsEqual(aS)) {
1291         aBB.Add(aC, aS);
1292         ++i;
1293       }
1294     }
1295   }
1296   //
1297   di << i << " SD shapes found\n";
1298   //
1299   sprintf(buf, "%s_sd", a[1]);
1300   DBRep::Set(buf, aC);
1301   //
1302   di << buf << "\n";
1303   return 0;
1304 }
1305
1306 //=======================================================================
1307 //function : bopbface
1308 //purpose  : 
1309 //=======================================================================
1310 Standard_Integer bopbface (Draw_Interpretor& di,
1311                            Standard_Integer n,
1312                            const char** a)
1313 {
1314   if ( n!= 3) {
1315     di << "Build faces from surface and set of shared edges. Use: bopbface fr cx\n";
1316     return 1;
1317   }
1318   //
1319   TopoDS_Shape aS = DBRep::Get(a[2]);
1320   if (aS.IsNull()) {
1321     di << a[1] << " is a null shape\n";
1322     return 1;
1323   }
1324   //
1325   TopoDS_Face aF;
1326   BOPCol_ListOfShape aLE;
1327   Standard_Integer i;
1328   //
1329   TopoDS_Iterator aItS(aS);
1330   for (i=0; aItS.More(); aItS.Next(), ++i) {
1331     const TopoDS_Shape& aSx = aItS.Value();
1332     if (!i) {
1333       if (aSx.ShapeType() != TopAbs_FACE) {
1334         di << " shape " << i << " is not a face\n";
1335         return 1;
1336       }
1337       aF = *(TopoDS_Face*)&aSx;
1338     }
1339     else {
1340       if (aSx.ShapeType() != TopAbs_EDGE) {
1341         di << " shape " << i << " is not an edge\n";
1342         return 1;
1343       }
1344       aLE.Append(aSx);
1345     }
1346   }
1347   //
1348   BOPAlgo_BuilderFace aBF;
1349   aBF.SetFace(aF);
1350   aBF.SetShapes(aLE);
1351   aBF.Perform();
1352   //
1353   Standard_Integer iErr = aBF.ErrorStatus();
1354   if (iErr != 0) {
1355     di << " Error: " << iErr << "\n";
1356     return 1;
1357   }
1358   //
1359   char buf[128];
1360   const BOPCol_ListOfShape& aLFR = aBF.Areas();
1361   BOPCol_ListIteratorOfListOfShape aIt(aLFR);
1362   for (i = 1; aIt.More(); aIt.Next(), ++i) {
1363     const TopoDS_Shape& aFR = aIt.Value();
1364     sprintf(buf, "%s_%d", a[1], i);
1365     DBRep::Set(buf, aFR);
1366     di << " " << buf;
1367   }
1368   //
1369   i = aLFR.Extent();
1370   if (i) {
1371     di << "\n " << i << " faces were built\n";
1372   }
1373   else {
1374     di << " No faces were built\n";
1375   }
1376   //
1377   return 0;
1378 }
1379
1380 //=======================================================================
1381 //function : bopbsolid
1382 //purpose  : 
1383 //=======================================================================
1384 Standard_Integer bopbsolid (Draw_Interpretor& di,
1385                             Standard_Integer n,
1386                             const char** a)
1387 {
1388   if ( n!= 3) {
1389     di << "Build solids from set of shared faces. Use: bopbsolid sr cx\n";
1390     return 1;
1391   }
1392   //
1393   TopoDS_Shape aS = DBRep::Get(a[2]);
1394   if (aS.IsNull()) {
1395     di << a[1] << " is a null shape\n";
1396     return 1;
1397   }
1398   //
1399   BOPCol_ListOfShape aLF;
1400   TopExp_Explorer aExp(aS, TopAbs_FACE);
1401   for (; aExp.More(); aExp.Next()) {
1402     const TopoDS_Shape& aF = aExp.Current();
1403     aLF.Append(aF);
1404   }
1405   //
1406   if (aLF.IsEmpty()) {
1407     di << " No faces to build solids\n";
1408     return 1;
1409   }
1410   //
1411   BOPAlgo_BuilderSolid aBS;
1412   aBS.SetShapes(aLF);
1413   aBS.Perform();
1414   //
1415   Standard_Integer iErr = aBS.ErrorStatus();
1416   if (iErr != 0) {
1417     di << " Error: " << iErr << "\n";
1418     return 1;
1419   }
1420   //
1421   Standard_Integer i;
1422   TopoDS_Compound aSolids;
1423   BRep_Builder aBB;
1424   //
1425   aBB.MakeCompound(aSolids);
1426   //
1427   char buf[128];
1428   const BOPCol_ListOfShape& aLSR = aBS.Areas();
1429   BOPCol_ListIteratorOfListOfShape aIt(aLSR);
1430   for (i = 1; aIt.More(); aIt.Next(), ++i) {
1431     const TopoDS_Shape& aSR = aIt.Value();
1432     sprintf(buf, "%s_%d", a[1], i);
1433     DBRep::Set(buf, aSR);
1434     di << " " << buf;
1435   }
1436   //
1437   i = aLSR.Extent();
1438   if (i) {
1439     di << "\n " << i << " solids were built\n";
1440   }
1441   else {
1442     di << " No solids were built\n";
1443   }
1444   //
1445   return 0;
1446 }
1447
1448 //=======================================================================
1449 //function : GetTypeByName
1450 //purpose  : 
1451 //=======================================================================
1452 void GetTypeByName(const char* theName,
1453                    TopAbs_ShapeEnum& theType)
1454 {
1455   if (!strcmp (theName, "v") ||
1456       !strcmp (theName, "V")) {
1457     theType = TopAbs_VERTEX;
1458   }
1459   else if (!strcmp (theName, "e") ||
1460            !strcmp (theName, "E")) {
1461     theType = TopAbs_EDGE;
1462   }
1463   else if (!strcmp (theName, "w") ||
1464            !strcmp (theName, "W")) {
1465     theType = TopAbs_WIRE;
1466   }
1467   else if (!strcmp (theName, "f") ||
1468            !strcmp (theName, "F")) {
1469     theType = TopAbs_FACE;
1470   }
1471   else if (!strcmp (theName, "sh") ||
1472            !strcmp (theName, "Sh") ||
1473            !strcmp (theName, "SH")) {
1474     theType = TopAbs_SHELL;
1475   }
1476   else if (!strcmp (theName, "s") ||
1477            !strcmp (theName, "S")) {
1478     theType = TopAbs_SOLID;
1479   }
1480   else if (!strcmp (theName, "cs") ||
1481            !strcmp (theName, "Cs") ||
1482            !strcmp (theName, "CS")) {
1483     theType = TopAbs_COMPSOLID;
1484   }
1485   else if (!strcmp (theName, "c") ||
1486            !strcmp (theName, "C")) {
1487     theType = TopAbs_COMPOUND;
1488   }
1489   else {
1490     theType = TopAbs_SHAPE;
1491   }
1492 }
1493
1494 //=======================================================================
1495 //function : GetNameByType
1496 //purpose  : 
1497 //=======================================================================
1498 void GetNameByType(const TopAbs_ShapeEnum& theType,
1499                    char* theName)
1500 {
1501   switch (theType) {
1502   case TopAbs_VERTEX:
1503     strcpy (theName, "V");
1504     break;
1505   case TopAbs_EDGE:
1506     strcpy (theName, "E");
1507     break; 
1508   case TopAbs_WIRE:
1509     strcpy (theName, "w");
1510     break;
1511   case TopAbs_FACE:
1512     strcpy (theName, "F");
1513     break;
1514   case TopAbs_SHELL:
1515     strcpy (theName, "Sh");
1516     break; 
1517   case TopAbs_SOLID:
1518     strcpy (theName, "S");
1519     break; 
1520   case TopAbs_COMPSOLID:
1521     strcpy (theName, "Cs");
1522     break; 
1523   case TopAbs_COMPOUND:
1524     strcpy (theName, "c");
1525     break; 
1526   default:
1527     strcpy (theName, "Shape");
1528     break; 
1529   }
1530 }
1531
1532 //=======================================================================
1533 //function : DumpInterfs
1534 //purpose  : 
1535 //=======================================================================
1536 template <class InterfType> void DumpInterfs
1537   (const BOPCol_NCVector<InterfType>& theVInterf,
1538    Draw_Interpretor& di)
1539 {
1540   Standard_Integer i, aNb, n1, n2, nNew;
1541   char buf[64];
1542   //
1543   aNb = theVInterf.Extent();
1544   if (aNb == 0) {
1545     di << "Not found\n";
1546     return;
1547   }
1548   //
1549   di << aNb << " interference(s) found\n";
1550   for (i = 0; i < aNb; ++i) {
1551     const InterfType& anInt = theVInterf(i);
1552     anInt.Indices(n1, n2);
1553     if (anInt.HasIndexNew()) {
1554       nNew = anInt.IndexNew();
1555       Sprintf(buf, " (%d, %d, %d)\n", n1, n2, nNew);
1556     }
1557     else {
1558       Sprintf(buf, " (%d, %d)\n", n1, n2);
1559     }
1560     di << buf;
1561   }
1562 }
1563
1564 //=======================================================================
1565 //function : SearchNewIndex
1566 //purpose  : 
1567 //=======================================================================
1568 template <class InterfType> void SearchNewIndex
1569   (const char* theCType,
1570    const Standard_Integer theInd,
1571    const BOPCol_NCVector<InterfType>& theVInterf,
1572    Draw_Interpretor& di)
1573 {
1574   char buf[64];
1575   Standard_Boolean bFound;
1576   Standard_Integer i, aNb, n1, n2, nNew;
1577   //
1578   bFound = Standard_False;
1579   aNb = theVInterf.Extent();
1580   for (i = 0 ; i < aNb; ++i) {
1581     const InterfType& anInt = theVInterf(i);
1582     nNew = anInt.IndexNew();
1583     if (theInd == nNew) {
1584       if (!bFound) {
1585         di << theCType;
1586         bFound = Standard_True;
1587       }
1588       //
1589       anInt.Indices(n1, n2);
1590       sprintf(buf,"(%d, %d) ", n1, n2);
1591       di << buf;
1592     }
1593   }
1594   if (bFound) {
1595     di << "\n";
1596   }
1597 }