ROOT logo
// $Id: GTSRetriangulator.cxx 2437 2010-08-15 11:06:50Z 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/.

//__________________________________________________________________________
// GTSRetriangulator
//
// Interface to GTS surface 'coarsen' and 'refine' functions.
// Out-of-core simplification is also supported. Note that it sometimes
// produces surfaces with holes.
//
// See GTS manual for details.


#include "GTSRetriangulator.h"
#include "GTSRetriangulator.c7"

#include <GTS/GTS.h>

#include <Gled/GTime.h>

#include <TMath.h>
#include <TSystem.h>

#include <cmath>

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

namespace
{
  using namespace GTS;

  gdouble edge_angle(GtsTriangle* t, GtsEdge* e)
  {
    static const gdouble r60 = 60*TMath::DegToRad();

    GtsVertex *v = gts_triangle_vertex_opposite(t, e);
    if (v)
    {
      GtsVector a, b, c;
      gts_vector_init(a, &v->p, &e->segment.v1->p);
      gts_vector_init(b, &v->p, &e->segment.v2->p);
      gts_vector_cross(c, a, b);

      gdouble phi = atan2(gts_vector_norm(c), gts_vector_scalar(a, b));
      if (phi <= r60)
	return phi / r60;
      else
	return 1.5 - 0.5 * phi / r60;
    }
    else
    {
      return 1.0;
    }
  }

  gdouble cost_angle (GtsEdge* e)
  {
    // Returns smallest cost of all triangles e is in, where cost for each
    // triangle is:
    //   1 if angle from edge to opposite vertex is 60deg;
    //   goes linearly to 0 as the angle falls (rises) to 0deg (180deg).
    // Works well for cost up 0.5, then becomes unstable.

    gdouble cost = 1.0;
    GSList *i = e->triangles;
    while (i)
    {
      cost = TMath::Min(edge_angle((GtsTriangle*) i->data, e), cost);
      i = i->next;
    }
    return cost;
  }

  gboolean refine_stop_number (gdouble cost, guint number, guint * max)
  {
    if (number > *max)
      return TRUE;
    return FALSE;
  }

  gboolean refine_stop_cost (gdouble cost, guint number, gdouble * min)
  {
    if (cost < *min)
      return TRUE;
    return FALSE;
  }
}

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

ClassImp(GTSRetriangulator);

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

void GTSRetriangulator::_init()
{
  mTarget = 0;

  mStopOpts = SO_Number;
  mStopNumber = 1000;
  mStopCost   = 0.5;

  mCostOpts = CO_Length;
  mVO_VolumeWght   = 0.5;
  mVO_BoundaryWght = 0.5;
  mVO_ShapeWght    = 0;

  mMidvertOpts = MO_Volume;

  mMinAngleDeg = 1;

  mOutOfCoreDelta = 1e-3;

  bMeasureTime = false;
  mRunTime     = 0;
}

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

