9#include <framework/logging/Logger.h> 
   10#include <framework/gearbox/GearDir.h> 
   11#include <geometry/utilities.h> 
   12#include <geometry/GeometryManager.h> 
   14#include <boost/algorithm/string.hpp> 
   15#include <boost/tuple/tuple.hpp> 
   18#include <G4LogicalVolume.hh> 
   19#include <G4VisAttributes.hh> 
   20#include <G4Polycone.hh> 
   46      boost::to_lower(colorString);
 
   47      double red(0), green(0), blue(0), alpha(0);
 
   48      if (colorString[0] == 
'#') {
 
   49        size_t size = colorString.size();
 
   50        unsigned int colorValue;
 
   51        std::stringstream in(colorString);
 
   53        in >> std::hex >> colorValue;
 
   54        if (in.fail()) size = 0;
 
   57            colorValue = (colorValue << 4) + 15;
 
   61            red   = ((colorValue & 0xf000) >> 12) / 15.;
 
   62            green = ((colorValue & 0x0f00) >>  8) / 15.;
 
   63            blue  = ((colorValue & 0x00f0) >>  4) / 15.;
 
   64            alpha = ((colorValue & 0x000f) >>  0) / 15.;
 
   67            colorValue = (colorValue << 8) + 255;
 
   71            red   = ((colorValue & 0xff000000) >> 24) / 255.;
 
   72            green = ((colorValue & 0x00ff0000) >> 16) / 255.;
 
   73            blue  = ((colorValue & 0x0000ff00) >>  8) / 255.;
 
   74            alpha = ((colorValue & 0x000000ff) >>  0) / 255.;
 
   77            B2WARNING(
"Could not parse color string '" + colorString + 
"'");
 
   79      } 
