ROOT logo
// $Id: Tringula.cxx 2513 2011-08-29 03:24:45Z 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/.

#include "Tringula.h"
#include <Glasses/ZHashList.h>
#include <Glasses/ZVector.h>
#include <Glasses/RectTerrain.h>
#include <Glasses/ZImage.h>
#include <Stones/TringTvor.h>
#include "TriMesh.h"
#include "ParaSurf.h"
#include "Statico.h"
#include "Dynamico.h"
#include "Crawler.h"
#include "Flyer.h"
#include "Airplane.h"
#include "Chopper.h"
#include "LandMark.h"
#include "ExtendioExplosion.h"
#include "LaserTraceExplosion.h"

#include "Tringula.c7"

#include <Glasses/WSTube.h>

#include <Glasses/ZQueen.h>

#include <Opcode/Opcode.h>

#include <TMath.h>

//__________________________________________________________________________
// Tringula
//
//

ClassImp(Tringula);

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

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

  // This is a temporary hack needed because the flyer dynamic is too simple.
  // It prevents flyers from flying into regions where gravity changes
  // direction abruptly.
  // There can be no reasonable default, so it is set to 0 to make
  // it rather obvious when it is not set.
  mMaxFlyerH   = 0;
  mMaxCameraH  = 0;

  bRnrBBoxes = false;

  mEdgeRule   = ER_Stop;

  mRndGen.SetSeed(0);

  mBoxPruner = new Opcode::BipartiteBoxPruner;
  mStatosLTS = mDynosLTS = mFlyersLTS = 0;
}

Tringula::~Tringula()
{
  delete mBoxPruner;
}

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

void Tringula::AdEnlightenment()
{
  PARENT_GLASS::AdEnlightenment();

  if (mStatos == 0) {
    assign_link<ZHashList>(mStatos, FID(), "Statos", GForm("Statos of Tringula %s", GetName()));
    mStatos->SetElementFID(Statico::FID());
  }
  if (mDynos == 0) {
    assign_link<ZHashList>(mDynos, FID(), "Dynos", GForm("Dynos of Tringula %s", GetName()));
    mDynos->SetElementFID(Dynamico::FID());
  }
  if (mFlyers == 0) {
    assign_link<ZHashList>(mFlyers, FID(), "Flyers", GForm("Flyers of Tringula %s", GetName()));
    mFlyers->SetElementFID(Dynamico::FID());
  }
  if (mLandMarks == 0) {
    assign_link<ZHashList>(mLandMarks, FID(), "LandMarks", GForm("LandMarks of Tringula %s", GetName()));
    mLandMarks->SetElementFID(LandMark::FID());
  }
  if (mTubes == 0) {
    assign_link<ZHashList>(mTubes, FID(), "Tubes", GForm("Tubes of Tringula %s", GetName()));
    mTubes->SetElementFID(WSTube::FID());
  }

  if (mExplodios == 0) {
    assign_link<ZHashList>(mExplodios, FID(), "Explodios", GForm("Exploding Extendios of Tringula %s", GetName()));
    mExplodios->SetElementFID(Extendio::FID());
  }
  if (mExplosions == 0) {
    assign_link<ZHashList>(mExplosions, FID(), "Explosions", GForm("Explosions of Tringula %s", GetName()));
    mExplosions->SetElementFID(Explosion::FID());
  }
}

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

Bool_t Tringula::RayCollide(const Opcode::Ray& ray, Float_t ray_length,
			    Bool_t cull_p, Bool_t closest_p,
			    Opcode::CollisionFaces& col_faces)
{
  // Intersect terrain mesh with given ray and stores result in col_faces.
  //  ray_length - if larger then 0, used as maximum hit distance.
  //  cull_p     - enable / disable triangle culling.
  //  closest_p  - return closest hit only / all hits.

  static const Exc_t _eh("Tringula::RayCollide ");

  if (mMesh == 0 || mMesh->GetOPCModel() == 0)
    throw _eh + "Opcode model not created.";

  using namespace Opcode;

  RayCollider RC;
  RC.SetCulling(cull_p);
  RC.SetClosestHit(closest_p);
  RC.SetDestination(&col_faces);
  if (ray_length > 0) RC.SetMaxDist(ray_length);

  const char* setval = RC.ValidateSettings();
  if (setval != 0)
    throw _eh + "setting validation failed: " + setval;

  return RC.Collide(ray, *mMesh->GetOPCModel());
}

Float_t Tringula::RayCollideClosestHit(const Opcode::Ray& ray, Bool_t cull_p)
{
  // Returns distance to the closest terrain hit from given ray.
  // Opcode::MAX_FLOAT is returned if terrain is is not hit.

  static const Exc_t _eh("Tringula::RayCollideClosestHit ");

  Opcode::CollisionFaces col_faces;

  if (RayCollide(ray, 0, cull_p, true, col_faces))
  {
    if (col_faces.GetNbFaces())
      return col_faces[0].mDistance;
    else
      return Opcode::MAX_FLOAT;
  }
  else
  {
    printf("%scollide status=<failed>.", _eh.Data());
    return Opcode::MAX_FLOAT;
  }
}

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

void Tringula::prepick_extendios(AList* extendios, const Opcode::Ray& ray, Float_t ray_length,
                                 lPickResult_t& candidates)
{
  // Select picking candiadates from among extendios.

  Opcode::Point dpos;
  Float_t       t;

  Stepper<> stepper(extendios);
  while (stepper.step())
  {
    Extendio* ext = (Extendio*) *stepper;

    dpos.Sub(ray.mOrig, ext->ref_last_aabb().Center());
    t = - (ray.mDir | dpos);

    if (t > 0 && t < ray_length && dpos.SquareMagnitude() - t*t <= ext->ref_last_aabb().GetSphereSquareRadius())
    {
      candidates.push_back(PickResult(ext, t));
    }
  }
}

Extendio* Tringula::PickExtendios(const Opcode::Ray& ray, Float_t ray_length,
				  Float_t* ext_distance)
{
  // Loop over extendios and calculate distance between ray and center
  // point.
  //  ray_length   - if larger than 0, limits the maximum extendio distance.
  //  ext_distance - if non 0, set to the distance of extendio.
  //
  // Original idea was to sub-divide ray into boxes and do split box prunning.
  //
  // Could increase size of boxes further away.
  //
  // In fact, only need to calculate until the first contact with terrain.
  //
  // Check both options.

  static const Exc_t _eh("Tringula::PickExtendios ");

  if (ray_length <= 0) ray_length = Opcode::MAX_FLOAT;

  lPickResult_t candidates;
  prepick_extendios(*mStatos,    ray, ray_length, candidates);
  prepick_extendios(*mDynos,     ray, ray_length, candidates);
  prepick_extendios(*mFlyers,    ray, ray_length, candidates);
  prepick_extendios(*mLandMarks, ray, ray_length, candidates);

  candidates.sort();

  Opcode::RayCollider RC;
  RC.SetFirstContact(true);

  for (lPickResult_i res = candidates.begin(); res != candidates.end(); ++res)
  {
    Extendio *ext = res->fExtendio;

    if (RC.Collide(ray, * ext->get_opc_model(), ext->RefLastTrans()))
    {
      if (RC.GetContactStatus())
      {
	if (ext_distance) *ext_distance = res->fTime;
        return ext;
      }
    }
    else
    {
      printf("%scollide status=<failed>, extendio='%s'.", _eh.Data(), ext->GetName());
    }
  }
  return 0;
}

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

void Tringula::ResetCollisionStuff()
{
  mMesh->BuildOpcStructs();

  Stepper<Dynamico> stepper(*mDynos);
  while (stepper.step())
  {
    stepper->mOPCRCCache = Opcode::OPC_INVALID_ID;
  }

  // mBoxPruner is not changed.
}

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

Float_t Tringula::PlaceAboveTerrain(ZTrans& trans, Float_t height, Float_t dh_fac)
{
  // Returns height to which the trans was placed.

  static const Exc_t _eh("Tringula::PlaceAboveTerrain ");

  using namespace Opcode;

  RayCollider    RC;
  RC.SetClosestHit(true);     // to keep the closes hit only
  CollisionFaces CF;
  RC.SetDestination(&CF);

  Point       pos;  trans.GetPos(pos);
  Opcode::Ray R;
  Float_t     ray_offset = mParaSurf->pos2hray(pos, R);

  Float_t     abs_height = height + dh_fac*mParaSurf->GetDeltaH();

  Bool_t status = RC.Collide(R, *mMesh->GetOPCModel());
  if (status && CF.GetNbFaces() == 1)
  {
    const CollisionFace& cf = CF.GetFaces()[0];
    pos.TMac(R.mDir, cf.mDistance - ray_offset - abs_height);
    trans.SetPos(pos);
  }
  else
  {
    throw _eh + RC.CollideInfo(status, R);
  }

  return abs_height;
}

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

Statico* Tringula::NewStatico(const Text_t* sname)
{
  if (sname == 0)
    sname = GForm("Statico %d", mStatos->GetSize() + 1);

  Statico* s = new Statico(sname);

  mParaSurf->origin_trans(s->ref_trans());

  place_on_terrain(s, *mDefStaMesh, false);

  mQueen->CheckIn(s);
  s->SetMesh(*mDefStaMesh);
  mStatos->Add(s);
  s->SetTringula(this);

  s->update_aabb();

  return s;
}

