/***************************************************************************** * Copyright (c) 2019 FrontISTR Commons * This software is released under the MIT License, see LICENSE.txt *****************************************************************************/ #include "hecmw_vis_tetra_intersect.h" #include #include "hecmw_vis_mem_util.h" #include "hecmw_vis_case_table.h" #include "hecmw_malloc.h" int get_tetra_data(Surface *sff, struct hecmwST_local_mesh *mesh, struct hecmwST_result_data *data, int elemID, Tetra *tetra, int tn_component) { int i, j; int nodeID; int c_base, s_base; double tmp; c_base = 0; if (sff->display_way != 4) { for (i = 0; i < sff->color_comp; i++) { c_base += data->nn_dof[i]; } } if (sff->surface_style == 2) { s_base = 0; for (i = 0; i < sff->data_comp; i++) s_base += data->nn_dof[i]; } /* set field data of voxel in cube */ for (i = 0; i < 4; i++) { nodeID = mesh->elem_node_item[mesh->elem_node_index[elemID] + i]; tetra->local_vid[i] = nodeID - 1; if (sff->display_way != 4) { if ((data->nn_dof[sff->color_comp] > 1) && (sff->color_subcomp == 0)) { tetra->c_data[i] = 0.0; for (j = 0; j < data->nn_dof[sff->color_comp]; j++) { tmp = data->node_val_item[(nodeID - 1) * tn_component + c_base + j]; tetra->c_data[i] += tmp * tmp; } tetra->c_data[i] = sqrt(tetra->c_data[i]); } else if ((data->nn_dof[sff->color_comp] > 1) && (sff->color_subcomp != 0)) tetra->c_data[i] = data->node_val_item[(nodeID - 1) * tn_component + c_base + (sff->color_subcomp - 1)]; else if (data->nn_dof[sff->color_comp] == 1) tetra->c_data[i] = data->node_val_item[(nodeID - 1) * tn_component + c_base]; } else if (sff->display_way == 4) tetra->c_data[i] = sff->specified_color; tetra->axis[i * 3] = mesh->node[(nodeID - 1) * 3]; tetra->axis[i * 3 + 1] = mesh->node[(nodeID - 1) * 3 + 1]; tetra->axis[i * 3 + 2] = mesh->node[(nodeID - 1) * 3 + 2]; if (sff->surface_style == 2) { if ((data->nn_dof[sff->data_comp] > 1) && (sff->data_subcomp == 0)) { tetra->s_data[i] = 0.0; for (j = 0; j < data->nn_dof[sff->data_comp]; j++) { tmp = data->node_val_item[(nodeID - 1) * tn_component + s_base + j]; tetra->s_data[i] += tmp * tmp; } tetra->s_data[i] = sqrt(tetra->s_data[i]); } else if ((data->nn_dof[sff->data_comp] > 1) && (sff->data_subcomp != 0)) tetra->s_data[i] = data->node_val_item[(nodeID - 1) * tn_component + s_base + (sff->data_subcomp - 1)]; else if (data->nn_dof[sff->data_comp] == 1) tetra->s_data[i] = data->node_val_item[(nodeID - 1) * tn_component + s_base]; } else if (sff->surface_style == 3) tetra->s_data[i] = get_value_equ(sff->cont_equ, sff->cross_type, tetra->axis[i * 3], tetra->axis[i * 3 + 1], tetra->axis[i * 3 + 2]); } tetra->elem_id[0] = mesh->elem_ID[elemID * 2]; tetra->elem_id[1] = mesh->elem_ID[elemID * 2 + 1]; return 1; } static double intersect_line(int v0, int v1, double isovalue, Tetra *tetra, double point[3]) { int j; double rate, color; if (fabs(tetra->s_data[v1] - tetra->s_data[v0]) < EPSILON) HECMW_vis_print_exit("There is something wrong in data precison"); else { rate = (isovalue - tetra->s_data[v0]) / (tetra->s_data[v1] - tetra->s_data[v0]); for (j = 0; j < 3; j++) point[j] = rate * (tetra->axis[v1 * 3 + j] - tetra->axis[v0 * 3 + j]) + tetra->axis[v0 * 3 + j]; color = rate * (tetra->c_data[v1] - tetra->c_data[v0]) + tetra->c_data[v0]; } return (color); } void find_intersection_tetra(Tetra *tetra, double isovalue, Tetra_point *tetra_point, Head_patch_tetra *head_patch_tetra, Hash_vertex *vertex_hash_table) { int i, j, k; int num_gt_0, v0_id; int tmp_int; double point[3], color; Hash_vertex *h1, *h2; Tetra_point *p1, *p2; Patch_tetra *t1, *t2; int flag_existing, index_patch, patch[4]; int v1, v2, v[4], count_minus, count_plus; double fp[4][3], n_f[3], n_norm, f_cen_point[3], sign_f, n_c, c_c[3]; num_gt_0 = 0; for (i = 0; i < 4; i++) { if (tetra->s_data[i] > isovalue) num_gt_0++; } if ((num_gt_0 != 0) && (num_gt_0 != 4)) { /* There are patches inside the tetra */ if ((num_gt_0 == 1) || (num_gt_0 == 3)) { /* There is one patch inside the tetra */ t1 = (Patch_tetra *)HECMW_malloc(sizeof(Patch_tetra)); if (t1 == NULL) HECMW_vis_memory_exit("t1"); t2 = head_patch_tetra->patch_link; head_patch_tetra->num_patch++; head_patch_tetra->patch_link = t1; t1->next_patch = t2; if (num_gt_0 == 1) { v0_id = -1; for (i = 0; i < 4; i++) { if (tetra->s_data[i] > isovalue) v0_id = i; } } else if (num_gt_0 == 3) { v0_id = -1; for (i = 0; i < 4; i++) { if (tetra->s_data[i] <= isovalue) v0_id = i; } } /* find intersection */ index_patch = -1; for (i = 0; i < 4; i++) { if (i != v0_id) { color = intersect_line(v0_id, i, isovalue, tetra, point); tmp_int = tetra->local_vid[v0_id] + tetra->local_vid[i]; /* if(vertex_hash_table[tmp_int].ident==0) { vertex_hash_table[tmp_int].ident++; h1=(Hash_vertex *)HECMW_malloc(sizeof(Hash_vertex)); if(h1==NULL) HECMW_vis_memory_exit("h1"); vertex_hash_table[tmp_int].next_vertex=h1; h1->next_vertex=NULL; h1->ident=tetra_point->ident; for(j=0;j<3;j++) h1->geom[j]=point[j]; p1=(Tetra_point *)HECMW_malloc(sizeof(Tetra_point)); if(p1==NULL) HECMW_vis_memory_exit("p1"); tetra_point->ident++; p2=tetra_point->nextpoint; tetra_point->nextpoint=p1; p1->cdata=color; p1->ident=tetra_point->ident-1; for(j=0;j<3;j++) p1->geom[j]=point[j]; p1->nextpoint=p2; index_patch++; t1->patch[index_patch]=p1->ident; } else if(vertex_hash_table[tmp_int].ident>0) { */ flag_existing = 0; h1 = vertex_hash_table[tmp_int].next_vertex; for (j = 0; j < vertex_hash_table[tmp_int].ident; j++) { if ((fabs(h1->geom[0] - point[0]) < EPSILON) && (fabs(h1->geom[1] - point[1]) < EPSILON) && (fabs(h1->geom[2] - point[2]) < EPSILON)) { flag_existing = 1; index_patch++; patch[index_patch] = h1->ident; for (k = 0; k < 3; k++) fp[index_patch][k] = point[k]; break; } h1 = h1->next_vertex; } if (flag_existing == 0) { /*adding new vertex */ vertex_hash_table[tmp_int].ident++; h1 = (Hash_vertex *)HECMW_malloc(sizeof(Hash_vertex)); if (h1 == NULL) HECMW_vis_memory_exit("h1"); h2 = vertex_hash_table[tmp_int].next_vertex; vertex_hash_table[tmp_int].next_vertex = h1; h1->next_vertex = h2; h1->ident = tetra_point->ident; for (j = 0; j < 3; j++) h1->geom[j] = point[j]; p1 = (Tetra_point *)HECMW_malloc(sizeof(Tetra_point)); if (p1 == NULL) HECMW_vis_memory_exit("p1"); tetra_point->ident++; p2 = tetra_point->nextpoint; tetra_point->nextpoint = p1; p1->cdata = color; p1->ident = tetra_point->ident - 1; for (j = 0; j < 3; j++) p1->geom[j] = point[j]; p1->nextpoint = p2; index_patch++; patch[index_patch] = p1->ident; for (k = 0; k < 3; k++) fp[index_patch][k] = point[k]; } /* } */ } } /* end for 0, 4 */ /* judge whether the rotation direction pointed out to isosurface */ n_f[0] = (fp[1][1] - fp[0][1]) * (fp[2][2] - fp[0][2]) - (fp[2][1] - fp[0][1]) * (fp[1][2] - fp[0][2]); n_f[1] = -(fp[1][0] - fp[0][0]) * (fp[2][2] - fp[0][2]) + (fp[2][0] - fp[0][0]) * (fp[1][2] - fp[0][2]); n_f[2] = (fp[1][0] - fp[0][0]) * (fp[2][1] - fp[0][1]) - (fp[2][0] - fp[0][0]) * (fp[1][1] - fp[0][1]); for (j = 0; j < 3; j++) fp[3][j] = tetra->axis[v0_id * 3 + j]; n_norm = sqrt(n_f[0] * n_f[0] + n_f[1] * n_f[1] + n_f[2] * n_f[2]); if (fabs(n_norm) > EPSILON) { for (j = 0; j < 3; j++) n_f[j] /= n_norm; } /*selce the direction point to inside the element */ for (j = 0; j < 3; j++) f_cen_point[j] = (fp[0][j] + fp[1][j] + fp[2][j]) / 3.0; for (j = 0; j < 3; j++) c_c[j] = fp[3][j] - f_cen_point[j]; n_c = sqrt(c_c[0] * c_c[0] + c_c[1] * c_c[1] + c_c[2] * c_c[2]); if (fabs(n_c) > EPSILON) { for (j = 0; j < 3; j++) c_c[j] /= n_c; } sign_f = n_f[0] * c_c[0] + n_f[1] * c_c[1] + n_f[2] * c_c[2]; if (((tetra->s_data[v0_id] > isovalue) && (sign_f < -EPSILON)) || ((tetra->s_data[v0_id] <= isovalue) && (sign_f > EPSILON))) { tmp_int = patch[1]; patch[1] = patch[2]; patch[2] = tmp_int; } for (j = 0; j < 3; j++) t1->patch[j] = patch[j]; } /* end if (num_gt_0==1 or 3) */ else if (num_gt_0 == 2) { /* Two patches inside the tetra */ index_patch = -1; count_minus = 0; count_plus = 0; for (i = 0; i < 4; i++) { if (tetra->s_data[i] <= isovalue) { v[count_minus] = i; count_minus++; } else { v[2 + count_plus] = i; count_plus++; } } #ifdef old /* judge the tetrahedra whether in the right rotation side */ for (i = 0; i < 4; i++) for (j = 0; j < 3; j++) fp[i][j] = tetra->axis[v[i] * 3 + j]; n_f[0] = (fp[2][1] - fp[1][1]) * (fp[1][2] - fp[0][2]) - (fp[1][1] - fp[0][1]) * (fp[2][2] - fp[1][2]); n_f[1] = -(fp[2][0] - fp[1][0]) * (fp[1][2] - fp[0][2]) + (fp[1][0] - fp[0][0]) * (fp[2][2] - fp[1][2]); n_f[2] = (fp[2][0] - fp[1][0]) * (fp[1][1] - fp[0][1]) - (fp[1][0] - fp[0][0]) * (fp[2][1] - fp[1][1]); n_norm = sqrt(n_f[0] * n_f[0] + n_f[1] * n_f[1] + n_f[2] * n_f[2]); if (fabs(n_norm) > EPSILON) { for (j = 0; j < 3; j++) n_f[j] /= n_norm; } /*selce the direction point to inside the element */ for (j = 0; j < 3; j++) f_cen_point[j] = (fp[0][j] + fp[1][j] + fp[2][j]) / 3.0; for (j = 0; j < 3; j++) c_c[j] = fp[3][j] - f_cen_point[j]; n_c = sqrt(c_c[0] * c_c[0] + c_c[1] * c_c[1] + c_c[2] * c_c[2]); if (fabs(n_c) > EPSILON) { for (j = 0; j < 3; j++) c_c[j] /= n_c; } sign_f = n_f[0] * c_c[0] + n_f[1] * c_c[1] + n_f[2] * c_c[2]; if (sign_f < -EPSILON) { tmp_int = v[2]; v[2] = v[3]; v[3] = tmp_int; } #endif for (i = 0; i < 4; i++) { if (i == 0) { v1 = v[0]; v2 = v[2]; } else if (i == 1) { v1 = v[1]; v2 = v[2]; } else if (i == 2) { v1 = v[1]; v2 = v[3]; } else if (i == 3) { v1 = v[0]; v2 = v[3]; } color = intersect_line(v1, v2, isovalue, tetra, point); tmp_int = tetra->local_vid[v1] + tetra->local_vid[v2]; /* if(vertex_hash_table[tmp_int].ident==0) { vertex_hash_table[tmp_int].ident++; h1=(Hash_vertex *)HECMW_malloc(sizeof(Hash_vertex)); if(h1==NULL) HECMW_vis_memory_exit("h1"); vertex_hash_table[tmp_int].next_vertex=h1; h1->next_vertex=NULL; h1->ident=tetra_point->ident; for(j=0;j<3;j++) h1->geom[j]=point[j]; p1=(Tetra_point *)HECMW_malloc(sizeof(Tetra_point)); if(p1==NULL) HECMW_vis_memory_exit("p1"); tetra_point->ident++; p2=tetra_point->nextpoint; tetra_point->nextpoint=p1; p1->cdata=color; p1->ident=tetra_point->ident-1; for(j=0;j<3;j++) p1->geom[j]=point[j]; p1->nextpoint=p2; index_patch++; patch[index_patch]=p1->ident; } else if(vertex_hash_table[tmp_int].ident>0) { */ flag_existing = 0; h1 = vertex_hash_table[tmp_int].next_vertex; for (j = 0; j < vertex_hash_table[tmp_int].ident; j++) { if ((fabs(h1->geom[0] - point[0]) < EPSILON) && (fabs(h1->geom[1] - point[1]) < EPSILON) && (fabs(h1->geom[2] - point[2]) < EPSILON)) { flag_existing = 1; index_patch++; patch[index_patch] = h1->ident; for (k = 0; k < 3; k++) fp[index_patch][k] = point[k]; break; } h1 = h1->next_vertex; } if (flag_existing == 0) { /*adding new vertex */ vertex_hash_table[tmp_int].ident++; h1 = (Hash_vertex *)HECMW_malloc(sizeof(Hash_vertex)); if (h1 == NULL) HECMW_vis_memory_exit("h1"); h2 = vertex_hash_table[tmp_int].next_vertex; vertex_hash_table[tmp_int].next_vertex = h1; h1->next_vertex = h2; h1->ident = tetra_point->ident; for (j = 0; j < 3; j++) h1->geom[j] = point[j]; p1 = (Tetra_point *)HECMW_malloc(sizeof(Tetra_point)); if (p1 == NULL) HECMW_vis_memory_exit("p1"); tetra_point->ident++; p2 = tetra_point->nextpoint; tetra_point->nextpoint = p1; p1->cdata = color; p1->ident = tetra_point->ident - 1; for (j = 0; j < 3; j++) p1->geom[j] = point[j]; p1->nextpoint = p2; index_patch++; patch[index_patch] = p1->ident; for (k = 0; k < 3; k++) fp[index_patch][k] = point[k]; /* } } */ } } /* end for i*/ /* judge whether the rotation direction pointed out to isosurface */ n_f[0] = (fp[1][1] - fp[0][1]) * (fp[2][2] - fp[0][2]) - (fp[2][1] - fp[0][1]) * (fp[1][2] - fp[0][2]); n_f[1] = -(fp[1][0] - fp[0][0]) * (fp[2][2] - fp[0][2]) + (fp[2][0] - fp[0][0]) * (fp[1][2] - fp[0][2]); n_f[2] = (fp[1][0] - fp[0][0]) * (fp[2][1] - fp[0][1]) - (fp[2][0] - fp[0][0]) * (fp[1][1] - fp[0][1]); for (j = 0; j < 3; j++) fp[3][j] = tetra->axis[0 * 3 + j]; n_norm = sqrt(n_f[0] * n_f[0] + n_f[1] * n_f[1] + n_f[2] * n_f[2]); if (fabs(n_norm) > EPSILON) { for (j = 0; j < 3; j++) n_f[j] /= n_norm; } /*selce the direction point to inside the element */ for (j = 0; j < 3; j++) f_cen_point[j] = (fp[0][j] + fp[1][j] + fp[2][j]) / 3.0; for (j = 0; j < 3; j++) c_c[j] = fp[3][j] - f_cen_point[j]; n_c = sqrt(c_c[0] * c_c[0] + c_c[1] * c_c[1] + c_c[2] * c_c[2]); if (fabs(n_c) > EPSILON) { for (j = 0; j < 3; j++) c_c[j] /= n_c; } sign_f = n_f[0] * c_c[0] + n_f[1] * c_c[1] + n_f[2] * c_c[2]; if (((tetra->s_data[0] > isovalue) && (sign_f < -EPSILON)) || ((tetra->s_data[0] <= isovalue) && (sign_f > EPSILON))) { tmp_int = patch[1]; patch[1] = patch[3]; patch[3] = tmp_int; } t1 = (Patch_tetra *)HECMW_malloc(sizeof(Patch_tetra)); if (t1 == NULL) HECMW_vis_memory_exit("t1"); t2 = head_patch_tetra->patch_link; head_patch_tetra->num_patch++; head_patch_tetra->patch_link = t1; t1->next_patch = t2; for (j = 0; j < 3; j++) t1->patch[j] = patch[j]; t1 = (Patch_tetra *)HECMW_malloc(sizeof(Patch_tetra)); if (t1 == NULL) HECMW_vis_memory_exit("t1"); t2 = head_patch_tetra->patch_link; head_patch_tetra->num_patch++; head_patch_tetra->patch_link = t1; t1->next_patch = t2; t1->patch[0] = patch[0]; t1->patch[1] = patch[2]; t1->patch[2] = patch[3]; } /* end if (num_gt_0==2) */ } return; }