Polygon.C

Deil Christoph, 10/11/2012 01:53 PM

Download (8.83 KB)

 
1

    
2
#include <iostream>
3
#include <string>
4
#include <sstream>
5

    
6

    
7
#include <TPad.h>
8
#include <TBox.h>
9
#include <TLine.h>
10
#include <TRandom.h>
11
#include <TGeoPolygon.h>
12

    
13
#include <sash/HESSArray.hh>
14
#include <sash/TimeDiff.hh>
15
#include <sash/Time.hh>
16
#include <stash/constants.h>
17

    
18
#include "../include/Region.hh"
19
#include "../include/Polygon.hh"
20

    
21
#define DEBUG 1
22
#include <utilities/debugging.hh>
23

    
24
using namespace std;
25

    
26
/**
27
 * 
28
 * \param vertices: list of vertex coordinates in absolute coordinates
29
 * (must have at least one entry). These must be defined clockwise. 
30
 *
31
 * The center of the polygon (used for e.g. bounding boxes, etc) will
32
 * be calculated using GetCentreOfGravity().
33
 */
34
Tools::Polygon::
35
Polygon(vector<Stash::Coordinate> vertices, string name) 
36
  : Region( vertices[0], name, "POLYGON", Stash::Lambda(0) ),
37
    fPoly(NULL), fX(NULL), fY(NULL)
38
{
39
    
40
  DEBUG_OUT << "Initializing vertices: " << vertices.size() << endl;
41

    
42

    
43
  // construct the TGeoPolygon:
44
  fX = new TArrayD(vertices.size());
45
  fY = new TArrayD(vertices.size());
46

    
47
  for (size_t ii=0; ii < vertices.size(); ii++) {
48

    
49
    (*fX)[ii] = vertices[ii].GetLambda().GetDegrees();
50
    (*fY)[ii] = vertices[ii].GetBeta().GetDegrees();
51

    
52
  }
53
    
54
  fPoly = new TGeoPolygon( vertices.size() );
55
  fPoly->SetXY( fX->GetArray(), fY->GetArray() );
56
  fPoly->FinishPolygon();
57
 
58
  // move the center to the COG:
59
  fCentre = GetCentreOfGravity();
60

    
61

    
62
}
63

    
64
Tools::Polygon::
65
Polygon( const Tools::Polygon &cpy) 
66
  : Region(cpy)
67
{
68
  fPoly = new TGeoPolygon( cpy.fPoly->GetNvert() );
69
  fX = new TArrayD( *(cpy.fX) );
70
  fY = new TArrayD( *(cpy.fY) );
71
  fPoly->SetXY(fX->GetArray(),fY->GetArray());
72
  fPoly->FinishPolygon();
73
}
74

    
75
Tools::Polygon::
76
Polygon() 
77
      : fPoly(NULL),fX(NULL),fY(NULL) {
78
  Sash::HESSArray::GetHESSArray();
79
  
80
}
81
    
