ROOT logo
// $Id: Extendio.cxx 2548 2011-10-10 07:03:57Z matevz $

// Copyright (C) 1999-2008, Matevz Tadel. All rights reserved.
// This file is part of GLED, released under GNU General Public License version 2.
// For the licensing terms see $GLEDSYS/LICENSE or http://www.gnu.org/.

//__________________________________________________________________________
// Extendio
//
//

#include "Extendio.h"
#include "Glasses/ZImage.h"
#include "Extendio.c7"

#include "Tringula.h"

ClassImp(Extendio);

/**************************************************************************/

void Extendio::_init()
{
  // Override settings from ZGlass
  bUseDispList = true;

  mTringula = 0;

  bExploding = false;

  mLastTransPtr = &mTrans;
  mLastAABBPtr  = &mAABB;

  mDebugBits = 0;
}

Extendio::Extendio(const Text_t* n, const Text_t* t) :
  ZGlass(n,t),
  mHitPoints(100, -100, 100)
{
  _init();
}

Extendio::~Extendio()
{}

//==============================================================================

void Extendio::SetTringula(Tringula* tring)
{
  // Set tringula to which the extendio is attached.
  // Sub-classes override this to reinitialize cached data.

  mTringula = tring;
}

//==============================================================================

void Extendio::TakeDamage(Float_t damage)
{
  Bool_t was_exploding = bExploding;
  mHitPoints.Delta(-damage);
  if (mHitPoints.Get() < 0 && !was_exploding)
  {
    bExploding = true;
    mTringula->ExtendioExploding(this);
  }
}

//==============================================================================
// Intersection utilities
//==============================================================================

Float_t Extendio::height_above_terrain(const Opcode::Point& down_dir)
{
  static const Exc_t _eh("Extendio::height_above_terrain ");

  Opcode::RayCollider    RC;
  RC.SetFirstContact(false);  // true to only take first hit (not closest!)
  RC.SetClosestHit(true);     // to keep the closes hit only
  Opcode::CollisionFaces CF;
  RC.SetDestination(&CF);

  Opcode::Ray R(ref_pos(), down_dir);

  bool cs = RC.Collide(R, *mTringula->GetMesh()->GetOPCModel());
  if (cs && CF.GetNbFaces() == 1)
  {
      const Opcode::CollisionFace& cf = CF.GetFaces()[0];
      return cf.mDistance;
  }
  else
  {
    ISwarn(_eh + RC.CollideInfo(cs, R));
    return 0;
  }

}

Int_t Extendio::collide_with_tringula(CollisionSegments& segments)
{
  static const Exc_t _eh("Extendio::collide_with_tringula ");

  Int_t count = 0;

  Opcode::AABBTreeCollider collider;
  Opcode::BVTCache         cache;
  cache.Model0 = mTringula->GetMesh()->GetOPCModel();
  cache.Model1 = get_opc_model();

  TringTvor *TT0 = mTringula->GetMesh()->GetTTvor();
  TringTvor *TT1 = GetMesh()->GetTTvor();
  HTransF    HT0;  // identity
  HTransF   &HT1 = ref_trans();

  Bool_t s0 = collider.Collide(cache, 0, HT1);
  Bool_t s1 = collider.GetContactStatus();
  UInt_t np = collider.GetNbPairs();

  if (!s0)
  {
    printf("%scrappy collision status - result=%d, contact=%d, n_pairs=%u!\n",
           _eh.Data(), s0, s1, np);
  }

  const Opcode::Pair *ps = collider.GetPairs();
  Opcode::Segment     segment;

  for (UInt_t j = 0; j < np; ++j)
  {
    if (intersect_triangle(TT0, TT1, HT0, HT1,
			   ps[j].id0, ps[j].id1,
			   segment))
    {
      segments.push_back(segment);
      ++count;
    }
  }

  return count;
}


//------------------------------------------------------------------------------
// Static intersection utilities
//------------------------------------------------------------------------------

