]> git.uio.no Git - u/mrichter/AliRoot.git/blame - MUON/AliMUONVGeometryBuilder.cxx
Changes needed on Alpha
[u/mrichter/AliRoot.git] / MUON / AliMUONVGeometryBuilder.cxx
CommitLineData
30178c30 1/**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
15
d1cd2474 16// $Id$
17//
18// Class AliMUONVGeometryBuilder
19// -----------------------------
20// Abstract base class for geometry construction per chamber(s).
d1cd2474 21// Author: Ivana Hrivnacova, IPN Orsay
5f1df83a 22// 23/01/2004
d1cd2474 23
2811276d 24#include <Riostream.h>
d1cd2474 25#include <TObjArray.h>
2811276d 26#include <TSystem.h>
27#include <TGeoMatrix.h>
28#include <TVirtualMC.h>
d1cd2474 29
30#include "AliMUONVGeometryBuilder.h"
31#include "AliMUONChamber.h"
2811276d 32#include "AliMUONChamberGeometry.h"
33#include "AliMUONGeometryTransformStore.h"
34#include "AliMUONGeometrySVMap.h"
35#include "AliMUONGeometryEnvelopeStore.h"
36#include "AliMUONGeometryEnvelope.h"
37#include "AliMUONGeometryConstituent.h"
38#include "AliMUONConstants.h"
d1cd2474 39
40ClassImp(AliMUONVGeometryBuilder)
41
2811276d 42const TString AliMUONVGeometryBuilder::fgkTransformFileNamePrefix = "transform_";
43const TString AliMUONVGeometryBuilder::fgkSVMapFileNamePrefix = "svmap_";
44const TString AliMUONVGeometryBuilder::fgkOutFileNameSuffix = ".out";
45
d1cd2474 46//______________________________________________________________________________
2811276d 47AliMUONVGeometryBuilder::AliMUONVGeometryBuilder(const TString& fileName,
d1cd2474 48 AliMUONChamber* ch1, AliMUONChamber* ch2,
49 AliMUONChamber* ch3, AliMUONChamber* ch4,
50 AliMUONChamber* ch5, AliMUONChamber* ch6)
51 : TObject(),
2811276d 52 fTransformFileName(fgkTransformFileNamePrefix+fileName),
53 fSVMapFileName(fgkSVMapFileNamePrefix+fileName),
d1cd2474 54 fChambers(0)
55 {
56// Standard constructor
57
58 // Create the chambers array
59 fChambers = new TObjArray();
60
61 if (ch1) fChambers->Add(ch1);
62 if (ch2) fChambers->Add(ch2);
63 if (ch3) fChambers->Add(ch3);
64 if (ch4) fChambers->Add(ch4);
65 if (ch5) fChambers->Add(ch5);
66 if (ch6) fChambers->Add(ch6);
d1cd2474 67}
68
69
70//______________________________________________________________________________
71AliMUONVGeometryBuilder::AliMUONVGeometryBuilder()
72 : TObject(),
2811276d 73 fTransformFileName(),
74 fSVMapFileName(),
d1cd2474 75 fChambers(0)
76{
77// Default constructor
78}
79
80
81//______________________________________________________________________________
82AliMUONVGeometryBuilder::AliMUONVGeometryBuilder(const AliMUONVGeometryBuilder& rhs)
83 : TObject(rhs)
84{
30178c30 85// Protected copy constructor
86
d1cd2474 87 Fatal("Copy constructor",
88 "Copy constructor is not implemented.");
89}
90
91//______________________________________________________________________________
92AliMUONVGeometryBuilder::~AliMUONVGeometryBuilder() {
93//
86b48c39 94 if (fChambers) {
95 fChambers->Clear(); // Sets pointers to 0 sinche it is not the owner
96 delete fChambers;
97 }
d1cd2474 98}
99
100//______________________________________________________________________________
101AliMUONVGeometryBuilder&
102AliMUONVGeometryBuilder::operator = (const AliMUONVGeometryBuilder& rhs)
103{
30178c30 104// Protected assignement operator
105
d1cd2474 106 // check assignement to self
107 if (this == &rhs) return *this;
108
109 Fatal("operator=",
110 "Assignment operator is not implemented.");
111
112 return *this;
113}
114
115//
2811276d 116// private methods
117//
118
119//______________________________________________________________________________
120 TString AliMUONVGeometryBuilder::ComposePath(const TString& volName,
121 Int_t copyNo) const
122{
123// Compose path from given volName and copyNo
124// ---
125
126 TString path(volName);
127 path += ".";
128 path += copyNo;
129
130 return path;
131}
132
133/*
134//______________________________________________________________________________
135void AliMUONVGeometryBuilder::MapSV(const TString& path0,
136 const TString& volName, Int_t detElemId) const
137{
138// Update the path with all daughters volumes recursively
139// and map it to the detection element Id if it is a sensitive volume
140// ---
141
142 Int_t nofDaughters = gMC->NofVolDaughters(volName);
143 if (nofDaughters == 0) {
144
145 // Get the name of the last volume in the path
146 Ssiz_t npos1 = path0.Last('/')+1;
147 Ssiz_t npos2 = path0.Last('.');
148 TString volName(path0(npos1, npos2-npos1));
149
150 // Check if it is sensitive volume
151 Int_t chamberId = AliMUONConstants::GetChamberId(detElemId);
152 AliMUONChamberGeometry* geometry = GetChamber(chamberId)->GetGeometry();
153 if (geometry->IsSensitiveVolume(volName)) {
154 //cout << ".. adding to the map "
155 // << path0 << " " << detElemId << endl;
156 FillData(path0, detElemId);
157 }
158 return;
159 }
160
161 for (Int_t i=0; i<nofDaughters; i++) {
162 Int_t copyNo = gMC->VolDaughterCopyNo(volName, i);
163 TString newName = gMC->VolDaughterName(volName, i);
164
165 TString path = path0;
166 path += "/";
167 path += ComposePath(newName, copyNo);
168
169 MapSV(path, newName, detElemId);
170 }
171}
172*/
173
174//______________________________________________________________________________
175void AliMUONVGeometryBuilder::MapSV(const TString& /*path0*/,
176 const TString& /*volName*/,
177 Int_t /*detElemId*/) const
178{
179// Update the path with all daughters volumes recursively
180// and map it to the detection element Id if it is a sensitive volume
181// ---
182
183 Warning("MapSV", "Not yet available");
184}
185
186//______________________________________________________________________________
187void AliMUONVGeometryBuilder::FillData(Int_t chamberId,
188 Double_t x, Double_t y, Double_t z,
189 Double_t a1, Double_t a2, Double_t a3,
190 Double_t a4, Double_t a5, Double_t a6) const
191{
192// Fill the transformation of the chamber.
193// ---
194
195 chamberId--;
196 // Chambers numbers in the file are starting from 1
197
198 GetChamber(chamberId)->GetGeometry()
199 ->SetTranslation(TGeoTranslation(x, y, z));
200 GetChamber(chamberId)->GetGeometry()
201 ->SetRotation(TGeoRotation("rot", a1, a2, a3, a4, a5, a6));
202}
203
204//______________________________________________________________________________
205void AliMUONVGeometryBuilder::FillData(
206 Int_t detElemId, const TString& volName, Int_t copyNo,
207 Double_t x, Double_t y, Double_t z,
208 Double_t a1, Double_t a2, Double_t a3,
209 Double_t a4, Double_t a5, Double_t a6) const
210{
211// Fill the transformation of the detection element.
212// ---
213
214 // Chamber Id
215 Int_t chamberId = AliMUONConstants::GetChamberId(detElemId);
216
217 // Get chamber transformations
218 AliMUONGeometryTransformStore* transforms
219 = GetTransforms(chamberId);
220
221 // Compose path
222 TString path = ComposePath(volName, copyNo);
223
224 // Compose matrix
225 TGeoCombiTrans transform(path, x, y, z,
226 new TGeoRotation(path, a1, a2, a3, a4, a5, a6));
227
228 // Add detection element transformation
229 transforms->Add(detElemId, path, transform);
230}
231
232//______________________________________________________________________________
233void AliMUONVGeometryBuilder::FillData(
234 const TString& sensVolumePath, Int_t detElemId) const
235{
236// Fill the mapping of the sensitive volume path to the detection element.
237// ---
238
239 // Chamber Id
240 Int_t chamberId = AliMUONConstants::GetChamberId(detElemId);
241
242 // Get chamber transformations
243 AliMUONGeometrySVMap* svMap = GetSVMap(chamberId);
244
245 // Map the sensitive volume to detection element
246 svMap->Add(sensVolumePath, detElemId);
247}
248
249//______________________________________________________________________________
250TString AliMUONVGeometryBuilder::ReadData1(ifstream& in) const
251{
252// Reads and fills chambers transformations from a file
253// Returns true, if reading finished correctly.
254// ---
255
256 TString key("CH");
257 while ( key == TString("CH") ) {
258 Int_t id;
259 Double_t x, y, z;
260 Double_t a1, a2, a3, a4, a5, a6;
261 TString dummy;
262
263 in >> id;
264 in >> dummy;
265 in >> x;
266 in >> y;
267 in >> z;
268 in >> dummy;
269 in >> a1;
270 in >> a2;
271 in >> a3;
272 in >> a4;
273 in >> a5;
274 in >> a6;
275
276 //cout << "id=" << id << " "
277 // << "position= " << x << ", " << y << ", " << z << " "
278 // << "rotation= " << a1 << ", " << a2 << ", " << a3 << ", "
279 // << a4 << ", " << a5 << ", " << a6
280 // << endl;
281
282 // Fill data
283 FillData(id, x, y, z, a1, a2, a3, a4, a5, a6);
284
285 // Go to next line
286 in >> key;
287 }
288
289 return key;
290}
291
292//______________________________________________________________________________
293TString AliMUONVGeometryBuilder::ReadData2(ifstream& in) const
294{
295// Reads detection elements transformations from a file
296// Returns true, if reading finished correctly.
297// ---
298
299 TString key("DE");
300 while ( key == TString("DE") ) {
301
302 // Input data
303 Int_t detElemId;
304 TString volumeName;
305 Int_t copyNo;
306 Double_t x, y, z;
307 Double_t a1, a2, a3, a4, a5, a6;
308 TString dummy;
309
310 in >> detElemId;
311 in >> volumeName;
312 in >> copyNo;
313 in >> dummy;
314 in >> x;
315 in >> y;
316 in >> z;
317 in >> dummy;
318 in >> a1;
319 in >> a2;
320 in >> a3;
321 in >> a4;
322 in >> a5;
323 in >> a6;
324
325 //cout << "detElemId=" << detElemId << " "
326 // << "volume=" << volumeName << " "
327 // << "copyNo=" << copyNo << " "
328 // << "position= " << x << ", " << y << ", " << z << " "
329 // << "rotation= " << a1 << ", " << a2 << ", " << a3 << ", "
330 // << a4 << ", " << a5 << ", " << a6
331 // << endl;
332
333 // Fill data
334 FillData(detElemId, volumeName, copyNo, x, y, z, a1, a2, a3, a4, a5, a6);
335
336 // Go to next line
337 in >> key;
338 }
339
340 return key;
341}
342
343//______________________________________________________________________________
344TString AliMUONVGeometryBuilder::ReadData3(ifstream& in) const
345{
346// Reads detection elements transformations from a file
347// Returns true, if reading finished correctly.
348// ---
349
350 TString key("SV");
351 while ( key == TString("SV") ) {
352
353 // Input data
354 TString volumePath;
355 Int_t detElemId;
356
357 in >> volumePath;
358 in >> detElemId;
359
360 //cout << "volumePath=" << volumePath << " "
361 // << "detElemId=" << detElemId
362 // << endl;
363
364 // Fill data
365 FillData(volumePath, detElemId);
366
367 // Go to next line
368 in >> key;
369 }
370
371 return key;
372}
373
374//______________________________________________________________________________
375void AliMUONVGeometryBuilder::WriteTransform(ofstream& out,
376 const TGeoCombiTrans* transform) const
377{
378// Writes the transformations
379// ---
380
381 out << " pos: ";
382 const Double_t* xyz = transform->GetTranslation();
383 out << setw(10) << setprecision(4) << xyz[0] << " "
384 << setw(10) << setprecision(4) << xyz[1] << " "
385 << setw(10) << setprecision(4) << xyz[2];
386
387 out << " rot: ";
388 Double_t a1, a2, a3, a4, a5, a6;
389 TGeoRotation* rotation = transform->GetRotation();
390 rotation->GetAngles(a1, a2, a3, a4, a5, a6);
391 out << setw(8) << setprecision(4) << a1 << " "
392 << setw(8) << setprecision(4) << a2 << " "
393 << setw(8) << setprecision(4) << a3 << " "
394 << setw(8) << setprecision(4) << a4 << " "
395 << setw(8) << setprecision(4) << a5 << " "
396 << setw(8) << setprecision(4) << a6 << " " << endl;
397}
398
399//______________________________________________________________________________
400void AliMUONVGeometryBuilder::WriteData1(ofstream& out) const
401{
402// Writes chamber transformations
403// ---
404
405 for (Int_t i=0; i<fChambers->GetEntriesFast(); i++) {
406 AliMUONChamber* chamber
407 = (AliMUONChamber*)fChambers->At(i);
408 AliMUONChamberGeometry* chamberGeometry
409 = chamber->GetGeometry();
410 const TGeoCombiTrans* transform
411 = chamberGeometry->GetTransformation();
412
413 out << "CH "
414 << setw(4) << chamber->GetId() + 1 << " ";
415
416 WriteTransform(out, transform);
417 }
418 out << endl;
419}
420
421//______________________________________________________________________________
422void AliMUONVGeometryBuilder::WriteData2(ofstream& out) const
423{
424// Writes detection elements (envelopes) transformations
425// ---
426
427
428 for (Int_t i=0; i<fChambers->GetEntriesFast(); i++) {
429 AliMUONChamber* chamber
430 = (AliMUONChamber*)fChambers->At(i);
431 AliMUONChamberGeometry* chamberGeometry
432 = chamber->GetGeometry();
433 const TObjArray* envelopes
434 = chamberGeometry->GetEnvelopeStore()->GetEnvelopes();
435
436 for (Int_t j=0; j<envelopes->GetEntriesFast(); j++) {
437 AliMUONGeometryEnvelope* envelope
438 = (AliMUONGeometryEnvelope*)envelopes->At(j);
439 const TGeoCombiTrans* transform
440 = envelope->GetTransformation();
441
442 // skip envelope not corresponding to detection element
443 if(envelope->GetUniqueID() == 0) continue;
444
445 out << "DE "
446 << setw(4) << envelope->GetUniqueID() << " "
447 << envelope->GetName() << " "
448 << setw(4)<< envelope->GetCopyNo();
449
450 WriteTransform(out, transform);
451 }
452 out << endl;
453 }
454}
455
456//______________________________________________________________________________
457void AliMUONVGeometryBuilder::WriteData3(ofstream& out) const
458{
459// Writes association of sensitive volumes and detection elements
460// from the sensitive volume map
461// ---
462
463 for (Int_t i=0; i<fChambers->GetEntriesFast(); i++) {
464 AliMUONChamber* chamber
465 = (AliMUONChamber*)fChambers->At(i);
466 AliMUONChamberGeometry* chamberGeometry
467 = chamber->GetGeometry();
468 AliMUONGeometrySVMap* svMap
469 = chamberGeometry->GetSVMap();
470
471 svMap->WriteMap(out);
472 out << endl;
473 }
474}
475
476//
477// protected methods
d1cd2474 478//
479
480//______________________________________________________________________________
481AliMUONChamber* AliMUONVGeometryBuilder::GetChamber(Int_t chamberId) const
482{
483// Returns the chamber specified by chamberId
484// ---
485
486 for (Int_t i=0; i<fChambers->GetEntriesFast(); i++) {
487 AliMUONChamber* chamber = (AliMUONChamber*)fChambers->At(i);
488 if ( chamber->GetId() == chamberId) return chamber;
489 }
490
491 return 0;
492}
2811276d 493
494//______________________________________________________________________________
495AliMUONGeometryEnvelopeStore*
496AliMUONVGeometryBuilder::GetEnvelopes(Int_t chamberId) const
497{
498// Returns the envelope store of the chamber specified by chamberId
499// ---
500
501 AliMUONChamber* chamber = GetChamber(chamberId);
502
503 if (!chamber) {
504 Fatal("GetEnvelopes", "Chamber %d is not defined", chamberId);
505 return 0;
506 }
507
508 return chamber->GetGeometry()->GetEnvelopeStore();
509}
510
511//______________________________________________________________________________
512AliMUONGeometryTransformStore*
513AliMUONVGeometryBuilder::GetTransforms(Int_t chamberId) const
514{
515// Returns the transformation store of the chamber specified by chamberId
516// ---
517
518 AliMUONChamber* chamber = GetChamber(chamberId);
519
520 if (!chamber) {
521 Fatal("GetTransforms", "Chamber %d is not defined", chamberId);
522 return 0;
523 }
524
525 return chamber->GetGeometry()->GetTransformStore();
526}
527
528//______________________________________________________________________________
529AliMUONGeometrySVMap*
530AliMUONVGeometryBuilder::GetSVMap(Int_t chamberId) const
531{
532// Returns the transformation store of the chamber specified by chamberId
533// ---
534
535 AliMUONChamber* chamber = GetChamber(chamberId);
536
537 if (!chamber) {
538 Fatal("GetSVMap", "Chamber %d is not defined", chamberId);
539 return 0;
540 }
541
542 return chamber->GetGeometry()->GetSVMap();
543}
544
545//
546// public functions
547//
548
549//______________________________________________________________________________
550void AliMUONVGeometryBuilder:: FillTransformations() const
551{
552// Fills transformations store from defined geometry.
553// ---
554
555 for (Int_t i=0; i<fChambers->GetEntriesFast(); i++) {
556 AliMUONChamber* chamber
557 = (AliMUONChamber*)fChambers->At(i);
558 AliMUONChamberGeometry* chamberGeometry
559 = chamber->GetGeometry();
560 const TObjArray* envelopes
561 = chamberGeometry->GetEnvelopeStore()->GetEnvelopes();
562 AliMUONGeometryTransformStore* transforms
563 = chamberGeometry->GetTransformStore();
564
565 for (Int_t j=0; j<envelopes->GetEntriesFast(); j++) {
566 AliMUONGeometryEnvelope* envelope
567 = (AliMUONGeometryEnvelope*)envelopes->At(j);
568
569 // skip envelope not corresponding to detection element
570 if(envelope->GetUniqueID() == 0) continue;
571
572 // Get envelope data
573 Int_t detElemId = envelope->GetUniqueID();
574 TString path = ComposePath(envelope->GetName(),
575 envelope->GetCopyNo());
576 const TGeoCombiTrans* transform = envelope->GetTransformation();
577
578 // Add detection element transformation
579 transforms->Add(detElemId, path, *transform);
580 }
581 }
582}
583
584//_____ _________________________________________________________________________
585void AliMUONVGeometryBuilder::RebuildSVMaps() const
586{
587// Clear the SV maps in memory and fill them from defined geometry.
588// ---
589
590 for (Int_t i=0; i<fChambers->GetEntriesFast(); i++) {
591 AliMUONChamber* chamber
592 = (AliMUONChamber*)fChambers->At(i);
593 AliMUONChamberGeometry* chamberGeometry
594 = chamber->GetGeometry();
595
596 // Clear the map
597 chamberGeometry->GetSVMap()->Clear();
598
599 // Fill the map from geometry
600 const TObjArray* envelopes
601 = chamberGeometry->GetEnvelopeStore()->GetEnvelopes();
602
603 for (Int_t j=0; j<envelopes->GetEntriesFast(); j++) {
604 AliMUONGeometryEnvelope* envelope
605 = (AliMUONGeometryEnvelope*)envelopes->At(j);
606
607 // skip envelope not corresponding to detection element
608 if(envelope->GetUniqueID() == 0) continue;
609
610 TString path0("/ALIC.1");
611 if (chamberGeometry->GetMotherVolume() != "ALIC") {
612 path0 += "/";
613 path0 += ComposePath(chamberGeometry->GetMotherVolume(), 1);
614 }
615
616 if (!envelope->IsVirtual()) {
617 TString path = path0;
618 path += "/";
619 path += ComposePath(envelope->GetName(), envelope->GetCopyNo());
620 MapSV(path, envelope->GetName(), envelope->GetUniqueID());
621 }
622 else {
623 for (Int_t k=0; k<envelope->GetConstituents()->GetEntriesFast(); k++) {
624 AliMUONGeometryConstituent* constituent
625 = (AliMUONGeometryConstituent*)envelope->GetConstituents()->At(k);
626 TString path = path0;
627 path += "/";
628 path += ComposePath(constituent->GetName(), constituent->GetCopyNo());
629 MapSV(path, constituent->GetName(), envelope->GetUniqueID());
630 }
631 }
632 }
633 }
634}
635
636//______________________________________________________________________________
637Bool_t AliMUONVGeometryBuilder::ReadTransformations() const
638{
639// Reads transformations from a file
640// Returns true, if reading finished correctly.
641// ---
642
643 // File path
644 TString filePath = gSystem->Getenv("ALICE_ROOT");
645 filePath += "/MUON/data/";
646 filePath += fTransformFileName;
647
648 // Open input file
649 ifstream in(filePath, ios::in);
650 if (!in) {
651 cerr << filePath << endl;
652 Fatal("ReadTransformations", "File not found.");
653 return false;
654 }
655
656 TString key;
657 in >> key;
658 while ( !in.eof() ) {
659 if (key == TString("CH"))
660 key = ReadData1(in);
661 else if (key == TString("DE"))
662 key = ReadData2(in);
663 else {
664 Fatal("ReadTransformations", "%s key not recognized", key.Data());
665 return false;
666 }
667 }
668
669 return true;
670}
671
672//______________________________________________________________________________
673Bool_t AliMUONVGeometryBuilder::ReadSVMap() const
674{
675// Reads the sensitive volume from a file
676// Returns true, if reading finished correctly.
677// ---
678
679 // File path
680 TString filePath = gSystem->Getenv("ALICE_ROOT");
681 filePath += "/MUON/data/";
682 filePath += fSVMapFileName;
683
684 // Open input file
685 ifstream in(filePath, ios::in);
686 if (!in) {
687 cerr << filePath << endl;
688 Fatal("ReadSVMap", "File not found.");
689 return false;
690 }
691
692 TString key;
693 in >> key;
694 while ( !in.eof() ) {
695 if (key == TString("SV"))
696 key = ReadData3(in);
697 else {
698 Fatal("ReadSVMap", "%s key not recognized", key.Data());
699 return false;
700 }
701 }
702
703 return true;
704}
705
706//______________________________________________________________________________
707Bool_t AliMUONVGeometryBuilder::WriteTransformations() const
708{
709// Writes transformations into a file
710// Returns true, if writing finished correctly.
711// ---
712
713 // File path
714 TString filePath = gSystem->Getenv("ALICE_ROOT");
715 filePath += "/MUON/data/";
716 filePath += fTransformFileName;
717 filePath += fgkOutFileNameSuffix;
718
719 // Open input file
720 ofstream out(filePath, ios::out);
721 if (!out) {
722 cerr << filePath << endl;
723 Error("WriteTransformations", "File not found.");
724 return false;
725 }
a6de0a61 726#if !defined (__DECCXX)
2811276d 727 out.setf(std::ios::fixed);
a6de0a61 728#endif
2811276d 729 WriteData1(out);
730 WriteData2(out);
731
732 return true;
733}
734
735//______________________________________________________________________________
736Bool_t AliMUONVGeometryBuilder::WriteSVMap(Bool_t rebuild) const
737{
738// Writes sensitive volume map into a file
739// Returns true, if writing finished correctly.
740// ---
741
742 // File path
743 TString filePath = gSystem->Getenv("ALICE_ROOT");
744 filePath += "/MUON/data/";
745 filePath += fSVMapFileName;
746 filePath += fgkOutFileNameSuffix;
747
748 // Open input file
749 ofstream out(filePath, ios::out);
750 if (!out) {
751 cerr << filePath << endl;
752 Error("WriteTransformations", "File not found.");
753 return false;
754 }
a6de0a61 755#if !defined (__DECCXX)
2811276d 756 out.setf(std::ios::fixed);
a6de0a61 757#endif
2811276d 758 if (rebuild) RebuildSVMaps();
759
760 WriteData3(out);
761
762 return true;
763}
764