82
Tools::Polygon::~Polygon() {
83
  delete fX;
84
  delete fY;
85
  delete fPoly;
86
}
87

    
88

    
89

    
90
double 
91
Tools::Polygon::GetArea() const {
92

    
93
  if (!fPoly) return 0;
94

    
95
  double centreX = fCentre.GetLambda().GetDegrees();
96
  double centreY = fCentre.GetBeta().GetDegrees();
97
  unsigned int nvert = fPoly->GetNvert();
98
  Double_t *px = fPoly->GetX();
99
  Double_t *py = fPoly->GetY();
100
  Double_t dx[nvert];
101
  Double_t dy[nvert];
102
  double rafactor;
103
  double area=0;
104

    
105
  for (unsigned int ii = 0; ii < nvert; ii++) {
106
    rafactor = cos(py[ii]*M_PI/180.0);
107
    dx[ii] = (px[ii] - centreX) * rafactor;
108
    dy[ii] = py[ii] - centreY;
109
  }
110

    
111
  for (unsigned int ii = 0; ii < nvert; ii++) {
112
    unsigned int jj = (ii+1)%nvert;
113

    
114
    area += dx[ii]*dy[jj] - dx[jj]*dy[ii];
115

    
116
  }
117

    
118
  return fabs(area)/2.0;
119

    
120
}
121

    
122
bool
123
Tools::Polygon::IsInside( const Stash::Coordinate& dir ) const {
124
  double point[2];
125
  point[0] = dir.GetLambda().GetDegrees();
126
  point[1] = dir.GetBeta().GetDegrees();
127
  return fPoly->Contains( point );
128
}
129

    
130
Tools::Region::VertexList 
131
Tools::Polygon::AsVertexList() const {
132

    
133
  Tools::Region::VertexList vlist;
134
  if (!fPoly) return vlist;
135
  int nvert = fPoly->GetNvert();
136
  Double_t *px = fPoly->GetX();
137
  Double_t *py = fPoly->GetY();
138

    
139
  vlist.resize(1);
140

    
141
  for (int ii=0; ii < nvert; ii++) {
142
    Stash::Lambda lambda(px[ii], Stash::Angle::Degrees);
143
    Stash::Beta beta(py[ii], Stash::Angle::Degrees);
144
    Stash::Coordinate cor(lambda,
145
                          beta,
146
                          GetCentre().GetSystem());
147
    vlist[0].push_back(InverseTransform(cor));
148
  }
149

    
150
  vlist[0].push_back( vlist[0][0] ); // close the curve
151
    
152
  return vlist;
153

    
154
}
155

    
156

    
157
string
158
Tools::Polygon::
159
AsFITSRegionString() const{
160

    
161
  if (!fPoly) return "";
162

    
163
  ostringstream ost;
164
  int nvert = fPoly->GetNvert();
165
  Double_t *px = fPoly->GetX();
166
  Double_t *py = fPoly->GetY();   
167

    
168
  ost << GetFITSSystemName()<<"; polygon(";
169
  for (int ii=0; ii < nvert; ii++) {
170
    Stash::Lambda lambda(px[ii], Stash::Angle::Degrees);
171
    Stash::Beta beta(py[ii], Stash::Angle::Degrees);
172
    Stash::Coordinate cor(lambda,
173
                          beta,
174
                          GetCentre().GetSystem());
175
    double xx = InverseTransform(cor).GetLambda().GetDegrees();
176
    double yy = InverseTransform(cor).GetBeta().GetDegrees();
177
    ost<<xx<<","<<yy;
178
    if (ii!= nvert-1) ost<<",";
179
  }  
180
  ost << ") # text={" << GetName() <<"} ";
181
  return ost.str();
182
  
183
}
184

    
185

    
186

    
187
/**
188
 * Grows the boundary of the region out from the center point. 
189
 *
190
 * \bug: this doesn't actually work. Need to properly get the polar coordinates.
191
 */