Statico* Tringula::RandomStatico(ZVector *mesh_list,
                                 Bool_t   check_inside,
                                 Int_t    max_tries)
{
  // Randomly select a mesh for statico from mesh_list and place it on
  // a random location on the terrain. Makes sure the new statico
  // does not overlap with existing ones.
  //
  // check_inside: make sure all corners of the bbox are within
  //   parasurf which is relevant for planar surfaces where statos might
  //   stick out.
  //   check_inside is also passed to place_on_terrain() where it
  //   suppresses the warnings about missed intersection.
  // max_tries: how many times to try statico's placement on terrain.
  //   If this limit is reached an exception is thrown.
  //   As CINT doesn't handle this very well, 0 is returned at the moment.
  //
  //   This is relevant when many staticos are already on the terrain
  //   and for steep terrain.
  //
  // How much of statico's bbox must stick out of terrain on each
  // sampling-point is hardcoded to 0.5*bbox_z_size.

  static const Exc_t _eh("Tringula::RandomStatico ");

  Statico* s = new Statico(GForm("Statico %d", mStatos->GetSize() + 1));

  TriMesh* mesh;
  if (mesh_list) {
    mesh = dynamic_cast<TriMesh*>
      (mesh_list->GetElementById(mRndGen.Integer(mesh_list->GetSize())));
  } else {
    mesh = *mDefStaMesh;
  }

  // For bounding-box selection of collision candidates.
  setup_stato_pruner();
  // For mesh-mesh collision detection.
  Opcode::AABB             bbox;
  Opcode::AABBTreeCollider collider;
  Opcode::BVTCache         cache;
  cache.Model0 = mesh->GetOPCModel();

  Int_t top_cnt = 0;
place:
  if (++top_cnt > max_tries)
  {
    delete s;
    // throw (_eh + "max_tries reached.");
    // This is temporary solution to bypass the problem with exceptions 
    // not being deliver into interpreted code.
    // Using semi-functional solution now for further investigation.
    return 0;
  }

  mParaSurf->random_trans(mRndGen, s->ref_trans());
  s->ref_trans().RotateLF(1, 2, mRndGen.Uniform(0, TMath::TwoPi()));

  Bool_t place_status = place_on_terrain(s, mesh, check_inside,
                                         0.5f * mesh->ref_mesh_bbox().GetZSize());

  if (check_inside && ! place_status)
    goto place;

  mesh->ref_mesh_bbox().Rotate(s->ref_trans(), bbox);

  Opcode::Container hits;
  mBoxPruner->SinglePruning(hits, 0, bbox);
  for (UInt_t i = 0; i < hits.GetNbEntries(); ++i)
  {
    Statico *hit = (Statico*) mBoxPruner->GetUserData(0, hits.GetEntry(i));
    cache.Model1 = hit->get_opc_model();
    collider.Collide(cache, s->ref_trans(), hit->ref_trans());
    if (collider.GetContactStatus())
      goto place;
  }

  mQueen->CheckIn(s);
  s->SetMesh(mesh);
  mStatos->Add(s);
  s->SetTringula(this);

  s->update_aabb();

  return s;
}

void Tringula::RegisterCrawler(Crawler* d)
{
  mParaSurf->origin_trans(d->ref_trans());
  place_on_terrain(d, d->GetLevH());

  mQueen->CheckIn(d);
  d->SetMesh(*mDefDynMesh);
  mDynos->Add(d);
  d->SetTringula(this);

  d->update_aabb();
  d->update_last_data();
}

Crawler* Tringula::NewDynamico(const Text_t* dname)
{
  if (dname == 0)
    dname = GForm("Dynamico %d", mDynos->GetSize() + 1);

  Crawler* d = new Crawler(dname);

  RegisterCrawler(d);

  return d;
}

Crawler* Tringula::RandomDynamico(ZVector* mesh_list,
                                   Float_t v_min, Float_t v_max, Float_t w_max)
{
  Crawler* d = new Crawler(GForm("Dynamico %d", mDynos->GetSize() + 1));
  HTransF& t = d->ref_trans();

  TriMesh* mesh;
  if (mesh_list) {
    mesh = dynamic_cast<TriMesh*>
      (mesh_list->GetElementById(mRndGen.Integer(mesh_list->GetSize())));
  } else {
    mesh = *mDefDynMesh;
  }

  mParaSurf->random_trans(mRndGen, t);

  Float_t phi = mRndGen.Uniform(0, TMath::TwoPi());
  t.RotateLF(1, 2, phi);

  d->SetV(mRndGen.Uniform( v_min, v_max));
  d->SetW(mRndGen.Uniform(-w_max, w_max));

  place_on_terrain(d, d->GetLevH());

  mQueen->CheckIn(d);
  d->SetMesh(mesh);
  mDynos->Add(d);
  d->SetTringula(this);

  d->update_aabb();
  d->update_last_data();

  return d;
}

Dynamico* Tringula::RandomAirplane(Float_t v_min, Float_t v_max,
                                   Float_t w_max,
                                   Float_t h_min_fac, Float_t h_max_fac)
{
  static const Exc_t _eh("Tringula::RandomAirplane ");

  Flyer* d = new Airplane(GForm("Airplane %d", mFlyers->GetSize() + 1));
  HTransF& t = d->ref_trans();

  mParaSurf->random_trans(mRndGen, t);

  Float_t phi = mRndGen.Uniform(0, TMath::TwoPi());
  t.RotateLF(1, 2, phi);

  Float_t point_h, terrain_h;
  if ( ! terrain_height(t.ref_pos(), point_h, terrain_h))
    throw _eh + "problem determining terrain height.";

  Float_t h = mRndGen.Uniform(h_min_fac * mMaxFlyerH, h_max_fac * mMaxFlyerH);
  h = TMath::Max(h, terrain_h + mDefFlyMesh->GetTTvor()->BoundingBoxDiagonal());
  t.MoveLF(3, h);
  d->SetHeight(h);
  // printf("Set height=%+6.2f for flyer '%12s', th=%+6.2f, ph=%+6.2f, maxfh=%+6.2f; %+6.2f-%+6.2f\n",
  //        h, d->GetName(), terrain_h, point_h, mMaxFlyerH,
  //        h_min_fac * mMaxFlyerH, h_max_fac * mMaxFlyerH);

  d->SetV(mRndGen.Uniform( v_min, v_max));
  d->SetW(mRndGen.Uniform(-w_max, w_max));

  mQueen->CheckIn(d);
  d->SetMesh(*mDefFlyMesh);
  mFlyers->Add(d);
  d->SetTringula(this);

  d->update_aabb();
  d->update_last_data();

  return d;
}

Dynamico* Tringula::RandomChopper(Float_t v_min, Float_t v_max,
                                  Float_t w_max,
                                  Float_t h_min_fac, Float_t h_max_fac)
{
  static const Exc_t _eh("Tringula::RandomChopper ");

  Flyer* d = new Chopper(GForm("Chopper %d", mFlyers->GetSize() + 1));
  HTransF& t = d->ref_trans();

  mParaSurf->random_trans(mRndGen, t);

  Float_t phi = mRndGen.Uniform(0, TMath::TwoPi());
  t.RotateLF(1, 2, phi);

  Float_t point_h, terrain_h;
  if ( ! terrain_height(t.ref_pos(), point_h, terrain_h))
    throw _eh + "problem determining terrain height.";

  Float_t h = mRndGen.Uniform(h_min_fac * mMaxFlyerH, h_max_fac * mMaxFlyerH);
  h = TMath::Max(h, terrain_h + mDefChopMesh->GetTTvor()->BoundingBoxDiagonal());
  t.MoveLF(3, h);
  d->SetHeight(h);
  // printf("Set height=%+6.2f for flyer '%12s', th=%+6.2f, ph=%+6.2f, maxfh=%+6.2f; %+6.2f-%+6.2f\n",
  //        h, d->GetName(), terrain_h, point_h, mMaxFlyerH,
  //        h_min_fac * mMaxFlyerH, h_max_fac * mMaxFlyerH);

  d->SetV(mRndGen.Uniform( v_min, v_max));
  d->SetW(mRndGen.Uniform(-w_max, w_max));

  mQueen->CheckIn(d);
  d->SetMesh(*mDefChopMesh);
  mFlyers->Add(d);
  d->SetTringula(this);

  d->update_aabb();
  d->update_last_data();

  return d;
}

LandMark* Tringula::AddLandMark(TriMesh* mesh, const Float_t* pos)
{
  LandMark* d = new LandMark(GForm("LandMark %d", mLandMarks->GetSize() + 1));
  HTransF& t = d->ref_trans();

  Float_t fgh[3];
  mParaSurf->pos2fgh(pos, fgh);
  mParaSurf->fgh2trans(fgh, t);

  mQueen->CheckIn(d);
  d->SetMesh(mesh);
  mLandMarks->Add(d);
  d->SetTringula(this);
  d->SetFGH(fgh[0], fgh[1], fgh[2]);

  d->update_aabb();
  d->update_last_data();

  return d;
}

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

Bool_t Tringula::CheckBoundaries(Dynamico* dyno, Float_t& safety)
{
  // Checks if dyno crossed some important boundary and handles that.
  // This means that Dyno's velocity and transformation matrix might be
  // modified.
  //
  // Distance to the closest boundary is returned in safety argument.
  //
  // Returns true if transformation matrix of the dynos gets changed.
  //
  // In future, when an inter-tringula boundary is crossed this will
  // also pass the dyno to neighbouring tringula.

  Bool_t trans_changed = false;

  Int_t np = mParaSurf->n_edge_planes();

  Float_t min_d = 1e5;
  for (Int_t p = 0; p < np; ++p)
  {
    Opcode::Point& pos     = * (Opcode::Point*) dyno->ref_trans().ArrT();
    Opcode::Point& old_pos = * (Opcode::Point*) dyno->ref_last_trans().ArrT();
    Float_t d = mParaSurf->edge_planes()[p].Distance(pos);
    if (d > 0)
    {
      trans_changed = true;
      handle_edge_crossing(*dyno, old_pos, pos, p, d);
      d = mParaSurf->edge_planes()[p].Distance(pos);
    }
    d = -d;
    if (d < min_d)
      min_d = d;
  }

  safety = min_d;

  return trans_changed;
}

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

void Tringula::DoFullBoxPrunning(vector<Opcode::Segment>& its_lines,
				 Bool_t accumulate, Bool_t verbose)
{
  // Du full box-prunning step:
  // - fill prunning list with statos, dynos and flyers,
  // - perform box prunning,
  // - do detail checks on collision candidates.
  //
  // Output: mItsLines contain intersection segments from all collisions.
  //
  // Mainly here to compare speed against split-box-prunning.

  static const Exc_t _eh("Tringula::DoFullBoxPrunning ");

  using namespace Opcode;

  GTime  time(GTime::I_Now);

  UInt_t nboxes = mStatos->GetSize() + mDynos->GetSize() + mFlyers->GetSize();
  Extendio    *extarr[nboxes];
  const AABB  *bboxes[nboxes];

  {
    int n = 0;
    fill_pruning_list(*mStatos, n, bboxes, (void**) extarr);
    fill_pruning_list(*mDynos,  n, bboxes, (void**) extarr);
    fill_pruning_list(*mFlyers, n, bboxes, (void**) extarr);
  }

  // printf("Box-o-pruno, fill took %fs\n", time.TimeUntilNow().ToDouble());

  Pairs  pairs;
  Axes   axes(AXES_XZY); // somewhat random
  Bool_t res = CompleteBoxPruning(nboxes, bboxes, pairs, axes);

  printf("%son %3u: res=%d, npairs=%3u, time=%f\n", _eh.Data(),
         nboxes, res, pairs.GetNbPairs(), time.TimeUntilNow().ToDouble());

  if (accumulate)
  {
    its_lines.reserve(its_lines.size() + 2*pairs.GetNbPairs());
  }
  else
  {
    its_lines.clear();
    its_lines.reserve(2*pairs.GetNbPairs());
  }

  const Text_t* debug_prefix = verbose ? "        " : 0;

  AABBTreeCollider collider;

  for (UInt_t i = 0; i < pairs.GetNbPairs(); ++i)
  {
    const Pair& p  = * pairs.GetPair(i);
    if (verbose)
      printf("  %3u:", i);

    Extendio::intersect_extendios(extarr[p.id0], extarr[p.id1], collider,
                                  its_lines, debug_prefix);
  }
  printf(" Vector size = %zu, segments per pair = %f\n",
         its_lines.size(), (float)its_lines.size()/pairs.GetNbPairs());
}

