EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
EicCadWizard.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file EicCadWizard.cxx
1 
2 #include <assert.h>
3 #include <sys/stat.h>
4 #include <dirent.h>
5 
6 #include <STEPControl_Reader.hxx>
7 #include <STEPControl_Writer.hxx>
8 #include <StlAPI_Writer.hxx>
9 
10 #include <Message.hxx>
11 #include <Message_Messenger.hxx>
12 #include <Message_PrinterOStream.hxx>
13 
14 #include <TopoDS_Shape.hxx>
15 #include <TopoDS_Face.hxx>
16 #include <Geom_Surface.hxx>
17 
18 #include <Geom_Plane.hxx>
19 #include <Geom_CylindricalSurface.hxx>
20 #include <Geom_ConicalSurface.hxx>
21 #include <Geom_SphericalSurface.hxx>
22 #include <Geom_ToroidalSurface.hxx>
23 
24 #include <Geom_BSplineSurface.hxx>
25 #include <Geom_RectangularTrimmedSurface.hxx>
26 
27 #include <BRep_Tool.hxx>
28 #include <BRepBuilderAPI_MakeFace.hxx>
29 #include <BRepAlgoAPI_Cut.hxx>
30 #include <BRepAlgoAPI_Common.hxx>
31 #include <BRepMesh_IncrementalMesh.hxx>
32 #include <BRepBuilderAPI_Transform.hxx>
33 
34 #include <Bnd_Box.hxx>
35 #include <BRepBndLib.hxx>
36 
37 #include <gp_Pln.hxx>
38 #include <gp_Cylinder.hxx>
39 #include <gp_Cone.hxx>
40 #include <gp_Sphere.hxx>
41 #include <gp_Torus.hxx>
42 
43 #include <TopExp_Explorer.hxx>
44 
45 #include <TGeoCompositeShape.h>
46 #include <TGeoMatrix.h>
47 #include <TGeoSphere.h>
48 
49 #include <EicStlFactory.h>
50 #include <EicCadWizard.h>
51 // FIXME: get rid of this include file;
52 #include <EicCadFileConfig.h>
53 #include <EicCompositeShape.h>
54 
55 #define _DOT_STEP_ (".stp")
56 #define _DOT_ROOT_ (".root")
57 #define _DOT_SPLIT_ (".split")
58 
59 // =======================================================================================
60 
61 EicCadWizardFile *EicCadWizard::AddSourceFile(const char *fname, const char *material) {
62  EicCadWizardFile *wfile = new EicCadWizardFile(fname, material);
63 
64  mSourceFiles.push_back(wfile);
65 
66  return wfile;
67 } // EicCadWizard::AddSourceFile()
68 
69 // ---------------------------------------------------------------------------------------
70 #if _LATER_
71 void EicCadWizard::AddSourceDirectory(const char *dname) {
72  struct stat St;
73  unsigned stlen = strlen(_DOT_STP_);
74  // NB: stat(), since I want to dereference the link;
75  stat(dname, &St);
76 
77  DIR *curr_dir = opendir(dname); assert(curr_dir);
78  struct dirent *curr_file;
79 
80  while((curr_file = readdir(curr_dir))) {
81  int len = strlen(curr_file->d_name);
82 
83  if (len >= stlen &&
84  !memcmp(curr_file->d_name + len - stlen, _DOT_STP_, stlen)) {
85  TString fileName = TString(dname) + "/" + curr_file->d_name;
86  AddSourceFile(fileName.Data());
87  } //if
88  } //while
89 } // EicCadWizard::AddSourceDirectory()
90 #endif
91 // ---------------------------------------------------------------------------------------
92 
94 {
95  // Either convert or check already existing conversion for all files recursively;
96  for(unsigned fl=0; fl<mSourceFiles.size(); fl++) {
97  EicCadWizardFile *wfile = mSourceFiles[fl];
98 
99  //std::vector<EicCadWizardCut*> *tried_cuts = new std::vector<EicCadWizardCut*>;
100  std::vector<std::pair<EicCadWizardCut*,bool> > *tried_cuts = new std::vector<std::pair<EicCadWizardCut*,bool> >;
101 
102  {
103  int ret = ConvertSourceFileToRoot(wfile, tried_cuts);
104 
105  if (ret) return ret;
106  }
107  } //for fl
108 
109  return 0;
110 } // EicCadWizard::ConvertSourceFilesToRoot()
111 
112 // ---------------------------------------------------------------------------------------
113 
114 Bool_t EicCadWizard::IsElementaryFace(const TopoDS_Face &face) const
115 {
116  Handle(Geom_Surface) SS = BRep_Tool::Surface(face);
117 
118  return (SS->IsKind(STANDARD_TYPE(Geom_Plane))
119  || SS->IsKind(STANDARD_TYPE(Geom_CylindricalSurface))
120  || SS->IsKind(STANDARD_TYPE(Geom_ConicalSurface))
121  || SS->IsKind(STANDARD_TYPE(Geom_ToroidalSurface))
122  || SS->IsKind(STANDARD_TYPE(Geom_SphericalSurface)));
123 } // EicCadWizard::IsElementaryFace()
124 
125 // ---------------------------------------------------------------------------------------
126 
127 Bool_t EicCadWizard::IsKnownFace(const TopoDS_Face &face) const
128 {
129  if (IsElementaryFace(face)) return true;
130 
131  {
132  Handle(Geom_Surface) SS = BRep_Tool::Surface(face);
133 
134  return (SS->IsKind(STANDARD_TYPE(Geom_BSplineSurface))
135  || SS->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)));
136  }
137 } // EicCadWizard::IsKnownFace()
138 
139 // ---------------------------------------------------------------------------------------
140 
141 //
142 // FIXME: need to pass the vector of cuts, which were used so far (so there is not need
143 // to try them again);
144 //
145 
146 EicCadWizardCut *EicCadWizard::GetCut(const TopoDS_Face &face, const gp_Pnt *bcenter, double bradius)
147 {
148  Handle(Geom_Surface) SS = BRep_Tool::Surface(face);
149 
150  // Well, here I have to resort to a switch;
151  if (SS->IsKind(STANDARD_TYPE(Geom_Plane))) {
152  Handle(Geom_Plane) es = Handle(Geom_Plane)::DownCast(SS);
153 
154  return new EicCadWizardPlane(es->Pln());
155  } else
156  if (SS->IsKind(STANDARD_TYPE(Geom_CylindricalSurface))) {
157  Handle(Geom_CylindricalSurface) es = Handle(Geom_CylindricalSurface)::DownCast(SS);
158 
159  return new EicCadWizardCylinder(es->Cylinder(), bcenter, bradius);
160  }
161  else
162  if (SS->IsKind(STANDARD_TYPE(Geom_ConicalSurface))) {
163  Handle(Geom_ConicalSurface) es = Handle(Geom_ConicalSurface)::DownCast(SS);
164 
165  return new EicCadWizardCone(es->Cone(), bcenter, bradius);
166  }
167  else
168  if (SS->IsKind(STANDARD_TYPE(Geom_SphericalSurface))) {
169  Handle(Geom_SphericalSurface) es = Handle(Geom_SphericalSurface)::DownCast(SS);
170 
171  return new EicCadWizardSphere(es->Sphere());
172  }
173  else
174  if (SS->IsKind(STANDARD_TYPE(Geom_ToroidalSurface))) {
175  Handle(Geom_ToroidalSurface) es = Handle(Geom_ToroidalSurface)::DownCast(SS);
176 
177  return new EicCadWizardTorus(es->Torus());
178  } //if
179 
180  // Can not happen;
181  return 0;
182 } // EicCadWizard::GetCut()
183 
184 // ---------------------------------------------------------------------------------
185 
187  const std::vector<std::pair<EicCadWizardCut*,bool> > *tried_cuts)
188 {
189  struct stat St;
190  unsigned fCounter = 0, stlen = strlen(_DOT_STEP_);
191  // NB: stat(), since I want to dereference the link;
192  stat(dname, &St);
193 
194  //printf("%d %d\n", S_ISLNK(St.st_mode), S_ISDIR(St.st_mode));
195  DIR *curr_dir = opendir(dname); assert(curr_dir);
196  struct dirent *curr_file;
197 
198  while((curr_file = readdir(curr_dir))) {
199  int len = strlen(curr_file->d_name);
200  //printf("%d\n", len);
201 
202  if (len >= stlen &&
203  !memcmp(curr_file->d_name + len - stlen, _DOT_STEP_, stlen)) {
204  TString fileName = TString(dname) + "/" + curr_file->d_name;
205  //printf("--> %s\n", fileName.Data());
206  int ret = ConvertSourceFileToRoot(fileName.Data(), config, tried_cuts);
207  if (ret) return ret;
208 
209  fCounter++;
210  } //if
211  } //while
212 
213  //printf("fCounter: %d\n", fCounter);
214  // FIXME: do it better; for now assume at least two files should have been there;
215  //assert(fCounter >= 2);
216  return 0;
217 } // EicCadWizard::ConvertSourceDirectoryToRoot()
218 
219 // ---------------------------------------------------------------------------------------
220 
221 int EicCadWizard::AccountRootFile(const TString &fname)
222 {
223  mRootFiles.push_back(fname);
224 
225  return 0;
226 } // EicCadWizard::AccountRootFile()
227 
228 // ---------------------------------------------------------------------------------------
229 
230 #include <TKey.h>
231 #include <TGeoTube.h>
232 
233 #if 1//_OFF_
234 static void SetDefaultMatrixName(TGeoMatrix* matrix)
235 {
236  // Copied from root TGeoMatrix::SetDefaultName() and modified (memory leak)
237  // If no name was supplied in the ctor, the type of transformation is checked.
238  // A letter will be prepended to the name :
239  // t - translation
240  // r - rotation
241  // s - scale
242  // c - combi (translation + rotation)
243  // g - general (tr+rot+scale)
244  // The index of the transformation in gGeoManager list of transformations will
245  // be appended.
246  if (!gGeoManager) { return; }
247  if (strlen(matrix->GetName())) { return; }
248  char type = 'n';
249  if (matrix->IsTranslation()) { type = 't'; }
250  if (matrix->IsRotation()) { type = 'r'; }
251  if (matrix->IsScale()) { type = 's'; }
252  if (matrix->IsCombi()) { type = 'c'; }
253  if (matrix->IsGeneral()) { type = 'g'; }
254  TObjArray* matrices = gGeoManager->GetListOfMatrices();
255  Int_t index = 0;
256  if (matrices) { index =matrices->GetEntriesFast() - 1; }
257  matrix->SetName(Form("%c%i", type, index));
258  printf("Here: %s\n", matrix->GetName());
259 }
260 #endif
261 
262 //
263 // (?) sudo sysctl -w fs.file-max=100000
264 //
265 
266 void EicCadWizard::AddRootDirectory(const char *dname) {
267  unsigned rtlen = strlen(_DOT_ROOT_), splen = strlen(_DOT_SPLIT_);
268 
269  printf("--> %s ... \n", dname);
270  DIR *curr_dir = opendir(dname);
271  if (!curr_dir) printf("errno: %d\n", errno);
272  assert(curr_dir);
273  struct dirent *curr_file;
274 
275  while((curr_file = readdir(curr_dir))) {
276  if (!strcmp(curr_file->d_name, ".") || !strcmp(curr_file->d_name, "..")) continue;
277 
278  struct stat St;
279  TString fname = TString(dname) + "/" + curr_file->d_name;
280 #if 1//_LATER_
281  // NB: stat(), since I want to dereference the link;
282  stat(fname.Data(), &St);
283  if (S_ISDIR(St.st_mode) && strlen(fname) > splen &&
284  // FIXME: do it better;
285  TString(fname).EndsWith(_DOT_SPLIT_))
286  AddRootDirectory(fname.Data());
287 #endif
288 
289  int len = strlen(curr_file->d_name);
290 
291  if (len >= rtlen &&
292  !memcmp(curr_file->d_name + len - rtlen, _DOT_ROOT_, rtlen)) {
293  AccountRootFile(fname.Data());
294  } //if
295  } //while
296 
297  closedir(curr_dir);
298 } // EicCadWizard::AddRootDirectory()
299 
300 int EicCadWizard::AssembleRootFiles(const char *dname, const char *detname)
301 {
302  // FIXME: do this better later; in fact this suffices I guess;
304  config->CreateMediaHub();//(char*)"air");
305 
306  //EicGeoParData *geo = new EicGeoParData("DUMMY", 0, 0);
307  EicGeoParData *geo = new EicGeoParData(detname, 0, 0);
308  {
309  char rname[1024];
310  snprintf(rname, 1024-1, "%s.root", geo->GetDetName()->name().Data());//detname);
311  geo->SetFileName(rname);
312  }
313 
314  config->mhub()->Init();
315 
316  // In this case add all .root files in this directory by hand;
317  if (dname) {
318  mRootFiles.clear();
319  AddRootDirectory(dname);
320  } //if
321 
322  unsigned vCounter = 0;
323 
324  for(unsigned fl=0; fl<mRootFiles.size(); fl++) {
325  TString &fname = mRootFiles[fl];
326 
327  printf("%3d -> %s\n", fl, fname.Data());
328 
329  TFile *f = new TFile(fname.Data()); assert(f);
330  TList* l= f->GetListOfKeys();
331 
332  TKey* key = (TKey*) l->At(0); //Get the first key in the list
333  TGeoVolumeAssembly *assembly = dynamic_cast<TGeoVolumeAssembly*> (key->ReadObj());
334  assert(assembly);
335 
336  // NB: this way it works for both boolean and tetrahedra shapes;
337  //printf("--> %d\n", assembly->GetNode(0)->GetVolume()->GetNtotal());
338  unsigned node_num = assembly->GetNode(0)->GetVolume()->GetNtotal();
339  // THINK: why '-1' (this way it does not crash)???;
340  for(unsigned nd=0; nd<node_num-1; nd++) {
341  //printf("--> %d\n", nd);
342  TGeoNode *node = assembly->GetNode(0)->GetVolume()->GetNode(nd);
343 
344 #if 0
345  TGeoMatrix* M = node->GetMatrix();
347  gGeoManager->GetListOfMatrices()->Remove(M);
348  TGeoHMatrix* global = gGeoManager->GetHMatrix();
349  gGeoManager->GetListOfMatrices()->Remove(global);
350 #endif
351 
352  TGeoVolume *volume = node->GetVolume();
353 
354  //printf("-> %s\n", volume->GetName());
355  char vname[128];
356  const char *oname = volume->GetName();
357  //snprintf(vname, 128-1, "C%06d", vCounter++);
358  printf("-> %s\n", volume->GetName());
359  assert(strlen(oname) >= 4 && oname[0] == '@' && oname[2] == 'V' && oname[3] == '@');
360  snprintf(vname, 128-1, "@%cV@%06d", oname[1], vCounter++);
361  volume->SetName(vname);
362 
363  //volume->RegisterYourself();
364  //assert(node->GetMatrix()->IsIdentity());
365  // NB: new TGeoCombiTrans() is essential here even if identity;
366  //geo->GetTopVolume()->AddNode(volume, 0, new TGeoCombiTrans(10.0*vCounter, 0.0, 0.0, node->GetMatrix()));
367  //TGeoMatrix* M = node->GetMatrix(); M->SetDx(10.0*vCounter);
368  geo->GetTopVolume()->AddNode(volume, 0, node->GetMatrix());
369  volume->RegisterYourself();
370  } //for nd
371 
372  f->Close();
373  } //for fl
374 
375 #if 0
376  TGeoMatrix* M = n->GetMatrix();
378 
380  gGeoManager->GetListOfMatrices()->Remove(M);
381  TGeoHMatrix* global = gGeoManager->GetHMatrix();
382  gGeoManager->GetListOfMatrices()->Remove(global); //Remove the Identity matrix
384  Cave->AddNode(v1,0, M);
385 #endif
386 
387  {
388  //TGeoRotation *rw = new TGeoRotation();
389  TGeoHMatrix *rw = new TGeoHMatrix();
390  rw->RotateY(90);
391  //rw->SetScale(1.);
392  printf("%f\n", rw->GetScale());
393 
394  //geo->SetTopVolumeTransformation(new TGeoCombiTrans(0.0, 0.0, 0.0, rw));
395  }
396 
397  // FIXME this, please!;
398  geo->GetColorTable()->AddPatternMatch ("@RV@", kGray);
399  geo->GetTransparencyTable()->AddPatternMatch("@RV@", 0);
400  //geo->GetColorTable()->AddPatternMatch ("@GV@", kSpring);
401  //geo->GetTransparencyTable()->AddPatternMatch("@GV@", 50);
402  geo->GetColorTable()->AddPatternMatch ("@GV@", kGray);
403  geo->GetTransparencyTable()->AddPatternMatch("@GV@", 0);
404 
405  geo->FinalizeOutput();
406 
407  return 0;
408 } // EicCadWizard::AssembleRootFiles()
409 
410 // ---------------------------------------------------------------------------------------
411 
413 {
414  // FIXME: do it better later; use std::string or TString;
415  assert(fname.EndsWith(_DOT_STEP_));
416  char bname[1024];
417  snprintf(bname, 1024-1, "%s", fname.Data());
418  bname[strlen(bname)-4] = 0;
419 
420  // There are >1 solids in this file; create one level down directory and populate it
421  // with individual shapes;
422  char dname[1024];
423  unsigned csCounter = 0;
424  snprintf(dname, 1024-1, "%s.split", bname);
425  // FIXME: once debugging is over, use Boost remove_all() to clean up non-empty directory;
426  mkdir(dname, 0755);
427 
428  {
429  //unsigned sCounter = 0;
430  STEPControl_Reader cReader;
431  IFSelect_ReturnStatus cstatus = cReader.ReadFile(fname.Data());
432 
433  // FIXME: may want to loop through all roots; should be easy fix?;
434  //assert(cReader.NbRootsForTransfer() == 1);
435  cReader.TransferRoots();//(1);
436  printf("%d root(s) in STEP file; %d shape(s)\n", cReader.NbRootsForTransfer(), cReader.NbShapes());
437 
438  // FIXME: hardcode 90-degree rotation and scale factor 0.1;
439  gp_Trsf scaling;
440  {
441  gp_Pnt x0(0.0, 0.0, 0.0);
442  // FIXME: do it better later;
443  //assert(config()->GetRotationAxis() == EicCadFileConfig::_Y_);
444  gp_Dir n0(0.0, 1.0, 0.0);
445  gp_Ax1 axis(x0, n0);
446 
447  scaling.SetRotation(axis, -90.0 * TMath::DegToRad());
448  } //if
449  // Yes, first rotate, then re-scale (otherwise scaling takes no effect);
450  scaling.SetScaleFactor(0.10);
451  BRepBuilderAPI_Transform sc(scaling);
452 
453  // FIXME: do this check more efficiently later;
454  for(unsigned sh=0; sh<cReader.NbShapes(); sh++) {
455  TopoDS_Shape shape = cReader.Shape(sh+1);
456 
457  for (TopExp_Explorer itf(shape,TopAbs_SOLID); itf.More(); itf.Next()) {
458  STEPControl_Writer cWriter;
459 
460  sc.Perform(itf.Current());
461  const TopoDS_Shape &solid = sc.ModifiedShape(itf.Current());
462 
463  cWriter.Transfer(solid, STEPControl_ManifoldSolidBrep);
464  char qname[1024];
465  snprintf(qname, 1024-1, "%s/part-%05d.stp", dname, csCounter);
466  cWriter.Write(qname);
467 
468  // FIXME: and need to deal with these files right away here, recursively; later
469  // on - in multi-threading mode - this will not interrupt the processing sequence;
470 
471  csCounter++;
472  } //for itf
473 
474  //for (TopExp_Explorer itf(shape,TopAbs_SOLID); itf.More(); itf.Next())
475  //sCounter++;
476  } //for sh
477 
478  //printf("-> sCounter %d\n", sCounter);
479  }
480 
481  return 0;
482 } // EicCadWizard::SplitAndRescaleSourceFile()
483 
484 // ---------------------------------------------------------------------------------------
485 
487  const std::vector<std::pair<EicCadWizardCut*,bool> > *tried_cuts)
488 {
489  printf("\n Entering EicCadWizard::ConvertSourceFileToRoot(): %s ...\n", fname.Data());
490  // FIXME: do it better later; use std::string or TString;
491  assert(fname.EndsWith(_DOT_STEP_));
492  char bname[1024];
493  snprintf(bname, 1024-1, "%s", fname.Data());
494  bname[strlen(bname)-4] = 0;
495  //printf("%s\n", bname);
496 
497  // Check #1: if ROOT file exists already, assume there is nothing else to do;
498  {
499  char rfile[1024];
500 
501  snprintf(rfile, 1024-1, "%s.root", bname);
502  if (!access(rfile, R_OK)) return AccountRootFile(rfile);
503  }
504 
505  // Check #2: if split link to a directory exists already, deal with respective
506  // root files in the subdirectory, recursively; then return;
507  {
508  char slink[1024];
509 
510  snprintf(slink, 1024-1, "%s.split", bname);
511  //printf("%s\n", slink);
512  if (!access(slink, R_OK)) return ConvertSourceDirectoryToRoot(slink, config, tried_cuts);
513  }
514 
515  // Ok, should work on this file; first figure out whether there are more than one solid
516  // there (almost certainly indicating it is a primary model file; or a bug :-);
517  {
518  unsigned sCounter = 0;
519  STEPControl_Reader cReader;
520  IFSelect_ReturnStatus cstatus = cReader.ReadFile(fname.Data());
521 
522  // FIXME: may want to loop through all roots; should be easy fix?;
523  //assert(cReader.NbRootsForTransfer() == 1);
524  cReader.TransferRoots();//(1);
525  printf("%d root(s) in STEP file; %d shape(s)\n", cReader.NbRootsForTransfer(), cReader.NbShapes());
526 
527  //gp_Trsf scaling;
528  //scaling.SetScaleFactor(10.0);//config()->scale() * config()->units());
529  //BRepBuilderAPI_Transform sc(scaling);
530 
531  // FIXME: do this check more efficiently later;
532  for(unsigned sh=0; sh<cReader.NbShapes(); sh++) {
533  TopoDS_Shape shape = cReader.Shape(sh+1);
534 
535  for (TopExp_Explorer itf(shape,TopAbs_SOLID); itf.More(); itf.Next())
536  sCounter++;
537  } //for sh
538 
539  // FIXME: handle this situation correctly;
540  //assert(sCounter);
541  if (!sCounter) unlink(fname.Data());
542  printf("-> sCounter %d\n", sCounter);
543 
544  if (sCounter == 1) {
545  // Check if flat cut makes sense; otherwise proceed with the FaceGuidedSplit();
546  //+if (!FlatSurfaceSplit(cReader, bname, config, tried_cuts)) return 0;
547 
548  return FaceGuidedSplit(cReader, bname, config, tried_cuts);
549  }
550  else
551  // FIXME: should also be some sort of recursion up to the very end of the
552  // dissection procedure;
553  return StraightforwardSplit(cReader, bname);
554  }
555 
556  return 0;
557 } // EicCadWizard::ConvertSourceFileToRoot()
558 
559 // ---------------------------------------------------------------------------------------
560 
561 class ObjectFace {
562 public:
563  ObjectFace(TopoDS_Face *face): mFace(face), xMin(0.0), yMin(0.0), zMin(0.0),
564  xMax(0.0), yMax(0.0), zMax(0.0) {};
566 
567  const TopoDS_Face *mFace;
568  double xMin, yMin, zMin, xMax, yMax, zMax, mMin[3], mMax[3];
569 };
570 
571 int EicCadWizard::FlatSurfaceSplit(const STEPControl_Reader &cReader, const char *bname,
573  const std::vector<std::pair<EicCadWizardCut*,bool> > *tried_cuts)
574 {
575  // So need to deal with a single solid; perform cuts; FIXME: re-use 'itf' later;
576  // for now just re-enter the same loop;
577  for(unsigned sh=0; sh<cReader.NbShapes(); sh++) {
578  TopoDS_Shape shape = cReader.Shape(sh+1);
579 
580  // NB: here I do know there is a single unique shape available;
581  for (TopExp_Explorer itf(shape,TopAbs_SOLID); itf.More(); itf.Next()) {
582  const TopoDS_Shape &solid = itf.Current();
583 
584  // FIXME: avoid duplication here and in EicCadWizard::FaceGuidedSplit();
585  if (config->mForcedStlSolidCreation) {
586  CreateStlSolidRootFile(solid, bname, config);
587  return 0;
588  } //if
589  //if (config->mForcedGhostSolidCreation) {
590  if (config->mMaterial.IsNull()) {
591  CreateGhostSolidRootFile(solid, bname, config);
592  return 0;
593  } //if
594 
595  gp_Pnt *bcenter;
596  double bradius;
597  {
598  double xMin, yMin, zMin, xMax, yMax, zMax;
599  Bnd_Box Boundary;
600  BRepBndLib::Add(solid, Boundary);
601 
602  Boundary.Get(xMin, yMin, zMin, xMax, yMax, zMax);
603 
604  // Be lazy; determine bounding sphere;
605  bcenter = new gp_Pnt((xMin+xMax)/2., (yMin+yMax)/2., (zMin+zMax)/2.);
606  bradius = sqrt(SQR(xMax-xMin) + SQR(yMax-yMin) + SQR(zMax-zMin))/2.;
607  }
608 
609  {
610  std::vector<ObjectFace*> faces;
611  // Get boundary box for the whole object;
612  double gxMin, gyMin, gzMin, gxMax, gyMax, gzMax;
613  Bnd_Box Gboundary;
614  BRepBndLib::Add(solid, Gboundary);
615 
616  Gboundary.Get(gxMin, gyMin, gzMin, gxMax, gyMax, gzMax);
617 
618  // Allocate all faces (except for those which were tried out already)
619  // together with their boundary boxes;
620  for (TopExp_Explorer itg(solid,TopAbs_FACE); itg.More(); itg.Next()) {
621  {
622  TopoDS_Face &face = (TopoDS_Face&)itg.Current();
623 
624  Handle(Geom_Surface) SS = BRep_Tool::Surface(face);
625  cout << " " << SS->DynamicType() << endl;
626  if (IsElementaryFace(face)) {
627  // Elementary face -> get cutting surface;
628  EicCadWizardCut *fcut = GetCut(face, bcenter, bradius);
629 
630  bool tried = false;
631  for(unsigned tct=0; tct<tried_cuts->size(); tct++) {
632  EicCadWizardCut *tcut = (*tried_cuts)[tct].first;
633 
634  if (fcut->IsEqual(tcut)) {
635  tried = true;
636  break;
637  } //if
638  } //for tct
639 
640  // No reason to account for this face in the flat cut procedure;
641  if (tried) continue;
642  } //if
643  }
644 
645  // Otherwise proceed with the allocation;
646  ObjectFace *objface = new ObjectFace(&(TopoDS_Face&)itg.Current());
647 
648  Bnd_Box Boundary;
649  BRepBndLib::Add(itg.Current(), Boundary);
650  Boundary.Get(objface->xMin, objface->yMin, objface->zMin,
651  objface->xMax, objface->yMax, objface->zMax);
652  // FIXME: this looks stupid;
653  objface->mMin[0] = objface->xMin; objface->mMin[1] = objface->yMin; objface->mMin[2] = objface->zMin;
654  objface->mMax[0] = objface->xMax; objface->mMax[1] = objface->yMax; objface->mMax[2] = objface->zMax;
655 
656  faces.push_back(objface);
657  } //for itg
658 
659  printf("%3d non-trivial faces total!\n", faces.size());
660 
661  // Well, some sanity must be there; require at least that many non-trivial faces;
662  if (faces.size() <= 10) return -1;
663 
664  // Now loop through all 3 dimensions, try out N locations of splitting
665  // plane and see whether can separate faces in a better way; FIXME:
666  // something like a binary tree approximation is due here;
667  {
668  int best_iq = -1;
669  // FIXME: even in this ugly approach should do this parameter configurable;
670  unsigned ndim = 10, best_st = 0, best_metric = 0;
671  double gMin[3] = {gxMin, gyMin, gzMin}, gMax[3] = {gxMax, gyMax, gzMax}, gStep[3];
672  for(unsigned iq=0; iq<3; iq++)
673  gStep[iq] = (gMax[iq] - gMin[iq])/ndim;
674 
675  for(unsigned iq=0; iq<3; iq++) {
676  for(unsigned st=1; st<ndim; st++) {
677  double coord = gMin[iq] + st*gStep[iq];
678 
679  // Calculate number of left-side/crossed/right-side faces;
680  int left = 0, crossed = 0, right = 0;
681  for(unsigned fc=0; fc<faces.size(); fc++) {
682  ObjectFace *objface = faces[fc];
683 
684  if (objface->mMin[iq] <= coord && objface->mMax[iq] <= coord)
685  left++;
686  else
687  if(objface->mMin[iq] >= coord && objface->mMax[iq] >= coord)
688  right++;
689  else
690  crossed++;
691  } //for fc
692 
693  // This cut would be useless, nothing to talk about;
694  if (!left || !right) continue;
695 
696  unsigned metric = abs(left - right) + crossed;
697  if (best_iq == -1 || metric < best_metric) {
698  best_iq = iq;
699  best_st = st;
700  best_metric = metric;
701  } //if
702 
703  printf("%3d %3d -> %4d %4d %4d -> %4d\n", iq, st, left, crossed, right, abs(left-right)+crossed);
704  } //for st
705  } //for iq
706 
707  printf("--> %d %d -> %3d\n", best_iq, best_st, best_metric);
708  if (best_iq == -1) return -1;
709 
710  // FIXME: make configurable; anyway, for now take this decision here, make a cut
711  // and create 'split' subdirectory without any further considerations;
712  //if (best_metric + 2 >= faces.size()) return -1;
713 
714  // Define the cutting plane;
715  double pt[3], nn[3];
716  for(unsigned iq=0; iq<3; iq++) {
717  pt[iq] = best_iq == iq ? gMin[iq] + best_st*gStep[iq] : 0.0;
718  nn[iq] = best_iq == iq ? 1.0 : 0.0;
719  } //for iq
720  gp_Pnt x0(pt[0], pt[1], pt[2]);
721  gp_Dir n0(nn[0], nn[1], nn[2]);
722  gp_Pln pl(x0, n0);
723 
724  // This is my best guess flat cut;
725  EicCadWizardCut *fcut = new EicCadWizardPlane(pl);
726 
727  // Check that it was not used already;
728  for(unsigned tct=0; tct<tried_cuts->size(); tct++) {
729  EicCadWizardCut *tcut = (*tried_cuts)[tct].first;
730 
731  // Yes, just return failure of this attempt;
732  if (fcut->IsEqual(tcut)) return -1;
733  } //for tct
734 
735  TopoDS_Shape commonHalf = BRepAlgoAPI_Common(solid, fcut->GetSolid());
736  for (TopExp_Explorer itq(commonHalf,TopAbs_SOLID); itq.More(); itq.Next())
737  fcut->AddCommonSolid(new TopoDS_Shape(itq.Current()));
738 
739  TopoDS_Shape cutHalf = BRepAlgoAPI_Cut(solid, fcut->GetSolid());
740  for (TopExp_Explorer itq(cutHalf,TopAbs_SOLID); itq.More(); itq.Next())
741  fcut->AddCutSolid(new TopoDS_Shape(itq.Current()));
742 
743  //@@@fcut->mSubtractionFlag = fcut->GetCutSolidsCount();
744 
745  printf("-> multi %3d; --> %3d %3d\n",
746  fcut->GetMultiplicity(), fcut->GetCommonSolidsCount(), fcut->GetCutSolidsCount());
747 
748  // Yes, this would be a failure;
749  if (fcut->GetCommonSolidsCount() + fcut->GetCutSolidsCount() <= 1) return -1;
750 
751  {
752  char dname[1024];
753  unsigned csCounter = 0;
754  std::vector<TopoDS_Shape*> *arr[2] = {&fcut->mCommonSolids, &fcut->mCutSolids};
755 
756  snprintf(dname, 1024-1, "%s.cut-%05d", bname, 0);
757  // FIXME: once debugging is over, use Boost remove_all() to clean up non-empty directory;
758  mkdir(dname, 0755);
759 
760  for(unsigned gr=0; gr<2; gr++) {
761  std::vector<TopoDS_Shape*> *group = arr[gr];
762  std::vector<std::pair<EicCadWizardCut*,bool> > *fwd_cuts = new std::vector<std::pair<EicCadWizardCut*,bool> >;
763  for(unsigned tct=0; tct<tried_cuts->size(); tct++)
764  fwd_cuts->push_back((*tried_cuts)[tct]);
765  fwd_cuts->push_back(std::pair<EicCadWizardCut*,bool>(fcut, gr == 1));
766 
767  for(unsigned pt=0; pt<group->size(); pt++) {
768  const TopoDS_Shape &qshape = *(*group)[pt];
769 
770  STEPControl_Writer cWriter;
771 
772  cWriter.Transfer(qshape, STEPControl_ManifoldSolidBrep);
773  char qname[1024];
774  snprintf(qname, 1024-1, "%s/part-%05d.stp", dname, csCounter);
775  cWriter.Write(qname);
776 
777  {
778  //static unsigned counter;
779 
780  //if (counter == 1) {
781  int ret = ConvertSourceFileToRoot(qname, config, fwd_cuts);
782  if (ret) return ret;
783  //}
784  //counter++;
785  }
786 
787  csCounter++;
788  } //for pt
789  } //for gr
790  }
791 
792  {
793  // Create .split link;
794  char dname[1024], lname[1024];
795  // FIXME: this looks like a hack;
796  snprintf(dname, 1024-1, "%s.cut-%05d", strrchr(bname, '/') + 1, 0);
797  snprintf(lname, 1024-1, "%s.split", bname);
798  unlink(lname);
799  symlink(dname, lname);
800 
801 #if _OLD_
802  {
803  // Copy over tried_cuts[] vector and append it with this selected cut;
804  std::vector<std::pair<EicCadWizardCut*,bool> > *fwd_cuts = new std::vector<std::pair<EicCadWizardCut*,bool> >;
805  for(unsigned tct=0; tct<tried_cuts->size(); tct++)
806  fwd_cuts->push_back((*tried_cuts)[tct]);
807  fwd_cuts->push_back(std::pair<EicCadWizardCut*,bool>(fcut,true));
808 
809  int ret = ConvertSourceDirectoryToRoot(lname, config, fwd_cuts);
810  if (ret) return ret;
811  }
812 #endif
813  }
814  }
815  }
816  } //for itf
817  } //for sh
818 
819  return 0;
820 } // EicCadWizard::FlatSurfaceSplit()
821 
822 // ---------------------------------------------------------------------------------------
823 
824 int EicCadWizard::FaceGuidedSplit(const STEPControl_Reader &cReader, const char *bname,
826  const std::vector<std::pair<EicCadWizardCut*,bool> > *tried_cuts)
827 {
828  // So need to deal with a single solid; perform cuts; FIXME: re-use 'itf' later;
829  // for now just re-enter the same loop;
830  for(unsigned sh=0; sh<cReader.NbShapes(); sh++) {
831  TopoDS_Shape shape = cReader.Shape(sh+1);
832 
833  // NB: here I do know there is a single unique shape available;
834  for (TopExp_Explorer itf(shape,TopAbs_SOLID); itf.More(); itf.Next()) {
835  const TopoDS_Shape &solid = itf.Current();
836 
837  if (config->mForcedStlSolidCreation) {
838  CreateStlSolidRootFile(solid, bname, config);
839  return 0;
840  } //if
841  //if (config->mForcedGhostSolidCreation) {
842  if (config->mMaterial.IsNull()) {
843  CreateGhostSolidRootFile(solid, bname, config);
844  return 0;
845  } //if
846 
847  // THINK: is it really harmless to keep this boundary sphere global in view
848  // of recursion?; NB: will certainly fail in multi-threaded mode;
849  gp_Pnt *bcenter;
850  double bradius;
851  {
852  double xMin, yMin, zMin, xMax, yMax, zMax;
853  Bnd_Box Boundary;
854  BRepBndLib::Add(solid, Boundary);
855 
856  Boundary.Get(xMin, yMin, zMin, xMax, yMax, zMax);
857 
858  // Be lazy; determine bounding sphere;
859  bcenter = new gp_Pnt((xMin+xMax)/2., (yMin+yMax)/2., (zMin+zMax)/2.);
860  bradius = sqrt(SQR(xMax-xMin) + SQR(yMax-yMin) + SQR(zMax-zMin))/2.;
861  }
862 
863  {
864  bool has_complex_faces = false;
865  // FIXME: may want to get rid of uCounter;
866  unsigned faceCounter = 0, uCounter = 0;
867  for (TopExp_Explorer itg(solid,TopAbs_FACE); itg.More(); itg.Next())
868  faceCounter++;
869  printf("%3d faces total!\n", faceCounter);
870 
871  {
872  // FIXME: some sort of std::map would help;
873  std::vector<std::pair<EicCadWizardCut*,bool> > *cuts = new std::vector<std::pair<EicCadWizardCut*,bool> >;
874  //std::vector<EicCadWizardCut*> *cuts = new std::vector<EicCadWizardCut*>;
875 
876  std::vector<std::vector<std::pair<std::string,bool> > > vgdumb;
877 
878  unsigned single_piece_face_count_max_min = 0, ct_best = 0, tried_already = 0;
879  for (TopExp_Explorer itg(solid,TopAbs_FACE); itg.More(); itg.Next()) {
880  TopoDS_Face &face = (TopoDS_Face&)itg.Current();
881 
882  std::vector<std::pair<std::string,bool> > vldumb;
883 
884  Handle(Geom_Surface) SS = BRep_Tool::Surface(face);
885  cout << " " << SS->DynamicType() << endl;
886  if (!IsElementaryFace(face)) {
887  has_complex_faces = true;
888  continue;
889  } //if
890 
891  // Elementary face -> get cutting surface;
892  EicCadWizardCut *fcut = GetCut(face, bcenter, bradius);
893 
894  // Check whether it was tried out already;
895  {
896  bool exists = false;
897 
898  for(unsigned ct=0; ct<cuts->size(); ct++) {
899  EicCadWizardCut *cut = (*cuts)[ct].first;
900 
901  if (cut->IsEqual(fcut)) {
902  cut->IncrementMultiplicity();
903 
904  exists = true;
905  break;
906  } //if
907  } //for ct
908 
909  if (exists) continue;
910  }
911 
912  // Account this (new) cut in the cutting surface array;
913  cuts->push_back(std::pair<EicCadWizardCut*,bool>(fcut,true));
914  //cuts->push_back(fcut);//,true));
915 
916  // Check whether it was tried before (then there is no chance
917  // one gets a non-trivial split);
918  {
919  bool tried = false;
920 
921  for(unsigned tct=0; tct<tried_cuts->size(); tct++) {
922  EicCadWizardCut *tcut = (*tried_cuts)[tct].first;
923 
924  if (fcut->IsEqual(tcut)) {
925  // Yes, this suffices;
926  //fcut->mSubtractionFlag = tcut->mSubtractionFlag;
927  (*cuts)[cuts->size()-1].second = (*tried_cuts)[tct].second;
928 
929  tried_already++;
930  tried = true;
931  break;
932  } //if
933  } //for tct
934 
935  if (tried) goto _continue;
936  }
937 
938  // Cut has not been tried yet -> do it now;
939  {
940  TopoDS_Shape commonHalf = BRepAlgoAPI_Common(solid, fcut->GetSolid());
941  for (TopExp_Explorer itq(commonHalf,TopAbs_SOLID); itq.More(); itq.Next())
942  fcut->AddCommonSolid(new TopoDS_Shape(itq.Current()));
943 
944  TopoDS_Shape cutHalf = BRepAlgoAPI_Cut(solid, fcut->GetSolid());
945  for (TopExp_Explorer itq(cutHalf,TopAbs_SOLID); itq.More(); itq.Next())
946  fcut->AddCutSolid(new TopoDS_Shape(itq.Current()));
947 
948  //fcut->mSubtractionFlag = fcut->GetCutSolidsCount();
949  (*cuts)[cuts->size()-1].second = fcut->GetCutSolidsCount();
950  // Account this (new) cut in the cutting surface array;
951  //cuts->push_back(std::pair<EicCadWizardCut*,bool>(fcut,fcut->GetCutSolidsCount()));
952 
953  printf("%4d -> multi %3d; --> %3d %3d\n",
954  cuts->size()-1, fcut->GetMultiplicity(), fcut->GetCommonSolidsCount(), fcut->GetCutSolidsCount());
955  }
956 
957  // Save all cut options, which keep splitting the file in smaller objects;
958  if (fcut->GetCommonSolidsCount() + fcut->GetCutSolidsCount() >= 2) {
959  char dname[1024];
960  unsigned csCounter = 0, fCounter[2] = {0, 0}, single_piece_face_count_max = 0;
961  std::vector<TopoDS_Shape*> *arr[2] = {&fcut->mCommonSolids, &fcut->mCutSolids};
962 
963  snprintf(dname, 1024-1, "%s.cut-%05d", bname, cuts->size()-1);
964  // FIXME: once debugging is over, use Boost remove_all() to clean up non-empty directory;
965  mkdir(dname, 0755);
966 
967  for(unsigned gr=0; gr<2; gr++) {
968  std::vector<TopoDS_Shape*> *group = arr[gr];
969 
970  for(unsigned pt=0; pt<group->size(); pt++) {
971  const TopoDS_Shape &qshape = *(*group)[pt];
972 
973  unsigned single_piece_face_count = 0;
974  for (TopExp_Explorer itx(qshape,TopAbs_FACE); itx.More(); itx.Next()) {
975  fCounter[gr]++;
976  single_piece_face_count++;
977  } //for itx
978  if (single_piece_face_count > single_piece_face_count_max)
979  single_piece_face_count_max = single_piece_face_count;
980 
981  STEPControl_Writer cWriter;
982 
983  cWriter.Transfer(qshape, STEPControl_ManifoldSolidBrep);
984  char qname[1024];
985  snprintf(qname, 1024-1, "%s/part-%05d.stp", dname, csCounter);
986  cWriter.Write(qname);
987 
988  vldumb.push_back(std::pair<std::string,bool>(qname, gr == 1));
989 
990  csCounter++;
991  } //for pt
992  } //for gr
993 
994  printf(" --> %4d & %4d faces total; max per piece: %4d!\n",
995  fCounter[0], fCounter[1], single_piece_face_count_max);
996 
997  if (!single_piece_face_count_max_min ||
998  single_piece_face_count_max < single_piece_face_count_max_min) {
999  ct_best = cuts->size()-1;
1000  single_piece_face_count_max_min = single_piece_face_count_max;
1001  } //if
1002 
1003  uCounter++;
1004  } //if
1005 
1006  _continue:
1007  vgdumb.push_back(vldumb);
1008  } //for itg
1009 
1010  printf("%d new cuts total (and %d tried out already)!\n", cuts->size(), tried_already);
1011 
1012  if (uCounter) {
1013  // Create .split link to the best option;
1014  char dname[1024], lname[1024];
1015  // FIXME: this looks like a hack;
1016  snprintf(dname, 1024-1, "%s.cut-%05d", strrchr(bname, '/') + 1, ct_best);
1017  snprintf(lname, 1024-1, "%s.split", bname);
1018  unlink(lname);
1019  symlink(dname, lname);
1020 
1021  {
1022  printf("@@@ %d %d\n", vgdumb.size(), ct_best);
1023  std::vector<std::pair<std::string,bool> > &vldumb = vgdumb[ct_best];
1024  for(unsigned fl=0; fl<vldumb.size(); fl++) {
1025  std::vector<std::pair<EicCadWizardCut*,bool> > *fwd_cuts = new std::vector<std::pair<EicCadWizardCut*,bool> >;
1026  for(unsigned tct=0; tct<tried_cuts->size(); tct++)
1027  fwd_cuts->push_back((*tried_cuts)[tct]);
1028  fwd_cuts->push_back(std::pair<EicCadWizardCut*,bool>((*cuts)[ct_best].first, vldumb[fl].second));
1029 
1030  int ret = ConvertSourceFileToRoot(vldumb[fl].first, config, fwd_cuts);
1031  if (ret) return ret;
1032  } //for fl
1033 
1034  // Copy over tried_cuts[] vector and append it with this selected cut;
1035  //std::vector<std::pair<EicCadWizardCut*,bool> > *fwd_cuts = new std::vector<std::pair<EicCadWizardCut*,bool> >;
1036  //for(unsigned tct=0; tct<tried_cuts->size(); tct++)
1037  //fwd_cuts->push_back((*tried_cuts)[tct]);
1038  //fwd_cuts->push_back((*cuts)[ct_best]);
1039 
1040  //int ret = ConvertSourceDirectoryToRoot(lname, config, fwd_cuts);
1041  //if (ret) return ret;
1042  }
1043  } else {
1044  //{
1045  //std::vector<EicCadWizardCut*> *fwd_cuts = new std::vector<EicCadWizardCut*>;
1046  //return FaceGuidedSplit(cReader, bname, config, fwd_cuts);
1047  //}
1048 
1049  // Now, since no more cuts possible, take the decision;
1050  if (has_complex_faces) {
1051  // FIXME: later on may want to try out non-face cuts in order to isolate
1052  // parts of the solid, which may still be represented as a boolean operation
1053  // on basic shapes;
1054  //assert(config->mStlSolidCreationAllowed);
1055 
1056  printf("Creating ROOT file with tetrahedra (shape has a complex face, sorry) ...\n");
1057 
1058  CreateStlSolidRootFile(solid, bname, config);
1059  } else {
1060  // FIXME: this is leas efficient than in the original EicCadFile implementation,
1061  // but much more straightforward; the loop over
1062  if (config->mBooleanSolidCreationAllowed) {
1063  printf("Decomposing into basic ROOT shapes ...\n");
1064 
1065  CreateBooleanSolidRootFile(solid, bcenter, bradius, cuts, bname, config);
1066  } else {
1067  //assert(config->mStlSolidCreationAllowed);
1068 
1069  printf("Creating ROOT file with tetrahedra (Boolean representation disabled, sorry) ...\n");
1070 
1071  CreateStlSolidRootFile(solid, bname, config);
1072  } //if
1073  } //if
1074  } //if
1075  }
1076  }
1077  } //for itf
1078  } //for sh
1079 
1080  return 0;
1081 } // EicCadWizard::FaceGuidedSplit()
1082 
1083 // ---------------------------------------------------------------------------------------
1084 
1085 //
1086 // Essentially an adapted EicCadFile::DumpAsStlSolid() call;
1087 //
1088 
1089 int EicCadWizard::CreateStlSolidRootFile(const TopoDS_Shape &solid, const char *bname,
1091 {
1092  char fname[1024];
1093  snprintf(fname, 1024-1, "%s.stl", bname);
1094 
1095  // Yes, in newer OCC versions this operation is required;
1096  {
1097  StlAPI_Writer writer;
1098 
1099  BRepMesh_IncrementalMesh(solid, config->GetStlQualityCoefficient());
1100  //writer.SetCoefficient(0.03);
1101 
1102  writer.ASCIIMode() = true;
1103  writer.Write(solid, fname);
1104  }
1105 
1106  {
1107  // FIXME: do this better later; in fact this suffices I guess;
1108  EicCadFileConfig *qconfig = new EicCadFileConfig();
1109  //qconfig->SetStlVertexMergingTolerance(0.01);
1110  qconfig->CreateMediaHub(strdup(config->mMaterial.Data()));//(char*)"air");
1111 
1112  EicGeoParData *geo = new EicGeoParData("DUMMY", 0, 0);
1113  char rname[1024];
1114  snprintf(rname, 1024-1, "%s.root", bname);
1115  geo->SetFileName(rname);
1116 
1117  qconfig->mhub()->Init();
1118 
1119  // 'false': yes, here I should ignore units and scaling given in mConfig because
1120  // they were taken into account when creating the STEP model; THINK!
1121  EicStlFactory stl_factory(0, fname, qconfig, false);
1122 
1123  stl_factory.CreateRootFile(geo->GetTopVolume(), bname);
1124 
1125  // FIXME;
1126  geo->GetColorTable()->AddPatternMatch ("-Ass0", kBlue);
1127  geo->GetTransparencyTable()->AddPatternMatch("-Ass0", 0);
1128 
1129  geo->FinalizeOutput();
1130 
1131  AccountRootFile(rname);
1132  }
1133 
1134  unlink(fname);
1135 
1136  return 0;
1137 } // EicCadWizard::CreateStlSolidRootFile()
1138 
1139 // ---------------------------------------------------------------------------------------
1140 
1141 TGeoCombiTrans *Ax3ToCombiTrans(const char *name, const gp_Ax3 &ax3, double offset)
1142 {
1143  gp_Pnt x0 = ax3.Location();
1144  gp_Dir xDir = ax3.XDirection(), yDir = ax3.YDirection(), zDir = ax3.Axis().Direction();
1145 
1146  double data[9] = {xDir.X(), yDir.X(), zDir.X(),
1147  xDir.Y(), yDir.Y(), zDir.Y(),
1148  xDir.Z(), yDir.Z(), zDir.Z()};
1149  TGeoRotation *grr = new TGeoRotation();
1150  grr->SetMatrix(data);
1151 
1152  return new TGeoCombiTrans(name,
1153  x0.X() + offset * zDir.X(),
1154  x0.Y() + offset * zDir.Y(),
1155  x0.Z() + offset * zDir.Z(), grr);
1156 } // Ax3ToCombiTrans()
1157 
1158 // ---------------------------------------------------------------------------------------
1159 
1160 int EicCadWizard::CreateBooleanSolidRootFile(const TopoDS_Shape &solid, const gp_Pnt *bcenter, double bradius,
1161  const std::vector<std::pair<EicCadWizardCut*,bool> > *cuts,
1162  const char *bname, EicCadWizardFileConfig *config)
1163 {
1164  // FIXME: unify this code in both places;
1165  EicCadFileConfig *qconfig = new EicCadFileConfig();
1166  //qconfig->CreateMediaHub((char*)"air");
1167  // FIXME: do it better;
1168  qconfig->CreateMediaHub(strdup(config->mMaterial.Data()));
1169 
1170  EicGeoParData *geo = new EicGeoParData("DUMMY", 0, 0);
1171  char rname[1024];
1172  snprintf(rname, 1024-1, "%s.root", bname);
1173  geo->SetFileName(rname);
1174 
1175  qconfig->mhub()->Init();
1176 
1177  TString cmd(":");
1178 
1179  {
1180  static unsigned scounter;
1181  char vname[128], tname[128];
1182 
1183  //printf("counter=%d\n", counter);
1184 
1185  snprintf(vname, 128-1, "VS%04d", scounter);
1186  snprintf(tname, 128-1, "TS%04d", scounter++);
1187 
1188  cmd = vname + cmd + tname;
1189 
1190  // Define big enough ROOT sphere;
1191  //TGeoSphere *shell = new TGeoSphere(vname, 0.0, mBoundarySphereRadius + 1E-10*counter);
1192  //TGeoCombiTrans *ts = new TGeoCombiTrans(tname, mBoundarySphereCenter->X(),
1193  // mBoundarySphereCenter->Y(),
1194  // mBoundarySphereCenter->Z(), 0);
1195  TGeoSphere *shell = new TGeoSphere(vname, 0.0, bradius + 1E-10*scounter);
1196  TGeoCombiTrans *ts = new TGeoCombiTrans(tname, bcenter->X(),
1197  bcenter->Y(),
1198  bcenter->Z(), 0);
1199  ts->RegisterYourself();
1200  }
1201 
1202  for(unsigned ct=0; ct<cuts->size(); ct++) {
1203  //EicCadWizardCut *cut = (*cuts)[ct].first;
1204  std::pair<EicCadWizardCut*,bool> cut = (*cuts)[ct];
1205 
1206  // FIXME: multi-threading!!!;
1207  static unsigned counter;
1208  char vname[128], tname[128];
1209 
1210  snprintf(vname, 128-1, "V%06d", counter);
1211  snprintf(tname, 128-1, "T%06d", counter++);
1212 
1213  TGeoCombiTrans *ts = cut.first->BuildRootVolume(vname, tname);
1214 
1215  if (ts) ts->RegisterYourself();
1216 
1217  //cmd = "(" + cmd + ")" + (cut->GetCutSolidsCount() ? "-" : "*") + vname + (ts ? TString(":") + tname : "");
1218  //cmd = "(" + cmd + ")" + (cut->mSubtractionFlag ? "-" : "*") + vname + (ts ? TString(":") + tname : "");
1219  //cmd = "(" + cmd + ")" + (cut.first->mSubtractionFlag ? "-" : "*") + vname + (ts ? TString(":") + tname : "");
1220  cmd = "(" + cmd + ")" + (cut.second ? "-" : "*") + vname + (ts ? TString(":") + tname : "");
1221  } //for ct
1222 
1223  printf("%s\n", cmd.Data());
1224 
1225  {
1226  static unsigned ccounter;
1227  char cname[128];
1228 
1229  snprintf(cname, 128-1, "@RV@%06d", ccounter++);
1230 
1231  TGeoVolume *vcomp;
1233  EicCompositeShape *comp = new EicCompositeShape(cname, cmd.Data(), &solid);
1234  //EicCompositeShape *comp = new EicCompositeShape(cname, "", &solid);
1236  vcomp = new TGeoVolume(cname, comp, qconfig->mhub()->fSingleMedium);
1237  } else {
1238  TGeoCompositeShape *comp = new TGeoCompositeShape(cname, cmd.Data());
1239  vcomp = new TGeoVolume(cname, comp, qconfig->mhub()->fSingleMedium);
1240  } //if
1241  //TGeoVolume *vcomp = new TGeoVolume(cname, comp, qconfig->mhub()->fSingleMedium);
1242 
1243  geo->GetTopVolume()->AddNode(vcomp, 0, new TGeoCombiTrans(0, 0, 0, 0));
1244  vcomp->RegisterYourself();
1245 
1246  // FIXME: please;
1247  geo->GetColorTable()->AddPatternMatch ("@RV@", kGray);
1248  geo->GetTransparencyTable()->AddPatternMatch("@RV@", 0);
1249 
1250  geo->FinalizeOutput();
1251 
1252  AccountRootFile(rname);
1253  }
1254 
1255  return 0;
1256 } // EicCadWizard::CreateBooleanSolidRootFile()
1257 
1258 // ---------------------------------------------------------------------------------------
1259 
1261  const char *bname, EicCadWizardFileConfig *config)
1262 {
1263  // FIXME: unify this code in both places;
1264  EicCadFileConfig *qconfig = new EicCadFileConfig();
1265  // FIXME: this works only as long as material is the same as of CAVE volume;
1266  qconfig->CreateMediaHub((char*)"air");
1267 
1268  EicGeoParData *geo = new EicGeoParData("GHOST", 0, 0);
1269  char rname[1024];
1270  snprintf(rname, 1024-1, "%s.root", bname);
1271  geo->SetFileName(rname);
1272 
1273  qconfig->mhub()->Init();
1274 
1275  {
1276  static unsigned ccounter;
1277  char cname[128];
1278 
1279  snprintf(cname, 128-1, "@GV@%06d", ccounter++);
1280 
1281  // FIXME: this is indeed a hack;
1282  EicCompositeShape *comp = new EicCompositeShape(cname, "", &solid);
1284  TGeoVolume *vcomp = new TGeoVolume(cname, comp, qconfig->mhub()->fSingleMedium);
1285 
1286  geo->GetTopVolume()->AddNode(vcomp, 0, new TGeoCombiTrans(0, 0, 0, 0));
1287  vcomp->RegisterYourself();
1288 
1289  // FIXME: please;
1290  //geo->GetColorTable()->AddPatternMatch ("@GV@", kSpring);
1291  //geo->GetTransparencyTable()->AddPatternMatch("@GV@", 50);
1292  geo->GetColorTable()->AddPatternMatch ("@GV@", kGray);
1293  geo->GetTransparencyTable()->AddPatternMatch("@GV@", 0);
1294 
1295  geo->FinalizeOutput();
1296 
1297  AccountRootFile(rname);
1298  }
1299 
1300  return 0;
1301 } // EicCadWizard::CreateGhostSolidRootFile()
1302 
1303 // ---------------------------------------------------------------------------------------
1304 
1305 int EicCadWizard::StraightforwardSplit(const STEPControl_Reader &cReader, const char *bname)
1306 {
1307  // There are >1 solids in this file; create one level down directory and populate it
1308  // with individual shapes;
1309  char dname[1024];
1310  unsigned csCounter = 0;
1311  snprintf(dname, 1024-1, "%s.split", bname);
1312  // FIXME: once debugging is over, use Boost remove_all() to clean up non-empty directory;
1313  mkdir(dname, 0755);
1314 
1315  for(unsigned sh=0; sh<cReader.NbShapes(); sh++) {
1316  TopoDS_Shape shape = cReader.Shape(sh+1);
1317 
1318  for (TopExp_Explorer itf(shape,TopAbs_SOLID); itf.More(); itf.Next()) {
1319  STEPControl_Writer cWriter;
1320 
1321  cWriter.Transfer(itf.Current(), STEPControl_ManifoldSolidBrep);
1322  char qname[1024];
1323  snprintf(qname, 1024-1, "%s/part-%05d.stp", dname, csCounter);
1324  cWriter.Write(qname);
1325 
1326  // FIXME: and need to deal with these files right away here, recursively; later
1327  // on - in multi-threading mode - this will not interrupt the processing sequence;
1328 
1329  csCounter++;
1330  } //for itf
1331  } //for sh
1332 
1333  return 0;
1334 } // EicCadWizard::StraightforwardSplit()
1335 
1336 // ---------------------------------------------------------------------------------------
1337 
1339  const std::vector<std::pair<EicCadWizardCut*,bool> > *tried_cuts)
1340 {
1341  return ConvertSourceFileToRoot(wfile->GetFileName(), wfile->config(), tried_cuts);
1342 } // EicCadWizard::ConvertSourceFileToRoot()
1343 
1344 // =======================================================================================
1345 
1349 
1350 
1351 #if _OFF_
1352  Handle(Geom_Surface) SS = BRep_Tool::Surface(face);
1353  if (!IsElementaryFace(face)) {
1354  cout << setw(3) << rfCounter << " " << SS->DynamicType() << endl;
1355  unsigned dim = 1000;
1356  double u1, u2, v1, v2;
1357  SS->Bounds(u1, u2, v1, v2);
1358  double du = (u2 - u1)/dim, dv = (v2 - v1)/dim;
1359  //printf("%f %f %f %f\n", u1, u2, v1, v2);
1360  for(unsigned iu=0; iu<=dim; iu++)
1361  for(unsigned iv=0; iv<=dim; iv++) {
1362  double u = u1 + du*iu, v = v1 + dv*iv;
1363  gp_Pnt pt = SS->Value(u, v);
1364 
1365  //printf("%3d %3d -> %f %f %f\n", iu, iv, pt.X(), pt.Y(), pt.Z());
1366  } //for iu ..iv
1367 #endif
1368 
1369  //Handle(Message_PrinterOStream) filePrinter =
1370  //new Message_PrinterOStream("export.log", Standard_False, Message_Info);
1371  //Handle(Message_Messenger) msgr = Message::DefaultMessenger();
1372  //msgr->AddPrinter(filePrinter);