bool Extendio::intersect_triangle(TringTvor* TT0, TringTvor* TT1,
                                  HTransF  & HT0, HTransF  & HT1,
                                  Int_t    tidx0, Int_t    tidx1,
                                  Opcode::Segment& segment,
                                  const Text_t* debug_prefix)
{
  // Calculate intersection line between triangle tidx0 from Extendio ext0
  // and triangle tidx1 from ext1 in parent coordinate system.
  // Output:
  //   segment - contains the endpoints of the intersection line
  //
  // Returns: false if triangles actually do not intersect.
  // !!!! This is not fully checked, only distance_pattern is.
  //
  // If debug_prefix is set, some information is dumped along the
  // path, each line prefixed with this string.

  static const Exc_t _eh("Extendio::intersect_triangle ");

  using namespace Opcode;

  Int_t* T0 = TT0->Triangle(tidx0);
  Int_t* T1 = TT1->Triangle(tidx1);

  // Transform triangle vertices to parent coordinate system.
  // [ If we ever get proper dynamics, transform also velocities.
  //   Or maybe transform the intersection lines or whatever. ]
  Point V0[3], V1[3];
  for (int k=0; k<3; ++k)
  {
    HT0.MultiplyVec3(TT0->Vertex(T0[k]), 1.0f, V0[k]);
    HT1.MultiplyVec3(TT1->Vertex(T1[k]), 1.0f, V1[k]);
  }

  // Define plane of triangle T0
  Plane P(V0[0], V0[1], V0[2]);

  // Calculate distance of T1's vertices to plane P
  Float_t dst[3];
  dst[0] = P.Distance(V1[0]);
  dst[1] = P.Distance(V1[1]);
  dst[2] = P.Distance(V1[2]);

  // Determine edges of T1 that intersect plane P
  // Calculate intersection points
  Point ip[2];
  Int_t pat =  4*(dst[2] > 0) + 2*(dst[1] > 0) + (dst[0] > 0);

  if (debug_prefix)
    printf("%sdistances = %f, %f, %f; sign_patern = %d\n", debug_prefix,
           dst[0], dst[1], dst[2], pat);

  switch (pat)
  {
    // void intersection_point(const Plane& P, const Point& a, const Point&b, Point& result)
    case 1:
      ip[0].Mac(V1[0], V1[1]-V1[0], dst[0] / (dst[0] - dst[1]));
      ip[1].Mac(V1[0], V1[2]-V1[0], dst[0] / (dst[0] - dst[2]));
      break;
    case 6:
      ip[0].Mac(V1[1], V1[0]-V1[1], dst[1] / (dst[1] - dst[0]));
      ip[1].Mac(V1[2], V1[0]-V1[2], dst[2] / (dst[2] - dst[0]));
      break;
    case 2:
      ip[0].Mac(V1[1], V1[0]-V1[1], dst[1] / (dst[1] - dst[0]));
      ip[1].Mac(V1[1], V1[2]-V1[1], dst[1] / (dst[1] - dst[2]));
      break;
    case 5:
      ip[0].Mac(V1[0], V1[1]-V1[0], dst[0] / (dst[0] - dst[1]));
      ip[1].Mac(V1[2], V1[1]-V1[2], dst[2] / (dst[2] - dst[1]));
      break;
    case 3:
      ip[0].Mac(V1[1], V1[2]-V1[1], dst[1] / (dst[1] - dst[2]));
      ip[1].Mac(V1[0], V1[2]-V1[0], dst[0] / (dst[0] - dst[2]));
      break;
    case 4:
      ip[0].Mac(V1[2], V1[1]-V1[2], dst[2] / (dst[2] - dst[1]));
      ip[1].Mac(V1[2], V1[0]-V1[2], dst[2] / (dst[2] - dst[0]));
      break;
    default:
      return false;
  }

  // Clip line into triangle T0: 3 steps

  // Define triangle coords
  Point e1; e1.Sub(V0[1], V0[0]);
  Point e2; e2.Sub(V0[2], V0[0]);
  Float_t e1sq = e1.SquareMagnitude();
  Float_t e2sq = e2.SquareMagnitude();
  Float_t d    = e1 | e2;

  // Calculate u,v coords of both points.
  Point uv[2];
  for (int k=0; k<2; ++k)
  {
    Point p; p.Sub(ip[k], V0[0]);
    Float_t e1p  = e1 | p;
    Float_t e2p  = e2 | p;
    uv[k].x = (e1p * e2sq - e2p * d) / (e1sq * e2sq - d * d);
    uv[k].y = (e2p - uv[k].x * d) / e2sq;
    // uv[k].z = 0; // if this becomes relevant, now always used by x,y components.
  }
  Point duv;  duv.Sub(uv[1], uv[0]);

  if (debug_prefix)
    printf("%suv0 = % 5.3f, % 5.3f; uv1 = % 5.3f, % 5.3f; duv = % 5.3f, % 5.3f\n", debug_prefix,
           uv[0].x, uv[0].y, uv[1].x, uv[1].y, duv.x, duv.y);

  // Check if outside triangle limits
  Float_t t[3];    // intersection times holder
  Int_t   ti, ts;  // time index; selected (maximal) index

  // First point ... calculate intersection multipliers
  ti = ts = 0;
  if (uv[0].x < 0)
  {
    t[ti] = -uv[0].x / duv.x;
    if (t[ti] > 0.0f && t[ti] < 1.0f) ++ti;
  }
  if (uv[0].y < 0 )
  {
    t[ti] = -uv[0].y / duv.y;
    if (t[ti] > 0.0f && t[ti] < 1.0f) ++ti;
  }
  if (uv[0].x+uv[0].y > 1)
  {
    t[ti] = (1 - uv[0].x - uv[0].y) / (duv.x + duv.y);
    if (t[ti] > 0.0f && t[ti] < 1.0f) ++ti;
  }

  if (debug_prefix)
    printf("%sfirst pnt: ti=%d, t0=%f, t1=%f, ts=%d\n", debug_prefix,
           ti, t[0], t[1], ts);

  // First point ... fix if necessary; assume positive 't[ts]'!
  if (ti > 0)
  {
    if (ti >= 2)
    {
      if (ti == 3)
      {
        printf("%sWarning-1, all 3 conditions true! Ignoring last solution.\n", _eh.Data());
      }
      if (t[1] > t[0]) ts = 1;
    }
    ip[0].TMac2(e1, t[ts]*duv.x, e2, t[ts]*duv.y);

    if (debug_prefix)
      printf("%sfirst pnt: ti=%d, t0=%f, t1=%f, ts=%d\n", debug_prefix,
             ti, t[0], t[1], ts);
  }

  // Second point ... calculate intersection multipliers
  // Invert du, dv and at the end also sign of t[ts]
  ti = ts = 0;
  if (uv[1].x < 0)
  {
    t[ti] = uv[1].x / duv.x;
    if (t[ti] > 0.0f && t[ti] < 1.0f) ++ti;
  }
  if (uv[1].y < 0 )
  {
    t[ti] = uv[1].y / duv.y;
    if (t[ti] > 0.0f && t[ti] < 1.0f) ++ti;
  }
  if (uv[1].x+uv[1].y > 1)
  {
    t[ti] = - (1 - uv[1].x - uv[1].y) / (duv.x + duv.y);
    if (t[ti] > 0.0f && t[ti] < 1.0f) ++ti;
  }

  if (debug_prefix)
    printf("%ssecnd pnt: ti=%d, t0=%f, t1=%f, ts=%d\n", debug_prefix,
           ti, t[0], t[1], ts);

  // Second point ... fix if necessary; assume positive 't[ts]'!
  if (ti > 0)
  {
    if (ti >= 2)
    {
      if (ti == 3)
      {
        printf("%sWarning-2, all 3 conditions true! Ignoring last solution.\n", _eh.Data());
      }
      if (t[1] > t[0]) ts = 1;
    }
    ip[1].TMac2(e1, -t[ts]*duv.x, e2, -t[ts]*duv.y);

    if (debug_prefix)
      printf("%ssecnd pnt: ti=%d, t0=%f, t1=%f, ts=%d\n", debug_prefix,
             ti, t[0], t[1], ts);
  }

  if (debug_prefix)
      printf("%s(%f,%f,%f), (%f, %f,%f) -- %f\n", debug_prefix,
             ip[0].x, ip[0].y, ip[0].z,
             ip[1].x, ip[1].y, ip[1].z, (ip[1]-ip[0]).Magnitude());


  // Copy the result
  segment.mP0 = ip[0];
  segment.mP1 = ip[1];

  return true;
}