void Tringula::DoSplitBoxPrunning()
{
  // Extendio-extendio collision detection and handling routine.

  static const Exc_t _eh("Tringula::DoSplitBoxPrunning ");

  // GTime  time(GTime::I_Now);

  setup_box_pruner();

  Opcode::Pairs ds_pairs;
  mBoxPruner->BipartitePruning(ds_pairs, 0, 1);

  Opcode::Pairs dd_pairs;
  mBoxPruner->CompletePruning(dd_pairs, 1);

  /*
    printf("Box-o-pruno on %d/%d: pairs=%d (%d/%d), time=%f\n",
    mBoxPruner->ListSize(0), mBoxPruner->ListSize(1),
    ds_pairs.GetNbPairs() + dd_pairs.GetNbPairs(),
    ds_pairs.GetNbPairs(),  dd_pairs.GetNbPairs(),
    time.TimeUntilNow().ToDouble());
  */

  // For mesh-mesh collisions.
  Opcode::AABBTreeCollider    collider;
  Extendio::CollisionSegments segments;

  // For COM inside tests.
  Opcode::RayCollider      RC;
  Opcode::CollisionFaces   CF;
  RC.SetDestination(&CF);
  RC.SetCulling(false);

  for (UInt_t i = 0; i < ds_pairs.GetNbPairs(); ++i)
  {
    using namespace Opcode;

    const Pair *p  = ds_pairs.GetPair(i);
    Statico   *stato = (Statico*)  mBoxPruner->GetUserData(0, p->id0);
    Dynamico  *dyno  = (Dynamico*) mBoxPruner->GetUserData(1, p->id1);
    // printf("    %2d %s, %s\n", i+1, stato->Identify().Data(), dyno->Identify().Data());

    Int_t ns = Extendio::intersect_extendios(stato, dyno, collider, segments);
    if (ns > 0)
    {
      // Calculate centers of mass for dyno and stato in global coordinates.

      ++stato->mNDynoColls;

      HTransF& t_dyno = dyno->ref_trans();
      Point com_dyno;
      t_dyno.MultiplyVec3(dyno->GetMesh()->RefCOM(), 1.0f, com_dyno);

      HTransF& t_stato = stato->ref_trans();
      Point com_stato;
      t_stato.MultiplyVec3(stato->GetMesh()->RefCOM(), 1.0f, com_stato);

      // Construct ray outwards from com_dyno in dir of com_dyno - com_stato.
      Opcode::Ray R;
      R.mOrig = com_dyno;
      R.mDir  = com_dyno - com_stato;

      Bool_t ok_p = Dynamico::handle_collision(dyno, stato, RC, R, com_dyno,
                                               segments);

      if (!ok_p)
        printf("%sDyno-Stato dyno->handle_collision failed.\n", _eh.Data());

      segments.Clear();
    }
  }

  for (UInt_t i = 0; i < dd_pairs.GetNbPairs(); ++i)
  {
    using namespace Opcode;

    const Pair *p  = dd_pairs.GetPair(i);
    Dynamico  *dyno0 = (Dynamico*) mBoxPruner->GetUserData(1, p->id0);
    Dynamico  *dyno1 = (Dynamico*) mBoxPruner->GetUserData(1, p->id1);
    // printf("    %2d %s, %s\n", i+1, dyno0->Identify().Data(), dyno1->Identify().Data());

    Int_t ns = Extendio::intersect_extendios(dyno0, dyno1, collider, segments);
    if (ns > 0)
    {
      Point up_dir;
      mParaSurf->pos2hdir(segments.RefCenter(), up_dir);

      Dynamico::handle_collision(dyno0, dyno1, up_dir, segments);

      segments.Clear();
    }

  }

  //printf("Box-o-pruno on %3u: res=%d, npairs=%3u, time=%f\n",
  //       nboxes, res, pairs.GetNbPairs(), time.TimeUntilNow().ToDouble());
}


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

void Tringula::TimeTick(Double_t t, Double_t dt)
{
  static const Exc_t _eh("Tringula::TimeTick ");

  GLensWriteHolder wlck(this);

  // Make time step for dynos, flyers
  {
    Stepper<> dyno_stepper(*mDynos);
    while (dyno_stepper.step())
    {
      Dynamico& D = * (Dynamico*) *dyno_stepper;
      D.TimeTick(t, dt);
    }

    Stepper<> flyo_stepper(*mFlyers);
    while (flyo_stepper.step())
    {
      Dynamico& D = * (Dynamico*) *flyo_stepper;
      D.TimeTick(t, dt);
    }

    Stepper<> tube_stepper(*mTubes);
    while (tube_stepper.step())
    {
      WSTube& D = * (WSTube*) *tube_stepper;
      D.TimeTick(t, dt);
    }
  }

  // Weapons -- rays, grenades, rockets come here ... maybe.
  {
    Stepper<> explosion_stepper(*mExplosions);
    while (explosion_stepper.step())
    {
      Explosion& E = * (Explosion*) *explosion_stepper;
      E.TimeTick(t, dt);
    }

    Stepper<> explodio_stepper(*mExplodios);
    while (explodio_stepper.step())
    {
      Extendio& E = * (Extendio*) *explodio_stepper;
      E.TimeTick(t, dt);
    }
  }

  // Process explosidios.
  {
    GMutexHolder _elck(mExplosionMutex);

    for (lpZGlass_i i = mFreshExplodingExtendios.begin(); i != mFreshExplodingExtendios.end(); ++i)
    {
      Extendio *ext = (Extendio*) *i;
      ExtendioExplosion *exp = new ExtendioExplosion;
      mQueen->CheckIn(exp);
      exp->SetExplodeDuration(1.0f + TMath::Log10(ext->GetMesh()->GetM() + 1.0f));
      exp->SetTringula(this);
      exp->SetExtendio(ext);
      mExplosions->Add(exp);
      mExplodios->Add(ext);
      // Remove extendio from whatever list it is in ... this should be done better.
      // Eg, have a ZVector of extendio lists and a field in Extendio that allows
      // Tringula to mark where it currently is.
      if (mDynos->RemoveAll(ext) == 0)
      {
	if (mFlyers->RemoveAll(ext) == 0)
	  if (mStatos->RemoveAll(ext) == 0)
	    mLandMarks->RemoveAll(ext);
      }
      EmitExtendioExplodingRay(ext, exp);
    }
    mFreshExplodingExtendios.clear();

    for (lpZGlass_i i = mFinishedExtendioExplosions.begin(); i != mFinishedExtendioExplosions.end(); ++i)
    {
      ExtendioExplosion *exp = (ExtendioExplosion*) *i;
      Extendio *ext = exp->GetExtendio();
      EmitExtendioDyingRay(ext);

      mExplosions->RemoveAll(exp);
      mExplodios->RemoveAll(ext);

      // Request deletion in queen not strictly needed - should auto-destruct.
      // Here we expect to be on the Sun of Tringula and Extendios.
      delete_lens_if_alive(exp);
      delete_lens_if_alive(ext);
    }
    mFinishedExtendioExplosions.clear();

    for (lpZGlass_i i = mFreshExplosions.begin(); i != mFreshExplosions.end(); ++i)
    {
      mExplosions->Add(*i);
    }
    mFreshExplosions.clear();

    for (lpZGlass_i i =mFinishedExplosions.begin(); i != mFinishedExplosions.end(); ++i)
    {
      mExplosions->RemoveAll(*i);
      // Request deletion in queen not strictly needed - should auto-destruct.
      // Here we expect to be on the Sun of Tringula and Extendios.
      delete_lens_if_alive(*i);
    }
    mFinishedExplosions.clear();
  }

  // Box-pruning, minimalistic collision handling.
  DoSplitBoxPrunning();


  // Update velocities, render-pos.
  {
    Stepper<> dyno_stepper(*mDynos);
    while (dyno_stepper.step())
    {
      Dynamico& D = * (Dynamico*) *dyno_stepper;

      D.update_aabb();
      D.update_last_data();
    }

    Stepper<> flyo_stepper(*mFlyers);
    while (flyo_stepper.step())
    {
      Dynamico& D = * (Dynamico*) *flyo_stepper;

      D.update_aabb();
      D.update_last_data();
    }

    Stepper<> explodio_stepper(*mExplodios);
    while (explodio_stepper.step())
    {
      Extendio& E = * (Extendio*) *explodio_stepper;
      E.update_aabb();
      E.update_last_data();
    }
  }

  // Loop over TimeMakerClient children
  {
    Stepper<TimeMakerClient> tcl(this);
    while (tcl.step())
      tcl->TimeTick(t, dt);
  }
}


//==============================================================================
// Explosions, effects and who knows what else
//==============================================================================

void Tringula::ExtendioExploding(Extendio* ext)
{
  GMutexHolder _lck(mExplosionMutex);
  mFreshExplodingExtendios.push_back(ext);
}

void Tringula::ExtendioExplosionFinished(Explosion* exp)
{
  GMutexHolder _lck(mExplosionMutex);
  mFinishedExtendioExplosions.push_back(exp);
}

void Tringula::ExplosionStarted(Explosion* exp)
{
  GMutexHolder _lck(mExplosionMutex);
  mFreshExplosions.push_back(exp);
}

void Tringula::ExplosionFinished(Explosion* exp)
{
  GMutexHolder _lck(mExplosionMutex);
  mFinishedExplosions.push_back(exp);
}

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

