LBPM/analysis/pmmc.h
2023-10-23 04:18:20 -04:00

4914 lines
181 KiB
C++

/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#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 nwx, nwy, nwz;
double nwsx, nwsy, nwsz;
double nwnx, nwny, nwnz;
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++) {
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 fluid surface
Nx.Corners(i - ic, j - jc, k - kc) = fx;
Ny.Corners(i - ic, j - jc, k - kc) = fy;
Nz.Corners(i - ic, j - jc, k - kc) = fz;
// 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 vector to the fluid surface
nwx = Nx.eval(P);
nwy = Ny.eval(P);
nwz = Nz.eval(P);
norm = sqrt(nwx * nwx + nwy * nwy + nwz * nwz);
if (norm == 0.0)
norm = 1.0;
nwx /= norm;
nwy /= norm;
nwz /= norm;
// common curve normal in the solid 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;
/* normal to ws interface boundary should point into fluid (same direction as gradient) */
if (nwx * nwsx + nwy * nwsy + nwz * nwsz < 0.0) {
nwsx = -nwsx;
nwsy = -nwsy;
nwsz = -nwsz;
}
// common curve normal in the fluid surface tangent plane (rel. geodesic curvature)
nwnx = twnsy * nwz - twnsz * nwy;
nwny = twnsz * nwx - twnsx * nwz;
nwnz = twnsx * nwy - twnsy * nwx;
norm = sqrt(nwnx * nwnx + nwny * nwny + nwnz * nwnz);
if (norm == 0.0)
norm = 1.0;
nwnx /= norm;
nwny /= norm;
nwnz /= norm;
/* normal to wn interface boundary should point into the solid */
if (nsx * nwnx + nsy * nwny + nsz * nwnz > 0.0) {
nwnx = -nwnx;
nwny = -nwny;
nwnz = -nwnz;
}
if (length > 0.0) {
// normal curvature component in the direction of the solid surface
//KNavg += K * (nsx * nwnsx + nsy * nwnsy + nsz * nwnsz) * length;
KNavg += K * (nwnx * nwnsx + nwny * nwnsy + nwnz * 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