Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4ToolsSGSceneHandler.cc
Go to the documentation of this file.
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// John Allison 6th October 2020
27
29
30#include "G4ToolsSGNode.hh"
31
33#include "G4Polyline.hh"
34#include "G4Polymarker.hh"
35#include "G4Circle.hh"
36#include "G4Square.hh"
37#include "G4Polyhedron.hh"
38#include "G4Text.hh"
39#include "G4Mesh.hh"
40#include "G4PlotterManager.hh"
41
42#include <tools/sg/separator>
43#include <tools/sg/matrix>
44#include <tools/sg/rgba>
45#include <tools/sg/draw_style>
46#include <tools/sg/atb_vertices>
47#include <tools/sg/markers>
48#ifdef TOOLS_USE_FREETYPE
49#include <toolx/sg/text_freetype>
50#include <tools/sg/strings>
51#include <tools/font/lato_regular_ttf>
52#include <tools/font/roboto_bold_ttf>
53#include <toolx/sg/text_freetype_marker>
54#else
55#include <tools/sg/dummy_freetype>
56#include <tools/sg/text_hershey_marker>
57#endif
58
59//for plotting:
60#include <tools/sg/dummy_freetype>
61#include <tools/sg/light_off>
62#include <tools/sg/plots>
63#include <tools/sg/h2plot_cp>
64#include <tools/sg/plotter_style>
65#include <tools/sg/event_dispatcher>
66#include <tools/sg/path>
67#include <tools/sg/search>
68#include <tools/histo/h1d>
69#include <tools/histo/h2d>
70#include <tools/sg/plotter_some_styles>
71
72#include <utility>
73
75
77(G4VGraphicsSystem& system, const G4String& name)
78:parent(system, fSceneIdCount++, name)
79,fFreetypeNode(0)
80{
81 //::printf("debug : G4ToolsSGSceneHandler : %lu, %s\n",this,name.c_str());
83#if defined(TOOLS_USE_FREETYPE)
84 fFreetypeNode = new toolx::sg::text_freetype();
85 fFreetypeNode->add_embedded_font(tools::sg::font_lato_regular_ttf(),tools::font::lato_regular_ttf);
86 fFreetypeNode->add_embedded_font(tools::sg::font_roboto_bold_ttf(),tools::font::roboto_bold_ttf);
87#else
88 fFreetypeNode = new tools::sg::dummy_freetype();
89#endif
91}
92
94{
95 //::printf("debug : ~G4ToolsSGSceneHandler : %lu\n",this);
96 //WARNING : nodes may refer graphics managers (as tools/sg/[GL_manager,gl2ps_manager,zb_manager]
97 // used by viewers) to handle gstos (for GPU) or textures, then we have to delete them first.
98 // It is assumed that we pass here BEFORE the attached/managed viewers are deleted.
100 fpPersistent2DObjects.clear();
101 fpTransient3DObjects.clear();
102 fpPersistent3DObjects.clear();
103 delete fFreetypeNode;
104}
105
107{
108 // Physical volume objects for each world hang from POs
110 size_t nWorlds = transportationManager->GetNoWorlds();
111 std::vector<G4VPhysicalVolume*>::iterator iterWorld = transportationManager->GetWorldsIterator();
112 fpPhysicalVolumeObjects.resize(nWorlds);
113 for (size_t i = 0; i < nWorlds; ++i, ++iterWorld) {
114 G4VPhysicalVolume* _world = (*iterWorld);
115 auto entity = new G4ToolsSGNode;
116 fpPersistent3DObjects.add(entity);
117 entity->SetPVNodeID(G4PhysicalVolumeModel::G4PhysicalVolumeNodeID(_world));
118 fpPhysicalVolumeObjects[i] = entity;
119 }
120}
121
123{ // Retrieve or create a G4ToolsSGNode node suitable for next solid or primitive
124
125 // For time being, avoid errors in MT mode - see G4ToolsSGViewer::SwitchToMasterThread
126#ifdef G4MULTITHREADED
127 if (!G4Threading::IsMasterThread()) return nullptr;
128#endif
129
130 if (fReadyForTransients) { // All transients hang from this node
131 tools::sg::separator* sep = new tools::sg::separator;
132 fpTransient3DObjects.add(sep);
133 return sep;
134 }
135
136 auto* pPVModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
137
138 if (!pPVModel) { // Persistent objects (e.g., axes)
139 tools::sg::separator* sep = new tools::sg::separator;
140 fpPersistent3DObjects.add(sep);
141 return sep;
142 }
143
144 // So this is a G4PhysicalVolumeModel
146 typedef std::vector<PVNodeID> PVPath;
147 //const PVPath& drawnPVPath = pPVModel->GetDrawnPVPath();
148 const PVPath& fullPVPath = pPVModel->GetFullPVPath();
149 //G4int currentDepth = pPVModel->GetCurrentDepth();
150 //G4VPhysicalVolume* pCurrentPV = pPVModel->GetCurrentPV();
151 //G4LogicalVolume* pCurrentLV = pPVModel->GetCurrentLV();
152 //G4Material* pCurrentMaterial = pPVModel->GetCurrentMaterial();
153 // Note: pCurrentMaterial may be zero (parallel world).
154
155 // Find appropriate root
156 const size_t nWorlds = fpPhysicalVolumeObjects.size();
157 size_t iWorld = 0;
158 for (; iWorld < nWorlds; ++iWorld) {
159 if (fullPVPath[0].GetPhysicalVolume() ==
160 fpPhysicalVolumeObjects[iWorld]->GetPVNodeID().GetPhysicalVolume()) break;
161 }
162 if (iWorld == nWorlds) {
163 G4Exception("G4ToolsSGSceneHandler::GetOrCreateNode", "ToolsSG-0000", FatalException,
164 "World mis-match - not possible(!?)");
165 }
166
167 // (Re-)establish pv path of root entity
168 G4ToolsSGNode* _world = fpPhysicalVolumeObjects[iWorld];
169 _world->SetPVNodeID(fullPVPath[0]);
170
171 // Provide nodes as required - may be a new node or a pre-existing node
172 G4ToolsSGNode* node = _world; // Working variable - default to world
173 const size_t depth = fullPVPath.size();
174 size_t iDepth = 1;
175 while (iDepth < depth) {
176 const auto& children = node->children();
177 const G4int nChildren = (G4int)children.size();
178 G4int iChild = 0;
179 G4ToolsSGNode* child = nullptr;
180 for (; iChild < nChildren; ++iChild) {
181 child = static_cast<G4ToolsSGNode*>(children[iChild]);
182 if (child->GetPVNodeID() == fullPVPath[iDepth]) break;
183 }
184 if (iChild != nChildren) { // Existing node found
185 node = child; // Must be the ancestor of new node (subsequent iteration)
186 } else {
187 // Add a new node as child of node
188 G4ToolsSGNode* newNode = new G4ToolsSGNode;
189 node->add(newNode);
190 newNode->SetPVNodeID(fullPVPath[iDepth]);
191 node = newNode;
192 }
193 ++iDepth;
194 }
195 return node;
196}
197
199{
200 fpTransient2DObjects.clear();
201 fpPersistent2DObjects.clear();
202 fpTransient3DObjects.clear();
203 fpPersistent3DObjects.clear();
205}
206
208{
209 fpTransient2DObjects.clear();
210 fpTransient3DObjects.clear();
211}
212
214{
215 //G4cout << "debug : G4ToolsSGSceneHandler::AddPrimitive(const G4Polyline&) : \n" << a_polyline << G4endl;
216 if (a_polyline.size() == 0) return;
217
218 tools::sg::separator* parentNode = 0;
219 if(fProcessing2D) {
220 parentNode = new tools::sg::separator;
222 fpTransient2DObjects.add(parentNode);
223 } else {
224 fpPersistent2DObjects.add(parentNode);
225 }
226
227 } else {
228 parentNode = GetOrCreateNode();
229 if(!parentNode) return;
230
231 tools::sg::matrix* mtx = new tools::sg::matrix;
233 mtx->mtx.value().set_matrix(elem(0,0),elem(0,1),elem(0,2),elem(0,3),
234 elem(1,0),elem(1,1),elem(1,2),elem(1,3),
235 elem(2,0),elem(2,1),elem(2,2),elem(2,3),
236 0, 0, 0, 1);
237 parentNode->add(mtx);
238 }
239
240 {const auto& colour = GetColour(a_polyline);
241 tools::sg::rgba* mat = new tools::sg::rgba();
242 mat->color =
243 tools::colorf(float(colour.GetRed()),
244 float(colour.GetGreen()),
245 float(colour.GetBlue()),
246 float(colour.GetAlpha()));
247 parentNode->add(mat);}
248
249 {tools::sg::draw_style* ds = new tools::sg::draw_style;
250 ds->style = tools::sg::draw_lines;
251 ds->line_width = 1;
252 parentNode->add(ds);}
253
254 tools::sg::vertices* vtxs = new tools::sg::vertices;
255 vtxs->mode = tools::gl::line_strip(); //polyline
256 parentNode->add(vtxs);
257
258 {for (size_t i = 0; i < a_polyline.size(); ++i) {
259 vtxs->add(float(a_polyline[i].x()),float(a_polyline[i].y()),float(a_polyline[i].z()));
260 }}
261
262}
263
265{
266 //::printf("debug G4ToolsSGSceneHandler::AddPrimitive(const G4Polymarker&) : %lu, type %d\n",
267 // a_polymarker.size(),a_polymarker.GetMarkerType());
268 if (a_polymarker.size() == 0) return;
269 auto currentNode = GetOrCreateNode();
270 if (!currentNode) return; // Node not available
271
272 // Transformation
273 {tools::sg::matrix* mtx = new tools::sg::matrix;
275 mtx->mtx.value().set_matrix(elem(0,0),elem(0,1),elem(0,2),elem(0,3),
276 elem(1,0),elem(1,1),elem(1,2),elem(1,3),
277 elem(2,0),elem(2,1),elem(2,2),elem(2,3),
278 0, 0, 0, 1);
279 currentNode->add(mtx);}
280
281 {const auto& colour = GetColour(a_polymarker);
282 tools::sg::rgba* mat = new tools::sg::rgba();
283 mat->color =
284 tools::colorf(float(colour.GetRed()),
285 float(colour.GetGreen()),
286 float(colour.GetBlue()),
287 float(colour.GetAlpha()));
288 currentNode->add(mat);}
289
290 MarkerSizeType markerSizeType;
291 G4double markerSize = GetMarkerSize(a_polymarker, markerSizeType);
292
293 switch (a_polymarker.GetMarkerType()) {
294 default:
295 case G4Polymarker::dots:{
296 //::printf("debug : GB : Add Markers : +++++++++++++++++++++++++++++++++++++++++++ : dots\n");
297 tools::sg::draw_style* ds = new tools::sg::draw_style;
298 ds->style = tools::sg::draw_points;
299 ds->point_size = 1;
300 currentNode->add(ds);
301 tools::sg::vertices* vtxs = new tools::sg::vertices;
302 vtxs->mode = tools::gl::points();
303 {for (size_t i = 0; i < a_polymarker.size(); ++i) {
304 vtxs->add(float(a_polymarker[i].x()),float(a_polymarker[i].y()),float(a_polymarker[i].z()));
305 }}
306 currentNode->add(vtxs);
307 }break;
309 //::printf("debug : GB : Add Markers : +++++++++++++++++++++++++++++++++++++++++++ : circles\n");
310 {tools::sg::markers* markers = new tools::sg::markers;
311 G4double diameter = markerSize; // OK for "screen-size" (the usual case)
312 if (markerSizeType == G4VSceneHandler::world ) {
313 const G4double scale = 200.; // Roughly pixels per scene
314 diameter *= fpScene->GetExtent().GetExtentRadius()/scale;
315 }
316 markers->size = diameter;
317 markers->style = tools::sg::marker_circle_line;
318 for (size_t i = 0; i < a_polymarker.size(); ++i) {
319 markers->add(float(a_polymarker[i].x()),float(a_polymarker[i].y()),float(a_polymarker[i].z()));
320 }
321 currentNode->add(markers);}
322 }break;
324 //::printf("debug : GB : Add Markers : +++++++++++++++++++++++++++++++++++++++++++ : square\n");
325 {tools::sg::markers* markers = new tools::sg::markers;
326 G4double side = markerSize; // OK for "screen-size" (the usual case)
327 if (markerSizeType == G4VSceneHandler::world ) {
328 const G4double scale = 200.; // Roughly pixels per scene
329 side *= fpScene->GetExtent().GetExtentRadius()/scale;
330 }
331 markers->size = side;
332 markers->style = tools::sg::marker_square_line;
333 for (size_t i = 0; i < a_polymarker.size(); ++i) {
334 markers->add(float(a_polymarker[i].x()),float(a_polymarker[i].y()),float(a_polymarker[i].z()));
335 }
336 currentNode->add(markers);}
337 }break;
338 }
339}
340
342{
343 //::printf("debug : G4ToolsSGSceneHandler::AddPrimitive(const G4Text&) : 000 : \"%s\"\n",a_text.GetText().c_str());
344 //::printf("debug : G4ToolsSGSceneHandler::AddPrimitive(const G4Text&) : 2D ? %d\n",fProcessing2D);
345 auto pos = a_text.GetPosition();
346 //::printf("debug : Add Text : pos %g %g %g\n",pos.x(),pos.y(),pos.z());
347
348 tools::sg::separator* parentNode = 0;
349 if(fProcessing2D) {
350 parentNode = new tools::sg::separator;
352 fpTransient2DObjects.add(parentNode);
353 } else {
354 fpPersistent2DObjects.add(parentNode);
355 }
356
357 tools::sg::matrix* mtx = new tools::sg::matrix;
358 mtx->set_translate(pos.x(),pos.y(),pos.z());
359 parentNode->add(mtx);
360
361 } else {
362 parentNode = GetOrCreateNode();
363 if (!parentNode) return;
364
365 tools::sg::matrix* mtx = new tools::sg::matrix;
367 mtx->mtx.value().set_matrix(elem(0,0),elem(0,1),elem(0,2),elem(0,3),
368 elem(1,0),elem(1,1),elem(1,2),elem(1,3),
369 elem(2,0),elem(2,1),elem(2,2),elem(2,3),
370 0, 0, 0, 1);
371 parentNode->add(mtx);
372 }
373
374 MarkerSizeType sizeType;
375 G4double size = GetMarkerSize(a_text, sizeType);
376
377 {const auto& colour = GetTextColour(a_text);
378 tools::sg::rgba* mat = new tools::sg::rgba();
379 mat->color =
380 tools::colorf(float(colour.GetRed()),
381 float(colour.GetGreen()),
382 float(colour.GetBlue()),
383 float(colour.GetAlpha()));
384 parentNode->add(mat);}
385
386#ifdef TOOLS_USE_FREETYPE
387 toolx::sg::text_freetype_marker* text = new toolx::sg::text_freetype_marker;
388 text->add_embedded_font(tools::sg::font_lato_regular_ttf(),tools::font::lato_regular_ttf);
389 text->font = tools::sg::font_lato_regular_ttf();
390 text->front_face = tools::sg::winding_cw;
391//text->modeling = tools::sg::font_pixmap; //problem with Qt/GL. It slows rendering!
392#else
393 tools::sg::text_hershey_marker* text = new tools::sg::text_hershey_marker;
394//text->encoding.value(a_encoding);
395#endif
396 text->height = float(size); //pixels
397 text->strings.add(a_text.GetText());
398 {switch (a_text.GetLayout()) {
399 default:
400 case G4Text::left:
401 text->hjust = tools::sg::left;
402 break;
403 case G4Text::centre:
404 text->hjust = tools::sg::center;
405 break;
406 case G4Text::right:
407 text->hjust = tools::sg::right;
408 break;
409 }}
410//text->vjust.value(a_vjust);
411 parentNode->add(text);
412
413}
414
416{
417 G4Polymarker oneCircle(a_circle);
418 oneCircle.push_back(a_circle.GetPosition());
420 // Call this AddPrimitive to avoid re-doing sub-class code.
422}
423
425{
426 G4Polymarker oneSquare(a_square);
427 oneSquare.push_back(a_square.GetPosition());
429 // Call this AddPrimitive to avoid re-doing sub-class code.
431}
432
434{
435 if (a_polyhedron.GetNoFacets() == 0) return;
436
437 //::printf("debug : G4ToolsSGSceneHandler::AddPrimitive(const G4Polyhedron&) : %d\n",a_polyhedron.GetNoFacets());
438
440
441 // Roll out vertices and normals for the faces. Note that this means vertices
442 // are duplicated. For example a box has 8 vertices, but to define 6 faces
443 // you need 12 triangles and 36 vertices. If it was just a matter of vertices
444 // we could restrict the number to 8 and use the indices to define the
445 // triangles, but we also have to consider the normals. A vertex can be have
446 // more than one normal, depending on which face it is being used to define.
447 // So we roll out all the vertices and normals for each triangle.
448 std::vector<G4Point3D> vertices;
449 std::vector<G4Normal3D> normals;
450
451 // Also roll out edges (as lines) for wireframe. Avoid duplicate lines,
452 // including those that differ only in the order of vertices.
453 typedef std::pair<G4Point3D,G4Point3D> Line;
454 std::vector<Line> lines;
455 auto insertIfNew = [&lines](const Line& newLine) {
456// for (const auto& line: lines) {
457// if ((newLine.first==line.first && newLine.second==line.second) ||
458// (newLine.first==line.second && newLine.second==line.first))
459// return;
460// }
461 lines.push_back(newLine);
462 };
463
464 G4bool isAuxilaryEdgeVisible = fpViewer->GetViewParameters().IsAuxEdgeVisible();
465 G4bool notLastFace;
466 do {
467 G4int nEdges;
468 G4Point3D vertex [4];
469 G4int edgeFlag[4];
470 G4Normal3D normal [4];
471 notLastFace = a_polyhedron.GetNextFacet(nEdges, vertex, edgeFlag, normal);
472 vertices.push_back(vertex[0]);
473 vertices.push_back(vertex[1]);
474 vertices.push_back(vertex[2]);
475 normals.push_back(normal[0]);
476 normals.push_back(normal[1]);
477 normals.push_back(normal[2]);
478 if(isAuxilaryEdgeVisible||edgeFlag[0]>0)insertIfNew(Line(vertex[0],vertex[1]));
479 if(isAuxilaryEdgeVisible||edgeFlag[1]>0)insertIfNew(Line(vertex[1],vertex[2]));
480 if (nEdges == 3) {
481 // Face is a triangle
482 // One more line for wireframe, triangles for surfaces are complete
483 if(isAuxilaryEdgeVisible||edgeFlag[2]>0)insertIfNew(Line(vertex[2],vertex[0]));
484 } else if (nEdges == 4) {
485 // Face is a quadrilateral
486 // Create another triangle for surfaces, add two more lines for wireframe
487 vertices.push_back(vertex[2]);
488 vertices.push_back(vertex[3]);
489 vertices.push_back(vertex[0]);
490 normals.push_back(normal[2]);
491 normals.push_back(normal[3]);
492 normals.push_back(normal[0]);
493 if(isAuxilaryEdgeVisible||edgeFlag[2]>0)insertIfNew(Line(vertex[2],vertex[3]));
494 if(isAuxilaryEdgeVisible||edgeFlag[3]>0)insertIfNew(Line(vertex[3],vertex[0]));
495 } else {
496 G4cerr
497 << "ERROR: polyhedron face with unexpected number of edges (" << nEdges << ')'
498 << "\n Tag: " << fpModel->GetCurrentTag()
499 << G4endl;
500 return;
501 }
502 } while (notLastFace);
503
505 switch (drawing_style) {
507 //vertices.clear();
508 break;
510 break;
512 //lines.clear();
513 break;
515 break;
517 // Shouldn't happen in this function (it's a polyhedron!) - ignore
518 return;
519 }
520
521 auto currentNode = GetOrCreateNode();
522 if (!currentNode) return; // Node not available
523
524 tools::sg::separator* sep = new tools::sg::separator;
525 currentNode->add(sep);
526
527 // Transformation
528 {tools::sg::matrix* mtx = new tools::sg::matrix;
530 mtx->mtx.value().set_matrix(elem(0,0),elem(0,1),elem(0,2),elem(0,3),
531 elem(1,0),elem(1,1),elem(1,2),elem(1,3),
532 elem(2,0),elem(2,1),elem(2,2),elem(2,3),
533 0, 0, 0, 1);
534 sep->add(mtx);}
535
536 {const auto& colour = GetColour(a_polyhedron);
537 tools::sg::rgba* mat = new tools::sg::rgba();
538 mat->color =
539 tools::colorf(float(colour.GetRed()),
540 float(colour.GetGreen()),
541 float(colour.GetBlue()),
542 float(colour.GetAlpha()));
543 sep->add(mat);}
544
545 if (drawing_style == G4ViewParameters::hlr ||
546 drawing_style == G4ViewParameters::hsr ||
547 drawing_style == G4ViewParameters::hlhsr) {
548
549 {tools::sg::draw_style* ds = new tools::sg::draw_style;
550 ds->style = tools::sg::draw_filled;
551 //ds->cull_face = true;
552 sep->add(ds);}
553
554 tools::sg::atb_vertices* vtxs = new tools::sg::atb_vertices;
555 vtxs->mode = tools::gl::triangles();
556 sep->add(vtxs);
557
558 const auto nVerts = vertices.size();
559 for (size_t i = 0; i < nVerts; i++) {
560 vtxs->add(float(vertices[i].x()),float(vertices[i].y()),float(vertices[i].z()));
561 vtxs->add_normal(float(normals[i].x()),float(normals[i].y()),float(normals[i].z()));
562 }
563 }
564
565 if (drawing_style == G4ViewParameters::wireframe ||
566 drawing_style == G4ViewParameters::hlr ||
567 drawing_style == G4ViewParameters::hlhsr) {
568
569 {tools::sg::draw_style* ds = new tools::sg::draw_style;
570 ds->style = tools::sg::draw_lines;
571 ds->line_width = 1;
572 sep->add(ds);}
573
574 tools::sg::vertices* vtxs = new tools::sg::vertices;
575 vtxs->mode = tools::gl::lines(); //segments
576 sep->add(vtxs);
577
578 for (const auto& line: lines) {
579 vtxs->add(float(line.first.x()),float(line.first.y()),float(line.first.z()));
580 vtxs->add(float(line.second.x()),float(line.second.y()),float(line.second.z()));
581 }
582
583 }
584}
585
587{
589}
590
591//plotting:
592inline void SetRegionStyles(tools::xml::styles& a_styles,
593 tools::sg::plots& a_plots,
594 tools::sg::plotter& a_plotter,
595 const G4String& a_style) {
596 if(a_style=="reset") {
597 a_plotter.reset_style(true);
598 a_plots.touch(); //to apply indirectly plots::set_plotter_layout() on _plotter.
599 } else if( (a_style=="inlib_default")|| (a_style=="default")) {
600 tools::sg::set_inlib_default_style(G4cout,a_styles.cmaps(),a_plotter,tools::sg::font_hershey());
601 } else if(a_style=="ROOT_default") {
602 tools::sg::set_ROOT_default_style(G4cout,a_styles.cmaps(),a_plotter,tools::sg::font_roboto_bold_ttf());
603 } else if(a_style=="hippodraw") {
604 tools::sg::set_hippodraw_style(G4cout,a_styles.cmaps(),a_plotter,tools::sg::font_lato_regular_ttf());
605 } else {
606 tools::sg::style_from_res(a_styles,a_style,a_plotter,false);
607 }
608}
609
610inline tools::xml::styles::style_t* find_style(tools::xml::styles& a_styles,const std::string& a_name) {
611 tools_vforit(tools::xml::styles::named_style_t,a_styles.named_styles(),it){
612 if((*it).first==a_name) return &((*it).second);
613 }
614 return 0;
615}
616
617inline void SetPlotterStyles(tools::sg::plots& a_plots,
618 const std::vector<G4String>& a_plotter_styles,
619 const std::vector<G4Plotter::RegionStyle>& a_region_styles) {
620
622
623 tools::xml::styles _tools_styles(G4cout);
624 _tools_styles.add_colormap("default",tools::sg::style_default_colormap());
625 _tools_styles.add_colormap("ROOT",tools::sg::style_ROOT_colormap());
626
627 {tools_vforcit(G4PlotterManager::NamedStyle,_styles,it) {
628 tools::xml::styles::style_t _tools_style;
629 tools_vforcit(G4PlotterManager::StyleItem,(*it).second,its) {
630 const G4String& param = (*its).first;
631 if(param.find('.')==std::string::npos) {
632 const G4String& value = (*its).second;
633 _tools_style.push_back(tools::xml::styles::style_item_t(param,value));
634 }
635 }
636 _tools_styles.add_style((*it).first,_tools_style);
637 }}
638
639 // sub styles:
640 {tools_vforcit(G4PlotterManager::NamedStyle,_styles,it) {
641 tools_vforcit(G4PlotterManager::StyleItem,(*it).second,its) {
642 const G4String& param = (*its).first;
643 std::string::size_type pos = param.rfind('.');
644 if(pos!=std::string::npos) {
645 std::string sub_style = (*it).first+"."+param.substr(0,pos);
646 G4String parameter = param.substr(pos+1,param.size()-pos);
647 const G4String& value = (*its).second;
648 tools::xml::styles::style_t* _tools_style = find_style(_tools_styles,sub_style);
649 if(_tools_style) {
650 _tools_style->push_back(tools::xml::styles::style_item_t(parameter,value));
651 } else {
652 tools::xml::styles::style_t _tools_style_2;
653 _tools_style_2.push_back(tools::xml::styles::style_item_t(parameter,value));
654 _tools_styles.add_style(sub_style,_tools_style_2);
655 }
656 }
657 }
658 }}
659
660 {unsigned int number = a_plots.number();
661 for(unsigned int index=0;index<number;index++) {
662 tools::sg::plotter* _plotter = a_plots.find_plotter(index);
663 if(_plotter) {
664 tools_vforcit(G4String,a_plotter_styles,it) {
665 SetRegionStyles(_tools_styles,a_plots,*_plotter,*it);
666 }
667 }
668 }}
669 {tools_vforcit(G4Plotter::RegionStyle,a_region_styles,it) {
670 tools::sg::plotter* _plotter = a_plots.find_plotter((*it).first);
671 if(_plotter) {
672 SetRegionStyles(_tools_styles,a_plots,*_plotter,(*it).second);
673 }
674 }}
675}
676
677inline void SetPlotterParameters(tools::sg::cmaps_t& a_cmaps,tools::sg::plots& a_plots,
678 const std::vector<G4Plotter::RegionParameter>& a_region_parameters) {
679 // parameter/field examples :
680 // title_automated
681 // title
682 // bins_style.0.color
683 // x_axis.divisions
684 // x_axis.line_style.color
685 // background_style.back_color
686 tools_vforcit(G4Plotter::RegionParameter,a_region_parameters,it) {
687 tools::sg::plotter* _plotter = a_plots.find_plotter((*it).first);
688 if(_plotter) {
689 const G4String& parameter = (*it).second.first;
690 const G4String& value = (*it).second.second;
691 tools::sg::field* fd = _plotter->find_field_by_name(parameter);
692 if(!fd) fd = _plotter->find_field_by_name(_plotter->s_cls()+"."+parameter);
693 if(fd) {if(fd->s2value(value)) continue;}
694 // look for sf_enum for which value is given with a string, or
695 // for sf<bool> for which value given with true/false, or
696 // for a style, for example: bins_style.0.color:
697 if(!_plotter->set_from_string(G4cout,a_cmaps,parameter,value)) {
698 G4cout << "G4ToolsSGSceneHandler::SetPlotterParameters: plotter.set_from_string() failed for field "
699 << tools::sout(parameter) << ", and value " << tools::sout(value) << "."
700 << std::endl;
701 }
702 }
703 }
704}
705
706#include "G4UImanager.hh"
707
708void G4ToolsSGSceneHandler::SetPlotterHistograms(tools::sg::plots& a_plots) {
709 a_plots.clear();
711 if(UI==NULL) return;
712 {tools_vforcit(Region_h1,fRegionH1s,it) {
713 tools::sg::plotter* _plotter = a_plots.find_plotter((*it).first);
714 if(_plotter) {
715 int hid = (*it).second;
716 std::ostringstream os;
717 os << hid;
718 std::string cmd("/analysis/h1/get ");
719 cmd += std::string(os.str());
720 auto keepControlVerbose = UI->GetVerboseLevel();
721 UI->SetVerboseLevel(0);
722 G4int status = UI->ApplyCommand(cmd.c_str());
723 UI->SetVerboseLevel(keepControlVerbose);
724 if(status==G4UIcommandStatus::fCommandSucceeded) {
725 G4String hexString = UI->GetCurrentValues("/analysis/h1/get");
726 if(hexString.size()) {
727 void* ptr;
728 std::istringstream is(hexString);
729 is >> ptr;
730 tools::histo::h1d* _h = (tools::histo::h1d*)ptr;
731 tools::sg::plottable* p = new tools::sg::h1d2plot_cp(*_h);
732 _plotter->add_plottable(p); //give ownership of p to sg::plotter.
733 }
734 } else {
735 G4cerr <<
736 "G4ToolsSGSceneHandler::SetPlotterHistograms: cannot get histogram - maybe doesn't exist?"
737 "\n Maybe this app does not do analysis at all?"
738 << G4endl;
739 }
740 }
741 }}
742 {tools_vforcit(Region_h2,fRegionH2s,it) {
743 tools::sg::plotter* _plotter = a_plots.find_plotter((*it).first);
744 if(_plotter) {
745 int hid = (*it).second;
746 std::ostringstream os;
747 os << hid;
748 std::string cmd("/analysis/h2/get ");
749 cmd += std::string(os.str());
750 auto keepControlVerbose = UI->GetVerboseLevel();
751 UI->SetVerboseLevel(0);
752 G4int status = UI->ApplyCommand(cmd.c_str());
753 UI->SetVerboseLevel(keepControlVerbose);
754 if(status==G4UIcommandStatus::fCommandSucceeded) {
755 G4String hexString = UI->GetCurrentValues("/analysis/h2/get");
756 if(hexString.size()) {
757 void* ptr;
758 std::istringstream is(hexString);
759 is >> ptr;
760 tools::histo::h2d* _h = (tools::histo::h2d*)ptr;
761 tools::sg::plottable* p = new tools::sg::h2d2plot_cp(*_h);
762 _plotter->add_plottable(p); //give ownership of p to sg::plotter.
763 }
764 } else {
765 G4cerr <<
766 "G4ToolsSGSceneHandler::SetPlotterHistograms: cannot get histogram - maybe doesn't exist?"
767 "\n Maybe this app does not do analysis at all?"
768 << G4endl;
769 }
770 }
771 }}
772}
773
774class plots_cbk : public tools::sg::ecbk {
775 TOOLS_CBK(plots_cbk,plots_cbk,tools::sg::ecbk)
776public:
777 virtual tools::sg::return_action action() {
778 if(const tools::sg::size_event* sz_evt = tools::sg::event_cast<tools::sg::event,tools::sg::size_event>(*m_event)){
779 m_plots.adjust_size(sz_evt->width(),sz_evt->height());
780 m_event_action->set_done(true);
781 return tools::sg::return_to_render;
782 }
783 return tools::sg::return_none;
784 }
785public:
786 plots_cbk(tools::sg::plots& a_plots)
787 :parent()
788 ,m_plots(a_plots)
789 {}
790 virtual ~plots_cbk(){}
791public:
792 plots_cbk(const plots_cbk& a_from)
793 :parent(a_from)
794 ,m_plots(a_from.m_plots)
795 {}
797 parent::operator=(a_from);
798 return *this;
799 }
800protected:
801 tools::sg::plots& m_plots;
802};
803
804void G4ToolsSGSceneHandler::TouchPlotters(tools::sg::node& a_sg) {
805 tools::sg::search_action sa(G4cout);
806 const tools::sg::search_action::paths_t& paths = tools::sg::find_paths<tools::sg::plots>(sa,a_sg);
807 tools_vforcit(tools::sg::path_t,paths,it) {
808 tools::sg::plots* _plots = tools::sg::tail<tools::sg::plots>(*it);
809 if(_plots) {
810 SetPlotterHistograms(*_plots);
811 }
812 }
813}
814
816{
817//G4cout << "debug : G4ToolsSGSceneHandler::AddPrimitive : 004" << std::endl;
818 if(!fpViewer) return;
819
820 auto currentNode = GetOrCreateNode();
821 if (!currentNode) return; // Node not available
822
823 currentNode->add(new tools::sg::light_off());
824
825 tools::sg::plots* _plots = new tools::sg::plots(*fFreetypeNode);
826 currentNode->add(_plots);
827
828 _plots->view_border = false;
829 _plots->set_regions(a_plotter.GetColumns(),a_plotter.GetRows());
830
831 {tools::sg::event_dispatcher* dpt = new tools::sg::event_dispatcher;
832 dpt->add_callback(new plots_cbk(*_plots));
833 currentNode->add(dpt);}
834
835 SetPlotterStyles(*_plots,a_plotter.GetStyles(),a_plotter.GetRegionStyles());
836
837 tools::sg::cmaps_t _cmaps;
838 _cmaps["default"] = tools::sg::style_default_colormap();
839 _cmaps["ROOT"] = tools::sg::style_ROOT_colormap();
840
841 SetPlotterParameters(_cmaps,*_plots,a_plotter.GetRegionParameters());
842
843 fRegionH1s = a_plotter.GetRegionH1s();
844 fRegionH2s = a_plotter.GetRegionH2s();
845
846 SetPlotterHistograms(*_plots);
847}
848
851 if (!pSceneHandler) {
852 G4cout << "G4ToolsSGSceneHandler::Messenger::SetNewValue: no current sceneHandler. Please create one." << G4endl;
853 return;
854 }
855 auto* tsg_scene_handler = dynamic_cast<G4ToolsSGSceneHandler*>(pSceneHandler);
856 if(!tsg_scene_handler) {
857 G4cout << "G4ToolsSGSceneHandler::Messenger::SetNewValue: current sceneHandler not a G4ToolsSGSceneHandler." << G4endl;
858 return;
859 }
860 if(a_cmd==print_plotter_params) {
861 tools::sg::dummy_freetype _ttf;
862 tools::sg::plotter _plotter(_ttf);
863 _plotter.print_available_customization(G4cout);
864 }
865}
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
#define elem(i, j)
void SetPlotterParameters(tools::sg::cmaps_t &a_cmaps, tools::sg::plots &a_plots, const std::vector< G4Plotter::RegionParameter > &a_region_parameters)
void SetRegionStyles(tools::xml::styles &a_styles, tools::sg::plots &a_plots, tools::sg::plotter &a_plotter, const G4String &a_style)
tools::xml::styles::style_t * find_style(tools::xml::styles &a_styles, const std::string &a_name)
void SetPlotterStyles(tools::sg::plots &a_plots, const std::vector< G4String > &a_plotter_styles, const std::vector< G4Plotter::RegionStyle > &a_region_styles)
HepGeom::Translate3D G4Translate3D
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
G4GLOB_DLL std::ostream G4cerr
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
Definition: G4Mesh.hh:48
std::vector< NamedStyle > Styles
std::pair< G4String, Style > NamedStyle
std::pair< G4String, G4String > StyleItem
static G4PlotterManager & GetInstance()
const Styles & GetStyles() const
std::pair< unsigned int, G4String > RegionStyle
Definition: G4Plotter.hh:42
unsigned int GetRows() const
Definition: G4Plotter.hh:68
const std::vector< RegionParameter > & GetRegionParameters() const
Definition: G4Plotter.hh:71
const std::vector< G4String > & GetStyles() const
Definition: G4Plotter.hh:69
const std::vector< Region_h2 > & GetRegionH2s() const
Definition: G4Plotter.hh:76
const std::vector< RegionStyle > & GetRegionStyles() const
Definition: G4Plotter.hh:70
std::pair< unsigned int, Parameter > RegionParameter
Definition: G4Plotter.hh:44
const std::vector< Region_h1 > & GetRegionH1s() const
Definition: G4Plotter.hh:75
unsigned int GetColumns() const
Definition: G4Plotter.hh:67
void SetMarkerType(MarkerType)
MarkerType GetMarkerType() const
const G4VisExtent & GetExtent() const
Definition: G4Text.hh:72
Layout GetLayout() const
G4String GetText() const
@ centre
Definition: G4Text.hh:76
@ right
Definition: G4Text.hh:76
@ left
Definition: G4Text.hh:76
const G4PhysicalVolumeModel::G4PhysicalVolumeNodeID & GetPVNodeID() const
void SetPVNodeID(const G4PhysicalVolumeModel::G4PhysicalVolumeNodeID &id)
virtual void SetNewValue(G4UIcommand *, G4String)
void SetPlotterHistograms(tools::sg::plots &)
tools::sg::base_freetype * fFreetypeNode
virtual void AddCompound(const G4Mesh &)
virtual void AddPrimitive(const G4Polyline &)
std::vector< Region_h1 > fRegionH1s
tools::sg::separator fpPersistent2DObjects
std::pair< unsigned int, int > Region_h2
tools::sg::separator fpTransient3DObjects
tools::sg::separator * GetOrCreateNode()
tools::sg::separator fpTransient2DObjects
std::vector< Region_h2 > fRegionH2s
G4ToolsSGSceneHandler(G4VGraphicsSystem &system, const G4String &name)
std::vector< G4ToolsSGNode * > fpPhysicalVolumeObjects
void TouchPlotters(tools::sg::node &)
std::pair< unsigned int, int > Region_h1
tools::sg::separator fpPersistent3DObjects
static G4TransportationManager * GetTransportationManager()
std::vector< G4VPhysicalVolume * >::iterator GetWorldsIterator()
std::size_t GetNoWorlds() const
G4int ApplyCommand(const char *aCommand)
Definition: G4UImanager.cc:495
G4int GetVerboseLevel() const
Definition: G4UImanager.hh:200
G4String GetCurrentValues(const char *aCommand)
Definition: G4UImanager.cc:166
static G4UImanager * GetUIpointer()
Definition: G4UImanager.cc:77
void SetVerboseLevel(G4int val)
Definition: G4UImanager.hh:199
G4Point3D GetPosition() const
virtual G4String GetCurrentTag() const
Definition: G4VModel.cc:46
const G4Colour & GetTextColour(const G4Text &)
const G4Colour & GetColour()
G4Transform3D fObjectTransformation
G4double GetMarkerSize(const G4VMarker &, MarkerSizeType &)
G4VViewer * fpViewer
const G4VisAttributes * fpVisAttribs
G4ViewParameters::DrawingStyle GetDrawingStyle(const G4VisAttributes *)
void StandardSpecialMeshRendering(const G4Mesh &)
const G4VisAttributes * GetApplicableVisAttributes(const G4VisAttributes *) const
const G4ViewParameters & GetViewParameters() const
static G4VisManager * GetVisManager()
G4bool IsAuxEdgeVisible() const
G4double GetExtentRadius() const
Definition: G4VisExtent.cc:75
G4VSceneHandler * GetCurrentSceneHandler() const
const G4VisAttributes * GetVisAttributes() const
G4int GetNoFacets() const
G4bool GetNextFacet(G4int &n, G4Point3D *nodes, G4int *edgeFlags=nullptr, G4Normal3D *normals=nullptr) const
plots_cbk(const plots_cbk &a_from)
plots_cbk(tools::sg::plots &a_plots)
virtual tools::sg::return_action action()
plots_cbk & operator=(const plots_cbk &a_from)
tools::sg::plots & m_plots
G4bool IsMasterThread()
Definition: G4Threading.cc:124