void GTSRetriangulator::Coarsen()
{
  static const Exc_t _eh("GTSRetriangulator::Coarsen ");

  using namespace GTS;

  gSystem->SetFPEMask(kDefaultMask); // kAllMask);

  GTSurf* target = *mTarget;
  if (target == 0)
    throw _eh + "Link Target should be set.";
  GtsSurface* s = target->CopySurface();
  if (s == 0)
    throw _eh + "Target should have non-null surface.";

  double stop_cost = mStopCost;

  GtsStopFunc l_stop_func = 0;
  gpointer    l_stop_data = 0;
  switch (mStopOpts)
  {
    case SO_Number:
      l_stop_func = (GtsStopFunc) gts_coarsen_stop_number;
      l_stop_data = &mStopNumber;
      break;
    case SO_Cost:
      l_stop_func = (GtsStopFunc) gts_coarsen_stop_cost;
      l_stop_data = &stop_cost;
      break;
    default:
      throw _eh + "Unknown StopOpts.";
  }

  GtsVolumeOptimizedParams l_vo_params =
    { mVO_VolumeWght, mVO_BoundaryWght, mVO_ShapeWght };

  GtsKeyFunc  l_cost_func  = 0;
  gpointer    l_cost_data  = 0;
  switch (mCostOpts)
  {
    case CO_Length:
      stop_cost = stop_cost * stop_cost; // edge-length uses square edge length.
      break;
    case CO_Volume:
      l_cost_func = (GtsKeyFunc) gts_volume_optimized_cost;
      l_cost_data = &l_vo_params;
      break;
    case CO_Angle:
      l_cost_func = (GtsKeyFunc) cost_angle;
      break;
    default:
      throw _eh + "Unknown CostOpts.";
  }

  GtsCoarsenFunc l_coarsen_func = 0;
  gpointer       l_coarsen_data = 0;
  switch (mMidvertOpts)
  {
    case MO_Midvert:
      break;
    case MO_Volume:
      l_coarsen_func = (GtsCoarsenFunc) gts_volume_optimized_vertex;
      l_coarsen_data = &l_vo_params;
      break;
    default:
      throw _eh + "Unknown MidvertOpts.";
  }

  ::GTime* start_time = 0;
  if (bMeasureTime) start_time = new ::GTime(::GTime::I_Now);

  gts_surface_coarsen(s,
		      l_cost_func, l_cost_data,
		      l_coarsen_func, l_coarsen_data,
		      l_stop_func, l_stop_data,
		      mMinAngleDeg*TMath::DegToRad());

  if (bMeasureTime) SetRunTime(start_time->TimeUntilNow().ToDouble());

  target->ReplaceSurface(s);
}

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

void GTSRetriangulator::Refine()
{
  static const Exc_t _eh("GTSRetriangulator::Refine ");

  using namespace GTS;

  GTSurf* target = *mTarget;
  if (target == 0)
    throw _eh + "Link Target should be set.";
  GtsSurface* s = target->CopySurface();
  if (s == 0)
    throw _eh + "Target should have non-null surface.";

  double stop_cost = mStopCost;

  GtsStopFunc l_stop_func = 0;
  gpointer    l_stop_data = 0;
  switch(mStopOpts)
  {
    case SO_Number:
      l_stop_func = (GtsStopFunc) refine_stop_number;
      l_stop_data = &mStopNumber;
      break;
    case SO_Cost:
      l_stop_func = (GtsStopFunc) refine_stop_cost;
      l_stop_data = &stop_cost;
      break;
    default:
      throw _eh + "Unknown StopOpts.";
  }

  GtsVolumeOptimizedParams l_vo_params =
    { mVO_VolumeWght, mVO_BoundaryWght, mVO_ShapeWght };

  GtsKeyFunc  l_cost_func  = 0;
  gpointer    l_cost_data  = 0;
  switch (mCostOpts)
  {
    case CO_Length:
      stop_cost = stop_cost * stop_cost; // edge-length uses square edge length.
      break;
    case CO_Volume:
      l_cost_func = (GtsKeyFunc) gts_volume_optimized_cost;
      l_cost_data = &l_vo_params;
      break;
    case CO_Angle:
      l_cost_func = (GtsKeyFunc) cost_angle;
      break;
    default:
      throw _eh + "Unknown CostOpts.";
  }

  ::GTime* start_time = 0;
  if (bMeasureTime) start_time = new ::GTime(::GTime::I_Now);

  gts_surface_refine(s,
		     l_cost_func, l_cost_data,
		     0, 0,
		     l_stop_func, l_stop_data);

  if (bMeasureTime) SetRunTime(start_time->TimeUntilNow().ToDouble());

  target->ReplaceSurface(s);
}

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

namespace
{
  void bbox_vertex_foo(GtsVertex* v, GtsBBox* bbox)
  {
    GtsPoint &p = v->p;
    GtsBBox  &b = *bbox;
    if (p.x < b.x1) b.x1 = p.x;
    if (p.x > b.x2) b.x2 = p.x;
    if (p.y < b.y1) b.y1 = p.y;
    if (p.y > b.y2) b.y2 = p.y;
    if (p.z < b.z1) b.z1 = p.z;
    if (p.z > b.z2) b.z2 = p.z;
  }

  void cluster_face_adder_foo(GtsFace* f, GtsClusterGrid* c_grid)
  {
    GtsVertex* vp[3];
    gts_triangle_vertices(&f->triangle, &vp[0], &vp[1], &vp[2]);
    gts_cluster_grid_add_triangle(c_grid, &vp[0]->p, &vp[1]->p, &vp[2]->p, NULL);
  }
}

