Loading...
Searching...
No Matches
geompack.C
Go to the documentation of this file.
1# include <cstdlib>
2# include <iostream>
3# include <iomanip>
4# include <fstream>
5# include <cmath>
6# include <ctime>
7# include <cstring>
8
9#if defined(__APPLE__) && defined(__clang__)
10#pragma clang fp exceptions(ignore)
11#endif
12
13using namespace std;
14
15# include "geompack.H"
16
17//******************************************************************************
18
19double d_epsilon ( void )
20
21//******************************************************************************
22//
23// Purpose:
24//
25// D_EPSILON returns the round off unit for double precision arithmetic.
26//
27// Discussion:
28//
29// D_EPSILON is a number R which is a power of 2 with the property that,
30// to the precision of the computer's arithmetic,
31// 1 < 1 + R
32// but
33// 1 = ( 1 + R / 2 )
34//
35// Modified:
36//
37// 06 May 2003
38//
39// Author:
40//
41// John Burkardt
42//
43// Parameters:
44//
45// Output, double D_EPSILON, the floating point round-off unit.
46//
47{
48 double r = 1.0;
49
50 while (1.0 < 1.0 + r)
51 {
52 r = r/2.0;
53 }
54
55 return 2.0*r;
56}
57
58
59//*********************************************************************
60
61double d_max ( double x, double y )
62
63//*********************************************************************
64//
65// Purpose:
66//
67// D_MAX returns the maximum of two real values.
68//
69// Modified:
70//
71// 10 January 2002
72//
73// Author:
74//
75// John Burkardt
76//
77// Parameters:
78//
79// Input, double X, Y, the quantities to compare.
80//
81// Output, double D_MAX, the maximum of X and Y.
82//
83{
84 if ( y < x )
85 {
86 return x;
87 }
88 else
89 {
90 return y;
91 }
92}
93//*********************************************************************
94
95double d_min ( double x, double y )
96
97//*********************************************************************
98//
99// Purpose:
100//
101// D_MIN returns the minimum of two real values.
102//
103// Modified:
104//
105// 09 May 2003
106//
107// Author:
108//
109// John Burkardt
110//
111// Parameters:
112//
113// Input, double X, Y, the quantities to compare.
114//
115// Output, double D_MIN, the minimum of X and Y.
116//
117{
118 if ( y < x )
119 {
120 return y;
121 }
122 else
123 {
124 return x;
125 }
126}
127//******************************************************************************
128
129void d2vec_part_quick_a ( int n, double a[], int *l, int *r )
130
131//******************************************************************************
132//
133// Purpose:
134//
135// D2VEC_PART_QUICK_A reorders an R2 vector as part of a quick sort.
136//
137// Discussion:
138//
139// The routine reorders the entries of A. Using A(1:2,1) as a
140// key, all entries of A that are less than or equal to the key will
141// precede the key, which precedes all entries that are greater than the key.
142//
143// Example:
144//
145// Input:
146//
147// N = 8
148//
149// A = ( (2,4), (8,8), (6,2), (0,2), (10,6), (10,0), (0,6), (4,8) )
150//
151// Output:
152//
153// L = 2, R = 4
154//
155// A = ( (0,2), (0,6), (2,4), (8,8), (6,2), (10,6), (10,0), (4,8) )
156// ----------- ----------------------------------
157// LEFT KEY RIGHT
158//
159// Modified:
160//
161// 01 September 2003
162//
163// Author:
164//
165// John Burkardt
166//
167// Parameters:
168//
169// Input, int N, the number of entries of A.
170//
171// Input/output, double A[N*2]. On input, the array to be checked.
172// On output, A has been reordered as described above.
173//
174// Output, int *L, *R, the indices of A that define the three segments.
175// Let KEY = the input value of A(1:2,1). Then
176// I <= L A(1:2,I) < KEY;
177// L < I < R A(1:2,I) = KEY;
178// R <= I A(1:2,I) > KEY.
179//
180{
181 int i;
182 int j;
183 double key[2];
184 int ll;
185 int m;
186 int rr;
187
188 if ( n < 1 )
189 {
190 cout << "\n";
191 cout << "D2VEC_PART_QUICK_A - Fatal error!\n";
192 cout << " N < 1.\n";
193 exit ( 1 );
194 }
195
196 if ( n == 1 )
197 {
198 *l = 0;
199 *r = 2;
200 return;
201 }
202
203 key[0] = a[2*0+0];
204 key[1] = a[2*0+1];
205 m = 1;
206//
207// The elements of unknown size have indices between L+1 and R-1.
208//
209 ll = 1;
210 rr = n + 1;
211
212 for ( i = 2; i <= n; i++ )
213 {
214 if ( dvec_gt ( 2, a+2*ll, key ) )
215 {
216 rr = rr - 1;
217 dvec_swap ( 2, a+2*(rr-1), a+2*ll );
218 }
219 else if ( dvec_eq ( 2, a+2*ll, key ) )
220 {
221 m = m + 1;
222 dvec_swap ( 2, a+2*(m-1), a+2*ll );
223 ll = ll + 1;
224 }
225 else if ( dvec_lt ( 2, a+2*ll, key ) )
226 {
227 ll = ll + 1;
228 }
229
230 }
231//
232// Now shift small elements to the left, and KEY elements to center.
233//
234 for ( i = 0; i < ll - m; i++ )
235 {
236 for ( j = 0; j < 2; j++ )
237 {
238 a[2*i+j] = a[2*(i+m)+j];
239 }
240 }
241
242 ll = ll - m;
243
244 for ( i = ll; i < ll+m; i++ )
245 {
246 for ( j = 0; j < 2; j++ )
247 {
248 a[2*i+j] = key[j];
249 }
250 }
251
252 *l = ll;
253 *r = rr;
254
255 return;
256}
257//******************************************************************************
258
259void d2vec_permute ( int n, double a[], int p[] )
260
261//******************************************************************************
262//
263// Purpose:
264//
265// D2VEC_PERMUTE permutes an R2 vector in place.
266//
267// Discussion:
268//
269// This routine permutes an array of real "objects", but the same
270// logic can be used to permute an array of objects of any arithmetic
271// type, or an array of objects of any complexity. The only temporary
272// storage required is enough to store a single object. The number
273// of data movements made is N + the number of cycles of order 2 or more,
274// which is never more than N + N/2.
275//
276// Example:
277//
278// Input:
279//
280// N = 5
281// P = ( 2, 4, 5, 1, 3 )
282// A = ( 1.0, 2.0, 3.0, 4.0, 5.0 )
283// (11.0, 22.0, 33.0, 44.0, 55.0 )
284//
285// Output:
286//
287// A = ( 2.0, 4.0, 5.0, 1.0, 3.0 )
288// ( 22.0, 44.0, 55.0, 11.0, 33.0 ).
289//
290// Modified:
291//
292// 19 February 2004
293//
294// Author:
295//
296// John Burkardt
297//
298// Parameters:
299//
300// Input, int N, the number of objects.
301//
302// Input/output, double A[2*N], the array to be permuted.
303//
304// Input, int P[N], the permutation. P(I) = J means
305// that the I-th element of the output array should be the J-th
306// element of the input array. P must be a legal permutation
307// of the integers from 1 to N, otherwise the algorithm will
308// fail catastrophically.
309//
310{
311 double a_temp[2];
312 int i;
313 int iget;
314 int iput;
315 int istart;
316
317 if ( !perm_check ( n, p ) )
318 {
319 cout << "\n";
320 cout << "D2VEC_PERMUTE - Fatal error!\n";
321 cout << " The input array does not represent\n";
322 cout << " a proper permutation.\n";
323 exit ( 1 );
324 }
325//
326// Search for the next element of the permutation that has not been used.
327//
328 for ( istart = 1; istart <= n; istart++ )
329 {
330 if ( p[istart-1] < 0 )
331 {
332 continue;
333 }
334 else if ( p[istart-1] == istart )
335 {
336 p[istart-1] = -p[istart-1];
337 continue;
338 }
339 else
340 {
341 a_temp[0] = a[0+(istart-1)*2];
342 a_temp[1] = a[1+(istart-1)*2];
343 iget = istart;
344//
345// Copy the new value into the vacated entry.
346//
347 for ( ; ; )
348 {
349 iput = iget;
350 iget = p[iget-1];
351
352 p[iput-1] = -p[iput-1];
353
354 if ( iget < 1 || n < iget )
355 {
356 cout << "\n";
357 cout << "D2VEC_PERMUTE - Fatal error!\n";
358 exit ( 1 );
359 }
360
361 if ( iget == istart )
362 {
363 a[0+(iput-1)*2] = a_temp[0];
364 a[1+(iput-1)*2] = a_temp[1];
365 break;
366 }
367 a[0+(iput-1)*2] = a[0+(iget-1)*2];
368 a[1+(iput-1)*2] = a[1+(iget-1)*2];
369 }
370 }
371 }
372//
373// Restore the signs of the entries.
374//
375 for ( i = 0; i < n; i++ )
376 {
377 p[i] = -p[i];
378 }
379
380 return;
381}
382//******************************************************************************
383
384int *d2vec_sort_heap_index_a ( int n, double a[] )
385
386//******************************************************************************
387//
388// Purpose:
389//
390// D2VEC_SORT_HEAP_INDEX_A does an indexed heap ascending sort of
391// an R2 vector.
392//
393// Discussion:
394//
395// The sorting is not actually carried out. Rather an index array is
396// created which defines the sorting. This array may be used to sort
397// or index the array, or to sort or index related arrays keyed on the
398// original array.
399//
400// Once the index array is computed, the sorting can be carried out
401// "implicitly:
402//
403// A(1:2,INDX(I)), I = 1 to N is sorted,
404//
405// or explicitly, by the call
406//
407// call D2VEC_PERMUTE ( N, A, INDX )
408//
409// after which A(1:2,I), I = 1 to N is sorted.
410//
411// Modified:
412//
413// 13 January 2004
414//
415// Author:
416//
417// John Burkardt
418//
419// Parameters:
420//
421// Input, int N, the number of entries in the array.
422//
423// Input, double A[2*N], an array to be index-sorted.
424//
425// Output, int D2VEC_SORT_HEAP_INDEX_A[N], the sort index. The
426// I-th element of the sorted array is A(0:1,D2VEC_SORT_HEAP_INDEX_A(I-1)).
427//
428{
429 double aval[2];
430 int i;
431 int *indx;
432 int indxt;
433 int ir;
434 int j;
435 int l;
436
437 if ( n < 1 )
438 {
439 return NULL;
440 }
441
442 if ( n == 1 )
443 {
444 indx = new int[1];
445 indx[0] = 1;
446 return indx;
447 }
448
449 indx = ivec_indicator ( n );
450
451 l = n / 2 + 1;
452 ir = n;
453
454 for ( ; ; )
455 {
456 if ( 1 < l )
457 {
458 l = l - 1;
459 indxt = indx[l-1];
460 aval[0] = a[0+(indxt-1)*2];
461 aval[1] = a[1+(indxt-1)*2];
462 }
463 else
464 {
465 indxt = indx[ir-1];
466 aval[0] = a[0+(indxt-1)*2];
467 aval[1] = a[1+(indxt-1)*2];
468 indx[ir-1] = indx[0];
469 ir = ir - 1;
470
471 if ( ir == 1 )
472 {
473 indx[0] = indxt;
474 break;
475 }
476
477 }
478
479 i = l;
480 j = l + l;
481
482 while ( j <= ir )
483 {
484 if ( j < ir )
485 {
486 if ( a[0+(indx[j-1]-1)*2] < a[0+(indx[j]-1)*2] ||
487 ( a[0+(indx[j-1]-1)*2] == a[0+(indx[j]-1)*2] &&
488 a[1+(indx[j-1]-1)*2] < a[1+(indx[j]-1)*2] ) )
489 {
490 j = j + 1;
491 }
492 }
493
494 if ( aval[0] < a[0+(indx[j-1]-1)*2] ||
495 ( aval[0] == a[0+(indx[j-1]-1)*2] &&
496 aval[1] < a[1+(indx[j-1]-1)*2] ) )
497 {
498 indx[i-1] = indx[j-1];
499 i = j;
500 j = j + j;
501 }
502 else
503 {
504 j = ir + 1;
505 }
506 }
507 indx[i-1] = indxt;
508 }
509
510 return indx;
511}
512//*****************************************************************************
513
514void d2vec_sort_quick_a ( int n, double a[] )
515
516//*****************************************************************************
517//
518// Purpose:
519//
520// D2VEC_SORT_QUICK_A ascending sorts an R2 vector using quick sort.
521//
522// Discussion:
523//
524// The data structure is a set of N pairs of real numbers.
525// These values are stored in a one dimensional array, by pairs.
526//
527// Modified:
528//
529// 01 September 2003
530//
531// Author:
532//
533// John Burkardt
534//
535// Parameters:
536//
537// Input, int N, the number of entries in the array.
538//
539// Input/output, double A[N*2].
540// On input, the array to be sorted.
541// On output, the array has been sorted.
542//
543{
544# define LEVEL_MAX 25
545
546 int base;
547 int l_segment;
548 int level;
549 int n_segment;
550 int rsave[LEVEL_MAX];
551 int r_segment;
552
553 if ( n < 1 )
554 {
555 cout << "\n";
556 cout << "D2VEC_SORT_QUICK_A - Fatal error!\n";
557 cout << " N < 1.\n";
558 exit ( 1 );
559 }
560
561 if ( n == 1 )
562 {
563 return;
564 }
565
566 level = 1;
567 rsave[level-1] = n + 1;
568 base = 1;
569 n_segment = n;
570
571 while ( 0 < n_segment )
572 {
573//
574// Partition the segment.
575//
576 d2vec_part_quick_a ( n_segment, a+2*(base-1)+0, &l_segment, &r_segment );
577//
578// If the left segment has more than one element, we need to partition it.
579//
580 if ( 1 < l_segment )
581 {
582 if ( LEVEL_MAX < level )
583 {
584 cout << "\n";
585 cout << "D2VEC_SORT_QUICK_A - Fatal error!\n";
586 cout << " Exceeding recursion maximum of " << LEVEL_MAX << "\n";
587 exit ( 1 );
588 }
589
590 level = level + 1;
591 n_segment = l_segment;
592 rsave[level-1] = r_segment + base - 1;
593 }
594//
595// The left segment and the middle segment are sorted.
596// Must the right segment be partitioned?
597//
598 else if ( r_segment < n_segment )
599 {
600 n_segment = n_segment + 1 - r_segment;
601 base = base + r_segment - 1;
602 }
603//
604// Otherwise, we back up a level if there is an earlier one.
605//
606 else
607 {
608 for ( ; ; )
609 {
610 if ( level <= 1 )
611 {
612 n_segment = 0;
613 break;
614 }
615
616 base = rsave[level-1];
617 n_segment = rsave[level-2] - rsave[level-1];
618 level = level - 1;
619
620 if ( 0 < n_segment )
621 {
622 break;
623 }
624 }
625 }
626 }
627 return;
628# undef LEVEL_MAX
629}
630//******************************************************************************
631
632int diaedg ( double x0, double y0, double x1, double y1, double x2, double y2,
633 double x3, double y3 )
634
635//******************************************************************************
636//
637// Purpose:
638//
639// DIAEDG chooses a diagonal edge.
640//
641// Discussion:
642//
643// The routine determines whether 0--2 or 1--3 is the diagonal edge
644// that should be chosen, based on the circumcircle criterion, where
645// (X0,Y0), (X1,Y1), (X2,Y2), (X3,Y3) are the vertices of a simple
646// quadrilateral in counterclockwise order.
647//
648// Modified:
649//
650// 28 August 2003
651//
652// Author:
653//
654// Barry Joe,
655// Department of Computing Science,
656// University of Alberta,
657// Edmonton, Alberta, Canada T6G 2H1
658//
659// Reference:
660//
661// Barry Joe,
662// GEOMPACK - a software package for the generation of meshes
663// using geometric algorithms,
664// Advances in Engineering Software,
665// Volume 13, pages 325-331, 1991.
666//
667// Parameters:
668//
669// Input, double X0, Y0, X1, Y1, X2, Y2, X3, Y3, the coordinates of the
670// vertices of a quadrilateral, given in counter clockwise order.
671//
672// Output, int DIAEDG, chooses a diagonal:
673// +1, if diagonal edge 02 is chosen;
674// -1, if diagonal edge 13 is chosen;
675// 0, if the four vertices are cocircular.
676//
677{
678 double ca;
679 double cb;
680 double dx10;
681 double dx12;
682 double dx30;
683 double dx32;
684 double dy10;
685 double dy12;
686 double dy30;
687 double dy32;
688 double s;
689 double tol;
690 double tola;
691 double tolb;
692 int value;
693
694 tol = 100.0 * d_epsilon ( );
695
696 dx10 = x1 - x0;
697 dy10 = y1 - y0;
698 dx12 = x1 - x2;
699 dy12 = y1 - y2;
700 dx30 = x3 - x0;
701 dy30 = y3 - y0;
702 dx32 = x3 - x2;
703 dy32 = y3 - y2;
704
705 tola = tol * d_max ( fabs ( dx10 ),
706 d_max ( fabs ( dy10 ),
707 d_max ( fabs ( dx30 ), fabs ( dy30 ) ) ) );
708
709 tolb = tol * d_max ( fabs ( dx12 ),
710 d_max ( fabs ( dy12 ),
711 d_max ( fabs ( dx32 ), fabs ( dy32 ) ) ) );
712
713 ca = dx10 * dx30 + dy10 * dy30;
714 cb = dx12 * dx32 + dy12 * dy32;
715
716 if ( tola < ca && tolb < cb )
717 {
718 value = -1;
719 }
720 else if ( ca < -tola && cb < -tolb )
721 {
722 value = 1;
723 }
724 else
725 {
726 tola = d_max ( tola, tolb );
727 s = ( dx10 * dy30 - dx30 * dy10 ) * cb
728 + ( dx32 * dy12 - dx12 * dy32 ) * ca;
729
730 if ( tola < s )
731 {
732 value = -1;
733 }
734 else if ( s < -tola )
735 {
736 value = 1;
737 }
738 else
739 {
740 value = 0;
741 }
742
743 }
744
745 return value;
746}
747//******************************************************************************
748
749void dmat_transpose_print ( int m, int n, double a[], const char *title )
750
751//******************************************************************************
752//
753// Purpose:
754//
755// DMAT_TRANSPOSE_PRINT prints a real matrix, transposed.
756//
757// Modified:
758//
759// 11 August 2004
760//
761// Author:
762//
763// John Burkardt
764//
765// Parameters:
766//
767// Input, int M, N, the number of rows and columns.
768//
769// Input, double A[M*N], an M by N matrix to be printed.
770//
771// Input, const char *TITLE, an optional title.
772//
773{
774 dmat_transpose_print_some ( m, n, a, 1, 1, m, n, title );
775
776 return;
777}
778//******************************************************************************
779
780void dmat_transpose_print_some ( int m, int n, double a[], int ilo, int jlo,
781 int ihi, int jhi, const char *title )
782
783//******************************************************************************
784//
785// Purpose:
786//
787// DMAT_TRANSPOSE_PRINT_SOME prints some of a real matrix, transposed.
788//
789// Modified:
790//
791// 11 August 2004
792//
793// Author:
794//
795// John Burkardt
796//
797// Parameters:
798//
799// Input, int M, N, the number of rows and columns.
800//
801// Input, double A[M*N], an M by N matrix to be printed.
802//
803// Input, int ILO, JLO, the first row and column to print.
804//
805// Input, int IHI, JHI, the last row and column to print.
806//
807// Input, const char *TITLE, an optional title.
808//
809{
810# define INCX 5
811
812 int i;
813 int i2;
814 int i2hi;
815 int i2lo;
816 int inc;
817 int j;
818 int j2hi;
819 int j2lo;
820
821 if ( 0 < s_len_trim ( title ) )
822 {
823 cout << "\n";
824 cout << title << "\n";
825 }
826
827 for ( i2lo = i_max ( ilo, 1 ); i2lo <= i_min ( ihi, m ); i2lo = i2lo + INCX )
828 {
829 i2hi = i2lo + INCX - 1;
830 i2hi = i_min ( i2hi, m );
831 i2hi = i_min ( i2hi, ihi );
832
833 inc = i2hi + 1 - i2lo;
834
835 cout << "\n";
836 cout << " Row: ";
837 for ( i = i2lo; i <= i2hi; i++ )
838 {
839 cout << setw(7) << i << " ";
840 }
841 cout << "\n";
842 cout << " Col\n";
843 cout << "\n";
844
845 j2lo = i_max ( jlo, 1 );
846 j2hi = i_min ( jhi, n );
847
848 for ( j = j2lo; j <= j2hi; j++ )
849 {
850 cout << setw(5) << j << " ";
851 for ( i2 = 1; i2 <= inc; i2++ )
852 {
853 i = i2lo - 1 + i2;
854 cout << setw(14) << a[(i-1)+(j-1)*m];
855 }
856 cout << "\n";
857 }
858 }
859 cout << "\n";
860
861 return;
862# undef INCX
863}
864//******************************************************************************
865
866void dmat_uniform ( int m, int n, double b, double c, int *seed, double r[] )
867
868//******************************************************************************
869//
870// Purpose:
871//
872// DMAT_UNIFORM fills a double precision array with scaled
873// pseudorandom values.
874//
875// Discussion:
876//
877// This routine implements the recursion
878//
879// seed = 16807 * seed mod ( 2**31 - 1 )
880// unif = seed / ( 2**31 - 1 )
881//
882// The integer arithmetic never requires more than 32 bits,
883// including a sign bit.
884//
885// Modified:
886//
887// 30 January 2005
888//
889// Author:
890//
891// John Burkardt
892//
893// Reference:
894//
895// Paul Bratley, Bennett Fox, Linus Schrage,
896// A Guide to Simulation,
897// Springer Verlag, pages 201-202, 1983.
898//
899// Bennett Fox,
900// Algorithm 647:
901// Implementation and Relative Efficiency of Quasirandom
902// Sequence Generators,
903// ACM Transactions on Mathematical Software,
904// Volume 12, Number 4, pages 362-376, 1986.
905//
906// Peter Lewis, Allen Goodman, James Miller,
907// A Pseudo-Random Number Generator for the System/360,
908// IBM Systems Journal,
909// Volume 8, pages 136-143, 1969.
910//
911// Parameters:
912//
913// Input, int M, N, the number of rows and columns.
914//
915// Input, double B, C, the limits of the pseudorandom values.
916//
917// Input/output, int *SEED, the "seed" value. Normally, this
918// value should not be 0, otherwise the output value of SEED
919// will still be 0, and D_UNIFORM will be 0. On output, SEED has
920// been updated.
921//
922// Output, double DMAT_UNIFORM[M*N], a matrix of pseudorandom values.
923//
924{
925 int i;
926 int j;
927 int k;
928
929 for ( j = 0; j < n; j++ )
930 {
931 for ( i = 0; i < m; i++ )
932 {
933 k = *seed / 127773;
934
935 *seed = 16807 * ( *seed - k * 127773 ) - k * 2836;
936
937 if ( *seed < 0 )
938 {
939 *seed = *seed + 2147483647;
940 }
941//
942// Although SEED can be represented exactly as a 32 bit integer,
943// it generally cannot be represented exactly as a 32 bit real number!
944//
945 r[i+j*m] = b + ( c - b ) * double( *seed ) * 4.656612875E-10;
946 }
947 }
948
949 return;
950}
951//******************************************************************************
952
953int dtris2 ( int point_num, double point_xy[], int *tri_num,
954 int tri_vert[], int tri_nabe[] )
955
956//******************************************************************************
957//
958// Purpose:
959//
960// DTRIS2 constructs a Delaunay triangulation of 2D vertices.
961//
962// Discussion:
963//
964// The routine constructs the Delaunay triangulation of a set of 2D vertices
965// using an incremental approach and diagonal edge swaps. Vertices are
966// first sorted in lexicographically increasing (X,Y) order, and
967// then are inserted one at a time from outside the convex hull.
968//
969// Modified:
970//
971// 15 January 2004
972//
973// Author:
974//
975// Barry Joe,
976// Department of Computing Science,
977// University of Alberta,
978// Edmonton, Alberta, Canada T6G 2H1
979//
980// Reference:
981//
982// Barry Joe,
983// GEOMPACK - a software package for the generation of meshes
984// using geometric algorithms,
985// Advances in Engineering Software,
986// Volume 13, pages 325-331, 1991.
987//
988// Parameters:
989//
990// Input, int POINT_NUM, the number of vertices.
991//
992// Input/output, double POINT_XY[POINT_NUM*2], the coordinates of
993// the vertices. On output, the vertices have been sorted into
994// dictionary order.
995//
996// Output, int *TRI_NUM, the number of triangles in the triangulation;
997// TRI_NUM is equal to 2*POINT_NUM - NB - 2, where NB is the number
998// of boundary vertices.
999//
1000// Output, int TRI_VERT[TRI_NUM*3], the nodes that make up each triangle.
1001// The elements are indices of POINT_XY. The vertices of the triangles are
1002// in counter clockwise order.
1003//
1004// Output, int TRI_NABE[TRI_NUM*3], the triangle neighbor list.
1005// Positive elements are indices of TIL; negative elements are used for links
1006// of a counter clockwise linked list of boundary edges; LINK = -(3*I + J-1)
1007// where I, J = triangle, edge index; TRI_NABE[I,J] refers to
1008// the neighbor along edge from vertex J to J+1 (mod 3).
1009//
1010// Output, int DTRIS2, is 0 for no error.
1011{
1012 double cmax;
1013 int e;
1014 int error;
1015 int i;
1016 int *indx;
1017 int j;
1018 int k;
1019 int l;
1020 int ledg;
1021 int lr;
1022 int ltri;
1023 int m;
1024 int m1;
1025 int m2;
1026 int n;
1027 int redg;
1028 int rtri;
1029 int *stack;
1030 int t;
1031 double tol;
1032 int top;
1033
1034 stack = new int[point_num];
1035
1036 tol = 100.0 * d_epsilon ( );
1037//
1038// Sort the vertices by increasing (x,y).
1039//
1040 indx = d2vec_sort_heap_index_a ( point_num, point_xy );
1041
1042 d2vec_permute ( point_num, point_xy, indx );
1043//
1044// Make sure that the data points are "reasonably" distinct.
1045//
1046 m1 = 1;
1047
1048 for ( i = 2; i <= point_num; i++ )
1049 {
1050 m = m1;
1051 m1 = i;
1052
1053 k = -1;
1054
1055 for ( j = 0; j <= 1; j++ )
1056 {
1057 cmax = d_max ( fabs ( point_xy[2*(m-1)+j] ),
1058 fabs ( point_xy[2*(m1-1)+j] ) );
1059
1060 if ( tol * ( cmax + 1.0 )
1061 < fabs ( point_xy[2*(m-1)+j] - point_xy[2*(m1-1)+j] ) )
1062 {
1063 k = j;
1064 break;
1065 }
1066
1067 }
1068
1069 if ( k == -1 )
1070 {
1071 cout << "\n";
1072 cout << "DTRIS2 - Fatal error!\n";
1073 cout << " Fails for point number I = " << i << "\n";
1074 cout << " M = " << m << "\n";
1075 cout << " M1 = " << m1 << "\n";
1076 cout << " X,Y(M) = " << point_xy[2*(m-1)+0] << " "
1077 << point_xy[2*(m-1)+1] << "\n";
1078 cout << " X,Y(M1) = " << point_xy[2*(m1-1)+0] << " "
1079 << point_xy[2*(m1-1)+1] << "\n";
1080 delete [] stack;
1081 return 224;
1082 }
1083
1084 }
1085//
1086// Starting from points M1 and M2, search for a third point M that
1087// makes a "healthy" triangle (M1,M2,M)
1088//
1089 m1 = 1;
1090 m2 = 2;
1091 j = 3;
1092
1093 for ( ; ; )
1094 {
1095 if ( point_num < j )
1096 {
1097 cout << "\n";
1098 cout << "DTRIS2 - Fatal error!\n";
1099 delete [] stack;
1100 return 225;
1101 }
1102
1103 m = j;
1104
1105 lr = lrline ( point_xy[2*(m-1)+0], point_xy[2*(m-1)+1],
1106 point_xy[2*(m1-1)+0], point_xy[2*(m1-1)+1],
1107 point_xy[2*(m2-1)+0], point_xy[2*(m2-1)+1], 0.0 );
1108
1109 if ( lr != 0 )
1110 {
1111 break;
1112 }
1113
1114 j = j + 1;
1115
1116 }
1117//
1118// Set up the triangle information for (M1,M2,M), and for any other
1119// triangles you created because points were collinear with M1, M2.
1120//
1121 *tri_num = j - 2;
1122
1123 if ( lr == -1 )
1124 {
1125 tri_vert[3*0+0] = m1;
1126 tri_vert[3*0+1] = m2;
1127 tri_vert[3*0+2] = m;
1128 tri_nabe[3*0+2] = -3;
1129
1130 for ( i = 2; i <= *tri_num; i++ )
1131 {
1132 m1 = m2;
1133 m2 = i+1;
1134 tri_vert[3*(i-1)+0] = m1;
1135 tri_vert[3*(i-1)+1] = m2;
1136 tri_vert[3*(i-1)+2] = m;
1137 tri_nabe[3*(i-2)+0] = -3 * i;
1138 tri_nabe[3*(i-2)+1] = i;
1139 tri_nabe[3*(i-1)+2] = i - 1;
1140
1141 }
1142
1143 tri_nabe[3*(*tri_num-1)+0] = -3 * (*tri_num) - 1;
1144 tri_nabe[3*(*tri_num-1)+1] = -5;
1145 ledg = 2;
1146 ltri = *tri_num;
1147 }
1148 else
1149 {
1150 tri_vert[3*0+0] = m2;
1151 tri_vert[3*0+1] = m1;
1152 tri_vert[3*0+2] = m;
1153 tri_nabe[3*0+0] = -4;
1154
1155 for ( i = 2; i <= *tri_num; i++ )
1156 {
1157 m1 = m2;
1158 m2 = i+1;
1159 tri_vert[3*(i-1)+0] = m2;
1160 tri_vert[3*(i-1)+1] = m1;
1161 tri_vert[3*(i-1)+2] = m;
1162 tri_nabe[3*(i-2)+2] = i;
1163 tri_nabe[3*(i-1)+0] = -3 * i - 3;
1164 tri_nabe[3*(i-1)+1] = i - 1;
1165 }
1166
1167 tri_nabe[3*(*tri_num-1)+2] = -3 * (*tri_num);
1168 tri_nabe[3*0+1] = -3 * (*tri_num) - 2;
1169 ledg = 2;
1170 ltri = 1;
1171 }
1172//
1173// Insert the vertices one at a time from outside the convex hull,
1174// determine visible boundary edges, and apply diagonal edge swaps until
1175// Delaunay triangulation of vertices (so far) is obtained.
1176//
1177 top = 0;
1178
1179 for ( i = j+1; i <= point_num; i++ )
1180 {
1181 m = i;
1182 m1 = tri_vert[3*(ltri-1)+ledg-1];
1183
1184 if ( ledg <= 2 )
1185 {
1186 m2 = tri_vert[3*(ltri-1)+ledg];
1187 }
1188 else
1189 {
1190 m2 = tri_vert[3*(ltri-1)+0];
1191 }
1192
1193 lr = lrline ( point_xy[2*(m-1)+0], point_xy[2*(m-1)+1],
1194 point_xy[2*(m1-1)+0], point_xy[2*(m1-1)+1],
1195 point_xy[2*(m2-1)+0], point_xy[2*(m2-1)+1], 0.0 );
1196
1197 if ( 0 < lr )
1198 {
1199 rtri = ltri;
1200 redg = ledg;
1201 ltri = 0;
1202 }
1203 else
1204 {
1205 l = -tri_nabe[3*(ltri-1)+ledg-1];
1206 rtri = l / 3;
1207 redg = (l % 3) + 1;
1208 }
1209
1210 vbedg ( point_xy[2*(m-1)+0], point_xy[2*(m-1)+1], point_num,
1211 point_xy, *tri_num, tri_vert, tri_nabe, &ltri, &ledg, &rtri, &redg );
1212
1213 n = *tri_num + 1;
1214 l = -tri_nabe[3*(ltri-1)+ledg-1];
1215
1216 for ( ; ; )
1217 {
1218 t = l / 3;
1219 e = ( l % 3 ) + 1;
1220 l = -tri_nabe[3*(t-1)+e-1];
1221 m2 = tri_vert[3*(t-1)+e-1];
1222
1223 if ( e <= 2 )
1224 {
1225 m1 = tri_vert[3*(t-1)+e];
1226 }
1227 else
1228 {
1229 m1 = tri_vert[3*(t-1)+0];
1230 }
1231
1232 *tri_num = *tri_num + 1;
1233 tri_nabe[3*(t-1)+e-1] = *tri_num;
1234 tri_vert[3*(*tri_num-1)+0] = m1;
1235 tri_vert[3*(*tri_num-1)+1] = m2;
1236 tri_vert[3*(*tri_num-1)+2] = m;
1237 tri_nabe[3*(*tri_num-1)+0] = t;
1238 tri_nabe[3*(*tri_num-1)+1] = *tri_num - 1;
1239 tri_nabe[3*(*tri_num-1)+2] = *tri_num + 1;
1240 top = top + 1;
1241
1242 if ( point_num < top )
1243 {
1244 cout << "\n";
1245 cout << "DTRIS2 - Fatal error!\n";
1246 cout << " Stack overflow.\n";
1247 delete [] stack;
1248 return 8;
1249 }
1250
1251 stack[top-1] = *tri_num;
1252
1253 if ( t == rtri && e == redg )
1254 {
1255 break;
1256 }
1257
1258 }
1259
1260 tri_nabe[3*(ltri-1)+ledg-1] = -3 * n - 1;
1261 tri_nabe[3*(n-1)+1] = -3 * (*tri_num) - 2;
1262 tri_nabe[3*(*tri_num-1)+2] = -l;
1263 ltri = n;
1264 ledg = 2;
1265
1266 error = swapec ( m, &top, &ltri, &ledg, point_num, point_xy, *tri_num,
1267 tri_vert, tri_nabe, stack );
1268
1269 if ( error != 0 )
1270 {
1271 cout << "\n";
1272 cout << "DTRIS2 - Fatal error!\n";
1273 cout << " Error return from SWAPEC.\n";
1274 delete [] stack;
1275 return error;
1276 }
1277
1278 }
1279//
1280// Now account for the sorting that we did.
1281//
1282 for ( i = 0; i < 3; i++ )
1283 {
1284 for ( j = 0; j < *tri_num; j++ )
1285 {
1286 tri_vert[i+j*3] = indx [ tri_vert[i+j*3] - 1 ];
1287 }
1288 }
1289
1290 perm_inv ( point_num, indx );
1291
1292 d2vec_permute ( point_num, point_xy, indx );
1293
1294 delete [] indx;
1295 delete [] stack;
1296
1297 return 0;
1298}
1299//******************************************************************************
1300
1301bool dvec_eq ( int n, double a1[], double a2[] )
1302
1303//******************************************************************************
1304//
1305// Purpose:
1306//
1307// DVEC_EQ is true if every pair of entries in two vectors is equal.
1308//
1309// Modified:
1310//
1311// 28 August 2003
1312//
1313// Author:
1314//
1315// John Burkardt
1316//
1317// Parameters:
1318//
1319// Input, int N, the number of entries in the vectors.
1320//
1321// Input, double A1[N], A2[N], two vectors to compare.
1322//
1323// Output, bool DVEC_EQ.
1324// DVEC_EQ is TRUE if every pair of elements A1(I) and A2(I) are equal,
1325// and FALSE otherwise.
1326//
1327{
1328 int i;
1329
1330 for ( i = 0; i < n; i++ )
1331 {
1332 if ( a1[i] != a2[i] )
1333 {
1334 return false;
1335 }
1336 }
1337 return true;
1338
1339}
1340//******************************************************************************
1341
1342bool dvec_gt ( int n, double a1[], double a2[] )
1343
1344//******************************************************************************
1345//
1346// Purpose:
1347//
1348// DVEC_GT == ( A1 > A2 ) for real vectors.
1349//
1350// Discussion:
1351//
1352// The comparison is lexicographic.
1353//
1354// A1 > A2 <=> A1(1) > A2(1) or
1355// ( A1(1) == A2(1) and A1(2) > A2(2) ) or
1356// ...
1357// ( A1(1:N-1) == A2(1:N-1) and A1(N) > A2(N)
1358//
1359// Modified:
1360//
1361// 28 August 2003
1362//
1363// Author:
1364//
1365// John Burkardt
1366//
1367// Parameters:
1368//
1369// Input, int N, the dimension of the vectors.
1370//
1371// Input, double A1[N], A2[N], the vectors to be compared.
1372//
1373// Output, bool DVEC_GT, is TRUE if and only if A1 > A2.
1374//
1375{
1376 int i;
1377
1378 for ( i = 0; i < n; i++ )
1379 {
1380
1381 if ( a2[i] < a1[i] )
1382 {
1383 return true;
1384 }
1385 else if ( a1[i] < a2[i] )
1386 {
1387 return false;
1388 }
1389
1390 }
1391
1392 return false;
1393}
1394//******************************************************************************
1395
1396bool dvec_lt ( int n, double a1[], double a2[] )
1397
1398//******************************************************************************
1399//
1400// Purpose:
1401//
1402// DVEC_LT == ( A1 < A2 ) for real vectors.
1403//
1404// Discussion:
1405//
1406// The comparison is lexicographic.
1407//
1408// A1 < A2 <=> A1(1) < A2(1) or
1409// ( A1(1) == A2(1) and A1(2) < A2(2) ) or
1410// ...
1411// ( A1(1:N-1) == A2(1:N-1) and A1(N) < A2(N)
1412//
1413// Modified:
1414//
1415// 28 August 2003
1416//
1417// Author:
1418//
1419// John Burkardt
1420//
1421// Parameters:
1422//
1423// Input, int N, the dimension of the vectors.
1424//
1425// Input, double A1[N], A2[N], the vectors to be compared.
1426//
1427// Output, bool DVEC_LT, is TRUE if and only if A1 < A2.
1428//
1429{
1430 int i;
1431
1432 for ( i = 0; i < n; i++ )
1433 {
1434 if ( a1[i] < a2[i] )
1435 {
1436 return true;
1437 }
1438 else if ( a2[i] < a1[i] )
1439 {
1440 return false;
1441 }
1442
1443 }
1444
1445 return false;
1446}
1447//********************************************************************
1448
1449void dvec_print ( int n, double a[], const char *title )
1450
1451//********************************************************************
1452//
1453// Purpose:
1454//
1455// DVEC_PRINT prints a double precision vector.
1456//
1457// Modified:
1458//
1459// 16 August 2004
1460//
1461// Author:
1462//
1463// John Burkardt
1464//
1465// Parameters:
1466//
1467// Input, int N, the number of components of the vector.
1468//
1469// Input, double A[N], the vector to be printed.
1470//
1471// Input, const char *TITLE, a title to be printed first.
1472// TITLE may be blank.
1473//
1474{
1475 int i;
1476
1477 if ( 0 < s_len_trim ( title ) )
1478 {
1479 cout << "\n";
1480 cout << title << "\n";
1481 }
1482
1483 cout << "\n";
1484 for ( i = 0; i <= n-1; i++ )
1485 {
1486 cout << setw(6) << i + 1 << " "
1487 << setw(14) << a[i] << "\n";
1488 }
1489
1490 return;
1491}
1492//******************************************************************************
1493
1494void dvec_swap ( int n, double a1[], double a2[] )
1495
1496//******************************************************************************
1497//
1498// Purpose:
1499//
1500// DVEC_SWAP swaps the entries of two real vectors.
1501//
1502// Modified:
1503//
1504// 28 August 2003
1505//
1506// Author:
1507//
1508// John Burkardt
1509//
1510// Parameters:
1511//
1512// Input, int N, the number of entries in the arrays.
1513//
1514// Input/output, double A1[N], A2[N], the vectors to swap.
1515//
1516{
1517 int i;
1518 double temp;
1519
1520 for ( i = 0; i < n; i++ )
1521 {
1522 temp = a1[i];
1523 a1[i] = a2[i];
1524 a2[i] = temp;
1525 }
1526
1527 return;
1528}
1529//****************************************************************************
1530
1531int i_max ( int i1, int i2 )
1532
1533//****************************************************************************
1534//
1535// Purpose:
1536//
1537// I_MAX returns the maximum of two integers.
1538//
1539// Modified:
1540//
1541// 13 October 1998
1542//
1543// Author:
1544//
1545// John Burkardt
1546//
1547// Parameters:
1548//
1549// Input, int I1, I2, are two integers to be compared.
1550//
1551// Output, int I_MAX, the larger of I1 and I2.
1552//
1553{
1554 if ( i2 < i1 )
1555 {
1556 return i1;
1557 }
1558 else
1559 {
1560 return i2;
1561 }
1562
1563}
1564//****************************************************************************
1565
1566int i_min ( int i1, int i2 )
1567
1568//****************************************************************************
1569//
1570// Purpose:
1571//
1572// I_MIN returns the smaller of two integers.
1573//
1574// Modified:
1575//
1576// 13 October 1998
1577//
1578// Author:
1579//
1580// John Burkardt
1581//
1582// Parameters:
1583//
1584// Input, int I1, I2, two integers to be compared.
1585//
1586// Output, int I_MIN, the smaller of I1 and I2.
1587//
1588{
1589 if ( i1 < i2 )
1590 {
1591 return i1;
1592 }
1593 else
1594 {
1595 return i2;
1596 }
1597
1598}
1599//*********************************************************************
1600
1601int i_modp ( int i, int j )
1602
1603//*********************************************************************
1604//
1605// Purpose:
1606//
1607// I_MODP returns the nonnegative remainder of integer division.
1608//
1609// Formula:
1610//
1611// If
1612// NREM = I_MODP ( I, J )
1613// NMULT = ( I - NREM ) / J
1614// then
1615// I = J * NMULT + NREM
1616// where NREM is always nonnegative.
1617//
1618// Comments:
1619//
1620// The MOD function computes a result with the same sign as the
1621// quantity being divided. Thus, suppose you had an angle A,
1622// and you wanted to ensure that it was between 0 and 360.
1623// Then mod(A,360) would do, if A was positive, but if A
1624// was negative, your result would be between -360 and 0.
1625//
1626// On the other hand, I_MODP(A,360) is between 0 and 360, always.
1627//
1628// Examples:
1629//
1630// I J MOD I_MODP I_MODP Factorization
1631//
1632// 107 50 7 7 107 = 2 * 50 + 7
1633// 107 -50 7 7 107 = -2 * -50 + 7
1634// -107 50 -7 43 -107 = -3 * 50 + 43
1635// -107 -50 -7 43 -107 = 3 * -50 + 43
1636//
1637// Modified:
1638//
1639// 26 May 1999
1640//
1641// Author:
1642//
1643// John Burkardt
1644//
1645// Parameters:
1646//
1647// Input, int I, the number to be divided.
1648//
1649// Input, int J, the number that divides I.
1650//
1651// Output, int I_MODP, the nonnegative remainder when I is
1652// divided by J.
1653//
1654{
1655 int value;
1656
1657 if ( j == 0 )
1658 {
1659 cout << "\n";
1660 cout << "I_MODP - Fatal error!\n";
1661 cout << " I_MODP ( I, J ) called with J = " << j << "\n";
1662 exit ( 1 );
1663 }
1664
1665 value = i % j;
1666
1667 if ( value < 0 )
1668 {
1669 value = value + abs ( j );
1670 }
1671
1672 return value;
1673}
1674//********************************************************************
1675
1676int i_sign ( int i )
1677
1678//********************************************************************
1679//
1680// Purpose:
1681//
1682// I_SIGN returns the sign of an integer.
1683//
1684// Discussion:
1685//
1686// The sign of 0 and all positive integers is taken to be +1.
1687// The sign of all negative integers is -1.
1688//
1689// Modified:
1690//
1691// 06 May 2003
1692//
1693// Author:
1694//
1695// John Burkardt
1696//
1697// Parameters:
1698//
1699// Input, int I, the integer whose sign is desired.
1700//
1701// Output, int I_SIGN, the sign of I.
1702{
1703 if ( i < 0 )
1704 {
1705 return (-1);
1706 }
1707 else
1708 {
1709 return 1;
1710 }
1711
1712}
1713//******************************************************************************
1714
1715int i_wrap ( int ival, int ilo, int ihi )
1716
1717//******************************************************************************
1718//
1719// Purpose:
1720//
1721// I_WRAP forces an integer to lie between given limits by wrapping.
1722//
1723// Example:
1724//
1725// ILO = 4, IHI = 8
1726//
1727// I I_WRAP
1728//
1729// -2 8
1730// -1 4
1731// 0 5
1732// 1 6
1733// 2 7
1734// 3 8
1735// 4 4
1736// 5 5
1737// 6 6
1738// 7 7
1739// 8 8
1740// 9 4
1741// 10 5
1742// 11 6
1743// 12 7
1744// 13 8
1745// 14 4
1746//
1747// Modified:
1748//
1749// 19 August 2003
1750//
1751// Author:
1752//
1753// John Burkardt
1754//
1755// Parameters:
1756//
1757// Input, int IVAL, an integer value.
1758//
1759// Input, int ILO, IHI, the desired bounds for the integer value.
1760//
1761// Output, int I_WRAP, a "wrapped" version of IVAL.
1762//
1763{
1764 int jhi;
1765 int jlo;
1766 int value;
1767 int wide;
1768
1769 jlo = i_min ( ilo, ihi );
1770 jhi = i_max ( ilo, ihi );
1771
1772 wide = jhi + 1 - jlo;
1773
1774 if ( wide == 1 )
1775 {
1776 value = jlo;
1777 }
1778 else
1779 {
1780 value = jlo + i_modp ( ival - jlo, wide );
1781 }
1782
1783 return value;
1784}
1785//******************************************************************************
1786
1787void imat_transpose_print ( int m, int n, int a[], const char *title )
1788
1789//******************************************************************************
1790//
1791// Purpose:
1792//
1793// IMAT_TRANSPOSE_PRINT prints an integer matrix, transposed.
1794//
1795// Modified:
1796//
1797// 31 January 2005
1798//
1799// Author:
1800//
1801// John Burkardt
1802//
1803// Parameters:
1804//
1805// Input, int M, the number of rows in A.
1806//
1807// Input, int N, the number of columns in A.
1808//
1809// Input, int A[M*N], the M by N matrix.
1810//
1811// Input, const char *TITLE, a title to be printed.
1812//
1813{
1814 imat_transpose_print_some ( m, n, a, 1, 1, m, n, title );
1815
1816 return;
1817}
1818//******************************************************************************
1819
1820void imat_transpose_print_some ( int m, int n, int a[], int ilo, int jlo,
1821 int ihi, int jhi, const char *title )
1822
1823//******************************************************************************
1824//
1825// Purpose:
1826//
1827// IMAT_TRANSPOSE_PRINT_SOME prints some of an integer matrix, transposed.
1828//
1829// Modified:
1830//
1831// 09 February 2005
1832//
1833// Author:
1834//
1835// John Burkardt
1836//
1837// Parameters:
1838//
1839// Input, int M, the number of rows of the matrix.
1840// M must be positive.
1841//
1842// Input, int N, the number of columns of the matrix.
1843// N must be positive.
1844//
1845// Input, int A[M*N], the matrix.
1846//
1847// Input, int ILO, JLO, IHI, JHI, designate the first row and
1848// column, and the last row and column to be printed.
1849//
1850// Input, const char *TITLE, a title for the matrix.
1851{
1852# define INCX 10
1853
1854 int i;
1855 int i2hi;
1856 int i2lo;
1857 int j;
1858 int j2hi;
1859 int j2lo;
1860
1861 if ( 0 < s_len_trim ( title ) )
1862 {
1863 cout << "\n";
1864 cout << title << "\n";
1865 }
1866//
1867// Print the columns of the matrix, in strips of INCX.
1868//
1869 for ( i2lo = ilo; i2lo <= ihi; i2lo = i2lo + INCX )
1870 {
1871 i2hi = i2lo + INCX - 1;
1872 i2hi = i_min ( i2hi, m );
1873 i2hi = i_min ( i2hi, ihi );
1874
1875 cout << "\n";
1876//
1877// For each row I in the current range...
1878//
1879// Write the header.
1880//
1881 cout << " Row: ";
1882 for ( i = i2lo; i <= i2hi; i++ )
1883 {
1884 cout << setw(7) << i << " ";
1885 }
1886 cout << "\n";
1887 cout << " Col\n";
1888 cout << "\n";
1889//
1890// Determine the range of the rows in this strip.
1891//
1892 j2lo = i_max ( jlo, 1 );
1893 j2hi = i_min ( jhi, n );
1894
1895 for ( j = j2lo; j <= j2hi; j++ )
1896 {
1897//
1898// Print out (up to INCX) entries in column J, that lie in the current strip.
1899//
1900 cout << setw(5) << j << " ";
1901 for ( i = i2lo; i <= i2hi; i++ )
1902 {
1903 cout << setw(6) << a[i-1+(j-1)*m] << " ";
1904 }
1905 cout << "\n";
1906 }
1907
1908 }
1909
1910 cout << "\n";
1911
1912 return;
1913# undef INCX
1914}
1915//********************************************************************
1916
1917void ivec_heap_d ( int n, int a[] )
1918
1919/*********************************************************************
1920//
1921// Purpose:
1922//
1923// IVEC_HEAP_D reorders an array of integers into a descending heap.
1924//
1925// Definition:
1926//
1927// A heap is an array A with the property that, for every index J,
1928// A[J] >= A[2*J+1] and A[J] >= A[2*J+2], (as long as the indices
1929// 2*J+1 and 2*J+2 are legal).
1930//
1931// Diagram:
1932//
1933// A(0)
1934// / \
1935// A(1) A(2)
1936// / \ / \
1937// A(3) A(4) A(5) A(6)
1938// / \ / \
1939// A(7) A(8) A(9) A(10)
1940//
1941// Reference:
1942//
1943// Albert Nijenhuis, Herbert Wilf,
1944// Combinatorial Algorithms,
1945// Academic Press, 1978, second edition,
1946// ISBN 0-12-519260-6.
1947//
1948// Modified:
1949//
1950// 30 April 1999
1951//
1952// Author:
1953//
1954// John Burkardt
1955//
1956// Parameters:
1957//
1958// Input, int N, the size of the input array.
1959//
1960// Input/output, int A[N].
1961// On input, an unsorted array.
1962// On output, the array has been reordered into a heap.
1963*/
1964{
1965 int i;
1966 int ifree;
1967 int key;
1968 int m;
1969//
1970// Only nodes (N/2)-1 down to 0 can be "parent" nodes.
1971//
1972 for ( i = (n/2)-1; 0 <= i; i-- )
1973 {
1974//
1975// Copy the value out of the parent node.
1976// Position IFREE is now "open".
1977//
1978 key = a[i];
1979 ifree = i;
1980
1981 for ( ;; )
1982 {
1983//
1984// Positions 2*IFREE + 1 and 2*IFREE + 2 are the descendants of position
1985// IFREE. (One or both may not exist because they equal or exceed N.)
1986//
1987 m = 2 * ifree + 1;
1988//
1989// Does the first position exist?
1990//
1991 if ( n <= m )
1992 {
1993 break;
1994 }
1995 else
1996 {
1997//
1998// Does the second position exist?
1999//
2000 if ( m + 1 < n )
2001 {
2002//
2003// If both positions exist, take the larger of the two values,
2004// and update M if necessary.
2005//
2006 if ( a[m] < a[m+1] )
2007 {
2008 m = m + 1;
2009 }
2010 }
2011//
2012// If the large descendant is larger than KEY, move it up,
2013// and update IFREE, the location of the free position, and
2014// consider the descendants of THIS position.
2015//
2016 if ( key < a[m] )
2017 {
2018 a[ifree] = a[m];
2019 ifree = m;
2020 }
2021 else
2022 {
2023 break;
2024 }
2025
2026 }
2027
2028 }
2029//
2030// When you have stopped shifting items up, return the item you
2031// pulled out back to the heap.
2032//
2033 a[ifree] = key;
2034
2035 }
2036
2037 return;
2038}
2039//******************************************************************************
2040
2041int *ivec_indicator ( int n )
2042
2043//******************************************************************************
2044//
2045// Purpose:
2046//
2047// IVEC_INDICATOR sets an integer vector to the indicator vector.
2048//
2049// Modified:
2050//
2051// 13 January 2004
2052//
2053// Author:
2054//
2055// John Burkardt
2056//
2057// Parameters:
2058//
2059// Input, int N, the number of elements of A.
2060//
2061// Output, int IVEC_INDICATOR(N), the initialized array.
2062//
2063{
2064 int *a;
2065 int i;
2066
2067 a = new int[n];
2068
2069 for ( i = 0; i < n; i++ )
2070 {
2071 a[i] = i + 1;
2072 }
2073
2074 return a;
2075}
2076//********************************************************************
2077
2078void ivec_sort_heap_a ( int n, int a[] )
2079
2080//********************************************************************
2081//
2082// Purpose:
2083//
2084// IVEC_SORT_HEAP_A ascending sorts an array of integers using heap sort.
2085//
2086// Reference:
2087//
2088// Albert Nijenhuis, Herbert Wilf,
2089// Combinatorial Algorithms,
2090// Academic Press, 1978, second edition,
2091// ISBN 0-12-519260-6.
2092//
2093// Modified:
2094//
2095// 30 April 1999
2096//
2097// Author:
2098//
2099// John Burkardt
2100//
2101// Parameters:
2102//
2103// Input, int N, the number of entries in the array.
2104//
2105// Input/output, int A[N].
2106// On input, the array to be sorted;
2107// On output, the array has been sorted.
2108//
2109{
2110 int n1;
2111 int temp;
2112
2113 if ( n <= 1 )
2114 {
2115 return;
2116 }
2117//
2118// 1: Put A into descending heap form.
2119//
2120 ivec_heap_d ( n, a );
2121//
2122// 2: Sort A.
2123//
2124// The largest object in the heap is in A[0].
2125// Move it to position A[N-1].
2126//
2127 temp = a[0];
2128 a[0] = a[n-1];
2129 a[n-1] = temp;
2130//
2131// Consider the diminished heap of size N1.
2132//
2133 for ( n1 = n-1; 2 <= n1; n1-- )
2134 {
2135//
2136// Restore the heap structure of the initial N1 entries of A.
2137//
2138 ivec_heap_d ( n1, a );
2139//
2140// Take the largest object from A[0] and move it to A[N1-1].
2141//
2142 temp = a[0];
2143 a[0] = a[n1-1];
2144 a[n1-1] = temp;
2145
2146 }
2147
2148 return;
2149}
2150//******************************************************************************
2151
2152void ivec_sorted_unique ( int n, int a[], int *nuniq )
2153
2154//******************************************************************************
2155//
2156// Purpose:
2157//
2158// IVEC_SORTED_UNIQUE finds unique elements in a sorted integer array.
2159//
2160// Modified:
2161//
2162// 02 September 2003
2163//
2164// Author:
2165//
2166// John Burkardt
2167//
2168// Parameters:
2169//
2170// Input, int N, the number of elements in A.
2171//
2172// Input/output, int A[N]. On input, the sorted
2173// integer array. On output, the unique elements in A.
2174//
2175// Output, int *NUNIQ, the number of unique elements in A.
2176//
2177{
2178 int i;
2179
2180 *nuniq = 0;
2181
2182 if ( n <= 0 )
2183 {
2184 return;
2185 }
2186
2187 *nuniq = 1;
2188
2189 for ( i = 1; i < n; i++ )
2190 {
2191 if ( a[i] != a[*nuniq] )
2192 {
2193 *nuniq = *nuniq + 1;
2194 a[*nuniq] = a[i];
2195 }
2196
2197 }
2198
2199 return;
2200}
2201//******************************************************************************
2202
2203int lrline ( double xu, double yu, double xv1, double yv1, double xv2,
2204 double yv2, double dv )
2205
2206//******************************************************************************
2207//
2208// Purpose:
2209//
2210// LRLINE determines where a point lies in relation to a directed line.
2211//
2212// Discussion:
2213//
2214// LRLINE determines whether a point is to the left of, right of,
2215// or on a directed line parallel to a line through given points.
2216//
2217// Modified:
2218//
2219// 28 August 2003
2220//
2221// Author:
2222//
2223// Barry Joe,
2224// Department of Computing Science,
2225// University of Alberta,
2226// Edmonton, Alberta, Canada T6G 2H1
2227//
2228// Reference:
2229//
2230// Barry Joe,
2231// GEOMPACK - a software package for the generation of meshes
2232// using geometric algorithms,
2233// Advances in Engineering Software,
2234// Volume 13, pages 325-331, 1991.
2235//
2236// Parameters:
2237//
2238// Input, double XU, YU, XV1, YV1, XV2, YV2, are vertex coordinates; the
2239// directed line is parallel to and at signed distance DV to the left of
2240// the directed line from (XV1,YV1) to (XV2,YV2); (XU,YU) is the vertex for
2241// which the position relative to the directed line is to be determined.
2242//
2243// Input, double DV, the signed distance, positive for left.
2244//
2245// Output, int LRLINE, is +1, 0, or -1 depending on whether (XU,YU) is
2246// to the right of, on, or left of the directed line. LRLINE is 0 if
2247// the line degenerates to a point.
2248//
2249{
2250 double dx;
2251 double dxu;
2252 double dy;
2253 double dyu;
2254 double t;
2255 double tol = 0.0000001;
2256 double tolabs;
2257 int value = 0;
2258
2259 dx = xv2 - xv1;
2260 dy = yv2 - yv1;
2261 dxu = xu - xv1;
2262 dyu = yu - yv1;
2263
2264 tolabs = tol * d_max ( fabs ( dx ),
2265 d_max ( fabs ( dy ),
2266 d_max ( fabs ( dxu ),
2267 d_max ( fabs ( dyu ), fabs ( dv ) ) ) ) );
2268
2269 t = dy * dxu - dx * dyu + dv * sqrt ( dx * dx + dy * dy );
2270
2271 if ( tolabs < t )
2272 {
2273 value = 1;
2274 }
2275 else if ( -tolabs <= t )
2276 {
2277 value = 0;
2278 }
2279 else if ( t < -tolabs )
2280 {
2281 value = -1;
2282 }
2283
2284 return value;
2285}
2286//******************************************************************************
2287
2288bool perm_check ( int n, int p[] )
2289
2290//******************************************************************************
2291//
2292// Purpose:
2293//
2294// PERM_CHECK checks that a vector represents a permutation.
2295//
2296// Discussion:
2297//
2298// The routine verifies that each of the integers from 1
2299// to N occurs among the N entries of the permutation.
2300//
2301// Modified:
2302//
2303// 13 January 2004
2304//
2305// Author:
2306//
2307// John Burkardt
2308//
2309// Parameters:
2310//
2311// Input, int N, the number of entries.
2312//
2313// Input, int P[N], the array to check.
2314//
2315// Output, bool PERM_CHECK, is TRUE if the permutation is OK.
2316//
2317{
2318 bool found;
2319 int i;
2320 int seek;
2321
2322 for ( seek = 1; seek <= n; seek++ )
2323 {
2324 found = false;
2325
2326 for ( i = 0; i < n; i++ )
2327 {
2328 if ( p[i] == seek )
2329 {
2330 found = true;
2331 break;
2332 }
2333 }
2334
2335 if ( !found )
2336 {
2337 return false;
2338 }
2339
2340 }
2341
2342 return true;
2343}
2344//******************************************************************************
2345
2346void perm_inv ( int n, int p[] )
2347
2348//******************************************************************************
2349//
2350// Purpose:
2351//
2352// PERM_INV inverts a permutation "in place".
2353//
2354// Modified:
2355//
2356// 13 January 2004
2357//
2358// Parameters:
2359//
2360// Input, int N, the number of objects being permuted.
2361//
2362// Input/output, int P[N], the permutation, in standard index form.
2363// On output, P describes the inverse permutation
2364//
2365{
2366 int i;
2367 int i0;
2368 int i1;
2369 int i2;
2370 int is;
2371
2372 if ( n <= 0 )
2373 {
2374 cout << "\n";
2375 cout << "PERM_INV - Fatal error!\n";
2376 cout << " Input value of N = " << n << "\n";
2377 exit ( 1 );
2378 }
2379
2380 if ( !perm_check ( n, p ) )
2381 {
2382 cout << "\n";
2383 cout << "PERM_INV - Fatal error!\n";
2384 cout << " The input array does not represent\n";
2385 cout << " a proper permutation.\n";
2386 exit ( 1 );
2387 }
2388
2389 is = 1;
2390
2391 for ( i = 1; i <= n; i++ )
2392 {
2393 i1 = p[i-1];
2394
2395 while ( i < i1 )
2396 {
2397 i2 = p[i1-1];
2398 p[i1-1] = -i2;
2399 i1 = i2;
2400 }
2401
2402 is = - i_sign ( p[i-1] );
2403 p[i-1] = i_sign ( is ) * abs ( p[i-1] );
2404 }
2405
2406 for ( i = 1; i <= n; i++ )
2407 {
2408 i1 = -p[i-1];
2409
2410 if ( 0 <= i1 )
2411 {
2412 i0 = i;
2413
2414 for ( ; ; )
2415 {
2416 i2 = p[i1-1];
2417 p[i1-1] = i0;
2418
2419 if ( i2 < 0 )
2420 {
2421 break;
2422 }
2423 i0 = i1;
2424 i1 = i2;
2425 }
2426 }
2427 }
2428
2429 return;
2430}
2431//********************************************************************
2432
2433int *points_delaunay_naive_2d ( int n, double p[], int *ntri )
2434
2435//********************************************************************
2436//
2437// Purpose:
2438//
2439// POINTS_DELAUNAY_NAIVE_2D computes the Delaunay triangulation in 2D.
2440//
2441// Discussion:
2442//
2443// A naive and inefficient (but extremely simple) method is used.
2444//
2445// This routine is only suitable as a demonstration code for small
2446// problems. Its running time is of order N^4. Much faster algorithms
2447// are available.
2448//
2449// Given a set of nodes in the plane, a triangulation is a set of
2450// triples of distinct nodes, forming triangles, so that every
2451// point with the convex hull of the set of nodes is either one
2452// of the nodes, or lies on an edge of one or more triangles,
2453// or lies within exactly one triangle.
2454//
2455// Modified:
2456//
2457// 05 February 2005
2458//
2459// Author:
2460//
2461// John Burkardt
2462//
2463// Reference:
2464//
2465// Joseph O'Rourke,
2466// Computational Geometry,
2467// Cambridge University Press,
2468// Second Edition, 1998, page 187.
2469//
2470// Parameters:
2471//
2472// Input, int N, the number of nodes. N must be at least 3.
2473//
2474// Input, double P[2*N], the coordinates of the nodes.
2475//
2476// Output, int *NTRI, the number of triangles.
2477//
2478// Output, int POINTS_DELAUNAY_NAIVE_2D[3*NTRI], the indices of the
2479// nodes making each triangle.
2480//
2481{
2482 int count;
2483 int flag;
2484 int i;
2485 int j;
2486 int k;
2487 int m;
2488 int pass;
2489 int *tri = NULL;
2490 double xn;
2491 double yn;
2492 double zn;
2493 double *z;
2494
2495 count = 0;
2496
2497 z = new double [ n ];
2498
2499 for ( i = 0; i < n; i++ )
2500 {
2501 z[i] = p[0+i*2] * p[0+i*2] + p[1+i*2] * p[1+i*2];
2502 }
2503//
2504// First pass counts triangles,
2505// Second pass allocates triangles and sets them.
2506//
2507 for ( pass = 1; pass <= 2; pass++ )
2508 {
2509 if ( pass == 2 )
2510 {
2511 tri = new int[3*count];
2512 }
2513 count = 0;
2514//
2515// For each triple (I,J,K):
2516//
2517 for ( i = 0; i < n - 2; i++ )
2518 {
2519 for ( j = i+1; j < n; j++ )
2520 {
2521 for ( k = i+1; k < n; k++ )
2522 {
2523 if ( j != k )
2524 {
2525 xn = ( p[1+j*2] - p[1+i*2] ) * ( z[k] - z[i] )
2526 - ( p[1+k*2] - p[1+i*2] ) * ( z[j] - z[i] );
2527 yn = ( p[0+k*2] - p[0+i*2] ) * ( z[j] - z[i] )
2528 - ( p[0+j*2] - p[0+i*2] ) * ( z[k] - z[i] );
2529 zn = ( p[0+j*2] - p[0+i*2] ) * ( p[1+k*2] - p[1+i*2] )
2530 - ( p[0+k*2] - p[0+i*2] ) * ( p[1+j*2] - p[1+i*2] );
2531
2532 flag = ( zn < 0 );
2533
2534 if ( flag )
2535 {
2536 for ( m = 0; m < n; m++ )
2537 {
2538 flag = flag && ( ( p[0+m*2] - p[0+i*2] ) * xn
2539 + ( p[1+m*2] - p[1+i*2] ) * yn
2540 + ( z[m] - z[i] ) * zn <= 0 );
2541 }
2542 }
2543
2544 if ( flag )
2545 {
2546 if ( pass == 2 )
2547 {
2548 tri[0+count*3] = i;
2549 tri[1+count*3] = j;
2550 tri[2+count*3] = k;
2551 }
2552 count = count + 1;
2553 }
2554
2555 }
2556 }
2557 }
2558 }
2559 }
2560
2561 *ntri = count;
2562 delete [] z;
2563
2564 return tri;
2565}
2566//******************************************************************************
2567
2568int s_len_trim ( const char *s )
2569
2570//******************************************************************************
2571//
2572// Purpose:
2573//
2574// S_LEN_TRIM returns the length of a string to the last nonblank.
2575//
2576// Modified:
2577//
2578// 26 April 2003
2579//
2580// Author:
2581//
2582// John Burkardt
2583//
2584// Parameters:
2585//
2586// Input, const char *S, a pointer to a string.
2587//
2588// Output, int S_LEN_TRIM, the length of the string to the last nonblank.
2589// If S_LEN_TRIM is 0, then the string is entirely blank.
2590//
2591{
2592 int n;
2593 char* t;
2594
2595 n = strlen ( s );
2596 t = const_cast<char*>(s) + n - 1;
2597
2598 while ( 0 < n )
2599 {
2600 if ( *t != ' ' )
2601 {
2602 return n;
2603 }
2604 t--;
2605 n--;
2606 }
2607
2608 return n;
2609}
2610//******************************************************************************
2611
2612int swapec ( int i, int *top, int *btri, int *bedg, int point_num,
2613 double point_xy[], int tri_num, int tri_vert[], int tri_nabe[],
2614 int stack[] )
2615
2616//******************************************************************************
2617//
2618// Purpose:
2619//
2620// SWAPEC swaps diagonal edges until all triangles are Delaunay.
2621//
2622// Discussion:
2623//
2624// The routine swaps diagonal edges in a 2D triangulation, based on
2625// the empty circumcircle criterion, until all triangles are Delaunay,
2626// given that I is the index of the new vertex added to the triangulation.
2627//
2628// Modified:
2629//
2630// 03 September 2003
2631//
2632// Author:
2633//
2634// Barry Joe,
2635// Department of Computing Science,
2636// University of Alberta,
2637// Edmonton, Alberta, Canada T6G 2H1
2638//
2639// Reference:
2640//
2641// Barry Joe,
2642// GEOMPACK - a software package for the generation of meshes
2643// using geometric algorithms,
2644// Advances in Engineering Software,
2645// Volume 13, pages 325-331, 1991.
2646//
2647// Parameters:
2648//
2649// Input, int I, the index of the new vertex.
2650//
2651// Input/output, int *TOP, the index of the top of the stack.
2652// On output, TOP is zero.
2653//
2654// Input/output, int *BTRI, *BEDG; on input, if positive, are the
2655// triangle and edge indices of a boundary edge whose updated indices
2656// must be recorded. On output, these may be updated because of swaps.
2657//
2658// Input, int POINT_NUM, the number of points.
2659//
2660// Input, double POINT_XY[POINT_NUM*2], the coordinates of the points.
2661//
2662// Input, int TRI_NUM, the number of triangles.
2663//
2664// Input/output, int TRI_VERT[TRI_NUM*3], the triangle incidence list.
2665// May be updated on output because of swaps.
2666//
2667// Input/output, int TRI_NABE[TRI_NUM*3], the triangle neighbor list;
2668// negative values are used for links of the counter-clockwise linked
2669// list of boundary edges; May be updated on output because of swaps.
2670//
2671// LINK = -(3*I + J-1) where I, J = triangle, edge index.
2672//
2673// Workspace, int STACK[MAXST]; on input, entries 1 through TOP
2674// contain the indices of initial triangles (involving vertex I)
2675// put in stack; the edges opposite I should be in interior; entries
2676// TOP+1 through MAXST are used as a stack.
2677//
2678// Output, int SWAPEC, is set to 8 for abnormal return.
2679//
2680{
2681 int a;
2682 int b;
2683 int c;
2684 int e;
2685 int ee;
2686 int em1;
2687 int ep1;
2688 int f;
2689 int fm1;
2690 int fp1;
2691 int l;
2692 int r;
2693 int s;
2694 int swap;
2695 int t;
2696 int tt;
2697 int u;
2698 double x;
2699 double y;
2700//
2701// Determine whether triangles in stack are Delaunay, and swap
2702// diagonal edge of convex quadrilateral if not.
2703//
2704 x = point_xy[2*(i-1)+0];
2705 y = point_xy[2*(i-1)+1];
2706
2707 for ( ; ; )
2708 {
2709 if ( *top <= 0 )
2710 {
2711 break;
2712 }
2713
2714 t = stack[(*top)-1];
2715 *top = *top - 1;
2716
2717 if ( tri_vert[3*(t-1)+0] == i )
2718 {
2719 e = 2;
2720 b = tri_vert[3*(t-1)+2];
2721 }
2722 else if ( tri_vert[3*(t-1)+1] == i )
2723 {
2724 e = 3;
2725 b = tri_vert[3*(t-1)+0];
2726 }
2727 else
2728 {
2729 e = 1;
2730 b = tri_vert[3*(t-1)+1];
2731 }
2732
2733 a = tri_vert[3*(t-1)+e-1];
2734 u = tri_nabe[3*(t-1)+e-1];
2735
2736 if ( tri_nabe[3*(u-1)+0] == t )
2737 {
2738 f = 1;
2739 c = tri_vert[3*(u-1)+2];
2740 }
2741 else if ( tri_nabe[3*(u-1)+1] == t )
2742 {
2743 f = 2;
2744 c = tri_vert[3*(u-1)+0];
2745 }
2746 else
2747 {
2748 f = 3;
2749 c = tri_vert[3*(u-1)+1];
2750 }
2751
2752 swap = diaedg ( x, y,
2753 point_xy[2*(a-1)+0], point_xy[2*(a-1)+1],
2754 point_xy[2*(c-1)+0], point_xy[2*(c-1)+1],
2755 point_xy[2*(b-1)+0], point_xy[2*(b-1)+1] );
2756
2757 if ( swap == 1 )
2758 {
2759 em1 = i_wrap ( e - 1, 1, 3 );
2760 ep1 = i_wrap ( e + 1, 1, 3 );
2761 fm1 = i_wrap ( f - 1, 1, 3 );
2762 fp1 = i_wrap ( f + 1, 1, 3 );
2763
2764 tri_vert[3*(t-1)+ep1-1] = c;
2765 tri_vert[3*(u-1)+fp1-1] = i;
2766 r = tri_nabe[3*(t-1)+ep1-1];
2767 s = tri_nabe[3*(u-1)+fp1-1];
2768 tri_nabe[3*(t-1)+ep1-1] = u;
2769 tri_nabe[3*(u-1)+fp1-1] = t;
2770 tri_nabe[3*(t-1)+e-1] = s;
2771 tri_nabe[3*(u-1)+f-1] = r;
2772
2773 if ( 0 < tri_nabe[3*(u-1)+fm1-1] )
2774 {
2775 *top = *top + 1;
2776 stack[(*top)-1] = u;
2777 }
2778
2779 if ( 0 < s )
2780 {
2781 if ( tri_nabe[3*(s-1)+0] == u )
2782 {
2783 tri_nabe[3*(s-1)+0] = t;
2784 }
2785 else if ( tri_nabe[3*(s-1)+1] == u )
2786 {
2787 tri_nabe[3*(s-1)+1] = t;
2788 }
2789 else
2790 {
2791 tri_nabe[3*(s-1)+2] = t;
2792 }
2793
2794 *top = *top + 1;
2795
2796 if ( point_num < *top )
2797 {
2798 return 8;
2799 }
2800
2801 stack[(*top)-1] = t;
2802 }
2803 else
2804 {
2805 if ( u == *btri && fp1 == *bedg )
2806 {
2807 *btri = t;
2808 *bedg = e;
2809 }
2810
2811 l = - ( 3 * t + e - 1 );
2812 tt = t;
2813 ee = em1;
2814
2815 while ( 0 < tri_nabe[3*(tt-1)+ee-1] )
2816 {
2817 tt = tri_nabe[3*(tt-1)+ee-1];
2818
2819 if ( tri_vert[3*(tt-1)+0] == a )
2820 {
2821 ee = 3;
2822 }
2823 else if ( tri_vert[3*(tt-1)+1] == a )
2824 {
2825 ee = 1;
2826 }
2827 else
2828 {
2829 ee = 2;
2830 }
2831
2832 }
2833
2834 tri_nabe[3*(tt-1)+ee-1] = l;
2835
2836 }
2837
2838 if ( 0 < r )
2839 {
2840 if ( tri_nabe[3*(r-1)+0] == t )
2841 {
2842 tri_nabe[3*(r-1)+0] = u;
2843 }
2844 else if ( tri_nabe[3*(r-1)+1] == t )
2845 {
2846 tri_nabe[3*(r-1)+1] = u;
2847 }
2848 else
2849 {
2850 tri_nabe[3*(r-1)+2] = u;
2851 }
2852 }
2853 else
2854 {
2855 if ( t == *btri && ep1 == *bedg )
2856 {
2857 *btri = u;
2858 *bedg = f;
2859 }
2860
2861 l = - ( 3 * u + f - 1 );
2862 tt = u;
2863 ee = fm1;
2864
2865 while ( 0 < tri_nabe[3*(tt-1)+ee-1] )
2866 {
2867 tt = tri_nabe[3*(tt-1)+ee-1];
2868
2869 if ( tri_vert[3*(tt-1)+0] == b )
2870 {
2871 ee = 3;
2872 }
2873 else if ( tri_vert[3*(tt-1)+1] == b )
2874 {
2875 ee = 1;
2876 }
2877 else
2878 {
2879 ee = 2;
2880 }
2881 }
2882 tri_nabe[3*(tt-1)+ee-1] = l;
2883 }
2884 }
2885 }
2886 return 0;
2887}
2888//**********************************************************************
2889
2890void timestamp ( void )
2891
2892//**********************************************************************
2893//
2894// Purpose:
2895//
2896// TIMESTAMP prints the current YMDHMS date as a time stamp.
2897//
2898// Example:
2899//
2900// May 31 2001 09:45:54 AM
2901//
2902// Modified:
2903//
2904// 21 August 2002
2905//
2906// Author:
2907//
2908// John Burkardt
2909//
2910// Parameters:
2911//
2912// None
2913//
2914{
2915# define TIME_SIZE 29
2916
2917 static char time_buffer[TIME_SIZE];
2918 const struct tm *tm;
2919 size_t len;
2920 time_t now;
2921
2922 now = time ( NULL );
2923 tm = localtime ( &now );
2924
2925 len = strftime ( time_buffer, TIME_SIZE, "%d %B %Y %I:%M:%S %p", tm );
2926
2927 if ( len != 0 )
2928 {
2929 cout << time_buffer << "\n";
2930 }
2931
2932 return;
2933# undef TIME_SIZE
2934}
2935//**********************************************************************
2936
2937char *timestring ( void )
2938
2939//**********************************************************************
2940//
2941// Purpose:
2942//
2943// TIMESTRING returns the current YMDHMS date as a string.
2944//
2945// Example:
2946//
2947// May 31 2001 09:45:54 AM
2948//
2949// Modified:
2950//
2951// 13 June 2003
2952//
2953// Author:
2954//
2955// John Burkardt
2956//
2957// Parameters:
2958//
2959// Output, char *TIMESTRING, a string containing the current YMDHMS date.
2960//
2961{
2962# define TIME_SIZE 29
2963
2964 const struct tm *tm;
2965 time_t now;
2966 char *s;
2967
2968 now = time ( NULL );
2969 tm = localtime ( &now );
2970
2971 s = new char[TIME_SIZE];
2972
2973 strftime ( s, TIME_SIZE, "%d %B %Y %I:%M:%S %p", tm );
2974
2975 return s;
2976# undef TIME_SIZE
2977}
2978//******************************************************************************
2979
2980double *triangle_circumcenter_2d ( double t[] )
2981
2982//******************************************************************************
2983//
2984// Purpose:
2985//
2986// TRIANGLE_CIRCUMCENTER_2D computes the circumcenter of a triangle in 2D.
2987//
2988// Discussion:
2989//
2990// The circumcenter of a triangle is the center of the circumcircle, the
2991// circle that passes through the three vertices of the triangle.
2992//
2993// The circumcircle contains the triangle, but it is not necessarily the
2994// smallest triangle to do so.
2995//
2996// If all angles of the triangle are no greater than 90 degrees, then
2997// the center of the circumscribed circle will lie inside the triangle.
2998// Otherwise, the center will lie outside the circle.
2999//
3000// The circumcenter is the intersection of the perpendicular bisectors
3001// of the sides of the triangle.
3002//
3003// In geometry, the circumcenter of a triangle is often symbolized by "O".
3004//
3005// Modified:
3006//
3007// 09 February 2005
3008//
3009// Author:
3010//
3011// John Burkardt
3012//
3013// Parameters:
3014//
3015// Input, double T[2*3], the triangle vertices.
3016//
3017// Output, double *X, *Y, the coordinates of the circumcenter of
3018// the triangle.
3019//
3020{
3021# define DIM_NUM 2
3022
3023 double asq;
3024 double bot;
3025 double *center;
3026 double csq;
3027 double top1;
3028 double top2;
3029
3030 center = new double[DIM_NUM];
3031
3032 asq = ( t[0+1*2] - t[0+0*2] ) * ( t[0+1*2] - t[0+0*2] )
3033 + ( t[1+1*2] - t[1+0*2] ) * ( t[1+1*2] - t[1+0*2] );
3034
3035 csq = ( t[0+2*2] - t[0+0*2] ) * ( t[0+2*2] - t[0+0*2] )
3036 + ( t[1+2*2] - t[1+0*2] ) * ( t[1+2*2] - t[1+0*2] );
3037
3038 top1 = ( t[1+1*2] - t[1+0*2] ) * csq - ( t[1+2*2] - t[1+0*2] ) * asq;
3039 top2 = ( t[0+1*2] - t[0+0*2] ) * csq - ( t[0+2*2] - t[0+0*2] ) * asq;
3040
3041 bot = ( t[1+1*2] - t[1+0*2] ) * ( t[0+2*2] - t[0+0*2] )
3042 - ( t[1+2*2] - t[1+0*2] ) * ( t[0+1*2] - t[0+0*2] );
3043
3044 center[0] = t[0+0*2] + 0.5 * top1 / bot;
3045 center[1] = t[1+0*2] + 0.5 * top2 / bot;
3046
3047 return center;
3048
3049# undef DIM_NUM
3050}
3051//******************************************************************************
3052
3053bool triangulation_plot_eps ( const char *file_out_name, int g_num,
3054 double g_xy[], int tri_num, int nod_tri[] )
3055
3056//******************************************************************************
3057//
3058// Purpose:
3059//
3060// TRIANGULATION_PLOT_EPS plots a triangulation of a pointset.
3061//
3062// Discussion:
3063//
3064// The triangulation is most usually a Delaunay triangulation,
3065// but this is not necessary.
3066//
3067// The data can be generated by calling DTRIS2, but this is not
3068// necessary.
3069//
3070// Modified:
3071//
3072// 08 September 2003
3073//
3074// Author:
3075//
3076// John Burkardt
3077//
3078// Parameters:
3079//
3080// Input, const char *FILE_OUT_NAME, the name of the output file.
3081//
3082// Input, int G_NUM, the number of points.
3083//
3084// Input, double G_XY[G_NUM,2], the coordinates of the points.
3085//
3086// Input, int TRI_NUM, the number of triangles.
3087//
3088// Input, int NOD_TRI[3,TRI_NUM], lists, for each triangle,
3089// the indices of the points that form the vertices of the triangle.
3090//
3091// Output, bool TRIANGULATION_PLOT_EPS, is TRUE for success.
3092//
3093{
3094 char *date_time;
3095 int e;
3096 ofstream file_out;
3097 int g;
3098 int j;
3099 int k;
3100 int t;
3101 double x_max;
3102 double x_min;
3103 int x_ps;
3104 int x_ps_max = 576;
3105 int x_ps_max_clip = 594;
3106 int x_ps_min = 36;
3107 int x_ps_min_clip = 18;
3108 double y_max;
3109 double y_min;
3110 int y_ps;
3111 int y_ps_max = 666;
3112 int y_ps_max_clip = 684;
3113 int y_ps_min = 126;
3114 int y_ps_min_clip = 108;
3115
3116 date_time = timestring ( );
3117
3118 x_max = g_xy[0+0*2];
3119 x_min = g_xy[0+0*2];
3120 y_max = g_xy[1+0*2];
3121 y_min = g_xy[1+0*2];
3122
3123 for ( g = 0; g < g_num; g++ )
3124 {
3125 x_max = d_max ( x_max, g_xy[0+g*2] );
3126 x_min = d_min ( x_min, g_xy[0+g*2] );
3127 y_max = d_max ( y_max, g_xy[1+g*2] );
3128 y_min = d_min ( y_min, g_xy[1+g*2] );
3129 }
3130//
3131// Plot the Delaunay triangulation.
3132//
3133//
3134// Open the output file.
3135//
3136 file_out.open ( file_out_name );
3137
3138 if ( !file_out )
3139 {
3140 cout << "\n";
3141 cout << "TRIANGULATION_PLOT_EPS - Fatal error!\n";
3142 cout << " Cannot open the output file \"" << file_out_name << "\".\n";
3143 return false;
3144 }
3145
3146 file_out << "%!PS-Adobe-3.0 EPSF-3.0\n";
3147 file_out << "%%Creator: triangulation_plot_eps.cc\n";
3148 file_out << "%%Title: " << file_out_name << "\n";
3149 file_out << "%%CreationDate: " << date_time << "\n";
3150 file_out << "%%Pages: 1\n";
3151 file_out << "%%Bounding Box: " << x_ps_min << " " << y_ps_min << " "
3152 << x_ps_max << " " << y_ps_max << "\n";
3153 file_out << "%%Document-Fonts: Times-Roman\n";
3154 file_out << "%%LanguageLevel: 1\n";
3155 file_out << "%%EndComments\n";
3156 file_out << "%%BeginProlog\n";
3157 file_out << "/inch {72 mul} def\n";
3158 file_out << "%%EndProlog\n";
3159 file_out << "%%Page: 1 1\n";
3160 file_out << "save\n";
3161 file_out << "%\n";
3162 file_out << "% Set the RGB line color to very light gray.\n";
3163 file_out << "%\n";
3164 file_out << "0.900 0.900 0.900 setrgbcolor\n";
3165 file_out << "%\n";
3166 file_out << "% Draw a gray border around the page.\n";
3167 file_out << "%\n";
3168 file_out << "newpath\n";
3169 file_out << " " << x_ps_min << " " << y_ps_min << " moveto\n";
3170 file_out << " " << x_ps_max << " " << y_ps_min << " lineto\n";
3171 file_out << " " << x_ps_max << " " << y_ps_max << " lineto\n";
3172 file_out << " " << x_ps_min << " " << y_ps_max << " lineto\n";
3173 file_out << " " << x_ps_min << " " << y_ps_min << " lineto\n";
3174 file_out << "stroke\n";
3175 file_out << "%\n";
3176 file_out << "% Set the RGB line color to black.\n";
3177 file_out << "%\n";
3178 file_out << "0.000 0.000 0.000 setrgbcolor\n";
3179 file_out << "%\n";
3180 file_out << "% Set the font and its size.\n";
3181 file_out << "%\n";
3182 file_out << "/Times-Roman findfont\n";
3183 file_out << "0.50 inch scalefont\n";
3184 file_out << "setfont\n";
3185 file_out << "%\n";
3186 file_out << "% Print a title.\n";
3187 file_out << "%\n";
3188 file_out << "210 702 moveto\n";
3189 file_out << "(Triangulation) show\n";
3190 file_out << "%\n";
3191 file_out << "% Define a clipping polygon.\n";
3192 file_out << "%\n";
3193 file_out << "newpath\n";
3194 file_out << " " << x_ps_min_clip << " " << y_ps_min_clip << " moveto\n";
3195 file_out << " " << x_ps_max_clip << " " << y_ps_min_clip << " lineto\n";
3196 file_out << " " << x_ps_max_clip << " " << y_ps_max_clip << " lineto\n";
3197 file_out << " " << x_ps_min_clip << " " << y_ps_max_clip << " lineto\n";
3198 file_out << " " << x_ps_min_clip << " " << y_ps_min_clip << " lineto\n";
3199 file_out << "clip newpath\n";
3200 file_out << "%\n";
3201 file_out << "% Set the RGB line color to green.\n";
3202 file_out << "%\n";
3203 file_out << "0.000 0.750 0.150 setrgbcolor\n";
3204 file_out << "%\n";
3205 file_out << "% Draw the nodes.\n";
3206 file_out << "%\n";
3207
3208 for ( g = 0; g < g_num; g++ )
3209 {
3210 x_ps = int(
3211 ( ( x_max - g_xy[0+g*2] ) * double( x_ps_min )
3212 + ( g_xy[0+g*2] - x_min ) * double( x_ps_max ) )
3213 / ( x_max - x_min ) );
3214
3215 y_ps = int(
3216 ( ( y_max - g_xy[1+g*2] ) * double( y_ps_min )
3217 + ( g_xy[1+g*2] - y_min ) * double( y_ps_max ) )
3218 / ( y_max - y_min ) );
3219
3220 file_out << "newpath " << x_ps << " "
3221 << y_ps << " 5 0 360 arc closepath fill\n";
3222 }
3223
3224 file_out << "%\n";
3225 file_out << "% Set the RGB line color to red.\n";
3226 file_out << "%\n";
3227 file_out << "0.900 0.200 0.100 setrgbcolor\n";
3228 file_out << "%\n";
3229 file_out << "% Draw the triangles.\n";
3230 file_out << "%\n";
3231
3232 for ( t = 1; t <= tri_num; t++ )
3233 {
3234 file_out << "newpath\n";
3235
3236 for ( j = 1; j <= 4; j++ )
3237 {
3238 e = i_wrap ( j, 1, 3 );
3239
3240 k = nod_tri[3*(t-1)+e-1];
3241
3242 x_ps = int(
3243 ( ( x_max - g_xy[0+(k-1)*2] ) * double( x_ps_min )
3244 + ( g_xy[0+(k-1)*2] - x_min ) * double( x_ps_max ) )
3245 / ( x_max - x_min ) );
3246
3247 y_ps = int(
3248 ( ( y_max - g_xy[1+(k-1)*2] ) * double( y_ps_min )
3249 + ( g_xy[1+(k-1)*2] - y_min ) * double( y_ps_max ) )
3250 / ( y_max - y_min ) );
3251
3252 if ( j == 1 )
3253 {
3254 file_out << x_ps << " " << y_ps << " moveto\n";
3255 }
3256 else
3257 {
3258 file_out << x_ps << " " << y_ps << " lineto\n";
3259 }
3260
3261 }
3262
3263 file_out << "stroke\n";
3264
3265 }
3266
3267 file_out << "restore showpage\n";
3268 file_out << "%\n";
3269 file_out << "% End of page.\n";
3270 file_out << "%\n";
3271 file_out << "%%Trailer\n";
3272 file_out << "%%EOF\n";
3273
3274 file_out.close ( );
3275
3276 return true;
3277}
3278//******************************************************************************
3279
3280void triangulation_print ( int point_num, double xc[], int tri_num,
3281 int tri_vert[], int tri_nabe[] )
3282
3283//******************************************************************************
3284//
3285// Purpose:
3286//
3287// TRIANGULATION_PRINT prints information defining a Delaunay triangulation.
3288//
3289// Discussion:
3290//
3291// Triangulations created by RTRIS include extra information encoded
3292// in the negative values of TRI_NABE.
3293//
3294// Because some of the nodes counted in POINT_NUM may not actually be
3295// used in the triangulation, I needed to compute the true number
3296// of vertices. I added this calculation on 13 October 2001.
3297//
3298// Ernest Fasse pointed out an error in the indexing of VERTEX_LIST,
3299// which was corrected on 19 February 2004.
3300//
3301// Modified:
3302//
3303// 19 February 2004
3304//
3305// Author:
3306//
3307// John Burkardt
3308//
3309// Parameters:
3310//
3311// Input, int POINT_NUM, the number of points.
3312//
3313// Input, double XC[2*POINT_NUM], the point coordinates.
3314//
3315// Input, int TRI_NUM, the number of triangles.
3316//
3317// Input, int TRI_VERT[3*TRI_NUM], the nodes that make up the triangles.
3318//
3319// Input, int TRI_NABE[3*TRI_NUM], the triangle neighbors on each side.
3320// If there is no triangle neighbor on a particular side, the value of
3321// TRI_NABE should be negative. If the triangulation data was created by
3322// DTRIS2, then there is more information encoded in the negative values.
3323//
3324{
3325# define DIM_NUM 2
3326
3327 int boundary_num;
3328 int i;
3329 int j;
3330 int k;
3331 int n1;
3332 int n2;
3333 int s;
3334 int s1;
3335 int s2;
3336 bool skip;
3337 int t;
3338 int *vertex_list;
3339 int vertex_num;
3340
3341 cout << "\n";
3342 cout << "TRIANGULATION_PRINT\n";
3343 cout << " Information defining a triangulation.\n";
3344 cout << "\n";
3345 cout << " The number of points is " << point_num << "\n";
3346
3347 dmat_transpose_print ( DIM_NUM, point_num, xc, " Point coordinates" );
3348
3349 cout << "\n";
3350 cout << " The number of triangles is " << tri_num << "\n";
3351 cout << "\n";
3352 cout << " Sets of three points are used as vertices of\n";
3353 cout << " the triangles. For each triangle, the points\n";
3354 cout << " are listed in counterclockwise order.\n";
3355
3356 imat_transpose_print ( 3, tri_num, tri_vert, " Triangle nodes" );
3357
3358 cout << "\n";
3359 cout << " On each side of a given triangle, there is either\n";
3360 cout << " another triangle, or a piece of the convex hull.\n";
3361 cout << " For each triangle, we list the indices of the three\n";
3362 cout << " neighbors, or (if negative) the codes of the\n";
3363 cout << " segments of the convex hull.\n";
3364
3365 imat_transpose_print ( 3, tri_num, tri_nabe, " Triangle neighbors" );
3366//
3367// Determine VERTEX_NUM, the number of vertices. This is not
3368// the same as the number of points!
3369//
3370 vertex_list = new int[3*tri_num];
3371
3372 k = 0;
3373 for ( t = 0; t < tri_num; t++ )
3374 {
3375 for ( s = 0; s < 3; s++ )
3376 {
3377 vertex_list[k] = tri_vert[s+t*3];
3378 k = k + 1;
3379 }
3380 }
3381
3382 ivec_sort_heap_a ( 3*tri_num, vertex_list );
3383
3384 ivec_sorted_unique ( 3*tri_num, vertex_list, &vertex_num );
3385
3386 delete [] vertex_list;
3387//
3388// Determine the number of boundary points.
3389//
3390 boundary_num = 2 * vertex_num - tri_num - 2;
3391
3392 cout << "\n";
3393 cout << " The number of boundary points is " << boundary_num << "\n";
3394 cout << "\n";
3395 cout << " The segments that make up the convex hull can be\n";
3396 cout << " determined from the negative entries of the triangle\n";
3397 cout << " neighbor list.\n";
3398 cout << "\n";
3399 cout << " # Tri Side N1 N2\n";
3400 cout << "\n";
3401
3402 skip = false;
3403
3404 k = 0;
3405
3406 for ( i = 0; i < tri_num; i++ )
3407 {
3408 for ( j = 0; j < 3; j++ )
3409 {
3410 if ( tri_nabe[j+i*3] < 0 )
3411 {
3412 s = -tri_nabe[j+i*3];
3413 t = s / 3;
3414
3415 if ( t < 1 || tri_num < t )
3416 {
3417 cout << "\n";
3418 cout << " Sorry, this data does not use the DTRIS2\n";
3419 cout << " convention for convex hull segments.\n";
3420 skip = true;
3421 break;
3422 }
3423
3424 s1 = ( s % 3 ) + 1;
3425 s2 = i_wrap ( s1+1, 1, 3 );
3426 k = k + 1;
3427 n1 = tri_vert[s1-1+(t-1)*3];
3428 n2 = tri_vert[s2-1+(t-1)*3];
3429 cout << setw(4) << k << " "
3430 << setw(4) << t << " "
3431 << setw(4) << s1 << " "
3432 << setw(4) << n1 << " "
3433 << setw(4) << n2 << "\n";
3434 }
3435
3436 }
3437
3438 if ( skip )
3439 {
3440 break;
3441 }
3442
3443 }
3444
3445 return;
3446# undef DIM_NUM
3447}
3448//******************************************************************************
3449
3450void vbedg ( double x, double y, int point_num, double point_xy[], int tri_num,
3451 int tri_vert[], int tri_nabe[], int *ltri, int *ledg, int *rtri, int *redg )
3452
3453//******************************************************************************
3454//
3455// Purpose:
3456//
3457// VBEDG determines which boundary edges are visible to a point.
3458//
3459// Discussion:
3460//
3461// The point (X,Y) is assumed to be outside the convex hull of the
3462// region covered by the 2D triangulation.
3463//
3464// Author:
3465//
3466// Barry Joe,
3467// Department of Computing Science,
3468// University of Alberta,
3469// Edmonton, Alberta, Canada T6G 2H1
3470//
3471// Reference:
3472//
3473// Barry Joe,
3474// GEOMPACK - a software package for the generation of meshes
3475// using geometric algorithms,
3476// Advances in Engineering Software,
3477// Volume 13, pages 325-331, 1991.
3478//
3479// Modified:
3480//
3481// 02 September 2003
3482//
3483// Parameters:
3484//
3485// Input, double X, Y, the coordinates of a point outside the convex hull
3486// of the current triangulation.
3487//
3488// Input, int POINT_NUM, the number of points.
3489//
3490// Input, double POINT_XY[POINT_NUM*2], the coordinates of the vertices.
3491//
3492// Input, int TRI_NUM, the number of triangles.
3493//
3494// Input, int TRI_VERT[TRI_NUM*3], the triangle incidence list.
3495//
3496// Input, int TRI_NABE[TRI_NUM*3], the triangle neighbor list; negative
3497// values are used for links of a counter clockwise linked list of boundary
3498// edges;
3499// LINK = -(3*I + J-1) where I, J = triangle, edge index.
3500//
3501// Input/output, int *LTRI, *LEDG. If LTRI != 0 then these values are
3502// assumed to be already computed and are not changed, else they are updated.
3503// On output, LTRI is the index of boundary triangle to the left of the
3504// leftmost boundary triangle visible from (X,Y), and LEDG is the boundary
3505// edge of triangle LTRI to the left of the leftmost boundary edge visible
3506// from (X,Y). 1 <= LEDG <= 3.
3507//
3508// Input/output, int *RTRI. On input, the index of the boundary triangle
3509// to begin the search at. On output, the index of the rightmost boundary
3510// triangle visible from (X,Y).
3511//
3512// Input/output, int *REDG, the edge of triangle RTRI that is visible
3513// from (X,Y). 1 <= REDG <= 3.
3514//
3515{
3516 int a;
3517 double ax;
3518 double ay;
3519 int b;
3520 double bx;
3521 double by;
3522 bool done;
3523 int e;
3524 int l;
3525 int lr;
3526 int t;
3527//
3528// Find the rightmost visible boundary edge using links, then possibly
3529// leftmost visible boundary edge using triangle neighbor information.
3530//
3531 if ( *ltri == 0 )
3532 {
3533 done = false;
3534 *ltri = *rtri;
3535 *ledg = *redg;
3536 }
3537 else
3538 {
3539 done = true;
3540 }
3541
3542 for ( ; ; )
3543 {
3544 l = -tri_nabe[3*((*rtri)-1)+(*redg)-1];
3545 t = l / 3;
3546 e = 1 + l % 3;
3547 a = tri_vert[3*(t-1)+e-1];
3548
3549 if ( e <= 2 )
3550 {
3551 b = tri_vert[3*(t-1)+e];
3552 }
3553 else
3554 {
3555 b = tri_vert[3*(t-1)+0];
3556 }
3557
3558 ax = point_xy[2*(a-1)+0];
3559 ay = point_xy[2*(a-1)+1];
3560
3561 bx = point_xy[2*(b-1)+0];
3562 by = point_xy[2*(b-1)+1];
3563
3564 lr = lrline ( x, y, ax, ay, bx, by, 0.0 );
3565
3566 if ( lr <= 0 )
3567 {
3568 break;
3569 }
3570
3571 *rtri = t;
3572 *redg = e;
3573
3574 }
3575
3576 if ( done )
3577 {
3578 return;
3579 }
3580
3581 t = *ltri;
3582 e = *ledg;
3583
3584 for ( ; ; )
3585 {
3586 b = tri_vert[3*(t-1)+e-1];
3587 e = i_wrap ( e-1, 1, 3 );
3588
3589 while ( 0 < tri_nabe[3*(t-1)+e-1] )
3590 {
3591 t = tri_nabe[3*(t-1)+e-1];
3592
3593 if ( tri_vert[3*(t-1)+0] == b )
3594 {
3595 e = 3;
3596 }
3597 else if ( tri_vert[3*(t-1)+1] == b )
3598 {
3599 e = 1;
3600 }
3601 else
3602 {
3603 e = 2;
3604 }
3605
3606 }
3607
3608 a = tri_vert[3*(t-1)+e-1];
3609 ax = point_xy[2*(a-1)+0];
3610 ay = point_xy[2*(a-1)+1];
3611
3612 bx = point_xy[2*(b-1)+0];
3613 by = point_xy[2*(b-1)+1];
3614
3615 lr = lrline ( x, y, ax, ay, bx, by, 0.0 );
3616
3617 if ( lr <= 0 )
3618 {
3619 break;
3620 }
3621
3622 }
3623
3624 *ltri = t;
3625 *ledg = e;
3626
3627 return;
3628}
scalar y
label k
bool found
label n
const uniformDimensionedVectorField & g
volScalarField & p
void timestamp(void)
Definition geompack.C:2890
int * points_delaunay_naive_2d(int n, double p[], int *ntri)
Definition geompack.C:2433
int lrline(double xu, double yu, double xv1, double yv1, double xv2, double yv2, double dv)
Definition geompack.C:2203
void dvec_print(int n, double a[], const char *title)
Definition geompack.C:1449
int dtris2(int point_num, double point_xy[], int *tri_num, int tri_vert[], int tri_nabe[])
Definition geompack.C:953
#define LEVEL_MAX
void vbedg(double x, double y, int point_num, double point_xy[], int tri_num, int tri_vert[], int tri_nabe[], int *ltri, int *ledg, int *rtri, int *redg)
Definition geompack.C:3450
int * ivec_indicator(int n)
Definition geompack.C:2041
int i_modp(int i, int j)
Definition geompack.C:1601
void imat_transpose_print(int m, int n, int a[], const char *title)
Definition geompack.C:1787
double d_min(double x, double y)
Definition geompack.C:95
void imat_transpose_print_some(int m, int n, int a[], int ilo, int jlo, int ihi, int jhi, const char *title)
Definition geompack.C:1820
int i_max(int i1, int i2)
Definition geompack.C:1531
void d2vec_sort_quick_a(int n, double a[])
Definition geompack.C:514
#define DIM_NUM
void triangulation_print(int point_num, double xc[], int tri_num, int tri_vert[], int tri_nabe[])
Definition geompack.C:3280
void perm_inv(int n, int p[])
Definition geompack.C:2346
void dmat_transpose_print_some(int m, int n, double a[], int ilo, int jlo, int ihi, int jhi, const char *title)
Definition geompack.C:780
bool perm_check(int n, int p[])
Definition geompack.C:2288
int swapec(int i, int *top, int *btri, int *bedg, int point_num, double point_xy[], int tri_num, int tri_vert[], int tri_nabe[], int stack[])
Definition geompack.C:2612
void ivec_sort_heap_a(int n, int a[])
Definition geompack.C:2078
void d2vec_permute(int n, double a[], int p[])
Definition geompack.C:259
#define INCX
bool dvec_eq(int n, double a1[], double a2[])
Definition geompack.C:1301
void ivec_sorted_unique(int n, int a[], int *nuniq)
Definition geompack.C:2152
int i_min(int i1, int i2)
Definition geompack.C:1566
int s_len_trim(const char *s)
Definition geompack.C:2568
void d2vec_part_quick_a(int n, double a[], int *l, int *r)
Definition geompack.C:129
void dmat_transpose_print(int m, int n, double a[], const char *title)
Definition geompack.C:749
int i_sign(int i)
Definition geompack.C:1676
double d_max(double x, double y)
Definition geompack.C:61
#define TIME_SIZE
int * d2vec_sort_heap_index_a(int n, double a[])
Definition geompack.C:384
bool dvec_lt(int n, double a1[], double a2[])
Definition geompack.C:1396
int diaedg(double x0, double y0, double x1, double y1, double x2, double y2, double x3, double y3)
Definition geompack.C:632
double d_epsilon(void)
Definition geompack.C:19
bool triangulation_plot_eps(const char *file_out_name, int g_num, double g_xy[], int tri_num, int nod_tri[])
Definition geompack.C:3053
int i_wrap(int ival, int ilo, int ihi)
Definition geompack.C:1715
void dmat_uniform(int m, int n, double b, double c, int *seed, double r[])
Definition geompack.C:866
void ivec_heap_d(int n, int a[])
Definition geompack.C:1917
double * triangle_circumcenter_2d(double t[])
Definition geompack.C:2980
void dvec_swap(int n, double a1[], double a2[])
Definition geompack.C:1494
bool dvec_gt(int n, double a1[], double a2[])
Definition geompack.C:1342
char * timestring(void)
Definition geompack.C:2937
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
labelList f(nPoints)
volScalarField & b
volScalarField & e