else if (colorString.substr(0, 3) == 
"rgb") {
 
   81        size_t startPos = colorString.find(
'(');
 
   82        size_t stopPos = colorString.find(
')');
 
   83        std::string ws(
" \t\r\n,");
 
   84        std::stringstream in(colorString.substr(startPos + 1, stopPos - startPos - 1));
 
   86        while (ws.find(in.peek()) != std::string::npos) in.get();
 
   88        while (ws.find(in.peek()) != std::string::npos) in.get();
 
   90        while (ws.find(in.peek()) != std::string::npos) in.get();
 
   92        red   = std::min(1.0, std::max(0.0, red));
 
   93        green = std::min(1.0, std::max(0.0, green));
 
   94        blue  = std::min(1.0, std::max(0.0, blue));
 
   95        alpha = std::min(1.0, std::max(0.0, alpha));
 
   97      return G4Colour(red, green, blue, alpha);
 
  100    void setColor(G4LogicalVolume& volume, 
const std::string& color)
 
  102      auto* attr = 
const_cast<G4VisAttributes*
>(volume.GetVisAttributes());
 
  105      volume.SetVisAttributes(attr);
 
  110      auto* attr = 
const_cast<G4VisAttributes*
>(volume.GetVisAttributes());
 
  112      attr->SetVisibility(visible);
 
  113      volume.SetVisAttributes(attr);
 
  118      if (!params) 
return nullptr;
 
  120      double minPhi = params.getAngle(
"minPhi", 0);
 
  121      double dPhi   = params.getAngle(
"maxPhi", 2 * M_PI) - minPhi;
 
  122      const std::vector<GearDir> planes = params.getNodes(
"Plane");
 
  123      int nPlanes = planes.size();
 
  125        B2ERROR(
"Polycone needs at least two planes");
 
  128      std::vector<double> z(nPlanes, 0);
 
  129      std::vector<double> rMin(nPlanes, 0);
 
  130      std::vector<double> rMax(nPlanes, 0);
 
  132      minZ = std::numeric_limits<double>::infinity();
 
  133      maxZ = -std::numeric_limits<double>::infinity();
 
  134      for (
const GearDir& plane : planes) {
 
  135        z[index]    = plane.getLength(
"posZ") / 
Unit::mm;
 
  136        minZ = std::min(minZ, z[index]);
 
  137        maxZ = std::max(maxZ, z[index]);
 
  138        rMin[index] = plane.getLength(
"innerRadius") / 
Unit::mm;
 
  139        rMax[index] = plane.getLength(
"outerRadius") / 
Unit::mm;
 
  142      G4Polycone* polycone = 
new G4Polycone(name, minPhi, dPhi, nPlanes, z.data(), rMin.data(), rMax.data());
 
  149      using ZXPoint = std::pair<double, double>;
 
  151      using PointList = std::list<ZXPoint>;
 
  165      void subdivideSegments(
const PointList& points, PointList& segments)
 
  167        double lastZ = -std::numeric_limits<double>::infinity();
 
  168        for (
const ZXPoint& p : points) {
 
  169          if (p.first < lastZ) {
 
  170            B2FATAL(
"createRotationSolid: Points have to be given with ascending z positions");
 
  177          auto segStart = segments.begin();
 
  178          auto segEnd = segStart;
 
  180          for (; segEnd != segments.end(); ++segEnd) {
 
  181            if ((p.first > segStart->first && p.first < segEnd->first) ||
 
  182                (p.first < segStart->first && p.first > segEnd->first)) {
 
  183              double dZ = segEnd->first - segStart->first;
 
  184              double dX = segEnd->second - segStart->second;
 
  185              double newX = segStart->second + dX * (p.first - segStart->first) / dZ;
 
  186              segments.insert(segEnd, ZXPoint(p.first, newX));
 
  194        if (points.front().first < segments.front().first) {
 
  195          segments.insert(segments.begin(), points.front());
 
  197        if (points.back().first > segments.back().first) {
 
  198          segments.insert(segments.end(), points.back());
 
  207      PointList innerPoints;
 
  208      PointList outerPoints;
 
  209      for (
const GearDir& point : params.getNodes(
"InnerPoints/point")) {
 
  210        innerPoints.push_back(ZXPoint(point.getLength(
"z") / 
Unit::mm, point.getLength(
"x") / 
Unit::mm));
 
  212      for (
const GearDir& point : params.getNodes(
"OuterPoints/point")) {
 
  213        outerPoints.push_back(ZXPoint(point.getLength(
"z") / 
Unit::mm, point.getLength(
"x") / 
Unit::mm));
 
  217      subdivideSegments(innerPoints, outerPoints);
 
  218      subdivideSegments(outerPoints, innerPoints);
 
  219      minZ = innerPoints.front().first;
 
  220      maxZ = outerPoints.front().first;
 
  223      std::vector<double> z;
 
  224      std::vector<double> rMin;
 
  225      std::vector<double> rMax;
 
  232      while (!(innerPoints.empty() && outerPoints.empty())) {
 
  233        bool popInner = 
false;
 
  238        if (!innerPoints.empty() && innerPoints.front().first <= outerPoints.front().first) {
 
  239          boost::tie(innerZ, innerX) = innerPoints.front();
 
  242        if (!outerPoints.empty() && outerPoints.front().first <= innerPoints.front().first) {
 
  243          boost::tie(outerZ, outerX) = outerPoints.front();
 
  244          outerPoints.pop_front();
 
  246        if (popInner) innerPoints.pop_front();
 
  247        if (innerZ != outerZ) {
 
  248          B2ERROR(
"createRotationSolid: Something is wrong, z values should be identical");
 
  252        rMin.push_back(innerX);
 
  253        rMax.push_back(outerX);
 
  257      int nPlanes = z.size();
 
  258      double minPhi = params.getAngle(
"minPhi", 0);
 
  259      double dPhi   = params.getAngle(
"maxPhi", 2 * M_PI) - minPhi;
 
  260      return new G4Polycone(name, minPhi, dPhi, nPlanes, &z.front(), &rMin.front(), &rMax.front());
 
  264                                    std::list< std::pair<double, double> > innerPoints,
 
  265                                    std::list< std::pair<double, double> > outerPoints,
 
  266                                    double minPhi, 
double maxPhi, 
double& minZ, 
double& maxZ)
 
  270      subdivideSegments(innerPoints, outerPoints);
 
  271      subdivideSegments(outerPoints, innerPoints);
 
  272      minZ = innerPoints.front().first;
 
  273      maxZ = outerPoints.front().first;
 
  276      std::vector<double> z;
 
  277      std::vector<double> rMin;
 
  278      std::vector<double> rMax;
 
  285      while (!(innerPoints.empty() && outerPoints.empty())) {
 
  286        bool popInner = 
false;
 
  292        if (!innerPoints.empty() && innerPoints.front().first <= outerPoints.front().first) {
 
  293          boost::tie(innerZ, innerX) = innerPoints.front();
 
  296        if (!outerPoints.empty() && outerPoints.front().first <= innerPoints.front().first) {
 
  297          boost::tie(outerZ, outerX) = outerPoints.front();
 
  298          outerPoints.pop_front();
 
  300        if (popInner) innerPoints.pop_front();
 
  301        if (innerZ != outerZ) {
 
  302          B2ERROR(
"createRotationSolid: Something is wrong, z values should be identical");
 
  311      int nPlanes = z.size();
 
  312      double dPhi = maxPhi - minPhi;
 
  313      return new G4Polycone(name, minPhi, dPhi, nPlanes, &z.front(), &rMin.front(), &rMax.front());
 
GearDir is the basic class used for accessing the parameter store.
static const double mm
[millimeters]
G4VisAttributes * newVisAttributes()
Create an anonymous G4VisAttributes for an existing G4LogicalVolume.
static GeometryManager & getInstance()
Return a reference to the instance.
G4Polycone * createPolyCone(const std::string &name, const GearDir ¶ms, double &minZ, double &maxZ)
Create Polycone Shape from XML Parameters.
G4Polycone * createRotationSolid(const std::string &name, const GearDir ¶ms, double &minZ, double &maxZ)
Create a solid by roating two polylines around the Z-Axis.
void setVisibility(G4LogicalVolume &volume, bool visible)
Helper function to quickly set the visibility of a given volume.
void setColor(G4LogicalVolume &volume, const std::string &color)
Set the color of a logical volume.
G4Colour parseColor(std::string colorString)
Parse a color string of the form "#rgb", "#rrggbb", "#rgba", "#rrggbbaa" or "rgb(r,...
Abstract base class for different kinds of events.