Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/visualization/Vtk/src/G4VtkStore.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  1 //
  2 // ********************************************************************
  3 // * License and Disclaimer                                           *
  4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.                             *
 10 // *                                                                  *
 11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                                                  *
 18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // ********************************************************************
 25 //
 26 // Created by Stewart Boogert on 13/11/2021.
 27 //
 28 
 29 #include "G4VtkStore.hh"
 30 
 31 #include "G4Circle.hh"
 32 #include "G4Mesh.hh"
 33 #include "G4Plane3D.hh"
 34 #include "G4Polyhedron.hh"
 35 #include "G4Polyline.hh"
 36 #include "G4Square.hh"
 37 #include "G4Text.hh"
 38 #include "G4VSceneHandler.hh"
 39 #include "G4VisAttributes.hh"
 40 #include "G4VtkUtility.hh"
 41 #include "G4VtkViewer.hh"
 42 #include "G4VtkVisContext.hh"
 43 // #include "G4VtkClipperClosedPipeline.hh"
 44 #include "G4VtkClipClosedSurfacePipeline.hh"
 45 #include "G4VtkClipOpenPipeline.hh"
 46 #include "G4VtkCutterPipeline.hh"
 47 #include "G4VtkImagePipeline.hh"
 48 #include "G4VtkPolydataInstanceAppendPipeline.hh"
 49 #include "G4VtkPolydataInstanceBakePipeline.hh"
 50 #include "G4VtkPolydataInstanceTensorPipeline.hh"
 51 #include "G4VtkPolydataPipeline.hh"
 52 #include "G4VtkPolydataPolygonPipeline.hh"
 53 #include "G4VtkPolydataPolyline2DPipeline.hh"
 54 #include "G4VtkPolydataPolylinePipeline.hh"
 55 #include "G4VtkPolydataSpherePipeline.hh"
 56 #include "G4VtkText2DPipeline.hh"
 57 #include "G4VtkTextPipeline.hh"
 58 #include "G4VtkUnstructuredGridPipeline.hh"
 59 
 60 #ifndef WIN32
 61 #pragma GCC diagnostic push
 62 #pragma GCC diagnostic ignored "-Wextra-semi"
 63 #endif
 64 
 65 #include <vtkNew.h>
 66 #include <vtkSmartPointer.h>
 67 #include <vtkBillboardTextActor3D.h>
 68 #include <vtkLine.h>
 69 #include <vtkMatrix3x3.h>
 70 #include <vtkOBJReader.h>
 71 #include <vtkPLYReader.h>
 72 #include <vtkSTLReader.h>
 73 #include <vtkPolyDataReader.h>
 74 #include <vtkProperty.h>
 75 #include <vtkProperty2D.h>
 76 #include <vtkRegularPolygonSource.h>
 77 #include <vtkTextProperty.h>
 78 
 79 #ifndef WIN32
 80 #pragma GCC diagnostic pop
 81 #endif
 82 
 83 G4VtkStore::G4VtkStore(G4String nameIn) : name(nameIn) {}
 84 
 85 G4VtkStore::~G4VtkStore()
 86 {
 87   Clear();
 88 }
 89 
 90 void G4VtkStore::Modified()
 91 {
 92 #ifdef G4VTKDEBUG
 93   G4cout << "G4VtkStore::Modified() " << name << G4endl;
 94 #endif
 95 
 96   for (const auto& it : polylinePipeMap)
 97     it.second->Modified();
 98 
 99   for (const auto& it : polyline2DPipeMap)
100     it.second->Modified();
101 
102   for (const auto& it : circlePipeMap)
103     it.second->Modified();
104 
105   for (const auto& it : squarePipeMap)
106     it.second->Modified();
107 
108   for (const auto& it : textPipeMap)
109     it.second->Modified();
110 
111   for (const auto& it : text2DPipeMap)
112     it.second->Modified();
113 
114   for (const auto& it : separatePipeMap)
115     it.second->Modified();
116 
117   for (const auto& it : tensorGlyphPipeMap)
118     it.second->Modified();
119 
120   for (const auto& it : appendPipeMap)
121     it.second->Modified();
122 
123   for (const auto& it : bakePipeMap)
124     it.second->Modified();
125 }
126 
127 void G4VtkStore::Clear()
128 {
129 #ifdef G4VTKDEBUG
130   G4cout << "G4VtkStore::Clear() " << name << G4endl;
131 #endif
132 
133   for (const auto& v : polylinePipeMap) {
134     v.second->Clear();
135   }
136   polylinePipeMap.clear();
137 
138   for (const auto& v : polyline2DPipeMap) {
139     v.second->Clear();
140   }
141   polyline2DPipeMap.clear();
142 
143   for (const auto& v : circlePipeMap) {
144     v.second->Clear();
145   }
146   circlePipeMap.clear();
147 
148   for (const auto& v : squarePipeMap) {
149     v.second->Clear();
150   }
151   squarePipeMap.clear();
152 
153   for (const auto& v : textPipeMap) {
154     v.second->Clear();
155   }
156   textPipeMap.clear();
157 
158   for (const auto& v : text2DPipeMap) {
159     v.second->Clear();
160   }
161   text2DPipeMap.clear();
162 
163   for (const auto& v : separatePipeMap) {
164     v.second->Clear();
165   }
166   separatePipeMap.clear();
167 
168   for (const auto& v : tensorGlyphPipeMap) {
169     v.second->Clear();
170   }
171   tensorGlyphPipeMap.clear();
172 
173   for (const auto& v : appendPipeMap) {
174     v.second->Clear();
175   }
176   appendPipeMap.clear();
177 
178   for (const auto& v : bakePipeMap) {
179     v.second->Clear();
180   }
181   bakePipeMap.clear();
182 }
183 
184 void G4VtkStore::ClearNonG4()
185 {
186 #ifdef G4VTKDEBUG
187   G4cout << "G4VtkStore::Clear() " << name << G4endl;
188 #endif
189 
190   for (const auto& v : imagePipeMap) {
191     v.second->Clear();
192   }
193   imagePipeMap.clear();
194 
195   for (const auto& v : sideloadPipeMap) {
196     v.second->Clear();
197   }
198   sideloadPipeMap.clear();
199 }
200 
201 void G4VtkStore::Print()
202 {
203   G4cout << "G4VtkStore::Print() " << name << std::endl;
204   G4cout << "G4VtkStore::Print() polylinePipeMap size        > " << polylinePipeMap.size()
205          << G4endl;
206   G4cout << "G4VtkStore::Print() polyline2DPipeMap size      > " << polyline2DPipeMap.size()
207          << G4endl;
208   G4cout << "G4VtkStore::Print() circlePipeMap size          > " << circlePipeMap.size() << G4endl;
209   G4cout << "G4VtkStore::Print() squarePipeMap size          > " << squarePipeMap.size() << G4endl;
210   G4cout << "G4VtkStore::Print() textPipeMap size            > " << textPipeMap.size() << G4endl;
211   G4cout << "G4VtkStore::Print() text2DPipeMap size          > " << text2DPipeMap.size() << G4endl;
212   G4cout << "G4VtkStore::Print() separatePipeMap size        > " << separatePipeMap.size()
213          << G4endl;
214   G4cout << "G4VtkStore::Print() tensorGlyphPipeMap size     > " << tensorGlyphPipeMap.size()
215          << G4endl;
216   G4cout << "G4VtkStore::Print() transformAppendPipeMap size > " << appendPipeMap.size() << G4endl;
217   G4cout << "G4VtkStore::Print() bakePipeMap size            > " << bakePipeMap.size() << G4endl;
218   G4cout << "G4VtkStore::Print() ugridPipeMap size           > " << ugridPipeMap.size() << G4endl;
219   G4cout << "G4VtkStore::Print() imagePipeMap size           > " << imagePipeMap.size() << G4endl;
220 
221   for (const auto& it : polylinePipeMap)
222     it.second->Print();
223 
224   for (const auto& it : polyline2DPipeMap)
225     it.second->Print();
226 
227   for (const auto& it : circlePipeMap)
228     it.second->Print();
229 
230   for (const auto& it : squarePipeMap)
231     it.second->Print();
232 
233   for (const auto& it : separatePipeMap)
234     it.second->Print();
235 
236   for (const auto& it : tensorGlyphPipeMap)
237     it.second->Print();
238 
239   for (const auto& it : appendPipeMap)
240     it.second->Print();
241 
242   for (const auto& it : bakePipeMap)
243     it.second->Print();
244 
245   for (const auto& it : ugridPipeMap) {
246     G4cout << it.first << G4endl;
247     it.second->Print();
248   }
249 
250   for (const auto& it : imagePipeMap)
251     it.second->Print();
252 }
253 
254 void G4VtkStore::AddPrimitive(const G4Polyline& polyline, const G4VtkVisContext& vc)
255 {
256   G4VSceneHandler::MarkerSizeType sizeType;
257   if (vc.fProcessing2D) {
258     sizeType = G4VSceneHandler::MarkerSizeType::screen;
259   }
260   else {
261     sizeType = G4VSceneHandler::MarkerSizeType::world;
262   }
263 
264   // Get vis attributes - pick up defaults if none.
265   const G4VisAttributes* pVA = vc.fViewer->GetApplicableVisAttributes(polyline.GetVisAttributes());
266 
267   if (sizeType == G4VSceneHandler::MarkerSizeType::world) {
268     std::size_t hash = G4VtkPolydataPolylinePipeline::MakeHash(pVA);
269     std::shared_ptr<G4VtkPolydataPolylinePipeline> pl;
270 
271     if (polylinePipeMap.find(hash) == polylinePipeMap.end()) {
272       // Create new pipeline
273       pl = std::make_shared<G4VtkPolydataPolylinePipeline>(G4String("name"), vc, pVA);
274 
275       // Add to map
276       polylinePipeMap.insert(std::make_pair(hash, pl));
277     }
278     else {
279       pl = polylinePipeMap[hash];
280     }
281     pl->SetPolydata(polyline);
282   }
283 
284   else if (sizeType == G4VSceneHandler::MarkerSizeType::screen) {
285     std::size_t hash = G4VtkPolydataPolyline2DPipeline::MakeHash(pVA);
286     std::shared_ptr<G4VtkPolydataPolyline2DPipeline> pl;
287 
288     if (polyline2DPipeMap.find(hash) == polyline2DPipeMap.end()) {
289       // Create new pipeline
290       pl = std::make_shared<G4VtkPolydataPolyline2DPipeline>(G4String("name"), vc, pVA);
291 
292       // Add to map
293       polyline2DPipeMap.insert(std::make_pair(hash, pl));
294     }
295     else {
296       pl = polyline2DPipeMap[hash];
297     }
298     pl->SetPolydata(polyline);
299   }
300 }
301 
302 void G4VtkStore::AddPrimitive(const G4Text& text, const G4VtkVisContext& vc)
303 {
304   G4VSceneHandler::MarkerSizeType sizeType;
305   if (vc.fProcessing2D) {
306     sizeType = G4VSceneHandler::MarkerSizeType::screen;
307   }
308   else {
309     sizeType = G4VSceneHandler::MarkerSizeType::world;
310   }
311 
312   auto pVA = vc.fViewer->GetApplicableVisAttributes(text.GetVisAttributes());
313 
314   switch (sizeType) {
315     default:
316     case (G4VSceneHandler::MarkerSizeType::screen): {
317       std::size_t hash = G4VtkTextPipeline::MakeHash(text, vc, pVA);
318       auto pl = std::make_shared<G4VtkText2DPipeline>(text, vc, pVA);
319       text2DPipeMap.insert(std::make_pair(hash, pl));
320       break;
321     }
322     case G4VSceneHandler::MarkerSizeType::world: {
323       std::size_t hash = G4VtkTextPipeline::MakeHash(text, vc, pVA);
324       auto pl = std::make_shared<G4VtkTextPipeline>(text, vc, pVA);
325       textPipeMap.insert(std::make_pair(hash, pl));
326       break;
327     }
328   }
329 }
330 
331 void G4VtkStore::AddPrimitive(const G4Circle& circle, const G4VtkVisContext& vc)
332 {
333   G4VSceneHandler::MarkerSizeType sizeType;
334 
335   if (vc.fProcessing2D) {
336     sizeType = G4VSceneHandler::MarkerSizeType::screen;
337   }
338   else {
339     sizeType = G4VSceneHandler::MarkerSizeType::world;
340   }
341 
342   // Get vis attributes - pick up defaults if none.
343   const G4VisAttributes* pVA = vc.fViewer->GetApplicableVisAttributes(circle.GetVisAttributes());
344 
345   if (sizeType == G4VSceneHandler::MarkerSizeType::world) {
346     std::size_t hash = G4VtkPolydataSpherePipeline::MakeHash(pVA);
347     std::shared_ptr<G4VtkPolydataSpherePipeline> pl;
348 
349     if (circlePipeMap.find(hash) == circlePipeMap.end()) {
350       // Create new pipeline
351       pl = std::make_shared<G4VtkPolydataSpherePipeline>(G4String("name"), vc, pVA);
352 
353       // add to map
354       circlePipeMap.insert(std::make_pair(hash, pl));
355     }
356     else {
357       pl = circlePipeMap[hash];
358     }
359 
360     // Data data point
361     const CLHEP::HepRotation rot = vc.fTransform.getRotation();
362     G4Point3D posPrime = rot * circle.GetPosition();
363     pl->SetPolydataData(vc.fTransform.dx() + posPrime.x(), vc.fTransform.dy() + posPrime.y(),
364                         vc.fTransform.dz() + posPrime.z());
365   }
366 }
367 
368 void G4VtkStore::AddPrimitive(const G4Square& square, const G4VtkVisContext& vc)
369 {
370   G4VSceneHandler::MarkerSizeType sizeType;
371 
372   if (vc.fProcessing2D) {
373     sizeType = G4VSceneHandler::MarkerSizeType::screen;
374   }
375   else {
376     sizeType = G4VSceneHandler::MarkerSizeType::world;
377   }
378 
379   // Get vis attributes - pick up defaults if none.
380   const G4VisAttributes* pVA = vc.fViewer->GetApplicableVisAttributes(square.GetVisAttributes());
381 
382   if (sizeType == G4VSceneHandler::MarkerSizeType::world) {
383     std::size_t hash = std::hash<G4VisAttributes>{}(*pVA);
384 
385     std::shared_ptr<G4VtkPolydataPolygonPipeline> pl;
386     if (squarePipeMap.find(hash) == squarePipeMap.end()) {
387       // Create new pipeline
388       pl = std::make_shared<G4VtkPolydataPolygonPipeline>(G4String("name"), vc, pVA);
389 
390       // add to map
391       squarePipeMap.insert(std::make_pair(hash, pl));
392     }
393     else {
394       pl = squarePipeMap[hash];
395     }
396 
397     // Data data point
398     const CLHEP::HepRotation rot = vc.fTransform.getRotation();
399     G4Point3D posPrime = rot * square.GetPosition();
400     pl->SetPolydataData(vc.fTransform.dx() + posPrime.x(), vc.fTransform.dy() + posPrime.y(),
401                         vc.fTransform.dz() + posPrime.z());
402   }
403 }
404 
405 void G4VtkStore::AddPrimitiveSeparate(const G4Polyhedron& polyhedron, const G4VtkVisContext& vc)
406 {
407   // Return if empty polyhedron
408   if (polyhedron.GetNoFacets() == 0) {
409     return;
410   }
411 
412   auto hash = G4VtkPolydataPipeline::MakeHash(polyhedron, vc);
413 
414   auto pl = std::make_shared<G4VtkPolydataPipeline>(G4String("name"), vc);
415   pl->SetPolydata(polyhedron);
416 
417   separatePipeMap.insert(std::make_pair(hash, pl));
418 
419   const G4VisAttributes* pVA =
420     vc.fViewer->GetApplicableVisAttributes(polyhedron.GetVisAttributes());
421   G4Color colour = pVA->GetColour();
422   G4Transform3D fInvObjTrans = vc.fTransform.inverse();
423 
424   pl->SetActorTransform(vc.fTransform.dx(), vc.fTransform.dy(), vc.fTransform.dz(),
425                         fInvObjTrans.xx(), fInvObjTrans.xy(), fInvObjTrans.xz(),
426                         fInvObjTrans.yx(), fInvObjTrans.yy(), fInvObjTrans.yz(),
427                         fInvObjTrans.zx(), fInvObjTrans.zy(), fInvObjTrans.zz());
428   pl->SetActorColour(colour.GetRed(), colour.GetGreen(), colour.GetBlue(), colour.GetAlpha());
429 }
430 
431 void G4VtkStore::AddPrimitiveTensorGlyph(const G4Polyhedron& polyhedron, const G4VtkVisContext& vc)
432 {
433   // Return if empty polyhedron
434   if (polyhedron.GetNoFacets() == 0) {
435     return;
436   }
437 
438   // Possible the polyhedron already has a transform baked in (definitely the case
439   // for scoring meshes. Remove them here
440   auto centre = polyhedron.vertexUnweightedMean();
441   auto transform = G4Translate3D(-centre.x(), -centre.y(), -centre.z());
442 
443   auto polyhedronNew = G4Polyhedron(polyhedron);
444   auto fTransformNew = G4Transform3D(vc.fTransform*transform.inverse());
445 
446   polyhedronNew.Transform(transform);
447 
448   auto hash = G4VtkPolydataInstanceTensorPipeline::MakeHash(polyhedronNew, vc);
449   std::shared_ptr<G4VtkPolydataInstanceTensorPipeline> pl;
450 
451   if (tensorGlyphPipeMap.find(hash) == tensorGlyphPipeMap.end()) {
452     pl = std::make_shared<G4VtkPolydataInstanceTensorPipeline>(G4String("name"), vc);
453     pl->SetPolydata(polyhedronNew);
454     tensorGlyphPipeMap.insert(std::make_pair(hash, pl));
455   }
456   else {
457     pl = tensorGlyphPipeMap[hash];
458   }
459 
460   G4Transform3D fInvObjTrans = fTransformNew.inverse();
461   const G4VisAttributes* pVA =
462     vc.fViewer->GetApplicableVisAttributes(polyhedron.GetVisAttributes());
463   G4Color colour = pVA->GetColour();
464 
465   pl->addInstance(fTransformNew.dx(), fTransformNew.dy(), fTransformNew.dz(),
466                   fInvObjTrans.xx(), fInvObjTrans.xy(), fInvObjTrans.xz(),
467                   fInvObjTrans.yx(), fInvObjTrans.yy(), fInvObjTrans.yz(),
468                   fInvObjTrans.zx(), fInvObjTrans.zy(), fInvObjTrans.zz(),
469                   colour.GetRed(), colour.GetGreen(), colour.GetBlue(), colour.GetAlpha(),
470                   G4String("null"));
471 }
472 
473 void G4VtkStore::AddPrimitiveAppend(const G4Polyhedron& polyhedron, const G4VtkVisContext& vc)
474 {
475   // Empty polyhedron
476   if (polyhedron.GetNoFacets() == 0) {
477     return;
478   }
479 
480   // Possible the polyhedron already has a transform baked in (definitely the case
481   // for scoring meshes. Remove them here
482   auto centre = polyhedron.vertexUnweightedMean();
483   auto transform = G4Translate3D(-centre.x(), -centre.y(), -centre.z());
484 
485   auto polyhedronNew = G4Polyhedron(polyhedron);
486   auto fTransformNew = G4Transform3D(vc.fTransform*transform.inverse());
487 
488   polyhedronNew.Transform(transform);
489 
490   auto hash = G4VtkPolydataInstanceAppendPipeline::MakeHash(polyhedronNew, vc);
491   std::shared_ptr<G4VtkPolydataInstanceAppendPipeline> pl;
492 
493   if (appendPipeMap.find(hash) == appendPipeMap.end()) {
494     pl = std::make_shared<G4VtkPolydataInstanceAppendPipeline>(G4String("name"), vc);
495     pl->SetPolydata(polyhedronNew);
496     appendPipeMap.insert(std::make_pair(hash, pl));
497   }
498   else {
499     pl = appendPipeMap[hash];
500   }
501 
502   G4Transform3D fInvObjTrans = fTransformNew.inverse();
503 
504   pl->addInstance(fTransformNew.dx(), fTransformNew.dy(), fTransformNew.dz(),
505                   fInvObjTrans.xx(), fInvObjTrans.xy(), fInvObjTrans.xz(),
506                   fInvObjTrans.yx(), fInvObjTrans.yy(), fInvObjTrans.yz(),
507                   fInvObjTrans.zx(), fInvObjTrans.zy(), fInvObjTrans.zz(),
508                   0, 0, 0, 0, G4String("null"));
509 };
510 
511 void G4VtkStore::AddPrimitiveTransformBake(const G4Polyhedron& polyhedron,
512                                            const G4VtkVisContext& vc)
513 {
514   // Empty polyhedron
515   if (polyhedron.GetNoFacets() == 0) {
516     return;
517   }
518 
519   // Possible the polyhedron already has a transform baked in (definitely the case
520   // for scoring meshes. Remove them here
521   auto centre = polyhedron.vertexUnweightedMean();
522   auto transform = G4Translate3D(-centre.x(), -centre.y(), -centre.z());
523 
524   auto polyhedronNew = G4Polyhedron(polyhedron);
525   auto fTransformNew = G4Transform3D(vc.fTransform*transform.inverse());
526 
527   polyhedronNew.Transform(transform);
528 
529   // Get vis attributes - pick up defaults if none.
530   const G4VisAttributes* pVA =
531     vc.fViewer->GetApplicableVisAttributes(polyhedron.GetVisAttributes());
532 
533   // Polyhedron colour
534   G4Colour colour = pVA->GetColour();
535 
536   // Hash the vis (alpha) attributes and polyhedron
537   std::size_t hash = G4VtkPolydataInstanceBakePipeline::MakeHash(polyhedronNew, vc);
538 
539   std::shared_ptr<G4VtkPolydataInstanceBakePipeline> pl;
540   if (bakePipeMap.find(hash) == bakePipeMap.end()) {
541     pl = std::make_shared<G4VtkPolydataInstanceBakePipeline>(G4String("none"), vc);
542 
543     bakePipeMap.insert(std::make_pair(hash, pl));
544   }
545   else {
546     pl = bakePipeMap[hash];
547   }
548 
549   G4Transform3D fInvObjTrans = fTransformNew.inverse();
550   pl->SetPolydata(polyhedronNew);
551 
552   pl->addInstance(fTransformNew.dx(), fTransformNew.dy(), fTransformNew.dz(),
553                   fInvObjTrans.xx(), fInvObjTrans.xy(), fInvObjTrans.xz(),
554                   fInvObjTrans.yx(), fInvObjTrans.yy(), fInvObjTrans.yz(),
555                   fInvObjTrans.zx(), fInvObjTrans.zy(), fInvObjTrans.zz(),
556                   colour.GetRed(), colour.GetGreen(), colour.GetBlue(), colour.GetAlpha(),
557                   G4String("null"));
558 };
559 
560 void G4VtkStore::AddCompound(const G4Mesh& mesh, const G4VtkVisContext& vc) {
561   const auto& container = mesh.GetContainerVolume();
562   auto& containerName = const_cast<G4String&>(container->GetName());
563 
564   auto pl = std::make_shared<G4VtkUnstructuredGridPipeline>(containerName,vc);
565   pl->SetUnstructuredGridData(mesh);
566   ugridPipeMap.insert(std::make_pair(G4String("test"), pl));
567 }
568 
569 void G4VtkStore::UpdatePlanePipelines(G4String nameIn, G4String type, const G4Plane3D plane)
570 {
571   if (type == "clipper") {
572     UpdateClipper(nameIn, plane);
573   }
574   else if (type == "cutter") {
575     UpdateCutter(nameIn, plane);
576   }
577 }
578 
579 void G4VtkStore::AddClipper(G4String nameIn, const G4Plane3D& plane)
580 {
581   for (const auto& v : separatePipeMap) {
582     auto clip_pl = new G4VtkClipClosedSurfacePipeline(nameIn, v.second->GetVtkVisContext(),
583                                                       v.second->GetFinalFilter(), true);
584     clip_pl->SetPlane(plane);
585     v.second->AddChildPipeline(clip_pl);
586   }
587 
588   for (const auto& v : tensorGlyphPipeMap) {
589     auto clip_pl = new G4VtkClipClosedSurfacePipeline(nameIn, v.second->GetVtkVisContext(),
590                                                       v.second->GetFinalFilter());
591     clip_pl->SetPlane(plane);
592     v.second->AddChildPipeline(clip_pl);
593   }
594 
595   for (const auto& v : appendPipeMap) {
596     auto clip_pl = new G4VtkClipClosedSurfacePipeline(nameIn, v.second->GetVtkVisContext(),
597                                                       v.second->GetFinalFilter(), true);
598     clip_pl->SetPlane(plane);
599     v.second->AddChildPipeline(clip_pl);
600   }
601 
602   for (const auto& v : bakePipeMap) {
603     auto clip_pl = new G4VtkClipClosedSurfacePipeline(nameIn, v.second->GetVtkVisContext(),
604                                                       v.second->GetFinalFilter(), true);
605     clip_pl->SetPlane(plane);
606     v.second->AddChildPipeline(clip_pl);
607   }
608 }
609 
610 void G4VtkStore::UpdateClipper(G4String nameIn, const G4Plane3D& plane)
611 {
612   for (const auto& v : separatePipeMap) {
613     auto children = v.second->GetChildPipelines();
614     for (auto c : children) {
615       if (c->GetName() == nameIn) {
616         auto cc = dynamic_cast<G4VtkClipClosedSurfacePipeline*>(c);
617         cc->SetPlane(plane);
618       }
619     }
620   }
621 
622   for (const auto& v : tensorGlyphPipeMap) {
623     auto children = v.second->GetChildPipelines();
624     for (auto c : children) {
625       if (c->GetName() == nameIn) {
626         auto cc = dynamic_cast<G4VtkClipClosedSurfacePipeline*>(c);
627         cc->SetPlane(plane);
628       }
629     }
630   }
631 
632   for (const auto& v : appendPipeMap) {
633     auto children = v.second->GetChildPipelines();
634     for (auto c : children) {
635       if (c->GetName() == nameIn) {
636         auto cc = dynamic_cast<G4VtkClipClosedSurfacePipeline*>(c);
637         cc->SetPlane(plane);
638       }
639     }
640   }
641 
642   for (const auto& v : bakePipeMap) {
643     auto children = v.second->GetChildPipelines();
644     for (auto c : children) {
645       if (c->GetName() == nameIn) {
646         auto cc = dynamic_cast<G4VtkClipClosedSurfacePipeline*>(c);
647         cc->SetPlane(plane);
648       }
649     }
650   }
651 }
652 
653 void G4VtkStore::RemoveClipper(G4String /*nameIn*/) {}
654 
655 void G4VtkStore::AddCutter(G4String nameIn, const G4Plane3D& plane)
656 {
657   for (const auto& v : separatePipeMap) {
658     auto cut_pl = new G4VtkCutterPipeline(nameIn, v.second->GetVtkVisContext(),
659                                           v.second->GetFinalFilter(), true);
660     cut_pl->SetPlane(plane);
661     v.second->AddChildPipeline(cut_pl);
662   }
663 
664   for (const auto& v : tensorGlyphPipeMap) {
665     auto cut_pl =
666       new G4VtkCutterPipeline(nameIn, v.second->GetVtkVisContext(), v.second->GetFinalFilter());
667     cut_pl->SetPlane(plane);
668     v.second->AddChildPipeline(cut_pl);
669   }
670 
671   for (const auto& v : appendPipeMap) {
672     auto cut_pl =
673       new G4VtkCutterPipeline(nameIn, v.second->GetVtkVisContext(), v.second->GetFinalFilter());
674     cut_pl->SetPlane(plane);
675     v.second->AddChildPipeline(cut_pl);
676   }
677 
678   for (const auto& v : bakePipeMap) {
679     auto cut_pl =
680       new G4VtkCutterPipeline(nameIn, v.second->GetVtkVisContext(), v.second->GetFinalFilter());
681     cut_pl->SetPlane(plane);
682     v.second->AddChildPipeline(cut_pl);
683   }
684 }
685 
686 void G4VtkStore::UpdateCutter(G4String nameIn, const G4Plane3D& plane)
687 {
688   for (const auto& v : separatePipeMap) {
689     auto children = v.second->GetChildPipelines();
690     for (auto c : children) {
691       if (c->GetName() == nameIn) {
692         auto cc = dynamic_cast<G4VtkCutterPipeline*>(c);
693         cc->SetPlane(plane);
694       }
695     }
696   }
697 
698   for (const auto& v : tensorGlyphPipeMap) {
699     auto children = v.second->GetChildPipelines();
700     for (auto c : children) {
701       if (c->GetName() == nameIn) {
702         auto cc = dynamic_cast<G4VtkCutterPipeline*>(c);
703         cc->SetPlane(plane);
704       }
705     }
706   }
707 
708   for (const auto& v : appendPipeMap) {
709     auto children = v.second->GetChildPipelines();
710     for (auto c : children) {
711       if (c->GetName() == nameIn) {
712         auto cc = dynamic_cast<G4VtkCutterPipeline*>(c);
713         cc->SetPlane(plane);
714       }
715     }
716   }
717 
718   for (const auto& v : bakePipeMap) {
719     auto children = v.second->GetChildPipelines();
720     for (auto c : children) {
721       if (c->GetName() == nameIn) {
722         auto cc = dynamic_cast<G4VtkCutterPipeline*>(c);
723         cc->SetPlane(plane);
724       }
725     }
726   }
727 }
728 
729 void G4VtkStore::RemoveCutter(G4String /*nameIn*/) {}
730 
731 void G4VtkStore::AddNonG4ObjectImage(const G4String& fileName, const G4VtkVisContext& vc)
732 {
733   auto pl = std::make_shared<G4VtkImagePipeline>(G4String("name"), vc);
734   pl->SetImage(fileName);
735   imagePipeMap.insert(std::make_pair(fileName, pl));
736 }
737 
738 void G4VtkStore::AddNonG4ObjectPolydata(const G4String fileName, const G4VtkVisContext& vc)
739 {
740 
741   vtkSmartPointer<vtkPolyData> pd;
742 
743   if (fileName.find("obj") != G4String::npos) {
744     vtkNew<vtkOBJReader> objReader;
745     objReader->SetFileName(fileName.c_str());
746     objReader->Update();
747     pd = objReader->GetOutput();
748   }
749   else if (fileName.find("ply") != G4String::npos) {
750     vtkNew<vtkPLYReader> plyReader;
751     plyReader->SetFileName(fileName.c_str());
752     plyReader->Update();
753     pd = plyReader->GetOutput();
754   }
755   else if (fileName.find("stl") != G4String::npos) {
756     vtkNew<vtkSTLReader> stlReader;
757     stlReader->SetFileName(fileName.c_str());
758     stlReader->Update();
759     pd = stlReader->GetOutput();
760   }
761   else if (fileName.find("vtp") != G4String::npos && fileName.find("vtu") != G4String::npos) {
762     G4cout << "G4VtkStore::AddNonG4ObjectPolydata> vtp/vtu Warning not yet implemented" << G4endl;
763   }
764 
765   auto pl = std::make_shared<G4VtkPolydataPipeline>(G4String("name"), vc);
766 
767 
768   G4Transform3D fInvObjTrans = vc.fTransform.inverse();
769   pl->SetPolydata(pd);
770   pl->SetActorTransform(vc.fTransform.dx(), vc.fTransform.dy(), vc.fTransform.dz(),
771                         fInvObjTrans.xx(), fInvObjTrans.xy(), fInvObjTrans.xz(),
772                         fInvObjTrans.yx(), fInvObjTrans.yy(), fInvObjTrans.yz(),
773                         fInvObjTrans.zx(), fInvObjTrans.zy(), fInvObjTrans.zz());
774   pl->SetActorColour(vc.red, vc.green, vc.blue, vc.alpha);
775 }
776 
777 void G4VtkStore::GetBounds(G4double maxBoundIn[6])
778 {
779   G4double maxBound[6] = {1e99, -1e99, 1e99, -1e99, 1e99, -1e99};
780 
781   for (const auto& v : separatePipeMap) {
782     auto b = v.second->GetBounds();
783     MaxBounds(maxBound, b);
784   }
785 
786   for (const auto& v : tensorGlyphPipeMap) {
787     auto b = v.second->GetBounds();
788     MaxBounds(maxBound, b);
789   }
790 
791   for (const auto& v : appendPipeMap) {
792     auto b = v.second->GetBounds();
793     MaxBounds(maxBound, b);
794   }
795 
796   for (const auto& v : bakePipeMap) {
797     auto b = v.second->GetBounds();
798     MaxBounds(maxBound, b);
799   }
800 
801   maxBoundIn[0] = maxBound[0];
802   maxBoundIn[1] = maxBound[1];
803   maxBoundIn[2] = maxBound[2];
804   maxBoundIn[3] = maxBound[3];
805   maxBoundIn[4] = maxBound[4];
806   maxBoundIn[5] = maxBound[5];
807 }
808 
809 void G4VtkStore::AddToRenderer(vtkRenderer* renderer)
810 {
811   for (const auto& it : polylinePipeMap)
812     renderer->AddActor(it.second->GetActor());
813   for (const auto& it : polyline2DPipeMap)
814     renderer->AddActor(it.second->GetActor());
815   for (const auto& it : circlePipeMap)
816     renderer->AddActor(it.second->GetActor());
817   for (const auto& it : squarePipeMap)
818     renderer->AddActor(it.second->GetActor());
819   for (const auto& it : textPipeMap)
820     renderer->AddActor(it.second->GetActor());
821   for (const auto& it : text2DPipeMap)
822     renderer->AddActor(it.second->GetActor());
823   for (const auto& it : separatePipeMap)
824     renderer->AddActor(it.second->GetActor());
825   for (const auto& it : tensorGlyphPipeMap)
826     renderer->AddActor(it.second->GetActor());
827   for (const auto& it : appendPipeMap)
828     renderer->AddActor(it.second->GetActor());
829   for (const auto& it : bakePipeMap)
830     renderer->AddActor(it.second->GetActor());
831 }
832