00001
00002
00003 #include "VisGeant4/VisG4Core/interface/VisG4VisSceneHandler.h"
00004 #include "VisGeant4/VisG4Core/interface/VisG4VisTransform3D.h"
00005
00006 #include "Iguana/Inventor/interface/IgSoCube.h"
00007 #include "Iguana/Inventor/interface/IgSoG4Box.h"
00008 #include "Iguana/Inventor/interface/IgSoRotSolid.h"
00009 #include "Iguana/Inventor/interface/IgSoG4Trd.h"
00010 #include "Iguana/Inventor/interface/IgSoG4Trap.h"
00011
00012 #include <Inventor/nodes/SoCoordinate4.h>
00013 #include <Inventor/nodes/SoSeparator.h>
00014 #include <Inventor/nodes/SoDrawStyle.h>
00015 #include <Inventor/nodes/SoMaterial.h>
00016 #include <Inventor/nodes/SoCube.h>
00017 #include <Inventor/nodes/SoLineSet.h>
00018 #include <Inventor/nodes/SoPointSet.h>
00019 #include <Inventor/nodes/SoMarkerSet.h>
00020 #include <Inventor/nodes/SoSphere.h>
00021 #include <Inventor/nodes/SoFont.h>
00022 #include <Inventor/nodes/SoText2.h>
00023 #include <Inventor/nodes/SoFaceSet.h>
00024 #include <Inventor/nodes/SoNormalBinding.h>
00025 #include <Inventor/nodes/SoComplexity.h>
00026 #include <Inventor/nodes/SoNurbsSurface.h>
00027 #include <Inventor/nodes/SoTranslation.h>
00028 #include <Inventor/nodes/SoMatrixTransform.h>
00029 #include <Inventor/nodes/SoTransform.h>
00030
00031 #include <G4ThreeVector.hh>
00032 #include <G4Point3D.hh>
00033 #include <G4Normal3D.hh>
00034 #include <G4Transform3D.hh>
00035 #include <G4Polyline.hh>
00036 #include <G4Scale.hh>
00037 #include <G4Text.hh>
00038 #include <G4Circle.hh>
00039 #include <G4Square.hh>
00040 #include <G4Polyhedron.hh>
00041 #include <G4NURBS.hh>
00042 #include <G4Box.hh>
00043 #include <G4Tubs.hh>
00044 #include <G4Cons.hh>
00045 #include <G4Trap.hh>
00046 #include <G4Trd.hh>
00047 #include <G4Sphere.hh>
00048 #include <G4Para.hh>
00049 #include <G4Torus.hh>
00050 #include <G4Polycone.hh>
00051 #include <G4Polyhedra.hh>
00052 #include <G4VisAttributes.hh>
00053 #include <CLHEP/config/CLHEP.h>
00054
00055 #include <classlib/utils/DebugAids.h>
00056 #include <classlib/utils/Log.h>
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 static inline bool operator== (const G4Colour &x, const G4Colour &y)
00067 {
00068 float xrgba [4] = { x.GetRed (), x.GetGreen (), x.GetBlue (), x.GetAlpha () };
00069 float yrgba [4] = { y.GetRed (), y.GetGreen (), y.GetBlue (), y.GetAlpha () };
00070 for (unsigned i = 0; i < 4; ++i)
00071 if (xrgba [i] != yrgba [i])
00072 return false;
00073
00074 return true;
00075 }
00076
00077 static inline bool operator< (const G4Colour &x, const G4Colour &y)
00078 {
00079 float xrgba [4] = { x.GetRed (), x.GetGreen (), x.GetBlue (), x.GetAlpha () };
00080 float yrgba [4] = { y.GetRed (), y.GetGreen (), y.GetBlue (), y.GetAlpha () };
00081 for (unsigned i = 0; i < 4; ++i)
00082 if (xrgba [i] < yrgba [i])
00083 return true;
00084 else if (xrgba [i] > yrgba [i])
00085 return false;
00086
00087 return false;
00088 }
00089
00090
00091
00092
00093 VisG4VisSceneHandler *
00094 VisG4VisSceneHandler::instance (void)
00095 {
00096 static VisG4VisSceneHandler *instance = new VisG4VisSceneHandler;
00097 return instance;
00098 }
00099
00100
00101 VisG4VisSceneHandler::VisG4VisSceneHandler (void)
00102 : m_node (0),
00103 m_caching (false),
00104 m_cached (false),
00105 m_cacheNodes (0),
00106 m_cacheIndex (0),
00107 m_lines (new SoDrawStyle),
00108 m_solid (new SoDrawStyle),
00109 m_fallback (G4ViewParameters::polyhedron),
00110 m_bbox (0, .5),
00111 m_sides (24),
00112 m_fontSize (12)
00113 {
00114
00115 m_lines->ref ();
00116 m_solid->ref ();
00117 m_lines->style = SoDrawStyle::LINES;
00118 m_solid->style = SoDrawStyle::FILLED;
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 const char *cachingStr = getenv ("IGUANA_CACHING");
00143 m_caching = (! cachingStr
00144 || !strcmp (cachingStr, "1")
00145 || !strcmp (cachingStr, "on")
00146 || !strcmp (cachingStr, "yes"));
00147 }
00148
00149 void
00150 VisG4VisSceneHandler::defineFallback (RepStyle style)
00151 { m_fallback = style; }
00152
00153 void
00154 VisG4VisSceneHandler::defineBounds (G4VisExtent bbox)
00155 { m_bbox = bbox; }
00156
00157 void
00158 VisG4VisSceneHandler::defineNoOfSides (int sides)
00159 { m_sides = sides; }
00160
00164 void
00165 VisG4VisSceneHandler::enableCache (bool enabled)
00166 {
00167 cacheEnd ();
00168 if (! (m_caching = enabled))
00169 clearCache ();
00170 }
00171
00172 void
00173 VisG4VisSceneHandler::clearCache (void)
00174 {
00175 cacheEnd ();
00176 while (! m_shapeCache.empty ())
00177 {
00178 m_shapeCache.begin ()->second->unref ();
00179 m_shapeCache.erase (m_shapeCache.begin ());
00180 }
00181 while (! m_materialCache.empty ())
00182 {
00183 m_materialCache.begin ()->second->unref ();
00184 m_materialCache.erase (m_materialCache.begin ());
00185 }
00186 }
00187
00188 void
00189 VisG4VisSceneHandler::cacheBegin (const void *object)
00190 {
00191 cacheEnd ();
00192 if (m_caching && object)
00193 {
00194 ASSERT (object);
00195 if (! m_shapeCache.count (object))
00196 {
00197 m_shapeCache [object] = m_cacheNodes = new SoGroup;
00198 m_cacheNodes->ref ();
00199 }
00200 else
00201 {
00202 m_cacheNodes = m_shapeCache [object];
00203 m_cached = true;
00204 }
00205 }
00206 }
00207
00208 bool
00209 VisG4VisSceneHandler::cached (void)
00210 {
00211 if (m_cached)
00212 {
00213 ASSERT (m_node);
00214 ASSERT (m_cacheNodes);
00215 ASSERT (m_cacheIndex < m_cacheNodes->getNumChildren ());
00216 m_node->addChild (m_cacheNodes->getChild (m_cacheIndex));
00217 m_cacheIndex++;
00218 return true;
00219 }
00220 else
00221 return false;
00222 }
00223
00224 void
00225 VisG4VisSceneHandler::cache (SoNode *node)
00226 {
00227 if (m_cacheNodes)
00228 {
00229 m_cacheNodes->addChild (node);
00230 m_cacheIndex++;
00231 }
00232 }
00233
00234 void
00235 VisG4VisSceneHandler::cacheEnd (void)
00236 {
00237 m_cached = false;
00238 m_cacheNodes = 0;
00239 m_cacheIndex = 0;
00240 }
00241
00245 void
00246 VisG4VisSceneHandler::beginObject (SoSeparator *node, const void *object)
00247 {
00248
00249 ASSERT (! m_node);
00250 ASSERT (node);
00251 m_node = node;
00252
00253
00254 cacheBegin (object);
00255 }
00256
00257 void
00258 VisG4VisSceneHandler::endObject (void)
00259 {
00260 ASSERT (m_node);
00261 cacheEnd ();
00262 m_node = 0;
00263 }
00264
00268 void
00269 VisG4VisSceneHandler::addStyle (const G4VisAttributes *from)
00270 {
00271
00272 ASSERT (from);
00273 addStyle (GetDrawingStyle (from));
00274
00275 }
00276
00277 void
00278 VisG4VisSceneHandler::addStyle (DrawStyle style)
00279 {
00280 ASSERT (m_node);
00281
00282 switch (style)
00283 {
00284 case G4ViewParameters::hlr:
00285 case G4ViewParameters::wireframe:
00286 m_node->addChild (m_lines);
00287 break;
00288
00289 case G4ViewParameters::hlhsr:
00290 case G4ViewParameters::hsr:
00291 default:
00292 m_node->addChild (m_solid);
00293 break;
00294 }
00295 }
00296
00297 void
00298 VisG4VisSceneHandler::addMaterial (SoMaterial *mat)
00299 {
00300 ASSERT (mat);
00301 ASSERT (m_node);
00302
00303 m_node->addChild (mat);
00304 }
00305
00306 void
00307 VisG4VisSceneHandler::addTransform (const G4Transform3D &by)
00308 {
00309 ASSERT (m_node);
00310
00311
00312 SbMatrix scale;
00313 scale.setScale (1./m);
00314
00315 SoMatrixTransform *xform = new SoMatrixTransform;
00316 xform->matrix.setValue (scale * VisG4VisTransform3D (by));
00317 m_node->addChild (xform);
00318 }
00319
00323 void
00324 VisG4VisSceneHandler::addTranslation (SoSeparator *to, const G4Point3D ¢er)
00325 {
00326 ASSERT (to);
00327
00328 SoTranslation *t = new SoTranslation;
00329 t->translation.setValue (center.x (), center.y (), center.z ());
00330 to->addChild (t);
00331 }
00332
00333 void
00334 VisG4VisSceneHandler::addTranslation (SoSeparator *to, SbVec3f center)
00335 {
00336 ASSERT (to);
00337
00338 SoTranslation *t = new SoTranslation;
00339 t->translation = center;
00340 to->addChild (t);
00341 }
00342
00346 void
00347 VisG4VisSceneHandler::AddSolid (const G4Box &solid)
00348 {
00349 ASSERT (m_node);
00350 if (cached ()) return;
00351
00352
00353
00354
00355
00356
00357 IgSoCube *rep = new IgSoCube;
00358 rep->width = 2 * solid.GetXHalfLength ();
00359 rep->length = 2 * solid.GetYHalfLength ();
00360 rep->thickness = 2 * solid.GetZHalfLength ();
00361
00362 m_node->addChild (rep);
00363 cache (rep);
00364 }
00365
00366 void
00367 VisG4VisSceneHandler::AddSolid (const G4Cons &solid)
00368 {
00369 ASSERT (m_node);
00370 if (cached ()) return;
00371
00372 IgSoRotSolid *rep = new IgSoRotSolid;
00373
00374 rep->makeCons (solid.GetRmin1 (),
00375 solid.GetRmax1 (),
00376 solid.GetRmin2 (),
00377 solid.GetRmax2 (),
00378 solid.GetDz (),
00379 solid.GetSPhi (),
00380 solid.GetDPhi ());
00381
00382 m_node->addChild (rep);
00383 cache (rep);
00384 }
00385
00386 void
00387 VisG4VisSceneHandler::AddSolid (const G4Tubs &solid)
00388 {
00389 ASSERT (m_node);
00390 if (cached ()) return;
00391
00392 IgSoRotSolid *rep = new IgSoRotSolid;
00393
00394 rep->makeTubs (solid.GetRMin (),
00395 solid.GetRMax (),
00396 solid.GetDz (),
00397 solid.GetSPhi (),
00398 solid.GetDPhi ());
00399 m_node->addChild (rep);
00400 cache (rep);
00401 }
00402
00403 void
00404 VisG4VisSceneHandler::AddSolid (const G4Trd &solid)
00405 {
00406 ASSERT (m_node);
00407 if (cached ()) return;
00408
00409 IgSoG4Trd *rep = new IgSoG4Trd;
00410 rep->dx1 = solid.GetXHalfLength1 ();
00411 rep->dx2 = solid.GetXHalfLength2 ();
00412 rep->dy1 = solid.GetYHalfLength1 ();
00413 rep->dy2 = solid.GetYHalfLength2 ();
00414 rep->dz = solid.GetZHalfLength ();
00415 m_node->addChild (rep);
00416 cache (rep);
00417 }
00418
00419 void
00420 VisG4VisSceneHandler::AddSolid (const G4Trap &solid)
00421 {
00422 ASSERT (m_node);
00423 if (cached ()) return;
00424
00425 G4ThreeVector axis = solid.GetSymAxis ();
00426 IgSoG4Trap *rep = new IgSoG4Trap;
00427 rep->phi = atan2 (axis (kYAxis), axis (kXAxis));
00428 rep->theta = acos (axis (kZAxis));
00429 rep->dz = solid.GetZHalfLength ();
00430 rep->dy1 = solid.GetYHalfLength1 ();
00431 rep->dx1 = solid.GetXHalfLength1 ();
00432 rep->dx2 = solid.GetXHalfLength2 ();
00433 rep->alp1 = solid.GetTanAlpha1 ();
00434 rep->dy2 = solid.GetYHalfLength2 ();
00435 rep->dx3 = solid.GetXHalfLength3 ();
00436 rep->dx4 = solid.GetXHalfLength4 ();
00437 rep->alp2 = solid.GetTanAlpha2 ();
00438 m_node->addChild (rep);
00439 cache (rep);
00440 }
00441
00442 void
00443 VisG4VisSceneHandler::AddSolid (const G4Sphere &solid)
00444 { RequestPrimitives (solid); }
00445
00446 void
00447 VisG4VisSceneHandler::AddSolid (const G4Para &solid)
00448 { RequestPrimitives (solid); }
00449
00450 void
00451 VisG4VisSceneHandler::AddSolid (const G4Torus &solid)
00452 { RequestPrimitives (solid); }
00453
00454 void
00455 VisG4VisSceneHandler::AddSolid (const G4Polycone &solid)
00456 {
00457 ASSERT (m_node);
00458 if (cached ()) return;
00459
00460 int nr = solid.GetNumRZCorner();
00461 std::vector<SbVec2f> polygon (nr);
00462
00463 for (int i = 0; i < nr; ++i)
00464 polygon[i] = SbVec2f (solid.GetCorner (i).r, solid.GetCorner (i).z);
00465
00466 IgSoRotSolid *rep = new IgSoRotSolid;
00467 rep->phiStart = solid.GetStartPhi ();
00468 rep->phiDelta = solid.GetEndPhi () - solid.GetStartPhi ();
00469 rep->smooth = true;
00470 rep->polygon.setValues (0, nr, &polygon[0]);
00471
00472 m_node->addChild (rep);
00473 cache (rep);
00474 }
00475
00476 void
00477 VisG4VisSceneHandler::AddSolid (const G4Polyhedra &solid)
00478 {
00479 ASSERT (m_node);
00480 if (cached ()) return;
00481
00482 int nr = solid.GetNumRZCorner();
00483 std::vector<SbVec2f> polygon (nr);
00484
00485 for (int i = 0; i < nr; ++i)
00486 polygon[i] = SbVec2f (solid.GetCorner (i).r, solid.GetCorner (i).z);
00487
00488 IgSoRotSolid *rep = new IgSoRotSolid;
00489 rep->phiStart = solid.GetStartPhi ();
00490 (solid.GetEndPhi () == solid.GetStartPhi ()) ? rep->phiDelta = 2 * M_PI :
00491 rep->phiDelta = solid.GetEndPhi () - solid.GetStartPhi ();
00492 rep->divisions = solid.GetNumSide ();
00493 rep->smooth = false;
00494 rep->polygon.setValues (0, nr, &polygon[0]);
00495
00496 m_node->addChild (rep);
00497 cache (rep);
00498 }
00499
00500 void
00501 VisG4VisSceneHandler::AddSolid (const G4VSolid &solid)
00502 {
00503
00504
00505
00506 if (const G4Polycone *pcon = dynamic_cast<const G4Polycone *> (&solid))
00507 AddSolid (*pcon);
00508 else if (const G4Polyhedra *pgon = dynamic_cast<const G4Polyhedra *> (&solid))
00509 AddSolid (*pgon);
00510 else
00511 RequestPrimitives (solid);
00512 }
00513
00514 void
00515 VisG4VisSceneHandler::AddCompound (const G4VTrajectory & )
00516 {
00517 }
00518
00519 void
00520 VisG4VisSceneHandler::AddCompound (const G4VHit & )
00521 {
00522 }
00523
00527 void
00528 VisG4VisSceneHandler::AddPrimitive (const G4Polyline &object)
00529 {
00530 ASSERT (m_node);
00531 if (cached ()) return;
00532
00533 SoSeparator *me = new SoSeparator;
00534 m_node->addChild (me);
00535
00536
00537 me->addChild (m_lines);
00538
00539
00540 std::vector<SbVec3f> points (object.size (), SbVec3f ());
00541 for (unsigned i = 0; i < object.size (); ++i)
00542 points [i].setValue (object [i].x(), object [i].y(), object [i].z());
00543
00544 SoLineSet *lines = new SoLineSet;
00545 SoVertexProperty *vtx = new SoVertexProperty;
00546 vtx->vertex.setValues (0, object.size (), &points[0]);
00547 lines->numVertices = object.size ();
00548 lines->vertexProperty = vtx;
00549 me->addChild (lines);
00550 cache (me);
00551 }
00552
00553 void
00554 VisG4VisSceneHandler::AddPrimitive (const G4Scale &object)
00555 {
00556
00557
00558
00559
00560
00561 double length = object.GetLength ();
00562 double halfLength = length / 2;
00563 double tickLength = length / 20;
00564 double piBy2 = M_PI / 2;
00565
00566
00567 double xmin = m_bbox.GetXmin ();
00568 double xmax = m_bbox.GetXmax ();
00569 double ymin = m_bbox.GetYmin ();
00570 double ymax = m_bbox.GetYmax ();
00571 double zmin = m_bbox.GetZmin ();
00572 double zmax = m_bbox.GetZmax ();
00573
00574
00575
00576
00577 G4Polyline scaleLine, tick11, tick12, tick21, tick22;
00578 G4Point3D r1 (-halfLength, 0, 0);
00579 G4Point3D r2 ( halfLength, 0, 0);
00580 G4Point3D ticky (0, tickLength, 0);
00581 G4Point3D tickz (0, 0, tickLength);
00582
00583 scaleLine.push_back (r1);
00584 scaleLine.push_back (r2);
00585 tick11.push_back (r1 + ticky);
00586 tick11.push_back (r1 - ticky);
00587 tick12.push_back (r1 + tickz);
00588 tick12.push_back (r1 - tickz);
00589 tick21.push_back (r2 + ticky);
00590 tick21.push_back (r2 - ticky);
00591 tick22.push_back (r2 + tickz);
00592 tick22.push_back (r2 - tickz);
00593
00594
00595 G4Text text (object.GetAnnotation(), G4Point3D (0., tickLength, 0.));
00596 text.SetScreenSize (24.);
00597
00598
00599 G4Transform3D rotation;
00600 switch (object.GetDirection ()) {
00601 case G4Scale::x: break;
00602 case G4Scale::y: rotation = G4RotateZ3D (piBy2); break;
00603 case G4Scale::z: rotation = G4RotateY3D (piBy2); break;
00604 }
00605
00606 G4double sxmid (object.GetXmid ());
00607 G4double symid (object.GetYmid ());
00608 G4double szmid (object.GetZmid ());
00609
00610 if (object.GetAutoPlacing ()) {
00611
00612 double lomargin = 0.01;
00613 double himargin = 1 - lomargin;
00614
00615 sxmid = xmin + himargin * (xmax - xmin);
00616 symid = ymin + lomargin * (ymax - ymin);
00617 szmid = zmin + himargin * (zmax - zmin);
00618 switch (object.GetDirection ()) {
00619 case G4Scale::x: sxmid -= halfLength; break;
00620 case G4Scale::y: symid += halfLength; break;
00621 case G4Scale::z: szmid -= halfLength; break;
00622 }
00623 }
00624
00625
00626 SoSeparator *node = m_node;
00627 m_node = new SoSeparator;
00628 addTransform (G4Transform3D (G4Translate3D(sxmid,symid,szmid) * rotation));
00629 AddPrimitive (scaleLine);
00630 AddPrimitive (tick11);
00631 AddPrimitive (tick12);
00632 AddPrimitive (tick21);
00633 AddPrimitive (tick22);
00634 AddPrimitive (text);
00635 m_node = node;
00636 }
00637
00638 void
00639 VisG4VisSceneHandler::AddPrimitive (const G4Text &object)
00640 {
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651 ASSERT (m_node);
00652 if (cached ()) return;
00653
00654 SoSeparator *me = new SoSeparator;
00655 m_node->addChild (me);
00656
00657
00658 addTranslation (me, object.GetPosition ());
00659
00660
00661
00662
00663
00664
00665 double size = object.GetScreenSize ();
00666 SoFont *font = new SoFont;
00667 font->size = size ? size : m_fontSize;
00668 me->addChild (font);
00669
00670
00671 SoText2 *text = new SoText2;
00672 text->string.setValue (object.GetText ());
00673 switch (object.GetLayout ()) {
00674 case G4Text::left: text->justification = SoText2::LEFT; break;
00675 case G4Text::centre: text->justification = SoText2::CENTER; break;
00676 case G4Text::right: text->justification = SoText2::RIGHT; break;
00677 }
00678 me->addChild (text);
00679 cache (me);
00680 }
00681
00682 void
00683 VisG4VisSceneHandler::AddPrimitive (const G4Circle &object)
00684 {
00685
00686
00687
00688
00689
00690 ASSERT (m_node);
00691 if (cached ()) return;
00692
00693 SoSeparator *me = new SoSeparator;
00694 m_node->addChild (me);
00695
00696 MarkerSizeType type;
00697 G4VMarker::FillStyle fill = object.GetFillStyle ();
00698 G4ThreeVector pos (object.GetPosition ());
00699 double size = GetMarkerSize (object, type);
00700 SoMarkerSet *mset;
00701 SoVertexProperty *vtx;
00702
00703 switch (type)
00704 {
00705 case screen:
00706
00707
00708
00709 mset = makeScreenMarker (G4Polymarker::circles, fill, size);
00710 vtx = new SoVertexProperty;
00711 vtx->vertex.setValue (SbVec3f (pos.x (), pos.y (), pos.z ()));
00712 mset->vertexProperty = vtx;
00713 mset->numPoints = 1;
00714 me->addChild (mset);
00715 break;
00716
00717 case world:
00718
00719
00720
00721
00722
00723
00724
00725
00726 if (fill != G4VMarker::filled)
00727 me->addChild (m_lines);
00728 addTranslation (me, pos);
00729 me->addChild (makeWorldMarker (G4Polymarker::circles, size));
00730 break;
00731 }
00732 cache (me);
00733 }
00734
00735 void
00736 VisG4VisSceneHandler::AddPrimitive (const G4Square &object)
00737 {
00738
00739
00740
00741
00742
00743
00744 ASSERT (m_node);
00745 if (cached ()) return;
00746
00747 SoSeparator *me = new SoSeparator;
00748 m_node->addChild (me);
00749
00750 MarkerSizeType type;
00751 G4VMarker::FillStyle fill = object.GetFillStyle ();
00752 G4ThreeVector pos (object.GetPosition ());
00753 double size = GetMarkerSize (object, type);
00754 SoMarkerSet *mset;
00755 SoVertexProperty *vtx;
00756
00757 switch (type)
00758 {
00759 case screen:
00760
00761
00762
00763 mset = makeScreenMarker (G4Polymarker::squares, fill, size);
00764 vtx = new SoVertexProperty;
00765 vtx->vertex.setValue (SbVec3f (pos.x (), pos.y (), pos.z ()));
00766 mset->vertexProperty = vtx;
00767 mset->numPoints = 1;
00768 me->addChild (mset);
00769 break;
00770
00771 case world:
00772
00773
00774
00775
00776
00777
00778
00779
00780 if (fill != G4VMarker::filled)
00781 me->addChild (m_lines);
00782 addTranslation (me, pos);
00783 me->addChild (makeWorldMarker (G4Polymarker::squares, size));
00784 break;
00785 }
00786 cache (me);
00787 }
00788
00789 void
00790 VisG4VisSceneHandler::AddPrimitive (const G4Polyhedron &object)
00791 {
00792 ASSERT (m_node);
00793 if (! object.GetNoFacets () || cached ())
00794 return;
00795
00796
00797 G4bool notLastFace;
00798 std::vector<SbVec3f> vertices;
00799 std::vector<SbVec3f> normals;
00800 std::vector<G4int> nfaces;
00801 G4Normal3D normal;
00802 do {
00803 notLastFace = object.GetNextUnitNormal (normal);
00804 normals.push_back (SbVec3f (normal.x (), normal.y (), normal.z ()));
00805
00806 G4int faces = 0;
00807 G4bool notLastEdge;
00808 G4Point3D vertex;
00809 G4int edgeFlag = 1;
00810
00811 do {
00812 notLastEdge = object.GetNextVertex (vertex, edgeFlag);
00813 vertices.push_back (SbVec3f (vertex.x(), vertex.y(), vertex.z()));
00814 faces++;
00815 } while (notLastEdge);
00816
00817 nfaces.push_back (faces);
00818 } while (notLastFace);
00819
00820
00821 SoSeparator *me = new SoSeparator;
00822 m_node->addChild (me);
00823
00824
00825 SoFaceSet *faces = new SoFaceSet;
00826 SoVertexProperty *vtx = new SoVertexProperty;
00827
00828 vtx->normalBinding = SoNormalBinding::PER_FACE;
00829 vtx->normal.setValues (0, normals.size (), &normals[0]);
00830 vtx->vertex.setValues (0, vertices.size (), &vertices[0]);
00831 faces->numVertices.setValues (0, nfaces.size (), &nfaces[0]);
00832 faces->vertexProperty = vtx;
00833 me->addChild (faces);
00834 cache (me);
00835 }
00836
00837 void
00838 VisG4VisSceneHandler::AddPrimitive (const G4NURBS &nurb)
00839 {
00840
00841 ASSERT (m_node);
00842 ASSERT (G4NURBS::NofC == 4);
00843 if (cached ()) return;
00844
00845
00846 std::vector<G4float> uknots (nurb.GetnbrKnots(G4NURBS::U), 0.);
00847 std::vector<G4float> vknots (nurb.GetnbrKnots(G4NURBS::V), 0.);
00848 std::vector<G4float> ctrls (nurb.GettotalnbrCtrlPts () * G4NURBS::NofC,0.);
00849
00850 G4NURBS::KnotsIterator u (nurb, G4NURBS::U);
00851 for (int i = 0; u.pick (&uknots [i]); i++)
00852 ;
00853
00854 G4NURBS::KnotsIterator v (nurb, G4NURBS::V);
00855 for (int i = 0; v.pick (&vknots [i]); i++)
00856 ;
00857
00858 G4NURBS::CtrlPtsCoordsIterator c (nurb);
00859 for (int i = 0; c.pick (&ctrls [i]); i++)
00860 ;
00861
00862
00863 SoSeparator *me = new SoSeparator;
00864 m_node->addChild (me);
00865
00866
00867 G4int n = nurb.GettotalnbrCtrlPts ();
00868 std::vector<SbVec4f> points (n, SbVec4f ());
00869 for (G4int i = 0, j = 0; i < n ; ++i, j += 4)
00870 points [i].setValue (ctrls[j+0], ctrls[j+1], ctrls[j+2], ctrls[j+3]);
00871
00872 SoComplexity *complexity = new SoComplexity;
00873 complexity->value = 0.6;
00874 me->addChild (complexity);
00875
00876 SoCoordinate4 *controls = new SoCoordinate4;
00877 controls->point.setValues (0, n, &points[0]);
00878 me->addChild (controls);
00879
00880 SoNurbsSurface *surface = new SoNurbsSurface;
00881 surface->numUControlPoints = uknots.size ();
00882 surface->numVControlPoints = vknots.size ();
00883 surface->uKnotVector.setValues (0,uknots.size (), &uknots [0]);
00884 surface->vKnotVector.setValues (0,vknots.size (), &vknots [0]);
00885 me->addChild (surface);
00886 cache (me);
00887 }
00888
00889 void
00890 VisG4VisSceneHandler::AddPrimitive (const G4Polymarker &object)
00891 {
00892 ASSERT (m_node);
00893 if (cached ()) return;
00894
00895 SoSeparator *me = new SoSeparator;
00896 m_node->addChild (me);
00897
00898
00899 addTranslation (me, object.GetPosition ());
00900
00901
00902 std::vector<SbVec3f> points (object.size (), SbVec3f ());
00903 for (unsigned i = 0; i < object.size (); ++i)
00904 points [i].setValue (object [i].x(),
00905 object [i].y(),
00906 object [i].z());
00907
00908
00909 MarkerSizeType type;
00910 G4VMarker::FillStyle fill = object.GetFillStyle ();
00911 double size = GetMarkerSize (object, type);
00912 SoPointSet *pset;
00913 SoMarkerSet *mset;
00914 SoVertexProperty *vtx;
00915 SoShape *shape;
00916 SbVec3f last (0, 0, 0);
00917
00918
00919 switch (object.GetMarkerType ())
00920 {
00921 default:
00922 case G4Polymarker::dots:
00923
00924 vtx = new SoVertexProperty;
00925 vtx->vertex.setValues (0, object.size (), &points[0]);
00926 pset = new SoPointSet;
00927 pset->numPoints = object.size ();
00928 pset->vertexProperty = vtx;
00929 me->addChild (pset);
00930 break;
00931
00932 case G4Polymarker::circles:
00933 case G4Polymarker::squares:
00934
00935 switch (type)
00936 {
00937 case screen:
00938 vtx = new SoVertexProperty;
00939 vtx->vertex.setValues (0, object.size (), &points[0]);
00940 mset = makeScreenMarker (object.GetMarkerType (), fill, size);
00941 mset->numPoints = object.size ();
00942 mset->vertexProperty = vtx;
00943 me->addChild (mset);
00944 break;
00945
00946 case world:
00947 if (fill != G4VMarker::filled)
00948 me->addChild (m_lines);
00949 shape = makeWorldMarker (object.GetMarkerType (), size);
00950 for (unsigned i = 0; i < object.size (); last = points [i++])
00951 {
00952 addTranslation (me, points [i] - last);
00953 me->addChild (shape);
00954 }
00955 break;
00956 }
00957 break;
00958 }
00959 cache (me);
00960 }
00961
00965 SoMarkerSet *
00966 VisG4VisSceneHandler::makeScreenMarker (G4Polymarker::MarkerType type,
00967 G4VMarker::FillStyle fill,
00968 double size)
00969 {
00970
00971
00972
00973
00974
00975
00976
00977 SoMarkerSet *mset = new SoMarkerSet;
00978 switch (type)
00979 {
00980 case G4Polymarker::circles:
00981 switch (fill)
00982 {
00983 case G4VMarker::noFill:
00984 mset->markerIndex
00985 = size <= 2.5 ? SoMarkerSet::CIRCLE_LINE_5_5
00986 : size <= 3.5 ? SoMarkerSet::CIRCLE_LINE_7_7
00987 : SoMarkerSet::CIRCLE_LINE_9_9;
00988 break;
00989
00990 case G4VMarker::hashed:
00991 mset->markerIndex
00992 = size <= 2.5 ? SoMarkerSet::STAR_5_5
00993 : size <= 3.5 ? SoMarkerSet::STAR_7_7
00994 : SoMarkerSet::STAR_9_9;
00995 break;
00996
00997 case G4VMarker::filled:
00998 mset->markerIndex
00999 = size <= 2.5 ? SoMarkerSet::CIRCLE_FILLED_5_5
01000 : size <= 3.5 ? SoMarkerSet::CIRCLE_FILLED_7_7
01001 : SoMarkerSet::CIRCLE_FILLED_9_9;
01002 break;
01003 }
01004 return mset;
01005
01006 case G4Polymarker::squares:
01007 switch (fill)
01008 {
01009 case G4VMarker::noFill:
01010 mset->markerIndex
01011 = size <= 2.5 ? SoMarkerSet::SQUARE_LINE_5_5
01012 : size <= 3.5 ? SoMarkerSet::SQUARE_LINE_7_7
01013 : SoMarkerSet::SQUARE_LINE_9_9;
01014 break;
01015
01016 case G4VMarker::hashed:
01017 mset->markerIndex
01018 = size <= 2.5 ? SoMarkerSet::CROSS_5_5
01019 : size <= 3.5 ? SoMarkerSet::CROSS_7_7
01020 : SoMarkerSet::CROSS_9_9;
01021 break;
01022
01023 case G4VMarker::filled:
01024 mset->markerIndex
01025 = size <= 2.5 ? SoMarkerSet::SQUARE_FILLED_5_5
01026 : size <= 3.5 ? SoMarkerSet::SQUARE_FILLED_7_7
01027 : SoMarkerSet::SQUARE_FILLED_9_9;
01028 break;
01029 }
01030 return mset;
01031
01032 default:
01033 ASSERT (false);
01034 return 0;
01035 }
01036 }
01037
01038 SoShape *
01039 VisG4VisSceneHandler::makeWorldMarker (G4Polymarker::MarkerType type, double size)
01040 {
01041 SoSphere *sphere;
01042 SoCube *cube;
01043
01044 switch (type)
01045 {
01046 case G4Polymarker::circles:
01047 sphere = new SoSphere;
01048 sphere->radius = size;
01049 return sphere;
01050
01051 case G4Polymarker::squares:
01052 cube = new SoCube;
01053 cube->width = size * 2;
01054 cube->height = size * 2;
01055 cube->depth = size * 2;
01056 return cube;
01057
01058 default:
01059 ASSERT (false);
01060 return 0;
01061 }
01062 }
01063
01067 double
01068 VisG4VisSceneHandler::GetMarkerSize (const G4VMarker &marker,
01069 MarkerSizeType &type)
01070 {
01071
01072 double size = marker.GetWorldSize ();
01073
01074 if (size)
01075
01076 type = world;
01077 else
01078 {
01079
01080 size = marker.GetScreenSize ();
01081 type = screen;
01082 }
01083
01084 return (size <= 0. ? 1. : size);
01085
01086 }
01087
01091 void
01092 VisG4VisSceneHandler::RequestPrimitives (const G4VSolid &solid)
01093 {
01094 if (m_fallback == G4ViewParameters::nurbs)
01095 if (G4NURBS *nurb = solid.CreateNURBS ())
01096 {
01097 AddPrimitive (*nurb);
01098 delete nurb;
01099 return;
01100 }
01101
01102
01103 G4Polyhedron::SetNumberOfRotationSteps (m_sides);
01104 if (G4Polyhedron *polyh = solid.CreatePolyhedron ())
01105 {
01106 AddPrimitive (*polyh);
01107 delete polyh;
01108 }
01109 G4Polyhedron::ResetNumberOfRotationSteps ();
01110 }
01111
01112 G4ViewParameters::DrawingStyle
01113 VisG4VisSceneHandler::GetDrawingStyle (const G4VisAttributes *attrs)
01114 {
01115 G4ViewParameters::DrawingStyle style = G4ViewParameters::hlhsr;
01116 if (attrs->IsForceDrawingStyle ())
01117
01118
01119 switch (attrs->GetForcedDrawingStyle ())
01120 {
01121 case G4VisAttributes::solid:
01122 switch (style)
01123 {
01124 case G4ViewParameters::hlr:
01125 style = G4ViewParameters::hlhsr;
01126 break;
01127 case G4ViewParameters::wireframe:
01128 style = G4ViewParameters::hsr;
01129 break;
01130 default:
01131 break;
01132 }
01133 break;
01134
01135 default:
01136 case G4VisAttributes::wireframe:
01137 switch (style)
01138 {
01139 case G4ViewParameters::hlhsr:
01140 style = G4ViewParameters::hlr;
01141 break;
01142 case G4ViewParameters::hsr:
01143 style = G4ViewParameters::wireframe;
01144 break;
01145 default:
01146 break;
01147 }
01148 break;
01149 }
01150
01151 return style;
01152 }
01153
01157 void
01158 VisG4VisSceneHandler::PreAddSolid (const G4Transform3D &,const G4VisAttributes &)
01159 { ASSERT (false); }
01160
01161 void
01162 VisG4VisSceneHandler::PostAddSolid (void)
01163 { ASSERT (false); }
01164
01165 void
01166 VisG4VisSceneHandler::BeginPrimitives (const G4Transform3D &)
01167 { ASSERT (false); }
01168
01169 void
01170 VisG4VisSceneHandler::EndPrimitives (void)
01171 { ASSERT (false); }