Files
LBPM/analysis/pmmc.h
2018-05-15 14:06:53 -04:00

4609 lines
145 KiB
C++

#ifndef pmmc_INC
#define pmmc_INC
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <math.h>
#include "common/Array.h"
#include "PointList.h"
#include "common/Utilities.h"
using namespace std;
static int edgeTable[256]={
0x0 , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c,
0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac,
0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c,
0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc,
0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c,
0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc ,
0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460,
0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0,
0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230,
0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190,
0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 };
static signed char triTable[256][16] =
{{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1},
{3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1},
{3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1},
{3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1},
{9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1},
{1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1},
{9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
{2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1},
{8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1},
{9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
{4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1},
{3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1},
{1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1},
{4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1},
{4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1},
{9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1},
{1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
{5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1},
{2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1},
{9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
{0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
{2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1},
{10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1},
{4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1},
{5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1},
{5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1},
{9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1},
{0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1},
{1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1},
{10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1},
{8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1},
{2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1},
{7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1},
{9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1},
{2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1},
{11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1},
{9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1},
{5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1},
{11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1},
{11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
{1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1},
{9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1},
{5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1},
{2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
{0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
{5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1},
{6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1},
{0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1},
{3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1},
{6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1},
{5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1},
{1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
{10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1},
{6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1},
{1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1},
{8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1},
{7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1},
{3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
{5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1},
{0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1},
{9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1},
{8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1},
{5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1},
{0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1},
{6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1},
{10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1},
{10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1},
{8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1},
{1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1},
{3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1},
{0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1},
{10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1},
{0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1},
{3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1},
{6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1},
{9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1},
{8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1},
{3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1},
{6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1},
{0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1},
{10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1},
{10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1},
{1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1},
{2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1},
{7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1},
{7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1},
{2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1},
{1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1},
{11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1},
{8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1},
{0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1},
{7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
{10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
{2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
{6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1},
{7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1},
{2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1},
{1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1},
{10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1},
{10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1},
{0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1},
{7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1},
{6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1},
{8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1},
{9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1},
{6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1},
{1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1},
{4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1},
{10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1},
{8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1},
{0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1},
{1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1},
{8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1},
{10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1},
{4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1},
{10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
{5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
{11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1},
{9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
{6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1},
{7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1},
{3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1},
{7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1},
{9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1},
{3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1},
{6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1},
{9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1},
{1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1},
{4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1},
{7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1},
{6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1},
{3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1},
{0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1},
{6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1},
{1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1},
{0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1},
{11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1},
{6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1},
{5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1},
{9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1},
{1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1},
{1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1},
{10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1},
{0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1},
{5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1},
{10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1},
{11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1},
{0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1},
{9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1},
{7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1},
{2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1},
{8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1},
{9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1},
{9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1},
{1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1},
{9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1},
{9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1},
{5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1},
{0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1},
{10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1},
{2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1},
{0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1},
{0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1},
{9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1},
{5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1},
{3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1},
{5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1},
{8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1},
{0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1},
{9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1},
{0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1},
{1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1},
{3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1},
{4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1},
{9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1},
{11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1},
{11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1},
{2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1},
{9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1},
{3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1},
{1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1},
{4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1},
{4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1},
{0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1},
{3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1},
{3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1},
{0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1},
{9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1},
{1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}};
//--------------------------------------------------------------------------------------------------------
class TriLinPoly{
/* Compute a tri-linear polynomial within a given cube (i,j,k) x (i+1,j+1,k+1)
* Values are provided at the corners in CubeValues
* x,y,z must be defined on [0,1] where the length of the cube edge is one
*/
int ic,jc,kc;
double a,b,c,d,e,f,g,h;
double x,y,z;
public:
DoubleArray Corners;
TriLinPoly(){
Corners.resize(2,2,2);
}
~TriLinPoly(){
}
// Assign the polynomial within a cube from a mesh
void assign(DoubleArray &A, int i, int j, int k){
// Save the cube indices
ic=i; jc=j; kc=k;
// local copy of the cube values
Corners(0,0,0) = A(i,j,k);
Corners(1,0,0) = A(i+1,j,k);
Corners(0,1,0) = A(i,j+1,k);
Corners(1,1,0) = A(i+1,j+1,k);
Corners(0,0,1) = A(i,j,k+1);
Corners(1,0,1) = A(i+1,j,k+1);
Corners(0,1,1) = A(i,j+1,k+1);
Corners(1,1,1) = A(i+1,j+1,k+1);
// coefficients of the tri-linear approximation
a = Corners(0,0,0);
b = Corners(1,0,0)-a;
c = Corners(0,1,0)-a;
d = Corners(0,0,1)-a;
e = Corners(1,1,0)-a-b-c;
f = Corners(1,0,1)-a-b-d;
g = Corners(0,1,1)-a-c-d;
h = Corners(1,1,1)-a-b-c-d-e-f-g;
}
// Assign polynomial based on values manually assigned to Corners
void assign(){
ic=0; jc=0; kc=0;
// coefficients of the tri-linear approximation
a = Corners(0,0,0);
b = Corners(1,0,0)-a;
c = Corners(0,1,0)-a;
d = Corners(0,0,1)-a;
e = Corners(1,1,0)-a-b-c;
f = Corners(1,0,1)-a-b-d;
g = Corners(0,1,1)-a-c-d;
h = Corners(1,1,1)-a-b-c-d-e-f-g;
}
// Evaluate the polynomial at a point
double eval(Point P){
double returnValue;
x = P.x - 1.0*ic;
y = P.y - 1.0*jc;
z = P.z - 1.0*kc;
returnValue = a + b*x + c*y+d*z + e*x*y + f*x*z + g*y*z + h*x*y*z;
return returnValue;
}
};
//--------------------------------------------------------------------------------------------------
/*
inline DoubleArray SOLVE( DoubleArray &A, DoubleArray &b)
{
// solves the system A*x = b exactly
DoubleArray AA = A.Copy();
long int n = A.n;
long int nrhs =1;
IntArray piv(2*n);
DoubleArray solution = b.Copy();
long int info = 0;
int ret = dgesv_(&n,&nrhs,AA.Pointer(),&n,(long int *)piv.Pointer(),solution.Pointer(),&n,&info);
// DTErrorMessage("Computation", string("Error=")+ DTInt2String(ret) + "info = " + DTInt2String(info));
return solution;
}
//-----------------------------------------------------------------------------
inline Point NEWTON(Point x0, DoubleArray &F, double &v,DoubleArray &S, int i, int j, int k, int &newton_steps)
{
Point pt;
// Performs a Newton iteration to compute the point x from initial guess x0
double tol = 0.001;
double dist = 1;
// Map x0 into unit coordinates
Point X0 = x0;
x0.x = x0.x - i;
x0.y = x0.y - j;
x0.z = x0.z - k;
// Compute coefficients for tri-linear approximations to the functions F and S
// coefficients for F
double Af, Bf, Cf, Df, Ef, Ff, Gf, Hf;
Af = F(i,j,k);
Bf = F(i+1,j,k)-Af;
Cf = F(i,j+1,k)-Af;
Df = F(i,j,k+1)-Af;
Ef = F(i+1,j+1,k)-Af-Bf-Cf;
Ff = F(i+1,j,k+1)-Af-Bf-Df;
Gf = F(i,j+1,k+1)-Af-Cf-Df;
Hf = F(i+1,j+1,k+1)-Af-Bf-Cf-Df-Ef-Ff-Gf;
// coefficients for S
double As, Bs, Cs, Ds, Es, Fs, Gs, Hs;
As = S(i,j,k);
Bs = S(i+1,j,k)-As;
Cs = S(i,j+1,k)-As;
Ds = S(i,j,k+1)-As;
Es = S(i+1,j+1,k)-As-Bs-Cs;
Fs = S(i+1,j,k+1)-As-Bs-Ds;
Gs = S(i,j+1,k+1)-As-Cs-Ds;
Hs = S(i+1,j+1,k+1)-As-Bs-Cs-Ds-Es-Fs-Gs;
// Compute coefficients for plane in direction of grad F, grad S at point x0
// Compute grad u = grad F , v = grad S
int count; int number;
count = 0;
number = int(floor(newton_steps));
//number = 2;
pt = x0;
bool pt_on_cube_leg = 0;
// Compute the u = grad F, v = grad S and the normal vector N = u x v
double u1, u2, u3, v1, v2, v3;
u1 = Bf+Ef*x0.y+Ff*x0.z+Hf*x0.y*x0.z;
u2 = Cf+Ef*x0.x+Gf*x0.z+Hf*x0.x*x0.z;
u3 = Df+Ff*x0.x+Gf*x0.y+Hf*x0.x*x0.y;
v1 = Bs+Es*x0.y+Fs*x0.z+Hs*x0.y*x0.z;
v2 = Cs+Es*x0.x+Gs*x0.z+Hs*x0.x*x0.z;
v3 = Ds+Fs*x0.x+Gs*x0.y+Hs*x0.x*x0.y;
// Compute the normal vector N
Point N;
if (x0.x == 0 || x0.x == 1){
if (x0.y == 0 || x0.y == 1){
// on a cube leg
pt_on_cube_leg = 1;
}
else if (x0.z == 0 || x0.z == 1){
// on a cube leg
pt_on_cube_leg = 1;
}
else {
// use this cube face as the normal
N.x = 1;
N.y = 0;
N.z = 0;
}
}
else if (x0.y == 0 || x0.y == 1){
if (x0.z == 0 || x0.z == 1){
// on a cube leg
pt_on_cube_leg = 1;
}
else {
// use this cube face as the normal
N.x = 0;
N.y = 1;
N.z = 0;
}
}
else if (x0.z == 0 || x0.z == 1){
// use this cube face as the normal
N.x = 0;
N.y = 0;
N.z = 1;
}
else {
// Compute N = u x v
N.x = u2*v3 - u3*v2;
N.y = u3*v1 - u1*v3;
N.z = u1*v2 - u2*v1;
}
if ( pt_on_cube_leg == 1){
// return x0
pt = x0;
}
else {
while (count < number ){
// Construct the Jacobean Matrix J
DoubleArray J(3,3);
J(0,0) = u1;
J(0,1) = u2;
J(0,2) = u3;
J(1,0) = v1;
J(1,1) = v2;
J(1,2) = v3;
J(2,0) = N.x;
J(2,1) = N.y;
J(2,2) = N.z;
// Evaluate the vector M(x0)
DoubleArray M(3);
M(0) = -(Af+Bf*x0.x+Cf*x0.y+Df*x0.z+Ef*x0.x*x0.y+Ff*x0.x*x0.z+Gf*x0.y*x0.z+Hf*x0.x*x0.y*x0.z - v);
M(1) = -(As+Bs*x0.x+Cs*x0.y+Ds*x0.z+Es*x0.x*x0.y+Fs*x0.x*x0.z+Gs*x0.y*x0.z+Hs*x0.x*x0.y*x0.z);
M(2) = 0;
// Compute the update to x0 using Newton's method
Point dX;
DoubleArray d = SOLVE(J,M);
dX.x = d(0);
dX.y = d(1);
dX.z = d(2);
if ( dX.x > 0.1 || dX.y > 0.1 || dX.z > 0.1 ||
dX.x < -0.1 || dX.y < -0.1 || dX.z < -0.1){
count = number;
}
else {
pt = x0+dX;
x0 = pt;
}
M(0) = -(Af+Bf*x0.x+Cf*x0.y+Df*x0.z+Ef*x0.x*x0.y+Ff*x0.x*x0.z+Gf*x0.y*x0.z+Hf*x0.x*x0.y*x0.z - v);
M(1) = -(As+Bs*x0.x+Cs*x0.y+Ds*x0.z+Es*x0.x*x0.y+Fs*x0.x*x0.z+Gs*x0.y*x0.z+Hs*x0.x*x0.y*x0.z);
M(2) = 0;
dist = sqrt(M(0)*M(0)+M(1)*M(1)+M(2)*M(2));
// Compute u, v at new x0
u1 = Bf+Ef*x0.y+Ff*x0.z+Hf*x0.y*x0.z;
u2 = Cf+Ef*x0.x+Gf*x0.z+Hf*x0.x*x0.z;
u3 = Df+Ff*x0.x+Gf*x0.y+Hf*x0.x*x0.y;
v1 = Bs+Es*x0.y+Fs*x0.z+Hs*x0.y*x0.z;
v2 = Cs+Es*x0.x+Gs*x0.z+Hs*x0.x*x0.z;
v3 = Ds+Fs*x0.x+Gs*x0.y+Hs*x0.x*x0.y;
count++;
}
}
// map pt back to original coordinates
pt.x = pt.x+i;
pt.y = pt.y+j;
pt.z = pt.z+k;
return pt;
}
*/
//--------------------------------------------------------------------------------------------------
inline bool vertexcheck(Point &P, int n, int pos, DTMutableList<Point> &cellvertices){
// returns true if P is a new vertex (one previously unencountered
bool V = 1;
int i = pos-n;
for (i = pos-n; i < pos; i++){
if ( P == cellvertices(i)){
V = 0;
}
}
return V;
}
//--------------------------------------------------------------------------------------------------
inline bool ShareSide( Point &A, Point &B)
{
// returns true if points A and B share an x,y, or z coordinate
bool l = 0;
if ( A.x != B.x && A.y != B.y && A.z != B.z){
l=0;
}
else{
if (floor(A.x)==A.x && floor(B.x)==B.x && A.x==B.x) {
l = 1;
}
if (floor(A.y)==A.y && floor(B.y)==B.y && A.y==B.y) {
l = 1;
}
if (floor(A.z)==A.z && floor(B.z)==B.z && A.z==B.z) {
l = 1;
}
}
return l;
}
//--------------------------------------------------------------------------------------------------
inline bool Interface( DoubleArray &A, const double v, int i, int j, int k){
// returns true if grid cell i, j, k contains a section of the interface
bool Y = 0;
if ((A(i,j,k)-v)*(A(i+1,j,k)-v) < 0 ){
Y=1;
}
// 2
if ((A(i+1,j,k)-v)*(A(i+1,j+1,k)-v) < 0){
Y=1;
}
//3
if ((A(i+1,j+1,k)-v)*(A(i,j+1,k)-v) < 0){
Y=1;
}
//4
if ((A(i,j+1,k)-v)*(A(i,j,k)-v) < 0 ){
Y=1;
}
//5
if ((A(i,j,k)-v)*(A(i,j,k+1)-v) < 0 ){
Y=1;
}
//6
if ((A(i+1,j,k)-v)*(A(i+1,j,k+1)-v) < 0 ){
Y=1;
}
//7
if ((A(i+1,j+1,k)-v)*(A(i+1,j+1,k+1)-v) < 0 ){
Y=1;
}
//8
if ((A(i,j+1,k)-v)*(A(i,j+1,k+1)-v) < 0 ){
Y=1;
}
//9
if ((A(i,j,k+1)-v)*(A(i+1,j,k+1)-v) < 0 ){
Y=1;
}
//10
if ((A(i+1,j,k+1)-v)*(A(i+1,j+1,k+1)-v) < 0 ){
Y=1;
}
//11
if ((A(i+1,j+1,k+1)-v)*(A(i,j+1,k+1)-v) < 0 ){
Y=1;
}
//12
if ((A(i,j+1,k+1)-v)*(A(i,j,k+1)-v) < 0 ){
Y=1;
}
return Y;
}
//--------------------------------------------------------------------------------------------------
inline bool Fluid_Interface( DoubleArray &A, DoubleArray &S, const double v, int i, int j, int k){
// returns true if grid cell i, j, k contains a section of the interface
bool Y = 0;
if ((A(i,j,k)-v)*(A(i+1,j,k)-v) < 0 && S(i,j,k) > 0 && S(i+1,j,k) > 0){
Y=1;
}
// 2
if ((A(i+1,j,k)-v)*(A(i+1,j+1,k)-v) < 0 && S(i+1,j,k) > 0 && S(i+1,j+1,k) > 0){
Y=1;
}
//3
if ((A(i+1,j+1,k)-v)*(A(i,j+1,k)-v) < 0 && S(i+1,j+1,k) > 0 && S(i,j+1,k) > 0){
Y=1;
}
//4
if ((A(i,j+1,k)-v)*(A(i,j,k)-v) < 0 && S(i,j,k) > 0 && S(i,j+1,k) > 0){
Y=1;
}
//5
if ((A(i,j,k)-v)*(A(i,j,k+1)-v) < 0 && S(i,j,k) > 0 && S(i,j,k+1) > 0){
Y=1;
}
//6
if ((A(i+1,j,k)-v)*(A(i+1,j,k+1)-v) < 0 && S(i+1,j,k) > 0 && S(i+1,j,k+1) > 0){
Y=1;
}
//7
if ((A(i+1,j+1,k)-v)*(A(i+1,j+1,k+1)-v) < 0 && S(i+1,j+1,k) > 0 && S(i+1,j+1,k+1) > 0){
Y=1;
}
//8
if ((A(i,j+1,k)-v)*(A(i,j+1,k+1)-v) < 0 && S(i,j+1,k) > 0 && S(i,j+1,k+1) > 0){
Y=1;
}
//9
if ((A(i,j,k+1)-v)*(A(i+1,j,k+1)-v) < 0 && S(i,j,k+1) > 0 && S(i+1,j,k+1) > 0){
Y=1;
}
//10
if ((A(i+1,j,k+1)-v)*(A(i+1,j+1,k+1)-v) < 0 && S(i+1,j,k+1) > 0 && S(i+1,j+1,k+1) > 0){
Y=1;
}
//11
if ((A(i+1,j+1,k+1)-v)*(A(i,j+1,k+1)-v) < 0 && S(i+1,j+1,k+1) > 0 && S(i,j+1,k+1) > 0){
Y=1;
}
//12
if ((A(i,j+1,k+1)-v)*(A(i,j,k+1)-v) < 0 && S(i,j,k+1) > 0 && S(i,j+1,k+1) > 0){
Y=1;
}
return Y;
}
//--------------------------------------------------------------------------------------------------
inline bool Solid( DoubleArray &A, int i, int j, int k){
bool X = 0;
// return 0 if there is no solid phase in grid cell i,j,k
if (A(i,j,k) == 0){
X = 1;
}
if (A(i+1,j,k) == 0){
X = 1;
}
if (A(i,j+1,k) == 0){
X = 1;
}
if (A(i,j,k+1) == 0){
X = 1;
}
if (A(i+1,j+1,k) == 0){
X = 1;
}
if (A(i+1,j,k+1) == 0){
X = 1;
}
if (A(i,j+1,k+1) == 0){
X = 1;
}
if (A(i+1,j+1,k+1) == 0){
X = 1;
}
return X;
}
//-------------------------------------------------------------------------------
inline Point VertexInterp(const Point &p1, const Point &p2, double valp1, double valp2)
{
return (p1 + (-valp1 / (valp2 - valp1)) * (p2 - p1));
}
//-------------------------------------------------------------------------------
inline void SolidMarchingCubes(DoubleArray &A, const double &v, DoubleArray &B, const double &isovalue,
int i,int j,int k, int m, int n, int o, DTMutableList<Point>
&cellvertices, int &lengthvertices, IntArray &Triangles, int &nTris,
DoubleArray &values)
{
NULL_USE( isovalue );
NULL_USE( m );
NULL_USE( n );
NULL_USE( o );
// THIS SUBROUTINE COMPUTES THE VERTICES FOR THE SOLID PHASE IN
// A PARTICULAR GRID CELL, THEN ARRANGES THEM INTO TRIANGLES
// ALSO ORGANIZES THE LIST OF VALUES TO CORRESPOND WITH VERTEX LIST
NULL_USE( v );
//int N = 0;
Point P,Q;
Point PlaceHolder;
//int pos = lengthvertices;
double temp;
Point C0,C1,C2,C3,C4,C5,C6,C7;
int TriangleCount;
int NewVertexCount;
int CubeIndex;
Point VertexList[12];
Point NewVertexList[12];
double ValueList[12];
double NewValueList[12];
int LocalRemap[12];
// int m; int n; int o;
//int p; int q;
// Values from array 'A' at the cube corners
double CubeValues[8];
CubeValues[0] = A(i,j,k);
CubeValues[1] = A(i+1,j,k);
CubeValues[2] = A(i+1,j+1,k);
CubeValues[3] = A(i,j+1,k);
CubeValues[4] = A(i,j,k+1);
CubeValues[5] = A(i+1,j,k+1);
CubeValues[6] = A(i+1,j+1,k+1);
CubeValues[7] = A(i,j+1,k+1);
// Values from array 'B' at the cube corners
double CubeValues_B[8];
CubeValues_B[0] = B(i,j,k);
CubeValues_B[1] = B(i+1,j,k);
CubeValues_B[2] = B(i+1,j+1,k);
CubeValues_B[3] = B(i,j+1,k);
CubeValues_B[4] = B(i,j,k+1);
CubeValues_B[5] = B(i+1,j,k+1);
CubeValues_B[6] = B(i+1,j+1,k+1);
CubeValues_B[7] = B(i,j+1,k+1);
// Points corresponding to cube corners
C0.x = 0.0; C0.y = 0.0; C0.z = 0.0;
C1.x = 1.0; C1.y = 0.0; C1.z = 0.0;
C2.x = 1.0; C2.y = 1.0; C2.z = 0.0;
C3.x = 0.0; C3.y = 1.0; C3.z = 0.0;
C4.x = 0.0; C4.y = 0.0; C4.z = 1.0;
C5.x = 1.0; C5.y = 0.0; C5.z = 1.0;
C6.x = 1.0; C6.y = 1.0; C6.z = 1.0;
C7.x = 0.0; C7.y = 1.0; C7.z = 1.0;
//Determine the index into the edge table which
//tells us which vertices are inside of the surface
CubeIndex = 0;
if (CubeValues[0] < 0.0f) CubeIndex |= 1;
if (CubeValues[1] < 0.0f) CubeIndex |= 2;
if (CubeValues[2] < 0.0f) CubeIndex |= 4;
if (CubeValues[3] < 0.0f) CubeIndex |= 8;
if (CubeValues[4] < 0.0f) CubeIndex |= 16;
if (CubeValues[5] < 0.0f) CubeIndex |= 32;
if (CubeValues[6] < 0.0f) CubeIndex |= 64;
if (CubeValues[7] < 0.0f) CubeIndex |= 128;
//Find the vertices where the surface intersects the cube
if (edgeTable[CubeIndex] & 1){
P = VertexInterp(C0,C1,CubeValues[0],CubeValues[1]);
VertexList[0] = P;
Q = C0;
temp = sqrt((P.x-Q.x)*(P.x-Q.x)+(P.y-Q.y)*(P.y-Q.y)+(P.z-Q.z)*(P.z-Q.z));
ValueList[0] = CubeValues_B[0] + temp*(CubeValues_B[1]-CubeValues_B[0]);
}
if (edgeTable[CubeIndex] & 2){
P = VertexInterp(C1,C2,CubeValues[1],CubeValues[2]);
VertexList[1] = P;
Q = C1;
temp = sqrt((P.x-Q.x)*(P.x-Q.x)+(P.y-Q.y)*(P.y-Q.y)+(P.z-Q.z)*(P.z-Q.z));
ValueList[1] = CubeValues_B[1] + temp*(CubeValues_B[2]-CubeValues_B[1]);
}
if (edgeTable[CubeIndex] & 4){
P = VertexInterp(C2,C3,CubeValues[2],CubeValues[3]);
VertexList[2] = P;
Q = C2;
temp = sqrt((P.x-Q.x)*(P.x-Q.x)+(P.y-Q.y)*(P.y-Q.y)+(P.z-Q.z)*(P.z-Q.z));
ValueList[2] = CubeValues_B[2] + temp*(CubeValues_B[3]-CubeValues_B[2]);
}
if (edgeTable[CubeIndex] & 8){
P = VertexInterp(C3,C0,CubeValues[3],CubeValues[0]);
VertexList[3] = P;
Q = C3;
temp = sqrt((P.x-Q.x)*(P.x-Q.x)+(P.y-Q.y)*(P.y-Q.y)+(P.z-Q.z)*(P.z-Q.z));
ValueList[3] = CubeValues_B[3] + temp*(CubeValues_B[0]-CubeValues_B[3]);
}
if (edgeTable[CubeIndex] & 16){
P = VertexInterp(C4,C5,CubeValues[4],CubeValues[5]);
VertexList[4] = P;
Q = C4;
temp = sqrt((P.x-Q.x)*(P.x-Q.x)+(P.y-Q.y)*(P.y-Q.y)+(P.z-Q.z)*(P.z-Q.z));
ValueList[4] = CubeValues_B[4] + temp*(CubeValues_B[5]-CubeValues_B[4]);
}
if (edgeTable[CubeIndex] & 32){
P = VertexInterp(C5,C6,CubeValues[5],CubeValues[6]);
VertexList[5] = P;
Q = C5;
temp = sqrt((P.x-Q.x)*(P.x-Q.x)+(P.y-Q.y)*(P.y-Q.y)+(P.z-Q.z)*(P.z-Q.z));
ValueList[5] = CubeValues_B[5] + temp*(CubeValues_B[6]-CubeValues_B[5]);
}
if (edgeTable[CubeIndex] & 64){
P = VertexInterp(C6,C7,CubeValues[6],CubeValues[7]);
VertexList[6] = P;
Q = C6;
temp = sqrt((P.x-Q.x)*(P.x-Q.x)+(P.y-Q.y)*(P.y-Q.y)+(P.z-Q.z)*(P.z-Q.z));
ValueList[6] = CubeValues_B[6] + temp*(CubeValues_B[7]-CubeValues_B[6]);
}
if (edgeTable[CubeIndex] & 128){
P = VertexInterp(C7,C4,CubeValues[7],CubeValues[4]);
VertexList[7] = P;
Q = C7;
temp = sqrt((P.x-Q.x)*(P.x-Q.x)+(P.y-Q.y)*(P.y-Q.y)+(P.z-Q.z)*(P.z-Q.z));
ValueList[7] = CubeValues_B[7] + temp*(CubeValues_B[4]-CubeValues_B[7]);
}
if (edgeTable[CubeIndex] & 256){
P = VertexInterp(C0,C4,CubeValues[0],CubeValues[4]);
VertexList[8] = P;
Q = C0;
temp = sqrt((P.x-Q.x)*(P.x-Q.x)+(P.y-Q.y)*(P.y-Q.y)+(P.z-Q.z)*(P.z-Q.z));
ValueList[8] = CubeValues_B[0] + temp*(CubeValues_B[4]-CubeValues_B[0]);
}
if (edgeTable[CubeIndex] & 512){
P = VertexInterp(C1,C5,CubeValues[1],CubeValues[5]);
VertexList[9] = P;
Q = C1;
temp = sqrt((P.x-Q.x)*(P.x-Q.x)+(P.y-Q.y)*(P.y-Q.y)+(P.z-Q.z)*(P.z-Q.z));
ValueList[9] = CubeValues_B[1] + temp*(CubeValues_B[5]-CubeValues_B[1]);
}
if (edgeTable[CubeIndex] & 1024){
P = VertexInterp(C2,C6,CubeValues[2],CubeValues[6]);
VertexList[10] = P;
Q = C2;
temp = sqrt((P.x-Q.x)*(P.x-Q.x)+(P.y-Q.y)*(P.y-Q.y)+(P.z-Q.z)*(P.z-Q.z));
ValueList[10] = CubeValues_B[2] + temp*(CubeValues_B[6]-CubeValues_B[2]);
}
if (edgeTable[CubeIndex] & 2048){
P = VertexInterp(C3,C7,CubeValues[3],CubeValues[7]);
VertexList[11] = P;
Q = C3;
temp = sqrt((P.x-Q.x)*(P.x-Q.x)+(P.y-Q.y)*(P.y-Q.y)+(P.z-Q.z)*(P.z-Q.z));
ValueList[11] = CubeValues_B[3] + temp*(CubeValues_B[7]-CubeValues_B[3]);
}
NewVertexCount=0;
for (int idx=0;idx<12;idx++)
LocalRemap[idx] = -1;
for (int idx=0;triTable[CubeIndex][idx]!=-1;idx++)
{
if(LocalRemap[triTable[CubeIndex][idx]] == -1)
{
NewVertexList[NewVertexCount] = VertexList[triTable[CubeIndex][idx]];
NewValueList[NewVertexCount] = ValueList[triTable[CubeIndex][idx]];
LocalRemap[triTable[CubeIndex][idx]] = NewVertexCount;
NewVertexCount++;
}
}
for (int idx=0;idx<NewVertexCount;idx++) {
P = NewVertexList[idx];
P.x += i;
P.y += j;
P.z += k;
cellvertices(idx) = P;
values(idx) = NewValueList[idx];
}
lengthvertices = NewVertexCount;
TriangleCount = 0;
for (int idx=0;triTable[CubeIndex][idx]!=-1;idx+=3) {
Triangles(0,TriangleCount) = LocalRemap[triTable[CubeIndex][idx+0]];
Triangles(1,TriangleCount) = LocalRemap[triTable[CubeIndex][idx+1]];
Triangles(2,TriangleCount) = LocalRemap[triTable[CubeIndex][idx+2]];
TriangleCount++;
}
nTris = TriangleCount;
// * * * ARRANGE VERTICES SO THAT NEIGHBORS SHARE A FACE * * *
// * * * PERFORM SAME OPERATIONS TO THE LIST OF VALUES * * *
/* pos = N = lengthvertices;
for (q = pos-N; q < pos-2; q++) {
for (o = q+2; o < pos-1; o++) {
if (ShareSide(cellvertices(q), cellvertices(o)) == 1) {
PlaceHolder = cellvertices(q+1);
cellvertices(q+1) = cellvertices(o);
cellvertices(o) = PlaceHolder;
temp = values(q+1);
values(q+1) = values(o);
values(o) = temp;
// Swap the triangle lists as needed
for (int idx=0; idx<TriangleCount; idx++){
if (Triangles(0,idx) == q+1) Triangles(0,idx) = o;
else if (Triangles(0,idx) == o) Triangles(0,idx) = q+1;
if (Triangles(1,idx) == q+1) Triangles(1,idx) = o;
else if (Triangles(1,idx) == o) Triangles(1,idx) = q+1;
if (Triangles(2,idx) == q+1) Triangles(2,idx) = o;
else if (Triangles(2,idx) == o) Triangles(2,idx) = q+1;
}
}
}
// make sure other neighbor of vertex 1 is in last spot
if (q == pos-N){
for (p = q+2; p < pos-1; p++){
if (ShareSide(cellvertices(q), cellvertices(p)) == 1){
PlaceHolder = cellvertices(pos-1);
cellvertices(pos-1) = cellvertices(p);
cellvertices(p) = PlaceHolder;
temp = values(pos-1);
values(pos-1) = values(p);
values(p) = temp;
// Swap the triangle lists as needed
for (int idx=0; idx<TriangleCount; idx++){
if (Triangles(0,idx) == p) Triangles(0,idx) = pos-1;
else if (Triangles(0,idx) == pos-1) Triangles(0,idx) = p;
if (Triangles(1,idx) == p) Triangles(1,idx) = pos-1;
else if (Triangles(1,idx) == pos-1) Triangles(1,idx) = p;
if (Triangles(2,idx) == p) Triangles(2,idx) = pos-1;
else if (Triangles(2,idx) == pos-1) Triangles(2,idx) = p;
}
}
}
}
if ( ShareSide(cellvertices(pos-2), cellvertices(pos-3)) != 1 ){
if (ShareSide( cellvertices(pos-3), cellvertices(pos-1)) == 1 && ShareSide( cellvertices(pos-N),
cellvertices(pos-2)) == 1 ){
PlaceHolder = cellvertices(pos-2);
cellvertices(pos-2) = cellvertices(pos-1);
cellvertices(pos-1) = PlaceHolder;
temp = values(pos-2);
values(pos-2) = values(pos-1);
values(pos-1) = temp;
// Swap the triangle lists as needed
for (int idx=0; idx<TriangleCount; idx++){
if (Triangles(0,idx) == pos-1) Triangles(0,idx) = pos-2;
else if (Triangles(0,idx) == pos-2) Triangles(0,idx) = pos-1;
if (Triangles(1,idx) == pos-1) Triangles(1,idx) = pos-2;
else if (Triangles(1,idx) == pos-2) Triangles(1,idx) = pos-1;
if (Triangles(2,idx) == pos-1) Triangles(2,idx) = pos-2;
else if (Triangles(2,idx) == pos-2) Triangles(2,idx) = pos-1;
}
}
}
if ( ShareSide(cellvertices(pos-1), cellvertices(pos-2)) != 1 ){
if (ShareSide( cellvertices(pos-3), cellvertices(pos-1)) == 1 && ShareSide(cellvertices(pos-4),
cellvertices(pos-2)) == 1 ){
PlaceHolder = cellvertices(pos-3);
cellvertices(pos-3) = cellvertices(pos-2);
cellvertices(pos-2) = PlaceHolder;
temp = values(pos-3);
values(pos-3) = values(pos-2);
values(pos-2) = temp;
// Swap the triangle lists as needed
for (int idx=0; idx<TriangleCount; idx++){
if (Triangles(0,idx) == pos-2) Triangles(0,idx) = pos-3;
else if (Triangles(0,idx) == pos-2) Triangles(0,idx) = pos-2;
if (Triangles(1,idx) == pos-2) Triangles(1,idx) = pos-3;
else if (Triangles(1,idx) == pos-2) Triangles(1,idx) = pos-2;
if (Triangles(2,idx) == pos-2) Triangles(2,idx) = pos-3;
else if (Triangles(2,idx) == pos-2) Triangles(2,idx) = pos-2;
}
}
if (ShareSide( cellvertices(pos-N+1), cellvertices(pos-3)) == 1 && ShareSide(cellvertices(pos-1),
cellvertices(pos-N+1)) == 1 ){
PlaceHolder = cellvertices(pos-2);
cellvertices(pos-2) = cellvertices(pos-N+1);
cellvertices(pos-N+1) = PlaceHolder;
temp = values(pos-2);
values(pos-2) = values(pos-N+1);
values(pos-N+1) = temp;
// Swap the triangle lists as needed
for (int idx=0; idx<TriangleCount; idx++){
if (Triangles(0,idx) == pos-N+1) Triangles(0,idx) = pos-2;
else if (Triangles(0,idx) == pos-2) Triangles(0,idx) = pos-N+1;
if (Triangles(1,idx) == pos-N+1) Triangles(1,idx) = pos-2;
else if (Triangles(1,idx) == pos-2) Triangles(1,idx) = pos-N+1;
if (Triangles(2,idx) == pos-N+1) Triangles(2,idx) = pos-2;
else if (Triangles(2,idx) == pos-2) Triangles(2,idx) = pos-N+1;
}
}
}
if ( ShareSide(cellvertices(pos-N), cellvertices(pos-N+1)) != 1 ){
if (ShareSide( cellvertices(pos-N), cellvertices(pos-2)) == 1 && ShareSide(cellvertices(pos-1),
cellvertices(pos-N+1)) == 1){
PlaceHolder = cellvertices(pos-1);
cellvertices(pos-1) = cellvertices(pos-N);
cellvertices(pos-N) = PlaceHolder;
temp = values(pos-1);
values(pos-1) = values(pos-N);
values(pos-N) = temp;
// Swap the triangle lists as needed
for (int idx=0; idx<TriangleCount; idx++){
if (Triangles(0,idx) == pos-N) Triangles(0,idx) = pos-1;
else if (Triangles(0,idx) == pos-1) Triangles(0,idx) = pos-N;
if (Triangles(1,idx) == pos-N) Triangles(1,idx) = pos-1;
else if (Triangles(1,idx) == pos-1) Triangles(1,idx) = pos-N;
if (Triangles(2,idx) == pos-N) Triangles(2,idx) = pos-1;
else if (Triangles(2,idx) == pos-1) Triangles(2,idx) = pos-N;
}
}
}
}
*/
}
//-------------------------------------------------------------------------------
inline void SOL_SURF(DoubleArray &A, const double &v, DoubleArray &B, const double &isovalue,
int i,int j,int k, int m, int n, int o, DTMutableList<Point>
&cellvertices, int &lengthvertices, IntArray &Tlist, int &nTris,
DoubleArray &values)
{
NULL_USE( isovalue );
NULL_USE( m );
NULL_USE( n );
NULL_USE( o );
// THIS SUBROUTINE COMPUTES THE VERTICES FOR THE SOLID PHASE IN
// A PARTICULAR GRID CELL, THEN ARRANGES THEM INTO TRIANGLES
// ALSO ORGANIZES THE LIST OF VALUES TO CORRESPOND WITH VERTEX LIST
int N = 0;
Point P;
Point PlaceHolder;
int pos = lengthvertices;
float temp;
// int m; int n; int o;
int p; int q;
// for each leg of the triangle, see if a vertex exists
// if so, find the vertex, and perform an extrapolation
// Go over each corner -- check to see if the corners are themselves vertices
//1
if (A(i,j,k) == v){
P.x = i;
P.y = j;
P.z = k;
values(pos) = B(i,j,k);
cellvertices(pos++) = P;
N++;
}
//2
if (A(i+1,j,k) == v){
P.x = i+1;
P.y = j;
P.z = k;
values(pos) = B(i+1,j,k);
cellvertices(pos++) = P;
N++;
}
//3
if (A(i+1,j+1,k) == v){
P.x = i+1;
P.y = j+1;
P.z = k;
values(pos) = B(i+1,j+1,k);
cellvertices(pos++) = P;
N++;
}
//4
if (A(i,j+1,k) == v){
P.x = i;
P.y = j+1;
P.z = k;
values(pos) = B(i,j+1,k);
cellvertices(pos++) = P;
N++;
}
//5
if (A(i,j,k+1) == v){
P.x = i;
P.y = j;
P.z = k+1;
values(pos) = B(i,j,k+1);
cellvertices(pos++) = P;
N++;
}
//6
if (A(i+1,j,k+1) == v){
P.x = i+1;
P.y = j;
P.z = k+1;
values(pos) = B(i+1,j,k+1);
cellvertices(pos++) = P;
N++;
}
//7
if (A(i+1,j+1,k+1) == v){
P.x = i+1;
P.y = j+1;
P.z = k+1;
values(pos) = B(i+1,j+1,k+1);
cellvertices(pos++) = P;
N++;
}
//8
if (A(i,j+1,k+1) == v){
P.x = i;
P.y = j+1;
P.z = k+1;
values(pos) = B(i,j+1,k+1);
cellvertices(pos++) = P;
N++;
}
// Go through each side, compute P for sides of box spiraling up
if ((A(i,j,k)-v)*(A(i+1,j,k)-v) < 0)
{
P.x = i + (A(i,j,k)-v)/(A(i,j,k)-A(i+1,j,k));
P.y = j;
P.z = k;
// compute extrapolated fluid value at P
// if ( A(i,j,k) > v){
// values(pos) = EXTRAP(B, isovalue, i,j,k,4, P);
// }
// else{
// values(pos) = EXTRAP(B,isovalue, i+1,j,k, 1, P);
// }
// Interpolate value at P using padded mesh B
values(pos) = B(i,j,k)*(1-P.x+i)+B(i+1,j,k)*(P.x-i);
cellvertices(pos++) = P;
N++;
}
// 2
if ((A(i+1,j,k)-v)*(A(i+1,j+1,k)-v) < 0)
{
P.x = i+1;
P.y = j + (A(i+1,j,k)-v)/(A(i+1,j,k)-A(i+1,j+1,k));
P.z = k;
if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice)
// compute extrapolated fluid value at P
// if ( A(i+1,j,k) > v){
// values(pos) = EXTRAP(B,isovalue, i+1,j,k, 5, P);
// }
// else{
// values(pos) = EXTRAP(B,isovalue, i+1,j+1,k, 2, P);
// }
// Interpolate value at P using padded mesh B
values(pos) = B(i+1,j,k)*(1-P.y+j)+B(i+1,j+1,k)*(P.y-j);
cellvertices(pos++) = P;
N++;
}
}
//3
if ((A(i+1,j+1,k)-v)*(A(i,j+1,k)-v) < 0)
{
P.x = i + (A(i,j+1,k)-v) / (A(i,j+1,k)-A(i+1,j+1,k));
P.y = j+1;
P.z = k;
if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice)
// compute extrapolated fluid value at P
// if ( A(i+1,j+1,k) > v){
// values(pos) = EXTRAP(B,isovalue, i+1,j+1,k, 1, P);
// }
// else{
// values(pos) = EXTRAP(B,isovalue, i,j+1,k, 4, P);
// }
// Interpolate value at P using padded mesh B
values(pos) = B(i,j+1,k)*(1-P.x+i)+B(i+1,j+1,k)*(P.x-i);
cellvertices(pos++) = P;
N++;
}
}
//4
if ((A(i,j+1,k)-v)*(A(i,j,k)-v) < 0)
{
P.x = i;
P.y = j + (A(i,j,k)-v) / (A(i,j,k)-A(i,j+1,k));
P.z = k;
if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice)
// compute extrapolated fluid value at P
// if ( A(i,j,k) > v){
// values(pos) = EXTRAP(B,isovalue, i,j,k, 5, P);
// }
// else{
// values(pos) = EXTRAP(B,isovalue, i,j+1,k, 2, P);
// }
// Interpolate value at P using padded mesh B
values(pos) = B(i,j,k)*(1-P.y+j)+B(i,j+1,k)*(P.y-j);
cellvertices(pos++) = P;
N++;
}
}
//5
if ((A(i,j,k)-v)*(A(i,j,k+1)-v) < 0)
{
P.x = i;
P.y = j;
P.z = k + (A(i,j,k)-v) / (A(i,j,k)-A(i,j,k+1));
if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice)
// compute extrapolated fluid value at P
// if ( A(i,j,k) > v){
// values(pos) = EXTRAP(B,isovalue, i,j,k, 6, P);
// }
// else{
// values(pos) = EXTRAP(B,isovalue, i,j,k+1, 3, P);
// }
// Interpolate value at P using padded mesh B
values(pos) = B(i,j,k)*(1-P.z+k)+B(i,j,k+1)*(P.z-k);
cellvertices(pos++) = P;
N++;
}
}
//6
if ((A(i+1,j,k)-v)*(A(i+1,j,k+1)-v) < 0)
{
P.x = i+1;
P.y = j;
P.z = k + (A(i+1,j,k)-v) / (A(i+1,j,k)-A(i+1,j,k+1));
if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice)
// compute extrapolated fluid value at P
// if ( A(i+1,j,k) > v){
// values(pos) = EXTRAP(B,isovalue, i+1,j,k, 6, P);
// }
// else{
// values(pos) = EXTRAP(B,isovalue, i+1,j,k+1, 3, P);
// }
// Interpolate value at P using padded mesh B
values(pos) = B(i+1,j,k)*(1-P.z+k)+B(i+1,j,k+1)*(P.z-k);
cellvertices(pos++) = P;
N++;
}
}
//7
if ((A(i+1,j+1,k)-v)*(A(i+1,j+1,k+1)-v) < 0)
{
P.x = i+1;
P.y = j+1;
P.z = k + (A(i+1,j+1,k)-v) / (A(i+1,j+1,k)-A(i+1,j+1,k+1));
if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice)
// compute extrapolated fluid value at P
// if ( A(i+1,j+1,k) > v){
// values(pos) = EXTRAP(B,isovalue, i+1,j+1,k, 6, P);
// }
// else{
// values(pos) = EXTRAP(B,isovalue, i+1,j+1,k+1, 3, P);
// }
// Interpolate value at P using padded mesh B
values(pos) = B(i+1,j+1,k)*(1-P.z+k)+B(i+1,j+1,k+1)*(P.z-k);
cellvertices(pos++) = P;
N++;
}
}
//8
if ((A(i,j+1,k)-v)*(A(i,j+1,k+1)-v) < 0)
{
P.x = i;
P.y = j+1;
P.z = k + (A(i,j+1,k)-v) / (A(i,j+1,k)-A(i,j+1,k+1));
if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice)
// compute extrapolated fluid value at P
// if ( A(i,j+1,k) > v){
// values(pos) = EXTRAP(B,isovalue, i,j+1,k, 6, P);
// }
// else{
// values(pos) = EXTRAP(B,isovalue, i,j+1,k+1, 3, P);
// }
// Interpolate value at P using padded mesh B
values(pos) = B(i,j+1,k)*(1-P.z+k)+B(i,j+1,k+1)*(P.z-k);
cellvertices(pos++) = P;
N++;
}
}
//9
if ((A(i,j,k+1)-v)*(A(i+1,j,k+1)-v) < 0)
{
P.x = i + (A(i,j,k+1)-v) / (A(i,j,k+1)-A(i+1,j,k+1));
P.y = j;
P.z = k+1;
if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice)
// compute extrapolated fluid value at P
// if ( A(i,j,k+1) > v){
// values(pos) = EXTRAP(B,isovalue, i,j,k+1, 4, P);
// }
// else{
// values(pos) = EXTRAP(B,isovalue, i+1,j,k+1, 1, P);
// }
// Interpolate value at P using padded mesh B
values(pos) = B(i,j,k+1)*(1-P.x+i)+B(i+1,j,k+1)*(P.x-i);
cellvertices(pos++) = P;
N++;
}
}
//10
if ((A(i+1,j,k+1)-v)*(A(i+1,j+1,k+1)-v) < 0)
{
P.x = i+1;
P.y = j + (A(i+1,j,k+1)-v) / (A(i+1,j,k+1)-A(i+1,j+1,k+1));
P.z = k+1;
if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice)
// compute extrapolated fluid value at P
// if ( A(i+1,j,k+1) > v){
// values(pos) = EXTRAP(B,isovalue, i+1,j,k+1, 5, P);
// }
// else{
// values(pos) = EXTRAP(B,isovalue, i+1,j+1,k+1, 2, P);
// }
// Interpolate value at P using padded mesh B
values(pos) = B(i+1,j,k+1)*(1-P.y+j)+B(i+1,j+1,k+1)*(P.y-j);
cellvertices(pos++) = P;
N++;
}
}
//11
if ((A(i+1,j+1,k+1)-v)*(A(i,j+1,k+1)-v) < 0)
{
P.x = i+(A(i,j+1,k+1)-v) / (A(i,j+1,k+1)-A(i+1,j+1,k+1));
P.y = j+1;
P.z = k+1;
if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice)
// compute extrapolated fluid value at P
// if ( A(i,j+1,k+1) > v){
// values(pos) = EXTRAP(B,isovalue, i,j+1,k+1, 4, P);
// }
// else{
// values(pos) = EXTRAP(B,isovalue, i+1,j+1,k+1, 1, P);
// }
// Interpolate value at P using padded mesh B
values(pos) = B(i,j+1,k+1)*(1-P.x+i)+B(i+1,j+1,k+1)*(P.x-i);
cellvertices(pos++) = P;
N++;
}
}
//12
if ((A(i,j+1,k+1)-v)*(A(i,j,k+1)-v) < 0)
{
P.x = i;
P.y = j + (A(i,j,k+1)-v) / (A(i,j,k+1)-A(i,j+1,k+1));
P.z = k+1;
if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice)
// compute extrapolated fluid value at P
// if ( A(i,j,k+1) > v){
// values(pos) = EXTRAP(B,isovalue, i,j,k+1, 5, P);
// }
// else{
// values(pos) = EXTRAP(B,isovalue, i,j+1,k+1, 2, P);
// }
// Interpolate value at P using padded mesh B
values(pos) = B(i,j,k+1)*(1-P.y+j)+B(i,j+1,k+1)*(P.y-j);
cellvertices(pos++) = P;
N++;
}
}
lengthvertices = pos;
// * * * ARRANGE VERTICES SO THAT NEIGHBORS SHARE A FACE * * *
// * * * PERFORM SAME OPERATIONS TO THE LIST OF VALUES * * *
for (q = pos-N; q < pos-2; q++) {
for (o = q+2; o < pos-1; o++) {
if (ShareSide(cellvertices(q), cellvertices(o)) == 1) {
PlaceHolder = cellvertices(q+1);
cellvertices(q+1) = cellvertices(o);
cellvertices(o) = PlaceHolder;
temp = values(q+1);
values(q+1) = values(o);
values(o) = temp;
}
}
// make sure other neighbor of vertex 1 is in last spot
if (q == pos-N){
for (p = q+2; p < pos-1; p++){
if (ShareSide(cellvertices(q), cellvertices(p)) == 1){
PlaceHolder = cellvertices(pos-1);
cellvertices(pos-1) = cellvertices(p);
cellvertices(p) = PlaceHolder;
temp = values(pos-1);
values(pos-1) = values(p);
values(p) = temp;
}
}
}
if ( ShareSide(cellvertices(pos-2), cellvertices(pos-3)) != 1 ){
if (ShareSide( cellvertices(pos-3), cellvertices(pos-1)) == 1 && ShareSide( cellvertices(pos-N),
cellvertices(pos-2)) == 1 ){
PlaceHolder = cellvertices(pos-2);
cellvertices(pos-2) = cellvertices(pos-1);
cellvertices(pos-1) = PlaceHolder;
temp = values(pos-2);
values(pos-2) = values(pos-1);
values(pos-1) = temp;
}
}
if ( ShareSide(cellvertices(pos-1), cellvertices(pos-2)) != 1 ){
if (ShareSide( cellvertices(pos-3), cellvertices(pos-1)) == 1 && ShareSide(cellvertices(pos-4),
cellvertices(pos-2)) == 1 ){
PlaceHolder = cellvertices(pos-3);
cellvertices(pos-3) = cellvertices(pos-2);
cellvertices(pos-2) = PlaceHolder;
temp = values(pos-3);
values(pos-3) = values(pos-2);
values(pos-2) = temp;
}
if (ShareSide( cellvertices(pos-N+1), cellvertices(pos-3)) == 1 && ShareSide(cellvertices(pos-1),
cellvertices(pos-N+1)) == 1 ){
PlaceHolder = cellvertices(pos-2);
cellvertices(pos-2) = cellvertices(pos-N+1);
cellvertices(pos-N+1) = PlaceHolder;
temp = values(pos-2);
values(pos-2) = values(pos-N+1);
values(pos-N+1) = temp;
}
}
if ( ShareSide(cellvertices(pos-N), cellvertices(pos-N+1)) != 1 ){
if (ShareSide( cellvertices(pos-N), cellvertices(pos-2)) == 1 && ShareSide(cellvertices(pos-1),
cellvertices(pos-N+1)) == 1){
PlaceHolder = cellvertices(pos-1);
cellvertices(pos-1) = cellvertices(pos-N);
cellvertices(pos-N) = PlaceHolder;
temp = values(pos-1);
values(pos-1) = values(pos-N);
values(pos-N) = temp;
}
}
}
// * * * ESTABLISH TRIANGLE CONNECTIONS * * *
for (p=pos-N+2; p<pos; p++){
Tlist(0,nTris) = pos-N;
Tlist(1,nTris) = p-1;
Tlist(2,nTris) = p;
nTris++;
}
}
//-------------------------------------------------------------------------------
/*inline void TRIM(DTMutableList<Point> &local_sol_pts, int &n_local_sol_pts, double isovalue,
IntArray &local_sol_tris, int &n_local_sol_tris,
DTMutableList<Point> &ns_pts, int &n_ns_pts, IntArray &ns_tris,
int &n_ns_tris, DTMutableList<Point> &ws_pts, int &n_ws_pts,
IntArray &ws_tris, int &n_ws_tris, DoubleArray &values,
DTMutableList<Point> &local_nws_pts, int &n_local_nws_pts,
DoubleArray &fluid_pad, DoubleArray &S, int &i, int &j, int &k,
int &newton_steps)
inline void TRIM(DTMutableList<DTPoint3D> &local_sol_pts, int &n_local_sol_pts, double isovalue,
DTMutableIntArray &local_sol_tris, int &n_local_sol_tris,
DTMutableList<DTPoint3D> &ns_pts, int &n_ns_pts, DTMutableIntArray &ns_tris,
int &n_ns_tris, DTMutableList<DTPoint3D> &ws_pts, int &n_ws_pts,
DTMutableIntArray &ws_tris, int &n_ws_tris, DTFloatArray &values,
DTMutableList<DTPoint3D> &local_nws_pts, int &n_local_nws_pts)
*/
//-------------------------------------------------------------------------------
inline void TRIM(DTMutableList<Point> &local_sol_pts, int &n_local_sol_pts, double isovalue,
IntArray &local_sol_tris, int &n_local_sol_tris,
DTMutableList<Point> &ns_pts, int &n_ns_pts, IntArray &ns_tris,
int &n_ns_tris, DTMutableList<Point> &ws_pts, int &n_ws_pts,
IntArray &ws_tris, int &n_ws_tris, DoubleArray &values,
DTMutableList<Point> &local_nws_pts, int &n_local_nws_pts)
{
// Trim the local solid surface
int map_ws;
int map_ns;
int p; int q;
int a; int b; int c;
Point A; Point B; Point C;
Point D; Point E;
Point P;
bool all_to_ns = 1;
// Check to see if all triangles in the cell are in ns_surface
for (q=0; q < n_local_sol_pts; q++){
if ( values(q) < isovalue && all_to_ns == 1){
all_to_ns = 0;
}
}
bool all_to_ws = 1;
// Check to see if all triangles in the cell are in ws surface
for (q=0; q < n_local_sol_pts; q++){
if ( values(q) > isovalue && all_to_ws == 1){
all_to_ws = 0;
}
}
if (all_to_ws == 1){
map_ws = n_ws_pts;
map_ws = 0;
for ( p=0; p<n_local_sol_pts; p++){
ws_pts(n_ws_pts++) = local_sol_pts(p);
}
for ( p=0; p<n_local_sol_tris; p++){
ws_tris(0,n_ws_tris) = local_sol_tris(0,p) + map_ws;
ws_tris(1,n_ws_tris) = local_sol_tris(1,p) + map_ws;
ws_tris(2,n_ws_tris) = local_sol_tris(2,p) + map_ws;
n_ws_tris++;
}
}
else if (all_to_ns == 1){
map_ns = n_ns_pts;
map_ns = 0;
for ( p=0; p<n_local_sol_pts; p++){
ns_pts(n_ns_pts++) = local_sol_pts(p);
}
for ( p=0; p<n_local_sol_tris; p++){
ns_tris(0,n_ns_tris) = local_sol_tris(0,p) + map_ns;
ns_tris(1,n_ns_tris) = local_sol_tris(1,p) + map_ns;
ns_tris(2,n_ns_tris) = local_sol_tris(2,p) + map_ns;
n_ns_tris++;
}
}
else {
// this section of surface contains a common line
map_ns = n_ns_tris;
map_ws = n_ws_tris;
// Go through all triangles
for ( p=0; p<n_local_sol_tris; p++){
a = local_sol_tris(0,p);
b = local_sol_tris(1,p);
c = local_sol_tris(2,p);
A = local_sol_pts(a);
B = local_sol_pts(b);
C = local_sol_pts(c);
if (values(a) > isovalue && values(b) > isovalue && values(c) > isovalue ){
// Triangle is in ns surface
// Add points
ns_pts(n_ns_pts++) = A;
ns_pts(n_ns_pts++) = B;
ns_pts(n_ns_pts++) = C;
// Add triangles
ns_tris(0,n_ns_tris) = n_ns_pts-3;
ns_tris(1,n_ns_tris) = n_ns_pts-2;
ns_tris(2,n_ns_tris) = n_ns_pts-1;
n_ns_tris++;
}
else if (values(a) < isovalue && values(b) < isovalue && values(c) < isovalue ){
// Triangle is in ws surface
// Add points
ws_pts(n_ws_pts++) = A;
ws_pts(n_ws_pts++) = B;
ws_pts(n_ws_pts++) = C;
// Add triangles
ws_tris(0,n_ws_tris) = n_ws_pts-3;
ws_tris(1,n_ws_tris) = n_ws_pts-2;
ws_tris(2,n_ws_tris) = n_ws_pts-1;
n_ws_tris++;
}
else {
// Triangle contains common line
////////////////////////////////////////
///////// FIND THE COMMON LINE /////////
////////////////////////////////////////
if ( (values(a)-isovalue)*(values(b)-isovalue) < 0){
// compute common line vertex
// P = A + (values(a) - isovalue)/(values(a)-values(b))*(B-A);
P.x = A.x + (values(a) - isovalue)/(values(a)-values(b))*(B.x-A.x);
P.y = A.y + (values(a) - isovalue)/(values(a)-values(b))*(B.y-A.y);
P.z = A.z + (values(a) - isovalue)/(values(a)-values(b))*(B.z-A.z);
local_nws_pts(n_local_nws_pts++) = P;
/* if ( n_local_nws_pts == 0 ){
local_nws_pts(n_local_nws_pts++) = P;
}
else if ( P != local_nws_pts(n_local_nws_pts-1) ){
local_nws_pts(n_local_nws_pts++) = P;
}
*/ }
if ( (values(b)-isovalue)*(values(c)-isovalue) < 0){
// compute common line vertex
// P = B + (values(b) - isovalue)/(values(b)-values(c))*(C-B);
P.x = B.x + (values(b) - isovalue)/(values(b)-values(c))*(C.x-B.x);
P.y = B.y + (values(b) - isovalue)/(values(b)-values(c))*(C.y-B.y);
P.z = B.z + (values(b) - isovalue)/(values(b)-values(c))*(C.z-B.z);
local_nws_pts(n_local_nws_pts++) = P;
/* if ( n_local_nws_pts == 0 ){
local_nws_pts(n_local_nws_pts++) = P;
}
else if ( P != local_nws_pts(n_local_nws_pts-1) ){
local_nws_pts(n_local_nws_pts++) = P;
}
*/ }
if ( (values(a)-isovalue)*(values(c)-isovalue) < 0){
// compute common line vertex
// P = A + (values(a) - isovalue)/(values(a)-values(c))*(C-A);
P.x = A.x + (values(a) - isovalue)/(values(a)-values(c))*(C.x-A.x);
P.y = A.y + (values(a) - isovalue)/(values(a)-values(c))*(C.y-A.y);
P.z = A.z + (values(a) - isovalue)/(values(a)-values(c))*(C.z-A.z);
local_nws_pts(n_local_nws_pts++) = P;
}
// Store common line points as D and E
D = local_nws_pts(n_local_nws_pts-2);
E = local_nws_pts(n_local_nws_pts-1);
// Construct the new triangles
if ( (values(a)-isovalue)*(values(b)-isovalue) < 0 &&
(values(b)-isovalue)*(values(c)-isovalue) < 0){
if (values(b) > isovalue){
// Points
ns_pts(n_ns_pts++) = B;
ns_pts(n_ns_pts++) = D;
ns_pts(n_ns_pts++) = E;
// Triangles
ns_tris(0,n_ns_tris) = n_ns_pts-3; // B
ns_tris(1,n_ns_tris) = n_ns_pts-2; // D
ns_tris(2,n_ns_tris) = n_ns_pts-1; // E
n_ns_tris++;
// Points
ws_pts(n_ws_pts++) = A;
ws_pts(n_ws_pts++) = C;
ws_pts(n_ws_pts++) = D;
ws_pts(n_ws_pts++) = E;
// Triangles (A,C,D),(C,D,E)
ws_tris(0,n_ws_tris) = n_ws_pts-4; // A
ws_tris(1,n_ws_tris) = n_ws_pts-3; // C
ws_tris(2,n_ws_tris) = n_ws_pts-2; // D
n_ws_tris++;
ws_tris(0,n_ws_tris) = n_ws_pts-3; // C
ws_tris(1,n_ws_tris) = n_ws_pts-2; // D
ws_tris(2,n_ws_tris) = n_ws_pts-1; // E
n_ws_tris++;
}
else {
// Points
ws_pts(n_ws_pts++) = B;
ws_pts(n_ws_pts++) = D;
ws_pts(n_ws_pts++) = E;
// Triangles
ws_tris(0,n_ws_tris) = n_ws_pts-3; // B
ws_tris(1,n_ws_tris) = n_ws_pts-2; // D
ws_tris(2,n_ws_tris) = n_ws_pts-1; // E
n_ws_tris++;
// Points
ns_pts(n_ns_pts++) = A;
ns_pts(n_ns_pts++) = C;
ns_pts(n_ns_pts++) = D;
ns_pts(n_ns_pts++) = E;
// Triangles (A,C,D),(C,D,E)
ns_tris(0,n_ns_tris) = n_ns_pts-4; // A
ns_tris(1,n_ns_tris) = n_ns_pts-3; // C
ns_tris(2,n_ns_tris) = n_ns_pts-2; // D
n_ns_tris++;
ns_tris(0,n_ns_tris) = n_ns_pts-3; // C
ns_tris(1,n_ns_tris) = n_ns_pts-1; // E
ns_tris(2,n_ns_tris) = n_ns_pts-2; // D
n_ns_tris++;
}
}
else if ( (values(a)-isovalue)*(values(b)-isovalue) < 0 &&
(values(a)-isovalue)*(values(c)-isovalue) < 0){
if (values(a) > isovalue){
// Points
ns_pts(n_ns_pts++) = A;
ns_pts(n_ns_pts++) = D;
ns_pts(n_ns_pts++) = E;
// Triangles
ns_tris(0,n_ns_tris) = n_ns_pts-3; // A
ns_tris(1,n_ns_tris) = n_ns_pts-2; // D
ns_tris(2,n_ns_tris) = n_ns_pts-1; // E
n_ns_tris++;
// Points
ws_pts(n_ws_pts++) = B;
ws_pts(n_ws_pts++) = C;
ws_pts(n_ws_pts++) = D;
ws_pts(n_ws_pts++) = E;
// Triangles (B,C,D),(C,D,E)
ws_tris(0,n_ws_tris) = n_ws_pts-4; // B
ws_tris(1,n_ws_tris) = n_ws_pts-2; // D
ws_tris(2,n_ws_tris) = n_ws_pts-3; // C
n_ws_tris++;
ws_tris(0,n_ws_tris) = n_ws_pts-3; // C
ws_tris(1,n_ws_tris) = n_ws_pts-2; // D
ws_tris(2,n_ws_tris) = n_ws_pts-1; // E
n_ws_tris++;
}
else {
// Points
ws_pts(n_ws_pts++) = A;
ws_pts(n_ws_pts++) = D;
ws_pts(n_ws_pts++) = E;
// Triangles
ws_tris(0,n_ws_tris) = n_ws_pts-3; // A
ws_tris(1,n_ws_tris) = n_ws_pts-2; // D
ws_tris(2,n_ws_tris) = n_ws_pts-1; // E
n_ws_tris++;
// Points
ns_pts(n_ns_pts++) = B;
ns_pts(n_ns_pts++) = C;
ns_pts(n_ns_pts++) = D;
ns_pts(n_ns_pts++) = E;
// Triangles (B,C,D),(C,D,E)
ns_tris(0,n_ns_tris) = n_ns_pts-4; // B
ns_tris(1,n_ns_tris) = n_ns_pts-3; // C
ns_tris(2,n_ns_tris) = n_ns_pts-2; // D
n_ns_tris++;
ns_tris(0,n_ns_tris) = n_ns_pts-3; // C
ns_tris(1,n_ns_tris) = n_ns_pts-1; // E
ns_tris(2,n_ns_tris) = n_ns_pts-2; // D
n_ns_tris++;
}
}
else {
if (values(c) > isovalue){
// Points
ns_pts(n_ns_pts++) = C;
ns_pts(n_ns_pts++) = D;
ns_pts(n_ns_pts++) = E;
// Triangles
ns_tris(0,n_ns_tris) = n_ns_pts-3; // C
ns_tris(1,n_ns_tris) = n_ns_pts-2; // D
ns_tris(2,n_ns_tris) = n_ns_pts-1; // E
n_ns_tris++;
// Points
ws_pts(n_ws_pts++) = A;
ws_pts(n_ws_pts++) = B;
ws_pts(n_ws_pts++) = D;
ws_pts(n_ws_pts++) = E;
// Triangles (A,B,D),(A,D,E)
ws_tris(0,n_ws_tris) = n_ws_pts-4; // A
ws_tris(1,n_ws_tris) = n_ws_pts-3; // B
ws_tris(2,n_ws_tris) = n_ws_pts-2; // D
n_ws_tris++;
ws_tris(0,n_ws_tris) = n_ws_pts-4; // A
ws_tris(1,n_ws_tris) = n_ws_pts-2; // D
ws_tris(2,n_ws_tris) = n_ws_pts-1; // E
n_ws_tris++;
}
else {
// Points
ws_pts(n_ws_pts++) = C;
ws_pts(n_ws_pts++) = D;
ws_pts(n_ws_pts++) = E;
// Triangles
ws_tris(0,n_ws_tris) = n_ws_pts-3; // C
ws_tris(1,n_ws_tris) = n_ws_pts-2; // D
ws_tris(2,n_ws_tris) = n_ws_pts-1; // E
n_ws_tris++;
// Points
ns_pts(n_ns_pts++) = A;
ns_pts(n_ns_pts++) = B;
ns_pts(n_ns_pts++) = D;
ns_pts(n_ns_pts++) = E;
// Triangles (A,B,D),(A,D,E)
ns_tris(0,n_ns_tris) = n_ns_pts-4; // A
ns_tris(1,n_ns_tris) = n_ns_pts-3; // B
ns_tris(2,n_ns_tris) = n_ns_pts-2; // D
n_ns_tris++;
ns_tris(0,n_ns_tris) = n_ns_pts-4; // A
ns_tris(1,n_ns_tris) = n_ns_pts-2; // D
ns_tris(2,n_ns_tris) = n_ns_pts-1; // E
n_ns_tris++;
}
}
}
}
}
}
inline double geomavg_MarchingCubes( DoubleArray &A, double &v, int &i, int &j, int &k,
DTMutableList<Point> &nw_pts, int &n_nw_pts, IntArray &nw_tris,
int &n_nw_tris)
{
int N = 0; // n will be the number of vertices in this grid cell only
Point P;
Point pt;
Point PlaceHolder;
int m;
int o;
int p;
// Go over each corner -- check to see if the corners are themselves vertices
//1
if (A(i,j,k) == v){
P.x = i;
P.y = j;
P.z = k;
nw_pts(n_nw_pts++) = P;
N++;
}
//2
if (A(i+1,j,k) == v){
P.x = i+1;
P.y = j;
P.z = k;
nw_pts(n_nw_pts++) = P;
N++;
}
//3
if (A(i+1,j+1,k) == v){
P.x = i+1;
P.y = j+1;
P.z = k;
nw_pts(n_nw_pts++) = P;
N++;
}
//4
if (A(i,j+1,k) == v){
P.x = i;
P.y = j+1;
P.z = k;
nw_pts(n_nw_pts++) = P;
N++;
}
//5
if (A(i,j,k+1) == v){
P.x = i;
P.y = j;
P.z = k+1;
nw_pts(n_nw_pts++) = P;
N++;
}
//6
if (A(i+1,j,k+1) == v){
P.x = i+1;
P.y = j;
P.z = k+1;
nw_pts(n_nw_pts++) = P;
N++;
}
//7
if (A(i+1,j+1,k+1) == v){
P.x = i+1;
P.y = j+1;
P.z = k+1;
nw_pts(n_nw_pts++) = P;
N++;
}
//8
if (A(i,j+1,k+1) == v){
P.x = i;
P.y = j+1;
P.z = k+1;
nw_pts(n_nw_pts++) = P;
N++;
}
// Go through each side, compute P for sides of box spiraling up
// float val;
if ((A(i,j,k)-v)*(A(i+1,j,k)-v) < 0)
{
// If both points are in the fluid region
if (A(i,j,k) != 0 && A(i+1,j,k) != 0){
P.x = i + (A(i,j,k)-v)/(A(i,j,k)-A(i+1,j,k));
P.y = j;
P.z = k;
nw_pts(n_nw_pts++) = P;
N++;
}
}
if ((A(i+1,j,k)-v)*(A(i+1,j+1,k)-v) < 0)
{
if ( A(i+1,j,k) != 0 && A(i+1,j+1,k) != 0 ){
P.x = i+1;
P.y = j + (A(i+1,j,k)-v)/(A(i+1,j,k)-A(i+1,j+1,k));
P.z = k;
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ // P is a new vertex (not counted twice)
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
if ((A(i+1,j+1,k)-v)*(A(i,j+1,k)-v) < 0 )
{
if ( A(i+1,j+1,k) != 0 && A(i,j+1,k) != 0 ){
P.x = i + (A(i,j+1,k)-v) / (A(i,j+1,k)-A(i+1,j+1,k));
P.y = j+1;
P.z = k;
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ // P is a new vertex (not counted twice)
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
//4
if ((A(i,j+1,k)-v)*(A(i,j,k)-v) < 0 )
{
if (A(i,j+1,k) != 0 && A(i,j,k) != 0 ){
P.x = i;
P.y = j + (A(i,j,k)-v) / (A(i,j,k)-A(i,j+1,k));
P.z = k;
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ // P is a new vertex (not counted twice)
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
//5
if ((A(i,j,k)-v)*(A(i,j,k+1)-v) < 0 )
{
if ( A(i,j,k) != 0 && A(i,j,k+1) != 0 ){
P.x = i;
P.y = j;
P.z = k + (A(i,j,k)-v) / (A(i,j,k)-A(i,j,k+1));
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ // P is a new vertex (not counted twice)
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
//6
if ((A(i+1,j,k)-v)*(A(i+1,j,k+1)-v) < 0 )
{
if ( A(i+1,j,k) != 0 && A(i+1,j,k+1) != 0 ){
P.x = i+1;
P.y = j;
P.z = k + (A(i+1,j,k)-v) / (A(i+1,j,k)-A(i+1,j,k+1));
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
//7
if ((A(i+1,j+1,k)-v)*(A(i+1,j+1,k+1)-v) < 0 )
{
if ( A(i+1,j+1,k) != 0 && A(i+1,j+1,k+1) != 0 ){
P.x = i+1;
P.y = j+1;
P.z = k + (A(i+1,j+1,k)-v) / (A(i+1,j+1,k)-A(i+1,j+1,k+1));
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
//8
if ((A(i,j+1,k)-v)*(A(i,j+1,k+1)-v) < 0 )
{
if ( A(i,j+1,k) != 0 && A(i,j+1,k+1) != 0 ){
P.x = i;
P.y = j+1;
P.z = k + (A(i,j+1,k)-v) / (A(i,j+1,k)-A(i,j+1,k+1));
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
//9
if ((A(i,j,k+1)-v)*(A(i+1,j,k+1)-v) < 0 )
{
if ( A(i,j,k+1) != 0 && A(i+1,j,k+1) != 0 ){
P.x = i + (A(i,j,k+1)-v) / (A(i,j,k+1)-A(i+1,j,k+1));
P.y = j;
P.z = k+1;
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
//10
if ((A(i+1,j,k+1)-v)*(A(i+1,j+1,k+1)-v) < 0 )
{
if ( A(i+1,j,k+1) != 0 && A(i+1,j+1,k+1) != 0 ){
P.x = i+1;
P.y = j + (A(i+1,j,k+1)-v) / (A(i+1,j,k+1)-A(i+1,j+1,k+1));
P.z = k+1;
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
//11
if ((A(i+1,j+1,k+1)-v)*(A(i,j+1,k+1)-v) < 0 )
{
if ( A(i+1,j+1,k+1) != 0 && A(i,j+1,k+1) != 0 ){
P.x = i+(A(i,j+1,k+1)-v) / (A(i,j+1,k+1)-A(i+1,j+1,k+1));
P.y = j+1;
P.z = k+1;
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
//12
if ((A(i,j+1,k+1)-v)*(A(i,j,k+1)-v) < 0 )
{
if ( A(i,j+1,k+1) != 0 && A(i,j,k+1) != 0 ){
P.x = i;
P.y = j + (A(i,j,k+1)-v) / (A(i,j,k+1)-A(i,j+1,k+1));
P.z = k+1;
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
// Assemble the triangles as long as points are found
if (N > 0){
for (m = n_nw_pts-N; m < n_nw_pts-2; m++) {
for (o = m+2; o < n_nw_pts-1; o++) {
if (ShareSide(nw_pts(m), nw_pts(o)) == 1) {
PlaceHolder = nw_pts(m+1);
nw_pts(m+1) = nw_pts(o);
nw_pts(o) = PlaceHolder;
}
}
// make sure other neighbor of vertex 1 is in last spot
if (m == n_nw_pts-N){
for (p = m+2; p < n_nw_pts-1; p++){
if (ShareSide(nw_pts(m), nw_pts(p)) == 1){
PlaceHolder = nw_pts(n_nw_pts-1);
nw_pts(n_nw_pts-1) = nw_pts(p);
nw_pts(p) = PlaceHolder;
}
}
}
if ( ShareSide(nw_pts(n_nw_pts-2), nw_pts(n_nw_pts-3)) != 1 ){
if (ShareSide( nw_pts(n_nw_pts-3), nw_pts(n_nw_pts-1)) == 1 &&
ShareSide( nw_pts(n_nw_pts-N),nw_pts(n_nw_pts-2)) == 1 ){
PlaceHolder = nw_pts(n_nw_pts-2);
nw_pts(n_nw_pts-2) = nw_pts(n_nw_pts-1);
nw_pts(n_nw_pts-1) = PlaceHolder;
}
}
if ( ShareSide(nw_pts(n_nw_pts-1), nw_pts(n_nw_pts-2)) != 1 ){
if (ShareSide( nw_pts(n_nw_pts-3), nw_pts(n_nw_pts-1)) == 1 &&
ShareSide(nw_pts(n_nw_pts-4),nw_pts(n_nw_pts-2)) == 1 ){
PlaceHolder = nw_pts(n_nw_pts-3);
nw_pts(n_nw_pts-3) = nw_pts(n_nw_pts-2);
nw_pts(n_nw_pts-2) = PlaceHolder;
}
if (ShareSide( nw_pts(n_nw_pts-N+1), nw_pts(n_nw_pts-3)) == 1 &&
ShareSide(nw_pts(n_nw_pts-1),nw_pts(n_nw_pts-N+1)) == 1 ){
PlaceHolder = nw_pts(n_nw_pts-2);
nw_pts(n_nw_pts-2) = nw_pts(n_nw_pts-N+1);
nw_pts(n_nw_pts-N+1) = PlaceHolder;
}
}
if ( ShareSide(nw_pts(n_nw_pts-N), nw_pts(n_nw_pts-N+1)) != 1 ){
if (ShareSide( nw_pts(n_nw_pts-N), nw_pts(n_nw_pts-2)) == 1 &&
ShareSide(nw_pts(n_nw_pts-1), nw_pts(n_nw_pts-N+1)) == 1){
PlaceHolder = nw_pts(n_nw_pts-1);
nw_pts(n_nw_pts-1) = nw_pts(n_nw_pts-N);
nw_pts(n_nw_pts-N) = PlaceHolder;
}
}
}
// * * * ESTABLISH TRIANGLE CONNECTIONS * * *
for (p=n_nw_pts-N+2; p<n_nw_pts; p++){
nw_tris(0,n_nw_tris) = n_nw_pts-N;
nw_tris(1,n_nw_tris) = p-1;
nw_tris(2,n_nw_tris) = p;
n_nw_tris++;
}
}
// Compute the Interfacial Area
double s1,s2,s3,s;
Point pA,pB,pC;
double area = 0.0;
for (int r=0;r<n_nw_tris;r++){
pA = nw_pts(nw_tris(0,r));
pB = nw_pts(nw_tris(1,r));
pC = nw_pts(nw_tris(2,r));
// Compute length of sides (assume dx=dy=dz)
s1 = sqrt((pA.x-pB.x)*(pA.x-pB.x)+(pA.y-pB.y)*(pA.y-pB.y)+(pA.z-pB.z)*(pA.z-pB.z));
s2 = sqrt((pA.x-pC.x)*(pA.x-pC.x)+(pA.y-pC.y)*(pA.y-pC.y)+(pA.z-pC.z)*(pA.z-pC.z));
s3 = sqrt((pB.x-pC.x)*(pB.x-pC.x)+(pB.y-pC.y)*(pB.y-pC.y)+(pB.z-pC.z)*(pB.z-pC.z));
s = 0.5*(s1+s2+s3);
area+=sqrt(s*(s-s1)*(s-s2)*(s-s3));
}
return area;
}
//-------------------------------------------------------------------------------
inline void MC( DoubleArray &A, double &v, DoubleArray &solid, int &i, int &j, int &k,
DTMutableList<Point> &nw_pts, int &n_nw_pts, IntArray &nw_tris,
int &n_nw_tris)
{
int N = 0; // n will be the number of vertices in this grid cell only
Point P;
Point pt;
DoubleArray TEST(3);
Point PlaceHolder;
int m;
int o;
int p;
// Go over each corner -- check to see if the corners are themselves vertices
//1
if (A(i,j,k) == v){
P.x = i;
P.y = j;
P.z = k;
nw_pts(n_nw_pts++) = P;
N++;
}
//2
if (A(i+1,j,k) == v){
P.x = i+1;
P.y = j;
P.z = k;
nw_pts(n_nw_pts++) = P;
N++;
}
//3
if (A(i+1,j+1,k) == v){
P.x = i+1;
P.y = j+1;
P.z = k;
nw_pts(n_nw_pts++) = P;
N++;
}
//4
if (A(i,j+1,k) == v){
P.x = i;
P.y = j+1;
P.z = k;
nw_pts(n_nw_pts++) = P;
N++;
}
//5
if (A(i,j,k+1) == v){
P.x = i;
P.y = j;
P.z = k+1;
nw_pts(n_nw_pts++) = P;
N++;
}
//6
if (A(i+1,j,k+1) == v){
P.x = i+1;
P.y = j;
P.z = k+1;
nw_pts(n_nw_pts++) = P;
N++;
}
//7
if (A(i+1,j+1,k+1) == v){
P.x = i+1;
P.y = j+1;
P.z = k+1;
nw_pts(n_nw_pts++) = P;
N++;
}
//8
if (A(i,j+1,k+1) == v){
P.x = i;
P.y = j+1;
P.z = k+1;
nw_pts(n_nw_pts++) = P;
N++;
}
// Go through each side, compute P for sides of box spiraling up
// float val;
if ((A(i,j,k)-v)*(A(i+1,j,k)-v) < 0)
{
// If both points are in the fluid region
if (A(i,j,k) != 0 && A(i+1,j,k) != 0){
P.x = i + (A(i,j,k)-v)/(A(i,j,k)-A(i+1,j,k));
P.y = j;
P.z = k;
// Evaluate the function S at the new point
if ( solid(i,j,k)*(1-P.x+i) + solid(i+1,j,k)*(P.x-i) > 0 ){
// This point is in the fluid region
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
if ((A(i+1,j,k)-v)*(A(i+1,j+1,k)-v) < 0)
{
if ( A(i+1,j,k) != 0 && A(i+1,j+1,k) != 0 ){
P.x = i+1;
P.y = j + (A(i+1,j,k)-v)/(A(i+1,j,k)-A(i+1,j+1,k));
P.z = k;
// Evaluate the function S at the new point
if ( solid(i+1,j,k)*(1-P.y+j) + solid(i+1,j+1,k)*(P.y-j) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ // P is a new vertex (not counted twice)
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
if ((A(i+1,j+1,k)-v)*(A(i,j+1,k)-v) < 0 )
{
if ( A(i+1,j+1,k) != 0 && A(i,j+1,k) != 0 ){
P.x = i + (A(i,j+1,k)-v) / (A(i,j+1,k)-A(i+1,j+1,k));
P.y = j+1;
P.z = k;
// Evaluate the function S at the new point
if ( solid(i,j+1,k)*(1-P.x+i) + solid(i+1,j+1,k)*(P.x-i) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ // P is a new vertex (not counted twice)
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
//4
if ((A(i,j+1,k)-v)*(A(i,j,k)-v) < 0 )
{
if (A(i,j+1,k) != 0 && A(i,j,k) != 0 ){
P.x = i;
P.y = j + (A(i,j,k)-v) / (A(i,j,k)-A(i,j+1,k));
P.z = k;
// Evaluate the function S at the new point
if ( solid(i,j,k)*(1-P.y+j) + solid(i,j+1,k)*(P.y-j) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ // P is a new vertex (not counted twice)
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
//5
if ((A(i,j,k)-v)*(A(i,j,k+1)-v) < 0 )
{
if ( A(i,j,k) != 0 && A(i,j,k+1) != 0 ){
P.x = i;
P.y = j;
P.z = k + (A(i,j,k)-v) / (A(i,j,k)-A(i,j,k+1));
// Evaluate the function S at the new point
if ( solid(i,j,k)*(1-P.z+k) + solid(i,j,k+1)*(P.z-k) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ // P is a new vertex (not counted twice)
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
//6
if ((A(i+1,j,k)-v)*(A(i+1,j,k+1)-v) < 0 )
{
if ( A(i+1,j,k) != 0 && A(i+1,j,k+1) != 0 ){
P.x = i+1;
P.y = j;
P.z = k + (A(i+1,j,k)-v) / (A(i+1,j,k)-A(i+1,j,k+1));
// Evaluate the function S at the new point
if ( solid(i+1,j,k)*(1-P.z+k) + solid(i+1,j,k+1)*(P.z-k) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
//7
if ((A(i+1,j+1,k)-v)*(A(i+1,j+1,k+1)-v) < 0 )
{
if ( A(i+1,j+1,k) != 0 && A(i+1,j+1,k+1) != 0 ){
P.x = i+1;
P.y = j+1;
P.z = k + (A(i+1,j+1,k)-v) / (A(i+1,j+1,k)-A(i+1,j+1,k+1));
// Evaluate the function S at the new point
if ( solid(i+1,j+1,k)*(1-P.z+k) + solid(i+1,j+1,k+1)*(P.z-k) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
//8
if ((A(i,j+1,k)-v)*(A(i,j+1,k+1)-v) < 0 )
{
if ( A(i,j+1,k) != 0 && A(i,j+1,k+1) != 0 ){
P.x = i;
P.y = j+1;
P.z = k + (A(i,j+1,k)-v) / (A(i,j+1,k)-A(i,j+1,k+1));
// Evaluate the function S at the new point
if ( solid(i,j+1,k)*(1-P.z+k) + solid(i,j+1,k+1)*(P.z-k) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
//9
if ((A(i,j,k+1)-v)*(A(i+1,j,k+1)-v) < 0 )
{
if ( A(i,j,k+1) != 0 && A(i+1,j,k+1) != 0 ){
P.x = i + (A(i,j,k+1)-v) / (A(i,j,k+1)-A(i+1,j,k+1));
P.y = j;
P.z = k+1;
// Evaluate the function S at the new point
if ( solid(i,j,k+1)*(1-P.x+i) + solid(i+1,j,k+1)*(P.x-i) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
//10
if ((A(i+1,j,k+1)-v)*(A(i+1,j+1,k+1)-v) < 0 )
{
if ( A(i+1,j,k+1) != 0 && A(i+1,j+1,k+1) != 0 ){
P.x = i+1;
P.y = j + (A(i+1,j,k+1)-v) / (A(i+1,j,k+1)-A(i+1,j+1,k+1));
P.z = k+1;
// Evaluate the function S at the new point
if ( solid(i+1,j,k+1)*(1-P.y+j) + solid(i+1,j+1,k+1)*(P.y-j) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
//11
if ((A(i+1,j+1,k+1)-v)*(A(i,j+1,k+1)-v) < 0 )
{
if ( A(i+1,j+1,k+1) != 0 && A(i,j+1,k+1) != 0 ){
P.x = i+(A(i,j+1,k+1)-v) / (A(i,j+1,k+1)-A(i+1,j+1,k+1));
P.y = j+1;
P.z = k+1;
// Evaluate the function S at the new point
if ( solid(i,j+1,k+1)*(1-P.x+i) + solid(i+1,j+1,k+1)*(P.x-i) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
//12
if ((A(i,j+1,k+1)-v)*(A(i,j,k+1)-v) < 0 )
{
if ( A(i,j+1,k+1) != 0 && A(i,j,k+1) != 0 ){
P.x = i;
P.y = j + (A(i,j,k+1)-v) / (A(i,j,k+1)-A(i,j+1,k+1));
P.z = k+1;
// Evaluate the function S at the new point
if ( solid(i,j,k+1)*(1-P.y+j) + solid(i,j+1,k+1)*(P.y-j) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
// sort vertices so that they are connected to "neighbors"
// DTMatlabDataFile("/tmp/Dump.mat",DTFile::NewReadWrite);
// n_nw_pts = number of vertices in total (location n_nw_pts is first unfilled position)
// n = number of vertices in this grid cell
// Assemble the triangles as long as points are found
if (N > 0){
for (m = n_nw_pts-N; m < n_nw_pts-2; m++) {
for (o = m+2; o < n_nw_pts-1; o++) {
if (ShareSide(nw_pts(m), nw_pts(o)) == 1) {
PlaceHolder = nw_pts(m+1);
nw_pts(m+1) = nw_pts(o);
nw_pts(o) = PlaceHolder;
}
}
// make sure other neighbor of vertex 1 is in last spot
if (m == n_nw_pts-N){
for (p = m+2; p < n_nw_pts-1; p++){
if (ShareSide(nw_pts(m), nw_pts(p)) == 1){
PlaceHolder = nw_pts(n_nw_pts-1);
nw_pts(n_nw_pts-1) = nw_pts(p);
nw_pts(p) = PlaceHolder;
}
}
}
if ( ShareSide(nw_pts(n_nw_pts-2), nw_pts(n_nw_pts-3)) != 1 ){
if (ShareSide( nw_pts(n_nw_pts-3), nw_pts(n_nw_pts-1)) == 1 &&
ShareSide( nw_pts(n_nw_pts-N),nw_pts(n_nw_pts-2)) == 1 ){
PlaceHolder = nw_pts(n_nw_pts-2);
nw_pts(n_nw_pts-2) = nw_pts(n_nw_pts-1);
nw_pts(n_nw_pts-1) = PlaceHolder;
}
}
if ( ShareSide(nw_pts(n_nw_pts-1), nw_pts(n_nw_pts-2)) != 1 ){
if (ShareSide( nw_pts(n_nw_pts-3), nw_pts(n_nw_pts-1)) == 1 &&
ShareSide(nw_pts(n_nw_pts-4),nw_pts(n_nw_pts-2)) == 1 ){
PlaceHolder = nw_pts(n_nw_pts-3);
nw_pts(n_nw_pts-3) = nw_pts(n_nw_pts-2);
nw_pts(n_nw_pts-2) = PlaceHolder;
}
if (ShareSide( nw_pts(n_nw_pts-N+1), nw_pts(n_nw_pts-3)) == 1 &&
ShareSide(nw_pts(n_nw_pts-1),nw_pts(n_nw_pts-N+1)) == 1 ){
PlaceHolder = nw_pts(n_nw_pts-2);
nw_pts(n_nw_pts-2) = nw_pts(n_nw_pts-N+1);
nw_pts(n_nw_pts-N+1) = PlaceHolder;
}
}
if ( ShareSide(nw_pts(n_nw_pts-N), nw_pts(n_nw_pts-N+1)) != 1 ){
if (ShareSide( nw_pts(n_nw_pts-N), nw_pts(n_nw_pts-2)) == 1 &&
ShareSide(nw_pts(n_nw_pts-1), nw_pts(n_nw_pts-N+1)) == 1){
PlaceHolder = nw_pts(n_nw_pts-1);
nw_pts(n_nw_pts-1) = nw_pts(n_nw_pts-N);
nw_pts(n_nw_pts-N) = PlaceHolder;
}
}
}
// * * * ESTABLISH TRIANGLE CONNECTIONS * * *
for (p=n_nw_pts-N+2; p<n_nw_pts; p++){
nw_tris(0,n_nw_tris) = n_nw_pts-N;
nw_tris(1,n_nw_tris) = p-1;
nw_tris(2,n_nw_tris) = p;
n_nw_tris++;
}
}
}
//-------------------------------------------------------------------------------
inline void EDGE(DoubleArray &A, double &v, DoubleArray &solid, int &i, int &j, int &k, int &m, int &n, int &o,
DTMutableList<Point> &nw_pts, int &n_nw_pts, IntArray &nw_tris, int &n_nw_tris,
DTMutableList<Point> &local_nws_pts, int &n_local_nws_pts)
{
NULL_USE( m );
NULL_USE( n );
NULL_USE( o );
// FIND THE POINTS ON THE nw SURFACE THAT ARE ON THE EDGE (COMMON LINE WITH SOLID PHASE)
// function A is the fluid data padded (so that it has values inside the solid phase)
int N = 0; // n will be the number of vertices in this grid cell only
Point P;
Point temp;
int p; int q; int r;
// Add common line points to nw_pts
for (p=0;p<n_local_nws_pts;p++){
nw_pts(n_nw_pts++) = local_nws_pts(p);
}
// Go over each corner -- check to see if the corners are themselves vertices
//1
if (A(i,j,k) == v){
P.x = i;
P.y = j;
P.z = k;
nw_pts(n_nw_pts++) = P;
N++;
}
//2
if (A(i+1,j,k) == v){
P.x = i+1;
P.y = j;
P.z = k;
nw_pts(n_nw_pts++) = P;
N++;
}
//3
if (A(i+1,j+1,k) == v){
P.x = i+1;
P.y = j+1;
P.z = k;
nw_pts(n_nw_pts++) = P;
N++;
}
//4
if (A(i,j+1,k) == v){
P.x = i;
P.y = j+1;
P.z = k;
nw_pts(n_nw_pts++) = P;
N++;
}
//5
if (A(i,j,k+1) == v){
P.x = i;
P.y = j;
P.z = k+1;
nw_pts(n_nw_pts++) = P;
N++;
}
//6
if (A(i+1,j,k+1) == v){
P.x = i+1;
P.y = j;
P.z = k+1;
nw_pts(n_nw_pts++) = P;
N++;
}
//7
if (A(i+1,j+1,k+1) == v){
P.x = i+1;
P.y = j+1;
P.z = k+1;
nw_pts(n_nw_pts++) = P;
N++;
}
//8
if (A(i,j+1,k+1) == v){
P.x = i;
P.y = j+1;
P.z = k+1;
nw_pts(n_nw_pts++) = P;
N++;
}
// Go through each side, compute P for sides of box spiraling up
// float val;
Point pt;
// 1
if ((A(i,j,k)-v)*(A(i+1,j,k)-v) < 0)
{
// If both points are in the fluid region
if (A(i,j,k) != 0 && A(i+1,j,k) != 0){
P.x = i + (A(i,j,k)-v)/(A(i,j,k)-A(i+1,j,k));
P.y = j;
P.z = k;
// Evaluate the function S at the new point
if ( solid(i,j,k)*(1-P.x+i) + solid(i+1,j,k)*(P.x-i) > 0 ){
// This point is in the fluid region
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
// 2
if ((A(i+1,j,k)-v)*(A(i+1,j+1,k)-v) < 0)
{
if ( A(i+1,j,k) != 0 && A(i+1,j+1,k) != 0 ){
P.x = i+1;
P.y = j + (A(i+1,j,k)-v)/(A(i+1,j,k)-A(i+1,j+1,k));
P.z = k;
// Evaluate the function S at the new point
if ( solid(i+1,j,k)*(1-P.y+j) + solid(i+1,j+1,k)*(P.y-j) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ // P is a new vertex (not counted twice)
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
//3
if ((A(i+1,j+1,k)-v)*(A(i,j+1,k)-v) < 0 )
{
if ( A(i+1,j+1,k) != 0 && A(i,j+1,k) != 0 ){
P.x = i + (A(i,j+1,k)-v) / (A(i,j+1,k)-A(i+1,j+1,k));
P.y = j+1;
P.z = k;
// Evaluate the function S at the new point
if ( solid(i,j+1,k)*(1-P.x+i) + solid(i+1,j+1,k)*(P.x-i) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ // P is a new vertex (not counted twice)
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
//4
if ((A(i,j+1,k)-v)*(A(i,j,k)-v) < 0 )
{
if (A(i,j+1,k) != 0 && A(i,j,k) != 0 ){
P.x = i;
P.y = j + (A(i,j,k)-v) / (A(i,j,k)-A(i,j+1,k));
P.z = k;
// Evaluate the function S at the new point
if ( solid(i,j,k)*(1-P.y+j) + solid(i,j+1,k)*(P.y-j) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ // P is a new vertex (not counted twice)
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
//5
if ((A(i,j,k)-v)*(A(i,j,k+1)-v) < 0 )
{
if ( A(i,j,k) != 0 && A(i,j,k+1) != 0 ){
P.x = i;
P.y = j;
P.z = k + (A(i,j,k)-v) / (A(i,j,k)-A(i,j,k+1));
// Evaluate the function S at the new point
if ( solid(i,j,k)*(1-P.z+k) + solid(i,j,k+1)*(P.z-k) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ // P is a new vertex (not counted twice)
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
//6
if ((A(i+1,j,k)-v)*(A(i+1,j,k+1)-v) < 0 )
{
if ( A(i+1,j,k) != 0 && A(i+1,j,k+1) != 0 ){
P.x = i+1;
P.y = j;
P.z = k + (A(i+1,j,k)-v) / (A(i+1,j,k)-A(i+1,j,k+1));
// Evaluate the function S at the new point
if ( solid(i+1,j,k)*(1-P.z+k) + solid(i+1,j,k+1)*(P.z-k) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
//7
if ((A(i+1,j+1,k)-v)*(A(i+1,j+1,k+1)-v) < 0 )
{
if ( A(i+1,j+1,k) != 0 && A(i+1,j+1,k+1) != 0 ){
P.x = i+1;
P.y = j+1;
P.z = k + (A(i+1,j+1,k)-v) / (A(i+1,j+1,k)-A(i+1,j+1,k+1));
// Evaluate the function S at the new point
if ( solid(i+1,j+1,k)*(1-P.z+k) + solid(i+1,j+1,k+1)*(P.z-k) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
//8
if ((A(i,j+1,k)-v)*(A(i,j+1,k+1)-v) < 0 )
{
if ( A(i,j+1,k) != 0 && A(i,j+1,k+1) != 0 ){
P.x = i;
P.y = j+1;
P.z = k + (A(i,j+1,k)-v) / (A(i,j+1,k)-A(i,j+1,k+1));
// Evaluate the function S at the new point
if ( solid(i,j+1,k)*(1-P.z+k) + solid(i,j+1,k+1)*(P.z-k) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
//9
if ((A(i,j,k+1)-v)*(A(i+1,j,k+1)-v) < 0 )
{
if ( A(i,j,k+1) != 0 && A(i+1,j,k+1) != 0 ){
P.x = i + (A(i,j,k+1)-v) / (A(i,j,k+1)-A(i+1,j,k+1));
P.y = j;
P.z = k+1;
// Evaluate the function S at the new point
if ( solid(i,j,k+1)*(1-P.x+i) + solid(i+1,j,k+1)*(P.x-i) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
//10
if ((A(i+1,j,k+1)-v)*(A(i+1,j+1,k+1)-v) < 0 )
{
if ( A(i+1,j,k+1) != 0 && A(i+1,j+1,k+1) != 0 ){
P.x = i+1;
P.y = j + (A(i+1,j,k+1)-v) / (A(i+1,j,k+1)-A(i+1,j+1,k+1));
P.z = k+1;
// Evaluate the function S at the new point
if ( solid(i+1,j,k+1)*(1-P.y+j) + solid(i+1,j+1,k+1)*(P.y-j) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
//11
if ((A(i+1,j+1,k+1)-v)*(A(i,j+1,k+1)-v) < 0 )
{
if ( A(i+1,j+1,k+1) != 0 && A(i,j+1,k+1) != 0 ){
P.x = i+(A(i,j+1,k+1)-v) / (A(i,j+1,k+1)-A(i+1,j+1,k+1));
P.y = j+1;
P.z = k+1;
// Evaluate the function S at the new point
if ( solid(i,j+1,k+1)*(1-P.x+i) + solid(i+1,j+1,k+1)*(P.x-i) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
//12
if ((A(i,j+1,k+1)-v)*(A(i,j,k+1)-v) < 0 )
{
if ( A(i,j+1,k+1) != 0 && A(i,j,k+1) != 0 ){
P.x = i;
P.y = j + (A(i,j,k+1)-v) / (A(i,j,k+1)-A(i,j+1,k+1));
P.z = k+1;
// Evaluate the function S at the new point
if ( solid(i,j,k+1)*(1-P.y+j) + solid(i,j+1,k+1)*(P.y-j) > 0 ){
// This point is in the fluid region
if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){
nw_pts(n_nw_pts++) = P;
N++;
}
}
}
}
////////////////////////////////////////////////
////// SORT VERTICES SO THAT THEY CONNECT //////
////// TO ALL "NEIGHBORS" //////
////////////////////////////////////////////////
// First common line point should connect to last MC point
for (q=n_nw_pts-N; q<n_nw_pts-1; q++){
if ( ShareSide(nw_pts(n_nw_pts-N-n_local_nws_pts), nw_pts(n_nw_pts-1)) == 0 &&
ShareSide(nw_pts(n_nw_pts-N-n_local_nws_pts), nw_pts(q)) == 1 ){
// Switch point q with point n_nw_pts-N-n_local_nws_pts
temp = nw_pts(n_nw_pts-1);
nw_pts(n_nw_pts-1) = nw_pts(q);
nw_pts(q) = temp;
}
}
// Last common line point should connect to first MC point
for (q=n_nw_pts-N+1; q<n_nw_pts-1; q++){
if ( ShareSide(nw_pts(n_nw_pts-N-1), nw_pts(n_nw_pts-N)) == 0 &&
ShareSide(nw_pts(n_nw_pts-N-1), nw_pts(q)) == 1 ){
// Switch these points
temp = nw_pts(n_nw_pts-N);
nw_pts(n_nw_pts-N) = nw_pts(q);
nw_pts(q) = temp;
}
}
// All MC points should connect to their neighbors
for (q=n_nw_pts-N; q<n_nw_pts-2; q++){
if ( ShareSide(nw_pts(q), nw_pts(q+1)) == 0){
for (r=q+2; r < n_nw_pts-1; r++){
if ( ShareSide(nw_pts(q), nw_pts(q+1)) == 0 &&
ShareSide(nw_pts(q), nw_pts(r)) == 1){
// Switch r and q+1
temp = nw_pts(q+1);
nw_pts(q+1) = nw_pts(r);
nw_pts(r) = temp;
}
}
}
}
// * * * ESTABLISH TRIANGLE CONNECTIONS * * *
for (p=n_nw_pts-N-n_local_nws_pts; p<n_nw_pts-2; p++){
nw_tris(0,n_nw_tris) = n_nw_pts-1;
nw_tris(1,n_nw_tris) = p;
nw_tris(2,n_nw_tris) = p+1;
n_nw_tris++;
}
// for (p=n_nw_pts-N-n_local_nws_pts+2; p<n_nw_pts; p++){
// nw_tris(0,n_nw_tris) = n_nw_pts-N-n_local_nws_pts;
// nw_tris(1,n_nw_tris) = p-1;
// nw_tris(2,n_nw_tris) = p;
// n_nw_tris++;
// }
}
//--------------------------------------------------------------------------------------------------------
inline bool PointsEqual(const Point &A, const Point &B)
{
bool equal = false;
// double value;
// value = (A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y) + (A.z-B.z)*(A.z-B.z);
// if (value < 1e-14) equal = true;
if (A.x == B.x && A.y == B.y && A.z == B.z) equal = true;
return equal;
}
//--------------------------------------------------------------------------------------------------------
inline void ComputeAreasPMMC(IntArray &cubeList, int start, int finish,
DoubleArray &F, DoubleArray &S, double vF, double vS,
double &blob_volume, double &ans, double &aws, double &awn, double &lwns,
int Nx, int Ny, int Nz)
{
/* ****************************************************************
VARIABLES FOR THE PMMC ALGORITHM
****************************************************************** */
awn = aws = ans = lwns = 0.0;
// bool add=1; // Set to false if any corners contain nw-phase ( F > vF)
int cube[8][3] = {{0,0,0},{1,0,0},{0,1,0},{1,1,0},{0,0,1},{1,0,1},{0,1,1},{1,1,1}}; // cube corners
// int count_in=0,count_out=0;
// int nodx,nody,nodz;
// initialize lists for vertices for surfaces, common line
DTMutableList<Point> nw_pts(20);
DTMutableList<Point> ns_pts(20);
DTMutableList<Point> ws_pts(20);
DTMutableList<Point> nws_pts(20);
// initialize triangle lists for surfaces
IntArray nw_tris(3,20);
IntArray ns_tris(3,20);
IntArray ws_tris(3,20);
// initialize list for line segments
IntArray nws_seg(2,20);
DTMutableList<Point> tmp(20);
// IntArray store;
int i,j,k,p,q,r;
int n_nw_pts=0,n_ns_pts=0,n_ws_pts=0,n_nws_pts=0, map=0;
int n_nw_tris=0, n_ns_tris=0, n_ws_tris=0, n_nws_seg=0;
double s,s1,s2,s3; // Triangle sides (lengths)
Point A,B,C,P;
// double area;
// Initialize arrays for local solid surface
DTMutableList<Point> local_sol_pts(20);
int n_local_sol_pts = 0;
IntArray local_sol_tris(3,18);
int n_local_sol_tris;
DoubleArray values(20);
DTMutableList<Point> local_nws_pts(20);
int n_local_nws_pts;
int n_nw_tris_beg, n_ns_tris_beg, n_ws_tris_beg;
int c;
// int newton_steps = 0;
// double blob_volume;
/* ****************************************************************
RUN PMMC ON EACH BLOB
****************************************************************** */
// printf("Running the PMMC Algorithm \n");
// printf("The number of blobs is %i \n",nblobs);
// Store beginning points for surfaces for blob p
n_nw_tris_beg = n_nw_tris;
n_ns_tris_beg = n_ns_tris;
n_ws_tris_beg = n_ws_tris;
// n_nws_seg_beg = n_nws_seg;
// Loop over all cubes
blob_volume = 0; // Initialize the volume for blob a to zero
for (c=start;c<finish;c++){
// Get cube from the list
i = cubeList(0,c);
j = cubeList(1,c);
k = cubeList(2,c);
// printf("somewhere inside %i \n",c);
/* // Compute the volume
for (p=0;p<8;p++){
if ( indicator(i+cube[p][0],j+cube[p][1],k+cube[p][2]) > -1){
blob_volume += 0.125;
}
}
*/
for (p=0;p<8;p++){
if ( F(i+cube[p][0],j+cube[p][1],k+cube[p][2]) > 0
&& S(i+cube[p][0],j+cube[p][1],k+cube[p][2]) > 0 ){
blob_volume += 0.125;
}
}
// Run PMMC
n_local_sol_tris = 0;
n_local_sol_pts = 0;
n_local_nws_pts = 0;
// if there is a solid phase interface in the grid cell
if (Interface(S,vS,i,j,k) == 1){
/////////////////////////////////////////
/// CONSTRUCT THE LOCAL SOLID SURFACE ///
/////////////////////////////////////////
// find the local solid surface
SOL_SURF(S,0,F,vF,i,j,k, Nx,Ny,Nz,local_sol_pts,n_local_sol_pts,
local_sol_tris,n_local_sol_tris,values);
/////////////////////////////////////////
//////// TRIM THE SOLID SURFACE /////////
/////////////////////////////////////////
/* TRIM(local_sol_pts, n_local_sol_pts, fluid_isovalue,local_sol_tris, n_local_sol_tris,
ns_pts, n_ns_pts, ns_tris, n_ns_tris, ws_pts, n_ws_pts,
ws_tris, n_ws_tris, values, local_nws_pts, n_local_nws_pts,
Phase, SignDist, i, j, k, newton_steps);
*/
TRIM(local_sol_pts, n_local_sol_pts, vF, local_sol_tris, n_local_sol_tris,
ns_pts, n_ns_pts, ns_tris, n_ns_tris, ws_pts, n_ws_pts,
ws_tris, n_ws_tris, values, local_nws_pts, n_local_nws_pts);
/////////////////////////////////////////
//////// WRITE COMMON LINE POINTS ///////
//////// TO MAIN ARRAYS ///////
/////////////////////////////////////////
map = n_nws_pts;
for (p=0; p < n_local_nws_pts; p++){
nws_pts(n_nws_pts++) = local_nws_pts(p);
}
for (q=0; q < n_local_nws_pts-1; q++){
nws_seg(0,n_nws_seg) = map+q;
nws_seg(1,n_nws_seg) = map+q+1;
n_nws_seg++;
}
/////////////////////////////////////////
////// CONSTRUCT THE nw SURFACE /////////
/////////////////////////////////////////
if ( n_local_nws_pts > 0){
EDGE(F, vF, S, i,j,k, Nx, Ny, Nz, nw_pts, n_nw_pts, nw_tris, n_nw_tris,
local_nws_pts, n_local_nws_pts);
}
else {
MC(F, vF, S, i,j,k, nw_pts, n_nw_pts, nw_tris, n_nw_tris);
}
}
/////////////////////////////////////////
////// CONSTRUCT THE nw SURFACE /////////
/////////////////////////////////////////
else if (Fluid_Interface(F,S,vF,i,j,k) == 1){
MC(F, vF, S, i,j,k, nw_pts, n_nw_pts, nw_tris, n_nw_tris);
}
//******END OF BLOB PMMC*********************************************
//*******************************************************************
// Compute the Interfacial Areas, Common Line length for blob p
// nw surface
for (r=n_nw_tris_beg;r<n_nw_tris;r++){
A = nw_pts(nw_tris(0,r));
B = nw_pts(nw_tris(1,r));
C = nw_pts(nw_tris(2,r));
// Compute length of sides (assume dx=dy=dz)
s1 = sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z));
s2 = sqrt((A.x-C.x)*(A.x-C.x)+(A.y-C.y)*(A.y-C.y)+(A.z-C.z)*(A.z-C.z));
s3 = sqrt((B.x-C.x)*(B.x-C.x)+(B.y-C.y)*(B.y-C.y)+(B.z-C.z)*(B.z-C.z));
s = 0.5*(s1+s2+s3);
awn=awn+sqrt(s*(s-s1)*(s-s2)*(s-s3));
}
for (r=n_ns_tris_beg;r<n_ns_tris;r++){
A = ns_pts(ns_tris(0,r));
B = ns_pts(ns_tris(1,r));
C = ns_pts(ns_tris(2,r));
// Compute length of sides (assume dx=dy=dz)
s1 = sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z));
s2 = sqrt((A.x-C.x)*(A.x-C.x)+(A.y-C.y)*(A.y-C.y)+(A.z-C.z)*(A.z-C.z));
s3 = sqrt((B.x-C.x)*(B.x-C.x)+(B.y-C.y)*(B.y-C.y)+(B.z-C.z)*(B.z-C.z));
s = 0.5*(s1+s2+s3);
ans=ans+sqrt(s*(s-s1)*(s-s2)*(s-s3));
}
for (r=n_ws_tris_beg;r<n_ws_tris;r++){
A = ws_pts(ws_tris(0,r));
B = ws_pts(ws_tris(1,r));
C = ws_pts(ws_tris(2,r));
// Compute length of sides (assume dx=dy=dz)
s1 = sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z));
s2 = sqrt((A.x-C.x)*(A.x-C.x)+(A.y-C.y)*(A.y-C.y)+(A.z-C.z)*(A.z-C.z));
s3 = sqrt((B.x-C.x)*(B.x-C.x)+(B.y-C.y)*(B.y-C.y)+(B.z-C.z)*(B.z-C.z));
s = 0.5*(s1+s2+s3);
aws=aws+sqrt(s*(s-s1)*(s-s2)*(s-s3));
}
//*******************************************************************
// Reset the triangle counts to zero
n_nw_pts=0,n_ns_pts=0,n_ws_pts=0,n_nws_pts=0, map=0;
n_nw_tris=0, n_ns_tris=0, n_ws_tris=0, n_nws_seg=0;
n_nw_tris_beg = n_nw_tris;
n_ns_tris_beg = n_ns_tris;
n_ws_tris_beg = n_ws_tris;
// n_nws_seg_beg = n_nws_seg;
//*******************************************************************
}
}
//--------------------------------------------------------------------------------------------------------
inline void pmmc_ConstructLocalCube(DoubleArray &SignDist, DoubleArray &Phase, double solid_isovalue, double fluid_isovalue,
DTMutableList<Point> &nw_pts, IntArray &nw_tris, DoubleArray &values,
DTMutableList<Point> &ns_pts, IntArray &ns_tris,
DTMutableList<Point> &ws_pts, IntArray &ws_tris,
DTMutableList<Point> &local_nws_pts, DTMutableList<Point> &nws_pts, IntArray &nws_seg,
DTMutableList<Point> &local_sol_pts, IntArray &local_sol_tris,
int &n_local_sol_tris, int &n_local_sol_pts, int &n_nw_pts, int &n_nw_tris,
int &n_ws_pts, int &n_ws_tris, int &n_ns_tris, int &n_ns_pts,
int &n_local_nws_pts, int &n_nws_pts, int &n_nws_seg,
int i, int j, int k, int Nx, int Ny, int Nz)
{
int p,q,map;
Point A,B,C,P;
// Only the local values are constructed and retained! (set counts to zero to force this)
n_local_sol_tris = 0;
n_local_sol_pts = 0;
n_local_nws_pts = 0;
n_nw_pts=0,n_ns_pts=0,n_ws_pts=0,n_nws_pts=0, map=0;
n_nw_tris=0, n_ns_tris=0, n_ws_tris=0, n_nws_seg=0;
// if there is a solid phase interface in the grid cell
if (Interface(SignDist,solid_isovalue,i,j,k) == 1){
/////////////////////////////////////////
/// CONSTRUCT THE LOCAL SOLID SURFACE ///
/////////////////////////////////////////
// find the local solid surface using the regular Marching Cubes algorithm
SolidMarchingCubes(SignDist,0.0,Phase,fluid_isovalue,i,j,k,Nx,Ny,Nz,local_sol_pts,n_local_sol_pts,
local_sol_tris,n_local_sol_tris,values);
/////////////////////////////////////////
//////// TRIM THE SOLID SURFACE /////////
/////////////////////////////////////////
TRIM(local_sol_pts, n_local_sol_pts, fluid_isovalue,local_sol_tris, n_local_sol_tris,
ns_pts, n_ns_pts, ns_tris, n_ns_tris, ws_pts, n_ws_pts,
ws_tris, n_ws_tris, values, local_nws_pts, n_local_nws_pts);
/////////////////////////////////////////
//////// WRITE COMMON LINE POINTS ///////
//////// TO MAIN ARRAYS ///////
/////////////////////////////////////////
// SORT THE LOCAL COMMON LINE POINTS
/////////////////////////////////////////
// Make sure the first common line point is on a face
// Common curve points are located pairwise and must
// be searched and rearranged accordingly
if (n_local_nws_pts > 0){
for (p=0; p<n_local_nws_pts-1; p++){
P = local_nws_pts(p);
if ( P.x == 1.0*i || P.x ==1.0*(i+1)||
P.y == 1.0*j || P.y == 1.0*(j+1) ||
P.z == 1.0*k || P.z == 1.0*(k+1) ){
if (p%2 == 0){
// even points
// Swap the pair of points
local_nws_pts(p) = local_nws_pts(0);
local_nws_pts(0) = P;
P = local_nws_pts(p+1);
local_nws_pts(p+1) = local_nws_pts(1);
local_nws_pts(1) = P;
p = n_local_nws_pts;
}
else{
// odd points - flip the order
local_nws_pts(p) = local_nws_pts(p-1);
local_nws_pts(p-1) = P;
p-=2;
}
// guarantee exit from the loop
}
}
// Two common curve points per triangle
// 0-(1=2)-(3=4)-...
for (p=1; p<n_local_nws_pts-1; p+=2){
A = local_nws_pts(p);
for (q=p+1; q<n_local_nws_pts; q++){
B = local_nws_pts(q);
if ( A.x == B.x && A.y == B.y && A.z == B.z){
if (q%2 == 0){
// even points
// Swap the pair of points
local_nws_pts(q) = local_nws_pts(p+1);
local_nws_pts(p+1) = B;
B = local_nws_pts(q+1);
local_nws_pts(q+1) = local_nws_pts(p+2);
local_nws_pts(p+2) = B;
q = n_local_nws_pts;
}
else{
// odd points - flip the order
local_nws_pts(q) = local_nws_pts(q-1);
local_nws_pts(q-1) = B;
q-=2;
}
}
}
}
map = n_nws_pts = 0;
nws_pts(n_nws_pts++) = local_nws_pts(0);
for (p=2; p < n_local_nws_pts; p+=2){
nws_pts(n_nws_pts++) = local_nws_pts(p);
}
nws_pts(n_nws_pts++) = local_nws_pts(n_local_nws_pts-1);
for (q=0; q < n_nws_pts-1; q++){
nws_seg(0,n_nws_seg) = map+q;
nws_seg(1,n_nws_seg) = map+q+1;
n_nws_seg++;
}
// End of the common line sorting algorithm
/////////////////////////////////////////
}
/////////////////////////////////////////
////// CONSTRUCT THE nw SURFACE /////////
/////////////////////////////////////////
if ( n_local_nws_pts > 0){
n_nw_tris =0;
EDGE(Phase, fluid_isovalue, SignDist, i,j,k, Nx, Ny, Nz, nw_pts, n_nw_pts, nw_tris, n_nw_tris,
nws_pts, n_nws_pts);
}
else {
MC(Phase, fluid_isovalue, SignDist, i,j,k, nw_pts, n_nw_pts, nw_tris, n_nw_tris);
}
}
/////////////////////////////////////////
////// CONSTRUCT THE nw SURFACE /////////
/////////////////////////////////////////
else if (Fluid_Interface(Phase,SignDist,fluid_isovalue,i,j,k) == 1){
MC(Phase, fluid_isovalue, SignDist, i,j,k, nw_pts, n_nw_pts, nw_tris, n_nw_tris);
}
}
//--------------------------------------------------------------------------------------------------------
inline void pmmc_MeshGradient(DoubleArray &f, DoubleArray &fx, DoubleArray &fy, DoubleArray &fz, int Nx, int Ny, int Nz)
{
int i,j,k;
// Compute the Gradient everywhere except the halo region
for (k=1; k<Nz-1; k++){
for (j=1; j<Ny-1; j++){
for (i=1; i<Nx-1; i++){
// Compute all of the derivatives using finite differences
fx(i,j,k) = 0.5*(f(i+1,j,k) - f(i-1,j,k));
fy(i,j,k) = 0.5*(f(i,j+1,k) - f(i,j-1,k));
fz(i,j,k) = 0.5*(f(i,j,k+1) - f(i,j,k-1));
}
}
}
}
//--------------------------------------------------------------------------------------------------------
inline void pmmc_MeshCurvature(DoubleArray &f, DoubleArray &MeanCurvature, DoubleArray &GaussCurvature,
int Nx, int Ny, int Nz)
{
// Mesh spacing is taken to be one to simplify the calculation
int i,j,k;
double denominator;
double fxx,fyy,fzz,fxy,fxz,fyz,fx,fy,fz;
// Compute the curvature everywhere except the halo region
for (k=1; k<Nz-1; k++){
for (j=1; j<Ny-1; j++){
for (i=1; i<Nx-1; i++){
// Compute all of the derivatives using finite differences
fx = 0.5*(f(i+1,j,k) - f(i-1,j,k));
fy = 0.5*(f(i,j+1,k) - f(i,j-1,k));
fz = 0.5*(f(i,j,k+1) - f(i,j,k-1));
fxx = f(i+1,j,k) - 2.0*f(i,j,k) + f(i-1,j,k);
fyy = f(i,j+1,k) - 2.0*f(i,j,k) + f(i,j-1,k);
fzz = f(i,j,k+1) - 2.0*f(i,j,k) + f(i,j,k-1);
fxy = 0.25*(f(i+1,j+1,k) - f(i+1,j-1,k) - f(i-1,j+1,k) + f(i-1,j-1,k));
fxz = 0.25*(f(i+1,j,k+1) - f(i+1,j,k-1) - f(i-1,j,k+1) + f(i-1,j,k-1));
fyz = 0.25*(f(i,j+1,k+1) - f(i,j+1,k-1) - f(i,j-1,k+1) + f(i,j-1,k-1));
// Evaluate the Mean Curvature
denominator = pow(sqrt(fx*fx + fy*fy + fz*fz),3);
if (denominator == 0.0){
MeanCurvature(i,j,k) = 0.0;
}
else{
MeanCurvature(i,j,k)=(1.0/denominator)*((fyy+fzz)*fx*fx + (fxx+fzz)*fy*fy + (fxx+fyy)*fz*fz
-2.0*fx*fy*fxy - 2.0*fx*fz*fxz - 2.0*fy*fz*fyz);
}
// Evaluate the Gaussian Curvature
denominator = pow(fx*fx + fy*fy + fz*fz,2);
if (denominator == 0.0){
GaussCurvature(i,j,k) = 0.0;
}
else{
GaussCurvature(i,j,k) = (1.0/denominator)*(fx*fx*(fyy*fzz-fyz*fyz) + fy*fy*(fxx*fzz-fxz*fxz) + fz*fz*(fxx*fyy-fxy*fxy)
+2.0*(fx*fy*(fxz*fyz-fxy*fzz) + fy*fz*(fxy*fxz-fyz*fxx)
+ fx*fz*(fxy*fyz-fxz*fyy)));
}
}
}
}
}
//--------------------------------------------------------------------------------------------------------
inline int pmmc_CubeListFromMesh(IntArray &cubeList, int ncubes, int Nx, int Ny, int Nz)
{
NULL_USE( ncubes );
int i,j,k,nc;
nc=0;
//...........................................................................
// Set up the cube list (very regular in this case due to lack of blob-ID)
for (k=1; k<Nz-2; k++){
for (j=1; j<Ny-2; j++){
for (i=1; i<Nx-2; i++){
cubeList(0,nc) = i;
cubeList(1,nc) = j;
cubeList(2,nc) = k;
nc++;
}
}
}
return nc;
}
//--------------------------------------------------------------------------------------------------------
inline void pmmc_CubeListFromBlobs()
{
}
//--------------------------------------------------------------------------------------------------------
inline double pmmc_CubeSurfaceArea(DTMutableList<Point> &Points, IntArray &Triangles, int ntris)
{
int r;
double temp,area,s,s1,s2,s3;
Point A,B,C;
area = 0.0;
for (r=0;r<ntris;r++){
A = Points(Triangles(0,r));
B = Points(Triangles(1,r));
C = Points(Triangles(2,r));
// Compute length of sides (assume dx=dy=dz)
s1 = sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z));
s2 = sqrt((A.x-C.x)*(A.x-C.x)+(A.y-C.y)*(A.y-C.y)+(A.z-C.z)*(A.z-C.z));
s3 = sqrt((B.x-C.x)*(B.x-C.x)+(B.y-C.y)*(B.y-C.y)+(B.z-C.z)*(B.z-C.z));
s = 0.5*(s1+s2+s3);
temp = s*(s-s1)*(s-s2)*(s-s3);
if (temp > 0.0) area += sqrt(temp);
}
return area;
}
//--------------------------------------------------------------------------------------------------------
inline double pmmc_CubeCurveLength(DTMutableList<Point> &Points, int npts)
{
int p;
double s,lwns;
Point A,B;
lwns = 0.0;
for (p=0; p < npts-1; p++){
// Extract the line segment
A = Points(p);
B = Points(p+1);
// Compute the length of the segment
s = sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z));
// Add the length to the common line
lwns += s;
}
return lwns;
}
//--------------------------------------------------------------------------------------------------------
inline void pmmc_CubeTrimSurfaceInterpValues(DoubleArray &CubeValues, DoubleArray &MeshValues, DoubleArray &SignDist,
DTMutableList<Point> &Points, IntArray &Triangles,
DoubleArray &SurfaceValues, DoubleArray &DistanceValues, int i, int j, int k, int npts, int ntris,
double mindist, double &area, double &integral)
{
// mindist - minimum distance to consider in the average (in voxel lengths)
Point A,B,C;
int p;
double vA,vB,vC;
double dA,dB,dC;
double x,y,z;
double s,s1,s2,s3,temp;
double a,b,c,d,e,f,g,h;
// Copy the curvature values for the cube
CubeValues(0,0,0) = MeshValues(i,j,k);
CubeValues(1,0,0) = MeshValues(i+1,j,k);
CubeValues(0,1,0) = MeshValues(i,j+1,k);
CubeValues(1,1,0) = MeshValues(i+1,j+1,k);
CubeValues(0,0,1) = MeshValues(i,j,k+1);
CubeValues(1,0,1) = MeshValues(i+1,j,k+1);
CubeValues(0,1,1) = MeshValues(i,j+1,k+1);
CubeValues(1,1,1) = MeshValues(i+1,j+1,k+1);
// trilinear coefficients: f(x,y,z) = a+bx+cy+dz+exy+fxz+gyz+hxyz
// Evaluate the coefficients
a = CubeValues(0,0,0);
b = CubeValues(1,0,0)-a;
c = CubeValues(0,1,0)-a;
d = CubeValues(0,0,1)-a;
e = CubeValues(1,1,0)-a-b-c;
f = CubeValues(1,0,1)-a-b-d;
g = CubeValues(0,1,1)-a-c-d;
h = CubeValues(1,1,1)-a-b-c-d-e-f-g;
for (p=0; p<npts; p++){
A = Points(p);
x = A.x-1.0*i;
y = A.y-1.0*j;
z = A.z-1.0*k;
SurfaceValues(p) = a + b*x + c*y+d*z + e*x*y + f*x*z + g*y*z + h*x*y*z;
}
// Copy the signed distance values for the cube
CubeValues(0,0,0) = SignDist(i,j,k);
CubeValues(1,0,0) = SignDist(i+1,j,k);
CubeValues(0,1,0) = SignDist(i,j+1,k);
CubeValues(1,1,0) = SignDist(i+1,j+1,k);
CubeValues(0,0,1) = SignDist(i,j,k+1);
CubeValues(1,0,1) = SignDist(i+1,j,k+1);
CubeValues(0,1,1) = SignDist(i,j+1,k+1);
CubeValues(1,1,1) = SignDist(i+1,j+1,k+1);
// trilinear coefficients: f(x,y,z) = a+bx+cy+dz+exy+fxz+gyz+hxyz
// Evaluate the coefficients
a = CubeValues(0,0,0);
b = CubeValues(1,0,0)-a;
c = CubeValues(0,1,0)-a;
d = CubeValues(0,0,1)-a;
e = CubeValues(1,1,0)-a-b-c;
f = CubeValues(1,0,1)-a-b-d;
g = CubeValues(0,1,1)-a-c-d;
h = CubeValues(1,1,1)-a-b-c-d-e-f-g;
for (p=0; p<npts; p++){
A = Points(p);
x = A.x-1.0*i;
y = A.y-1.0*j;
z = A.z-1.0*k;
DistanceValues(p) = a + b*x + c*y+d*z + e*x*y + f*x*z + g*y*z + h*x*y*z;
}
for (int r=0; r<ntris; r++){
A = Points(Triangles(0,r));
B = Points(Triangles(1,r));
C = Points(Triangles(2,r));
vA = SurfaceValues(Triangles(0,r));
vB = SurfaceValues(Triangles(1,r));
vC = SurfaceValues(Triangles(2,r));
dA = DistanceValues(Triangles(0,r));
dB = DistanceValues(Triangles(1,r));
dC = DistanceValues(Triangles(2,r));
// Compute length of sides (assume dx=dy=dz)
s1 = sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z));
s2 = sqrt((A.x-C.x)*(A.x-C.x)+(A.y-C.y)*(A.y-C.y)+(A.z-C.z)*(A.z-C.z));
s3 = sqrt((B.x-C.x)*(B.x-C.x)+(B.y-C.y)*(B.y-C.y)+(B.z-C.z)*(B.z-C.z));
s = 0.5*(s1+s2+s3);
temp = s*(s-s1)*(s-s2)*(s-s3);
if (temp > 0.0){
if (dA > mindist){
integral += sqrt(temp)*0.33333333333333333*(vA);
area += sqrt(temp)*0.33333333333333333;
}
if (dB > mindist){
integral += sqrt(temp)*0.33333333333333333*(vB);
area += sqrt(temp)*0.33333333333333333;
}
if (dC > mindist){
integral += sqrt(temp)*0.33333333333333333*(vC);
area += sqrt(temp)*0.33333333333333333;
}
}
}
}
inline void pmmc_CubeTrimSurfaceInterpInverseValues(DoubleArray &CubeValues, DoubleArray &MeshValues, DoubleArray &SignDist,
DTMutableList<Point> &Points, IntArray &Triangles,
DoubleArray &SurfaceValues, DoubleArray &DistanceValues, int i, int j, int k, int npts, int ntris,
double mindist, double &area, double &integral)
{
// mindist - minimum distance to consider in the average (in voxel lengths)
Point A,B,C;
int p;
double vA,vB,vC;
double dA,dB,dC;
double x,y,z;
double s,s1,s2,s3,temp;
double a,b,c,d,e,f,g,h;
// Copy the curvature values for the cube
CubeValues(0,0,0) = MeshValues(i,j,k);
CubeValues(1,0,0) = MeshValues(i+1,j,k);
CubeValues(0,1,0) = MeshValues(i,j+1,k);
CubeValues(1,1,0) = MeshValues(i+1,j+1,k);
CubeValues(0,0,1) = MeshValues(i,j,k+1);
CubeValues(1,0,1) = MeshValues(i+1,j,k+1);
CubeValues(0,1,1) = MeshValues(i,j+1,k+1);
CubeValues(1,1,1) = MeshValues(i+1,j+1,k+1);
// trilinear coefficients: f(x,y,z) = a+bx+cy+dz+exy+fxz+gyz+hxyz
// Evaluate the coefficients
a = CubeValues(0,0,0);
b = CubeValues(1,0,0)-a;
c = CubeValues(0,1,0)-a;
d = CubeValues(0,0,1)-a;
e = CubeValues(1,1,0)-a-b-c;
f = CubeValues(1,0,1)-a-b-d;
g = CubeValues(0,1,1)-a-c-d;
h = CubeValues(1,1,1)-a-b-c-d-e-f-g;
for (p=0; p<npts; p++){
A = Points(p);
x = A.x-1.0*i;
y = A.y-1.0*j;
z = A.z-1.0*k;
SurfaceValues(p) = a + b*x + c*y+d*z + e*x*y + f*x*z + g*y*z + h*x*y*z;
}
// Copy the signed distance values for the cube
CubeValues(0,0,0) = SignDist(i,j,k);
CubeValues(1,0,0) = SignDist(i+1,j,k);
CubeValues(0,1,0) = SignDist(i,j+1,k);
CubeValues(1,1,0) = SignDist(i+1,j+1,k);
CubeValues(0,0,1) = SignDist(i,j,k+1);
CubeValues(1,0,1) = SignDist(i+1,j,k+1);
CubeValues(0,1,1) = SignDist(i,j+1,k+1);
CubeValues(1,1,1) = SignDist(i+1,j+1,k+1);
// trilinear coefficients: f(x,y,z) = a+bx+cy+dz+exy+fxz+gyz+hxyz
// Evaluate the coefficients
a = CubeValues(0,0,0);
b = CubeValues(1,0,0)-a;
c = CubeValues(0,1,0)-a;
d = CubeValues(0,0,1)-a;
e = CubeValues(1,1,0)-a-b-c;
f = CubeValues(1,0,1)-a-b-d;
g = CubeValues(0,1,1)-a-c-d;
h = CubeValues(1,1,1)-a-b-c-d-e-f-g;
for (p=0; p<npts; p++){
A = Points(p);
x = A.x-1.0*i;
y = A.y-1.0*j;
z = A.z-1.0*k;
DistanceValues(p) = a + b*x + c*y+d*z + e*x*y + f*x*z + g*y*z + h*x*y*z;
}
for (int r=0; r<ntris; r++){
A = Points(Triangles(0,r));
B = Points(Triangles(1,r));
C = Points(Triangles(2,r));
vA = SurfaceValues(Triangles(0,r));
vB = SurfaceValues(Triangles(1,r));
vC = SurfaceValues(Triangles(2,r));
dA = DistanceValues(Triangles(0,r));
dB = DistanceValues(Triangles(1,r));
dC = DistanceValues(Triangles(2,r));
// Compute length of sides (assume dx=dy=dz)
s1 = sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z));
s2 = sqrt((A.x-C.x)*(A.x-C.x)+(A.y-C.y)*(A.y-C.y)+(A.z-C.z)*(A.z-C.z));
s3 = sqrt((B.x-C.x)*(B.x-C.x)+(B.y-C.y)*(B.y-C.y)+(B.z-C.z)*(B.z-C.z));
s = 0.5*(s1+s2+s3);
temp = s*(s-s1)*(s-s2)*(s-s3);
if (temp > 0.0){
if (dA > mindist && vA != 0.0){
integral += sqrt(temp)*0.33333333333333333*(1.0/vA);
area += sqrt(temp)*0.33333333333333333;
}
if (dB > mindist && vB != 0.0){
integral += sqrt(temp)*0.33333333333333333*(1.0/vB);
area += sqrt(temp)*0.33333333333333333;
}
if (dC > mindist && vC != 0.0){
integral += sqrt(temp)*0.33333333333333333*(1.0/vC);
area += sqrt(temp)*0.33333333333333333;
}
}
}
}
inline double pmmc_CubeSurfaceInterpValue(DoubleArray &CubeValues, DoubleArray &MeshValues, DTMutableList<Point> &Points, IntArray &Triangles,
DoubleArray &SurfaceValues, int i, int j, int k, int npts, int ntris)
{
Point A,B,C;
int p;
double vA,vB,vC;
double x,y,z;
double s,s1,s2,s3,temp;
double a,b,c,d,e,f,g,h;
double integral;
// Copy the curvature values for the cube
CubeValues(0,0,0) = MeshValues(i,j,k);
CubeValues(1,0,0) = MeshValues(i+1,j,k);
CubeValues(0,1,0) = MeshValues(i,j+1,k);
CubeValues(1,1,0) = MeshValues(i+1,j+1,k);
CubeValues(0,0,1) = MeshValues(i,j,k+1);
CubeValues(1,0,1) = MeshValues(i+1,j,k+1);
CubeValues(0,1,1) = MeshValues(i,j+1,k+1);
CubeValues(1,1,1) = MeshValues(i+1,j+1,k+1);
// trilinear coefficients: f(x,y,z) = a+bx+cy+dz+exy+fxz+gyz+hxyz
// Evaluate the coefficients
a = CubeValues(0,0,0);
b = CubeValues(1,0,0)-a;
c = CubeValues(0,1,0)-a;
d = CubeValues(0,0,1)-a;
e = CubeValues(1,1,0)-a-b-c;
f = CubeValues(1,0,1)-a-b-d;
g = CubeValues(0,1,1)-a-c-d;
h = CubeValues(1,1,1)-a-b-c-d-e-f-g;
for (p=0; p<npts; p++){
A = Points(p);
x = A.x-1.0*i;
y = A.y-1.0*j;
z = A.z-1.0*k;
SurfaceValues(p) = a + b*x + c*y+d*z + e*x*y + f*x*z + g*y*z + h*x*y*z;
}
integral = 0.0;
for (int r=0; r<ntris; r++){
A = Points(Triangles(0,r));
B = Points(Triangles(1,r));
C = Points(Triangles(2,r));
vA = SurfaceValues(Triangles(0,r));
vB = SurfaceValues(Triangles(1,r));
vC = SurfaceValues(Triangles(2,r));
// Compute length of sides (assume dx=dy=dz)
s1 = sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z));
s2 = sqrt((A.x-C.x)*(A.x-C.x)+(A.y-C.y)*(A.y-C.y)+(A.z-C.z)*(A.z-C.z));
s3 = sqrt((B.x-C.x)*(B.x-C.x)+(B.y-C.y)*(B.y-C.y)+(B.z-C.z)*(B.z-C.z));
s = 0.5*(s1+s2+s3);
temp = s*(s-s1)*(s-s2)*(s-s3);
if (temp > 0.0) integral += sqrt(temp)*0.33333333333333333*(vA+vB+vC);
}
return integral;
}
//--------------------------------------------------------------------------------------------------------
inline double pmmc_CubeCurveInterpValue(DoubleArray &CubeValues, DoubleArray &CurveValues,
DTMutableList<Point> &Points, int i, int j, int k, int npts)
{
int p;
Point A,B;
double vA,vB;
double x,y,z;
// double s,s1,s2,s3,temp;
double a,b,c,d,e,f,g,h;
double integral;
double length;
// trilinear coefficients: f(x,y,z) = a+bx+cy+dz+exy+fxz+gyz+hxyz
// Evaluate the coefficients
a = CubeValues(0,0,0);
b = CubeValues(1,0,0)-a;
c = CubeValues(0,1,0)-a;
d = CubeValues(0,0,1)-a;
e = CubeValues(1,1,0)-a-b-c;
f = CubeValues(1,0,1)-a-b-d;
g = CubeValues(0,1,1)-a-c-d;
h = CubeValues(1,1,1)-a-b-c-d-e-f-g;
for (p=0; p<npts; p++){
A = Points(p);
x = A.x-1.0*i;
y = A.y-1.0*j;
z = A.z-1.0*k;
CurveValues(p) = a + b*x + c*y+d*z + e*x*y + f*x*z + g*y*z + h*x*y*z;
}
integral = 0.0;
for (p=0; p < npts-1; p++){
// Extract the line segment
A = Points(p);
B = Points(p+1);
vA = CurveValues(p);
vB = CurveValues(p+1);
// Compute the length of the segment
length = sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z));
integral += 0.5*length*(vA + vB);
}
return integral;
}
//--------------------------------------------------------------------------------------------------------
inline double pmmc_CubeContactAngle(DoubleArray &CubeValues, DoubleArray &CurveValues,
DoubleArray &Fx, DoubleArray &Fy, DoubleArray &Fz,
DoubleArray &Sx, DoubleArray &Sy, DoubleArray &Sz,
DTMutableList<Point> &Points, int i, int j, int k, int npts)
{
int p;
Point A,B;
double vA,vB;
double x,y,z;
// double s,s1,s2,s3,temp;
double a,b,c,d,e,f,g,h;
double integral;
double length;
double denom;
// theta = acos ( -(gradF*gradS) / (|gradF| |gradS|) )
denom = sqrt(pow(Fx(i,j,k),2)+pow(Fy(i,j,k),2)+pow(Fz(i,j,k),2))
*sqrt(pow(Sx(i,j,k),2)+pow(Sy(i,j,k),2)+pow(Sz(i,j,k),2));
if (denom == 0.0) denom =1.0;
CubeValues(0,0,0) = -( Fx(i,j,k)*Sx(i,j,k)+Fy(i,j,k)*Sy(i,j,k)+Fz(i,j,k)*Sz(i,j,k) )/(denom);
denom = sqrt(pow(Fx(i+1,j,k),2)+pow(Fy(i+1,j,k),2)+pow(Fz(i+1,j,k),2))
*sqrt(pow(Sx(i+1,j,k),2)+pow(Sy(i+1,j,k),2)+pow(Sz(i+1,j,k),2));
if (denom == 0.0) denom =1.0;
CubeValues(1,0,0) = -( Fx(i+1,j,k)*Sx(i+1,j,k)+Fy(i+1,j,k)*Sy(i+1,j,k)+Fz(i+1,j,k)*Sz(i+1,j,k) )
/( denom );
denom = sqrt(pow(Fx(i,j+1,k),2)+pow(Fy(i,j+1,k),2)+pow(Fz(i,j+1,k),2))
*sqrt(pow(Sx(i,j+1,k),2)+pow(Sy(i,j+1,k),2)+pow(Sz(i,j+1,k),2));
if (denom == 0.0) denom =1.0;
CubeValues(0,1,0) = -( Fx(i,j+1,k)*Sx(i,j+1,k)+Fy(i,j+1,k)*Sy(i,j+1,k)+Fz(i,j+1,k)*Sz(i,j+1,k) )
/( denom );
denom = sqrt(pow(Fx(i,j,k+1),2)+pow(Fy(i,j,k+1),2)+pow(Fz(i,j,k+1),2))
*sqrt(pow(Sx(i,j,k+1),2)+pow(Sy(i,j,k+1),2)+pow(Sz(i,j,k+1),2));
if (denom == 0.0) denom =1.0;
CubeValues(0,0,1) = -( Fx(i,j,k+1)*Sx(i,j,k+1)+Fy(i,j,k+1)*Sy(i,j,k+1)+Fz(i,j,k+1)*Sz(i,j,k+1) )
/( denom);
denom = sqrt(pow(Fx(i+1,j+1,k),2)+pow(Fy(i+1,j+1,k),2)+pow(Fz(i+1,j+1,k),2))
*sqrt(pow(Sx(i+1,j+1,k),2)+pow(Sy(i+1,j+1,k),2)+pow(Sz(i+1,j+1,k),2));
if (denom == 0.0) denom =1.0;
CubeValues(1,1,0) = -( Fx(i+1,j+1,k)*Sx(i+1,j+1,k)+Fy(i+1,j+1,k)*Sy(i+1,j+1,k)+Fz(i+1,j+1,k)*Sz(i+1,j+1,k) )
/( denom );
denom = sqrt(pow(Fx(i+1,j,k+1),2)+pow(Fy(i+1,j,k+1),2)+pow(Fz(i+1,j,k+1),2))
*sqrt(pow(Sx(i+1,j,k+1),2)+pow(Sy(i+1,j,k+1),2)+pow(Sz(i+1,j,k+1),2));
if (denom == 0.0) denom =1.0;
CubeValues(1,0,1) = -( Fx(i+1,j,k+1)*Sx(i+1,j,k+1)+Fy(i+1,j,k+1)*Sy(i+1,j,k+1)+Fz(i+1,j,k+1)*Sz(i+1,j,k+1) )
/( denom );
denom = sqrt(pow(Fx(i,j+1,k+1),2)+pow(Fy(i,j+1,k+1),2)+pow(Fz(i,j+1,k+1),2))
*sqrt(pow(Sx(i,j+1,k+1),2)+pow(Sy(i,j+1,k+1),2)+pow(Sz(i,j+1,k+1),2));
if (denom == 0.0) denom =1.0;
CubeValues(0,1,1) = -( Fx(i,j+1,k+1)*Sx(i,j+1,k+1)+Fy(i,j+1,k+1)*Sy(i,j+1,k+1)+Fz(i,j+1,k+1)*Sz(i,j+1,k+1) )
/( denom );
denom = sqrt(pow(Fx(i+1,j+1,k+1),2)+pow(Fy(i+1,j+1,k+1),2)+pow(Fz(i+1,j+1,k+1),2))
*sqrt(pow(Sx(i+1,j+1,k+1),2)+pow(Sy(i+1,j+1,k+1),2)+pow(Sz(i+1,j+1,k+1),2));
if (denom == 0.0) denom =1.0;
CubeValues(1,1,1) = -( Fx(i+1,j+1,k+1)*Sx(i+1,j+1,k+1)+Fy(i+1,j+1,k+1)*Sy(i+1,j+1,k+1)+Fz(i+1,j+1,k+1)*Sz(i+1,j+1,k+1) )
/( denom );
// trilinear coefficients: f(x,y,z) = a+bx+cy+dz+exy+fxz+gyz+hxyz
// Evaluate the coefficients
a = CubeValues(0,0,0);
b = CubeValues(1,0,0)-a;
c = CubeValues(0,1,0)-a;
d = CubeValues(0,0,1)-a;
e = CubeValues(1,1,0)-a-b-c;
f = CubeValues(1,0,1)-a-b-d;
g = CubeValues(0,1,1)-a-c-d;
h = CubeValues(1,1,1)-a-b-c-d-e-f-g;
for (p=0; p<npts; p++){
A = Points(p);
x = A.x-1.0*i;
y = A.y-1.0*j;
z = A.z-1.0*k;
CurveValues(p) = a + b*x + c*y+d*z + e*x*y + f*x*z + g*y*z + h*x*y*z;
// printf("grad F = %f \n", sqrt(pow(Fx(i,j,k),2)+pow(Fy(i,j,k),2)+pow(Fz(i,j,k),2)));
}
integral = 0.0;
for (p=0; p < npts-1; p++){
// Extract the line segment
A = Points(p);
B = Points(p+1);
vA = CurveValues(p);
vB = CurveValues(p+1);
// Compute the length of the segment
length = sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z));
integral += 0.5*length*(vA + vB);
}
return integral;
}
//--------------------------------------------------------------------------------------------------------
inline void pmmc_CubeSurfaceInterpVector(DoubleArray &Vec_x, DoubleArray &Vec_y, DoubleArray &Vec_z,
DoubleArray &CubeValues, DTMutableList<Point> &Points, IntArray &Triangles,
DoubleArray &SurfaceVector, DoubleArray &VecAvg, int i, int j, int k, int npts, int ntris)
{
Point A,B,C;
int p;
double vA,vB,vC;
double x,y,z;
double s,s1,s2,s3,temp;
double a,b,c,d,e,f,g,h;
// ................x component .............................
// Copy the curvature values for the cube
CubeValues(0,0,0) = Vec_x(i,j,k);
CubeValues(1,0,0) = Vec_x(i+1,j,k);
CubeValues(0,1,0) = Vec_x(i,j+1,k);
CubeValues(1,1,0) = Vec_x(i+1,j+1,k);
CubeValues(0,0,1) = Vec_x(i,j,k+1);
CubeValues(1,0,1) = Vec_x(i+1,j,k+1);
CubeValues(0,1,1) = Vec_x(i,j+1,k+1);
CubeValues(1,1,1) = Vec_x(i+1,j+1,k+1);
// trilinear coefficients: f(x,y,z) = a+bx+cy+dz+exy+fxz+gyz+hxyz
a = CubeValues(0,0,0);
b = CubeValues(1,0,0)-a;
c = CubeValues(0,1,0)-a;
d = CubeValues(0,0,1)-a;
e = CubeValues(1,1,0)-a-b-c;
f = CubeValues(1,0,1)-a-b-d;
g = CubeValues(0,1,1)-a-c-d;
h = CubeValues(1,1,1)-a-b-c-d-e-f-g;
for (p=0; p<npts; p++){
A = Points(p);
x = A.x-1.0*i;
y = A.y-1.0*j;
z = A.z-1.0*k;
SurfaceVector(p) = a + b*x + c*y+d*z + e*x*y + f*x*z + g*y*z + h*x*y*z;
}
// ................y component .............................
// Copy the curvature values for the cube
CubeValues(0,0,0) = Vec_y(i,j,k);
CubeValues(1,0,0) = Vec_y(i+1,j,k);
CubeValues(0,1,0) = Vec_y(i,j+1,k);
CubeValues(1,1,0) = Vec_y(i+1,j+1,k);
CubeValues(0,0,1) = Vec_y(i,j,k+1);
CubeValues(1,0,1) = Vec_y(i+1,j,k+1);
CubeValues(0,1,1) = Vec_y(i,j+1,k+1);
CubeValues(1,1,1) = Vec_y(i+1,j+1,k+1);
// trilinear coefficients: f(x,y,z) = a+bx+cy+dz+exy+fxz+gyz+hxyz
a = CubeValues(0,0,0);
b = CubeValues(1,0,0)-a;
c = CubeValues(0,1,0)-a;
d = CubeValues(0,0,1)-a;
e = CubeValues(1,1,0)-a-b-c;
f = CubeValues(1,0,1)-a-b-d;
g = CubeValues(0,1,1)-a-c-d;
h = CubeValues(1,1,1)-a-b-c-d-e-f-g;
for (p=0; p<npts; p++){
A = Points(p);
x = A.x-1.0*i;
y = A.y-1.0*j;
z = A.z-1.0*k;
SurfaceVector(npts+p) = a + b*x + c*y+d*z + e*x*y + f*x*z + g*y*z + h*x*y*z;
}
// ................z component .............................
// Copy the curvature values for the cube
CubeValues(0,0,0) = Vec_z(i,j,k);
CubeValues(1,0,0) = Vec_z(i+1,j,k);
CubeValues(0,1,0) = Vec_z(i,j+1,k);
CubeValues(1,1,0) = Vec_z(i+1,j+1,k);
CubeValues(0,0,1) = Vec_z(i,j,k+1);
CubeValues(1,0,1) = Vec_z(i+1,j,k+1);
CubeValues(0,1,1) = Vec_z(i,j+1,k+1);
CubeValues(1,1,1) = Vec_z(i+1,j+1,k+1);
// trilinear coefficients: f(x,y,z) = a+bx+cy+dz+exy+fxz+gyz+hxyz
a = CubeValues(0,0,0);
b = CubeValues(1,0,0)-a;
c = CubeValues(0,1,0)-a;
d = CubeValues(0,0,1)-a;
e = CubeValues(1,1,0)-a-b-c;
f = CubeValues(1,0,1)-a-b-d;
g = CubeValues(0,1,1)-a-c-d;
h = CubeValues(1,1,1)-a-b-c-d-e-f-g;
for (p=0; p<npts; p++){
A = Points(p);
x = A.x-1.0*i;
y = A.y-1.0*j;
z = A.z-1.0*k;
SurfaceVector(2*npts+p) = a + b*x + c*y + d*z + e*x*y + f*x*z + g*y*z + h*x*y*z;
}
//.............................................................................
for (int r=0; r<ntris; r++){
A = Points(Triangles(0,r));
B = Points(Triangles(1,r));
C = Points(Triangles(2,r));
// Compute length of sides (assume dx=dy=dz)
s1 = sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z));
s2 = sqrt((A.x-C.x)*(A.x-C.x)+(A.y-C.y)*(A.y-C.y)+(A.z-C.z)*(A.z-C.z));
s3 = sqrt((B.x-C.x)*(B.x-C.x)+(B.y-C.y)*(B.y-C.y)+(B.z-C.z)*(B.z-C.z));
s = 0.5*(s1+s2+s3);
temp = s*(s-s1)*(s-s2)*(s-s3);
if (temp > 0.0){
// Increment the averaged values
// x component
vA = SurfaceVector(Triangles(0,r));
vB = SurfaceVector(Triangles(1,r));
vC = SurfaceVector(Triangles(2,r));
VecAvg(0) += sqrt(temp)*0.33333333333333333*(vA+vB+vC);
// y component
vA = SurfaceVector(npts+Triangles(0,r));
vB = SurfaceVector(npts+Triangles(1,r));
vC = SurfaceVector(npts+Triangles(2,r));
VecAvg(1) += sqrt(temp)*0.33333333333333333*(vA+vB+vC);
// z component
vA = SurfaceVector(2*npts+Triangles(0,r));
vB = SurfaceVector(2*npts+Triangles(1,r));
vC = SurfaceVector(2*npts+Triangles(2,r));
VecAvg(2) += sqrt(temp)*0.33333333333333333*(vA+vB+vC);
}
}
}
//--------------------------------------------------------------------------------------------------------
inline double pmmc_CubeSurfaceOrientation(DoubleArray &Orientation, DTMutableList<Point> &Points, IntArray &Triangles, int ntris)
{
int r;
double temp,area,s,s1,s2,s3;
double nx,ny,nz,normsq;
Point A,B,C;
area = 0.0;
for (r=0;r<ntris;r++){
A = Points(Triangles(0,r));
B = Points(Triangles(1,r));
C = Points(Triangles(2,r));
// Compute the triangle normal vector
nx = (B.y-A.y)*(C.z-A.z) - (B.z-A.z)*(C.y-A.y);
ny = (B.z-A.z)*(C.x-A.x) - (B.x-A.x)*(C.z-A.z);
nz = (B.x-A.x)*(C.y-A.y) - (B.y-A.y)*(C.x-A.x);
normsq = 1.0/(nx*nx+ny*ny+nz*nz);
// Compute length of sides (assume dx=dy=dz)
s1 = sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z));
s2 = sqrt((A.x-C.x)*(A.x-C.x)+(A.y-C.y)*(A.y-C.y)+(A.z-C.z)*(A.z-C.z));
s3 = sqrt((B.x-C.x)*(B.x-C.x)+(B.y-C.y)*(B.y-C.y)+(B.z-C.z)*(B.z-C.z));
s = 0.5*(s1+s2+s3);
temp = s*(s-s1)*(s-s2)*(s-s3);
if (temp > 0.0){
temp = sqrt(temp);
area += temp;
Orientation(0) += temp*nx*nx*normsq; // Gxx
Orientation(1) += temp*ny*ny*normsq; // Gyy
Orientation(2) += temp*nz*nz*normsq; // Gzz
Orientation(3) += temp*nx*ny*normsq; // Gxy
Orientation(4) += temp*nx*nz*normsq; // Gxz
Orientation(5) += temp*ny*nz*normsq; // Gyz
}
}
return area;
}
//--------------------------------------------------------------------------------------------------------
inline double pmmc_CommonCurveSpeed(DoubleArray &CubeValues, DoubleArray &dPdt, DoubleArray &ReturnVector,
DoubleArray &Fx, DoubleArray &Fy, DoubleArray &Fz,
DoubleArray &Sx, DoubleArray &Sy, DoubleArray &Sz,
DTMutableList<Point> &Points, int i, int j, int k, int npts)
{
NULL_USE( CubeValues );
int p;
double s,lwns,norm;
double zeta;
double tangent_x,tangent_y,tangent_z;
double ns_x, ns_y, ns_z;
double nwn_x, nwn_y, nwn_z;
double nwns_x, nwns_y, nwns_z;
Point P,A,B;
lwns = 0.0;
double ReturnValue = 0;
NULL_USE(lwns);
TriLinPoly Px,Py,Pz,SDx,SDy,SDz,Pt;
Px.assign(Fx,i,j,k);
Py.assign(Fy,i,j,k);
Pz.assign(Fz,i,j,k);
SDx.assign(Sx,i,j,k);
SDy.assign(Sy,i,j,k);
SDz.assign(Sz,i,j,k);
Pt.assign(dPdt,i,j,k);
for (p=0; p < npts-1; p++){
// Extract the line segment
A = Points(p);
B = Points(p+1);
// Midpoint of the line
P.x = 0.5*(A.x+B.x);
P.y = 0.5*(A.y+B.y);
P.z = 0.5*(A.z+B.z);
// Compute the curve tangent
tangent_x = A.x - B.x;
tangent_y = A.y - B.y;
tangent_z = A.z - B.z;
// Get the normal to the solid surface
ns_x = SDx.eval(P);
ns_y = SDy.eval(P);
ns_z = SDz.eval(P);
norm = ns_x*ns_x + ns_y*ns_y + ns_z*ns_z;
if (norm > 0.0){
ns_x /= norm;
ns_y /= norm;
ns_z /= norm;
}
// Get the Color gradient
nwn_x = Px.eval(P);
nwn_y = Py.eval(P);
nwn_z = Pz.eval(P);
// to compute zeta, consider the change only in the plane of the solid surface
norm = nwn_x*ns_x + nwn_y*ns_y + nwn_z*ns_z; // component of color gradient aligned with solid
nwns_x = nwn_x - norm*ns_x;
nwns_y = nwn_y - norm*ns_y;
nwns_z = nwn_z - norm*ns_z;
// now {nwns_x, nwns_y, nwns_z} is the color gradient confined to the solid plane
norm = sqrt(nwns_x*nwns_x + nwns_y*nwns_y + nwns_z*nwns_z);
zeta = -Pt.eval(P) / norm;
// normalize the normal to the common curve within the solid surface
if (norm > 0.0){
nwns_x /= norm;
nwns_y /= norm;
nwns_z /= norm;
}
/*
// normal to the wn interface
norm = nwn_x*nwn_x + nwn_y*nwn_y + nwn_z*nwn_z;
// Compute the interface speed
if (norm > 0.0){
nwn_x /= norm;
nwn_y /= norm;
nwn_z /= norm;
}
// Compute the normal to the common curve (vector product of tangent and solid normal)
nwns_x = ns_y*tangent_z - ns_z*tangent_y;
nwns_y = ns_z*tangent_x - ns_x*tangent_z;
nwns_z = ns_x*tangent_y - ns_y*tangent_x;
// dot product of nwns and nwn should be positive
if (nwn_x*nwns_x+nwn_y*nwns_y+nwn_z*nwns_z < 0.0){
nwns_x = -nwns_x;
nwns_y = -nwns_y;
nwns_z = -nwns_z;
}
// normalize the common curve normal
norm = sqrt(nwns_x*nwns_x + nwns_y*nwns_y + nwns_z*nwns_z);
if (norm > 0.0){
nwns_x /= norm;
nwns_y /= norm;
nwns_z /= norm;
}
*/
// Compute the length of the segment
s = sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z));
// Add the length to the common line
// lwns += s;
// Compute the common curve velocity
if (norm > 0.0){
ReturnVector(0) += zeta*nwns_x*s;
ReturnVector(1) += zeta*nwns_y*s;
ReturnVector(2) += zeta*nwns_z*s;
ReturnValue += zeta*s;
}
}
NULL_USE(tangent_x);
NULL_USE(tangent_y);
NULL_USE(tangent_z);
return ReturnValue;
}
inline void pmmc_CurveOrientation(DoubleArray &Orientation, DTMutableList<Point> &Points, int npts, int i, int j, int k){
double twnsx,twnsy,twnsz,length; // tangent, norm
Point P,A,B;
for (int p=0; p<npts-1; p++){
// Extract the line segment
A = Points(p);
B = Points(p+1);
P.x = 0.5*(A.x+B.x) - 1.0*i;
P.y = 0.5*(A.y+B.y) - 1.0*j;
P.z = 0.5*(A.z+B.z) - 1.0*k;
A.x -= 1.0*i;
A.y -= 1.0*j;
A.z -= 1.0*k;
B.x -= 1.0*i;
B.y -= 1.0*j;
B.z -= 1.0*k;
length = sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z));// tangent vector
twnsx = (B.x - A.x)/length;
twnsy = (B.y - A.y)/length;
twnsz = (B.z - A.z)/length;
Orientation(0) += (1.0 - twnsx*twnsx)*length; // Gxx
Orientation(1) += (1.0 - twnsy*twnsy)*length; // Gyy
Orientation(2) += (1.0 - twnsz*twnsz)*length; // Gzz
Orientation(3) += (0.0 - twnsx*twnsy)*length; // Gxy
Orientation(4) += (0.0 - twnsx*twnsz)*length; // Gxz
Orientation(5) += (0.0 - twnsy*twnsz)*length; // Gyz
}
}
inline void pmmc_CurveCurvature(DoubleArray &f, DoubleArray &s,
DoubleArray &f_x, DoubleArray &f_y, DoubleArray &f_z,
DoubleArray &s_x, DoubleArray &s_y, DoubleArray &s_z,
DoubleArray &KN, DoubleArray &KG,
double &KNavg, double &KGavg, DTMutableList<Point> &Points, int npts, int ic, int jc, int kc)
{
NULL_USE( f );
NULL_USE( s );
NULL_USE( KN );
NULL_USE( KG );
int p,i,j,k;
double length;
double fxx,fyy,fzz,fxy,fxz,fyz,fx,fy,fz;
double sxx,syy,szz,sxy,sxz,syz,sx,sy,sz;
// double Axx,Axy,Axz,Ayx,Ayy,Ayz,Azx,Azy,Azz;
// double Tx[8],Ty[8],Tz[8]; // Tangent vector
// double Nx[8],Ny[8],Nz[8]; // Principle normal
double twnsx,twnsy,twnsz,nwnsx,nwnsy,nwnsz,K; // tangent,normal and curvature
double nsx,nsy,nsz,norm;
double nwsx,nwsy,nwsz;
Point P,A,B;
// Local trilinear approximation for tangent and normal vector
TriLinPoly Tx,Ty,Tz,Nx,Ny,Nz,Sx,Sy,Sz;
// Loop over the cube and compute the derivatives
for (k=kc; k<kc+2; k++){
for (j=jc; j<jc+2; j++){
for (i=ic; i<ic+2; i++){
// Compute all of the derivatives using finite differences
// fluid phase indicator field
// fx = 0.5*(f(i+1,j,k) - f(i-1,j,k));
// fy = 0.5*(f(i,j+1,k) - f(i,j-1,k));
// fz = 0.5*(f(i,j,k+1) - f(i,j,k-1));
/*fxx = f(i+1,j,k) - 2.0*f(i,j,k) + f(i-1,j,k);
fyy = f(i,j+1,k) - 2.0*f(i,j,k) + f(i,j-1,k);
fzz = f(i,j,k+1) - 2.0*f(i,j,k) + f(i,j,k-1);
fxy = 0.25*(f(i+1,j+1,k) - f(i+1,j-1,k) - f(i-1,j+1,k) + f(i-1,j-1,k));
fxz = 0.25*(f(i+1,j,k+1) - f(i+1,j,k-1) - f(i-1,j,k+1) + f(i-1,j,k-1));
fyz = 0.25*(f(i,j+1,k+1) - f(i,j+1,k-1) - f(i,j-1,k+1) + f(i,j-1,k-1));
*/
// solid distance function
// sx = 0.5*(s(i+1,j,k) - s(i-1,j,k));
// sy = 0.5*(s(i,j+1,k) - s(i,j-1,k));
// sz = 0.5*(s(i,j,k+1) - s(i,j,k-1));
/* sxx = s(i+1,j,k) - 2.0*s(i,j,k) + s(i-1,j,k);
syy = s(i,j+1,k) - 2.0*s(i,j,k) + s(i,j-1,k);
szz = s(i,j,k+1) - 2.0*s(i,j,k) + s(i,j,k-1);
sxy = 0.25*(s(i+1,j+1,k) - s(i+1,j-1,k) - s(i-1,j+1,k) + s(i-1,j-1,k));
sxz = 0.25*(s(i+1,j,k+1) - s(i+1,j,k-1) - s(i-1,j,k+1) + s(i-1,j,k-1));
syz = 0.25*(s(i,j+1,k+1) - s(i,j+1,k-1) - s(i,j-1,k+1) + s(i,j-1,k-1));
*/
/* // Compute the Jacobean matrix for tangent vector
Axx = sxy*fz + sy*fxz - sxz*fy - sz*fxy;
Axy = sxz*fx + sz*fxx - sxx*fz - sx*fxz;
Axz = sxx*fy + sx*fxy - sxy*fx - sy*fxx;
Ayx = syy*fz + sy*fyz - syz*fy - sz*fyy;
Ayy = syz*fx + sz*fxy - sxy*fz - sx*fyz;
Ayz = sxy*fy + sx*fyy - syy*fx - sy*fxy;
Azx = syz*fz + sy*fzz - szz*fy - sz*fyz;
Azy = szz*fx + sz*fxz - sxz*fz - sx*fzz;
Azz = sxz*fy + sx*fyz - syz*fx - sy*fxz;
*/
sx = s_x(i,j,k);
sy = s_y(i,j,k);
sz = s_z(i,j,k);
fx = f_x(i,j,k);
fy = f_y(i,j,k);
fz = f_z(i,j,k);
// Normal to solid surface
Sx.Corners(i-ic,j-jc,k-kc) = sx;
Sy.Corners(i-ic,j-jc,k-kc) = sy;
Sz.Corners(i-ic,j-jc,k-kc) = sz;
// Compute the tangent vector
norm = sqrt((sy*fz-sz*fy)*(sy*fz-sz*fy)+(sz*fx-sx*fz)*(sz*fx-sx*fz)+(sx*fy-sy*fx)*(sx*fy-sy*fx));
if (norm == 0.0) norm=1.0;
Tx.Corners(i-ic,j-jc,k-kc) = (sy*fz-sz*fy)/norm;
Ty.Corners(i-ic,j-jc,k-kc) = (sz*fx-sx*fz)/norm;
Tz.Corners(i-ic,j-jc,k-kc) = (sx*fy-sy*fx)/norm;
}
}
}
// Assign the tri-linear polynomial coefficients
Sx.assign();
Sy.assign();
Sz.assign();
Tx.assign();
Ty.assign();
Tz.assign();
Nx.assign();
Ny.assign();
Nz.assign();
double tax,tay,taz,tbx,tby,tbz;
for (p=0; p<npts-1; p++){
// Extract the line segment
A = Points(p);
B = Points(p+1);
P.x = 0.5*(A.x+B.x) - 1.0*i;
P.y = 0.5*(A.y+B.y) - 1.0*j;
P.z = 0.5*(A.z+B.z) - 1.0*k;
A.x -= 1.0*i;
A.y -= 1.0*j;
A.z -= 1.0*k;
B.x -= 1.0*i;
B.y -= 1.0*j;
B.z -= 1.0*k;
length = sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z));
// tangent vector
twnsx = B.x - A.x;
twnsy = B.y - A.y;
twnsz = B.z - A.z;
norm = sqrt(twnsx*twnsx+twnsy*twnsy+twnsz*twnsz);
if (norm == 0.0) norm = 1.0;
twnsx /= norm;
twnsy /= norm;
twnsz /= norm;
// *****************************************************
// Compute tangent vector at A and B and normalize
tax = Tx.eval(A);
tay = Ty.eval(A);
taz = Tz.eval(A);
norm = sqrt(tax*tax+tay*tay+taz*taz);
if (norm==0.0) norm=1.0;
tax /= norm;
tay /= norm;
taz /= norm;
tbx = Tx.eval(B);
tby = Ty.eval(B);
tbz = Tz.eval(B);
norm = sqrt(tbx*tbx+tby*tby+tbz*tbz);
if (norm==0.0) norm=1.0;
tbx /= norm;
tby /= norm;
tbz /= norm;
// *****************************************************
// *****************************************************
// Compute the divergence of the tangent vector
nwnsx = (tax - tbx) / length;
nwnsy = (tay - tby) / length;
nwnsz = (taz - tbz) / length;
K = sqrt(nwnsx*nwnsx+nwnsy*nwnsy+nwnsz*nwnsz);
if (K == 0.0) K=1.0;
nwnsx /= K;
nwnsy /= K;
nwnsz /= K;
// *****************************************************
// Normal vector to the solid surface
nsx = Sx.eval(P);
nsy = Sy.eval(P);
nsz = Sz.eval(P);
norm = sqrt(nsx*nsx+nsy*nsy+nsz*nsz);
if (norm == 0.0) norm=1.0;
nsx /= norm;
nsy /= norm;
nsz /= norm;
// normal in the surface tangent plane (rel. geodesic curvature)
nwsx = twnsy*nsz-twnsz*nsy;
nwsy = twnsz*nsx-twnsx*nsz;
nwsz = twnsx*nsy-twnsy*nsx;
norm = sqrt(nwsx*nwsx+nwsy*nwsy+nwsz*nwsz);
if (norm == 0.0) norm=1.0;
nwsx /= norm;
nwsy /= norm;
nwsz /= norm;
if (nsx*nwnsx + nsy*nwnsy + nsz*nwnsz < 0.0){
nwnsx = -nwnsx;
nwnsy = -nwnsy;
nwnsz = -nwnsz;
}
if (length > 0.0){
// normal curvature component in the direction of the solid surface
KNavg += K*(nsx*nwnsx + nsy*nwnsy + nsz*nwnsz)*length;
//geodesic curvature
KGavg += K*(nwsx*nwnsx + nwsy*nwnsy + nwsz*nwnsz)*length;
}
}
NULL_USE(fxx); NULL_USE(fyy); NULL_USE(fzz);
NULL_USE(fxy); NULL_USE(fxz); NULL_USE(fyz);
NULL_USE(fx); NULL_USE(fy); NULL_USE(fz);
NULL_USE(sxx); NULL_USE(syy); NULL_USE(szz);
NULL_USE(sxy); NULL_USE(sxz); NULL_USE(syz);
NULL_USE(sx); NULL_USE(sy); NULL_USE(sz);
}
//--------------------------------------------------------------------------------------------------------
inline double pmmc_InterfaceSpeed(DoubleArray &dPdt, DoubleArray &P_x, DoubleArray &P_y, DoubleArray &P_z,
DoubleArray &CubeValues, DTMutableList<Point> &Points, IntArray &Triangles,
DoubleArray &SurfaceVector, DoubleArray &AvgSpeed, DoubleArray &AvgVel,
int i, int j, int k, int npts, int ntris)
{
NULL_USE( CubeValues );
NULL_USE( SurfaceVector );
NULL_USE( npts );
Point A,B,C,P;
double x,y,z;
double s,s1,s2,s3,area;
double norm, zeta;
double ReturnValue=0.0;
TriLinPoly Px,Py,Pz,Pt;
Px.assign(P_x,i,j,k);
Py.assign(P_y,i,j,k);
Pz.assign(P_z,i,j,k);
Pt.assign(dPdt,i,j,k);
//.............................................................................
// Compute the average speed of the interface
for (int r=0; r<ntris; r++){
A = Points(Triangles(0,r));
B = Points(Triangles(1,r));
C = Points(Triangles(2,r));
// Compute length of sides (assume dx=dy=dz)
s1 = sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z));
s2 = sqrt((A.x-C.x)*(A.x-C.x)+(A.y-C.y)*(A.y-C.y)+(A.z-C.z)*(A.z-C.z));
s3 = sqrt((B.x-C.x)*(B.x-C.x)+(B.y-C.y)*(B.y-C.y)+(B.z-C.z)*(B.z-C.z));
s = 0.5*(s1+s2+s3);
area = sqrt(s*(s-s1)*(s-s2)*(s-s3));
// Compute the centroid P
P.x = 0.33333333333333333*(A.x+B.x+C.x);
P.y = 0.33333333333333333*(A.y+B.y+C.y);
P.z = 0.33333333333333333*(A.z+B.z+C.z);
if (area > 0.0){
x = Px.eval(P);
y = Py.eval(P);
z = Pz.eval(P);
norm = sqrt(x*x+y*y+z*z);
if (norm==0.0) norm=1.0;
// Compute the interface speed from time derivative and gradient (Level Set Equation)
zeta = -Pt.eval(P) / norm;
// Normalize the normal vector
x /= norm;
y /= norm;
z /= norm;
// Compute the average
AvgVel(0) += area*zeta*x;
AvgVel(1) += area*zeta*y;
AvgVel(2) += area*zeta*z;
AvgSpeed(r) = zeta*area;
ReturnValue += zeta*area;
}
}
return ReturnValue;
//.............................................................................
}
//--------------------------------------------------------------------------------------------------------
inline double geomavg_EulerCharacteristic(DTMutableList<Point> &Points, IntArray &Triangles,
int &npts, int &ntris, int &i, int &j, int &k)
{
NULL_USE( Points );
NULL_USE( Triangles );
NULL_USE( npts );
NULL_USE( ntris );
NULL_USE( i );
NULL_USE( j );
NULL_USE( k );
/* REFERENCE
* Huang, Liu, Lee, Yang, Tsang
* On concise 3-D simple point comparisons: a marching cubes paradigm
* IEEE Transactions on Medical Imaging, Vol. 28, No. 1
* January 2009
*/
// Compute the Euler characteristic for triangles in a cube
/*
bool graph[3][3];
double CountSideExternal=0;
double ShareSideInternal=0;
// Exclude edges and vertices shared with between multiple cubes
for (int p=0; p<ntris; p++){
Point A = Points(Triangles(0,p));
Point B = Points(Triangles(1,p));
Point C = Points(Triangles(2,p));
// Check to see if triangle sides are on the cube edge
if ( fabs(floor(A.x) - A.x) < 1e-14 && fabs(floor(B.x) - B.x) < 1e-14 ) CountSideExternal+=1.0;
if ( fabs(floor(A.x) - A.x) < 1e-14 && fabs(floor(C.x) - C.x) < 1e-14 ) CountSideExternal+=1.0;
if ( fabs(floor(B.x) - B.x) < 1e-14 && fabs(floor(C.x) - C.x) < 1e-14 ) CountSideExternal+=1.0;
// See if any edges were already counted
for (int r=0; r<p; r++){
Point D = Points(Triangles(0,r));
Point E = Points(Triangles(1,r));
Point F = Points(Triangles(2,r));
// Initialize the graph
for (int jj=0; jj<3; jj++){
for (int ii=0; ii<3; ii++){
graph[ii][jj] = false;
}
}
// Check to see if the triangles share vertices
if (Triangles(0,r) == Triangles(0,p)) graph[0][0]=true;
if (Triangles(0,r) == Triangles(1,p)) graph[0][1]=true;
if (Triangles(0,r) == Triangles(2,p)) graph[0][2]=true;
if (Triangles(1,r) == Triangles(0,p)) graph[1][0]=true;
if (Triangles(1,r) == Triangles(1,p)) graph[1][1]=true;
if (Triangles(1,r) == Triangles(2,p)) graph[1][2]=true;
if (Triangles(2,r) == Triangles(0,p)) graph[2][0]=true;
if (Triangles(2,r) == Triangles(1,p)) graph[2][1]=true;
if (Triangles(2,r) == Triangles(2,p)) graph[2][2]=true;
// Count the number of vertices that are shared
int count=0;
for (int jj=0; jj<3; jj++){
for (int ii=0; ii<3; ii++){
if (graph[ii][jj] == true) count++;
}
}
// 0,1,2 are valid possible numbers for shared vertices
// if 3 are obtained, then it is the same triangle :(
if (count == 2) ShareSideInternal += 1.0;
}
}
*/
double EulerChar,nvert,nface;
// Number of faces is number of triangles
nface = double(ntris);
// Each vertex is shared by four cubes
nvert = double(npts);
// Subtract shared sides to avoid double counting
// nside = 2.0*double(npts)- 3.0 - 0.5*double(npts);
double nside_extern = double(npts);
double nside_intern = double(npts)-3.0;
EulerChar=0.0;
if (npts > 0) EulerChar = (0.25*nvert - nside_intern - 0.5*nside_extern + nface);
return EulerChar;
}
inline double mink_phase_epc6(IntArray &PhaseID, DoubleArray &CubeValues, int PhaseLabel,
int &i, int &j, int &k){
/*
* Compute the Euler Poincare characteristic for a phase based on 6 adjacency
* compute the local contribution within the specified cube must sum to get total
* PhaseID -- label of phases on a mesh
* PhaseLabel -- label assigned to phase that we are computing
* i,j,k -- identifies the local cube
*/
double epc_ncubes, epc_nface, epc_nedge, epc_nvert;
epc_ncubes=epc_nface=epc_nedge=epc_nvert = 0;
// Assign CubeValues to be phase indicator for
for (int kk=0; kk<2; kk++){
for (int jj=0; jj<2; jj++){
for (int ii=0; ii<2; ii++){
if ( PhaseID(i+ii,j+jj,k+kk) == PhaseLabel) CubeValues(ii,jj,kk)=1;
else CubeValues(ii,jj,kk)=0;
}
}
}
// update faces edges and cubes for NWP
epc_ncubes += CubeValues(0,0,0)*CubeValues(1,0,0)*CubeValues(0,1,0)*CubeValues(0,0,1)*
CubeValues(1,1,0)*CubeValues(1,0,1)*CubeValues(0,1,1)*CubeValues(1,1,1);
// three faces (others shared by other cubes)
epc_nface += CubeValues(1,0,0)*CubeValues(1,1,0)*CubeValues(1,0,1)*CubeValues(1,1,1);
epc_nface += CubeValues(0,1,0)*CubeValues(1,1,0)*CubeValues(0,1,1)*CubeValues(1,1,1);
epc_nface += CubeValues(0,0,1)*CubeValues(0,1,1)*CubeValues(1,0,1)*CubeValues(1,1,1);
// six of twelve edges (others shared by other cubes)
epc_nedge += CubeValues(1,1,1)*CubeValues(1,1,0);
epc_nedge += CubeValues(1,1,1)*CubeValues(1,0,1);
epc_nedge += CubeValues(1,1,1)*CubeValues(0,1,1);
epc_nedge += CubeValues(1,0,1)*CubeValues(1,0,0);
epc_nedge += CubeValues(1,0,1)*CubeValues(0,0,1);
epc_nedge += CubeValues(0,1,1)*CubeValues(0,0,1);
// four of eight vertices
epc_nvert += CubeValues(1,1,0);
epc_nvert += CubeValues(1,0,1);
epc_nvert += CubeValues(0,1,1);
epc_nvert += CubeValues(1,1,1);
double chi= epc_nvert - epc_nedge + epc_nface - epc_ncubes;
return chi;
}
inline double mink_EulerCharacteristic(DTMutableList<Point> &Points, IntArray &Triangles,
DoubleArray &CubeValues, int &npts, int &ntris, int &i, int &j, int &k)
{
NULL_USE( CubeValues );
// Compute the Euler characteristic for triangles in a cube
// Exclude edges and vertices shared with between multiple cubes
double EulerChar;
int nvert=npts;
int nside=2*nvert-3;
int nface=nvert-2;
//if (ntris != nface){
// nface = ntris;
// nside =
//}
//...........................................................
// Check that this point is not on a previously computed face
// Note direction that the marching cubes algorithm marches
// In parallel, other sub-domains fill in the lower boundary
for (int p=0; p<npts; p++){
Point PT = Points(p);
if (PT.x - double(i) < 1e-12) nvert-=1;
else if (PT.y - double(j) < 1e-12) nvert-=1;
else if (PT.z - double(k) < 1e-12) nvert-=1;
}
// Remove redundantly computed edges (shared by two cubes across a cube face)
for (int p=0; p<ntris; p++){
Point A = Points(Triangles(0,p));
Point B = Points(Triangles(1,p));
Point C = Points(Triangles(2,p));
// Check side A-B
bool newside = true;
if (A.x - double(i) < 1e-12 && B.x - double(i) < 1e-12) newside=false;
if (A.y - double(j) < 1e-12 && B.y - double(j) < 1e-12) newside=false;
if (A.z - double(k) < 1e-12 && B.z - double(k) < 1e-12) newside=false;
if (!newside) nside-=1;
// Check side A-C
newside = true;
if (A.x - double(i)< 1e-12 && C.x - double(i) < 1e-12) newside=false;
if (A.y - double(j)< 1e-12 && C.y - double(j) < 1e-12) newside=false;
if (A.z - double(k)< 1e-12 && C.z - double(k) < 1e-12) newside=false;
if (!newside) nside-=1;
// Check side B-C
newside = true;
if (B.x - double(i) < 1e-12 && C.x - double(i) < 1e-12) newside=false;
if (B.y - double(j) < 1e-12 && C.y - double(j) < 1e-12) newside=false;
if (B.z - double(k) < 1e-12 && C.z - double(k) < 1e-12) newside=false;
if (!newside) nside-=1;
}
EulerChar = 1.0*(nvert - nside + nface);
return EulerChar;
}
#endif