192
Tools::Polygon* 
193
Tools::Polygon::
194
GrowBoundary(const double degrees, const std::string name) const{
195
  // implement using GetOffsetOfPointFromCenter and GetPointAtOffsetFromCenter
196

    
197
  if (!fPoly) return NULL;
198

    
199
  int nvert = fPoly->GetNvert();
200
  Double_t *px = fPoly->GetX();
201
  Double_t *py = fPoly->GetY();
202

    
203
  vector<Stash::Coordinate> vertices;
204
  
205
  for (int ii=0; ii < nvert; ii++) {
206
    Stash::Lambda lambda(px[ii], Stash::Angle::Degrees);
207
    Stash::Beta beta(py[ii], Stash::Angle::Degrees);
208
    Stash::Coordinate cor(lambda,
209
                          beta,
210
                          fCentre.GetSystem());
211

    
212
    
213
    // calculate radial coordinate (R,phi) for each point centered on
214
    // the region center:
215
    Stash::DirectionVector cdv = fCentre.GetDirectionVector();
216
    Stash::DirectionVector pdv = cor.GetDirectionVector();
217
    Stash::DirectionVector ddv = pdv.RotateToZenith(cdv);
218

    
219
    Stash::Lambda phi( ddv.GetTheta().GetDegrees(), Stash::Angle::Degrees );
220
    double rad = cor.GetAngularDistance(fCentre).GetDegrees();
221

    
222
    // increase the radius, and create the new point:
223
    Stash::Beta newrad(degrees + rad, Stash::Angle::Degrees);
224
    DEBUG_OUT << ii  <<" PHI "<< phi.GetDegrees()
225
              << " RAD : " << rad << " NEW : " << newrad.GetDegrees() << endl;
226
    
227
    Stash::Coordinate newcor = GetPointAtRadius( newrad, phi );
228
    vertices.push_back(newcor);
229

    
230
  }
231

    
232
  return new Tools::Polygon( vertices, string(GetName())+name );
233

    
234
};
235

    
236

    
237
double
238
Tools::Polygon::
239
GetBound1() const {
240
  
241
  if (!fPoly) return 0;
242

    
243
  int nvert = fPoly->GetNvert();
244
  Double_t *px = fPoly->GetX();
245
  Double_t *py = fPoly->GetY();
246

    
247
  double maxdx = -1000;
248

    
249
  for (int ii=0; ii < nvert; ii++) {
250
    Stash::Lambda lambda(px[ii], Stash::Angle::Degrees);
251
    Stash::Beta beta(py[ii], Stash::Angle::Degrees);
252
    Stash::Coordinate cor(lambda,
253
                          beta,
254
                          GetCentre().GetSystem());
255
    double dx,dy;
256
    GetOffsetOfPointFromCenter( InverseTransform(cor), dx, dy, true );
257
    if (fabs(dx) > maxdx) maxdx = fabs(dx);
258

    
259
  }
260

    
261
  return 2.0*maxdx;
262

    
263
}
264

    
265

    
266
double
267
Tools::Polygon::
268
GetBound2() const {
269
  
270
  if (!fPoly) return 0;
271

    
272
  int nvert = fPoly->GetNvert();
273
  Double_t *px = fPoly->GetX();
274
  Double_t *py = fPoly->GetY();
275

    
276
  double maxdy = -1000;
277

    
278
  Stash::Coordinate cen = GetCentreOfGravity();
279

    
280
  for (int ii=0; ii < nvert; ii++) {
281
    Stash::Lambda lambda(px[ii], Stash::Angle::Degrees);
282
    Stash::Beta beta(py[ii], Stash::Angle::Degrees);
283
    Stash::Coordinate cor(lambda,
284
                          beta,
285
                          cen.GetSystem());
286
    double dx,dy;
287
    GetOffsetOfPointFromCenter( InverseTransform(cor), dx, dy,true );
288
    if (fabs(dy) > maxdy) maxdy = fabs(dy);
289

    
290
  }
291

    
292
  return 2.0*maxdy;
293

    
294
}
295

    
296

    
297

    
298

    
299
double
300
Tools::Polygon::
301
GetRadialBound() const {
302
  
303
  if (!fPoly) return 0;
304

    
305
  int nvert = fPoly->GetNvert();
306
  Double_t *px = fPoly->GetX();
307
  Double_t *py = fPoly->GetY();
308

    
309
  double maxdist = -1000;
310

    
311
  for (int ii=0; ii < nvert; ii++) {
312
    Stash::Lambda lambda(px[ii], Stash::Angle::Degrees);
313
    Stash::Beta beta(py[ii], Stash::Angle::Degrees);
314
    Stash::Coordinate cor(lambda,
315
                          beta,
316
                          GetCentre().GetSystem());
317
    
318
    double dist = cor.GetAngularDistance( fCentre ).GetDegrees();
319
    if (dist > maxdist) maxdist=dist;
320

    
321
  }
322

    
323
  return maxdist;
324

    
325
}
326

    
327

    
328
void 
329
Tools::Polygon::
330
MoveTo( Stash::Coordinate newpos ) {
331
  
332
  if (!fPoly) return;
333

    
334
  int nvert = fPoly->GetNvert();
335
  Double_t *px = fPoly->GetX();
336
  Double_t *py = fPoly->GetY();
337

    
338
  double cx = fCentre.GetLambda().GetDegrees();
339
  double cy = fCentre.GetBeta().GetDegrees();
340

    
341
  double nx = newpos.GetLambda().GetDegrees();
342
  double ny = newpos.GetBeta().GetDegrees();
343

    
344
  for (int ii=0; ii < nvert; ii++) {
345
      
346
    px[ii] += cx-nx;
347
    py[ii] += cy-ny;
348

    
349
  }
350

    
351
  fCentre = newpos;
352

    
353
}
354

    
355
/**
356
 * Custom streamer since TGeoPolygon doesn't automatically get updated when streamed...
357
 */
358
void Tools::Polygon::Streamer(TBuffer &R__b)
359
{
360
   // Stream an object of class Tools::Polygon.
361

    
362
   //This works around a msvc bug and should be harmless on other platforms
363
   typedef ::Tools::Polygon thisClass;
364
   UInt_t R__s, R__c;
365
   if (R__b.IsReading()) {
366
      Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }
367
      //This works around a msvc bug and should be harmless on other platforms
368
      typedef Tools::Region baseClass0;
369
      baseClass0::Streamer(R__b);
370
      R__b >> fPoly;
371
      R__b >> fX;
372
      R__b >> fY;
373
      R__b.CheckByteCount(R__s, R__c, thisClass::IsA());
374

    
375
      // Initialize Polygon:
376
      fPoly->SetXY( fX->GetArray(), fY->GetArray() );
377
      fPoly->FinishPolygon();
378

    
379
   } else {
380
      R__c = R__b.WriteVersion(thisClass::IsA(), kTRUE);
381
      //This works around a msvc bug and should be harmless on other platforms
382
      typedef Tools::Region baseClass0;
383
      baseClass0::Streamer(R__b);
384
      R__b << fPoly;
385
      R__b << fX;
386
      R__b << fY;
387
      R__b.SetByteCount(R__c, kTRUE);
388
   }
389
}