void Tringula::LaserShot(Extendio* ext, const Opcode::Ray& ray, Float_t power)
{
  // Preliminary, should be done in a more general way with other weapons.
  // Also, need spot surface and ray divergence. Or sth.

  static const Exc_t _eh("Tringula::LaserShot ");

  Bool_t  terrain_hit = false;
  Float_t ray_length = 0;
  Opcode::CollisionFaces col_faces;
  if (RayCollide(ray, 0, true, true, col_faces))
  {
    if (col_faces.GetNbFaces())
    {
      terrain_hit = true;
      ray_length = col_faces[0].mDistance;
    }
  }
  else
  {
    printf("%scollide status=<failed>.", _eh.Data());
  }

  Extendio* dmg_ext = PickExtendios(ray, ray_length, &ray_length);
  if (dmg_ext) 
  {
    dmg_ext->TakeDamage(power);
  }

  if (ray_length == 0)
  {
    ray_length = 10.0f * power;
  }

  Opcode::Point end;
  end.Mac(ray.mOrig, ray.mDir, ray_length);

  // Lock, or sth.
  LaserTraceExplosion* e = new LaserTraceExplosion("LaserShot");
  e->SetTringula(this);
  e->RefA().Set(ray.mOrig);
  e->RefB().Set(end);
  if (terrain_hit || dmg_ext)
  {
    e->SetEndRadius(0.03125f*sqrtf(power));
  }
  mQueen->CheckIn(e);
  ExplosionStarted(e);

  EmitExtendioSoundRay(ext, "PewPew");
}

//==============================================================================
// Protected methods
//==============================================================================

void Tringula::fill_pruning_list(AList* extendios, Int_t& n,
                                 const Opcode::AABB** boxes, void** user_data)
{
  Stepper<> stepper(extendios);
  while (stepper.step())
  {
    boxes[n]     = &((Extendio*)*stepper)->RefAABB();
    user_data[n] = *stepper;
    ++n;
  }
}

void Tringula::fill_pruning_list(AList* extendios, Int_t& n, Int_t l)
{
  fill_pruning_list(extendios, n, mBoxPruner->BoxList(l), mBoxPruner->UserData(l));
}

void Tringula::setup_box_pruner()
{
  // Make sure internal representation of static and dynamic objects
  // for box-pruning is ok.

  setup_stato_pruner();
  setup_dyno_pruner();
}

void Tringula::setup_stato_pruner()
{
  if (mStatosLTS < mStatos->GetListTimeStamp())
  {
    mBoxPruner->InitList(0, mStatos->Size());
    int n = 0;
    fill_pruning_list(*mStatos, n, 0);
    mStatosLTS = mStatos->GetListTimeStamp();
    mBoxPruner->Sort(0);
  }
}

void Tringula::setup_dyno_pruner()
{
  if (mDynosLTS  < mDynos ->GetListTimeStamp() ||
      mFlyersLTS < mFlyers->GetListTimeStamp())
  {
    mBoxPruner->InitList(1, mDynos->Size() + mFlyers->Size());
    int n = 0;
    fill_pruning_list(*mDynos,  n, 1);
    fill_pruning_list(*mFlyers, n, 1);
    mDynosLTS  = mDynos ->GetListTimeStamp();
    mFlyersLTS = mFlyers->GetListTimeStamp();
  }

  mBoxPruner->Sort(1);
}

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

void Tringula::handle_edge_crossing
( Dynamico& D, Opcode::Point& old_pos, Opcode::Point& pos,
  Int_t plane, Float_t dist )
{
  using namespace Opcode;

  Plane& P = mParaSurf->edge_planes()[plane];

  switch (mEdgeRule)
  {
    case ER_Stop:
    {
      pos -= dist*P.n;
      D.mVVec.Zero();
      D.mWVec.Zero();
      D.Stamp(D.FID());
      break;
    }

    case ER_Hold:
    {
      Point step = pos; step -= old_pos;
      Float_t depth = fabsf(P.Distance(old_pos));
      pos = old_pos + depth*step/(depth+dist);
      break;
    }

    case ER_Wrap:
    {
      if (mParaSurf->support_wrap())
      {
        mParaSurf->wrap(pos, plane, dist);
        break;
      }
      // NO BREAK if wrap not supported, fallback to bounce.
    }

    case ER_Bounce:
    {
      pos -= 2*dist*P.n;
      // Rotate accordingly
      HTransF& t = D.ref_trans();
      Point& fwd = * (Point*) t.PtrBaseVec(1);
      fwd += -2 * (fwd | P.n) * P.n;
      t.OrtoNorm3Column(3, 1);
      t.SetBaseVecViaCross(2);
      break;
    }

  } // end switch
}

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

Bool_t Tringula::terrain_height(const Opcode::Point& pos, Float_t& point_h, Float_t& terrain_h)
{
  // Calculates height of given point and of the terrain at given pos.
  // Return true if all went ok.

  static const Exc_t _eh("Tringula::terrain_height ");

  Opcode::RayCollider    RC;
  RC.SetClosestHit(true);     // to keep the closes hit only
  Opcode::CollisionFaces CF;
  RC.SetDestination(&CF);

  Opcode::Point fgh;
  Opcode::Point hzero_pos;

  mParaSurf->pos2fgh(pos, fgh);
  point_h = fgh.z;
  fgh.z   = 0;
  mParaSurf->fgh2pos(fgh, hzero_pos);

  Opcode::Ray R;
  Float_t ray_offset = mParaSurf->pos2hray(hzero_pos, R);

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

}

Bool_t Tringula::place_on_terrain(Statico* S, TriMesh* M, Bool_t check_inside,
                                  Float_t min_h_above)
{
  // Place statico on terrain so that the bounding box of the mesh
  // touches or penetrates the terrain. The distance is sampled on a
  // 3x3 grid.
  //
  // It is assumed that the statico is oriented along the local up
  // direction with zero height. If the trans matrix were fixed here,
  // the rotation would be somewhat poorly defined.
  //
  // check_inside - if true, the first miss of the terrain in the ray
  // collision test results in a termination of the loop over sampling
  // points. false is returned and no error message is printed.
  //
  // min_h_above - how much of statico's bbox must stick out of
  // terrain on each sampling-point. If this is not the case, false is
  // returned. If min_h_above <= 0, the check is not performed.
  //
  // Otherwise true is returned.

  static const Exc_t _eh("Tringula::place_on_terrain ");

  if (M == 0)
  {
    M = S->GetMesh();
    if (M == 0)
      throw(_eh + "TriMesh not passed as argument nor available from Statico.\n");
  }

  HTransF&      trans = S->ref_trans();
  Opcode::AABB& aabb  = M->ref_mesh_bbox();

  Float_t ray_offset = mParaSurf->GetMaxH() + mParaSurf->GetEpsilon() +
    0.1f*(mParaSurf->GetMaxH() - mParaSurf->GetMinH()); // !! For local curvature, 1/10 of delta_h

  Float_t max_dist = 0, min_dist = 1e12f;

  Opcode::Point fdir  (trans.ArrX());
  Opcode::Point gdir  (trans.ArrY());
  Opcode::Point center(trans.ArrT());
  center.TMac(trans.ArrZ(), ray_offset);

  Opcode::Ray R;
  // R.mOrig set in loop
  R.mDir.Set(trans.ArrZ()); R.mDir.Neg();

  Opcode::RayCollider RC;
  RC.SetClosestHit(true);     // to keep the closes hit only

  Opcode::CollisionFaces CF;
  RC.SetDestination(&CF);

  static const Float_t sample[] = { -1, 0, 1 };
  static const Int_t   ns = 3;

  for (Int_t sf = 0; sf < ns; ++sf)
  {
    for (Int_t sg = 0; sg < ns; ++sg)
    {
      R.mOrig.Mac2(center,
                   fdir, sample[sf]*aabb.GetExtents(Opcode::_X),
                   gdir, sample[sg]*aabb.GetExtents(Opcode::_Y));

      Bool_t coll_status = RC.Collide(R, *mMesh->GetOPCModel());

      if (coll_status && CF.GetNbFaces() == 1)
      {
        max_dist = TMath::Max(max_dist, CF.GetFaces()[0].mDistance);
        min_dist = TMath::Min(min_dist, CF.GetFaces()[0].mDistance);
      }
      else
      {
        if (check_inside && coll_status)
          return false;
        else
          printf("%s(Statico*) sample_id %2d,%2d; status=%s, nfaces=%d\n"
                 "  nbvt=%d, nprt=%d, ni=%d\n"
                 "  ray_orig = %6.2f, %6.2f, %6.2f; ray_dir = %6.2f, %6.2f, %6.2f\n",
                 _eh.Data(), sf, sg, coll_status ? "ok" : "failed", CF.GetNbFaces(),
                 RC.GetNbRayBVTests(), RC.GetNbRayPrimTests(), RC.GetNbIntersections(),
                 R.mOrig.x, R.mOrig.y, R.mOrig.z, R.mDir.x, R.mDir.y, R.mDir.z);
      }
    }
  }

  if (aabb.GetZSize() - (max_dist - min_dist) < min_h_above)
    return false;

  // printf("ray_offset = %f, max_dist = %f; to_move = %f\n",
  //        ray_offset, max_dist, ray_offset - max_dist);

  trans.MoveLF(3, ray_offset - max_dist);

  return true;
}

Bool_t Tringula::place_on_terrain(Dynamico* D, Float_t h_above)
{
  static const Exc_t _eh("Tringula::place_on_terrain ");

  Opcode::RayCollider    RC;
  RC.SetClosestHit(true);     // to keep the closes hit only
  Opcode::CollisionFaces CF;
  RC.SetDestination(&CF);

  Opcode::Point& pos = D->ref_pos();
  Opcode::Ray R;
  Float_t ray_offset = mParaSurf->pos2hray(pos, R);

  Int_t cs = RC.Collide(R, *mMesh->GetOPCModel());
  if (cs && CF.GetNbFaces() == 1)
  {
      const Opcode::CollisionFace& cf = CF.GetFaces()[0];
      pos.TMac(R.mDir, cf.mDistance - ray_offset - h_above);

      Float_t* n = mMesh->GetTTvor()->TriangleNormal(cf.mFaceID);

      HTransF& trans = D->ref_trans();
      trans.SetBaseVec(3, n);
      trans.OrtoNorm3Column(1, 3);
      trans.SetBaseVecViaCross(2);
      return true;
  }
  else
  {
    printf("%s(Dynamico*) status=%s, nfaces=%d\n"
           "  nbvt=%d, nprt=%d, ni=%d\n"
           "  ray_orig = %6.2f, %6.2f, %6.2f; ray_dir = %6.2f, %6.2f, %6.2f\n",
           _eh.Data(), cs ? "ok" : "failed", CF.GetNbFaces(),
           RC.GetNbRayBVTests(), RC.GetNbRayPrimTests(), RC.GetNbIntersections(),
           R.mOrig.x, R.mOrig.y, R.mOrig.z, R.mDir.x, R.mDir.y, R.mDir.z);
    return false;
  }
}


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

