]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/mapping/AliMpSectorSegmentation.cxx
Removing useless ifs
[u/mrichter/AliRoot.git] / MUON / mapping / AliMpSectorSegmentation.cxx
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
16 // $Id$
17 // $MpId: AliMpSectorSegmentation.cxx,v 1.10 2005/10/28 15:22:02 ivana Exp $
18 // Category: sector
19 //
20 // Class AliMpSectorSegmentation
21 // -----------------------------
22 // Class describing the segmentation of the sector.        
23 // Provides methods related to pads:
24 // conversion between pad indices, pad location, pad position;
25 // finding pad neighbour.
26 //
27 // Authors: David Guez, Ivana Hrivnacova; IPN Orsay
28
29 #include <Riostream.h>
30 #include <TMath.h>
31 #include <TError.h>
32
33 #include "AliLog.h"
34
35 #include "AliMpSectorSegmentation.h"
36 #include "AliMpSector.h"
37 #include "AliMpZone.h"
38 #include "AliMpSubZone.h"
39 #include "AliMpRow.h"
40 #include "AliMpVRowSegment.h"
41 #include "AliMpMotifMap.h"
42 #include "AliMpVMotif.h"
43 #include "AliMpMotifPosition.h"
44 #include "AliMpConnection.h"
45 #include "AliMpNeighboursPadIterator.h"
46 #include "AliMpSectorAreaHPadIterator.h"
47 #include "AliMpSectorAreaVPadIterator.h"
48 #include "AliMpIntPair.h"
49 #include "AliMpArea.h"
50 #include "AliMpConstants.h"
51
52 ClassImp(AliMpSectorSegmentation)
53
54 #ifdef WITH_ROOT
55 const Double_t AliMpSectorSegmentation::fgkS1 = 100000.;
56 const Double_t AliMpSectorSegmentation::fgkS2 = 1000.;
57 #endif
58
59 //______________________________________________________________________________
60 AliMpSectorSegmentation::AliMpSectorSegmentation(const AliMpSector* sector) 
61   : AliMpVSegmentation(),
62     fkSector(sector),
63     fMaxIndexInX(0),
64     fMaxIndexInY(0)
65 {
66 /// Standard constructor
67
68   fPadBuffer = new AliMpPad(AliMpPad::Invalid());
69   
70   FillPadDimensionsMap();
71 }
72
73 //______________________________________________________________________________
74 AliMpSectorSegmentation::AliMpSectorSegmentation() 
75   : AliMpVSegmentation(),
76     fkSector(0),
77     fPadBuffer(0),
78     fPadDimensionsMap(),      
79     fMaxIndexInX(0),
80     fMaxIndexInY(0)
81 {
82 /// Default constructor
83 }
84
85 //_____________________________________________________________________________
86 AliMpSectorSegmentation::AliMpSectorSegmentation(
87                                     const AliMpSectorSegmentation& right) 
88   : AliMpVSegmentation(right) 
89 {
90 /// Protected copy constructor (not provided) 
91
92   Fatal("AliMpSectorSegmentation", "Copy constructor not provided.");
93 }
94
95 //______________________________________________________________________________
96 AliMpSectorSegmentation::~AliMpSectorSegmentation() 
97 {
98 /// Destructor 
99
100   delete fPadBuffer;
101 }
102
103 //
104 // operators
105 //
106
107 //_____________________________________________________________________________
108 AliMpSectorSegmentation& 
109 AliMpSectorSegmentation::operator=(const AliMpSectorSegmentation& right)
110 {
111 /// Protected assignment operator (not provided)
112
113   // check assignment to self
114   if (this == &right) return *this;
115
116   Fatal("operator =", "Assignment operator not provided.");
117     
118   return *this;  
119 }    
120
121 //
122 // private methods
123 //
124
125 #ifdef WITH_ROOT
126 //______________________________________________________________________________
127 Long_t AliMpSectorSegmentation::GetIndex(const TVector2& vector2) const
128 {
129 /// Convert the two vector to long.
130
131   return Long_t(TMath::Floor((vector2.X()*fgkS1 + vector2.Y())*fgkS2));
132 }  
133
134 //______________________________________________________________________________
135 TVector2  AliMpSectorSegmentation::GetVector(Long_t index) const
136 {
137 /// Convert the long index to twovector.
138
139   return TVector2( TMath::Floor(index/fgkS1)/fgkS2,
140                    (index - TMath::Floor(index/fgkS1)*fgkS1)/fgkS2 );
141 }  
142 #endif
143
144 //______________________________________________________________________________
145 void AliMpSectorSegmentation::FillPadDimensionsMap()
146 {
147 /// Fill the maps between zone ids and pad dimensions.
148
149   for (Int_t i=0; i<fkSector->GetNofZones(); i++) {
150     AliMpZone* zone   = fkSector->GetZone(i+1);
151     Int_t  zoneID = zone->GetID();
152     
153     if (!AliMpConstants::IsEqual(zone->GetPadDimensions(), TVector2())) {
154
155       // regular zone
156 #ifdef WITH_STL
157       fPadDimensionsMap[zoneID*10] = zone->GetPadDimensions();
158 #endif
159 #ifdef WITH_ROOT
160      AliDebug(1,Form("Filling fPadDimensions[%d]=(%e,%e)",
161                      zoneID*10,zone->GetPadDimensions().X(),
162                      zone->GetPadDimensions().Y()));
163      fPadDimensionsMap.Add((Long_t)(zoneID*10), 
164                             GetIndex(zone->GetPadDimensions()));
165 #endif
166     }
167     else {
168       // special zone
169       Int_t subIndex = 0;
170       for (Int_t j=0; j<zone->GetNofSubZones(); j++) {
171         AliMpSubZone* subZone = zone->GetSubZone(j);
172         AliMpVMotif*  motif = subZone->GetMotif();
173         
174         for (Int_t k=0; k<motif->GetNofPadDimensions(); k++) {
175           Int_t index = zoneID*10 +  subIndex++;
176 #ifdef WITH_STL
177           fPadDimensionsMap[index] = motif->GetPadDimensions(k);
178 #endif
179 #ifdef WITH_ROOT
180           AliDebug(1,Form("Filling fPadDimensions[%d]=(%e,%e) motif %s-%d",
181                           index,
182                           motif->GetPadDimensions(k).X(),
183                           motif->GetPadDimensions(k).Y(),
184                           motif->GetID().Data(),k));
185           
186           fPadDimensionsMap.Add((Long_t)(index), 
187                             GetIndex(motif->GetPadDimensions(k)));
188 #endif
189         }
190       }   
191     }     
192   }      
193 }
194
195 //______________________________________________________________________________
196 AliMpMotifPosition* 
197 AliMpSectorSegmentation::FindMotifPosition(const AliMpIntPair& indices) const
198 {
199 /// Find the motif position which contains the given pad indices
200 /// return 0 if not found
201
202   switch (fkSector->GetDirection()) {
203     case kX : {
204     // Case where all the pads have the same size along X direction
205
206       for (Int_t irow=0; irow<fkSector->GetNofRows(); ++irow) {
207         AliMpRow* row = fkSector->GetRow(irow);
208         if (row->GetLowIndicesLimit().GetFirst()<=indices.GetFirst() &&
209             row->GetHighIndicesLimit().GetFirst()>=indices.GetFirst()) {
210             
211            for (Int_t iseg=0;iseg<row->GetNofRowSegments();++iseg){
212             AliMpVRowSegment* seg = row->GetRowSegment(iseg);
213             if (seg->GetLowIndicesLimit().GetFirst()<=indices.GetFirst() &&
214                 seg->GetHighIndicesLimit().GetFirst()>=indices.GetFirst()) {
215
216               AliMpMotifPosition* motifPos;
217               for (Int_t imot=0;imot<seg->GetNofMotifs();++imot) {
218                 motifPos 
219                   = fkSector->GetMotifMap()
220                     ->FindMotifPosition(seg->GetMotifPositionId(imot));
221                 if (motifPos && motifPos->HasPad(indices)) return motifPos;
222               }
223             }
224           }
225         }
226       }
227       return 0;
228     }
229     break;
230     ////////////////////////////////////////////////////////////////////////////////
231     case kY : {
232       // Case where all the pads have the same size along Y direction   
233       // look for the row which contains the indices
234       AliMpRow* row=0;
235       Int_t irow;
236       for (irow=0; irow<fkSector->GetNofRows(); ++irow) {
237         row = fkSector->GetRow(irow);
238         AliMpVRowSegment* lastSeg = row->GetRowSegment(row->GetNofRowSegments()-1);
239         if (lastSeg->GetLowIndicesLimit().GetSecond()<=indices.GetSecond() &&
240             lastSeg->GetHighIndicesLimit().GetSecond()>=indices.GetSecond()) break;
241         // NOTE : We use the last row segment in order to ensure that
242         // we are not on a special motif
243       }
244       if (irow==fkSector->GetNofRows()) return 0;
245       // look for the row segment, in the found row, which contains the indices
246       AliMpVRowSegment* seg=0;
247       Int_t iseg;
248       for (iseg=0;iseg<row->GetNofRowSegments();++iseg){
249         seg = row->GetRowSegment(iseg);
250         if (seg->HasIndices(indices)) break;
251       }
252       if (iseg==row->GetNofRowSegments()) return 0;
253   
254       // look for the motif position which contains the indices
255       AliMpMotifPosition* motifPos=0;
256       Int_t imot=0;
257       for (imot=0;imot<seg->GetNofMotifs();++imot) {
258         motifPos 
259           = fkSector->GetMotifMap()
260             ->FindMotifPosition(seg->GetMotifPositionId(imot));
261         if (motifPos && motifPos->HasPad(indices)) break;
262       }      
263       if (imot==seg->GetNofMotifs()) return 0;
264    
265       return motifPos;      
266     }
267     default: return 0;
268   }
269 }
270
271 //______________________________________________________________________________
272 AliMpPad 
273 AliMpSectorSegmentation::PadByXDirection(const TVector2& startPosition, 
274                                          Double_t maxX) const
275 {
276 /// Find the first valid pad from starting position in the
277 /// direction of pad lines up to distance dx.
278
279   // Define step limits
280   Double_t  stepX = fkSector->GetMinPadDimensions().X();
281  
282   // Search in X direction
283   AliMpPad pad;
284   TVector2 position(startPosition);    
285   do {
286     pad = PadByPosition(position, false);
287     position += TVector2(stepX, 0.);
288   }   
289   while ( !pad.IsValid() && position.X() < maxX ); 
290   
291   // Invalidate pad if it is outside limits
292   if ((pad.Position().X() - pad.Dimensions().X()) > maxX) 
293     pad = AliMpPad::Invalid();
294
295   return pad;
296 }
297
298 //______________________________________________________________________________
299 AliMpPad 
300 AliMpSectorSegmentation::PadByYDirection(const TVector2& startPosition, 
301                                          Double_t maxY) const
302 {
303 /// Find the first valid pad from starting position in the
304 /// direction of pad columns up to distance dx.
305   
306   // Define step limits
307   Double_t stepY = fkSector->GetMinPadDimensions().Y();
308  
309   // Search in Y direction
310   AliMpPad pad;
311   TVector2 position(startPosition);    
312   do {
313     pad = PadByPosition(position, false);
314     position += TVector2(0., stepY);
315   }   
316   while ( !pad.IsValid() && position.Y() < maxY ); 
317   
318   // Invalidate pad if it is outside limits
319   if ((pad.Position().Y() - pad.Dimensions().Y()) > maxY) 
320     pad = AliMpPad::Invalid();
321
322   return pad;
323 }
324
325 //
326 // public methods
327 //
328
329 //______________________________________________________________________________
330 AliMpVPadIterator* 
331 AliMpSectorSegmentation::CreateIterator(const AliMpArea& area) const
332 {
333 /// Create the area iterator. 
334
335   switch (fkSector->GetDirection()) {
336   
337     case kX: return new AliMpSectorAreaVPadIterator(this, area);
338              ;;
339     case kY: return new AliMpSectorAreaHPadIterator(this, area);
340              ;;
341   }
342   
343   Fatal("CreateIterator", "Incomplete switch on Sector direction");
344   return 0;  
345 }   
346   
347 //______________________________________________________________________________
348 AliMpVPadIterator* 
349 AliMpSectorSegmentation::CreateIterator(const AliMpPad& centerPad,
350                                         Bool_t includeCenter) const
351 {
352 /// Create the neighbours pad iterator.
353
354   return new AliMpNeighboursPadIterator(this, centerPad, includeCenter);
355 }   
356   
357 //______________________________________________________________________________
358 AliMpPad 
359 AliMpSectorSegmentation::PadByLocation(const AliMpIntPair& location, 
360                                        Bool_t warning) const
361 {
362 /// Find the pad which corresponds to the given location
363   
364   if ((*fPadBuffer).GetLocation()==location) return (*fPadBuffer);
365   
366   AliMpMotifPosition* motifPos = 
367     fkSector->GetMotifMap()->FindMotifPosition(location.GetFirst());
368   if (!motifPos){
369     if (warning) Warning("PadByLocation","The pad motif position ID doesn't exists");
370     return AliMpPad::Invalid();
371   }
372   
373   AliMpVMotif* motif = motifPos->GetMotif();
374   AliMpIntPair localIndices = 
375     motif->GetMotifType()->FindLocalIndicesByGassiNum(location.GetSecond());
376   if (! localIndices.IsValid()) {
377     if (warning) Warning("PadByLocation","The pad number doesn't exists");
378     return AliMpPad::Invalid();
379   }
380   TVector2 delta = motif->PadPositionLocal(localIndices);
381   return (*fPadBuffer) = AliMpPad(location,
382               motifPos->GlobalIndices(localIndices),
383               motifPos->Position()+delta,
384               motif->GetPadDimensions(localIndices));
385
386 }
387 //______________________________________________________________________________
388 AliMpPad 
389 AliMpSectorSegmentation::PadByIndices(const AliMpIntPair& indices,
390                                       Bool_t warning ) const
391 {
392 /// Find the pad which corresponds to the given indices  
393
394   if ((*fPadBuffer).GetIndices()==indices) return (*fPadBuffer);    
395    
396   AliMpMotifPosition* motifPos = FindMotifPosition(indices);
397   if (!motifPos) {    
398     if (warning) {
399       cout << "indices " <<  indices << endl;
400       Warning("PadByIndices","Pad indices not contained in any motif!");
401     }  
402     return AliMpPad::Invalid();
403   }
404   
405   // retrieve the local indices in the found motif
406   AliMpVMotif* motif = motifPos->GetMotif();
407   AliMpIntPair localIndices = indices - motifPos->GetLowIndicesLimit();
408   
409   AliMpConnection* connection=
410     motif->GetMotifType()->FindConnectionByLocalIndices(localIndices);
411     
412   if (!connection){
413     if (warning) Warning("PadByIndices","No connection with the given indices!");
414     return AliMpPad::Invalid();
415   }
416
417   TVector2 localPos = motif->PadPositionLocal(localIndices);
418
419   return (*fPadBuffer) 
420     = AliMpPad(AliMpIntPair(motifPos->GetID(),connection->GetGassiNum()),
421                indices,
422                motifPos->Position()+localPos,
423                motif->GetPadDimensions(localIndices)); 
424
425 }
426 //______________________________________________________________________________
427 AliMpPad 
428 AliMpSectorSegmentation::PadByPosition(const TVector2& position,
429                                        Bool_t warning) const
430 {
431 /// Find the pad which corresponds to the given position
432
433   if ((*fPadBuffer).Position().X()==position.X() && 
434       (*fPadBuffer).Position().Y()==position.Y()) return (*fPadBuffer);  
435
436   Int_t motifPosID = fkSector->FindMotifPositionId(position);
437   AliMpMotifPosition* motifPos 
438     = fkSector->GetMotifMap()
439         ->FindMotifPosition(motifPosID);
440     
441   if (!motifPos){
442     if (warning) Warning("PadByPosition","Position outside limits");
443     return AliMpPad::Invalid();
444   }
445
446   AliMpVMotif* motif =  motifPos->GetMotif();  
447   AliMpIntPair localIndices 
448     = motif->PadIndicesLocal(position-motifPos->Position());
449     
450   AliMpConnection* connect = 
451     motif->GetMotifType()->FindConnectionByLocalIndices(localIndices);
452
453    if (!connect){
454     if (warning) Warning("PadByPosition","Position outside motif limits");
455     return AliMpPad::Invalid();
456   }
457   
458   return (*fPadBuffer)
459     = AliMpPad(AliMpIntPair(motifPosID,connect->GetGassiNum()),
460                motifPos->GlobalIndices(localIndices),
461                motifPos->Position()+motif->PadPositionLocal(localIndices),
462                motif->GetPadDimensions(localIndices));
463
464 }
465
466 //______________________________________________________________________________
467 AliMpPad 
468 AliMpSectorSegmentation::PadByDirection(const TVector2& startPosition, 
469                                         Double_t distance) const
470 {
471 /// Find the first valid pad from starting position in the
472 /// direction of pad lines/columns up to the specified distance.
473 /// Pad lines are the lines of pads in the sector with constant pad y size,
474 /// pad columns are the columns of pads in the sector with constant pad x size. 
475
476   switch (fkSector->GetDirection()) {
477   
478     case kX: return PadByYDirection(startPosition, distance);
479              ;;
480     case kY: return PadByXDirection(startPosition, distance);
481              ;;
482   }
483   
484   Fatal("PadByDirection", "Incomplete switch on Sector direction");
485   return AliMpPad::Invalid();  
486 }
487
488 //______________________________________________________________________________
489 Int_t  AliMpSectorSegmentation::MaxPadIndexX()
490 {
491 /// Return maximum pad index in x
492
493   if (fMaxIndexInX) return fMaxIndexInX;
494   
495   for (Int_t i=0; i<fkSector->GetNofRows(); i++) {
496     Int_t ixh = fkSector->GetRow(i)->GetHighIndicesLimit().GetFirst();
497     if ( ixh > fMaxIndexInX ) fMaxIndexInX = ixh;
498   }  
499   return fMaxIndexInX;
500 }
501
502 //______________________________________________________________________________
503 Int_t  AliMpSectorSegmentation::MaxPadIndexY()
504 {
505 /// Return maximum pad index in y
506
507   if (fMaxIndexInY) return fMaxIndexInY;
508   
509   for (Int_t i=0; i<fkSector->GetNofRows(); i++) {
510     Int_t iyh = fkSector->GetRow(i)->GetHighIndicesLimit().GetSecond();
511     if ( iyh > fMaxIndexInY ) fMaxIndexInY = iyh;
512   }  
513   return fMaxIndexInY;
514 }
515
516 //______________________________________________________________________________
517 Bool_t AliMpSectorSegmentation::HasPad(const AliMpIntPair& indices) const
518 {
519 /// Does the pad specified by <indices> exist ?
520
521   return PadByIndices(indices,kFALSE) != AliMpPad::Invalid();
522 }
523
524 //______________________________________________________________________________
525 Bool_t AliMpSectorSegmentation::HasMotifPosition(Int_t motifPositionID) const
526 {
527 /// Does the motif position specified by motifPositionID exist ?
528
529   return (fkSector->GetMotifMap()->FindMotifPosition(motifPositionID) != 0);
530 }
531
532 //______________________________________________________________________________
533 TVector2  AliMpSectorSegmentation::GetMinPadDimensions() const
534 {
535 /// Returne the dimensions of the smallest pad.
536
537   return fkSector->GetMinPadDimensions();
538 }  
539
540 //______________________________________________________________________________
541 Int_t AliMpSectorSegmentation::Zone(const AliMpPad& pad, Bool_t warning) const
542 {
543 /// Return the zone index of the zone containing the specified pad.
544 /// This zone index is different from the zone ID,
545 /// as it is unique for each pad dimensions.
546 /// It is composed in this way:
547 ///   zoneID*10 + specific index 
548 /// Specific index is present only for zones containing special motifs.
549
550   if (!pad.IsValid()) {
551     if (warning) Warning("Zone(AliMpPad)", "Invalid pad");
552     return 0;
553   }  
554
555 #ifdef WITH_STL
556   PadDimensionsMapCIterator it;
557   for (it = fPadDimensionsMap.begin(); it != fPadDimensionsMap.end(); ++it) {
558     if (AliMpConstants::IsEqual(it->second, pad.Dimensions()))
559       return it->first;
560   }
561 #endif
562
563 #ifdef WITH_ROOT
564   PadDimensionsMapCIterator it(&fPadDimensionsMap);
565   Long_t key, value;
566   while ( it.Next(key, value) ) {
567     TVector2 dimensions =  GetVector(value);
568     if (AliMpConstants::IsEqual(dimensions, pad.Dimensions()))
569       return (Int_t)key;
570   } 
571   
572   AliError(Form("fPadDimensionsMap size is %d",fPadDimensionsMap.GetSize()));
573   
574 #endif
575
576   // Should never happen
577   AliError("Zone(AliMpPad pad) not found, where pad is :");
578   StderrToAliError(cerr << pad << endl;);
579   return 0;
580 }  
581
582 //______________________________________________________________________________
583 TVector2 
584 AliMpSectorSegmentation::PadDimensions(Int_t zone, Bool_t warning) const
585 {
586 /// Return the pad dimensions for the zone with the specified zone index.
587
588 #ifdef WITH_STL
589   PadDimensionsMapCIterator it = fPadDimensionsMap.find(zone);
590   if (it != fPadDimensionsMap.end()) return it->second;
591 #endif
592
593 #ifdef WITH_ROOT
594   Long_t value = fPadDimensionsMap.GetValue(zone);
595   if (value) return GetVector(value);
596 #endif
597
598   if (warning) Warning("PadDimensions(zone)", "not found");
599   return TVector2();
600 }  
601
602 //______________________________________________________________________________
603 Bool_t AliMpSectorSegmentation::CircleTest(const AliMpIntPair& indices) const
604 {
605 /// Verify that all methods for retrieving pads are consistents between them.
606 /// Return true if the pad with specified indices was found and verified,
607 /// false otherwise.
608
609   if (!HasPad(indices)) return false;
610
611   // Verify the indice->location->position->indice way
612   AliMpIntPair location = PadByIndices(indices).GetLocation();
613   TVector2 position = PadByLocation(location).Position();
614   AliMpIntPair retIndices = PadByPosition(position).GetIndices();
615     
616   if (retIndices != indices) {
617     cout << "Pad " << indices << " lead to inconsistency" << endl;
618     cout << "in indice->location->position->indice way..." << endl;
619     cout << "starting from " << indices << "-->" << location << "-->" 
620          << '(' << position.X() << ',' << position.Y() << ')'
621          << " and retIndices: " << retIndices << endl;
622   }
623     
624     
625   // Verify the indice->position->location->indice way    
626   position = PadByIndices(indices).Position();
627   location = PadByPosition(position).GetLocation();
628   retIndices = PadByLocation(location).GetIndices();
629
630   if (retIndices != indices) {
631     cout << "Pad " << indices << " lead to inconsistency" << endl;
632     cout << "in indice->position->location->indice way..." <<endl;
633     cout << "starting from " << indices 
634          << " and retIndices: " << retIndices << endl;
635   }
636   
637   return true;
638 }
639
640 //______________________________________________________________________________
641 void AliMpSectorSegmentation::PrintZones() const
642 {
643 /// Print all zones and pads dimensions from the map.
644
645   cout << "Zones: " << endl;
646
647 #ifdef WITH_STL
648   PadDimensionsMapCIterator it;
649   for (it = fPadDimensionsMap.begin(); it != fPadDimensionsMap.end(); ++it) {
650     cout << "    zone: " <<   setw(4) << it->first;
651     cout << "    pad dimensions: ( " 
652          << it->second.X() << ", " << it->second.Y() << ")" << endl; 
653   }
654 #endif
655
656 #ifdef WITH_ROOT
657   PadDimensionsMapCIterator it(&fPadDimensionsMap);
658   Long_t key, value;
659   while ( it.Next(key, value) ) {
660     //cout << "Iterating over: " << key << ", " << value << endl;
661     TVector2 dimensions =  GetVector(value);
662
663     cout << "    zone: " <<   setw(4) << key;
664     cout << "    pad dimensions: ( " 
665          << dimensions.X() << ", " << dimensions.Y() << ")" << endl; 
666   }
667 #endif
668 }
669