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