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