Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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