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>
17 #include <G4Colour.hh>
18 #include <G4LogicalVolume.hh>
19 #include <G4VisAttributes.hh>
20 #include <G4Polycone.hh>
43 boost::to_lower(colorString);
44 double red(0), green(0), blue(0), alpha(0);
45 if (colorString[0] ==
'#') {
46 size_t size = colorString.size();
47 unsigned int colorValue;
48 std::stringstream in(colorString);
50 in >> std::hex >> colorValue;
51 if (in.fail()) size = 0;
54 colorValue = (colorValue << 4) + 15;
58 red = ((colorValue & 0xf000) >> 12) / 15.;
59 green = ((colorValue & 0x0f00) >> 8) / 15.;
60 blue = ((colorValue & 0x00f0) >> 4) / 15.;
61 alpha = ((colorValue & 0x000f) >> 0) / 15.;
64 colorValue = (colorValue << 8) + 255;
68 red = ((colorValue & 0xff000000) >> 24) / 255.;
69 green = ((colorValue & 0x00ff0000) >> 16) / 255.;
70 blue = ((colorValue & 0x0000ff00) >> 8) / 255.;
71 alpha = ((colorValue & 0x000000ff) >> 0) / 255.;
74 B2WARNING(
"Could not parse color string '" + colorString +
"'");
76 }
else if (colorString.substr(0, 3) ==
"rgb") {
78 size_t startPos = colorString.find(
'(');
79 size_t stopPos = colorString.find(
')');
80 std::string ws(
" \t\r\n,");
81 std::stringstream in(colorString.substr(startPos + 1, stopPos - startPos - 1));
83 while (ws.find(in.peek()) != std::string::npos) in.get();
85 while (ws.find(in.peek()) != std::string::npos) in.get();
87 while (ws.find(in.peek()) != std::string::npos) in.get();
89 red = std::min(1.0, std::max(0.0, red));
90 green = std::min(1.0, std::max(0.0, green));
91 blue = std::min(1.0, std::max(0.0, blue));
92 alpha = std::min(1.0, std::max(0.0, alpha));
94 return G4Colour(red, green, blue, alpha);
97 void setColor(G4LogicalVolume& volume,
const std::string& color)
99 auto* attr =
const_cast<G4VisAttributes*
>(volume.GetVisAttributes());
102 volume.SetVisAttributes(attr);
107 auto* attr =
const_cast<G4VisAttributes*
>(volume.GetVisAttributes());
109 attr->SetVisibility(visible);
110 volume.SetVisAttributes(attr);
115 if (!params)
return nullptr;
117 double minPhi = params.getAngle(
"minPhi", 0);
118 double dPhi = params.getAngle(
"maxPhi", 2 * M_PI) - minPhi;
119 const std::vector<GearDir> planes = params.getNodes(
"Plane");
120 int nPlanes = planes.size();
122 B2ERROR(
"Polycone needs at least two planes");
125 std::vector<double> z(nPlanes, 0);
126 std::vector<double> rMin(nPlanes, 0);
127 std::vector<double> rMax(nPlanes, 0);
129 minZ = std::numeric_limits<double>::infinity();
130 maxZ = -std::numeric_limits<double>::infinity();
131 for (
const GearDir& plane : planes) {
132 z[index] = plane.getLength(
"posZ") /
Unit::mm;
133 minZ = std::min(minZ, z[index]);
134 maxZ = std::max(maxZ, z[index]);
135 rMin[index] = plane.getLength(
"innerRadius") /
Unit::mm;
136 rMax[index] = plane.getLength(
"outerRadius") /
Unit::mm;
139 G4Polycone* polycone =
new G4Polycone(name, minPhi, dPhi, nPlanes, z.data(), rMin.data(), rMax.data());
146 using ZXPoint = std::pair<double, double>;
148 using PointList = std::list<ZXPoint>;
162 void subdivideSegments(
const PointList& points, PointList& segments)
164 double lastZ = -std::numeric_limits<double>::infinity();
165 for (
const ZXPoint& p : points) {
166 if (p.first < lastZ) {
167 B2FATAL(
"createRotationSolid: Points have to be given with ascending z positions");
174 auto segStart = segments.begin();
175 auto segEnd = segStart;
177 for (; segEnd != segments.end(); ++segEnd) {
178 if ((p.first > segStart->first && p.first < segEnd->first) ||
179 (p.first < segStart->first && p.first > segEnd->first)) {
180 double dZ = segEnd->first - segStart->first;
181 double dX = segEnd->second - segStart->second;
182 double newX = segStart->second + dX * (p.first - segStart->first) / dZ;
183 segments.insert(segEnd, ZXPoint(p.first, newX));
191 if (points.front().first < segments.front().first) {
192 segments.insert(segments.begin(), points.front());
194 if (points.back().first > segments.back().first) {
195 segments.insert(segments.end(), points.back());
204 PointList innerPoints;
205 PointList outerPoints;
206 for (
const GearDir& point : params.getNodes(
"InnerPoints/point")) {
207 innerPoints.push_back(ZXPoint(point.getLength(
"z") /
Unit::mm, point.getLength(
"x") /
Unit::mm));
209 for (
const GearDir& point : params.getNodes(
"OuterPoints/point")) {
210 outerPoints.push_back(ZXPoint(point.getLength(
"z") /
Unit::mm, point.getLength(
"x") /
Unit::mm));
214 subdivideSegments(innerPoints, outerPoints);
215 subdivideSegments(outerPoints, innerPoints);
216 minZ = innerPoints.front().first;
217 maxZ = outerPoints.front().first;
220 std::vector<double> z;
221 std::vector<double> rMin;
222 std::vector<double> rMax;
229 while (!(innerPoints.empty() && outerPoints.empty())) {
230 bool popInner =
false;
235 if (!innerPoints.empty() && innerPoints.front().first <= outerPoints.front().first) {
236 boost::tie(innerZ, innerX) = innerPoints.front();
239 if (!outerPoints.empty() && outerPoints.front().first <= innerPoints.front().first) {
240 boost::tie(outerZ, outerX) = outerPoints.front();
241 outerPoints.pop_front();
243 if (popInner) innerPoints.pop_front();
244 if (innerZ != outerZ) {
245 B2ERROR(
"createRotationSolid: Something is wrong, z values should be identical");
249 rMin.push_back(innerX);
250 rMax.push_back(outerX);
254 int nPlanes = z.size();
255 double minPhi = params.getAngle(
"minPhi", 0);
256 double dPhi = params.getAngle(
"maxPhi", 2 * M_PI) - minPhi;
257 return new G4Polycone(name, minPhi, dPhi, nPlanes, &z.front(), &rMin.front(), &rMax.front());
271 std::list< std::pair<double, double> > innerPoints,
272 std::list< std::pair<double, double> > outerPoints,
273 double minPhi,
double maxPhi,
double& minZ,
double& maxZ)
277 subdivideSegments(innerPoints, outerPoints);
278 subdivideSegments(outerPoints, innerPoints);
279 minZ = innerPoints.front().first;
280 maxZ = outerPoints.front().first;
283 std::vector<double> z;
284 std::vector<double> rMin;
285 std::vector<double> rMax;
292 while (!(innerPoints.empty() && outerPoints.empty())) {
293 bool popInner =
false;
298 if (!innerPoints.empty() && innerPoints.front().first <= outerPoints.front().first) {
299 boost::tie(innerZ, innerX) = innerPoints.front();
302 if (!outerPoints.empty() && outerPoints.front().first <= innerPoints.front().first) {
303 boost::tie(outerZ, outerX) = outerPoints.front();
304 outerPoints.pop_front();
306 if (popInner) innerPoints.pop_front();
307 if (innerZ != outerZ) {
308 B2ERROR(
"createRotationSolid: Something is wrong, z values should be identical");
317 int nPlanes = z.size();
318 double dPhi = maxPhi - minPhi;
319 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, g, b) and return a corresp...
Abstract base class for different kinds of events.