/************************************************************************ Yutaka Ohtake MeshData.cpp Mesh data Copyright (c) 1999-2001 The University of Aizu. All Rights Reserved. ************************************************************************/ #include "stdafx.h" #include "MeshEditor.h" #include "MeshData.h" #include "Simplifier.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif #define PI 3.14159265 ////////////////////////////////////////////////////////////////////// // \z/ ////////////////////////////////////////////////////////////////////// MeshData::MeshData() { face_N = 0; vertex_N = 0; vertex = NULL; face = NULL; vertex_link_v = NULL; vertex_link_f = NULL; degree_v = NULL; degree_f = NULL; face_link_E = NULL; face_link_V_N = NULL; face_link_V = NULL; isBound = NULL; isRidge = NULL; isRavine = NULL; ridge_tri = NULL; ravine_tri = NULL; ridge_edge = NULL; ravine_edge = NULL; normal = NULL; normal_f = NULL; K = NULL; midK = 0; varience = 0; k_max = NULL; k_min = NULL; t_max = NULL; t_min = NULL; k_edge = NULL; ridge_dir = NULL; ravine_dir = NULL; //edge_list = NULL; isRidge_T = NULL; isRavine_T = NULL; ridge_T = NULL; ravine_T = NULL; sample_point = NULL; sample_N = 0; center = NULL; triangle_id = NULL; selected_triangle = NULL; ridge_S = NULL; ravine_S = NULL; } MeshData::~MeshData() { this->deleteLinkData(); /* if(vertex != NULL) delete[] vertex; if(face != NULL) delete[] face; if(isBound != NULL) delete[] isBound; if(vertex_link_v != NULL){ for(int i=0; ivertex_N = vertex_N; vertex = new float[vertex_N][3]; } void MeshData::setFaceCount(int face_N) { if(face != NULL) delete[] face; this->face_N = face_N; face = (int (*)[3])new int[face_N][3]; } int MeshData::getVertexCount() { return vertex_N; } int MeshData::getFaceCount() { return face_N; } void MeshData::setVertex(int index, float coordinates[3]) { vertex[index][0] = coordinates[0]; vertex[index][1] = coordinates[1]; vertex[index][2] = coordinates[2]; } void MeshData::setFace(int index, int vertex_index[]) { face[index][0] = vertex_index[0]; face[index][1] = vertex_index[1]; face[index][2] = vertex_index[2]; } void MeshData::getVertex(int index, float coordinates[3]) { coordinates[0] = vertex[index][0]; coordinates[1] = vertex[index][1]; coordinates[2] = vertex[index][2]; } void MeshData::getFace(int index, int vertex_index[]) { vertex_index[0] = face[index][0]; vertex_index[1] = face[index][1]; vertex_index[2] = face[index][2]; } void MeshData::normalizeScale() { float max[3], min[3]; max[0] = max[1] = max[2] = -1000000; min[0] = min[1] = min[2] = 1000000; for(int i=0; i vertex[i][j]) min[j] = vertex[i][j]; } } float sizeX = max[0] - min[0]; float sizeY = max[1] - min[1]; float sizeZ = max[2] - min[2]; double scale = sizeX; if(scale < sizeY) scale = sizeY; if(scale < sizeZ) scale = sizeZ; normalize_scale = scale*0.05; scale = 20.0/scale; //20.0f/scale; for(i=0; iappend(face[i][1], i); vertex_link[face[i][0]]->append(face[i][2], i); vertex_link[face[i][1]]->append(face[i][2], i); vertex_link[face[i][1]]->append(face[i][0], i); vertex_link[face[i][2]]->append(face[i][0], i); vertex_link[face[i][2]]->append(face[i][1], i); } */ int* link_N = new int[vertex_N]; for(int i=0; i= vertex_N) face[i][0] = face[i][1] = face[i][2] = -1; if(face[i][j] == face[i][(j+1)%3]) face[i][0] = face[i][1] = face[i][2] = -1; } } for(i=0; isortVertexLink(link[i], link_N[i], vertex_link_v[i], vertex_link_f[i], degree_v[i], degree_f[i]); if(link_N[i] != 0) delete[] link[i]; /* isBound[i] = this->sortVertexLink(vertex_link[i], vertex_link_v[i], vertex_link_f[i], degree_v[i], degree_f[i]); */ } /* for(i=0; i 0.001){ A += 0.5*Ai; double dot1 = DOT(PQ1, QQ); double dot2 = -DOT(PQ2,QQ); double cot1 = dot2/Ai; double cot2 = dot1/Ai; Hn[0] += cot1*PQ1[0] + cot2*PQ2[0]; Hn[1] += cot1*PQ1[1] + cot2*PQ2[1]; Hn[2] += cot1*PQ1[2] + cot2*PQ2[2]; } } if((float)A != 0){ //> 0.006){ Hn[0] /= A; Hn[1] /= A; Hn[2] /= A; } else{ Hn[0] = 0; Hn[1] = 0; Hn[2] = 0; } } void MeshData::computePrincipal() { if(k_max != NULL){ delete[] k_max; } k_max = new double[vertex_N]; if(k_min != NULL){ delete[] k_min; } k_min = new double[vertex_N]; if(t_max != NULL){ delete[] t_max; } t_max = new double[vertex_N][3]; if(t_min != NULL){ delete[] t_min; } t_min = new double[vertex_N][3]; if(normal == NULL) computeNormal(); for(int i=0; i 1) in = 1; else if (in < -1) in = -1; float ki = -acos(in)/LENGTH(v); */ /* float ki; if(in > 1) ki = 0; else ki = -(2.0*sqrt(0.5*(1.0-in)))/LENGTH(v);*/ //tangent double t[3]; t[0] = (1.0-normal[i][0]*normal[i][0])*v[0] - normal[i][0]*normal[i][1]*v[1] - normal[i][0]*normal[i][2]*v[2]; t[1] = -normal[i][0]*normal[i][1]*v[0] + (1.0-normal[i][1]*normal[i][1])*v[1] - normal[i][1]*normal[i][2]*v[2]; t[2] = -normal[i][0]*normal[i][2]*v[0] - normal[i][1]*normal[i][2]*v[1] + (1.0-normal[i][2]*normal[i][2])*v[2]; //another approximation of directinal curvature //if concave then -1 times //if(DOT(normal[j],t) < 0) //ki = -ki; double len = LENGTH(t); if((float)len != 0){ t[0] /= len; t[1] /= len; t[2] /= len; for(int row=0; row<3; row++) for(int column=0; column<3; column++) M[row][column] += w[m]*ki*t[row]*t[column]; } } delete[] w; //normalize weight if(total_w == 0){ k_max[i] = k_min[i] = 0; t_max[i][0] = t_max[i][1] = t_max[i][2] = 0; t_min[i][0] = t_min[i][1] = t_min[i][2] = 0; continue; } for(int j=0; j<3; j++) for(int k=0; k<3; k++) M[j][k] /= total_w; double e1[3] = {1.0, 0.0, 0.0}; double W[3]; if(normal[i][0] < 0){ W[0] = (1.0 - normal[i][0])/sqrt(2.0-2.0*normal[i][0]); W[1] = -normal[i][1]/sqrt(2.0-2.0*normal[i][0]); W[2] = -normal[i][2]/sqrt(2.0-2.0*normal[i][0]); } else{ W[0] = (1.0 + normal[i][0])/sqrt(2.0+2.0*normal[i][0]); W[1] = normal[i][1]/sqrt(2.0+2.0*normal[i][0]); W[2] = normal[i][2]/sqrt(2.0+2.0*normal[i][0]); } double Q[3][3]; for(int row=0; row<3; row++) for(int column=0; column<3; column++) if(row != column) Q[row][column] = -2.0*W[row]*W[column]; else Q[row][column] = 1.0 - 2.0*W[row]*W[column]; double T1[3] = {Q[1][0], Q[1][1], Q[1][2]}; double T2[3] = {Q[2][0], Q[2][1], Q[2][2]}; double M2[2][2]; M2[0][0] = M[0][0]*Q[0][1]*Q[0][1] + 2.0f*M[0][1]*Q[0][1]*Q[1][1] + M[1][1]*Q[1][1]*Q[1][1] + 2.0f*M[0][2]*Q[0][1]*Q[1][2] + 2.0f*M[1][2]*Q[1][1]*Q[1][2] + M[2][2]*Q[1][2]*Q[1][2]; M2[0][1] = Q[0][2]*(M[0][0]*Q[0][1] + M[0][1]*Q[1][1] + M[0][2]*Q[1][2]) + Q[1][2]*(M[0][1]*Q[0][1] + M[1][1]*Q[1][1] + M[1][2]*Q[1][2]) + Q[2][2]*(M[0][2]*Q[0][1] + M[1][2]*Q[1][1] + M[2][2]*Q[1][2]); M2[1][0] = M2[0][1]; M2[1][1] = M[0][0]*Q[0][2]*Q[0][2] + 2.0f*M[0][1]*Q[0][2]*Q[1][2] + M[1][1]*Q[1][2]*Q[1][2] + 2.0f*M[0][2]*Q[0][2]*Q[2][2] + M[2][2]*Q[2][2]*Q[2][2] + 2.0f*M[1][2]*Q[1][2]*Q[2][2]; double th = 0; if(M2[0][1] != 0) th = 0.5*(M2[1][1]-M2[0][0])/M2[0][1]; double t = 1.0/(fabs(th)+sqrt(th*th+1)); if(th < 0) t = -t; double cos = 1.0/sqrt(t*t+1); double sin = t*cos; double K1_tmp = M2[0][0] - t*M2[0][1]; double K2_tmp = M2[1][1] + t*M2[0][1]; double K1 = 3.0*K1_tmp - K2_tmp; double K2 = 3.0*K2_tmp - K1_tmp; if(K1 > K2){ k_max[i] = K1; t_max[i][0] = cos*T1[0] - sin*T2[0]; t_max[i][1] = cos*T1[1] - sin*T2[1]; t_max[i][2] = cos*T1[2] - sin*T2[2]; k_min[i] = K2; t_min[i][0] = sin*T1[0] + cos*T2[0]; t_min[i][1] = sin*T1[1] + cos*T2[1]; t_min[i][2] = sin*T1[2] + cos*T2[2]; } else{ k_min[i] = K1; t_min[i][0] = cos*T1[0] - sin*T2[0]; t_min[i][1] = cos*T1[1] - sin*T2[1]; t_min[i][2] = cos*T1[2] - sin*T2[2]; k_max[i] = K2; t_max[i][0] = sin*T1[0] + cos*T2[0]; t_max[i][1] = sin*T1[1] + cos*T2[1]; t_max[i][2] = sin*T1[2] + cos*T2[2]; } } for(i=0; igetConsistent1Ring(i, nei_v, nei_N); if(nei_N == 0) continue; double k_max_max1, k_max_max2; double k_min_min1, k_min_min2; double l_max1, l_max2, l_min1, l_min2; double n1[3]; CROSS(n1, normal[i], t_max[i]); double n2[3]; CROSS(n2, normal[i], t_min[i]); for(int m=0; mgetConsistent1Ring(i, nei, nei_N); if(nei_N == 0) continue; double k_max_max1, k_max_max2, k_max_min1, k_max_min2; double k_min_min1, k_min_min2, k_min_max1, k_min_max2; double l_max1, l_max2, l_min1, l_min2; double n1[3]; CROSS(n1, normal[i], t_max[i]); double n2[3]; CROSS(n2, normal[i], t_min[i]); for(int m=0; m= face_N) return -1; else if(vertex_id < 0 || vertex_id >= vertex_N) return -1; else if(face[face_id][0] == vertex_id) return face_link_E[face_id][2]; else if(face[face_id][1] == vertex_id) return face_link_E[face_id][0]; else if(face[face_id][2] == vertex_id) return face_link_E[face_id][1]; else return -1; } int MeshData::nextVertex(int face_id, int vertex_id) { if(face_id < 0 || face_id >= face_N) return -1; else if(face[face_id][0] == vertex_id) return face[face_id][1]; else if(face[face_id][1] == vertex_id) return face[face_id][2]; else if(face[face_id][2] == vertex_id) return face[face_id][0]; else return -1; } int MeshData::previousFace(int face_id, int vertex_id) { if(face_id < 0 || face_id >= face_N) return -1; else if(vertex_id < 0 || vertex_id >= vertex_N) return -1; else if(face[face_id][0] == vertex_id) return face_link_E[face_id][0]; else if(face[face_id][1] == vertex_id) return face_link_E[face_id][1]; else if(face[face_id][2] == vertex_id) return face_link_E[face_id][2]; else return -1; } double MeshData::getVolume() { double vol = 0; double g[3],n[3],v1[3],v2[3]; for(int i=0; iv = index; //In this list, f is distance(the number of edges) from the target vertex Node* visit = new Node; visit->append(index, 0); visit->append(index, 0); Node* currentQ = que; //breath first numbering //this code can not compute the exact rings near boundary vertex. while(true){ for(Node* currentL = vertex_link[currentQ->v]; currentL->next != NULL; currentL = currentL->next->next){ //check if currentL->v is visited for(Node* currentV = visit; currentV->next != NULL; currentV = currentV->next->next){ if(currentV->v == currentL->v) break; } if(currentV->next == NULL){ //search currentQ->v from visit-list for computing distance for(currentV = visit; currentV->next != NULL; currentV = currentV->next->next) if(currentV->v == currentQ->v) break; if(currentV->f < n){ int dist = currentV->f+1; for(currentV = visit; currentV->next != NULL; currentV = currentV->next->next) if(currentV->v == currentL->next->v) break; if(currentV->next == NULL || currentV->f == dist){ visit->append(currentL->v, dist); //additinal element is appended for generating triangle data visit->append(currentL->next->v, dist); //prepend node into que Node* head = new Node; head->v = currentL->v; head->next = que; que = head; } } } } if(que == currentQ){ delete que; break; } for(Node* currentQ2 = que; currentQ2->next != currentQ; currentQ2 = currentQ2->next); currentQ2->next = NULL; delete currentQ; // currentQ is setted to tail of que for(currentQ = que; currentQ->next != NULL; currentQ = currentQ->next); } nei_N = new int[n]; for(int i=0; inext->next; currentV->next != NULL; currentV = currentV->next) nei_N[currentV->f-1]++; nei = (int **)new int[n]; int* counter = new int[n]; for(i=0; inext->next; currentV->next != NULL; currentV = currentV->next){ nei[currentV->f-1][counter[currentV->f-1]++] = currentV->v; } delete visit; delete[] counter; //sort ring index consistently for(i=0; i= 0){ int tmp1 = nei[i][0]; int tmp2 = nei[i][1]; nei[i][0] = nei[i][bound_flag]; nei[i][1] = nei[i][bound_flag+1]; nei[i][bound_flag] = tmp1; nei[i][bound_flag+1] = tmp2; } for(j=0; j= face_N) return; for(int i=0; i<3; i++){ int pair = face_link_E[index][i]; if(pair >= 0){ if(face_link_E[pair][0] == index) face_link_E[pair][0] = -1; else if(face_link_E[pair][1] == index) face_link_E[pair][1] = -1; else if(face_link_E[pair][2] == index) face_link_E[pair][2] = -1; face_link_E[index][i] = -1; } } face[index][0] = -1; face[index][1] = -1; face[index][2] = -1; } void MeshData::generateFaceLinkV() { if(face_link_V_N != NULL) delete[] face_link_V_N; if(face_link_V != NULL){ for(int i=0; iappend(-1, nei_f[k]); face_link_V_N[i]++; } } } if(face_link_V_N[i] != 0){ face_link_V[i] = new int[face_link_V_N[i]]; Node* current = list; for(j=0; jf; current = current->next; } } delete list; } } float MeshData::minEdge() { double min = 1000000; for(int i=0; i link_v[j]){ float v[3]; VEC(v, vertex[i], vertex[link_v[j]]); double len = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); if((float)len != 0 && min > len) min = len; } } } return (float)min; } void MeshData::copyMesh(MeshData *mesh) { setVertexCount(mesh->vertex_N); for(int i=0; ivertex[i][0]; vertex[i][1] = mesh->vertex[i][1]; vertex[i][2] = mesh->vertex[i][2]; } setFaceCount(mesh->face_N); for(i=0; iface[i][0]; face[i][1] = mesh->face[i][1]; face[i][2] = mesh->face[i][2]; } this->normalize_scale = mesh->normalize_scale; this->original_max[0] = mesh->original_max[0]; this->original_max[1] = mesh->original_max[1]; this->original_max[2] = mesh->original_max[2]; this->original_min[0] = mesh->original_min[0]; this->original_min[1] = mesh->original_min[1]; this->original_min[2] = mesh->original_min[2]; } void MeshData::allocateTagEdges() { if(ridge_edge != NULL){ for(int i=0; inext!=NULL; current=current->next->next) f++; //if no face is incident, then the point is isolated. if(f == 0){ v = 0; link_v = NULL; link_f = NULL; return NON_MANIFOLD; } //un-sorted adjacent vertex data link_f = new int[f]; int *link_v_tmp = new int[2*f]; int i = 0; for(current=link; current->next!=NULL; current=current->next->next){ link_v_tmp[2*i] = current->v; link_v_tmp[2*i+1] = current->next->v; link_f[i] = current->f; i++; } //check topology int b_even = 0; int b_odd = 0; int b_index; for(i=0; i= 0){ for(i=1; i pair){ double dot = DOT(normal_f[i], normal_f[pair]); if(dot > 1.0) dot = 1.0; else if(dot < -1.0) dot = -1.0; double a1 = faceArea(pair); double l = DIST(vertex[face[i][j]], vertex[face[i][(j+1)%3]]); if((float)a != 0 && (float)a1 != 0) k_edge[i][j] = acos(dot)*l/(a+a1); else k_edge[i][j] = 0; double c1[3]; faceCenter(c1, pair); double v[3]; MeshData::VEC(v, c, c1); double len = MeshData::LENGTH(v); double dot1, dot2; if((float)len != 0){ dot1 = MeshData::DOT(v, normal_f[i])/len; dot2 = -MeshData::DOT(v, normal_f[pair])/len; } else{ dot1 = 1; dot2 = 1; } if(dot1 > 1.0) dot1 = 1.0; else if(dot1 < -1.0) dot1 = -1.0; if(dot2 > 1.0) dot2 = 1.0; else if(dot2 < -1.0) dot2 = -1.0; double angle = acos(dot1) + acos(dot2); if(angle < PI) k_edge[i][j] = -k_edge[i][j]; if(face_link_E[pair][0] == i) k_edge[pair][0] = k_edge[i][j]; else if(face_link_E[pair][1] == i) k_edge[pair][1] = k_edge[i][j]; else k_edge[pair][2] = k_edge[i][j]; } } } } void MeshData::copyMesh2(MeshData *mesh) { int f_N = mesh->countValidFace(); int v_N = mesh->countValidVertex(); int* vertex_table = new int[mesh->vertex_N]; setVertexCount(v_N); int counter = 0; for(int i=0; ivertex_N; i++){ if(mesh->degree_v[i] != 0){ vertex[counter][0] = mesh->vertex[i][0]; vertex[counter][1] = mesh->vertex[i][1]; vertex[counter][2] = mesh->vertex[i][2]; vertex_table[i] = counter; counter++; } else vertex_table[i] = -1; } setFaceCount(f_N); counter = 0; for(i=0; iface_N; i++){ if(mesh->face[i][0] >= 0){ face[counter][0] = vertex_table[mesh->face[i][0]]; face[counter][1] = vertex_table[mesh->face[i][1]]; face[counter][2] = vertex_table[mesh->face[i][2]]; counter++; } } delete[] vertex_table; this->normalize_scale = mesh->normalize_scale; this->original_max[0] = mesh->original_max[0]; this->original_max[1] = mesh->original_max[1]; this->original_max[2] = mesh->original_max[2]; this->original_min[0] = mesh->original_min[0]; this->original_min[1] = mesh->original_min[1]; this->original_min[2] = mesh->original_min[2]; } void MeshData::generateSamplePointRandamly(int sample_N) { this->sample_N = sample_N; sample_point = new tri_point[sample_N]; t_max_line_N = new int[sample_N]; t_min_line_N = new int[sample_N]; t_max_line = new tri_point*[sample_N]; t_min_line = new tri_point*[sample_N]; float *area = new float[face_N]; int *index = new int[face_N]; for(int i=0; isample_N = sample_N; sample_point = new tri_point[sample_N]; t_max_line_N = new int[sample_N]; t_min_line_N = new int[sample_N]; t_max_line = new tri_point*[sample_N]; t_min_line = new tri_point*[sample_N]; float *area = new float[face_N]; int *index = new int[face_N]; for(int i=0; i i){ for(i = i+1; w[i] < v; i++); for(j = j-1; w[j] > v; j--); float t = w[i]; w[i] = w[j]; w[j] = t; int tmp = index[i]; index[i] = index[j]; index[j] = tmp; } float t = w[j]; w[j] = w[i]; w[i] = w[end]; w[end] = t; int tmp = index[j]; index[j] = index[i]; index[i] = index[end]; index[end] = tmp; quickSort(index, w, start, i-1); quickSort(index, w, i+1, end); } else return; } int MeshData::barycentricCoor(int id, float p[], double &u, double &v) { double a = faceArea(id); double a0 = AREA(p, vertex[face[id][1]], vertex[face[id][2]]); double a1 = AREA(p, vertex[face[id][2]], vertex[face[id][0]]); double a2 = AREA(p, vertex[face[id][0]], vertex[face[id][1]]); if(a < a1 + a2){ u = a1/a; //(a1+a2); v = a2/a; //(a1+a2); return -1; } if(a < a2 + a0){ u = -a1/a; v = a2/a; //(a2+a0); return -2; } if(a < a0 + a1){ u = a1/a; //(a0+a1); v = -a2/a; return -3; } u = a1/a; v = a2/a; return 0; } void MeshData::traceRidgeDir(struct TRI_POINT seed, float length, struct TRI_POINT *&line, int &point_N, float step, double T) { int max = 200; int n1 = 0; int n2 = 0; tri_point *tmp1 = new tri_point[max]; tri_point *tmp2 = new tri_point[max]; tri_point current; int *f; double dir0[3], dir1[3], dir2[3]; //trace forward current = seed; f = face[current.id]; dir0[0] = ridge_dir[f[0]][0]; dir0[1] = ridge_dir[f[0]][1]; dir0[2] = ridge_dir[f[0]][2]; dir1[0] = ridge_dir[f[1]][0]; dir1[1] = ridge_dir[f[1]][1]; dir1[2] = ridge_dir[f[1]][2]; dir2[0] = ridge_dir[f[2]][0]; dir2[1] = ridge_dir[f[2]][1]; dir2[2] = ridge_dir[f[2]][2]; double l = 0; if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } while(l < 0.5*length && n1 < max){ double t1 = current.u; double t2 = current.v; double t0 = 1.0 - t1 - t2; double v[3]; float p[3]; p[0] = (float)(t0*vertex[f[0]][0] + t1*vertex[f[1]][0] + t2*vertex[f[2]][0]); p[1] = (float)(t0*vertex[f[0]][1] + t1*vertex[f[1]][1] + t2*vertex[f[2]][1]); p[2] = (float)(t0*vertex[f[0]][2] + t1*vertex[f[1]][2] + t2*vertex[f[2]][2]); v[0] = t0*dir0[0] + t1*dir1[0] + t2*dir2[0]; v[1] = t0*dir0[1] + t1*dir1[1] + t2*dir2[1]; v[2] = t0*dir0[2] + t1*dir1[2] + t2*dir2[2]; float* n = normal_f[current.id]; double dot = DOT(v, n); v[0] = v[0] - dot*n[0]; v[1] = v[1] - dot*n[1]; v[2] = v[2] - dot*n[2]; double len = LENGTH(v); v[0] = v[0]*step/len; v[1] = v[1]*step/len; v[2] = v[2]*step/len; float next_p[3]; next_p[0] = p[0] + (float)v[0]; next_p[1] = p[1] + (float)v[1]; next_p[2] = p[2] + (float)v[2]; double next_u, next_v; int result = barycentricCoor(current.id, next_p, next_u, next_v); tmp1[n1].id = current.id; tmp1[n1].u = next_u; tmp1[n1].v = next_v; if(result < 0){ double a = next_v - t2; double b = next_u - t1; double c = a*t1 - b*t2; int base_v; double old_dir[3]; if(result == -1){ next_u = (b+c)/(a+b); next_v = (a-c)/(a+b); current.id = face_link_E[current.id][1]; old_dir[0] = dir1[0]; old_dir[1] = dir1[1]; old_dir[2] = dir1[2]; if(face[current.id][0] == f[1]) base_v = 0; else if(face[current.id][1] == f[1]) base_v = 1; else base_v = 2; } else if(result == -2){ next_u = 0; next_v = -c/b; current.id = face_link_E[current.id][2]; old_dir[0] = dir2[0]; old_dir[1] = dir2[1]; old_dir[2] = dir2[2]; if(face[current.id][0] == f[2]) base_v = 0; else if(face[current.id][1] == f[2]) base_v = 1; else base_v = 2; } else{ next_u = c/a; next_v = 0; current.id = face_link_E[current.id][0]; old_dir[0] = dir0[0]; old_dir[1] = dir0[1]; old_dir[2] = dir0[2]; if(face[current.id][0] == f[0]) base_v = 0; else if(face[current.id][1] == f[0]) base_v = 1; else base_v = 2; } tmp1[n1].u = next_u; tmp1[n1].v = next_v; if(current.id < 0) break; t1 = next_u; t2 = next_v; t0 = 1.0 - t1 - t2; next_p[0] = (float)(t0*vertex[f[0]][0] + t1*vertex[f[1]][0] + t2*vertex[f[2]][0]); next_p[1] = (float)(t0*vertex[f[0]][1] + t1*vertex[f[1]][1] + t2*vertex[f[2]][1]); next_p[2] = (float)(t0*vertex[f[0]][2] + t1*vertex[f[1]][2] + t2*vertex[f[2]][2]); l += (float)DIST(next_p, p); barycentricCoor(current.id, next_p, current.u, current.v); f = face[current.id]; dir0[0] = ridge_dir[f[0]][0]; dir0[1] = ridge_dir[f[0]][1]; dir0[2] = ridge_dir[f[0]][2]; dir1[0] = ridge_dir[f[1]][0]; dir1[1] = ridge_dir[f[1]][1]; dir1[2] = ridge_dir[f[1]][2]; dir2[0] = ridge_dir[f[2]][0]; dir2[1] = ridge_dir[f[2]][1]; dir2[2] = ridge_dir[f[2]][2]; if(base_v == 0){ if(DOT(old_dir, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } } else if(base_v == 1){ if(DOT(old_dir, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir1, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir1, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } } else{ if(DOT(old_dir, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir2, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir2, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } } } else{ l += step; current = tmp1[n1]; } if(n1 > 1){ float p1[3], p2[3], p3[3]; worldcoor(tmp1[n1-2], p1); worldcoor(tmp1[n1-1], p2); worldcoor(tmp1[n1], p3); if((p1[0]-p2[0])*(p3[0]-p2[0]) + (p1[1]-p2[1])*(p3[1]-p2[1]) + (p1[2]-p2[2])*(p3[2]-p2[2]) > 0) break; } n1++; if(T > (1.0-current.u-current.v)*k_max[face[current.id][0]] + current.u*k_max[face[current.id][1]] + current.v*k_max[face[current.id][2]]) break; } //trace backward current = seed; f = face[current.id]; dir0[0] = -ridge_dir[f[0]][0]; dir0[1] = -ridge_dir[f[0]][1]; dir0[2] = -ridge_dir[f[0]][2]; dir1[0] = -ridge_dir[f[1]][0]; dir1[1] = -ridge_dir[f[1]][1]; dir1[2] = -ridge_dir[f[1]][2]; dir2[0] = -ridge_dir[f[2]][0]; dir2[1] = -ridge_dir[f[2]][1]; dir2[2] = -ridge_dir[f[2]][2]; l = 0; if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } while(l < 0.5*length && n2 < max){ double t1 = current.u; double t2 = current.v; double t0 = 1.0 - t1 - t2; double v[3]; float p[3]; p[0] = (float)(t0*vertex[f[0]][0] + t1*vertex[f[1]][0] + t2*vertex[f[2]][0]); p[1] = (float)(t0*vertex[f[0]][1] + t1*vertex[f[1]][1] + t2*vertex[f[2]][1]); p[2] = (float)(t0*vertex[f[0]][2] + t1*vertex[f[1]][2] + t2*vertex[f[2]][2]); v[0] = t0*dir0[0] + t1*dir1[0] + t2*dir2[0]; v[1] = t0*dir0[1] + t1*dir1[1] + t2*dir2[1]; v[2] = t0*dir0[2] + t1*dir1[2] + t2*dir2[2]; float* n = normal_f[current.id]; double dot = DOT(v, n); v[0] = v[0] - dot*n[0]; v[1] = v[1] - dot*n[1]; v[2] = v[2] - dot*n[2]; double len = LENGTH(v); v[0] = v[0]*step/len; v[1] = v[1]*step/len; v[2] = v[2]*step/len; float next_p[3]; next_p[0] = p[0] + (float)v[0]; next_p[1] = p[1] + (float)v[1]; next_p[2] = p[2] + (float)v[2]; double next_u, next_v; int result = barycentricCoor(current.id, next_p, next_u, next_v); tmp2[n2].id = current.id; tmp2[n2].u = next_u; tmp2[n2].v = next_v; if(result < 0){ double a = next_v - t2; double b = next_u - t1; double c = a*t1 - b*t2; int base_v; double old_dir[3]; if(result == -1){ next_u = (b+c)/(a+b); next_v = (a-c)/(a+b); current.id = face_link_E[current.id][1]; old_dir[0] = dir1[0]; old_dir[1] = dir1[1]; old_dir[2] = dir1[2]; if(face[current.id][0] == f[1]) base_v = 0; else if(face[current.id][1] == f[1]) base_v = 1; else base_v = 2; } else if(result == -2){ next_u = 0; next_v = -c/b; current.id = face_link_E[current.id][2]; old_dir[0] = dir2[0]; old_dir[1] = dir2[1]; old_dir[2] = dir2[2]; if(face[current.id][0] == f[2]) base_v = 0; else if(face[current.id][1] == f[2]) base_v = 1; else base_v = 2; } else{ next_u = c/a; next_v = 0; current.id = face_link_E[current.id][0]; old_dir[0] = dir0[0]; old_dir[1] = dir0[1]; old_dir[2] = dir0[2]; if(face[current.id][0] == f[0]) base_v = 0; else if(face[current.id][1] == f[0]) base_v = 1; else base_v = 2; } tmp2[n2].u = next_u; tmp2[n2].v = next_v; if(current.id < 0) break; t1 = next_u; t2 = next_v; t0 = 1.0 - t1 - t2; next_p[0] = (float)(t0*vertex[f[0]][0] + t1*vertex[f[1]][0] + t2*vertex[f[2]][0]); next_p[1] = (float)(t0*vertex[f[0]][1] + t1*vertex[f[1]][1] + t2*vertex[f[2]][1]); next_p[2] = (float)(t0*vertex[f[0]][2] + t1*vertex[f[1]][2] + t2*vertex[f[2]][2]); l += (float)DIST(next_p, p); barycentricCoor(current.id, next_p, current.u, current.v); f = face[current.id]; dir0[0] = ridge_dir[f[0]][0]; dir0[1] = ridge_dir[f[0]][1]; dir0[2] = ridge_dir[f[0]][2]; dir1[0] = ridge_dir[f[1]][0]; dir1[1] = ridge_dir[f[1]][1]; dir1[2] = ridge_dir[f[1]][2]; dir2[0] = ridge_dir[f[2]][0]; dir2[1] = ridge_dir[f[2]][1]; dir2[2] = ridge_dir[f[2]][2]; if(base_v == 0){ if(DOT(old_dir, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } } else if(base_v == 1){ if(DOT(old_dir, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir1, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir1, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } } else{ if(DOT(old_dir, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir2, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir2, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } } } else{ l += step; current = tmp2[n2]; } if(n2 > 1){ float p1[3], p2[3], p3[3]; worldcoor(tmp2[n2-2], p1); worldcoor(tmp2[n2-1], p2); worldcoor(tmp2[n2], p3); if((p1[0]-p2[0])*(p3[0]-p2[0]) + (p1[1]-p2[1])*(p3[1]-p2[1]) + (p1[2]-p2[2])*(p3[2]-p2[2]) > 0) break; } n2++; if(T > (1.0-current.u-current.v)*k_max[face[current.id][0]] + current.u*k_max[face[current.id][1]] + current.v*k_max[face[current.id][2]]) break; } //concatnation point_N = n1+n2+1; line = new tri_point[n1+n2+1]; for(int i=0; i 1){ float p1[3], p2[3], p3[3]; worldcoor(tmp1[n1-2], p1); worldcoor(tmp1[n1-1], p2); worldcoor(tmp1[n1], p3); if((p1[0]-p2[0])*(p3[0]-p2[0]) + (p1[1]-p2[1])*(p3[1]-p2[1]) + (p1[2]-p2[2])*(p3[2]-p2[2]) > 0) break; } n1++; if(T < (1.0-current.u-current.v)*k_min[face[current.id][0]] + current.u*k_min[face[current.id][1]] + current.v*k_min[face[current.id][2]]) break; } //trace backward current = seed; f = face[current.id]; dir0[0] = -ravine_dir[f[0]][0]; dir0[1] = -ravine_dir[f[0]][1]; dir0[2] = -ravine_dir[f[0]][2]; dir1[0] = -ravine_dir[f[1]][0]; dir1[1] = -ravine_dir[f[1]][1]; dir1[2] = -ravine_dir[f[1]][2]; dir2[0] = -ravine_dir[f[2]][0]; dir2[1] = -ravine_dir[f[2]][1]; dir2[2] = -ravine_dir[f[2]][2]; l = 0; if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } while(l < 0.5*length && n2 < max){ double t1 = current.u; double t2 = current.v; double t0 = 1.0 - t1 - t2; double v[3]; float p[3]; p[0] = (float)(t0*vertex[f[0]][0] + t1*vertex[f[1]][0] + t2*vertex[f[2]][0]); p[1] = (float)(t0*vertex[f[0]][1] + t1*vertex[f[1]][1] + t2*vertex[f[2]][1]); p[2] = (float)(t0*vertex[f[0]][2] + t1*vertex[f[1]][2] + t2*vertex[f[2]][2]); v[0] = t0*dir0[0] + t1*dir1[0] + t2*dir2[0]; v[1] = t0*dir0[1] + t1*dir1[1] + t2*dir2[1]; v[2] = t0*dir0[2] + t1*dir1[2] + t2*dir2[2]; float* n = normal_f[current.id]; double dot = DOT(v, n); v[0] = v[0] - dot*n[0]; v[1] = v[1] - dot*n[1]; v[2] = v[2] - dot*n[2]; double len = LENGTH(v); v[0] = v[0]*step/len; v[1] = v[1]*step/len; v[2] = v[2]*step/len; float next_p[3]; next_p[0] = p[0] + (float)v[0]; next_p[1] = p[1] + (float)v[1]; next_p[2] = p[2] + (float)v[2]; double next_u, next_v; int result = barycentricCoor(current.id, next_p, next_u, next_v); tmp2[n2].id = current.id; tmp2[n2].u = next_u; tmp2[n2].v = next_v; if(result < 0){ double a = next_v - t2; double b = next_u - t1; double c = a*t1 - b*t2; int base_v; double old_dir[3]; if(result == -1){ next_u = (b+c)/(a+b); next_v = (a-c)/(a+b); current.id = face_link_E[current.id][1]; old_dir[0] = dir1[0]; old_dir[1] = dir1[1]; old_dir[2] = dir1[2]; if(face[current.id][0] == f[1]) base_v = 0; else if(face[current.id][1] == f[1]) base_v = 1; else base_v = 2; } else if(result == -2){ next_u = 0; next_v = -c/b; current.id = face_link_E[current.id][2]; old_dir[0] = dir2[0]; old_dir[1] = dir2[1]; old_dir[2] = dir2[2]; if(face[current.id][0] == f[2]) base_v = 0; else if(face[current.id][1] == f[2]) base_v = 1; else base_v = 2; } else{ next_u = c/a; next_v = 0; current.id = face_link_E[current.id][0]; old_dir[0] = dir0[0]; old_dir[1] = dir0[1]; old_dir[2] = dir0[2]; if(face[current.id][0] == f[0]) base_v = 0; else if(face[current.id][1] == f[0]) base_v = 1; else base_v = 2; } tmp2[n2].u = next_u; tmp2[n2].v = next_v; if(current.id < 0) break; t1 = next_u; t2 = next_v; t0 = 1.0 - t1 - t2; next_p[0] = (float)(t0*vertex[f[0]][0] + t1*vertex[f[1]][0] + t2*vertex[f[2]][0]); next_p[1] = (float)(t0*vertex[f[0]][1] + t1*vertex[f[1]][1] + t2*vertex[f[2]][1]); next_p[2] = (float)(t0*vertex[f[0]][2] + t1*vertex[f[1]][2] + t2*vertex[f[2]][2]); l += (float)DIST(next_p, p); barycentricCoor(current.id, next_p, current.u, current.v); f = face[current.id]; dir0[0] = ravine_dir[f[0]][0]; dir0[1] = ravine_dir[f[0]][1]; dir0[2] = ravine_dir[f[0]][2]; dir1[0] = ravine_dir[f[1]][0]; dir1[1] = ravine_dir[f[1]][1]; dir1[2] = ravine_dir[f[1]][2]; dir2[0] = ravine_dir[f[2]][0]; dir2[1] = ravine_dir[f[2]][1]; dir2[2] = ravine_dir[f[2]][2]; if(base_v == 0){ if(DOT(old_dir, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } } else if(base_v == 1){ if(DOT(old_dir, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir1, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir1, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } } else{ if(DOT(old_dir, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir2, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir2, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } } } else{ l += step; current = tmp2[n2]; } if(n2 > 1){ float p1[3], p2[3], p3[3]; worldcoor(tmp2[n2-2], p1); worldcoor(tmp2[n2-1], p2); worldcoor(tmp2[n2], p3); if((p1[0]-p2[0])*(p3[0]-p2[0]) + (p1[1]-p2[1])*(p3[1]-p2[1]) + (p1[2]-p2[2])*(p3[2]-p2[2]) > 0) break; } n2++; if(T < (1.0-current.u-current.v)*k_min[face[current.id][0]] + current.u*k_min[face[current.id][1]] + current.v*k_min[face[current.id][2]]) break; } //concatnation point_N = n1+n2+1; line = new tri_point[n1+n2+1]; for(int i=0; i fabs(det12)){ if(fabs(det01) > fabs(det20)){ //max is |det01| if((float)det01 == 0) return false; u = (v2[1]*t[0] - v2[0]*t[1])/det01; v = (-v1[1]*t[0] + v1[0]*t[1])/det01; } else{ //max is |det20| if((float)det20 == 0) return false; u = (v2[0]*t[2] - v2[2]*t[0])/det20; v = (-v1[0]*t[2] + v1[2]*t[0])/det20; } } else if(fabs(det12) > fabs(det20)){ //max is |det12| if((float)det12 == 0) return false; u = (v2[2]*t[1] - v2[1]*t[2])/det12; v = (-v1[2]*t[1] + v1[1]*t[2])/det12; } else{ //max is |det20| if((float)det20 == 0) return false; u = (v2[0]*t[2] - v2[2]*t[0])/det20; v = (-v1[0]*t[2] + v1[2]*t[0])/det20; } return true; } void MeshData::traceRidgeDir2(tri_point seed, float length, tri_point *&line, int &point_N, float step, double T) { int max = 5000; int n1 = 0; int n2 = 0; tri_point *tmp1 = new tri_point[max]; tri_point *tmp2 = new tri_point[max]; tri_point current; int *f; double dir0[3], dir1[3], dir2[3]; //trace forward current = seed; f = face[current.id]; dir0[0] = ridge_dir[f[0]][0]; dir0[1] = ridge_dir[f[0]][1]; dir0[2] = ridge_dir[f[0]][2]; dir1[0] = ridge_dir[f[1]][0]; dir1[1] = ridge_dir[f[1]][1]; dir1[2] = ridge_dir[f[1]][2]; dir2[0] = ridge_dir[f[2]][0]; dir2[1] = ridge_dir[f[2]][1]; dir2[2] = ridge_dir[f[2]][2]; double l = 0; if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } while(l < 0.5*length && n1 < max){ double t1 = current.u; double t2 = current.v; double t0 = 1.0 - t1 - t2; double v[3]; v[0] = t0*dir0[0] + t1*dir1[0] + t2*dir2[0]; v[1] = t0*dir0[1] + t1*dir1[1] + t2*dir2[1]; v[2] = t0*dir0[2] + t1*dir1[2] + t2*dir2[2]; float* n = normal_f[current.id]; double dot = DOT(v, n); v[0] = v[0] - dot*n[0]; v[1] = v[1] - dot*n[1]; v[2] = v[2] - dot*n[2]; double len = LENGTH(v); if((float)len == 0) break; v[0] = v[0]*step/len; v[1] = v[1]*step/len; v[2] = v[2]*step/len; double du, dv; if(!barycentricVector(current.id, v, du, dv)) break; double next_u = current.u + du; double next_v = current.v + dv; tmp1[n1].id = current.id; //The next position is inside the same triangle. if(next_u + next_v <= 1.0 && next_u >= 0 && next_v >= 0){ tmp1[n1].u = next_u; tmp1[n1].v = next_v; l += step; current = tmp1[n1]; } //Outside the triangle. else{ double a = next_v - t2; double b = next_u - t1; double c = a*t1 - b*t2; double s0 = -c; double s1 = a*(1.0-t1) + b*t2; double s2 = -a*t1 - b*(1.0-t2); int result; if(s1*s2 > 0){ if(next_v > 0) result = 1; else result = 2; } else if(s2*s0 > 0){ if(next_v > 0) result = 3; else result = 2; } else if(s0*s1 > 0){ if(next_u > 0) result = 3; else result = 1; } else{ break; } int base_v; double old_dir[3]; if(result == 1){ next_u = 0; if(b == 0) break; next_v = -c/b; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][2]; old_dir[0] = dir2[0]; old_dir[1] = dir2[1]; old_dir[2] = dir2[2]; if(face[current.id][0] == f[2]){ current.u = 0; current.v = (1.0 - next_v); base_v = 0; } else if(face[current.id][1] == f[2]){ current.u = next_v; current.v = 0; base_v = 1; } else{ current.u = 1.0 - next_v; current.v = next_v; base_v = 2; } } else if(result == 2){ if(a == 0) break; next_u = c/a; next_v = 0; if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; current.id = face_link_E[current.id][0]; old_dir[0] = dir0[0]; old_dir[1] = dir0[1]; old_dir[2] = dir0[2]; if(face[current.id][0] == f[0]){ current.u = 0; current.v = next_u; base_v = 0; } else if(face[current.id][1] == f[0]){ current.u = 1.0 - next_u; current.v = 0; base_v = 1; } else{ current.u = next_u; current.v = 1.0 - next_u; base_v = 2; } } else{ if(a+b == 0) break; next_u = (b+c)/(a+b); next_v = (a-c)/(a+b); if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][1]; old_dir[0] = dir1[0]; old_dir[1] = dir1[1]; old_dir[2] = dir1[2]; if(face[current.id][0] == f[1]){ base_v = 0; current.u = 0; current.v = next_v; } else if(face[current.id][1] == f[1]){ base_v = 1; current.u = next_u; current.v = 0; } else{ base_v = 2; current.u = next_v; current.v = next_u; } } tmp1[n1].u = next_u; tmp1[n1].v = next_v; if(current.id < 0) break; float ud = (float)(next_u - t1); float vd = (float)(next_v - t2); float v1[3], v2[3], v12[3]; VEC(v1, vertex[f[0]], vertex[f[1]]); v1[0] *= ud; v1[1] *= ud; v1[2] *= ud; VEC(v2, vertex[f[2]], vertex[f[2]]); v2[0] *= vd; v2[1] *= vd; v2[2] *= vd; VEC(v12, v1, v2); l += (float)LENGTH(v12); f = face[current.id]; dir0[0] = ridge_dir[f[0]][0]; dir0[1] = ridge_dir[f[0]][1]; dir0[2] = ridge_dir[f[0]][2]; dir1[0] = ridge_dir[f[1]][0]; dir1[1] = ridge_dir[f[1]][1]; dir1[2] = ridge_dir[f[1]][2]; dir2[0] = ridge_dir[f[2]][0]; dir2[1] = ridge_dir[f[2]][1]; dir2[2] = ridge_dir[f[2]][2]; if(base_v == 0){ if(DOT(old_dir, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } } else if(base_v == 1){ if(DOT(old_dir, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir1, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir1, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } } else{ if(DOT(old_dir, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir2, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir2, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } } } if(n1 > 1){ float p1[3], p2[3], p3[3]; worldcoor(tmp1[n1-2], p1); worldcoor(tmp1[n1-1], p2); worldcoor(tmp1[n1], p3); if((p1[0]-p2[0])*(p3[0]-p2[0]) + (p1[1]-p2[1])*(p3[1]-p2[1]) + (p1[2]-p2[2])*(p3[2]-p2[2]) > 0) break; } if(current.u >= 0 && current.u <= 1 && current.v >= 0 && current.v <= 1) n1++; else break; double max_in = (1.0-current.u-current.v)*k_max[face[current.id][0]] + current.u*k_max[face[current.id][1]] + current.v*k_max[face[current.id][2]]; double min_in = (1.0-current.u-current.v)*k_min[face[current.id][0]] + current.u*k_min[face[current.id][1]] + current.v*k_min[face[current.id][2]]; if(fabs(max_in) < fabs(min_in)) break; if(T > max_in) break; } //trace backward current = seed; f = face[current.id]; dir0[0] = -ridge_dir[f[0]][0]; dir0[1] = -ridge_dir[f[0]][1]; dir0[2] = -ridge_dir[f[0]][2]; dir1[0] = -ridge_dir[f[1]][0]; dir1[1] = -ridge_dir[f[1]][1]; dir1[2] = -ridge_dir[f[1]][2]; dir2[0] = -ridge_dir[f[2]][0]; dir2[1] = -ridge_dir[f[2]][1]; dir2[2] = -ridge_dir[f[2]][2]; l = 0; if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } while(l < 0.5*length && n2 < max){ double t1 = current.u; double t2 = current.v; double t0 = 1.0 - t1 - t2; double v[3]; v[0] = t0*dir0[0] + t1*dir1[0] + t2*dir2[0]; v[1] = t0*dir0[1] + t1*dir1[1] + t2*dir2[1]; v[2] = t0*dir0[2] + t1*dir1[2] + t2*dir2[2]; float* n = normal_f[current.id]; double dot = DOT(v, n); v[0] = v[0] - dot*n[0]; v[1] = v[1] - dot*n[1]; v[2] = v[2] - dot*n[2]; double len = LENGTH(v); if((float)len == 0) break; v[0] = v[0]*step/len; v[1] = v[1]*step/len; v[2] = v[2]*step/len; double du, dv; if(!barycentricVector(current.id, v, du, dv)) break; double next_u = current.u + du; double next_v = current.v + dv; tmp2[n2].id = current.id; //The next position is inside the same triangle. if(next_u + next_v <= 1.0 && next_u >= 0 && next_v >= 0){ tmp2[n2].u = next_u; tmp2[n2].v = next_v; l += step; current = tmp2[n2]; } //Outside the triangle. else{ double a = next_v - t2; double b = next_u - t1; double c = a*t1 - b*t2; double s0 = -c; double s1 = a*(1.0-t1) + b*t2; double s2 = -a*t1 - b*(1.0-t2); int result; if(s1*s2 > 0){ if(next_v > 0) result = 1; else result = 2; } else if(s2*s0 > 0){ if(next_v > 0) result = 3; else result = 2; } else if(s0*s1 > 0){ if(next_u > 0) result = 3; else result = 1; } else{ break; } int base_v; double old_dir[3]; if(result == 1){ next_u = 0; if(b == 0) break; next_v = -c/b; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][2]; old_dir[0] = dir2[0]; old_dir[1] = dir2[1]; old_dir[2] = dir2[2]; if(face[current.id][0] == f[2]){ current.u = 0; current.v = (1.0 - next_v); base_v = 0; } else if(face[current.id][1] == f[2]){ current.u = next_v; current.v = 0; base_v = 1; } else{ current.u = 1.0 - next_v; current.v = next_v; base_v = 2; } } else if(result == 2){ if(a == 0) break; next_u = c/a; next_v = 0; if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; current.id = face_link_E[current.id][0]; old_dir[0] = dir0[0]; old_dir[1] = dir0[1]; old_dir[2] = dir0[2]; if(face[current.id][0] == f[0]){ current.u = 0; current.v = next_u; base_v = 0; } else if(face[current.id][1] == f[0]){ current.u = 1.0 - next_u; current.v = 0; base_v = 1; } else{ current.u = next_u; current.v = 1.0 - next_u; base_v = 2; } } else{ if(a+b == 0) break; next_u = (b+c)/(a+b); next_v = (a-c)/(a+b); if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][1]; old_dir[0] = dir1[0]; old_dir[1] = dir1[1]; old_dir[2] = dir1[2]; if(face[current.id][0] == f[1]){ base_v = 0; current.u = 0; current.v = next_v; } else if(face[current.id][1] == f[1]){ base_v = 1; current.u = next_u; current.v = 0; } else{ base_v = 2; current.u = next_v; current.v = next_u; } } tmp2[n2].u = next_u; tmp2[n2].v = next_v; if(current.id < 0) break; float ud = (float)(next_u - t1); float vd = (float)(next_v - t2); float v1[3], v2[3], v12[3]; VEC(v1, vertex[f[0]], vertex[f[1]]); v1[0] *= ud; v1[1] *= ud; v1[2] *= ud; VEC(v2, vertex[f[2]], vertex[f[2]]); v2[0] *= vd; v2[1] *= vd; v2[2] *= vd; VEC(v12, v1, v2); l += (float)LENGTH(v12); f = face[current.id]; dir0[0] = ridge_dir[f[0]][0]; dir0[1] = ridge_dir[f[0]][1]; dir0[2] = ridge_dir[f[0]][2]; dir1[0] = ridge_dir[f[1]][0]; dir1[1] = ridge_dir[f[1]][1]; dir1[2] = ridge_dir[f[1]][2]; dir2[0] = ridge_dir[f[2]][0]; dir2[1] = ridge_dir[f[2]][1]; dir2[2] = ridge_dir[f[2]][2]; if(base_v == 0){ if(DOT(old_dir, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } } else if(base_v == 1){ if(DOT(old_dir, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir1, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir1, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } } else{ if(DOT(old_dir, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir2, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir2, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } } } if(n2 > 1){ float p1[3], p2[3], p3[3]; worldcoor(tmp2[n2-2], p1); worldcoor(tmp2[n2-1], p2); worldcoor(tmp2[n2], p3); if((p1[0]-p2[0])*(p3[0]-p2[0]) + (p1[1]-p2[1])*(p3[1]-p2[1]) + (p1[2]-p2[2])*(p3[2]-p2[2]) > 0) break; } if(current.u >= 0 && current.u <= 1 && current.v >= 0 && current.v <= 1) n2++; else break; double max_in = (1.0-current.u-current.v)*k_max[face[current.id][0]] + current.u*k_max[face[current.id][1]] + current.v*k_max[face[current.id][2]]; double min_in = (1.0-current.u-current.v)*k_min[face[current.id][0]] + current.u*k_min[face[current.id][1]] + current.v*k_min[face[current.id][2]]; if(fabs(max_in) < fabs(min_in)) break; if(T > max_in) break; } //concatnation point_N = n1+n2+1; line = new tri_point[n1+n2+1]; for(int i=0; i= 0 && next_v >= 0){ tmp1[n1].u = next_u; tmp1[n1].v = next_v; l += step; current = tmp1[n1]; } //Outside the triangle. else{ double a = next_v - t2; double b = next_u - t1; double c = a*t1 - b*t2; double s0 = -c; double s1 = a*(1.0-t1) + b*t2; double s2 = -a*t1 - b*(1.0-t2); int result; if(s1*s2 > 0){ if(next_v > 0) result = 1; else result = 2; } else if(s2*s0 > 0){ if(next_v > 0) result = 3; else result = 2; } else if(s0*s1 > 0){ if(next_u > 0) result = 3; else result = 1; } else{ break; } int base_v; double old_dir[3]; if(result == 1){ next_u = 0; if(b == 0) break; next_v = -c/b; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][2]; old_dir[0] = dir2[0]; old_dir[1] = dir2[1]; old_dir[2] = dir2[2]; if(face[current.id][0] == f[2]){ current.u = 0; current.v = (1.0 - next_v); base_v = 0; } else if(face[current.id][1] == f[2]){ current.u = next_v; current.v = 0; base_v = 1; } else{ current.u = 1.0 - next_v; current.v = next_v; base_v = 2; } } else if(result == 2){ if(a == 0) break; next_u = c/a; next_v = 0; if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; current.id = face_link_E[current.id][0]; old_dir[0] = dir0[0]; old_dir[1] = dir0[1]; old_dir[2] = dir0[2]; if(face[current.id][0] == f[0]){ current.u = 0; current.v = next_u; base_v = 0; } else if(face[current.id][1] == f[0]){ current.u = 1.0 - next_u; current.v = 0; base_v = 1; } else{ current.u = next_u; current.v = 1.0 - next_u; base_v = 2; } } else{ if(a+b == 0) break; next_u = (b+c)/(a+b); next_v = (a-c)/(a+b); if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][1]; old_dir[0] = dir1[0]; old_dir[1] = dir1[1]; old_dir[2] = dir1[2]; if(face[current.id][0] == f[1]){ base_v = 0; current.u = 0; current.v = next_v; } else if(face[current.id][1] == f[1]){ base_v = 1; current.u = next_u; current.v = 0; } else{ base_v = 2; current.u = next_v; current.v = next_u; } } tmp1[n1].u = next_u; tmp1[n1].v = next_v; if(current.id < 0) break; float ud = (float)(next_u - t1); float vd = (float)(next_v - t2); float v1[3], v2[3], v12[3]; VEC(v1, vertex[f[0]], vertex[f[1]]); v1[0] *= ud; v1[1] *= ud; v1[2] *= ud; VEC(v2, vertex[f[2]], vertex[f[2]]); v2[0] *= vd; v2[1] *= vd; v2[2] *= vd; VEC(v12, v1, v2); l += (float)LENGTH(v12); f = face[current.id]; dir0[0] = ravine_dir[f[0]][0]; dir0[1] = ravine_dir[f[0]][1]; dir0[2] = ravine_dir[f[0]][2]; dir1[0] = ravine_dir[f[1]][0]; dir1[1] = ravine_dir[f[1]][1]; dir1[2] = ravine_dir[f[1]][2]; dir2[0] = ravine_dir[f[2]][0]; dir2[1] = ravine_dir[f[2]][1]; dir2[2] = ravine_dir[f[2]][2]; if(base_v == 0){ if(DOT(old_dir, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } } else if(base_v == 1){ if(DOT(old_dir, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir1, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir1, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } } else{ if(DOT(old_dir, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir2, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir2, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } } } if(n1 > 1){ float p1[3], p2[3], p3[3]; worldcoor(tmp1[n1-2], p1); worldcoor(tmp1[n1-1], p2); worldcoor(tmp1[n1], p3); if((p1[0]-p2[0])*(p3[0]-p2[0]) + (p1[1]-p2[1])*(p3[1]-p2[1]) + (p1[2]-p2[2])*(p3[2]-p2[2]) > 0) break; } if(current.u >= 0 && current.u <= 1 && current.v >= 0 && current.v <= 1) n1++; else break; double max_in = (1.0-current.u-current.v)*k_max[face[current.id][0]] + current.u*k_max[face[current.id][1]] + current.v*k_max[face[current.id][2]]; double min_in = (1.0-current.u-current.v)*k_min[face[current.id][0]] + current.u*k_min[face[current.id][1]] + current.v*k_min[face[current.id][2]]; if(fabs(max_in) > fabs(min_in)) break; if(T < min_in) break; } //trace backward current = seed; f = face[current.id]; dir0[0] = -ravine_dir[f[0]][0]; dir0[1] = -ravine_dir[f[0]][1]; dir0[2] = -ravine_dir[f[0]][2]; dir1[0] = -ravine_dir[f[1]][0]; dir1[1] = -ravine_dir[f[1]][1]; dir1[2] = -ravine_dir[f[1]][2]; dir2[0] = -ravine_dir[f[2]][0]; dir2[1] = -ravine_dir[f[2]][1]; dir2[2] = -ravine_dir[f[2]][2]; l = 0; if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } while(l < 0.5*length && n2 < max){ double t1 = current.u; double t2 = current.v; double t0 = 1.0 - t1 - t2; double v[3]; v[0] = t0*dir0[0] + t1*dir1[0] + t2*dir2[0]; v[1] = t0*dir0[1] + t1*dir1[1] + t2*dir2[1]; v[2] = t0*dir0[2] + t1*dir1[2] + t2*dir2[2]; float* n = normal_f[current.id]; double dot = DOT(v, n); v[0] = v[0] - dot*n[0]; v[1] = v[1] - dot*n[1]; v[2] = v[2] - dot*n[2]; double len = LENGTH(v); if((float)len == 0) break; v[0] = v[0]*step/len; v[1] = v[1]*step/len; v[2] = v[2]*step/len; double du, dv; if(!barycentricVector(current.id, v, du, dv)) break; double next_u = current.u + du; double next_v = current.v + dv; tmp2[n2].id = current.id; //The next position is inside the same triangle. if(next_u + next_v <= 1.0 && next_u >= 0 && next_v >= 0){ tmp2[n2].u = next_u; tmp2[n2].v = next_v; l += step; current = tmp2[n2]; } //Outside the triangle. else{ double a = next_v - t2; double b = next_u - t1; double c = a*t1 - b*t2; double s0 = -c; double s1 = a*(1.0-t1) + b*t2; double s2 = -a*t1 - b*(1.0-t2); int result; if(s1*s2 > 0){ if(next_v > 0) result = 1; else result = 2; } else if(s2*s0 > 0){ if(next_v > 0) result = 3; else result = 2; } else if(s0*s1 > 0){ if(next_u > 0) result = 3; else result = 1; } else{ break; } int base_v; double old_dir[3]; if(result == 1){ next_u = 0; if(b == 0) break; next_v = -c/b; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][2]; old_dir[0] = dir2[0]; old_dir[1] = dir2[1]; old_dir[2] = dir2[2]; if(face[current.id][0] == f[2]){ current.u = 0; current.v = (1.0 - next_v); base_v = 0; } else if(face[current.id][1] == f[2]){ current.u = next_v; current.v = 0; base_v = 1; } else{ current.u = 1.0 - next_v; current.v = next_v; base_v = 2; } } else if(result == 2){ if(a == 0) break; next_u = c/a; next_v = 0; if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; current.id = face_link_E[current.id][0]; old_dir[0] = dir0[0]; old_dir[1] = dir0[1]; old_dir[2] = dir0[2]; if(face[current.id][0] == f[0]){ current.u = 0; current.v = next_u; base_v = 0; } else if(face[current.id][1] == f[0]){ current.u = 1.0 - next_u; current.v = 0; base_v = 1; } else{ current.u = next_u; current.v = 1.0 - next_u; base_v = 2; } } else{ if(a+b == 0) break; next_u = (b+c)/(a+b); next_v = (a-c)/(a+b); if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][1]; old_dir[0] = dir1[0]; old_dir[1] = dir1[1]; old_dir[2] = dir1[2]; if(face[current.id][0] == f[1]){ base_v = 0; current.u = 0; current.v = next_v; } else if(face[current.id][1] == f[1]){ base_v = 1; current.u = next_u; current.v = 0; } else{ base_v = 2; current.u = next_v; current.v = next_u; } } tmp2[n2].u = next_u; tmp2[n2].v = next_v; if(current.id < 0) break; float ud = (float)(next_u - t1); float vd = (float)(next_v - t2); float v1[3], v2[3], v12[3]; VEC(v1, vertex[f[0]], vertex[f[1]]); v1[0] *= ud; v1[1] *= ud; v1[2] *= ud; VEC(v2, vertex[f[2]], vertex[f[2]]); v2[0] *= vd; v2[1] *= vd; v2[2] *= vd; VEC(v12, v1, v2); l += (float)LENGTH(v12); f = face[current.id]; dir0[0] = ravine_dir[f[0]][0]; dir0[1] = ravine_dir[f[0]][1]; dir0[2] = ravine_dir[f[0]][2]; dir1[0] = ravine_dir[f[1]][0]; dir1[1] = ravine_dir[f[1]][1]; dir1[2] = ravine_dir[f[1]][2]; dir2[0] = ravine_dir[f[2]][0]; dir2[1] = ravine_dir[f[2]][1]; dir2[2] = ravine_dir[f[2]][2]; if(base_v == 0){ if(DOT(old_dir, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } } else if(base_v == 1){ if(DOT(old_dir, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir1, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir1, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } } else{ if(DOT(old_dir, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir2, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir2, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } } } if(n2 > 1){ float p1[3], p2[3], p3[3]; worldcoor(tmp2[n2-2], p1); worldcoor(tmp2[n2-1], p2); worldcoor(tmp2[n2], p3); if((p1[0]-p2[0])*(p3[0]-p2[0]) + (p1[1]-p2[1])*(p3[1]-p2[1]) + (p1[2]-p2[2])*(p3[2]-p2[2]) > 0) break; } if(current.u >= 0 && current.u <= 1 && current.v >= 0 && current.v <= 1) n2++; else break; double max_in = (1.0-current.u-current.v)*k_max[face[current.id][0]] + current.u*k_max[face[current.id][1]] + current.v*k_max[face[current.id][2]]; double min_in = (1.0-current.u-current.v)*k_min[face[current.id][0]] + current.u*k_min[face[current.id][1]] + current.v*k_min[face[current.id][2]]; if(fabs(max_in) > fabs(min_in)) break; if(T < min_in) break; } //concatnation point_N = n1+n2+1; line = new tri_point[n1+n2+1]; for(int i=0; i 0){ wk_max += w; k_max_tmp += w*k; } else if(k < 0){ wk_min += w; k_min_tmp += w*k; } } if(wk_max != 0) k_max_tmp /= wk_max; if(wk_min != 0) k_min_tmp /= wk_min; k_max[i] = k_max_tmp; k_min[i] = k_min_tmp; } } void MeshData::traceTmax(tri_point seed, float length, tri_point *&line, int &point_N, float step) { int max = 200; int n1 = 0; int n2 = 0; tri_point *tmp1 = new tri_point[max]; tri_point *tmp2 = new tri_point[max]; tri_point current; int *f; double dir0[3], dir1[3], dir2[3]; //trace forward current = seed; f = face[current.id]; dir0[0] = t_max[f[0]][0]; dir0[1] = t_max[f[0]][1]; dir0[2] = t_max[f[0]][2]; dir1[0] = t_max[f[1]][0]; dir1[1] = t_max[f[1]][1]; dir1[2] = t_max[f[1]][2]; dir2[0] = t_max[f[2]][0]; dir2[1] = t_max[f[2]][1]; dir2[2] = t_max[f[2]][2]; double l = 0; if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } while(l < 0.5*length && n1 < max){ double t1 = current.u; double t2 = current.v; double t0 = 1.0 - t1 - t2; double v[3]; v[0] = t0*dir0[0] + t1*dir1[0] + t2*dir2[0]; v[1] = t0*dir0[1] + t1*dir1[1] + t2*dir2[1]; v[2] = t0*dir0[2] + t1*dir1[2] + t2*dir2[2]; float* n = normal_f[current.id]; double dot = DOT(v, n); v[0] = v[0] - dot*n[0]; v[1] = v[1] - dot*n[1]; v[2] = v[2] - dot*n[2]; double len = LENGTH(v); if((float)len == 0) break; v[0] = v[0]*step/len; v[1] = v[1]*step/len; v[2] = v[2]*step/len; double du, dv; if(!barycentricVector(current.id, v, du, dv)) break; double next_u = current.u + du; double next_v = current.v + dv; tmp1[n1].id = current.id; //The next position is inside the same triangle. if(next_u + next_v <= 1.0 && next_u >= 0 && next_v >= 0){ tmp1[n1].u = next_u; tmp1[n1].v = next_v; l += step; current = tmp1[n1]; } //Outside the triangle. else{ double a = next_v - t2; double b = next_u - t1; double c = a*t1 - b*t2; double s0 = -c; double s1 = a*(1.0-t1) + b*t2; double s2 = -a*t1 - b*(1.0-t2); int result; if(s1*s2 > 0){ if(next_v > 0) result = 1; else result = 2; } else if(s2*s0 > 0){ if(next_v > 0) result = 3; else result = 2; } else if(s0*s1 > 0){ if(next_u > 0) result = 3; else result = 1; } else{ break; } int base_v; double old_dir[3]; if(result == 1){ next_u = 0; if(b == 0) break; next_v = -c/b; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][2]; old_dir[0] = dir2[0]; old_dir[1] = dir2[1]; old_dir[2] = dir2[2]; if(face[current.id][0] == f[2]){ current.u = 0; current.v = (1.0 - next_v); base_v = 0; } else if(face[current.id][1] == f[2]){ current.u = next_v; current.v = 0; base_v = 1; } else{ current.u = 1.0 - next_v; current.v = next_v; base_v = 2; } } else if(result == 2){ if(a == 0) break; next_u = c/a; next_v = 0; if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; current.id = face_link_E[current.id][0]; old_dir[0] = dir0[0]; old_dir[1] = dir0[1]; old_dir[2] = dir0[2]; if(face[current.id][0] == f[0]){ current.u = 0; current.v = next_u; base_v = 0; } else if(face[current.id][1] == f[0]){ current.u = 1.0 - next_u; current.v = 0; base_v = 1; } else{ current.u = next_u; current.v = 1.0 - next_u; base_v = 2; } } else{ if(a+b == 0) break; next_u = (b+c)/(a+b); next_v = (a-c)/(a+b); if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][1]; old_dir[0] = dir1[0]; old_dir[1] = dir1[1]; old_dir[2] = dir1[2]; if(face[current.id][0] == f[1]){ base_v = 0; current.u = 0; current.v = next_v; } else if(face[current.id][1] == f[1]){ base_v = 1; current.u = next_u; current.v = 0; } else{ base_v = 2; current.u = next_v; current.v = next_u; } } tmp1[n1].u = next_u; tmp1[n1].v = next_v; if(current.id < 0) break; float ud = (float)(next_u - t1); float vd = (float)(next_v - t2); float v1[3], v2[3], v12[3]; VEC(v1, vertex[f[0]], vertex[f[1]]); v1[0] *= ud; v1[1] *= ud; v1[2] *= ud; VEC(v2, vertex[f[2]], vertex[f[2]]); v2[0] *= vd; v2[1] *= vd; v2[2] *= vd; VEC(v12, v1, v2); l += (float)LENGTH(v12); f = face[current.id]; dir0[0] = t_max[f[0]][0]; dir0[1] = t_max[f[0]][1]; dir0[2] = t_max[f[0]][2]; dir1[0] = t_max[f[1]][0]; dir1[1] = t_max[f[1]][1]; dir1[2] = t_max[f[1]][2]; dir2[0] = t_max[f[2]][0]; dir2[1] = t_max[f[2]][1]; dir2[2] = t_max[f[2]][2]; if(base_v == 0){ if(DOT(old_dir, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } } else if(base_v == 1){ if(DOT(old_dir, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir1, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir1, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } } else{ if(DOT(old_dir, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir2, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir2, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } } } if(n1 > 1){ float p1[3], p2[3], p3[3]; worldcoor(tmp1[n1-2], p1); worldcoor(tmp1[n1-1], p2); worldcoor(tmp1[n1], p3); if((p1[0]-p2[0])*(p3[0]-p2[0]) + (p1[1]-p2[1])*(p3[1]-p2[1]) + (p1[2]-p2[2])*(p3[2]-p2[2]) > 0) break; } if(current.u >= 0 && current.u <= 1 && current.v >= 0 && current.v <= 1) n1++; else break; } //trace backward current = seed; f = face[current.id]; dir0[0] = -t_max[f[0]][0]; dir0[1] = -t_max[f[0]][1]; dir0[2] = -t_max[f[0]][2]; dir1[0] = -t_max[f[1]][0]; dir1[1] = -t_max[f[1]][1]; dir1[2] = -t_max[f[1]][2]; dir2[0] = -t_max[f[2]][0]; dir2[1] = -t_max[f[2]][1]; dir2[2] = -t_max[f[2]][2]; l = 0; if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } while(l < 0.5*length && n2 < max){ double t1 = current.u; double t2 = current.v; double t0 = 1.0 - t1 - t2; double v[3]; v[0] = t0*dir0[0] + t1*dir1[0] + t2*dir2[0]; v[1] = t0*dir0[1] + t1*dir1[1] + t2*dir2[1]; v[2] = t0*dir0[2] + t1*dir1[2] + t2*dir2[2]; float* n = normal_f[current.id]; double dot = DOT(v, n); v[0] = v[0] - dot*n[0]; v[1] = v[1] - dot*n[1]; v[2] = v[2] - dot*n[2]; double len = LENGTH(v); if((float)len == 0) break; v[0] = v[0]*step/len; v[1] = v[1]*step/len; v[2] = v[2]*step/len; double du, dv; if(!barycentricVector(current.id, v, du, dv)) break; double next_u = current.u + du; double next_v = current.v + dv; tmp2[n2].id = current.id; //The next position is inside the same triangle. if(next_u + next_v <= 1.0 && next_u >= 0 && next_v >= 0){ tmp2[n2].u = next_u; tmp2[n2].v = next_v; l += step; current = tmp2[n2]; } //Outside the triangle. else{ double a = next_v - t2; double b = next_u - t1; double c = a*t1 - b*t2; double s0 = -c; double s1 = a*(1.0-t1) + b*t2; double s2 = -a*t1 - b*(1.0-t2); int result; if(s1*s2 > 0){ if(next_v > 0) result = 1; else result = 2; } else if(s2*s0 > 0){ if(next_v > 0) result = 3; else result = 2; } else if(s0*s1 > 0){ if(next_u > 0) result = 3; else result = 1; } else{ break; } int base_v; double old_dir[3]; if(result == 1){ next_u = 0; if(b == 0) break; next_v = -c/b; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][2]; old_dir[0] = dir2[0]; old_dir[1] = dir2[1]; old_dir[2] = dir2[2]; if(face[current.id][0] == f[2]){ current.u = 0; current.v = (1.0 - next_v); base_v = 0; } else if(face[current.id][1] == f[2]){ current.u = next_v; current.v = 0; base_v = 1; } else{ current.u = 1.0 - next_v; current.v = next_v; base_v = 2; } } else if(result == 2){ if(a == 0) break; next_u = c/a; next_v = 0; if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; current.id = face_link_E[current.id][0]; old_dir[0] = dir0[0]; old_dir[1] = dir0[1]; old_dir[2] = dir0[2]; if(face[current.id][0] == f[0]){ current.u = 0; current.v = next_u; base_v = 0; } else if(face[current.id][1] == f[0]){ current.u = 1.0 - next_u; current.v = 0; base_v = 1; } else{ current.u = next_u; current.v = 1.0 - next_u; base_v = 2; } } else{ if(a+b == 0) break; next_u = (b+c)/(a+b); next_v = (a-c)/(a+b); if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][1]; old_dir[0] = dir1[0]; old_dir[1] = dir1[1]; old_dir[2] = dir1[2]; if(face[current.id][0] == f[1]){ base_v = 0; current.u = 0; current.v = next_v; } else if(face[current.id][1] == f[1]){ base_v = 1; current.u = next_u; current.v = 0; } else{ base_v = 2; current.u = next_v; current.v = next_u; } } tmp2[n2].u = next_u; tmp2[n2].v = next_v; if(current.id < 0) break; float ud = (float)(next_u - t1); float vd = (float)(next_v - t2); float v1[3], v2[3], v12[3]; VEC(v1, vertex[f[0]], vertex[f[1]]); v1[0] *= ud; v1[1] *= ud; v1[2] *= ud; VEC(v2, vertex[f[2]], vertex[f[2]]); v2[0] *= vd; v2[1] *= vd; v2[2] *= vd; VEC(v12, v1, v2); l += (float)LENGTH(v12); f = face[current.id]; dir0[0] = t_max[f[0]][0]; dir0[1] = t_max[f[0]][1]; dir0[2] = t_max[f[0]][2]; dir1[0] = t_max[f[1]][0]; dir1[1] = t_max[f[1]][1]; dir1[2] = t_max[f[1]][2]; dir2[0] = t_max[f[2]][0]; dir2[1] = t_max[f[2]][1]; dir2[2] = t_max[f[2]][2]; if(base_v == 0){ if(DOT(old_dir, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } } else if(base_v == 1){ if(DOT(old_dir, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir1, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir1, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } } else{ if(DOT(old_dir, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir2, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir2, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } } } if(n2 > 1){ float p1[3], p2[3], p3[3]; worldcoor(tmp2[n2-2], p1); worldcoor(tmp2[n2-1], p2); worldcoor(tmp2[n2], p3); if((p1[0]-p2[0])*(p3[0]-p2[0]) + (p1[1]-p2[1])*(p3[1]-p2[1]) + (p1[2]-p2[2])*(p3[2]-p2[2]) > 0) break; } if(current.u >= 0 && current.u <= 1 && current.v >= 0 && current.v <= 1) n2++; else break; } //concatnation point_N = n1+n2+1; line = new tri_point[n1+n2+1]; for(int i=0; i= 0 && next_v >= 0){ tmp1[n1].u = next_u; tmp1[n1].v = next_v; l += step; current = tmp1[n1]; } //Outside the triangle. else{ double a = next_v - t2; double b = next_u - t1; double c = a*t1 - b*t2; double s0 = -c; double s1 = a*(1.0-t1) + b*t2; double s2 = -a*t1 - b*(1.0-t2); int result; if(s1*s2 > 0){ if(next_v > 0) result = 1; else result = 2; } else if(s2*s0 > 0){ if(next_v > 0) result = 3; else result = 2; } else if(s0*s1 > 0){ if(next_u > 0) result = 3; else result = 1; } else{ break; } int base_v; double old_dir[3]; if(result == 1){ next_u = 0; if(b == 0) break; next_v = -c/b; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][2]; old_dir[0] = dir2[0]; old_dir[1] = dir2[1]; old_dir[2] = dir2[2]; if(face[current.id][0] == f[2]){ current.u = 0; current.v = (1.0 - next_v); base_v = 0; } else if(face[current.id][1] == f[2]){ current.u = next_v; current.v = 0; base_v = 1; } else{ current.u = 1.0 - next_v; current.v = next_v; base_v = 2; } } else if(result == 2){ if(a == 0) break; next_u = c/a; next_v = 0; if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; current.id = face_link_E[current.id][0]; old_dir[0] = dir0[0]; old_dir[1] = dir0[1]; old_dir[2] = dir0[2]; if(face[current.id][0] == f[0]){ current.u = 0; current.v = next_u; base_v = 0; } else if(face[current.id][1] == f[0]){ current.u = 1.0 - next_u; current.v = 0; base_v = 1; } else{ current.u = next_u; current.v = 1.0 - next_u; base_v = 2; } } else{ if(a+b == 0) break; next_u = (b+c)/(a+b); next_v = (a-c)/(a+b); if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][1]; old_dir[0] = dir1[0]; old_dir[1] = dir1[1]; old_dir[2] = dir1[2]; if(face[current.id][0] == f[1]){ base_v = 0; current.u = 0; current.v = next_v; } else if(face[current.id][1] == f[1]){ base_v = 1; current.u = next_u; current.v = 0; } else{ base_v = 2; current.u = next_v; current.v = next_u; } } tmp1[n1].u = next_u; tmp1[n1].v = next_v; if(current.id < 0) break; float ud = (float)(next_u - t1); float vd = (float)(next_v - t2); float v1[3], v2[3], v12[3]; VEC(v1, vertex[f[0]], vertex[f[1]]); v1[0] *= ud; v1[1] *= ud; v1[2] *= ud; VEC(v2, vertex[f[2]], vertex[f[2]]); v2[0] *= vd; v2[1] *= vd; v2[2] *= vd; VEC(v12, v1, v2); l += (float)LENGTH(v12); f = face[current.id]; dir0[0] = t_max[f[0]][0]; dir0[1] = t_max[f[0]][1]; dir0[2] = t_max[f[0]][2]; dir1[0] = t_max[f[1]][0]; dir1[1] = t_max[f[1]][1]; dir1[2] = t_max[f[1]][2]; dir2[0] = t_max[f[2]][0]; dir2[1] = t_max[f[2]][1]; dir2[2] = t_max[f[2]][2]; if(base_v == 0){ if(DOT(old_dir, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } } else if(base_v == 1){ if(DOT(old_dir, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir1, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir1, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } } else{ if(DOT(old_dir, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir2, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir2, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } } double v[3]; paralellTrans(v, dir1, f[1], f[0]); if(DOT(dir0, v) < T) break; paralellTrans(v, dir2, f[2], f[1]); if(DOT(dir1, v) < T) break; paralellTrans(v, dir0, f[0], f[2]); if(DOT(dir2, v) < T) break; } if(n1 > 1){ float p1[3], p2[3], p3[3]; worldcoor(tmp1[n1-2], p1); worldcoor(tmp1[n1-1], p2); worldcoor(tmp1[n1], p3); if((p1[0]-p2[0])*(p3[0]-p2[0]) + (p1[1]-p2[1])*(p3[1]-p2[1]) + (p1[2]-p2[2])*(p3[2]-p2[2]) > 0) break; } if(current.u >= 0 && current.u <= 1 && current.v >= 0 && current.v <= 1) n1++; else break; } //trace backward current = seed; f = face[current.id]; dir0[0] = -t_max[f[0]][0]; dir0[1] = -t_max[f[0]][1]; dir0[2] = -t_max[f[0]][2]; dir1[0] = -t_max[f[1]][0]; dir1[1] = -t_max[f[1]][1]; dir1[2] = -t_max[f[1]][2]; dir2[0] = -t_max[f[2]][0]; dir2[1] = -t_max[f[2]][1]; dir2[2] = -t_max[f[2]][2]; l = 0; if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } while(l < 0.5*length && n2 < max){ double t1 = current.u; double t2 = current.v; double t0 = 1.0 - t1 - t2; double v[3]; v[0] = t0*dir0[0] + t1*dir1[0] + t2*dir2[0]; v[1] = t0*dir0[1] + t1*dir1[1] + t2*dir2[1]; v[2] = t0*dir0[2] + t1*dir1[2] + t2*dir2[2]; float* n = normal_f[current.id]; double dot = DOT(v, n); v[0] = v[0] - dot*n[0]; v[1] = v[1] - dot*n[1]; v[2] = v[2] - dot*n[2]; double len = LENGTH(v); if((float)len == 0) break; v[0] = v[0]*step/len; v[1] = v[1]*step/len; v[2] = v[2]*step/len; double du, dv; if(!barycentricVector(current.id, v, du, dv)) break; double next_u = current.u + du; double next_v = current.v + dv; tmp2[n2].id = current.id; //The next position is inside the same triangle. if(next_u + next_v <= 1.0 && next_u >= 0 && next_v >= 0){ tmp2[n2].u = next_u; tmp2[n2].v = next_v; l += step; current = tmp2[n2]; } //Outside the triangle. else{ double a = next_v - t2; double b = next_u - t1; double c = a*t1 - b*t2; double s0 = -c; double s1 = a*(1.0-t1) + b*t2; double s2 = -a*t1 - b*(1.0-t2); int result; if(s1*s2 > 0){ if(next_v > 0) result = 1; else result = 2; } else if(s2*s0 > 0){ if(next_v > 0) result = 3; else result = 2; } else if(s0*s1 > 0){ if(next_u > 0) result = 3; else result = 1; } else{ break; } int base_v; double old_dir[3]; if(result == 1){ next_u = 0; if(b == 0) break; next_v = -c/b; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][2]; old_dir[0] = dir2[0]; old_dir[1] = dir2[1]; old_dir[2] = dir2[2]; if(face[current.id][0] == f[2]){ current.u = 0; current.v = (1.0 - next_v); base_v = 0; } else if(face[current.id][1] == f[2]){ current.u = next_v; current.v = 0; base_v = 1; } else{ current.u = 1.0 - next_v; current.v = next_v; base_v = 2; } } else if(result == 2){ if(a == 0) break; next_u = c/a; next_v = 0; if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; current.id = face_link_E[current.id][0]; old_dir[0] = dir0[0]; old_dir[1] = dir0[1]; old_dir[2] = dir0[2]; if(face[current.id][0] == f[0]){ current.u = 0; current.v = next_u; base_v = 0; } else if(face[current.id][1] == f[0]){ current.u = 1.0 - next_u; current.v = 0; base_v = 1; } else{ current.u = next_u; current.v = 1.0 - next_u; base_v = 2; } } else{ if(a+b == 0) break; next_u = (b+c)/(a+b); next_v = (a-c)/(a+b); if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][1]; old_dir[0] = dir1[0]; old_dir[1] = dir1[1]; old_dir[2] = dir1[2]; if(face[current.id][0] == f[1]){ base_v = 0; current.u = 0; current.v = next_v; } else if(face[current.id][1] == f[1]){ base_v = 1; current.u = next_u; current.v = 0; } else{ base_v = 2; current.u = next_v; current.v = next_u; } } tmp2[n2].u = next_u; tmp2[n2].v = next_v; if(current.id < 0) break; float ud = (float)(next_u - t1); float vd = (float)(next_v - t2); float v1[3], v2[3], v12[3]; VEC(v1, vertex[f[0]], vertex[f[1]]); v1[0] *= ud; v1[1] *= ud; v1[2] *= ud; VEC(v2, vertex[f[2]], vertex[f[2]]); v2[0] *= vd; v2[1] *= vd; v2[2] *= vd; VEC(v12, v1, v2); l += (float)LENGTH(v12); f = face[current.id]; dir0[0] = t_max[f[0]][0]; dir0[1] = t_max[f[0]][1]; dir0[2] = t_max[f[0]][2]; dir1[0] = t_max[f[1]][0]; dir1[1] = t_max[f[1]][1]; dir1[2] = t_max[f[1]][2]; dir2[0] = t_max[f[2]][0]; dir2[1] = t_max[f[2]][1]; dir2[2] = t_max[f[2]][2]; if(base_v == 0){ if(DOT(old_dir, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } } else if(base_v == 1){ if(DOT(old_dir, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir1, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir1, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } } else{ if(DOT(old_dir, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir2, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir2, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } } double v[3]; paralellTrans(v, dir1, f[1], f[0]); if(DOT(dir0, v) < T) break; paralellTrans(v, dir2, f[2], f[1]); if(DOT(dir1, v) < T) break; paralellTrans(v, dir0, f[0], f[2]); if(DOT(dir2, v) < T) break; } if(n2 > 1){ float p1[3], p2[3], p3[3]; worldcoor(tmp2[n2-2], p1); worldcoor(tmp2[n2-1], p2); worldcoor(tmp2[n2], p3); if((p1[0]-p2[0])*(p3[0]-p2[0]) + (p1[1]-p2[1])*(p3[1]-p2[1]) + (p1[2]-p2[2])*(p3[2]-p2[2]) > 0) break; } if(current.u >= 0 && current.u <= 1 && current.v >= 0 && current.v <= 1) n2++; else break; } //concatnation point_N = n1+n2+1; line = new tri_point[n1+n2+1]; for(int i=0; i= 0 && next_v >= 0){ tmp1[n1].u = next_u; tmp1[n1].v = next_v; l += step; current = tmp1[n1]; } //Outside the triangle. else{ double a = next_v - t2; double b = next_u - t1; double c = a*t1 - b*t2; double s0 = -c; double s1 = a*(1.0-t1) + b*t2; double s2 = -a*t1 - b*(1.0-t2); int result; if(s1*s2 > 0){ if(next_v > 0) result = 1; else result = 2; } else if(s2*s0 > 0){ if(next_v > 0) result = 3; else result = 2; } else if(s0*s1 > 0){ if(next_u > 0) result = 3; else result = 1; } else{ break; } int base_v; double old_dir[3]; if(result == 1){ next_u = 0; if(b == 0) break; next_v = -c/b; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][2]; old_dir[0] = dir2[0]; old_dir[1] = dir2[1]; old_dir[2] = dir2[2]; if(face[current.id][0] == f[2]){ current.u = 0; current.v = (1.0 - next_v); base_v = 0; } else if(face[current.id][1] == f[2]){ current.u = next_v; current.v = 0; base_v = 1; } else{ current.u = 1.0 - next_v; current.v = next_v; base_v = 2; } } else if(result == 2){ if(a == 0) break; next_u = c/a; next_v = 0; if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; current.id = face_link_E[current.id][0]; old_dir[0] = dir0[0]; old_dir[1] = dir0[1]; old_dir[2] = dir0[2]; if(face[current.id][0] == f[0]){ current.u = 0; current.v = next_u; base_v = 0; } else if(face[current.id][1] == f[0]){ current.u = 1.0 - next_u; current.v = 0; base_v = 1; } else{ current.u = next_u; current.v = 1.0 - next_u; base_v = 2; } } else{ if(a+b == 0) break; next_u = (b+c)/(a+b); next_v = (a-c)/(a+b); if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][1]; old_dir[0] = dir1[0]; old_dir[1] = dir1[1]; old_dir[2] = dir1[2]; if(face[current.id][0] == f[1]){ base_v = 0; current.u = 0; current.v = next_v; } else if(face[current.id][1] == f[1]){ base_v = 1; current.u = next_u; current.v = 0; } else{ base_v = 2; current.u = next_v; current.v = next_u; } } tmp1[n1].u = next_u; tmp1[n1].v = next_v; if(current.id < 0) break; float ud = (float)(next_u - t1); float vd = (float)(next_v - t2); float v1[3], v2[3], v12[3]; VEC(v1, vertex[f[0]], vertex[f[1]]); v1[0] *= ud; v1[1] *= ud; v1[2] *= ud; VEC(v2, vertex[f[2]], vertex[f[2]]); v2[0] *= vd; v2[1] *= vd; v2[2] *= vd; VEC(v12, v1, v2); l += (float)LENGTH(v12); f = face[current.id]; dir0[0] = t_min[f[0]][0]; dir0[1] = t_min[f[0]][1]; dir0[2] = t_min[f[0]][2]; dir1[0] = t_min[f[1]][0]; dir1[1] = t_min[f[1]][1]; dir1[2] = t_min[f[1]][2]; dir2[0] = t_min[f[2]][0]; dir2[1] = t_min[f[2]][1]; dir2[2] = t_min[f[2]][2]; if(base_v == 0){ if(DOT(old_dir, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } } else if(base_v == 1){ if(DOT(old_dir, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir1, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir1, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } } else{ if(DOT(old_dir, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir2, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir2, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } } } if(n1 > 1){ float p1[3], p2[3], p3[3]; worldcoor(tmp1[n1-2], p1); worldcoor(tmp1[n1-1], p2); worldcoor(tmp1[n1], p3); if((p1[0]-p2[0])*(p3[0]-p2[0]) + (p1[1]-p2[1])*(p3[1]-p2[1]) + (p1[2]-p2[2])*(p3[2]-p2[2]) > 0) break; } if(current.u >= 0 && current.u <= 1 && current.v >= 0 && current.v <= 1) n1++; else break; } //trace backward current = seed; f = face[current.id]; dir0[0] = -t_min[f[0]][0]; dir0[1] = -t_min[f[0]][1]; dir0[2] = -t_min[f[0]][2]; dir1[0] = -t_min[f[1]][0]; dir1[1] = -t_min[f[1]][1]; dir1[2] = -t_min[f[1]][2]; dir2[0] = -t_min[f[2]][0]; dir2[1] = -t_min[f[2]][1]; dir2[2] = -t_min[f[2]][2]; l = 0; if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } while(l < 0.5*length && n2 < max){ double t1 = current.u; double t2 = current.v; double t0 = 1.0 - t1 - t2; double v[3]; v[0] = t0*dir0[0] + t1*dir1[0] + t2*dir2[0]; v[1] = t0*dir0[1] + t1*dir1[1] + t2*dir2[1]; v[2] = t0*dir0[2] + t1*dir1[2] + t2*dir2[2]; float* n = normal_f[current.id]; double dot = DOT(v, n); v[0] = v[0] - dot*n[0]; v[1] = v[1] - dot*n[1]; v[2] = v[2] - dot*n[2]; double len = LENGTH(v); if((float)len == 0) break; v[0] = v[0]*step/len; v[1] = v[1]*step/len; v[2] = v[2]*step/len; double du, dv; if(!barycentricVector(current.id, v, du, dv)) break; double next_u = current.u + du; double next_v = current.v + dv; tmp2[n2].id = current.id; //The next position is inside the same triangle. if(next_u + next_v <= 1.0 && next_u >= 0 && next_v >= 0){ tmp2[n2].u = next_u; tmp2[n2].v = next_v; l += step; current = tmp2[n2]; } //Outside the triangle. else{ double a = next_v - t2; double b = next_u - t1; double c = a*t1 - b*t2; double s0 = -c; double s1 = a*(1.0-t1) + b*t2; double s2 = -a*t1 - b*(1.0-t2); int result; if(s1*s2 > 0){ if(next_v > 0) result = 1; else result = 2; } else if(s2*s0 > 0){ if(next_v > 0) result = 3; else result = 2; } else if(s0*s1 > 0){ if(next_u > 0) result = 3; else result = 1; } else{ break; } int base_v; double old_dir[3]; if(result == 1){ next_u = 0; if(b == 0) break; next_v = -c/b; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][2]; old_dir[0] = dir2[0]; old_dir[1] = dir2[1]; old_dir[2] = dir2[2]; if(face[current.id][0] == f[2]){ current.u = 0; current.v = (1.0 - next_v); base_v = 0; } else if(face[current.id][1] == f[2]){ current.u = next_v; current.v = 0; base_v = 1; } else{ current.u = 1.0 - next_v; current.v = next_v; base_v = 2; } } else if(result == 2){ if(a == 0) break; next_u = c/a; next_v = 0; if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; current.id = face_link_E[current.id][0]; old_dir[0] = dir0[0]; old_dir[1] = dir0[1]; old_dir[2] = dir0[2]; if(face[current.id][0] == f[0]){ current.u = 0; current.v = next_u; base_v = 0; } else if(face[current.id][1] == f[0]){ current.u = 1.0 - next_u; current.v = 0; base_v = 1; } else{ current.u = next_u; current.v = 1.0 - next_u; base_v = 2; } } else{ if(a+b == 0) break; next_u = (b+c)/(a+b); next_v = (a-c)/(a+b); if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][1]; old_dir[0] = dir1[0]; old_dir[1] = dir1[1]; old_dir[2] = dir1[2]; if(face[current.id][0] == f[1]){ base_v = 0; current.u = 0; current.v = next_v; } else if(face[current.id][1] == f[1]){ base_v = 1; current.u = next_u; current.v = 0; } else{ base_v = 2; current.u = next_v; current.v = next_u; } } tmp2[n2].u = next_u; tmp2[n2].v = next_v; if(current.id < 0) break; float ud = (float)(next_u - t1); float vd = (float)(next_v - t2); float v1[3], v2[3], v12[3]; VEC(v1, vertex[f[0]], vertex[f[1]]); v1[0] *= ud; v1[1] *= ud; v1[2] *= ud; VEC(v2, vertex[f[2]], vertex[f[2]]); v2[0] *= vd; v2[1] *= vd; v2[2] *= vd; VEC(v12, v1, v2); l += (float)LENGTH(v12); f = face[current.id]; dir0[0] = t_min[f[0]][0]; dir0[1] = t_min[f[0]][1]; dir0[2] = t_min[f[0]][2]; dir1[0] = t_min[f[1]][0]; dir1[1] = t_min[f[1]][1]; dir1[2] = t_min[f[1]][2]; dir2[0] = t_min[f[2]][0]; dir2[1] = t_min[f[2]][1]; dir2[2] = t_min[f[2]][2]; if(base_v == 0){ if(DOT(old_dir, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } } else if(base_v == 1){ if(DOT(old_dir, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir1, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir1, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } } else{ if(DOT(old_dir, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir2, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir2, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } } } if(n2 > 1){ float p1[3], p2[3], p3[3]; worldcoor(tmp2[n2-2], p1); worldcoor(tmp2[n2-1], p2); worldcoor(tmp2[n2], p3); if((p1[0]-p2[0])*(p3[0]-p2[0]) + (p1[1]-p2[1])*(p3[1]-p2[1]) + (p1[2]-p2[2])*(p3[2]-p2[2]) > 0) break; } if(current.u >= 0 && current.u <= 1 && current.v >= 0 && current.v <= 1) n2++; else break; } //concatnation point_N = n1+n2+1; line = new tri_point[n1+n2+1]; for(int i=0; i= 0 && next_v >= 0){ tmp1[n1].u = next_u; tmp1[n1].v = next_v; l += step; current = tmp1[n1]; } //Outside the triangle. else{ double a = next_v - t2; double b = next_u - t1; double c = a*t1 - b*t2; double s0 = -c; double s1 = a*(1.0-t1) + b*t2; double s2 = -a*t1 - b*(1.0-t2); int result; if(s1*s2 > 0){ if(next_v > 0) result = 1; else result = 2; } else if(s2*s0 > 0){ if(next_v > 0) result = 3; else result = 2; } else if(s0*s1 > 0){ if(next_u > 0) result = 3; else result = 1; } else{ break; } int base_v; double old_dir[3]; if(result == 1){ next_u = 0; if(b == 0) break; next_v = -c/b; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][2]; old_dir[0] = dir2[0]; old_dir[1] = dir2[1]; old_dir[2] = dir2[2]; if(face[current.id][0] == f[2]){ current.u = 0; current.v = (1.0 - next_v); base_v = 0; } else if(face[current.id][1] == f[2]){ current.u = next_v; current.v = 0; base_v = 1; } else{ current.u = 1.0 - next_v; current.v = next_v; base_v = 2; } } else if(result == 2){ if(a == 0) break; next_u = c/a; next_v = 0; if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; current.id = face_link_E[current.id][0]; old_dir[0] = dir0[0]; old_dir[1] = dir0[1]; old_dir[2] = dir0[2]; if(face[current.id][0] == f[0]){ current.u = 0; current.v = next_u; base_v = 0; } else if(face[current.id][1] == f[0]){ current.u = 1.0 - next_u; current.v = 0; base_v = 1; } else{ current.u = next_u; current.v = 1.0 - next_u; base_v = 2; } } else{ if(a+b == 0) break; next_u = (b+c)/(a+b); next_v = (a-c)/(a+b); if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][1]; old_dir[0] = dir1[0]; old_dir[1] = dir1[1]; old_dir[2] = dir1[2]; if(face[current.id][0] == f[1]){ base_v = 0; current.u = 0; current.v = next_v; } else if(face[current.id][1] == f[1]){ base_v = 1; current.u = next_u; current.v = 0; } else{ base_v = 2; current.u = next_v; current.v = next_u; } } tmp1[n1].u = next_u; tmp1[n1].v = next_v; if(current.id < 0) break; float ud = (float)(next_u - t1); float vd = (float)(next_v - t2); float v1[3], v2[3], v12[3]; VEC(v1, vertex[f[0]], vertex[f[1]]); v1[0] *= ud; v1[1] *= ud; v1[2] *= ud; VEC(v2, vertex[f[2]], vertex[f[2]]); v2[0] *= vd; v2[1] *= vd; v2[2] *= vd; VEC(v12, v1, v2); l += (float)LENGTH(v12); f = face[current.id]; dir0[0] = t_min[f[0]][0]; dir0[1] = t_min[f[0]][1]; dir0[2] = t_min[f[0]][2]; dir1[0] = t_min[f[1]][0]; dir1[1] = t_min[f[1]][1]; dir1[2] = t_min[f[1]][2]; dir2[0] = t_min[f[2]][0]; dir2[1] = t_min[f[2]][1]; dir2[2] = t_min[f[2]][2]; if(base_v == 0){ if(DOT(old_dir, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } } else if(base_v == 1){ if(DOT(old_dir, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir1, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir1, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } } else{ if(DOT(old_dir, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir2, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir2, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } } double v[3]; paralellTrans(v, dir1, f[1], f[0]); if(DOT(dir0, v) < T) break; paralellTrans(v, dir2, f[2], f[1]); if(DOT(dir1, v) < T) break; paralellTrans(v, dir0, f[0], f[2]); if(DOT(dir2, v) < T) break; } if(n1 > 1){ float p1[3], p2[3], p3[3]; worldcoor(tmp1[n1-2], p1); worldcoor(tmp1[n1-1], p2); worldcoor(tmp1[n1], p3); if((p1[0]-p2[0])*(p3[0]-p2[0]) + (p1[1]-p2[1])*(p3[1]-p2[1]) + (p1[2]-p2[2])*(p3[2]-p2[2]) > 0) break; } if(current.u >= 0 && current.u <= 1 && current.v >= 0 && current.v <= 1) n1++; else break; } //trace backward current = seed; f = face[current.id]; dir0[0] = -t_min[f[0]][0]; dir0[1] = -t_min[f[0]][1]; dir0[2] = -t_min[f[0]][2]; dir1[0] = -t_min[f[1]][0]; dir1[1] = -t_min[f[1]][1]; dir1[2] = -t_min[f[1]][2]; dir2[0] = -t_min[f[2]][0]; dir2[1] = -t_min[f[2]][1]; dir2[2] = -t_min[f[2]][2]; l = 0; if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } while(l < 0.5*length && n2 < max){ double t1 = current.u; double t2 = current.v; double t0 = 1.0 - t1 - t2; double v[3]; v[0] = t0*dir0[0] + t1*dir1[0] + t2*dir2[0]; v[1] = t0*dir0[1] + t1*dir1[1] + t2*dir2[1]; v[2] = t0*dir0[2] + t1*dir1[2] + t2*dir2[2]; float* n = normal_f[current.id]; double dot = DOT(v, n); v[0] = v[0] - dot*n[0]; v[1] = v[1] - dot*n[1]; v[2] = v[2] - dot*n[2]; double len = LENGTH(v); if((float)len == 0) break; v[0] = v[0]*step/len; v[1] = v[1]*step/len; v[2] = v[2]*step/len; double du, dv; if(!barycentricVector(current.id, v, du, dv)) break; double next_u = current.u + du; double next_v = current.v + dv; tmp2[n2].id = current.id; //The next position is inside the same triangle. if(next_u + next_v <= 1.0 && next_u >= 0 && next_v >= 0){ tmp2[n2].u = next_u; tmp2[n2].v = next_v; l += step; current = tmp2[n2]; } //Outside the triangle. else{ double a = next_v - t2; double b = next_u - t1; double c = a*t1 - b*t2; double s0 = -c; double s1 = a*(1.0-t1) + b*t2; double s2 = -a*t1 - b*(1.0-t2); int result; if(s1*s2 > 0){ if(next_v > 0) result = 1; else result = 2; } else if(s2*s0 > 0){ if(next_v > 0) result = 3; else result = 2; } else if(s0*s1 > 0){ if(next_u > 0) result = 3; else result = 1; } else{ break; } int base_v; double old_dir[3]; if(result == 1){ next_u = 0; if(b == 0) break; next_v = -c/b; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][2]; old_dir[0] = dir2[0]; old_dir[1] = dir2[1]; old_dir[2] = dir2[2]; if(face[current.id][0] == f[2]){ current.u = 0; current.v = (1.0 - next_v); base_v = 0; } else if(face[current.id][1] == f[2]){ current.u = next_v; current.v = 0; base_v = 1; } else{ current.u = 1.0 - next_v; current.v = next_v; base_v = 2; } } else if(result == 2){ if(a == 0) break; next_u = c/a; next_v = 0; if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; current.id = face_link_E[current.id][0]; old_dir[0] = dir0[0]; old_dir[1] = dir0[1]; old_dir[2] = dir0[2]; if(face[current.id][0] == f[0]){ current.u = 0; current.v = next_u; base_v = 0; } else if(face[current.id][1] == f[0]){ current.u = 1.0 - next_u; current.v = 0; base_v = 1; } else{ current.u = next_u; current.v = 1.0 - next_u; base_v = 2; } } else{ if(a+b == 0) break; next_u = (b+c)/(a+b); next_v = (a-c)/(a+b); if(next_u < 0) next_u = 0; else if(next_u > 1) next_u = 1; if(next_v < 0) next_v = 0; else if(next_v > 1) next_v = 1; current.id = face_link_E[current.id][1]; old_dir[0] = dir1[0]; old_dir[1] = dir1[1]; old_dir[2] = dir1[2]; if(face[current.id][0] == f[1]){ base_v = 0; current.u = 0; current.v = next_v; } else if(face[current.id][1] == f[1]){ base_v = 1; current.u = next_u; current.v = 0; } else{ base_v = 2; current.u = next_v; current.v = next_u; } } tmp2[n2].u = next_u; tmp2[n2].v = next_v; if(current.id < 0) break; float ud = (float)(next_u - t1); float vd = (float)(next_v - t2); float v1[3], v2[3], v12[3]; VEC(v1, vertex[f[0]], vertex[f[1]]); v1[0] *= ud; v1[1] *= ud; v1[2] *= ud; VEC(v2, vertex[f[2]], vertex[f[2]]); v2[0] *= vd; v2[1] *= vd; v2[2] *= vd; VEC(v12, v1, v2); l += (float)LENGTH(v12); f = face[current.id]; dir0[0] = t_min[f[0]][0]; dir0[1] = t_min[f[0]][1]; dir0[2] = t_min[f[0]][2]; dir1[0] = t_min[f[1]][0]; dir1[1] = t_min[f[1]][1]; dir1[2] = t_min[f[1]][2]; dir2[0] = t_min[f[2]][0]; dir2[1] = t_min[f[2]][1]; dir2[2] = t_min[f[2]][2]; if(base_v == 0){ if(DOT(old_dir, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir0, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir0, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } } else if(base_v == 1){ if(DOT(old_dir, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } if(DOT(dir1, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir1, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } } else{ if(DOT(old_dir, dir2) < 0){ dir2[0] = - dir2[0]; dir2[1] = - dir2[1]; dir2[2] = - dir2[2]; } if(DOT(dir2, dir0) < 0){ dir0[0] = - dir0[0]; dir0[1] = - dir0[1]; dir0[2] = - dir0[2]; } if(DOT(dir2, dir1) < 0){ dir1[0] = - dir1[0]; dir1[1] = - dir1[1]; dir1[2] = - dir1[2]; } } double v[3]; paralellTrans(v, dir1, f[1], f[0]); if(DOT(dir0, v) < T) break; paralellTrans(v, dir2, f[2], f[1]); if(DOT(dir1, v) < T) break; paralellTrans(v, dir0, f[0], f[2]); if(DOT(dir2, v) < T) break; } if(n2 > 1){ float p1[3], p2[3], p3[3]; worldcoor(tmp2[n2-2], p1); worldcoor(tmp2[n2-1], p2); worldcoor(tmp2[n2], p3); if((p1[0]-p2[0])*(p3[0]-p2[0]) + (p1[1]-p2[1])*(p3[1]-p2[1]) + (p1[2]-p2[2])*(p3[2]-p2[2]) > 0) break; } if(current.u >= 0 && current.u <= 1 && current.v >= 0 && current.v <= 1) n2++; else break; } //concatnation point_N = n1+n2+1; line = new tri_point[n1+n2+1]; for(int i=0; i 1.0) dot = 1; else if(dot < -1.0) dot = -1; GENERATE_MAT(R, acos(dot), cross); } MAT_VEC(vj, R, vi); } void MeshData::computeHatchTriangle(float T) { is_hatch = new BOOL[face_N]; for(int i=0; i 1) dot = 1; else if(dot < -1) dot = -1; if(acos(fabs(dot)) > d*T){ is_hatch[i] = false; break; } } } } void MeshData::tangent(double t[], int from, int to) { float v[3]; VEC(v, vertex[from], vertex[to]); float *n = normal[from]; double dot = DOT(n, v); t[0] = v[0] - dot*n[0]; t[1] = v[1] - dot*n[1]; t[2] = v[2] - dot*n[2]; double l = LENGTH(t); if(l != 0){ t[0] /= l; t[1] /= l; t[2] /= l; } else t[0] = t[1] = t[2] = 0; } void MeshData::undoNormalizeScale() { for(int i=0; i 0.001){ A += 0.5*Ai; double dot1 = DOT(PQ1, QQ); double dot2 = -DOT(PQ2,QQ); double cot1 = dot2/Ai; double cot2 = dot1/Ai; Hn[0] += cot1*PQ1[0] + cot2*PQ2[0]; Hn[1] += cot1*PQ1[1] + cot2*PQ2[1]; Hn[2] += cot1*PQ1[2] + cot2*PQ2[2]; } } /* if((float)A != 0){ //> 0.006){ Hn[0] /= A; Hn[1] /= A; Hn[2] /= A; } else{ Hn[0] = 0; Hn[1] = 0; Hn[2] = 0; } */ } void MeshData::computeCenter() { if(center != NULL) delete[] center; center = new float[face_N][3]; for(int i=0; i dist){ index = i; min = dist; } } if(index < 0) return -1; if(selected_triangle != NULL) delete selected_triangle; selected_triangle = new Node; selected_triangle->append(-1, index); return index; } float MeshData::averageOfEdgeLength() { double total = 0; int n = 0; for(int i=0; i