//------------------------------------------------------------------------------

int Extendio::intersect_extendios(Extendio* ext0, Extendio* ext1,
                                  Opcode::AABBTreeCollider& collider,
                                  vector<Opcode::Segment> & segments,
                                  const Text_t* debug_prefix)
{
  // Intersect extendios ext0 and ext1.
  //
  // Output vector 'segments' is filled with line-segments of
  // intersecting triangles.
  //
  // Returns number of added segments.

  using namespace Opcode;

  int count = 0;

  BVTCache cache;
  cache.Model0 = ext0->get_opc_model();
  cache.Model1 = ext1->get_opc_model();

  Bool_t s0 = collider.Collide(cache, ext0->ref_trans(), ext1->ref_trans());
  Bool_t s1 = collider.GetContactStatus();
  UInt_t np = collider.GetNbPairs();

  const Text_t* sec_debug_prefix = 0;
  TString foo;
  if (debug_prefix)
  {
    printf("%s .vs. %s; result=%d, contact=%d, n_pairs=%u\n",
           ext0->GetName(), ext1->GetName(), s0, s1, np);
    foo = debug_prefix;
    foo += "    ";
    sec_debug_prefix = foo.Data();
  }

  // Triangle pairs
  const Pair* ps = collider.GetPairs();
  Segment     segment;

  TringTvor* TT0 = ext0->GetMesh()->GetTTvor();
  TringTvor* TT1 = ext1->GetMesh()->GetTTvor();
  HTransF  & HT0 = ext0->ref_trans();
  HTransF  & HT1 = ext1->ref_trans();

  for (UInt_t j = 0; j < np; ++j)
  {
    if (debug_prefix)
      printf("%s%2u: tri_idx0=%3d tri_idx1=%3d\n", debug_prefix,
             j, ps[j].id0, ps[j].id1);

    if (Extendio::intersect_triangle(TT0, TT1, HT0, HT1,
                                     ps[j].id0, ps[j].id1,
                                     segment, sec_debug_prefix))
    {
      segments.push_back(segment);
      ++count;
    }
  }

  return count;
}


