static bool find_fourth_point(int num_points, const double (*points)[3], int a, int b, int c, int* p_d) { double plane_normal[3]; calculate_plane_normal(points, a, b, c, plane_normal); int bi = -1; double max_dist = 0.0; for (int i = 0;i<num_points;i++) { if (i == a || i == b || i == c) continue; const double* x0 = points[i]; double dist = fabs(point_plane_distance(x0, points[a], plane_normal)); if (dist > max_dist) { max_dist = dist; bi = i; } } *p_d = bi; return max_dist > TOLERANCE; }
double point3_plane_distance(const point_type * p0 , const point_type * p1 , const point_type * p2 , const point_type * x) { point_type n; point_normal_vector( &n , p0 , p1 , p2 ); return point_plane_distance( x , &n , p0 ) / sqrt( n.x*n.x + n.y*n.y + n.z*n.z); }
DBL BicubicPatch::determine_subpatch_flatness(const ControlPoints *Patch) { int i, j; DBL d, dist, temp1; Vector3d n; Vector3d TempV; Vector3d vertices[3]; vertices[0] = (*Patch)[0][0]; vertices[1] = (*Patch)[0][3]; TempV = vertices[0] - vertices[1]; temp1 = TempV.length(); if (fabs(temp1) < EPSILON) { /* * Degenerate in the V direction for U = 0. This is ok if the other * two corners are distinct from the lower left corner - I'm sure there * are cases where the corners coincide and the middle has good values, * but that is somewhat pathalogical and won't be considered. */ vertices[1] = (*Patch)[3][3]; TempV = vertices[0] - vertices[1]; temp1 = TempV.length(); if (fabs(temp1) < EPSILON) { return (-1.0); } vertices[2] = (*Patch)[3][0]; TempV = vertices[0] - vertices[1]; temp1 = TempV.length(); if (fabs(temp1) < EPSILON) { return (-1.0); } TempV = vertices[1] - vertices[2]; temp1 = TempV.length(); if (fabs(temp1) < EPSILON) { return (-1.0); } } else { vertices[2] = (*Patch)[3][0]; TempV = vertices[0] - vertices[1]; temp1 = TempV.length(); if (fabs(temp1) < EPSILON) { vertices[2] = (*Patch)[3][3]; TempV = vertices[0] - vertices[2]; temp1 = TempV.length(); if (fabs(temp1) < EPSILON) { return (-1.0); } TempV = vertices[1] - vertices[2]; temp1 = TempV.length(); if (fabs(temp1) < EPSILON) { return (-1.0); } } else { TempV = vertices[1] - vertices[2]; temp1 = TempV.length(); if (fabs(temp1) < EPSILON) { return (-1.0); } } } /* * Now that a good set of candidate points has been found, * find the plane equations for the patch. */ if (subpatch_normal(vertices[0], vertices[1], vertices[2], n, &d)) { /* * Step through all vertices and see what the maximum * distance from the plane happens to be. */ dist = 0.0; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { temp1 = fabs(point_plane_distance((*Patch)[i][j], n, d)); if (temp1 > dist) { dist = temp1; } } } return (dist); } else { /* Debug_Info("Subpatch normal failed in determine_subpatch_flatness\n"); */ return (-1.0); } }
int get_convex_hull(int num_points, const double (*points)[3], int num_expected_facets, convexhull_t* ch, int8_t simplex[][3]) { assert(num_points == 7 || num_points == 13 || num_points == 15); int ret = 0; int num_prev = ch->num_prev; ch->num_prev = num_points; if (!ch->ok || 0) { ret = initialize_convex_hull(num_points, points, ch->facets, ch->plane_normal, ch->processed, ch->initial_vertices, ch->barycentre); if (ret != 0) return ret; ch->num_facets = 4; num_prev = 0; } for (int i = num_prev;i<num_points;i++) { if (ch->processed[i]) continue; ch->processed[i] = true; int num_to_add = 0; int8_t to_add[MAXF][3]; int8_t edge_visible[15][15]; memset(edge_visible, 0, sizeof(int8_t) * 15 * 15); for (int j = 0;j<ch->num_facets;j++) { int a = ch->facets[j][0]; int b = ch->facets[j][1]; int c = ch->facets[j][2]; int u = 0, v = 0, w = 0; double distance = point_plane_distance(points[i], points[a], ch->plane_normal[j]); bool vis = distance > TOLERANCE; if (vis) { u = edge_visible[a][b] |= VISIBLE; edge_visible[b][a] |= VISIBLE; v = edge_visible[b][c] |= VISIBLE; edge_visible[c][b] |= VISIBLE; w = edge_visible[c][a] |= VISIBLE; edge_visible[a][c] |= VISIBLE; memcpy(ch->facets[j], ch->facets[ch->num_facets-1], 3 * sizeof(int8_t)); memcpy(ch->plane_normal[j], ch->plane_normal[ch->num_facets-1], 3 * sizeof(double)); ch->num_facets--; j--; } else { u = edge_visible[a][b] |= INVISIBLE; edge_visible[b][a] |= INVISIBLE; v = edge_visible[b][c] |= INVISIBLE; edge_visible[c][b] |= INVISIBLE; w = edge_visible[c][a] |= INVISIBLE; edge_visible[a][c] |= INVISIBLE; } if (u == BOTH) { to_add[num_to_add][0] = i; to_add[num_to_add][1] = a; to_add[num_to_add][2] = b; num_to_add++; } if (v == BOTH) { to_add[num_to_add][0] = i; to_add[num_to_add][1] = b; to_add[num_to_add][2] = c; num_to_add++; } if (w == BOTH) { to_add[num_to_add][0] = i; to_add[num_to_add][1] = c; to_add[num_to_add][2] = a; num_to_add++; } } for (int j = 0;j<num_to_add;j++) { if (ch->num_facets >= MAXF) return -4; add_facet(points, to_add[j][0], to_add[j][1], to_add[j][2], ch->facets[ch->num_facets], ch->plane_normal[ch->num_facets], ch->barycentre); ch->num_facets++; } } if (ch->num_facets != num_expected_facets) return -5; //incorrect number of facets in convex hull for (int i=0;i<ch->num_facets;i++) { int a = ch->facets[i][0]; int b = ch->facets[i][1]; int c = ch->facets[i][2]; if (a == 0 || b == 0 || c == 0) return -6; //central atom contained in convex hull simplex[i][0] = a - 1; simplex[i][1] = b - 1; simplex[i][2] = c - 1; } return ret; }
static bool visible(const double* w, const double* plane_point, const double* plane_normal) { return point_plane_distance(w, plane_point, plane_normal) > 0; }
static DBL determine_subpatch_flatness(VECTOR (*Patch)[4][4]) { int i, j; DBL d, dist, temp1; VECTOR n, TempV; VECTOR vertices[4]; Assign_Vector(vertices[0], (*Patch)[0][0]); Assign_Vector(vertices[1], (*Patch)[0][3]); VSub(TempV, vertices[0], vertices[1]); VLength(temp1, TempV); if (fabs(temp1) < EPSILON) { /* * Degenerate in the V direction for U = 0. This is ok if the other * two corners are distinct from the lower left corner - I'm sure there * are cases where the corners coincide and the middle has good values, * but that is somewhat pathalogical and won't be considered. */ Assign_Vector(vertices[1], (*Patch)[3][3]); VSub(TempV, vertices[0], vertices[1]); VLength(temp1, TempV); if (fabs(temp1) < EPSILON) { return (-1.0); } Assign_Vector(vertices[2], (*Patch)[3][0]); VSub(TempV, vertices[0], vertices[1]); VLength(temp1, TempV); if (fabs(temp1) < EPSILON) { return (-1.0); } VSub(TempV, vertices[1], vertices[2]); VLength(temp1, TempV); if (fabs(temp1) < EPSILON) { return (-1.0); } } else { Assign_Vector(vertices[2], (*Patch)[3][0]); VSub(TempV, vertices[0], vertices[1]); VLength(temp1, TempV); if (fabs(temp1) < EPSILON) { Assign_Vector(vertices[2], (*Patch)[3][3]); VSub(TempV, vertices[0], vertices[2]); VLength(temp1, TempV); if (fabs(temp1) < EPSILON) { return (-1.0); } VSub(TempV, vertices[1], vertices[2]); VLength(temp1, TempV); if (fabs(temp1) < EPSILON) { return (-1.0); } } else { VSub(TempV, vertices[1], vertices[2]); VLength(temp1, TempV); if (fabs(temp1) < EPSILON) { return (-1.0); } } } /* * Now that a good set of candidate points has been found, * find the plane equations for the patch. */ if (subpatch_normal(vertices[0], vertices[1], vertices[2], n, &d)) { /* * Step through all vertices and see what the maximum * distance from the plane happens to be. */ dist = 0.0; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { temp1 = fabs(point_plane_distance(((*Patch)[i][j]), n, &d)); if (temp1 > dist) { dist = temp1; } } } return (dist); } else { /* Debug_Info("Subpatch normal failed in determine_subpatch_flatness\n"); */ return (-1.0); } }