00001
00002 #include <OnXSvc/Win32.h>
00003
00004
00005 #include "SoDetConverter.h"
00006
00007
00008 #include <Inventor/SbColor.h>
00009 #include <Inventor/SoPickedPoint.h>
00010 #include <Inventor/nodes/SoSeparator.h>
00011 #include <Inventor/nodes/SoTransform.h>
00012 #include <Inventor/nodes/SoMaterial.h>
00013 #include <Inventor/nodes/SoLightModel.h>
00014 #include <Inventor/nodes/SoEventCallback.h>
00015
00016 #include <Inventor/events/SoMouseButtonEvent.h>
00017
00018
00019 #include <HEPVis/SbMath.h>
00020 #include <HEPVis/SbPolyhedron.h>
00021 #include <HEPVis/misc/SoStyleCache.h>
00022 #include <HEPVis/nodes/SoPolyhedron.h>
00023
00024 #include <HEPVis/nodekits/SoDetectorTreeKit.h>
00025
00026 #include <Lib/smanip.h>
00027 #include <Lib/Interfaces/ISession.h>
00028
00029 #include <GaudiKernel/Transform3DTypes.h>
00030
00031 #include <OnXSvc/ISoConversionSvc.h>
00032 #include <OnXSvc/IUserInterfaceSvc.h>
00033 #include <OnXSvc/ClassID.h>
00034
00035 #include <GaudiKernel/MsgStream.h>
00036 #include <GaudiKernel/ISvcLocator.h>
00037
00038 #include <DetDesc/Material.h>
00039 #include <DetDesc/ILVolume.h>
00040 #include <DetDesc/IPVolume.h>
00041 #include <DetDesc/ISolid.h>
00042 #include <DetDesc/Solids.h>
00043
00044 #include <VisSvc/IVisualizationSvc.h>
00045
00046 class SoDetTreeKit : public SoDetectorTreeKit {
00047 const ILVolume& m_lvolume;
00048 bool m_modeling;
00049 bool m_expanded;
00050 SoDetConverter* m_soConverter;
00051 public:
00052 SoDetTreeKit(const ILVolume& aLVolume,
00053 bool aModeling,
00054 SoDetConverter* soConverter) :
00055 m_lvolume(aLVolume),
00056 m_modeling(aModeling),
00057 m_expanded(false),
00058 m_soConverter(soConverter){
00059 }
00060 virtual ~SoDetTreeKit() {
00061 }
00062 const ILVolume& lvolume() {return m_lvolume;}
00063 bool modeling() {return m_modeling;}
00064 bool expanded() {return m_expanded;}
00065 SoDetConverter* soConverter() {return m_soConverter;}
00066 void setExpanded(bool aValue) {m_expanded = aValue;}
00067 };
00068
00069 void expand(void *userData, SoEventCallback *eventCB);
00070 void contract(void *userData, SoEventCallback *eventCB);
00071
00072 #define None (-1)
00073
00075 SoDetConverter::SoDetConverter (ISvcLocator* aSvcLoc, CLID clid)
00076 :Converter(So_TechnologyType, clid, aSvcLoc)
00077 ,fSoCnvSvc(0)
00078 ,fUISvc(0)
00079 ,m_visSvc(0)
00080 ,m_out(0)
00081 ,fStyleCache(0)
00082 ,fRotationSteps(None)
00083 ,fDoBooleanOperation(true)
00086 {
00087 m_out = new MsgStream(msgSvc(),"SoDetConverter");
00088 StatusCode sc = aSvcLoc->service ("VisualizationSvc", m_visSvc, true);
00089 if (!sc.isSuccess()) {
00090 (*m_out) << MSG::WARNING << "Unable to get VisualizationSvc" << endreq;
00091 }
00092 fStyleCache = new SoStyleCache;
00093 fStyleCache->ref();
00094 }
00096 SoDetConverter::~SoDetConverter()
00099 {
00100
00101 fStyleCache->unref();
00102
00103 delete m_out;
00104 }
00106 StatusCode SoDetConverter::initialize()
00109 {
00110 StatusCode status = Converter::initialize();
00111 if(status.isFailure()) return status;
00112 status = serviceLocator()->service("SoConversionSvc",fSoCnvSvc);
00113 if(status.isFailure()) return status;
00114 status = serviceLocator()->service("OnXSvc",fUISvc);
00115 if(status.isFailure()) return status;
00116 return status;
00117 }
00119 StatusCode SoDetConverter::finalize()
00122 {
00123
00124
00125
00126 return StatusCode::SUCCESS;
00127 }
00129 long SoDetConverter::repSvcType() const
00132 {
00133 return i_repSvcType();
00134 }
00136 MsgStream* SoDetConverter::out() { return m_out;}
00138 SoNode* SoDetConverter::volumeToSoDetectorTreeKit(
00139 const ILVolume& aLVolume
00140 ,const Gaudi::Transform3D& aMatrix
00141 ,bool aOpened
00142 )
00145 {
00146 ISession* session = fUISvc->session();
00147 if(!session) return 0;
00148
00149 MsgStream log(msgSvc(), "SoDetConverter" );
00150
00151
00152 std::string value;
00153 double r = 0.5, g = 0.5, b = 0.5;
00154
00155 double transparency = 0;
00156 bool modelingSolid = true;
00157 fRotationSteps = None;
00158
00159 if(session->parameterValue("modeling.color",value))
00160 if(!Lib::smanip::torgb(value,r,g,b)) { r = 0.5; g = 0.5; b = 0.5;}
00161 if(session->parameterValue("modeling.transparency",value))
00162 if(!Lib::smanip::todouble(value,transparency)) transparency = 0;
00163
00164
00165 if(session->parameterValue("modeling.modeling",value)) {
00166 modelingSolid = (value=="solid" ? true : false);
00167 } else {
00168 if(session->parameterValue("modeling.type",value)) {
00169 modelingSolid = (value=="solid" ? true : false);
00170 }
00171 }
00172 if(session->parameterValue("modeling.rotationSteps",value)) {
00173 if(!Lib::smanip::toint(value,fRotationSteps)) fRotationSteps = None;
00174 }
00175 if(session->parameterValue("modeling.doBooleanOperation",value)) {
00176 if(!Lib::smanip::tobool(value,fDoBooleanOperation)) fDoBooleanOperation = true;
00177 }
00178
00179 bool modelingOpened = aOpened;
00180 bool modelingVisible = true;
00181
00182
00183 bool useVisSvc = true;
00184 if(session->parameterValue("modeling.useVisSvc",value)) {
00185 if(!Lib::smanip::tobool(value,useVisSvc)) useVisSvc = true;
00186 }
00187
00188 VisAttribute attr;
00189 if(m_visSvc && useVisSvc) {
00190 attr = m_visSvc->visAttribute(&aLVolume);
00191 const Color color = attr.color();
00192 if (color.isValid()) {
00193 r = color.red();
00194 g = color.green();
00195 b = color.blue();
00196 transparency = color.alpha();
00197 }
00198 if(attr.displayMode()==VisAttribute::WIRE_FRAME) {
00199 modelingSolid = false;
00200 }
00201 if(attr.openStatus()==VisAttribute::OPENED) {
00202 modelingOpened = true;
00203 }
00204 if(attr.visible()==VisAttribute::NOT_VISIBLE) {
00205 modelingVisible = false;
00206 }
00207 }
00208
00209 log << MSG::DEBUG << " opened " << modelingOpened << endreq;
00210
00211
00212 SoNode* node = 0;
00213 const ISolid* solid = aLVolume.solid();
00214 if(!solid) {
00215
00216 } else {
00217 SbPolyhedron* result = solidToSbPolyhedron(*solid);
00218 if(result) {
00219 SoPolyhedron* soPolyhedron = new SoPolyhedron(*result);
00220 delete (result);
00221 soPolyhedron->solid.setValue(modelingSolid);
00222 node = soPolyhedron;
00223 }
00224 }
00225
00226 if(node) {
00227 std::string s;
00228 Lib::smanip::printf(s,128,"LVolume/0x%lx",(unsigned long)&aLVolume);
00229 node->setName(s.c_str());
00230 }
00231
00232
00233 Gaudi::Rotation3D rot;
00234 Gaudi::XYZVector c;
00235 aMatrix.GetDecomposition(rot,c);
00236 c = c * -1.0;
00237 rot.Invert();
00238
00239 const Gaudi::Quaternion q(rot);
00240 Gaudi::AxisAngle axisAngle( q );
00241 double angle;
00242 Gaudi::XYZVector v;
00243 axisAngle.GetComponents(v,angle);
00244
00245 int childn = aLVolume.noPVolumes();
00246 log << MSG::DEBUG << " childn " << childn << " node " << node << endreq;
00247 if(childn==0) {
00248
00249
00250
00251
00252
00253
00254
00255 if (node && modelingVisible) {
00256 SoSeparator* separator = new SoSeparator;
00257 separator->setName("sceneGraph");
00258
00259 if(modelingSolid) {
00260 separator->addChild
00261 (fStyleCache->getMaterial(SbColor((float)r,(float)g,(float)b),(float)transparency));
00262 separator->addChild(fStyleCache->getLightModelPhong());
00263 } else {
00264 separator->addChild
00265 (fStyleCache->getMaterial(SbColor((float)r,(float)g,(float)b),(float)transparency,TRUE));
00266 separator->addChild(fStyleCache->getLightModelBaseColor());
00267 }
00268
00269
00270 SbMatrix mtx;
00271 mtx.makeIdentity();
00272 {SbMatrix tmp;
00273 tmp.setRotate(SbRotation(SbVec3f((float)v.x(),(float)v.y(),(float)v.z()),
00274 (float)angle));
00275 mtx.multLeft(tmp);}
00276 {SbMatrix tmp;
00277 tmp.setTranslate(SbVec3f((float)c.x(),(float)c.y(),(float)c.z()));
00278 mtx.multLeft(tmp);}
00279
00280 SoTransform* transform = new SoTransform;
00281 transform->setMatrix(mtx);
00282
00283
00284 separator->addChild(transform);
00285 separator->addChild(node);
00286 return separator;
00287
00288 } else {
00289 if(node) node->unref();
00290 return 0;
00291 }
00292
00293 } else {
00294
00295 SoDetTreeKit* dtk = new SoDetTreeKit(aLVolume,modelingSolid,this);
00296
00297
00298 SoEventCallback* evtCbk =
00299 (SoEventCallback*)dtk->getPart("callbackList[0]",FALSE);
00300 if(evtCbk) {
00301 SoEventCallback* eventCallback = new SoEventCallback;
00302
00303 eventCallback->addEventCallback(SoMouseButtonEvent::getClassTypeId(),
00304 expand,dtk);
00305 eventCallback->addEventCallback(SoMouseButtonEvent::getClassTypeId(),
00306 contract,dtk);
00307 if(dtk->setPart("callbackList[0]",eventCallback)==FALSE)
00308 eventCallback->unref();
00309 }
00310
00311
00312 SbMatrix mtx;
00313 mtx.makeIdentity();
00314 {SbMatrix tmp;
00315 tmp.setRotate(SbRotation(SbVec3f((float)v.x(),(float)v.y(),(float)v.z()),
00316 (float)angle));
00317 mtx.multLeft(tmp);}
00318 {SbMatrix tmp;
00319 tmp.setTranslate(SbVec3f((float)c.x(),(float)c.y(),(float)c.z()));
00320 mtx.multLeft(tmp);}
00321
00322 SoTransform* transform = (SoTransform*)dtk->getPart("transform",TRUE);
00323 transform->setMatrix(mtx);
00324
00325
00326
00327
00328 SoSeparator* previewSeparator =
00329 (SoSeparator*)dtk->getPart("previewSeparator",TRUE);
00330
00331 bool childOpened = false;
00332 if (node && modelingVisible) {
00333
00334 SoSeparator* separator = new SoSeparator;
00335 separator->setName("sceneGraph");
00336
00337 if(modelingSolid) {
00338 separator->addChild
00339 (fStyleCache->getMaterial
00340 (SbColor((float)r,(float)g,(float)b),(float)transparency));
00341 separator->addChild(fStyleCache->getLightModelPhong());
00342 } else {
00343 separator->addChild
00344 (fStyleCache->getMaterial
00345 (SbColor((float)r,(float)g,(float)b),(float)transparency,TRUE));
00346 separator->addChild(fStyleCache->getLightModelBaseColor());
00347 }
00348
00349 separator->addChild(new SoTransform);
00350 separator->addChild(node);
00351
00352 previewSeparator->addChild(separator);
00353
00354 if(modelingOpened) dtk->setPreview(FALSE);
00355 } else {
00356 dtk->setPreview(FALSE);
00357 if(node) node->unref();
00358 else childOpened = aOpened;
00359 }
00360
00361 SoSeparator* fullSeparator =
00362 (SoSeparator*)dtk->getPart("fullSeparator",TRUE);
00363
00364
00365 if (!node || modelingOpened) {
00366
00367 for(int count=0;count<childn;count++) {
00368 const IPVolume* pvolume = aLVolume[count];
00369 if (!pvolume) {
00370 log << MSG::ERROR << "found a null pvolume in " << aLVolume.name()
00371 << " at index " << count
00372 << ". Check the name of the logical volume associated to it"
00373 << endreq;
00374 } else {
00375 if(!pvolume->lvolume()) {
00376 log << MSG::ERROR << "pvolume with a null lvolume." << endreq;
00377 } else {
00378 SoNode* child = volumeToSoDetectorTreeKit(*(pvolume->lvolume()),
00379 pvolume->matrix(),
00380 childOpened);
00381 if (child) fullSeparator->addChild(child);
00382 }
00383 }
00384 }
00385 }
00386
00387 if(fullSeparator->getNumChildren()==0) {
00388
00389 dtk->setPreview(TRUE);
00390 if(previewSeparator->getNumChildren()==0) {
00391
00392
00393
00394 dtk->unref();
00395 return 0;
00396 }
00397 }
00398
00399
00400
00401 return dtk;
00402 }
00403
00404 }
00406 SbPolyhedron* SoDetConverter::solidToSbPolyhedron(
00407 const ISolid& aSolid
00408 )
00411 {
00412 SbPolyhedron* result = simpleSolidToSbPolyhedron(aSolid);
00413 if(!result) result = booleanSolidToSbPolyhedron(aSolid);
00414 if(!result) {
00415 std::string type = aSolid.typeName();
00416 MsgStream log(msgSvc(),"SoDetConverter::solidToSbPolyhedron");
00417 log << MSG::INFO
00418 << " type " << type << " not treated."
00419 << endreq;
00420 }
00421 return result;
00422 }
00424 SbPolyhedron* SoDetConverter::simpleSolidToSbPolyhedron(
00425 const ISolid& aSolid
00426 )
00429 {
00430 #ifdef WIN32 //FIXME. Waiting code of HEPVis of OSC-v15r0p2
00431
00432 int oldRotationSteps = DEFAULT_NUMBER_OF_STEPS;
00433 #else
00434 int oldRotationSteps = SbPolyhedron::GetNumberOfRotationSteps() ;
00435 #endif
00436
00437 if(fRotationSteps!=None)
00438 SbPolyhedron::SetNumberOfRotationSteps(fRotationSteps);
00439
00440 SbPolyhedron* result = 0;
00441
00442 if(const SolidBox* box = dynamic_cast<const SolidBox*>(&aSolid)) {
00443 result = new SbPolyhedronBox(box->xHalfLength(),
00444 box->yHalfLength(),
00445 box->zHalfLength());
00446 } else if(const SolidCons* cons = dynamic_cast<const SolidCons*>(&aSolid)) {
00447 result = new SbPolyhedronCons(cons->innerRadiusAtMinusZ(),
00448 cons->outerRadiusAtMinusZ(),
00449 cons->innerRadiusAtPlusZ(),
00450 cons->outerRadiusAtPlusZ(),
00451 cons->zHalfLength(),
00452 cons->startPhiAngle(),
00453 cons->deltaPhiAngle());
00454 } else if(const SolidPolycone* cons =
00455 dynamic_cast<const SolidPolycone*>(&aSolid)) {
00456 unsigned int nb = cons->number();
00457 if(nb<=0) {
00458 MsgStream log(msgSvc(), "SoDetConverter::simpleSolidToSbPolyhedron");
00459 log << MSG::INFO
00460 << " SolidPolycone with null cons->number()."
00461 << endreq;
00462 } else {
00463 double* z = new double[nb];
00464 double* innerRadius = new double[nb];
00465 double* outerRadius = new double[nb];
00466 unsigned int i = 0;
00467 for (SolidPolycone::Iterator it=cons->begin();it < cons->end();it++) {
00468 z[i] = (*it).first;
00469 outerRadius[i] = (*it).second.first;
00470 innerRadius[i] = (*it).second.second;
00471 i++;
00472 }
00473 result = new SbPolyhedronPcon(cons->startPhiAngle(),
00474 cons->deltaPhiAngle(),
00475 nb,
00476 z,
00477 innerRadius,
00478 outerRadius);
00479 delete [] z;
00480 delete [] innerRadius;
00481 delete [] outerRadius;
00482
00483 }
00484 } else if(const SolidSphere* sphere =
00485 dynamic_cast<const SolidSphere*>(&aSolid)) {
00486
00487 if( (sphere->deltaPhiAngle()<=0) || (sphere->deltaThetaAngle()<=0) ){
00488 MsgStream log(msgSvc(), "SoDetConverter::simpleSolidToSbPolyhedron");
00489 log << MSG::INFO
00490 << " SolidSphere with null deltaPhiAngle or deltaThetaAngle."
00491 << endreq;
00492 } else {
00493
00494
00495
00496
00497
00498
00499
00500
00501 int nphi = int(M_PI_2 / sphere->deltaPhiAngle());
00502 int ntheta = int(M_PI / sphere->deltaThetaAngle());
00503
00504
00505
00506
00507 int rotationSteps = SbMaximum(nphi,ntheta);
00508 #ifdef WIN32 //FIXME. Waiting code of HEPVis of OSC-v15r0p2
00509
00510 rotationSteps *=
00511 (fRotationSteps!=None ? fRotationSteps : DEFAULT_NUMBER_OF_STEPS);
00512 #else
00513 rotationSteps *= SbPolyhedron::GetNumberOfRotationSteps();
00514 #endif
00515 if(rotationSteps<=0) rotationSteps = DEFAULT_NUMBER_OF_STEPS;
00516 SbPolyhedron::SetNumberOfRotationSteps(rotationSteps);
00517
00518 result = new SbPolyhedronSphere(sphere->insideRadius(),
00519 sphere->outerRadius(),
00520 sphere->startPhiAngle(),
00521 sphere->deltaPhiAngle(),
00522 sphere->startThetaAngle(),
00523 sphere->deltaThetaAngle());
00524
00525 }
00526
00527 } else if(const SolidTubs* tubs = dynamic_cast<const SolidTubs*>(&aSolid)) {
00528
00529 if( (tubs->deltaPhiAngle()<=0) ){
00530 MsgStream log(msgSvc(), "SoDetConverter::simpleSolidToSbPolyhedron");
00531 log << MSG::INFO
00532 << " SolidTubs with null deltaPhiAngle."
00533 << endreq;
00534 } else {
00535
00536
00537
00538
00539
00540
00541
00542
00543 int rotationSteps = int(M_PI_2 / tubs->deltaPhiAngle());
00544
00545 #ifdef WIN32 //FIXME. Waiting code of HEPVis of OSC-v15r0p2
00546
00547 rotationSteps *=
00548 (fRotationSteps!=None ? fRotationSteps : DEFAULT_NUMBER_OF_STEPS);
00549 #else
00550 rotationSteps *= SbPolyhedron::GetNumberOfRotationSteps();
00551 #endif
00552 if(rotationSteps<=0) rotationSteps = DEFAULT_NUMBER_OF_STEPS;
00553 SbPolyhedron::SetNumberOfRotationSteps(rotationSteps);
00554
00555 result = new SbPolyhedronTubs(tubs->innerRadius(),
00556 tubs->outerRadius(),
00557 tubs->zHalfLength(),
00558 tubs->startPhiAngle(),
00559 tubs->deltaPhiAngle());
00560 }
00561
00562 } else if(const SolidTrd* trd = dynamic_cast<const SolidTrd*>(&aSolid)) {
00563 result = new SbPolyhedronTrd2(trd->xHalfLength1(),
00564 trd->xHalfLength2(),
00565 trd->yHalfLength1(),
00566 trd->yHalfLength2(),
00567 trd->zHalfLength());
00568 } else if(const SolidTrap* trap = dynamic_cast<const SolidTrap*>(&aSolid)) {
00569 result = new SbPolyhedronTrap(trap->zHalfLength(),
00570 trap->theta(),
00571 trap->phi(),
00572 trap->dyAtMinusZ(),
00573 trap->dxAtMinusZMinusY(),
00574 trap->dxAtMinusZPlusY(),
00575 trap->alphaAtMinusZ(),
00576 trap->dyAtPlusZ(),
00577 trap->dxAtPlusZMinusY(),
00578 trap->dxAtPlusZPlusY(),
00579 trap->alphaAtPlusZ());
00580 } else {
00581
00582 }
00583
00584 SbPolyhedron::SetNumberOfRotationSteps(oldRotationSteps);
00585
00586 return result;
00587 }
00589 SbPolyhedron* SoDetConverter::booleanSolidToSbPolyhedron(
00590 const ISolid& aSolid
00591 )
00594 {
00595 if (const SolidSubtraction* sub =
00596 dynamic_cast<const SolidSubtraction*>(&aSolid)) {
00597
00598 MsgStream log(msgSvc(),"SoDetConverter::booleanSolidToSbPolyhedron");
00599 log << MSG::DEBUG << " SolidSubtraction" << endreq;
00600
00601 if(!sub->first()) return 0;
00602
00603 SbPolyhedron* sbPoly = solidToSbPolyhedron(*(sub->first()));
00604 if(!sbPoly) return 0;
00605 sbPoly->setName(sub->first()->name().c_str());
00606 if(!fDoBooleanOperation) return sbPoly;
00607
00608 SbPolyhedronProcessor sbPP;
00609
00610 int childn = sub->noChildrens();
00611 for(int count=0;count<childn;count++) {
00612 if(!((*sub)[count])) {
00613 delete sbPoly;
00614 return 0;
00615 }
00616 const SolidChild* solidChild =
00617 dynamic_cast<const SolidChild*>((*sub)[count]);
00618 if(!solidChild) {
00619 delete sbPoly;
00620 return 0;
00621 }
00622 const ISolid* solidChildSolid = solidChild->solid();
00623 if(!solidChildSolid) {
00624 delete sbPoly;
00625 return 0;
00626 }
00627 SbPolyhedron* scsPoly = solidToSbPolyhedron(*solidChildSolid);
00628 if(!scsPoly) {
00629 delete sbPoly;
00630 return 0;
00631 }
00632 scsPoly->setName(solidChildSolid->name().c_str());
00633
00634
00635 Gaudi::XYZVector trans;
00636 Gaudi::Rotation3D rot;
00637 solidChild->matrix().GetDecomposition(rot,trans);
00638 trans = trans * -1.0;
00639 rot.Invert();
00640
00641 const Gaudi::Quaternion q(rot);
00642 Gaudi::AxisAngle axisAngle( q );
00643 Gaudi::XYZVector v;
00644 double angle;
00645 axisAngle.GetComponents(v,angle);
00646
00647
00648 scsPoly->Transform(HEPVis::SbRotation(SbVec3d(1, 0, 0),0),
00649 SbVec3d(trans.x(),trans.y(),trans.z()));
00650 scsPoly->Transform(HEPVis::SbRotation(SbVec3d(v.x(),v.y(),v.z()),angle),
00651 SbVec3d(0, 0, 0));
00652 sbPP.push_back(SbPolyhedronProcessor::SUBTRACTION,*scsPoly);
00653
00654
00655
00656
00657
00658
00659
00660 delete scsPoly;
00661 }
00662
00663
00664 if(sbPP.execute(*sbPoly)==FALSE) {
00665 log << MSG::INFO << " SolidSubtraction failed" << endreq;
00666 }
00667
00668 return sbPoly;
00669
00670 } else if(const SolidIntersection* inter =
00671 dynamic_cast<const SolidIntersection*>(&aSolid)) {
00672
00673 MsgStream log(msgSvc(),"SoDetConverter::booleanSolidToSbPolyhedron");
00674 log << MSG::DEBUG << " SolidIntersection" << endreq;
00675
00676 if(!inter->first()) return 0;
00677
00678 SbPolyhedron* sbPoly = solidToSbPolyhedron(*(inter->first()));
00679 if(!sbPoly) return 0;
00680 sbPoly->setName(inter->first()->name().c_str());
00681 if(!fDoBooleanOperation) return sbPoly;
00682
00683 SbPolyhedronProcessor sbPP;
00684
00685 int childn = inter->noChildrens();
00686 for(int count=0;count<childn;count++) {
00687 if(!((*inter)[count])) {
00688 delete sbPoly;
00689 return 0;
00690 }
00691 const SolidChild* solidChild =
00692 dynamic_cast<const SolidChild*>((*inter)[count]);
00693 if(!solidChild) {
00694 delete sbPoly;
00695 return 0;
00696 }
00697 const ISolid* solidChildSolid = solidChild->solid();
00698 if(!solidChildSolid) {
00699 delete sbPoly;
00700 return 0;
00701 }
00702 SbPolyhedron* scsPoly = solidToSbPolyhedron(*solidChildSolid);
00703 if(!scsPoly) {
00704 delete sbPoly;
00705 return 0;
00706 }
00707 scsPoly->setName(solidChildSolid->name().c_str());
00708
00709
00710 Gaudi::XYZVector trans;
00711 Gaudi::Rotation3D rot;
00712 solidChild->matrix().GetDecomposition(rot,trans);
00713 trans = trans * -1.0;
00714 rot.Invert();
00715
00716 const Gaudi::Quaternion q(rot);
00717 Gaudi::AxisAngle axisAngle( q );
00718 Gaudi::XYZVector v;
00719 double angle;
00720 axisAngle.GetComponents(v,angle);
00721
00722
00723 scsPoly->Transform(HEPVis::SbRotation(SbVec3d(1, 0, 0),0),
00724 SbVec3d(trans.x(),trans.y(),trans.z()));
00725 scsPoly->Transform(HEPVis::SbRotation(SbVec3d(v.x(),v.y(),v.z()),angle),
00726 SbVec3d(0, 0, 0));
00727 sbPP.push_back(SbPolyhedronProcessor::INTERSECTION,*scsPoly);
00728
00729
00730
00731
00732
00733
00734
00735 delete scsPoly;
00736 }
00737
00738
00739 if(sbPP.execute(*sbPoly)==FALSE) {
00740 log << MSG::INFO << " SolidIntersection failed" << endreq;
00741 }
00742
00743 return sbPoly;
00744
00745 } else if(const SolidUnion* un = dynamic_cast<const SolidUnion*>(&aSolid)) {
00746
00747 MsgStream log(msgSvc(),"SoDetConverter::booleanSolidToSbPolyhedron");
00748 log << MSG::DEBUG << " SolidUnion" << endreq;
00749
00750 if(!un->first()) return 0;
00751
00752 SbPolyhedron* sbPoly = solidToSbPolyhedron(*(un->first()));
00753 if(!sbPoly) return 0;
00754 sbPoly->setName(un->first()->name().c_str());
00755 if(!fDoBooleanOperation) return sbPoly;
00756
00757 SbPolyhedronProcessor sbPP;
00758
00759 int childn = un->noChildrens();
00760 for(int count=0;count<childn;count++) {
00761 if(!((*un)[count])) {
00762 delete sbPoly;
00763 return 0;
00764 }
00765 const SolidChild* solidChild =
00766 dynamic_cast<const SolidChild*>((*un)[count]);
00767 if(!solidChild) {
00768 delete sbPoly;
00769 return 0;
00770 }
00771 const ISolid* solidChildSolid = solidChild->solid();
00772 if(!solidChildSolid) {
00773 delete sbPoly;
00774 return 0;
00775 }
00776 SbPolyhedron* scsPoly = solidToSbPolyhedron(*solidChildSolid);
00777 if(!scsPoly) {
00778 delete sbPoly;
00779 return 0;
00780 }
00781 scsPoly->setName(solidChildSolid->name().c_str());
00782
00783
00784 Gaudi::XYZVector trans;
00785 Gaudi::Rotation3D rot;
00786 solidChild->matrix().GetDecomposition(rot,trans);
00787 trans = trans * -1.0;
00788 rot.Invert();
00789
00790 const Gaudi::Quaternion q(rot);
00791 Gaudi::AxisAngle axisAngle( q );
00792 Gaudi::XYZVector v;
00793 double angle;
00794 axisAngle.GetComponents(v,angle);
00795
00796
00797 scsPoly->Transform(HEPVis::SbRotation(SbVec3d(1, 0, 0),0),
00798 SbVec3d(trans.x(),trans.y(),trans.z()));
00799 scsPoly->Transform(HEPVis::SbRotation(SbVec3d(v.x(),v.y(),v.z()),angle),
00800 SbVec3d(0, 0, 0));
00801 sbPP.push_back(SbPolyhedronProcessor::UNION,*scsPoly);
00802
00803
00804
00805
00806
00807
00808
00809 delete scsPoly;
00810 }
00811
00812
00813 if(sbPP.execute(*sbPoly)==FALSE) {
00814 log << MSG::INFO << " SolidUnion failed" << endreq;
00815 }
00816
00817 return sbPoly;
00818 }
00819 return 0;
00820 }
00821
00822 void expand(void* userData, SoEventCallback* eventCB){
00823 if (eventCB->isHandled()) return;
00824
00825 const SoMouseButtonEvent* event = (SoMouseButtonEvent*)eventCB->getEvent();
00826
00827 if (!SO_MOUSE_RELEASE_EVENT(event,BUTTON1)) return;
00828 if (!event->wasCtrlDown()) return;
00829 if (event->wasShiftDown()) return;
00830
00831 SoHandleEventAction* handleEventAction = eventCB->getAction();
00832 const SoPickedPoint* pickedPoint = handleEventAction->getPickedPoint();
00833 if (!pickedPoint) return;
00834 SoFullPath* path = (SoFullPath*)pickedPoint->getPath();
00835 SoNode* ancestorNode = NULL;
00836 for (int i=0;i<path->getLength();i++) {
00837 ancestorNode = path->getNodeFromTail(i);
00838 if (ancestorNode->isOfType(SoDetectorTreeKit::getClassTypeId())) break;
00839 }
00840
00841 SoDetTreeKit* This = (SoDetTreeKit*)userData;
00842
00843 if(This!=ancestorNode) return;
00844
00845 SoDetConverter* soConverter = This->soConverter();
00846 const ILVolume& volume = This->lvolume();
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870 (*soConverter->out()) << MSG::DEBUG <<
00871 " expand : dtk expanded ? " << This->expanded() << endreq;
00872
00873 if(This->expanded()) {
00874 This->setPreview(FALSE);
00875 } else {
00876
00877 This->setExpanded(true);
00878 SoSeparator* fullSeparator =
00879 (SoSeparator*)This->getPart("fullSeparator",TRUE);
00880 SbBool preview = TRUE;
00881 int childn = volume.noPVolumes();
00882 for(int count=0;count<childn;count++) {
00883 const IPVolume* pvolume = volume[count];
00884 if (!pvolume) {
00885 (*soConverter->out())
00886 << MSG::ERROR << "found a null pvolume in " << volume.name()
00887 << " at index " << count
00888 << ". Check the name of the logical volume associated to it"
00889 << endreq;
00890 } else {
00891 if(!pvolume->lvolume()) {
00892 (*soConverter->out())
00893 << MSG::ERROR << "pvolume with a null lvolume." << endreq;
00894 } else {
00895 SoNode* node = soConverter->volumeToSoDetectorTreeKit
00896 (*(pvolume->lvolume()),pvolume->matrix());
00897 if (node) {
00898 (*soConverter->out()) << MSG::DEBUG <<
00899 " expand, add a node." << endreq;
00900 fullSeparator->addChild(node);
00901 preview = FALSE;
00902 }
00903 }
00904 }
00905 }
00906 This->setPreview(preview);
00907 }
00908 eventCB->setHandled();
00909 }
00910
00911 void contract(void *userData, SoEventCallback *eventCB){
00912
00913
00914 if (eventCB->isHandled()) return;
00915
00916 const SoMouseButtonEvent* event = (SoMouseButtonEvent*)eventCB->getEvent();
00917
00918 if (!SO_MOUSE_RELEASE_EVENT(event,BUTTON1)) return;
00919 if(event->wasCtrlDown()) return;
00920 if(!event->wasShiftDown()) return;
00921
00922
00923 SoHandleEventAction *handleEventAction = eventCB->getAction();
00924 const SoPickedPoint *pickedPoint = handleEventAction->getPickedPoint();
00925 if (!pickedPoint) return;
00926
00927
00928 SoDetTreeKit* This = (SoDetTreeKit*)userData;
00929 SoDetConverter* soConverter = This->soConverter();
00930
00931
00932
00933 SoFullPath* path = (SoFullPath*)pickedPoint->getPath();
00934 SoNode* ancestorNode = NULL;
00935 SbBool firstTreeFound = FALSE;
00936 for (int i=0;i<path->getLength();i++) {
00937 ancestorNode = path->getNodeFromTail(i);
00938 if (ancestorNode->isOfType(SoDetectorTreeKit::getClassTypeId())) {
00939 if (!firstTreeFound) {
00940 if (This!=ancestorNode) return;
00941 firstTreeFound=TRUE;
00942 }
00943 SoDetTreeKit* That = (SoDetTreeKit*)ancestorNode;
00944 if (!That->getPreview()) {
00945
00946 SoSeparator* previewSep =
00947 (SoSeparator*)That->getPart("previewSeparator",TRUE);
00948 if(previewSep->getNumChildren()) {
00949
00950
00951 SoSeparator* fullSeparator =
00952 (SoSeparator*)That->getPart("fullSeparator",TRUE);
00953 fullSeparator->removeAllChildren();
00954 That->setExpanded(false);
00955 (*soConverter->out()) << MSG::DEBUG <<
00956 " contract & delete. " << endreq;
00957 That->setPreview(TRUE);
00958 eventCB->setHandled();
00959 return;
00960 }
00961 }
00962 }
00963 }
00964 }