//==============================================================================
// Extendio::CollisionSegments
//==============================================================================

void Extendio::CollisionSegments::calculate_center()
{
  HPointD sum;
  for (iterator s = begin(); s != end(); ++s)
  {
    sum += s->mP0;
    sum += s->mP1;
  }
  sum *= 0.5 / size();
  mCenter.Set(sum.x, sum.y, sum.z);
}
 Extendio.cxx:1
 Extendio.cxx:2
 Extendio.cxx:3
 Extendio.cxx:4
 Extendio.cxx:5
 Extendio.cxx:6
 Extendio.cxx:7
 Extendio.cxx:8
 Extendio.cxx:9
 Extendio.cxx:10
 Extendio.cxx:11
 Extendio.cxx:12
 Extendio.cxx:13
 Extendio.cxx:14
 Extendio.cxx:15
 Extendio.cxx:16
 Extendio.cxx:17
 Extendio.cxx:18
 Extendio.cxx:19
 Extendio.cxx:20
 Extendio.cxx:21
 Extendio.cxx:22
 Extendio.cxx:23
 Extendio.cxx:24
 Extendio.cxx:25
 Extendio.cxx:26
 Extendio.cxx:27
 Extendio.cxx:28
 Extendio.cxx:29
 Extendio.cxx:30
 Extendio.cxx:31
 Extendio.cxx:32
 Extendio.cxx:33
 Extendio.cxx:34
 Extendio.cxx:35
 Extendio.cxx:36
 Extendio.cxx:37
 Extendio.cxx:38
 Extendio.cxx:39
 Extendio.cxx:40
 Extendio.cxx:41
 Extendio.cxx:42
 Extendio.cxx:43
 Extendio.cxx:44
 Extendio.cxx:45
 Extendio.cxx:46
 Extendio.cxx:47
 Extendio.cxx:48
 Extendio.cxx:49
 Extendio.cxx:50
 Extendio.cxx:51
 Extendio.cxx:52
 Extendio.cxx:53
 Extendio.cxx:54
 Extendio.cxx:55
 Extendio.cxx:56
 Extendio.cxx:57
 Extendio.cxx:58
 Extendio.cxx:59
 Extendio.cxx:60
 Extendio.cxx:61
 Extendio.cxx:62
 Extendio.cxx:63
 Extendio.cxx:64
 Extendio.cxx:65
 Extendio.cxx:66
 Extendio.cxx:67
 Extendio.cxx:68
 Extendio.cxx:69
 Extendio.cxx:70
 Extendio.cxx:71
 Extendio.cxx:72
 Extendio.cxx:73
 Extendio.cxx:74
 Extendio.cxx:75
 Extendio.cxx:76
 Extendio.cxx:77
 Extendio.cxx:78
 Extendio.cxx:79
 Extendio.cxx:80
 Extendio.cxx:81
 Extendio.cxx:82
 Extendio.cxx:83
 Extendio.cxx:84
 Extendio.cxx:85
 Extendio.cxx:86
 Extendio.cxx:87
 Extendio.cxx:88
 Extendio.cxx:89
 Extendio.cxx:90
 Extendio.cxx:91
 Extendio.cxx:92
 Extendio.cxx:93
 Extendio.cxx:94
 Extendio.cxx:95
 Extendio.cxx:96
 Extendio.cxx:97
 Extendio.cxx:98
 Extendio.cxx:99
 Extendio.cxx:100
 Extendio.cxx:101
 Extendio.cxx:102
 Extendio.cxx:103
 Extendio.cxx:104
 Extendio.cxx:105
 Extendio.cxx:106
 Extendio.cxx:107
 Extendio.cxx:108
 Extendio.cxx:109
 Extendio.cxx:110
 Extendio.cxx:111
 Extendio.cxx:112
 Extendio.cxx:113
 Extendio.cxx:114
 Extendio.cxx:115
 Extendio.cxx:116
 Extendio.cxx:117
 Extendio.cxx:118
 Extendio.cxx:119
 Extendio.cxx:120
 Extendio.cxx:121
 Extendio.cxx:122
 Extendio.cxx:123
 Extendio.cxx:124
 Extendio.cxx:125
 Extendio.cxx:126
 Extendio.cxx:127
 Extendio.cxx:128
 Extendio.cxx:129
 Extendio.cxx:130
 Extendio.cxx:131
 Extendio.cxx:132
 Extendio.cxx:133
 Extendio.cxx:134
 Extendio.cxx:135
 Extendio.cxx:136
 Extendio.cxx:137
 Extendio.cxx:138
 Extendio.cxx:139
 Extendio.cxx:140
 Extendio.cxx:141
 Extendio.cxx:142
 Extendio.cxx:143
 Extendio.cxx:144
 Extendio.cxx:145
 Extendio.cxx:146
 Extendio.cxx:147
 Extendio.cxx:148
 Extendio.cxx:149
 Extendio.cxx:150
 Extendio.cxx:151
 Extendio.cxx:152
 Extendio.cxx:153
 Extendio.cxx:154
 Extendio.cxx:155
 Extendio.cxx:156
 Extendio.cxx:157
 Extendio.cxx:158
 Extendio.cxx:159
 Extendio.cxx:160
 Extendio.cxx:161
 Extendio.cxx:162
 Extendio.cxx:163
 Extendio.cxx:164
 Extendio.cxx:165
 Extendio.cxx:166
 Extendio.cxx:167
 Extendio.cxx:168
 Extendio.cxx:169
 Extendio.cxx:170
 Extendio.cxx:171
 Extendio.cxx:172
 Extendio.cxx:173
 Extendio.cxx:174
 Extendio.cxx:175
 Extendio.cxx:176
 Extendio.cxx:177
 Extendio.cxx:178
 Extendio.cxx:179
 Extendio.cxx:180
 Extendio.cxx:181
 Extendio.cxx:182
 Extendio.cxx:183
 Extendio.cxx:184
 Extendio.cxx:185
 Extendio.cxx:186
 Extendio.cxx:187
 Extendio.cxx:188
 Extendio.cxx:189
 Extendio.cxx:190
 Extendio.cxx:191
 Extendio.cxx:192
 Extendio.cxx:193
 Extendio.cxx:194
 Extendio.cxx:195
 Extendio.cxx:196
 Extendio.cxx:197
 Extendio.cxx:198
 Extendio.cxx:199
 Extendio.cxx:200
 Extendio.cxx:201
 Extendio.cxx:202
 Extendio.cxx:203
 Extendio.cxx:204
 Extendio.cxx:205
 Extendio.cxx:206
 Extendio.cxx:207
 Extendio.cxx:208
 Extendio.cxx:209
 Extendio.cxx:210
 Extendio.cxx:211
 Extendio.cxx:212
 Extendio.cxx:213
 Extendio.cxx:214
 Extendio.cxx:215
 Extendio.cxx:216
 Extendio.cxx:217
 Extendio.cxx:218
 Extendio.cxx:219
 Extendio.cxx:220
 Extendio.cxx:221
 Extendio.cxx:222
 Extendio.cxx:223
 Extendio.cxx:224
 Extendio.cxx:225
 Extendio.cxx:226
 Extendio.cxx:227
 Extendio.cxx:228
 Extendio.cxx:229
 Extendio.cxx:230
 Extendio.cxx:231
 Extendio.cxx:232
 Extendio.cxx:233
 Extendio.cxx:234
 Extendio.cxx:235
 Extendio.cxx:236
 Extendio.cxx:237
 Extendio.cxx:238
 Extendio.cxx:239
 Extendio.cxx:240
 Extendio.cxx:241
 Extendio.cxx:242
 Extendio.cxx:243
 Extendio.cxx:244
 Extendio.cxx:245
 Extendio.cxx:246
 Extendio.cxx:247
 Extendio.cxx:248
 Extendio.cxx:249
 Extendio.cxx:250
 Extendio.cxx:251
 Extendio.cxx:252
 Extendio.cxx:253
 Extendio.cxx:254
 Extendio.cxx:255
 Extendio.cxx:256
 Extendio.cxx:257
 Extendio.cxx:258
 Extendio.cxx:259
 Extendio.cxx:260
 Extendio.cxx:261
 Extendio.cxx:262
 Extendio.cxx:263
 Extendio.cxx:264
 Extendio.cxx:265
 Extendio.cxx:266
 Extendio.cxx:267
 Extendio.cxx:268
 Extendio.cxx:269
 Extendio.cxx:270
 Extendio.cxx:271
 Extendio.cxx:272
 Extendio.cxx:273
 Extendio.cxx:274
 Extendio.cxx:275
 Extendio.cxx:276
 Extendio.cxx:277
 Extendio.cxx:278
 Extendio.cxx:279
 Extendio.cxx:280
 Extendio.cxx:281
 Extendio.cxx:282
 Extendio.cxx:283
 Extendio.cxx:284
 Extendio.cxx:285
 Extendio.cxx:286
 Extendio.cxx:287
 Extendio.cxx:288
 Extendio.cxx:289
 Extendio.cxx:290
 Extendio.cxx:291
 Extendio.cxx:292
 Extendio.cxx:293
 Extendio.cxx:294
 Extendio.cxx:295
 Extendio.cxx:296
 Extendio.cxx:297
 Extendio.cxx:298
 Extendio.cxx:299
 Extendio.cxx:300
 Extendio.cxx:301
 Extendio.cxx:302
 Extendio.cxx:303
 Extendio.cxx:304
 Extendio.cxx:305
 Extendio.cxx:306
 Extendio.cxx:307
 Extendio.cxx:308
 Extendio.cxx:309
 Extendio.cxx:310
 Extendio.cxx:311
 Extendio.cxx:312
 Extendio.cxx:313
 Extendio.cxx:314
 Extendio.cxx:315
 Extendio.cxx:316
 Extendio.cxx:317
 Extendio.cxx:318
 Extendio.cxx:319
 Extendio.cxx:320
 Extendio.cxx:321
 Extendio.cxx:322
 Extendio.cxx:323
 Extendio.cxx:324
 Extendio.cxx:325
 Extendio.cxx:326
 Extendio.cxx:327
 Extendio.cxx:328
 Extendio.cxx:329
 Extendio.cxx:330
 Extendio.cxx:331
 Extendio.cxx:332
 Extendio.cxx:333
 Extendio.cxx:334
 Extendio.cxx:335
 Extendio.cxx:336
 Extendio.cxx:337
 Extendio.cxx:338
 Extendio.cxx:339
 Extendio.cxx:340
 Extendio.cxx:341
 Extendio.cxx:342
 Extendio.cxx:343
 Extendio.cxx:344
 Extendio.cxx:345
 Extendio.cxx:346
 Extendio.cxx:347
 Extendio.cxx:348
 Extendio.cxx:349
 Extendio.cxx:350
 Extendio.cxx:351
 Extendio.cxx:352
 Extendio.cxx:353
 Extendio.cxx:354
 Extendio.cxx:355
 Extendio.cxx:356
 Extendio.cxx:357
 Extendio.cxx:358
 Extendio.cxx:359
 Extendio.cxx:360
 Extendio.cxx:361
 Extendio.cxx:362
 Extendio.cxx:363
 Extendio.cxx:364
 Extendio.cxx:365
 Extendio.cxx:366
 Extendio.cxx:367
 Extendio.cxx:368
 Extendio.cxx:369
 Extendio.cxx:370
 Extendio.cxx:371
 Extendio.cxx:372
 Extendio.cxx:373
 Extendio.cxx:374
 Extendio.cxx:375
 Extendio.cxx:376
 Extendio.cxx:377
 Extendio.cxx:378
 Extendio.cxx:379
 Extendio.cxx:380
 Extendio.cxx:381
 Extendio.cxx:382
 Extendio.cxx:383
 Extendio.cxx:384
 Extendio.cxx:385
 Extendio.cxx:386
 Extendio.cxx:387
 Extendio.cxx:388
 Extendio.cxx:389
 Extendio.cxx:390
 Extendio.cxx:391
 Extendio.cxx:392
 Extendio.cxx:393
 Extendio.cxx:394
 Extendio.cxx:395
 Extendio.cxx:396
 Extendio.cxx:397
 Extendio.cxx:398
 Extendio.cxx:399
 Extendio.cxx:400
 Extendio.cxx:401
 Extendio.cxx:402
 Extendio.cxx:403
 Extendio.cxx:404
 Extendio.cxx:405
 Extendio.cxx:406
 Extendio.cxx:407
 Extendio.cxx:408
 Extendio.cxx:409
 Extendio.cxx:410
 Extendio.cxx:411
 Extendio.cxx:412
 Extendio.cxx:413
 Extendio.cxx:414
 Extendio.cxx:415
 Extendio.cxx:416
 Extendio.cxx:417
 Extendio.cxx:418
 Extendio.cxx:419
 Extendio.cxx:420
 Extendio.cxx:421
 Extendio.cxx:422
 Extendio.cxx:423
 Extendio.cxx:424
 Extendio.cxx:425
 Extendio.cxx:426
 Extendio.cxx:427
 Extendio.cxx:428
 Extendio.cxx:429
 Extendio.cxx:430
 Extendio.cxx:431
 Extendio.cxx:432
 Extendio.cxx:433
 Extendio.cxx:434