void Tringula::delete_lens_if_alive(ZGlass* lens)
{
  // If lens is not dying, send a MIR requesting its deletion.

  if (!lens->CheckBit(kDyingBit))
  {
    auto_ptr<ZMIR> mir(mQueen->S_RemoveLens(lens));
    mSaturn->ShootMIR(mir);
  }
}

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

void Tringula::EmitExtendioExplodingRay(Extendio* ext, Explosion* exp)
{
  if (mQueen && mSaturn->AcceptsRays())
  {
    auto_ptr<Ray> ray
      (Ray::PtrCtor(this, PRQN_extendio_exploding, mTimeStamp, FID()));

    TBuffer &b = ray->CustomBuffer();
    GledNS::WriteLensID(b, ext);
    GledNS::WriteLensID(b, exp);

    mQueen->EmitRay(ray);
  }
}

void Tringula::EmitExtendioDyingRay(Extendio* ext)
{
  if (mQueen && mSaturn->AcceptsRays())
  {
    auto_ptr<Ray> ray
      (Ray::PtrCtor(this, PRQN_extendio_dying, mTimeStamp, FID()));

    TBuffer &b = ray->CustomBuffer();
    GledNS::WriteLensID(b, ext);

    mQueen->EmitRay(ray);
  }
}

void Tringula::EmitExtendioSoundRay(Extendio* ext, const TString& effect)
{
  if (mQueen && mSaturn->AcceptsRays())
  {
    auto_ptr<Ray> ray
      (Ray::PtrCtor(this, PRQN_extendio_sound, mTimeStamp, FID()));

    TBuffer &b = ray->CustomBuffer();
    GledNS::WriteLensID(b, ext);
    b << effect;

    mQueen->EmitRay(ray);
  }
}
 Tringula.cxx:1
 Tringula.cxx:2
 Tringula.cxx:3
 Tringula.cxx:4
 Tringula.cxx:5
 Tringula.cxx:6
 Tringula.cxx:7
 Tringula.cxx:8
 Tringula.cxx:9
 Tringula.cxx:10
 Tringula.cxx:11
 Tringula.cxx:12
 Tringula.cxx:13
 Tringula.cxx:14
 Tringula.cxx:15
 Tringula.cxx:16
 Tringula.cxx:17
 Tringula.cxx:18
 Tringula.cxx:19
 Tringula.cxx:20
 Tringula.cxx:21
 Tringula.cxx:22
 Tringula.cxx:23
 Tringula.cxx:24
 Tringula.cxx:25
 Tringula.cxx:26
 Tringula.cxx:27
 Tringula.cxx:28
 Tringula.cxx:29
 Tringula.cxx:30
 Tringula.cxx:31
 Tringula.cxx:32
 Tringula.cxx:33
 Tringula.cxx:34
 Tringula.cxx:35
 Tringula.cxx:36
 Tringula.cxx:37
 Tringula.cxx:38
 Tringula.cxx:39
 Tringula.cxx:40
 Tringula.cxx:41
 Tringula.cxx:42
 Tringula.cxx:43
 Tringula.cxx:44
 Tringula.cxx:45
 Tringula.cxx:46
 Tringula.cxx:47
 Tringula.cxx:48
 Tringula.cxx:49
 Tringula.cxx:50
 Tringula.cxx:51
 Tringula.cxx:52
 Tringula.cxx:53
 Tringula.cxx:54
 Tringula.cxx:55
 Tringula.cxx:56
 Tringula.cxx:57
 Tringula.cxx:58
 Tringula.cxx:59
 Tringula.cxx:60
 Tringula.cxx:61
 Tringula.cxx:62
 Tringula.cxx:63
 Tringula.cxx:64
 Tringula.cxx:65
 Tringula.cxx:66
 Tringula.cxx:67
 Tringula.cxx:68
 Tringula.cxx:69
 Tringula.cxx:70
 Tringula.cxx:71
 Tringula.cxx:72
 Tringula.cxx:73
 Tringula.cxx:74
 Tringula.cxx:75
 Tringula.cxx:76
 Tringula.cxx:77
 Tringula.cxx:78
 Tringula.cxx:79
 Tringula.cxx:80
 Tringula.cxx:81
 Tringula.cxx:82
 Tringula.cxx:83
 Tringula.cxx:84
 Tringula.cxx:85
 Tringula.cxx:86
 Tringula.cxx:87
 Tringula.cxx:88
 Tringula.cxx:89
 Tringula.cxx:90
 Tringula.cxx:91
 Tringula.cxx:92
 Tringula.cxx:93
 Tringula.cxx:94
 Tringula.cxx:95
 Tringula.cxx:96
 Tringula.cxx:97
 Tringula.cxx:98
 Tringula.cxx:99
 Tringula.cxx:100
 Tringula.cxx:101
 Tringula.cxx:102
 Tringula.cxx:103
 Tringula.cxx:104
 Tringula.cxx:105
 Tringula.cxx:106
 Tringula.cxx:107
 Tringula.cxx:108
 Tringula.cxx:109
 Tringula.cxx:110
 Tringula.cxx:111
 Tringula.cxx:112
 Tringula.cxx:113
 Tringula.cxx:114
 Tringula.cxx:115
 Tringula.cxx:116
 Tringula.cxx:117
 Tringula.cxx:118
 Tringula.cxx:119
 Tringula.cxx:120
 Tringula.cxx:121
 Tringula.cxx:122
 Tringula.cxx:123
 Tringula.cxx:124
 Tringula.cxx:125
 Tringula.cxx:126
 Tringula.cxx:127
 Tringula.cxx:128
 Tringula.cxx:129
 Tringula.cxx:130
 Tringula.cxx:131
 Tringula.cxx:132
 Tringula.cxx:133
 Tringula.cxx:134
 Tringula.cxx:135
 Tringula.cxx:136
 Tringula.cxx:137
 Tringula.cxx:138
 Tringula.cxx:139
 Tringula.cxx:140
 Tringula.cxx:141
 Tringula.cxx:142
 Tringula.cxx:143
 Tringula.cxx:144
 Tringula.cxx:145
 Tringula.cxx:146
 Tringula.cxx:147
 Tringula.cxx:148
 Tringula.cxx:149
 Tringula.cxx:150
 Tringula.cxx:151
 Tringula.cxx:152
 Tringula.cxx:153
 Tringula.cxx:154
 Tringula.cxx:155
 Tringula.cxx:156
 Tringula.cxx:157
 Tringula.cxx:158
 Tringula.cxx:159
 Tringula.cxx:160
 Tringula.cxx:161
 Tringula.cxx:162
 Tringula.cxx:163
 Tringula.cxx:164
 Tringula.cxx:165
 Tringula.cxx:166
 Tringula.cxx:167
 Tringula.cxx:168
 Tringula.cxx:169
 Tringula.cxx:170
 Tringula.cxx:171
 Tringula.cxx:172
 Tringula.cxx:173
 Tringula.cxx:174
 Tringula.cxx:175
 Tringula.cxx:176
 Tringula.cxx:177
 Tringula.cxx:178
 Tringula.cxx:179
 Tringula.cxx:180
 Tringula.cxx:181
 Tringula.cxx:182
 Tringula.cxx:183
 Tringula.cxx:184
 Tringula.cxx:185
 Tringula.cxx:186
 Tringula.cxx:187
 Tringula.cxx:188
 Tringula.cxx:189
 Tringula.cxx:190
 Tringula.cxx:191
 Tringula.cxx:192
 Tringula.cxx:193
 Tringula.cxx:194
 Tringula.cxx:195
 Tringula.cxx:196
 Tringula.cxx:197
 Tringula.cxx:198
 Tringula.cxx:199
 Tringula.cxx:200
 Tringula.cxx:201
 Tringula.cxx:202
 Tringula.cxx:203
 Tringula.cxx:204
 Tringula.cxx:205
 Tringula.cxx:206
 Tringula.cxx:207
 Tringula.cxx:208
 Tringula.cxx:209
 Tringula.cxx:210
 Tringula.cxx:211
 Tringula.cxx:212
 Tringula.cxx:213
 Tringula.cxx:214
 Tringula.cxx:215
 Tringula.cxx:216
 Tringula.cxx:217
 Tringula.cxx:218
 Tringula.cxx:219
 Tringula.cxx:220
 Tringula.cxx:221
 Tringula.cxx:222
 Tringula.cxx:223
 Tringula.cxx:224
 Tringula.cxx:225
 Tringula.cxx:226
 Tringula.cxx:227
 Tringula.cxx:228
 Tringula.cxx:229
 Tringula.cxx:230
 Tringula.cxx:231
 Tringula.cxx:232
 Tringula.cxx:233
 Tringula.cxx:234
 Tringula.cxx:235
 Tringula.cxx:236
 Tringula.cxx:237
 Tringula.cxx:238
 Tringula.cxx:239
 Tringula.cxx:240
 Tringula.cxx:241
 Tringula.cxx:242
 Tringula.cxx:243
 Tringula.cxx:244
 Tringula.cxx:245
 Tringula.cxx:246
 Tringula.cxx:247
 Tringula.cxx:248
 Tringula.cxx:249
 Tringula.cxx:250
 Tringula.cxx:251
 Tringula.cxx:252
 Tringula.cxx:253
 Tringula.cxx:254
 Tringula.cxx:255
 Tringula.cxx:256
 Tringula.cxx:257
 Tringula.cxx:258
 Tringula.cxx:259
 Tringula.cxx:260
 Tringula.cxx:261
 Tringula.cxx:262
 Tringula.cxx:263
 Tringula.cxx:264
 Tringula.cxx:265
 Tringula.cxx:266
 Tringula.cxx:267
 Tringula.cxx:268
 Tringula.cxx:269
 Tringula.cxx:270
 Tringula.cxx:271
 Tringula.cxx:272
 Tringula.cxx:273
 Tringula.cxx:274
 Tringula.cxx:275
 Tringula.cxx:276
 Tringula.cxx:277
 Tringula.cxx:278
 Tringula.cxx:279
 Tringula.cxx:280
 Tringula.cxx:281
 Tringula.cxx:282
 Tringula.cxx:283
 Tringula.cxx:284
 Tringula.cxx:285
 Tringula.cxx:286
 Tringula.cxx:287
 Tringula.cxx:288
 Tringula.cxx:289
 Tringula.cxx:290
 Tringula.cxx:291
 Tringula.cxx:292
 Tringula.cxx:293
 Tringula.cxx:294
 Tringula.cxx:295
 Tringula.cxx:296
 Tringula.cxx:297
 Tringula.cxx:298
 Tringula.cxx:299
 Tringula.cxx:300
 Tringula.cxx:301
 Tringula.cxx:302
 Tringula.cxx:303
 Tringula.cxx:304
 Tringula.cxx:305
 Tringula.cxx:306
 Tringula.cxx:307
 Tringula.cxx:308
 Tringula.cxx:309
 Tringula.cxx:310
 Tringula.cxx:311
 Tringula.cxx:312
 Tringula.cxx:313
 Tringula.cxx:314
 Tringula.cxx:315
 Tringula.cxx:316
 Tringula.cxx:317
 Tringula.cxx:318
 Tringula.cxx:319
 Tringula.cxx:320
 Tringula.cxx:321
 Tringula.cxx:322
 Tringula.cxx:323
 Tringula.cxx:324
 Tringula.cxx:325
 Tringula.cxx:326
 Tringula.cxx:327
 Tringula.cxx:328
 Tringula.cxx:329
 Tringula.cxx:330
 Tringula.cxx:331
 Tringula.cxx:332
 Tringula.cxx:333
 Tringula.cxx:334
 Tringula.cxx:335
 Tringula.cxx:336
 Tringula.cxx:337
 Tringula.cxx:338
 Tringula.cxx:339
 Tringula.cxx:340
 Tringula.cxx:341
 Tringula.cxx:342
 Tringula.cxx:343
 Tringula.cxx:344
 Tringula.cxx:345
 Tringula.cxx:346
 Tringula.cxx:347
 Tringula.cxx:348
 Tringula.cxx:349
 Tringula.cxx:350
 Tringula.cxx:351
 Tringula.cxx:352
 Tringula.cxx:353
 Tringula.cxx:354
 Tringula.cxx:355
 Tringula.cxx:356
 Tringula.cxx:357
 Tringula.cxx:358
 Tringula.cxx:359
 Tringula.cxx:360
 Tringula.cxx:361
 Tringula.cxx:362
 Tringula.cxx:363
 Tringula.cxx:364
 Tringula.cxx:365
 Tringula.cxx:366
 Tringula.cxx:367
 Tringula.cxx:368
 Tringula.cxx:369
 Tringula.cxx:370
 Tringula.cxx:371
 Tringula.cxx:372
 Tringula.cxx:373
 Tringula.cxx:374
 Tringula.cxx:375
 Tringula.cxx:376
 Tringula.cxx:377
 Tringula.cxx:378
 Tringula.cxx:379
 Tringula.cxx:380
 Tringula.cxx:381
 Tringula.cxx:382
 Tringula.cxx:383
 Tringula.cxx:384
 Tringula.cxx:385
 Tringula.cxx:386
 Tringula.cxx:387
 Tringula.cxx:388
 Tringula.cxx:389
 Tringula.cxx:390
 Tringula.cxx:391
 Tringula.cxx:392
 Tringula.cxx:393
 Tringula.cxx:394
 Tringula.cxx:395
 Tringula.cxx:396
 Tringula.cxx:397
 Tringula.cxx:398
 Tringula.cxx:399
 Tringula.cxx:400
 Tringula.cxx:401
 Tringula.cxx:402
 Tringula.cxx:403
 Tringula.cxx:404
 Tringula.cxx:405
 Tringula.cxx:406
 Tringula.cxx:407
 Tringula.cxx:408
 Tringula.cxx:409
 Tringula.cxx:410
 Tringula.cxx:411
 Tringula.cxx:412
 Tringula.cxx:413
 Tringula.cxx:414
 Tringula.cxx:415
 Tringula.cxx:416
 Tringula.cxx:417
 Tringula.cxx:418
 Tringula.cxx:419
 Tringula.cxx:420
 Tringula.cxx:421
 Tringula.cxx:422
 Tringula.cxx:423
 Tringula.cxx:424
 Tringula.cxx:425
 Tringula.cxx:426
 Tringula.cxx:427
 Tringula.cxx:428
 Tringula.cxx:429
 Tringula.cxx:430
 Tringula.cxx:431
 Tringula.cxx:432
 Tringula.cxx:433
 Tringula.cxx:434
 Tringula.cxx:435
 Tringula.cxx:436
 Tringula.cxx:437
 Tringula.cxx:438
 Tringula.cxx:439
 Tringula.cxx:440
 Tringula.cxx:441
 Tringula.cxx:442
 Tringula.cxx:443
 Tringula.cxx:444
 Tringula.cxx:445
 Tringula.cxx:446
 Tringula.cxx:447
 Tringula.cxx:448
 Tringula.cxx:449
 Tringula.cxx:450
 Tringula.cxx:451
 Tringula.cxx:452
 Tringula.cxx:453
 Tringula.cxx:454
 Tringula.cxx:455
 Tringula.cxx:456
 Tringula.cxx:457
 Tringula.cxx:458
 Tringula.cxx:459
 Tringula.cxx:460
 Tringula.cxx:461
 Tringula.cxx:462
 Tringula.cxx:463
 Tringula.cxx:464
 Tringula.cxx:465
 Tringula.cxx:466
 Tringula.cxx:467
 Tringula.cxx:468
 Tringula.cxx:469
 Tringula.cxx:470
 Tringula.cxx:471
 Tringula.cxx:472
 Tringula.cxx:473
 Tringula.cxx:474
 Tringula.cxx:475
 Tringula.cxx:476
 Tringula.cxx:477
 Tringula.cxx:478
 Tringula.cxx:479
 Tringula.cxx:480
 Tringula.cxx:481
 Tringula.cxx:482
 Tringula.cxx:483
 Tringula.cxx:484
 Tringula.cxx:485
 Tringula.cxx:486
 Tringula.cxx:487
 Tringula.cxx:488
 Tringula.cxx:489
 Tringula.cxx:490
 Tringula.cxx:491
 Tringula.cxx:492
 Tringula.cxx:493
 Tringula.cxx:494
 Tringula.cxx:495
 Tringula.cxx:496
 Tringula.cxx:497
 Tringula.cxx:498
 Tringula.cxx:499
 Tringula.cxx:500
 Tringula.cxx:501
 Tringula.cxx:502
 Tringula.cxx:503
 Tringula.cxx:504
 Tringula.cxx:505
 Tringula.cxx:506
 Tringula.cxx:507
 Tringula.cxx:508
 Tringula.cxx:509
 Tringula.cxx:510
 Tringula.cxx:511
 Tringula.cxx:512
 Tringula.cxx:513
 Tringula.cxx:514
 Tringula.cxx:515
 Tringula.cxx:516
 Tringula.cxx:517
 Tringula.cxx:518
 Tringula.cxx:519
 Tringula.cxx:520
 Tringula.cxx:521
 Tringula.cxx:522
 Tringula.cxx:523
 Tringula.cxx:524
 Tringula.cxx:525
 Tringula.cxx:526
 Tringula.cxx:527
 Tringula.cxx:528
 Tringula.cxx:529
 Tringula.cxx:530
 Tringula.cxx:531
 Tringula.cxx:532
 Tringula.cxx:533
 Tringula.cxx:534
 Tringula.cxx:535
 Tringula.cxx:536
 Tringula.cxx:537
 Tringula.cxx:538
 Tringula.cxx:539
 Tringula.cxx:540
 Tringula.cxx:541
 Tringula.cxx:542
 Tringula.cxx:543
 Tringula.cxx:544
 Tringula.cxx:545
 Tringula.cxx:546
 Tringula.cxx:547
 Tringula.cxx:548
 Tringula.cxx:549
 Tringula.cxx:550
 Tringula.cxx:551
 Tringula.cxx:552
 Tringula.cxx:553
 Tringula.cxx:554
 Tringula.cxx:555
 Tringula.cxx:556
 Tringula.cxx:557
 Tringula.cxx:558
 Tringula.cxx:559
 Tringula.cxx:560
 Tringula.cxx:561
 Tringula.cxx:562
 Tringula.cxx:563
 Tringula.cxx:564
 Tringula.cxx:565
 Tringula.cxx:566
 Tringula.cxx:567
 Tringula.cxx:568
 Tringula.cxx:569
 Tringula.cxx:570
 Tringula.cxx:571
 Tringula.cxx:572
 Tringula.cxx:573
 Tringula.cxx:574
 Tringula.cxx:575
 Tringula.cxx:576
 Tringula.cxx:577
 Tringula.cxx:578
 Tringula.cxx:579
 Tringula.cxx:580
 Tringula.cxx:581
 Tringula.cxx:582
 Tringula.cxx:583
 Tringula.cxx:584
 Tringula.cxx:585
 Tringula.cxx:586
 Tringula.cxx:587
 Tringula.cxx:588
 Tringula.cxx:589
 Tringula.cxx:590
 Tringula.cxx:591
 Tringula.cxx:592
 Tringula.cxx:593
 Tringula.cxx:594
 Tringula.cxx:595
 Tringula.cxx:596
 Tringula.cxx:597
 Tringula.cxx:598
 Tringula.cxx:599
 Tringula.cxx:600
 Tringula.cxx:601
 Tringula.cxx:602
 Tringula.cxx:603
 Tringula.cxx:604
 Tringula.cxx:605
 Tringula.cxx:606
 Tringula.cxx:607
 Tringula.cxx:608
 Tringula.cxx:609
 Tringula.cxx:610
 Tringula.cxx:611
 Tringula.cxx:612
 Tringula.cxx:613
 Tringula.cxx:614
 Tringula.cxx:615
 Tringula.cxx:616
 Tringula.cxx:617
 Tringula.cxx:618
 Tringula.cxx:619
 Tringula.cxx:620
 Tringula.cxx:621
 Tringula.cxx:622
 Tringula.cxx:623
 Tringula.cxx:624
 Tringula.cxx:625
 Tringula.cxx:626
 Tringula.cxx:627
 Tringula.cxx:628
 Tringula.cxx:629
 Tringula.cxx:630
 Tringula.cxx:631
 Tringula.cxx:632
 Tringula.cxx:633
 Tringula.cxx:634
 Tringula.cxx:635
 Tringula.cxx:636
 Tringula.cxx:637
 Tringula.cxx:638
 Tringula.cxx:639
 Tringula.cxx:640
 Tringula.cxx:641
 Tringula.cxx:642
 Tringula.cxx:643
 Tringula.cxx:644
 Tringula.cxx:645
 Tringula.cxx:646
 Tringula.cxx:647
 Tringula.cxx:648
 Tringula.cxx:649
 Tringula.cxx:650
 Tringula.cxx:651
 Tringula.cxx:652
 Tringula.cxx:653
 Tringula.cxx:654
 Tringula.cxx:655
 Tringula.cxx:656
 Tringula.cxx:657
 Tringula.cxx:658
 Tringula.cxx:659
 Tringula.cxx:660
 Tringula.cxx:661
 Tringula.cxx:662
 Tringula.cxx:663
 Tringula.cxx:664
 Tringula.cxx:665
 Tringula.cxx:666
 Tringula.cxx:667
 Tringula.cxx:668
 Tringula.cxx:669
 Tringula.cxx:670
 Tringula.cxx:671
 Tringula.cxx:672
 Tringula.cxx:673
 Tringula.cxx:674
 Tringula.cxx:675
 Tringula.cxx:676
 Tringula.cxx:677
 Tringula.cxx:678
 Tringula.cxx:679
 Tringula.cxx:680
 Tringula.cxx:681
 Tringula.cxx:682
 Tringula.cxx:683
 Tringula.cxx:684
 Tringula.cxx:685
 Tringula.cxx:686
 Tringula.cxx:687
 Tringula.cxx:688
 Tringula.cxx:689
 Tringula.cxx:690
 Tringula.cxx:691
 Tringula.cxx:692
 Tringula.cxx:693
 Tringula.cxx:694
 Tringula.cxx:695
 Tringula.cxx:696
 Tringula.cxx:697
 Tringula.cxx:698
 Tringula.cxx:699
 Tringula.cxx:700
 Tringula.cxx:701
 Tringula.cxx:702
 Tringula.cxx:703
 Tringula.cxx:704
 Tringula.cxx:705
 Tringula.cxx:706
 Tringula.cxx:707
 Tringula.cxx:708
 Tringula.cxx:709
 Tringula.cxx:710
 Tringula.cxx:711
 Tringula.cxx:712
 Tringula.cxx:713
 Tringula.cxx:714
 Tringula.cxx:715
 Tringula.cxx:716
 Tringula.cxx:717
 Tringula.cxx:718
 Tringula.cxx:719
 Tringula.cxx:720
 Tringula.cxx:721
 Tringula.cxx:722
 Tringula.cxx:723
 Tringula.cxx:724
 Tringula.cxx:725
 Tringula.cxx:726
 Tringula.cxx:727
 Tringula.cxx:728
 Tringula.cxx:729
 Tringula.cxx:730
 Tringula.cxx:731
 Tringula.cxx:732
 Tringula.cxx:733
 Tringula.cxx:734
 Tringula.cxx:735
 Tringula.cxx:736
 Tringula.cxx:737
 Tringula.cxx:738
 Tringula.cxx:739
 Tringula.cxx:740
 Tringula.cxx:741
 Tringula.cxx:742
 Tringula.cxx:743
 Tringula.cxx:744
 Tringula.cxx:745
 Tringula.cxx:746
 Tringula.cxx:747
 Tringula.cxx:748
 Tringula.cxx:749
 Tringula.cxx:750
 Tringula.cxx:751
 Tringula.cxx:752
 Tringula.cxx:753
 Tringula.cxx:754
 Tringula.cxx:755
 Tringula.cxx:756
 Tringula.cxx:757
 Tringula.cxx:758
 Tringula.cxx:759
 Tringula.cxx:760
 Tringula.cxx:761
 Tringula.cxx:762
 Tringula.cxx:763
 Tringula.cxx:764
 Tringula.cxx:765
 Tringula.cxx:766
 Tringula.cxx:767
 Tringula.cxx:768
 Tringula.cxx:769
 Tringula.cxx:770
 Tringula.cxx:771
 Tringula.cxx:772
 Tringula.cxx:773
 Tringula.cxx:774
 Tringula.cxx:775
 Tringula.cxx:776
 Tringula.cxx:777
 Tringula.cxx:778
 Tringula.cxx:779
 Tringula.cxx:780
 Tringula.cxx:781
 Tringula.cxx:782
 Tringula.cxx:783
 Tringula.cxx:784
 Tringula.cxx:785
 Tringula.cxx:786
 Tringula.cxx:787
 Tringula.cxx:788
 Tringula.cxx:789
 Tringula.cxx:790
 Tringula.cxx:791
 Tringula.cxx:792
 Tringula.cxx:793
 Tringula.cxx:794
 Tringula.cxx:795
 Tringula.cxx:796
 Tringula.cxx:797
 Tringula.cxx:798
 Tringula.cxx:799
 Tringula.cxx:800
 Tringula.cxx:801
 Tringula.cxx:802
 Tringula.cxx:803
 Tringula.cxx:804
 Tringula.cxx:805
 Tringula.cxx:806
 Tringula.cxx:807
 Tringula.cxx:808
 Tringula.cxx:809
 Tringula.cxx:810
 Tringula.cxx:811
 Tringula.cxx:812
 Tringula.cxx:813
 Tringula.cxx:814
 Tringula.cxx:815
 Tringula.cxx:816
 Tringula.cxx:817
 Tringula.cxx:818
 Tringula.cxx:819
 Tringula.cxx:820
 Tringula.cxx:821
 Tringula.cxx:822
 Tringula.cxx:823
 Tringula.cxx:824
 Tringula.cxx:825
 Tringula.cxx:826
 Tringula.cxx:827
 Tringula.cxx:828
 Tringula.cxx:829
 Tringula.cxx:830
 Tringula.cxx:831
 Tringula.cxx:832
 Tringula.cxx:833
 Tringula.cxx:834
 Tringula.cxx:835
 Tringula.cxx:836
 Tringula.cxx:837
 Tringula.cxx:838
 Tringula.cxx:839
 Tringula.cxx:840
 Tringula.cxx:841
 Tringula.cxx:842
 Tringula.cxx:843
 Tringula.cxx:844
 Tringula.cxx:845
 Tringula.cxx:846
 Tringula.cxx:847
 Tringula.cxx:848
 Tringula.cxx:849
 Tringula.cxx:850
 Tringula.cxx:851
 Tringula.cxx:852
 Tringula.cxx:853
 Tringula.cxx:854
 Tringula.cxx:855
 Tringula.cxx:856
 Tringula.cxx:857
 Tringula.cxx:858
 Tringula.cxx:859
 Tringula.cxx:860
 Tringula.cxx:861
 Tringula.cxx:862
 Tringula.cxx:863
 Tringula.cxx:864
 Tringula.cxx:865
 Tringula.cxx:866
 Tringula.cxx:867
 Tringula.cxx:868
 Tringula.cxx:869
 Tringula.cxx:870
 Tringula.cxx:871
 Tringula.cxx:872
 Tringula.cxx:873
 Tringula.cxx:874
 Tringula.cxx:875
 Tringula.cxx:876
 Tringula.cxx:877
 Tringula.cxx:878
 Tringula.cxx:879
 Tringula.cxx:880
 Tringula.cxx:881
 Tringula.cxx:882
 Tringula.cxx:883
 Tringula.cxx:884
 Tringula.cxx:885
 Tringula.cxx:886
 Tringula.cxx:887
 Tringula.cxx:888
 Tringula.cxx:889
 Tringula.cxx:890
 Tringula.cxx:891
 Tringula.cxx:892
 Tringula.cxx:893
 Tringula.cxx:894
 Tringula.cxx:895
 Tringula.cxx:896
 Tringula.cxx:897
 Tringula.cxx:898
 Tringula.cxx:899
 Tringula.cxx:900
 Tringula.cxx:901
 Tringula.cxx:902
 Tringula.cxx:903
 Tringula.cxx:904
 Tringula.cxx:905
 Tringula.cxx:906
 Tringula.cxx:907
 Tringula.cxx:908
 Tringula.cxx:909
 Tringula.cxx:910
 Tringula.cxx:911
 Tringula.cxx:912
 Tringula.cxx:913
 Tringula.cxx:914
 Tringula.cxx:915
 Tringula.cxx:916
 Tringula.cxx:917
 Tringula.cxx:918
 Tringula.cxx:919
 Tringula.cxx:920
 Tringula.cxx:921
 Tringula.cxx:922
 Tringula.cxx:923
 Tringula.cxx:924
 Tringula.cxx:925
 Tringula.cxx:926
 Tringula.cxx:927
 Tringula.cxx:928
 Tringula.cxx:929
 Tringula.cxx:930
 Tringula.cxx:931
 Tringula.cxx:932
 Tringula.cxx:933
 Tringula.cxx:934
 Tringula.cxx:935
 Tringula.cxx:936
 Tringula.cxx:937
 Tringula.cxx:938
 Tringula.cxx:939
 Tringula.cxx:940
 Tringula.cxx:941
 Tringula.cxx:942
 Tringula.cxx:943
 Tringula.cxx:944
 Tringula.cxx:945
 Tringula.cxx:946
 Tringula.cxx:947
 Tringula.cxx:948
 Tringula.cxx:949
 Tringula.cxx:950
 Tringula.cxx:951
 Tringula.cxx:952
 Tringula.cxx:953
 Tringula.cxx:954
 Tringula.cxx:955
 Tringula.cxx:956
 Tringula.cxx:957
 Tringula.cxx:958
 Tringula.cxx:959
 Tringula.cxx:960
 Tringula.cxx:961
 Tringula.cxx:962
 Tringula.cxx:963
 Tringula.cxx:964
 Tringula.cxx:965
 Tringula.cxx:966
 Tringula.cxx:967
 Tringula.cxx:968
 Tringula.cxx:969
 Tringula.cxx:970
 Tringula.cxx:971
 Tringula.cxx:972
 Tringula.cxx:973
 Tringula.cxx:974
 Tringula.cxx:975
 Tringula.cxx:976
 Tringula.cxx:977
 Tringula.cxx:978
 Tringula.cxx:979
 Tringula.cxx:980
 Tringula.cxx:981
 Tringula.cxx:982
 Tringula.cxx:983
 Tringula.cxx:984
 Tringula.cxx:985
 Tringula.cxx:986
 Tringula.cxx:987
 Tringula.cxx:988
 Tringula.cxx:989
 Tringula.cxx:990
 Tringula.cxx:991
 Tringula.cxx:992
 Tringula.cxx:993
 Tringula.cxx:994
 Tringula.cxx:995
 Tringula.cxx:996
 Tringula.cxx:997
 Tringula.cxx:998
 Tringula.cxx:999
 Tringula.cxx:1000
 Tringula.cxx:1001
 Tringula.cxx:1002
 Tringula.cxx:1003
 Tringula.cxx:1004
 Tringula.cxx:1005
 Tringula.cxx:1006
 Tringula.cxx:1007
 Tringula.cxx:1008
 Tringula.cxx:1009
 Tringula.cxx:1010
 Tringula.cxx:1011
 Tringula.cxx:1012
 Tringula.cxx:1013
 Tringula.cxx:1014
 Tringula.cxx:1015
 Tringula.cxx:1016
 Tringula.cxx:1017
 Tringula.cxx:1018
 Tringula.cxx:1019
 Tringula.cxx:1020
 Tringula.cxx:1021
 Tringula.cxx:1022
 Tringula.cxx:1023
 Tringula.cxx:1024
 Tringula.cxx:1025
 Tringula.cxx:1026
 Tringula.cxx:1027
 Tringula.cxx:1028
 Tringula.cxx:1029
 Tringula.cxx:1030
 Tringula.cxx:1031
 Tringula.cxx:1032
 Tringula.cxx:1033
 Tringula.cxx:1034
 Tringula.cxx:1035
 Tringula.cxx:1036
 Tringula.cxx:1037
 Tringula.cxx:1038
 Tringula.cxx:1039
 Tringula.cxx:1040
 Tringula.cxx:1041
 Tringula.cxx:1042
 Tringula.cxx:1043
 Tringula.cxx:1044
 Tringula.cxx:1045
 Tringula.cxx:1046
 Tringula.cxx:1047
 Tringula.cxx:1048
 Tringula.cxx:1049
 Tringula.cxx:1050
 Tringula.cxx:1051
 Tringula.cxx:1052
 Tringula.cxx:1053
 Tringula.cxx:1054
 Tringula.cxx:1055
 Tringula.cxx:1056
 Tringula.cxx:1057
 Tringula.cxx:1058
 Tringula.cxx:1059
 Tringula.cxx:1060
 Tringula.cxx:1061
 Tringula.cxx:1062
 Tringula.cxx:1063
 Tringula.cxx:1064
 Tringula.cxx:1065
 Tringula.cxx:1066
 Tringula.cxx:1067
 Tringula.cxx:1068
 Tringula.cxx:1069
 Tringula.cxx:1070
 Tringula.cxx:1071
 Tringula.cxx:1072
 Tringula.cxx:1073
 Tringula.cxx:1074
 Tringula.cxx:1075
 Tringula.cxx:1076
 Tringula.cxx:1077
 Tringula.cxx:1078
 Tringula.cxx:1079
 Tringula.cxx:1080
 Tringula.cxx:1081
 Tringula.cxx:1082
 Tringula.cxx:1083
 Tringula.cxx:1084
 Tringula.cxx:1085
 Tringula.cxx:1086
 Tringula.cxx:1087
 Tringula.cxx:1088
 Tringula.cxx:1089
 Tringula.cxx:1090
 Tringula.cxx:1091
 Tringula.cxx:1092
 Tringula.cxx:1093
 Tringula.cxx:1094
 Tringula.cxx:1095
 Tringula.cxx:1096
 Tringula.cxx:1097
 Tringula.cxx:1098
 Tringula.cxx:1099
 Tringula.cxx:1100
 Tringula.cxx:1101
 Tringula.cxx:1102
 Tringula.cxx:1103
 Tringula.cxx:1104
 Tringula.cxx:1105
 Tringula.cxx:1106
 Tringula.cxx:1107
 Tringula.cxx:1108
 Tringula.cxx:1109
 Tringula.cxx:1110
 Tringula.cxx:1111
 Tringula.cxx:1112
 Tringula.cxx:1113
 Tringula.cxx:1114
 Tringula.cxx:1115
 Tringula.cxx:1116
 Tringula.cxx:1117
 Tringula.cxx:1118
 Tringula.cxx:1119
 Tringula.cxx:1120
 Tringula.cxx:1121
 Tringula.cxx:1122
 Tringula.cxx:1123
 Tringula.cxx:1124
 Tringula.cxx:1125
 Tringula.cxx:1126
 Tringula.cxx:1127
 Tringula.cxx:1128
 Tringula.cxx:1129
 Tringula.cxx:1130
 Tringula.cxx:1131
 Tringula.cxx:1132
 Tringula.cxx:1133
 Tringula.cxx:1134
 Tringula.cxx:1135
 Tringula.cxx:1136
 Tringula.cxx:1137
 Tringula.cxx:1138
 Tringula.cxx:1139
 Tringula.cxx:1140
 Tringula.cxx:1141
 Tringula.cxx:1142
 Tringula.cxx:1143
 Tringula.cxx:1144
 Tringula.cxx:1145
 Tringula.cxx:1146
 Tringula.cxx:1147
 Tringula.cxx:1148
 Tringula.cxx:1149
 Tringula.cxx:1150
 Tringula.cxx:1151
 Tringula.cxx:1152
 Tringula.cxx:1153
 Tringula.cxx:1154
 Tringula.cxx:1155
 Tringula.cxx:1156
 Tringula.cxx:1157
 Tringula.cxx:1158
 Tringula.cxx:1159
 Tringula.cxx:1160
 Tringula.cxx:1161
 Tringula.cxx:1162
 Tringula.cxx:1163
 Tringula.cxx:1164
 Tringula.cxx:1165
 Tringula.cxx:1166
 Tringula.cxx:1167
 Tringula.cxx:1168
 Tringula.cxx:1169
 Tringula.cxx:1170
 Tringula.cxx:1171
 Tringula.cxx:1172
 Tringula.cxx:1173
 Tringula.cxx:1174
 Tringula.cxx:1175
 Tringula.cxx:1176
 Tringula.cxx:1177
 Tringula.cxx:1178
 Tringula.cxx:1179
 Tringula.cxx:1180
 Tringula.cxx:1181
 Tringula.cxx:1182
 Tringula.cxx:1183
 Tringula.cxx:1184
 Tringula.cxx:1185
 Tringula.cxx:1186
 Tringula.cxx:1187
 Tringula.cxx:1188
 Tringula.cxx:1189
 Tringula.cxx:1190
 Tringula.cxx:1191
 Tringula.cxx:1192
 Tringula.cxx:1193
 Tringula.cxx:1194
 Tringula.cxx:1195
 Tringula.cxx:1196
 Tringula.cxx:1197
 Tringula.cxx:1198
 Tringula.cxx:1199
 Tringula.cxx:1200
 Tringula.cxx:1201
 Tringula.cxx:1202
 Tringula.cxx:1203
 Tringula.cxx:1204
 Tringula.cxx:1205
 Tringula.cxx:1206
 Tringula.cxx:1207
 Tringula.cxx:1208
 Tringula.cxx:1209
 Tringula.cxx:1210
 Tringula.cxx:1211
 Tringula.cxx:1212
 Tringula.cxx:1213
 Tringula.cxx:1214
 Tringula.cxx:1215
 Tringula.cxx:1216
 Tringula.cxx:1217
 Tringula.cxx:1218
 Tringula.cxx:1219
 Tringula.cxx:1220
 Tringula.cxx:1221
 Tringula.cxx:1222
 Tringula.cxx:1223
 Tringula.cxx:1224
 Tringula.cxx:1225
 Tringula.cxx:1226
 Tringula.cxx:1227
 Tringula.cxx:1228
 Tringula.cxx:1229
 Tringula.cxx:1230
 Tringula.cxx:1231
 Tringula.cxx:1232
 Tringula.cxx:1233
 Tringula.cxx:1234
 Tringula.cxx:1235
 Tringula.cxx:1236
 Tringula.cxx:1237
 Tringula.cxx:1238
 Tringula.cxx:1239
 Tringula.cxx:1240
 Tringula.cxx:1241
 Tringula.cxx:1242
 Tringula.cxx:1243
 Tringula.cxx:1244
 Tringula.cxx:1245
 Tringula.cxx:1246
 Tringula.cxx:1247
 Tringula.cxx:1248
 Tringula.cxx:1249
 Tringula.cxx:1250
 Tringula.cxx:1251
 Tringula.cxx:1252
 Tringula.cxx:1253
 Tringula.cxx:1254
 Tringula.cxx:1255
 Tringula.cxx:1256
 Tringula.cxx:1257
 Tringula.cxx:1258
 Tringula.cxx:1259
 Tringula.cxx:1260
 Tringula.cxx:1261
 Tringula.cxx:1262
 Tringula.cxx:1263
 Tringula.cxx:1264
 Tringula.cxx:1265
 Tringula.cxx:1266
 Tringula.cxx:1267
 Tringula.cxx:1268
 Tringula.cxx:1269
 Tringula.cxx:1270
 Tringula.cxx:1271
 Tringula.cxx:1272
 Tringula.cxx:1273
 Tringula.cxx:1274
 Tringula.cxx:1275
 Tringula.cxx:1276
 Tringula.cxx:1277
 Tringula.cxx:1278
 Tringula.cxx:1279
 Tringula.cxx:1280
 Tringula.cxx:1281
 Tringula.cxx:1282
 Tringula.cxx:1283
 Tringula.cxx:1284
 Tringula.cxx:1285
 Tringula.cxx:1286
 Tringula.cxx:1287
 Tringula.cxx:1288
 Tringula.cxx:1289
 Tringula.cxx:1290
 Tringula.cxx:1291
 Tringula.cxx:1292
 Tringula.cxx:1293
 Tringula.cxx:1294
 Tringula.cxx:1295
 Tringula.cxx:1296
 Tringula.cxx:1297
 Tringula.cxx:1298
 Tringula.cxx:1299
 Tringula.cxx:1300
 Tringula.cxx:1301
 Tringula.cxx:1302
 Tringula.cxx:1303
 Tringula.cxx:1304
 Tringula.cxx:1305
 Tringula.cxx:1306
 Tringula.cxx:1307
 Tringula.cxx:1308
 Tringula.cxx:1309
 Tringula.cxx:1310
 Tringula.cxx:1311
 Tringula.cxx:1312
 Tringula.cxx:1313
 Tringula.cxx:1314
 Tringula.cxx:1315
 Tringula.cxx:1316
 Tringula.cxx:1317
 Tringula.cxx:1318
 Tringula.cxx:1319
 Tringula.cxx:1320
 Tringula.cxx:1321
 Tringula.cxx:1322
 Tringula.cxx:1323
 Tringula.cxx:1324
 Tringula.cxx:1325
 Tringula.cxx:1326
 Tringula.cxx:1327
 Tringula.cxx:1328
 Tringula.cxx:1329
 Tringula.cxx:1330
 Tringula.cxx:1331
 Tringula.cxx:1332
 Tringula.cxx:1333
 Tringula.cxx:1334
 Tringula.cxx:1335
 Tringula.cxx:1336
 Tringula.cxx:1337
 Tringula.cxx:1338
 Tringula.cxx:1339
 Tringula.cxx:1340
 Tringula.cxx:1341
 Tringula.cxx:1342
 Tringula.cxx:1343
 Tringula.cxx:1344
 Tringula.cxx:1345
 Tringula.cxx:1346
 Tringula.cxx:1347
 Tringula.cxx:1348