void GTSRetriangulator::OutOfCoreSimplification()
{
  static const Exc_t _eh("GTSRetriangulator::OutOfCoreSimplification ");

  using namespace GTS;

  GTSurf* target = *mTarget;
  if (target == 0)
    throw _eh + "Link Target should be set.";
  GtsSurface* s = target->CopySurface();
  if (s == 0)
    throw _eh + "Target should have non-null surface.";

  ::GTime* start_time = 0;
  if (bMeasureTime) start_time = new ::GTime(::GTime::I_Now);

  GtsSurface *d = MakeDefaultSurface();

  const Double_t big = 1e100;
  GtsBBox *bbox = gts_bbox_new(gts_bbox_class(), d, 0, 0, 0, 0, 0, 0);
  bbox->x1 = bbox->y1 = bbox->z1 =  big;
  bbox->x2 = bbox->y2 = bbox->z2 = -big;
  gts_surface_foreach_vertex(s, (GtsFunc)bbox_vertex_foo, bbox);

  printf("Boundingbox is (%f,%f,%f)-(%f,%f,%f)\n", bbox->x1, bbox->y1, bbox->z1, bbox->x2, bbox->y2, bbox->z2);

  GtsClusterGrid *c_grid = gts_cluster_grid_new(gts_cluster_grid_class(),
						gts_cluster_class(), 
						d, bbox, mOutOfCoreDelta);
  gts_surface_foreach_face(s, (GTS::GtsFunc) cluster_face_adder_foo, c_grid);

  GtsRange c_stats = gts_cluster_grid_update(c_grid);

  gts_object_destroy(GTS_OBJECT(s));
  gts_object_destroy(GTS_OBJECT(c_grid));
  gts_object_destroy(GTS_OBJECT(bbox));

  printf ("%d clusters of size: min: %g avg: %.1f|%.1f max: %g\n",
	   c_stats.n, c_stats.min, c_stats.mean, c_stats.stddev, c_stats.max);

  if (bMeasureTime) SetRunTime(start_time->TimeUntilNow().ToDouble());

  target->ReplaceSurface(d);
}
 GTSRetriangulator.cxx:1
 GTSRetriangulator.cxx:2
 GTSRetriangulator.cxx:3
 GTSRetriangulator.cxx:4
 GTSRetriangulator.cxx:5
 GTSRetriangulator.cxx:6
 GTSRetriangulator.cxx:7
 GTSRetriangulator.cxx:8
 GTSRetriangulator.cxx:9
 GTSRetriangulator.cxx:10
 GTSRetriangulator.cxx:11
 GTSRetriangulator.cxx:12
 GTSRetriangulator.cxx:13
 GTSRetriangulator.cxx:14
 GTSRetriangulator.cxx:15
 GTSRetriangulator.cxx:16
 GTSRetriangulator.cxx:17
 GTSRetriangulator.cxx:18
 GTSRetriangulator.cxx:19
 GTSRetriangulator.cxx:20
 GTSRetriangulator.cxx:21
 GTSRetriangulator.cxx:22
 GTSRetriangulator.cxx:23
 GTSRetriangulator.cxx:24
 GTSRetriangulator.cxx:25
 GTSRetriangulator.cxx:26
 GTSRetriangulator.cxx:27
 GTSRetriangulator.cxx:28
 GTSRetriangulator.cxx:29
 GTSRetriangulator.cxx:30
 GTSRetriangulator.cxx:31
 GTSRetriangulator.cxx:32
 GTSRetriangulator.cxx:33
 GTSRetriangulator.cxx:34
 GTSRetriangulator.cxx:35
 GTSRetriangulator.cxx:36
 GTSRetriangulator.cxx:37
 GTSRetriangulator.cxx:38
 GTSRetriangulator.cxx:39
 GTSRetriangulator.cxx:40
 GTSRetriangulator.cxx:41
 GTSRetriangulator.cxx:42
 GTSRetriangulator.cxx:43
 GTSRetriangulator.cxx:44
 GTSRetriangulator.cxx:45
 GTSRetriangulator.cxx:46
 GTSRetriangulator.cxx:47
 GTSRetriangulator.cxx:48
 GTSRetriangulator.cxx:49
 GTSRetriangulator.cxx:50
 GTSRetriangulator.cxx:51
 GTSRetriangulator.cxx:52
 GTSRetriangulator.cxx:53
 GTSRetriangulator.cxx:54
 GTSRetriangulator.cxx:55
 GTSRetriangulator.cxx:56
 GTSRetriangulator.cxx:57
 GTSRetriangulator.cxx:58
 GTSRetriangulator.cxx:59
 GTSRetriangulator.cxx:60
 GTSRetriangulator.cxx:61
 GTSRetriangulator.cxx:62
 GTSRetriangulator.cxx:63
 GTSRetriangulator.cxx:64
 GTSRetriangulator.cxx:65
 GTSRetriangulator.cxx:66
 GTSRetriangulator.cxx:67
 GTSRetriangulator.cxx:68
 GTSRetriangulator.cxx:69
 GTSRetriangulator.cxx:70
 GTSRetriangulator.cxx:71
 GTSRetriangulator.cxx:72
 GTSRetriangulator.cxx:73
 GTSRetriangulator.cxx:74
 GTSRetriangulator.cxx:75
 GTSRetriangulator.cxx:76
 GTSRetriangulator.cxx:77
 GTSRetriangulator.cxx:78
 GTSRetriangulator.cxx:79
 GTSRetriangulator.cxx:80
 GTSRetriangulator.cxx:81
 GTSRetriangulator.cxx:82
 GTSRetriangulator.cxx:83
 GTSRetriangulator.cxx:84
 GTSRetriangulator.cxx:85
 GTSRetriangulator.cxx:86
 GTSRetriangulator.cxx:87
 GTSRetriangulator.cxx:88
 GTSRetriangulator.cxx:89
 GTSRetriangulator.cxx:90
 GTSRetriangulator.cxx:91
 GTSRetriangulator.cxx:92
 GTSRetriangulator.cxx:93
 GTSRetriangulator.cxx:94
 GTSRetriangulator.cxx:95
 GTSRetriangulator.cxx:96
 GTSRetriangulator.cxx:97
 GTSRetriangulator.cxx:98
 GTSRetriangulator.cxx:99
 GTSRetriangulator.cxx:100
 GTSRetriangulator.cxx:101
 GTSRetriangulator.cxx:102
 GTSRetriangulator.cxx:103
 GTSRetriangulator.cxx:104
 GTSRetriangulator.cxx:105
 GTSRetriangulator.cxx:106
 GTSRetriangulator.cxx:107
 GTSRetriangulator.cxx:108
 GTSRetriangulator.cxx:109
 GTSRetriangulator.cxx:110
 GTSRetriangulator.cxx:111
 GTSRetriangulator.cxx:112
 GTSRetriangulator.cxx:113
 GTSRetriangulator.cxx:114
 GTSRetriangulator.cxx:115
 GTSRetriangulator.cxx:116
 GTSRetriangulator.cxx:117
 GTSRetriangulator.cxx:118
 GTSRetriangulator.cxx:119
 GTSRetriangulator.cxx:120
 GTSRetriangulator.cxx:121
 GTSRetriangulator.cxx:122
 GTSRetriangulator.cxx:123
 GTSRetriangulator.cxx:124
 GTSRetriangulator.cxx:125
 GTSRetriangulator.cxx:126
 GTSRetriangulator.cxx:127
 GTSRetriangulator.cxx:128
 GTSRetriangulator.cxx:129
 GTSRetriangulator.cxx:130
 GTSRetriangulator.cxx:131
 GTSRetriangulator.cxx:132
 GTSRetriangulator.cxx:133
 GTSRetriangulator.cxx:134
 GTSRetriangulator.cxx:135
 GTSRetriangulator.cxx:136
 GTSRetriangulator.cxx:137
 GTSRetriangulator.cxx:138
 GTSRetriangulator.cxx:139
 GTSRetriangulator.cxx:140
 GTSRetriangulator.cxx:141
 GTSRetriangulator.cxx:142
 GTSRetriangulator.cxx:143
 GTSRetriangulator.cxx:144
 GTSRetriangulator.cxx:145
 GTSRetriangulator.cxx:146
 GTSRetriangulator.cxx:147
 GTSRetriangulator.cxx:148
 GTSRetriangulator.cxx:149
 GTSRetriangulator.cxx:150
 GTSRetriangulator.cxx:151
 GTSRetriangulator.cxx:152
 GTSRetriangulator.cxx:153
 GTSRetriangulator.cxx:154
 GTSRetriangulator.cxx:155
 GTSRetriangulator.cxx:156
 GTSRetriangulator.cxx:157
 GTSRetriangulator.cxx:158
 GTSRetriangulator.cxx:159
 GTSRetriangulator.cxx:160
 GTSRetriangulator.cxx:161
 GTSRetriangulator.cxx:162
 GTSRetriangulator.cxx:163
 GTSRetriangulator.cxx:164
 GTSRetriangulator.cxx:165
 GTSRetriangulator.cxx:166
 GTSRetriangulator.cxx:167
 GTSRetriangulator.cxx:168
 GTSRetriangulator.cxx:169
 GTSRetriangulator.cxx:170
 GTSRetriangulator.cxx:171
 GTSRetriangulator.cxx:172
 GTSRetriangulator.cxx:173
 GTSRetriangulator.cxx:174
 GTSRetriangulator.cxx:175
 GTSRetriangulator.cxx:176
 GTSRetriangulator.cxx:177
 GTSRetriangulator.cxx:178
 GTSRetriangulator.cxx:179
 GTSRetriangulator.cxx:180
 GTSRetriangulator.cxx:181
 GTSRetriangulator.cxx:182
 GTSRetriangulator.cxx:183
 GTSRetriangulator.cxx:184
 GTSRetriangulator.cxx:185
 GTSRetriangulator.cxx:186
 GTSRetriangulator.cxx:187
 GTSRetriangulator.cxx:188
 GTSRetriangulator.cxx:189
 GTSRetriangulator.cxx:190
 GTSRetriangulator.cxx:191
 GTSRetriangulator.cxx:192
 GTSRetriangulator.cxx:193
 GTSRetriangulator.cxx:194
 GTSRetriangulator.cxx:195
 GTSRetriangulator.cxx:196
 GTSRetriangulator.cxx:197
 GTSRetriangulator.cxx:198
 GTSRetriangulator.cxx:199
 GTSRetriangulator.cxx:200
 GTSRetriangulator.cxx:201
 GTSRetriangulator.cxx:202
 GTSRetriangulator.cxx:203
 GTSRetriangulator.cxx:204
 GTSRetriangulator.cxx:205
 GTSRetriangulator.cxx:206
 GTSRetriangulator.cxx:207
 GTSRetriangulator.cxx:208
 GTSRetriangulator.cxx:209
 GTSRetriangulator.cxx:210
 GTSRetriangulator.cxx:211
 GTSRetriangulator.cxx:212
 GTSRetriangulator.cxx:213
 GTSRetriangulator.cxx:214
 GTSRetriangulator.cxx:215
 GTSRetriangulator.cxx:216
 GTSRetriangulator.cxx:217
 GTSRetriangulator.cxx:218
 GTSRetriangulator.cxx:219
 GTSRetriangulator.cxx:220
 GTSRetriangulator.cxx:221
 GTSRetriangulator.cxx:222
 GTSRetriangulator.cxx:223
 GTSRetriangulator.cxx:224
 GTSRetriangulator.cxx:225
 GTSRetriangulator.cxx:226
 GTSRetriangulator.cxx:227
 GTSRetriangulator.cxx:228
 GTSRetriangulator.cxx:229
 GTSRetriangulator.cxx:230
 GTSRetriangulator.cxx:231
 GTSRetriangulator.cxx:232
 GTSRetriangulator.cxx:233
 GTSRetriangulator.cxx:234
 GTSRetriangulator.cxx:235
 GTSRetriangulator.cxx:236
 GTSRetriangulator.cxx:237
 GTSRetriangulator.cxx:238
 GTSRetriangulator.cxx:239
 GTSRetriangulator.cxx:240
 GTSRetriangulator.cxx:241
 GTSRetriangulator.cxx:242
 GTSRetriangulator.cxx:243
 GTSRetriangulator.cxx:244
 GTSRetriangulator.cxx:245
 GTSRetriangulator.cxx:246
 GTSRetriangulator.cxx:247
 GTSRetriangulator.cxx:248
 GTSRetriangulator.cxx:249
 GTSRetriangulator.cxx:250
 GTSRetriangulator.cxx:251
 GTSRetriangulator.cxx:252
 GTSRetriangulator.cxx:253
 GTSRetriangulator.cxx:254
 GTSRetriangulator.cxx:255
 GTSRetriangulator.cxx:256
 GTSRetriangulator.cxx:257
 GTSRetriangulator.cxx:258
 GTSRetriangulator.cxx:259
 GTSRetriangulator.cxx:260
 GTSRetriangulator.cxx:261
 GTSRetriangulator.cxx:262
 GTSRetriangulator.cxx:263
 GTSRetriangulator.cxx:264
 GTSRetriangulator.cxx:265
 GTSRetriangulator.cxx:266
 GTSRetriangulator.cxx:267
 GTSRetriangulator.cxx:268
 GTSRetriangulator.cxx:269
 GTSRetriangulator.cxx:270
 GTSRetriangulator.cxx:271
 GTSRetriangulator.cxx:272
 GTSRetriangulator.cxx:273
 GTSRetriangulator.cxx:274
 GTSRetriangulator.cxx:275
 GTSRetriangulator.cxx:276
 GTSRetriangulator.cxx:277
 GTSRetriangulator.cxx:278
 GTSRetriangulator.cxx:279
 GTSRetriangulator.cxx:280
 GTSRetriangulator.cxx:281
 GTSRetriangulator.cxx:282
 GTSRetriangulator.cxx:283
 GTSRetriangulator.cxx:284
 GTSRetriangulator.cxx:285
 GTSRetriangulator.cxx:286
 GTSRetriangulator.cxx:287
 GTSRetriangulator.cxx:288
 GTSRetriangulator.cxx:289
 GTSRetriangulator.cxx:290
 GTSRetriangulator.cxx:291
 GTSRetriangulator.cxx:292
 GTSRetriangulator.cxx:293
 GTSRetriangulator.cxx:294
 GTSRetriangulator.cxx:295
 GTSRetriangulator.cxx:296
 GTSRetriangulator.cxx:297
 GTSRetriangulator.cxx:298
 GTSRetriangulator.cxx:299
 GTSRetriangulator.cxx:300
 GTSRetriangulator.cxx:301
 GTSRetriangulator.cxx:302
 GTSRetriangulator.cxx:303
 GTSRetriangulator.cxx:304
 GTSRetriangulator.cxx:305
 GTSRetriangulator.cxx:306
 GTSRetriangulator.cxx:307
 GTSRetriangulator.cxx:308
 GTSRetriangulator.cxx:309
 GTSRetriangulator.cxx:310
 GTSRetriangulator.cxx:311
 GTSRetriangulator.cxx:312
 GTSRetriangulator.cxx:313
 GTSRetriangulator.cxx:314
 GTSRetriangulator.cxx:315
 GTSRetriangulator.cxx:316
 GTSRetriangulator.cxx:317
 GTSRetriangulator.cxx:318
 GTSRetriangulator.cxx:319
 GTSRetriangulator.cxx:320
 GTSRetriangulator.cxx:321
 GTSRetriangulator.cxx:322
 GTSRetriangulator.cxx:323
 GTSRetriangulator.cxx:324
 GTSRetriangulator.cxx:325
 GTSRetriangulator.cxx:326
 GTSRetriangulator.cxx:327
 GTSRetriangulator.cxx:328
 GTSRetriangulator.cxx:329
 GTSRetriangulator.cxx:330
 GTSRetriangulator.cxx:331
 GTSRetriangulator.cxx:332
 GTSRetriangulator.cxx:333
 GTSRetriangulator.cxx:334
 GTSRetriangulator.cxx:335
 GTSRetriangulator.cxx:336
 GTSRetriangulator.cxx:337
 GTSRetriangulator.cxx:338
 GTSRetriangulator.cxx:339