File: | /group/halld/Software/builds/Linux_RHEL7-x86_64-gcc4.8.5/hdds/hdds-4.14.0/hddsCommon.cpp |
Location: | line 1686, column 19 |
Description: | Value stored to 'rMax' is never read |
1 | /* HDDS Common Classes |
2 | * |
3 | * Author: richard.t.jones@uconn.edu |
4 | * |
5 | * Original version - Richard Jones, January 6, 2006. |
6 | * Revision 1.1 - Richard Jones, September 10, 2013. |
7 | * |
8 | * Revision 1.1 Notes: |
9 | * ------------------- |
10 | * 1. Updated to HDDS-1.1 which adds support for geometry layers, using |
11 | * the geometry_layer="int" attribute of the object placement tags. |
12 | * |
13 | * Original Notes: |
14 | * --------------- |
15 | * 1. The HDDS specification is an xml document in the standard W3C |
16 | * schema namespace http://www.gluex.org/hdds, as described by the |
17 | * HDDS-1_0.xsd schema document. |
18 | * 2. Access to the xml source is through the industry-standard DOM interface. |
19 | * 3. The code has been tested with the xerces-c DOM implementation from |
20 | * Apache, and is intended to be used with the xerces-c library. |
21 | * 4. The common classes were created originally as tools for the hdds-geant |
22 | * converter to write Fortran geometry definition code for the Geant3 |
23 | * simulation. Later they were reused for other simulation packages, |
24 | * but occasionally the original purpose is still visible in comments |
25 | * and some of the implementation details. |
26 | * |
27 | * Implementation: |
28 | * --------------- |
29 | * Most of the translation was straight-forward, but there were a couple |
30 | * of tricky cases where decisions had to be made. I think that these |
31 | * choices should work out in most cases. If not, further tuning of the |
32 | * algorithm will be necessary. Here are the tricky cases. |
33 | * |
34 | * 1. When to use divisions instead of placing multiple copies. |
35 | * |
36 | * Most of the time when a <mpos...> command appears it can be translated |
37 | * into a division of the mother volume in Geant. This is good to do |
38 | * because it makes both more compact description and is more efficient |
39 | * at tracking time. The difficulty here is that there is no easy way |
40 | * to check if the contents fit entirely inside the division. This is |
41 | * not a problem in the HDDS geometry description because the <mpos...> |
42 | * command is only for positioning, and makes no statement about what |
43 | * slice of the mother it occupies. But it is a problem for Geant because |
44 | * contents of divisions have to fit inside the division. This can |
45 | * happen at any time, but it most frequently happens when the object |
46 | * is being rotated before placement, as in the case of stereo layers |
47 | * in a drift chamber. My solution is to make a strict set of rules |
48 | * that are required before hdds-geant will create a division in response |
49 | * to a <mpos...> command, and do individual placement by default. |
50 | * The rules for creation of divisions are as follows: |
51 | * (a) the <composition> command must have a solid container, either |
52 | * via the envelope="..." attribute or by itself being a division. |
53 | * (b) the <mpos...> command must be alone inside its <composition> |
54 | * (c) the kind of shape of the container must be compatible with the |
55 | * <mpos...> type, eg. <mposPhi> would work if its container is |
56 | * a "tubs" (or division theroef) but not if it is a "box". |
57 | * (d) for <mposPhi> the impliedRot attribute must be "true". |
58 | * (e) the rot="..." attribute must be zeros or missing. |
59 | * The last condition is not logically necessary for it to work, but it |
60 | * avoids the problems that often occur with rotated placements failing |
61 | * to fit inside the division. To bypass this limitation and place |
62 | * rotated volumes inside divisions, one can simply create a new volume |
63 | * as a <composition> into which the content is placed with rotation, |
64 | * and then place the new volume with the <mpos...> command without rot. |
65 | * |
66 | * 2. How to recognize which media contain magnetic fields. |
67 | * |
68 | * There is was originally no provision in the AGDD geometry model for |
69 | * magnetic field information. This information was introduced in HDDS |
70 | * through a new concept called a "region" and a new tag "apply" which |
71 | * associates a volume in the geometry definition with a region. For more |
72 | * information about the meaning of regions in HDDS and the methods for |
73 | * specifying a region's magnetic field, see the documentation in the |
74 | * HDDS schema file. Geant needs to distinguish between 4 cases: |
75 | * ifield=0 : no magnetic field |
76 | * ifield=1 : general case of inhomogenous field (Runge-Kutta) |
77 | * ifield=2 : quasi-homogenous field with map (helical segments) |
78 | * ifield=3 : uniform field (helices along local z-axis) |
79 | * For detector regions with no magnetic field, the volume is created with |
80 | * ifield=0. If a field map is provided for the region, it is assigned |
81 | * ifield=1 and the field interpolator is written as a part of the output |
82 | * code. If the field is uniform then it is assigned ifield=2 unless it |
83 | * is along the z-axis, in which case it is assigned ifield=3. |
84 | * |
85 | * 3. What to do about stackX/stackY/stackZ tags |
86 | * |
87 | * In the case of Boolean tags (union/intersection/subtraction) the choice |
88 | * was easy: no support in Geant3 for these cases. For the stacks it is |
89 | * possible to construct such structures in Geant3 but it is complicated |
90 | * by the fact that the stacks do not give information about the kind or |
91 | * size of volume that should be used for the mother. Since stacks can |
92 | * be implemented easily using compositions anyway, I decided not to include |
93 | * support for them in hdds-geant. |
94 | */ |
95 | |
96 | #include <xercesc/util/PlatformUtils.hpp> |
97 | #include <xercesc/util/XMLString.hpp> |
98 | #include <xercesc/util/XMLStringTokenizer.hpp> |
99 | #include <xercesc/sax/SAXParseException.hpp> |
100 | #include <xercesc/parsers/XercesDOMParser.hpp> |
101 | #include <xercesc/framework/LocalFileFormatTarget.hpp> |
102 | #include <xercesc/dom/DOM.hpp> |
103 | #include <xercesc/util/XercesDefs.hpp> |
104 | #include <xercesc/sax/ErrorHandler.hpp> |
105 | |
106 | using namespace xercesc; |
107 | |
108 | #include "XString.hpp" |
109 | #include "XParsers.hpp" |
110 | #include "hddsCommon.hpp" |
111 | |
112 | #include <assert.h> |
113 | #include <stdlib.h> |
114 | #include <ctype.h> |
115 | #include <stdio.h> |
116 | #include <math.h> |
117 | |
118 | #include <iostream> |
119 | #include <fstream> |
120 | #include <sstream> |
121 | #include <string> |
122 | #include <iomanip> |
123 | #include <vector> |
124 | #include <list> |
125 | |
126 | #define APP_NAME"hddsCommon" "hddsCommon" |
127 | |
128 | #define X(str)XString(str).unicode_str() XString(str).unicode_str() |
129 | #define S(str)str.c_str() str.c_str() |
130 | |
131 | #define NOT_USED(x)((void)(x)) ((void)(x)) |
132 | |
133 | /* Refsys class: |
134 | * Stores persistent information about coordinate |
135 | * reference systems which are used to orient and place |
136 | * volumes in the simulation geometry. |
137 | */ |
138 | |
139 | int Refsys::fVolumes = 0; |
140 | int Refsys::fRegions = 0; |
141 | int Refsys::fRotations = 0; |
142 | std::map<std::string,Refsys::VolIdent> Refsys::fIdentifiers; |
143 | std::vector<std::map<std::string,std::vector<int> > > Refsys::fIdentifierTable; |
144 | |
145 | Refsys::Refsys() // empty constructor |
146 | : fMother(0), |
147 | fRegion(0), |
148 | fPhiOffset(0), |
149 | fRegionID(0), |
150 | fGeometryLayer(0), |
151 | fRelativeLayer(0), |
152 | fIdentifier() |
153 | { |
154 | fMOrigin[0] = fMOrigin[1] = fMOrigin[2] = 0; |
155 | fMRmatrix[0][0] = fMRmatrix[1][1] = fMRmatrix[2][2] = 1; |
156 | fMRmatrix[0][1] = fMRmatrix[1][0] = fMRmatrix[1][2] = |
157 | fMRmatrix[0][2] = fMRmatrix[2][0] = fMRmatrix[2][1] = 0; |
158 | reset(); |
159 | } |
160 | |
161 | Refsys::Refsys(const Refsys& src) // copy constructor |
162 | : fMother(src.fMother), |
163 | fRegion(src.fRegion), |
164 | fPhiOffset(src.fPhiOffset), |
165 | fRegionID(src.fRegionID), |
166 | fGeometryLayer(src.fGeometryLayer), |
167 | fRelativeLayer(src.fRelativeLayer), |
168 | fIdentifier(src.fIdentifier), |
169 | fPartition(src.fPartition) |
170 | { |
171 | for (int i=0; i<3; i++) |
172 | { |
173 | fMOrigin[i] = src.fMOrigin[i]; |
174 | fMRmatrix[i][0] = src.fMRmatrix[i][0]; |
175 | fMRmatrix[i][1] = src.fMRmatrix[i][1]; |
176 | fMRmatrix[i][2] = src.fMRmatrix[i][2]; |
177 | } |
178 | std::map<std::string,double>::const_iterator iter; |
179 | for (iter = src.fPar.begin(); iter != src.fPar.end(); ++iter) |
180 | { |
181 | fPar[iter->first] = iter->second; |
182 | } |
183 | reset(src); |
184 | } |
185 | |
186 | Refsys& Refsys::operator=(const Refsys& src) // copy operator (deep sematics) |
187 | { |
188 | fIdentifier = src.fIdentifier; |
189 | fMother = src.fMother; |
190 | fRegion = src.fRegion; |
191 | fRegionID = src.fRegionID; |
192 | fGeometryLayer = src.fGeometryLayer; |
193 | fRelativeLayer = src.fRelativeLayer; |
194 | fPhiOffset = src.fPhiOffset; |
195 | fPartition = src.fPartition; |
196 | for (int i=0; i<3; i++) |
197 | { |
198 | fMOrigin[i] = src.fMOrigin[i]; |
199 | fMRmatrix[i][0] = src.fMRmatrix[i][0]; |
200 | fMRmatrix[i][1] = src.fMRmatrix[i][1]; |
201 | fMRmatrix[i][2] = src.fMRmatrix[i][2]; |
202 | } |
203 | std::map<std::string,double>::const_iterator iter; |
204 | for (iter = src.fPar.begin(); iter != src.fPar.end(); ++iter) |
205 | { |
206 | fPar[iter->first] = iter->second; |
207 | } |
208 | reset(src); |
209 | return *this; |
210 | } |
211 | |
212 | Refsys& Refsys::reset() // reset origin, Rmatrix to null |
213 | { |
214 | fOrigin[0] = fOrigin[1] = fOrigin[2] = 0; |
215 | fRmatrix[0][0] = fRmatrix[1][1] = fRmatrix[2][2] = 1; |
216 | fRmatrix[0][1] = fRmatrix[1][0] = fRmatrix[1][2] = |
217 | fRmatrix[0][2] = fRmatrix[2][0] = fRmatrix[2][1] = 0; |
218 | fRotation = 0; |
219 | return *this; |
220 | } |
221 | |
222 | Refsys& Refsys::reset(const Refsys& ref) // reset origin, Rmatrix to ref |
223 | { |
224 | for (int i = 0; i < 3; i++) |
225 | { |
226 | fOrigin[i] = ref.fOrigin[i]; |
227 | fRmatrix[i][0] = ref.fRmatrix[i][0]; |
228 | fRmatrix[i][1] = ref.fRmatrix[i][1]; |
229 | fRmatrix[i][2] = ref.fRmatrix[i][2]; |
230 | } |
231 | fRotation = ref.fRotation; |
232 | return *this; |
233 | } |
234 | |
235 | Refsys& Refsys::shift(const double vector[3]) // translate origin |
236 | { |
237 | for (int i = 0; i < 3; i++) |
238 | { |
239 | fOrigin[i] += fRmatrix[i][0] * vector[0] + |
240 | fRmatrix[i][1] * vector[1] + |
241 | fRmatrix[i][2] * vector[2]; |
242 | fMOrigin[i] += fMRmatrix[i][0] * vector[0] + |
243 | fMRmatrix[i][1] * vector[1] + |
244 | fMRmatrix[i][2] * vector[2]; |
245 | } |
246 | return *this; |
247 | } |
248 | |
249 | Refsys& Refsys::shift(const Refsys& ref) // copy origin from ref |
250 | { |
251 | fOrigin[0] = ref.fOrigin[0]; |
252 | fOrigin[1] = ref.fOrigin[1]; |
253 | fOrigin[2] = ref.fOrigin[2]; |
254 | fMOrigin[0] = ref.fMOrigin[0]; |
255 | fMOrigin[1] = ref.fMOrigin[1]; |
256 | fMOrigin[2] = ref.fMOrigin[2]; |
257 | return *this; |
258 | } |
259 | |
260 | Refsys& Refsys::shift(const Refsys& ref, |
261 | const double vector[3]) // translate origin in ref frame |
262 | { |
263 | Refsys myRef(ref); |
264 | myRef.shift(vector); |
265 | return shift(myRef); |
266 | } |
267 | |
268 | Refsys& Refsys::rotate(const double omega[3]) // rotate by vector omega (rad) |
269 | { |
270 | if ( (omega[0] != 0) || (omega[1] != 0) || (omega[2] != 0) ) |
271 | { |
272 | double cosx = cos(omega[0]); |
273 | double sinx = sin(omega[0]); |
274 | double cosy = cos(omega[1]); |
275 | double siny = sin(omega[1]); |
276 | double cosz = cos(omega[2]); |
277 | double sinz = sin(omega[2]); |
278 | |
279 | for (int i = 0; i < 3; i++) |
280 | { |
281 | double x[3]; |
282 | double xx[3]; |
283 | |
284 | x[0] = fRmatrix[i][0] * cosz + fRmatrix[i][1] * sinz; |
285 | x[1] = fRmatrix[i][1] * cosz - fRmatrix[i][0] * sinz; |
286 | x[2] = fRmatrix[i][2]; |
287 | xx[0] = x[0] * cosy - x[2] * siny; |
288 | xx[1] = x[1]; |
289 | xx[2] = x[2] * cosy + x[0] * siny; |
290 | fRmatrix[i][0] = xx[0]; |
291 | fRmatrix[i][1] = xx[1] * cosx + xx[2] * sinx; |
292 | fRmatrix[i][2] = xx[2] * cosx - xx[1] * sinx; |
293 | |
294 | x[0] = fMRmatrix[i][0] * cosz + fMRmatrix[i][1] * sinz; |
295 | x[1] = fMRmatrix[i][1] * cosz - fMRmatrix[i][0] * sinz; |
296 | x[2] = fMRmatrix[i][2]; |
297 | xx[0] = x[0] * cosy - x[2] * siny; |
298 | xx[1] = x[1]; |
299 | xx[2] = x[2] * cosy + x[0] * siny; |
300 | fMRmatrix[i][0] = xx[0]; |
301 | fMRmatrix[i][1] = xx[1] * cosx + xx[2] * sinx; |
302 | fMRmatrix[i][2] = xx[2] * cosx - xx[1] * sinx; |
303 | } |
304 | |
305 | fRotation = -1; |
306 | } |
307 | |
308 | return *this; |
309 | } |
310 | |
311 | Refsys& Refsys::rotate(const Refsys& ref) // copy Rmatrix from ref |
312 | { |
313 | for (int i = 0; i < 3; i++) |
314 | { |
315 | fRmatrix[i][0] = ref.fRmatrix[i][0]; |
316 | fRmatrix[i][1] = ref.fRmatrix[i][1]; |
317 | fRmatrix[i][2] = ref.fRmatrix[i][2]; |
318 | fMRmatrix[i][0] = ref.fMRmatrix[i][0]; |
319 | fMRmatrix[i][1] = ref.fMRmatrix[i][1]; |
320 | fMRmatrix[i][2] = ref.fMRmatrix[i][2]; |
321 | } |
322 | fRotation = ref.fRotation; |
323 | return *this; |
324 | } |
325 | |
326 | Refsys& Refsys::rotate(const Refsys& ref, |
327 | const double omega[3]) // rotate by omega in ref frame |
328 | { |
329 | Refsys myRef(ref); |
330 | myRef.rotate(omega); |
331 | return rotate(myRef); |
332 | } |
333 | |
334 | std::vector<double>& Refsys::getRotation() const |
335 | { |
336 | std::vector<double> *angles = new std::vector<double>(3); |
337 | if (fRmatrix[2][1] == 0 && fRmatrix[2][2] == 0) { |
338 | if (fRmatrix[2][0] < 0) { |
339 | (*angles)[0] = atan2(fRmatrix[0][1],fRmatrix[1][1]); |
340 | (*angles)[1] = M_PI3.14159265358979323846/2.; |
341 | (*angles)[2] = 0; |
342 | } |
343 | else { |
344 | (*angles)[0] = atan2(-fRmatrix[0][1],fRmatrix[1][1]); |
345 | (*angles)[1] = -M_PI3.14159265358979323846/2.; |
346 | (*angles)[2] = 0; |
347 | } |
348 | } |
349 | else { |
350 | (*angles)[0] = atan2(fRmatrix[2][1],fRmatrix[2][2]); |
351 | (*angles)[1] = atan2(-fRmatrix[2][0], |
352 | fRmatrix[2][2]/(cos((*angles)[0])+1e-100)); |
353 | (*angles)[2] = atan2(fRmatrix[1][0],fRmatrix[0][0]); |
354 | } |
355 | return *angles; |
356 | } |
357 | |
358 | std::vector<double>& Refsys::getMRotation() const |
359 | { |
360 | std::vector<double> *angles = new std::vector<double>(3); |
361 | if (fMRmatrix[2][1] == 0 && fMRmatrix[2][2] == 0) { |
362 | if (fMRmatrix[2][0] < 0) { |
363 | (*angles)[0] = atan2(fMRmatrix[0][1],fMRmatrix[1][1]); |
364 | (*angles)[1] = M_PI3.14159265358979323846/2.; |
365 | (*angles)[2] = 0; |
366 | } |
367 | else { |
368 | (*angles)[0] = atan2(-fMRmatrix[0][1],fMRmatrix[1][1]); |
369 | (*angles)[1] = -M_PI3.14159265358979323846/2.; |
370 | (*angles)[2] = 0; |
371 | } |
372 | } |
373 | else { |
374 | (*angles)[0] = atan2(fMRmatrix[2][1],fMRmatrix[2][2]); |
375 | (*angles)[1] = atan2(-fMRmatrix[2][0], |
376 | fMRmatrix[2][2]/(cos((*angles)[0])+1e-100)); |
377 | (*angles)[2] = atan2(fMRmatrix[1][0],fMRmatrix[0][0]); |
378 | } |
379 | return *angles; |
380 | } |
381 | |
382 | void Refsys::clearIdentifiers() |
383 | { |
384 | fIdentifier.clear(); |
385 | } |
386 | |
387 | void Refsys::incrementIdentifiers() |
388 | { |
389 | std::map<std::string,Refsys::VolIdent>::iterator iter; |
390 | for (iter = fIdentifier.begin(); iter != fIdentifier.end(); ++iter) |
391 | { |
392 | iter->second.value += iter->second.step; |
393 | } |
394 | } |
395 | |
396 | void Refsys::addIdentifier(XString ident, int value, int step) |
397 | { |
398 | VolIdent id; |
399 | id.value = value; |
400 | id.step = step; |
401 | fIdentifier[ident] = id; |
402 | fIdentifiers[ident] = id; |
403 | } |
404 | |
405 | int Refsys::nextRotationID() |
406 | { |
407 | return ++fRotations; |
408 | } |
409 | |
410 | int Refsys::nextVolumeID() |
411 | { |
412 | unsigned int ivolu = ++fVolumes; |
413 | while (fIdentifierTable.size() <= ivolu) |
414 | { |
415 | std::map<std::string,std::vector<int> > unmarked; |
416 | fIdentifierTable.push_back(unmarked); |
417 | } |
418 | return ivolu; |
419 | } |
420 | |
421 | int Refsys::nextRegionID() |
422 | { |
423 | return ++fRegions; |
424 | } |
425 | |
426 | /* Substance class: |
427 | * Computes and saves properties of materials that are used |
428 | * in the detector description, sometimes using directly the |
429 | * values in the hdds file and other times computing them |
430 | * based on the hdds information. |
431 | */ |
432 | |
433 | Substance::Substance() |
434 | : fUniqueID(0), |
435 | fBrewList(0), |
436 | fMaterialEl(0), |
437 | fAtomicWeight(0), |
438 | fAtomicNumber(0), |
439 | fDensity(-1), |
440 | fRadLen(0), |
441 | fAbsLen(0), |
442 | fColLen(0), |
443 | fMIdEdx(0) |
444 | {} |
445 | |
446 | Substance::Substance(const Substance& src) |
447 | : fUniqueID(src.fUniqueID), |
448 | fMaterialEl(src.fMaterialEl), |
449 | fAtomicWeight(src.fAtomicWeight), |
450 | fAtomicNumber(src.fAtomicNumber), |
451 | fDensity(src.fDensity), |
452 | fRadLen(src.fRadLen), |
453 | fAbsLen(src.fAbsLen), |
454 | fColLen(src.fColLen), |
455 | fMIdEdx(src.fMIdEdx) |
456 | { |
457 | std::list<Brew>::const_iterator iter; |
458 | for (iter = src.fBrewList.begin(); |
459 | iter != src.fBrewList.end(); |
460 | ++iter) |
461 | { |
462 | Brew formula = *iter; |
463 | formula.sub = new Substance(*iter->sub); |
464 | fBrewList.push_back(formula); |
465 | } |
466 | } |
467 | |
468 | Substance::Substance(DOMElement* elem) |
469 | : fUniqueID(0), |
470 | fBrewList(0), |
471 | fMaterialEl(elem), |
472 | fAtomicWeight(0), |
473 | fAtomicNumber(0), |
474 | fDensity(-1), |
475 | fRadLen(0), |
476 | fAbsLen(0), |
477 | fColLen(0), |
478 | fMIdEdx(0) |
479 | { |
480 | XString aS(fMaterialEl->getAttribute(X("a")XString("a").unicode_str())); |
481 | fAtomicWeight = atof(S(aS)aS.c_str()); |
482 | XString zS(fMaterialEl->getAttribute(X("z")XString("z").unicode_str())); |
483 | fAtomicNumber = atof(S(zS)zS.c_str()); |
484 | |
485 | double wfactSum = 0; |
486 | |
487 | DOMNode* cont; |
488 | for (cont = fMaterialEl->getFirstChild(); cont != 0; |
489 | cont = cont->getNextSibling()) |
490 | { |
491 | if (cont->getNodeType() == DOMNode::ELEMENT_NODE) |
492 | { |
493 | DOMElement* contEl = (DOMElement*)cont; |
494 | XString tagS(contEl->getTagName()); |
495 | if (tagS == "real") |
496 | { |
497 | Units unit; |
498 | unit.getConversions(contEl); |
499 | XString nameS(contEl->getAttribute(X("name")XString("name").unicode_str())); |
500 | XString valueS(contEl->getAttribute(X("value")XString("value").unicode_str())); |
501 | if (nameS == "density") |
502 | { |
503 | fDensity = atof(S(valueS)valueS.c_str()) /(unit.g/unit.cm3); |
504 | } |
505 | else if (nameS == "radlen") |
506 | { |
507 | fRadLen = atof(S(valueS)valueS.c_str()) /unit.cm; |
508 | } |
509 | else if (nameS == "abslen") |
510 | { |
511 | fAbsLen = atof(S(valueS)valueS.c_str()) /unit.cm; |
512 | } |
513 | else if (nameS == "collen") |
514 | { |
515 | fColLen = atof(S(valueS)valueS.c_str()) /unit.cm; |
516 | } |
517 | else if (nameS == "dedx") |
518 | { |
519 | fMIdEdx = atof(S(valueS)valueS.c_str()) /(unit.MeV/unit.cm); |
520 | } |
521 | } |
522 | else if (tagS == "addmaterial") |
523 | { |
524 | XString matS(contEl->getAttribute(X("material")XString("material").unicode_str())); |
525 | DOMDocument* document = fMaterialEl->getOwnerDocument(); |
526 | DOMElement* targEl = document->getElementById(X(matS)XString(matS).unicode_str()); |
527 | XString typeS(targEl->getTagName()); |
528 | Substance::Brew formula; |
529 | formula.sub = new Substance(targEl); |
530 | formula.natoms = 0; |
531 | formula.wfact = 0; |
532 | DOMNode* mix; |
533 | for (mix = contEl->getFirstChild(); mix != 0; |
534 | mix = mix->getNextSibling()) |
535 | { |
536 | if (mix->getNodeType() == DOMNode::ELEMENT_NODE) |
537 | { |
538 | DOMElement* mixEl = (DOMElement*)mix; |
539 | XString mixS(mixEl->getTagName()); |
540 | if (mixS == "natoms") |
541 | { |
542 | if (typeS != "element") |
543 | { |
544 | std::cerr << APP_NAME"hddsCommon" |
545 | << " - error processing composite " |
546 | << S(matS)matS.c_str() << std::endl |
547 | << "natoms can only be specified for elements." |
548 | << std::endl; |
549 | exit(1); |
550 | } |
551 | XString nS(mixEl->getAttribute(X("n")XString("n").unicode_str())); |
552 | formula.natoms = atoi(S(nS)nS.c_str()); |
553 | formula.wfact = formula.natoms * formula.sub->getAtomicWeight(); |
554 | } |
555 | else if (mixS == "fractionmass") |
556 | { |
557 | XString fS(mixEl->getAttribute(X("fraction")XString("fraction").unicode_str())); |
558 | formula.wfact = atof(S(fS)fS.c_str()); |
559 | } |
560 | } |
561 | } |
562 | fBrewList.push_back(formula); |
563 | wfactSum += formula.wfact; |
564 | } |
565 | } |
566 | } |
567 | |
568 | double aSum=0; double aNorm=0; |
569 | double zSum=0; double zNorm=0; |
570 | double densitySum=0; double densityNorm=0; |
571 | double radlenSum=0; double radlenNorm=0; |
572 | double abslenSum=0; double abslenNorm=0; |
573 | double collenSum=0; double collenNorm=0; |
574 | double dedxSum=0; double dedxNorm=0; |
575 | |
576 | std::list<Substance::Brew>::iterator iter; |
577 | for (iter = fBrewList.begin(); iter != fBrewList.end(); ++iter) |
578 | { |
579 | iter->wfact /= wfactSum; |
580 | double weight = (iter->natoms > 0)? |
581 | iter->natoms * iter->sub->fAtomicWeight : iter->wfact; |
582 | aSum += weight*iter->sub->fAtomicWeight; |
583 | aNorm += weight; |
584 | zSum += weight*iter->sub->fAtomicNumber; |
585 | zNorm += weight; |
586 | densitySum += weight/iter->sub->fDensity; |
587 | densityNorm += weight; |
588 | weight /= iter->sub->fDensity; |
589 | radlenSum += weight/(iter->sub->fRadLen + 1e-99); |
590 | radlenNorm += weight; |
591 | abslenSum += weight/(iter->sub->fAbsLen + 1e-99); |
592 | abslenNorm += weight; |
593 | collenSum += weight/(iter->sub->fColLen + 1e-99); |
594 | collenNorm += weight; |
595 | dedxSum += weight*iter->sub->fMIdEdx; |
596 | dedxNorm += weight; |
597 | } |
598 | |
599 | if (fAtomicWeight == 0 && aNorm > 0) |
600 | { |
601 | fAtomicWeight = aSum/aNorm; |
602 | } |
603 | |
604 | if (fAtomicNumber == 0 && zNorm > 0) |
605 | { |
606 | fAtomicNumber = zSum/zNorm; |
607 | } |
608 | |
609 | if (fDensity <= 0 && densitySum > 0) |
610 | { |
611 | fDensity = densityNorm/densitySum; |
612 | } |
613 | |
614 | if (fRadLen == 0 && radlenSum > 0) |
615 | { |
616 | fRadLen = radlenNorm/radlenSum; |
617 | } |
618 | |
619 | if (fAbsLen == 0 && abslenSum > 0) |
620 | { |
621 | fAbsLen = abslenNorm/abslenSum; |
622 | } |
623 | |
624 | if (fColLen == 0 && collenSum > 0) |
625 | { |
626 | fColLen = collenNorm/collenSum; |
627 | } |
628 | |
629 | if (fMIdEdx == 0 && dedxNorm > 0) |
630 | { |
631 | fMIdEdx = dedxSum/dedxNorm; |
632 | } |
633 | |
634 | if (fDensity < 0) |
635 | { |
636 | XString tagS(fMaterialEl->getTagName()); |
637 | XString nameS(fMaterialEl->getAttribute(X("name")XString("name").unicode_str())); |
638 | std::cerr |
639 | << APP_NAME"hddsCommon" << " error: " << S(tagS)tagS.c_str() << " " << S(nameS)nameS.c_str() |
640 | << ", atomic number " << fAtomicNumber |
641 | << ", atomic weight " << fAtomicWeight |
642 | << " is missing a density specification." << std::endl; |
643 | exit(1); |
644 | } |
645 | } |
646 | |
647 | Substance::~Substance() |
648 | { |
649 | std::list<Brew>::iterator iter; |
650 | for (iter = fBrewList.begin(); iter != fBrewList.end(); ++iter) |
651 | { |
652 | delete iter->sub; |
653 | } |
654 | } |
655 | |
656 | Substance& Substance::operator=(const Substance& src) |
657 | { |
658 | fMaterialEl = src.fMaterialEl; |
659 | fAtomicWeight = src.fAtomicWeight; |
660 | fAtomicNumber = src.fAtomicNumber; |
661 | fDensity = src.fDensity; |
662 | fRadLen = src.fRadLen; |
663 | fAbsLen = src.fAbsLen; |
664 | fColLen = src.fColLen; |
665 | fMIdEdx = src.fMIdEdx; |
666 | fUniqueID = src.fUniqueID; |
667 | fBrewList = src.fBrewList; |
668 | std::list<Brew>::iterator iter; |
669 | for (iter = fBrewList.begin(); |
670 | iter != fBrewList.end(); |
671 | ++iter) |
672 | { |
673 | iter->sub = new Substance(*iter->sub); |
674 | } |
675 | return *this; |
676 | } |
677 | |
678 | double Substance::getAtomicWeight() |
679 | { |
680 | return fAtomicWeight; |
681 | } |
682 | |
683 | double Substance::getAtomicNumber() |
684 | { |
685 | return fAtomicNumber; |
686 | } |
687 | |
688 | double Substance::getDensity() |
689 | { |
690 | return fDensity; |
691 | } |
692 | |
693 | double Substance::getRadLength() |
694 | { |
695 | return fRadLen; |
696 | } |
697 | |
698 | double Substance::getAbsLength() |
699 | { |
700 | return fAbsLen; |
701 | } |
702 | |
703 | double Substance::getColLength() |
704 | { |
705 | return fColLen; |
706 | } |
707 | |
708 | double Substance::getMIdEdx() |
709 | { |
710 | return fMIdEdx; |
711 | } |
712 | |
713 | XString Substance::getName() |
714 | { |
715 | return XString(fMaterialEl->getAttribute(X("name")XString("name").unicode_str())); |
716 | } |
717 | |
718 | XString Substance::getSymbol() |
719 | { |
720 | return XString(fMaterialEl->getAttribute(X("symbol")XString("symbol").unicode_str())); |
721 | } |
722 | |
723 | DOMElement* Substance::getDOMElement() |
724 | { |
725 | return fMaterialEl; |
726 | } |
727 | |
728 | |
729 | /* Units class: |
730 | * Provides conversion constants for convenient extraction of |
731 | * dimensioned parameters in the hdds file. |
732 | */ |
733 | |
734 | Units::Units() |
735 | { |
736 | set_1s(1.); |
737 | set_1cm(1.); |
738 | set_1rad(1.); |
739 | set_1MeV(1.); |
740 | set_1g(1.); |
741 | set_1cm2(1.); |
742 | set_1cm3(1.); |
743 | set_1G(1.); |
744 | percent = 0.01; |
745 | } |
746 | |
747 | Units::Units(const Units& u) |
748 | { |
749 | set_1s(u.s); |
750 | set_1cm(u.cm); |
751 | set_1rad(u.rad); |
752 | set_1MeV(u.MeV); |
753 | set_1g(u.g); |
754 | set_1cm2(u.cm2); |
755 | set_1cm3(u.cm3); |
756 | set_1G(u.G); |
757 | percent = 0.01; |
758 | } |
759 | |
760 | void Units::set_1s(double tu) |
761 | { |
762 | s=tu; |
763 | ns=s*1e-9; ms=s*1e-3; |
764 | min=s/60; hr=min/60; days=hr/24; weeks=days/7; |
765 | } |
766 | |
767 | void Units::set_1cm(double lu) |
768 | { |
769 | cm=lu; |
770 | m=cm*1e2; mm=m*1e-3; um=m*1e-6; nm=m*1e-9; km=m*1e3; |
771 | in=cm*2.54; ft=in*12; miles=ft*5280; mils=in*1e-3; |
772 | } |
773 | |
774 | void Units::set_1rad(double au) |
775 | { |
776 | rad=au; |
777 | mrad=rad*1e-3; urad=rad*1e-6; |
778 | deg=rad*M_PI3.14159265358979323846/180; arcmin=deg/60; arcsec=arcmin/60; |
779 | } |
780 | |
781 | void Units::set_1deg(double au) |
782 | { |
783 | deg=au; |
784 | arcmin=deg/60; arcsec=arcmin/60; |
785 | rad=deg*180/M_PI3.14159265358979323846; mrad=rad*1e-3; urad=rad*1e-6; |
786 | } |
787 | |
788 | void Units::set_1MeV(double eu) |
789 | { |
790 | MeV=eu; |
791 | eV=MeV*1e-6; KeV=eV*1e3; GeV=eV*1e9; TeV=eV*1e12; |
792 | } |
793 | |
794 | void Units::set_1g(double mu) |
795 | { |
796 | g=mu; |
797 | kg=g*1e3; mg=g*1e-3; |
798 | } |
799 | |
800 | void Units::set_1cm2(double l2u) |
801 | { |
802 | cm2=l2u; |
803 | m2=cm2*1e4; mm2=cm2*1e-2; |
804 | b=cm2*1e-24; mb=b*1e-3; ub=b*1e-6; nb=b*1e-9; pb=b*1e-12; |
805 | } |
806 | |
807 | void Units::set_1cm3(double l3u) |
808 | { |
809 | cm3=l3u; |
810 | ml=cm3; l=ml*1e3; |
811 | } |
812 | |
813 | void Units::set_1G(double bfu) |
814 | { |
815 | G=bfu; |
816 | kG=G*1e3; Tesla=kG*10; |
817 | } |
818 | |
819 | void Units::getConversions(DOMElement* el) |
820 | { |
821 | XString unitlS(el->getAttribute(X("unit_length")XString("unit_length").unicode_str())); |
822 | if (unitlS.size() == 0) |
823 | { |
824 | ; |
825 | } |
826 | else if (unitlS == "mm") |
827 | { |
828 | set_1cm(10); |
829 | } |
830 | else if (unitlS == "cm") |
831 | { |
832 | set_1cm(1); |
833 | } |
834 | else if (unitlS == "m") |
835 | { |
836 | set_1cm(0.01); |
837 | } |
838 | else if (unitlS == "km") |
839 | { |
840 | set_1cm(1e-5); |
841 | } |
842 | else if (unitlS == "um") |
843 | { |
844 | set_1cm(1e6); |
845 | } |
846 | else if (unitlS == "nm") |
847 | { |
848 | set_1cm(1e9); |
849 | } |
850 | else if (unitlS == "in") |
851 | { |
852 | set_1cm(1/2.54); |
853 | } |
854 | else if (unitlS == "ft") |
855 | { |
856 | set_1cm(1/(12*2.54)); |
857 | } |
858 | else if (unitlS == "mil") |
859 | { |
860 | set_1cm(1000/2.54); |
861 | } |
862 | else |
863 | { |
864 | XString tagS(el->getTagName()); |
865 | std::cerr |
866 | << APP_NAME"hddsCommon" << " error: unknown length unit " << S(unitlS)unitlS.c_str() |
867 | << " on tag " << S(tagS)tagS.c_str() << std::endl; |
868 | exit(1); |
869 | } |
870 | |
871 | XString unitaS = el->getAttribute(X("unit_angle")XString("unit_angle").unicode_str()); |
872 | if (unitaS.size() == 0) |
873 | { |
874 | ; |
875 | } |
876 | else if (unitaS == "deg") |
877 | { |
878 | set_1deg(1); |
879 | } |
880 | else if (unitaS == "rad") |
881 | { |
882 | set_1rad(1); |
883 | } |
884 | else if (unitaS == "mrad") |
885 | { |
886 | set_1rad(1e3); |
887 | } |
888 | else |
889 | { |
890 | XString tagS(el->getTagName()); |
891 | std::cerr |
892 | << APP_NAME"hddsCommon" << " error: unknown angle unit " << S(unitaS)unitaS.c_str() |
893 | << " on volume " << S(tagS)tagS.c_str() << std::endl; |
894 | exit(1); |
895 | } |
896 | |
897 | XString unitS = el->getAttribute(X("unit")XString("unit").unicode_str()); |
898 | if (unitS.size() == 0) |
899 | { |
900 | ; |
901 | } |
902 | else if (unitS == "mm") |
903 | { |
904 | set_1cm(10); |
905 | } |
906 | else if (unitS == "cm") |
907 | { |
908 | set_1cm(1); |
909 | } |
910 | else if (unitS == "m") |
911 | { |
912 | set_1cm(0.01); |
913 | } |
914 | else if (unitlS == "km") |
915 | { |
916 | set_1cm(1e-5); |
917 | } |
918 | else if (unitlS == "um") |
919 | { |
920 | set_1cm(1e6); |
921 | } |
922 | else if (unitlS == "nm") |
923 | { |
924 | set_1cm(1e9); |
925 | } |
926 | else if (unitlS == "in") |
927 | { |
928 | set_1cm(1/2.54); |
929 | } |
930 | else if (unitlS == "ft") |
931 | { |
932 | set_1cm(1/(12*2.54)); |
933 | } |
934 | else if (unitlS == "mil") |
935 | { |
936 | set_1cm(1000/2.54); |
937 | } |
938 | else if (unitaS == "deg") |
939 | { |
940 | set_1deg(1); |
941 | } |
942 | else if (unitaS == "rad") |
943 | { |
944 | set_1rad(1); |
945 | } |
946 | else if (unitaS == "mrad") |
947 | { |
948 | set_1rad(1e3); |
949 | } |
950 | else if (unitS == "eV") |
951 | { |
952 | set_1MeV(1e6); |
953 | } |
954 | else if (unitS == "KeV") |
955 | { |
956 | set_1MeV(1e3); |
957 | } |
958 | else if (unitS == "MeV") |
959 | { |
960 | set_1MeV(1); |
961 | } |
962 | else if (unitS == "GeV") |
963 | { |
964 | set_1MeV(1e-3); |
965 | } |
966 | else if (unitS == "g/cm^2") |
967 | { |
968 | set_1g(1); |
969 | set_1cm2(1); |
970 | } |
971 | else if (unitS == "g/cm^3") |
972 | { |
973 | set_1g(1); |
974 | set_1cm3(1); |
975 | } |
976 | else if (unitS == "MeV/g/cm^2") |
977 | { |
978 | set_1MeV(1); |
979 | set_1g(1); |
980 | set_1cm2(1); |
981 | } |
982 | else if (unitS == "Tesla" || unitS == "T") |
983 | { |
984 | set_1G(1e-4); |
985 | } |
986 | else if (unitS == "kG" || unitS == "kGs") |
987 | { |
988 | set_1G(1e-3); |
989 | } |
990 | else if (unitS == "G" || unitS == "Gs") |
991 | { |
992 | set_1G(1); |
993 | } |
994 | else if (unitS == "percent") |
995 | { |
996 | ; |
997 | } |
998 | else if (unitS == "none") |
999 | { |
1000 | ; |
1001 | } |
1002 | else |
1003 | { |
1004 | XString tagS(el->getTagName()); |
1005 | std::cerr |
1006 | << APP_NAME"hddsCommon" << " error: unknown unit " << S(unitS)unitS.c_str() |
1007 | << " on volume " << S(tagS)tagS.c_str() << std::endl; |
1008 | exit(1); |
1009 | } |
1010 | } |
1011 | |
1012 | #ifdef LINUX_CPUTIME_PROFILING |
1013 | CPUtimer::CPUtimer() |
1014 | { |
1015 | getRusage(); |
1016 | gettimeofday(&fClock0,&fTZ); |
1017 | fClockRef = fClock0; |
1018 | fRef = fLast; |
1019 | } |
1020 | |
1021 | double CPUtimer::getUserTime() |
1022 | { |
1023 | if (getRusage() == 0) |
1024 | { |
1025 | return fLast.ru_utime.tv_sec + fLast.ru_utime.tv_usec/1e6; |
1026 | } |
1027 | else |
1028 | { |
1029 | return -1; |
1030 | } |
1031 | } |
1032 | |
1033 | double CPUtimer::getSystemTime() |
1034 | { |
1035 | if (getRusage() == 0) |
1036 | { |
1037 | return fLast.ru_stime.tv_sec + fLast.ru_stime.tv_usec/1e6; |
1038 | } |
1039 | else |
1040 | { |
1041 | return -1; |
1042 | } |
1043 | } |
1044 | |
1045 | double CPUtimer::getRealTime() |
1046 | { |
1047 | if (getRusage() == 0) |
1048 | { |
1049 | return (fClock.tv_sec - fClock0.tv_sec) |
1050 | +(fClock.tv_usec - fClock0.tv_usec)/1e6; |
1051 | } |
1052 | else |
1053 | { |
1054 | return -1; |
1055 | } |
1056 | } |
1057 | |
1058 | double CPUtimer::getUserDelta() |
1059 | { |
1060 | if (getRusage() == 0) |
1061 | { |
1062 | return fLast.ru_utime.tv_sec + fLast.ru_utime.tv_usec/1e6 |
1063 | -(fRef.ru_utime.tv_sec + fRef.ru_utime.tv_usec/1e6); |
1064 | } |
1065 | else |
1066 | { |
1067 | return -1; |
1068 | } |
1069 | } |
1070 | |
1071 | double CPUtimer::getSystemDelta() |
1072 | { |
1073 | if (getRusage() == 0) |
1074 | { |
1075 | return fLast.ru_stime.tv_sec + fLast.ru_stime.tv_usec/1e6 |
1076 | -(fRef.ru_stime.tv_sec + fRef.ru_stime.tv_usec/1e6); |
1077 | } |
1078 | else |
1079 | { |
1080 | return -1; |
1081 | } |
1082 | } |
1083 | |
1084 | double CPUtimer::getRealDelta() |
1085 | { |
1086 | if (getRusage() == 0) |
1087 | { |
1088 | return (fClock.tv_sec - fClockRef.tv_sec) |
1089 | +(fClock.tv_usec - fClockRef.tv_usec)/1e6; |
1090 | } |
1091 | else |
1092 | { |
1093 | return -1; |
1094 | } |
1095 | } |
1096 | |
1097 | void CPUtimer::resetClocks() |
1098 | { |
1099 | getRusage(); |
1100 | fRef = fLast; |
1101 | fClockRef = fClock; |
1102 | } |
1103 | |
1104 | int CPUtimer::getRusage() |
1105 | { |
1106 | return getrusage(RUSAGE_SELF,&fLast) + gettimeofday(&fClock,&fTZ); |
1107 | } |
1108 | |
1109 | CPUtimer timer; |
1110 | #endif |
1111 | |
1112 | int CodeWriter::createMaterial(DOMElement* el) |
1113 | { |
1114 | static int imateCount = 0; |
1115 | int imate = ++imateCount; |
1116 | std::stringstream imateStr; |
1117 | imateStr << imate; |
1118 | el->setAttribute(X("HDDSmate")XString("HDDSmate").unicode_str(),X(imateStr.str())XString(imateStr.str()).unicode_str()); |
1119 | |
1120 | Substance subst(el); |
1121 | std::list<Substance::Brew>::iterator iter; |
1122 | for (iter = subst.fBrewList.begin(); |
1123 | iter != subst.fBrewList.end(); ++iter) |
1124 | { |
1125 | DOMElement* subEl = iter->sub->getDOMElement(); |
1126 | XString subS(subEl->getAttribute(X("HDDSmate")XString("HDDSmate").unicode_str())); |
1127 | iter->sub->fUniqueID = atoi(S(subS)subS.c_str()); |
1128 | if (iter->sub->fUniqueID == 0) |
1129 | { |
1130 | iter->sub->fUniqueID = createMaterial(subEl); |
1131 | } |
1132 | } |
1133 | fSubst = subst; |
1134 | return imate; |
1135 | } |
1136 | |
1137 | int CodeWriter::createSolid(DOMElement* el, Refsys& ref) |
1138 | { |
1139 | XString nameS(el->getAttribute(X("name")XString("name").unicode_str())); |
1140 | XString matS(el->getAttribute(X("material")XString("material").unicode_str())); |
1141 | |
1142 | DOMDocument* document = el->getOwnerDocument(); |
1143 | DOMElement* matEl = document->getElementById(X(matS)XString(matS).unicode_str()); |
1144 | if (matEl == 0) |
1145 | { |
1146 | std::cerr << APP_NAME"hddsCommon" << " error: material " << S(matS)matS.c_str() |
1147 | << " is referenced but not defined." << std::endl; |
1148 | exit(1); |
1149 | } |
1150 | XString imateS(matEl->getAttribute(X("HDDSmate")XString("HDDSmate").unicode_str())); |
1151 | if (imateS.size() != 0) |
1152 | { |
1153 | fSubst.fUniqueID = atoi(S(imateS)imateS.c_str()); |
1154 | } |
1155 | else |
1156 | { |
1157 | fSubst.fUniqueID = createMaterial(matEl); |
1158 | } |
1159 | |
1160 | int ivolu = ref.nextVolumeID(); |
1161 | std::stringstream ivoluStr; |
1162 | ivoluStr << ivolu; |
1163 | el->setAttribute(X("HDDSvolu")XString("HDDSvolu").unicode_str(),X(ivoluStr.str())XString(ivoluStr.str()).unicode_str()); |
1164 | el->setAttribute(X("HDDScopy")XString("HDDScopy").unicode_str(),X("0")XString("0").unicode_str()); |
1165 | |
1166 | return ivolu; |
1167 | } |
1168 | |
1169 | int CodeWriter::createRotation(Refsys& ref) |
1170 | { |
1171 | if (ref.fRotation < 0) |
1172 | { |
1173 | ref.fRotation = ref.nextRotationID(); |
1174 | } |
1175 | return ref.fRotation; |
1176 | } |
1177 | |
1178 | int CodeWriter::createRegion(DOMElement* el, Refsys& ref) |
1179 | { |
1180 | int iregion = ref.nextRegionID(); |
1181 | |
1182 | XString regionS(el->getAttribute(X("region")XString("region").unicode_str())); |
1183 | DOMDocument* document = el->getOwnerDocument(); |
1184 | ref.fRegion = document->getElementById(X(regionS)XString(regionS).unicode_str()); |
1185 | ref.fRegionID = iregion; |
1186 | |
1187 | double origin[3], angle[3]; |
1188 | XString rotS(el->getAttribute(X("rot")XString("rot").unicode_str())); |
1189 | std::stringstream listr(rotS); |
1190 | listr >> angle[0] >> angle[1] >> angle[2]; |
1191 | Units unit; |
1192 | unit.getConversions(el); |
1193 | angle[0] /= unit.rad; |
1194 | angle[1] /= unit.rad; |
1195 | angle[2] /= unit.rad; |
1196 | XString xyzS(el->getAttribute(X("origin")XString("origin").unicode_str())); |
1197 | listr.clear(), listr.str(xyzS); |
1198 | listr >> origin[0] >> origin[1] >> origin[2]; |
1199 | origin[0] /= unit.cm; |
1200 | origin[1] /= unit.cm; |
1201 | origin[2] /= unit.cm; |
1202 | ref.shift(origin); |
1203 | ref.rotate(angle); |
1204 | |
1205 | std::stringstream attStr; |
1206 | attStr << iregion; |
1207 | el->setAttribute(X("HDDSregion")XString("HDDSregion").unicode_str(),X(attStr.str())XString(attStr.str()).unicode_str()); |
1208 | DOMElement* regEl = document->createElement(X("HDDSregion")XString("HDDSregion").unicode_str()); |
1209 | regEl->setAttribute(X("id")XString("id").unicode_str(),X(attStr.str())XString(attStr.str()).unicode_str()); |
1210 | |
1211 | attStr.clear(), attStr.str(""); |
1212 | attStr << ref.fMOrigin[0] << " " |
1213 | << ref.fMOrigin[1] << " " |
1214 | << ref.fMOrigin[2]; |
1215 | regEl->setAttribute(X("origin")XString("origin").unicode_str(),X(attStr.str())XString(attStr.str()).unicode_str()); |
1216 | attStr.clear(), attStr.str(""); |
1217 | attStr << ref.fMRmatrix[0][0] << " " |
1218 | << ref.fMRmatrix[0][1] << " " |
1219 | << ref.fMRmatrix[0][2] << " " |
1220 | << ref.fMRmatrix[1][0] << " " |
1221 | << ref.fMRmatrix[1][1] << " " |
1222 | << ref.fMRmatrix[1][2] << " " |
1223 | << ref.fMRmatrix[2][0] << " " |
1224 | << ref.fMRmatrix[2][1] << " " |
1225 | << ref.fMRmatrix[2][2]; |
1226 | regEl->setAttribute(X("Rmatrix")XString("Rmatrix").unicode_str(),X(attStr.str())XString(attStr.str()).unicode_str()); |
1227 | ref.fRegion->appendChild(regEl); |
1228 | |
1229 | for (DOMNode* cont = ref.fRegion->getFirstChild(); |
1230 | cont != 0; |
1231 | cont = cont->getNextSibling()) |
1232 | { |
1233 | if (cont->getNodeType() == DOMNode::ELEMENT_NODE) |
1234 | { |
1235 | XString tagS(((DOMElement*)cont)->getTagName()); |
1236 | if (tagS.find("Bfield") != XString::npos) |
1237 | { |
1238 | ref.addIdentifier(XString("map"),iregion,0); |
1239 | break; |
1240 | } |
1241 | } |
1242 | } |
1243 | return iregion; |
1244 | } |
1245 | |
1246 | int CodeWriter::createDivision(XString& divStr, Refsys& ref) |
1247 | { |
1248 | int ncopy = ref.fPartition.ncopy; |
1249 | int ivolu = ref.nextVolumeID(); |
1250 | |
1251 | assert (ref.fMother != 0)((ref.fMother != 0) ? static_cast<void> (0) : __assert_fail ("ref.fMother != 0", "/group/halld/Software/builds/Linux_RHEL7-x86_64-gcc4.8.5/hdds/hdds-4.14.0/hddsCommon.cpp" , 1251, __PRETTY_FUNCTION__)); |
1252 | |
1253 | std::stringstream attStr; |
1254 | DOMDocument* document = ref.fMother->getOwnerDocument(); |
1255 | DOMElement* divEl = document->createElement(X("HDDSdivision")XString("HDDSdivision").unicode_str()); |
1256 | divEl->setAttribute(X("name")XString("name").unicode_str(),X(divStr)XString(divStr).unicode_str()); |
1257 | XString motherS(ref.fMother->getAttribute(X("name")XString("name").unicode_str())); |
1258 | divEl->setAttribute(X("volume")XString("volume").unicode_str(),X(motherS)XString(motherS).unicode_str()); |
1259 | attStr << ivolu; |
1260 | divEl->setAttribute(X("HDDSvolu")XString("HDDSvolu").unicode_str(),X(attStr.str())XString(attStr.str()).unicode_str()); |
1261 | std::stringstream copyStr; |
1262 | copyStr << ncopy; |
1263 | divEl->setAttribute(X("HDDScopy")XString("HDDScopy").unicode_str(),X(copyStr.str())XString(copyStr.str()).unicode_str()); |
1264 | ref.fMother->appendChild(divEl); |
1265 | ref.fPartition.divEl = divEl; |
1266 | |
1267 | std::map<std::string,Refsys::VolIdent>::iterator iter; |
1268 | for (iter = ref.fIdentifier.begin(); |
1269 | iter != ref.fIdentifier.end(); |
1270 | ++iter) |
1271 | { |
1272 | int value = iter->second.value; |
1273 | int step = iter->second.step; |
1274 | XString fieldS(iter->first); |
1275 | std::vector<int>* idlist = &Refsys::fIdentifierTable[ivolu][fieldS]; |
1276 | for (int ic = 0; ic < ncopy; ic++) |
1277 | { |
1278 | idlist->push_back(value); |
1279 | value += step; |
1280 | } |
1281 | } |
1282 | Refsys::fIdentifierTable[ivolu]["copy counter"].push_back(ncopy); |
1283 | ref.clearIdentifiers(); |
1284 | return ncopy; |
1285 | } |
1286 | |
1287 | int CodeWriter::createVolume(DOMElement* el, Refsys& ref) |
1288 | { |
1289 | fPending = false; |
1290 | int icopy = 0; |
1291 | |
1292 | XString tagS(el->getTagName()); |
1293 | XString nameS(el->getAttribute(X("name")XString("name").unicode_str())); |
1294 | |
1295 | Refsys myRef(ref); |
1296 | DOMElement* env = 0; |
1297 | DOMDocument* document = el->getOwnerDocument(); |
1298 | XString envS(el->getAttribute(X("envelope")XString("envelope").unicode_str())); |
1299 | if (envS.size() != 0) |
1300 | { |
1301 | env = document->getElementById(X(envS)XString(envS).unicode_str()); |
1302 | XString containS(env->getAttribute(X("contains")XString("contains").unicode_str())); |
1303 | if (containS == nameS) |
1304 | { |
1305 | return createVolume(env,myRef); |
1306 | } |
1307 | else if (containS.size() != 0) |
1308 | { |
1309 | std::cerr |
1310 | << APP_NAME"hddsCommon" << " error: re-use of shape " << S(envS)envS.c_str() |
1311 | << " is not allowed by " << APP_NAME"hddsCommon" << std::endl; |
1312 | exit(1); |
1313 | } |
1314 | |
1315 | DOMNode* cont; |
1316 | for (cont = env->getFirstChild(); |
1317 | cont != 0; |
1318 | cont = cont->getNextSibling()) |
1319 | { |
1320 | if (cont->getNodeType() != DOMNode::ELEMENT_NODE) |
1321 | { |
1322 | continue; |
1323 | } |
1324 | DOMElement* contEl = (DOMElement*) cont; |
1325 | XString comdS(contEl->getTagName()); |
1326 | if (comdS == "apply") |
1327 | { |
1328 | Refsys drs(myRef); |
1329 | myRef.fRegionID = createRegion(contEl,drs); |
1330 | myRef.fIdentifier["map"] = drs.fIdentifier["map"]; |
1331 | myRef.fRegion = drs.fRegion; |
1332 | myRef.fPar = drs.fPar; |
1333 | } |
1334 | } |
1335 | |
1336 | env->setAttribute(X("contains")XString("contains").unicode_str(),X(nameS)XString(nameS).unicode_str()); |
1337 | icopy = createVolume(env,myRef); |
1338 | myRef.clearIdentifiers(); |
1339 | myRef.fMother = env; |
1340 | myRef.reset(); |
1341 | } |
1342 | |
1343 | if (tagS == "intersection" || |
1344 | tagS == "subtraction" || |
1345 | tagS == "union") |
1346 | { |
1347 | std::cerr |
1348 | << APP_NAME"hddsCommon" << " error: boolean " << S(tagS)tagS.c_str() |
1349 | << " operator is not supported by "<< APP_NAME"hddsCommon" << std::endl; |
1350 | exit(1); |
1351 | } |
1352 | else if (tagS == "composition") |
1353 | { |
1354 | DOMNode* cont; |
1355 | int nSiblings = 0; |
1356 | for (cont = el->getFirstChild(); |
1357 | cont != 0; |
1358 | cont = cont->getNextSibling()) |
1359 | { |
1360 | if (cont->getNodeType() == DOMNode::ELEMENT_NODE) |
1361 | { |
1362 | ++nSiblings; |
1363 | } |
1364 | } |
1365 | |
1366 | for (cont = el->getFirstChild(); |
1367 | cont != 0; |
1368 | cont = cont->getNextSibling()) |
1369 | { |
1370 | if (cont->getNodeType() != DOMNode::ELEMENT_NODE) |
1371 | { |
1372 | continue; |
1373 | } |
1374 | DOMElement* contEl = (DOMElement*) cont; |
1375 | XString comdS(contEl->getTagName()); |
1376 | XString targS(contEl->getAttribute(X("volume")XString("volume").unicode_str())); |
1377 | DOMElement* targEl = document->getElementById(X(targS)XString(targS).unicode_str()); |
1378 | |
1379 | Refsys drs(myRef); |
1380 | double origin[3], angle[3]; |
1381 | XString rotS(contEl->getAttribute(X("rot")XString("rot").unicode_str())); |
1382 | std::stringstream listr1(rotS); |
1383 | listr1 >> angle[0] >> angle[1] >> angle[2]; |
1384 | Units unit; |
1385 | unit.getConversions(contEl); |
1386 | angle[0] /= unit.rad; |
1387 | angle[1] /= unit.rad; |
1388 | angle[2] /= unit.rad; |
1389 | bool noRotation = (angle[0] == 0) && |
1390 | (angle[1] == 0) && |
1391 | (angle[2] == 0) ; |
1392 | |
1393 | DOMNode* ident; |
1394 | for (ident = cont->getFirstChild(); |
1395 | ident != 0; |
1396 | ident = ident->getNextSibling()) |
1397 | { |
1398 | if (ident->getNodeType() != DOMNode::ELEMENT_NODE) |
1399 | { |
1400 | continue; |
1401 | } |
1402 | DOMElement* identEl = (DOMElement*) ident; |
1403 | XString fieldS(identEl->getAttribute(X("field")XString("field").unicode_str())); |
1404 | XString valueS(identEl->getAttribute(X("value")XString("value").unicode_str())); |
1405 | XString stepS(identEl->getAttribute(X("step")XString("step").unicode_str())); |
1406 | drs.addIdentifier(fieldS,atoi(S(valueS)valueS.c_str()),atoi(S(stepS)stepS.c_str())); |
1407 | } |
1408 | |
1409 | XString geolayerS(contEl->getAttribute(X("geometry_layer")XString("geometry_layer").unicode_str())); |
1410 | if (geolayerS.size() != 0) |
1411 | { |
1412 | std::stringstream geolayerStr(geolayerS); |
1413 | geolayerStr >> drs.fRelativeLayer; |
1414 | } |
1415 | else |
1416 | { |
1417 | drs.fRelativeLayer = 0; |
1418 | } |
1419 | drs.fGeometryLayer += drs.fRelativeLayer; |
1420 | |
1421 | if (comdS == "posXYZ") |
1422 | { |
1423 | XString xyzS(contEl->getAttribute(X("X_Y_Z")XString("X_Y_Z").unicode_str())); |
1424 | std::stringstream listr(xyzS); |
1425 | listr >> origin[0] >> origin[1] >> origin[2]; |
1426 | origin[0] /= unit.cm; |
1427 | origin[1] /= unit.cm; |
1428 | origin[2] /= unit.cm; |
1429 | drs.shift(origin); |
1430 | drs.rotate(angle); |
1431 | createVolume(targEl,drs); |
1432 | } |
1433 | else if (comdS == "posRPhiZ") |
1434 | { |
1435 | double r, phi, z; |
1436 | XString rphizS(contEl->getAttribute(X("R_Phi_Z")XString("R_Phi_Z").unicode_str())); |
1437 | std::stringstream listr(rphizS); |
1438 | listr >> r >> phi >> z; |
1439 | double s; |
1440 | XString sS(contEl->getAttribute(X("S")XString("S").unicode_str())); |
1441 | s = atof(S(sS)sS.c_str()); |
1442 | phi /= unit.rad; |
1443 | r /= unit.cm; |
1444 | z /= unit.cm; |
1445 | s /= unit.cm; |
1446 | origin[0] = r * cos(phi) - s * sin(phi); |
1447 | origin[1] = r * sin(phi) + s * cos(phi); |
1448 | origin[2] = z; |
1449 | XString implrotS(contEl->getAttribute(X("impliedRot")XString("impliedRot").unicode_str())); |
1450 | if (implrotS == "true" && (phi != 0)) |
1451 | { |
1452 | angle[2] += phi; |
1453 | } |
1454 | drs.shift(origin); |
1455 | drs.rotate(angle); |
1456 | createVolume(targEl,drs); |
1457 | } |
1458 | else if (comdS == "mposPhi") |
1459 | { |
1460 | XString ncopyS(contEl->getAttribute(X("ncopy")XString("ncopy").unicode_str())); |
1461 | int ncopy = atoi(S(ncopyS)ncopyS.c_str()); |
1462 | if (ncopy <= 0) |
1463 | { |
1464 | std::cerr |
1465 | << APP_NAME"hddsCommon" << " error: volume " << S(nameS)nameS.c_str() |
1466 | << " is positioned with " << ncopy << " copies!" |
1467 | << std::endl; |
1468 | exit(1); |
1469 | } |
1470 | |
1471 | double phi0, dphi; |
1472 | XString phi0S(contEl->getAttribute(X("Phi0")XString("Phi0").unicode_str())); |
1473 | phi0 = atof(S(phi0S)phi0S.c_str()) /unit.rad; |
1474 | XString dphiS(contEl->getAttribute(X("dPhi")XString("dPhi").unicode_str())); |
1475 | if (dphiS.size() != 0) |
1476 | { |
1477 | dphi = atof(S(dphiS)dphiS.c_str()) /unit.rad; |
1478 | } |
1479 | else |
1480 | { |
1481 | dphi = 2 * M_PI3.14159265358979323846 / ncopy; |
1482 | } |
1483 | |
1484 | double r, s, z; |
1485 | XString rzS(contEl->getAttribute(X("R_Z")XString("R_Z").unicode_str())); |
1486 | std::stringstream listr(rzS); |
1487 | listr >> r >> z; |
1488 | XString sS(contEl->getAttribute(X("S")XString("S").unicode_str())); |
1489 | s = atof(S(sS)sS.c_str()); |
1490 | r /= unit.cm; |
1491 | z /= unit.cm; |
1492 | s /= unit.cm; |
1493 | |
1494 | XString containerS; |
1495 | XString containerTypeS; |
1496 | if (env != 0) |
1497 | { |
1498 | containerS = env->getAttribute(X("name")XString("name").unicode_str()); |
1499 | containerTypeS = env->getTagName(); |
1500 | } |
1501 | else |
1502 | { |
1503 | containerS = el->getAttribute(X("container_name")XString("container_name").unicode_str()); |
1504 | containerTypeS = el->getAttribute(X("container_type")XString("container_type").unicode_str()); |
1505 | env = document->getElementById(X(containerS)XString(containerS).unicode_str()); |
1506 | } |
1507 | XString implrotS(contEl->getAttribute(X("impliedRot")XString("impliedRot").unicode_str())); |
1508 | XString targTagS(targEl->getTagName()); |
1509 | XString targEnvS(targEl->getAttribute(X("envelope")XString("envelope").unicode_str())); |
1510 | DOMElement* targEnv; |
1511 | if (targEnvS.size() != 0) |
1512 | { |
1513 | targEnv = document->getElementById(X(targEnvS)XString(targEnvS).unicode_str()); |
1514 | } |
1515 | else |
1516 | { |
1517 | targEnv = targEl; |
1518 | } |
1519 | if (noRotation && (nSiblings == 1) && |
1520 | (containerTypeS == "pcon" || |
1521 | containerTypeS == "cons" || |
1522 | containerTypeS == "tubs") && |
1523 | (implrotS == "true")) |
1524 | { |
1525 | double phiMax, phiMin, dphiM; |
1526 | XString envProfS(env->getAttribute(X("profile")XString("profile").unicode_str())); |
1527 | if (envProfS.size() > 0) |
1528 | { |
1529 | std::stringstream profstr(envProfS); |
1530 | profstr >> phiMin >> dphiM; |
1531 | Units munit; |
1532 | munit.getConversions(env); |
1533 | phiMin /= munit.deg; |
1534 | dphiM /= munit.deg; |
1535 | phiMax = phiMin + dphiM; |
1536 | } |
1537 | else { |
1538 | phiMin = 0; |
1539 | phiMax = 360; |
1540 | } |
1541 | phi0 *= unit.rad /unit.deg; |
1542 | dphi *= unit.rad /unit.deg; |
1543 | double phigap = phi0-phiMin; |
1544 | double phipull = dphi/2; |
1545 | if (phiMax < phiMin + 360) |
1546 | { |
1547 | phipull = (phipull > phigap)? phigap : phipull; |
1548 | } |
1549 | if (phi0 - phipull + ncopy*dphi > phiMax) |
1550 | { |
1551 | std::cerr |
1552 | << APP_NAME"hddsCommon" << " error: volume " << S(nameS)nameS.c_str() |
1553 | << " overflows " << phiMax |
1554 | << " degrees when positioned with " |
1555 | << ncopy << " copies starting at " |
1556 | << phi0 << " degrees and spaced " |
1557 | << dphi << " degrees apart." |
1558 | << std::endl; |
1559 | exit(1); |
1560 | } |
1561 | double phi1=0, dphi1=0; |
1562 | XString targProfS(targEnv->getAttribute(X("profile")XString("profile").unicode_str())); |
1563 | if (r == 0 && s == 0 && targProfS.size() > 0) |
1564 | { |
1565 | std::stringstream profstr(targProfS); |
1566 | profstr >> phi1 >> dphi1; |
1567 | Units tunit; |
1568 | tunit.getConversions(targEnv); |
1569 | phi1 /= tunit.deg; |
1570 | dphi1 /= tunit.deg; |
1571 | } |
1572 | if (phipull+phi1 < -0.001 || phipull+phi1+dphi1 > dphi+0.001) |
1573 | { |
1574 | std::cerr |
1575 | << APP_NAME"hddsCommon" << " error: volume " << S(targS)targS.c_str() |
1576 | << " overflows its sector division of size " |
1577 | << dphi << " degrees." |
1578 | << std::endl; |
1579 | exit(1); |
1580 | } |
1581 | static int phiDivisions = 0xd00; |
1582 | std::stringstream divStr; |
1583 | divStr << "s" << std::setfill('0') << std::setw(3) << std::hex |
1584 | << ++phiDivisions; |
1585 | drs.fPartition.ncopy = ncopy; |
1586 | drs.fPartition.axis = "phi"; |
1587 | drs.fPartition.start = phi0 - phipull - myRef.fPhiOffset; |
1588 | drs.fPartition.offset = drs.fPartition.start - phiMin; |
1589 | drs.fPartition.step = dphi; |
1590 | XString divS(divStr.str()); |
1591 | createDivision(divS, drs); |
1592 | drs.fMother = drs.fPartition.divEl; |
1593 | targEl->setAttribute(X("container_name")XString("container_name").unicode_str(),X(containerS)XString(containerS).unicode_str()); |
1594 | targEl->setAttribute(X("container_type")XString("container_type").unicode_str(),X(containerTypeS)XString(containerTypeS).unicode_str()); |
1595 | drs.reset(); |
1596 | |
1597 | double phioffset = dphi/2 - phipull; |
1598 | if (fabs(phioffset) > 0.001) |
1599 | { |
1600 | angle[0] = 0; |
1601 | angle[1] = 0; |
1602 | angle[2] = -phioffset*unit.deg /unit.rad; |
1603 | drs.rotate(angle); |
1604 | } |
1605 | origin[0] = r; |
1606 | origin[1] = s; |
1607 | origin[2] = z; |
1608 | drs.shift(origin); |
1609 | createVolume(targEl,drs); |
1610 | } |
1611 | else |
1612 | { |
1613 | Refsys drs0(drs); |
1614 | drs.rotate(angle); |
1615 | for (int inst = 0; inst < ncopy; inst++) |
1616 | { |
1617 | double phi = phi0 + inst * dphi; |
1618 | origin[0] = r * cos(phi) - s * sin(phi); |
1619 | origin[1] = r * sin(phi) + s * cos(phi); |
1620 | origin[2] = z; |
1621 | drs.shift(drs0, origin); |
1622 | if (implrotS == "true") |
1623 | { |
1624 | angle[2] += ((inst == 0) ? phi0 : dphi); |
1625 | drs.rotate(drs0, angle); |
1626 | } |
1627 | createVolume(targEl,drs); |
1628 | drs.incrementIdentifiers(); |
1629 | } |
1630 | } |
1631 | } |
1632 | else if (comdS == "mposR") |
1633 | { |
1634 | XString ncopyS(contEl->getAttribute(X("ncopy")XString("ncopy").unicode_str())); |
1635 | int ncopy = atoi(S(ncopyS)ncopyS.c_str()); |
1636 | if (ncopy <= 0) |
1637 | { |
1638 | std::cerr |
1639 | << APP_NAME"hddsCommon" << " error: volume " << S(nameS)nameS.c_str() |
1640 | << " is positioned with " << ncopy << " copies!" |
1641 | << std::endl; |
1642 | exit(1); |
1643 | } |
1644 | |
1645 | double r0, dr; |
1646 | XString r0S(contEl->getAttribute(X("R0")XString("R0").unicode_str())); |
1647 | r0 = atof(S(r0S)r0S.c_str()) /unit.cm; |
1648 | XString drS(contEl->getAttribute(X("dR")XString("dR").unicode_str())); |
1649 | dr = atof(S(drS)drS.c_str()) /unit.cm; |
1650 | |
1651 | double phi, z, s; |
1652 | XString zphiS(contEl->getAttribute(X("Z_Phi")XString("Z_Phi").unicode_str())); |
1653 | std::stringstream listr(zphiS); |
1654 | listr >> z >> phi; |
1655 | XString sS(contEl->getAttribute(X("S")XString("S").unicode_str())); |
1656 | s = atof(S(sS)sS.c_str()); |
1657 | phi /= unit.rad; |
1658 | z /= unit.cm; |
1659 | s /= unit.cm; |
1660 | |
1661 | XString containerS; |
1662 | XString containerTypeS; |
1663 | if (env != 0) |
1664 | { |
1665 | containerS = env->getAttribute(X("name")XString("name").unicode_str()); |
1666 | containerTypeS = env->getTagName(); |
1667 | } |
1668 | else |
1669 | { |
1670 | containerS = el->getAttribute(X("container_name")XString("container_name").unicode_str()); |
1671 | containerTypeS = el->getAttribute(X("container_type")XString("container_type").unicode_str()); |
1672 | env = document->getElementById(X(containerS)XString(containerS).unicode_str()); |
1673 | } |
1674 | if (noRotation && (nSiblings == 1) && |
1675 | (containerTypeS == "tubs" )) |
1676 | { |
1677 | double rMax, rMin; |
1678 | XString envRioZS(env->getAttribute(X("Rio_Z")XString("Rio_Z").unicode_str())); |
1679 | if (envRioZS.size() > 0) |
1680 | { |
1681 | std::stringstream riozstr(envRioZS); |
1682 | riozstr >> rMin >> rMax; |
1683 | Units munit; |
1684 | munit.getConversions(env); |
1685 | rMin /= munit.deg; |
1686 | rMax /= munit.deg; |
Value stored to 'rMax' is never read | |
1687 | // drM = rMax-rMin; commented out to avoid compiler warnings 4/26/2015 DL |
1688 | } |
1689 | else |
1690 | { |
1691 | std::cerr |
1692 | << APP_NAME"hddsCommon" << " error: volume " << S(targS)targS.c_str() |
1693 | << " is missing a Rio_Z attribute." |
1694 | << std::endl; |
1695 | exit(1); |
1696 | } |
1697 | static int rDivisions = 0xd00; |
1698 | std::stringstream divStr; |
1699 | divStr << "r" << std::setfill('0') << std::setw(3) << std::hex |
1700 | << ++rDivisions; |
1701 | drs.fPartition.ncopy = ncopy; |
1702 | drs.fPartition.axis = "rho"; |
1703 | drs.fPartition.start = r0 - dr/2; |
1704 | drs.fPartition.offset = drs.fPartition.start - rMin; |
1705 | drs.fPartition.step = dr; |
1706 | XString divS(divStr.str()); |
1707 | createDivision(divS, drs); |
1708 | drs.fMother = drs.fPartition.divEl; |
1709 | targEl->setAttribute(X("container_name")XString("container_name").unicode_str(),X(containerS)XString(containerS).unicode_str()); |
1710 | targEl->setAttribute(X("container_type")XString("container_type").unicode_str(),X(containerTypeS)XString(containerTypeS).unicode_str()); |
1711 | origin[0] = r0 * cos(phi) - s * sin(phi); |
1712 | origin[1] = r0 * sin(phi) + s * cos(phi); |
1713 | origin[2] = z; |
1714 | drs.reset(); |
1715 | drs.shift(origin); |
1716 | drs.rotate(angle); |
1717 | createVolume(targEl,drs); |
1718 | } |
1719 | else |
1720 | { |
1721 | Refsys drs0(drs); |
1722 | drs.rotate(angle); |
1723 | for (int inst = 0; inst < ncopy; inst++) |
1724 | { |
1725 | double r = r0 + inst * dr; |
1726 | origin[0] = r * cos(phi) - s * sin(phi); |
1727 | origin[1] = r * sin(phi) + s * cos(phi); |
1728 | origin[2] = z; |
1729 | drs.shift(drs0, origin); |
1730 | createVolume(targEl,drs); |
1731 | drs.incrementIdentifiers(); |
1732 | } |
1733 | } |
1734 | } |
1735 | else if (comdS == "mposX") |
1736 | { |
1737 | XString ncopyS(contEl->getAttribute(X("ncopy")XString("ncopy").unicode_str())); |
1738 | int ncopy = atoi(S(ncopyS)ncopyS.c_str()); |
1739 | if (ncopy <= 0) |
1740 | { |
1741 | std::cerr |
1742 | << APP_NAME"hddsCommon" << " error: volume " << S(nameS)nameS.c_str() |
1743 | << " is positioned with " << ncopy << " copies!" |
1744 | << std::endl; |
1745 | exit(1); |
1746 | } |
1747 | |
1748 | double x0, dx; |
1749 | XString x0S(contEl->getAttribute(X("X0")XString("X0").unicode_str())); |
1750 | x0 = atof(S(x0S)x0S.c_str()) /unit.cm; |
1751 | XString dxS(contEl->getAttribute(X("dX")XString("dX").unicode_str())); |
1752 | dx = atof(S(dxS)dxS.c_str()) /unit.cm; |
1753 | |
1754 | double y, z, s; |
1755 | XString yzS(contEl->getAttribute(X("Y_Z")XString("Y_Z").unicode_str())); |
1756 | std::stringstream listr(yzS); |
1757 | listr >> y >> z; |
1758 | XString sS(contEl->getAttribute(X("S")XString("S").unicode_str())); |
1759 | s = atof(S(sS)sS.c_str()); |
1760 | y /= unit.cm; |
1761 | z /= unit.cm; |
1762 | s /= unit.cm; |
1763 | |
1764 | XString containerS; |
1765 | XString containerTypeS; |
1766 | if (env != 0) |
1767 | { |
1768 | containerS = env->getAttribute(X("name")XString("name").unicode_str()); |
1769 | containerTypeS = env->getTagName(); |
1770 | } |
1771 | else |
1772 | { |
1773 | containerS = el->getAttribute(X("container_name")XString("container_name").unicode_str()); |
1774 | containerTypeS = el->getAttribute(X("container_type")XString("container_type").unicode_str()); |
1775 | env = document->getElementById(X(containerS)XString(containerS).unicode_str()); |
1776 | } |
1777 | if (noRotation && (nSiblings == 1) && |
1778 | containerTypeS == "box") |
1779 | { |
1780 | double xMax, xMin; |
1781 | XString envXYZS(env->getAttribute(X("X_Y_Z")XString("X_Y_Z").unicode_str())); |
1782 | if (envXYZS.size() > 0) |
1783 | { |
1784 | std::stringstream xyzstr(envXYZS); |
1785 | double hx, hy, hz; |
1786 | xyzstr >> hx >> hy >> hz; |
1787 | Units munit; |
1788 | munit.getConversions(env); |
1789 | xMax = hx/2 /munit.cm; |
1790 | xMin = -xMax; |
1791 | // dxM = hx; commented out to avoid compiler warnings 4/26/2015 DL |
1792 | } |
1793 | else |
1794 | { |
1795 | std::cerr |
1796 | << APP_NAME"hddsCommon" << " error: volume " << S(targS)targS.c_str() |
1797 | << " is missing a X_Y_Z attribute." |
1798 | << std::endl; |
1799 | exit(1); |
1800 | } |
1801 | static int xDivisions = 0xd00; |
1802 | std::stringstream divStr; |
1803 | divStr << "x" << std::setfill('0') << std::setw(3) << std::hex |
1804 | << ++xDivisions; |
1805 | drs.fPartition.ncopy = ncopy; |
1806 | drs.fPartition.axis = "x"; |
1807 | drs.fPartition.start = x0 - dx/2; |
1808 | drs.fPartition.offset = drs.fPartition.start - xMin; |
1809 | drs.fPartition.step = dx; |
1810 | XString divS(divStr.str()); |
1811 | createDivision(divS, drs); |
1812 | drs.fMother = drs.fPartition.divEl; |
1813 | targEl->setAttribute(X("container_name")XString("container_name").unicode_str(),X(containerS)XString(containerS).unicode_str()); |
1814 | targEl->setAttribute(X("container_type")XString("container_type").unicode_str(),X(containerTypeS)XString(containerTypeS).unicode_str()); |
1815 | origin[0] = 0; |
1816 | origin[1] = y + s; |
1817 | origin[2] = z; |
1818 | drs.reset(); |
1819 | drs.shift(origin); |
1820 | drs.rotate(angle); |
1821 | createVolume(targEl,drs); |
1822 | } |
1823 | else |
1824 | { |
1825 | Refsys drs0(drs); |
1826 | drs.rotate(angle); |
1827 | for (int inst = 0; inst < ncopy; inst++) |
1828 | { |
1829 | double x = x0 + inst * dx; |
1830 | origin[0] = x; |
1831 | origin[1] = y + s; |
1832 | origin[2] = z; |
1833 | drs.shift(drs0, origin); |
1834 | createVolume(targEl,drs); |
1835 | drs.incrementIdentifiers(); |
1836 | } |
1837 | } |
1838 | } |
1839 | else if (comdS == "mposY") |
1840 | { |
1841 | XString ncopyS(contEl->getAttribute(X("ncopy")XString("ncopy").unicode_str())); |
1842 | int ncopy = atoi(S(ncopyS)ncopyS.c_str()); |
1843 | if (ncopy <= 0) |
1844 | { |
1845 | std::cerr |
1846 | << APP_NAME"hddsCommon" << " error: volume " << S(nameS)nameS.c_str() |
1847 | << " is positioned with " << ncopy << " copies!" |
1848 | << std::endl; |
1849 | exit(1); |
1850 | } |
1851 | |
1852 | double y0, dy; |
1853 | XString y0S(contEl->getAttribute(X("Y0")XString("Y0").unicode_str())); |
1854 | y0 = atof(S(y0S)y0S.c_str()) /unit.cm; |
1855 | XString dyS(contEl->getAttribute(X("dY")XString("dY").unicode_str())); |
1856 | dy = atof(S(dyS)dyS.c_str()) /unit.cm; |
1857 | |
1858 | double x, z, s; |
1859 | XString zxS(contEl->getAttribute(X("Z_X")XString("Z_X").unicode_str())); |
1860 | std::stringstream listr(zxS); |
1861 | listr >> z >> x; |
1862 | XString sS(contEl->getAttribute(X("S")XString("S").unicode_str())); |
1863 | s = atof(S(sS)sS.c_str()); |
1864 | x /= unit.cm; |
1865 | z /= unit.cm; |
1866 | s /= unit.cm; |
1867 | |
1868 | XString containerS; |
1869 | XString containerTypeS; |
1870 | if (env != 0) |
1871 | { |
1872 | containerS = env->getAttribute(X("name")XString("name").unicode_str()); |
1873 | containerTypeS = env->getTagName(); |
1874 | } |
1875 | else |
1876 | { |
1877 | containerS = el->getAttribute(X("container_name")XString("container_name").unicode_str()); |
1878 | containerTypeS = el->getAttribute(X("container_type")XString("container_type").unicode_str()); |
1879 | env = document->getElementById(X(containerS)XString(containerS).unicode_str()); |
1880 | } |
1881 | if (noRotation && (nSiblings == 1) && |
1882 | containerTypeS == "box") |
1883 | { |
1884 | double yMax, yMin; |
1885 | XString envXYZS(env->getAttribute(X("X_Y_Z")XString("X_Y_Z").unicode_str())); |
1886 | if (envXYZS.size() > 0) |
1887 | { |
1888 | std::stringstream xyzstr(envXYZS); |
1889 | double hx, hy, hz; |
1890 | xyzstr >> hx >> hy >> hz; |
1891 | Units munit; |
1892 | munit.getConversions(env); |
1893 | yMax = hy/2 /munit.cm; |
1894 | yMin = -yMax; |
1895 | // dyM = hy; commented out to avoid compiler warnings 4/26/2015 DL |
1896 | } |
1897 | else |
1898 | { |
1899 | std::cerr |
1900 | << APP_NAME"hddsCommon" << " error: volume " << S(targS)targS.c_str() |
1901 | << " is missing a X_Y_Z attribute." |
1902 | << std::endl; |
1903 | exit(1); |
1904 | } |
1905 | static int yDivisions = 0xd00; |
1906 | std::stringstream divStr; |
1907 | divStr << "y" << std::setfill('0') << std::setw(3) << std::hex |
1908 | << ++yDivisions; |
1909 | drs.fPartition.ncopy = ncopy; |
1910 | drs.fPartition.axis = "y"; |
1911 | drs.fPartition.start = y0 - dy/2; |
1912 | drs.fPartition.offset = drs.fPartition.start - yMin; |
1913 | drs.fPartition.step = dy; |
1914 | XString divS(divStr.str()); |
1915 | createDivision(divS, drs); |
1916 | drs.fMother = drs.fPartition.divEl; |
1917 | targEl->setAttribute(X("container_name")XString("container_name").unicode_str(),X(containerS)XString(containerS).unicode_str()); |
1918 | targEl->setAttribute(X("container_type")XString("container_type").unicode_str(),X(containerTypeS)XString(containerTypeS).unicode_str()); |
1919 | origin[0] = x + s; |
1920 | origin[1] = 0; |
1921 | origin[2] = z; |
1922 | drs.reset(); |
1923 | drs.shift(origin); |
1924 | drs.rotate(angle); |
1925 | createVolume(targEl,drs); |
1926 | } |
1927 | else |
1928 | { |
1929 | Refsys drs0(drs); |
1930 | drs.rotate(angle); |
1931 | for (int inst = 0; inst < ncopy; inst++) |
1932 | { |
1933 | double y = y0 + inst * dy; |
1934 | // double phi = atan2(y,x); |
1935 | origin[0] = x; |
1936 | origin[1] = y; |
1937 | origin[2] = z; |
1938 | drs.shift(drs0, origin); |
1939 | createVolume(targEl,drs); |
1940 | drs.incrementIdentifiers(); |
1941 | } |
1942 | } |
1943 | } |
1944 | else if (comdS == "mposZ") |
1945 | { |
1946 | XString ncopyS(contEl->getAttribute(X("ncopy")XString("ncopy").unicode_str())); |
1947 | int ncopy = atoi(S(ncopyS)ncopyS.c_str()); |
1948 | if (ncopy <= 0) |
1949 | { |
1950 | std::cerr |
1951 | << APP_NAME"hddsCommon" << " error: volume " << S(nameS)nameS.c_str() |
1952 | << " is positioned with " << ncopy << " copies!" |
1953 | << std::endl; |
1954 | exit(1); |
1955 | } |
1956 | |
1957 | double z0, dz; |
1958 | XString z0S(contEl->getAttribute(X("Z0")XString("Z0").unicode_str())); |
1959 | z0 = atof(S(z0S)z0S.c_str()) /unit.cm; |
1960 | XString dzS(contEl->getAttribute(X("dZ")XString("dZ").unicode_str())); |
1961 | dz = atof(S(dzS)dzS.c_str()) /unit.cm; |
1962 | |
1963 | double x, y, s; |
1964 | XString xyS(contEl->getAttribute(X("X_Y")XString("X_Y").unicode_str())); |
1965 | if (xyS.size() > 0) |
1966 | { |
1967 | std::stringstream listr(xyS); |
1968 | listr >> x >> y; |
1969 | } |
1970 | else |
1971 | { |
1972 | double r, phi; |
1973 | XString rphiS(contEl->getAttribute(X("R_Phi")XString("R_Phi").unicode_str())); |
1974 | std::stringstream listr(rphiS); |
1975 | listr >> r >> phi; |
1976 | phi /= unit.rad; |
1977 | x = r * cos(phi); |
1978 | y = r * sin(phi); |
1979 | } |
1980 | XString sS(contEl->getAttribute(X("S")XString("S").unicode_str())); |
1981 | s = atof(S(sS)sS.c_str()); |
1982 | x /= unit.cm; |
1983 | y /= unit.cm; |
1984 | s /= unit.cm; |
1985 | |
1986 | XString containerS; |
1987 | XString containerTypeS; |
1988 | if (env != 0) |
1989 | { |
1990 | containerS = env->getAttribute(X("name")XString("name").unicode_str()); |
1991 | containerTypeS = env->getTagName(); |
1992 | } |
1993 | else |
1994 | { |
1995 | containerS = el->getAttribute(X("container_name")XString("container_name").unicode_str()); |
1996 | containerTypeS = el->getAttribute(X("container_type")XString("container_type").unicode_str()); |
1997 | env = document->getElementById(X(containerS)XString(containerS).unicode_str()); |
1998 | } |
1999 | if (noRotation && (nSiblings == 1) && |
2000 | (containerTypeS == "tubs" || |
2001 | containerTypeS == "cons" || |
2002 | containerTypeS == "pcon" || |
2003 | containerTypeS == "pgon" || |
2004 | containerTypeS == "box") && |
2005 | (containerS.size() != 0)) |
2006 | { |
2007 | double zMax, zMin; |
2008 | XString envXYZS(env->getAttribute(X("X_Y_Z")XString("X_Y_Z").unicode_str())); |
2009 | XString envRioZS(el->getAttribute(X("Rio_Z")XString("Rio_Z").unicode_str())); |
2010 | XString envRxyZS(el->getAttribute(X("Rxy_Z")XString("Rxy_Z").unicode_str())); |
2011 | XString envXmpYmpZS(el->getAttribute(X("Xmp_Ymp_Z")XString("Xmp_Ymp_Z").unicode_str())); |
2012 | if (envXYZS.size() > 0) |
2013 | { |
2014 | std::stringstream xyzstr(envXYZS); |
2015 | double hx, hy, hz; |
2016 | xyzstr >> hx >> hy >> hz; |
2017 | Units munit; |
2018 | munit.getConversions(env); |
2019 | zMax = hz/2 /munit.cm; |
2020 | zMin = -zMax; |
2021 | // dzM = hz; commented out to avoid compiler warnings 4/26/2015 DL |
2022 | } |
2023 | else if (envRioZS.size() > 0) |
2024 | { |
2025 | std::stringstream riozstr(envRioZS); |
2026 | double ri, ro, hz; |
2027 | riozstr >> ri >> ro >> hz; |
2028 | Units munit; |
2029 | munit.getConversions(env); |
2030 | zMax = hz/2 /munit.cm; |
2031 | zMin = -zMax; |
2032 | // dzM = hz; commented out to avoid compiler warnings 4/26/2015 DL |
2033 | } |
2034 | else if (envRxyZS.size() > 0) |
2035 | { |
2036 | std::stringstream xyzstr(envRxyZS); |
2037 | double rx, ry, hz; |
2038 | xyzstr >> rx >> ry >> hz; |
2039 | Units munit; |
2040 | munit.getConversions(env); |
2041 | zMax = hz/2 /munit.cm; |
2042 | zMin = -zMax; |
2043 | // dzM = hz; commented out to avoid compiler warnings 4/26/2015 DL |
2044 | } |
2045 | else if (envXmpYmpZS.size() > 0) |
2046 | { |
2047 | std::stringstream xyzstr(envXmpYmpZS); |
2048 | double xm, xp, ym, yp, hz; |
2049 | xyzstr >> xm >> xp >> ym >> yp >> hz; |
2050 | Units munit; |
2051 | munit.getConversions(env); |
2052 | zMax = hz/2 /munit.cm; |
2053 | zMin = -zMax; |
2054 | // dzM = hz; commented out to avoid compiler warnings 4/26/2015 DL |
2055 | } |
2056 | else |
2057 | { |
2058 | std::cerr |
2059 | << APP_NAME"hddsCommon" << " error: volume " << S(targS)targS.c_str() |
2060 | << " is missing a *_Z attribute." |
2061 | << std::endl; |
2062 | exit(1); |
2063 | } |
2064 | static int zDivisions = 0xd00; |
2065 | std::stringstream divStr; |
2066 | divStr << "z" << std::setfill('0') << std::setw(3) << std::hex |
2067 | << ++zDivisions; |
2068 | drs.fPartition.ncopy = ncopy; |
2069 | drs.fPartition.axis = "z"; |
2070 | drs.fPartition.start = z0 - dz/2; |
2071 | drs.fPartition.offset = drs.fPartition.start - zMin; |
2072 | drs.fPartition.step = dz; |
2073 | XString divS(divStr.str()); |
2074 | createDivision(divS, drs); |
2075 | drs.fMother = drs.fPartition.divEl; |
2076 | targEl->setAttribute(X("container_name")XString("container_name").unicode_str(),X(containerS)XString(containerS).unicode_str()); |
2077 | targEl->setAttribute(X("container_type")XString("container_type").unicode_str(),X(containerTypeS)XString(containerTypeS).unicode_str()); |
2078 | double phi = atan2(y,x); |
2079 | origin[0] = x - s * sin(phi); |
2080 | origin[1] = y + s * cos(phi); |
2081 | origin[2] = 0; |
2082 | drs.reset(); |
2083 | drs.shift(origin); |
2084 | drs.rotate(angle); |
2085 | createVolume(targEl,drs); |
2086 | } |
2087 | else |
2088 | { |
2089 | Refsys drs0(drs); |
2090 | drs.rotate(angle); |
2091 | double phi = atan2(y,x); |
2092 | origin[0] = x - s * sin(phi); |
2093 | origin[1] = y + s * cos(phi); |
2094 | for (int inst = 0; inst < ncopy; inst++) |
2095 | { |
2096 | double z = z0 + inst * dz; |
2097 | origin[2] = z; |
2098 | drs.shift(drs0, origin); |
2099 | createVolume(targEl,drs); |
2100 | drs.incrementIdentifiers(); |
2101 | } |
2102 | } |
2103 | } |
2104 | else if (comdS == "apply") |
2105 | { |
2106 | myRef.fRegionID = createRegion(contEl,drs); |
2107 | myRef.fIdentifier["map"] = drs.fIdentifier["map"]; |
2108 | myRef.fRegion = drs.fRegion; |
2109 | myRef.fPar = drs.fPar; |
2110 | } |
2111 | else |
2112 | { |
2113 | std::cerr |
2114 | << APP_NAME"hddsCommon" << " error: composition of volume " << S(nameS)nameS.c_str() |
2115 | << " contains unknown tag " << S(comdS)comdS.c_str() << std::endl; |
2116 | exit(1); |
2117 | } |
2118 | } |
2119 | } |
2120 | else if (tagS == "stackX" || |
2121 | tagS == "stackY" || |
2122 | tagS == "stackZ") |
2123 | { |
2124 | std::cerr |
2125 | << APP_NAME"hddsCommon" << " error: stacks are not supported by " << APP_NAME"hddsCommon" |
2126 | << std::endl |
2127 | << "Use compositions instead." << std::endl; |
2128 | exit(1); |
2129 | } |
2130 | else |
2131 | { |
2132 | XString icopyS(el->getAttribute(X("HDDScopy")XString("HDDScopy").unicode_str())); |
2133 | if (icopyS.size() != 0) |
2134 | { |
2135 | icopy = atoi(S(icopyS)icopyS.c_str()); |
2136 | } |
2137 | else |
2138 | { |
2139 | XString profS(el->getAttribute(X("profile")XString("profile").unicode_str())); |
2140 | if (profS.size() != 0) |
2141 | { |
2142 | double phi0, dphi; |
2143 | std::stringstream listr(profS); |
2144 | listr >> phi0 >> dphi; |
2145 | Units punit; |
2146 | punit.getConversions(el); |
2147 | phi0 /= punit.deg; |
2148 | dphi /= punit.deg; |
2149 | if ( (myRef.fOrigin[0] == 0) && (myRef.fOrigin[1] == 0) ) |
2150 | { |
2151 | phi0 -= myRef.fPhiOffset; |
2152 | } |
2153 | std::stringstream pStr; |
2154 | pStr << phi0 << " " << dphi; |
2155 | el->setAttribute(X("profile")XString("profile").unicode_str(),X(pStr.str())XString(pStr.str()).unicode_str()); |
2156 | } |
2157 | createSolid(el,myRef); |
2158 | icopy = 0; |
2159 | } |
2160 | |
2161 | if (myRef.fMother != 0) |
2162 | { |
2163 | createRotation(myRef); |
2164 | fPending = true; |
2165 | fRef = myRef; |
2166 | ++icopy; |
2167 | } |
2168 | |
2169 | std::stringstream icopyStr; |
2170 | icopyStr << icopy; |
2171 | el->setAttribute(X("HDDScopy")XString("HDDScopy").unicode_str(),X(icopyStr.str())XString(icopyStr.str()).unicode_str()); |
2172 | XString voluS(el->getAttribute(X("HDDSvolu")XString("HDDSvolu").unicode_str())); |
2173 | int ivolu = atoi(S(voluS)voluS.c_str()); |
2174 | std::map<std::string,Refsys::VolIdent>::iterator iter; |
2175 | for (iter = myRef.fIdentifier.begin(); |
2176 | iter != myRef.fIdentifier.end(); |
2177 | ++iter) |
2178 | { |
2179 | XString fieldS(iter->first); |
2180 | std::vector<int>* idlist = &Refsys::fIdentifierTable[ivolu][fieldS]; |
2181 | while (idlist->size() < (unsigned int)icopy-1) |
2182 | { |
2183 | idlist->push_back(0); |
2184 | } |
2185 | idlist->push_back(iter->second.value); |
2186 | } |
2187 | Refsys::fIdentifierTable[ivolu]["copy counter"].push_back(icopy); |
2188 | } |
2189 | return icopy; |
2190 | } |
2191 | |
2192 | void CodeWriter::createHeader() |
2193 | { |
2194 | } |
2195 | |
2196 | void CodeWriter::createTrailer() |
2197 | { |
2198 | } |
2199 | |
2200 | void CodeWriter::createSetFunctions(DOMElement* el, const XString& ident) |
2201 | { |
2202 | NOT_USED(el)((void)(el)); |
2203 | NOT_USED(ident)((void)(ident)); |
2204 | } |
2205 | |
2206 | void CodeWriter::createGetFunctions(DOMElement* el, const XString& ident) |
2207 | { |
2208 | NOT_USED(el)((void)(el)); |
2209 | NOT_USED(ident)((void)(ident)); |
2210 | } |
2211 | |
2212 | void CodeWriter::createMapFunctions(DOMElement* el, const XString& ident) |
2213 | { |
2214 | NOT_USED(el)((void)(el)); |
2215 | NOT_USED(ident)((void)(ident)); |
2216 | } |
2217 | |
2218 | void CodeWriter::createUtilityFunctions(DOMElement* el, const XString& ident) |
2219 | { |
2220 | NOT_USED(el)((void)(el)); |
2221 | NOT_USED(ident)((void)(ident)); |
2222 | } |
2223 | |
2224 | void CodeWriter::translate(DOMElement* topel) |
2225 | { |
2226 | Refsys mrs; |
2227 | createHeader(); |
2228 | createVolume(topel,mrs); |
2229 | createTrailer(); |
2230 | |
2231 | DOMNodeList* propL = topel->getOwnerDocument() |
2232 | ->getElementsByTagName(X("optical_properties")XString("optical_properties").unicode_str()); |
2233 | for (unsigned int iprop=0; iprop < propL->getLength(); ++iprop) |
2234 | { |
2235 | DOMElement* propEl = (DOMElement*)propL->item(iprop); |
2236 | DOMElement* matEl = (DOMElement*)propEl->getParentNode(); |
2237 | XString imateS(matEl->getAttribute(X("HDDSmate")XString("HDDSmate").unicode_str())); |
2238 | if (imateS.size() > 0) |
2239 | { |
2240 | createSetFunctions(propEl,imateS); |
2241 | } |
2242 | } |
2243 | |
2244 | std::map<std::string,Refsys::VolIdent>::iterator iter; |
2245 | for (iter = mrs.fIdentifiers.begin(); |
2246 | iter != mrs.fIdentifiers.end(); ++iter) |
2247 | { |
2248 | createGetFunctions(topel, iter->first); |
2249 | } |
2250 | |
2251 | DOMNodeList* regionsL = topel->getOwnerDocument() |
2252 | ->getElementsByTagName(X("regions")XString("regions").unicode_str()); |
2253 | createMapFunctions((DOMElement*)regionsL->item(0),XString("map")); |
2254 | |
2255 | createUtilityFunctions(topel,XString("user")); |
2256 | } |
2257 | |
2258 | void CodeWriter::dump(DOMElement* el, int level=0) // useful debug function |
2259 | { |
2260 | XString tagS(el->getTagName()); |
2261 | for (int i=0; i<level; i++) |
2262 | { |
2263 | std::cerr << " "; |
2264 | } |
2265 | std::cerr << "<" << tagS; |
2266 | DOMNamedNodeMap* attribL = el->getAttributes(); |
2267 | for (unsigned int i=0; i < attribL->getLength(); i++) |
2268 | { |
2269 | XString nameS(attribL->item(i)->getNodeName()); |
2270 | XString valueS(attribL->item(i)->getNodeValue()); |
2271 | std::cerr << " " << nameS << "=\"" << valueS << "\""; |
2272 | } |
2273 | int n=0; |
2274 | for (DOMNode* cont = el->getFirstChild(); |
2275 | cont != 0; |
2276 | cont = cont->getNextSibling()) |
2277 | { |
2278 | if (cont->getNodeType() == DOMNode::ELEMENT_NODE) |
2279 | { |
2280 | ++n; |
2281 | } |
2282 | } |
2283 | if (n > 0) |
2284 | { |
2285 | std::cerr << ">" << std::endl; |
2286 | for (DOMNode* cont = el->getFirstChild(); |
2287 | cont != 0; |
2288 | cont = cont->getNextSibling()) |
2289 | { |
2290 | if (cont->getNodeType() == DOMNode::ELEMENT_NODE) |
2291 | { |
2292 | dump((DOMElement*)cont,level+1); |
2293 | } |
2294 | } |
2295 | for (int i=0; i<level; i++) |
2296 | { |
2297 | std::cerr << " "; |
2298 | } |
2299 | std::cerr << "</" << tagS << ">" << std::endl; |
2300 | } |
2301 | else |
2302 | { |
2303 | std::cerr << "/>" << std::endl; |
2304 | } |
2305 | } |